diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java index 9d990658f5..6bb58b0501 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java @@ -75,6 +75,7 @@ public final class Context { private boolean addSuppressWarningsAnnotation; private boolean addTransactionScopedAnnotation; private AccessType persistenceUnitDefaultAccessType; + private boolean generateJakartaDataStaticMetamodel; private boolean jakartaDataStyle; // keep track of all classes for which model have been generated @@ -128,6 +129,15 @@ public final class Context { public void setJakartaDataStyle(boolean jakartaDataStyle) { this.jakartaDataStyle = jakartaDataStyle; } + + public boolean generateJakartaDataStaticMetamodel() { + return generateJakartaDataStaticMetamodel; + } + + public void setGenerateJakartaDataStaticMetamodel(boolean generateJakartaDataStaticMetamodel) { + this.generateJakartaDataStaticMetamodel = generateJakartaDataStaticMetamodel; + } + public boolean addInjectAnnotation() { return addInjectAnnotation; } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java index d62738ce92..1904040839 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java @@ -152,12 +152,16 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor { final PackageElement jakartaTransactionsPackage = context.getProcessingEnvironment().getElementUtils() .getPackageElement( "jakarta.transactions" ); + final PackageElement jakartaDataPackage = + context.getProcessingEnvironment().getElementUtils() + .getPackageElement( "jakarta.data" ); context.setAddInjectAnnotation( jakartaInjectPackage != null ); context.setAddNonnullAnnotation( jakartaAnnotationPackage != null ); context.setAddGeneratedAnnotation( jakartaAnnotationPackage != null ); context.setAddDependentAnnotation( jakartaContextPackage != null ); context.setAddTransactionScopedAnnotation( jakartaTransactionsPackage != null ); + context.setGenerateJakartaDataStaticMetamodel( jakartaDataPackage != null ); final Map options = environment.getOptions(); diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaAttribute.java index 8857306401..7a84311758 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaAttribute.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaAttribute.java @@ -6,16 +6,13 @@ */ package org.hibernate.jpamodelgen.annotation; -import java.beans.Introspector; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.util.Elements; - import org.hibernate.jpamodelgen.model.MetaAttribute; import org.hibernate.jpamodelgen.model.Metamodel; -import static java.beans.Introspector.decapitalize; +import javax.lang.model.element.Element; + import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFromLowerCamelCase; +import static org.hibernate.jpamodelgen.util.TypeUtils.propertyName; /** * Captures all information about an annotated persistent attribute. @@ -62,6 +59,7 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute { .append( parent.importType( getTypeDeclaration() ) ) .append( "> " ) .append( getPropertyName() ) + .append( parent.getContext().useJakartaDataStyle() ? "_" : "" ) .append( ";" ) .toString(); } @@ -83,23 +81,7 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute { @Override public String getPropertyName() { - final Elements elementsUtil = parent.getContext().getElementUtils(); - if ( element.getKind() == ElementKind.FIELD ) { - return element.getSimpleName().toString(); - } - else if ( element.getKind() == ElementKind.METHOD ) { - final String name = element.getSimpleName().toString(); - if ( name.startsWith( "get" ) ) { - return elementsUtil.getName( decapitalize( name.substring( "get".length() ) ) ).toString(); - } - else if ( name.startsWith( "is" ) ) { - return ( elementsUtil.getName( decapitalize( name.substring( "is".length() ) ) ) ).toString(); - } - return elementsUtil.getName( decapitalize( name ) ).toString(); - } - else { - return elementsUtil.getName( element.getSimpleName() + "/* " + element.getKind() + " */" ).toString(); - } + return propertyName(parent, element); } @Override diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java index 5188bba22d..db846ed62b 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java @@ -6,31 +6,6 @@ */ package org.hibernate.jpamodelgen.annotation; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.regex.Pattern; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.Name; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.ExecutableType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.WildcardType; -import javax.lang.model.util.Types; -import javax.tools.Diagnostic; - import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.AssertionFailure; import org.hibernate.jpamodelgen.Context; @@ -57,6 +32,31 @@ import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.ExecutableType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.WildcardType; +import javax.lang.model.util.Types; +import javax.tools.Diagnostic; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.regex.Pattern; + import static java.beans.Introspector.decapitalize; import static java.lang.Boolean.FALSE; import static java.util.Collections.emptyList; @@ -498,11 +498,19 @@ public class AnnotationMetaEntity extends AnnotationMeta { private void addPersistentMembers(List membersOfClass, AccessType membersKind) { for ( Element memberOfClass : membersOfClass ) { if ( isPersistent( memberOfClass, membersKind ) ) { - final AnnotationMetaAttribute result = + final AnnotationMetaAttribute jpaMetaAttribute = memberOfClass.asType() .accept( new MetaAttributeGenerationVisitor( this, context ), memberOfClass ); - if ( result != null ) { - members.put( result.getPropertyName(), result ); + if ( jpaMetaAttribute != null ) { + members.put( jpaMetaAttribute.getPropertyName(), jpaMetaAttribute ); + } + if ( context.generateJakartaDataStaticMetamodel() ) { + final DataAnnotationMetaAttribute dataMetaAttribute = + memberOfClass.asType() + .accept( new DataMetaAttributeGenerationVisitor( this, context ), memberOfClass ); + if ( dataMetaAttribute != null ) { + members.put( '_' + dataMetaAttribute.getPropertyName(), dataMetaAttribute ); + } } } } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaMap.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaMap.java index 0a06cf80fb..2a71b2b749 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaMap.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaMap.java @@ -41,6 +41,7 @@ public class AnnotationMetaMap extends AnnotationMetaCollection { .append( parent.importType( getTypeDeclaration() ) ) .append("> ") .append( getPropertyName() ) + .append( parent.getContext().useJakartaDataStyle() ? "_" : "" ) .append(";") .toString(); } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/DataAnnotationMetaAttribute.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/DataAnnotationMetaAttribute.java new file mode 100644 index 0000000000..8e912e9836 --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/DataAnnotationMetaAttribute.java @@ -0,0 +1,159 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.annotation; + +import org.hibernate.jpamodelgen.model.MetaAttribute; +import org.hibernate.jpamodelgen.model.Metamodel; +import org.hibernate.jpamodelgen.util.Constants; + +import javax.lang.model.element.Element; + +import static org.hibernate.jpamodelgen.util.TypeUtils.propertyName; + +/** + * Captures all information about an annotated persistent attribute. + * + * @author Gavin King + */ +public class DataAnnotationMetaAttribute implements MetaAttribute { + + final Element element; + final AnnotationMetaEntity parent; + private final String type; + + public DataAnnotationMetaAttribute(AnnotationMetaEntity parent, Element element, String type) { + this.element = element; + this.parent = parent; + this.type = type; + } + + @Override + public boolean hasTypedAttribute() { + return true; + } + + @Override + public boolean hasStringAttribute() { + return false; + } + + private boolean isTextual() { + return String.class.getName().equals(type); + } + + @Override + public String getAttributeDeclarationString() { + final String className = parent.importType( parent.getQualifiedName() ); + final String memberName = element.getSimpleName().toString(); + return new StringBuilder() + .append("\n/**\n * @see ") + .append(className) + .append( "#") + .append(memberName) + .append( "\n **/\n" ) + .append( "public static volatile " ) + .append( parent.importType( getMetaType() ) ) + .append( "<" ) + .append( className ) + .append( "> " ) + .append( parent.getContext().useJakartaDataStyle() ? "" : "_" ) + .append( getPropertyName() ) + .append(" = ") + .append( getMetaImpl(className, memberName) ) + .append( ";" ) + .toString(); + } + + private String getMetaImpl(String className, String memberName) { + parent.importType(Constants.JD_SORT); + return (isTextual() ? TEXT_IMPL : SORTABLE_IMPL) + .replace("Entity", className ) + .replace( "\"name\"", "\"" + memberName + "\"" ); + } + + private static final String TEXT_IMPL = + "new TextAttribute<>() {\n" + + "\t\t@Override\n" + + "\t\tpublic Sort ascIgnoreCase() {\n" + + "\t\t\treturn Sort.ascIgnoreCase(name());\n" + + "\t\t}\n" + + "\n" + + "\t\t@Override\n" + + "\t\tpublic Sort descIgnoreCase() {\n" + + "\t\t\treturn Sort.descIgnoreCase(name());\n" + + "\t\t}\n" + + "\n" + + "\t\t@Override\n" + + "\t\tpublic Sort asc() {\n" + + "\t\t\treturn Sort.asc(name());\n" + + "\t\t}\n" + + "\n" + + "\t\t@Override\n" + + "\t\tpublic Sort desc() {\n" + + "\t\t\treturn Sort.desc(name());\n" + + "\t\t}\n" + + "\n" + + "\t\t@Override\n" + + "\t\tpublic String name() {\n" + + "\t\t\treturn \"name\";\n" + + "\t\t}\n" + + "\t}"; + + private static final String SORTABLE_IMPL = + "new SortableAttribute<>() {\n" + + "\t\t@Override\n" + + "\t\tpublic Sort asc() {\n" + + "\t\t\treturn Sort.asc(name());\n" + + "\t\t}\n" + + "\n" + + "\t\t@Override\n" + + "\t\tpublic Sort desc() {\n" + + "\t\t\treturn Sort.desc(name());\n" + + "\t\t}\n" + + "\n" + + "\t\t@Override\n" + + "\t\tpublic String name() {\n" + + "\t\t\treturn \"name\";\n" + + "\t\t}\n" + + "\t}"; + + @Override + public String getAttributeNameDeclarationString(){ + throw new UnsupportedOperationException(); + } + + @Override + public String getPropertyName() { + return propertyName( parent, element ); + } + + @Override + public Metamodel getHostingEntity() { + return parent; + } + + @Override + public String getMetaType() { + return isTextual() + ? "jakarta.data.metamodel.TextAttribute" + : "jakarta.data.metamodel.SortableAttribute"; + } + + @Override + public String getTypeDeclaration() { + return type; + } + + @Override + public String toString() { + return new StringBuilder() + .append( "DataAnnotationMetaAttribute" ) + .append( "{element=" ).append( element ) + .append( ", type='" ).append( type ).append( '\'' ) + .append( '}' ).toString(); + } +} diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/DataMetaAttributeGenerationVisitor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/DataMetaAttributeGenerationVisitor.java new file mode 100644 index 0000000000..8aa7adddaf --- /dev/null +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/DataMetaAttributeGenerationVisitor.java @@ -0,0 +1,89 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpamodelgen.annotation; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.hibernate.jpamodelgen.Context; +import org.hibernate.jpamodelgen.util.Constants; +import org.hibernate.jpamodelgen.util.TypeUtils; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.ExecutableType; +import javax.lang.model.type.PrimitiveType; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.util.SimpleTypeVisitor8; +import javax.lang.model.util.Types; + +import static org.hibernate.jpamodelgen.util.TypeUtils.getTargetEntity; +import static org.hibernate.jpamodelgen.util.TypeUtils.isBasicAttribute; +import static org.hibernate.jpamodelgen.util.TypeUtils.toArrayTypeString; +import static org.hibernate.jpamodelgen.util.TypeUtils.toTypeString; + +/** + * @author Gavin King + */ +public class DataMetaAttributeGenerationVisitor extends SimpleTypeVisitor8<@Nullable DataAnnotationMetaAttribute, Element> { + + private final AnnotationMetaEntity entity; + private final Context context; + + DataMetaAttributeGenerationVisitor(AnnotationMetaEntity entity, Context context) { + this.entity = entity; + this.context = context; + } + + private Types typeUtils() { + return context.getTypeUtils(); + } + + @Override + public @Nullable DataAnnotationMetaAttribute visitPrimitive(PrimitiveType primitiveType, Element element) { + return new DataAnnotationMetaAttribute( entity, element, toTypeString( primitiveType ) ); + } + + @Override + public @Nullable DataAnnotationMetaAttribute visitArray(ArrayType arrayType, Element element) { + return new DataAnnotationMetaAttribute( entity, element, toArrayTypeString( arrayType, context ) ); + } + + @Override + public @Nullable DataAnnotationMetaAttribute visitTypeVariable(TypeVariable typeVariable, Element element) { + // METAGEN-29 - for a type variable we use the upper bound + return new DataAnnotationMetaAttribute( entity, element, + typeUtils().erasure( typeVariable.getUpperBound() ).toString() ); + } + + @Override + public @Nullable DataAnnotationMetaAttribute visitDeclared(DeclaredType declaredType, Element element) { + final TypeElement returnedElement = (TypeElement) typeUtils().asElement( declaredType ); + // WARNING: .toString() is necessary here since Name equals does not compare to String + final String returnTypeName = returnedElement.getQualifiedName().toString(); + final String collection = Constants.COLLECTIONS.get( returnTypeName ); + final String targetEntity = getTargetEntity( element.getAnnotationMirrors() ); + if ( collection != null ) { + return null; + } + else if ( isBasicAttribute( element, returnedElement, context ) ) { + final String type = targetEntity != null ? targetEntity : returnedElement.getQualifiedName().toString(); + return new DataAnnotationMetaAttribute( entity, element, type ); + } + else { + return null; + } + } + + @Override + public @Nullable DataAnnotationMetaAttribute visitExecutable(ExecutableType executable, Element element) { + return TypeUtils.isPropertyGetter( executable, element ) + ? executable.getReturnType().accept(this, element) + : null; + } +} + diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttributeGenerationVisitor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttributeGenerationVisitor.java index 516c938ed9..206c239644 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttributeGenerationVisitor.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/MetaAttributeGenerationVisitor.java @@ -6,10 +6,15 @@ */ package org.hibernate.jpamodelgen.annotation; -import java.util.List; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.hibernate.jpamodelgen.Context; +import org.hibernate.jpamodelgen.util.AccessType; +import org.hibernate.jpamodelgen.util.AccessTypeInformation; +import org.hibernate.jpamodelgen.util.Constants; +import org.hibernate.jpamodelgen.util.TypeUtils; + import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; @@ -21,26 +26,13 @@ import javax.lang.model.type.TypeVariable; import javax.lang.model.util.SimpleTypeVisitor8; import javax.lang.model.util.Types; import javax.tools.Diagnostic; +import java.util.List; -import org.hibernate.jpamodelgen.Context; -import org.hibernate.jpamodelgen.util.AccessType; -import org.hibernate.jpamodelgen.util.AccessTypeInformation; -import org.hibernate.jpamodelgen.util.Constants; - -import org.checkerframework.checker.nullness.qual.Nullable; - -import static org.hibernate.jpamodelgen.util.Constants.BASIC; import static org.hibernate.jpamodelgen.util.Constants.ELEMENT_COLLECTION; -import static org.hibernate.jpamodelgen.util.Constants.EMBEDDED_ID; -import static org.hibernate.jpamodelgen.util.Constants.ID; import static org.hibernate.jpamodelgen.util.Constants.MANY_TO_ANY; import static org.hibernate.jpamodelgen.util.Constants.MANY_TO_MANY; -import static org.hibernate.jpamodelgen.util.Constants.MANY_TO_ONE; import static org.hibernate.jpamodelgen.util.Constants.ONE_TO_MANY; -import static org.hibernate.jpamodelgen.util.Constants.ONE_TO_ONE; -import static org.hibernate.jpamodelgen.util.TypeUtils.hasAnnotation; import static org.hibernate.jpamodelgen.util.NullnessUtil.castNonNull; -import static org.hibernate.jpamodelgen.util.StringUtil.isProperty; import static org.hibernate.jpamodelgen.util.TypeUtils.DEFAULT_ANNOTATION_PARAMETER_NAME; import static org.hibernate.jpamodelgen.util.TypeUtils.determineAnnotationSpecifiedAccessType; import static org.hibernate.jpamodelgen.util.TypeUtils.extractClosestRealTypeAsString; @@ -48,7 +40,9 @@ import static org.hibernate.jpamodelgen.util.TypeUtils.getAnnotationMirror; import static org.hibernate.jpamodelgen.util.TypeUtils.getAnnotationValue; import static org.hibernate.jpamodelgen.util.TypeUtils.getCollectionElementType; import static org.hibernate.jpamodelgen.util.TypeUtils.getKeyType; -import static org.hibernate.jpamodelgen.util.TypeUtils.isAnnotationMirrorOfType; +import static org.hibernate.jpamodelgen.util.TypeUtils.hasAnnotation; +import static org.hibernate.jpamodelgen.util.TypeUtils.isBasicAttribute; +import static org.hibernate.jpamodelgen.util.TypeUtils.isPropertyGetter; import static org.hibernate.jpamodelgen.util.TypeUtils.toArrayTypeString; import static org.hibernate.jpamodelgen.util.TypeUtils.toTypeString; @@ -57,18 +51,6 @@ import static org.hibernate.jpamodelgen.util.TypeUtils.toTypeString; */ public class MetaAttributeGenerationVisitor extends SimpleTypeVisitor8<@Nullable AnnotationMetaAttribute, Element> { - /** - * FQCN of the Hibernate-specific {@code @Target} annotation. - * We do not use the class directly to avoid depending on Hibernate Core. - */ - private static final String ORG_HIBERNATE_ANNOTATIONS_TARGET = "org.hibernate.annotations.Target"; - - /** - * FQCN of the Hibernate-specific {@code @Type} annotation. - * We do not use the class directly to avoid depending on Hibernate Core. - */ - private static final String ORG_HIBERNATE_ANNOTATIONS_TYPE = "org.hibernate.annotations.Type"; - private final AnnotationMetaEntity entity; private final Context context; @@ -104,11 +86,11 @@ public class MetaAttributeGenerationVisitor extends SimpleTypeVisitor8<@Nullable // WARNING: .toString() is necessary here since Name equals does not compare to String final String returnTypeName = returnedElement.getQualifiedName().toString(); final String collection = Constants.COLLECTIONS.get( returnTypeName ); - final String targetEntity = getTargetEntity( element.getAnnotationMirrors() ); + final String targetEntity = TypeUtils.getTargetEntity( element.getAnnotationMirrors() ); if ( collection != null ) { return createMetaCollectionAttribute( declaredType, element, returnTypeName, collection, targetEntity ); } - else if ( isBasicAttribute( element, returnedElement ) ) { + else if ( isBasicAttribute( element, returnedElement, context ) ) { final String type = targetEntity != null ? targetEntity : returnedElement.getQualifiedName().toString(); return new AnnotationMetaSingleAttribute( entity, element, type ); } @@ -121,7 +103,7 @@ public class MetaAttributeGenerationVisitor extends SimpleTypeVisitor8<@Nullable DeclaredType declaredType, Element element, String returnTypeName, String collection, @Nullable String targetEntity) { if ( hasAnnotation( element, ELEMENT_COLLECTION ) ) { - final String explicitTargetEntity = getTargetEntity( element.getAnnotationMirrors() ); + final String explicitTargetEntity = TypeUtils.getTargetEntity( element.getAnnotationMirrors() ); final TypeMirror collectionElementType = getCollectionElementType( declaredType, returnTypeName, explicitTargetEntity, context ); if ( collectionElementType.getKind() == TypeKind.DECLARED ) { @@ -177,18 +159,6 @@ public class MetaAttributeGenerationVisitor extends SimpleTypeVisitor8<@Nullable : null; } - private static boolean isPropertyGetter(ExecutableType executable, Element element) { - return element.getKind() == ElementKind.METHOD - && isProperty( element.getSimpleName().toString(), - toTypeString( executable.getReturnType() ) ); - } - - private boolean isBasicAttribute(Element element, Element returnedElement) { - return hasAnnotation( element, BASIC, ONE_TO_ONE, MANY_TO_ONE, EMBEDDED_ID, ID ) - || hasAnnotation( element, ORG_HIBERNATE_ANNOTATIONS_TYPE ) // METAGEN-28 - || returnedElement.asType().accept( new BasicAttributeVisitor( context ), returnedElement ); - } - private String getMapKeyType(DeclaredType declaredType, Element element) { final AnnotationMirror annotationMirror = getAnnotationMirror(element, Constants.MAP_KEY_CLASS ); return annotationMirror == null @@ -219,41 +189,5 @@ public class MetaAttributeGenerationVisitor extends SimpleTypeVisitor8<@Nullable } } - /** - * @param annotations list of annotation mirrors. - * - * @return target entity class name as string or {@code null} if no targetEntity is here or if equals to void - */ - private @Nullable String getTargetEntity(List annotations) { - for ( AnnotationMirror mirror : annotations ) { - if ( isAnnotationMirrorOfType( mirror, ELEMENT_COLLECTION ) ) { - return getFullyQualifiedClassNameOfTargetEntity( mirror, "targetClass" ); - } - else if ( isAnnotationMirrorOfType( mirror, ONE_TO_MANY ) - || isAnnotationMirrorOfType( mirror, MANY_TO_MANY ) - || isAnnotationMirrorOfType( mirror, MANY_TO_ONE ) - || isAnnotationMirrorOfType( mirror, ONE_TO_ONE ) ) { - return getFullyQualifiedClassNameOfTargetEntity( mirror, "targetEntity" ); - } - else if ( isAnnotationMirrorOfType( mirror, ORG_HIBERNATE_ANNOTATIONS_TARGET ) ) { - return getFullyQualifiedClassNameOfTargetEntity( mirror, "value" ); - } - } - return null; - } - - private @Nullable String getFullyQualifiedClassNameOfTargetEntity(AnnotationMirror mirror, String parameterName) { - assert mirror != null; - assert parameterName != null; - - final Object parameterValue = getAnnotationValue( mirror, parameterName ); - if ( parameterValue != null ) { - final TypeMirror parameterType = (TypeMirror) parameterValue; - if ( parameterType.getKind() != TypeKind.VOID ) { - return parameterType.toString(); - } - } - return null; - } } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/BasicAttributeVisitor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/BasicAttributeVisitor.java similarity index 98% rename from tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/BasicAttributeVisitor.java rename to tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/BasicAttributeVisitor.java index fe5630ad2e..ef3f6bee10 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/BasicAttributeVisitor.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/BasicAttributeVisitor.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.jpamodelgen.annotation; +package org.hibernate.jpamodelgen.util; import org.hibernate.jpamodelgen.Context; import org.hibernate.jpamodelgen.util.Constants; diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/TypeUtils.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/TypeUtils.java index 374997dfbe..49edc12d5e 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/TypeUtils.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/util/TypeUtils.java @@ -6,12 +6,11 @@ */ package org.hibernate.jpamodelgen.util; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.hibernate.jpamodelgen.Context; +import org.hibernate.jpamodelgen.MetaModelGenerationException; +import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity; + import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; @@ -28,16 +27,31 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeVariable; import javax.lang.model.type.WildcardType; import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.Elements; import javax.lang.model.util.SimpleTypeVisitor8; import javax.tools.Diagnostic; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; -import org.hibernate.jpamodelgen.Context; -import org.hibernate.jpamodelgen.MetaModelGenerationException; - -import org.checkerframework.checker.nullness.qual.Nullable; - +import static java.beans.Introspector.decapitalize; +import static org.hibernate.jpamodelgen.util.Constants.ACCESS; +import static org.hibernate.jpamodelgen.util.Constants.BASIC; +import static org.hibernate.jpamodelgen.util.Constants.ELEMENT_COLLECTION; +import static org.hibernate.jpamodelgen.util.Constants.EMBEDDABLE; +import static org.hibernate.jpamodelgen.util.Constants.EMBEDDED_ID; +import static org.hibernate.jpamodelgen.util.Constants.ENTITY; +import static org.hibernate.jpamodelgen.util.Constants.ID; import static org.hibernate.jpamodelgen.util.Constants.JAVA_OBJECT; +import static org.hibernate.jpamodelgen.util.Constants.MANY_TO_MANY; +import static org.hibernate.jpamodelgen.util.Constants.MANY_TO_ONE; import static org.hibernate.jpamodelgen.util.Constants.MAP; +import static org.hibernate.jpamodelgen.util.Constants.MAPPED_SUPERCLASS; +import static org.hibernate.jpamodelgen.util.Constants.ONE_TO_MANY; +import static org.hibernate.jpamodelgen.util.Constants.ONE_TO_ONE; import static org.hibernate.jpamodelgen.util.NullnessUtil.castNonNull; import static org.hibernate.jpamodelgen.util.StringUtil.isProperty; @@ -382,7 +396,7 @@ public final class TypeUtils { if ( accessTypeInfo != null && accessTypeInfo.getDefaultAccessType() != null ) { return accessTypeInfo.getDefaultAccessType(); } - if ( containsAnnotation( superClass, Constants.ENTITY, Constants.MAPPED_SUPERCLASS ) ) { + if ( containsAnnotation( superClass, ENTITY, MAPPED_SUPERCLASS ) ) { defaultAccessType = getAccessTypeInCaseElementIsRoot( superClass, context ); if ( defaultAccessType != null ) { final AccessTypeInformation newAccessTypeInfo @@ -416,7 +430,7 @@ public final class TypeUtils { superClass = getSuperclassTypeElement( superClass ); if ( superClass != null ) { final String qualifiedName = superClass.getQualifiedName().toString(); - if ( containsAnnotation( superClass, Constants.MAPPED_SUPERCLASS ) ) { + if ( containsAnnotation( superClass, MAPPED_SUPERCLASS ) ) { final AccessType forcedAccessType = determineAnnotationSpecifiedAccessType( superClass ); final AccessTypeInformation accessTypeInfo = forcedAccessType != null @@ -462,12 +476,12 @@ public final class TypeUtils { } private static boolean isIdAnnotation(AnnotationMirror annotationMirror) { - return isAnnotationMirrorOfType( annotationMirror, Constants.ID ) - || isAnnotationMirrorOfType( annotationMirror, Constants.EMBEDDED_ID ); + return isAnnotationMirrorOfType( annotationMirror, ID ) + || isAnnotationMirrorOfType( annotationMirror, EMBEDDED_ID ); } public static @Nullable AccessType determineAnnotationSpecifiedAccessType(Element element) { - final AnnotationMirror mirror = getAnnotationMirror( element, Constants.ACCESS ); + final AnnotationMirror mirror = getAnnotationMirror( element, ACCESS ); if ( mirror != null ) { final Object accessType = getAnnotationValue( mirror, DEFAULT_ANNOTATION_PARAMETER_NAME ); if ( accessType instanceof VariableElement) { @@ -529,6 +543,73 @@ public final class TypeUtils { } } + public static boolean isPropertyGetter(ExecutableType executable, Element element) { + return element.getKind() == ElementKind.METHOD + && isProperty( element.getSimpleName().toString(), + toTypeString( executable.getReturnType() ) ); + } + + public static boolean isBasicAttribute(Element element, Element returnedElement, Context context) { + return hasAnnotation( element, BASIC, ONE_TO_ONE, MANY_TO_ONE, EMBEDDED_ID, ID ) + || hasAnnotation( element, "org.hibernate.annotations.Type") // METAGEN-28 + || returnedElement.asType().accept( new BasicAttributeVisitor( context ), returnedElement ); + } + + public static @Nullable String getFullyQualifiedClassNameOfTargetEntity( + AnnotationMirror mirror, String parameterName) { + final Object parameterValue = getAnnotationValue( mirror, parameterName ); + if ( parameterValue != null ) { + final TypeMirror parameterType = (TypeMirror) parameterValue; + if ( parameterType.getKind() != TypeKind.VOID ) { + return parameterType.toString(); + } + } + return null; + } + + /** + * @param annotations list of annotation mirrors. + * + * @return target entity class name as string or {@code null} if no targetEntity is here or if equals to void + */ + public static @Nullable String getTargetEntity(List annotations) { + for ( AnnotationMirror mirror : annotations ) { + if ( isAnnotationMirrorOfType( mirror, ELEMENT_COLLECTION ) ) { + return getFullyQualifiedClassNameOfTargetEntity( mirror, "targetClass" ); + } + else if ( isAnnotationMirrorOfType( mirror, ONE_TO_MANY ) + || isAnnotationMirrorOfType( mirror, MANY_TO_MANY ) + || isAnnotationMirrorOfType( mirror, MANY_TO_ONE ) + || isAnnotationMirrorOfType( mirror, ONE_TO_ONE ) ) { + return getFullyQualifiedClassNameOfTargetEntity( mirror, "targetEntity" ); + } + else if ( isAnnotationMirrorOfType( mirror, "org.hibernate.annotations.Target") ) { + return getFullyQualifiedClassNameOfTargetEntity( mirror, "value" ); + } + } + return null; + } + + public static String propertyName(AnnotationMetaEntity parent, Element element) { + final Elements elementsUtil = parent.getContext().getElementUtils(); + if ( element.getKind() == ElementKind.FIELD ) { + return element.getSimpleName().toString(); + } + else if ( element.getKind() == ElementKind.METHOD ) { + final String name = element.getSimpleName().toString(); + if ( name.startsWith( "get" ) ) { + return elementsUtil.getName(decapitalize(name.substring(3))).toString(); + } + else if ( name.startsWith( "is" ) ) { + return (elementsUtil.getName(decapitalize(name.substring(2)))).toString(); + } + return elementsUtil.getName(decapitalize(name)).toString(); + } + else { + return elementsUtil.getName(element.getSimpleName() + "/* " + element.getKind() + " */").toString(); + } + } + static class EmbeddedAttributeVisitor extends SimpleTypeVisitor8<@Nullable String, Element> { private final Context context; @@ -540,7 +621,7 @@ public final class TypeUtils { public @Nullable String visitDeclared(DeclaredType declaredType, Element element) { final TypeElement returnedElement = (TypeElement) context.getTypeUtils().asElement( declaredType ); - return containsAnnotation( returnedElement, Constants.EMBEDDABLE ) + return containsAnnotation( returnedElement, EMBEDDABLE ) ? returnedElement.getQualifiedName().toString() : null; }