mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Refactor/findannotation (#1104)
* refactor: renamed findAnnotation method that searches recursive to findAnnotationRecursive * CHG: searching namedQueries & indices also recursive in superclasses * FIX: Using the AnnotationBase methods on several places and documented them
This commit is contained in:
committed by
Rob Bygrave
parent
e908d16ba8
commit
46cdc84e6b
@@ -1,13 +1,13 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.server.deploy.parse.AnnotationBase;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.Table;
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* Provides some base implementation for NamingConventions.
|
||||
@@ -219,15 +219,10 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
* Return true if this class is part of entity inheritance.
|
||||
*/
|
||||
protected boolean hasInheritance(Class<?> supCls) {
|
||||
return hasAnnotation(supCls, Inheritance.class) || hasAnnotation(supCls, DiscriminatorValue.class);
|
||||
return AnnotationBase.findAnnotationRecursive(supCls, Inheritance.class) != null
|
||||
|| AnnotationBase.findAnnotation(supCls, DiscriminatorValue.class) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the class has the given annotation.
|
||||
*/
|
||||
protected boolean hasAnnotation(Class<?> supCls, Class<? extends Annotation> annotation) {
|
||||
return supCls.getAnnotation(annotation) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableName getM2MJoinTableName(TableName lhsTable, TableName rhsTable) {
|
||||
@@ -258,7 +253,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
*/
|
||||
protected TableName getTableNameFromAnnotation(Class<?> beanClass) {
|
||||
|
||||
final Table t = findTableAnnotation(beanClass);
|
||||
final Table t = AnnotationBase.findAnnotationRecursive(beanClass, Table.class);
|
||||
|
||||
// Take the annotation if defined
|
||||
if (t != null && !isEmpty(t.name())) {
|
||||
@@ -271,22 +266,6 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search recursively for an @Table in the class hierarchy.
|
||||
*/
|
||||
protected Table findTableAnnotation(Class<?> cls) {
|
||||
while (true) {
|
||||
if (cls.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
Table table = cls.getAnnotation(Table.class);
|
||||
if (table != null) {
|
||||
return table;
|
||||
}
|
||||
cls = cls.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace back ticks (if they are used) with database platform specific
|
||||
* quoted identifiers.
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.ebean.cache.ServerCacheFactory;
|
||||
import io.ebean.cache.ServerCacheOptions;
|
||||
import io.ebean.cache.ServerCacheType;
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
import io.ebeaninternal.server.deploy.parse.AnnotationBase;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -82,7 +83,7 @@ class DefaultCacheHolder {
|
||||
}
|
||||
|
||||
private ServerCacheOptions getQueryOptions(Class<?> cls) {
|
||||
CacheQueryTuning tuning = cls.getAnnotation(CacheQueryTuning.class);
|
||||
CacheQueryTuning tuning = AnnotationBase.findAnnotation(cls, CacheQueryTuning.class);
|
||||
if (tuning != null) {
|
||||
return new ServerCacheOptions(tuning).applyDefaults(queryDefault);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class DefaultChangeLogRegister implements ChangeLogRegister {
|
||||
* Find and return the ChangeLog annotation in the inheritance hierarchy.
|
||||
*/
|
||||
private ChangeLog getChangeLog(Class<?> beanType) {
|
||||
return AnnotationBase.findAnnotation(beanType, ChangeLog.class);
|
||||
return AnnotationBase.findAnnotationRecursive(beanType, ChangeLog.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@ import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeLogRegister;
|
||||
import io.ebean.event.readaudit.ReadAuditLogger;
|
||||
import io.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import io.ebeaninternal.server.deploy.parse.AnnotationBase;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
import org.avaje.classpath.scanner.ClassFilter;
|
||||
import org.slf4j.Logger;
|
||||
@@ -470,7 +471,10 @@ public class BootupClasses implements ClassFilter {
|
||||
return has(cls, Embeddable.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this class has the annotation (or meta annotation). Does not search recursively.
|
||||
*/
|
||||
private boolean has(Class<?> cls, Class<? extends Annotation> ann) {
|
||||
return cls.getAnnotation(ann) != null;
|
||||
return AnnotationBase.findAnnotation(cls, ann) != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanTable;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import io.ebeaninternal.server.deploy.parse.AnnotationBase;
|
||||
import io.ebeaninternal.server.deploy.parse.DeployBeanInfo;
|
||||
import io.ebeaninternal.server.deploy.parse.DeployCreateProperties;
|
||||
import io.ebeaninternal.server.deploy.parse.DeployInherit;
|
||||
@@ -1451,8 +1452,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
* If so it is ok for it not to be enhanced.
|
||||
*/
|
||||
private boolean isMappedSuperWithNoProperties(Class<?> beanClass) {
|
||||
// Attention: do not use AnnotationBase.findAnnotation(cls,...) here.
|
||||
MappedSuperclass annotation = beanClass.getAnnotation(MappedSuperclass.class);
|
||||
// do not search recursive here
|
||||
MappedSuperclass annotation = AnnotationBase.findAnnotation(beanClass, MappedSuperclass.class);
|
||||
if (annotation == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,29 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* Provides some base methods for processing deployment annotations.
|
||||
* Provides some base methods for processing deployment annotations. All findAnnotation* methods
|
||||
* are capable to search for meta-annotations (annotation that has an other annotation)
|
||||
*
|
||||
* <p>search algorithm for ONE annotation:</p>
|
||||
* <ul>
|
||||
* <li>Check if annotation is direct on the property</li>
|
||||
* <li>if not found: Check all annotations at the annotateElement
|
||||
* if they have the needed annotation as meta annotation</li>
|
||||
* <li>if not found: go up to super class and try again
|
||||
* (only findAnnotationRecursive)</li>
|
||||
* </ul>
|
||||
* 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.
|
||||
*
|
||||
* <p>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.</p>
|
||||
*
|
||||
* <p>To prevent endless recursion, the search algoritm tracks all visited annotations</p>
|
||||
*
|
||||
* <p>Supports also "java 1.6 repeatable containers" like{@link JoinColumn} / {@link JoinColumns}.</p>
|
||||
*
|
||||
* <p>This means, searching for <code>JoinColumn</code> will find them also if they are inside a
|
||||
* <code>JoinColumn<b>s</b></code> annotation</p>
|
||||
*/
|
||||
public abstract class AnnotationBase {
|
||||
|
||||
@@ -51,12 +73,13 @@ public abstract class AnnotationBase {
|
||||
/**
|
||||
* Return the annotation for the property.
|
||||
* <p>
|
||||
* Looks first at the field and then at the getter method.
|
||||
* Looks first at the field and then at the getter method. It searches for meta-annotations, but not
|
||||
* recursively in the class hierarchy.
|
||||
* </p>
|
||||
* <p>
|
||||
* If a <code>repeatable</code> 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 must no longer
|
||||
* 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.
|
||||
* </p>
|
||||
* <p>
|
||||
@@ -101,6 +124,7 @@ public abstract class AnnotationBase {
|
||||
* Return the annotation for the property.
|
||||
* <p>
|
||||
* Looks first at the field and then at the getter method. then at class level.
|
||||
* (This is used for SequenceGenerator e.g.)
|
||||
* </p>
|
||||
*/
|
||||
protected <T extends Annotation> T find(DeployBeanProperty prop, Class<T> annClass) {
|
||||
@@ -134,7 +158,7 @@ public abstract class AnnotationBase {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
// check if directly present, if not, start recursive traversal
|
||||
// check if directly present, if not, start search for meta-annotations.
|
||||
A ann = annotatedElement.getAnnotation(annotationType);
|
||||
if (ann != null) {
|
||||
return ann;
|
||||
@@ -149,11 +173,11 @@ public abstract class AnnotationBase {
|
||||
* the supplied element.
|
||||
* <p><strong>Note</strong>: this method searches for annotations at class & superClass(es)!
|
||||
*/
|
||||
public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
|
||||
public static <A extends Annotation> A findAnnotationRecursive(Class<?> clazz, Class<A> annotationType) {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
// check if directly present, if not, start recursive traversal
|
||||
// check if directly present, if not, start search for meta-annotations.
|
||||
A ann = clazz.getAnnotation(annotationType);
|
||||
if (ann != null) {
|
||||
return ann;
|
||||
@@ -163,7 +187,7 @@ public abstract class AnnotationBase {
|
||||
if (ann != null) {
|
||||
return ann;
|
||||
}
|
||||
// not present at this class - traverse to superclass
|
||||
// no meta-annotation present at this class - traverse to superclass
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
@@ -182,6 +206,22 @@ public abstract class AnnotationBase {
|
||||
return getPlatformMatchingAnnotation(anns, platform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all annotations recusively for a class and its superclasses.
|
||||
*/
|
||||
public static <A extends Annotation> Set<A> findAnnotationsRecursive(Class<?> clazz, Class<A> annotationType) {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
Set<A> ret = new LinkedHashSet<>();
|
||||
Set<Annotation> visited = new HashSet<>();
|
||||
while (clazz != null && clazz != Object.class) {
|
||||
findMetaAnnotations(clazz, annotationType, ret, visited);
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the search algorithm avoiding endless recursion by tracking which
|
||||
* annotations have already been visited.
|
||||
@@ -265,6 +305,7 @@ public abstract class AnnotationBase {
|
||||
}
|
||||
|
||||
private static final ConcurrentMap<Annotation, Method> valueMethods = new ConcurrentHashMap<>();
|
||||
// only a non-null-marker the valueMethods - Cache
|
||||
private static final Method nullMethod = getNullMethod();
|
||||
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public class AnnotationClass extends AnnotationParser {
|
||||
public void parseAttributeOverride() {
|
||||
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
AttributeOverride override = AnnotationBase.findAnnotation(cls, AttributeOverride.class);
|
||||
AttributeOverride override = AnnotationBase.findAnnotationRecursive(cls, AttributeOverride.class);
|
||||
if (override != null) {
|
||||
String propertyName = override.name();
|
||||
Column column = override.column();
|
||||
@@ -109,14 +109,14 @@ public class AnnotationClass extends AnnotationParser {
|
||||
private void read(Class<?> cls) {
|
||||
|
||||
// maybe doc store only so check for this before @Entity
|
||||
DocStore docStore = AnnotationBase.findAnnotation(cls, DocStore.class);
|
||||
DocStore docStore = AnnotationBase.findAnnotationRecursive(cls, DocStore.class);
|
||||
if (docStore != null) {
|
||||
descriptor.readDocStore(docStore);
|
||||
descriptor.setEntityType(EntityType.DOC);
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
}
|
||||
|
||||
Entity entity = AnnotationBase.findAnnotation(cls, Entity.class);
|
||||
Entity entity = AnnotationBase.findAnnotationRecursive(cls, Entity.class);
|
||||
if (entity != null) {
|
||||
descriptor.setEntityType(EntityType.ORM);
|
||||
if (entity.name().isEmpty()) {
|
||||
@@ -126,27 +126,27 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
Embeddable embeddable = AnnotationBase.findAnnotation(cls, Embeddable.class);
|
||||
Embeddable embeddable = AnnotationBase.findAnnotationRecursive(cls, Embeddable.class);
|
||||
if (embeddable != null) {
|
||||
descriptor.setEntityType(EntityType.EMBEDDED);
|
||||
descriptor.setName("Embeddable:" + cls.getSimpleName());
|
||||
}
|
||||
|
||||
Set<Index> indices = AnnotationBase.findAnnotations(cls, Index.class);
|
||||
Set<Index> indices = AnnotationBase.findAnnotationsRecursive(cls, Index.class);
|
||||
for (Index index : indices) {
|
||||
descriptor.addIndex(new IndexDefinition(index.columnNames(), index.name(), index.unique()));
|
||||
}
|
||||
|
||||
UniqueConstraint uc = AnnotationBase.findAnnotation(cls, UniqueConstraint.class);
|
||||
UniqueConstraint uc = AnnotationBase.findAnnotationRecursive(cls, UniqueConstraint.class);
|
||||
if (uc != null) {
|
||||
descriptor.addIndex(new IndexDefinition(uc.columnNames()));
|
||||
}
|
||||
|
||||
View view = AnnotationBase.findAnnotation(cls, View.class);
|
||||
View view = AnnotationBase.findAnnotationRecursive(cls, View.class);
|
||||
if (view != null) {
|
||||
descriptor.setView(view.name(), view.dependentTables());
|
||||
}
|
||||
Table table = AnnotationBase.findAnnotation(cls, Table.class);
|
||||
Table table = AnnotationBase.findAnnotationRecursive(cls, Table.class);
|
||||
if (table != null) {
|
||||
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
|
||||
for (UniqueConstraint c : uniqueConstraints) {
|
||||
@@ -154,42 +154,42 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
Draftable draftable = AnnotationBase.findAnnotation(cls, Draftable.class);
|
||||
Draftable draftable = AnnotationBase.findAnnotationRecursive(cls, Draftable.class);
|
||||
if (draftable != null) {
|
||||
descriptor.setDraftable();
|
||||
}
|
||||
|
||||
DraftableElement draftableElement = AnnotationBase.findAnnotation(cls, DraftableElement.class);
|
||||
DraftableElement draftableElement = AnnotationBase.findAnnotationRecursive(cls, DraftableElement.class);
|
||||
if (draftableElement != null) {
|
||||
descriptor.setDraftableElement();
|
||||
}
|
||||
|
||||
ReadAudit readAudit = AnnotationBase.findAnnotation(cls, ReadAudit.class);
|
||||
ReadAudit readAudit = AnnotationBase.findAnnotationRecursive(cls, ReadAudit.class);
|
||||
if (readAudit != null) {
|
||||
descriptor.setReadAuditing();
|
||||
}
|
||||
|
||||
History history = AnnotationBase.findAnnotation(cls, History.class);
|
||||
History history = AnnotationBase.findAnnotationRecursive(cls, History.class);
|
||||
if (history != null) {
|
||||
descriptor.setHistorySupport();
|
||||
}
|
||||
|
||||
DbComment comment = AnnotationBase.findAnnotation(cls, DbComment.class);
|
||||
DbComment comment = AnnotationBase.findAnnotationRecursive(cls, DbComment.class);
|
||||
if (comment != null) {
|
||||
descriptor.setDbComment(comment.value());
|
||||
}
|
||||
|
||||
UpdateMode updateMode = AnnotationBase.findAnnotation(cls, UpdateMode.class);
|
||||
UpdateMode updateMode = AnnotationBase.findAnnotationRecursive(cls, UpdateMode.class);
|
||||
if (updateMode != null) {
|
||||
descriptor.setUpdateChangesOnly(updateMode.updateChangesOnly());
|
||||
}
|
||||
|
||||
Cache cache = AnnotationBase.findAnnotation(cls, Cache.class);
|
||||
Cache cache = AnnotationBase.findAnnotationRecursive(cls, Cache.class);
|
||||
if (cache != null && !disableL2Cache) {
|
||||
descriptor.setCache(cache);
|
||||
}
|
||||
|
||||
Set<NamedQuery> namedQueries = AnnotationBase.findAnnotations(cls, NamedQuery.class);
|
||||
Set<NamedQuery> namedQueries = AnnotationBase.findAnnotationsRecursive(cls, NamedQuery.class);
|
||||
for (NamedQuery namedQuery : namedQueries) {
|
||||
descriptor.addNamedQuery(namedQuery.name(), namedQuery.query());
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class AnnotationSql extends AnnotationParser {
|
||||
@Override
|
||||
public void parse() {
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
Sql sql = AnnotationBase.findAnnotation(cls, Sql.class);
|
||||
Sql sql = AnnotationBase.findAnnotationRecursive(cls, Sql.class);
|
||||
if (sql != null) {
|
||||
descriptor.setEntityType(BeanDescriptor.EntityType.SQL);
|
||||
}
|
||||
|
||||
@@ -109,11 +109,11 @@ public class DeployInherit {
|
||||
info.setParent(parent);
|
||||
}
|
||||
|
||||
Inheritance ia = AnnotationBase.findAnnotation(cls, Inheritance.class);
|
||||
Inheritance ia = AnnotationBase.findAnnotationRecursive(cls, Inheritance.class);
|
||||
if (ia != null) {
|
||||
ia.strategy();
|
||||
}
|
||||
DiscriminatorColumn da = AnnotationBase.findAnnotation(cls, DiscriminatorColumn.class);
|
||||
DiscriminatorColumn da = AnnotationBase.findAnnotationRecursive(cls, DiscriminatorColumn.class);
|
||||
if (da != null) {
|
||||
// lowercase the discriminator column for RawSql and JSON
|
||||
info.setColumnName(da.name().toLowerCase());
|
||||
@@ -122,7 +122,7 @@ public class DeployInherit {
|
||||
info.setColumnDefn(da.columnDefinition());
|
||||
}
|
||||
|
||||
DiscriminatorValue dv = AnnotationBase.findAnnotation(cls, DiscriminatorValue.class);
|
||||
DiscriminatorValue dv = AnnotationBase.findAnnotationRecursive(cls, DiscriminatorValue.class);
|
||||
if (dv != null) {
|
||||
info.setDiscriminatorValue(dv.value());
|
||||
}
|
||||
@@ -144,7 +144,7 @@ public class DeployInherit {
|
||||
if (cls.equals(Object.class)) {
|
||||
return false;
|
||||
}
|
||||
Annotation a = AnnotationBase.findAnnotation(cls, Inheritance.class);
|
||||
Annotation a = AnnotationBase.findAnnotationRecursive(cls, Inheritance.class);
|
||||
if (a != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.dbmigration.DbOffline;
|
||||
import io.ebean.plugin.ExtraTypeFactory;
|
||||
import io.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import io.ebeaninternal.server.deploy.parse.AnnotationBase;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -543,7 +544,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
Field[] fields = enumType.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
EnumValue enumValue = field.getAnnotation(EnumValue.class);
|
||||
EnumValue enumValue = AnnotationBase.findAnnotation(field, EnumValue.class);
|
||||
if (enumValue != null) {
|
||||
nameValueMap.put(field.getName(), enumValue.value());
|
||||
if (integerType && !isIntegerType(enumValue.value())) {
|
||||
@@ -574,7 +575,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
Method[] methods = enumType.getMethods();
|
||||
for (Method method : methods) {
|
||||
DbEnumValue dbValue = method.getAnnotation(DbEnumValue.class);
|
||||
DbEnumValue dbValue = AnnotationBase.findAnnotation(method, DbEnumValue.class);
|
||||
if (dbValue != null) {
|
||||
boolean integerValues = DbEnumType.INTEGER == dbValue.storage();
|
||||
return createEnumScalarTypeDbValue(enumType, method, integerValues);
|
||||
|
||||
Reference in New Issue
Block a user