HHH-17772 Jakarta Data static metamodel

This commit is contained in:
Gavin King 2024-02-24 15:39:28 +01:00
parent d6125e21f5
commit a23792ca1b
10 changed files with 417 additions and 149 deletions

View File

@ -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;
}

View File

@ -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<String, String> options = environment.getOptions();

View File

@ -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

View File

@ -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<? extends Element> 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 );
}
}
}
}

View File

@ -41,6 +41,7 @@ public class AnnotationMetaMap extends AnnotationMetaCollection {
.append( parent.importType( getTypeDeclaration() ) )
.append("> ")
.append( getPropertyName() )
.append( parent.getContext().useJakartaDataStyle() ? "_" : "" )
.append(";")
.toString();
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Entity> ascIgnoreCase() {\n" +
"\t\t\treturn Sort.ascIgnoreCase(name());\n" +
"\t\t}\n" +
"\n" +
"\t\t@Override\n" +
"\t\tpublic Sort<Entity> descIgnoreCase() {\n" +
"\t\t\treturn Sort.descIgnoreCase(name());\n" +
"\t\t}\n" +
"\n" +
"\t\t@Override\n" +
"\t\tpublic Sort<Entity> asc() {\n" +
"\t\t\treturn Sort.asc(name());\n" +
"\t\t}\n" +
"\n" +
"\t\t@Override\n" +
"\t\tpublic Sort<Entity> 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<Entity> asc() {\n" +
"\t\t\treturn Sort.asc(name());\n" +
"\t\t}\n" +
"\n" +
"\t\t@Override\n" +
"\t\tpublic Sort<Entity> 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();
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}
}

View File

@ -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<? extends AnnotationMirror> 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;
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpamodelgen.annotation;
package org.hibernate.jpamodelgen.util;
import org.hibernate.jpamodelgen.Context;
import org.hibernate.jpamodelgen.util.Constants;

View File

@ -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<? extends AnnotationMirror> 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;
}