001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *                               ***
008 *
009 *   Community License: GPL 3.0
010 *
011 *   This file is free software: you can redistribute it and/or modify
012 *   it under the terms of the GNU General Public License as published
013 *   by the Free Software Foundation, either version 3 of the License,
014 *   or (at your option) any later version.
015 *
016 *   This file is distributed in the hope that it will be useful, but
017 *   WITHOUT ANY WARRANTY; without even the implied warranty of
018 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019 *   GNU General Public License for more details.
020 *
021 *   You should have received a copy of the GNU General Public License
022 *   along with this program. If not, see <http://www.gnu.org/licenses/>.
023 *
024 *                               ***
025 *
026 *   Available Commercial License: GraniteDS SLA 1.0
027 *
028 *   This is the appropriate option if you are creating proprietary
029 *   applications and you are not prepared to distribute and share the
030 *   source code of your application under the GPL v3 license.
031 *
032 *   Please visit http://www.granitedataservices.com/license for more
033 *   details.
034 */
035package org.granite.client.tide.data.spi;
036
037import java.util.Map;
038
039/**
040 * SPI for integrating with different types of data objects (javabeans, javafx bindable beans, ...)
041 *
042 * @author William DRAI
043 */
044public interface DataManager {
045
046    /**
047     * Is the object an entity (i.e. annotated with {@link org.granite.client.persistence.Entity}) ?
048     * @param object object
049     * @return true if entity
050     */
051    public boolean isEntity(Object object);
052
053    /**
054     * Return the persistent id of an entity (field annotated with {@link org.granite.client.persistence.Id}) ?
055     * @param entity object
056     * @return id if field found, error if no id field
057     */
058    public Object getId(Object entity);
059
060    /**
061     * Has the entity an id field ?
062     * @param entity object
063     * @return true if id field found
064     */
065    public boolean hasIdProperty(Object entity);
066
067    /**
068     * Return the persistent detached state of an entity (private field name __detachedState__)
069     * @param entity object
070     * @return detached state if field found, error if field not found
071     */
072    public String getDetachedState(Object entity);
073
074    /**
075     * Define the target object as a proxy for the source entity
076     * @param target target object
077     * @param source source entity
078     * @return true if proxy was setup, false if source was not an entity or did not have any detached state
079     */
080    public boolean defineProxy(Object target, Object source);
081
082    /**
083     * Copy the proxy state (fields __initialized__ and __detachedState__) from source to target
084     * @param target target object
085     * @param source source entity
086     */
087    public void copyProxyState(Object target, Object source);
088
089    /**
090     * Copy the uid field (annotated with {@link org.granite.client.persistence.Uid}) from source to target
091     * @param target target object
092     * @param source source entity
093     */
094    public void copyUid(Object target, Object source);
095
096    /**
097     * Return the version (field annotated with {@link org.granite.client.persistence.Version}) for an entity
098     * @param entity entity
099     * @return version or error if no version field found
100     */
101    public Object getVersion(Object entity);
102
103    /**
104     * Has the entity a version field (annotated with {@link org.granite.client.persistence.Version}) ?
105     * @param entity object
106     * @return true if version field found
107     */
108    public boolean hasVersionProperty(Object entity);
109
110    /**
111     * Name of the version field for the entity
112     * @param entity object
113     * @return property name or null if not found
114     */
115    public String getVersionPropertyName(Object entity);
116
117    /**
118     * Get the uid field (annotated with {@link org.granite.client.persistence.Uid}) for the entity
119     * Note that the data manager implementation is allowed to generate a reasonable uid value from other fields
120     * if no uid field is present
121     * @param entity object
122     * @return uid or error if uid could not be generated
123     */
124    public String getUid(Object entity);
125
126    /**
127     * Return a map of property values for the specified entity instance
128     * @param entity object instance
129     * @param excludeIdUid true to exclude id and uid fields from the map
130     * @param excludeVersion true to exclude version field from the map
131     * @param includeReadOnly true to include readonly fields in the map
132     * @return a map of values keyed by property names
133     */
134    public Map<String, Object> getPropertyValues(Object entity, boolean excludeIdUid, boolean excludeVersion, boolean includeReadOnly);
135
136    /**
137     * Return a map of property values for the specified entity instance
138     * @param entity object instance
139     * @param excludeVersion true to exclude version field from the map
140     * @param includeReadOnly true to include readonly fields in the map
141     * @return a map of values keyed by property names
142     */
143    public Map<String, Object> getPropertyValues(Object entity, boolean excludeVersion, boolean includeReadOnly);
144
145    /**
146     * Return the value of the property for the specified entity instance
147     * @param entity object instance
148     * @param name property name
149     * @return property value
150     */
151    public Object getPropertyValue(Object entity, String name);
152
153    /**
154     * Set the value of the property for the specified entity instance
155     * @param entity object instance
156     * @param name property name
157     * @param value property value
158     */
159    public void setPropertyValue(Object entity, String name, Object value);
160
161    /**
162     * Is the specified property lazy ?
163     * A property is considered lazy if it is annotated with {@link org.granite.client.persistence.Lazy} or if the
164     * server has returned an initialized value
165     * @param entity entity instance
166     * @param name property name
167     * @return true if property defined as lazy
168     */
169    public boolean isLazyProperty(Object entity, String name);
170
171    /**
172     * Define a property as lazy
173     * @param entity entity instance
174     * @param name property name
175     */
176    public void setLazyProperty(Object entity, String name);
177
178    /**
179     * Return a unique key for the entity to be used in a local cache
180     * @param entity entity instance
181     * @return unique key
182     */
183    public String getCacheKey(Object entity);
184
185    /**
186     * Is the entity initialized (field __initialized__ true) ?
187     * @param entity entity instance
188     * @return true if initialized
189     */
190    public boolean isInitialized(Object entity);
191
192    /**
193     * Is the data manager dirty (any managed entity instance has been modified since last received from server) ?
194     * @return true if modified
195     */
196    public boolean isDirty();
197
198    /**
199     * Is the entity instance dirty (modified since last received from server) ?
200     * @return true if modified
201     */
202    public boolean isDirtyEntity(Object entity);
203
204    /**
205     * Is the entity graph dirty (any object in the graph of this entity has been modified since last received from server) ?
206     * @return true if modified
207     */
208    public boolean isDeepDirtyEntity(Object entity);
209
210
211    /**
212     * Register a handler that will be notified when any managed entity is modified
213     * @param trackingHandler tracking handler
214     */
215    public void setTrackingHandler(TrackingHandler trackingHandler);
216
217    /**
218     * Types of tracked events
219     */
220    public static enum TrackingType {        
221        LIST,
222        SET,
223        MAP,
224        ENTITY_PROPERTY,
225        ENTITY_LIST,
226        ENTITY_SET,
227        ENTITY_MAP
228    }
229
230    /**
231     * Kinds of changes for collections and maps
232     */
233    public static enum ChangeKind {
234        ADD,
235        REMOVE,
236        REPLACE,
237        UPDATE
238    }
239
240    
241    /**
242     *  Start tracking for the specified object / parent
243     *
244     *  @param previous previously existing object in the entity manager cache (null if no existing object)
245     *  @param parent parent object for collections
246     */
247    public void startTracking(Object previous, Object parent);
248    
249    /**
250     *  Stop tracking for the specified object / parent
251     *
252     *  @param previous previously existing object in the entity manager cache (null if no existing object)
253     *  @param parent parent object for collections
254     */
255    public void stopTracking(Object previous, Object parent);
256
257    /**
258     *  Reset all currently tracked objects
259     */
260    public void clear();
261
262    /**
263     * Callback interface for objects that need to be notified when modifications are made on managed entities
264     */
265    public static interface TrackingHandler {
266
267        /**
268         * Callback called when a collection is modified
269         * @param kind kind of collection change
270         * @param target modified collection
271         * @param location index/key of the modification
272         * @param items array of modified items
273         */
274        public void collectionChangeHandler(ChangeKind kind, Object target, Integer location, Object[] items);
275
276        /**
277         * Callback called when a map is modified
278         * @param kind kind of map change
279         * @param target modified map
280         * @param location key of the modification
281         * @param items array of modified entries (each entry is an array [ key, value ])
282         */
283        public void mapChangeHandler(ChangeKind kind, Object target, Integer location, Object[] items);
284
285        /**
286         * Callback when a property of an entity is modified
287         * @param target modified entity
288         * @param property property name
289         * @param oldValue previous value
290         * @param newValue new value
291         */
292        public void entityPropertyChangeHandler(Object target, String property, Object oldValue, Object newValue);
293
294        /**
295         * Callback called when a collection owned by an entity (x-to-many association) is modified
296         * @param kind kind of collection change
297         * @param target modified collection
298         * @param location index/key of the modification
299         * @param items array of modified items
300         */
301        public void entityCollectionChangeHandler(ChangeKind kind, Object target, Integer location, Object[] items);
302
303        /**
304         * Callback called when a map owned by an entity (x-to-many association) is modified
305         * @param kind kind of map change
306         * @param target modified map
307         * @param location key of the modification
308         * @param items array of modified entries (each entry is an array [ key, value ])
309         */
310        public void entityMapChangeHandler(ChangeKind kind, Object target, Integer location, Object[] items);
311    }
312
313    /**
314     * Notify listeners that the dirty state of this data manager has changed
315     * Called by dirty checking
316     * @param oldDirty old value
317     * @param dirty new value
318     * @see org.granite.client.tide.data.spi.DirtyCheckContext
319     */
320    public void notifyDirtyChange(boolean oldDirty, boolean dirty);
321
322    /**
323     * Notify listeners that the dirty state of the specified has changed
324     * @param entity entity instance
325     * @param oldDirtyEntity old value
326     * @param newDirtyEntity new value
327     * @see org.granite.client.tide.data.spi.DirtyCheckContext
328     */
329    public void notifyEntityDirtyChange(Object entity, boolean oldDirtyEntity, boolean newDirtyEntity);
330
331}