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++;
}