Skip to content

Commit 3ce1570

Browse files
committed
Fix annotation default values extraction
1 parent df2f29f commit 3ce1570

File tree

3 files changed

+100
-6
lines changed

3 files changed

+100
-6
lines changed

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

Lines changed: 55 additions & 4 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,20 @@ 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 );
36+
public DynamicAnnotationUsage(
37+
AnnotationDescriptor<A> annotationDescriptor,
38+
SourceModelBuildingContext context) {
39+
this( annotationDescriptor, null, context );
3440
}
3541

36-
public DynamicAnnotationUsage(AnnotationDescriptor<A> annotationDescriptor, AnnotationTarget target) {
42+
public DynamicAnnotationUsage(
43+
AnnotationDescriptor<A> annotationDescriptor,
44+
AnnotationTarget target,
45+
SourceModelBuildingContext context) {
3746
this.annotationDescriptor = annotationDescriptor;
3847
this.target = target;
3948

40-
this.values = extractBaselineValues( annotationDescriptor );
49+
this.values = extractBaselineValues( annotationDescriptor, target, context );
4150
}
4251

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

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)