Permalink
Browse files

Implemented JPA lifecycle callbacks.

This involved updating the PrivateAccessUtil to be able to create non-static method accessors
like the previous change that allows non-static field accessors.

This also involved a refactoring of the EntityManager to centralize most of the entity state
transition logic.
  • Loading branch information...
jfuerth committed May 8, 2012
1 parent fefbc18 commit 656845ec9d884c1fd4256fd70aa8fe5dd9b321ae
@@ -16,6 +16,9 @@
package org.jboss.errai.codegen.meta;
+import java.lang.annotation.Annotation;
+import java.util.List;
+
/**
* @author Mike Brock <cbrock@redhat.com>
*/
@@ -34,6 +37,21 @@
public abstract MetaMethod[] getMethods();
+ /**
+ * Returns all declared and inherited methods on this class that have the
+ * given annotation targeting them.
+ * <p>
+ * TODO: the returned collection should not include overridden methods from superclasses.
+ *
+ * @param annotation
+ * The annotation to scan this class's methods for. Must not be null.
+ * @return An unmodifiable list of all declared and inherited methods of this
+ * class that are annotated with the given annotation.
+ * @throws NullPointerException
+ * if {@code} annotation is null.
+ */
+ public abstract List<MetaMethod> getMethodsAnnotatedWith(Class<? extends Annotation> annotation);
+
public abstract MetaMethod[] getDeclaredMethods();
public abstract MetaMethod getMethod(String name, Class... parameters);
@@ -124,10 +142,6 @@
public abstract boolean isAssignableFrom(Class clazz);
public abstract boolean isAssignableTo(Class clazz);
-//
-// public abstract boolean isAssignableFrom(JClassType clazz);
-//
-// public abstract boolean isAssignableTo(JClassType clazz);
public abstract boolean isPrimitive();
@@ -16,15 +16,13 @@
package org.jboss.errai.codegen.meta.impl;
-import static org.jboss.errai.codegen.meta.MetaClassFactory.asClassArray;
import static org.jboss.errai.codegen.util.GenUtil.classToMeta;
import static org.jboss.errai.codegen.util.GenUtil.getArrayDimensions;
-import static org.jboss.errai.codegen.util.GenUtil.getBestConstructorCandidate;
import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -38,7 +36,6 @@
import org.jboss.errai.codegen.meta.MetaType;
import org.jboss.errai.codegen.util.GenUtil;
import org.mvel2.util.NullType;
-import org.mvel2.util.ParseTools;
/**
* @author Mike Brock <cbrock@redhat.com>
@@ -374,6 +371,22 @@ public final boolean isAnnotationPresent(Class<? extends Annotation> annotation)
return getAnnotation(annotation) != null;
}
+ // docs inherited from superclass
+ @Override
+ public final List<MetaMethod> getMethodsAnnotatedWith(Class<? extends Annotation> annotation) {
+ List<MetaMethod> methods = new ArrayList<MetaMethod>();
+ MetaClass scanTarget = this;
+ while (scanTarget != null) {
+ for (MetaMethod m : scanTarget.getDeclaredMethods()) {
+ if (m.isAnnotationPresent(annotation)) {
+ methods.add(m);
+ }
+ }
+ scanTarget = scanTarget.getSuperClass();
+ }
+ return Collections.unmodifiableList(methods); // in case we want to cache this in the future
+ }
+
public T getEnclosedMetaObject() {
return enclosedMetaObject;
}
@@ -23,7 +23,13 @@
import org.jboss.errai.codegen.meta.MetaParameter;
/**
+ * Utility class with methods that generate code to access private, default
+ * access ("package private"), and protected methods and fields in arbirtary
+ * classes. Each generator allows the choice of generating Java Reflection code
+ * (for use on the server side) or JSNI code (for use on the client side).
+ *
* @author Mike Brock
+ * @author Jonathan Fuerth
*/
public class PrivateAccessUtil {
private static final String JAVA_REFL_FLD_UTIL_METH = "_getAccessibleField";
@@ -175,11 +181,7 @@ public static void addPrivateAccessStubs(PrivateAccessType accessType,
if (useJSNIStubs) {
- // append JSNI modifier to the given modifier array
- Modifier[] origModifiers = modifiers;
- modifiers = new Modifier[origModifiers.length + 1];
- System.arraycopy(origModifiers, 0, modifiers, 0, origModifiers.length);
- modifiers[modifiers.length - 1] = Modifier.JSNI;
+ modifiers = appendJsni(modifiers);
if (write) {
final MethodCommentBuilder<? extends ClassStructureBuilder<?>> methodBuilder
@@ -269,7 +271,47 @@ public static void addPrivateAccessStubs(PrivateAccessType accessType,
}
}
+ /**
+ * Generates methods for accessing a nonpublic method using either JSNI or
+ * Java Reflection. The generated method will be private and static. The name
+ * of the generated method can be discovered by calling
+ * {@link #getPrivateMethodName(MetaMethod)}.
+ *
+ * @param useJSNIStubs
+ * If true, the generated method will use JSNI to access the field.
+ * Otherwise, Java reflection will be used (in this case, the
+ * generated code will not be GWT translatable).
+ * @param classBuilder
+ * The class builder to add the generated method to.
+ * @param m
+ * The method the generated accessors read and write.
+ */
public static void addPrivateAccessStubs(boolean useJSNIStubs, ClassStructureBuilder<?> classBuilder, MetaMethod m) {
+ addPrivateAccessStubs(useJSNIStubs, classBuilder, m, new Modifier[] { Modifier.Static });
+ }
+
+ /**
+ * Generates methods for accessing a nonpublic method using either JSNI or Java
+ * Reflection. The generated method will be private and static.
+ *
+ * @param useJSNIStubs
+ * If true, the generated method will use JSNI to access the field.
+ * Otherwise, Java reflection will be used (in this case, the
+ * generated code will not be GWT translatable).
+ * @param classBuilder
+ * The class builder to add the generated method to.
+ * @param m
+ * The method the generated accessors read and write.
+ * @param modifiers
+ * The modifiers on the generated method, for example
+ * {@link Modifier#Final} or {@link Modifier#Synchronized}. <i>Never
+ * specify {@code Modifier.JSNI}</i>; it is added automatically when
+ * needed.
+ */
+ public static void addPrivateAccessStubs(
+ boolean useJSNIStubs, ClassStructureBuilder<?> classBuilder,
+ MetaMethod m, Modifier[] modifiers) {
+
List<Parameter> wrapperDefParms = new ArrayList<Parameter>();
if (!m.isStatic()) {
@@ -281,9 +323,10 @@ public static void addPrivateAccessStubs(boolean useJSNIStubs, ClassStructureBui
wrapperDefParms.addAll(methodDefParms);
if (useJSNIStubs) {
+ modifiers = appendJsni(modifiers);
classBuilder.publicMethod(m.getReturnType(), getPrivateMethodName(m))
.parameters(new DefParameters(wrapperDefParms))
- .modifiers(Modifier.Static, Modifier.JSNI)
+ .modifiers(modifiers)
.body()
._(new StringStatement(JSNIUtil.methodAccess(m)))
.finish();
@@ -301,7 +344,7 @@ public static void addPrivateAccessStubs(boolean useJSNIStubs, ClassStructureBui
BlockBuilder<? extends ClassStructureBuilder> body = classBuilder.publicMethod(m.getReturnType(),
getPrivateMethodName(m))
.parameters(new DefParameters(wrapperDefParms))
- .modifiers(Modifier.Static)
+ .modifiers(modifiers)
.body();
BlockBuilder<CatchBlockBuilder> tryBuilder = Stmt.try_();
@@ -342,6 +385,23 @@ public static String getPrivateMethodName(MetaMethod method) {
return buf.toString();
}
+ /**
+ * Returns a new array consisting of a copy of the given array, plus
+ * Modifiers.JSNI as the last element.
+ *
+ * @param modifiers The array to copy. May be empty, but must not be null.
+ * @return An array of length {@code n + 1}, where {@code n} is the length of
+ * the given array. Positions 0..n-1 correspond with the respective
+ * entries in the given array, and position n contains Modifiers.JSNI.
+ */
+ private static Modifier[] appendJsni(Modifier[] modifiers) {
+ Modifier[] origModifiers = modifiers;
+ modifiers = new Modifier[origModifiers.length + 1];
+ System.arraycopy(origModifiers, 0, modifiers, 0, origModifiers.length);
+ modifiers[modifiers.length - 1] = Modifier.JSNI;
+ return modifiers;
+ }
+
private static String _getReflectionFieldMethGetName(MetaField f) {
MetaClass t = f.getType();
@@ -0,0 +1,14 @@
+package org.jboss.errai.jpa.client.local;
+
+/**
+ * Represents the states an entity instance can be in, according to the
+ * ErraiEntityManager.
+ *
+ * @author Jonathan Fuerth <jfuerth@gmail.com>
+ */
+public enum EntityState {
+ NEW,
+ MANAGED,
+ DETACHED,
+ REMOVED
+}
Oops, something went wrong.

0 comments on commit 656845e

Please sign in to comment.