Nested context on ROP proposal Preface CayenneContext definitely misses functionality avaliable for DataContext - nested (child) contexts. This is a description of how to implement the feature.
Functionality It must be logically the same as DataContext's nested contexts. Main API usage methods are: -creation of nested context -> ObjectContext.createChildObjectContext. -committing changes to parent Cayennecontext -> ObjectContext.commitChangesToParent() -committing changes to all context tree, likely until DataContext and underlying database -> ObjectContext.commitChanges() -rolling back current changes -> ObjectContext.rollbackChanges and ObjectContext.rollbackChangesLocally(). Changes should go: -from child to parent -> through DataChannel API -from parent to child -> through EventManager API Once again, feature should work same as via DataContext.createChildDataContext(), so I will not describe it here more in detail API changes (possibly incomplete list) Important note here is that all changes are only increasing method's visibility or moving them from inherited class to superclass, so no user's code will break. New classes/ifaces: none. all required classes are already in Cayenne. Method changes/additions (all in ObjectContext, BaseContext, DataContext and CayenneContext): ObjectContext ObjectContext.createChildObjectContext() - new method, creates and returns a new child ObjectContext. DataContext implementation calls createChildDataContext() DataContext DataContext.createChildDataContext() - needs deprecation, previous method should be used instead. This is just another step to unification Data- and Cay- contexts BaseContext - to implement DataChannel, because both descendants need that API. DataContext already has implementation. EventManager getEventManager() impl is same for both contexts and should be moved to BaseContext QueryResponse CayenneContext.onQuery(ObjectContext context, Query query) should be made public since now CayenneContext supports dataChannel API public GraphDiff DataContext.onSync(ObjectContext originatingContext, GraphDiff changes, int syncType) method should be moved from DataContext to BaseContext GraphDiff DataContext.onContextRollback(ObjectContext originatingContext) - method used by previous method, also should be moved up GraphDiff DataContext.onContextFlush(ObjectContext originatingContext, GraphDiff changes, boolean cascade) - should be moved up to BaseContext and made protected and abstract, because implementations will differ. void DataContext.fireDataChannelCommitted(Object postedBy, GraphDiff changes) void DataContext.fireDataChannelRolledback(Object postedBy, GraphDiff changes) void DataContext.fireDataChannelChanged(Object postedBy, GraphDiff changes) - now used by both contexts, so should be moved up to BaseContext and made protected boolean ObjectContext.hasChanges() - returns true if there are any modified, deleted or new objects registered with this ObjectContext. This is useful method to add to ObjectContext. dataContext already has implementation. /** * "Invalidates" a Collection of persistent objects. This operation would remove each * object's snapshot from cache and change object's state to HOLLOW. On the next * access to this object, it will be refetched. * * @see RefreshQuery */ void ObjectContext.invalidateObjects(Collection objects) - another useful method from dataContext that should be added to ObjectContext Obsolete method - void CayenneContextGraphManager.send(GraphDiff diff, EventSubject subject, Object eventSource) now replaced by calls to fireDataChannel* methods described above and can be removed. It is package-private so no user's code should break. Tests Everything's quite simple with junits here because dataContext's nested contexts already have full suite of tests. All we need is to convert them to client classes. I'm really looking for some feedback. I think this feature is must-have for Cayenne and I'll need it in my work Thanks, Andrey
