Author: aadamchik
Date: Wed Dec 22 18:31:31 2010
New Revision: 1052020
URL: http://svn.apache.org/viewvc?rev=1052020&view=rev
Log:
@AuditableChild
Added:
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AuditableChild.java
Modified:
cayenne/sandbox/cayenne-mixin/trunk/README.txt
cayenne/sandbox/cayenne-mixin/trunk/pom.xml
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AbstractAuditableHandler.java
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/Auditable.java
Modified: cayenne/sandbox/cayenne-mixin/trunk/README.txt
URL:
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/README.txt?rev=1052020&r1=1052019&r2=1052020&view=diff
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/README.txt (original)
+++ cayenne/sandbox/cayenne-mixin/trunk/README.txt Wed Dec 22 18:31:31 2010
@@ -1,9 +1,11 @@
TODO:
1. A reverse of @MixinRelationship - injecting mixin records into objects
annotated with some mixin annotation.
+2. Transactional auditable processing (with a mix of AuditableChild changes,
multiple audit events are generated for the same object)
IMPLEMENTED:
+5. @AuditableChild
4. Changeset tracking functionality
3. @MixinRelationship and MixinRelationshipFilter to batch-fault and inject
related objects into mixin entity (e.g. Audit entity)
2. @Auditable mixin with abstract handler allowing to store audit records in
an arbitrary format.
Modified: cayenne/sandbox/cayenne-mixin/trunk/pom.xml
URL:
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/pom.xml?rev=1052020&r1=1052019&r2=1052020&view=diff
==============================================================================
--- cayenne/sandbox/cayenne-mixin/trunk/pom.xml (original)
+++ cayenne/sandbox/cayenne-mixin/trunk/pom.xml Wed Dec 22 18:31:31 2010
@@ -8,7 +8,7 @@
<version>3.1M1</version>
</parent>
<artifactId>cayenne-mixin</artifactId>
- <version>3.1.0.8</version>
+ <version>3.1.0.11</version>
<name>Library: cayenne-mixin</name>
<packaging>jar</packaging>
<properties>
Modified:
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AbstractAuditableHandler.java
URL:
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AbstractAuditableHandler.java?rev=1052020&r1=1052019&r2=1052020&view=diff
==============================================================================
---
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AbstractAuditableHandler.java
(original)
+++
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AbstractAuditableHandler.java
Wed Dec 22 18:31:31 2010
@@ -18,34 +18,79 @@
****************************************************************/
package org.apache.cayenne.mixin.audit;
+import org.apache.cayenne.DataObject;
import org.apache.cayenne.annotation.PostPersist;
import org.apache.cayenne.annotation.PostRemove;
import org.apache.cayenne.annotation.PostUpdate;
/**
- * A superclass of application specific handlers of the {...@link Auditable}
mixin
- * that provides basic needed callbacks.
+ * A superclass of application specific handlers of the {...@link Auditable}
mixin that
+ * provides basic needed callbacks.
*/
public abstract class AbstractAuditableHandler {
- /**
- * A worker method that creates audit records, as appropriate in a given
- * application. Subclasses may insert audit records, log a message, etc.
- */
- protected abstract void audit(Object object, AuditableOperation
operation);
-
- @PostPersist(entityAnnotations = Auditable.class)
- void insertAudit(Object object) {
- audit(object, AuditableOperation.INSERT);
- }
-
- @PostRemove(entityAnnotations = Auditable.class)
- void deleteAudit(Object object) {
- audit(object, AuditableOperation.DELETE);
- }
-
- @PostUpdate(entityAnnotations = Auditable.class)
- void updateAudit(Object object) {
- audit(object, AuditableOperation.UPDATE);
- }
+ /**
+ * A worker method that creates audit records, as appropriate in a given
application.
+ * Subclasses may insert audit records, log a message, etc.
+ */
+ protected abstract void audit(
+ Object auditRoot,
+ Object auditSource,
+ AuditableOperation operation);
+
+ @PostPersist(entityAnnotations = Auditable.class)
+ void insertAudit(Object object) {
+ audit(object, object, AuditableOperation.INSERT);
+ }
+
+ @PostRemove(entityAnnotations = Auditable.class)
+ void deleteAudit(Object object) {
+ audit(object, object, AuditableOperation.DELETE);
+ }
+
+ @PostUpdate(entityAnnotations = Auditable.class)
+ void updateAudit(Object object) {
+ audit(object, object, AuditableOperation.UPDATE);
+ }
+
+ // only catching child updates... child insert/delete presumably causes an
event on
+ // the owner object
+
+ @PostUpdate(entityAnnotations = AuditableChild.class)
+ void updateAuditChild(Object object) {
+
+ Object parent = getParent(object);
+
+ if (parent != null) {
+ audit(parent, object, AuditableOperation.UPDATE);
+ }
+ else {
+ // at least og 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) {
+
+ if (object == null) {
+ throw new NullPointerException("Null object");
+ }
+
+ if (!(object instanceof DataObject)) {
+ throw new IllegalArgumentException("Object is not a DataObject: "
+ + object.getClass().getName());
+ }
+
+ DataObject dataObject = (DataObject) object;
+
+ AuditableChild annotation = dataObject.getClass().getAnnotation(
+ AuditableChild.class);
+ if (annotation == null) {
+ throw new IllegalArgumentException("No 'AuditableChild' annotation
found");
+ }
+
+ // support for nested paths
+ return dataObject.readNestedProperty(annotation.value());
+ }
}
Modified:
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/Auditable.java
URL:
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/Auditable.java?rev=1052020&r1=1052019&r2=1052020&view=diff
==============================================================================
---
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/Auditable.java
(original)
+++
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/Auditable.java
Wed Dec 22 18:31:31 2010
@@ -28,9 +28,9 @@ import java.lang.annotation.Target;
import org.apache.cayenne.mixin.ref.Referenceable;
/**
- * A built-in mixin annotation that adds auditable behavior to DataObjects. All
- * Auditable objects must be also tagged with {...@link Referenceable}
annotation,
- * as audit records are based on UUIDs.
+ * A built-in annotation that adds auditable behavior to DataObjects. All
Auditable
+ * objects must be also tagged with {...@link Referenceable} annotation, as
audit records are
+ * based on UUIDs.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
Added:
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AuditableChild.java
URL:
http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AuditableChild.java?rev=1052020&view=auto
==============================================================================
---
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AuditableChild.java
(added)
+++
cayenne/sandbox/cayenne-mixin/trunk/src/main/java/org/apache/cayenne/mixin/audit/AuditableChild.java
Wed Dec 22 18:31:31 2010
@@ -0,0 +1,26 @@
+package org.apache.cayenne.mixin.audit;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A built-in annotation used to tag an object that is not auditable on its
own, but whose
+ * changes should be tracked together with changes of another ("parent")
object. This
+ * annotation allows to group changes in a closely related subtree of objects.
+ */
+...@target(ElementType.TYPE)
+...@retention(RetentionPolicy.RUNTIME)
+...@documented
+...@inherited
+public @interface AuditableChild {
+
+ /**
+ * Returns the name of a to-one relationship from an annotated object to
the "parent"
+ * object that should be audited when annotated object is changed.
+ */
+ String value();
+}