7
7
package org .hibernate .models .internal .dynamic ;
8
8
9
9
import java .lang .annotation .Annotation ;
10
+ import java .lang .reflect .InvocationTargetException ;
11
+ import java .util .ArrayList ;
10
12
import java .util .HashMap ;
13
+ import java .util .List ;
11
14
import java .util .Locale ;
12
15
import java .util .Map ;
13
16
17
+ import org .hibernate .models .AnnotationAccessException ;
14
18
import org .hibernate .models .UnknownAnnotationAttributeException ;
15
19
import org .hibernate .models .internal .AnnotationProxy ;
16
20
import org .hibernate .models .spi .AnnotationDescriptor ;
17
21
import org .hibernate .models .spi .AnnotationTarget ;
18
22
import org .hibernate .models .spi .AttributeDescriptor ;
19
23
import org .hibernate .models .spi .MutableAnnotationUsage ;
24
+ import org .hibernate .models .spi .SourceModelBuildingContext ;
20
25
21
26
/**
22
27
* AnnotationUsage built dynamically (for dynamic models, XML mappings, etc.)
@@ -29,15 +34,20 @@ public class DynamicAnnotationUsage<A extends Annotation> implements MutableAnno
29
34
30
35
private Map <String ,Object > values ;
31
36
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 );
34
41
}
35
42
36
- public DynamicAnnotationUsage (AnnotationDescriptor <A > annotationDescriptor , AnnotationTarget target ) {
43
+ public DynamicAnnotationUsage (
44
+ AnnotationDescriptor <A > annotationDescriptor ,
45
+ AnnotationTarget target ,
46
+ SourceModelBuildingContext context ) {
37
47
this .annotationDescriptor = annotationDescriptor ;
38
48
this .target = target ;
39
49
40
- this .values = extractBaselineValues ( annotationDescriptor );
50
+ this .values = extractBaselineValues ( annotationDescriptor , target , context );
41
51
}
42
52
43
53
@ Override
@@ -70,19 +80,32 @@ public <V> V findAttributeValue(String name) {
70
80
*/
71
81
@ Override
72
82
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
+ );
79
92
}
80
- //noinspection unchecked
81
- return (V ) value ;
93
+ return findAttributeValue ( name );
82
94
}
83
95
84
96
@ Override
85
97
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
+
86
109
if ( annotationDescriptor .getAttribute ( name ) == null ) {
87
110
throw new UnknownAnnotationAttributeException (
88
111
String .format (
@@ -102,11 +125,67 @@ public <V> V setAttributeValue(String name, V value) {
102
125
return (V ) values .put ( name , value );
103
126
}
104
127
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 ) {
106
132
final HashMap <String , Object > values = new HashMap <>();
107
133
for ( AttributeDescriptor <?> attribute : annotationDescriptor .getAttributes () ) {
108
- values .put ( attribute .getName (), attribute . getAttributeMethod (). getDefaultValue () );
134
+ values .put ( attribute .getName (), getDefaultValue ( attribute , target , context ) );
109
135
}
110
136
return values ;
111
137
}
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
+ }
112
191
}
0 commit comments