diff --git a/src/main/java/io/ebean/config/AbstractNamingConvention.java b/src/main/java/io/ebean/config/AbstractNamingConvention.java index e123bec55..870c2e2b2 100644 --- a/src/main/java/io/ebean/config/AbstractNamingConvention.java +++ b/src/main/java/io/ebean/config/AbstractNamingConvention.java @@ -1,7 +1,7 @@ package io.ebean.config; import io.ebean.config.dbplatform.DatabasePlatform; -import io.ebeaninternal.server.deploy.parse.AnnotationBase; +import io.ebean.util.AnnotationUtil; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -219,8 +219,8 @@ public abstract class AbstractNamingConvention implements NamingConvention { * Return true if this class is part of entity inheritance. */ protected boolean hasInheritance(Class> supCls) { - return AnnotationBase.findAnnotationRecursive(supCls, Inheritance.class) != null - || AnnotationBase.findAnnotation(supCls, DiscriminatorValue.class) != null; + return AnnotationUtil.findAnnotationRecursive(supCls, Inheritance.class) != null + || AnnotationUtil.findAnnotation(supCls, DiscriminatorValue.class) != null; } @@ -253,7 +253,7 @@ public abstract class AbstractNamingConvention implements NamingConvention { */ protected TableName getTableNameFromAnnotation(Class> beanClass) { - final Table t = AnnotationBase.findAnnotationRecursive(beanClass, Table.class); + final Table t = AnnotationUtil.findAnnotationRecursive(beanClass, Table.class); // Take the annotation if defined if (t != null && !isEmpty(t.name())) { diff --git a/src/main/java/io/ebean/util/AnnotationUtil.java b/src/main/java/io/ebean/util/AnnotationUtil.java new file mode 100644 index 000000000..bad0b6dfa --- /dev/null +++ b/src/main/java/io/ebean/util/AnnotationUtil.java @@ -0,0 +1,270 @@ +package io.ebean.util; + +import io.ebean.annotation.Formula; +import io.ebean.annotation.Platform; +import io.ebean.annotation.Where; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Annotation utility methods to find annotations recursively - taken from the spring framework. + */ +public class AnnotationUtil { + + /** + * Determine if the supplied {@link Annotation} is defined in the core JDK {@code java.lang.annotation} package. + */ + public static boolean isInJavaLangAnnotationPackage(Annotation annotation) { + return annotation.annotationType().getName().startsWith("java.lang.annotation"); + } + + /** + * Find a single {@link Annotation} of {@code annotationType} on the supplied {@link AnnotatedElement}. + *
+ * Meta-annotations will be searched if the annotation is not directly present on the supplied element. + *
+ * Warning: this method operates generically on annotated elements. In other words, this method
+ * does not execute specialized search algorithms for classes or methods. It only traverses through Annotations!
+ * It also does not filter out platform dependent annotations!
+ */
+ public static A findAnnotation(AnnotatedElement annotatedElement, Class annotationType) {
+ if (annotationType == null) {
+ return null;
+ }
+ // check if directly present, if not, start search for meta-annotations.
+ A ann = annotatedElement.getAnnotation(annotationType);
+ if (ann != null) {
+ return ann;
+ } else {
+ return findAnnotation(annotatedElement, annotationType, new HashSet<>());
+ }
+ }
+
+ /**
+ * Find a single {@link Annotation} of {@code annotationType} on the supplied class.
+ * Meta-annotations will be searched if the annotation is not directly present on
+ * the supplied element.
+ * Note: this method searches for annotations at class & superClass(es)!
+ */
+ public static A findAnnotationRecursive(Class> clazz, Class annotationType) {
+ if (annotationType == null) {
+ return null;
+ }
+ // check if directly present, if not, start search for meta-annotations.
+ A ann = clazz.getAnnotation(annotationType);
+ if (ann != null) {
+ return ann;
+ } else {
+ while (clazz != null && clazz != Object.class) {
+ ann = findAnnotation(clazz, annotationType, new HashSet<>());
+ if (ann != null) {
+ return ann;
+ }
+ // no meta-annotation present at this class - traverse to superclass
+ clazz = clazz.getSuperclass();
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Finds the first annotation of a type for this platform. (if annotation is platform specific, otherwise first
+ * found annotation is returned)
+ */
+ public static A findAnnotation(AnnotatedElement annotatedElement, Class annotationType, Platform platform) {
+ if (annotationType == null) {
+ return null;
+ }
+ Set anns = findAnnotations(annotatedElement, annotationType);
+ return getPlatformMatchingAnnotation(anns, platform);
+ }
+
+ /**
+ * Finds all annotations recusively for a class and its superclasses.
+ */
+ public static Set findAnnotationsRecursive(Class> clazz, Class annotationType) {
+ if (annotationType == null) {
+ return null;
+ }
+ Set ret = new LinkedHashSet<>();
+ Set
+ * Meta-annotations will be searched if the annotation is not directly present on the supplied element.
+ *
+ * Warning: this method operates generically on annotated elements. In other words, this method
+ * does not execute specialized search algorithms for classes or methods. It only traverses through Annotations!
+ */
+ public static Set findAnnotations(AnnotatedElement annotatedElement, Class annotationType) {
+ if (annotationType == null) {
+ return null;
+ }
+ Set ret = new LinkedHashSet<>();
+ findMetaAnnotations(annotatedElement, annotationType, ret, new HashSet<>());
+ return ret;
+ }
+
+ /**
+ * Perform the search algorithm avoiding endless recursion by tracking which
+ * annotations have already been visited.
+ */
+ @SuppressWarnings("unchecked")
+ private static void findMetaAnnotations(AnnotatedElement annotatedElement, Class annotationType, Set ret, Set
+ *
* search algorithm for ONE annotation:
* search algoritm for a Set<Annotation> works a litte bit different, as it does not stop
* on the first match, but continues searching down to the last corner to find all annotations.
* To prevent endless recursion, the search algoritm tracks all visited annotations
* Supports also "java 1.6 repeatable containers" like{@link JoinColumn} / {@link JoinColumns}.
* This means, searching for
* If a
*/
@@ -135,16 +130,6 @@ public abstract class AnnotationBase {
return a;
}
-
- // this code is taken from the spring framework to find annotations recursively
-
- /**
- * Determine if the supplied {@link Annotation} is defined in the core JDK {@code java.lang.annotation} package.
- */
- public static boolean isInJavaLangAnnotationPackage(Annotation annotation) {
- return annotation.annotationType().getName().startsWith("java.lang.annotation");
- }
-
/**
* Find a single {@link Annotation} of {@code annotationType} on the supplied {@link AnnotatedElement}.
*
@@ -155,16 +140,7 @@ public abstract class AnnotationBase {
* It also does not filter out platform dependent annotations!
*/
public static A findAnnotation(AnnotatedElement annotatedElement, Class annotationType) {
- if (annotationType == null) {
- return null;
- }
- // check if directly present, if not, start search for meta-annotations.
- A ann = annotatedElement.getAnnotation(annotationType);
- if (ann != null) {
- return ann;
- } else {
- return findAnnotation(annotatedElement, annotationType, new HashSet<>());
- }
+ return AnnotationUtil.findAnnotation(annotatedElement, annotationType);
}
/**
@@ -174,24 +150,7 @@ public abstract class AnnotationBase {
* Note: this method searches for annotations at class & superClass(es)!
*/
public static A findAnnotationRecursive(Class> clazz, Class annotationType) {
- if (annotationType == null) {
- return null;
- }
- // check if directly present, if not, start search for meta-annotations.
- A ann = clazz.getAnnotation(annotationType);
- if (ann != null) {
- return ann;
- } else {
- while (clazz != null && clazz != Object.class) {
- ann = findAnnotation(clazz, annotationType, new HashSet<>());
- if (ann != null) {
- return ann;
- }
- // no meta-annotation present at this class - traverse to superclass
- clazz = clazz.getSuperclass();
- }
- return null;
- }
+ return AnnotationUtil.findAnnotationRecursive(clazz, annotationType);
}
/**
@@ -199,51 +158,14 @@ public abstract class AnnotationBase {
* found annotation is returned)
*/
public static A findAnnotation(AnnotatedElement annotatedElement, Class annotationType, Platform platform) {
- if (annotationType == null) {
- return null;
- }
- Set anns = findAnnotations(annotatedElement, annotationType);
- return getPlatformMatchingAnnotation(anns, platform);
+ return AnnotationUtil.findAnnotation(annotatedElement, annotationType, platform);
}
/**
* Finds all annotations recusively for a class and its superclasses.
*/
public static Set findAnnotationsRecursive(Class> clazz, Class annotationType) {
- if (annotationType == null) {
- return null;
- }
- Set ret = new LinkedHashSet<>();
- Set
- * value() method for a possible containerAnnotation.
+ * Method is retuned only, if its signature is array of containingType.
+ */
+ private static Method getRepeatableValueMethod(
+ Annotation containerAnnotation, Class containingType) {
+
+ Method method = valueMethods.get(containerAnnotation);
+ if (method == null) {
+ try {
+ method = containerAnnotation.annotationType().getMethod("value");
+ } catch (NoSuchMethodException e) {
+ method = nullMethod;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ Method prev = valueMethods.putIfAbsent(containerAnnotation, method);
+ method = prev == null ? method : prev;
+ }
+ if (method != nullMethod) {
+ Class> retType = method.getReturnType();
+ if (retType.isArray() && retType.getComponentType() == containingType) {
+ return method;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Finds a suitable annotation from Set for this platform.
+ * To distinguish between platforms, annotation type T must define
+ * a method withthis signature:
+ * Class extends DatabasePlatform>[] platforms() default {};
+ *
+ *
+ * (This mechanism is currently used by {@link Where} and {@link Formula})
+ */
+ public static ann[0]
+ * databasePlatform
- *
* DFS (Depth-First-Search) is used. The algorithm is the same as it is used in Spring-Framework,
* as the code is taken from there.
- *
+ * JoinColumn will find them also if they are inside a
* JoinColumns annotationrepeatable annotation class is specified and the annotation is platform
- * specific(see {@link #getPlatformMatchingAnnotation(Set, Platform)}), then the platform specific
- * annotation is returned. Otherwise the first annotation is returned. Note that you need no longer
- * handle "java 1.6 repeatable containers" like {@link JoinColumn} / {@link JoinColumns} yourself.
+ * specific then the platform specific annotation is returned. Otherwise the first annotation
+ * is returned. Note that you need no longer handle "java 1.6 repeatable containers"
+ * like {@link JoinColumn} / {@link JoinColumns} yourself.
* value() method for a possible containerAnnotation.
- * Method is retuned only, if its signature is array of containingType.
- */
- private static Method getRepeatableValueMethod(
- Annotation containerAnnotation, Class containingType) {
-
- Method method = valueMethods.get(containerAnnotation);
- if (method == null) {
- try {
- method = containerAnnotation.annotationType().getMethod("value");
- } catch (NoSuchMethodException e) {
- method = nullMethod;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- Method prev = valueMethods.putIfAbsent(containerAnnotation, method);
- method = prev == null ? method : prev;
- }
- if (method != nullMethod) {
- Class> retType = method.getReturnType();
- if (retType.isArray() && retType.getComponentType() == containingType) {
- return method;
- }
- }
- return null;
- }
-
- /**
- * Finds a suitable annotation from Set for this platform.
- * To distinguish between platforms, annotation type T must define
- * a method withthis signature:
- * Class extends DatabasePlatform>[] platforms() default {};
- *
- *
- * (This mechanism is currently used by {@link Where} and {@link Formula})
- */
- public static ann[0]
- * databasePlatform