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 2010/11/14 10:51:47 UTC
svn commit: r1034969 - in /cayenne/main/trunk: docs/doc/src/main/resources/
framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/
framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/
framework/cayen...
Author: aadamchik
Date: Sun Nov 14 09:51:47 2010
New Revision: 1034969
URL: http://svn.apache.org/viewvc?rev=1034969&view=rev
Log:
CAY-1509 Lifecycle event annotations support
Added:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostAdd.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostLoad.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostPersist.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostRemove.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostUpdate.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PrePersist.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreRemove.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreUpdate.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/LifecycleCallbackRegistryTest.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/annotations/
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/annotations/Tag1.java
Modified:
cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/CallbackOnListener.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.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/test/java/org/apache/cayenne/testdo/testmap/Artist.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=1034969&r1=1034968&r2=1034969&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 Sun Nov 14 09:51:47 2010
@@ -14,6 +14,7 @@ Date:
Changes/New Features Since 3.1M1:
CAY-1508 Support for DataChannel filters
+CAY-1509 Lifecycle event annotations support
----------------------------------
Release: 3.1 M1
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostAdd.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostAdd.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostAdd.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostAdd.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,46 @@
+/*****************************************************************
+ * 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.annotation;
+
+import java.lang.annotation.Annotation;
+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;
+
+import org.apache.cayenne.map.LifecycleEvent;
+
+/**
+ * An annotation to place on the entity event listener method to receive
+ * {@link LifecycleEvent#POST_ADD} events.
+ *
+ * @since 3.1
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface PostAdd {
+
+ Class<?>[] value() default {};
+
+ Class<? extends Annotation>[] entityAnnotations() default {};
+}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostLoad.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostLoad.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostLoad.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostLoad.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,46 @@
+/*****************************************************************
+ * 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.annotation;
+
+import java.lang.annotation.Annotation;
+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;
+
+import org.apache.cayenne.map.LifecycleEvent;
+
+/**
+ * An annotation to place on the entity event listener method to receive
+ * {@link LifecycleEvent#POST_ADD} events.
+ *
+ * @since 3.1
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface PostLoad {
+
+ Class<?>[] value() default {};
+
+ Class<? extends Annotation>[] entityAnnotations() default {};
+}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostPersist.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostPersist.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostPersist.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostPersist.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,41 @@
+/*****************************************************************
+ * 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.annotation;
+
+import java.lang.annotation.Annotation;
+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;
+
+/**
+ * @since 3.1
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface PostPersist {
+
+ Class<?>[] value() default {};
+
+ Class<? extends Annotation>[] entityAnnotations() default {};
+}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostRemove.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostRemove.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostRemove.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostRemove.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,41 @@
+/*****************************************************************
+ * 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.annotation;
+
+import java.lang.annotation.Annotation;
+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;
+
+/**
+ * @since 3.1
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface PostRemove {
+
+ Class<?>[] value() default {};
+
+ Class<? extends Annotation>[] entityAnnotations() default {};
+}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostUpdate.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostUpdate.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostUpdate.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PostUpdate.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,41 @@
+/*****************************************************************
+ * 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.annotation;
+
+import java.lang.annotation.Annotation;
+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;
+
+/**
+ * @since 3.1
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface PostUpdate {
+
+ Class<?>[] value() default {};
+
+ Class<? extends Annotation>[] entityAnnotations() default {};
+}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PrePersist.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PrePersist.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PrePersist.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PrePersist.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,46 @@
+/*****************************************************************
+ * 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.annotation;
+
+import java.lang.annotation.Annotation;
+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;
+
+import org.apache.cayenne.map.LifecycleEvent;
+
+/**
+ * An annotation to place on the entity event listener method to receive
+ * {@link LifecycleEvent#POST_ADD} events.
+ *
+ * @since 3.1
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface PrePersist {
+
+ Class<?>[] value() default {};
+
+ Class<? extends Annotation>[] entityAnnotations() default {};
+}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreRemove.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreRemove.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreRemove.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreRemove.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,41 @@
+/*****************************************************************
+ * 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.annotation;
+
+import java.lang.annotation.Annotation;
+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;
+
+/**
+ * @since 3.1
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface PreRemove {
+
+ Class<?>[] value() default {};
+
+ Class<? extends Annotation>[] entityAnnotations() default {};
+}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreUpdate.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreUpdate.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreUpdate.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/annotation/PreUpdate.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,41 @@
+/*****************************************************************
+ * 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.annotation;
+
+import java.lang.annotation.Annotation;
+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;
+
+/**
+ * @since 3.1
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface PreUpdate {
+
+ Class<?>[] value() default {};
+
+ Class<? extends Annotation>[] entityAnnotations() default {};
+}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/CallbackOnListener.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/CallbackOnListener.java?rev=1034969&r1=1034968&r2=1034969&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/CallbackOnListener.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/CallbackOnListener.java Sun Nov 14 09:51:47 2010
@@ -52,6 +52,22 @@ class CallbackOnListener extends Abstrac
this.listener = listener;
}
+ CallbackOnListener(Object listener, Method method, Class<?> entityType)
+ throws IllegalArgumentException {
+
+ if (listener == null) {
+ throw new IllegalArgumentException("Null listener");
+ }
+
+ if (!verifyMethod(method, entityType)) {
+ throw new IllegalArgumentException("Invalid annotated listener method: "
+ + method.getName());
+ }
+
+ this.callbackMethod = method;
+ this.listener = listener;
+ }
+
@Override
public void performCallback(Object entity) {
try {
@@ -73,28 +89,33 @@ class CallbackOnListener extends Abstrac
+ callbackMethod.getName();
}
+ private boolean verifyMethod(Method method, Class<?> entityType) {
+ // must be non-static, void, with a single arg assignable to entity type
+ // JPA spec also requires it to be non-final, but we don't care
+ int modifiers = method.getModifiers();
+ Class<?>[] parameters = method.getParameterTypes();
+ if (!Modifier.isStatic(modifiers)
+ && Void.TYPE.isAssignableFrom(method.getReturnType())
+ && parameters.length == 1
+ && parameters[0].isAssignableFrom(entityType)) {
+
+ if (!Util.isAccessible(method)) {
+ method.setAccessible(true);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
private Method findMethod(Class<?> objectClass, String methodName, Class<?> entityType)
throws IllegalArgumentException {
Method[] methods = objectClass.getDeclaredMethods();
for (Method method : methods) {
- if (methodName.equals(method.getName())) {
-
- // must be non-static, void, with a single arg assignable to entity type
- // JPA spec also requires it to be non-final, but we don't care
- int modifiers = method.getModifiers();
- Class<?>[] parameters = method.getParameterTypes();
- if (!Modifier.isStatic(modifiers)
- && Void.TYPE.isAssignableFrom(method.getReturnType())
- && parameters.length == 1
- && parameters[0].isAssignableFrom(entityType)) {
-
- if (!Util.isAccessible(method)) {
- method.setAccessible(true);
- }
-
- return method;
- }
+ if (methodName.equals(method.getName()) && verifyMethod(method, entityType)) {
+ return method;
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java?rev=1034969&r1=1034968&r2=1034969&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java Sun Nov 14 09:51:47 2010
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.reflect;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -102,11 +103,20 @@ class LifecycleCallbackEventHandler {
addCallback(entityClass, callback);
}
+ void addListener(Class<?> entityClass, Object listener, Method method) {
+ CallbackOnListener callback = new CallbackOnListener(
+ listener,
+ method,
+ entityClass);
+ addCallback(entityClass, callback);
+ }
+
/**
* Registers a callback object to be invoked when a lifecycle event occurs.
*/
private void addCallback(Class<?> entityClass, AbstractCallback callback) {
- Collection<AbstractCallback> entityListeners = listeners.get(entityClass.getName());
+ Collection<AbstractCallback> entityListeners = listeners.get(entityClass
+ .getName());
if (entityListeners == null) {
entityListeners = new ArrayList<AbstractCallback>(3);
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=1034969&r1=1034968&r2=1034969&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 Sun Nov 14 09:51:47 2010
@@ -18,12 +18,32 @@
****************************************************************/
package org.apache.cayenne.reflect;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.LifecycleListener;
import org.apache.cayenne.Persistent;
+import org.apache.cayenne.annotation.PostAdd;
+import org.apache.cayenne.annotation.PostLoad;
+import org.apache.cayenne.annotation.PostPersist;
+import org.apache.cayenne.annotation.PostRemove;
+import org.apache.cayenne.annotation.PostUpdate;
+import org.apache.cayenne.annotation.PrePersist;
+import org.apache.cayenne.annotation.PreRemove;
+import org.apache.cayenne.annotation.PreUpdate;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.LifecycleEvent;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.util.Util;
/**
* A registry of lifecycle callbacks for all callback event types. Valid event types are
@@ -33,16 +53,27 @@ import org.apache.cayenne.map.LifecycleE
*/
public class LifecycleCallbackRegistry {
+ private EntityResolver entityResolver;
private LifecycleCallbackEventHandler[] eventCallbacks;
+ private Map<String, AnnotationReader> annotationsMap;
+ private Map<String, Collection<Class<?>>> entitiesByAnnotation;
/**
* Creates an empty callback registry.
*/
public LifecycleCallbackRegistry(EntityResolver resolver) {
- eventCallbacks = new LifecycleCallbackEventHandler[LifecycleEvent.values().length];
+
+ this.entityResolver = resolver;
+
+ // initialize callbacks map in constructor to avoid synchronization issues
+ // downstream.
+ this.eventCallbacks = new LifecycleCallbackEventHandler[LifecycleEvent.values().length];
for (int i = 0; i < eventCallbacks.length; i++) {
eventCallbacks[i] = new LifecycleCallbackEventHandler(resolver);
}
+
+ // other "static" lookup maps are initialized on-demand
+ this.entitiesByAnnotation = new ConcurrentHashMap<String, Collection<Class<?>>>();
}
/**
@@ -129,6 +160,46 @@ public class LifecycleCallbackRegistry {
}
/**
+ * Adds a listener, mapping its methods to events based on annotations.
+ *
+ * @since 3.1
+ */
+ public void addListener(Object listener) {
+ if (listener == null) {
+ throw new NullPointerException("Null listener");
+ }
+
+ for (Method m : listener.getClass().getDeclaredMethods()) {
+
+ for (Annotation a : m.getAnnotations()) {
+ AnnotationReader reader = getAnnotationsMap().get(
+ a.annotationType().getName());
+
+ if (reader != null) {
+
+ Set<Class<?>> types = new HashSet<Class<?>>();
+ for (Class<?> type : reader.entities(a)) {
+ // TODO: ignoring entity subclasses? whenever we add those, take
+ // into account "exlcudeSuperclassListeners" flag
+ types.add(type);
+ }
+
+ for (Class<? extends Annotation> type : reader.entityAnnotations(a)) {
+ types.addAll(getAnnotatedEntities(type));
+ }
+
+ for (Class<?> type : types) {
+ eventCallbacks[reader.eventType().ordinal()].addListener(
+ type,
+ listener,
+ m);
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Invokes callbacks of a specific type for a given entity object.
*/
public void performCallbacks(LifecycleEvent type, Persistent object) {
@@ -141,4 +212,203 @@ public class LifecycleCallbackRegistry {
public void performCallbacks(LifecycleEvent type, Collection<?> objects) {
eventCallbacks[type.ordinal()].performCallbacks(objects);
}
+
+ private Map<String, AnnotationReader> getAnnotationsMap() {
+ if (annotationsMap == null) {
+
+ Map<String, AnnotationReader> annotationsMap = new HashMap<String, AnnotationReader>();
+ annotationsMap.put(PostAdd.class.getName(), new AnnotationReader() {
+
+ @Override
+ LifecycleEvent eventType() {
+ return LifecycleEvent.POST_ADD;
+ }
+
+ @Override
+ Class<? extends Annotation>[] entityAnnotations(Annotation a) {
+ return ((PostAdd) a).entityAnnotations();
+ }
+
+ @Override
+ Class<?>[] entities(Annotation a) {
+ return ((PostAdd) a).value();
+ }
+ });
+
+ annotationsMap.put(PrePersist.class.getName(), new AnnotationReader() {
+
+ @Override
+ LifecycleEvent eventType() {
+ return LifecycleEvent.PRE_PERSIST;
+ }
+
+ @Override
+ Class<? extends Annotation>[] entityAnnotations(Annotation a) {
+ return ((PrePersist) a).entityAnnotations();
+ }
+
+ @Override
+ Class<?>[] entities(Annotation a) {
+ return ((PrePersist) a).value();
+ }
+ });
+
+ annotationsMap.put(PreRemove.class.getName(), new AnnotationReader() {
+
+ @Override
+ LifecycleEvent eventType() {
+ return LifecycleEvent.PRE_REMOVE;
+ }
+
+ @Override
+ Class<? extends Annotation>[] entityAnnotations(Annotation a) {
+ return ((PreRemove) a).entityAnnotations();
+ }
+
+ @Override
+ Class<?>[] entities(Annotation a) {
+ return ((PreRemove) a).value();
+ }
+ });
+
+ annotationsMap.put(PreUpdate.class.getName(), new AnnotationReader() {
+
+ @Override
+ LifecycleEvent eventType() {
+ return LifecycleEvent.PRE_UPDATE;
+ }
+
+ @Override
+ Class<? extends Annotation>[] entityAnnotations(Annotation a) {
+ return ((PreUpdate) a).entityAnnotations();
+ }
+
+ @Override
+ Class<?>[] entities(Annotation a) {
+ return ((PreUpdate) a).value();
+ }
+ });
+
+ annotationsMap.put(PostLoad.class.getName(), new AnnotationReader() {
+
+ @Override
+ LifecycleEvent eventType() {
+ return LifecycleEvent.POST_LOAD;
+ }
+
+ @Override
+ Class<? extends Annotation>[] entityAnnotations(Annotation a) {
+ return ((PostLoad) a).entityAnnotations();
+ }
+
+ @Override
+ Class<?>[] entities(Annotation a) {
+ return ((PostLoad) a).value();
+ }
+ });
+
+ annotationsMap.put(PostPersist.class.getName(), new AnnotationReader() {
+
+ @Override
+ LifecycleEvent eventType() {
+ return LifecycleEvent.POST_PERSIST;
+ }
+
+ @Override
+ Class<? extends Annotation>[] entityAnnotations(Annotation a) {
+ return ((PostPersist) a).entityAnnotations();
+ }
+
+ @Override
+ Class<?>[] entities(Annotation a) {
+ return ((PostPersist) a).value();
+ }
+ });
+
+ annotationsMap.put(PostUpdate.class.getName(), new AnnotationReader() {
+
+ @Override
+ LifecycleEvent eventType() {
+ return LifecycleEvent.POST_UPDATE;
+ }
+
+ @Override
+ Class<? extends Annotation>[] entityAnnotations(Annotation a) {
+ return ((PostUpdate) a).entityAnnotations();
+ }
+
+ @Override
+ Class<?>[] entities(Annotation a) {
+ return ((PostUpdate) a).value();
+ }
+ });
+
+ annotationsMap.put(PostRemove.class.getName(), new AnnotationReader() {
+
+ @Override
+ LifecycleEvent eventType() {
+ return LifecycleEvent.POST_REMOVE;
+ }
+
+ @Override
+ Class<? extends Annotation>[] entityAnnotations(Annotation a) {
+ return ((PostRemove) a).entityAnnotations();
+ }
+
+ @Override
+ Class<?>[] entities(Annotation a) {
+ return ((PostRemove) a).value();
+ }
+ });
+
+ this.annotationsMap = annotationsMap;
+ }
+
+ return annotationsMap;
+ }
+
+ private Collection<Class<?>> getAnnotatedEntities(Class<? extends Annotation> type) {
+
+ Collection<Class<?>> entities = entitiesByAnnotation.get(type.getName());
+
+ if (entities == null) {
+ entities = new ArrayList<Class<?>>();
+
+ boolean inherited = type.isAnnotationPresent(Inherited.class);
+ for (ObjEntity entity : entityResolver.getObjEntities()) {
+ Class<?> entityType;
+ try {
+ entityType = Util.getJavaClass(entity.getClassName());
+ }
+ catch (ClassNotFoundException e) {
+ throw new CayenneRuntimeException("Class not found: "
+ + entity.getClassName(), e);
+ }
+
+ Class<?> entityTypeOrSupertype = entityType;
+ do {
+ if (entityTypeOrSupertype.isAnnotationPresent(type)) {
+ entities.add(entityType);
+ break;
+ }
+
+ entityTypeOrSupertype = entityTypeOrSupertype.getSuperclass();
+
+ } while (inherited && entityTypeOrSupertype != null);
+ }
+
+ entitiesByAnnotation.put(type.getName(), entities);
+ }
+
+ return entities;
+ }
+
+ abstract class AnnotationReader {
+
+ abstract LifecycleEvent eventType();
+
+ abstract Class<?>[] entities(Annotation a);
+
+ abstract Class<? extends Annotation>[] entityAnnotations(Annotation a);
+ }
}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/LifecycleCallbackRegistryTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/LifecycleCallbackRegistryTest.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/LifecycleCallbackRegistryTest.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/LifecycleCallbackRegistryTest.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,83 @@
+/*****************************************************************
+ * 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.reflect;
+
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.Persistent;
+import org.apache.cayenne.annotation.PostAdd;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Exhibit;
+import org.apache.cayenne.testdo.testmap.Gallery;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.testdo.testmap.annotations.Tag1;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+
+@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
+public class LifecycleCallbackRegistryTest extends ServerCase {
+
+ @Inject
+ private ObjectContext context;
+
+ public void testAddListener_PostAdd() {
+ LifecycleCallbackRegistry registry = new LifecycleCallbackRegistry(context
+ .getEntityResolver());
+
+ context.getEntityResolver().setCallbackRegistry(registry);
+
+ PostAddListener listener = new PostAddListener();
+ registry.addListener(listener);
+
+ context.newObject(Gallery.class);
+ assertEquals("e:Gallery;", listener.getAndReset());
+
+ context.newObject(Artist.class);
+ assertEquals("a:Artist;", listener.getAndReset());
+
+ context.newObject(Exhibit.class);
+ assertEquals("", listener.getAndReset());
+
+ context.newObject(Painting.class);
+ assertEquals("e:Painting;", listener.getAndReset());
+ }
+}
+
+class PostAddListener {
+
+ StringBuilder callbackBuffer = new StringBuilder();
+
+ @PostAdd( {
+ Gallery.class, Painting.class
+ })
+ void postAddEntities(Persistent object) {
+ callbackBuffer.append("e:" + object.getObjectId().getEntityName() + ";");
+ }
+
+ @PostAdd(entityAnnotations = Tag1.class)
+ void postAddAnnotated(Persistent object) {
+ callbackBuffer.append("a:" + object.getObjectId().getEntityName() + ";");
+ }
+
+ String getAndReset() {
+ String v = callbackBuffer.toString();
+ callbackBuffer = new StringBuilder();
+ return v;
+ }
+}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/Artist.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/Artist.java?rev=1034969&r1=1034968&r2=1034969&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/Artist.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/Artist.java Sun Nov 14 09:51:47 2010
@@ -18,10 +18,12 @@
****************************************************************/
package org.apache.cayenne.testdo.testmap;
+import org.apache.cayenne.testdo.testmap.annotations.Tag1;
import org.apache.cayenne.testdo.testmap.auto._Artist;
import org.apache.cayenne.unit.util.ValidationDelegate;
import org.apache.cayenne.validation.ValidationResult;
+@Tag1
public class Artist extends _Artist {
protected transient ValidationDelegate validationDelegate;
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/annotations/Tag1.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/annotations/Tag1.java?rev=1034969&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/annotations/Tag1.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/testmap/annotations/Tag1.java Sun Nov 14 09:51:47 2010
@@ -0,0 +1,30 @@
+/*****************************************************************
+ * 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.testdo.testmap.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Tag1 {
+
+}