77package org .hibernate .models .internal .dynamic ;
88
99import java .lang .annotation .Annotation ;
10+ import java .lang .reflect .InvocationTargetException ;
11+ import java .util .ArrayList ;
1012import java .util .HashMap ;
13+ import java .util .List ;
1114import java .util .Locale ;
1215import java .util .Map ;
1316
17+ import org .hibernate .models .AnnotationAccessException ;
1418import org .hibernate .models .UnknownAnnotationAttributeException ;
1519import org .hibernate .models .internal .AnnotationProxy ;
1620import org .hibernate .models .spi .AnnotationDescriptor ;
1721import org .hibernate .models .spi .AnnotationTarget ;
1822import org .hibernate .models .spi .AttributeDescriptor ;
1923import org .hibernate .models .spi .MutableAnnotationUsage ;
24+ import org .hibernate .models .spi .SourceModelBuildingContext ;
2025
2126/**
2227 * AnnotationUsage built dynamically (for dynamic models, XML mappings, etc.)
@@ -29,15 +34,20 @@ public class DynamicAnnotationUsage<A extends Annotation> implements MutableAnno
2934
3035 private Map <String ,Object > values ;
3136
32- public DynamicAnnotationUsage (AnnotationDescriptor <A > annotationDescriptor ) {
33- this ( annotationDescriptor , null );
37+ public DynamicAnnotationUsage (
38+ AnnotationDescriptor <A > annotationDescriptor ,
39+ SourceModelBuildingContext context ) {
40+ this ( annotationDescriptor , null , context );
3441 }
3542
36- public DynamicAnnotationUsage (AnnotationDescriptor <A > annotationDescriptor , AnnotationTarget target ) {
43+ public DynamicAnnotationUsage (
44+ AnnotationDescriptor <A > annotationDescriptor ,
45+ AnnotationTarget target ,
46+ SourceModelBuildingContext context ) {
3747 this .annotationDescriptor = annotationDescriptor ;
3848 this .target = target ;
3949
40- this .values = extractBaselineValues ( annotationDescriptor );
50+ this .values = extractBaselineValues ( annotationDescriptor , target , context );
4151 }
4252
4353 @ Override
@@ -70,19 +80,32 @@ public <V> V findAttributeValue(String name) {
7080 */
7181 @ Override
7282 public <V > V getAttributeValue (String name ) {
73- final Object value = findAttributeValue ( name );
74- if ( value == null ) {
75- // null values are not supported as annotation attribute values; we honor that
76- // in hibernate-models. return the default.
77- //noinspection unchecked
78- return (V ) getAnnotationDescriptor ().getAttribute ( name ).getAttributeMethod ().getDefaultValue ();
83+ if ( annotationDescriptor .getAttribute ( name ) == null ) {
84+ throw new UnknownAnnotationAttributeException (
85+ String .format (
86+ Locale .ROOT ,
87+ "Unknown attribute `%s` for annotation `%s`" ,
88+ name ,
89+ getAnnotationType ().getName ()
90+ )
91+ );
7992 }
80- //noinspection unchecked
81- return (V ) value ;
93+ return findAttributeValue ( name );
8294 }
8395
8496 @ Override
8597 public <V > V setAttributeValue (String name , V value ) {
98+ if (value == null ){
99+ throw new IllegalArgumentException (
100+ String .format (
101+ Locale .ROOT ,
102+ "Null value not allowed for attribute `%s` of annotation `%s`" ,
103+ name ,
104+ getAnnotationType ().getName ()
105+ )
106+ );
107+ }
108+
86109 if ( annotationDescriptor .getAttribute ( name ) == null ) {
87110 throw new UnknownAnnotationAttributeException (
88111 String .format (
@@ -102,11 +125,67 @@ public <V> V setAttributeValue(String name, V value) {
102125 return (V ) values .put ( name , value );
103126 }
104127
105- private static <A extends Annotation > Map <String , Object > extractBaselineValues (AnnotationDescriptor <A > annotationDescriptor ) {
128+ private static <A extends Annotation > Map <String , Object > extractBaselineValues (
129+ AnnotationDescriptor <A > annotationDescriptor ,
130+ AnnotationTarget target ,
131+ SourceModelBuildingContext context ) {
106132 final HashMap <String , Object > values = new HashMap <>();
107133 for ( AttributeDescriptor <?> attribute : annotationDescriptor .getAttributes () ) {
108- values .put ( attribute .getName (), attribute . getAttributeMethod (). getDefaultValue () );
134+ values .put ( attribute .getName (), getDefaultValue ( attribute , target , context ) );
109135 }
110136 return values ;
111137 }
138+
139+ private static Object getDefaultValue (
140+ AttributeDescriptor <?> attribute ,
141+ AnnotationTarget target ,
142+ SourceModelBuildingContext context ) {
143+ final Object defaultValue = attribute .getAttributeMethod ().getDefaultValue ();
144+ Object annotation = wrapValue ( defaultValue , target , context );
145+ if ( annotation != null ) {
146+ return annotation ;
147+ }
148+ return defaultValue ;
149+ }
150+
151+ private static Object wrapValue (Object value , AnnotationTarget target , SourceModelBuildingContext context ) {
152+ if ( value instanceof Annotation annotation ) {
153+ try {
154+ return extractDynamicAnnotationUsage ( annotation , target , context );
155+ }
156+ catch (InvocationTargetException | IllegalAccessException e ) {
157+ throw new AnnotationAccessException ( "Error accessing default annotation attribute value" , e );
158+ }
159+ }
160+ else if ( value != null && value .getClass ().isArray () ) {
161+ return getList ( value , target , context );
162+ }
163+ return value ;
164+ }
165+
166+ private static <E > List getList (Object defaultValue , AnnotationTarget target , SourceModelBuildingContext context ) {
167+ List result = new ArrayList <>();
168+ E [] d = (E []) defaultValue ;
169+ for ( E e : d ) {
170+ result .add ( wrapValue ( e , target , context ) );
171+ }
172+ return result ;
173+ }
174+
175+ private static DynamicAnnotationUsage <?> extractDynamicAnnotationUsage (
176+ Annotation annotation ,
177+ AnnotationTarget target ,
178+ SourceModelBuildingContext context ) throws InvocationTargetException , IllegalAccessException {
179+ final Class <? extends Annotation > annotationType = annotation .annotationType ();
180+ final AnnotationDescriptor <?> descriptor = context .getAnnotationDescriptorRegistry ()
181+ .getDescriptor ( annotationType );
182+ final DynamicAnnotationUsage <?> annotationUsage = new DynamicAnnotationUsage <>( descriptor , target , context );
183+ for ( AttributeDescriptor <?> attribute : descriptor .getAttributes () ) {
184+ annotationUsage .setAttributeValue (
185+ attribute .getName (),
186+ attribute .getAttributeMethod ().invoke ( annotation )
187+ );
188+ }
189+ return annotationUsage ;
190+ }
112191}
0 commit comments