Andrey, after your commit I have this problem: [INFO] Compilation failure /home/olga/cayenne-git/framework/cayenne-tools/src/test/java/org/apache/cayenne/gen/ClientDataMapGeneratedQueryRunTest.java:[59,86] incompatible types found : java.util.List<org.apache.cayenne.testdo.mt.MtTable1> required: java.util.List<org.apache.cayenne.testdo.mt.ClientMtTable1>
and reasonable error in cayenne-tools. 2009/11/18 <[email protected]> > Author: andrey > Date: Wed Nov 18 12:08:20 2009 > New Revision: 881740 > > URL: http://svn.apache.org/viewvc?rev=881740&view=rev > Log: > CAY-1312 Allow lifecycle callbacks on ROP client. Only method invokes, i.e. > no configuration for those callbacks yet > > Added: > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java > - copied, changed from r881253, > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataChannelSyncCallbackAction.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/RemoteCallbacksTest.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/ClientMtLifecycles.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/MtLifecycles.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMtLifecycles.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MtLifecycles.java > Removed: > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataChannelSyncCallbackAction.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContextDeleteAction.java > Modified: > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ObjectContextDeleteAction.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackRegistry.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/ClientChannel.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMultiTier.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MultiTier.java > > > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/multi-tier.map.xml > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java > Wed Nov 18 12:08:20 2009 > @@ -33,6 +33,7 @@ > import org.apache.cayenne.graph.GraphEvent; > import org.apache.cayenne.graph.GraphManager; > import org.apache.cayenne.map.EntityResolver; > +import org.apache.cayenne.map.LifecycleEvent; > import org.apache.cayenne.map.ObjEntity; > import org.apache.cayenne.query.ObjectIdQuery; > import org.apache.cayenne.query.Query; > @@ -103,8 +104,6 @@ > > public abstract void commitChangesToParent(); > > - public abstract void deleteObject(Object object) throws > DeleteDenyException; > - > public abstract Collection<?> deletedObjects(); > > public DataChannel getChannel() { > @@ -381,9 +380,24 @@ > } > > /** > - * If ObjEntity qualifier is set, asks it to inject initial value to > an object > + * If ObjEntity qualifier is set, asks it to inject initial value to > an object. > + * Also performs all Persistent initialization operations > */ > - protected void injectInitialValue(Object object) { > + protected void injectInitialValue(Object obj) { > + // must follow this exact order of property initialization per > CAY-653, i.e. have > + // the id and the context in place BEFORE setPersistence is called > + > + Persistent object = (Persistent) obj; > + > + object.setObjectContext(this); > + object.setPersistenceState(PersistenceState.NEW); > + > + GraphManager graphManager = getGraphManager(); > + synchronized (graphManager) { > + graphManager.registerNode(object.getObjectId(), object); > + graphManager.nodeCreated(object.getObjectId()); > + } > + > ObjEntity entity; > try { > entity = > getEntityResolver().lookupObjEntity(object.getClass()); > @@ -398,5 +412,37 @@ > ((ValueInjector) > entity.getDeclaredQualifier()).injectValue(object); > } > } > + > + // invoke callbacks > + getEntityResolver().getCallbackRegistry().performCallbacks( > + LifecycleEvent.POST_ADD, > + object); > + } > + > + /** > + * Schedules an object for deletion on the next commit of this > context. Object's > + * persistence state is changed to PersistenceState.DELETED; objects > related to this > + * object are processed according to delete rules, i.e. relationships > can be unset > + * ("nullify" rule), deletion operation is cascaded (cascade rule). > + * > + * @param object a persistent object that we want to delete. > + * @throws DeleteDenyException if a DENY delete rule is applicable for > object > + * deletion. > + * @throws NullPointerException if object is null. > + */ > + public void deleteObject(Object object) { > + new ObjectContextDeleteAction(this).performDelete((Persistent) > object); > + } > + > + public void deleteObjects(Collection<?> objects) throws > DeleteDenyException { > + if (objects.isEmpty()) > + return; > + > + // Don't call deleteObject() directly since it would be less > efficient. > + ObjectContextDeleteAction ocda = new > ObjectContextDeleteAction(this); > + > + // Make a copy to iterate over to avoid > ConcurrentModificationException. > + for (Persistent object : (ArrayList<Persistent>) new > ArrayList(objects)) > + ocda.performDelete(object); > } > } > \ No newline at end of file > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java > Wed Nov 18 12:08:20 2009 > @@ -308,27 +308,6 @@ > } > > /** > - * Deletes an object locally, scheduling it for future deletion from > the external data > - * store. > - */ > - @Override > - public void deleteObject(Object object) { > - new ObjectContextDeleteAction(this).performDelete((Persistent) > object); > - } > - > - public void deleteObjects(Collection<?> objects) throws > DeleteDenyException { > - if (objects.isEmpty()) > - return; > - > - // Don't call deleteObject() directly since it would be less > efficient. > - ObjectContextDeleteAction ocda = new > ObjectContextDeleteAction(this); > - > - // Make a copy to iterate over to avoid > ConcurrentModificationException. > - for (Persistent object : (ArrayList<Persistent>) new > ArrayList(objects)) > - ocda.performDelete(object); > - } > - > - /** > * Creates and registers a new Persistent object instance. > */ > @Override > @@ -527,16 +506,6 @@ > object.setObjectId(id); > } > > - // must follow this exact order of property initialization per > CAY-653, i.e. have > - // the id and the context in place BEFORE setPersistence is called > - object.setObjectContext(this); > - object.setPersistenceState(PersistenceState.NEW); > - > - synchronized (graphManager) { > - graphManager.registerNode(id, object); > - graphManager.nodeCreated(id); > - } > - > injectInitialValue(object); > } > > > Copied: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java > (from r881253, > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataChannelSyncCallbackAction.java) > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java?p2=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java&p1=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataChannelSyncCallbackAction.java&r1=881253&r2=881740&rev=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataChannelSyncCallbackAction.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java > Wed Nov 18 12:08:20 2009 > @@ -16,14 +16,13 @@ > * specific language governing permissions and limitations > * under the License. > ****************************************************************/ > -package org.apache.cayenne.access; > +package org.apache.cayenne; > > import java.util.ArrayList; > import java.util.Collection; > import java.util.HashSet; > import java.util.Set; > > -import org.apache.cayenne.DataChannel; > import org.apache.cayenne.graph.GraphChangeHandler; > import org.apache.cayenne.graph.GraphDiff; > import org.apache.cayenne.graph.GraphManager; > @@ -32,10 +31,11 @@ > > /** > * @since 3.0 > + * note: made public in 3.1 to be used in all tiers > */ > -abstract class DataChannelSyncCallbackAction implements GraphChangeHandler > { > +public abstract class DataChannelSyncCallbackAction implements > GraphChangeHandler { > > - static DataChannelSyncCallbackAction getCallbackAction( > + public static DataChannelSyncCallbackAction getCallbackAction( > LifecycleCallbackRegistry callbackRegistry, > GraphManager graphManager, > GraphDiff changes, > @@ -73,9 +73,9 @@ > > protected abstract boolean hasListeners(); > > - abstract void applyPreCommit(); > + public abstract void applyPreCommit(); > > - abstract void applyPostCommit(); > + public abstract void applyPostCommit(); > > void apply(LifecycleEvent callbackType, Collection<?> objects) { > if (seenIds != null && objects != null) { > @@ -166,13 +166,13 @@ > } > > @Override > - void applyPreCommit() { > + public void applyPreCommit() { > apply(LifecycleEvent.PRE_PERSIST, persisted); > apply(LifecycleEvent.PRE_UPDATE, updated); > } > > @Override > - void applyPostCommit() { > + public void applyPostCommit() { > apply(LifecycleEvent.POST_UPDATE, updated); > apply(LifecycleEvent.POST_REMOVE, removed); > apply(LifecycleEvent.POST_PERSIST, persisted); > @@ -192,12 +192,12 @@ > } > > @Override > - void applyPreCommit() { > + public void applyPreCommit() { > // noop > } > > @Override > - void applyPostCommit() { > + public void applyPostCommit() { > apply(LifecycleEvent.POST_LOAD, updated); > apply(LifecycleEvent.POST_LOAD, removed); > } > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ObjectContextDeleteAction.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ObjectContextDeleteAction.java?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ObjectContextDeleteAction.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ObjectContextDeleteAction.java > Wed Nov 18 12:08:20 2009 > @@ -23,14 +23,14 @@ > import java.util.Collection; > import java.util.Collections; > import java.util.Iterator; > +import java.util.Map; > > import org.apache.cayenne.map.DeleteRule; > -import org.apache.cayenne.map.ObjEntity; > +import org.apache.cayenne.map.LifecycleEvent; > import org.apache.cayenne.map.ObjRelationship; > import org.apache.cayenne.reflect.ArcProperty; > import org.apache.cayenne.reflect.AttributeProperty; > import org.apache.cayenne.reflect.ClassDescriptor; > -import org.apache.cayenne.reflect.Property; > import org.apache.cayenne.reflect.PropertyVisitor; > import org.apache.cayenne.reflect.ToManyProperty; > import org.apache.cayenne.reflect.ToOneProperty; > @@ -54,6 +54,10 @@ > > if (oldState == PersistenceState.TRANSIENT > || oldState == PersistenceState.DELETED) { > + // Drop out... especially in case of DELETED we might be about > to get > + // into a horrible recursive loop due to CASCADE delete rules. > + // Assume that everything must have been done correctly > already > + // and *don't* do it again > return false; > } > > @@ -69,6 +73,11 @@ > + ", context: " > + context); > } > + > + // must resolve HOLLOW objects before delete... needed > + // to process relationships and optimistic locking... > + > + context.prepareForAccess(object, null, false); > > if (oldState == PersistenceState.NEW) { > deleteNew(object); > @@ -80,133 +89,148 @@ > return true; > } > > - private void deleteNew(Persistent object) { > + private void deleteNew(Persistent object) throws DeleteDenyException { > object.setPersistenceState(PersistenceState.TRANSIENT); > processDeleteRules(object, PersistenceState.NEW); > + > + // if an object was NEW, we must throw it out > context.getGraphManager().unregisterNode(object.getObjectId()); > } > > - private void deletePersistent(Persistent object) { > + private void deletePersistent(Persistent object) throws > DeleteDenyException { > + > context.getEntityResolver().getCallbackRegistry().performCallbacks( > + LifecycleEvent.PRE_REMOVE, > + object); > + > int oldState = object.getPersistenceState(); > object.setPersistenceState(PersistenceState.DELETED); > processDeleteRules(object, oldState); > context.getGraphManager().nodeRemoved(object.getObjectId()); > } > > - private void processDeleteRules(final Persistent object, final int > oldState) { > + private Collection toCollection(Object object) { > > - String entityName = object.getObjectId().getEntityName(); > - final ObjEntity entity = > context.getEntityResolver().getObjEntity(entityName); > - ClassDescriptor descriptor = > context.getEntityResolver().getClassDescriptor( > - entityName); > + if (object == null) { > + return Collections.EMPTY_LIST; > + } > > - descriptor.visitProperties(new PropertyVisitor() { > + // create copies of collections to avoid iterator exceptions > + if (object instanceof Collection) { > + return new ArrayList((Collection) object); > + } > + else if (object instanceof Map) { > + return new ArrayList(((Map) object).values()); > + } > + else { > + return Collections.singleton(object); > + } > + } > > - public boolean visitToMany(ToManyProperty property) { > - ObjRelationship relationship = (ObjRelationship) entity > - .getRelationship(property.getName()); > + private void processDeleteRules(final Persistent object, int oldState) > + throws DeleteDenyException { > > - processRules(object, property, > relationship.getDeleteRule(), oldState); > - return true; > - } > + ClassDescriptor descriptor = > context.getEntityResolver().getClassDescriptor( > + object.getObjectId().getEntityName()); > > - public boolean visitToOne(ToOneProperty property) { > - ObjRelationship relationship = (ObjRelationship) entity > - .getRelationship(property.getName()); > + for (final ObjRelationship relationship : > descriptor.getEntity().getRelationships()) { > > - processRules(object, property, > relationship.getDeleteRule(), oldState); > - return true; > - } > + boolean processFlattened = relationship.isFlattened() > + && relationship.isToDependentEntity() > + && !relationship.isReadOnly(); > > - public boolean visitAttribute(AttributeProperty property) { > - return true; > + // first check for no action... bail out if no flattened > processing is needed > + if (relationship.getDeleteRule() == DeleteRule.NO_ACTION && > !processFlattened) { > + continue; > } > - }); > - } > - > - private void processRules( > - Persistent object, > - ArcProperty property, > - int deleteRule, > - int oldState) { > - > - if (deleteRule == DeleteRule.NO_ACTION) { > - return; > - } > - > - Collection<?> relatedObjects = relatedObjects(object, property); > - if (relatedObjects.isEmpty()) { > - return; > - } > > - switch (deleteRule) { > + ArcProperty property = (ArcProperty) > descriptor.getProperty(relationship > + .getName()); > + Collection relatedObjects = > toCollection(property.readProperty(object)); > + > + // no related object, bail out > + if (relatedObjects.size() == 0) { > + continue; > + } > > - case DeleteRule.DENY: > + // process DENY rule first... > + if (relationship.getDeleteRule() == DeleteRule.DENY) { > object.setPersistenceState(oldState); > + > String message = relatedObjects.size() == 1 > ? "1 related object" > : relatedObjects.size() + " related objects"; > - throw new DeleteDenyException(object, property.getName(), > message); > - > - case DeleteRule.NULLIFY: > - ArcProperty reverseArc = > property.getComplimentaryReverseArc(); > + throw new DeleteDenyException(object, > relationship.getName(), message); > + } > > - if (reverseArc != null) { > + // process flattened with dependent join tables... > + // joins must be removed even if they are non-existent or > ignored in the > + // object graph > + if (processFlattened) { > + Iterator iterator = relatedObjects.iterator(); > + while (iterator.hasNext()) { > + Persistent relatedObject = (Persistent) > iterator.next(); > + > context.getGraphManager().arcDeleted(object.getObjectId(), relatedObject > + .getObjectId(), relationship.getName()); > + } > + } > > - if (reverseArc instanceof ToManyProperty) { > - for (Object relatedObject : relatedObjects) { > - ((ToManyProperty) reverseArc).removeTarget( > - relatedObject, > - object, > - true); > - } > + // process remaining rules > + switch (relationship.getDeleteRule()) { > + case DeleteRule.NO_ACTION: > + break; > + case DeleteRule.NULLIFY: > + ArcProperty reverseArc = > property.getComplimentaryReverseArc(); > + > + if (reverseArc == null) { > + // nothing we can do here > + break; > } > - else { > - for (Object relatedObject : relatedObjects) { > - ((ToOneProperty) reverseArc).setTarget( > - relatedObject, > - null, > - true); > - } > - } > - } > > - break; > - case DeleteRule.CASCADE: > + final Collection finalRelatedObjects = relatedObjects; > > - Iterator<?> iterator = relatedObjects.iterator(); > - while (iterator.hasNext()) { > - Persistent relatedObject = (Persistent) > iterator.next(); > + reverseArc.visit(new PropertyVisitor() { > > - // this action object is stateless, so we can use > 'performDelete' > - // recursively. > - performDelete(relatedObject); > - } > + public boolean visitAttribute(AttributeProperty > property) { > + return false; > + } > > - break; > - default: > - object.setPersistenceState(oldState); > - throw new CayenneRuntimeException("Invalid delete rule: " > + deleteRule); > - } > - } > + public boolean visitToMany(ToManyProperty > property) { > + Iterator iterator = > finalRelatedObjects.iterator(); > + while (iterator.hasNext()) { > + Object relatedObject = iterator.next(); > + property.removeTarget(relatedObject, > object, true); > + } > > - private Collection<?> relatedObjects(Object object, Property property) > { > - Object related = property.readProperty(object); > + return false; > + } > > - if (related == null) { > - return Collections.EMPTY_LIST; > - } > - // return collections by copy, to allow removal of objects from > the underlying > - // relationship inside the iterator > - else if (property instanceof ToManyProperty) { > - Collection<?> relatedCollection = (Collection<?>) related; > - return relatedCollection.isEmpty() > - ? Collections.EMPTY_LIST > - : new ArrayList<Object>(relatedCollection); > - } > - // TODO: andrus 11/21/2007 - ToManyMapProperty check > - else { > - return Collections.singleton(related); > + public boolean visitToOne(ToOneProperty property) > { > + // Inverse is to-one - find all related > objects and > + // nullify the reverse relationship > + Iterator iterator = > finalRelatedObjects.iterator(); > + while (iterator.hasNext()) { > + Object relatedObject = iterator.next(); > + property.setTarget(relatedObject, null, > true); > + } > + return false; > + } > + }); > + > + break; > + case DeleteRule.CASCADE: > + // Delete all related objects > + Iterator iterator = relatedObjects.iterator(); > + while (iterator.hasNext()) { > + Persistent relatedObject = (Persistent) > iterator.next(); > + performDelete(relatedObject); > + } > + > + break; > + default: > + object.setPersistenceState(oldState); > + throw new CayenneRuntimeException("Invalid delete rule > " > + + relationship.getDeleteRule()); > + } > } > } > } > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java > Wed Nov 18 12:08:20 2009 > @@ -35,7 +35,6 @@ > import org.apache.cayenne.DataChannel; > import org.apache.cayenne.DataObject; > import org.apache.cayenne.DataRow; > -import org.apache.cayenne.DeleteDenyException; > import org.apache.cayenne.Fault; > import org.apache.cayenne.ObjectContext; > import org.apache.cayenne.ObjectId; > @@ -54,7 +53,6 @@ > import org.apache.cayenne.map.DbJoin; > import org.apache.cayenne.map.DbRelationship; > import org.apache.cayenne.map.EntityResolver; > -import org.apache.cayenne.map.LifecycleEvent; > import org.apache.cayenne.map.ObjAttribute; > import org.apache.cayenne.map.ObjEntity; > import org.apache.cayenne.map.ObjRelationship; > @@ -629,18 +627,9 @@ > // note that the order of initialization of persistence artifacts > below is > // important - do not change it lightly > object.setObjectId(id); > - object.setObjectContext(this); > - object.setPersistenceState(PersistenceState.NEW); > - getObjectStore().registerNode(id, object); > - getObjectStore().nodeCreated(id); > > injectInitialValue(object); > > - // invoke callbacks > - getEntityResolver().getCallbackRegistry().performCallbacks( > - LifecycleEvent.POST_ADD, > - object); > - > return object; > } > > @@ -684,21 +673,17 @@ > else { > persistent.setObjectId(new ObjectId(entity.getName())); > } > - > - persistent.setObjectContext(this); > - persistent.setPersistenceState(PersistenceState.NEW); > - > - getObjectStore().registerNode(persistent.getObjectId(), object); > - getObjectStore().nodeCreated(persistent.getObjectId()); > - > - // now we need to find all arc changes, inject missing value > holders and pull in > - // all transient connected objects > - > + > ClassDescriptor descriptor = > getEntityResolver().getClassDescriptor( > entity.getName()); > if (descriptor == null) { > throw new IllegalArgumentException("Invalid entity name: " + > entity.getName()); > } > + > + injectInitialValue(object); > + > + // now we need to find all arc changes, inject missing value > holders and pull in > + // all transient connected objects > > descriptor.visitProperties(new PropertyVisitor() { > > @@ -752,13 +737,6 @@ > return true; > } > }); > - > - injectInitialValue(object); > - > - // invoke callbacks > - getEntityResolver().getCallbackRegistry().performCallbacks( > - LifecycleEvent.POST_ADD, > - persistent); > } > > /** > @@ -773,48 +751,6 @@ > } > > /** > - * Schedules all objects in the collection for deletion on the next > commit of this > - * DataContext. Object's persistence state is changed to > PersistenceState.DELETED; > - * objects related to this object are processed according to delete > rules, i.e. > - * relationships can be unset ("nullify" rule), deletion operation is > cascaded > - * (cascade rule). > - * <p> > - * <i>"Nullify" delete rule side effect: </i> passing a collection > representing > - * to-many relationship with nullify delete rule may result in objects > being removed > - * from collection. > - * </p> > - * > - * @since 1.2 > - */ > - public void deleteObjects(Collection objects) { > - if (objects.isEmpty()) { > - return; > - } > - > - // clone object list... this maybe a relationship collection with > nullify delete > - // rule, so modifying > - for (Persistent object : new ArrayList<Persistent>(objects)) { > - deleteObject(object); > - } > - } > - > - /** > - * Schedules an object for deletion on the next commit of this > DataContext. Object's > - * persistence state is changed to PersistenceState.DELETED; objects > related to this > - * object are processed according to delete rules, i.e. relationships > can be unset > - * ("nullify" rule), deletion operation is cascaded (cascade rule). > - * > - * @param object a persistent object that we want to delete. > - * @throws DeleteDenyException if a DENY delete rule is applicable for > object > - * deletion. > - * @throws NullPointerException if object is null. > - */ > - @Override > - public void deleteObject(Object object) throws DeleteDenyException { > - new DataContextDeleteAction(this).performDelete((Persistent) > object); > - } > - > - /** > * If the parent channel is a DataContext, reverts local changes to > make this context > * look like the parent, if the parent channel is a DataDomain, reverts > all changes. > * > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java > Wed Nov 18 12:08:20 2009 > @@ -28,6 +28,7 @@ > > import org.apache.cayenne.CayenneRuntimeException; > import org.apache.cayenne.DataChannel; > +import org.apache.cayenne.DataChannelSyncCallbackAction; > import org.apache.cayenne.ObjectContext; > import org.apache.cayenne.QueryResponse; > import org.apache.cayenne.access.jdbc.BatchQueryBuilderFactory; > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackRegistry.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackRegistry.java?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackRegistry.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackRegistry.java > Wed Nov 18 12:08:20 2009 > @@ -99,6 +99,7 @@ > */ > public void addListener(Class<?> entityClass, LifecycleListener > listener) { > addListener(LifecycleEvent.POST_ADD, entityClass, listener, > "postAdd"); > + addListener(LifecycleEvent.POST_PERSIST, entityClass, listener, > "prePersist"); > addListener(LifecycleEvent.POST_PERSIST, entityClass, listener, > "postPersist"); > addListener(LifecycleEvent.PRE_REMOVE, entityClass, listener, > "preRemove"); > addListener(LifecycleEvent.POST_REMOVE, entityClass, listener, > "postRemove"); > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/ClientChannel.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/ClientChannel.java?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/ClientChannel.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/ClientChannel.java > Wed Nov 18 12:08:20 2009 > @@ -24,6 +24,7 @@ > > import org.apache.cayenne.CayenneRuntimeException; > import org.apache.cayenne.DataChannel; > +import org.apache.cayenne.DataChannelSyncCallbackAction; > import org.apache.cayenne.ObjectContext; > import org.apache.cayenne.ObjectId; > import org.apache.cayenne.Persistent; > @@ -169,6 +170,14 @@ > ObjectContext originatingContext, > GraphDiff changes, > int syncType) { > + > + DataChannelSyncCallbackAction callbackAction = > DataChannelSyncCallbackAction > + .getCallbackAction( > + getEntityResolver().getCallbackRegistry(), > + originatingContext.getGraphManager(), > + changes, > + syncType); > + callbackAction.applyPreCommit(); > > changes = diffCompressor.compress(changes); > > @@ -221,6 +230,7 @@ > } > } > > + callbackAction.applyPostCommit(); > return replyDiff; > } > > > Added: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/RemoteCallbacksTest.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/RemoteCallbacksTest.java?rev=881740&view=auto > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/RemoteCallbacksTest.java > (added) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/RemoteCallbacksTest.java > Wed Nov 18 12:08:20 2009 > @@ -0,0 +1,114 @@ > +/***************************************************************** > + * Licensed to the Apache Software Foundation (ASF) under one > + * or more contributor license agreements. See the NOTICE file > + * distributed with this work for additional information > + * regarding copyright ownership. The ASF licenses this file > + * to you under the Apache License, Version 2.0 (the > + * "License"); you may not use this file except in compliance > + * with the License. You may obtain a copy of the License at > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, > + * software distributed under the License is distributed on an > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY > + * KIND, either express or implied. See the License for the > + * specific language governing permissions and limitations > + * under the License. > + ****************************************************************/ > +package org.apache.cayenne.remote; > + > +import org.apache.cayenne.LifecycleListener; > +import org.apache.cayenne.ObjectContext; > +import org.apache.cayenne.testdo.mt.ClientMtLifecycles; > + > +public class RemoteCallbacksTest extends RemoteCayenneCase implements > LifecycleListener { > + private int added, loaded, prePersisted, postPersisted, preRemoved, > postRemoved, preUpdated, postUpdated; > + > + @Override > + public void setUp() throws Exception { > + super.setUp(); > + added = 0; > + loaded = 0; > + prePersisted = 0; > + postPersisted = 0; > + preRemoved = 0; > + postRemoved = 0; > + preUpdated = 0; > + postUpdated = 0; > + } > + > + public void testDefault() throws InterruptedException { > + ObjectContext context = createROPContext(); > + > > context.getEntityResolver().getCallbackRegistry().addListener(ClientMtLifecycles.class, > this); > + > + assertAll(0, 0, 0, 0, 0, 0, 0, 0); > + ClientMtLifecycles l1 = > context.newObject(ClientMtLifecycles.class); > + > + assertAll(1, 0, 0, 0, 0, 0, 0, 0); > + l1.setName("x"); > + assertAll(1, 0, 0, 0, 0, 0, 0, 0); > + > + context.commitChanges(); > + Thread.sleep(5); //until commit > + assertAll(1, 0, 1, 1, 0, 0, 0, 0); > + > + l1.setName("x2"); > + assertAll(1, 0, 1, 1, 0, 0, 0, 0); > + > + context.commitChanges(); > + Thread.sleep(5); //until commit > + assertAll(1, 0, 1, 1, 1, 1, 0, 0); > + > + context.deleteObject(l1); > + assertAll(1, 0, 1, 1, 1, 1, 1, 0); > + > + context.commitChanges(); > + Thread.sleep(5); //until commit > + assertAll(1, 0, 1, 1, 1, 1, 1, 1); > + } > + > + private void assertAll(int added, int loaded, int prePersisted, int > postPersisted, > + int preUpdated, int postUpdated, int preRemoved, int > postRemoved) { > + assertEquals(this.added, added); > + assertEquals(this.loaded, loaded); > + assertEquals(this.prePersisted, prePersisted); > + assertEquals(this.postPersisted, postPersisted); > + assertEquals(this.preRemoved, preRemoved); > + assertEquals(this.postRemoved, postRemoved); > + assertEquals(this.preUpdated, preUpdated); > + assertEquals(this.postUpdated, postUpdated); > + } > + > + public void postAdd(Object entity) { > + added++; > + } > + > + public void postLoad(Object entity) { > + loaded++; > + } > + > + public void postPersist(Object entity) { > + postPersisted++; > + } > + > + public void postRemove(Object entity) { > + postRemoved++; > + } > + > + public void postUpdate(Object entity) { > + postUpdated++; > + } > + > + public void prePersist(Object entity) { > + prePersisted++; > + } > + > + public void preRemove(Object entity) { > + preRemoved++; > + } > + > + public void preUpdate(Object entity) { > + preUpdated++; > + } > +} > > Added: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/ClientMtLifecycles.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/ClientMtLifecycles.java?rev=881740&view=auto > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/ClientMtLifecycles.java > (added) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/ClientMtLifecycles.java > Wed Nov 18 12:08:20 2009 > @@ -0,0 +1,10 @@ > +package org.apache.cayenne.testdo.mt; > + > +import org.apache.cayenne.testdo.mt.auto._ClientMtLifecycles; > + > +/** > + * A persistent class mapped as "MtLifecycles" Cayenne entity. > + */ > +public class ClientMtLifecycles extends _ClientMtLifecycles { > + > +} > > Added: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/MtLifecycles.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/MtLifecycles.java?rev=881740&view=auto > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/MtLifecycles.java > (added) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/MtLifecycles.java > Wed Nov 18 12:08:20 2009 > @@ -0,0 +1,7 @@ > +package org.apache.cayenne.testdo.mt; > + > +import org.apache.cayenne.testdo.mt.auto._MtLifecycles; > + > +public class MtLifecycles extends _MtLifecycles { > + > +} > > Added: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMtLifecycles.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMtLifecycles.java?rev=881740&view=auto > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMtLifecycles.java > (added) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMtLifecycles.java > Wed Nov 18 12:08:20 2009 > @@ -0,0 +1,37 @@ > +package org.apache.cayenne.testdo.mt.auto; > + > +import org.apache.cayenne.PersistentObject; > + > +/** > + * A generated persistent class mapped as "MtLifecycles" Cayenne entity. > It is a good idea to > + * avoid changing this class manually, since it will be overwritten next > time code is > + * regenerated. If you need to make any customizations, put them in a > subclass. > + */ > +public abstract class _ClientMtLifecycles extends PersistentObject { > + > + public static final String NAME_PROPERTY = "name"; > + > + protected String name; > + > + public String getName() { > + if(objectContext != null) { > + objectContext.prepareForAccess(this, "name", false); > + } > + > + return name; > + } > + public void setName(String name) { > + if(objectContext != null) { > + objectContext.prepareForAccess(this, "name", false); > + } > + > + Object oldValue = this.name; > + this.name = name; > + > + // notify objectContext about simple property change > + if(objectContext != null) { > + objectContext.propertyChanged(this, "name", oldValue, name); > + } > + } > + > +} > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMultiTier.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMultiTier.java?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMultiTier.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_ClientMultiTier.java > Wed Nov 18 12:08:20 2009 > @@ -5,7 +5,7 @@ > import org.apache.cayenne.ObjectContext; > import org.apache.cayenne.PersistentObject; > import org.apache.cayenne.query.NamedQuery; > -import org.apache.cayenne.testdo.mt.ClientMtTable1; > +import org.apache.cayenne.testdo.mt.MtTable1; > > /** > * This class was generated by Cayenne. > @@ -15,15 +15,21 @@ > */ > public class _ClientMultiTier { > > - public List<ClientMtTable1> performAllMtTable1(ObjectContext context ) > { > + public static final String ALL_MT_TABLE1_QUERYNAME = "AllMtTable1"; > + > + public static final String MT_QUERY_WITH_LOCAL_CACHE_QUERYNAME = > "MtQueryWithLocalCache"; > + > + public static final String > PARAMETERIZED_MT_QUERY_WITH_LOCAL_CACHE_QUERYNAME = > "ParameterizedMtQueryWithLocalCache"; > + > + public List<MtTable1> performAllMtTable1(ObjectContext context ) { > return context.performQuery(new NamedQuery("AllMtTable1")); > } > > - public List<ClientMtTable1> performMtQueryWithLocalCache(ObjectContext > context ) { > + public List<MtTable1> performMtQueryWithLocalCache(ObjectContext > context ) { > return context.performQuery(new > NamedQuery("MtQueryWithLocalCache")); > } > > - public List<ClientMtTable1> > performParameterizedMtQueryWithLocalCache(ObjectContext context , String g) > { > + public List<MtTable1> > performParameterizedMtQueryWithLocalCache(ObjectContext context , String g) > { > String[] parameters = { > "g", > }; > > Added: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MtLifecycles.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MtLifecycles.java?rev=881740&view=auto > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MtLifecycles.java > (added) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MtLifecycles.java > Wed Nov 18 12:08:20 2009 > @@ -0,0 +1,23 @@ > +package org.apache.cayenne.testdo.mt.auto; > + > +import org.apache.cayenne.CayenneDataObject; > + > +/** > + * Class _MtLifecycles was generated by Cayenne. > + * It is probably a good idea to avoid changing this class manually, > + * since it may be overwritten next time code is regenerated. > + * If you need to make any customizations, please use subclass. > + */ > +public abstract class _MtLifecycles extends CayenneDataObject { > + > + public static final String NAME_PROPERTY = "name"; > + > + > + public void setName(String name) { > + writeProperty("name", name); > + } > + public String getName() { > + return (String)readProperty("name"); > + } > + > +} > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MultiTier.java > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MultiTier.java?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MultiTier.java > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/mt/auto/_MultiTier.java > Wed Nov 18 12:08:20 2009 > @@ -14,6 +14,12 @@ > */ > public class _MultiTier { > > + public static final String ALL_MT_TABLE1_QUERYNAME = "AllMtTable1"; > + > + public static final String MT_QUERY_WITH_LOCAL_CACHE_QUERYNAME = > "MtQueryWithLocalCache"; > + > + public static final String > PARAMETERIZED_MT_QUERY_WITH_LOCAL_CACHE_QUERYNAME = > "ParameterizedMtQueryWithLocalCache"; > + > public List<MtTable1> performAllMtTable1(ObjectContext context ) { > return context.performQuery(new NamedQuery("AllMtTable1")); > } > > Modified: > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/multi-tier.map.xml > URL: > http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/multi-tier.map.xml?rev=881740&r1=881739&r2=881740&view=diff > > ============================================================================== > --- > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/multi-tier.map.xml > (original) > +++ > cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/multi-tier.map.xml > Wed Nov 18 12:08:20 2009 > @@ -29,6 +29,10 @@ > <db-attribute name="TABLE4_ID" type="INTEGER" > isPrimaryKey="true" isMandatory="true"/> > <db-attribute name="TABLE5_ID" type="INTEGER" > isPrimaryKey="true" isMandatory="true"/> > </db-entity> > + <db-entity name="MT_LIFECYCLES"> > + <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" > isMandatory="true"/> > + <db-attribute name="NAME" type="VARCHAR" isMandatory="true" > length="100"/> > + </db-entity> > <db-entity name="MT_MAP_TO_MANY"> > <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" > isMandatory="true"/> > </db-entity> > @@ -91,6 +95,9 @@ > <obj-entity name="MtDeleteRule" > className="org.apache.cayenne.testdo.mt.MtDeleteRule" > clientClassName="org.apache.cayenne.testdo.mt.ClientMtDeleteRule" > dbEntityName="MT_DELETE_RULE"> > <obj-attribute name="name" type="java.lang.String" > db-attribute-path="NAME"/> > </obj-entity> > + <obj-entity name="MtLifecycles" > className="org.apache.cayenne.testdo.mt.MtLifecycles" > clientClassName="org.apache.cayenne.testdo.mt.ClientMtLifecycles" > dbEntityName="MT_LIFECYCLES"> > + <obj-attribute name="name" type="java.lang.String" > db-attribute-path="NAME"/> > + </obj-entity> > <obj-entity name="MtMapToMany" > className="org.apache.cayenne.testdo.mt.MtMapToMany" > clientClassName="org.apache.cayenne.testdo.mt.ClientMtMapToMany" > dbEntityName="MT_MAP_TO_MANY"> > </obj-entity> > <obj-entity name="MtMapToManyTarget" > className="org.apache.cayenne.testdo.mt.MtMapToManyTarget" > clientClassName="org.apache.cayenne.testdo.mt.ClientMtMapToManyTarget" > dbEntityName="MT_MAP_TO_MANY_TARGET"> > > > -- Olga Tkacheva
