You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2013/05/18 16:04:19 UTC

svn commit: r1484122 - in /cayenne/main/trunk: docs/doc/src/main/resources/ framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/ framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/

Author: aadamchik
Date: Sat May 18 14:04:18 2013
New Revision: 1484122

URL: http://svn.apache.org/r1484122
Log:
CAY-1821 AuditableFilter and friends should explicitly work with Persistent instead of Object

Modified:
    cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
    cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableAggregator.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableFilter.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableProcessor.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilterTest.java
    cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilter_InRuntime_Test.java

Modified: cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=1484122&r1=1484121&r2=1484122&view=diff
==============================================================================
--- cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt Sat May 18 14:04:18 2013
@@ -48,6 +48,7 @@ CAY-1813 Missing ObjEntity Attribute Val
 CAY-1814 Support Property.nin 
 CAY-1819 When adding a filter, auto-register it as a listener 
 CAY-1820 DataDomain.addListener(Object) - a shortcut for adding annotated listeners 
+CAY-1821 AuditableFilter and friends should explicitly work with Persistent instead of Object
 
 Bug Fixes:
 

Modified: cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableAggregator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableAggregator.java?rev=1484122&r1=1484121&r2=1484122&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableAggregator.java (original)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableAggregator.java Sat May 18 14:04:18 2013
@@ -22,9 +22,11 @@ import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import org.apache.cayenne.Persistent;
+
 /**
- * Aggregates audit events per audit root object, and passes them to delegate processor at
- * the end of the transaction.
+ * Aggregates audit events per audit root object, and passes them to delegate
+ * processor at the end of the transaction.
  * 
  * @since 3.1
  */
