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,15 +80,17 @@ 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
@@ -98,15 +110,76 @@ public <V> V setAttributeValue(String name, V value) {
98110 values = new HashMap <>();
99111 }
100112
113+ if ( value != null ) {
114+
115+ //noinspection unchecked
116+ return (V ) values .put ( name , value );
117+ }
101118 //noinspection unchecked
102- return (V ) values .put ( name , value );
119+ return (V ) values .get ( name );
103120 }
104121
105- private static <A extends Annotation > Map <String , Object > extractBaselineValues (AnnotationDescriptor <A > annotationDescriptor ) {
122+ private static <A extends Annotation > Map <String , Object > extractBaselineValues (
123+ AnnotationDescriptor <A > annotationDescriptor ,
124+ AnnotationTarget target ,
125+ SourceModelBuildingContext context ) {
106126 final HashMap <String , Object > values = new HashMap <>();
107127 for ( AttributeDescriptor <?> attribute : annotationDescriptor .getAttributes () ) {
108- values .put ( attribute .getName (), attribute . getAttributeMethod (). getDefaultValue () );
128+ values .put ( attribute .getName (), getDefaultValue ( attribute , target , context ) );
109129 }
110130 return values ;
111131 }
132+
133+ private static Object getDefaultValue (
134+ AttributeDescriptor <?> attribute ,
135+ AnnotationTarget target ,
136+ SourceModelBuildingContext context ) {
137+ final Object defaultValue = attribute .getAttributeMethod ().getDefaultValue ();
138+ Object annotation = wrapValue ( defaultValue , target , context );
139+ if ( annotation != null ) {
140+ return annotation ;
141+ }
142+ return defaultValue ;
143+ }
144+
145+ private static Object wrapValue (Object value , AnnotationTarget target , SourceModelBuildingContext context ) {
146+ if ( value instanceof Annotation annotation ) {
147+ try {
148+ return extractDynamicAnnotationUsage ( annotation , target , context );
149+ }
150+ catch (InvocationTargetException | IllegalAccessException e ) {
151+ throw new AnnotationAccessException ( "Error accessing default annotation attribute value" , e );
152+ }
153+ }
154+ else if ( value != null && value .getClass ().isArray () ) {
155+ return getList ( value , target , context );
156+ }
157+ return value ;
158+ }
159+
160+ private static <E > List getList (Object defaultValue , AnnotationTarget target , SourceModelBuildingContext context ) {
161+ List result = new ArrayList <>();
162+ E [] d = (E []) defaultValue ;
163+ for ( E e : d ) {
164+ result .add ( wrapValue ( e , target , context ) );
165+ }
166+ return result ;
167+ }
168+
169+ private static DynamicAnnotationUsage <?> extractDynamicAnnotationUsage (
170+ Annotation annotation ,
171+ AnnotationTarget target ,
172+ SourceModelBuildingContext context ) throws InvocationTargetException , IllegalAccessException {
173+ final Class <? extends Annotation > annotationType = annotation .annotationType ();
174+ final AnnotationDescriptor <?> descriptor = context .getAnnotationDescriptorRegistry ()
175+ .getDescriptor ( annotationType );
176+ final DynamicAnnotationUsage <?> annotationUsage = new DynamicAnnotationUsage <>( descriptor , target , context );
177+ for ( AttributeDescriptor <?> attribute : descriptor .getAttributes () ) {
178+ annotationUsage .setAttributeValue (
179+ attribute .getName (),
180+ attribute .getAttributeMethod ().invoke ( annotation )
181+ );
182+ }
183+ return annotationUsage ;
184+ }
112185}
0 commit comments