Author: aadamchik
Date: Wed Sep 20 20:35:14 2006
New Revision: 448447
URL: http://svn.apache.org/viewvc?view=rev&rev=448447
Log:
CAY-660 fixing callback storage - must be stored by entity; adding interceptor
tests
Added:
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptorTst.java
Modified:
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptor.java
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Artist.java
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Painting.java
Modified:
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptor.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptor.java?view=diff&rev=448447&r1=448446&r2=448447
==============================================================================
---
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptor.java
(original)
+++
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptor.java
Wed Sep 20 20:35:14 2006
@@ -20,7 +20,9 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import org.apache.cayenne.DeleteDenyException;
import org.apache.cayenne.PersistenceState;
@@ -32,11 +34,11 @@
import org.apache.commons.collections.Closure;
/**
- * Implements JPA-compliant "PrePersist", "PreRemove", "PreUpdate" callbacks
for the
- * ObjectContext operations. Callbacks can be invoked either on the persistent
object
- * instances themselves or on an instance of an arbitrary class. Signature of
a method of
- * a persistent object is {code}"void method()"{code}, while for a
non-persistent object
- * it is {code}"void method(Object)"{code}. Note that if a new object is later
removed,
+ * Implements JPA-compliant "PrePersist", "PreRemove" callbacks for the
ObjectContext
+ * operations. Callbacks can be invoked either on the persistent object
instances
+ * themselves or on an instance of an arbitrary class. Signature of a method
of a
+ * persistent object is {code}"void method()"{code}, while for a
non-persistent object it
+ * is {code}"void method(Object)"{code}. Note that if a new object is later
removed,
* "PrePersist" callbacks will be invoked, while "PreRemove" will not.
*
* @since 3.0
@@ -44,9 +46,12 @@
*/
public class ObjectContextCallbackInterceptor extends ObjectContextDecorator {
- protected Collection prePersistCallbacks;
- protected Collection preRemoveCallbacks;
- protected Collection preUpdateCallbacks;
+ static final int PRE_PERSIST_INDEX = 0;
+ static final int PRE_REMOVE_INDEX = 1;
+
+ private static final int CALLBACK_SIZE = 2;
+
+ protected Map callbacks = new HashMap();
/**
* Creates a new object, applying "PrePersist" callbacks to it.
@@ -54,9 +59,7 @@
public Persistent newObject(Class persistentClass) {
Persistent object = super.newObject(persistentClass);
- if (prePersistCallbacks != null) {
- applyCallbacks(prePersistCallbacks, object);
- }
+ applyCallbacks(getCallbacks(persistentClass, PRE_PERSIST_INDEX),
object);
return object;
}
@@ -66,54 +69,59 @@
* dependencies.
*/
public void deleteObject(Persistent object) throws DeleteDenyException {
-
- if (preRemoveCallbacks != null
- && object.getPersistenceState() != PersistenceState.NEW) {
- applyPreRemoveCallbacks(object);
- }
-
+ applyPreRemoveCallbacks(object);
super.deleteObject(object);
}
- public void commitChanges() {
- if (preUpdateCallbacks != null) {
- applyPreUpdateCallbacks();
- }
-
- super.commitChanges();
+ public void addPrePersistCallback(Class entityClass, String methodName) {
+ addCallback(
+ entityClass,
+ new EntityCallback(entityClass, methodName),
+ PRE_PERSIST_INDEX);
}
- public void commitChangesToParent() {
+ public void addPrePersistCallback(
+ Class objectClass,
+ String methodName,
+ Class entityClass) {
- if (preUpdateCallbacks != null) {
- applyPreUpdateCallbacks();
- }
+ addCallback(entityClass, new ListenerCallback(
+ objectClass,
+ methodName,
+ entityClass), PRE_PERSIST_INDEX);
+ }
- super.commitChangesToParent();
+ public void addPreRemoveCallback(Class entityClass, String methodName) {
+ addCallback(
+ entityClass,
+ new EntityCallback(entityClass, methodName),
+ PRE_REMOVE_INDEX);
}
- protected void applyPreUpdateCallbacks() {
- Collection callbacks = getPreUpdateCallbacks();
+ public void addPreRemoveCallback(
+ Class objectClass,
+ String methodName,
+ Class entityClass) {
- Iterator it = context.modifiedObjects().iterator();
- while (it.hasNext()) {
- applyCallbacks(callbacks, it.next());
- }
+ addCallback(entityClass, new ListenerCallback(
+ objectClass,
+ methodName,
+ entityClass), PRE_REMOVE_INDEX);
}
/**
* Recursively applies PreRemove callbacks to an object and objects that
will be
* cascaded
*/
- protected void applyPreRemoveCallbacks(Object object) {
-
- Collection callbacks = getPreRemoveCallbacks();
+ void applyPreRemoveCallbacks(Persistent object) {
- applyCallbacks(callbacks, object);
+ if (object.getPersistenceState() != PersistenceState.NEW) {
+ applyCallbacks(getCallbacks(object.getClass(), PRE_REMOVE_INDEX),
object);
+ }
ObjEntity entity = getEntityResolver().lookupObjEntity(object);
ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(
- entity.getClassName());
+ entity.getName());
Iterator it = entity.getRelationships().iterator();
while (it.hasNext()) {
@@ -131,101 +139,50 @@
else if (related instanceof Collection) {
Iterator relatedObjects = ((Collection)
related).iterator();
while (relatedObjects.hasNext()) {
- applyPreRemoveCallbacks(relatedObjects.next());
+ applyPreRemoveCallbacks((Persistent)
relatedObjects.next());
}
}
else {
- applyPreRemoveCallbacks(related);
+ applyPreRemoveCallbacks((Persistent) related);
}
}
}
}
- protected void applyCallbacks(Collection callbacks, Object object) {
- Iterator it = (Iterator) callbacks.iterator();
- while (it.hasNext()) {
- ((Closure) it.next()).execute(object);
- }
- }
-
- public void addPrePersistCallback(Class objectClass, String methodName) {
- getPrePersistCallbacks().add(new EntityCallback(objectClass,
methodName));
- }
-
- public void addPrePersistCallback(
- Class objectClass,
- String methodName,
- Class entityClass) {
-
- ObjEntity entity =
context.getEntityResolver().lookupObjEntity(entityClass);
- if (entity == null) {
- throw new IllegalArgumentException(entityClass.getName()
- + " is not a persistent entity");
- }
-
- getPrePersistCallbacks().add(
- new ListenerCallback(objectClass, methodName,
entity.getJavaClass()));
- }
-
- public void addPreRemoveCallback(Class objectClass, String methodName) {
- getPreRemoveCallbacks().add(new EntityCallback(objectClass,
methodName));
- }
-
- public void addPreRemoveCallback(
- Class objectClass,
- String methodName,
- Class entityClass) {
-
- ObjEntity entity =
context.getEntityResolver().lookupObjEntity(entityClass);
- if (entity == null) {
- throw new IllegalArgumentException(entityClass.getName()
- + " is not a persistent entity");
+ /**
+ * Utility method applying callbacks to a collection.
+ */
+ void applyCallbacks(Collection callbacks, Object object) {
+ if (callbacks != null) {
+ Iterator it = (Iterator) callbacks.iterator();
+ while (it.hasNext()) {
+ ((Closure) it.next()).execute(object);
+ }
}
-
- getPreRemoveCallbacks().add(
- new ListenerCallback(objectClass, methodName,
entity.getJavaClass()));
}
- public void addPreUpdateCallback(Class objectClass, String methodName) {
- getPreUpdateCallbacks().add(new EntityCallback(objectClass,
methodName));
- }
-
- public void addPreUpdateCallback(
- Class objectClass,
- String methodName,
- Class entityClass) {
+ Collection getCallbacks(Class entityClass, int callbackType) {
- ObjEntity entity =
context.getEntityResolver().lookupObjEntity(entityClass);
- if (entity == null) {
- throw new IllegalArgumentException(entityClass.getName()
- + " is not a persistent entity");
- }
+ Collection[] entityCallbacks = (Collection[]) callbacks
+ .get(entityClass.getName());
- getPreRemoveCallbacks().add(
- new ListenerCallback(objectClass, methodName,
entity.getJavaClass()));
+ return (entityCallbacks != null) ? entityCallbacks[callbackType] :
null;
}
- protected Collection getPrePersistCallbacks() {
- if (prePersistCallbacks == null) {
- prePersistCallbacks = new ArrayList();
- }
+ void addCallback(Class entityClass, Closure callback, int callbackType) {
- return prePersistCallbacks;
- }
+ Collection[] entityCallbacks = (Collection[]) callbacks
+ .get(entityClass.getName());
- protected Collection getPreRemoveCallbacks() {
- if (preRemoveCallbacks == null) {
- preRemoveCallbacks = new ArrayList();
+ if (entityCallbacks == null) {
+ entityCallbacks = new Collection[CALLBACK_SIZE];
+ callbacks.put(entityClass.getName(), entityCallbacks);
}
- return preRemoveCallbacks;
- }
-
- protected Collection getPreUpdateCallbacks() {
- if (preUpdateCallbacks == null) {
- preUpdateCallbacks = new ArrayList();
+ if (entityCallbacks[callbackType] == null) {
+ entityCallbacks[callbackType] = new ArrayList(3);
}
- return preUpdateCallbacks;
+ entityCallbacks[callbackType].add(callback);
}
}
Modified:
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Artist.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Artist.java?view=diff&rev=448447&r1=448446&r2=448447
==============================================================================
---
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Artist.java
(original)
+++
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Artist.java
Wed Sep 20 20:35:14 2006
@@ -6,6 +6,9 @@
public class Artist extends _Artist {
protected boolean validateForSaveCalled;
+ protected boolean prePersisted;
+ protected boolean preRemoved;
+ protected boolean preUpdated;
public boolean isValidateForSaveCalled() {
return validateForSaveCalled;
@@ -15,8 +18,38 @@
validateForSaveCalled = false;
}
+ public void resetCallbackFlags() {
+ prePersisted = false;
+ preRemoved = false;
+ preUpdated = false;
+ }
+
public void validateForSave(ValidationResult validationResult) {
validateForSaveCalled = true;
super.validateForSave(validationResult);
+ }
+
+ public void prePersistCallback() {
+ prePersisted = true;
+ }
+
+ public void preRemoveCallback() {
+ preRemoved = true;
+ }
+
+ public void preUpdateCallback() {
+ preUpdated = true;
+ }
+
+ public boolean isPrePersisted() {
+ return prePersisted;
+ }
+
+ public boolean isPreRemoved() {
+ return preRemoved;
+ }
+
+ public boolean isPreUpdated() {
+ return preUpdated;
}
}
Modified:
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Painting.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Painting.java?view=diff&rev=448447&r1=448446&r2=448447
==============================================================================
---
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Painting.java
(original)
+++
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/art/Painting.java
Wed Sep 20 20:35:14 2006
@@ -24,6 +24,40 @@
public class Painting extends org.apache.art.auto._Painting {
protected boolean validateForSaveCalled;
+ protected boolean prePersisted;
+ protected boolean preRemoved;
+ protected boolean preUpdated;
+
+ public void resetCallbackFlags() {
+ prePersisted = false;
+ preRemoved = false;
+ preUpdated = false;
+ }
+
+ public void prePersistCallback() {
+ prePersisted = true;
+ }
+
+ public void preRemoveCallback() {
+ preRemoved = true;
+ }
+
+ public void preUpdateCallback() {
+ preUpdated = true;
+ }
+
+ public boolean isPrePersisted() {
+ return prePersisted;
+ }
+
+ public boolean isPreRemoved() {
+ return preRemoved;
+ }
+
+ public boolean isPreUpdated() {
+ return preUpdated;
+ }
+
public boolean isValidateForSaveCalled() {
return validateForSaveCalled;
}
Added:
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptorTst.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptorTst.java?view=auto&rev=448447
==============================================================================
---
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptorTst.java
(added)
+++
incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/intercept/ObjectContextCallbackInterceptorTst.java
Wed Sep 20 20:35:14 2006
@@ -0,0 +1,131 @@
+/*****************************************************************
+ * 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.intercept;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.art.Artist;
+import org.apache.art.Painting;
+import org.apache.cayenne.unit.CayenneTestCase;
+
+public class ObjectContextCallbackInterceptorTst extends CayenneTestCase {
+
+ protected void setUp() throws Exception {
+ deleteTestData();
+ }
+
+ public void testPrePersistCallbacks() {
+ ObjectContextCallbackInterceptor i = new
ObjectContextCallbackInterceptor();
+ i.setContext(createDataContext());
+
+ // no callbacks
+ Artist a1 = (Artist) i.newObject(Artist.class);
+ assertNotNull(a1);
+ assertFalse(a1.isPrePersisted());
+
+ i.addPrePersistCallback(Artist.class, "prePersistCallback");
+
+ Artist a2 = (Artist) i.newObject(Artist.class);
+ assertNotNull(a2);
+ assertTrue(a2.isPrePersisted());
+
+ i.addPrePersistCallback(
+ MockCallingBackListener.class,
+ "publicCallback",
+ Artist.class);
+
+ Artist a3 = (Artist) i.newObject(Artist.class);
+ assertNotNull(a3);
+ assertTrue(a3.isPrePersisted());
+
+ Collection prepersist = i.getCallbacks(
+ Artist.class,
+ ObjectContextCallbackInterceptor.PRE_PERSIST_INDEX);
+ assertNotNull(prepersist);
+ assertEquals(2, prepersist.size());
+
+ Iterator it = prepersist.iterator();
+ it.next();
+ ListenerCallback callback2 = (ListenerCallback) it.next();
+ MockCallingBackListener listener2 = (MockCallingBackListener) callback2
+ .getListener();
+ assertSame(a3, listener2.publicCalledbackEntity);
+
+ Painting p3 = (Painting) i.newObject(Painting.class);
+ assertNotNull(p3);
+ assertFalse(p3.isPrePersisted());
+ assertSame(a3, listener2.publicCalledbackEntity);
+ }
+
+ public void testPreRemoveCallbacks() {
+ ObjectContextCallbackInterceptor i = new
ObjectContextCallbackInterceptor();
+ i.setContext(createDataContext());
+
+ // no callbacks
+ Artist a1 = (Artist) i.newObject(Artist.class);
+ a1.setArtistName("XX");
+ i.commitChanges();
+ i.deleteObject(a1);
+ assertFalse(a1.isPrePersisted());
+ assertFalse(a1.isPreRemoved());
+
+ i.addPreRemoveCallback(Artist.class, "preRemoveCallback");
+
+ Artist a2 = (Artist) i.newObject(Artist.class);
+ a2.setArtistName("XX");
+ i.commitChanges();
+ i.deleteObject(a2);
+ assertFalse(a2.isPrePersisted());
+ assertTrue(a2.isPreRemoved());
+
+ i.addPreRemoveCallback(
+ MockCallingBackListener.class,
+ "publicCallback",
+ Artist.class);
+
+ Artist a3 = (Artist) i.newObject(Artist.class);
+ a3.setArtistName("XX");
+ i.commitChanges();
+ i.deleteObject(a3);
+ assertFalse(a3.isPrePersisted());
+ assertTrue(a3.isPreRemoved());
+
+ Collection preremove = i.getCallbacks(
+ Artist.class,
+ ObjectContextCallbackInterceptor.PRE_REMOVE_INDEX);
+ assertNotNull(preremove);
+ assertEquals(2, preremove.size());
+
+ Iterator it = preremove.iterator();
+ it.next();
+ ListenerCallback callback2 = (ListenerCallback) it.next();
+ MockCallingBackListener listener2 = (MockCallingBackListener) callback2
+ .getListener();
+ assertSame(a3, listener2.publicCalledbackEntity);
+
+ Painting p3 = (Painting) i.newObject(Painting.class);
+ p3.setPaintingTitle("XX");
+ i.commitChanges();
+ i.deleteObject(p3);
+ assertFalse(p3.isPrePersisted());
+ assertFalse(p3.isPreRemoved());
+ assertSame(a3, listener2.publicCalledbackEntity);
+ }
+}