@@ -44,14 +46,14 @@ class AuditableAggregator {
 
     private AuditableProcessor delegate;
 
-    private Map<Object, AuditableOperation> ops;
+    private Map<Persistent, AuditableOperation> ops;
 
     AuditableAggregator(AuditableProcessor delegate) {
         this.delegate = delegate;
-        this.ops = new IdentityHashMap<Object, AuditableOperation>();
+        this.ops = new IdentityHashMap<Persistent, AuditableOperation>();
     }
 
-    void audit(Object object, AuditableOperation operation) {
+    void audit(Persistent object, AuditableOperation operation) {
         AuditableOperation oldOp = ops.put(object, operation);
         if (oldOp != null) {
             if (OP_PRECEDENCE[operation.ordinal()] < OP_PRECEDENCE[oldOp.ordinal()]) {
@@ -61,7 +63,7 @@ class AuditableAggregator {
     }
 
     void postSync() {
-        for (Entry<Object, AuditableOperation> op : ops.entrySet()) {
+        for (Entry<Persistent, AuditableOperation> op : ops.entrySet()) {
             delegate.audit(op.getKey(), op.getValue());
         }
     }

Modified: cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableFilter.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableFilter.java?rev=1484122&r1=1484121&r2=1484122&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableFilter.java (original)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableFilter.java Sat May 18 14:04:18 2013
@@ -40,8 +40,8 @@ import org.apache.cayenne.query.Query;
 /**
  * A {@link DataChannelFilter} that enables audit of entities annotated with
  * {@link Auditable} and {@link AuditableChild}. Note that this filter relies on
- * {@link ChangeSetFilter} presence in the DataDomain filter chain to be able to analyze
- * ignored properties.
+ * {@link ChangeSetFilter} presence in the DataDomain filter chain to be able to
+ * analyze ignored properties.
  * 
  * @since 3.1
  */
@@ -63,29 +63,21 @@ public class AuditableFilter implements 
         // noop
     }
 
-    public QueryResponse onQuery(
-            ObjectContext originatingContext,
-            Query query,
-            DataChannelFilterChain filterChain) {
+    public QueryResponse onQuery(ObjectContext originatingContext, Query query, DataChannelFilterChain filterChain) {
         return filterChain.onQuery(originatingContext, query);
     }
 
-    public GraphDiff onSync(
-            ObjectContext originatingContext,
-            GraphDiff changes,
-            int syncType,
+    public GraphDiff onSync(ObjectContext originatingContext, GraphDiff changes, int syncType,
             DataChannelFilterChain filterChain) {
 
         GraphDiff response;
 
         try {
             response = filterChain.onSync(originatingContext, changes, syncType);
-            if (syncType == DataChannel.FLUSH_CASCADE_SYNC
-                    || syncType == DataChannel.FLUSH_NOCASCADE_SYNC) {
+            if (syncType == DataChannel.FLUSH_CASCADE_SYNC || syncType == DataChannel.FLUSH_NOCASCADE_SYNC) {
                 postSync();
             }
-        }
-        finally {
+        } finally {
             cleanupPostSync();
         }
 
@@ -94,9 +86,10 @@ public class AuditableFilter implements 
 
     /**
      * A method called at the end of every
-     * {@link #onSync(ObjectContext, GraphDiff, int, DataChannelFilterChain)} invocation.
-     * This implementation uses it for cleaning up thread-local state of the filter.
-     * Subclasses may override it to do their own cleanup, and are expected to call super.
+     * {@link #onSync(ObjectContext, GraphDiff, int, DataChannelFilterChain)}
+     * invocation. This implementation uses it for cleaning up thread-local
+     * state of the filter. Subclasses may override it to do their own cleanup,
+     * and are expected to call super.
      */
     protected void cleanupPostSync() {
         threadAggregator.set(null);
@@ -105,7 +98,8 @@ public class AuditableFilter implements 
     void postSync() {
         AuditableAggregator aggregator = threadAggregator.get();
         if (aggregator != null) {
-            // must reset thread aggregator before processing the audit operations
+            // must reset thread aggregator before processing the audit
+            // operations
             // to avoid an endless processing loop if audit processor commits
             // something
             threadAggregator.set(null);
@@ -124,60 +118,60 @@ public class AuditableFilter implements 
     }
 
     @PostPersist(entityAnnotations = Auditable.class)
-    void insertAudit(Object object) {
+    void insertAudit(Persistent object) {
         getAggregator().audit(object, AuditableOperation.INSERT);
     }
 
     @PostRemove(entityAnnotations = Auditable.class)
-    void deleteAudit(Object object) {
+    void deleteAudit(Persistent object) {
         getAggregator().audit(object, AuditableOperation.DELETE);
     }
 
     @PostUpdate(entityAnnotations = Auditable.class)
-    void updateAudit(Object object) {
+    void updateAudit(Persistent object) {
         if (isAuditableUpdate(object, false)) {
             getAggregator().audit(object, AuditableOperation.UPDATE);
         }
     }
 
-    // only catching child updates... child insert/delete presumably causes an event on
+    // only catching child updates... child insert/delete presumably causes an
+    // event on
     // the owner object
 
     @PostUpdate(entityAnnotations = AuditableChild.class)
-    void updateAuditChild(Object object) {
+    void updateAuditChild(Persistent object) {
 
         if (isAuditableUpdate(object, true)) {
 
-            Object parent = getParent(object);
+            Persistent parent = getParent(object);
 
             if (parent != null) {
-                // not calling 'updateAudit' to skip checking 'isAuditableUpdate' on
+                // not calling 'updateAudit' to skip checking
+                // 'isAuditableUpdate' on
                 // parent
                 getAggregator().audit(parent, AuditableOperation.UPDATE);
-            }
-            else {
-                // TODO: maybe log this fact... shouldn't normally happen, but I can
+            } else {
+                // TODO: maybe log this fact... shouldn't normally happen, but I
+                // can
                 // imagine certain combinations of object graphs, disconnected
                 // relationships, delete rules, etc. may cause this
             }
         }
     }
 
-    protected Object getParent(Object object) {
+    protected Persistent getParent(Persistent object) {
 
         if (object == null) {
             throw new NullPointerException("Null object");
         }
 
         if (!(object instanceof DataObject)) {
-            throw new IllegalArgumentException("Object is not a DataObject: "
-                    + object.getClass().getName());
+            throw new IllegalArgumentException("Object is not a DataObject: " + object.getClass().getName());
         }
 
         DataObject dataObject = (DataObject) object;
 
-        AuditableChild annotation = dataObject.getClass().getAnnotation(
-                AuditableChild.class);
+        AuditableChild annotation = dataObject.getClass().getAnnotation(AuditableChild.class);
         if (annotation == null) {
             throw new IllegalArgumentException("No 'AuditableChild' annotation found");
         }
@@ -189,16 +183,16 @@ public class AuditableFilter implements 
         }
 
         if (propertyPath == null || propertyPath.equals("")) {
-            throw new IllegalStateException(
-                    "Either 'value' or 'objectIdRelationship' of @AuditableChild must be set");
+            throw new IllegalStateException("Either 'value' or 'objectIdRelationship' of @AuditableChild must be set");
         }
 
-        return dataObject.readNestedProperty(propertyPath);
+        return (Persistent) dataObject.readNestedProperty(propertyPath);
     }
 
     // TODO: It's a temporary clone method of {@link
     // org.apache.cayenne.lifecycle.relationship.ObjectIdRelationshipHandler#objectIdRelationshipName(String)}.
-    // Needs to be encapsulated to some separate class to avoid a code duplication
+    // Needs to be encapsulated to some separate class to avoid a code
+    // duplication
     private String objectIdRelationshipName(String uuidPropertyName) {
         return "cay:related:" + uuidPropertyName;
     }
@@ -218,24 +212,16 @@ public class AuditableFilter implements 
             String[] ignoredProperties;
 
             if (child) {
-                AuditableChild annotation = object.getClass().getAnnotation(
-                        AuditableChild.class);
-                ignoredProperties = annotation != null
-                        ? annotation.ignoredProperties()
-                        : null;
-            }
-            else {
+                AuditableChild annotation = object.getClass().getAnnotation(AuditableChild.class);
+                ignoredProperties = annotation != null ? annotation.ignoredProperties() : null;
+            } else {
                 Auditable annotation = object.getClass().getAnnotation(Auditable.class);
-                ignoredProperties = annotation != null
-                        ? annotation.ignoredProperties()
-                        : null;
+                ignoredProperties = annotation != null ? annotation.ignoredProperties() : null;
             }
 
             descriptor = new AuditableEntityDescriptor(entity, ignoredProperties);
 
-            AuditableEntityDescriptor existingDescriptor = entityDescriptors.putIfAbsent(
-                    entity.getName(),
-                    descriptor);
+            AuditableEntityDescriptor existingDescriptor = entityDescriptors.putIfAbsent(entity.getName(), descriptor);
 
             if (existingDescriptor != null) {
                 descriptor = existingDescriptor;

Modified: cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableProcessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableProcessor.java?rev=1484122&r1=1484121&r2=1484122&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableProcessor.java (original)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableProcessor.java Sat May 18 14:04:18 2013
@@ -18,23 +18,27 @@
  ****************************************************************/
 package org.apache.cayenne.lifecycle.audit;
 
+import org.apache.cayenne.Persistent;
+
 /**
- * A superclass of application specific handlers of the {@link Auditable} annotation, that
- * provides basic needed callbacks.
+ * A superclass of application specific handlers of the {@link Auditable}
+ * annotation, that provides basic needed callbacks.
  * 
  * @since 3.1
  */
 public interface AuditableProcessor {
 
     /**
-     * A method called by {@link AuditableFilter} that should audit records as appropriate
-     * in a given application. Implementors may insert audit records in DB, log a message,
-     * etc.
+     * A method called by {@link AuditableFilter} that should audit records as
+     * appropriate in a given application. Implementors may insert audit records
+     * in DB, log a message, etc.
      * 
-     * @param object the root auditable object. This is an object that is either annotated
-     *            with {@link Auditable} or pointed to by another object annotated with
-     *            {@link AuditableChild}.
-     * @param operation a type of object change.
+     * @param object
+     *            the root auditable object. This is an object that is either
+     *            annotated with {@link Auditable} or pointed to by another
+     *            object annotated with {@link AuditableChild}.
+     * @param operation
+     *            a type of object change.
      */
-    void audit(Object object, AuditableOperation operation);
+    void audit(Persistent object, AuditableOperation operation);
 }

Modified: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilterTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilterTest.java?rev=1484122&r1=1484121&r2=1484122&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilterTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilterTest.java Sat May 18 14:04:18 2013
@@ -30,6 +30,7 @@ import org.apache.cayenne.DataChannelFil
 import org.apache.cayenne.DataObject;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.Persistent;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.lifecycle.db.Auditable1;
@@ -66,7 +67,7 @@ public class AuditableFilterTest extends
     public void testInsertAudit() {
 
         AuditableFilter filter = new AuditableFilter(resolver, processor);
-        Object audited = new Object();
+        Persistent audited = mock(Persistent.class);
         filter.insertAudit(audited);
         filter.postSync();
 
@@ -76,7 +77,7 @@ public class AuditableFilterTest extends
     public void testDeleteAudit() {
 
         AuditableFilter filter = new AuditableFilter(resolver, processor);
-        Object audited = new Object();
+        Persistent audited = mock(Persistent.class);
         filter.deleteAudit(audited);
         filter.postSync();
 
@@ -86,7 +87,7 @@ public class AuditableFilterTest extends
     public void testUpdateAudit() {
 
         AuditableFilter filter = new AuditableFilter(resolver, processor);
-        Object audited = new CayenneDataObject();
+        Persistent audited = mock(Persistent.class);
         filter.updateAudit(audited);
         filter.postSync();
 
@@ -97,7 +98,7 @@ public class AuditableFilterTest extends
 
         AuditableFilter filter = new AuditableFilter(resolver, processor);
 
-        Object auditedParent = new Object();
+        Persistent auditedParent = mock(Persistent.class);
         DataObject audited = new MockAuditableChild();
         audited.setObjectId(new ObjectId("MockAuditableChild", "a", 1));
         audited.writeProperty("parent", auditedParent);
@@ -145,7 +146,7 @@ public class AuditableFilterTest extends
         ObjectContext context = mock(ObjectContext.class);
         GraphDiff changes = mock(GraphDiff.class);
 
-        final Object auditedParent1 = new CayenneDataObject();
+        final DataObject auditedParent1 = new CayenneDataObject();
         final DataObject audited11 = new MockAuditableChild();
         audited11.writeProperty("parent", auditedParent1);
         final DataObject audited12 = new MockAuditableChild();

Modified: cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilter_InRuntime_Test.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilter_InRuntime_Test.java?rev=1484122&r1=1484121&r2=1484122&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilter_InRuntime_Test.java (original)
+++ cayenne/main/trunk/framework/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/audit/AuditableFilter_InRuntime_Test.java Sat May 18 14:04:18 2013
@@ -27,6 +27,7 @@ import junit.framework.TestCase;
 
 import org.apache.cayenne.Cayenne;
 import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.Persistent;
 import org.apache.cayenne.access.DataDomain;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.lifecycle.changeset.ChangeSetFilter;
@@ -276,7 +277,7 @@ public class AuditableFilter_InRuntime_T
             }
         }
 
-        public void audit(Object object, AuditableOperation operation) {
+        public void audit(Persistent object, AuditableOperation operation) {
             audited.get(operation).add(object);
             size++;
         }