001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2012 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.client.tide.data;
022
023 import java.util.List;
024 import java.util.Map;
025 import java.util.Set;
026
027 import org.granite.client.tide.Context;
028 import org.granite.client.tide.data.spi.DataManager;
029 import org.granite.client.tide.data.spi.MergeContext;
030 import org.granite.client.tide.server.ServerSession;
031 import org.granite.tide.Expression;
032
033 /**
034 * EntityManager is the interface for entity management (!)
035 * It is implemented by the Tide context
036 *
037 * @author William DRAI
038 */
039 public interface EntityManager {
040
041 /**
042 * Return the entity manager id
043 *
044 * @return the entity manager id
045 */
046 public String getId();
047
048 /**
049 * Return the entity manager state
050 *
051 * @return the entity manager state
052 */
053 public boolean isActive();
054
055 /**
056 * Clear entity cache
057 */
058 public void clearCache();
059
060 /**
061 * Clear the current context
062 * Destroys all components/context variables
063 */
064 public void clear();
065
066 public DataManager getDataManager();
067
068 /**
069 * Allow uninitialize of persistent collections
070 *
071 * @param allowed allow uninitialize of collections
072 */
073 public void setUninitializeAllowed(boolean allowed);
074
075 /**
076 * @return allow uninitialize of collections
077 */
078 public boolean isUninitializeAllowed();
079
080
081 public static interface Propagation {
082
083 public void propagate(Identifiable entity, Function func);
084 }
085
086 public static interface Function {
087
088 public void execute(EntityManager entityManager, Identifiable entity);
089 }
090
091 /**
092 * Setter for the propagation manager
093 *
094 * @param propagation propagation function that will visit child entity managers
095 */
096 public void setEntityManagerPropagation(Propagation propagation);
097
098 /**
099 * Setter for the remote initializer implementation
100 *
101 * @param remoteInitializer instance of IRemoteInitializer
102 */
103 public void setRemoteInitializer(RemoteInitializer remoteInitializer);
104
105 /**
106 * Setter for the remote validator implementation
107 *
108 * @param remoteValidator instance of IRemoteValidator
109 */
110 public void setRemoteValidator(RemoteValidator remoteValidator);
111
112 /**
113 * Create a new temporary entity manager
114 *
115 * @return a temporary entity manager
116 */
117 public EntityManager newTemporaryEntityManager();
118
119
120 /**
121 * Intercept a property getter
122 *
123 * @param entity intercepted entity
124 * @param propName intercepted property name
125 * @param value current value
126 */
127 public Object getEntityProperty(Identifiable entity, String propName, Object value);
128
129 /**
130 * Intercept a property setter
131 *
132 * @param entity intercepted entity
133 * @param propName intercepted property name
134 * @param oldValue old value
135 * @param newValue new value
136 */
137 public void setEntityProperty(Identifiable entity, String propName, Object oldValue, Object newValue);
138
139 /**
140 * Register a reference to the provided object with either a parent or res
141 *
142 * @param entity an entity
143 * @param parent the parent entity
144 * @param propName name of the parent entity property that references the entity
145 * @param res the context expression
146 */
147 public void addReference(Object entity, Object parent, String propName, Expression expr);
148
149 /**
150 * Remove a reference on the provided object
151 *
152 * @param obj an entity
153 * @param parent the parent entity to dereference
154 * @param propName name of the parent entity property that references the entity
155 * @param res expression to remove
156 */
157 public boolean removeReference(Object entity, Object parent, String propName, Expression exp);
158
159 /**
160 * Retrieves context expression path for the specified entity (internal implementation)
161 *
162 * @param obj an entity
163 * @param recurse should recurse until 'real' context path, otherwise object reference can be returned
164 * @param cache graph visitor cache
165 *
166 * @return the path from the entity context (or null is no path found)
167 */
168 public Expression getReference(Object entity, boolean recurse, Set<Object> cache);
169
170 /**
171 * Entity manager is dirty when any entity/collection/map has been modified
172 *
173 * @return is dirty
174 */
175 public boolean isDirty();
176
177 /**
178 * Entity is deep dirty when any element in its object graph has been modified
179 * @param entity root of the entity graph
180 *
181 * @return is dirty
182 */
183 public boolean isDeepDirtyEntity(Object entity);
184
185 /**
186 * Indicates if the entity is persisted on the server (id/version not null/NaN)
187 *
188 * @param entity an entity
189 * @return true if saved
190 */
191 public boolean isSaved(Object entity);
192
193 /**
194 * @private
195 * Retrieve an entity in the cache from its uid
196 *
197 * @param object an entity
198 * @param nullIfAbsent return null if entity not cached in context
199 */
200 public Object getCachedObject(Object object, boolean nullIfAbsent);
201
202 public Object[] getOwnerEntity(Object object);
203
204 public MergeContext initMerge();
205
206 public Object mergeExternal(final MergeContext mergeContext, Object obj, Object previous, Expression expr, Object parent, String propertyName, String setter, boolean forceUpdate);
207
208 /**
209 * Merge an object coming from a remote location (in general from a service) in the local context
210 *
211 * @param obj external object
212 * @param prev existing local object to merge with
213 * @param externalDataSessionId sessionId from which the data is coming (other user/server), null if local or current user session
214 * @param removals array of entities to remove from the entity manager cache
215 *
216 * @return merged object (should === previous when previous not null)
217 */
218 public Object mergeExternalData(Object obj, Object prev, String externalDataSessionId, List<Object> removals, List<Object> persists);
219
220 /**
221 * Merge an object coming from a remote location (in general from a service) in the local context
222 *
223 * @param obj external object
224 *
225 * @return merged object
226 */
227 public Object mergeExternalData(ServerSession serverSession, Object obj);
228
229 /**
230 * Merge an object coming from a remote location (in general from a service) in the local context
231 *
232 * @param obj external object
233 * @param prev existing local object to merge with
234 * @param externalDataSessionId sessionId from which the data is coming (other user/server), null if local or current user session
235 * @param removals array of entities to remove from the entity manager cache
236 *
237 * @return merged object (should === previous when previous not null)
238 */
239 public Object mergeExternalData(ServerSession serverSession, Object obj, Object prev, String externalDataSessionId, List<Object> removals, List<Object> persists);
240
241 /**
242 * Merge an object coming from a remote location (in general from a service) in the local context
243 *
244 * @param obj external object
245 *
246 * @return merged object
247 */
248 public Object mergeExternalData(Object obj);
249
250 // public Object internalMergeExternalData(MergeContext mergeContext, Object obj, Object prev, List<Object> removals);
251
252 /**
253 * @private
254 * Merge an object coming from another entity manager (in general in the global context) in the local context
255 *
256 * @param sourceEntityManager source context of incoming data
257 * @param obj external object
258 * @param externalDataSessionId is merge from external data
259 *
260 * @return merged object (should === previous when previous not null)
261 */
262 public Object mergeFromEntityManager(EntityManager sourceEntityManager, Object obj, String externalDataSessionId, boolean uninitializing);
263
264 /**
265 * Merge conversation entity manager context variables in global entity manager
266 * Only applicable to conversation contexts
267 *
268 * @param entityManager conversation entity manager
269 */
270 public void mergeInEntityManager(EntityManager entityManager);
271
272 /**
273 * Discard changes of entity from last version received from the server
274 *
275 * @param entity entity to restore
276 * @param cache reset cache
277 */
278 public void resetEntity(Identifiable entity);
279
280 /**
281 * Discard changes of all cached entities from last version received from the server
282 *
283 * @param cache reset cache
284 */
285 public void resetAllEntities();
286
287 /**
288 * Current map of saved properties for the specified entity
289 * @param entity an entity
290 *
291 * @return saved properties for this entity
292 */
293 public Map<String, Object> getSavedProperties(Object entity);
294
295
296 public static enum UpdateKind {
297 PERSIST,
298 UPDATE,
299 REMOVE,
300 REFRESH,
301 CONFLICT;
302
303 private static final String DATA_EVENT_PREFIX = "org.granite.client.tide.data.";
304
305 public static UpdateKind forName(String kind) {
306 if ("PERSIST".equals(kind))
307 return PERSIST;
308 else if ("UPDATE".equals(kind))
309 return UPDATE;
310 else if ("REMOVE".equals(kind))
311 return REMOVE;
312 throw new IllegalArgumentException("Unknown update kind " + kind);
313 }
314
315 public String eventName() {
316 return DATA_EVENT_PREFIX + name().toLowerCase();
317 }
318
319 public <T> String eventName(Class<T> entityClass) {
320 return DATA_EVENT_PREFIX + name().toLowerCase() + "." + entityClass.getSimpleName();
321 }
322 }
323
324 public static class Update {
325
326 private final UpdateKind kind;
327 private Object entity;
328
329 public Update(UpdateKind kind, Object entity) {
330 this.kind = kind;
331 this.entity = entity;
332 }
333
334 public UpdateKind getKind() {
335 return kind;
336 }
337
338 public Object getEntity() {
339 return entity;
340 }
341
342 public void setEntity(Object entity) {
343 this.entity = entity;
344 }
345
346 public static Update forUpdate(String kind, Object entity) {
347 return new Update(UpdateKind.forName(kind), entity);
348 }
349 }
350
351 /**
352 * @private
353 * Handle data updates
354 *
355 * @param sourceSessionId sessionId from which data updates come (null when from current session)
356 * @param updates list of data updates
357 */
358 public void handleUpdates(MergeContext mergeContext, String sourceSessionId, List<Update> updates);
359
360 public void raiseUpdateEvents(Context context, List<EntityManager.Update> updates);
361
362
363 public void addListener(DataConflictListener listener);
364
365 public void removeListener(DataConflictListener listener);
366
367 /**
368 * Accept values for conflict
369 *
370 * @param conflict conflict
371 * @param acceptClient true: keep client changes, false: override with server changes
372 */
373 public void acceptConflict(Conflict conflict, boolean acceptClient);
374
375 /**
376 * Trigger remote initialization of lazy-loaded objects
377 *
378 * @param object a lazy-loaded object
379 *
380 * @return true if initialization triggered
381 */
382 public boolean initializeObject(ServerSession serverSession, Object object);
383
384 /**
385 * Trigger remote validation of objects
386 *
387 * @param object a lazy-loaded object
388 *
389 * @return true if validation triggered
390 */
391 public boolean validateObject(Object object, String property, Object value);
392
393
394 public static interface PropagationPolicy {
395
396 public void propagate();
397 }
398 }