Skip to content

Commit 0144a6d

Browse files
committed
Fix annotation default values extraction
1 parent df2f29f commit 0144a6d

File tree

3 files changed

+96
-8
lines changed

3 files changed

+96
-8
lines changed

src/main/java/org/hibernate/models/internal/dynamic/DynamicAnnotationUsage.java

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,20 @@
77
package org.hibernate.models.internal.dynamic;
88

99
import java.lang.annotation.Annotation;
10+
import java.lang.reflect.InvocationTargetException;
11+
import java.util.Arrays;
1012
import java.util.HashMap;
1113
import java.util.Locale;
1214
import java.util.Map;
1315

16+
import org.hibernate.models.AnnotationAccessException;
1417
import org.hibernate.models.UnknownAnnotationAttributeException;
1518
import org.hibernate.models.internal.AnnotationProxy;
1619
import org.hibernate.models.spi.AnnotationDescriptor;
1720
import org.hibernate.models.spi.AnnotationTarget;
1821
import org.hibernate.models.spi.AttributeDescriptor;
1922
import org.hibernate.models.spi.MutableAnnotationUsage;
23+
import org.hibernate.models.spi.SourceModelBuildingContext;
2024

2125
/**
2226
* AnnotationUsage built dynamically (for dynamic models, XML mappings, etc.)
@@ -29,15 +33,14 @@ public class DynamicAnnotationUsage<A extends Annotation> implements MutableAnno
2933

3034
private Map<String,Object> values;
3135

32-
public DynamicAnnotationUsage(AnnotationDescriptor<A> annotationDescriptor) {
33-
this( annotationDescriptor, null );
34-
}
35-
36-
public DynamicAnnotationUsage(AnnotationDescriptor<A> annotationDescriptor, AnnotationTarget target) {
36+
public DynamicAnnotationUsage(
37+
AnnotationDescriptor<A> annotationDescriptor,
38+
AnnotationTarget target,
39+
SourceModelBuildingContext context) {
3740
this.annotationDescriptor = annotationDescriptor;
3841
this.target = target;
3942

40-
this.values = extractBaselineValues( annotationDescriptor );
43+
this.values = extractBaselineValues( annotationDescriptor, target, context );
4144
}
4245

4346
@Override
@@ -109,4 +112,46 @@ private static <A extends Annotation> Map<String, Object> extractBaselineValues(
109112
}
110113
return values;
111114
}
115+
116+
private static <A extends Annotation> Map<String, Object> extractBaselineValues(
117+
AnnotationDescriptor<A> annotationDescriptor,
118+
AnnotationTarget target,
119+
SourceModelBuildingContext context) {
120+
final HashMap<String, Object> values = new HashMap<>();
121+
for ( AttributeDescriptor<?> attribute : annotationDescriptor.getAttributes() ) {
122+
final Object defaultValue = attribute.getAttributeMethod().getDefaultValue();
123+
if ( defaultValue instanceof Annotation annotation ) {
124+
try {
125+
values.put( attribute.getName(), extractDynamicAnnotationUsage( annotation, target, context ) );
126+
}
127+
catch (InvocationTargetException | IllegalAccessException e) {
128+
throw new AnnotationAccessException( "Error accessing default annotation attribute value", e );
129+
}
130+
}
131+
else if ( attribute.isMultiValued() ) {
132+
values.put( attribute.getName(), Arrays.asList( defaultValue ) );
133+
}
134+
else {
135+
values.put( attribute.getName(), defaultValue );
136+
}
137+
}
138+
return values;
139+
}
140+
141+
private static DynamicAnnotationUsage<?> extractDynamicAnnotationUsage(
142+
Annotation annotation,
143+
AnnotationTarget target,
144+
SourceModelBuildingContext context) throws InvocationTargetException, IllegalAccessException {
145+
final Class<? extends Annotation> annotationType = annotation.annotationType();
146+
final AnnotationDescriptor<?> descriptor = context.getAnnotationDescriptorRegistry()
147+
.getDescriptor( annotationType );
148+
final DynamicAnnotationUsage<?> annotationUsage = new DynamicAnnotationUsage<>( descriptor, target, context );
149+
for ( AttributeDescriptor<?> attribute : descriptor.getAttributes() ) {
150+
annotationUsage.setAttributeValue(
151+
attribute.getName(),
152+
attribute.getAttributeMethod().invoke( annotation )
153+
);
154+
}
155+
return annotationUsage;
156+
}
112157
}

src/main/java/org/hibernate/models/spi/AnnotationDescriptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ default <V> AttributeDescriptor<V> getAttribute(String name) {
8888
* @param context Access to needed services
8989
*/
9090
default MutableAnnotationUsage<A> createUsage(AnnotationTarget target, SourceModelBuildingContext context) {
91-
final DynamicAnnotationUsage<A> usage = new DynamicAnnotationUsage<>( this, target );
91+
final DynamicAnnotationUsage<A> usage = new DynamicAnnotationUsage<>( this, target, context );
9292
getAttributes().forEach( (attr) -> {
9393
final Object value = attr.getTypeDescriptor().createValue( attr, target, context );
9494
usage.setAttributeValue( attr.getName(), value );

src/test/java/org/hibernate/models/annotations/DynamicAnnotationTests.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
package org.hibernate.models.annotations;
99

10+
import java.util.List;
11+
1012
import org.hibernate.models.UnknownAnnotationAttributeException;
1113
import org.hibernate.models.internal.SourceModelBuildingContextImpl;
1214
import org.hibernate.models.internal.dynamic.DynamicAnnotationUsage;
@@ -15,6 +17,8 @@
1517

1618
import org.junit.jupiter.api.Test;
1719

20+
import jakarta.persistence.ConstraintMode;
21+
import jakarta.persistence.JoinTable;
1822
import jakarta.persistence.SequenceGenerator;
1923

2024
import static org.assertj.core.api.Assertions.assertThat;
@@ -31,7 +35,8 @@ void testBasicUsage() {
3135
final DynamicClassDetails dynamicEntity = new DynamicClassDetails( "DynamicEntity", buildingContext );
3236
final DynamicAnnotationUsage<SequenceGenerator> generatorAnn = new DynamicAnnotationUsage<>(
3337
JpaAnnotations.SEQUENCE_GENERATOR,
34-
dynamicEntity
38+
dynamicEntity,
39+
buildingContext
3540
);
3641
assertThat( generatorAnn.getString( "name" ) ).isEqualTo( "" );
3742
assertThat( generatorAnn.getString( "sequenceName" ) ).isEqualTo( "" );
@@ -49,4 +54,42 @@ void testBasicUsage() {
4954
}
5055

5156
}
57+
58+
@Test
59+
void testJoinTableForeignKeyDefaultValue() {
60+
final SourceModelBuildingContextImpl buildingContext = createBuildingContext();
61+
final DynamicClassDetails dynamicEntity = new DynamicClassDetails( "DynamicEntity", buildingContext );
62+
final DynamicAnnotationUsage<JoinTable> generatorAnn = new DynamicAnnotationUsage<>(
63+
JpaAnnotations.JOIN_TABLE,
64+
dynamicEntity,
65+
buildingContext
66+
);
67+
68+
final Object foreignKey = generatorAnn.getAttributeValue( "foreignKey" );
69+
70+
assertThat( foreignKey ).isInstanceOf( DynamicAnnotationUsage.class );
71+
72+
final DynamicAnnotationUsage foreignKeyAnnotationUsage = (DynamicAnnotationUsage) foreignKey;
73+
74+
assertThat( foreignKeyAnnotationUsage.getAttributeValue( "value" ) ).isEqualTo( ConstraintMode.PROVIDER_DEFAULT );
75+
76+
assertThat( foreignKeyAnnotationUsage.getAttributeValue( "name" )).isEqualTo( "" );
77+
assertThat( foreignKeyAnnotationUsage.getAttributeValue( "options" )).isEqualTo( "" );
78+
assertThat( foreignKeyAnnotationUsage.getAttributeValue( "foreignKeyDefinition" )).isEqualTo( "" );
79+
}
80+
81+
@Test
82+
void testDefaultArrayValue() {
83+
final SourceModelBuildingContextImpl buildingContext = createBuildingContext();
84+
final DynamicClassDetails dynamicEntity = new DynamicClassDetails( "DynamicEntity", buildingContext );
85+
final DynamicAnnotationUsage<JoinTable> generatorAnn = new DynamicAnnotationUsage<>(
86+
JpaAnnotations.JOIN_TABLE,
87+
dynamicEntity,
88+
buildingContext
89+
);
90+
91+
final Object joinColumns = generatorAnn.getAttributeValue( "joinColumns" );
92+
assertThat( joinColumns ).isInstanceOf( List.class );
93+
94+
}
5295
}

0 commit comments

Comments
 (0)