diff --git a/src/main/java/org/hibernate/models/internal/dynamic/DynamicClassDetails.java b/src/main/java/org/hibernate/models/internal/dynamic/DynamicClassDetails.java index 6bef9da..2ababb2 100644 --- a/src/main/java/org/hibernate/models/internal/dynamic/DynamicClassDetails.java +++ b/src/main/java/org/hibernate/models/internal/dynamic/DynamicClassDetails.java @@ -20,6 +20,8 @@ import org.hibernate.models.spi.TypeVariableDetails; /** + * ClassDetails which does not necessarily map to a physical Class (dynamic models) + * * @author Steve Ebersole */ public class DynamicClassDetails extends AbstractAnnotationTarget implements ClassDetailsSupport { @@ -53,12 +55,24 @@ public DynamicClassDetails( ClassDetails superClass, TypeDetails genericSuperType, SourceModelBuildingContext buildingContext) { + this( name, className, null, isAbstract, superClass, genericSuperType, buildingContext ); + } + + public DynamicClassDetails( + String name, + String className, + Class javaType, + boolean isAbstract, + ClassDetails superClass, + TypeDetails genericSuperType, + SourceModelBuildingContext buildingContext) { super( buildingContext ); this.name = name; this.className = className; this.isAbstract = isAbstract; this.superClass = superClass; this.genericSuperType = genericSuperType; + this.javaType = javaType; } @Override diff --git a/src/main/java/org/hibernate/models/internal/dynamic/DynamicFieldDetails.java b/src/main/java/org/hibernate/models/internal/dynamic/DynamicFieldDetails.java index 0f4372c..2baad04 100644 --- a/src/main/java/org/hibernate/models/internal/dynamic/DynamicFieldDetails.java +++ b/src/main/java/org/hibernate/models/internal/dynamic/DynamicFieldDetails.java @@ -18,6 +18,8 @@ import org.hibernate.models.spi.TypeVariableScope; /** + * FieldDetails which does not necessarily map to a physical Field (dynamic models) + * * @author Steve Ebersole */ public class DynamicFieldDetails extends AbstractAnnotationTarget implements FieldDetails, MutableMemberDetails { @@ -35,20 +37,32 @@ public DynamicFieldDetails( ClassDetails declaringType, int modifierFlags, SourceModelBuildingContext buildingContext) { + this( + name, + type, + declaringType, + modifierFlags, + type != null && type.getName().startsWith( "[" ), + type != null && ( type.isImplementor( Collection.class ) || type.isImplementor( Map.class ) ), + buildingContext + ); + } + + public DynamicFieldDetails( + String name, + TypeDetails type, + ClassDetails declaringType, + int modifierFlags, + boolean isArray, + boolean isPlural, + SourceModelBuildingContext buildingContext) { super( buildingContext ); this.name = name; this.type = type; this.declaringType = declaringType; this.modifierFlags = modifierFlags; - - if ( type != null ) { - this.isArray = type.getName().startsWith( "[" ); - this.isPlural = isArray || type.isImplementor( Collection.class ) || type.isImplementor( Map.class ); - } - else { - this.isArray = false; - this.isPlural = false; - } + this.isArray = isArray; + this.isPlural = isPlural; } @Override diff --git a/src/main/java/org/hibernate/models/internal/dynamic/DynamicMethodDetails.java b/src/main/java/org/hibernate/models/internal/dynamic/DynamicMethodDetails.java index b0ef1e9..0d05656 100644 --- a/src/main/java/org/hibernate/models/internal/dynamic/DynamicMethodDetails.java +++ b/src/main/java/org/hibernate/models/internal/dynamic/DynamicMethodDetails.java @@ -19,6 +19,8 @@ import org.hibernate.models.spi.TypeVariableScope; /** + * MethodDetails which does not necessarily map to a physical Method (dynamic models) + * * @author Steve Ebersole */ public class DynamicMethodDetails extends AbstractAnnotationTarget implements MethodDetails, MutableMemberDetails { @@ -43,23 +45,41 @@ public DynamicMethodDetails( ClassDetails returnType, List argumentTypes, SourceModelBuildingContext buildingContext) { + this( + name, + type, + declaringType, + methodKind, + modifierFlags, + type != null && type.getName().startsWith( "[" ), + type != null && ( type.isImplementor( Collection.class ) || type.isImplementor( Map.class ) ), + returnType, + argumentTypes, + buildingContext + ); + } + + public DynamicMethodDetails( + String name, + TypeDetails type, + ClassDetails declaringType, + MethodKind methodKind, + int modifierFlags, + boolean isArray, + boolean isPlural, + ClassDetails returnType, + List argumentTypes, + SourceModelBuildingContext buildingContext) { super( buildingContext ); this.name = name; this.type = type; this.declaringType = declaringType; this.methodKind = methodKind; this.modifierFlags = modifierFlags; + this.isArray = isArray; + this.isPlural = isPlural; this.returnType = returnType; this.argumentTypes = argumentTypes; - - if ( type != null ) { - this.isArray = type.getName().startsWith( "[" ); - this.isPlural = isArray || type.isImplementor( Collection.class ) || type.isImplementor( Map.class ); - } - else { - this.isArray = false; - this.isPlural = false; - } } @Override diff --git a/src/test/java/org/hibernate/models/annotations/DynamicAnnotationTests.java b/src/test/java/org/hibernate/models/dynamic/DynamicAnnotationTests.java similarity index 99% rename from src/test/java/org/hibernate/models/annotations/DynamicAnnotationTests.java rename to src/test/java/org/hibernate/models/dynamic/DynamicAnnotationTests.java index f9d981a..6b36e42 100644 --- a/src/test/java/org/hibernate/models/annotations/DynamicAnnotationTests.java +++ b/src/test/java/org/hibernate/models/dynamic/DynamicAnnotationTests.java @@ -5,7 +5,7 @@ * Copyright: Red Hat Inc. and Hibernate Authors */ -package org.hibernate.models.annotations; +package org.hibernate.models.dynamic; import java.util.List; diff --git a/src/test/java/org/hibernate/models/dynamic/SimpleDynamicModelTests.java b/src/test/java/org/hibernate/models/dynamic/SimpleDynamicModelTests.java new file mode 100644 index 0000000..5089981 --- /dev/null +++ b/src/test/java/org/hibernate/models/dynamic/SimpleDynamicModelTests.java @@ -0,0 +1,130 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.dynamic; + +import java.lang.reflect.Modifier; + +import org.hibernate.models.SourceModelTestHelper; +import org.hibernate.models.internal.ClassTypeDetailsImpl; +import org.hibernate.models.internal.SourceModelBuildingContextImpl; +import org.hibernate.models.internal.dynamic.DynamicClassDetails; +import org.hibernate.models.internal.dynamic.DynamicFieldDetails; +import org.hibernate.models.orm.JpaAnnotations; +import org.hibernate.models.spi.ClassDetails; +import org.hibernate.models.spi.ClassDetailsRegistry; +import org.hibernate.models.spi.MutableClassDetails; +import org.hibernate.models.spi.TypeDetails; + +import org.junit.jupiter.api.Test; + +import org.jboss.jandex.Index; + +/** + * @author Steve Ebersole + */ +public class SimpleDynamicModelTests { + @Test + void testSimpleBasics() { + final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( (Index) null ); + final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); + + final ClassDetails integerClassDetails = classDetailsRegistry.getClassDetails( Integer.class.getName() ); + final ClassTypeDetailsImpl integerTypeDetails = new ClassTypeDetailsImpl( integerClassDetails, TypeDetails.Kind.CLASS ); + + final ClassDetails stringClassDetails = classDetailsRegistry.getClassDetails( String.class.getName() ); + final ClassTypeDetailsImpl stringTypeDetails = new ClassTypeDetailsImpl( stringClassDetails, TypeDetails.Kind.CLASS ); + + final MutableClassDetails entityDetails = (MutableClassDetails) classDetailsRegistry.resolveClassDetails( + "TheEntity", + name -> new DynamicClassDetails( name, buildingContext ) + ); + entityDetails.addAnnotationUsage( JpaAnnotations.ENTITY.createUsage( entityDetails, buildingContext ) ); + + + final DynamicFieldDetails idFieldDetails = new DynamicFieldDetails( + "id", + integerTypeDetails, + entityDetails, + Modifier.fieldModifiers(), + false, + false, + buildingContext + ); + entityDetails.addField( idFieldDetails ); + + final DynamicFieldDetails nameFieldDetails = new DynamicFieldDetails( + "name", + stringTypeDetails, + entityDetails, + Modifier.fieldModifiers(), + false, + false, + buildingContext + ); + entityDetails.addField( nameFieldDetails ); + } + + @Test + void testSimpleEmbedded() { + final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( (Index) null ); + final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); + + final ClassDetails integerClassDetails = classDetailsRegistry.getClassDetails( Integer.class.getName() ); + final ClassTypeDetailsImpl integerTypeDetails = new ClassTypeDetailsImpl( integerClassDetails, TypeDetails.Kind.CLASS ); + + final ClassDetails stringClassDetails = classDetailsRegistry.getClassDetails( String.class.getName() ); + final ClassTypeDetailsImpl stringTypeDetails = new ClassTypeDetailsImpl( stringClassDetails, TypeDetails.Kind.CLASS ); + + final MutableClassDetails entityDetails = (MutableClassDetails) classDetailsRegistry.resolveClassDetails( + "TheEntity", + name -> new DynamicClassDetails( name, buildingContext ) + ); + entityDetails.addAnnotationUsage( JpaAnnotations.ENTITY.createUsage( entityDetails, buildingContext ) ); + + final MutableClassDetails nameEmbeddableDetails = (MutableClassDetails) classDetailsRegistry.resolveClassDetails( + "TheName", + name -> new DynamicClassDetails( name, buildingContext ) + ); + nameEmbeddableDetails.addAnnotationUsage( JpaAnnotations.EMBEDDABLE.createUsage( entityDetails, buildingContext ) ); + final ClassTypeDetailsImpl nameEmbeddableTypeDetails = new ClassTypeDetailsImpl( nameEmbeddableDetails, TypeDetails.Kind.CLASS ); + + final DynamicFieldDetails firstFieldDetails = new DynamicFieldDetails( + "first", + stringTypeDetails, + nameEmbeddableDetails, + Modifier.fieldModifiers(), + false, + false, + buildingContext + ); + nameEmbeddableDetails.addField( firstFieldDetails ); + + final DynamicFieldDetails lastFieldDetails = new DynamicFieldDetails( + "last", + stringTypeDetails, + nameEmbeddableDetails, + Modifier.fieldModifiers(), + false, + false, + buildingContext + ); + nameEmbeddableDetails.addField( lastFieldDetails ); + + + final DynamicFieldDetails nameFieldDetails = new DynamicFieldDetails( + "name", + nameEmbeddableTypeDetails, + entityDetails, + Modifier.fieldModifiers(), + false, + false, + buildingContext + ); + entityDetails.addField( nameFieldDetails ); + } +} diff --git a/src/test/java/org/hibernate/models/dynamic/package-info.java b/src/test/java/org/hibernate/models/dynamic/package-info.java new file mode 100644 index 0000000..c29a1c1 --- /dev/null +++ b/src/test/java/org/hibernate/models/dynamic/package-info.java @@ -0,0 +1,14 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +/** + * Tests verifying expected usage patterns of {@linkplain org.hibernate.models.dynamic dynamic models} + * as expected by Hibernate ORM + * + * @author Steve Ebersole + */ +package org.hibernate.models.dynamic;