diff --git a/buildSrc/src/main/groovy/release-process.gradle b/buildSrc/src/main/groovy/release-process.gradle index bb633b5..80fbb8b 100644 --- a/buildSrc/src/main/groovy/release-process.gradle +++ b/buildSrc/src/main/groovy/release-process.gradle @@ -35,8 +35,9 @@ def releasePreparationTask = tasks.register( "releasePreparation" ) { dependsOn tasks.named( "compile" ) doFirst { - logger.lifecycle "Release version : {}", releaseVersion + logger.lifecycle "Release version : {}", releaseVersion logger.lifecycle "Development version : {}", developmentVersion + logger.lifecycle " - same version? : {}", releaseVersion == developmentVersion logger.lifecycle "Switching to branch {}", gitBranch executeGitCommand('checkout', gitBranch) @@ -61,6 +62,7 @@ def changeToReleaseVersionTask = tasks.register( "changeToReleaseVersion" ) { dependsOn releasePreparationTask onlyIf { releasePreparationTask.get().didWork + && releaseVersion != developmentVersion } doFirst { @@ -105,6 +107,7 @@ tasks.register( "prepareForRelease" ) { def tagReleaseTask = tasks.register( "tagRelease" ) { onlyIf { changeToReleaseVersionTask.get().didWork + && releaseVersion != developmentVersion } doLast { @@ -119,6 +122,11 @@ def changeToDevelopmentVersionTask = tasks.register( 'changeToDevelopmentVersion dependsOn tagReleaseTask + onlyIf { + changeToReleaseVersionTask.get().didWork + && releaseVersion != developmentVersion + } + doFirst { logger.lifecycle( "Updating version-file to development-version : `${developmentVersion}`" ) updateVersionFile( developmentVersion ) @@ -134,6 +142,11 @@ def changeToDevelopmentVersionTask = tasks.register( 'changeToDevelopmentVersion def pushToGitTask = tasks.register( 'pushToGit' ) { dependsOn changeToDevelopmentVersionTask + onlyIf { + changeToReleaseVersionTask.get().didWork + && releaseVersion != developmentVersion + } + doLast { def gitRemote = determineGitRemote( project ) logger.lifecycle "Pushing branch and tag to Git : {}", gitRemote diff --git a/src/main/java/org/hibernate/models/UnhandledMethodException.java b/src/main/java/org/hibernate/models/UnhandledMethodException.java new file mode 100644 index 0000000..84df409 --- /dev/null +++ b/src/main/java/org/hibernate/models/UnhandledMethodException.java @@ -0,0 +1,24 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models; + +/** + * Generally indicates an attempt to call an unknown/unhandled method on an annotation + * {@linkplain org.hibernate.models.internal.AnnotationProxy proxy}. + * + * @author Steve Ebersole + */ +public class UnhandledMethodException extends ModelsException { + public UnhandledMethodException(String message) { + super( message ); + } + + public UnhandledMethodException(String message, Throwable cause) { + super( message, cause ); + } +} diff --git a/src/main/java/org/hibernate/models/internal/AbstractAnnotationDescriptor.java b/src/main/java/org/hibernate/models/internal/AbstractAnnotationDescriptor.java new file mode 100644 index 0000000..43b04e2 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/AbstractAnnotationDescriptor.java @@ -0,0 +1,120 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.internal; + +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.EnumSet; + +import org.hibernate.models.IllegalCastException; +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.MethodDetails; +import org.hibernate.models.spi.MutableClassDetails; +import org.hibernate.models.spi.MutableMemberDetails; +import org.hibernate.models.spi.RecordComponentDetails; +import org.hibernate.models.spi.SourceModelBuildingContext; + +/** + * Base support for {@link AnnotationDescriptor} implementations + * + * @author Steve Ebersole + */ +public abstract class AbstractAnnotationDescriptor + extends AbstractAnnotationTarget + implements AnnotationDescriptor { + private final Class annotationType; + private final EnumSet allowableTargets; + + private final boolean inherited; + private final AnnotationDescriptor repeatableContainer; + + public AbstractAnnotationDescriptor( + Class annotationType, + EnumSet allowableTargets, + boolean inherited, + AnnotationDescriptor repeatableContainer) { + this.annotationType = annotationType; + this.allowableTargets = allowableTargets; + this.inherited = inherited; + this.repeatableContainer = repeatableContainer; + } + + @Override + public Class getAnnotationType() { + return annotationType; + } + + @Override + public String getName() { + return annotationType.getName(); + } + + @Override + public EnumSet getAllowableTargets() { + return allowableTargets; + } + + @Override + public boolean isInherited() { + return inherited; + } + + @Override + public AnnotationDescriptor getRepeatableContainer() { + return repeatableContainer; + } + + @Override + public Collection getDirectAnnotationUsages() { + return getUsageMap().values(); + } + + @Override + public X[] getRepeatedAnnotationUsages( + AnnotationDescriptor type, + SourceModelBuildingContext modelContext) { + return AnnotationUsageHelper.getRepeatedUsages( type, getUsageMap(), modelContext ); + } + + @Override + public X[] getRepeatedAnnotationUsages(Class type, SourceModelBuildingContext modelContext) { + return getRepeatedAnnotationUsages( modelContext.getAnnotationDescriptorRegistry().getDescriptor( type ), modelContext ); + } + + @Override + public AnnotationDescriptor asAnnotationDescriptor() { + //noinspection unchecked + return (AnnotationDescriptor) this; + } + + @Override + public MutableClassDetails asClassDetails() { + throw new IllegalCastException( "AnnotationDescriptor cannot be cast to ClassDetails" ); + } + + @Override + public MutableMemberDetails asMemberDetails() { + throw new IllegalCastException( "AnnotationDescriptor cannot be cast to MemberDetails" ); + } + + @Override + public FieldDetails asFieldDetails() { + throw new IllegalCastException( "AnnotationDescriptor cannot be cast to FieldDetails" ); + } + + @Override + public MethodDetails asMethodDetails() { + throw new IllegalCastException( "AnnotationDescriptor cannot be cast to MethodDetails" ); + } + + @Override + public RecordComponentDetails asRecordComponentDetails() { + throw new IllegalCastException( "AnnotationDescriptor cannot be cast to RecordComponentDetails" ); + } +} diff --git a/src/main/java/org/hibernate/models/internal/AbstractAnnotationTarget.java b/src/main/java/org/hibernate/models/internal/AbstractAnnotationTarget.java new file mode 100644 index 0000000..607adb8 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/AbstractAnnotationTarget.java @@ -0,0 +1,14 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.internal; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractAnnotationTarget implements AnnotationTargetSupport { +} diff --git a/src/main/java/org/hibernate/models/internal/AbstractTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/AbstractTypeDescriptor.java index d546345..e96bcde 100644 --- a/src/main/java/org/hibernate/models/internal/AbstractTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/AbstractTypeDescriptor.java @@ -6,14 +6,17 @@ */ package org.hibernate.models.internal; +import java.lang.annotation.Annotation; import java.util.Locale; -import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.internal.jdk.JdkPassThruConverter; +import org.hibernate.models.internal.jdk.JdkPassThruExtractor; import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.JdkValueConverter; +import org.hibernate.models.spi.JdkValueExtractor; import org.hibernate.models.spi.RenderingCollector; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.ValueTypeDescriptor; -import org.hibernate.models.spi.ValueWrapper; /** * Base support for {@linkplain AttributeDescriptor} implementations @@ -23,33 +26,28 @@ public abstract class AbstractTypeDescriptor implements ValueTypeDescriptor { @Override public AttributeDescriptor createAttributeDescriptor( - AnnotationDescriptor annotationDescriptor, + Class annotationType, String attributeName) { - return new AttributeDescriptorImpl<>( annotationDescriptor.getAnnotationType(), attributeName, this ); + return new AttributeDescriptorImpl<>( annotationType, attributeName, this ); } @Override - public V createValue( - AttributeDescriptor attributeDescriptor, - SourceModelBuildingContext context) { - final Object defaultValue = attributeDescriptor.getAttributeMethod().getDefaultValue(); - if ( defaultValue == null ) { - // a non-defaulted attribute, just return null for the baseline - return null; - } + public JdkValueConverter createJdkValueConverter(SourceModelBuildingContext modelContext) { + return JdkPassThruConverter.passThruConverter(); + } - //noinspection unchecked - final ValueWrapper valueWrapper = (ValueWrapper) createJdkWrapper( context ); - return valueWrapper.wrap( defaultValue, context ); + @Override + public JdkValueExtractor createJdkValueExtractor(SourceModelBuildingContext modelContext) { + return JdkPassThruExtractor.passThruExtractor(); } @Override - public void render(RenderingCollector collector, String name, Object attributeValue) { + public void render(RenderingCollector collector, String name, Object attributeValue, SourceModelBuildingContext modelContext) { collector.addLine( "%s = %s", name, attributeValue ); } @Override - public void render(RenderingCollector collector, Object attributeValue) { + public void render(RenderingCollector collector, Object attributeValue, SourceModelBuildingContext modelContext) { collector.addLine( "%s", attributeValue ); } @@ -58,7 +56,7 @@ public String toString() { return String.format( Locale.ROOT, "AttributeTypeDescriptor(%s)", - getWrappedValueType().getName() + getValueType().getName() ); } } diff --git a/src/main/java/org/hibernate/models/internal/AnnotationDescriptorBuilding.java b/src/main/java/org/hibernate/models/internal/AnnotationDescriptorBuilding.java new file mode 100644 index 0000000..e547f21 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/AnnotationDescriptorBuilding.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.internal; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.ValueTypeDescriptor; + +/** + * @author Steve Ebersole + */ +public class AnnotationDescriptorBuilding { + + public static List> extractAttributeDescriptors(Class annotationType) { + final Method[] methods = annotationType.getDeclaredMethods(); + final List> attributeDescriptors = new ArrayList<>( methods.length ); + for ( Method method : methods ) { + attributeDescriptors.add( createAttributeDescriptor( annotationType, method ) ); + } + return attributeDescriptors; + } + + private static AttributeDescriptor createAttributeDescriptor( + Class annotationType, + Method method) { + //noinspection unchecked + final Class attributeType = (Class) method.getReturnType(); + + final ValueTypeDescriptor typeDescriptor = TypeDescriptors.resolveTypeDescriptor( attributeType ); + return typeDescriptor.createAttributeDescriptor( annotationType, method.getName() ); + } +} diff --git a/src/main/java/org/hibernate/models/internal/AnnotationDescriptorRegistryStandard.java b/src/main/java/org/hibernate/models/internal/AnnotationDescriptorRegistryStandard.java index 655a6c6..70369cf 100644 --- a/src/main/java/org/hibernate/models/internal/AnnotationDescriptorRegistryStandard.java +++ b/src/main/java/org/hibernate/models/internal/AnnotationDescriptorRegistryStandard.java @@ -8,10 +8,7 @@ import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; -import java.util.Collections; -import java.util.HashMap; -import org.hibernate.models.internal.jdk.AnnotationDescriptorImpl; import org.hibernate.models.spi.AnnotationDescriptor; import org.hibernate.models.spi.AnnotationDescriptorRegistry; @@ -70,7 +67,7 @@ private AnnotationDescriptor buildAdHocAnnotationDescr containerDescriptor = null; } - final AnnotationDescriptorImpl descriptor = new AnnotationDescriptorImpl<>( + final StandardAnnotationDescriptor descriptor = new StandardAnnotationDescriptor<>( javaType, containerDescriptor, modelBuildingContext diff --git a/src/main/java/org/hibernate/models/internal/AnnotationHelper.java b/src/main/java/org/hibernate/models/internal/AnnotationHelper.java index 157f52c..deca3c8 100644 --- a/src/main/java/org/hibernate/models/internal/AnnotationHelper.java +++ b/src/main/java/org/hibernate/models/internal/AnnotationHelper.java @@ -9,11 +9,17 @@ import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; import java.lang.annotation.Target; +import java.lang.reflect.InvocationTargetException; import java.util.EnumSet; +import java.util.List; +import java.util.Locale; -import org.hibernate.models.internal.jdk.AnnotationDescriptorOrmImpl; +import org.hibernate.models.AnnotationAccessException; import org.hibernate.models.spi.AnnotationDescriptor; import org.hibernate.models.spi.AnnotationTarget; +import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.RenderingCollector; +import org.hibernate.models.spi.SourceModelBuildingContext; /** * Helper for dealing with actual {@link Annotation} references @@ -33,14 +39,98 @@ public static EnumSet extractTarge return AnnotationTarget.Kind.from( annotationType.getAnnotation( Target.class ) ); } - public static AnnotationDescriptor createOrmDescriptor(Class javaType) { - return createOrmDescriptor( javaType, null ); + public static void render( + RenderingCollector collector, + A annotation, + SourceModelBuildingContext context) { + //noinspection unchecked + render( + collector, + annotation, + (AnnotationDescriptor) context.getAnnotationDescriptorRegistry().getDescriptor( annotation.annotationType() ), + context + ); } - public static AnnotationDescriptor createOrmDescriptor( - Class javaType, - AnnotationDescriptor repeatableContainer) { - assert javaType != null; - return new AnnotationDescriptorOrmImpl<>( javaType, repeatableContainer ); + public static void render( + RenderingCollector collector, + A annotation, + AnnotationDescriptor descriptor, + SourceModelBuildingContext context) { + final List> attributes = descriptor.getAttributes(); + if ( attributes.isEmpty() ) { + collector.addLine( "@%s", descriptor.getAnnotationType().getName() ); + } + else { + collector.addLine( "@%s(", descriptor.getAnnotationType().getName() ); + collector.indent( 2 ); + attributes.forEach( (attribute) -> attribute.getTypeDescriptor().render( + collector, + attribute.getName(), + extractValue( annotation, attribute ), + context + ) ); + + collector.unindent( 2 ); + collector.addLine( ")" ); + } + } + + public static void render( + RenderingCollector collector, + String name, + A annotation, + SourceModelBuildingContext context) { + //noinspection unchecked + render( + collector, + name, + annotation, + (AnnotationDescriptor) context.getAnnotationDescriptorRegistry().getDescriptor( annotation.annotationType() ), + context + ); + } + + public static void render( + RenderingCollector collector, + String name, + A annotation, + AnnotationDescriptor descriptor, + SourceModelBuildingContext context) { + final List> attributes = descriptor.getAttributes(); + if ( attributes.isEmpty() ) { + collector.addLine( "%s = @%s", name, descriptor.getAnnotationType().getName() ); + } + else { + collector.addLine( "%s = @%s(", name, descriptor.getAnnotationType().getName() ); + collector.indent( 2 ); + attributes.forEach( (attribute) -> attribute.getTypeDescriptor().render( + collector, + attribute.getName(), + extractValue( annotation, attribute ), + context + ) ); + + collector.unindent( 2 ); + collector.addLine( ")" ); + } + } + + public static R extractValue(A annotationUsage, AttributeDescriptor attributeDescriptor) { + try { + //noinspection unchecked + return (R) attributeDescriptor.getAttributeMethod().invoke( annotationUsage ); + } + catch (IllegalAccessException | InvocationTargetException e) { + throw new AnnotationAccessException( + String.format( + Locale.ROOT, + "Unable to access annotation attribute value : %s.%s", + annotationUsage.annotationType().getName(), + attributeDescriptor.getName() + ), + e + ); + } } } diff --git a/src/main/java/org/hibernate/models/internal/AnnotationProxy.java b/src/main/java/org/hibernate/models/internal/AnnotationProxy.java index 3217fad..6d7770e 100644 --- a/src/main/java/org/hibernate/models/internal/AnnotationProxy.java +++ b/src/main/java/org/hibernate/models/internal/AnnotationProxy.java @@ -13,31 +13,78 @@ import java.lang.reflect.Proxy; import java.util.Map; +import org.hibernate.models.UnhandledMethodException; +import org.hibernate.models.internal.jandex.AnnotationUsageBuilder; import org.hibernate.models.spi.AnnotationDescriptor; import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; /** + * Acts as {@link Annotation} usage using {@link InvocationHandler} and {@link Proxy}. + * + * @apiNote Mainly this is used for handling Jandex-based annotations when the annotation + * is a non-ORM annotation. + * * @author Steve Ebersole */ public class AnnotationProxy implements InvocationHandler { private final AnnotationDescriptor annotationDescriptor; - private final Map valueMap; + private final Map valueMap; - public AnnotationProxy(AnnotationDescriptor annotationDescriptor, Map valueMap) { + public AnnotationProxy(AnnotationDescriptor annotationDescriptor, Map valueMap) { this.annotationDescriptor = annotationDescriptor; this.valueMap = valueMap; } + public void setValue(String name, Object value) { + valueMap.put( name, value ); + } + @Override public Object invoke(Object proxy, Method method, Object[] args) { - final AttributeDescriptor attributeDescriptor = annotationDescriptor.getAttribute( method.getName() ); - return attributeDescriptor.getTypeDescriptor().unwrap( valueMap.get( method.getName() ) ); + switch ( method.getName() ) { + case "annotationType" -> { + return annotationDescriptor.getAnnotationType(); + } + case "toString" -> { + return "AnnotationProxy(" + annotationDescriptor.getAnnotationType().getName() + ")"; + } + case "equals" -> { + return proxy == this; + } + } + + if ( method.getParameterCount() == 0 ) { + final AttributeDescriptor attributeDescriptor = annotationDescriptor.getAttribute( method.getName() ); + return attributeDescriptor.getTypeDescriptor().unwrap( valueMap.get( method.getName() ) ); + } + + // allow for mutability + if ( isSetValueMethod( method) ) { + assert method.getParameterCount() == 2; + valueMap.put( (String) args[0], args[1] ); + } + if ( method.getParameterCount() == 1 ) { + valueMap.put( method.getName(), args[0] ); + return null; + } + + throw new UnhandledMethodException( "Unhandled method - " + method.toGenericString() ); } + private boolean isSetValueMethod(Method method) { + if ( !"setValue".equals( method.getName() ) || method.getParameterCount() != 2 ) { + return false; + } + + return String.class.equals( method.getParameterTypes()[0] ); + } public static A makeProxy( AnnotationDescriptor descriptor, - Map valueMap) { + Map valueMap) { final AnnotationProxy handler = new AnnotationProxy<>( descriptor, valueMap ); //noinspection unchecked return (A) Proxy.newProxyInstance( @@ -47,4 +94,18 @@ public static A makeProxy( ); } + public static A makeProxy( + AnnotationDescriptor descriptor, + AnnotationInstance jandexAnnotationInstance, + SourceModelBuildingContext modelContext) { + return makeProxy( + descriptor, + AnnotationUsageBuilder.extractAttributeValues( + jandexAnnotationInstance, + descriptor, + modelContext + ) + ); + } + } diff --git a/src/main/java/org/hibernate/models/internal/AnnotationTargetSupport.java b/src/main/java/org/hibernate/models/internal/AnnotationTargetSupport.java index 8d049f4..39c8160 100644 --- a/src/main/java/org/hibernate/models/internal/AnnotationTargetSupport.java +++ b/src/main/java/org/hibernate/models/internal/AnnotationTargetSupport.java @@ -14,38 +14,63 @@ import java.util.function.Consumer; import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.spi.AnnotationUsage; +import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.MethodDetails; import org.hibernate.models.spi.MutableAnnotationTarget; -import org.hibernate.models.spi.MutableAnnotationUsage; +import org.hibernate.models.spi.MutableClassDetails; +import org.hibernate.models.spi.MutableMemberDetails; +import org.hibernate.models.spi.RecordComponentDetails; import org.hibernate.models.spi.SourceModelBuildingContext; /** * @author Steve Ebersole */ public interface AnnotationTargetSupport extends MutableAnnotationTarget { - SourceModelBuildingContext getBuildingContext(); - Map, AnnotationUsage> getUsageMap(); + /** + * Access to all annotation usages on this target. + */ + Map,? extends Annotation> getUsageMap(); @Override - default Collection> getAllAnnotationUsages() { + default void clearAnnotationUsages() { + getUsageMap().clear(); + } + + @Override + default void addAnnotationUsage(X annotationUsage) { + //noinspection unchecked,rawtypes + ( (Map) getUsageMap() ).put( annotationUsage.annotationType(), annotationUsage ); + } + + @Override + default Collection getDirectAnnotationUsages() { return getUsageMap().values(); } @Override - default boolean hasAnnotationUsage(Class type) { + default A getDirectAnnotationUsage(AnnotationDescriptor descriptor) { + return getDirectAnnotationUsage( descriptor.getAnnotationType() ); + } + + @Override + default A getDirectAnnotationUsage(Class type) { + //noinspection unchecked + return (A) getUsageMap().get( type ); + } + + @Override + default boolean hasDirectAnnotationUsage(Class type) { return getUsageMap().containsKey( type ); } @Override - default boolean hasRepeatableAnnotationUsage(Class type) { + default boolean hasAnnotationUsage(Class type, SourceModelBuildingContext modelContext) { final boolean containsDirectly = getUsageMap().containsKey( type ); if ( containsDirectly ) { return true; } - final AnnotationDescriptorRegistry descriptorRegistry = getBuildingContext().getAnnotationDescriptorRegistry(); - final AnnotationDescriptor descriptor = descriptorRegistry.getDescriptor( type ); + final AnnotationDescriptor descriptor = modelContext.getAnnotationDescriptorRegistry().getDescriptor( type ); if ( descriptor.isRepeatable() ) { // e.g. caller asks about NamedQuery... let's also check for NamedQueries (which implies NamedQuery) return getUsageMap().containsKey( descriptor.getRepeatableContainer().getAnnotationType() ); @@ -55,38 +80,62 @@ default boolean hasRepeatableAnnotationUsage(Class typ } @Override - default AnnotationUsage getAnnotationUsage(AnnotationDescriptor descriptor) { - return AnnotationUsageHelper.getUsage( descriptor, getUsageMap() ); + default A getAnnotationUsage(AnnotationDescriptor descriptor, SourceModelBuildingContext modelContext) { + return AnnotationUsageHelper.getUsage( descriptor, getUsageMap(), modelContext ); } @Override - default AnnotationUsage getAnnotationUsage(Class annotationType) { - return getAnnotationUsage( getBuildingContext().getAnnotationDescriptorRegistry().getDescriptor( annotationType ) ); + default A getAnnotationUsage(Class annotationType, SourceModelBuildingContext modelContext) { + return AnnotationUsageHelper.getUsage( annotationType, getUsageMap(), modelContext ); } @Override - default AnnotationUsage locateAnnotationUsage(Class annotationType) { + default A[] getRepeatedAnnotationUsages( + AnnotationDescriptor type, + SourceModelBuildingContext modelContext) { + return AnnotationUsageHelper.getRepeatedUsages( type, getUsageMap(), modelContext ); + } + + @Override + default void forEachRepeatedAnnotationUsages( + Class repeatableType, + Class containerType, + SourceModelBuildingContext modelContext, Consumer consumer) { + AnnotationUsageHelper.forEachRepeatedAnnotationUsages( repeatableType, containerType, consumer, getUsageMap(), modelContext ); + } + + @Override + default void forEachRepeatedAnnotationUsages( + AnnotationDescriptor repeatableDescriptor, + SourceModelBuildingContext modelContext, + Consumer consumer) { + AnnotationUsageHelper.forEachRepeatedAnnotationUsages( repeatableDescriptor, consumer, getUsageMap(), modelContext ); + } + + @Override + default A locateAnnotationUsage(Class annotationType, SourceModelBuildingContext modelContext) { // e.g., locate `@Nationalized` // first, check for direct use // - look for `Nationalized.class` in the usage map of the target - final AnnotationUsage localUsage = getAnnotationUsage( annotationType ); + final A localUsage = getAnnotationUsage( annotationType, modelContext ); if ( localUsage != null ) { return localUsage; } // next, check as a "meta annotation" // - for each local usage, check that annotation's annotations for `Nationalized.class` (one level deep) - final Map, AnnotationUsage> localUsageMap = getUsageMap(); - for ( Map.Entry, AnnotationUsage> usageEntry : localUsageMap.entrySet() ) { - final AnnotationUsage usage = usageEntry.getValue(); - if ( annotationType.equals( usage.getAnnotationType() ) ) { + final Map, ? extends Annotation> localUsageMap = getUsageMap(); + for ( Map.Entry, ? extends Annotation> usageEntry : localUsageMap.entrySet() ) { + final Annotation usage = usageEntry.getValue(); + if ( annotationType.equals( usage.annotationType() ) ) { // we would have found this on the direct search, so no need // to check its meta-annotations continue; } - final AnnotationUsage metaAnnotation = usage.getAnnotationDescriptor().getAnnotationUsage( annotationType ); + final AnnotationDescriptor usageDescriptor = modelContext.getAnnotationDescriptorRegistry().getDescriptor( usage.annotationType() ); + final A metaAnnotation = usageDescriptor.getDirectAnnotationUsage( annotationType ); if ( metaAnnotation != null ) { return metaAnnotation; } @@ -98,28 +147,12 @@ default AnnotationUsage locateAnnotationUsage(Class } @Override - default List> getRepeatedAnnotationUsages(AnnotationDescriptor type) { - return AnnotationUsageHelper.getRepeatedUsages( type, getUsageMap() ); - } - - @Override - default List> getRepeatedAnnotationUsages(Class type) { - return getRepeatedAnnotationUsages( getBuildingContext().getAnnotationDescriptorRegistry().getDescriptor( type ) ); - } - - @Override - default void forEachAnnotationUsage(Class type, Consumer> consumer) { - forEachAnnotationUsage( - getBuildingContext().getAnnotationDescriptorRegistry().getDescriptor( type ), - consumer - ); - } - - @Override - default List> getMetaAnnotated(Class metaAnnotationType) { - final List> usages = new ArrayList<>(); - forAllAnnotationUsages( (usage) -> { - final Annotation metaUsage = usage.getAnnotationType().getAnnotation( metaAnnotationType ); + default List getMetaAnnotated( + Class metaAnnotationType, + SourceModelBuildingContext modelContext) { + final List usages = new ArrayList<>(); + forEachDirectAnnotationUsage( (usage) -> { + final Annotation metaUsage = usage.annotationType().getAnnotation( metaAnnotationType ); if ( metaUsage != null ) { usages.add( usage ); } @@ -128,44 +161,71 @@ default List> getMe } @Override - default AnnotationUsage getNamedAnnotationUsage(Class type, String matchName) { - return getNamedAnnotationUsage( getBuildingContext().getAnnotationDescriptorRegistry().getDescriptor( type ), matchName ); + default X getNamedAnnotationUsage( + Class type, + String matchName, + SourceModelBuildingContext modelContext) { + return getNamedAnnotationUsage( modelContext.getAnnotationDescriptorRegistry().getDescriptor( type ), matchName, modelContext ); } @Override - default AnnotationUsage getNamedAnnotationUsage( + default X getNamedAnnotationUsage( AnnotationDescriptor type, String matchName, - String attributeToMatch) { - return AnnotationUsageHelper.getNamedUsage( type, matchName, attributeToMatch, getUsageMap() ); + String attributeToMatch, + SourceModelBuildingContext modelContext) { + return AnnotationUsageHelper.getNamedUsage( type, matchName, attributeToMatch, getUsageMap(), modelContext ); } @Override - default AnnotationUsage getNamedAnnotationUsage( + default X getNamedAnnotationUsage( Class type, String matchName, - String attributeToMatch) { + String attributeToMatch, + SourceModelBuildingContext modelContext) { return getNamedAnnotationUsage( - getBuildingContext().getAnnotationDescriptorRegistry().getDescriptor( type ), + modelContext.getAnnotationDescriptorRegistry().getDescriptor( type ), matchName, - attributeToMatch + attributeToMatch, + modelContext ); } @Override - default MutableAnnotationUsage

replaceAnnotationUsage( + default P replaceAnnotationUsage( AnnotationDescriptor repeatableType, AnnotationDescriptor

containerType, - SourceModelBuildingContext buildingContext) { + SourceModelBuildingContext modelContext) { assert repeatableType.isRepeatable(); assert repeatableType.getRepeatableContainer() == containerType; - final MutableAnnotationUsage

containerTypeUsage = containerType.createUsage( buildingContext ); + final P containerTypeUsage = containerType.createUsage( modelContext ); // effectively overwrites any previous registrations - getUsageMap().put( containerType.getAnnotationType(), containerTypeUsage ); + //noinspection unchecked,rawtypes + ( (Map) getUsageMap() ).put( containerType.getAnnotationType(), containerTypeUsage ); // remove any entry for the repeatable/singular form getUsageMap().remove( repeatableType.getAnnotationType() ); return containerTypeUsage; } + + @Override + default AnnotationDescriptor asAnnotationDescriptor() { + return null; + } + + @Override + FieldDetails asFieldDetails(); + + @Override + MethodDetails asMethodDetails(); + + @Override + RecordComponentDetails asRecordComponentDetails(); + + @Override + MutableClassDetails asClassDetails(); + + @Override + MutableMemberDetails asMemberDetails(); } diff --git a/src/main/java/org/hibernate/models/internal/AnnotationUsageHelper.java b/src/main/java/org/hibernate/models/internal/AnnotationUsageHelper.java index dae0de2..346710b 100644 --- a/src/main/java/org/hibernate/models/internal/AnnotationUsageHelper.java +++ b/src/main/java/org/hibernate/models/internal/AnnotationUsageHelper.java @@ -7,113 +7,212 @@ package org.hibernate.models.internal; import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.lang.reflect.Array; import java.util.Map; +import java.util.function.Consumer; import org.hibernate.models.AnnotationAccessException; +import org.hibernate.models.internal.jandex.JandexValueHelper; import org.hibernate.models.internal.util.CollectionHelper; import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationUsage; +import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.SourceModelBuildingContext; +import org.hibernate.models.spi.SourceModelContext; + +import org.jboss.jandex.AnnotationInstance; /** - * Helper for dealing with annotation wrappers -

- * * @see AnnotationHelper * * @author Steve Ebersole */ public class AnnotationUsageHelper { - public static AnnotationUsage findUsage( + public static A findUsage( AnnotationDescriptor type, - Map,AnnotationUsage> usageMap) { + Map,? extends Annotation> usageMap) { //noinspection unchecked - return (AnnotationUsage) usageMap.get( type.getAnnotationType() ); + return (A) usageMap.get( type.getAnnotationType() ); } /** - * Get the {@link AnnotationUsage} from the {@code usageMap} for the given {@code type} + * Get the annotation usage from the {@code usageMap} for the given {@code type} */ - public static AnnotationUsage getUsage( + public static A getUsage( + Class type, + Map,? extends Annotation> usageMap, + SourceModelBuildingContext modelContext) { + return getUsage( + modelContext.getAnnotationDescriptorRegistry().getDescriptor( type ), + usageMap, + modelContext + ); + } + + public static A[] extractRepeatedValues( + C container, + AnnotationDescriptor containerDescriptor, + SourceModelBuildingContext modelContext) { + return extractRepeatedValues( container, containerDescriptor.getAttribute( "value" ), modelContext ); + } + + public static A[] extractRepeatedValues( + C container, + AttributeDescriptor valuesAttribute, + SourceModelBuildingContext modelContext) { + return valuesAttribute.getTypeDescriptor().createJdkValueExtractor( modelContext ).extractValue( container, valuesAttribute, modelContext ); + } + + public static A[] extractRepeatedValues( + AnnotationInstance container, + AnnotationDescriptor containerDescriptor, + SourceModelBuildingContext modelContext) { + final AttributeDescriptor valuesAttribute = containerDescriptor.getAttribute( "value" ); + return extractRepeatedValues( container, valuesAttribute, modelContext ); + } + + public static A[] extractRepeatedValues( + AnnotationInstance container, + AttributeDescriptor valuesAttribute, + SourceModelBuildingContext modelContext) { + return JandexValueHelper.extractValue( container, valuesAttribute, modelContext ); + } + + /** + * Get the annotation usage from the {@code usageMap} for the given {@code type} + */ + public static A getUsage( AnnotationDescriptor type, - Map,AnnotationUsage> usageMap) { - final AnnotationUsage found = findUsage( type, usageMap ); + Map,? extends Annotation> usageMap, + SourceModelBuildingContext modelContext) { + final A found = findUsage( type, usageMap ); if ( found == null ) { - final AnnotationDescriptor repeatableContainer = type.getRepeatableContainer(); + //noinspection unchecked + final AnnotationDescriptor repeatableContainer = (AnnotationDescriptor) type.getRepeatableContainer(); if ( repeatableContainer != null ) { - final AnnotationUsage containerUsage = findUsage( repeatableContainer, usageMap ); + final C containerUsage = findUsage( repeatableContainer, usageMap ); if ( containerUsage != null ) { - final List> nestedUsages = containerUsage.getAttributeValue( "value" ); - if ( CollectionHelper.isEmpty( nestedUsages ) ) { + final A[] repeatedValues = extractRepeatedValues( containerUsage, repeatableContainer, modelContext ); + if ( CollectionHelper.isEmpty( repeatedValues ) ) { return null; } - if ( nestedUsages.size() > 1 ) { + if ( repeatedValues.length > 1 ) { throw new AnnotationAccessException( "Found more than one usage of " + type.getAnnotationType().getName() ); } - return nestedUsages.get( 0 ); + return repeatedValues[0]; } } } return found; } - public static List> getRepeatedUsages( + public static void forEachRepeatedAnnotationUsages( + Class repeatableType, + Class containerType, + Consumer consumer, + Map, ? extends Annotation> usageMap, + SourceModelBuildingContext modelContext) { + //noinspection unchecked + final A repeatable = (A) usageMap.get( repeatableType ); + if ( repeatable != null ) { + consumer.accept( repeatable ); + } + + //noinspection unchecked + final C container = (C) usageMap.get( containerType ); + if ( container != null ) { + final AnnotationDescriptor containerDescriptor = modelContext.getAnnotationDescriptorRegistry().getDescriptor( containerType ); + final AttributeDescriptor attribute = containerDescriptor.getAttribute( "value" ); + final A[] repetitions = AnnotationHelper.extractValue( container, attribute ); + CollectionHelper.forEach( repetitions, consumer ); + } + } + + public static void forEachRepeatedAnnotationUsages( + AnnotationDescriptor repeatableDescriptor, + Consumer consumer, + Map, ? extends Annotation> usageMap, + SourceModelBuildingContext modelContext) { + //noinspection unchecked + final A repeatable = (A) usageMap.get( repeatableDescriptor.getAnnotationType() ); + if ( repeatable != null ) { + consumer.accept( repeatable ); + } + + final Class containerType = repeatableDescriptor.getRepeatableContainer().getAnnotationType(); + final Annotation container = usageMap.get( containerType ); + if ( container != null ) { + final AnnotationDescriptor containerDescriptor = modelContext.getAnnotationDescriptorRegistry().getDescriptor( containerType ); + final AttributeDescriptor attribute = containerDescriptor.getAttribute( "value" ); + final A[] repetitions = AnnotationHelper.extractValue( container, attribute ); + CollectionHelper.forEach( repetitions, consumer ); + } + } + + public static A[] getRepeatedUsages( AnnotationDescriptor type, - Map, AnnotationUsage> usageMap) { + Map, ? extends Annotation> usageMap, + SourceModelBuildingContext modelContext) { // e.g. `@NamedQuery` - final AnnotationUsage usage = findUsage( type, usageMap ); + final A usage = findUsage( type, usageMap ); // e.g. `@NamedQueries` - final AnnotationUsage containerUsage = type.getRepeatableContainer() != null + final Annotation containerUsage = type.getRepeatableContainer() != null ? findUsage( type.getRepeatableContainer(), usageMap ) : null; if ( containerUsage != null ) { - final List> repetitions = containerUsage.getAttributeValue( "value" ); - if ( CollectionHelper.isNotEmpty( repetitions ) ) { + final AttributeDescriptor attribute = type.getRepeatableContainer().getAttribute( "value" ); + final A[] repeatableValues = AnnotationHelper.extractValue( containerUsage, attribute ); + + if ( CollectionHelper.isNotEmpty( repeatableValues ) ) { if ( usage != null ) { - final ArrayList> combined = new ArrayList<>( repetitions ); + //noinspection unchecked + final A[] combined = (A[]) Array.newInstance( type.getAnnotationType(), repeatableValues.length + 1 ); // prepend the singular usage - combined.add( 0, usage ); + combined[0] = usage; + System.arraycopy( repeatableValues, 0, combined, 1, repeatableValues.length ); return combined; } - return repetitions; + return repeatableValues; } } if ( usage != null ) { - return Collections.singletonList( usage ); + //noinspection unchecked + final A[] singleton = (A[]) Array.newInstance( type.getAnnotationType(), 1 ); + singleton[0] = usage; + return singleton; } - return Collections.emptyList(); + //noinspection unchecked + return (A[]) Array.newInstance( type.getAnnotationType(), 0 ); } - public static AnnotationUsage getNamedUsage( - AnnotationDescriptor type, + public static A getNamedUsage( + AnnotationDescriptor descriptor, String matchValue, String attributeToMatch, - Map, AnnotationUsage> usageMap) { - final AnnotationUsage annotationUsage = usageMap.get( type.getAnnotationType() ); + Map, ?> usageMap, + SourceModelBuildingContext modelContext) { + //noinspection unchecked + final A annotationUsage = (A) usageMap.get( descriptor.getAnnotationType() ); if ( annotationUsage != null ) { - if ( nameMatches( annotationUsage, matchValue, attributeToMatch ) ) { - //noinspection unchecked - return (AnnotationUsage) annotationUsage; + if ( nameMatches( annotationUsage, descriptor, matchValue, attributeToMatch, modelContext ) ) { + return annotationUsage; } return null; } - final AnnotationDescriptor containerType = type.getRepeatableContainer(); + //noinspection unchecked + final AnnotationDescriptor containerType = (AnnotationDescriptor) descriptor.getRepeatableContainer(); if ( containerType != null ) { - final AnnotationUsage containerUsage = usageMap.get( containerType.getAnnotationType() ); + //noinspection unchecked + final C containerUsage = (C) usageMap.get( containerType.getAnnotationType() ); if ( containerUsage != null ) { - final List> repeatedUsages = containerUsage.getAttributeValue( "value" ); - for ( int i = 0; i < repeatedUsages.size(); i++ ) { - final AnnotationUsage repeatedUsage = repeatedUsages.get( i ); - if ( nameMatches( repeatedUsage, matchValue, attributeToMatch ) ) { + final A[] repeatedUsages = extractRepeatedValues( containerUsage, containerType, modelContext ); + for ( int i = 0; i < repeatedUsages.length; i++ ) { + final A repeatedUsage = repeatedUsages[i]; + if ( nameMatches( repeatedUsage, descriptor, matchValue, attributeToMatch, modelContext ) ) { return repeatedUsage; } } @@ -123,9 +222,15 @@ public static AnnotationUsage getNamedUsage( return null; } - private static boolean nameMatches(AnnotationUsage annotationUsage, String matchValue, String attributeToMatch) { - final String name = annotationUsage.getAttributeValue( attributeToMatch ); - return matchValue.equals( name ); + private static boolean nameMatches( + A annotationUsage, + AnnotationDescriptor descriptor, + String matchValue, + String attributeToMatch, + SourceModelContext modelContext) { + final AttributeDescriptor attributeDescriptor = descriptor.getAttribute( attributeToMatch ); + final String usageName = AnnotationHelper.extractValue( annotationUsage, attributeDescriptor ); + return matchValue.equals( usageName ); } diff --git a/src/main/java/org/hibernate/models/internal/ArrayTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/ArrayTypeDescriptor.java index 9eafb00..5502bce 100644 --- a/src/main/java/org/hibernate/models/internal/ArrayTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/ArrayTypeDescriptor.java @@ -11,17 +11,19 @@ import java.util.List; import org.hibernate.models.internal.jandex.ArrayValueExtractor; -import org.hibernate.models.internal.jandex.ArrayValueWrapper; -import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.internal.jandex.ArrayValueConverter; +import org.hibernate.models.internal.jdk.JdkArrayValueConverter; +import org.hibernate.models.internal.jdk.JdkArrayValueExtractor; +import org.hibernate.models.internal.jdk.JdkPassThruConverter; +import org.hibernate.models.internal.jdk.JdkPassThruExtractor; import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.JdkValueConverter; +import org.hibernate.models.spi.JdkValueExtractor; import org.hibernate.models.spi.RenderingCollector; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; +import org.hibernate.models.spi.JandexValueExtractor; import org.hibernate.models.spi.ValueTypeDescriptor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; +import org.hibernate.models.spi.JandexValueConverter; /** * Descriptor for array values. These are modeled as an array in the @@ -29,54 +31,46 @@ * * @author Steve Ebersole */ -public class ArrayTypeDescriptor implements ValueTypeDescriptor> { +public class ArrayTypeDescriptor implements ValueTypeDescriptor { private final ValueTypeDescriptor elementTypeDescriptor; - private final Class componentType; + private final Class componentType; + private final Class arrayType; - private ValueWrapper, AnnotationValue> jandexValueWrapper; - private ValueExtractor> jandexValueExtractor; + private JandexValueConverter jandexValueConverter; + private JandexValueExtractor jandexValueExtractor; - private ValueWrapper,Object[]> jdkValueWrapper; - private ValueExtractor> jdkValueExtractor; + private JdkValueConverter jdkValueConverter; + private JdkValueExtractor jdkValueExtractor; - public ArrayTypeDescriptor(ValueTypeDescriptor elementTypeDescriptor, Class componentType) { + public ArrayTypeDescriptor(ValueTypeDescriptor elementTypeDescriptor) { this.elementTypeDescriptor = elementTypeDescriptor; - this.componentType = componentType; + this.componentType = elementTypeDescriptor.getValueType(); + //noinspection unchecked + this.arrayType = (Class) componentType.arrayType(); } - @Override - public Class> getWrappedValueType() { - //noinspection unchecked,rawtypes - return (Class) List.class; + public ValueTypeDescriptor getElementTypeDescriptor() { + return elementTypeDescriptor; } @Override - public List createValue( - AttributeDescriptor attributeDescriptor, - SourceModelBuildingContext context) { - final Object defaultValue = attributeDescriptor.getAttributeMethod().getDefaultValue(); - if ( defaultValue == null ) { - // a non-defaulted attribute, just return null for the baseline - return null; - } - - final ValueWrapper, Object[]> jdkWrapper = createJdkWrapper( context ); - return jdkWrapper.wrap( (Object[]) defaultValue, context ); + public Class getValueType() { + return arrayType; } @Override - public AttributeDescriptor> createAttributeDescriptor( - AnnotationDescriptor annotationDescriptor, + public AttributeDescriptor createAttributeDescriptor( + Class annotationType, String attributeName) { - return new AttributeDescriptorImpl<>( annotationDescriptor.getAnnotationType(), attributeName, this ); + return new AttributeDescriptorImpl<>( annotationType, attributeName, this ); } @Override - public ValueExtractor> createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext buildingContext) { return resolveJandexExtractor( buildingContext ); } - public ValueExtractor> resolveJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor resolveJandexExtractor(SourceModelBuildingContext buildingContext) { if ( jandexValueExtractor == null ) { this.jandexValueExtractor = new ArrayValueExtractor<>( resolveJandexWrapper( buildingContext ) ); } @@ -84,75 +78,86 @@ public ValueExtractor> resolveJandexExtractor(Source } @Override - public ValueWrapper, AnnotationValue> createJandexWrapper(SourceModelBuildingContext buildingContext) { + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext buildingContext) { return resolveJandexWrapper( buildingContext ); } - private ValueWrapper, AnnotationValue> resolveJandexWrapper(SourceModelBuildingContext buildingContext) { - if ( jandexValueWrapper == null ) { - final ValueWrapper jandexElementWrapper = elementTypeDescriptor.createJandexWrapper( buildingContext ); - jandexValueWrapper = new ArrayValueWrapper<>( jandexElementWrapper ); + private JandexValueConverter resolveJandexWrapper(SourceModelBuildingContext buildingContext) { + if ( jandexValueConverter == null ) { + jandexValueConverter = new ArrayValueConverter<>( elementTypeDescriptor ); } - return jandexValueWrapper; + return jandexValueConverter; } @Override - public ValueExtractor> createJdkExtractor(SourceModelBuildingContext buildingContext) { - return resolveJdkExtractor( buildingContext ); - } - - public ValueExtractor> resolveJdkExtractor(SourceModelBuildingContext buildingContext) { - if ( jdkValueExtractor == null ) { - this.jdkValueExtractor = new org.hibernate.models.internal.jdk.ArrayValueExtractor<>( resolveJkWrapper( buildingContext ) ); + public JdkValueConverter createJdkValueConverter(SourceModelBuildingContext modelContext) { + if ( jdkValueConverter == null ) { + if ( !elementTypeDescriptor.getValueType().isAnnotation() ) { + // for arrays of anything other than nested annotations we can simply return the raw array + jdkValueConverter = JdkPassThruConverter.passThruConverter(); + } + else { + jdkValueConverter = new JdkArrayValueConverter<>( elementTypeDescriptor ); + } } - return jdkValueExtractor; - } - @Override - public ValueWrapper,Object[]> createJdkWrapper(SourceModelBuildingContext buildingContext) { - return resolveJkWrapper( buildingContext ); + return jdkValueConverter; } - public ValueWrapper,Object[]> resolveJkWrapper(SourceModelBuildingContext buildingContext) { - if ( jdkValueWrapper == null ) { - //noinspection unchecked - final ValueWrapper jdkElementWrapper = (ValueWrapper) elementTypeDescriptor.createJdkWrapper( buildingContext ); - jdkValueWrapper = new org.hibernate.models.internal.jdk.ArrayValueWrapper<>( jdkElementWrapper ); + @Override + public JdkValueExtractor createJdkValueExtractor(SourceModelBuildingContext modelContext) { + if ( jdkValueExtractor == null ) { + if ( !elementTypeDescriptor.getValueType().isAnnotation() ) { + // for arrays of anything other than nested annotations we can simply return the raw array + jdkValueExtractor = JdkPassThruExtractor.passThruExtractor(); + } + else { + jdkValueExtractor = new JdkArrayValueExtractor<>( createJdkValueConverter( modelContext ) ); + } } - return jdkValueWrapper; + return jdkValueExtractor; } @Override - public Object unwrap(List value) { - final Object[] result = (Object[]) Array.newInstance( componentType, value.size() ); - for ( int i = 0; i < value.size(); i++ ) { - result[i] = elementTypeDescriptor.unwrap( value.get( i ) ); + public Object unwrap(V[] value) { + final Object[] result = (Object[]) Array.newInstance( componentType, value.length ); + for ( int i = 0; i < value.length; i++ ) { + result[i] = elementTypeDescriptor.unwrap( value[i] ); } return result; } @Override - public void render(RenderingCollector collector, String name, Object attributeValue) { + public void render(RenderingCollector collector, String name, Object attributeValue, SourceModelBuildingContext modelContext) { + assert attributeValue != null : "Annotation value was null - " + name; + //noinspection unchecked - final List values = (List) attributeValue; + final V[] values = (V[]) attributeValue; collector.addLine( "%s = {", name ); collector.indent( 2 ); - values.forEach( (value) -> elementTypeDescriptor.render( collector, value ) ); + for ( V value : values ) { + elementTypeDescriptor.render( collector, value, modelContext ); + } collector.unindent( 2 ); collector.addLine( "}" ); } @Override - public void render(RenderingCollector collector, Object attributeValue) { + public void render(RenderingCollector collector, Object attributeValue, SourceModelBuildingContext modelContext) { //noinspection unchecked final List values = (List) attributeValue; collector.addLine( "{" ); collector.indent( 2 ); - values.forEach( (value) -> elementTypeDescriptor.render( collector, value ) ); + values.forEach( (value) -> elementTypeDescriptor.render( collector, value, modelContext ) ); collector.unindent( 2 ); collector.addLine( "}" ); } + + @Override + public V[][] makeArray(int size, SourceModelBuildingContext modelContext) { + throw new UnsupportedOperationException( "Nested array creation not supported" ); + } } diff --git a/src/main/java/org/hibernate/models/internal/AttributeDescriptorImpl.java b/src/main/java/org/hibernate/models/internal/AttributeDescriptorImpl.java index e47d4e5..567bbc3 100644 --- a/src/main/java/org/hibernate/models/internal/AttributeDescriptorImpl.java +++ b/src/main/java/org/hibernate/models/internal/AttributeDescriptorImpl.java @@ -63,7 +63,7 @@ public String toString() { Locale.ROOT, "AttributeDescriptor(%s : %s)", name, - getTypeDescriptor().getWrappedValueType().getName() + getTypeDescriptor().getValueType().getName() ); } } diff --git a/src/main/java/org/hibernate/models/internal/BooleanTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/BooleanTypeDescriptor.java index 8551b37..7fce1c0 100644 --- a/src/main/java/org/hibernate/models/internal/BooleanTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/BooleanTypeDescriptor.java @@ -6,19 +6,11 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.BooleanValueConverter; import org.hibernate.models.internal.jandex.BooleanValueExtractor; -import org.hibernate.models.internal.jandex.BooleanValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; /** * Descriptor for boolean values @@ -29,34 +21,27 @@ public class BooleanTypeDescriptor extends AbstractTypeDescriptor { public static final BooleanTypeDescriptor BOOLEAN_TYPE_DESCRIPTOR = new BooleanTypeDescriptor(); @Override - public Class getWrappedValueType() { + public Class getValueType() { return Boolean.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return BooleanValueWrapper.JANDEX_BOOLEAN_VALUE_WRAPPER; + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext buildingContext) { + return BooleanValueConverter.JANDEX_BOOLEAN_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext buildingContext) { return BooleanValueExtractor.JANDEX_BOOLEAN_EXTRACTOR; } @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; + public Object unwrap(Boolean value) { + return value; } @Override - public Object unwrap(Boolean value) { - return value; + public Boolean[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new Boolean[size]; } } diff --git a/src/main/java/org/hibernate/models/internal/ByteTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/ByteTypeDescriptor.java index 9cb673f..fec1d6f 100644 --- a/src/main/java/org/hibernate/models/internal/ByteTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/ByteTypeDescriptor.java @@ -6,19 +6,11 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.ByteValueConverter; import org.hibernate.models.internal.jandex.ByteValueExtractor; -import org.hibernate.models.internal.jandex.ByteValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; /** * Descriptor for byte values @@ -29,34 +21,27 @@ public class ByteTypeDescriptor extends AbstractTypeDescriptor { public static final ByteTypeDescriptor BYTE_TYPE_DESCRIPTOR = new ByteTypeDescriptor(); @Override - public Class getWrappedValueType() { + public Class getValueType() { return Byte.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return ByteValueWrapper.JANDEX_BYTE_VALUE_WRAPPER; + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext buildingContext) { + return ByteValueConverter.JANDEX_BYTE_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext buildingContext) { return ByteValueExtractor.JANDEX_BYTE_EXTRACTOR; } @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; + public Object unwrap(Byte value) { + return value; } @Override - public Object unwrap(Byte value) { - return value; + public Byte[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new Byte[size]; } } diff --git a/src/main/java/org/hibernate/models/internal/CharacterTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/CharacterTypeDescriptor.java index 54c003d..b9e5b0c 100644 --- a/src/main/java/org/hibernate/models/internal/CharacterTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/CharacterTypeDescriptor.java @@ -6,19 +6,11 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.CharacterValueConverter; import org.hibernate.models.internal.jandex.CharacterValueExtractor; -import org.hibernate.models.internal.jandex.CharacterValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; /** * Descriptor for char values @@ -29,34 +21,27 @@ public class CharacterTypeDescriptor extends AbstractTypeDescriptor { public static final CharacterTypeDescriptor CHARACTER_TYPE_DESCRIPTOR = new CharacterTypeDescriptor(); @Override - public Class getWrappedValueType() { + public Class getValueType() { return Character.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return CharacterValueWrapper.JANDEX_CHARACTER_VALUE_WRAPPER; + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext buildingContext) { + return CharacterValueConverter.JANDEX_CHARACTER_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext buildingContext) { return CharacterValueExtractor.JANDEX_CHARACTER_EXTRACTOR; } @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; + public Object unwrap(Character value) { + return value; } @Override - public Object unwrap(Character value) { - return value; + public Character[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new Character[size]; } } diff --git a/src/main/java/org/hibernate/models/internal/ClassDetailsSupport.java b/src/main/java/org/hibernate/models/internal/ClassDetailsSupport.java index 8fbaebd..337c48a 100644 --- a/src/main/java/org/hibernate/models/internal/ClassDetailsSupport.java +++ b/src/main/java/org/hibernate/models/internal/ClassDetailsSupport.java @@ -9,13 +9,15 @@ import java.lang.annotation.Annotation; import java.util.List; -import org.hibernate.models.internal.util.CollectionHelper; +import org.hibernate.models.IllegalCastException; import org.hibernate.models.internal.util.IndexedConsumer; import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.FieldDetails; import org.hibernate.models.spi.MethodDetails; import org.hibernate.models.spi.MutableClassDetails; +import org.hibernate.models.spi.MutableMemberDetails; +import org.hibernate.models.spi.RecordComponentDetails; +import org.hibernate.models.spi.SourceModelBuildingContext; /** * @author Steve Ebersole @@ -47,44 +49,56 @@ default void forEachMethod(IndexedConsumer consumer) { } @Override - default AnnotationUsage getAnnotationUsage(AnnotationDescriptor type) { - final AnnotationUsage localUsage = AnnotationUsageHelper.getUsage( type, getUsageMap() ); + default A getAnnotationUsage( + AnnotationDescriptor descriptor, + SourceModelBuildingContext modelContext) { + final A localUsage = AnnotationUsageHelper.getUsage( descriptor, getUsageMap(),modelContext ); if ( localUsage != null ) { return localUsage; } - if ( type.isInherited() && getSuperClass() != null ) { - return getSuperClass().getAnnotationUsage( type ); + if ( descriptor.isInherited() && getSuperClass() != null ) { + return getSuperClass().getAnnotationUsage( descriptor, modelContext ); } return null; } @Override - default List> getRepeatedAnnotationUsages(AnnotationDescriptor type) { - final List> localUsages = AnnotationTargetSupport.super.getRepeatedAnnotationUsages( type ); + default A getAnnotationUsage(Class annotationType, SourceModelBuildingContext modelContext) { + return getAnnotationUsage( + modelContext.getAnnotationDescriptorRegistry().getDescriptor( annotationType ), + modelContext + ); + } - if ( type.isInherited() && getSuperClass() != null ) { - final List> inheritedUsages = getSuperClass().getRepeatedAnnotationUsages( type ); - return CollectionHelper.join( localUsages, inheritedUsages ); - } + @Override + default MutableClassDetails asClassDetails() { + return this; + } - return localUsages; + @Override + default AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "ClassDetails cannot be cast as AnnotationDescriptor" ); } @Override - default AnnotationUsage getNamedAnnotationUsage( - AnnotationDescriptor type, - String matchValue, - String attributeToMatch) { - final AnnotationUsage localUsage = AnnotationTargetSupport.super.getNamedAnnotationUsage( type, matchValue, attributeToMatch ); - if ( localUsage != null ) { - return localUsage; - } + default MutableMemberDetails asMemberDetails() { + throw new IllegalCastException( "ClassDetails cannot be cast as MemberDetails" ); + } - if ( type.isInherited() && getSuperClass() != null ) { - return getSuperClass().getNamedAnnotationUsage( type, matchValue, attributeToMatch ); - } - return null; + @Override + default FieldDetails asFieldDetails() { + throw new IllegalCastException( "ClassDetails cannot be cast as FieldDetails" ); + } + + @Override + default MethodDetails asMethodDetails() { + throw new IllegalCastException( "ClassDetails cannot be cast as MethodDetails" ); + } + + @Override + default RecordComponentDetails asRecordComponentDetails() { + throw new IllegalCastException( "ClassDetails cannot be cast as RecordComponentDetails" ); } } diff --git a/src/main/java/org/hibernate/models/internal/ClassTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/ClassTypeDescriptor.java index 6a7d9f5..cd060eb 100644 --- a/src/main/java/org/hibernate/models/internal/ClassTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/ClassTypeDescriptor.java @@ -6,64 +6,58 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.ClassValueConverter; import org.hibernate.models.internal.jandex.ClassValueExtractor; -import org.hibernate.models.internal.jandex.ClassValueWrapper; -import org.hibernate.models.spi.ClassDetails; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; import org.hibernate.models.spi.RenderingCollector; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; /** * Descriptor for class values * * @author Steve Ebersole */ -public class ClassTypeDescriptor extends AbstractTypeDescriptor { +public class ClassTypeDescriptor extends AbstractTypeDescriptor> { public static final ClassTypeDescriptor CLASS_TYPE_DESCRIPTOR = new ClassTypeDescriptor(); @Override - public Class getWrappedValueType() { - return ClassDetails.class; + public Class> getValueType() { + //noinspection unchecked,rawtypes + return (Class) Class.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return ClassValueWrapper.JANDEX_CLASS_VALUE_WRAPPER; + public JandexValueConverter> createJandexValueConverter(SourceModelBuildingContext buildingContext) { + return ClassValueConverter.JANDEX_CLASS_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor> createJandexValueExtractor(SourceModelBuildingContext buildingContext) { return ClassValueExtractor.JANDEX_CLASS_EXTRACTOR; } @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - return org.hibernate.models.internal.jdk.ClassValueWrapper.JDK_CLASS_VALUE_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - return org.hibernate.models.internal.jdk.ClassValueExtractor.JDK_CLASS_EXTRACTOR; + public Object unwrap(Class value) { + return value; } @Override - public Object unwrap(ClassDetails value) { - return value.toJavaClass(); + public void render( + RenderingCollector collector, + String name, + Object attributeValue, + SourceModelBuildingContext modelContext) { + super.render( collector, name, ( (Class) attributeValue ).getName(), modelContext ); } @Override - public void render(RenderingCollector collector, String name, Object attributeValue) { - super.render( collector, name, ( (ClassDetails) attributeValue ).getName() ); + public void render(RenderingCollector collector, Object attributeValue, SourceModelBuildingContext modelContext) { + super.render( collector, ( (Class) attributeValue ).getName(), modelContext ); } @Override - public void render(RenderingCollector collector, Object attributeValue) { - super.render( collector, ( (ClassDetails) attributeValue ).getName() ); + public Class[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new Class[size]; } } diff --git a/src/main/java/org/hibernate/models/internal/DoubleTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/DoubleTypeDescriptor.java index 546652b..59a9ea4 100644 --- a/src/main/java/org/hibernate/models/internal/DoubleTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/DoubleTypeDescriptor.java @@ -6,19 +6,11 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.DoubleValueConverter; import org.hibernate.models.internal.jandex.DoubleValueExtractor; -import org.hibernate.models.internal.jandex.DoubleValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; /** * Descriptor for double values @@ -29,34 +21,27 @@ public class DoubleTypeDescriptor extends AbstractTypeDescriptor { public static final DoubleTypeDescriptor DOUBLE_TYPE_DESCRIPTOR = new DoubleTypeDescriptor(); @Override - public Class getWrappedValueType() { + public Class getValueType() { return Double.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return DoubleValueWrapper.JANDEX_DOUBLE_VALUE_WRAPPER; + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext modelContext) { + return DoubleValueConverter.JANDEX_DOUBLE_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext modelContext) { return DoubleValueExtractor.JANDEX_DOUBLE_EXTRACTOR; } @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; + public Object unwrap(Double value) { + return value; } @Override - public Object unwrap(Double value) { - return value; + public Double[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new Double[size]; } } diff --git a/src/main/java/org/hibernate/models/internal/EnumTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/EnumTypeDescriptor.java index 7e19d03..d1bac6f 100644 --- a/src/main/java/org/hibernate/models/internal/EnumTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/EnumTypeDescriptor.java @@ -6,19 +6,13 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import org.hibernate.models.internal.jandex.EnumValueConverter; import org.hibernate.models.internal.jandex.EnumValueExtractor; -import org.hibernate.models.internal.jandex.EnumValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; /** * Descriptor for enum values @@ -28,44 +22,38 @@ public class EnumTypeDescriptor> extends AbstractTypeDescriptor { private final Class enumType; - private final EnumValueWrapper jandexWrapper; + private final EnumValueConverter jandexWrapper; private final EnumValueExtractor jandexExtractor; public EnumTypeDescriptor(Class enumType) { this.enumType = enumType; - this.jandexWrapper = new EnumValueWrapper<>( enumType ); + this.jandexWrapper = new EnumValueConverter<>( enumType ); this.jandexExtractor = new EnumValueExtractor<>( jandexWrapper ); } @Override - public Class getWrappedValueType() { + public Class getValueType() { return enumType; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext modelContext) { return jandexWrapper; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext modelContext) { return jandexExtractor; } @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; + public Object unwrap(E value) { + return value; } @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { + public E[] makeArray(int size, SourceModelBuildingContext modelContext) { //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; - } - - @Override - public Object unwrap(E value) { - return value; + return (E[]) Array.newInstance( enumType, size ); } } diff --git a/src/main/java/org/hibernate/models/internal/FloatTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/FloatTypeDescriptor.java index ef6f2e3..dd86eff 100644 --- a/src/main/java/org/hibernate/models/internal/FloatTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/FloatTypeDescriptor.java @@ -6,20 +6,12 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.FloatValueConverter; import org.hibernate.models.internal.jandex.FloatValueExtractor; -import org.hibernate.models.internal.jandex.FloatValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; import org.hibernate.models.spi.RenderingCollector; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; /** * Descriptor for float values @@ -30,44 +22,37 @@ public class FloatTypeDescriptor extends AbstractTypeDescriptor { public static final FloatTypeDescriptor FLOAT_TYPE_DESCRIPTOR = new FloatTypeDescriptor(); @Override - public Class getWrappedValueType() { + public Class getValueType() { return Float.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return FloatValueWrapper.JANDEX_FLOAT_VALUE_WRAPPER; + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext buildingContext) { + return FloatValueConverter.JANDEX_FLOAT_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext buildingContext) { return FloatValueExtractor.JANDEX_FLOAT_EXTRACTOR; } - @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; - } - @Override public Object unwrap(Float value) { return value; } @Override - public void render(RenderingCollector collector, String name, Object attributeValue) { + public void render(RenderingCollector collector, String name, Object attributeValue, SourceModelBuildingContext modelContext) { collector.addLine( "%s = %sF", name, attributeValue ); } @Override - public void render(RenderingCollector collector, Object attributeValue) { + public void render(RenderingCollector collector, Object attributeValue, SourceModelBuildingContext modelContext) { collector.addLine( "%sF", attributeValue ); } + + @Override + public Float[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new Float[size]; + } } diff --git a/src/main/java/org/hibernate/models/internal/IntegerTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/IntegerTypeDescriptor.java index 4dcc545..61c3bbb 100644 --- a/src/main/java/org/hibernate/models/internal/IntegerTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/IntegerTypeDescriptor.java @@ -6,19 +6,11 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.IntegerValueConverter; import org.hibernate.models.internal.jandex.IntegerValueExtractor; -import org.hibernate.models.internal.jandex.IntegerValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; /** * Descriptor for integer values @@ -29,34 +21,27 @@ public class IntegerTypeDescriptor extends AbstractTypeDescriptor { public static final IntegerTypeDescriptor INTEGER_TYPE_DESCRIPTOR = new IntegerTypeDescriptor(); @Override - public Class getWrappedValueType() { + public Class getValueType() { return Integer.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return IntegerValueWrapper.JANDEX_INTEGER_VALUE_WRAPPER; + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext modelContext) { + return IntegerValueConverter.JANDEX_INTEGER_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext modelContext) { return IntegerValueExtractor.JANDEX_INTEGER_EXTRACTOR; } @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; + public Object unwrap(Integer value) { + return value; } @Override - public Object unwrap(Integer value) { - return value; + public Integer[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new Integer[size]; } } diff --git a/src/main/java/org/hibernate/models/internal/LongTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/LongTypeDescriptor.java index 79dd661..ed47345 100644 --- a/src/main/java/org/hibernate/models/internal/LongTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/LongTypeDescriptor.java @@ -6,20 +6,12 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.LongValueConverter; import org.hibernate.models.internal.jandex.LongValueExtractor; -import org.hibernate.models.internal.jandex.LongValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; import org.hibernate.models.spi.RenderingCollector; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; /** * Descriptor for long values @@ -30,44 +22,37 @@ public class LongTypeDescriptor extends AbstractTypeDescriptor { public static final LongTypeDescriptor LONG_TYPE_DESCRIPTOR = new LongTypeDescriptor(); @Override - public Class getWrappedValueType() { + public Class getValueType() { return Long.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return LongValueWrapper.JANDEX_LONG_VALUE_WRAPPER; + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext modelContext) { + return LongValueConverter.JANDEX_LONG_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext modelContext) { return LongValueExtractor.JANDEX_LONG_EXTRACTOR; } - @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; - } - @Override public Object unwrap(Long value) { return value; } @Override - public void render(RenderingCollector collector, String name, Object attributeValue) { + public void render(RenderingCollector collector, String name, Object attributeValue, SourceModelBuildingContext modelContext) { collector.addLine( "%s = %sL", name, attributeValue ); } @Override - public void render(RenderingCollector collector, Object attributeValue) { + public void render(RenderingCollector collector, Object attributeValue, SourceModelBuildingContext modelContext) { collector.addLine( "%sL", attributeValue ); } + + @Override + public Long[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new Long[size]; + } } diff --git a/src/main/java/org/hibernate/models/internal/NestedTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/NestedTypeDescriptor.java index 1f4dd20..28cae43 100644 --- a/src/main/java/org/hibernate/models/internal/NestedTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/NestedTypeDescriptor.java @@ -7,121 +7,122 @@ package org.hibernate.models.internal; import java.lang.annotation.Annotation; +import java.lang.reflect.Array; import java.util.Locale; -import org.hibernate.models.internal.jandex.NestedValueExtractor; -import org.hibernate.models.internal.jandex.NestedValueWrapper; -import org.hibernate.models.internal.jdk.AnnotationDescriptorImpl; +import org.hibernate.models.internal.jandex.JandexNestedValueConverter; +import org.hibernate.models.internal.jandex.JandexNestedValueExtractor; +import org.hibernate.models.internal.jdk.JdkNestedValueConverter; +import org.hibernate.models.internal.jdk.JdkNestedValueExtractor; import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationUsage; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; +import org.hibernate.models.spi.JdkValueConverter; +import org.hibernate.models.spi.JdkValueExtractor; import org.hibernate.models.spi.RenderingCollector; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; /** * Descriptor for nested annotation values * * @author Steve Ebersole */ -public class NestedTypeDescriptor extends AbstractTypeDescriptor> { +public class NestedTypeDescriptor extends AbstractTypeDescriptor { private final Class annotationType; private AnnotationDescriptor descriptor; - private NestedValueWrapper jandexWrapper; - private NestedValueExtractor jandexExtractor; + private JandexNestedValueConverter jandexConverter; + private JandexNestedValueExtractor jandexExtractor; - private org.hibernate.models.internal.jdk.NestedValueWrapper jdkWrapper; - private org.hibernate.models.internal.jdk.NestedValueExtractor jdkExtractor; + private JdkNestedValueConverter jdkConverter; + private JdkNestedValueExtractor jdkExtractor; public NestedTypeDescriptor(Class annotationType) { this.annotationType = annotationType; } @Override - public Class> getWrappedValueType() { - //noinspection unchecked,rawtypes - return (Class) AnnotationUsage.class; + public Class getValueType() { + return annotationType; } private AnnotationDescriptor resolveDescriptor(SourceModelBuildingContext context) { if ( descriptor == null ) { - descriptor = context - .getAnnotationDescriptorRegistry() - .resolveDescriptor( annotationType, (t) -> new AnnotationDescriptorImpl<>( annotationType, context ) ); + descriptor = context.getAnnotationDescriptorRegistry().getDescriptor( annotationType ); } return descriptor; } @Override - public ValueWrapper, AnnotationValue> createJandexWrapper(SourceModelBuildingContext buildingContext) { + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext buildingContext) { return resolveJandexWrapper( buildingContext ); } - public NestedValueWrapper resolveJandexWrapper(SourceModelBuildingContext buildingContext) { - if ( jandexWrapper == null ) { - jandexWrapper = new NestedValueWrapper<>( resolveDescriptor( buildingContext ) ); + public JandexNestedValueConverter resolveJandexWrapper(SourceModelBuildingContext buildingContext) { + if ( jandexConverter == null ) { + jandexConverter = new JandexNestedValueConverter<>( resolveDescriptor( buildingContext ) ); } - return jandexWrapper; + return jandexConverter; } @Override - public ValueExtractor> createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext buildingContext) { return resolveJandexExtractor( buildingContext ); } - public NestedValueExtractor resolveJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexNestedValueExtractor resolveJandexExtractor(SourceModelBuildingContext buildingContext) { if ( jandexExtractor == null ) { - this.jandexExtractor = new NestedValueExtractor<>( resolveJandexWrapper( buildingContext ) ); + this.jandexExtractor = new JandexNestedValueExtractor<>( resolveJandexWrapper( buildingContext ) ); } return jandexExtractor; } @Override - public ValueWrapper, ?> createJdkWrapper(SourceModelBuildingContext buildingContext) { - return resolveJdkWrapper( buildingContext ); + public JdkValueConverter createJdkValueConverter(SourceModelBuildingContext modelContext) { + return resolveJdkValueConverter( modelContext ); } - public org.hibernate.models.internal.jdk.NestedValueWrapper resolveJdkWrapper(SourceModelBuildingContext buildingContext) { - if ( jdkWrapper == null ) { - jdkWrapper = new org.hibernate.models.internal.jdk.NestedValueWrapper<>( resolveDescriptor( buildingContext ) ); + public JdkNestedValueConverter resolveJdkValueConverter(SourceModelBuildingContext modelContext) { + if ( jdkConverter == null ) { + jdkConverter = new JdkNestedValueConverter<>( resolveDescriptor( modelContext ) ); } - return jdkWrapper; - } - - @Override - public ValueExtractor> createJdkExtractor(SourceModelBuildingContext buildingContext) { - return resolveJdkExtractor( buildingContext ); + return jdkConverter; } @Override - public Object unwrap(AnnotationUsage value) { - return value.toAnnotation(); + public JdkValueExtractor createJdkValueExtractor(SourceModelBuildingContext modelContext) { + return resolveJdkValueExtractor( modelContext ); } - public ValueExtractor> resolveJdkExtractor(SourceModelBuildingContext buildingContext) { + public JdkValueExtractor resolveJdkValueExtractor(SourceModelBuildingContext modelContext) { if ( jdkExtractor == null ) { - jdkExtractor = new org.hibernate.models.internal.jdk.NestedValueExtractor<>( resolveJdkWrapper( buildingContext ) ); + jdkExtractor = new JdkNestedValueExtractor<>( resolveJdkValueConverter( modelContext ) ); } return jdkExtractor; } @Override - public void render(RenderingCollector collector, String name, Object attributeValue) { + public Object unwrap(A value) { + return value; + } + + @Override + public void render(RenderingCollector collector, String name, Object attributeValue, SourceModelBuildingContext modelContext) { + //noinspection unchecked + resolveDescriptor( modelContext ).renderUsage( collector, name, (A) attributeValue, modelContext ); + } + + @Override + public void render(RenderingCollector collector, Object attributeValue, SourceModelBuildingContext modelContext) { //noinspection unchecked - final AnnotationUsage nested = (AnnotationUsage) attributeValue; - nested.renderAttributeValue( name, collector ); + resolveDescriptor( modelContext ).renderUsage( collector, (A) attributeValue, modelContext ); } @Override - public void render(RenderingCollector collector, Object attributeValue) { + public A[] makeArray(int size, SourceModelBuildingContext modelContext) { //noinspection unchecked - final AnnotationUsage nested = (AnnotationUsage) attributeValue; - nested.render( collector ); + return (A[]) Array.newInstance( resolveDescriptor( modelContext ).getAnnotationType(), size ); } @Override diff --git a/src/main/java/org/hibernate/models/internal/OrmAnnotationDescriptor.java b/src/main/java/org/hibernate/models/internal/OrmAnnotationDescriptor.java new file mode 100644 index 0000000..1676f84 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/OrmAnnotationDescriptor.java @@ -0,0 +1,192 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.internal; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +/** + * Specialized AnnotationDescriptor implementation intended for use in describing + * Hibernate and JPA annotations. Note especially that this implementation + * does not collect annotations from the annotation class as we never care about + * meta-annotations in these cases. + * + * @author Steve Ebersole + */ +public class OrmAnnotationDescriptor extends AbstractAnnotationDescriptor { + private final Class concreteClass; + private final List> attributeDescriptors; + + private DynamicCreator dynamicCreator; + private JdkCreator jdkCreator; + private JandexCreator jandexCreator; + + public OrmAnnotationDescriptor( + Class annotationType, + Class concreteClass) { + this( annotationType, concreteClass, null ); + } + + public OrmAnnotationDescriptor( + Class annotationType, + Class concreteClass, + AnnotationDescriptor repeatableContainer) { + super( + annotationType, + AnnotationHelper.extractTargets( annotationType ), + AnnotationHelper.isInherited( annotationType ), + repeatableContainer + ); + + this.concreteClass = concreteClass; + this.attributeDescriptors = AnnotationDescriptorBuilding.extractAttributeDescriptors( annotationType ); + } + + @Override + public Map, ? extends Annotation> getUsageMap() { + // we never care about the annotations on these annotation classes + // (aside from @Repeatable, which is handled separately) + return Collections.emptyMap(); + } + + @Override + public C createUsage(SourceModelBuildingContext context) { + if ( dynamicCreator == null ) { + dynamicCreator = new DynamicCreator<>( getAnnotationType(), concreteClass ); + } + return dynamicCreator.createUsage( context ); + } + + @Override + public C createUsage(A jdkAnnotation, SourceModelBuildingContext context) { + if ( jdkCreator == null ) { + jdkCreator = new JdkCreator<>( getAnnotationType(), concreteClass ); + } + return jdkCreator.createUsage( jdkAnnotation, context ); + } + + @Override + public C createUsage(AnnotationInstance jandexAnnotation, SourceModelBuildingContext context) { + if ( jandexCreator == null ) { + jandexCreator = new JandexCreator<>( concreteClass ); + } + return jandexCreator.createUsage( jandexAnnotation, context ); + } + + @Override + public List> getAttributes() { + return attributeDescriptors; + } + + @Override + public String toString() { + return String.format( "AnnotationDescriptor(%s)", getAnnotationType().getName() ); + } + + public static class DynamicCreator { + private final Constructor constructor; + + public DynamicCreator(Class annotationType, Class concreteClass) { + this( resolveConstructor( concreteClass ) ); + } + + private static Constructor resolveConstructor(Class concreteClass) { + try { + return concreteClass.getDeclaredConstructor( SourceModelBuildingContext.class ); + } + catch (NoSuchMethodException e) { + throw new RuntimeException( e ); + } + } + + public DynamicCreator(Constructor constructor) { + this.constructor = constructor; + } + + public C createUsage(SourceModelBuildingContext context) { + try { + return constructor.newInstance( context ); + } + catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { + throw new RuntimeException( e ); + } + } + } + + public static class JdkCreator { + private final Constructor constructor; + + public JdkCreator(Class annotationType, Class concreteClass) { + this( resolveConstructor( annotationType, concreteClass ) ); + } + + private static Constructor resolveConstructor( + Class annotationType, + Class concreteClass) { + try { + return concreteClass.getDeclaredConstructor( annotationType, SourceModelBuildingContext.class ); + } + catch (NoSuchMethodException e) { + throw new RuntimeException( e ); + } + } + + public JdkCreator(Constructor constructor) { + this.constructor = constructor; + } + + public C createUsage(A jdkAnnotation, SourceModelBuildingContext context) { + try { + return constructor.newInstance( jdkAnnotation, context ); + } + catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { + throw new RuntimeException( e ); + } + } + } + + public static class JandexCreator { + private final Constructor constructor; + + public JandexCreator(Class concreteClass) { + this( resolveConstructor( concreteClass ) ); + } + + private static Constructor resolveConstructor(Class concreteClass) { + try { + return concreteClass.getDeclaredConstructor( AnnotationInstance.class, SourceModelBuildingContext.class ); + } + catch (NoSuchMethodException e) { + throw new RuntimeException( e ); + } + } + + public JandexCreator(Constructor constructor) { + this.constructor = constructor; + } + + public C createUsage(AnnotationInstance jandexAnnotation, SourceModelBuildingContext context) { + try { + return constructor.newInstance( jandexAnnotation, context ); + } + catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { + throw new RuntimeException( e ); + } + } + } +} diff --git a/src/main/java/org/hibernate/models/internal/ShortTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/ShortTypeDescriptor.java index 2da8501..209e8e9 100644 --- a/src/main/java/org/hibernate/models/internal/ShortTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/ShortTypeDescriptor.java @@ -6,19 +6,11 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.ShortValueConverter; import org.hibernate.models.internal.jandex.ShortValueExtractor; -import org.hibernate.models.internal.jandex.ShortValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; /** * Descriptor for short values @@ -29,34 +21,27 @@ public class ShortTypeDescriptor extends AbstractTypeDescriptor { public static final ShortTypeDescriptor SHORT_TYPE_DESCRIPTOR = new ShortTypeDescriptor(); @Override - public Class getWrappedValueType() { + public Class getValueType() { return Short.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return ShortValueWrapper.JANDEX_SHORT_VALUE_WRAPPER; + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext buildingContext) { + return ShortValueConverter.JANDEX_SHORT_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext buildingContext) { return ShortValueExtractor.JANDEX_SHORT_EXTRACTOR; } @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; + public Object unwrap(Short value) { + return value; } @Override - public Object unwrap(Short value) { - return value; + public Short[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new Short[size]; } } diff --git a/src/main/java/org/hibernate/models/internal/SimpleClassDetails.java b/src/main/java/org/hibernate/models/internal/SimpleClassDetails.java index 25a17f8..4b3df6b 100644 --- a/src/main/java/org/hibernate/models/internal/SimpleClassDetails.java +++ b/src/main/java/org/hibernate/models/internal/SimpleClassDetails.java @@ -15,15 +15,18 @@ import org.hibernate.models.internal.util.IndexedConsumer; import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.FieldDetails; import org.hibernate.models.spi.MethodDetails; import org.hibernate.models.spi.RecordComponentDetails; +import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; import org.hibernate.models.spi.TypeVariableDetails; /** + * ClassDetails implementation for cases where we do not care about fields, + * methods, record-components nor annotations + * * @author Steve Ebersole */ public class SimpleClassDetails implements ClassDetails { @@ -136,67 +139,83 @@ public List getRecordComponents() { // nor do we care about its annotations @Override - public Collection> getAllAnnotationUsages() { + public Collection getDirectAnnotationUsages() { return Collections.emptyList(); } @Override - public boolean hasAnnotationUsage(Class type) { + public boolean hasDirectAnnotationUsage(Class type) { return false; } @Override - public boolean hasRepeatableAnnotationUsage(Class type) { - return false; + public A getDirectAnnotationUsage(AnnotationDescriptor descriptor) { + return null; } @Override - public AnnotationUsage getAnnotationUsage(AnnotationDescriptor descriptor) { + public A getDirectAnnotationUsage(Class type) { return null; } @Override - public AnnotationUsage getAnnotationUsage(Class type) { + public boolean hasAnnotationUsage(Class type, SourceModelBuildingContext modelContext) { + return false; + } + + @Override + public A getAnnotationUsage( + AnnotationDescriptor descriptor, + SourceModelBuildingContext modelContext) { return null; } @Override - public AnnotationUsage locateAnnotationUsage(Class type) { + public A getAnnotationUsage(Class type, SourceModelBuildingContext modelContext) { return null; } @Override - public List> getRepeatedAnnotationUsages(AnnotationDescriptor type) { - return Collections.emptyList(); + public A locateAnnotationUsage(Class type, SourceModelBuildingContext modelContext) { + return null; } @Override - public List> getRepeatedAnnotationUsages(Class type) { - return Collections.emptyList(); + public A[] getRepeatedAnnotationUsages( + AnnotationDescriptor type, + SourceModelBuildingContext modelContext) { + return null; } @Override - public void forEachAnnotationUsage(Class type, Consumer> consumer) { + public void forEachRepeatedAnnotationUsages( + Class repeatable, + Class container, + SourceModelBuildingContext modelContext, Consumer consumer) { } @Override - public List> getMetaAnnotated(Class metaAnnotationType) { - return Collections.emptyList(); + public List getMetaAnnotated( + Class metaAnnotationType, + SourceModelBuildingContext modelContext) { + return null; } @Override - public AnnotationUsage getNamedAnnotationUsage( + public X getNamedAnnotationUsage( AnnotationDescriptor type, String matchName, - String attributeToMatch) { + String attributeToMatch, + SourceModelBuildingContext modelContext) { return null; } @Override - public AnnotationUsage getNamedAnnotationUsage( + public X getNamedAnnotationUsage( Class type, String matchName, - String attributeToMatch) { + String attributeToMatch, + SourceModelBuildingContext modelContext) { return null; } } diff --git a/src/main/java/org/hibernate/models/internal/SourceModelBuildingContextImpl.java b/src/main/java/org/hibernate/models/internal/SourceModelBuildingContextImpl.java index 41b4c68..71a80c6 100644 --- a/src/main/java/org/hibernate/models/internal/SourceModelBuildingContextImpl.java +++ b/src/main/java/org/hibernate/models/internal/SourceModelBuildingContextImpl.java @@ -13,7 +13,6 @@ import org.hibernate.models.internal.jdk.JdkBuilders; import org.hibernate.models.spi.AnnotationDescriptor; import org.hibernate.models.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.ClassDetailsRegistry; import org.hibernate.models.spi.ClassLoading; @@ -70,12 +69,12 @@ public IndexView getJandexIndex() { } @Override - public List> getAllAnnotationUsages(Class annotationType) { + public List getAllAnnotationUsages(Class annotationType) { throw new UnsupportedOperationException( "Not yet implemented" ); } @Override - public void forEachAnnotationUsage(Class annotationType, Consumer> consumer) { + public void forEachAnnotationUsage(Class annotationType, Consumer consumer) { throw new UnsupportedOperationException( "Not yet implemented" ); } diff --git a/src/main/java/org/hibernate/models/internal/StandardAnnotationDescriptor.java b/src/main/java/org/hibernate/models/internal/StandardAnnotationDescriptor.java new file mode 100644 index 0000000..d2a281e --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/StandardAnnotationDescriptor.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.internal; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.AnnotationDescriptorRegistry; +import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +/** + * Simple implementation of {@link AnnotationDescriptor}. + * + * @author Steve Ebersole + */ +public class StandardAnnotationDescriptor extends AbstractAnnotationDescriptor { + private final List> attributeDescriptors; + private final Map, ? extends Annotation> usagesMap; + + public StandardAnnotationDescriptor( + Class annotationType, + SourceModelBuildingContext buildingContext) { + this( annotationType, null, buildingContext ); + } + + public StandardAnnotationDescriptor( + Class annotationType, + AnnotationDescriptor repeatableContainer, + SourceModelBuildingContext buildingContext) { + super( annotationType, AnnotationHelper.extractTargets( annotationType ), AnnotationHelper.isInherited( annotationType ), repeatableContainer ); + + this.attributeDescriptors = AnnotationDescriptorBuilding.extractAttributeDescriptors( annotationType ); + this.usagesMap = buildUsagesMap( annotationType, buildingContext ); + } + + @Override + public Map, ? extends Annotation> getUsageMap() { + return usagesMap; + } + + @Override + public A createUsage(A jdkAnnotation, SourceModelBuildingContext context) { + return jdkAnnotation; + } + + @Override + public A createUsage(AnnotationInstance jandexAnnotation, SourceModelBuildingContext context) { + return AnnotationProxy.makeProxy( + this, + jandexAnnotation, + context + ); + } + + @Override + public A createUsage(SourceModelBuildingContext context) { + throw new UnsupportedOperationException( + "Creating empty annotation usage mot supported from StandardAnnotationDescriptor : " + getAnnotationType().getName() + ); + } + + @Override + public List> getAttributes() { + return attributeDescriptors; + } + + /** + * Builds a map of the usages for the annotation's annotations + */ + private static Map, ? extends Annotation> buildUsagesMap( + Class annotationType, + SourceModelBuildingContext buildingContext) { + final Map, ? extends Annotation> result = new HashMap<>(); + + final AnnotationDescriptorRegistry annotationDescriptorRegistry = buildingContext.getAnnotationDescriptorRegistry(); + + final Annotation[] annotationTypeAnnotations = annotationType.getAnnotations(); + for ( int i = 0; i < annotationTypeAnnotations.length; i++ ) { + final Annotation annotationTypeAnnotation = annotationTypeAnnotations[i]; + final Class annotationTypeAnnotationType = annotationTypeAnnotation.annotationType(); + + // skip a few well-know ones that are irrelevant + if ( annotationTypeAnnotationType == Repeatable.class + || annotationTypeAnnotationType == Target.class + || annotationTypeAnnotationType == Retention.class + || annotationTypeAnnotationType == Documented.class ) { + continue; + } + + //noinspection rawtypes + final AnnotationDescriptor annotationDescriptor = annotationDescriptorRegistry.getDescriptor( annotationTypeAnnotationType ); + //noinspection unchecked + final Annotation annotationTypeAnnotationUsage = annotationDescriptor.createUsage( annotationTypeAnnotation, buildingContext ); + + //noinspection rawtypes,unchecked + ( (Map) result ).put( annotationTypeAnnotationType, annotationTypeAnnotationUsage ); + } + + return result; + } +} diff --git a/src/main/java/org/hibernate/models/internal/StringTypeDescriptor.java b/src/main/java/org/hibernate/models/internal/StringTypeDescriptor.java index 76bac99..a97bdf4 100644 --- a/src/main/java/org/hibernate/models/internal/StringTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/internal/StringTypeDescriptor.java @@ -6,20 +6,12 @@ */ package org.hibernate.models.internal; -import java.lang.annotation.Annotation; - +import org.hibernate.models.internal.jandex.StringValueConverter; import org.hibernate.models.internal.jandex.StringValueExtractor; -import org.hibernate.models.internal.jandex.StringValueWrapper; -import org.hibernate.models.internal.jdk.PassThruExtractor; +import org.hibernate.models.spi.JandexValueConverter; +import org.hibernate.models.spi.JandexValueExtractor; import org.hibernate.models.spi.RenderingCollector; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - -import static org.hibernate.models.internal.jdk.PassThruWrapper.PASS_THRU_WRAPPER; /** * Descriptor for string values @@ -30,44 +22,41 @@ public class StringTypeDescriptor extends AbstractTypeDescriptor { public static final StringTypeDescriptor STRING_TYPE_DESCRIPTOR = new StringTypeDescriptor(); @Override - public Class getWrappedValueType() { + public Class getValueType() { return String.class; } @Override - public ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext) { - return StringValueWrapper.JANDEX_STRING_VALUE_WRAPPER; + public JandexValueConverter createJandexValueConverter(SourceModelBuildingContext buildingContext) { + return StringValueConverter.JANDEX_STRING_VALUE_WRAPPER; } @Override - public ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext) { + public JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext buildingContext) { return StringValueExtractor.JANDEX_STRING_EXTRACTOR; } - @Override - public ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PASS_THRU_WRAPPER; - } - - @Override - public ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext) { - //noinspection unchecked - return PassThruExtractor.PASS_THRU_EXTRACTOR; - } - @Override public Object unwrap(String value) { return value; } @Override - public void render(RenderingCollector collector, String name, Object attributeValue) { + public void render( + RenderingCollector collector, + String name, + Object attributeValue, + SourceModelBuildingContext modelContext) { collector.addLine( "%s = \"%s\"", name, attributeValue ); } @Override - public void render(RenderingCollector collector, Object attributeValue) { + public void render(RenderingCollector collector, Object attributeValue, SourceModelBuildingContext modelContext) { collector.addLine( "\"%s\"", attributeValue ); } + + @Override + public String[] makeArray(int size, SourceModelBuildingContext modelContext) { + return new String[size]; + } } diff --git a/src/main/java/org/hibernate/models/internal/TypeDescriptors.java b/src/main/java/org/hibernate/models/internal/TypeDescriptors.java index bb414d1..0c0564c 100644 --- a/src/main/java/org/hibernate/models/internal/TypeDescriptors.java +++ b/src/main/java/org/hibernate/models/internal/TypeDescriptors.java @@ -74,7 +74,7 @@ public static ValueTypeDescriptor resolveTypeDescriptor(Class attrib if ( attributeType.isArray() ) { final Class componentType = attributeType.getComponentType(); final ValueTypeDescriptor elementTypeDescriptor = resolveTypeDescriptor( componentType ); - return (ValueTypeDescriptor) new ArrayTypeDescriptor<>( elementTypeDescriptor, componentType ); + return (ValueTypeDescriptor) new ArrayTypeDescriptor<>( elementTypeDescriptor ); } if ( attributeType.isEnum() ) { diff --git a/src/main/java/org/hibernate/models/internal/dynamic/AbstractAnnotationTarget.java b/src/main/java/org/hibernate/models/internal/dynamic/AbstractAnnotationTarget.java index 73e5c2b..fda6467 100644 --- a/src/main/java/org/hibernate/models/internal/dynamic/AbstractAnnotationTarget.java +++ b/src/main/java/org/hibernate/models/internal/dynamic/AbstractAnnotationTarget.java @@ -11,27 +11,25 @@ import java.util.Map; import org.hibernate.models.internal.AnnotationTargetSupport; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.SourceModelBuildingContext; /** * @author Steve Ebersole */ public abstract class AbstractAnnotationTarget implements AnnotationTargetSupport { - private final SourceModelBuildingContext buildingContext; - private final Map, AnnotationUsage> usageMap = new HashMap<>(); + private final SourceModelBuildingContext modelContext; + private final Map, ? extends Annotation> usageMap = new HashMap<>(); - public AbstractAnnotationTarget(SourceModelBuildingContext buildingContext) { - this.buildingContext = buildingContext; + public AbstractAnnotationTarget(SourceModelBuildingContext modelContext) { + this.modelContext = modelContext; } - @Override - public SourceModelBuildingContext getBuildingContext() { - return buildingContext; + public SourceModelBuildingContext getModelContext() { + return modelContext; } @Override - public Map, AnnotationUsage> getUsageMap() { + public Map, ? extends Annotation> getUsageMap() { return usageMap; } @@ -39,19 +37,4 @@ public Map, AnnotationUsage> g public void clearAnnotationUsages() { usageMap.clear(); } - - /** - * Applies the given {@code annotationUsage} to this target. - * - * @todo It is undefined currently what happens if the annotation type is already applied on this target. - */ - public void addAnnotationUsage(AnnotationUsage annotationUsage) { - assert annotationUsage.getAnnotationDescriptor().getAllowableTargets().contains( getKind() ); - final AnnotationUsage previous = usageMap.put( annotationUsage.getAnnotationType(), annotationUsage ); - - if ( previous != null ) { - // todo : ignore? log? exception? - } - } - } diff --git a/src/main/java/org/hibernate/models/internal/dynamic/DynamicAnnotationUsage.java b/src/main/java/org/hibernate/models/internal/dynamic/DynamicAnnotationUsage.java deleted file mode 100644 index eb086df..0000000 --- a/src/main/java/org/hibernate/models/internal/dynamic/DynamicAnnotationUsage.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.dynamic; - -import java.lang.annotation.Annotation; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import org.hibernate.models.internal.AnnotationProxy; -import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AttributeDescriptor; -import org.hibernate.models.spi.MutableAnnotationUsage; -import org.hibernate.models.spi.SourceModelBuildingContext; - -/** - * AnnotationUsage built dynamically (for dynamic models, XML mappings, etc.) - * - * @author Steve Ebersole - */ -public class DynamicAnnotationUsage implements MutableAnnotationUsage { - private final AnnotationDescriptor annotationDescriptor; - - private Map values; - - public DynamicAnnotationUsage( AnnotationDescriptor annotationDescriptor, SourceModelBuildingContext context) { - this( annotationDescriptor, extractBaselineValues( annotationDescriptor, context ) ); - } - - private DynamicAnnotationUsage(AnnotationDescriptor annotationDescriptor, Map values) { - this.annotationDescriptor = annotationDescriptor; - this.values = values; - } - - @Override - public AnnotationDescriptor getAnnotationDescriptor() { - return annotationDescriptor; - } - - @Override - public A toAnnotation() { - return AnnotationProxy.makeProxy( annotationDescriptor, values ); - } - - @Override - public V findAttributeValue(String name) { - if ( values != null ) { - //noinspection unchecked - return (V) values.get( name ); - } - - return null; - } - - /** - * DynamicAnnotationUsage - */ - @Override - public V getAttributeValue(String name) { - // Validate the attribute exists on the annotation descriptor - final AttributeDescriptor attribute = annotationDescriptor.getAttribute( name ); - return findAttributeValue( attribute.getName() ); - } - - @Override - public V setAttributeValue(String name, V value) { - if ( value == null ) { - throw new IllegalArgumentException( - String.format( - Locale.ROOT, - "Null value not allowed for attribute `%s` of annotation `%s`", - name, - getAnnotationType().getName() - ) - ); - } - - // Validate the attribute exists on the annotation descriptor - final AttributeDescriptor attribute = annotationDescriptor.getAttribute( name ); - - if ( values == null ) { - values = new HashMap<>(); - } - - //noinspection unchecked - return (V) values.put( attribute.getName(), value ); - } - - private static Map extractBaselineValues( - AnnotationDescriptor annotationDescriptor, - SourceModelBuildingContext context) { - final HashMap values = new HashMap<>(); - for ( AttributeDescriptor attribute : annotationDescriptor.getAttributes() ) { - values.put( - attribute.getName(), - attribute.getTypeDescriptor().createValue( attribute, context ) - ); - } - return values; - } -} 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 33101f7..af51b11 100644 --- a/src/main/java/org/hibernate/models/internal/dynamic/DynamicClassDetails.java +++ b/src/main/java/org/hibernate/models/internal/dynamic/DynamicClassDetails.java @@ -212,7 +212,7 @@ public DynamicFieldDetails applyAttribute( public Class toJavaClass() { if ( javaType == null ) { if ( className != null ) { - javaType = getBuildingContext().getClassLoading().classForName( className ); + javaType = getModelContext().getClassLoading().classForName( className ); } } //noinspection unchecked 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 106c9e5..74415e0 100644 --- a/src/main/java/org/hibernate/models/internal/dynamic/DynamicFieldDetails.java +++ b/src/main/java/org/hibernate/models/internal/dynamic/DynamicFieldDetails.java @@ -6,13 +6,19 @@ */ package org.hibernate.models.internal.dynamic; +import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.util.Collection; import java.util.Map; +import org.hibernate.models.IllegalCastException; +import org.hibernate.models.spi.AnnotationDescriptor; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.MethodDetails; +import org.hibernate.models.spi.MutableClassDetails; import org.hibernate.models.spi.MutableMemberDetails; +import org.hibernate.models.spi.RecordComponentDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; import org.hibernate.models.spi.TypeVariableScope; @@ -109,4 +115,34 @@ public TypeDetails resolveRelativeType(TypeVariableScope container) { public String toString() { return "DynamicFieldDetails(" + name + ")"; } + + @Override + public FieldDetails asFieldDetails() { + return this; + } + + @Override + public MutableMemberDetails asMemberDetails() { + return this; + } + + @Override + public MethodDetails asMethodDetails() { + throw new IllegalCastException( "FieldDetails cannot be cast as MethodDetails" ); + } + + @Override + public RecordComponentDetails asRecordComponentDetails() { + throw new IllegalCastException( "FieldDetails cannot be cast as RecordComponentDetails" ); + } + + @Override + public MutableClassDetails asClassDetails() { + throw new IllegalCastException( "FieldDetails cannot be cast as ClassDetails" ); + } + + @Override + public AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "FieldDetails cannot be cast as AnnotationDescriptor" ); + } } 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 0d05656..2627f8d 100644 --- a/src/main/java/org/hibernate/models/internal/dynamic/DynamicMethodDetails.java +++ b/src/main/java/org/hibernate/models/internal/dynamic/DynamicMethodDetails.java @@ -6,14 +6,20 @@ */ package org.hibernate.models.internal.dynamic; +import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.util.Collection; import java.util.List; import java.util.Map; +import org.hibernate.models.IllegalCastException; +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.MutableClassDetails; import org.hibernate.models.spi.MutableMemberDetails; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.MethodDetails; +import org.hibernate.models.spi.RecordComponentDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; import org.hibernate.models.spi.TypeVariableScope; @@ -141,4 +147,34 @@ public List getArgumentTypes() { public String toString() { return "DynamicMethodDetails(" + name + ")"; } + + @Override + public MethodDetails asMethodDetails() { + return this; + } + + @Override + public MutableMemberDetails asMemberDetails() { + return this; + } + + @Override + public FieldDetails asFieldDetails() { + throw new IllegalCastException( "MethodDetails cannot be cast as FieldDetails" ); + } + + @Override + public RecordComponentDetails asRecordComponentDetails() { + throw new IllegalCastException( "MethodDetails cannot be cast as RecordComponentDetails" ); + } + + @Override + public MutableClassDetails asClassDetails() { + throw new IllegalCastException( "MethodDetails cannot be cast as ClassDetails" ); + } + + @Override + public AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "MethodDetails cannot be cast as AnnotationDescriptor" ); + } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/AbstractAnnotationTarget.java b/src/main/java/org/hibernate/models/internal/jandex/AbstractAnnotationTarget.java index 4cf53fa..7265f0f 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/AbstractAnnotationTarget.java +++ b/src/main/java/org/hibernate/models/internal/jandex/AbstractAnnotationTarget.java @@ -10,19 +10,22 @@ import java.util.Map; import org.hibernate.models.internal.AnnotationTargetSupport; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.SourceModelBuildingContext; /** * @author Steve Ebersole */ public abstract class AbstractAnnotationTarget implements AnnotationTargetSupport { - private final SourceModelBuildingContext buildingContext; + private final SourceModelBuildingContext modelContext; - private Map, AnnotationUsage> usageMap; + private Map, ? extends Annotation> usageMap; - public AbstractAnnotationTarget(SourceModelBuildingContext buildingContext) { - this.buildingContext = buildingContext; + public AbstractAnnotationTarget(SourceModelBuildingContext modelContext) { + this.modelContext = modelContext; + } + + public SourceModelBuildingContext getModelContext() { + return modelContext; } /** @@ -32,9 +35,9 @@ public AbstractAnnotationTarget(SourceModelBuildingContext buildingContext) { protected abstract org.jboss.jandex.AnnotationTarget getJandexAnnotationTarget(); @Override - public Map, AnnotationUsage> getUsageMap() { + public Map, ? extends Annotation> getUsageMap() { if ( usageMap == null ) { - usageMap = AnnotationUsageBuilder.collectUsages( getJandexAnnotationTarget(), buildingContext ); + usageMap = AnnotationUsageBuilder.collectUsages( getJandexAnnotationTarget(), modelContext ); } return usageMap; } @@ -43,15 +46,4 @@ public Map, AnnotationUsage> getUsageMap() { public void clearAnnotationUsages() { getUsageMap().clear(); } - - @Override - public void addAnnotationUsage(AnnotationUsage annotationUsage) { - assert annotationUsage.getAnnotationDescriptor().getAllowableTargets().contains( getKind() ); - getUsageMap().put( annotationUsage.getAnnotationType(), annotationUsage ); - } - - @Override - public SourceModelBuildingContext getBuildingContext() { - return buildingContext; - } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/AbstractValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/AbstractValueExtractor.java index 72608ce..7595610 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/AbstractValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/AbstractValueExtractor.java @@ -7,7 +7,7 @@ package org.hibernate.models.internal.jandex; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; +import org.hibernate.models.spi.JandexValueExtractor; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; @@ -15,7 +15,7 @@ /** * @author Steve Ebersole */ -public abstract class AbstractValueExtractor implements ValueExtractor { +public abstract class AbstractValueExtractor implements JandexValueExtractor { protected abstract W extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext); diff --git a/src/main/java/org/hibernate/models/internal/jandex/AnnotationUsageBuilder.java b/src/main/java/org/hibernate/models/internal/jandex/AnnotationUsageBuilder.java index f3bc018..58ed27c 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/AnnotationUsageBuilder.java +++ b/src/main/java/org/hibernate/models/internal/jandex/AnnotationUsageBuilder.java @@ -21,16 +21,15 @@ import org.hibernate.models.internal.util.CollectionHelper; import org.hibernate.models.spi.AnnotationDescriptor; import org.hibernate.models.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.AttributeDescriptor; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; +import org.hibernate.models.spi.JandexValueExtractor; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.DotName; /** - * Helper for building {@link AnnotationUsage} instances based on + * Helper for building annotation usages/instances based on * Jandex {@linkplain AnnotationInstance} references * * @author Steve Ebersole @@ -44,13 +43,13 @@ public class AnnotationUsageBuilder { /** * Create the AnnotationUsages map for a given target */ - public static Map, AnnotationUsage> collectUsages( + public static Map, ? extends Annotation> collectUsages( org.jboss.jandex.AnnotationTarget jandexAnnotationTarget, SourceModelBuildingContext buildingContext) { if ( jandexAnnotationTarget == null ) { return Collections.emptyMap(); } - final Map, AnnotationUsage> result = new HashMap<>(); + final Map, Annotation> result = new HashMap<>(); processAnnotations( jandexAnnotationTarget.declaredAnnotations(), result::put, @@ -64,7 +63,7 @@ public static Map, AnnotationUsage> collectUsages */ public static void processAnnotations( Collection annotations, - BiConsumer, AnnotationUsage> consumer, + BiConsumer, Annotation> consumer, SourceModelBuildingContext buildingContext) { final AnnotationDescriptorRegistry annotationDescriptorRegistry = buildingContext.getAnnotationDescriptorRegistry(); @@ -81,7 +80,7 @@ public static void processAnnotations( .classForName( annotation.name().toString() ); final AnnotationDescriptor annotationDescriptor = annotationDescriptorRegistry.getDescriptor( annotationType ); - final AnnotationUsage usage = makeUsage( + final Annotation usage = makeUsage( annotation, annotationDescriptor, buildingContext @@ -90,21 +89,21 @@ public static void processAnnotations( } } - public static AnnotationUsage makeUsage( + public static A makeUsage( AnnotationInstance annotation, AnnotationDescriptor annotationDescriptor, - SourceModelBuildingContext buildingContext) { - return new JandexAnnotationUsage<>( annotation, annotationDescriptor, buildingContext ); + SourceModelBuildingContext modelContext) { + return annotationDescriptor.createUsage( annotation, modelContext ); } /** * Extracts values from an annotation creating AnnotationAttributeValue references. */ @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Map extractAttributeValues( + public static Map extractAttributeValues( AnnotationInstance annotationInstance, AnnotationDescriptor annotationDescriptor, - SourceModelBuildingContext buildingContext) { + SourceModelBuildingContext modelContext) { if ( CollectionHelper.isEmpty( annotationDescriptor.getAttributes() ) ) { return Collections.emptyMap(); } @@ -112,10 +111,14 @@ public static Map extractAttributeValues( final ConcurrentHashMap valueMap = new ConcurrentHashMap<>(); for ( int i = 0; i < annotationDescriptor.getAttributes().size(); i++ ) { final AttributeDescriptor attributeDescriptor = annotationDescriptor.getAttributes().get( i ); - final ValueExtractor extractor = attributeDescriptor + final JandexValueExtractor extractor = attributeDescriptor .getTypeDescriptor() - .createJandexExtractor( buildingContext ); - final Object attributeValue = extractor.extractValue( annotationInstance, attributeDescriptor, buildingContext ); + .createJandexValueExtractor( modelContext ); + final Object attributeValue = extractor.extractValue( + annotationInstance, + attributeDescriptor, + modelContext + ); valueMap.put( attributeDescriptor.getName(), attributeValue ); } return valueMap; diff --git a/src/main/java/org/hibernate/models/internal/jandex/ArrayValueConverter.java b/src/main/java/org/hibernate/models/internal/jandex/ArrayValueConverter.java new file mode 100644 index 0000000..85d1609 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jandex/ArrayValueConverter.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.internal.jandex; + +import java.util.List; + +import org.hibernate.models.spi.SourceModelBuildingContext; +import org.hibernate.models.spi.ValueTypeDescriptor; +import org.hibernate.models.spi.JandexValueConverter; + +import org.jboss.jandex.AnnotationValue; + +/** + * @author Steve Ebersole + */ +public class ArrayValueConverter implements JandexValueConverter { + private final ValueTypeDescriptor elementTypeDescriptor; + + public ArrayValueConverter(ValueTypeDescriptor elementTypeDescriptor) { + this.elementTypeDescriptor = elementTypeDescriptor; + } + + @Override + public V[] convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + + final List values = jandexValue.asArrayList(); + assert values != null; + + final V[] result = elementTypeDescriptor.makeArray( values.size(), modelContext ); + final JandexValueConverter elementWrapper = elementTypeDescriptor.createJandexValueConverter( modelContext ); + for ( int i = 0; i < values.size(); i++ ) { + result[i] = elementWrapper.convert( values.get( i ), modelContext ); + } + return result; + } +} diff --git a/src/main/java/org/hibernate/models/internal/jandex/ArrayValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/ArrayValueExtractor.java index b10bea1..8767648 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/ArrayValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/ArrayValueExtractor.java @@ -9,27 +9,27 @@ import java.util.List; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationValue; /** * @author Steve Ebersole */ -public class ArrayValueExtractor extends AbstractValueExtractor> { - private final ValueWrapper,AnnotationValue> wrapper; +public class ArrayValueExtractor extends AbstractValueExtractor { + private final JandexValueConverter wrapper; - public ArrayValueExtractor(ValueWrapper,AnnotationValue> wrapper) { + public ArrayValueExtractor(JandexValueConverter wrapper) { this.wrapper = wrapper; } @Override - protected List extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { + protected V[] extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; final List values = jandexValue.asArrayList(); assert values != null; - return wrapper.wrap( jandexValue, buildingContext ); + return wrapper.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/ArrayValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/ArrayValueWrapper.java deleted file mode 100644 index 92c3142..0000000 --- a/src/main/java/org/hibernate/models/internal/jandex/ArrayValueWrapper.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jandex; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationValue; - -/** - * @author Steve Ebersole - */ -public class ArrayValueWrapper implements ValueWrapper,AnnotationValue> { - private final ValueWrapper elementWrapper; - - public ArrayValueWrapper(ValueWrapper elementWrapper) { - this.elementWrapper = elementWrapper; - } - - @Override - public List wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - - final List values = rawValue.asArrayList(); - assert values != null; - - final List result = new ArrayList<>( values.size() ); - for ( final AnnotationValue value : values ) { - result.add( elementWrapper.wrap( value, buildingContext ) ); - } - return result; - } -} diff --git a/src/main/java/org/hibernate/models/internal/jandex/BooleanValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/BooleanValueConverter.java similarity index 50% rename from src/main/java/org/hibernate/models/internal/jandex/BooleanValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jandex/BooleanValueConverter.java index 1215045..2e80daf 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/BooleanValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jandex/BooleanValueConverter.java @@ -7,7 +7,7 @@ package org.hibernate.models.internal.jandex; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationValue; @@ -16,12 +16,12 @@ * * @author Steve Ebersole */ -public class BooleanValueWrapper implements ValueWrapper { - public static final BooleanValueWrapper JANDEX_BOOLEAN_VALUE_WRAPPER = new BooleanValueWrapper(); +public class BooleanValueConverter implements JandexValueConverter { + public static final BooleanValueConverter JANDEX_BOOLEAN_VALUE_WRAPPER = new BooleanValueConverter(); @Override - public Boolean wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - return rawValue.asBoolean(); + public Boolean convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + return jandexValue.asBoolean(); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/BooleanValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/BooleanValueExtractor.java index c62ebd6..f732ed5 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/BooleanValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/BooleanValueExtractor.java @@ -21,6 +21,6 @@ public class BooleanValueExtractor extends AbstractValueExtractor { @Override protected Boolean extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return BooleanValueWrapper.JANDEX_BOOLEAN_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return BooleanValueConverter.JANDEX_BOOLEAN_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/ByteValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/ByteValueConverter.java similarity index 51% rename from src/main/java/org/hibernate/models/internal/jandex/ByteValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jandex/ByteValueConverter.java index 8ca21d2..348d9e6 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/ByteValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jandex/ByteValueConverter.java @@ -7,7 +7,7 @@ package org.hibernate.models.internal.jandex; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationValue; @@ -16,12 +16,12 @@ * * @author Steve Ebersole */ -public class ByteValueWrapper implements ValueWrapper { - public static final ByteValueWrapper JANDEX_BYTE_VALUE_WRAPPER = new ByteValueWrapper(); +public class ByteValueConverter implements JandexValueConverter { + public static final ByteValueConverter JANDEX_BYTE_VALUE_WRAPPER = new ByteValueConverter(); @Override - public Byte wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - return rawValue.asByte(); + public Byte convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + return jandexValue.asByte(); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/ByteValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/ByteValueExtractor.java index 61cbca0..f88a5a9 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/ByteValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/ByteValueExtractor.java @@ -21,6 +21,6 @@ public class ByteValueExtractor extends AbstractValueExtractor { @Override protected Byte extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return ByteValueWrapper.JANDEX_BYTE_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return ByteValueConverter.JANDEX_BYTE_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/CharacterValueConverter.java b/src/main/java/org/hibernate/models/internal/jandex/CharacterValueConverter.java new file mode 100644 index 0000000..2e40146 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jandex/CharacterValueConverter.java @@ -0,0 +1,27 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.internal.jandex; + +import org.hibernate.models.spi.SourceModelBuildingContext; +import org.hibernate.models.spi.JandexValueConverter; + +import org.jboss.jandex.AnnotationValue; + +/** + * Wraps AnnotationValue as a character + * + * @author Steve Ebersole + */ +public class CharacterValueConverter implements JandexValueConverter { + public static final CharacterValueConverter JANDEX_CHARACTER_VALUE_WRAPPER = new CharacterValueConverter(); + + @Override + public Character convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + return jandexValue.asChar(); + } +} diff --git a/src/main/java/org/hibernate/models/internal/jandex/CharacterValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/CharacterValueExtractor.java index f5f31b0..e6cc626 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/CharacterValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/CharacterValueExtractor.java @@ -10,7 +10,7 @@ import org.jboss.jandex.AnnotationValue; -import static org.hibernate.models.internal.jandex.CharacterValueWrapper.JANDEX_CHARACTER_VALUE_WRAPPER; +import static org.hibernate.models.internal.jandex.CharacterValueConverter.JANDEX_CHARACTER_VALUE_WRAPPER; /** * Extracts character values from an attribute @@ -23,6 +23,6 @@ public class CharacterValueExtractor extends AbstractValueExtractor { @Override protected Character extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return JANDEX_CHARACTER_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return JANDEX_CHARACTER_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/CharacterValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/CharacterValueWrapper.java deleted file mode 100644 index cbd68e4..0000000 --- a/src/main/java/org/hibernate/models/internal/jandex/CharacterValueWrapper.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jandex; - -import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationValue; - -/** - * Wraps AnnotationValue as a character - * - * @author Steve Ebersole - */ -public class CharacterValueWrapper implements ValueWrapper { - public static final CharacterValueWrapper JANDEX_CHARACTER_VALUE_WRAPPER = new CharacterValueWrapper(); - - @Override - public Character wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - return rawValue.asChar(); - } -} diff --git a/src/main/java/org/hibernate/models/internal/jandex/ClassValueConverter.java b/src/main/java/org/hibernate/models/internal/jandex/ClassValueConverter.java new file mode 100644 index 0000000..370a37a --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jandex/ClassValueConverter.java @@ -0,0 +1,32 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.internal.jandex; + +import org.hibernate.models.spi.SourceModelBuildingContext; +import org.hibernate.models.spi.JandexValueConverter; + +import org.jboss.jandex.AnnotationValue; +import org.jboss.jandex.Type; +import org.jboss.jandex.VoidType; + +/** + * Wraps AnnotationValue as a class + * + * @author Steve Ebersole + */ +public class ClassValueConverter implements JandexValueConverter> { + public static final ClassValueConverter JANDEX_CLASS_VALUE_WRAPPER = new ClassValueConverter(); + + @Override + public Class convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + final Type classReference = jandexValue.asClass(); + if ( classReference == VoidType.VOID ) { + return void.class; + } + return modelContext.getClassLoading().classForName( classReference.name().toString() ); + } +} diff --git a/src/main/java/org/hibernate/models/internal/jandex/ClassValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/ClassValueExtractor.java index fd5e25f..0d35b8a 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/ClassValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/ClassValueExtractor.java @@ -6,7 +6,6 @@ */ package org.hibernate.models.internal.jandex; -import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.jboss.jandex.AnnotationValue; @@ -14,12 +13,12 @@ /** * @author Steve Ebersole */ -public class ClassValueExtractor extends AbstractValueExtractor { +public class ClassValueExtractor extends AbstractValueExtractor> { public static final ClassValueExtractor JANDEX_CLASS_EXTRACTOR = new ClassValueExtractor(); @Override - protected ClassDetails extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { + protected Class extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return ClassValueWrapper.JANDEX_CLASS_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return ClassValueConverter.JANDEX_CLASS_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/ClassValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/ClassValueWrapper.java deleted file mode 100644 index c3efdde..0000000 --- a/src/main/java/org/hibernate/models/internal/jandex/ClassValueWrapper.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jandex; - -import org.hibernate.models.spi.ClassDetails; -import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.Type; - -/** - * Wraps AnnotationValue as a class - * - * @author Steve Ebersole - */ -public class ClassValueWrapper implements ValueWrapper { - public static final ClassValueWrapper JANDEX_CLASS_VALUE_WRAPPER = new ClassValueWrapper(); - - @Override - public ClassDetails wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - final Type classReference = rawValue.asClass(); - return buildingContext.getClassDetailsRegistry().resolveClassDetails( classReference.name().toString() ); - } -} diff --git a/src/main/java/org/hibernate/models/internal/jandex/DoubleValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/DoubleValueConverter.java similarity index 50% rename from src/main/java/org/hibernate/models/internal/jandex/DoubleValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jandex/DoubleValueConverter.java index 84ec13e..9d7d4c2 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/DoubleValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jandex/DoubleValueConverter.java @@ -7,7 +7,7 @@ package org.hibernate.models.internal.jandex; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationValue; @@ -16,12 +16,12 @@ * * @author Steve Ebersole */ -public class DoubleValueWrapper implements ValueWrapper { - public static final DoubleValueWrapper JANDEX_DOUBLE_VALUE_WRAPPER = new DoubleValueWrapper(); +public class DoubleValueConverter implements JandexValueConverter { + public static final DoubleValueConverter JANDEX_DOUBLE_VALUE_WRAPPER = new DoubleValueConverter(); @Override - public Double wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - return rawValue.asDouble(); + public Double convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + return jandexValue.asDouble(); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/DoubleValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/DoubleValueExtractor.java index 2f96e2e..1636fcf 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/DoubleValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/DoubleValueExtractor.java @@ -21,6 +21,6 @@ protected Double extractAndWrap( AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return DoubleValueWrapper.JANDEX_DOUBLE_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return DoubleValueConverter.JANDEX_DOUBLE_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/EnumValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/EnumValueConverter.java similarity index 58% rename from src/main/java/org/hibernate/models/internal/jandex/EnumValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jandex/EnumValueConverter.java index a0d2824..6b19b3b 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/EnumValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jandex/EnumValueConverter.java @@ -7,7 +7,7 @@ package org.hibernate.models.internal.jandex; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationValue; @@ -16,17 +16,17 @@ * * @author Steve Ebersole */ -public class EnumValueWrapper> implements ValueWrapper { +public class EnumValueConverter> implements JandexValueConverter { private final Class enumClass; - public EnumValueWrapper(Class enumClass) { + public EnumValueConverter(Class enumClass) { this.enumClass = enumClass; } @Override - public E wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - final String enumName = rawValue.asEnum(); + public E convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + final String enumName = jandexValue.asEnum(); return Enum.valueOf( enumClass, enumName ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/EnumValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/EnumValueExtractor.java index 89ef408..8ffd7bb 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/EnumValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/EnumValueExtractor.java @@ -14,19 +14,15 @@ * @author Steve Ebersole */ public class EnumValueExtractor> extends AbstractValueExtractor { - private final EnumValueWrapper wrapper; + private final EnumValueConverter wrapper; - public EnumValueExtractor(EnumValueWrapper wrapper) { + public EnumValueExtractor(EnumValueConverter wrapper) { this.wrapper = wrapper; } - public EnumValueExtractor(Class enumClass) { - this( new EnumValueWrapper<>( enumClass ) ); - } - @Override protected E extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return wrapper.wrap( jandexValue, buildingContext ); + return wrapper.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/LongValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/FloatValueConverter.java similarity index 50% rename from src/main/java/org/hibernate/models/internal/jandex/LongValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jandex/FloatValueConverter.java index ee3159c..f8bca5b 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/LongValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jandex/FloatValueConverter.java @@ -7,7 +7,7 @@ package org.hibernate.models.internal.jandex; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationValue; @@ -16,12 +16,12 @@ * * @author Steve Ebersole */ -public class LongValueWrapper implements ValueWrapper { - public static final LongValueWrapper JANDEX_LONG_VALUE_WRAPPER = new LongValueWrapper(); +public class FloatValueConverter implements JandexValueConverter { + public static final FloatValueConverter JANDEX_FLOAT_VALUE_WRAPPER = new FloatValueConverter(); @Override - public Long wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - return rawValue.asLong(); + public Float convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + return jandexValue.asFloat(); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/FloatValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/FloatValueExtractor.java index 3c70086..af87c04 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/FloatValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/FloatValueExtractor.java @@ -19,6 +19,6 @@ public class FloatValueExtractor extends AbstractValueExtractor { @Override protected Float extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return FloatValueWrapper.JANDEX_FLOAT_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return FloatValueConverter.JANDEX_FLOAT_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/IntegerValueConverter.java b/src/main/java/org/hibernate/models/internal/jandex/IntegerValueConverter.java new file mode 100644 index 0000000..d78c146 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jandex/IntegerValueConverter.java @@ -0,0 +1,27 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.internal.jandex; + +import org.hibernate.models.spi.SourceModelBuildingContext; +import org.hibernate.models.spi.JandexValueConverter; + +import org.jboss.jandex.AnnotationValue; + +/** + * Wraps AnnotationValue as a float + * + * @author Steve Ebersole + */ +public class IntegerValueConverter implements JandexValueConverter { + public static final IntegerValueConverter JANDEX_INTEGER_VALUE_WRAPPER = new IntegerValueConverter(); + + @Override + public Integer convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + return jandexValue.asInt(); + } +} diff --git a/src/main/java/org/hibernate/models/internal/jandex/IntegerValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/IntegerValueExtractor.java index 0019f79..9b3fdbc 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/IntegerValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/IntegerValueExtractor.java @@ -19,6 +19,6 @@ public class IntegerValueExtractor extends AbstractValueExtractor { @Override protected Integer extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return IntegerValueWrapper.JANDEX_INTEGER_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return IntegerValueConverter.JANDEX_INTEGER_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/JandexAnnotationUsage.java b/src/main/java/org/hibernate/models/internal/jandex/JandexAnnotationUsage.java deleted file mode 100644 index 60ee334..0000000 --- a/src/main/java/org/hibernate/models/internal/jandex/JandexAnnotationUsage.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jandex; - -import java.lang.annotation.Annotation; -import java.util.Map; - -import org.hibernate.models.internal.AnnotationProxy; -import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.MutableAnnotationUsage; -import org.hibernate.models.spi.SourceModelBuildingContext; - -import org.jboss.jandex.AnnotationInstance; - -/** - * AnnotationUsage implementation based on the Jandex AnnotationInstance - * - * @author Steve Ebersole - */ -public class JandexAnnotationUsage implements MutableAnnotationUsage { - private final AnnotationDescriptor annotationDescriptor; - - private final Map attributeValueMap; - - public JandexAnnotationUsage( - AnnotationInstance annotationInstance, - AnnotationDescriptor annotationDescriptor, - SourceModelBuildingContext processingContext) { - assert annotationInstance != null : "Jandex AnnotationInstance was null"; - assert annotationDescriptor != null : "AnnotationDescriptor was null - " + annotationInstance; - - this.annotationDescriptor = annotationDescriptor; - - this.attributeValueMap = AnnotationUsageBuilder.extractAttributeValues( - annotationInstance, - annotationDescriptor, - processingContext - ); - } - - @Override - public AnnotationDescriptor getAnnotationDescriptor() { - return annotationDescriptor; - } - - @Override - public A toAnnotation() { - return AnnotationProxy.makeProxy( annotationDescriptor, attributeValueMap ); - } - - @Override - public W findAttributeValue(String name) { - //noinspection unchecked - return (W) attributeValueMap.get( name ); - } - - @Override - public V setAttributeValue(String name, V value) { - // for set, we need to check up front - // NOTE : the call to #getAttribute throws the exception if it does not - annotationDescriptor.getAttribute( name ); - - //noinspection unchecked - return (V) ( (Map) attributeValueMap ).put( name, value ); - } - - @Override - public String toString() { - return "JandexAnnotationUsage(" + annotationDescriptor.getAnnotationType().getName() + ")"; - } -} diff --git a/src/main/java/org/hibernate/models/internal/jandex/JandexClassDetails.java b/src/main/java/org/hibernate/models/internal/jandex/JandexClassDetails.java index c4d2aa2..883bd71 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/JandexClassDetails.java +++ b/src/main/java/org/hibernate/models/internal/jandex/JandexClassDetails.java @@ -49,12 +49,12 @@ public class JandexClassDetails extends AbstractAnnotationTarget implements Clas private List methods; private List recordComponents; - public JandexClassDetails(ClassInfo classInfo, SourceModelBuildingContext buildingContext) { - super( buildingContext ); + public JandexClassDetails(ClassInfo classInfo, SourceModelBuildingContext modelContext) { + super( modelContext ); this.classInfo = classInfo; - this.superClass = determineSuperType( classInfo, buildingContext ); - this.implementedInterfaces = determineInterfaces( classInfo, buildingContext ); + this.superClass = determineSuperType( classInfo, modelContext ); + this.implementedInterfaces = determineInterfaces( classInfo, modelContext ); } private static ClassDetails determineSuperType( @@ -147,7 +147,7 @@ public ClassDetails getSuperClass() { @Override public TypeDetails getGenericSuperType() { if ( genericSuperType == null && classInfo.superClassType() != null ) { - genericSuperType = determineGenericSuperType( classInfo, getBuildingContext() ); + genericSuperType = determineGenericSuperType( classInfo, getModelContext() ); } return genericSuperType; } @@ -160,7 +160,7 @@ public List getImplementedInterfaces() { @Override public List getTypeParameters() { if ( typeParameters == null ) { - this.typeParameters = determineTypeParameters( classInfo, getBuildingContext() ); + this.typeParameters = determineTypeParameters( classInfo, getModelContext() ); } return typeParameters; } @@ -196,7 +196,7 @@ private List resolveFields() { final List fieldsInfoList = classInfo.fields(); final List result = new ArrayList<>( fieldsInfoList.size() ); for ( FieldInfo fieldInfo : fieldsInfoList ) { - result.add( new JandexFieldDetails( fieldInfo, this, getBuildingContext() ) ); + result.add( new JandexFieldDetails( fieldInfo, this, getModelContext() ) ); } return result; } @@ -218,7 +218,7 @@ private List resolveRecordComponents() { final List componentInfoList = classInfo.recordComponents(); final List result = arrayList( componentInfoList.size() ); for ( RecordComponentInfo componentInfo : componentInfoList ) { - result.add( new JandexRecordComponentDetails( componentInfo, this, getBuildingContext() ) ); + result.add( new JandexRecordComponentDetails( componentInfo, this, getModelContext() ) ); } return result; } @@ -238,7 +238,7 @@ private List resolveMethods() { if ( methodInfo.isConstructor() || "".equals( methodInfo.name() ) ) { continue; } - result.add( JandexBuilders.buildMethodDetails( methodInfo, this, getBuildingContext() ) ); + result.add( JandexBuilders.buildMethodDetails( methodInfo, this, getModelContext() ) ); } return result; } @@ -257,7 +257,7 @@ public Class toJavaClass() { throw new UnsupportedOperationException( "Not supported" ); } MODELS_CLASS_LOGGER.debugf( "Loading `%s` on to classloader from Jandex ClassDetails", getClassName() ); - javaClass = getBuildingContext().getClassLoading().classForName( getClassName() ); + javaClass = getModelContext().getClassLoading().classForName( getClassName() ); } //noinspection unchecked return (Class) javaClass; diff --git a/src/main/java/org/hibernate/models/internal/jandex/JandexFieldDetails.java b/src/main/java/org/hibernate/models/internal/jandex/JandexFieldDetails.java index 02b7abc..3236960 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/JandexFieldDetails.java +++ b/src/main/java/org/hibernate/models/internal/jandex/JandexFieldDetails.java @@ -6,14 +6,21 @@ */ package org.hibernate.models.internal.jandex; +import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.util.Collection; import java.util.Map; +import org.hibernate.models.IllegalCastException; +import org.hibernate.models.internal.AnnotationTargetSupport; +import org.hibernate.models.spi.AnnotationDescriptor; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.MethodDetails; +import org.hibernate.models.spi.MutableClassDetails; import org.hibernate.models.spi.MutableMemberDetails; +import org.hibernate.models.spi.RecordComponentDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; @@ -26,7 +33,8 @@ /** * @author Steve Ebersole */ -public class JandexFieldDetails extends AbstractAnnotationTarget implements FieldDetails, MutableMemberDetails { +public class JandexFieldDetails extends AbstractAnnotationTarget + implements FieldDetails, MutableMemberDetails, AnnotationTargetSupport { private final FieldInfo fieldInfo; private final TypeDetails type; private final ClassDetails declaringType; @@ -113,4 +121,34 @@ private Field resolveJavaMember() { public String toString() { return "JandexFieldDetails(" + getName() + ")"; } + + @Override + public FieldDetails asFieldDetails() { + return this; + } + + @Override + public MutableMemberDetails asMemberDetails() { + return this; + } + + @Override + public MethodDetails asMethodDetails() { + throw new IllegalCastException( "FieldDetails cannot be cast as MethodDetails" ); + } + + @Override + public RecordComponentDetails asRecordComponentDetails() { + throw new IllegalCastException( "FieldDetails cannot be cast as RecordComponentDetails" ); + } + + @Override + public AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "FieldDetails cannot be cast to an AnnotationDescriptor" ); + } + + @Override + public MutableClassDetails asClassDetails() { + throw new IllegalCastException( "FieldDetails cannot be cast to a ClassDetails" ); + } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/JandexMethodDetails.java b/src/main/java/org/hibernate/models/internal/jandex/JandexMethodDetails.java index 6177193..2d10ac6 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/JandexMethodDetails.java +++ b/src/main/java/org/hibernate/models/internal/jandex/JandexMethodDetails.java @@ -6,6 +6,7 @@ */ package org.hibernate.models.internal.jandex; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; @@ -13,11 +14,16 @@ import java.util.Locale; import java.util.Map; +import org.hibernate.models.IllegalCastException; +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.MutableClassDetails; import org.hibernate.models.spi.MutableMemberDetails; import org.hibernate.models.spi.ClassBasedTypeDetails; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.ClassDetailsRegistry; import org.hibernate.models.spi.MethodDetails; +import org.hibernate.models.spi.RecordComponentDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; import org.hibernate.models.spi.TypeDetailsHelper; @@ -198,4 +204,34 @@ public String toString() { methodInfo.toString() ); } + + @Override + public MethodDetails asMethodDetails() { + return this; + } + + @Override + public MutableMemberDetails asMemberDetails() { + return this; + } + + @Override + public FieldDetails asFieldDetails() { + throw new IllegalCastException( "MethodDetails cannot be cast as FieldDetails" ); + } + + @Override + public RecordComponentDetails asRecordComponentDetails() { + throw new IllegalCastException( "MethodDetails cannot be cast as RecordComponentDetails" ); + } + + @Override + public AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "MethodDetails cannot be cast to an AnnotationDescriptor" ); + } + + @Override + public MutableClassDetails asClassDetails() { + throw new IllegalCastException( "MethodDetails cannot be cast to a ClassDetails" ); + } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/NestedValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/JandexNestedValueConverter.java similarity index 58% rename from src/main/java/org/hibernate/models/internal/jandex/NestedValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jandex/JandexNestedValueConverter.java index 1f7ee09..2110625 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/NestedValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jandex/JandexNestedValueConverter.java @@ -9,9 +9,8 @@ import java.lang.annotation.Annotation; import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; @@ -21,18 +20,18 @@ * * @author Steve Ebersole */ -public class NestedValueWrapper implements ValueWrapper,AnnotationValue> { +public class JandexNestedValueConverter implements JandexValueConverter { private final AnnotationDescriptor descriptor; - public NestedValueWrapper(AnnotationDescriptor descriptor) { + public JandexNestedValueConverter(AnnotationDescriptor descriptor) { assert descriptor != null : "AnnotationDescriptor was null"; this.descriptor = descriptor; } @Override - public AnnotationUsage wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - final AnnotationInstance nested = rawValue.asNested(); + public A convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + final AnnotationInstance nested = jandexValue.asNested(); assert nested.target() == null; - return AnnotationUsageBuilder.makeUsage( nested, descriptor, buildingContext ); + return AnnotationUsageBuilder.makeUsage( nested, descriptor, modelContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/JandexNestedValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/JandexNestedValueExtractor.java new file mode 100644 index 0000000..df9dc47 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jandex/JandexNestedValueExtractor.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.internal.jandex; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationValue; + +/** + * @author Steve Ebersole + */ +public class JandexNestedValueExtractor extends AbstractValueExtractor { + private final JandexNestedValueConverter wrapper; + + public JandexNestedValueExtractor(JandexNestedValueConverter wrapper) { + this.wrapper = wrapper; + } + + @Override + protected A extractAndWrap( + AnnotationValue jandexValue, + SourceModelBuildingContext buildingContext) { + return wrapper.convert( jandexValue, buildingContext ); + } +} diff --git a/src/main/java/org/hibernate/models/internal/jandex/JandexRecordComponentDetails.java b/src/main/java/org/hibernate/models/internal/jandex/JandexRecordComponentDetails.java index 609a753..cc55e02 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/JandexRecordComponentDetails.java +++ b/src/main/java/org/hibernate/models/internal/jandex/JandexRecordComponentDetails.java @@ -6,10 +6,16 @@ */ package org.hibernate.models.internal.jandex; +import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.util.Collection; import java.util.Map; +import org.hibernate.models.IllegalCastException; +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.MethodDetails; +import org.hibernate.models.spi.MutableClassDetails; import org.hibernate.models.spi.MutableMemberDetails; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.RecordComponentDetails; @@ -91,4 +97,34 @@ public Member toJavaMember() { public String toString() { return "JandexFieldDetails(" + getName() + ")"; } + + @Override + public RecordComponentDetails asRecordComponentDetails() { + return this; + } + + @Override + public MutableMemberDetails asMemberDetails() { + return this; + } + + @Override + public FieldDetails asFieldDetails() { + throw new IllegalCastException( "RecordComponentDetails cannot be cast as FieldDetails" ); + } + + @Override + public MethodDetails asMethodDetails() { + throw new IllegalCastException( "RecordComponentDetails cannot be cast as FieldDetails" ); + } + + @Override + public AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "RecordComponentDetails cannot be cast to an AnnotationDescriptor" ); + } + + @Override + public MutableClassDetails asClassDetails() { + throw new IllegalCastException( "RecordComponentDetails cannot be cast to a ClassDetails" ); + } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/JandexValueHelper.java b/src/main/java/org/hibernate/models/internal/jandex/JandexValueHelper.java new file mode 100644 index 0000000..9210a26 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jandex/JandexValueHelper.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.internal.jandex; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +/** + * @author Steve Ebersole + */ +public class JandexValueHelper { + public static V extractValue( + AnnotationInstance usage, + AnnotationDescriptor descriptor, + String attributeName, + SourceModelBuildingContext modelContext) { + final AttributeDescriptor attribute = descriptor.getAttribute( attributeName ); + return extractValue( usage, attribute, modelContext ); + } + + public static V extractValue( + AnnotationInstance usage, + AttributeDescriptor attributeDescriptor, + SourceModelBuildingContext modelContext) { + return attributeDescriptor + .getTypeDescriptor() + .createJandexValueExtractor( modelContext ) + .extractValue( usage, attributeDescriptor, modelContext ); +// final AnnotationValue value = usage.value( attributeDescriptor.getName() ); +// if ( value == null ) { +// //noinspection unchecked +// return (V) attributeDescriptor.getAttributeMethod().getDefaultValue(); +// } +// +// return attributeDescriptor +// .getTypeDescriptor() +// .createValueConverter( modelContext ) +// .convert( value, modelContext ); + } + + public static V extractOptionalValue( + AnnotationInstance usage, + AnnotationDescriptor descriptor, + String attributeName, + SourceModelBuildingContext modelContext) { + return extractOptionalValue( usage, descriptor.getAttribute( attributeName ), modelContext ); + } + + public static V extractOptionalValue( + AnnotationInstance usage, + AttributeDescriptor attributeDescriptor, + SourceModelBuildingContext modelContext) { + final AnnotationValue value = usage.value( attributeDescriptor.getName() ); + if ( value == null ) { + //noinspection unchecked + return (V) attributeDescriptor.getAttributeMethod().getDefaultValue(); + } + return attributeDescriptor.getTypeDescriptor().createJandexValueConverter( modelContext ).convert( value, modelContext ); + } +} diff --git a/src/main/java/org/hibernate/models/internal/jandex/FloatValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/LongValueConverter.java similarity index 51% rename from src/main/java/org/hibernate/models/internal/jandex/FloatValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jandex/LongValueConverter.java index 8546ace..1300261 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/FloatValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jandex/LongValueConverter.java @@ -7,7 +7,7 @@ package org.hibernate.models.internal.jandex; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationValue; @@ -16,12 +16,12 @@ * * @author Steve Ebersole */ -public class FloatValueWrapper implements ValueWrapper { - public static final FloatValueWrapper JANDEX_FLOAT_VALUE_WRAPPER = new FloatValueWrapper(); +public class LongValueConverter implements JandexValueConverter { + public static final LongValueConverter JANDEX_LONG_VALUE_WRAPPER = new LongValueConverter(); @Override - public Float wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - return rawValue.asFloat(); + public Long convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + return jandexValue.asLong(); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/LongValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/LongValueExtractor.java index 72ec23c..32cae3e 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/LongValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/LongValueExtractor.java @@ -19,6 +19,6 @@ public class LongValueExtractor extends AbstractValueExtractor { @Override protected Long extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return LongValueWrapper.JANDEX_LONG_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return LongValueConverter.JANDEX_LONG_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/NestedValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/NestedValueExtractor.java deleted file mode 100644 index d2c2ea0..0000000 --- a/src/main/java/org/hibernate/models/internal/jandex/NestedValueExtractor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jandex; - -import java.lang.annotation.Annotation; - -import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationUsage; -import org.hibernate.models.spi.SourceModelBuildingContext; - -import org.jboss.jandex.AnnotationValue; - -/** - * @author Steve Ebersole - */ -public class NestedValueExtractor extends AbstractValueExtractor> { - private final NestedValueWrapper wrapper; - - public NestedValueExtractor(NestedValueWrapper wrapper) { - this.wrapper = wrapper; - } - - public NestedValueExtractor(AnnotationDescriptor descriptor) { - this( new NestedValueWrapper<>( descriptor ) ); - } - - @Override - protected AnnotationUsage extractAndWrap( - AnnotationValue jandexValue, - SourceModelBuildingContext buildingContext) { - return wrapper.wrap( jandexValue, buildingContext ); - } -} diff --git a/src/main/java/org/hibernate/models/internal/jandex/IntegerValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/ShortValueConverter.java similarity index 50% rename from src/main/java/org/hibernate/models/internal/jandex/IntegerValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jandex/ShortValueConverter.java index 240fc49..c29e32b 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/IntegerValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jandex/ShortValueConverter.java @@ -7,7 +7,7 @@ package org.hibernate.models.internal.jandex; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationValue; @@ -16,12 +16,12 @@ * * @author Steve Ebersole */ -public class IntegerValueWrapper implements ValueWrapper { - public static final IntegerValueWrapper JANDEX_INTEGER_VALUE_WRAPPER = new IntegerValueWrapper(); +public class ShortValueConverter implements JandexValueConverter { + public static final ShortValueConverter JANDEX_SHORT_VALUE_WRAPPER = new ShortValueConverter(); @Override - public Integer wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - return rawValue.asInt(); + public Short convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + return jandexValue.asShort(); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/ShortValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/ShortValueExtractor.java index d0ea9f5..7cefe00 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/ShortValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/ShortValueExtractor.java @@ -18,7 +18,7 @@ public class ShortValueExtractor extends AbstractValueExtractor { protected Short extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return ShortValueWrapper.JANDEX_SHORT_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return ShortValueConverter.JANDEX_SHORT_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/ShortValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/StringValueConverter.java similarity index 50% rename from src/main/java/org/hibernate/models/internal/jandex/ShortValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jandex/StringValueConverter.java index 25951fb..6201072 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/ShortValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jandex/StringValueConverter.java @@ -7,7 +7,7 @@ package org.hibernate.models.internal.jandex; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; +import org.hibernate.models.spi.JandexValueConverter; import org.jboss.jandex.AnnotationValue; @@ -16,12 +16,12 @@ * * @author Steve Ebersole */ -public class ShortValueWrapper implements ValueWrapper { - public static final ShortValueWrapper JANDEX_SHORT_VALUE_WRAPPER = new ShortValueWrapper(); +public class StringValueConverter implements JandexValueConverter { + public static final StringValueConverter JANDEX_STRING_VALUE_WRAPPER = new StringValueConverter(); @Override - public Short wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - return rawValue.asShort(); + public String convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext) { + assert jandexValue != null; + return jandexValue.asString(); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/StringValueExtractor.java b/src/main/java/org/hibernate/models/internal/jandex/StringValueExtractor.java index 2474d3f..cb9303f 100644 --- a/src/main/java/org/hibernate/models/internal/jandex/StringValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jandex/StringValueExtractor.java @@ -19,6 +19,6 @@ public class StringValueExtractor extends AbstractValueExtractor { @Override protected String extractAndWrap(AnnotationValue jandexValue, SourceModelBuildingContext buildingContext) { assert jandexValue != null; - return StringValueWrapper.JANDEX_STRING_VALUE_WRAPPER.wrap( jandexValue, buildingContext ); + return StringValueConverter.JANDEX_STRING_VALUE_WRAPPER.convert( jandexValue, buildingContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jandex/StringValueWrapper.java b/src/main/java/org/hibernate/models/internal/jandex/StringValueWrapper.java deleted file mode 100644 index 5608cff..0000000 --- a/src/main/java/org/hibernate/models/internal/jandex/StringValueWrapper.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jandex; - -import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; - -import org.jboss.jandex.AnnotationValue; - -/** - * Wraps AnnotationValue as a float - * - * @author Steve Ebersole - */ -public class StringValueWrapper implements ValueWrapper { - public static final StringValueWrapper JANDEX_STRING_VALUE_WRAPPER = new StringValueWrapper(); - - @Override - public String wrap(AnnotationValue rawValue, SourceModelBuildingContext buildingContext) { - assert rawValue != null; - return rawValue.asString(); - } -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/AbstractAnnotationTarget.java b/src/main/java/org/hibernate/models/internal/jdk/AbstractAnnotationTarget.java deleted file mode 100644 index 0d92b57..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/AbstractAnnotationTarget.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import java.lang.annotation.Annotation; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Supplier; - -import org.hibernate.models.internal.AnnotationTargetSupport; -import org.hibernate.models.spi.AnnotationUsage; -import org.hibernate.models.spi.SourceModelBuildingContext; - -/** - * AnnotationTarget where we know the annotations up front, but - * want to delay processing them until (unless!) they are needed - * - * @author Steve Ebersole - */ -public abstract class AbstractAnnotationTarget implements AnnotationTargetSupport { - private final Supplier annotationSupplier; - private final SourceModelBuildingContext buildingContext; - - private Map, AnnotationUsage> usagesMap; - - public AbstractAnnotationTarget( - Supplier annotationSupplier, - SourceModelBuildingContext buildingContext) { - this.annotationSupplier = annotationSupplier; - this.buildingContext = buildingContext; - } - - @Override - public SourceModelBuildingContext getBuildingContext() { - return buildingContext; - } - - @Override - public Map, AnnotationUsage> getUsageMap() { - if ( usagesMap == null ) { - usagesMap = buildUsagesMap(); - } - return usagesMap; - } - - private Map, AnnotationUsage> buildUsagesMap() { - final Map, AnnotationUsage> result = new HashMap<>(); - AnnotationUsageBuilder.processAnnotations( - annotationSupplier.get(), - result::put, - buildingContext - ); - return result; - } - - @Override - public void clearAnnotationUsages() { - getUsageMap().clear(); - } - - @Override - public void addAnnotationUsage(AnnotationUsage annotationUsage) { - assert annotationUsage.getAnnotationDescriptor().getAllowableTargets().contains( getKind() ); - getUsageMap().put( annotationUsage.getAnnotationType(), annotationUsage ); - } -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/AbstractJdkAnnotationTarget.java b/src/main/java/org/hibernate/models/internal/jdk/AbstractJdkAnnotationTarget.java new file mode 100644 index 0000000..68eec9f --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jdk/AbstractJdkAnnotationTarget.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.internal.jdk; + +import java.lang.annotation.Annotation; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +import org.hibernate.models.internal.AnnotationTargetSupport; +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.SourceModelBuildingContext; + +/** + * AnnotationTarget where we know the annotations up front, but + * want to delay processing them until (unless!) they are needed + * + * @author Steve Ebersole + */ +public abstract class AbstractJdkAnnotationTarget implements AnnotationTargetSupport { + private final Supplier annotationSupplier; + private final SourceModelBuildingContext modelContext; + + private Map, ? extends Annotation> usagesMap; + + public AbstractJdkAnnotationTarget( + Supplier annotationSupplier, + SourceModelBuildingContext modelContext) { + this.annotationSupplier = annotationSupplier; + this.modelContext = modelContext; + } + + public SourceModelBuildingContext getModelContext() { + return modelContext; + } + + @Override + public Map, ? extends Annotation> getUsageMap() { + if ( usagesMap == null ) { + usagesMap = buildUsagesMap(); + } + return usagesMap; + } + + private Map, ? extends Annotation> buildUsagesMap() { + final Map, Annotation> result = new HashMap<>(); + for ( Annotation annotation : annotationSupplier.get() ) { + //noinspection unchecked + final AnnotationDescriptor descriptor = (AnnotationDescriptor) modelContext + .getAnnotationDescriptorRegistry() + .getDescriptor( annotation.annotationType() ); + result.put( annotation.annotationType(), descriptor.createUsage( annotation, modelContext ) ); + } + return result; + } + + @Override + public void clearAnnotationUsages() { + getUsageMap().clear(); + } + + @Override + public void addAnnotationUsage(X annotationUsage) { + //noinspection unchecked,rawtypes + ( (Map) getUsageMap() ).put( annotationUsage.annotationType(), annotationUsage ); + } +} diff --git a/src/main/java/org/hibernate/models/internal/jdk/AbstractValueExtractor.java b/src/main/java/org/hibernate/models/internal/jdk/AbstractJdkValueExtractor.java similarity index 68% rename from src/main/java/org/hibernate/models/internal/jdk/AbstractValueExtractor.java rename to src/main/java/org/hibernate/models/internal/jdk/AbstractJdkValueExtractor.java index 1399937..e7316cd 100644 --- a/src/main/java/org/hibernate/models/internal/jdk/AbstractValueExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jdk/AbstractJdkValueExtractor.java @@ -12,41 +12,23 @@ import org.hibernate.models.AnnotationAccessException; import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationTarget; import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.JdkValueExtractor; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; /** * @author Steve Ebersole */ -public abstract class AbstractValueExtractor implements ValueExtractor { - - protected abstract W wrap( - R rawValue, - AttributeDescriptor attributeDescriptor, - SourceModelBuildingContext buildingContext); - - @Override - public W extractValue( - Annotation annotation, - String attributeName, - SourceModelBuildingContext buildingContext) { - final AnnotationDescriptor annDescriptor = buildingContext - .getAnnotationDescriptorRegistry() - .getDescriptor( annotation.annotationType() ); - return extractValue( annotation, annDescriptor.getAttribute( attributeName ), buildingContext ); - } - +public abstract class AbstractJdkValueExtractor implements JdkValueExtractor { @Override - public W extractValue( - Annotation annotation, - AttributeDescriptor attributeDescriptor, - SourceModelBuildingContext buildingContext) { + public V extractValue( + A usage, + AttributeDescriptor attributeDescriptor, + SourceModelBuildingContext modelContext) { try { //noinspection unchecked - final R rawValue = (R) attributeDescriptor.getAttributeMethod().invoke( annotation ); - return wrap( rawValue, attributeDescriptor, buildingContext ); + final V rawValue = (V) attributeDescriptor.getAttributeMethod().invoke( usage ); + return wrap( rawValue, attributeDescriptor, modelContext ); } catch (IllegalAccessException | InvocationTargetException e) { throw new AnnotationAccessException( @@ -54,10 +36,26 @@ public W extractValue( Locale.ROOT, "Unable to extract attribute value [%s] from annotation [%s]", attributeDescriptor.getName(), - annotation + usage ), e ); } } + + @Override + public V extractValue( + Annotation annotation, + String attributeName, + SourceModelBuildingContext buildingContext) { + final AnnotationDescriptor annDescriptor = buildingContext + .getAnnotationDescriptorRegistry() + .getDescriptor( annotation.annotationType() ); + return extractValue( annotation, annDescriptor.getAttribute( attributeName ), buildingContext ); + } + + protected abstract V wrap( + V rawValue, + AttributeDescriptor attributeDescriptor, + SourceModelBuildingContext buildingContext); } diff --git a/src/main/java/org/hibernate/models/internal/jdk/AnnotationDescriptorImpl.java b/src/main/java/org/hibernate/models/internal/jdk/AnnotationDescriptorImpl.java deleted file mode 100644 index e68f377..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/AnnotationDescriptorImpl.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import java.lang.annotation.Annotation; -import java.util.EnumSet; -import java.util.List; - -import org.hibernate.models.IllegalCastException; -import org.hibernate.models.internal.AnnotationHelper; -import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AttributeDescriptor; -import org.hibernate.models.spi.MutableClassDetails; -import org.hibernate.models.spi.MutableMemberDetails; -import org.hibernate.models.spi.SourceModelBuildingContext; - -import static org.hibernate.models.internal.jdk.JdkBuilders.extractAttributeDescriptors; - -/** - * AnnotationDescriptor built from the Annotation's Class reference - * - * @author Steve Ebersole - */ -public class AnnotationDescriptorImpl extends AbstractAnnotationTarget implements AnnotationDescriptor { - private final Class annotationType; - private final EnumSet allowableTargets; - - private final boolean inherited; - private final AnnotationDescriptor repeatableContainer; - - private final List> attributeDescriptors; - - public AnnotationDescriptorImpl( - Class annotationType, - SourceModelBuildingContext context) { - this( annotationType, null, context ); - } - - public AnnotationDescriptorImpl( - Class annotationType, - AnnotationDescriptor repeatableContainer, - SourceModelBuildingContext context) { - super( annotationType::getAnnotations, context ); - - this.annotationType = annotationType; - this.repeatableContainer = repeatableContainer; - - this.inherited = AnnotationHelper.isInherited( annotationType ); - this.allowableTargets = AnnotationHelper.extractTargets( annotationType ); - - this.attributeDescriptors = extractAttributeDescriptors( this, annotationType ); - } - - @Override - public Class getAnnotationType() { - return annotationType; - } - - @Override - public EnumSet getAllowableTargets() { - return allowableTargets; - } - - @Override - public boolean isInherited() { - return inherited; - } - - @Override - public AnnotationDescriptor getRepeatableContainer() { - return repeatableContainer; - } - - @Override - public List> getAttributes() { - return attributeDescriptors; - } - - @Override - public String getName() { - return annotationType.getName(); - } - - @Override - public MutableClassDetails asClassDetails() { - throw new IllegalCastException( "AnnotationDescriptor cannot be cast to ClassDetails" ); - } - - @Override - public MutableMemberDetails asMemberDetails() { - throw new IllegalCastException( "AnnotationDescriptor cannot be cast to MemberDetails" ); - } -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/AnnotationDescriptorOrmImpl.java b/src/main/java/org/hibernate/models/internal/jdk/AnnotationDescriptorOrmImpl.java deleted file mode 100644 index 83cfea0..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/AnnotationDescriptorOrmImpl.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import java.lang.annotation.Annotation; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; -import java.util.function.Consumer; - -import org.hibernate.models.UnknownAnnotationAttributeException; -import org.hibernate.models.internal.AnnotationHelper; -import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationUsage; -import org.hibernate.models.spi.AttributeDescriptor; - -import static org.hibernate.models.internal.jdk.JdkBuilders.extractAttributeDescriptors; - -/** - * AnnotationDescriptor for cases where we do not want to deal with ANNOTATION_TYPE annotations, - * most notably, Jakarta and Hibernate annotations - * - * @author Steve Ebersole - */ -public class AnnotationDescriptorOrmImpl implements AnnotationDescriptor { - private final Class annotationType; - private final EnumSet allowableTargets; - - private final boolean inherited; - private final AnnotationDescriptor repeatableContainer; - - private final List> attributeDescriptors; - - public AnnotationDescriptorOrmImpl(Class annotationType, AnnotationDescriptor repeatableContainer) { - this.annotationType = annotationType; - this.repeatableContainer = repeatableContainer; - - this.inherited = AnnotationHelper.isInherited( annotationType ); - this.allowableTargets = AnnotationHelper.extractTargets( annotationType ); - - this.attributeDescriptors = extractAttributeDescriptors( this, annotationType ); - } - - @Override - public Class getAnnotationType() { - return annotationType; - } - - @Override - public EnumSet getAllowableTargets() { - return allowableTargets; - } - - @Override - public boolean isInherited() { - return inherited; - } - - @Override - public AnnotationDescriptor getRepeatableContainer() { - return repeatableContainer; - } - - @Override - public List> getAttributes() { - return attributeDescriptors; - } - - @Override - public String getName() { - return annotationType.getName(); - } - - @Override - public Collection> getAllAnnotationUsages() { - return Collections.emptyList(); - } - - @Override - public boolean hasAnnotationUsage(Class type) { - return false; - } - - @Override - public boolean hasRepeatableAnnotationUsage(Class type) { - return false; - } - - @Override - public AnnotationUsage getAnnotationUsage(AnnotationDescriptor descriptor) { - // there are none - return null; - } - - @Override - public AnnotationUsage getAnnotationUsage(Class type) { - // there are none - return null; - } - - @Override - public AnnotationUsage locateAnnotationUsage(Class type) { - // there are none - return null; - } - - @Override - public List> getRepeatedAnnotationUsages(AnnotationDescriptor type) { - // there are none - return null; - } - - @Override - public List> getRepeatedAnnotationUsages(Class type) { - // there are none - return null; - } - - @Override - public void forEachAnnotationUsage( - AnnotationDescriptor type, - Consumer> consumer) { - // there are none - } - - @Override - public void forEachAnnotationUsage(Class type, Consumer> consumer) { - // there are none - } - - public List> getMetaAnnotated(Class metaAnnotationType) { - // there are none - return Collections.emptyList(); - } - - @Override - public AnnotationUsage getNamedAnnotationUsage( - AnnotationDescriptor type, - String matchName, - String attributeToMatch) { - // there are none - return null; - } - - @Override - public AnnotationUsage getNamedAnnotationUsage( - Class type, - String matchName, - String attributeToMatch) { - // there are none - return null; - } - - @Override - public String toString() { - return "AnnotationDescriptor(" + annotationType + ")"; - } -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/AnnotationUsageBuilder.java b/src/main/java/org/hibernate/models/internal/jdk/AnnotationUsageBuilder.java deleted file mode 100644 index 27a6077..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/AnnotationUsageBuilder.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BiConsumer; - -import org.hibernate.models.internal.util.CollectionHelper; -import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.spi.AnnotationUsage; -import org.hibernate.models.spi.AttributeDescriptor; -import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueExtractor; - -/** - * Helper for building {@link AnnotationUsage} instances - * - * @author Steve Ebersole - */ -public class AnnotationUsageBuilder { - /** - * Process annotations creating usage instances passed back to the consumer - */ - public static void processAnnotations( - Annotation[] annotations, - BiConsumer, AnnotationUsage> consumer, - SourceModelBuildingContext buildingContext) { - final AnnotationDescriptorRegistry annotationDescriptorRegistry = buildingContext.getAnnotationDescriptorRegistry(); - - for ( int i = 0; i < annotations.length; i++ ) { - final Annotation annotation = annotations[ i ]; - final Class annotationType = annotation.annotationType(); - - // skip a few well-know ones that are irrelevant - if ( annotationType == Repeatable.class - || annotationType == Target.class - || annotationType == Retention.class - || annotationType == Documented.class ) { - continue; - } - - //noinspection rawtypes - final AnnotationDescriptor annotationDescriptor = annotationDescriptorRegistry.getDescriptor( annotationType ); - //noinspection unchecked - final AnnotationUsage usage = makeUsage( - annotation, - annotationDescriptor, - buildingContext - ); - consumer.accept( annotationType, usage ); - } - } - - public static AnnotationUsage makeUsage( - A annotation, - AnnotationDescriptor annotationDescriptor, - SourceModelBuildingContext buildingContext) { - //noinspection unchecked,rawtypes - return new JdkAnnotationUsage( annotation, annotationDescriptor, buildingContext ); - } - - /** - * Extracts values from an annotation - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Map extractAttributeValues( - A annotation, - AnnotationDescriptor annotationDescriptor, - SourceModelBuildingContext buildingContext) { - if ( CollectionHelper.isEmpty( annotationDescriptor.getAttributes() ) ) { - return Collections.emptyMap(); - } - - final ConcurrentHashMap valueMap = new ConcurrentHashMap<>(); - for ( int i = 0; i < annotationDescriptor.getAttributes().size(); i++ ) { - final AttributeDescriptor attributeDescriptor = annotationDescriptor.getAttributes().get( i ); - final ValueExtractor valueExtractor = attributeDescriptor - .getTypeDescriptor() - .createJdkExtractor( buildingContext ); - final Object value = valueExtractor.extractValue( annotation, attributeDescriptor, buildingContext ); - valueMap.put( attributeDescriptor.getName(), value ); - } - return valueMap; - } - - private AnnotationUsageBuilder() { - // disallow direct instantiation - } -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/ArrayValueExtractor.java b/src/main/java/org/hibernate/models/internal/jdk/ArrayValueExtractor.java deleted file mode 100644 index 3ccc698..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/ArrayValueExtractor.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import java.util.List; - -import org.hibernate.models.spi.AnnotationTarget; -import org.hibernate.models.spi.AttributeDescriptor; -import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; - -/** - * @author Steve Ebersole - */ -public class ArrayValueExtractor extends AbstractValueExtractor,R[]> { - private final ValueWrapper,R[]> wrapper; - - public ArrayValueExtractor(ValueWrapper, R[]> wrapper) { - this.wrapper = wrapper; - } - - @Override - protected List wrap( - R[] rawValues, - AttributeDescriptor> attributeDescriptor, - SourceModelBuildingContext buildingContext) { - return wrapper.wrap( rawValues, buildingContext ); - } -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/ArrayValueWrapper.java b/src/main/java/org/hibernate/models/internal/jdk/ArrayValueWrapper.java deleted file mode 100644 index d949da7..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/ArrayValueWrapper.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.hibernate.models.internal.util.CollectionHelper; -import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; - -/** - * @author Steve Ebersole - */ -public class ArrayValueWrapper implements ValueWrapper,R[]> { - private final ValueWrapper elementWrapper; - - public ArrayValueWrapper(ValueWrapper elementWrapper) { - this.elementWrapper = elementWrapper; - } - - @Override - public List wrap(R[] rawValues, SourceModelBuildingContext buildingContext) { - final List result = new ArrayList<>( rawValues.length ); - for ( final R rawValue : rawValues ) { - result.add( elementWrapper.wrap( rawValue, buildingContext ) ); - } - return result; - } -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/ClassValueExtractor.java b/src/main/java/org/hibernate/models/internal/jdk/ClassValueExtractor.java deleted file mode 100644 index 965a2ad..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/ClassValueExtractor.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import org.hibernate.models.spi.AnnotationTarget; -import org.hibernate.models.spi.AttributeDescriptor; -import org.hibernate.models.spi.ClassDetails; -import org.hibernate.models.spi.SourceModelBuildingContext; - -import static org.hibernate.models.internal.jdk.ClassValueWrapper.JDK_CLASS_VALUE_WRAPPER; - -/** - * @author Steve Ebersole - */ -public class ClassValueExtractor extends AbstractValueExtractor> { - public static final ClassValueExtractor JDK_CLASS_EXTRACTOR = new ClassValueExtractor(); - - @Override - protected ClassDetails wrap( - Class rawValue, - AttributeDescriptor attributeDescriptor, - SourceModelBuildingContext buildingContext) { - return JDK_CLASS_VALUE_WRAPPER.wrap( rawValue, buildingContext ); - } - -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/ClassValueWrapper.java b/src/main/java/org/hibernate/models/internal/jdk/ClassValueWrapper.java deleted file mode 100644 index a4a9486..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/ClassValueWrapper.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import org.hibernate.models.spi.ClassDetails; -import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; - -/** - * @author Steve Ebersole - */ -public class ClassValueWrapper implements ValueWrapper> { - public static final ClassValueWrapper JDK_CLASS_VALUE_WRAPPER = new ClassValueWrapper(); - - @Override - public ClassDetails wrap(Class rawValue, SourceModelBuildingContext buildingContext) { - return buildingContext.getClassDetailsRegistry().resolveClassDetails( rawValue.getName() ); - } -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/JdkAnnotationUsage.java b/src/main/java/org/hibernate/models/internal/jdk/JdkAnnotationUsage.java deleted file mode 100644 index a7a57af..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/JdkAnnotationUsage.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import java.lang.annotation.Annotation; -import java.util.Map; - -import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.MutableAnnotationUsage; -import org.hibernate.models.spi.SourceModelBuildingContext; - -/** - * @author Steve Ebersole - */ -public class JdkAnnotationUsage implements MutableAnnotationUsage { - private final A annotation; - private final AnnotationDescriptor annotationDescriptor; - - private final Map valueMap; - - public JdkAnnotationUsage( - A annotation, - AnnotationDescriptor annotationDescriptor, - SourceModelBuildingContext buildingContext) { - this.annotation = annotation; - this.annotationDescriptor = annotationDescriptor; - - this.valueMap = AnnotationUsageBuilder.extractAttributeValues( annotation, annotationDescriptor, buildingContext ); - } - - @Override - public AnnotationDescriptor getAnnotationDescriptor() { - return annotationDescriptor; - } - - @Override - public A toAnnotation() { - return annotation; - } - - @Override - public W findAttributeValue(String name) { - //noinspection unchecked - return (W) valueMap.get( name ); - } - - @Override - public V setAttributeValue(String name, V value) { - // for set, we need to check up front - // NOTE : the call to #getAttribute throws the exception if it does not - // todo : do we want to add a distinction for a checked versus unchecked set? - // - i.e. setAttributeValueSafely - annotationDescriptor.getAttribute( name ); - - //noinspection unchecked - return (V) ( (Map) valueMap ).put( name, value ); - } - - @Override - public String toString() { - return "JdkAnnotationUsage(" + annotationDescriptor.getAnnotationType().getName() + ")"; - } -} diff --git a/src/main/java/org/hibernate/models/internal/jdk/JdkArrayValueConverter.java b/src/main/java/org/hibernate/models/internal/jdk/JdkArrayValueConverter.java new file mode 100644 index 0000000..70569f7 --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkArrayValueConverter.java @@ -0,0 +1,32 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.internal.jdk; + +import org.hibernate.models.spi.JdkValueConverter; +import org.hibernate.models.spi.SourceModelBuildingContext; +import org.hibernate.models.spi.ValueTypeDescriptor; + +/** + * @author Steve Ebersole + */ +public class JdkArrayValueConverter implements JdkValueConverter { + private final ValueTypeDescriptor elementTypeDescriptor; + + public JdkArrayValueConverter(ValueTypeDescriptor elementTypeDescriptor) { + this.elementTypeDescriptor = elementTypeDescriptor; + } + + @Override + public V[] convert(V[] rawValue, SourceModelBuildingContext modelContext) { + final V[] result = elementTypeDescriptor.makeArray( rawValue.length, modelContext ); + final JdkValueConverter elementWrapper = elementTypeDescriptor.createJdkValueConverter( modelContext ); + for ( int i = 0; i < rawValue.length; i++ ) { + result[i] = elementWrapper.convert( rawValue[i], modelContext ); + } + return result; + } +} diff --git a/src/main/java/org/hibernate/models/internal/jdk/JdkArrayValueExtractor.java b/src/main/java/org/hibernate/models/internal/jdk/JdkArrayValueExtractor.java new file mode 100644 index 0000000..f7ff41c --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkArrayValueExtractor.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.internal.jdk; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.JdkValueConverter; +import org.hibernate.models.spi.SourceModelBuildingContext; + +/** + * @author Steve Ebersole + */ +public class JdkArrayValueExtractor extends AbstractJdkValueExtractor { + private final JdkValueConverter converter; + + public JdkArrayValueExtractor(JdkValueConverter converter) { + this.converter = converter; + } + + @Override + public V[] extractValue( + A usage, + AttributeDescriptor attributeDescriptor, + SourceModelBuildingContext modelContext) { + return super.extractValue( usage, attributeDescriptor, modelContext ); + } + + @Override + public V[] extractValue(Annotation annotation, String attributeName, SourceModelBuildingContext buildingContext) { + return super.extractValue( annotation, attributeName, buildingContext ); + } + + @Override + protected V[] wrap( + V[] rawValue, + AttributeDescriptor attributeDescriptor, + SourceModelBuildingContext buildingContext) { + return converter.convert( rawValue, buildingContext ); + } +} diff --git a/src/main/java/org/hibernate/models/internal/jdk/JdkBuilders.java b/src/main/java/org/hibernate/models/internal/jdk/JdkBuilders.java index 2a3b883..0da114e 100644 --- a/src/main/java/org/hibernate/models/internal/jdk/JdkBuilders.java +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkBuilders.java @@ -10,24 +10,20 @@ import java.lang.annotation.Repeatable; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; import org.hibernate.models.internal.AnnotationDescriptorRegistryStandard; import org.hibernate.models.internal.ModifierUtils; import org.hibernate.models.internal.PrimitiveKind; -import org.hibernate.models.internal.TypeDescriptors; +import org.hibernate.models.internal.StandardAnnotationDescriptor; import org.hibernate.models.internal.util.StringHelper; import org.hibernate.models.spi.AnnotationDescriptor; import org.hibernate.models.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.spi.AttributeDescriptor; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.ClassDetailsBuilder; import org.hibernate.models.spi.ClassDetailsRegistry; import org.hibernate.models.spi.MethodDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; -import org.hibernate.models.spi.ValueTypeDescriptor; /** * ClassDetailsBuilder implementation based on {@link Class} @@ -186,52 +182,35 @@ public static boolean isVoid(Class type) { return type == void.class || type == Void.class; } - public static AnnotationDescriptorOrmImpl buildAnnotationDescriptor( + public static AnnotationDescriptor buildAnnotationDescriptor( Class annotationType, - AnnotationDescriptorRegistry descriptorRegistry) { + SourceModelBuildingContext modelContext) { return buildAnnotationDescriptor( annotationType, - resolveRepeatableContainerDescriptor( annotationType, descriptorRegistry ) + resolveRepeatableContainerDescriptor( annotationType, modelContext ), + modelContext ); } public static AnnotationDescriptor resolveRepeatableContainerDescriptor( Class annotationType, - AnnotationDescriptorRegistry descriptorRegistry) { + SourceModelBuildingContext modelContext) { final Repeatable repeatableAnnotation = annotationType.getAnnotation( Repeatable.class ); if ( repeatableAnnotation == null ) { return null; } + final AnnotationDescriptorRegistry descriptorRegistry = modelContext.getAnnotationDescriptorRegistry(); //noinspection unchecked final AnnotationDescriptor containerDescriptor = (AnnotationDescriptor) descriptorRegistry.getDescriptor( repeatableAnnotation.value() ); ( (AnnotationDescriptorRegistryStandard) descriptorRegistry ).register( containerDescriptor ); return containerDescriptor; } - public static AnnotationDescriptorOrmImpl buildAnnotationDescriptor( + public static AnnotationDescriptor buildAnnotationDescriptor( Class annotationType, - AnnotationDescriptor repeatableContainer) { - return new AnnotationDescriptorOrmImpl<>( annotationType, repeatableContainer ); + AnnotationDescriptor repeatableContainer, + SourceModelBuildingContext modelContext) { + return new StandardAnnotationDescriptor<>( annotationType, repeatableContainer, modelContext ); } - public static List> extractAttributeDescriptors( - AnnotationDescriptor annotationDescriptor, - Class annotationType) { - final Method[] methods = annotationType.getDeclaredMethods(); - final List> attributeDescriptors = new ArrayList<>( methods.length ); - for ( Method method : methods ) { - attributeDescriptors.add( createAttributeDescriptor( annotationDescriptor, method ) ); - } - return attributeDescriptors; - } - - private static AttributeDescriptor createAttributeDescriptor( - AnnotationDescriptor annotationDescriptor, - Method method) { - //noinspection unchecked - final Class attributeType = (Class) method.getReturnType(); - - final ValueTypeDescriptor typeDescriptor = TypeDescriptors.resolveTypeDescriptor( attributeType ); - return typeDescriptor.createAttributeDescriptor( annotationDescriptor, method.getName() ); - } } diff --git a/src/main/java/org/hibernate/models/internal/jdk/JdkClassDetails.java b/src/main/java/org/hibernate/models/internal/jdk/JdkClassDetails.java index 55e2eca..71542c3 100644 --- a/src/main/java/org/hibernate/models/internal/jdk/JdkClassDetails.java +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkClassDetails.java @@ -35,7 +35,7 @@ * * @author Steve Ebersole */ -public class JdkClassDetails extends AbstractAnnotationTarget implements ClassDetailsSupport { +public class JdkClassDetails extends AbstractJdkAnnotationTarget implements ClassDetailsSupport { private final String name; private final Class managedClass; @@ -50,19 +50,19 @@ public class JdkClassDetails extends AbstractAnnotationTarget implements ClassDe public JdkClassDetails( Class managedClass, - SourceModelBuildingContext buildingContext) { - this( managedClass.getName(), managedClass, buildingContext ); + SourceModelBuildingContext modelContext) { + this( managedClass.getName(), managedClass, modelContext ); } public JdkClassDetails( String name, Class managedClass, - SourceModelBuildingContext buildingContext) { - super( managedClass::getAnnotations, buildingContext ); + SourceModelBuildingContext modelContext) { + super( managedClass::getAnnotations, modelContext ); this.name = name; this.managedClass = managedClass; - final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); + final ClassDetailsRegistry classDetailsRegistry = modelContext.getClassDetailsRegistry(); final Class superclass = managedClass.getSuperclass(); if ( superclass == null ) { @@ -71,7 +71,7 @@ public JdkClassDetails( else { superClass = classDetailsRegistry.resolveClassDetails( superclass.getName(), - (n) -> JdkBuilders.buildClassDetailsStatic( superclass, buildingContext ) + (n) -> JdkBuilders.buildClassDetailsStatic( superclass, modelContext ) ); } } @@ -115,7 +115,7 @@ public ClassDetails getSuperClass() { @Override public TypeDetails getGenericSuperType() { if ( genericSuperType == null && managedClass.getGenericSuperclass() != null ) { - genericSuperType = new JdkTrackingTypeSwitcher( getBuildingContext() ).switchType( managedClass.getGenericSuperclass() ); + genericSuperType = new JdkTrackingTypeSwitcher( getModelContext() ).switchType( managedClass.getGenericSuperclass() ); } return genericSuperType; } @@ -135,7 +135,7 @@ private List collectInterfaces() { } final ArrayList result = arrayList( jdkInterfaces.length ); - final JdkTrackingTypeSwitcher typeSwitcher = new JdkTrackingTypeSwitcher( getBuildingContext() ); + final JdkTrackingTypeSwitcher typeSwitcher = new JdkTrackingTypeSwitcher( getModelContext() ); for ( Type jdkInterface : jdkInterfaces ) { final TypeDetails switchedInterfaceType = typeSwitcher.switchType( jdkInterface ); result.add( switchedInterfaceType ); @@ -158,7 +158,7 @@ private List collectTypeParameters() { } final ArrayList result = arrayList( jdkTypeParameters.length ); - final JdkTrackingTypeSwitcher typeSwitcher = new JdkTrackingTypeSwitcher( getBuildingContext() ); + final JdkTrackingTypeSwitcher typeSwitcher = new JdkTrackingTypeSwitcher( getModelContext() ); for ( TypeVariable> jdkTypeParameter : jdkTypeParameters ) { result.add( (TypeVariableDetails) typeSwitcher.switchType( jdkTypeParameter ) ); } @@ -177,7 +177,7 @@ public List getFields() { this.fields = arrayList( reflectionFields.length ); for ( int i = 0; i < reflectionFields.length; i++ ) { final Field reflectionField = reflectionFields[i]; - fields.add( new JdkFieldDetails( reflectionField, this, getBuildingContext() ) ); + fields.add( new JdkFieldDetails( reflectionField, this, getModelContext() ) ); } } return fields; @@ -194,7 +194,7 @@ public List getMethods() { final Method[] reflectionMethods = managedClass.getDeclaredMethods(); this.methods = arrayList( reflectionMethods.length ); for ( int i = 0; i < reflectionMethods.length; i++ ) { - this.methods.add( buildMethodDetails( reflectionMethods[i], this, getBuildingContext() ) ); + this.methods.add( buildMethodDetails( reflectionMethods[i], this, getModelContext() ) ); } } return methods; @@ -214,7 +214,7 @@ public List getRecordComponents() { final RecordComponent[] jdkRecordComponents = managedClass.getRecordComponents(); recordComponents = arrayList( jdkRecordComponents.length ); for ( int i = 0; i < jdkRecordComponents.length; i++ ) { - recordComponents.add( new JdkRecordComponentDetails( jdkRecordComponents[i], this, getBuildingContext() ) ); + recordComponents.add( new JdkRecordComponentDetails( jdkRecordComponents[i], this, getModelContext() ) ); } } return recordComponents; diff --git a/src/main/java/org/hibernate/models/internal/jdk/JdkFieldDetails.java b/src/main/java/org/hibernate/models/internal/jdk/JdkFieldDetails.java index d09a253..c036813 100644 --- a/src/main/java/org/hibernate/models/internal/jdk/JdkFieldDetails.java +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkFieldDetails.java @@ -6,13 +6,19 @@ */ package org.hibernate.models.internal.jdk; +import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.Collection; import java.util.Map; +import org.hibernate.models.IllegalCastException; +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.MethodDetails; +import org.hibernate.models.spi.MutableClassDetails; import org.hibernate.models.spi.MutableMemberDetails; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.RecordComponentDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; @@ -20,7 +26,7 @@ /** * @author Steve Ebersole */ -public class JdkFieldDetails extends AbstractAnnotationTarget implements FieldDetails, MutableMemberDetails { +public class JdkFieldDetails extends AbstractJdkAnnotationTarget implements FieldDetails, MutableMemberDetails { private final Field field; private final JdkClassDetails declaringType; private final TypeDetails type; @@ -79,4 +85,34 @@ public int getModifiers() { public String toString() { return "JdkFieldDetails(" + getName() + ")"; } + + @Override + public FieldDetails asFieldDetails() { + return this; + } + + @Override + public MutableMemberDetails asMemberDetails() { + return this; + } + + @Override + public MethodDetails asMethodDetails() { + throw new IllegalCastException( "FieldDetails cannot be cast as MethodDetails" ); + } + + @Override + public RecordComponentDetails asRecordComponentDetails() { + throw new IllegalCastException( "FieldDetails cannot be cast as RecordComponentDetails" ); + } + + @Override + public MutableClassDetails asClassDetails() { + throw new IllegalCastException( "FieldDetails cannot be cast as ClassDetails" ); + } + + @Override + public AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "FieldDetails cannot be cast as AnnotationDescriptor" ); + } } diff --git a/src/main/java/org/hibernate/models/internal/jdk/JdkMethodDetails.java b/src/main/java/org/hibernate/models/internal/jdk/JdkMethodDetails.java index ef97546..73815e8 100644 --- a/src/main/java/org/hibernate/models/internal/jdk/JdkMethodDetails.java +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkMethodDetails.java @@ -6,6 +6,7 @@ */ package org.hibernate.models.internal.jdk; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; @@ -13,11 +14,16 @@ import java.util.Locale; import java.util.Map; +import org.hibernate.models.IllegalCastException; +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.MutableClassDetails; import org.hibernate.models.spi.MutableMemberDetails; import org.hibernate.models.spi.ClassBasedTypeDetails; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.ClassDetailsRegistry; import org.hibernate.models.spi.MethodDetails; +import org.hibernate.models.spi.RecordComponentDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.models.spi.TypeDetails; import org.hibernate.models.spi.TypeDetailsHelper; @@ -29,7 +35,7 @@ /** * @author Steve Ebersole */ -public class JdkMethodDetails extends AbstractAnnotationTarget implements MethodDetails, MutableMemberDetails { +public class JdkMethodDetails extends AbstractJdkAnnotationTarget implements MethodDetails, MutableMemberDetails { private final Method method; private final MethodKind methodKind; private final TypeDetails type; @@ -165,4 +171,34 @@ public String toString() { method.toString() ); } + + @Override + public MethodDetails asMethodDetails() { + return this; + } + + @Override + public MutableMemberDetails asMemberDetails() { + return this; + } + + @Override + public FieldDetails asFieldDetails() { + throw new IllegalCastException( "MethodDetails cannot be cast as FieldDetails" ); + } + + @Override + public RecordComponentDetails asRecordComponentDetails() { + throw new IllegalCastException( "MethodDetails cannot be cast as RecordComponentDetails" ); + } + + @Override + public MutableClassDetails asClassDetails() { + throw new IllegalCastException( "MethodDetails cannot be cast as ClassDetails" ); + } + + @Override + public AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "MethodDetails cannot be cast as AnnotationDescriptor" ); + } } diff --git a/src/main/java/org/hibernate/models/internal/jdk/NestedValueWrapper.java b/src/main/java/org/hibernate/models/internal/jdk/JdkNestedValueConverter.java similarity index 53% rename from src/main/java/org/hibernate/models/internal/jdk/NestedValueWrapper.java rename to src/main/java/org/hibernate/models/internal/jdk/JdkNestedValueConverter.java index 34c5ef9..37c35a6 100644 --- a/src/main/java/org/hibernate/models/internal/jdk/NestedValueWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkNestedValueConverter.java @@ -9,22 +9,21 @@ import java.lang.annotation.Annotation; import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationUsage; +import org.hibernate.models.spi.JdkValueConverter; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; /** * @author Steve Ebersole */ -public class NestedValueWrapper implements ValueWrapper,A> { +public class JdkNestedValueConverter implements JdkValueConverter { private final AnnotationDescriptor descriptor; - public NestedValueWrapper(AnnotationDescriptor descriptor) { + public JdkNestedValueConverter(AnnotationDescriptor descriptor) { this.descriptor = descriptor; } @Override - public AnnotationUsage wrap(A rawValue, SourceModelBuildingContext buildingContext) { - return AnnotationUsageBuilder.makeUsage( rawValue, descriptor, buildingContext ); + public A convert(A rawValue, SourceModelBuildingContext modelContext) { + return descriptor.createUsage( rawValue, modelContext ); } } diff --git a/src/main/java/org/hibernate/models/internal/jdk/JdkNestedValueExtractor.java b/src/main/java/org/hibernate/models/internal/jdk/JdkNestedValueExtractor.java new file mode 100644 index 0000000..bb1daff --- /dev/null +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkNestedValueExtractor.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.internal.jdk; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.SourceModelBuildingContext; + +/** + * @author Steve Ebersole + */ +public class JdkNestedValueExtractor extends AbstractJdkValueExtractor { + private final JdkNestedValueConverter converter; + + public JdkNestedValueExtractor(JdkNestedValueConverter converter) { + this.converter = converter; + } + + @Override + protected A wrap( + A rawValue, + AttributeDescriptor attributeDescriptor, + SourceModelBuildingContext buildingContext) { + return converter.convert( rawValue, buildingContext ); + } +} diff --git a/src/main/java/org/hibernate/models/internal/jdk/PassThruWrapper.java b/src/main/java/org/hibernate/models/internal/jdk/JdkPassThruConverter.java similarity index 53% rename from src/main/java/org/hibernate/models/internal/jdk/PassThruWrapper.java rename to src/main/java/org/hibernate/models/internal/jdk/JdkPassThruConverter.java index 6df8e1a..8e2792c 100644 --- a/src/main/java/org/hibernate/models/internal/jdk/PassThruWrapper.java +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkPassThruConverter.java @@ -6,8 +6,8 @@ */ package org.hibernate.models.internal.jdk; +import org.hibernate.models.spi.JdkValueConverter; import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; /** * Common ValueWrapper support for implementations with the same raw and @@ -15,11 +15,17 @@ * * @author Steve Ebersole */ -public class PassThruWrapper implements ValueWrapper { - public static final PassThruWrapper PASS_THRU_WRAPPER = new PassThruWrapper(); +public class JdkPassThruConverter implements JdkValueConverter { + @SuppressWarnings("rawtypes") + public static final JdkPassThruConverter PASS_THRU_CONVERTER = new JdkPassThruConverter(); + + public static JdkPassThruConverter passThruConverter() { + //noinspection unchecked + return PASS_THRU_CONVERTER; + } @Override - public V wrap(V rawValue, SourceModelBuildingContext buildingContext) { + public V convert(V rawValue, SourceModelBuildingContext modelContext) { return rawValue; } } diff --git a/src/main/java/org/hibernate/models/internal/jdk/PassThruExtractor.java b/src/main/java/org/hibernate/models/internal/jdk/JdkPassThruExtractor.java similarity index 57% rename from src/main/java/org/hibernate/models/internal/jdk/PassThruExtractor.java rename to src/main/java/org/hibernate/models/internal/jdk/JdkPassThruExtractor.java index 29f17ea..57675b9 100644 --- a/src/main/java/org/hibernate/models/internal/jdk/PassThruExtractor.java +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkPassThruExtractor.java @@ -6,15 +6,21 @@ */ package org.hibernate.models.internal.jdk; -import org.hibernate.models.spi.AnnotationTarget; import org.hibernate.models.spi.AttributeDescriptor; +import org.hibernate.models.spi.JdkValueExtractor; import org.hibernate.models.spi.SourceModelBuildingContext; /** * @author Steve Ebersole */ -public class PassThruExtractor extends AbstractValueExtractor { - public static final PassThruExtractor PASS_THRU_EXTRACTOR = new PassThruExtractor(); +public class JdkPassThruExtractor extends AbstractJdkValueExtractor { + @SuppressWarnings("rawtypes") + public static final JdkPassThruExtractor PASS_THRU_EXTRACTOR = new JdkPassThruExtractor(); + + public static JdkValueExtractor passThruExtractor() { + //noinspection unchecked + return PASS_THRU_EXTRACTOR; + } @Override protected V wrap( diff --git a/src/main/java/org/hibernate/models/internal/jdk/JdkRecordComponentDetails.java b/src/main/java/org/hibernate/models/internal/jdk/JdkRecordComponentDetails.java index e4f287b..51d1435 100644 --- a/src/main/java/org/hibernate/models/internal/jdk/JdkRecordComponentDetails.java +++ b/src/main/java/org/hibernate/models/internal/jdk/JdkRecordComponentDetails.java @@ -7,11 +7,17 @@ package org.hibernate.models.internal.jdk; +import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.lang.reflect.RecordComponent; import java.util.Collection; import java.util.Map; +import org.hibernate.models.IllegalCastException; +import org.hibernate.models.spi.AnnotationDescriptor; +import org.hibernate.models.spi.FieldDetails; +import org.hibernate.models.spi.MethodDetails; +import org.hibernate.models.spi.MutableClassDetails; import org.hibernate.models.spi.MutableMemberDetails; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.RecordComponentDetails; @@ -21,7 +27,8 @@ /** * @author Steve Ebersole */ -public class JdkRecordComponentDetails extends AbstractAnnotationTarget implements RecordComponentDetails, MutableMemberDetails { +public class JdkRecordComponentDetails extends AbstractJdkAnnotationTarget + implements RecordComponentDetails, MutableMemberDetails { private final RecordComponent recordComponent; private final TypeDetails type; private final ClassDetails declaringType; @@ -84,4 +91,34 @@ public int getModifiers() { public String toString() { return "JdkRecordComponentDetails(" + getName() + ")"; } + + @Override + public RecordComponentDetails asRecordComponentDetails() { + return this; + } + + @Override + public MutableMemberDetails asMemberDetails() { + return this; + } + + @Override + public FieldDetails asFieldDetails() { + throw new IllegalCastException( "RecordComponentDetails cannot be cast as FieldDetails" ); + } + + @Override + public MethodDetails asMethodDetails() { + throw new IllegalCastException( "RecordComponentDetails cannot be cast as MethodDetails" ); + } + + @Override + public MutableClassDetails asClassDetails() { + throw new IllegalCastException( "RecordComponentDetails cannot be cast as ClassDetails" ); + } + + @Override + public AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "RecordComponentDetails cannot be cast as AnnotationDescriptor" ); + } } diff --git a/src/main/java/org/hibernate/models/internal/jdk/NestedValueExtractor.java b/src/main/java/org/hibernate/models/internal/jdk/NestedValueExtractor.java deleted file mode 100644 index f2a8a82..0000000 --- a/src/main/java/org/hibernate/models/internal/jdk/NestedValueExtractor.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.internal.jdk; - -import java.lang.annotation.Annotation; - -import org.hibernate.models.spi.AnnotationTarget; -import org.hibernate.models.spi.AnnotationUsage; -import org.hibernate.models.spi.AttributeDescriptor; -import org.hibernate.models.spi.SourceModelBuildingContext; -import org.hibernate.models.spi.ValueWrapper; - -/** - * @author Steve Ebersole - */ -public class NestedValueExtractor extends AbstractValueExtractor,A> { - private final ValueWrapper,A> wrapper; - - public NestedValueExtractor(ValueWrapper, A> wrapper) { - this.wrapper = wrapper; - } - - @Override - protected AnnotationUsage wrap( - A rawValue, - AttributeDescriptor> attributeDescriptor, - SourceModelBuildingContext buildingContext) { - return wrapper.wrap( rawValue, buildingContext ); - } -} diff --git a/src/main/java/org/hibernate/models/internal/util/CollectionHelper.java b/src/main/java/org/hibernate/models/internal/util/CollectionHelper.java index e2a2062..2f838a3 100644 --- a/src/main/java/org/hibernate/models/internal/util/CollectionHelper.java +++ b/src/main/java/org/hibernate/models/internal/util/CollectionHelper.java @@ -7,11 +7,13 @@ package org.hibernate.models.internal.util; +import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.Consumer; /** * @author Steve Ebersole @@ -80,4 +82,12 @@ public static List join(List first, List second) { } return joined; } + + public static void forEach(T[] values, Consumer consumer) { + if ( isNotEmpty( values ) ) { + for ( int i = 0; i < values.length; i++ ) { + consumer.accept( values[i] ); + } + } + } } diff --git a/src/main/java/org/hibernate/models/spi/AnnotationDescriptor.java b/src/main/java/org/hibernate/models/spi/AnnotationDescriptor.java index 7b58b72..3227edd 100644 --- a/src/main/java/org/hibernate/models/spi/AnnotationDescriptor.java +++ b/src/main/java/org/hibernate/models/spi/AnnotationDescriptor.java @@ -13,7 +13,9 @@ import org.hibernate.models.IllegalCastException; import org.hibernate.models.UnknownAnnotationAttributeException; -import org.hibernate.models.internal.dynamic.DynamicAnnotationUsage; +import org.hibernate.models.internal.AnnotationHelper; + +import org.jboss.jandex.AnnotationInstance; /** * Describes an annotation type (the Class) @@ -31,6 +33,23 @@ default Kind getKind() { */ Class getAnnotationType(); + /** + * Create an empty usage. Used when there is no source form, such as XML processing. + */ + A createUsage(SourceModelBuildingContext context); + + /** + * Create a usage from the JDK representation. This will often just return the passed annotation, + * although for Hibernate and JPA annotations we generally want wrappers to be able to manipulate the + * values. + */ + A createUsage(A jdkAnnotation, SourceModelBuildingContext context); + + /** + * Create a usage from the Jandex representation. + */ + A createUsage(AnnotationInstance jandexAnnotation, SourceModelBuildingContext context); + /** * The places the described annotation can be used */ @@ -89,15 +108,6 @@ default AttributeDescriptor getAttribute(String name) { throw new UnknownAnnotationAttributeException( getAnnotationType(), name ); } - /** - * Create a usage of this annotation with all attribute values defaulted. - * - * @param context Access to needed services - */ - default MutableAnnotationUsage createUsage(SourceModelBuildingContext context) { - return new DynamicAnnotationUsage<>( this, context ); - } - @Override default AnnotationDescriptor asAnnotationDescriptor() { //noinspection unchecked @@ -130,12 +140,20 @@ default RecordComponentDetails asRecordComponentDetails() { } @Override - default void render() { - throw new UnsupportedOperationException( "Not yet implemented" ); + default void render(SourceModelBuildingContext modelContext) { + throw new UnsupportedOperationException( "Rendering of annotation classes not implemented" ); } @Override - default void render(RenderingCollector collector) { - throw new UnsupportedOperationException( "Not yet implemented" ); + default void render(RenderingCollector collector, SourceModelBuildingContext modelContext) { + throw new UnsupportedOperationException( "Rendering of annotation classes not implemented" ); + } + + default void renderUsage(RenderingCollector collector, A usage, SourceModelBuildingContext modelContext) { + AnnotationHelper.render( collector, usage, this, modelContext ); + } + + default void renderUsage(RenderingCollector collector, String name, A usage, SourceModelBuildingContext modelContext) { + AnnotationHelper.render( collector, name, usage, modelContext ); } } diff --git a/src/main/java/org/hibernate/models/spi/AnnotationDescriptorRegistry.java b/src/main/java/org/hibernate/models/spi/AnnotationDescriptorRegistry.java index b66f2be..62a568f 100644 --- a/src/main/java/org/hibernate/models/spi/AnnotationDescriptorRegistry.java +++ b/src/main/java/org/hibernate/models/spi/AnnotationDescriptorRegistry.java @@ -36,7 +36,10 @@ public interface AnnotationDescriptorRegistry { /** * Make a copy of this registry which cannot be added-to. + * + * @deprecated No real need to make this immutable */ + @Deprecated(forRemoval = true) AnnotationDescriptorRegistry makeImmutableCopy(); @FunctionalInterface diff --git a/src/main/java/org/hibernate/models/spi/AnnotationTarget.java b/src/main/java/org/hibernate/models/spi/AnnotationTarget.java index 7cc1e51..c18e217 100644 --- a/src/main/java/org/hibernate/models/spi/AnnotationTarget.java +++ b/src/main/java/org/hibernate/models/spi/AnnotationTarget.java @@ -20,7 +20,7 @@ import org.hibernate.models.internal.RenderingCollectorImpl; /** - * Abstract for something where an annotation can be {@linkplain AnnotationUsage used}. + * Abstract for something where an annotation can be used. * * @see java.lang.reflect.AnnotatedElement * @@ -43,7 +43,7 @@ public interface AnnotationTarget { * @apiNote This returns the usages directly available on the target; it does not * expand repeatable containers (e.g. NamedQueries -> *NamedQuery). */ - Collection> getAllAnnotationUsages(); + Collection getDirectAnnotationUsages(); /** * Allows to visit every annotation on the target. @@ -51,31 +51,44 @@ public interface AnnotationTarget { * @apiNote Only visits the usages directly available on the target; it does not * visit across repeatable containers (e.g. NamedQueries -> *NamedQuery). */ - default void forAllAnnotationUsages(Consumer> consumer) { - getAllAnnotationUsages().forEach( consumer ); + default void forEachDirectAnnotationUsage(Consumer consumer) { + //noinspection unchecked,rawtypes + getDirectAnnotationUsages().forEach( (Consumer) consumer ); } /** * Whether the given annotation is used on this target. * - * @see #hasRepeatableAnnotationUsage + * @see #hasAnnotationUsage * * @apiNote This form does not check across repeatable containers. E.g., calling this * method with {@code NamedQuery} will return {@code false} when the target directly * has a NamedQueries. */ - boolean hasAnnotationUsage(Class type); + boolean hasDirectAnnotationUsage(Class type); + + /** + * Form of {@linkplain #getAnnotationUsage(AnnotationDescriptor, SourceModelBuildingContext)} which returns {@code null} instead of + * throwing {@linkplain AnnotationAccessException} when more than one usage of the requested + * annotation exists. + */ + A getDirectAnnotationUsage(AnnotationDescriptor descriptor); + + /** + * Form of {@link #getDirectAnnotationUsage(AnnotationDescriptor)} accepting the annotation {@linkplain Class} + */ + A getDirectAnnotationUsage(Class type); /** * Whether the given annotation is used on this target. * - * @see #hasAnnotationUsage + * @see #hasDirectAnnotationUsage * * @apiNote This forms does check across repeatable containers. E.g., calling this * method with {@code NamedQuery} will return {@code true} when the target directly * has a NamedQueries. */ - boolean hasRepeatableAnnotationUsage(Class type); + boolean hasAnnotationUsage(Class type, SourceModelBuildingContext modelContext); /** * Get the usage of the given annotation on this target. @@ -96,48 +109,24 @@ default void forAllAnnotationUsages(Consumer> consumer) { * * *

- * For also checking across meta-annotations, see {@linkplain #locateAnnotationUsage(Class)}. + * For also checking across meta-annotations, see {@linkplain #locateAnnotationUsage(Class, SourceModelBuildingContext)}. * * @return The usage or {@code null} */ - AnnotationUsage getAnnotationUsage(AnnotationDescriptor descriptor); - - /** - * Form of {@link #getAnnotationUsage(AnnotationDescriptor)} accepting the annotation {@linkplain Class} - */ - AnnotationUsage getAnnotationUsage(Class type); - - /** - * Form of {@linkplain #getAnnotationUsage(AnnotationDescriptor)} which returns {@code null} instead of - * throwing {@linkplain AnnotationAccessException} when more than one usage of the requested - * annotation exists. - */ - default AnnotationUsage getSingleAnnotationUsage(AnnotationDescriptor descriptor) { - try { - return getAnnotationUsage( descriptor ); - } - catch (AnnotationAccessException ignore) { - return null; - } - } + A getAnnotationUsage(AnnotationDescriptor descriptor, SourceModelBuildingContext modelContext); /** - * Form of {@link #getSingleAnnotationUsage(AnnotationDescriptor)} accepting the annotation {@linkplain Class} + * Form of {@link #getAnnotationUsage(AnnotationDescriptor, SourceModelBuildingContext)} accepting the annotation {@linkplain Class} */ - default AnnotationUsage getSingleAnnotationUsage(Class type) { - try { - return getAnnotationUsage( type ); - } - catch (AnnotationAccessException ignore) { - return null; - } + default A getAnnotationUsage(Class type, SourceModelBuildingContext modelContext) { + return getAnnotationUsage( modelContext.getAnnotationDescriptorRegistry().getDescriptor( type ), modelContext ); } /** * Form of {@linkplain #getAnnotationUsage} which also considers meta-annotations - - * annotations on the classes of each {@linkplain #getAllAnnotationUsages() local annotation}. + * annotations on the classes of each {@linkplain #getDirectAnnotationUsages() local annotation}. */ - AnnotationUsage locateAnnotationUsage(Class type); + A locateAnnotationUsage(Class type, SourceModelBuildingContext modelContext); /** * Get all usages of the specified {@code annotationType} in this scope. @@ -148,39 +137,72 @@ default AnnotationUsage getSingleAnnotationUsage(Class *

  • the nested {@code @NamedQuery} usages from the {@code @NamedQueries} usage
  • * */ - List> getRepeatedAnnotationUsages(AnnotationDescriptor type); + A[] getRepeatedAnnotationUsages(AnnotationDescriptor type, SourceModelBuildingContext modelContext); /** - * Form of {@linkplain #getRepeatedAnnotationUsages(AnnotationDescriptor)} accepting the annotation {@linkplain Class} + * Form of {@linkplain #getRepeatedAnnotationUsages(AnnotationDescriptor, SourceModelBuildingContext)} accepting the annotation {@linkplain Class} */ - List> getRepeatedAnnotationUsages(Class type); + default A[] getRepeatedAnnotationUsages( + Class type, + SourceModelBuildingContext modelContext) { + return getRepeatedAnnotationUsages( modelContext.getAnnotationDescriptorRegistry().getDescriptor( type ), modelContext ); + } + + void forEachRepeatedAnnotationUsages( + Class repeatable, + Class container, + SourceModelBuildingContext modelContext, + Consumer consumer); + + default void forEachRepeatedAnnotationUsages( + AnnotationDescriptor repeatable, + SourceModelBuildingContext modelContext, + Consumer consumer) { + assert repeatable.isRepeatable(); + forEachRepeatedAnnotationUsages( + repeatable.getAnnotationType(), + repeatable.getRepeatableContainer().getAnnotationType(), + modelContext, + consumer + ); + } /** - * Call the {@code consumer} for each {@linkplain AnnotationUsage usage} of the - * given {@code type}. + * Call the {@code consumer} for each usage of the given {@code type}. * * @apiNote For {@linkplain Repeatable repeatable} annotation types, the consumer will also be * called for those defined on the container. */ default void forEachAnnotationUsage( AnnotationDescriptor type, - Consumer> consumer) { - final List> annotations = getRepeatedAnnotationUsages( type ); + SourceModelBuildingContext modelContext, + Consumer consumer) { + final X[] annotations = getRepeatedAnnotationUsages( type, modelContext ); if ( annotations == null ) { return; } - annotations.forEach( consumer ); + for ( X annotation : annotations ) { + consumer.accept( annotation ); + } } /** - * Form of {@link #forEachAnnotationUsage(AnnotationDescriptor, Consumer)} accepting the annotation {@linkplain Class} + * Form of {@link #forEachAnnotationUsage(AnnotationDescriptor, SourceModelBuildingContext, Consumer)} accepting the annotation {@linkplain Class} */ - void forEachAnnotationUsage(Class type, Consumer> consumer); + default void forEachAnnotationUsage( + Class type, + SourceModelBuildingContext modelContext, + Consumer consumer) { + forEachAnnotationUsage( + modelContext.getAnnotationDescriptorRegistry().getDescriptor( type ), + modelContext, + consumer + ); + } /** - * Returns all AnnotationUsage references from this target where the usage's - * {@linkplain AnnotationUsage#getAnnotationDescriptor() annotation class} is annotated - * with the given {@code metaAnnotationType}. + * Returns all Annotation usages from this target where the usage's annotation class + * is annotated with the given {@code metaAnnotationType}. *

    * E.g., given the following class and annotations *

    @@ -204,7 +226,7 @@ default  void forEachAnnotationUsage(
     	 * @apiNote This method does not check across repeatable containers.  Although the return is a List, we
     	 * are functionally wanting just the unique ones.
     	 */
    -	 List> getMetaAnnotated(Class metaAnnotationType);
    +	 List getMetaAnnotated(Class metaAnnotationType, SourceModelBuildingContext modelContext);
     
     	/**
     	 * Get a usage of the given annotation {@code type} whose {@code attributeToMatch} attribute value
    @@ -212,19 +234,21 @@ default  void forEachAnnotationUsage(
     	 *
     	 * @param matchName The name to match.
     	 */
    -	default  AnnotationUsage getNamedAnnotationUsage(
    +	default  X getNamedAnnotationUsage(
     			AnnotationDescriptor type,
    -			String matchName) {
    -		return getNamedAnnotationUsage( type, matchName, "name" );
    +			String matchName,
    +			SourceModelBuildingContext modelContext) {
    +		return getNamedAnnotationUsage( type, matchName, "name", modelContext );
     	}
     
     	/**
    -	 * Helper form of {@linkplain #getNamedAnnotationUsage(AnnotationDescriptor, String)}
    +	 * Helper form of {@linkplain #getNamedAnnotationUsage(AnnotationDescriptor, String, SourceModelBuildingContext)}
     	 */
    -	default  AnnotationUsage getNamedAnnotationUsage(
    +	default  X getNamedAnnotationUsage(
     			Class type,
    -			String matchName) {
    -		return getNamedAnnotationUsage( type, matchName, "name" );
    +			String matchName,
    +			SourceModelBuildingContext modelContext) {
    +		return getNamedAnnotationUsage( type, matchName, "name", modelContext );
     	}
     
     	/**
    @@ -234,18 +258,20 @@ default  AnnotationUsage getNamedAnnotationUsage(
     	 * @param matchName The name to match.
     	 * @param attributeToMatch Name of the attribute to match on.
     	 */
    -	 AnnotationUsage getNamedAnnotationUsage(
    +	 X getNamedAnnotationUsage(
     			AnnotationDescriptor type,
     			String matchName,
    -			String attributeToMatch);
    +			String attributeToMatch,
    +			SourceModelBuildingContext modelContext);
     
     	/**
    -	 * Helper form of {@linkplain #getNamedAnnotationUsage(AnnotationDescriptor, String, String)}
    +	 * Helper form of {@linkplain #getNamedAnnotationUsage(AnnotationDescriptor, String, String, SourceModelBuildingContext)}
     	 */
    -	 AnnotationUsage getNamedAnnotationUsage(
    +	 X getNamedAnnotationUsage(
     			Class type,
     			String matchName,
    -			String attributeToMatch);
    +			String attributeToMatch,
    +			SourceModelBuildingContext modelContext);
     
     	/**
     	 * Functional contract to process an annotation and return a value.
    @@ -253,11 +279,11 @@  AnnotationUsage getNamedAnnotationUsage(
     	 * @param  The type of the value being returned.
     	 */
     	@FunctionalInterface
    -	interface AnnotationUsageProcessor {
    +	interface AnnotationUsageProcessor {
     		/**
     		 * The processed value.  May be {@code null} to indicate a "no match"
     		 */
    -		T process(AnnotationUsage annotationUsage);
    +		T process(A annotationUsage);
     	}
     
     	/**
    @@ -274,9 +300,10 @@ interface AnnotationUsageProcessor {
     	 */
     	default  T fromAnnotations(
     			Class annotationType,
    -			AnnotationUsageProcessor processor) {
    -		final List> annotationUsages = getRepeatedAnnotationUsages( annotationType );
    -		for ( AnnotationUsage annotationUsage : annotationUsages ) {
    +			AnnotationUsageProcessor processor,
    +			SourceModelBuildingContext modelContext) {
    +		final A[] annotationUsages = getRepeatedAnnotationUsages( annotationType, modelContext );
    +		for ( A annotationUsage : annotationUsages ) {
     			final T result = processor.process( annotationUsage );
     			if ( result != null ) {
     				return result;
    @@ -327,15 +354,15 @@ default  T fromAnnotations(
     	 */
     	RecordComponentDetails asRecordComponentDetails();
     
    -	void render();
    +	void render(SourceModelBuildingContext modelContext);
     
    -	default String renderToString() {
    +	default String renderToString(SourceModelBuildingContext modelContext) {
     		final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl();
    -		render( renderingCollector );
    +		render( renderingCollector, modelContext );
     		return renderingCollector.toString();
     	}
     
    -	void render(RenderingCollector collector);
    +	void render(RenderingCollector collector, SourceModelBuildingContext modelContext);
     
     	/**
     	 * Subset of {@linkplain ElementType annotation targets} supported for mapping annotations
    diff --git a/src/main/java/org/hibernate/models/spi/AnnotationUsage.java b/src/main/java/org/hibernate/models/spi/AnnotationUsage.java
    deleted file mode 100644
    index d8956ed..0000000
    --- a/src/main/java/org/hibernate/models/spi/AnnotationUsage.java
    +++ /dev/null
    @@ -1,175 +0,0 @@
    -/*
    - * Hibernate, Relational Persistence for Idiomatic Java
    - *
    - * SPDX-License-Identifier: Apache-2.0
    - * Copyright: Red Hat Inc. and Hibernate Authors
    - */
    -package org.hibernate.models.spi;
    -
    -import java.lang.annotation.Annotation;
    -import java.util.List;
    -
    -import org.hibernate.models.internal.RenderingCollectorImpl;
    -
    -/**
    - * Describes the usage of an {@linkplain AnnotationDescriptor annotation class} on one of its
    - * allowable {@linkplain AnnotationTarget targets}.
    - * 

    - * The standard way to access values is using {@linkplain #getAttributeValue}. Convenience - * methods have been added for the allowable annotation types. These methods may throw - * exceptions (generally {@linkplain ClassCastException}, if the expected type does not match).

      - *
    • {@linkplain #getBoolean}
    • - *
    • {@linkplain #getByte}
    • - *
    • {@linkplain #getShort}
    • - *
    • {@linkplain #getInteger}
    • - *
    • {@linkplain #getLong}
    • - *
    • {@linkplain #getFloat}
    • - *
    • {@linkplain #getDouble}
    • - *
    • {@linkplain #getClassDetails}
    • - *
    • {@linkplain #getNestedUsage}
    • - *
    • {@linkplain #getList}
    • - *
    - * - * @apiNote Abstracts the underlying source of the annotation information, - * whether that is the {@linkplain Annotation annotation} itself, JAXB, Jandex, - * HCANN, etc. - * - * @author Steve Ebersole - */ -public interface AnnotationUsage
    { - /** - * Descriptor for the type of the used annotation - */ - AnnotationDescriptor getAnnotationDescriptor(); - - /** - * Type of the used annotation - */ - default Class getAnnotationType() { - return getAnnotationDescriptor().getAnnotationType(); - } - - /** - * Create the Annotation representation of this usage - */ - A toAnnotation(); - - /** - * The value of the named annotation attribute - */ - V findAttributeValue(String name); - - /** - * The value of the named annotation attribute - */ - default V getAttributeValue(String name) { - final Object value = findAttributeValue( name ); - if ( value == null ) { - // this is unusual. make sure the attribute exists. - // NOTE : the call to #getAttribute throws the exception if it does not - getAnnotationDescriptor().getAttribute( name ); - } - //noinspection unchecked - return (V) value; - } - - default V getAttributeValue(AttributeDescriptor attributeDescriptor) { - return getAttributeValue( attributeDescriptor.getName() ); - } - - default String getString(String name) { - return getAttributeValue( name ); - } - - default Boolean getBoolean(String name) { - return getAttributeValue( name ); - } - - default Byte getByte(String name) { - return getAttributeValue( name ); - } - - default Short getShort(String name) { - return getAttributeValue( name ); - } - - default Integer getInteger(String name) { - return getAttributeValue( name ); - } - - default Long getLong(String name) { - return getAttributeValue( name ); - } - - default Float getFloat(String name) { - return getAttributeValue( name ); - } - - default Double getDouble(String name) { - return getAttributeValue( name ); - } - - default > E getEnum(String name) { - return getAttributeValue( name ); - } - - default > E getEnum(String name, @SuppressWarnings("unused") Class type) { - return getAttributeValue( name ); - } - - default ClassDetails getClassDetails(String name) { - return getAttributeValue( name ); - } - - default AnnotationUsage getNestedUsage(String name) { - return getAttributeValue( name ); - } - - default List getList(String name) { - return getAttributeValue( name ); - } - - default void render() { - final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl(); - render( renderingCollector ); - renderingCollector.render(); - } - - default void render(RenderingCollector collector) { - final List> attributes = getAnnotationDescriptor().getAttributes(); - if ( attributes.isEmpty() ) { - collector.addLine( "@%s", getAnnotationType().getName() ); - } - else { - collector.addLine( "@%s(", getAnnotationType().getName() ); - collector.indent( 2 ); - attributes.forEach( (attribute) -> attribute.getTypeDescriptor().render( - collector, - attribute.getName(), - getAttributeValue( attribute.getName() ) - ) ); - - collector.unindent( 2 ); - collector.addLine( ")" ); - } - } - - default void renderAttributeValue(String name, RenderingCollector collector) { - final List> attributes = getAnnotationDescriptor().getAttributes(); - if ( attributes.isEmpty() ) { - collector.addLine( "%s = @%s", name, getAnnotationType().getName() ); - } - else { - collector.addLine( "%s = @%s(", name, getAnnotationType().getName() ); - collector.indent( 2 ); - attributes.forEach( (attribute) -> attribute.getTypeDescriptor().render( - collector, - attribute.getName(), - getAttributeValue( attribute.getName() ) - ) ); - - collector.unindent( 2 ); - collector.addLine( ")" ); - } - } -} diff --git a/src/main/java/org/hibernate/models/spi/ClassDetails.java b/src/main/java/org/hibernate/models/spi/ClassDetails.java index 51f5215..b4b17d8 100644 --- a/src/main/java/org/hibernate/models/spi/ClassDetails.java +++ b/src/main/java/org/hibernate/models/spi/ClassDetails.java @@ -11,6 +11,7 @@ import java.util.function.Predicate; import org.hibernate.models.IllegalCastException; +import org.hibernate.models.internal.AnnotationHelper; import org.hibernate.models.internal.RenderingCollectorImpl; import org.hibernate.models.internal.SimpleClassDetails; import org.hibernate.models.internal.util.IndexedConsumer; @@ -273,15 +274,15 @@ default RecordComponentDetails asRecordComponentDetails() { } @Override - default void render() { + default void render(SourceModelBuildingContext modelContext) { final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl(); - render( renderingCollector ); + render( renderingCollector, modelContext ); renderingCollector.render(); } @Override - default void render(RenderingCollector collector) { - getAllAnnotationUsages().forEach( (usage) -> usage.render( collector ) ); + default void render(RenderingCollector collector, SourceModelBuildingContext modelContext) { + forEachDirectAnnotationUsage( (usage) -> AnnotationHelper.render( collector, usage, modelContext ) ); final String pattern = isRecord() ? "record %s {" @@ -293,7 +294,7 @@ default void render(RenderingCollector collector) { collector.addLine( "// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); collector.addLine( "// fields" ); getFields().forEach( (fieldDetails) -> { - fieldDetails.render( collector ); + fieldDetails.render( collector, modelContext ); collector.addLine(); } ); collector.addLine(); @@ -301,7 +302,7 @@ default void render(RenderingCollector collector) { collector.addLine( "// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); collector.addLine( "// methods" ); getMethods().forEach( (methodDetails) -> { - methodDetails.render( collector ); + methodDetails.render( collector, modelContext ); collector.addLine(); } ); collector.addLine(); @@ -310,7 +311,7 @@ default void render(RenderingCollector collector) { collector.addLine( "// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); collector.addLine( "// record components" ); getRecordComponents().forEach( (recordComponentDetails) -> { - recordComponentDetails.render( collector ); + recordComponentDetails.render( collector, modelContext ); collector.addLine(); } ); } diff --git a/src/main/java/org/hibernate/models/spi/FieldDetails.java b/src/main/java/org/hibernate/models/spi/FieldDetails.java index eec7669..a4af347 100644 --- a/src/main/java/org/hibernate/models/spi/FieldDetails.java +++ b/src/main/java/org/hibernate/models/spi/FieldDetails.java @@ -7,6 +7,7 @@ package org.hibernate.models.spi; import org.hibernate.models.IllegalCastException; +import org.hibernate.models.internal.AnnotationHelper; import org.hibernate.models.internal.ModifierUtils; import org.hibernate.models.internal.RenderingCollectorImpl; @@ -47,15 +48,15 @@ default RecordComponentDetails asRecordComponentDetails() { } @Override - default void render() { + default void render(SourceModelBuildingContext modelContext) { final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl(); - render( renderingCollector ); + render( renderingCollector,modelContext ); renderingCollector.render(); } @Override - default void render(RenderingCollector collector) { - forAllAnnotationUsages( (usage) -> usage.render( collector ) ); + default void render(RenderingCollector collector, SourceModelBuildingContext modelContext) { + forEachDirectAnnotationUsage( (usage) -> AnnotationHelper.render( collector, usage, modelContext ) ); // todo : would be nice to render the type-details to include generics, etc collector.addLine( "%s %s", getType().determineRawClass().getName(), getName() ); } diff --git a/src/main/java/org/hibernate/models/spi/JandexValueConverter.java b/src/main/java/org/hibernate/models/spi/JandexValueConverter.java new file mode 100644 index 0000000..d9d0eb6 --- /dev/null +++ b/src/main/java/org/hibernate/models/spi/JandexValueConverter.java @@ -0,0 +1,19 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.spi; + +import org.jboss.jandex.AnnotationValue; + +/** + * Used in processing Jandex references. + * Given a Jandex {@linkplain AnnotationValue}, converts to the corresponding "value type". + * + * @author Steve Ebersole + */ +public interface JandexValueConverter { + V convert(AnnotationValue jandexValue, SourceModelBuildingContext modelContext); +} diff --git a/src/main/java/org/hibernate/models/spi/JandexValueExtractor.java b/src/main/java/org/hibernate/models/spi/JandexValueExtractor.java new file mode 100644 index 0000000..95c7b4c --- /dev/null +++ b/src/main/java/org/hibernate/models/spi/JandexValueExtractor.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.spi; + +import org.jboss.jandex.AnnotationInstance; + +/** + * Support for extracting attribute values from Jandex + * {@linkplain org.jboss.jandex.AnnotationInstance} references. + * + * @param The value type + * + * @author Steve Ebersole + */ +public interface JandexValueExtractor { + /** + * Extract the value of the named attribute from the given annotation + */ + V extractValue(AnnotationInstance annotation, String attributeName, SourceModelBuildingContext modelContext); + + /** + * Extract the value of the described attribute from the given annotation + */ + default V extractValue( + AnnotationInstance annotation, + AttributeDescriptor attributeDescriptor, + SourceModelBuildingContext modelContext) { + return extractValue( annotation, attributeDescriptor.getName(), modelContext ); + } +} diff --git a/src/main/java/org/hibernate/models/spi/JdkValueConverter.java b/src/main/java/org/hibernate/models/spi/JdkValueConverter.java new file mode 100644 index 0000000..3619eb4 --- /dev/null +++ b/src/main/java/org/hibernate/models/spi/JdkValueConverter.java @@ -0,0 +1,15 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.spi; + +/** + * @author Steve Ebersole + */ +public interface JdkValueConverter { + V convert(V rawValue, SourceModelBuildingContext modelContext); +} diff --git a/src/main/java/org/hibernate/models/spi/JdkValueExtractor.java b/src/main/java/org/hibernate/models/spi/JdkValueExtractor.java new file mode 100644 index 0000000..aab2da1 --- /dev/null +++ b/src/main/java/org/hibernate/models/spi/JdkValueExtractor.java @@ -0,0 +1,28 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.spi; + +import java.lang.annotation.Annotation; + +/** + * @author Steve Ebersole + */ +public interface JdkValueExtractor { + /** + * Extract the value of the named attribute from the given annotation + */ + V extractValue(A usage, String attributeName, SourceModelBuildingContext modelContext); + + /** + * Extract the value of the described attribute from the given annotation + */ + V extractValue( + A usage, + AttributeDescriptor attributeDescriptor, + SourceModelBuildingContext modelContext); +} diff --git a/src/main/java/org/hibernate/models/spi/MethodDetails.java b/src/main/java/org/hibernate/models/spi/MethodDetails.java index 57067a1..20079e0 100644 --- a/src/main/java/org/hibernate/models/spi/MethodDetails.java +++ b/src/main/java/org/hibernate/models/spi/MethodDetails.java @@ -10,6 +10,7 @@ import java.util.List; import org.hibernate.models.IllegalCastException; +import org.hibernate.models.internal.AnnotationHelper; import org.hibernate.models.internal.RenderingCollectorImpl; import static org.hibernate.models.internal.ModifierUtils.hasPersistableMethodModifiers; @@ -73,15 +74,15 @@ default RecordComponentDetails asRecordComponentDetails() { } @Override - default void render() { + default void render(SourceModelBuildingContext modelContext) { final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl(); - render( renderingCollector ); + render( renderingCollector, modelContext ); renderingCollector.render(); } @Override - default void render(RenderingCollector collector) { - forAllAnnotationUsages( (usage) -> usage.render( collector ) ); + default void render(RenderingCollector collector, SourceModelBuildingContext modelContext) { + forEachDirectAnnotationUsage( (usage) -> AnnotationHelper.render( collector, usage, modelContext ) ); // todo : would be nice to render the type-details to include generics, etc collector.addLine( diff --git a/src/main/java/org/hibernate/models/spi/MutableAnnotationTarget.java b/src/main/java/org/hibernate/models/spi/MutableAnnotationTarget.java index dbcdd82..81e4c50 100644 --- a/src/main/java/org/hibernate/models/spi/MutableAnnotationTarget.java +++ b/src/main/java/org/hibernate/models/spi/MutableAnnotationTarget.java @@ -23,21 +23,21 @@ public interface MutableAnnotationTarget extends AnnotationTarget { /** * Add an annotation usage to this target */ - void addAnnotationUsage(AnnotationUsage annotationUsage); + void addAnnotationUsage(X annotationUsage); /** * Applies a usage of the given {@code annotationType} to this target. Will return * an existing usage, if one, or create a new usage. */ - default MutableAnnotationUsage applyAnnotationUsage( + default A applyAnnotationUsage( AnnotationDescriptor annotationType, - SourceModelBuildingContext buildingContext) { - final MutableAnnotationUsage existing = (MutableAnnotationUsage) getAnnotationUsage( annotationType ); + SourceModelBuildingContext modelContext) { + final A existing = getAnnotationUsage( annotationType, modelContext ); if ( existing != null ) { return existing; } - final MutableAnnotationUsage usage = annotationType.createUsage( buildingContext ); + final A usage = annotationType.createUsage( modelContext ); addAnnotationUsage( usage ); return usage; } @@ -55,10 +55,10 @@ default MutableAnnotationUsage applyAnnotationUsage( * * @see #replaceAnnotationUsage(AnnotationDescriptor, AnnotationDescriptor, SourceModelBuildingContext) */ - default MutableAnnotationUsage replaceAnnotationUsage( + default A replaceAnnotationUsage( AnnotationDescriptor annotationType, - SourceModelBuildingContext buildingContext) { - final MutableAnnotationUsage usage = annotationType.createUsage( buildingContext ); + SourceModelBuildingContext modelContext) { + final A usage = annotationType.createUsage( modelContext ); // effectively overwrites any previous registration addAnnotationUsage( usage ); return usage; @@ -73,10 +73,10 @@ default MutableAnnotationUsage replaceAnnotationUsage( * * @see #replaceAnnotationUsage(AnnotationDescriptor, SourceModelBuildingContext) */ - MutableAnnotationUsage

    replaceAnnotationUsage( + P replaceAnnotationUsage( AnnotationDescriptor repeatableType, AnnotationDescriptor

    containerType, - SourceModelBuildingContext buildingContext); + SourceModelBuildingContext modelContext); @Override MutableClassDetails asClassDetails(); diff --git a/src/main/java/org/hibernate/models/spi/MutableAnnotationUsage.java b/src/main/java/org/hibernate/models/spi/MutableAnnotationUsage.java deleted file mode 100644 index f46320f..0000000 --- a/src/main/java/org/hibernate/models/spi/MutableAnnotationUsage.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.spi; - -import java.lang.annotation.Annotation; - -/** - * Specialization of AnnotationUsage allowing mutation of its attribute values - * - * @author Steve Ebersole - */ -public interface MutableAnnotationUsage extends AnnotationUsage { - /** - * Set the {@code value} of the named attribute - */ - @SuppressWarnings("UnusedReturnValue") - V setAttributeValue(String name, V value); -} diff --git a/src/main/java/org/hibernate/models/spi/MutableMemberDetails.java b/src/main/java/org/hibernate/models/spi/MutableMemberDetails.java index 89fa7f8..948d24c 100644 --- a/src/main/java/org/hibernate/models/spi/MutableMemberDetails.java +++ b/src/main/java/org/hibernate/models/spi/MutableMemberDetails.java @@ -6,6 +6,8 @@ */ package org.hibernate.models.spi; +import java.lang.annotation.Annotation; + import org.hibernate.models.IllegalCastException; /** @@ -19,6 +21,11 @@ default MutableClassDetails asClassDetails() { throw new IllegalCastException( "MemberDetails cannot be cast to ClassDetails" ); } + @Override + default AnnotationDescriptor asAnnotationDescriptor() { + throw new IllegalCastException( "MemberDetails cannot be cast to AnnotationDescriptor" ); + } + @Override default MutableMemberDetails asMemberDetails() { return this; diff --git a/src/main/java/org/hibernate/models/spi/RecordComponentDetails.java b/src/main/java/org/hibernate/models/spi/RecordComponentDetails.java index 661c469..4c80b1a 100644 --- a/src/main/java/org/hibernate/models/spi/RecordComponentDetails.java +++ b/src/main/java/org/hibernate/models/spi/RecordComponentDetails.java @@ -8,6 +8,7 @@ package org.hibernate.models.spi; import org.hibernate.models.IllegalCastException; +import org.hibernate.models.internal.AnnotationHelper; import org.hibernate.models.internal.RenderingCollectorImpl; import static org.hibernate.models.spi.AnnotationTarget.Kind.RECORD_COMPONENT; @@ -49,15 +50,15 @@ default RecordComponentDetails asRecordComponentDetails() { } @Override - default void render() { + default void render(SourceModelBuildingContext modelContext) { final RenderingCollectorImpl renderingCollector = new RenderingCollectorImpl(); - render( renderingCollector ); + render( renderingCollector, modelContext ); renderingCollector.render(); } @Override - default void render(RenderingCollector collector) { - forAllAnnotationUsages( (usage) -> usage.render( collector ) ); + default void render(RenderingCollector collector, SourceModelBuildingContext modelContext) { + forEachDirectAnnotationUsage( (usage) -> AnnotationHelper.render( collector, usage, modelContext ) ); // todo : would be nice to render the type-details to include generics, etc collector.addLine( "%s %s", getType().determineRawClass().getName(), getName() ); } diff --git a/src/main/java/org/hibernate/models/spi/SharedAnnotationScope.java b/src/main/java/org/hibernate/models/spi/SharedAnnotationScope.java index b44c192..5daff49 100644 --- a/src/main/java/org/hibernate/models/spi/SharedAnnotationScope.java +++ b/src/main/java/org/hibernate/models/spi/SharedAnnotationScope.java @@ -19,17 +19,17 @@ * @author Steve Ebersole */ public interface SharedAnnotationScope { - List> getAllAnnotationUsages(Class annotationType); + List getAllAnnotationUsages(Class annotationType); - default List> getAllAnnotationUsages(AnnotationDescriptor annotationDescriptor) { + default List getAllAnnotationUsages(AnnotationDescriptor annotationDescriptor) { return getAllAnnotationUsages( annotationDescriptor.getAnnotationType() ); } - void forEachAnnotationUsage(Class annotationType, Consumer> consumer); + void forEachAnnotationUsage(Class annotationType, Consumer consumer); default void forEachAnnotationUsage( AnnotationDescriptor annotationDescriptor, - Consumer> consumer) { + Consumer consumer) { forEachAnnotationUsage( annotationDescriptor.getAnnotationType(), consumer ); } } diff --git a/src/main/java/org/hibernate/models/spi/SharedNamedAnnotationScope.java b/src/main/java/org/hibernate/models/spi/SharedNamedAnnotationScope.java index f4e2b76..54a3953 100644 --- a/src/main/java/org/hibernate/models/spi/SharedNamedAnnotationScope.java +++ b/src/main/java/org/hibernate/models/spi/SharedNamedAnnotationScope.java @@ -10,6 +10,8 @@ import java.util.List; import java.util.Objects; +import org.hibernate.models.internal.AnnotationHelper; + /** * AnnotationScope with the ability to resolve "named" annotations * @@ -24,7 +26,7 @@ public interface SharedNamedAnnotationScope extends SharedAnnotationScope { * @param matchName The name to match. * @return The matching annotation usage, or {@code null} if none matched */ - default AnnotationUsage getNamedAnnotation( + default X getNamedAnnotation( AnnotationDescriptor annotationDescriptor, String matchName) { return getNamedAnnotation( annotationDescriptor, matchName, "name" ); @@ -40,14 +42,15 @@ default AnnotationUsage getNamedAnnotation( * * @return The matching annotation usage, or {@code null} if none matched */ - default AnnotationUsage getNamedAnnotation( + default A getNamedAnnotation( AnnotationDescriptor annotationDescriptor, String matchName, String attributeToMatch) { - final List> allUsages = getAllAnnotationUsages( annotationDescriptor ); + final List allUsages = getAllAnnotationUsages( annotationDescriptor ); + final AttributeDescriptor matchAttribute = annotationDescriptor.getAttribute( attributeToMatch ); for ( int i = 0; i < allUsages.size(); i++ ) { - final AnnotationUsage annotationUsage = allUsages.get( i ); - final Object usageName = annotationUsage.getAttributeValue( attributeToMatch ); + final A annotationUsage = allUsages.get( i ); + final String usageName = AnnotationHelper.extractValue( annotationUsage, matchAttribute ); if ( Objects.equals( matchName, usageName ) ) { return annotationUsage; } diff --git a/src/main/java/org/hibernate/models/spi/ValueExtractor.java b/src/main/java/org/hibernate/models/spi/ValueExtractor.java deleted file mode 100644 index 511f58d..0000000 --- a/src/main/java/org/hibernate/models/spi/ValueExtractor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.spi; - -/** - * Support for extracting values from {@linkplain java.lang.annotation.Annotation JDK} - * and {@linkplain org.jboss.jandex.AnnotationInstance Jandex} sources. - *

    - * Supported value types are generally one of

    - * - * @param The annotation source - * @param The value type - * - * @author Steve Ebersole - */ -public interface ValueExtractor { - /** - * Extract the value of the named attribute from the given annotation - */ - V extractValue(S annotation, String attributeName, SourceModelBuildingContext buildingContext); - - /** - * Extract the value of the described attribute from the given annotation - */ - default V extractValue( - S annotation, - AttributeDescriptor attributeDescriptor, - SourceModelBuildingContext buildingContext) { - return extractValue( annotation, attributeDescriptor.getName(), buildingContext ); - } -} diff --git a/src/main/java/org/hibernate/models/spi/ValueTypeDescriptor.java b/src/main/java/org/hibernate/models/spi/ValueTypeDescriptor.java index 41e7889..3dfec28 100644 --- a/src/main/java/org/hibernate/models/spi/ValueTypeDescriptor.java +++ b/src/main/java/org/hibernate/models/spi/ValueTypeDescriptor.java @@ -8,44 +8,42 @@ import java.lang.annotation.Annotation; -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; - /** * Descriptor for the annotation attribute types, acting as a producer for - * {@link AttributeDescriptor}, {@link ValueWrapper} and {@link ValueExtractor} references + * {@link AttributeDescriptor}, {@link JandexValueConverter} and {@link JandexValueExtractor} references * * @author Steve Ebersole */ public interface ValueTypeDescriptor { /** - * The type for the value as modeled in {@linkplain AnnotationUsage}. + * The type for the value. */ - Class getWrappedValueType(); - - /** - * Creates a properly typed default attribute value. Generally used in creating dynamic annotations. - */ - V createValue(AttributeDescriptor attributeDescriptor, SourceModelBuildingContext context); + Class getValueType(); /** * Factory for creating typed {@linkplain AttributeDescriptor} references */ - AttributeDescriptor createAttributeDescriptor(AnnotationDescriptor annotationDescriptor, String attributeName); + AttributeDescriptor createAttributeDescriptor(Class annotationType, String attributeName); - ValueWrapper createJandexWrapper(SourceModelBuildingContext buildingContext); + JandexValueConverter createJandexValueConverter(SourceModelBuildingContext modelContext); - ValueExtractor createJandexExtractor(SourceModelBuildingContext buildingContext); + JandexValueExtractor createJandexValueExtractor(SourceModelBuildingContext modelContext); - ValueWrapper createJdkWrapper(SourceModelBuildingContext buildingContext); + JdkValueConverter createJdkValueConverter(SourceModelBuildingContext modelContext); - ValueExtractor createJdkExtractor(SourceModelBuildingContext buildingContext); + JdkValueExtractor createJdkValueExtractor(SourceModelBuildingContext modelContext); Object unwrap(V value); - default void render(RenderingCollector collector, String name, Object attributeValue) { + V[] makeArray(int size, SourceModelBuildingContext modelContext); + + default void render( + RenderingCollector collector, + String name, + Object attributeValue, + SourceModelBuildingContext modelContext) { collector.addLine( "%s=%s", name, "..." ); } - void render(RenderingCollector collector, Object attributeValue); + void render(RenderingCollector collector, Object attributeValue, SourceModelBuildingContext modelContext); } diff --git a/src/main/java/org/hibernate/models/spi/ValueWrapper.java b/src/main/java/org/hibernate/models/spi/ValueWrapper.java deleted file mode 100644 index b1b4712..0000000 --- a/src/main/java/org/hibernate/models/spi/ValueWrapper.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.models.spi; - -/** - * Wraps a "raw" value. For most cases, this is a simple pass-thru. But for a few - * cases, the raw and wrapper types differ:
    - *
    {@linkplain Class}
    - *
    {@code Class} values are wrapped as {@linkplain ClassDetails}
    - - *
    {@linkplain java.lang.annotation.Annotation}
    - *
    {@code Class} values are wrapped as {@linkplain AnnotationUsage}
    - - *
    arrays
    - *
    Array values are wrapped as {@linkplain java.util.List}
    - *
    - * - * @author Steve Ebersole - */ -public interface ValueWrapper { - W wrap(R rawValue, SourceModelBuildingContext buildingContext); -} diff --git a/src/test/java/org/hibernate/models/PackageTests.java b/src/test/java/org/hibernate/models/PackageTests.java index d669cff..2184b35 100644 --- a/src/test/java/org/hibernate/models/PackageTests.java +++ b/src/test/java/org/hibernate/models/PackageTests.java @@ -25,7 +25,7 @@ void testExactReference() { .resolveClassDetails( packageInfoName ); assertThat( classDetails ).isNotNull(); assertThat( classDetails.getClassName() ).endsWith( "package-info" ); - assertThat( classDetails.getAnnotationUsage( CustomAnnotation.class ) ).isNotNull(); + assertThat( classDetails.getAnnotationUsage( CustomAnnotation.class, buildingContext ) ).isNotNull(); } @Test @@ -36,6 +36,6 @@ void testPackageReference() { .resolveClassDetails( PACKAGE_NAME ); assertThat( classDetails ).isNotNull(); assertThat( classDetails.getClassName() ).endsWith( "package-info" ); - assertThat( classDetails.getAnnotationUsage( CustomAnnotation.class ) ).isNotNull(); + assertThat( classDetails.getAnnotationUsage( CustomAnnotation.class, buildingContext ) ).isNotNull(); } } diff --git a/src/test/java/org/hibernate/models/RenderingSmokeTest.java b/src/test/java/org/hibernate/models/RenderingSmokeTest.java index bf1b98e..e80b082 100644 --- a/src/test/java/org/hibernate/models/RenderingSmokeTest.java +++ b/src/test/java/org/hibernate/models/RenderingSmokeTest.java @@ -30,7 +30,7 @@ void testRendering() { final SourceModelBuildingContextImpl buildingContext = createBuildingContext( (Index) null, SimpleEntity.class ); final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().resolveClassDetails( SimpleEntity.class.getName() ); - classDetails.render(); + classDetails.render( buildingContext ); } @Test @@ -38,7 +38,7 @@ void testRendering2() { final SourceModelBuildingContextImpl buildingContext = createBuildingContext( (org.jboss.jandex.Index) null, SimpleClass.class ); final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().resolveClassDetails( SimpleClass.class.getName() ); - System.out.println( classDetails.renderToString() ); + System.out.println( classDetails.renderToString( buildingContext ) ); } diff --git a/src/test/java/org/hibernate/models/SourceModelTestHelper.java b/src/test/java/org/hibernate/models/SourceModelTestHelper.java index 2df0141..54a0b74 100644 --- a/src/test/java/org/hibernate/models/SourceModelTestHelper.java +++ b/src/test/java/org/hibernate/models/SourceModelTestHelper.java @@ -52,9 +52,7 @@ public static SourceModelBuildingContextImpl createBuildingContext( final SourceModelBuildingContextImpl buildingContext = new SourceModelBuildingContextImpl( classLoadingAccess, jandexIndex, - (contributions, buildingContext1) -> { - OrmAnnotationHelper.forEachOrmAnnotation( contributions::registerAnnotation ); - } + (contributions, buildingContext1) -> OrmAnnotationHelper.forEachOrmAnnotation( contributions::registerAnnotation ) ); final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); final AnnotationDescriptorRegistryStandard annotationDescriptorRegistry = (AnnotationDescriptorRegistryStandard) buildingContext.getAnnotationDescriptorRegistry(); @@ -74,7 +72,7 @@ public static SourceModelBuildingContextImpl createBuildingContext( annotationClass, annotationType -> JdkBuilders.buildAnnotationDescriptor( annotationType, - annotationDescriptorRegistry + buildingContext ) ); } diff --git a/src/test/java/org/hibernate/models/annotations/AnnotationReplacementTests.java b/src/test/java/org/hibernate/models/annotations/AnnotationReplacementTests.java index b58dcd8..4adbc04 100644 --- a/src/test/java/org/hibernate/models/annotations/AnnotationReplacementTests.java +++ b/src/test/java/org/hibernate/models/annotations/AnnotationReplacementTests.java @@ -7,16 +7,10 @@ package org.hibernate.models.annotations; -import java.util.ArrayList; -import java.util.List; - import org.hibernate.models.internal.SourceModelBuildingContextImpl; import org.hibernate.models.orm.JpaAnnotations; -import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.spi.AnnotationUsage; -import org.hibernate.models.spi.ClassDetails; -import org.hibernate.models.spi.MutableAnnotationUsage; +import org.hibernate.models.orm.SecondaryTableAnnotation; +import org.hibernate.models.orm.SecondaryTablesAnnotation; import org.hibernate.models.spi.MutableClassDetails; import org.junit.jupiter.api.Test; @@ -48,36 +42,36 @@ void basicReplacementChecks(Index index) { final SourceModelBuildingContextImpl buildingContext = createBuildingContext( index, SimpleEntity.class ); final MutableClassDetails classDetails = (MutableClassDetails) buildingContext.getClassDetailsRegistry().getClassDetails( SimpleEntity.class.getName() ); - assertThat( classDetails.hasAnnotationUsage( SecondaryTable.class ) ).isTrue(); - assertThat( classDetails.hasAnnotationUsage( SecondaryTables.class ) ).isFalse(); + assertThat( classDetails.hasDirectAnnotationUsage( SecondaryTable.class ) ).isTrue(); + assertThat( classDetails.hasDirectAnnotationUsage( SecondaryTables.class ) ).isFalse(); - final MutableAnnotationUsage replacement = classDetails.replaceAnnotationUsage( + final SecondaryTablesAnnotation replacement = (SecondaryTablesAnnotation) classDetails.replaceAnnotationUsage( JpaAnnotations.SECONDARY_TABLE, JpaAnnotations.SECONDARY_TABLES, buildingContext ); - assertThat( classDetails.hasAnnotationUsage( SecondaryTable.class ) ).isFalse(); - assertThat( classDetails.hasAnnotationUsage( SecondaryTables.class ) ).isTrue(); + assertThat( classDetails.hasDirectAnnotationUsage( SecondaryTable.class ) ).isFalse(); + assertThat( classDetails.hasDirectAnnotationUsage( SecondaryTables.class ) ).isTrue(); + + assertThat( replacement.value() ).hasSize( 0 ); - List> valueList = replacement.getList( "value" ); - // because it is required - assertThat( valueList ).isNull(); - valueList = new ArrayList<>(); - replacement.setAttributeValue( "value", valueList ); + final SecondaryTable[] newValues = new SecondaryTable[1]; + replacement.value( newValues ); + assertThat( replacement.value() ).hasSize( 1 ); - final MutableAnnotationUsage fromXml = JpaAnnotations.SECONDARY_TABLE.createUsage( buildingContext ); - valueList.add( fromXml ); - fromXml.setAttributeValue( "name", "from_xml" ); + final SecondaryTableAnnotation fromXml = (SecondaryTableAnnotation) JpaAnnotations.SECONDARY_TABLE.createUsage( buildingContext ); + newValues[0] = fromXml; + fromXml.name( "from_xml" ); - final AnnotationUsage annotationUsage = classDetails.getAnnotationUsage( SecondaryTable.class ); - assertThat( annotationUsage.getString( "name" ) ).isEqualTo( "from_xml" ); + final SecondaryTable annotationUsage = classDetails.getAnnotationUsage( SecondaryTable.class, buildingContext ); + assertThat( annotationUsage.name() ).isEqualTo( "from_xml" ); - final AnnotationUsage annotationUsage1 = classDetails.getAnnotationUsage( SecondaryTables.class ); - assertThat( annotationUsage1.getList( "value" ) ).isSameAs( valueList ); + final SecondaryTables annotationUsage1 = classDetails.getAnnotationUsage( SecondaryTables.class, buildingContext ); + assertThat( annotationUsage1.value() ).isSameAs( newValues ); // see #76 - classDetails.locateAnnotationUsage( SecondaryTable.class ); + classDetails.locateAnnotationUsage( SecondaryTable.class, buildingContext ); } } diff --git a/src/test/java/org/hibernate/models/annotations/AnnotationUsageTests.java b/src/test/java/org/hibernate/models/annotations/AnnotationUsageTests.java index 952b12b..1a6c603 100644 --- a/src/test/java/org/hibernate/models/annotations/AnnotationUsageTests.java +++ b/src/test/java/org/hibernate/models/annotations/AnnotationUsageTests.java @@ -1,18 +1,17 @@ package org.hibernate.models.annotations; -import java.util.List; +import java.lang.reflect.Proxy; import org.hibernate.models.AnnotationAccessException; import org.hibernate.models.MutableInteger; -import org.hibernate.models.UnknownAnnotationAttributeException; -import org.hibernate.models.spi.AnnotationTarget; -import org.hibernate.models.spi.FieldDetails; -import org.hibernate.models.spi.MutableAnnotationUsage; import org.hibernate.models.internal.SourceModelBuildingContextImpl; +import org.hibernate.models.orm.EntityAnnotation; import org.hibernate.models.orm.JpaAnnotations; +import org.hibernate.models.orm.NamedQueryAnnotation; +import org.hibernate.models.orm.SecondaryTableAnnotation; +import org.hibernate.models.orm.TableAnnotation; import org.hibernate.models.spi.AnnotationDescriptor; import org.hibernate.models.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.ClassDetailsRegistry; @@ -20,13 +19,8 @@ import org.jboss.jandex.Index; -import jakarta.persistence.CheckConstraint; -import jakarta.persistence.CollectionTable; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.NamedNativeQueries; -import jakarta.persistence.NamedNativeQuery; import jakarta.persistence.NamedQueries; import jakarta.persistence.NamedQuery; import jakarta.persistence.SecondaryTable; @@ -65,16 +59,32 @@ void basicUsageChecks(Index index) { assertThat( descriptor ).isNotNull(); assertThat( metaDescriptor ).isNotNull(); - final AnnotationUsage metaUsage = descriptor.getAnnotationUsage( metaDescriptor ); + final CustomMetaAnnotation metaUsage = descriptor.getAnnotationUsage( metaDescriptor, buildingContext ); assertThat( metaUsage ).isNotNull(); + assertThat( Proxy.isProxyClass( metaUsage.getClass() ) ).isTrue(); final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().getClassDetails( SimpleEntity.class.getName() ); // NOTE : the 2 @NamedQuery refs get bundled into 1 @NamedQueries - assertThat( classDetails.getAllAnnotationUsages() ).hasSize( 7 ); + assertThat( classDetails.getDirectAnnotationUsages() ).hasSize( 7 ); - assertThat( classDetails.findFieldByName( "id" ).getAllAnnotationUsages() ).hasSize( 2 ); - assertThat( classDetails.findFieldByName( "name" ).getAllAnnotationUsages() ).hasSize( 2 ); - assertThat( classDetails.findFieldByName( "name2" ).getAllAnnotationUsages() ).hasSize( 2 ); + assertThat( classDetails.findFieldByName( "id" ).getDirectAnnotationUsages() ).hasSize( 2 ); + assertThat( classDetails.findFieldByName( "name" ).getDirectAnnotationUsages() ).hasSize( 2 ); + assertThat( classDetails.findFieldByName( "name2" ).getDirectAnnotationUsages() ).hasSize( 2 ); + + final Entity entityUsage = classDetails.getDirectAnnotationUsage( Entity.class ); + assertThat( entityUsage ).isInstanceOf( EntityAnnotation.class ); + + final Table tableUsage = classDetails.getDirectAnnotationUsage( Table.class ); + assertThat( tableUsage ).isInstanceOf( TableAnnotation.class ); + + final SecondaryTable secondaryTableUsage = classDetails.getDirectAnnotationUsage( SecondaryTable.class ); + assertThat( secondaryTableUsage ).isInstanceOf( SecondaryTableAnnotation.class ); + + assertThat( classDetails.getDirectAnnotationUsage( NamedQuery.class ) ).isNull(); + final NamedQuery[] namedQueryUsages = classDetails.getRepeatedAnnotationUsages( NamedQuery.class, buildingContext ); + assertThat( namedQueryUsages ).hasSize( 2 ); + assertThat( namedQueryUsages[0] ).isInstanceOf( NamedQueryAnnotation.class ); + assertThat( namedQueryUsages[1] ).isInstanceOf( NamedQueryAnnotation.class ); } @Test @@ -91,8 +101,9 @@ private void usageMutationChecks(Index index) { final SourceModelBuildingContextImpl buildingContext = createBuildingContext( index, SimpleEntity.class ); final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); final ClassDetails classDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); - final MutableAnnotationUsage entityAnn = (MutableAnnotationUsage) classDetails.getAnnotationUsage( Entity.class ); - entityAnn.setAttributeValue( "name", "SimpleEntity" ); + final EntityAnnotation entityAnn = (EntityAnnotation) classDetails.getAnnotationUsage( Entity.class, buildingContext ); + entityAnn.name( "SimpleEntity" ); + assertThat( entityAnn.name() ).isEqualTo( "SimpleEntity" ); } @Test @@ -111,23 +122,23 @@ void baselineChecks(Index index) { final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); final ClassDetails classDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); - final AnnotationUsage annotationUsage = classDetails.getAnnotationUsage( CustomAnnotation.class ); + final CustomAnnotation annotationUsage = classDetails.getAnnotationUsage( CustomAnnotation.class, buildingContext ); assertThat( annotationUsage ).isNotNull(); final AnnotationDescriptor descriptor = descriptorRegistry.getDescriptor( CustomAnnotation.class ); assertThat( descriptor ).isNotNull(); - final AnnotationUsage customMetaAnnotationUsage = descriptor.getAnnotationUsage( CustomMetaAnnotation.class ); + final CustomMetaAnnotation customMetaAnnotationUsage = descriptor.getAnnotationUsage( CustomMetaAnnotation.class, buildingContext ); assertThat( customMetaAnnotationUsage ).isNotNull(); - assertThat( customMetaAnnotationUsage.getString( "someValue" ) ).isEqualTo( "abc" ); + assertThat( customMetaAnnotationUsage.someValue() ).isEqualTo( "abc" ); - assertThat( classDetails.hasAnnotationUsage( Entity.class ) ).isTrue(); - final AnnotationUsage entityAnn = classDetails.getAnnotationUsage( Entity.class ); - assertThat( entityAnn.getString( "name" ) ).isEqualTo( "SimpleColumnEntity" ); + assertThat( classDetails.hasDirectAnnotationUsage( Entity.class ) ).isTrue(); + final Entity entityAnn = classDetails.getAnnotationUsage( Entity.class, buildingContext ); + assertThat( entityAnn.name() ).isEqualTo( "SimpleColumnEntity" ); - final AnnotationUsage columnAnn = classDetails.findFieldByName( "name" ).getAnnotationUsage( Column.class ); - assertThat( columnAnn.getString( "name" ) ).isEqualTo( "description" ); - assertThat( columnAnn.getString( "table" ) ).isEqualTo( "" ); - assertThat( columnAnn.getBoolean( "nullable" ) ).isFalse(); - assertThat( columnAnn.getAttributeValue( "unique" ) ).isTrue(); + final Column columnAnn = classDetails.findFieldByName( "name" ).getAnnotationUsage( Column.class, buildingContext ); + assertThat( columnAnn.name() ).isEqualTo( "description" ); + assertThat( columnAnn.table() ).isEqualTo( "" ); + assertThat( columnAnn.nullable() ).isFalse(); + assertThat( columnAnn.unique() ).isTrue(); } @Test @@ -142,37 +153,36 @@ void testCompositionsWithoutJandex() { private void compositionChecks(Index index) { final SourceModelBuildingContextImpl buildingContext = createBuildingContext( index, SimpleEntity.class ); - final AnnotationDescriptorRegistry descriptorRegistry = buildingContext.getAnnotationDescriptorRegistry(); final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); final ClassDetails classDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); - assertThat( classDetails.hasAnnotationUsage( CustomMetaAnnotation.class ) ).isFalse(); - assertThat( classDetails.getAnnotationUsage( CustomMetaAnnotation.class ) ).isNull(); - assertThat( classDetails.locateAnnotationUsage( CustomMetaAnnotation.class ) ).isNotNull(); + assertThat( classDetails.hasDirectAnnotationUsage( CustomMetaAnnotation.class ) ).isFalse(); + assertThat( classDetails.getAnnotationUsage( CustomMetaAnnotation.class, buildingContext ) ).isNull(); + assertThat( classDetails.locateAnnotationUsage( CustomMetaAnnotation.class, buildingContext ) ).isNotNull(); - assertThat( classDetails.getMetaAnnotated( CustomMetaAnnotation.class ) ).hasSize( 1 ); - assertThat( classDetails.getMetaAnnotated( CustomAnnotation.class ) ).isEmpty(); + assertThat( classDetails.getMetaAnnotated( CustomMetaAnnotation.class, buildingContext ) ).hasSize( 1 ); + assertThat( classDetails.getMetaAnnotated( CustomAnnotation.class, buildingContext ) ).isEmpty(); } @Test void testDynamicAttributeCreation() { final SourceModelBuildingContextImpl buildingContext = createBuildingContext( (Index) null, SimpleEntity.class ); - final AnnotationUsage usage = JpaAnnotations.COLUMN.createUsage( buildingContext ); + final Column usage = JpaAnnotations.COLUMN.createUsage( buildingContext ); // check the attribute defaults - assertThat( usage.getString( "name" ) ).isEqualTo( "" ); - assertThat( usage.getString( "table" ) ).isEqualTo( "" ); - assertThat( usage.getBoolean( "unique" ) ).isFalse(); - assertThat( usage.getBoolean( "nullable" ) ).isTrue(); - assertThat( usage.getBoolean( "insertable" ) ).isTrue(); - assertThat( usage.getBoolean( "updatable" ) ).isTrue(); - assertThat( usage.getString( "columnDefinition" ) ).isEqualTo( "" ); - assertThat( usage.getString( "options" ) ).isEqualTo( "" ); - assertThat( usage.getString( "comment" ) ).isEqualTo( "" ); - assertThat( usage.getInteger( "length" ) ).isEqualTo( 255 ); - assertThat( usage.getInteger( "precision" ) ).isEqualTo( 0 ); - assertThat( usage.getInteger( "scale" ) ).isEqualTo( 0 ); - assertThat( usage.getList( "check" ) ).isEmpty(); + assertThat( usage.name() ).isEqualTo( "" ); + assertThat( usage.table() ).isEqualTo( "" ); + assertThat( usage.unique() ).isFalse(); + assertThat( usage.nullable() ).isTrue(); + assertThat( usage.insertable() ).isTrue(); + assertThat( usage.updatable() ).isTrue(); + assertThat( usage.columnDefinition() ).isEqualTo( "" ); + assertThat( usage.options() ).isEqualTo( "" ); + assertThat( usage.comment() ).isEqualTo( "" ); + assertThat( usage.length() ).isEqualTo( 255 ); + assertThat( usage.precision() ).isEqualTo( 0 ); + assertThat( usage.scale() ).isEqualTo( 0 ); + assertThat( usage.check() ).isEmpty(); } @Test @@ -191,83 +201,12 @@ void namedAnnotationAccessChecks(Index index) { final ClassDetails entityClassDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); - final List> namedQueryAnns = entityClassDetails.getRepeatedAnnotationUsages( NamedQuery.class ); + final NamedQuery[] namedQueryAnns = entityClassDetails.getRepeatedAnnotationUsages( NamedQuery.class, buildingContext ); assertThat( namedQueryAnns ).hasSize( 2 ); - final AnnotationUsage abcAnn = entityClassDetails.getNamedAnnotationUsage( NamedQuery.class, "abc" ); + final NamedQuery abcAnn = entityClassDetails.getNamedAnnotationUsage( NamedQuery.class, "abc", buildingContext ); assertThat( abcAnn ).isNotNull(); - assertThat( abcAnn.getString( "query" ) ).isEqualTo( "select me" ); - } - - @Test - void testBadAttributeNamesWithJandex() { - badAttributeNamesChecks( buildJandexIndex( SimpleEntity.class ) ); - } - - @Test - void testBadAttributeNamesWithoutJandex() { - badAttributeNamesChecks( null ); - } - - void badAttributeNamesChecks(Index index) { - final SourceModelBuildingContextImpl buildingContext = createBuildingContext( index, SimpleEntity.class ); - final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); - - final ClassDetails entityClassDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); - final MutableAnnotationUsage entityAnn = (MutableAnnotationUsage) entityClassDetails.getAnnotationUsage( Entity.class ); - assertThat( entityAnn ).isNotNull(); - - try { - entityAnn.getAttributeValue( "doesNotExist" ); - fail( "Expecting an exception" ); - } - catch (UnknownAnnotationAttributeException expected) { - } - - try { - entityAnn.setAttributeValue( "doesNotExist", "stuff" ); - fail( "Expecting an exception" ); - } - catch (UnknownAnnotationAttributeException expected) { - } - } - - @Test - void testToAnnotationJandex() { - toAnnotationChecks( buildJandexIndex( SimpleEntity.class ) ); - } - - @Test - void testToAnnotationWithoutJandex() { - toAnnotationChecks( null ); - } - - private void toAnnotationChecks(Index index) { - final SourceModelBuildingContextImpl buildingContext = createBuildingContext( index, SimpleEntity.class ); - final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); - - final ClassDetails classDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); - - { - final AnnotationUsage annotationUsage = classDetails.getAnnotationUsage( CustomAnnotation.class ); - final CustomAnnotation annotation = annotationUsage.toAnnotation(); - assertThat( annotation ).isNotNull(); - } - - { - final AnnotationUsage annotationUsage = classDetails.getAnnotationUsage( Entity.class ); - final Entity annotation = annotationUsage.toAnnotation(); - assertThat( annotation.name() ).isEqualTo( "SimpleColumnEntity" ); - } - - { - final AnnotationUsage annotationUsage = classDetails.findFieldByName( "name" ).getAnnotationUsage( Column.class ); - final Column annotation = annotationUsage.toAnnotation(); - assertThat( annotation.name() ).isEqualTo( "description" ); - assertThat( annotation.table() ).isEqualTo( "" ); - assertThat( annotation.nullable() ).isFalse(); - assertThat( annotation.unique() ).isTrue(); - } + assertThat( abcAnn.query() ).isEqualTo( "select me" ); } @Test @@ -286,33 +225,44 @@ void testFromAnnotations(Index index) { final ClassDetails classDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); - final String query = classDetails.fromAnnotations( NamedQuery.class, (usage) -> { - final String name = usage.getString( "name" ); - if ( "abc".equals( name ) ) { - return usage.getString( "query" ); - } - return null; - } ); + final String query = classDetails.fromAnnotations( + NamedQuery.class, + (usage) -> { + final String name = usage.name(); + if ( "abc".equals( name ) ) { + return usage.query(); + } + return null; + }, + buildingContext + ); assertThat( query ).isEqualTo( "select me" ); - final String query2 = classDetails.fromAnnotations( NamedQuery.class, (usage) -> { - final String name = usage.getString( "name" ); - if ( "xyz".equals( name ) ) { - return usage.getString( "query" ); - } - return null; - } ); + final String query2 = classDetails.fromAnnotations( + NamedQuery.class, + (usage) -> { + final String name = usage.name(); + if ( "xyz".equals( name ) ) { + return usage.query(); + } + return null; + }, + buildingContext + ); assertThat( query2 ).isEqualTo( "select you" ); - final AnnotationUsage secondaryTable = classDetails.fromAnnotations( SecondaryTable.class, (usage) -> { - final String name = usage.getString( "name" ); - if ( "another_table".equals( name ) ) { - //noinspection unchecked - return (AnnotationUsage) usage; - } - return null; - } ); - assertThat( query2 ).isEqualTo( "select you" ); + final SecondaryTable secondaryTable = classDetails.fromAnnotations( + SecondaryTable.class, + (usage) -> { + final String name = usage.name(); + if ( "another_table".equals( name ) ) { + return usage; + } + return null; + }, + buildingContext + ); + assertThat( secondaryTable ).isNotNull(); } @Test @@ -332,16 +282,16 @@ void testHasAnnotation(Index index) { final ClassDetails classDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); // with #hasAnnotationUsage we only get true for the actual repeatable/container form used - assertThat( classDetails.hasAnnotationUsage( NamedQuery.class ) ).isFalse(); - assertThat( classDetails.hasAnnotationUsage( NamedQueries.class ) ).isTrue(); - assertThat( classDetails.hasAnnotationUsage( SecondaryTable.class ) ).isTrue(); - assertThat( classDetails.hasAnnotationUsage( SecondaryTables.class ) ).isFalse(); + assertThat( classDetails.hasDirectAnnotationUsage( NamedQuery.class ) ).isFalse(); + assertThat( classDetails.hasDirectAnnotationUsage( NamedQueries.class ) ).isTrue(); + assertThat( classDetails.hasDirectAnnotationUsage( SecondaryTable.class ) ).isTrue(); + assertThat( classDetails.hasDirectAnnotationUsage( SecondaryTables.class ) ).isFalse(); // with #hasRepeatableAnnotationUsage we get true regardless - assertThat( classDetails.hasRepeatableAnnotationUsage( NamedQuery.class ) ).isTrue(); - assertThat( classDetails.hasRepeatableAnnotationUsage( NamedQueries.class ) ).isTrue(); - assertThat( classDetails.hasRepeatableAnnotationUsage( SecondaryTable.class ) ).isTrue(); - assertThat( classDetails.hasRepeatableAnnotationUsage( SecondaryTables.class ) ).isFalse(); + assertThat( classDetails.hasAnnotationUsage( NamedQuery.class, buildingContext ) ).isTrue(); + assertThat( classDetails.hasAnnotationUsage( NamedQueries.class, buildingContext ) ).isTrue(); + assertThat( classDetails.hasAnnotationUsage( SecondaryTable.class, buildingContext ) ).isTrue(); + assertThat( classDetails.hasAnnotationUsage( SecondaryTables.class, buildingContext ) ).isFalse(); } @Test @@ -362,15 +312,15 @@ void testForEachAnnotation(Index index) { final MutableInteger counter = new MutableInteger(); - classDetails.forEachAnnotationUsage( Entity.class, entityAnnotationUsage -> counter.increment() ); + classDetails.forEachAnnotationUsage( Entity.class, buildingContext, entityAnnotationUsage -> counter.increment() ); assertThat( counter.get() ).isEqualTo( 1 ); counter.set( 0 ); - classDetails.forEachAnnotationUsage( SecondaryTable.class, entityAnnotationUsage -> counter.increment() ); + classDetails.forEachAnnotationUsage( SecondaryTable.class, buildingContext, entityAnnotationUsage -> counter.increment() ); assertThat( counter.get() ).isEqualTo( 1 ); counter.set( 0 ); - classDetails.forEachAnnotationUsage( NamedQuery.class, entityAnnotationUsage -> counter.increment() ); + classDetails.forEachAnnotationUsage( NamedQuery.class, buildingContext, entityAnnotationUsage -> counter.increment() ); assertThat( counter.get() ).isEqualTo( 2 ); } @@ -390,70 +340,15 @@ void testGetSingleUsage(Index index) { final ClassDetails classDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); try { - classDetails.getAnnotationUsage( NamedQuery.class ); + classDetails.getAnnotationUsage( NamedQuery.class, buildingContext ); fail( "Expecting an AnnotationAccessException to be thrown" ); } catch (AnnotationAccessException expected) { // this is expected } - final AnnotationUsage singleAnnotationUsage = classDetails.getSingleAnnotationUsage( NamedQuery.class ); + final NamedQuery singleAnnotationUsage = classDetails.getDirectAnnotationUsage( NamedQuery.class ); assertThat( singleAnnotationUsage ).isNull(); } - @Test - void testAnnotationTargetWithJandex() { - testAnnotationTarget( buildJandexIndex( SimpleEntity.class ) ); - } - - @Test - void testAnnotationTargetWithoutJandex() { - testAnnotationTarget( null ); - } - - void testAnnotationTarget(Index index) { - final SourceModelBuildingContextImpl buildingContext = createBuildingContext( index, SimpleEntity.class ); - final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); - final ClassDetails classDetails = classDetailsRegistry.getClassDetails( SimpleEntity.class.getName() ); - - // type annotation usage - final AnnotationUsage table = classDetails.getAnnotationUsage( Table.class ); - assertThat( table ).isNotNull(); - assertThat( table.getAnnotationDescriptor().getAllowableTargets() ).contains( classDetails.getKind() ); - // nested type annotation usage - final AnnotationUsage checkConstraint = table.>>getAttributeValue( "check" ).get( 0 ); - assertThat( checkConstraint.getAnnotationDescriptor().getAllowableTargets() ).isEmpty(); - assertThat( classDetails.getAnnotationUsage( CheckConstraint.class ) ).isNull(); - - // field annotation usage - final FieldDetails elementCollection = classDetails.findFieldByName( "elementCollection" ); - final AnnotationUsage collectionTable = elementCollection.getAnnotationUsage( CollectionTable.class ); - assertThat( collectionTable ).isNotNull(); - assertThat( collectionTable.getAnnotationDescriptor().getAllowableTargets() ).contains( elementCollection.getKind() ); - // nested field annotation usage - final AnnotationUsage joinColumn = collectionTable.>>getAttributeValue( "joinColumns" ).get( 0 ); - assertThat( joinColumn.getAnnotationDescriptor().getAllowableTargets() ).contains( elementCollection.getKind() ); - assertThat( elementCollection.getAnnotationUsage( JoinColumn.class ) ).isNull(); - - // repeatable parent annotation usage - final AnnotationUsage namedNativeQueries = classDetails.getAnnotationUsage( NamedNativeQueries.class ); - assertThat( namedNativeQueries ).isNotNull(); - assertThat( namedNativeQueries.getAnnotationDescriptor().getAllowableTargets() ).contains( classDetails.getKind() ); - // nested repeated annotation usage - final AnnotationUsage namedNativeQuery = namedNativeQueries.>>getAttributeValue("value" ).get( 0 ); - assertThat( namedNativeQuery.getAnnotationDescriptor().getAllowableTargets() ).contains( classDetails.getKind() ); - assertThat( classDetails.getAnnotationUsage( NamedNativeQuery.class ) ).isSameAs( namedNativeQuery ); - - // direct repeated annotation usage - final List> repeatedNamedQueries = classDetails.getRepeatedAnnotationUsages( NamedQuery.class ); - assertThat( repeatedNamedQueries ).hasSize( 2 ) - .allMatch( namedQuery -> namedQuery.getAnnotationDescriptor() - .getAllowableTargets() - .contains( classDetails.getKind() ) ); - assertThat( classDetails.getSingleAnnotationUsage( NamedQuery.class ) ).isNull(); - // we can still find a usage for the repeatable container - final AnnotationUsage namedQueries = classDetails.getAnnotationUsage( NamedQueries.class ); - assertThat( namedQueries ).isNotNull(); - assertThat( namedQueries.getAnnotationDescriptor().getAllowableTargets() ).contains( classDetails.getKind() ); - } } diff --git a/src/test/java/org/hibernate/models/annotations/AttributeAccessTests.java b/src/test/java/org/hibernate/models/annotations/AttributeAccessTests.java index 11d433f..e6185d3 100644 --- a/src/test/java/org/hibernate/models/annotations/AttributeAccessTests.java +++ b/src/test/java/org/hibernate/models/annotations/AttributeAccessTests.java @@ -8,7 +8,6 @@ package org.hibernate.models.annotations; import org.hibernate.models.internal.SourceModelBuildingContextImpl; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.ClassDetails; import org.junit.jupiter.api.Test; @@ -26,32 +25,21 @@ public class AttributeAccessTests { void testAttributeAccess() { final SourceModelBuildingContextImpl buildingContext = createBuildingContext( (Index) null, TheClass.class ); final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().getClassDetails( TheClass.class.getName() ); - final AnnotationUsage annotationUsage = classDetails.getAnnotationUsage( EverythingBagel.class ); + final EverythingBagel annotationUsage = classDetails.getAnnotationUsage( EverythingBagel.class, buildingContext ); - assertThat( annotationUsage.getAttributeValue( "theString" ) ).isEqualTo( "hello" ); - assertThat( annotationUsage.getAttributeValue( "theEnum" ) ).isEqualTo( Status.ACTIVE ); - assertThat( annotationUsage.getAttributeValue( "theBoolean" ) ).isEqualTo( true ); - assertThat( annotationUsage.getAttributeValue( "theByte" ) ).isEqualTo( (byte) 1 ); - assertThat( annotationUsage.getAttributeValue( "theShort" ) ).isEqualTo( (short) 2 ); - assertThat( annotationUsage.getAttributeValue( "theInteger" ) ).isEqualTo( 3 ); - assertThat( annotationUsage.getAttributeValue( "theLong" ) ).isEqualTo( 4L ); - assertThat( annotationUsage.getAttributeValue( "theFloat" ) ).isEqualTo( 5.1F ); - assertThat( annotationUsage.getAttributeValue( "theDouble" ) ).isEqualTo( 6.2 ); + assertThat( annotationUsage.theString() ).isEqualTo( "hello" ); + assertThat( annotationUsage.theEnum() ).isEqualTo( Status.ACTIVE ); + assertThat( annotationUsage.theBoolean() ).isEqualTo( true ); + assertThat( annotationUsage.theByte() ).isEqualTo( (byte) 1 ); + assertThat( annotationUsage.theShort() ).isEqualTo( (short) 2 ); + assertThat( annotationUsage.theInteger() ).isEqualTo( 3 ); + assertThat( annotationUsage.theLong() ).isEqualTo( 4L ); + assertThat( annotationUsage.theFloat() ).isEqualTo( 5.1F ); + assertThat( annotationUsage.theDouble() ).isEqualTo( 6.2 ); - assertThat( annotationUsage.getString( "theString" ) ).isEqualTo( "hello" ); - assertThat( annotationUsage.getEnum( "theEnum" ).name() ).isEqualTo( Status.ACTIVE.name() ); - assertThat( annotationUsage.getEnum( "theEnum", Status.class ) ).isEqualTo( Status.ACTIVE ); - assertThat( annotationUsage.getBoolean( "theBoolean" ) ).isEqualTo( true ); - assertThat( annotationUsage.getByte( "theByte" ) ).isEqualTo( (byte) 1 ); - assertThat( annotationUsage.getShort( "theShort" ) ).isEqualTo( (short) 2 ); - assertThat( annotationUsage.getInteger( "theInteger" ) ).isEqualTo( 3 ); - assertThat( annotationUsage.getLong( "theLong" ) ).isEqualTo( 4L ); - assertThat( annotationUsage.getFloat( "theFloat" ) ).isEqualTo( 5.1F ); - assertThat( annotationUsage.getDouble( "theDouble" ) ).isEqualTo( 6.2 ); - - assertThat( annotationUsage.getClassDetails( "theClass" ).toJavaClass() ).isEqualTo( TheClass.class ); - assertThat( annotationUsage.getNestedUsage( "theNested" ) ).isNotNull(); - assertThat( annotationUsage.getList( "theStrings" ) ).containsExactly( "a", "b", "c" ); + assertThat( annotationUsage.theClass() ).isEqualTo( TheClass.class ); + assertThat( annotationUsage.theNested() ).isNotNull(); + assertThat( annotationUsage.theStrings() ).containsExactly( "a", "b", "c" ); } @EverythingBagel( diff --git a/src/test/java/org/hibernate/models/annotations/DefaultValueTests.java b/src/test/java/org/hibernate/models/annotations/DefaultValueTests.java deleted file mode 100644 index caa15fc..0000000 --- a/src/test/java/org/hibernate/models/annotations/DefaultValueTests.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ - -package org.hibernate.models.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.List; -import java.util.stream.Collectors; - -import org.hibernate.models.internal.SourceModelBuildingContextImpl; -import org.hibernate.models.spi.AnnotationDescriptor; -import org.hibernate.models.spi.AnnotationDescriptorRegistry; -import org.hibernate.models.spi.AnnotationUsage; -import org.hibernate.models.spi.AttributeDescriptor; -import org.hibernate.models.spi.ClassDetails; -import org.hibernate.models.spi.ClassDetailsRegistry; -import org.hibernate.models.spi.MutableAnnotationUsage; - -import org.junit.jupiter.api.Test; - -import org.jboss.jandex.Index; - -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hibernate.models.SourceModelTestHelper.buildJandexIndex; -import static org.hibernate.models.SourceModelTestHelper.createBuildingContext; - -/** - * @author Steve Ebersole - */ -public class DefaultValueTests { - @Test - void testWithJandex() { - doTest( buildJandexIndex( SimpleEntity.class ) ); - } - - @Test - void testWithoutJandex() { - doTest( null ); - } - - private void doTest(Index index) { - final SourceModelBuildingContextImpl buildingContext = createBuildingContext( index, TestEntity.class ); - final AnnotationDescriptorRegistry descriptorRegistry = buildingContext.getAnnotationDescriptorRegistry(); - - final AnnotationDescriptor descriptor = descriptorRegistry.getDescriptor( CustomAnnotation.class ); - final List attributeNames = descriptor - .getAttributes() - .stream() - .map( AttributeDescriptor::getName ) - .toList(); - assertThat( attributeNames ).contains( "name", "someClassValue" ); - assertThat( descriptor.findAttribute( "someClassValue" ) ).isNotNull(); - - final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); - final ClassDetails entityClassDetails = classDetailsRegistry.getClassDetails( TestEntity.class.getName() ); - final AnnotationUsage annotationUsage = entityClassDetails.getAnnotationUsage( CustomAnnotation.class ); - assertThat( annotationUsage.getClassDetails( "someClassValue" ) ).isNotNull(); - assertThat( annotationUsage.getClassDetails( "someClassValue" ).toJavaClass() ).isEqualTo( Entity.class ); - - // apparently the models code does not use this method directly, but ORM does. This is the one that was leading to NPE - final MutableAnnotationUsage created = descriptor.createUsage( buildingContext ); - assertThat( created.getClassDetails( "someClassValue" ) ).isNull(); - } - - @Target( ElementType.TYPE ) - @Retention( RetentionPolicy.RUNTIME ) - public @interface CustomAnnotation { - String name(); - Class someClassValue(); - } - - @Entity(name="TestEntity") - @Table(name="TestEntity") - @CustomAnnotation( name="tester", someClassValue = Entity.class ) - public static class TestEntity { - @Id - private Integer id; - private String name; - } -} diff --git a/src/test/java/org/hibernate/models/annotations/RegistryTests.java b/src/test/java/org/hibernate/models/annotations/RegistryTests.java index e93c30a..439d6bb 100644 --- a/src/test/java/org/hibernate/models/annotations/RegistryTests.java +++ b/src/test/java/org/hibernate/models/annotations/RegistryTests.java @@ -11,7 +11,7 @@ import org.hibernate.models.SourceModelTestHelper; import org.hibernate.models.internal.AnnotationDescriptorRegistryStandard; import org.hibernate.models.internal.SourceModelBuildingContextImpl; -import org.hibernate.models.internal.jdk.AnnotationDescriptorImpl; +import org.hibernate.models.internal.StandardAnnotationDescriptor; import org.hibernate.models.spi.AnnotationDescriptorRegistry; import org.junit.jupiter.api.Test; @@ -28,18 +28,18 @@ void testImmutableRegistry() { final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext(); final AnnotationDescriptorRegistryStandard base = new AnnotationDescriptorRegistryStandard( buildingContext ); - base.register( new AnnotationDescriptorImpl<>( Annotation1.class, buildingContext ) ); + base.register( new StandardAnnotationDescriptor<>( Annotation1.class, buildingContext ) ); assertThat( base.getDescriptor( Annotation1.class ) ).isNotNull(); final AnnotationDescriptorRegistry immutableCopy = base.makeImmutableCopy(); assertThat( immutableCopy.getDescriptor( Annotation1.class ) ).isNotNull(); // this should succeed - base.resolveDescriptor( Annotation2.class, annotationType -> new AnnotationDescriptorImpl<>( annotationType, buildingContext ) ); + base.resolveDescriptor( Annotation2.class, annotationType -> new StandardAnnotationDescriptor<>( annotationType, buildingContext ) ); // this should fail try { - immutableCopy.resolveDescriptor( Annotation2.class, annotationType -> new AnnotationDescriptorImpl<>( annotationType, buildingContext ) ); + immutableCopy.resolveDescriptor( Annotation2.class, annotationType -> new StandardAnnotationDescriptor<>( annotationType, buildingContext ) ); fail( "Expecting an exception" ); } catch (ModelsException expected) { diff --git a/src/test/java/org/hibernate/models/annotations/RepeatableUsageTests.java b/src/test/java/org/hibernate/models/annotations/RepeatableUsageTests.java index 2036104..24d6518 100644 --- a/src/test/java/org/hibernate/models/annotations/RepeatableUsageTests.java +++ b/src/test/java/org/hibernate/models/annotations/RepeatableUsageTests.java @@ -1,11 +1,9 @@ package org.hibernate.models.annotations; import java.lang.reflect.Modifier; -import java.util.List; import org.hibernate.models.AnnotationAccessException; import org.hibernate.models.internal.SourceModelBuildingContextImpl; -import org.hibernate.models.spi.AnnotationUsage; import org.hibernate.models.spi.ClassDetails; import org.junit.jupiter.api.Test; @@ -72,16 +70,16 @@ private void verifyThing1(SourceModelBuildingContextImpl buildingContext) { final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().getClassDetails( Thing1.class.getName() ); try { - classDetails.getAnnotationUsage( NamedQuery.class ); + classDetails.getAnnotationUsage( NamedQuery.class, buildingContext ); fail( "Expecting failure" ); } catch (AnnotationAccessException expected) { } - final List> usages = classDetails.getRepeatedAnnotationUsages( NamedQuery.class ); + final NamedQuery[] usages = classDetails.getRepeatedAnnotationUsages( NamedQuery.class, buildingContext ); assertThat( usages ).hasSize( 2 ); - final AnnotationUsage containerUsage = classDetails.getAnnotationUsage( NamedQueries.class ); + final NamedQueries containerUsage = classDetails.getAnnotationUsage( NamedQueries.class, buildingContext ); assertThat( containerUsage ).isNotNull(); } @@ -89,50 +87,50 @@ private void verifyThing2(SourceModelBuildingContextImpl buildingContext) { final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().getClassDetails( Thing2.class.getName() ); try { - classDetails.getAnnotationUsage( NamedQuery.class ); + classDetails.getAnnotationUsage( NamedQuery.class, buildingContext ); fail( "Expecting failure" ); } catch (AnnotationAccessException expected) { } - final List> usages = classDetails.getRepeatedAnnotationUsages( NamedQuery.class ); + final NamedQuery[] usages = classDetails.getRepeatedAnnotationUsages( NamedQuery.class, buildingContext ); assertThat( usages ).hasSize( 2 ); - final AnnotationUsage containerUsage = classDetails.getAnnotationUsage( NamedQueries.class ); + final NamedQueries containerUsage = classDetails.getAnnotationUsage( NamedQueries.class, buildingContext ); assertThat( containerUsage ).isNotNull(); } private void verifyThing3(SourceModelBuildingContextImpl buildingContext) { final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().getClassDetails( Thing3.class.getName() ); - assertThat( classDetails.getAnnotationUsage( NamedQuery.class ) ).isNull(); - assertThat( classDetails.getAnnotationUsage( NamedQueries.class ) ).isNull(); + assertThat( classDetails.getAnnotationUsage( NamedQuery.class, buildingContext ) ).isNull(); + assertThat( classDetails.getAnnotationUsage( NamedQueries.class, buildingContext ) ).isNull(); } private void verifyThing4(SourceModelBuildingContextImpl buildingContext) { final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().getClassDetails( Thing4.class.getName() ); // NOTE : this works like the JDK call, though we may want to make this more sane - final AnnotationUsage usage = classDetails.getAnnotationUsage( NamedQuery.class ); + final NamedQuery usage = classDetails.getAnnotationUsage( NamedQuery.class, buildingContext ); assertThat( usage ).isNotNull(); - final List> usages = classDetails.getRepeatedAnnotationUsages( NamedQuery.class ); + final NamedQuery[] usages = classDetails.getRepeatedAnnotationUsages( NamedQuery.class, buildingContext ); assertThat( usages ).hasSize( 3 ); - final AnnotationUsage containerUsage = classDetails.getAnnotationUsage( NamedQueries.class ); + final NamedQueries containerUsage = classDetails.getAnnotationUsage( NamedQueries.class, buildingContext ); assertThat( containerUsage ).isNotNull(); } private void verifyThing5(SourceModelBuildingContextImpl buildingContext) { final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().getClassDetails( Thing5.class.getName() ); - final AnnotationUsage containerUsage = classDetails.getAnnotationUsage( NamedQueries.class ); + final NamedQueries containerUsage = classDetails.getAnnotationUsage( NamedQueries.class, buildingContext ); assertThat( containerUsage ).isNotNull(); - final AnnotationUsage usage = classDetails.getAnnotationUsage( NamedQuery.class ); + final NamedQuery usage = classDetails.getAnnotationUsage( NamedQuery.class, buildingContext ); assertThat( usage ).isNotNull(); - final List> usages = classDetails.getRepeatedAnnotationUsages( NamedQuery.class ); + final NamedQuery[] usages = classDetails.getRepeatedAnnotationUsages( NamedQuery.class, buildingContext ); assertThat( usages ).hasSize( 1 ); } diff --git a/src/test/java/org/hibernate/models/classes/InheritanceTests.java b/src/test/java/org/hibernate/models/classes/InheritanceTests.java index 1fa772e..a0f04dc 100644 --- a/src/test/java/org/hibernate/models/classes/InheritanceTests.java +++ b/src/test/java/org/hibernate/models/classes/InheritanceTests.java @@ -49,21 +49,21 @@ private void basicRootTest(Index index) { final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); final ClassDetails rootClassDetails = classDetailsRegistry.getClassDetails( RootClass.class.getName() ); - assertThat( rootClassDetails.getAnnotationUsage( ClassMarker.class ) ).isNotNull(); - assertThat( rootClassDetails.getAnnotationUsage( SubclassableMarker.class ) ).isNotNull(); - assertThat( rootClassDetails.getAnnotationUsage( Composable.class ) ).isNull(); - Assertions.assertThat( rootClassDetails.getAnnotationUsage( MemberMarker.class ) ).isNull(); + assertThat( rootClassDetails.getAnnotationUsage( ClassMarker.class, buildingContext ) ).isNotNull(); + assertThat( rootClassDetails.getAnnotationUsage( SubclassableMarker.class, buildingContext ) ).isNotNull(); + assertThat( rootClassDetails.getAnnotationUsage( Composable.class, buildingContext ) ).isNull(); + Assertions.assertThat( rootClassDetails.getAnnotationUsage( MemberMarker.class, buildingContext ) ).isNull(); assertThat( rootClassDetails.getFields() ).hasSize( 2 ); final FieldDetails value1 = rootClassDetails.findFieldByName( "value1" ); assertThat( value1 ).isNotNull(); - assertThat( value1.getAnnotationUsage( MemberMarker.class ) ).isNotNull(); - assertThat( value1.getAnnotationUsage( ClassMarker.class ) ).isNull(); - assertThat( value1.getAnnotationUsage( Transient.class ) ).isNull(); + assertThat( value1.getAnnotationUsage( MemberMarker.class, buildingContext ) ).isNotNull(); + assertThat( value1.getAnnotationUsage( ClassMarker.class, buildingContext ) ).isNull(); + assertThat( value1.getAnnotationUsage( Transient.class, buildingContext ) ).isNull(); final FieldDetails value2 = rootClassDetails.findFieldByName( "value2" ); - assertThat( value2.getAnnotationUsage( MemberMarker.class ) ).isNull(); - assertThat( value2.getAnnotationUsage( ClassMarker.class ) ).isNull(); - assertThat( value2.getAnnotationUsage( Transient.class ) ).isNotNull(); + assertThat( value2.getAnnotationUsage( MemberMarker.class, buildingContext ) ).isNull(); + assertThat( value2.getAnnotationUsage( ClassMarker.class, buildingContext ) ).isNull(); + assertThat( value2.getAnnotationUsage( Transient.class, buildingContext ) ).isNotNull(); assertThat( rootClassDetails.getSuperClass() ).isNotNull(); assertThat( rootClassDetails.getSuperClass().toJavaClass() ).isEqualTo( Object.class ); @@ -96,22 +96,22 @@ private void basicTrunkTest(Index index) { final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); final ClassDetails trunkClassDetails = classDetailsRegistry.getClassDetails( TrunkClass.class.getName() ); - assertThat( trunkClassDetails.getAnnotationUsage( ClassMarker.class ) ).isNotNull(); + assertThat( trunkClassDetails.getAnnotationUsage( ClassMarker.class, buildingContext ) ).isNotNull(); // NOTE : SubclassableMarker is @Inherited, so we should see it here too - assertThat( trunkClassDetails.getAnnotationUsage( SubclassableMarker.class ) ).isNotNull(); - assertThat( trunkClassDetails.getAnnotationUsage( MemberMarker.class ) ).isNull(); + assertThat( trunkClassDetails.getAnnotationUsage( SubclassableMarker.class, buildingContext ) ).isNotNull(); + assertThat( trunkClassDetails.getAnnotationUsage( MemberMarker.class, buildingContext ) ).isNull(); assertThat( trunkClassDetails.getFields() ).hasSize( 2 ); final FieldDetails value3 = trunkClassDetails.findFieldByName( "value3" ); assertThat( value3 ).isNotNull(); - assertThat( value3.getAnnotationUsage( MemberMarker.class ) ).isNotNull(); - assertThat( value3.getAnnotationUsage( ClassMarker.class ) ).isNull(); - assertThat( value3.getAnnotationUsage( Transient.class ) ).isNull(); + assertThat( value3.getAnnotationUsage( MemberMarker.class, buildingContext ) ).isNotNull(); + assertThat( value3.getAnnotationUsage( ClassMarker.class, buildingContext ) ).isNull(); + assertThat( value3.getAnnotationUsage( Transient.class, buildingContext ) ).isNull(); final FieldDetails value4 = trunkClassDetails.findFieldByName( "value4" ); - assertThat( value4.getAnnotationUsage( MemberMarker.class ) ).isNull(); - assertThat( value4.getAnnotationUsage( ClassMarker.class ) ).isNull(); - assertThat( value4.getAnnotationUsage( Transient.class ) ).isNotNull(); + assertThat( value4.getAnnotationUsage( MemberMarker.class, buildingContext ) ).isNull(); + assertThat( value4.getAnnotationUsage( ClassMarker.class, buildingContext ) ).isNull(); + assertThat( value4.getAnnotationUsage( Transient.class, buildingContext ) ).isNotNull(); assertThat( trunkClassDetails.getSuperClass() ).isNotNull(); assertThat( trunkClassDetails.getSuperClass().toJavaClass() ).isEqualTo( RootClass.class ); @@ -144,15 +144,15 @@ private void basicLeafTest(Index index) { final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry(); final ClassDetails leafClassDetails = classDetailsRegistry.getClassDetails( LeafClass.class.getName() ); - assertThat( leafClassDetails.getAnnotationUsage( ClassMarker.class ) ).isNotNull(); + assertThat( leafClassDetails.getAnnotationUsage( ClassMarker.class, buildingContext ) ).isNotNull(); // NOTE : SubclassableMarker is @Inherited, so we should see it here too - assertThat( leafClassDetails.getAnnotationUsage( SubclassableMarker.class ) ).isNotNull(); - assertThat( leafClassDetails.getAnnotationUsage( MemberMarker.class ) ).isNull(); + assertThat( leafClassDetails.getAnnotationUsage( SubclassableMarker.class, buildingContext ) ).isNotNull(); + assertThat( leafClassDetails.getAnnotationUsage( MemberMarker.class, buildingContext ) ).isNull(); - assertThat( leafClassDetails.getAnnotationUsage( ClassMarker.class ) ).isNotNull(); + assertThat( leafClassDetails.getAnnotationUsage( ClassMarker.class, buildingContext ) ).isNotNull(); // NOTE : SubclassableMarker is @Inherited, so we should see it even way down here too - assertThat( leafClassDetails.getAnnotationUsage( SubclassableMarker.class ) ).isNotNull(); - assertThat( leafClassDetails.getAnnotationUsage( MemberMarker.class ) ).isNull(); + assertThat( leafClassDetails.getAnnotationUsage( SubclassableMarker.class, buildingContext ) ).isNotNull(); + assertThat( leafClassDetails.getAnnotationUsage( MemberMarker.class, buildingContext ) ).isNull(); } @Test diff --git a/src/test/java/org/hibernate/models/dynamic/DynamicAnnotationTests.java b/src/test/java/org/hibernate/models/dynamic/DynamicAnnotationTests.java index 19d25cc..53fb5a0 100644 --- a/src/test/java/org/hibernate/models/dynamic/DynamicAnnotationTests.java +++ b/src/test/java/org/hibernate/models/dynamic/DynamicAnnotationTests.java @@ -7,29 +7,22 @@ package org.hibernate.models.dynamic; -import java.util.List; - -import org.hibernate.models.UnknownAnnotationAttributeException; import org.hibernate.models.internal.SourceModelBuildingContextImpl; -import org.hibernate.models.internal.dynamic.DynamicAnnotationUsage; import org.hibernate.models.internal.dynamic.DynamicClassDetails; +import org.hibernate.models.orm.ForeignKeyAnnotation; import org.hibernate.models.orm.JpaAnnotations; -import org.hibernate.models.spi.AnnotationUsage; -import org.hibernate.models.spi.ClassDetails; -import org.hibernate.models.spi.MutableAnnotationUsage; +import org.hibernate.models.orm.SecondaryTableAnnotation; +import org.hibernate.models.orm.TableAnnotation; import org.junit.jupiter.api.Test; -import jakarta.persistence.ConstraintMode; -import jakarta.persistence.ElementCollection; import jakarta.persistence.ForeignKey; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.JoinTable; +import jakarta.persistence.SecondaryTable; import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.SequenceGenerators; +import jakarta.persistence.Table; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Fail.fail; import static org.hibernate.models.SourceModelTestHelper.createBuildingContext; /** @@ -39,90 +32,41 @@ public class DynamicAnnotationTests { @Test void testBasicUsage() { final SourceModelBuildingContextImpl buildingContext = createBuildingContext(); - final DynamicClassDetails dynamicEntity = new DynamicClassDetails( "DynamicEntity", buildingContext ); - final DynamicAnnotationUsage generatorAnn = new DynamicAnnotationUsage<>( - JpaAnnotations.SEQUENCE_GENERATOR, - buildingContext - ); - assertThat( generatorAnn.getString( "name" ) ).isEqualTo( "" ); - assertThat( generatorAnn.getString( "sequenceName" ) ).isEqualTo( "" ); - assertThat( generatorAnn.getString( "catalog" ) ).isEqualTo( "" ); - assertThat( generatorAnn.getString( "schema" ) ).isEqualTo( "" ); - assertThat( generatorAnn.getInteger( "initialValue" ) ).isEqualTo( 1 ); - assertThat( generatorAnn.getInteger( "allocationSize" ) ).isEqualTo( 50 ); - - try { - generatorAnn.getInteger( "incrementBy" ); - fail( "Expecting UnknownAnnotationAttributeException" ); - } - catch (UnknownAnnotationAttributeException expected) { - // ignore - } - + final SequenceGenerator generatorAnn = JpaAnnotations.SEQUENCE_GENERATOR.createUsage( buildingContext ); + assertThat( generatorAnn.name() ).isEqualTo( "" ); + assertThat( generatorAnn.sequenceName() ).isEqualTo( "" ); + assertThat( generatorAnn.catalog() ).isEqualTo( "" ); + assertThat( generatorAnn.schema() ).isEqualTo( "" ); + assertThat( generatorAnn.initialValue() ).isEqualTo( 1 ); + assertThat( generatorAnn.allocationSize() ).isEqualTo( 50 ); + assertThat( generatorAnn.options() ).isEqualTo("" ); + + final SequenceGenerators generatorsAnn = JpaAnnotations.SEQUENCE_GENERATORS.createUsage( buildingContext ); + assertThat( generatorsAnn.value() ).isNotNull(); + assertThat( generatorsAnn.value() ).isEmpty(); } @Test - void testJoinTableForeignKeyDefaultValue() { + void testAnnotationWrapping() { final SourceModelBuildingContextImpl buildingContext = createBuildingContext(); final DynamicClassDetails dynamicEntity = new DynamicClassDetails( "DynamicEntity", buildingContext ); - final DynamicAnnotationUsage generatorAnn = new DynamicAnnotationUsage<>( - JpaAnnotations.JOIN_TABLE, + final Table tableUsage = dynamicEntity.applyAnnotationUsage( + JpaAnnotations.TABLE, buildingContext ); + assertThat( tableUsage ).isInstanceOf( TableAnnotation.class ); - final Object foreignKey = generatorAnn.getAttributeValue( "foreignKey" ); - - assertThat( foreignKey ).isInstanceOf( AnnotationUsage.class ); - - //noinspection unchecked - final AnnotationUsage foreignKeyAnnotationUsage = (AnnotationUsage) foreignKey; - - assertThat( foreignKeyAnnotationUsage.getAttributeValue( "value" ) ).isEqualTo( ConstraintMode.PROVIDER_DEFAULT ); - - assertThat( foreignKeyAnnotationUsage.getAttributeValue( "name" ) ).isEqualTo( "" ); - assertThat( foreignKeyAnnotationUsage.getAttributeValue( "options" ) ).isEqualTo( "" ); - assertThat( foreignKeyAnnotationUsage.getAttributeValue( "foreignKeyDefinition" ) ).isEqualTo( "" ); - } - - @Test - void testDefaultArrayValue() { - final SourceModelBuildingContextImpl buildingContext = createBuildingContext(); - final DynamicClassDetails dynamicEntity = new DynamicClassDetails( "DynamicEntity", buildingContext ); - final DynamicAnnotationUsage generatorAnn = new DynamicAnnotationUsage<>( - JpaAnnotations.JOIN_TABLE, + final SecondaryTable secondaryTableUsage = dynamicEntity.applyAnnotationUsage( + JpaAnnotations.SECONDARY_TABLE, buildingContext ); + assertThat( secondaryTableUsage ).isInstanceOf( SecondaryTableAnnotation.class ); - final Object joinColumns = generatorAnn.getAttributeValue( "joinColumns" ); - assertThat( joinColumns ).isInstanceOf( List.class ); - + final ForeignKey foreignKeyUsage = secondaryTableUsage.foreignKey(); + assertThat( foreignKeyUsage ).isInstanceOf( ForeignKeyAnnotation.class ); + assertThat( foreignKeyUsage.name() ).isEqualTo( "" ); + assertThat( foreignKeyUsage.options() ).isEqualTo( "" ); + assertThat( foreignKeyUsage.foreignKeyDefinition() ).isEqualTo( "" ); } - @Test - void testDefaultValues() { - final SourceModelBuildingContextImpl buildingContext = createBuildingContext(); - final DynamicClassDetails dynamicEntity = new DynamicClassDetails( "DynamicEntity", buildingContext ); - final DynamicAnnotationUsage generatorAnn = new DynamicAnnotationUsage<>( - JpaAnnotations.GENERATED_VALUE, - buildingContext - ); - - GenerationType strategy = generatorAnn.getAttributeValue( "strategy" ); - assertThat( strategy ).isEqualTo( GenerationType.AUTO ); - String generator = generatorAnn.findAttributeValue( "generator" ); - assertThat( generator ).isEqualTo( "" ); - } - - @Test - void testClassDetailsDefaultValue(){ - final SourceModelBuildingContextImpl buildingContext = createBuildingContext(); - final DynamicClassDetails dynamicEntity = new DynamicClassDetails( "DynamicEntity", buildingContext ); - final DynamicAnnotationUsage elementCollectionAnn = new DynamicAnnotationUsage<>( - JpaAnnotations.ELEMENT_COLLECTION, - buildingContext - ); - - Object value = elementCollectionAnn.getAttributeValue( "targetClass" ); - assertThat( value ).isInstanceOf( ClassDetails.class ); - } } diff --git a/src/test/java/org/hibernate/models/dynamic/SimpleDynamicModelTests.java b/src/test/java/org/hibernate/models/dynamic/SimpleDynamicModelTests.java index 591f92a..dbc0812 100644 --- a/src/test/java/org/hibernate/models/dynamic/SimpleDynamicModelTests.java +++ b/src/test/java/org/hibernate/models/dynamic/SimpleDynamicModelTests.java @@ -17,15 +17,12 @@ import org.hibernate.models.spi.ClassDetails; import org.hibernate.models.spi.ClassDetailsRegistry; import org.hibernate.models.spi.FieldDetails; -import org.hibernate.models.spi.MutableAnnotationUsage; import org.hibernate.models.spi.TypeDetails; import org.junit.jupiter.api.Test; import org.jboss.jandex.Index; -import jakarta.persistence.Embeddable; -import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.Id; @@ -50,11 +47,11 @@ void testSimpleBasics() { "TheEntity", name -> new DynamicClassDetails( name, buildingContext ) ); - final MutableAnnotationUsage created = entityDetails.applyAnnotationUsage( + final Entity created = entityDetails.applyAnnotationUsage( JpaAnnotations.ENTITY, buildingContext ); - final MutableAnnotationUsage preExisting = entityDetails.applyAnnotationUsage( + final Entity preExisting = entityDetails.applyAnnotationUsage( JpaAnnotations.ENTITY, buildingContext ); @@ -67,11 +64,11 @@ void testSimpleBasics() { false, buildingContext ); - final MutableAnnotationUsage first = idMember.applyAnnotationUsage( + final Id first = idMember.applyAnnotationUsage( JpaAnnotations.ID, buildingContext ); - final MutableAnnotationUsage second = idMember.applyAnnotationUsage( + final Id second = idMember.applyAnnotationUsage( JpaAnnotations.ID, buildingContext ); @@ -87,7 +84,7 @@ void testSimpleBasics() { assertThat( entityDetails.getFields() ).hasSize( 2 ); assertThat( entityDetails.getFields().get( 0 ).getName() ).isEqualTo( "id" ); - assertThat( entityDetails.getFields().get( 0 ).hasAnnotationUsage( Id.class ) ).isTrue(); + assertThat( entityDetails.getFields().get( 0 ).hasDirectAnnotationUsage( Id.class ) ).isTrue(); checkPersistability( entityDetails.getFields().get( 0 ) ); checkPersistability( entityDetails.getFields().get( 1 ) ); } @@ -102,94 +99,94 @@ private void checkPersistability(FieldDetails fieldDetails) { assertThat( ModifierUtils.isSynthetic( fieldDetails.getModifiers() ) ).isFalse(); } - @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 ); - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // EMBEDDABLE - TheName - - final DynamicClassDetails nameEmbeddableDetails = (DynamicClassDetails) classDetailsRegistry.resolveClassDetails( - "TheName", - name -> { - final DynamicClassDetails classDetails = new DynamicClassDetails( name, buildingContext ); - final MutableAnnotationUsage embeddableUsage = classDetails.applyAnnotationUsage( JpaAnnotations.EMBEDDABLE, buildingContext ); - assertThat( embeddableUsage ).isNotNull(); - return classDetails; - } - ); - - // NOTE : here we use the form accepting a ClassDetails for the attribute type - // rather than the TypeDetails form used elsewhere for code coverage - - final DynamicFieldDetails firstNameMember = nameEmbeddableDetails.applyAttribute( - "first", - stringClassDetails, - false, - false, - buildingContext - ); - - final DynamicFieldDetails lastNameMember = nameEmbeddableDetails.applyAttribute( - "last", - stringClassDetails, - false, - false, - buildingContext - ); - - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // ENTITY - TheEntity - - final DynamicClassDetails entityDetails = (DynamicClassDetails) classDetailsRegistry.resolveClassDetails( - "TheEntity", - name -> { - final DynamicClassDetails classDetails = new DynamicClassDetails( name, buildingContext ); - final MutableAnnotationUsage entityUsage = classDetails.applyAnnotationUsage( JpaAnnotations.ENTITY, buildingContext ); - assertThat( entityUsage ).isNotNull(); - return classDetails; - } - ); - - final DynamicFieldDetails idMember = entityDetails.applyAttribute( - "id", - integerTypeDetails, - false, - false, - buildingContext - ); - final MutableAnnotationUsage idUsage = idMember.applyAnnotationUsage( JpaAnnotations.ID, buildingContext ); - assertThat( idUsage ).isNotNull(); - - final DynamicFieldDetails nameMember = entityDetails.applyAttribute( - "name", - new ClassTypeDetailsImpl( nameEmbeddableDetails, TypeDetails.Kind.CLASS ), - false, - false, - buildingContext - ); - final MutableAnnotationUsage embeddedUsage = nameMember.applyAnnotationUsage( JpaAnnotations.EMBEDDED, buildingContext ); - assertThat( embeddedUsage ).isNotNull(); - - - // ASSERTIONS - - assertThat( entityDetails.getFields() ).containsExactly( idMember, nameMember ); - checkPersistability( idMember ); - assertThat( idMember.hasAnnotationUsage( Id.class ) ).isTrue(); - checkPersistability( nameMember ); - assertThat( nameMember.hasAnnotationUsage( Embedded.class ) ).isTrue(); - - assertThat( nameEmbeddableDetails.getFields() ).containsExactly( firstNameMember, lastNameMember ); - checkPersistability( firstNameMember ); - checkPersistability( lastNameMember ); - } +// @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 ); +// +// // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// // EMBEDDABLE - TheName +// +// final DynamicClassDetails nameEmbeddableDetails = (DynamicClassDetails) classDetailsRegistry.resolveClassDetails( +// "TheName", +// name -> { +// final DynamicClassDetails classDetails = new DynamicClassDetails( name, buildingContext ); +// final Embeddable embeddableUsage = classDetails.applyAnnotationUsage( JpaAnnotations.EMBEDDABLE, buildingContext ); +// assertThat( embeddableUsage ).isNotNull(); +// return classDetails; +// } +// ); +// +// // NOTE : here we use the form accepting a ClassDetails for the attribute type +// // rather than the TypeDetails form used elsewhere for code coverage +// +// final DynamicFieldDetails firstNameMember = nameEmbeddableDetails.applyAttribute( +// "first", +// stringClassDetails, +// false, +// false, +// buildingContext +// ); +// +// final DynamicFieldDetails lastNameMember = nameEmbeddableDetails.applyAttribute( +// "last", +// stringClassDetails, +// false, +// false, +// buildingContext +// ); +// +// +// // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// // ENTITY - TheEntity +// +// final DynamicClassDetails entityDetails = (DynamicClassDetails) classDetailsRegistry.resolveClassDetails( +// "TheEntity", +// name -> { +// final DynamicClassDetails classDetails = new DynamicClassDetails( name, buildingContext ); +// final MutableAnnotationUsage entityUsage = classDetails.applyAnnotationUsage( JpaAnnotations.ENTITY, buildingContext ); +// assertThat( entityUsage ).isNotNull(); +// return classDetails; +// } +// ); +// +// final DynamicFieldDetails idMember = entityDetails.applyAttribute( +// "id", +// integerTypeDetails, +// false, +// false, +// buildingContext +// ); +// final MutableAnnotationUsage idUsage = idMember.applyAnnotationUsage( JpaAnnotations.ID, buildingContext ); +// assertThat( idUsage ).isNotNull(); +// +// final DynamicFieldDetails nameMember = entityDetails.applyAttribute( +// "name", +// new ClassTypeDetailsImpl( nameEmbeddableDetails, TypeDetails.Kind.CLASS ), +// false, +// false, +// buildingContext +// ); +// final MutableAnnotationUsage embeddedUsage = nameMember.applyAnnotationUsage( JpaAnnotations.EMBEDDED, buildingContext ); +// assertThat( embeddedUsage ).isNotNull(); +// +// +// // ASSERTIONS +// +// assertThat( entityDetails.getFields() ).containsExactly( idMember, nameMember ); +// checkPersistability( idMember ); +// assertThat( idMember.hasDirectAnnotationUsage( Id.class ) ).isTrue(); +// checkPersistability( nameMember ); +// assertThat( nameMember.hasDirectAnnotationUsage( Embedded.class ) ).isTrue(); +// +// assertThat( nameEmbeddableDetails.getFields() ).containsExactly( firstNameMember, lastNameMember ); +// checkPersistability( firstNameMember ); +// checkPersistability( lastNameMember ); +// } } diff --git a/src/test/java/org/hibernate/models/dynamic/ToAnnotationTest.java b/src/test/java/org/hibernate/models/dynamic/ToAnnotationTest.java deleted file mode 100644 index 17f9cab..0000000 --- a/src/test/java/org/hibernate/models/dynamic/ToAnnotationTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.hibernate.models.dynamic; - -import org.hibernate.models.internal.SourceModelBuildingContextImpl; -import org.hibernate.models.internal.dynamic.DynamicAnnotationUsage; -import org.hibernate.models.internal.dynamic.DynamicClassDetails; -import org.hibernate.models.orm.JpaAnnotations; - -import org.junit.jupiter.api.Test; - -import jakarta.persistence.JoinTable; - -import static org.hibernate.models.SourceModelTestHelper.createBuildingContext; - -public class ToAnnotationTest { - - @Test - void testAccessArrayOfAnnotations() { - final SourceModelBuildingContextImpl buildingContext = createBuildingContext(); - final DynamicClassDetails dynamicEntity = new DynamicClassDetails( "DynamicEntity", buildingContext ); - final DynamicAnnotationUsage generatorAnn = new DynamicAnnotationUsage<>( - JpaAnnotations.JOIN_TABLE, - buildingContext - ); - - JoinTable joinTableAnn = generatorAnn.toAnnotation(); - - joinTableAnn.indexes(); - } -} diff --git a/src/test/java/org/hibernate/models/orm/BasicAnnotation.java b/src/test/java/org/hibernate/models/orm/BasicAnnotation.java new file mode 100644 index 0000000..11fb10e --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/BasicAnnotation.java @@ -0,0 +1,67 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.Basic; +import jakarta.persistence.FetchType; + +import static org.hibernate.models.internal.jandex.JandexValueHelper.extractOptionalValue; +import static org.hibernate.models.orm.JpaAnnotations.BASIC; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class BasicAnnotation implements Basic { + private FetchType fetch; + private boolean optional; + + public BasicAnnotation() { + fetch = FetchType.EAGER; + optional = true; + } + + public BasicAnnotation(Basic usage, SourceModelBuildingContext modelContext) { + fetch = usage.fetch(); + optional = usage.optional(); + } + + public BasicAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + fetch = extractOptionalValue( usage, BASIC, "fetch", modelContext ); + optional = extractOptionalValue( usage, BASIC, "optional", modelContext ); + } + + @Override + public FetchType fetch() { + return fetch; + } + + public void fetch(FetchType fetch) { + this.fetch = fetch; + } + + @Override + public boolean optional() { + return optional; + } + + public void optional(boolean optional) { + this.optional = optional; + } + + @Override + public Class annotationType() { + return Basic.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/CacheableAnnotation.java b/src/test/java/org/hibernate/models/orm/CacheableAnnotation.java new file mode 100644 index 0000000..d36c083 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/CacheableAnnotation.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.Cacheable; + +import static org.hibernate.models.internal.jandex.JandexValueHelper.extractOptionalValue; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class CacheableAnnotation implements Cacheable { + private boolean value; + + public CacheableAnnotation() { + value = true; + } + + public CacheableAnnotation(Cacheable usage, SourceModelBuildingContext modelContext) { + value = usage.value(); + } + + public CacheableAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + value = extractOptionalValue( usage, JpaAnnotations.CACHEABLE, "value", modelContext ); + } + + @Override + public boolean value() { + return value; + } + + public void value(boolean value) { + this.value = value; + } + + @Override + public Class annotationType() { + return Cacheable.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/CheckConstraintAnnotation.java b/src/test/java/org/hibernate/models/orm/CheckConstraintAnnotation.java new file mode 100644 index 0000000..e865156 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/CheckConstraintAnnotation.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.CheckConstraint; + +import static org.hibernate.models.internal.jandex.JandexValueHelper.extractOptionalValue; +import static org.hibernate.models.orm.JpaAnnotations.CHECK_CONSTRAINT; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class CheckConstraintAnnotation implements CheckConstraint { + private String name; + private String constraint; + private String options; + + public CheckConstraintAnnotation() { + name = ""; + options = ""; + } + + public CheckConstraintAnnotation(CheckConstraint usage, SourceModelBuildingContext modelContext) { + this.name = usage.name(); + this.constraint = usage.constraint(); + this.options = usage.options(); + } + + public CheckConstraintAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + this.name = extractOptionalValue( usage, CHECK_CONSTRAINT, "name", modelContext ); + this.constraint = extractOptionalValue( usage, CHECK_CONSTRAINT, "constraint", modelContext ); + this.options = extractOptionalValue( usage, CHECK_CONSTRAINT, "options", modelContext ); + } + + @Override + public String name() { + return name; + } + + public void name(String name) { + this.name = name; + } + + @Override + public String constraint() { + assert constraint != null; + return constraint; + } + + public void constraint(String constraint) { + this.constraint = constraint; + } + + @Override + public String options() { + return options; + } + + public void options(String options) { + this.options = options; + } + + @Override + public Class annotationType() { + return CheckConstraint.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/ColumnAnnotation.java b/src/test/java/org/hibernate/models/orm/ColumnAnnotation.java new file mode 100644 index 0000000..086eb65 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/ColumnAnnotation.java @@ -0,0 +1,214 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.CheckConstraint; +import jakarta.persistence.Column; + +import static org.hibernate.models.internal.AnnotationUsageHelper.extractRepeatedValues; +import static org.hibernate.models.internal.jandex.JandexValueHelper.extractOptionalValue; +import static org.hibernate.models.orm.JpaAnnotations.COLUMN; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class ColumnAnnotation implements Column, ColumnDetails { + private String name; + private String table; + + private boolean nullable; + private boolean unique; + private boolean insertable; + private boolean updatable; + private String comment; + private String columnDefinition; + private String options; + private int length; + private int precision; + private int scale; + + private CheckConstraint[] check; + + public ColumnAnnotation() { + name = ""; + table = ""; + nullable = true; + unique = false; + insertable = true; + updatable = true; + comment = ""; + columnDefinition = ""; + options = ""; + length = 255; + precision = 0; + scale = 0; + check = new CheckConstraint[0]; + } + + public ColumnAnnotation(Column usage, SourceModelBuildingContext modelContext) { + name = usage.name(); + table = usage.table(); + nullable = usage.nullable(); + unique = usage.unique(); + insertable = usage.insertable(); + updatable = usage.updatable(); + comment = usage.comment(); + columnDefinition = usage.columnDefinition(); + options = usage.options(); + length = usage.length(); + precision = usage.precision(); + scale = usage.scale(); + check = extractRepeatedValues( usage, COLUMN.getAttribute( "check" ), modelContext ); + } + + public ColumnAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + name = extractOptionalValue( usage, COLUMN, "name", modelContext ); + table = extractOptionalValue( usage, COLUMN, "table", modelContext ); + nullable = extractOptionalValue( usage, COLUMN, "nullable", modelContext ); + unique = extractOptionalValue( usage, COLUMN, "unique", modelContext ); + insertable = extractOptionalValue( usage, COLUMN, "insertable", modelContext ); + updatable = extractOptionalValue( usage, COLUMN, "updatable", modelContext ); + comment = extractOptionalValue( usage, COLUMN, "comment", modelContext ); + columnDefinition = extractOptionalValue( usage, COLUMN, "columnDefinition", modelContext ); + options = extractOptionalValue( usage, COLUMN, "options", modelContext ); + length = extractOptionalValue( usage, COLUMN, "length", modelContext ); + precision = extractOptionalValue( usage, COLUMN, "precision", modelContext ); + scale = extractOptionalValue( usage, COLUMN, "scale", modelContext ); + check = extractOptionalValue( usage, COLUMN, "check", modelContext ); + } + + @Override + public String name() { + return name; + } + + public void name(String name) { + this.name = name; + } + + @Override + public String table() { + return table; + } + + public void table(String table) { + this.table = table; + } + + @Override + public boolean nullable() { + return nullable; + } + + public void nullable(boolean nullable) { + this.nullable = nullable; + } + + @Override + public boolean unique() { + return unique; + } + + public void unique(boolean unique) { + this.unique = unique; + } + + @Override + public boolean insertable() { + return insertable; + } + + public void insertable(boolean insertable) { + this.insertable = insertable; + } + + @Override + public boolean updatable() { + return updatable; + } + + public void updatable(boolean updatable) { + this.updatable = updatable; + } + + @Override + public String columnDefinition() { + return columnDefinition; + } + + public void columnDefinition(String columnDefinition) { + this.columnDefinition = columnDefinition; + } + + @Override + public String options() { + return options; + } + + public void options(String options) { + this.options = options; + } + + + @Override + public int length() { + return length; + } + + public void length(int length) { + this.length = length; + } + + @Override + public int precision() { + return precision; + } + + public void precision(int precision) { + this.precision = precision; + } + + @Override + public int scale() { + return scale; + } + + public void scale(int scale) { + this.scale = scale; + } + + @Override + public CheckConstraint[] check() { + return check; + } + + public void check(CheckConstraint[] check) { + this.check = check; + } + + @Override + public String comment() { + return comment; + } + + public void comment(String comment) { + this.comment = comment; + } + + @Override + public Class annotationType() { + return Column.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/ColumnDetails.java b/src/test/java/org/hibernate/models/orm/ColumnDetails.java new file mode 100644 index 0000000..baab12c --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/ColumnDetails.java @@ -0,0 +1,15 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +/** + * @author Steve Ebersole + */ +public interface ColumnDetails { + String name(); +} diff --git a/src/test/java/org/hibernate/models/orm/CommonTableDetails.java b/src/test/java/org/hibernate/models/orm/CommonTableDetails.java new file mode 100644 index 0000000..5bc77c7 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/CommonTableDetails.java @@ -0,0 +1,34 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import jakarta.persistence.Index; +import jakarta.persistence.UniqueConstraint; + +/** + * Information which is common across all table annotations + * + * @author Steve Ebersole + */ +public interface CommonTableDetails extends DatabaseObjectDetails { + /** + * The table name + */ + String name(); + + /** + * Setter for {@linkplain #name()} + */ + void name(String name); + + UniqueConstraint[] uniqueConstraints(); + void uniqueConstraints(UniqueConstraint[] uniqueConstraints); + + Index[] indexes(); + void indexes(Index[] indexes); +} diff --git a/src/test/java/org/hibernate/models/orm/DatabaseObjectDetails.java b/src/test/java/org/hibernate/models/orm/DatabaseObjectDetails.java new file mode 100644 index 0000000..d8fc364 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/DatabaseObjectDetails.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import jakarta.persistence.SequenceGenerator; + +/** + * Commonality for database objects + * + * @author Steve Ebersole + * @apiNote While they all have names, some use an attribute named something other + * than {@code name()} - e.g. {@linkplain SequenceGenerator#sequenceName()} + */ +public interface DatabaseObjectDetails { + /** + * The catalog in which the object exists + */ + String catalog(); + + /** + * Setter for {@linkplain #catalog()} + */ + void catalog(String catalog); + + /** + * The schema in which the object exists + */ + String schema(); + + /** + * Setter for {@linkplain #schema()} + */ + void schema(String schema); +} diff --git a/src/test/java/org/hibernate/models/orm/EntityAnnotation.java b/src/test/java/org/hibernate/models/orm/EntityAnnotation.java new file mode 100644 index 0000000..49bb907 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/EntityAnnotation.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationValue; + +import jakarta.persistence.Entity; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class EntityAnnotation implements Entity { + private String name; + + public EntityAnnotation() { + name = ""; + } + + public EntityAnnotation(Entity jdkAnnotation, SourceModelBuildingContext modelContext) { + this.name = jdkAnnotation.name(); + } + + public EntityAnnotation(AnnotationInstance jandexAnnotation, SourceModelBuildingContext modelContext) { + final AnnotationValue nameValue = jandexAnnotation.value( "name" ); + this.name = nameValue == null ? "" : nameValue.asString(); + } + + @Override + public String name() { + return name; + } + + public void name(String name) { + this.name = name; + } + + @Override + public Class annotationType() { + return Entity.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/ForeignKeyAnnotation.java b/src/test/java/org/hibernate/models/orm/ForeignKeyAnnotation.java new file mode 100644 index 0000000..adf2158 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/ForeignKeyAnnotation.java @@ -0,0 +1,93 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.internal.jandex.JandexValueHelper; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.ConstraintMode; +import jakarta.persistence.ForeignKey; + +import static org.hibernate.models.orm.JpaAnnotations.FOREIGN_KEY; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class ForeignKeyAnnotation implements ForeignKey { + private String name; + private ConstraintMode value; + private String foreignKeyDefinition; + private String options; + + public ForeignKeyAnnotation() { + name = ""; + value = ConstraintMode.CONSTRAINT; + foreignKeyDefinition = ""; + options = ""; + } + + public ForeignKeyAnnotation(ForeignKey usage, SourceModelBuildingContext modelContext) { + name = usage.name(); + value = usage.value(); + foreignKeyDefinition = usage.foreignKeyDefinition(); + options = usage.options(); + } + + public ForeignKeyAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + name = JandexValueHelper.extractValue( usage, FOREIGN_KEY.getAttribute( "name" ), modelContext ); + value = JandexValueHelper.extractValue( usage, FOREIGN_KEY.getAttribute( "value" ), modelContext ); + foreignKeyDefinition = JandexValueHelper.extractValue( usage, FOREIGN_KEY.getAttribute( "foreignKeyDefinition" ), modelContext ); + options = JandexValueHelper.extractValue( usage, FOREIGN_KEY.getAttribute( "options" ), modelContext ); + } + + @Override + public String name() { + return name; + } + + public void name(String name) { + this.name = name; + } + + @Override + public ConstraintMode value() { + return value; + } + + public void value(ConstraintMode value) { + this.value = value; + } + + @Override + public String foreignKeyDefinition() { + return foreignKeyDefinition; + } + + public void foreignKeyDefinition(String foreignKeyDefinition) { + this.foreignKeyDefinition = foreignKeyDefinition; + } + + @Override + public String options() { + return options; + } + + public void options(String options) { + this.options = options; + } + + @Override + public Class annotationType() { + return ForeignKey.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/IdAnnotation.java b/src/test/java/org/hibernate/models/orm/IdAnnotation.java new file mode 100644 index 0000000..d87c881 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/IdAnnotation.java @@ -0,0 +1,36 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.Id; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class IdAnnotation implements Id { + public IdAnnotation() { + } + + public IdAnnotation(Id jdkAnnotation, SourceModelBuildingContext modelContext) { + } + + public IdAnnotation(AnnotationInstance jandexAnnotation, SourceModelBuildingContext modelContext) { + } + + @Override + public Class annotationType() { + return Id.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/IndexAnnotation.java b/src/test/java/org/hibernate/models/orm/IndexAnnotation.java new file mode 100644 index 0000000..35ffcf1 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/IndexAnnotation.java @@ -0,0 +1,91 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.internal.jandex.JandexValueHelper; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.Index; + +import static org.hibernate.models.orm.JpaAnnotations.INDEX; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class IndexAnnotation implements Index { + private String name; + private String columnList; + private boolean unique; + private String options; + + public IndexAnnotation() { + name = ""; + unique = false; + options = ""; + } + + public IndexAnnotation(Index usage, SourceModelBuildingContext modelContext) { + name = usage.name(); + columnList = usage.columnList(); + unique = usage.unique(); + options = usage.options(); + } + + public IndexAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + name = JandexValueHelper.extractValue( usage, INDEX.getAttribute( "name" ), modelContext ); + columnList = JandexValueHelper.extractValue( usage, INDEX.getAttribute( "columnList" ), modelContext ); + unique = JandexValueHelper.extractValue( usage, INDEX.getAttribute( "unique" ), modelContext ); + options = JandexValueHelper.extractValue( usage, INDEX.getAttribute( "options" ), modelContext ); + } + + @Override + public String name() { + return name; + } + + public void name(String name) { + this.name = name; + } + + @Override + public String columnList() { + return columnList; + } + + public void columnList(String columnList) { + this.columnList = columnList; + } + + @Override + public boolean unique() { + return unique; + } + + public void unique(boolean unique) { + this.unique = unique; + } + + @Override + public String options() { + return options; + } + + public void options(String options) { + this.options = options; + } + + @Override + public Class annotationType() { + return Index.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/JpaAnnotations.java b/src/test/java/org/hibernate/models/orm/JpaAnnotations.java index 68940b0..9508b66 100644 --- a/src/test/java/org/hibernate/models/orm/JpaAnnotations.java +++ b/src/test/java/org/hibernate/models/orm/JpaAnnotations.java @@ -9,190 +9,149 @@ import java.lang.annotation.Annotation; import java.util.function.Consumer; +import org.hibernate.models.internal.OrmAnnotationDescriptor; import org.hibernate.models.spi.AnnotationDescriptor; -import jakarta.persistence.Access; -import jakarta.persistence.AssociationOverride; -import jakarta.persistence.AssociationOverrides; -import jakarta.persistence.AttributeOverride; -import jakarta.persistence.AttributeOverrides; import jakarta.persistence.Basic; import jakarta.persistence.Cacheable; import jakarta.persistence.CheckConstraint; -import jakarta.persistence.CollectionTable; import jakarta.persistence.Column; -import jakarta.persistence.ColumnResult; -import jakarta.persistence.Convert; -import jakarta.persistence.Converter; -import jakarta.persistence.Converts; -import jakarta.persistence.DiscriminatorColumn; -import jakarta.persistence.DiscriminatorValue; -import jakarta.persistence.ElementCollection; -import jakarta.persistence.Embeddable; -import jakarta.persistence.Embedded; -import jakarta.persistence.EmbeddedId; import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.EntityResult; -import jakarta.persistence.Enumerated; -import jakarta.persistence.ExcludeDefaultListeners; -import jakarta.persistence.ExcludeSuperclassListeners; -import jakarta.persistence.FieldResult; import jakarta.persistence.ForeignKey; -import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; -import jakarta.persistence.IdClass; import jakarta.persistence.Index; -import jakarta.persistence.Inheritance; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.JoinColumns; -import jakarta.persistence.JoinTable; -import jakarta.persistence.Lob; -import jakarta.persistence.ManyToMany; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.MapKey; -import jakarta.persistence.MapKeyClass; -import jakarta.persistence.MapKeyColumn; -import jakarta.persistence.MapKeyEnumerated; -import jakarta.persistence.MapKeyJoinColumn; -import jakarta.persistence.MapKeyJoinColumns; -import jakarta.persistence.MapKeyTemporal; -import jakarta.persistence.MappedSuperclass; -import jakarta.persistence.MapsId; -import jakarta.persistence.NamedAttributeNode; -import jakarta.persistence.NamedEntityGraph; -import jakarta.persistence.NamedEntityGraphs; import jakarta.persistence.NamedNativeQueries; import jakarta.persistence.NamedNativeQuery; import jakarta.persistence.NamedQueries; import jakarta.persistence.NamedQuery; -import jakarta.persistence.NamedStoredProcedureQueries; -import jakarta.persistence.NamedStoredProcedureQuery; -import jakarta.persistence.NamedSubgraph; -import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; -import jakarta.persistence.OrderBy; -import jakarta.persistence.OrderColumn; -import jakarta.persistence.PostLoad; -import jakarta.persistence.PostPersist; -import jakarta.persistence.PostRemove; -import jakarta.persistence.PostUpdate; -import jakarta.persistence.PrePersist; -import jakarta.persistence.PreRemove; -import jakarta.persistence.PreUpdate; -import jakarta.persistence.PrimaryKeyJoinColumn; -import jakarta.persistence.PrimaryKeyJoinColumns; -import jakarta.persistence.QueryHint; import jakarta.persistence.SecondaryTable; import jakarta.persistence.SecondaryTables; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.SequenceGenerators; -import jakarta.persistence.SqlResultSetMapping; -import jakarta.persistence.SqlResultSetMappings; -import jakarta.persistence.StoredProcedureParameter; import jakarta.persistence.Table; -import jakarta.persistence.TableGenerator; -import jakarta.persistence.TableGenerators; -import jakarta.persistence.Temporal; -import jakarta.persistence.Transient; import jakarta.persistence.UniqueConstraint; -import jakarta.persistence.Version; - -import static org.hibernate.models.internal.AnnotationHelper.createOrmDescriptor; /** * Descriptors for JPA annotations * * @author Steve Ebersole */ -@SuppressWarnings({ "unused", "deprecation" }) +@SuppressWarnings("unused") public interface JpaAnnotations { - AnnotationDescriptor ACCESS = createOrmDescriptor( Access.class ); - AnnotationDescriptor ASSOCIATION_OVERRIDES = createOrmDescriptor( AssociationOverrides.class ); - AnnotationDescriptor ASSOCIATION_OVERRIDE = createOrmDescriptor( AssociationOverride.class, ASSOCIATION_OVERRIDES ); - AnnotationDescriptor ATTRIBUTE_OVERRIDES = createOrmDescriptor( AttributeOverrides.class ); - AnnotationDescriptor ATTRIBUTE_OVERRIDE = createOrmDescriptor( AttributeOverride.class, ATTRIBUTE_OVERRIDES ); - AnnotationDescriptor BASIC = createOrmDescriptor( Basic.class ); - AnnotationDescriptor CACHEABLE = createOrmDescriptor( Cacheable.class ); - AnnotationDescriptor COLLECTION_TABLE = createOrmDescriptor( CollectionTable.class ); - AnnotationDescriptor COLUMN = createOrmDescriptor( Column.class ); - AnnotationDescriptor COLUMN_RESULT = createOrmDescriptor( ColumnResult.class ); - AnnotationDescriptor CONVERTS = createOrmDescriptor( Converts.class ); - AnnotationDescriptor CONVERT = createOrmDescriptor( Convert.class, CONVERTS ); - AnnotationDescriptor CONVERTER = createOrmDescriptor( Converter.class ); - AnnotationDescriptor DISCRIMINATOR_COLUMN = createOrmDescriptor( DiscriminatorColumn.class ); - AnnotationDescriptor DISCRIMINATOR_VALUE = createOrmDescriptor( DiscriminatorValue.class ); - AnnotationDescriptor ELEMENT_COLLECTION = createOrmDescriptor( ElementCollection.class ); - AnnotationDescriptor EMBEDDABLE = createOrmDescriptor( Embeddable.class ); - AnnotationDescriptor EMBEDDED = createOrmDescriptor( Embedded.class ); - AnnotationDescriptor EMBEDDED_ID = createOrmDescriptor( EmbeddedId.class ); - AnnotationDescriptor ENTITY = createOrmDescriptor( Entity.class ); - AnnotationDescriptor ENTITY_LISTENERS = createOrmDescriptor( EntityListeners.class ); - AnnotationDescriptor ENTITY_RESULT = createOrmDescriptor( EntityResult.class ); - AnnotationDescriptor ENUMERATED = createOrmDescriptor( Enumerated.class ); - AnnotationDescriptor EXCLUDE_DEFAULT_LISTENERS = createOrmDescriptor( ExcludeDefaultListeners.class ); - AnnotationDescriptor EXCLUDE_SUPERCLASS_LISTENERS = createOrmDescriptor( ExcludeSuperclassListeners.class ); - AnnotationDescriptor FIELD_RESULT = createOrmDescriptor( FieldResult.class ); - AnnotationDescriptor FOREIGN_KEY = createOrmDescriptor( ForeignKey.class ); - AnnotationDescriptor GENERATED_VALUE = createOrmDescriptor( GeneratedValue.class ); - AnnotationDescriptor ID = createOrmDescriptor( Id.class ); - AnnotationDescriptor ID_CLASS = createOrmDescriptor( IdClass.class ); - AnnotationDescriptor INDEX = createOrmDescriptor( Index.class ); - AnnotationDescriptor INHERITANCE = createOrmDescriptor( Inheritance.class ); - AnnotationDescriptor JOIN_COLUMNS = createOrmDescriptor( JoinColumns.class ); - AnnotationDescriptor JOIN_COLUMN = createOrmDescriptor( JoinColumn.class, JOIN_COLUMNS ); - AnnotationDescriptor JOIN_TABLE = createOrmDescriptor( JoinTable.class ); - AnnotationDescriptor LOB = createOrmDescriptor( Lob.class ); - AnnotationDescriptor MANY_TO_MANY = createOrmDescriptor( ManyToMany.class ); - AnnotationDescriptor MANY_TO_ONE = createOrmDescriptor( ManyToOne.class ); - AnnotationDescriptor MAP_KEY = createOrmDescriptor( MapKey.class ); - AnnotationDescriptor MAP_KEY_CLASS = createOrmDescriptor( MapKeyClass.class ); - AnnotationDescriptor MAP_KEY_COLUMN = createOrmDescriptor( MapKeyColumn.class ); - AnnotationDescriptor MAP_KEY_ENUMERATED = createOrmDescriptor( MapKeyEnumerated.class ); - AnnotationDescriptor MAP_KEY_JOIN_COLUMNS = createOrmDescriptor( MapKeyJoinColumns.class ); - AnnotationDescriptor MAP_KEY_JOIN_COLUMN = createOrmDescriptor( MapKeyJoinColumn.class, MAP_KEY_JOIN_COLUMNS ); - AnnotationDescriptor MAP_KEY_TEMPORAL = createOrmDescriptor( MapKeyTemporal.class ); - AnnotationDescriptor MAPPED_SUPERCLASS = createOrmDescriptor( MappedSuperclass.class ); - AnnotationDescriptor MAPS_ID = createOrmDescriptor( MapsId.class ); - AnnotationDescriptor NAMED_ATTRIBUTE_NODE = createOrmDescriptor( NamedAttributeNode.class ); - AnnotationDescriptor NAMED_ENTITY_GRAPHS = createOrmDescriptor( NamedEntityGraphs.class ); - AnnotationDescriptor NAMED_ENTITY_GRAPH = createOrmDescriptor( NamedEntityGraph.class, NAMED_ENTITY_GRAPHS ); - AnnotationDescriptor NAMED_NATIVE_QUERIES = createOrmDescriptor( NamedNativeQueries.class ); - AnnotationDescriptor NAMED_NATIVE_QUERY = createOrmDescriptor( NamedNativeQuery.class, NAMED_NATIVE_QUERIES ); - AnnotationDescriptor NAMED_QUERIES = createOrmDescriptor( NamedQueries.class ); - AnnotationDescriptor NAMED_QUERY = createOrmDescriptor( NamedQuery.class, NAMED_QUERIES ); - AnnotationDescriptor NAMED_STORED_PROCEDURE_QUERIES = createOrmDescriptor( NamedStoredProcedureQueries.class ); - AnnotationDescriptor NAMED_STORED_PROCEDURE_QUERY = createOrmDescriptor( NamedStoredProcedureQuery.class, NAMED_STORED_PROCEDURE_QUERIES ); - AnnotationDescriptor NAMED_SUB_GRAPH = createOrmDescriptor( NamedSubgraph.class ); - AnnotationDescriptor ONE_TO_MANY = createOrmDescriptor( OneToMany.class ); - AnnotationDescriptor ONE_TO_ONE = createOrmDescriptor( OneToOne.class ); - AnnotationDescriptor ORDER_BY = createOrmDescriptor( OrderBy.class ); - AnnotationDescriptor ORDER_COLUMN = createOrmDescriptor( OrderColumn.class ); - AnnotationDescriptor POST_LOAD = createOrmDescriptor( PostLoad.class ); - AnnotationDescriptor POST_PERSIST = createOrmDescriptor( PostPersist.class ); - AnnotationDescriptor POST_REMOVE = createOrmDescriptor( PostRemove.class ); - AnnotationDescriptor POST_UPDATE = createOrmDescriptor( PostUpdate.class ); - AnnotationDescriptor PRE_PERSIST = createOrmDescriptor( PrePersist.class ); - AnnotationDescriptor PRE_REMOVE = createOrmDescriptor( PreRemove.class ); - AnnotationDescriptor PRE_UPDATE = createOrmDescriptor( PreUpdate.class ); - AnnotationDescriptor PRIMARY_KEY_JOIN_COLUMNS = createOrmDescriptor( PrimaryKeyJoinColumns.class ); - AnnotationDescriptor PRIMARY_KEY_JOIN_COLUMN = createOrmDescriptor( PrimaryKeyJoinColumn.class, PRIMARY_KEY_JOIN_COLUMNS ); - AnnotationDescriptor QUERY_HINT = createOrmDescriptor( QueryHint.class ); - AnnotationDescriptor SECONDARY_TABLES = createOrmDescriptor( SecondaryTables.class ); - AnnotationDescriptor SECONDARY_TABLE = createOrmDescriptor( SecondaryTable.class, SECONDARY_TABLES ); - AnnotationDescriptor SEQUENCE_GENERATORS = createOrmDescriptor( SequenceGenerators.class ); - AnnotationDescriptor SEQUENCE_GENERATOR = createOrmDescriptor( SequenceGenerator.class, SEQUENCE_GENERATORS ); - AnnotationDescriptor SQL_RESULT_SET_MAPPINGS = createOrmDescriptor( SqlResultSetMappings.class ); - AnnotationDescriptor SQL_RESULT_SET_MAPPING = createOrmDescriptor( SqlResultSetMapping.class, SQL_RESULT_SET_MAPPINGS ); - AnnotationDescriptor STORED_PROCEDURE_PARAMETER = createOrmDescriptor( StoredProcedureParameter.class ); - AnnotationDescriptor
    TABLE = createOrmDescriptor( Table.class ); - AnnotationDescriptor CHECK_CONSTRAINT = createOrmDescriptor( CheckConstraint.class ); - AnnotationDescriptor TABLE_GENERATORS = createOrmDescriptor( TableGenerators.class ); - AnnotationDescriptor TABLE_GENERATOR = createOrmDescriptor( TableGenerator.class, TABLE_GENERATORS ); - AnnotationDescriptor TEMPORAL = createOrmDescriptor( Temporal.class ); - AnnotationDescriptor TRANSIENT = createOrmDescriptor( Transient.class ); - AnnotationDescriptor UNIQUE_CONSTRAINT = createOrmDescriptor( UniqueConstraint.class ); - AnnotationDescriptor VERSION = createOrmDescriptor( Version.class ); + AnnotationDescriptor ENTITY = new OrmAnnotationDescriptor<>( Entity.class, EntityAnnotation.class ); + + AnnotationDescriptor ID = new OrmAnnotationDescriptor<>( Id.class, IdAnnotation.class ); + + AnnotationDescriptor SEQUENCE_GENERATORS = new OrmAnnotationDescriptor<>( SequenceGenerators.class, SequenceGeneratorsAnnotation.class ); + AnnotationDescriptor SEQUENCE_GENERATOR = new OrmAnnotationDescriptor<>( SequenceGenerator.class, SequenceGeneratorAnnotation.class, SEQUENCE_GENERATORS ); + + AnnotationDescriptor COLUMN = new OrmAnnotationDescriptor<>( Column.class, ColumnAnnotation.class ); + + AnnotationDescriptor BASIC = new OrmAnnotationDescriptor<>( Basic.class, BasicAnnotation.class ); + + AnnotationDescriptor NAMED_QUERIES = new OrmAnnotationDescriptor<>( NamedQueries.class, NamedQueriesAnnotation.class ); + AnnotationDescriptor NAMED_QUERY = new OrmAnnotationDescriptor<>( NamedQuery.class, NamedQueryAnnotation.class, NAMED_QUERIES ); + + AnnotationDescriptor NAMED_NATIVE_QUERIES = new OrmAnnotationDescriptor<>( NamedNativeQueries.class, NamedNativeQueriesAnnotation.class ); + AnnotationDescriptor NAMED_NATIVE_QUERY = new OrmAnnotationDescriptor<>( NamedNativeQuery.class, NamedNativeQueryAnnotation.class, NAMED_NATIVE_QUERIES ); + + AnnotationDescriptor
    TABLE = new OrmAnnotationDescriptor<>( Table.class, TableAnnotation.class ); + AnnotationDescriptor SECONDARY_TABLES = new OrmAnnotationDescriptor<>( SecondaryTables.class, SecondaryTablesAnnotation.class ); + AnnotationDescriptor SECONDARY_TABLE = new OrmAnnotationDescriptor<>( SecondaryTable.class, SecondaryTableAnnotation.class, SECONDARY_TABLES ); + + AnnotationDescriptor CHECK_CONSTRAINT = new OrmAnnotationDescriptor<>( CheckConstraint.class, CheckConstraintAnnotation.class ); + AnnotationDescriptor FOREIGN_KEY = new OrmAnnotationDescriptor<>( ForeignKey.class, ForeignKeyAnnotation.class ); + AnnotationDescriptor UNIQUE_CONSTRAINT = new OrmAnnotationDescriptor<>( UniqueConstraint.class, UniqueConstraintAnnotation.class ); + AnnotationDescriptor INDEX = new OrmAnnotationDescriptor<>( Index.class, IndexAnnotation.class ); + + AnnotationDescriptor CACHEABLE = new OrmAnnotationDescriptor<>( Cacheable.class, CacheableAnnotation.class ); + +// AnnotationDescriptor ACCESS = createOrmDescriptor( Access.class ); +// AnnotationDescriptor ASSOCIATION_OVERRIDES = createOrmDescriptor( AssociationOverrides.class ); +// AnnotationDescriptor ASSOCIATION_OVERRIDE = createOrmDescriptor( AssociationOverride.class, ASSOCIATION_OVERRIDES ); +// AnnotationDescriptor ATTRIBUTE_OVERRIDES = createOrmDescriptor( AttributeOverrides.class ); +// AnnotationDescriptor ATTRIBUTE_OVERRIDE = createOrmDescriptor( AttributeOverride.class, ATTRIBUTE_OVERRIDES ); +// AnnotationDescriptor BASIC = createOrmDescriptor( Basic.class ); +// AnnotationDescriptor CACHEABLE = createOrmDescriptor( Cacheable.class ); +// AnnotationDescriptor COLLECTION_TABLE = createOrmDescriptor( CollectionTable.class ); +// AnnotationDescriptor COLUMN = createOrmDescriptor( Column.class ); +// AnnotationDescriptor COLUMN_RESULT = createOrmDescriptor( ColumnResult.class ); +// AnnotationDescriptor CONVERTS = createOrmDescriptor( Converts.class ); +// AnnotationDescriptor CONVERT = createOrmDescriptor( Convert.class, CONVERTS ); +// AnnotationDescriptor CONVERTER = createOrmDescriptor( Converter.class ); +// AnnotationDescriptor DISCRIMINATOR_COLUMN = createOrmDescriptor( DiscriminatorColumn.class ); +// AnnotationDescriptor DISCRIMINATOR_VALUE = createOrmDescriptor( DiscriminatorValue.class ); +// AnnotationDescriptor ELEMENT_COLLECTION = createOrmDescriptor( ElementCollection.class ); +// AnnotationDescriptor EMBEDDABLE = createOrmDescriptor( Embeddable.class ); +// AnnotationDescriptor EMBEDDED = createOrmDescriptor( Embedded.class ); +// AnnotationDescriptor EMBEDDED_ID = createOrmDescriptor( EmbeddedId.class ); +// AnnotationDescriptor ENTITY = createOrmDescriptor( Entity.class ); +// AnnotationDescriptor ENTITY_LISTENERS = createOrmDescriptor( EntityListeners.class ); +// AnnotationDescriptor ENTITY_RESULT = createOrmDescriptor( EntityResult.class ); +// AnnotationDescriptor ENUMERATED = createOrmDescriptor( Enumerated.class ); +// AnnotationDescriptor EXCLUDE_DEFAULT_LISTENERS = createOrmDescriptor( ExcludeDefaultListeners.class ); +// AnnotationDescriptor EXCLUDE_SUPERCLASS_LISTENERS = createOrmDescriptor( ExcludeSuperclassListeners.class ); +// AnnotationDescriptor FIELD_RESULT = createOrmDescriptor( FieldResult.class ); +// AnnotationDescriptor FOREIGN_KEY = createOrmDescriptor( ForeignKey.class ); +// AnnotationDescriptor GENERATED_VALUE = createOrmDescriptor( GeneratedValue.class ); +// AnnotationDescriptor ID = createOrmDescriptor( Id.class ); +// AnnotationDescriptor ID_CLASS = createOrmDescriptor( IdClass.class ); +// AnnotationDescriptor INDEX = createOrmDescriptor( Index.class ); +// AnnotationDescriptor INHERITANCE = createOrmDescriptor( Inheritance.class ); +// AnnotationDescriptor JOIN_COLUMNS = createOrmDescriptor( JoinColumns.class ); +// AnnotationDescriptor JOIN_COLUMN = createOrmDescriptor( JoinColumn.class, JOIN_COLUMNS ); +// AnnotationDescriptor JOIN_TABLE = createOrmDescriptor( JoinTable.class ); +// AnnotationDescriptor LOB = createOrmDescriptor( Lob.class ); +// AnnotationDescriptor MANY_TO_MANY = createOrmDescriptor( ManyToMany.class ); +// AnnotationDescriptor MANY_TO_ONE = createOrmDescriptor( ManyToOne.class ); +// AnnotationDescriptor MAP_KEY = createOrmDescriptor( MapKey.class ); +// AnnotationDescriptor MAP_KEY_CLASS = createOrmDescriptor( MapKeyClass.class ); +// AnnotationDescriptor MAP_KEY_COLUMN = createOrmDescriptor( MapKeyColumn.class ); +// AnnotationDescriptor MAP_KEY_ENUMERATED = createOrmDescriptor( MapKeyEnumerated.class ); +// AnnotationDescriptor MAP_KEY_JOIN_COLUMNS = createOrmDescriptor( MapKeyJoinColumns.class ); +// AnnotationDescriptor MAP_KEY_JOIN_COLUMN = createOrmDescriptor( MapKeyJoinColumn.class, MAP_KEY_JOIN_COLUMNS ); +// AnnotationDescriptor MAP_KEY_TEMPORAL = createOrmDescriptor( MapKeyTemporal.class ); +// AnnotationDescriptor MAPPED_SUPERCLASS = createOrmDescriptor( MappedSuperclass.class ); +// AnnotationDescriptor MAPS_ID = createOrmDescriptor( MapsId.class ); +// AnnotationDescriptor NAMED_ATTRIBUTE_NODE = createOrmDescriptor( NamedAttributeNode.class ); +// AnnotationDescriptor NAMED_ENTITY_GRAPHS = createOrmDescriptor( NamedEntityGraphs.class ); +// AnnotationDescriptor NAMED_ENTITY_GRAPH = createOrmDescriptor( NamedEntityGraph.class, NAMED_ENTITY_GRAPHS ); +// AnnotationDescriptor NAMED_NATIVE_QUERIES = createOrmDescriptor( NamedNativeQueries.class ); +// AnnotationDescriptor NAMED_NATIVE_QUERY = createOrmDescriptor( NamedNativeQuery.class, NAMED_NATIVE_QUERIES ); +// AnnotationDescriptor NAMED_QUERIES = createOrmDescriptor( NamedQueries.class ); +// AnnotationDescriptor NAMED_QUERY = createOrmDescriptor( NamedQuery.class, NAMED_QUERIES ); +// AnnotationDescriptor NAMED_STORED_PROCEDURE_QUERIES = createOrmDescriptor( NamedStoredProcedureQueries.class ); +// AnnotationDescriptor NAMED_STORED_PROCEDURE_QUERY = createOrmDescriptor( NamedStoredProcedureQuery.class, NAMED_STORED_PROCEDURE_QUERIES ); +// AnnotationDescriptor NAMED_SUB_GRAPH = createOrmDescriptor( NamedSubgraph.class ); +// AnnotationDescriptor ONE_TO_MANY = createOrmDescriptor( OneToMany.class ); +// AnnotationDescriptor ONE_TO_ONE = createOrmDescriptor( OneToOne.class ); +// AnnotationDescriptor ORDER_BY = createOrmDescriptor( OrderBy.class ); +// AnnotationDescriptor ORDER_COLUMN = createOrmDescriptor( OrderColumn.class ); +// AnnotationDescriptor POST_LOAD = createOrmDescriptor( PostLoad.class ); +// AnnotationDescriptor POST_PERSIST = createOrmDescriptor( PostPersist.class ); +// AnnotationDescriptor POST_REMOVE = createOrmDescriptor( PostRemove.class ); +// AnnotationDescriptor POST_UPDATE = createOrmDescriptor( PostUpdate.class ); +// AnnotationDescriptor PRE_PERSIST = createOrmDescriptor( PrePersist.class ); +// AnnotationDescriptor PRE_REMOVE = createOrmDescriptor( PreRemove.class ); +// AnnotationDescriptor PRE_UPDATE = createOrmDescriptor( PreUpdate.class ); +// AnnotationDescriptor PRIMARY_KEY_JOIN_COLUMNS = createOrmDescriptor( PrimaryKeyJoinColumns.class ); +// AnnotationDescriptor PRIMARY_KEY_JOIN_COLUMN = createOrmDescriptor( PrimaryKeyJoinColumn.class, PRIMARY_KEY_JOIN_COLUMNS ); +// AnnotationDescriptor QUERY_HINT = createOrmDescriptor( QueryHint.class ); +// AnnotationDescriptor SECONDARY_TABLES = createOrmDescriptor( SecondaryTables.class ); +// AnnotationDescriptor SECONDARY_TABLE = createOrmDescriptor( SecondaryTable.class, SECONDARY_TABLES ); +// AnnotationDescriptor SEQUENCE_GENERATORS = createOrmDescriptor( SequenceGenerators.class ); +// AnnotationDescriptor SEQUENCE_GENERATOR = createOrmDescriptor( SequenceGenerator.class, SEQUENCE_GENERATORS ); +// AnnotationDescriptor SQL_RESULT_SET_MAPPINGS = createOrmDescriptor( SqlResultSetMappings.class ); +// AnnotationDescriptor SQL_RESULT_SET_MAPPING = createOrmDescriptor( SqlResultSetMapping.class, SQL_RESULT_SET_MAPPINGS ); +// AnnotationDescriptor STORED_PROCEDURE_PARAMETER = createOrmDescriptor( StoredProcedureParameter.class ); +// AnnotationDescriptor
    TABLE = createOrmDescriptor( Table.class ); +// AnnotationDescriptor CHECK_CONSTRAINT = createOrmDescriptor( CheckConstraint.class ); +// AnnotationDescriptor TABLE_GENERATORS = createOrmDescriptor( TableGenerators.class ); +// AnnotationDescriptor TABLE_GENERATOR = createOrmDescriptor( TableGenerator.class, TABLE_GENERATORS ); +// AnnotationDescriptor TEMPORAL = createOrmDescriptor( Temporal.class ); +// AnnotationDescriptor TRANSIENT = createOrmDescriptor( Transient.class ); +// AnnotationDescriptor UNIQUE_CONSTRAINT = createOrmDescriptor( UniqueConstraint.class ); +// AnnotationDescriptor VERSION = createOrmDescriptor( Version.class ); static void forEachAnnotation(Consumer> consumer) { OrmAnnotationHelper.forEachOrmAnnotation( JpaAnnotations.class, consumer ); diff --git a/src/test/java/org/hibernate/models/orm/Named.java b/src/test/java/org/hibernate/models/orm/Named.java new file mode 100644 index 0000000..b2b1692 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/Named.java @@ -0,0 +1,16 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +/** + * @author Steve Ebersole + */ +public interface Named { + String name(); + void name(String name); +} diff --git a/src/test/java/org/hibernate/models/orm/NamedNativeQueriesAnnotation.java b/src/test/java/org/hibernate/models/orm/NamedNativeQueriesAnnotation.java new file mode 100644 index 0000000..2b0efde --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/NamedNativeQueriesAnnotation.java @@ -0,0 +1,55 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.internal.AnnotationUsageHelper; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.NamedNativeQueries; +import jakarta.persistence.NamedNativeQuery; + +import static org.hibernate.models.orm.JpaAnnotations.NAMED_NATIVE_QUERIES; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class NamedNativeQueriesAnnotation implements NamedNativeQueries, RepeatableContainer { + private NamedNativeQuery[] value; + + public NamedNativeQueriesAnnotation() { + value = new NamedNativeQuery[0]; + } + + public NamedNativeQueriesAnnotation(NamedNativeQueries usage, SourceModelBuildingContext modelContext) { + value = AnnotationUsageHelper.extractRepeatedValues( usage, NAMED_NATIVE_QUERIES, modelContext ); + } + + public NamedNativeQueriesAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + value = AnnotationUsageHelper.extractRepeatedValues( usage, NAMED_NATIVE_QUERIES, modelContext ); + } + + @Override + public NamedNativeQuery[] value() { + return value; + } + + @Override + public void value(NamedNativeQuery[] value) { + this.value = value; + } + + @Override + public Class annotationType() { + return NamedNativeQueries.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/NamedNativeQueryAnnotation.java b/src/test/java/org/hibernate/models/orm/NamedNativeQueryAnnotation.java new file mode 100644 index 0000000..ac9180f --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/NamedNativeQueryAnnotation.java @@ -0,0 +1,155 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.ColumnResult; +import jakarta.persistence.ConstructorResult; +import jakarta.persistence.EntityResult; +import jakarta.persistence.NamedNativeQuery; +import jakarta.persistence.QueryHint; + +import static org.hibernate.models.internal.AnnotationUsageHelper.extractRepeatedValues; +import static org.hibernate.models.internal.jandex.JandexValueHelper.extractOptionalValue; +import static org.hibernate.models.internal.jandex.JandexValueHelper.extractValue; +import static org.hibernate.models.orm.JpaAnnotations.NAMED_NATIVE_QUERY; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class NamedNativeQueryAnnotation implements NamedNativeQuery, Named { + private String name; + private String query; + + private Class resultClass; + private String resultSetMapping; + private EntityResult[] entityResults; + private ConstructorResult[] constructorResults; + private ColumnResult[] columnResults; + + private QueryHint[] hints; + + public NamedNativeQueryAnnotation() { + resultClass = void.class; + resultSetMapping = ""; + entityResults = new EntityResult[0]; + constructorResults = new ConstructorResult[0]; + columnResults = new ColumnResult[0]; + hints = new QueryHint[0]; + } + + public NamedNativeQueryAnnotation(NamedNativeQuery usage, SourceModelBuildingContext modelContext) { + name = usage.name(); + query = usage.query(); + + resultClass = usage.resultClass(); + resultSetMapping = usage.resultSetMapping(); + entityResults = extractRepeatedValues( usage, NAMED_NATIVE_QUERY.getAttribute( "entities" ), modelContext ); + constructorResults = extractRepeatedValues( usage, NAMED_NATIVE_QUERY.getAttribute( "classes" ), modelContext ); + columnResults = extractRepeatedValues( usage, NAMED_NATIVE_QUERY.getAttribute( "columns" ), modelContext ); + + hints = extractRepeatedValues( usage, NAMED_NATIVE_QUERY.getAttribute( "hints" ), modelContext ); + } + + public NamedNativeQueryAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + name = usage.value( "name" ).asString(); + query = usage.value( "query" ).asString(); + + resultClass = extractValue( usage, NAMED_NATIVE_QUERY.getAttribute( "resultClass" ), modelContext ); + resultSetMapping = extractOptionalValue( usage, NAMED_NATIVE_QUERY.getAttribute( "resultSetMapping" ), modelContext ); + entityResults = extractRepeatedValues( usage, NAMED_NATIVE_QUERY.getAttribute( "entities" ), modelContext ); + constructorResults = extractRepeatedValues( usage, NAMED_NATIVE_QUERY.getAttribute( "classes" ), modelContext ); + columnResults = extractRepeatedValues( usage, NAMED_NATIVE_QUERY.getAttribute( "columns" ), modelContext ); + + hints = extractRepeatedValues( usage, NAMED_NATIVE_QUERY.getAttribute( "hints" ), modelContext ); + } + + @Override + public String name() { + return name; + } + + @Override + public void name(String name) { + this.name = name; + } + + @Override + public String query() { + return query; + } + + public void query(String query) { + this.query = query; + } + + @Override + public QueryHint[] hints() { + return hints; + } + + public void hints(QueryHint[] hints) { + this.hints = hints; + } + + @Override + public Class resultClass() { + return resultClass; + } + + public void resultClass(Class resultClass) { + this.resultClass = resultClass; + } + + @Override + public String resultSetMapping() { + return resultSetMapping; + } + + public void resultSetMapping(String resultSetMapping) { + this.resultSetMapping = resultSetMapping; + } + + @Override + public EntityResult[] entities() { + return entityResults; + } + + public void entities(EntityResult[] entityResults) { + this.entityResults = entityResults; + } + + @Override + public ConstructorResult[] classes() { + return constructorResults; + } + + public void classes(ConstructorResult[] constructorResults) { + this.constructorResults = constructorResults; + } + + @Override + public ColumnResult[] columns() { + return columnResults; + } + + public void columns(ColumnResult[] columnResults) { + this.columnResults = columnResults; + } + + @Override + public Class annotationType() { + return NamedNativeQuery.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/NamedQueriesAnnotation.java b/src/test/java/org/hibernate/models/orm/NamedQueriesAnnotation.java new file mode 100644 index 0000000..91f2b31 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/NamedQueriesAnnotation.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.internal.AnnotationUsageHelper; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.NamedQueries; +import jakarta.persistence.NamedQuery; + +import static org.hibernate.models.orm.JpaAnnotations.NAMED_QUERIES; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class NamedQueriesAnnotation implements NamedQueries, RepeatableContainer { + private NamedQuery[] value; + + public NamedQueriesAnnotation() { + } + + public NamedQueriesAnnotation(NamedQueries usage, SourceModelBuildingContext modelContext) { + value = AnnotationUsageHelper.extractRepeatedValues( usage, NAMED_QUERIES, modelContext ); + } + + public NamedQueriesAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + value = AnnotationUsageHelper.extractRepeatedValues( usage, NAMED_QUERIES, modelContext ); + } + + @Override + public NamedQuery[] value() { + return value; + } + + @Override + public void value(NamedQuery[] value) { + this.value = value; + } + + @Override + public Class annotationType() { + return NamedQueries.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/NamedQueryAnnotation.java b/src/test/java/org/hibernate/models/orm/NamedQueryAnnotation.java new file mode 100644 index 0000000..2985c9d --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/NamedQueryAnnotation.java @@ -0,0 +1,91 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.LockModeType; +import jakarta.persistence.NamedQuery; +import jakarta.persistence.QueryHint; + +import static org.hibernate.models.internal.AnnotationUsageHelper.extractRepeatedValues; +import static org.hibernate.models.orm.JpaAnnotations.NAMED_QUERY; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class NamedQueryAnnotation implements NamedQuery, Named { + private String name; + private String query; + private LockModeType lockModeType; + private QueryHint[] hints; + + public NamedQueryAnnotation() { + lockModeType = LockModeType.NONE; + hints = new QueryHint[0]; + } + + public NamedQueryAnnotation(NamedQuery usage, SourceModelBuildingContext modelContext) { + name = usage.name(); + query = usage.query(); + hints = extractRepeatedValues( usage, NAMED_QUERY.getAttribute( "hints" ), modelContext ); + } + + public NamedQueryAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + name = usage.value( "name" ).asString(); + query = usage.value( "query" ).asString(); + hints = extractRepeatedValues( usage, NAMED_QUERY.getAttribute( "hints" ), modelContext ); + } + + @Override + public String name() { + return name; + } + + @Override + public void name(String name) { + this.name = name; + } + + @Override + public String query() { + return query; + } + + public void query(String query) { + this.query = query; + } + + @Override + public LockModeType lockMode() { + return lockModeType; + } + + public void lockMode(LockModeType lockModeType) { + this.lockModeType = lockModeType; + } + + @Override + public QueryHint[] hints() { + return hints; + } + + public void hints(QueryHint[] hints) { + this.hints = hints; + } + + @Override + public Class annotationType() { + return NamedQuery.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/RepeatableContainer.java b/src/test/java/org/hibernate/models/orm/RepeatableContainer.java new file mode 100644 index 0000000..87732f6 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/RepeatableContainer.java @@ -0,0 +1,18 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +/** + * @author Steve Ebersole + */ +public interface RepeatableContainer extends Annotation { + R[] value(); + void value(R[] value); +} diff --git a/src/test/java/org/hibernate/models/orm/SecondaryTableAnnotation.java b/src/test/java/org/hibernate/models/orm/SecondaryTableAnnotation.java new file mode 100644 index 0000000..cbcc31e --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/SecondaryTableAnnotation.java @@ -0,0 +1,180 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.CheckConstraint; +import jakarta.persistence.ForeignKey; +import jakarta.persistence.Index; +import jakarta.persistence.PrimaryKeyJoinColumn; +import jakarta.persistence.SecondaryTable; +import jakarta.persistence.UniqueConstraint; + +import static org.hibernate.models.internal.AnnotationUsageHelper.extractRepeatedValues; +import static org.hibernate.models.internal.jandex.JandexValueHelper.extractOptionalValue; +import static org.hibernate.models.orm.JpaAnnotations.SECONDARY_TABLE; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class SecondaryTableAnnotation implements SecondaryTable, CommonTableDetails { + private String name; + private String catalog; + private String schema; + private String comment; + private String options; + private UniqueConstraint[] uniqueConstraints; + private Index[] indexes; + private CheckConstraint[] check; + private PrimaryKeyJoinColumn[] primaryKeyJoinColumns; + private ForeignKey foreignKey; + + public SecondaryTableAnnotation() { + catalog = ""; + schema = ""; + comment = ""; + options = ""; + uniqueConstraints = new UniqueConstraint[0]; + indexes = new Index[0]; + check = new CheckConstraint[0]; + primaryKeyJoinColumns = new PrimaryKeyJoinColumn[0]; + foreignKey = new ForeignKeyAnnotation(); + } + + public SecondaryTableAnnotation(SecondaryTable usage, SourceModelBuildingContext modelContext) { + name = usage.name(); + catalog = usage.catalog(); + schema = usage.schema(); + comment = usage.comment(); + options = usage.options(); + uniqueConstraints = extractRepeatedValues( usage, SECONDARY_TABLE.getAttribute( "uniqueConstraints" ), modelContext ); + indexes = extractRepeatedValues( usage, SECONDARY_TABLE.getAttribute( "indexes" ), modelContext ); + check = extractRepeatedValues( usage, SECONDARY_TABLE.getAttribute( "check" ), modelContext ); + primaryKeyJoinColumns = extractRepeatedValues( usage, SECONDARY_TABLE.getAttribute( "pkJoinColumns" ), modelContext ); + foreignKey = new ForeignKeyAnnotation( usage.foreignKey(), modelContext ); + } + + public SecondaryTableAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + name = usage.value( "name" ).asString(); + catalog = extractOptionalValue( usage, SECONDARY_TABLE.getAttribute( "catalog" ), modelContext ); + schema = extractOptionalValue( usage, SECONDARY_TABLE.getAttribute( "schema" ), modelContext ); + comment = extractOptionalValue( usage, SECONDARY_TABLE.getAttribute( "comment" ), modelContext ); + options = extractOptionalValue( usage, SECONDARY_TABLE.getAttribute( "options" ), modelContext ); + uniqueConstraints = extractRepeatedValues( usage, SECONDARY_TABLE.getAttribute( "uniqueConstraints" ), modelContext ); + indexes = extractRepeatedValues( usage, SECONDARY_TABLE.getAttribute( "indexes" ), modelContext ); + check = extractRepeatedValues( usage, SECONDARY_TABLE.getAttribute( "check" ), modelContext ); + primaryKeyJoinColumns = extractRepeatedValues( usage, SECONDARY_TABLE.getAttribute( "pkJoinColumns" ), modelContext ); + foreignKey = extractOptionalValue( usage, SECONDARY_TABLE.getAttribute( "foreignKey" ), modelContext ); + } + + @Override + public String name() { + return name; + } + + @Override + public void name(String name) { + this.name = name; + } + + @Override + public String catalog() { + return catalog; + } + + @Override + public void catalog(String catalog) { + this.catalog = catalog; + } + + @Override + public String schema() { + return schema; + } + + @Override + public void schema(String schema) { + this.schema = schema; + } + + @Override + public PrimaryKeyJoinColumn[] pkJoinColumns() { + return primaryKeyJoinColumns; + } + + public void pkJoinColumns(PrimaryKeyJoinColumn[] primaryKeyJoinColumns) { + this.primaryKeyJoinColumns = primaryKeyJoinColumns; + } + + @Override + public ForeignKey foreignKey() { + return foreignKey; + } + + public void foreignKey(ForeignKey foreignKey) { + this.foreignKey = foreignKey; + } + + @Override + public UniqueConstraint[] uniqueConstraints() { + return uniqueConstraints; + } + + @Override + public void uniqueConstraints(UniqueConstraint[] uniqueConstraints) { + this.uniqueConstraints = uniqueConstraints; + } + + @Override + public Index[] indexes() { + return indexes; + } + + @Override + public void indexes(Index[] indexes) { + this.indexes = indexes; + } + + @Override + public CheckConstraint[] check() { + return check; + } + + public void check(CheckConstraint[] check) { + this.check = check; + } + + @Override + public String comment() { + return comment; + } + + public void comment(String comment) { + this.comment = comment; + } + + @Override + public String options() { + return options; + } + + public void options(String options) { + this.options = options; + } + + @Override + public Class annotationType() { + return SecondaryTable.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/SecondaryTablesAnnotation.java b/src/test/java/org/hibernate/models/orm/SecondaryTablesAnnotation.java new file mode 100644 index 0000000..e16bf70 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/SecondaryTablesAnnotation.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.internal.AnnotationUsageHelper; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.SecondaryTable; +import jakarta.persistence.SecondaryTables; + +import static org.hibernate.models.orm.JpaAnnotations.SECONDARY_TABLES; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class SecondaryTablesAnnotation implements SecondaryTables, RepeatableContainer { + private SecondaryTable[] value; + + public SecondaryTablesAnnotation() { + value = new SecondaryTable[0]; + } + + public SecondaryTablesAnnotation(SecondaryTables usage, SourceModelBuildingContext modelContext) { + value = AnnotationUsageHelper.extractRepeatedValues( usage, SECONDARY_TABLES, modelContext ); + } + + + public SecondaryTablesAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + value = AnnotationUsageHelper.extractRepeatedValues( usage, SECONDARY_TABLES, modelContext ); + } + + @Override + public SecondaryTable[] value() { + return value; + } + + @Override + public void value(SecondaryTable[] values) { + this.value = values; + } + + @Override + public Class annotationType() { + return SecondaryTables.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/SequenceGeneratorAnnotation.java b/src/test/java/org/hibernate/models/orm/SequenceGeneratorAnnotation.java new file mode 100644 index 0000000..b9fe1c3 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/SequenceGeneratorAnnotation.java @@ -0,0 +1,129 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.SequenceGenerator; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class SequenceGeneratorAnnotation implements SequenceGenerator, Named, DatabaseObjectDetails { + private String name; + private String sequenceName; + private String catalog; + private String schema; + private int initialValue; + private int allocationSize; + private String options; + + public SequenceGeneratorAnnotation() { + name = ""; + sequenceName = ""; + catalog = ""; + schema = ""; + initialValue = 1; + allocationSize = 50; + options = ""; + } + + public SequenceGeneratorAnnotation(SequenceGenerator usage, SourceModelBuildingContext modelContext) { + name = usage.name(); + sequenceName = usage.sequenceName(); + catalog = usage.catalog(); + schema = usage.schema(); + initialValue = usage.initialValue(); + allocationSize = usage.allocationSize(); + options = usage.options(); + } + + public SequenceGeneratorAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + name = usage.value( "name" ).asString(); + sequenceName = usage.value( "sequenceName" ).asString(); + catalog = usage.value( "catalog" ).asString(); + schema = usage.value( "schema" ).asString(); + initialValue = usage.value( "initialValue" ).asInt(); + allocationSize = usage.value( "allocationSize" ).asInt(); + options = usage.value( "options" ).asString(); + } + + @Override + public String name() { + return name; + } + + @Override + public void name(String name) { + this.name = name; + } + + @Override + public String sequenceName() { + return sequenceName; + } + + public void sequenceName(String sequenceName) { + this.sequenceName = sequenceName; + } + + @Override + public String catalog() { + return catalog; + } + + public void catalog(String catalog) { + this.catalog = catalog; + } + + @Override + public String schema() { + return schema; + } + + public void schema(String schema) { + this.schema = schema; + } + + @Override + public int initialValue() { + return initialValue; + } + + public void initialValue(int initialValue) { + this.initialValue = initialValue; + } + + @Override + public int allocationSize() { + return allocationSize; + } + + public void allocationSize(int allocationSize) { + this.allocationSize = allocationSize; + } + + @Override + public String options() { + return options; + } + + public void options(String options) { + this.options = options; + } + + @Override + public Class annotationType() { + return SequenceGenerator.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/SequenceGeneratorsAnnotation.java b/src/test/java/org/hibernate/models/orm/SequenceGeneratorsAnnotation.java new file mode 100644 index 0000000..82cf301 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/SequenceGeneratorsAnnotation.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.internal.AnnotationUsageHelper; +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.SequenceGenerators; + +import static org.hibernate.models.orm.JpaAnnotations.SEQUENCE_GENERATORS; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class SequenceGeneratorsAnnotation implements SequenceGenerators, RepeatableContainer { + private SequenceGenerator[] value; + + public SequenceGeneratorsAnnotation() { + value = new SequenceGenerator[0]; + } + + public SequenceGeneratorsAnnotation(SequenceGenerators usage, SourceModelBuildingContext modelContext) { + value = AnnotationUsageHelper.extractRepeatedValues( usage, SEQUENCE_GENERATORS, modelContext ); + } + + + public SequenceGeneratorsAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + value = AnnotationUsageHelper.extractRepeatedValues( usage, SEQUENCE_GENERATORS, modelContext ); + } + + @Override + public SequenceGenerator[] value() { + return value; + } + + @Override + public void value(SequenceGenerator[] value) { + this.value = value; + } + + @Override + public Class annotationType() { + return SequenceGenerators.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/TableAnnotation.java b/src/test/java/org/hibernate/models/orm/TableAnnotation.java new file mode 100644 index 0000000..b06565c --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/TableAnnotation.java @@ -0,0 +1,154 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.CheckConstraint; +import jakarta.persistence.Index; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; + +import static org.hibernate.models.internal.AnnotationUsageHelper.extractRepeatedValues; +import static org.hibernate.models.internal.jandex.JandexValueHelper.extractOptionalValue; +import static org.hibernate.models.orm.JpaAnnotations.SECONDARY_TABLE; +import static org.hibernate.models.orm.JpaAnnotations.TABLE; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class TableAnnotation implements Table, CommonTableDetails { + private String name; + private String catalog; + private String schema; + private UniqueConstraint[] uniqueConstraints; + private Index[] indexes; + private CheckConstraint[] check; + private String comment; + private String options; + + public TableAnnotation() { + name = ""; + catalog = ""; + schema = ""; + comment = ""; + options = ""; + uniqueConstraints = new UniqueConstraint[0]; + indexes = new Index[0]; + check = new CheckConstraint[0]; + } + + public TableAnnotation(Table usage, SourceModelBuildingContext modelContext) { + name = usage.name(); + catalog = usage.catalog(); + schema = usage.schema(); + comment = usage.comment(); + options = usage.options(); + uniqueConstraints = extractRepeatedValues( usage, TABLE.getAttribute( "uniqueConstraints" ), modelContext ); + indexes = extractRepeatedValues( usage, TABLE.getAttribute( "indexes" ), modelContext ); + check = extractRepeatedValues( usage, TABLE.getAttribute( "check" ), modelContext ); + } + + public TableAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + name = usage.value( "name" ).asString(); + catalog = extractOptionalValue( usage, SECONDARY_TABLE.getAttribute( "catalog" ), modelContext ); + schema = extractOptionalValue( usage, SECONDARY_TABLE.getAttribute( "schema" ), modelContext ); + comment = extractOptionalValue( usage, SECONDARY_TABLE.getAttribute( "comment" ), modelContext ); + options = extractOptionalValue( usage, SECONDARY_TABLE.getAttribute( "options" ), modelContext ); + uniqueConstraints = extractRepeatedValues( usage, TABLE.getAttribute( "uniqueConstraints" ), modelContext ); + indexes = extractRepeatedValues( usage, TABLE.getAttribute( "indexes" ), modelContext ); + check = extractRepeatedValues( usage, TABLE.getAttribute( "check" ), modelContext ); + } + + @Override + public String name() { + return name; + } + + @Override + public void name(String name) { + this.name = name; + } + + @Override + public String catalog() { + return catalog; + } + + @Override + public void catalog(String catalog) { + this.catalog = catalog; + } + + @Override + public String schema() { + return schema; + } + + @Override + public void schema(String schema) { + this.schema = schema; + } + + @Override + public UniqueConstraint[] uniqueConstraints() { + return uniqueConstraints; + } + + @Override + public void uniqueConstraints(UniqueConstraint[] uniqueConstraints) { + this.uniqueConstraints = uniqueConstraints; + } + + @Override + public Index[] indexes() { + return indexes; + } + + @Override + public void indexes(Index[] indexes) { + this.indexes = indexes; + } + + @Override + public CheckConstraint[] check() { + return check; + } + + public void check(CheckConstraint[] check) { + this.check = check; + } + + @Override + public String comment() { + return comment; + } + + public void comment(String comment) { + this.comment = comment; + } + + @Override + public String options() { + return options; + } + + public void options(String options) { + this.options = options; + } + + @Override + public Class annotationType() { + return Table.class; + } +} diff --git a/src/test/java/org/hibernate/models/orm/UniqueConstraintAnnotation.java b/src/test/java/org/hibernate/models/orm/UniqueConstraintAnnotation.java new file mode 100644 index 0000000..1a89367 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/UniqueConstraintAnnotation.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ + +package org.hibernate.models.orm; + +import java.lang.annotation.Annotation; + +import org.hibernate.models.spi.SourceModelBuildingContext; + +import org.jboss.jandex.AnnotationInstance; + +import jakarta.persistence.UniqueConstraint; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" }) +public class UniqueConstraintAnnotation implements UniqueConstraint { + private String name; + private String[] columnNames; + private String options; + + public UniqueConstraintAnnotation() { + name = ""; + options = ""; + } + + public UniqueConstraintAnnotation(UniqueConstraint usage, SourceModelBuildingContext modelContext) { + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + public UniqueConstraintAnnotation(AnnotationInstance usage, SourceModelBuildingContext modelContext) { + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Override + public String name() { + return name; + } + + public void name(String name) { + this.name = name; + } + + @Override + public String[] columnNames() { + return columnNames; + } + + public void columnNames(String[] columnNames) { + this.columnNames = columnNames; + } + + @Override + public String options() { + return options; + } + + public void options(String options) { + this.options = options; + } + + @Override + public Class annotationType() { + return UniqueConstraint.class; + } +} diff --git a/version.txt b/version.txt index 5deada8..5613b45 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.0.0-SNAPSHOT \ No newline at end of file +1.0.0-USAGE \ No newline at end of file