Skip to content

Commit c18eeb9

Browse files
committed
#67 - Remove target arg from AnnotationDescriptor#ceateUsage forms
1 parent cf729a0 commit c18eeb9

File tree

5 files changed

+99
-13
lines changed

5 files changed

+99
-13
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
* Copyright: Red Hat Inc. and Hibernate Authors
6+
*/
7+
8+
package org.hibernate.models;
9+
10+
import java.lang.annotation.Annotation;
11+
import java.util.Locale;
12+
13+
import org.hibernate.models.spi.AnnotationDescriptor;
14+
import org.hibernate.models.spi.AnnotationTarget;
15+
16+
/**
17+
* Indicates an attempt to {@linkplain org.hibernate.models.spi.MutableAnnotationTarget#addAnnotationUsage add}
18+
* a {@linkplain AnnotationDescriptor#isRepeatable() repeatable} annotation to a target. The repeatable
19+
* {@linkplain AnnotationDescriptor#getRepeatableContainer() container} should always be used instead.
20+
*
21+
* @author Steve Ebersole
22+
*/
23+
public class RepeatableAnnotationException extends ModelsException {
24+
public RepeatableAnnotationException(AnnotationDescriptor<? extends Annotation> repeatableDescriptor, AnnotationTarget target) {
25+
super(
26+
String.format(
27+
Locale.ROOT,
28+
"A repeatable annotation (%s) was added to a target (%s); use the container annotation (%s) instead",
29+
repeatableDescriptor.getAnnotationType().getName(),
30+
target.getName(),
31+
repeatableDescriptor.getRepeatableContainer().getAnnotationType().getName()
32+
)
33+
);
34+
}
35+
}

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
import java.util.HashMap;
1111
import java.util.Map;
1212

13+
import org.hibernate.models.RepeatableAnnotationException;
1314
import org.hibernate.models.internal.AnnotationTargetSupport;
1415
import org.hibernate.models.spi.AnnotationUsage;
1516
import org.hibernate.models.spi.SourceModelBuildingContext;
1617

18+
import static org.hibernate.models.internal.ModelsLogging.MODELS_LOGGER;
19+
1720
/**
1821
* @author Steve Ebersole
1922
*/
@@ -40,17 +43,20 @@ public void clearAnnotationUsages() {
4043
usageMap.clear();
4144
}
4245

43-
/**
44-
* Applies the given {@code annotationUsage} to this target.
45-
*
46-
* @todo It is undefined currently what happens if the annotation type is already applied on this target.
47-
*/
46+
@Override
4847
public <X extends Annotation> void addAnnotationUsage(AnnotationUsage<X> annotationUsage) {
4948
assert annotationUsage.getAnnotationDescriptor().getAllowableTargets().contains( getKind() );
50-
final AnnotationUsage<?> previous = usageMap.put( annotationUsage.getAnnotationType(), annotationUsage );
5149

52-
if ( previous != null ) {
53-
// todo : ignore? log? exception?
50+
if ( annotationUsage.getAnnotationDescriptor().isRepeatable() ) {
51+
throw new RepeatableAnnotationException( annotationUsage.getAnnotationDescriptor(), this );
52+
}
53+
54+
final AnnotationUsage<? extends Annotation> previous = getUsageMap().put(
55+
annotationUsage.getAnnotationType(),
56+
annotationUsage
57+
);
58+
if ( previous != null && MODELS_LOGGER.isDebugEnabled() ) {
59+
MODELS_LOGGER.debugf( "AnnotationUsage (%s) was replaced (%s)", annotationUsage, previous );
5460
}
5561
}
5662

src/main/java/org/hibernate/models/internal/jandex/AbstractAnnotationTarget.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99
import java.lang.annotation.Annotation;
1010
import java.util.Map;
1111

12+
import org.hibernate.models.RepeatableAnnotationException;
1213
import org.hibernate.models.internal.AnnotationTargetSupport;
1314
import org.hibernate.models.spi.AnnotationUsage;
1415
import org.hibernate.models.spi.SourceModelBuildingContext;
1516

17+
import static org.hibernate.models.internal.ModelsLogging.MODELS_LOGGER;
18+
1619
/**
1720
* @author Steve Ebersole
1821
*/
@@ -47,7 +50,18 @@ public void clearAnnotationUsages() {
4750
@Override
4851
public <X extends Annotation> void addAnnotationUsage(AnnotationUsage<X> annotationUsage) {
4952
assert annotationUsage.getAnnotationDescriptor().getAllowableTargets().contains( getKind() );
50-
getUsageMap().put( annotationUsage.getAnnotationType(), annotationUsage );
53+
54+
if ( annotationUsage.getAnnotationDescriptor().isRepeatable() ) {
55+
throw new RepeatableAnnotationException( annotationUsage.getAnnotationDescriptor(), this );
56+
}
57+
58+
final AnnotationUsage<? extends Annotation> previous = getUsageMap().put(
59+
annotationUsage.getAnnotationType(),
60+
annotationUsage
61+
);
62+
if ( previous != null && MODELS_LOGGER.isDebugEnabled() ) {
63+
MODELS_LOGGER.debugf( "AnnotationUsage (%s) was replaced (%s)", annotationUsage, previous );
64+
}
5165
}
5266

5367
@Override

src/main/java/org/hibernate/models/internal/jdk/AbstractAnnotationTarget.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
import java.util.Map;
1212
import java.util.function.Supplier;
1313

14+
import org.hibernate.models.RepeatableAnnotationException;
1415
import org.hibernate.models.internal.AnnotationTargetSupport;
1516
import org.hibernate.models.spi.AnnotationUsage;
1617
import org.hibernate.models.spi.SourceModelBuildingContext;
1718

19+
import static org.hibernate.models.internal.ModelsLogging.MODELS_LOGGER;
20+
1821
/**
1922
* AnnotationTarget where we know the annotations up front, but
2023
* want to delay processing them until (unless!) they are needed
@@ -65,6 +68,16 @@ public void clearAnnotationUsages() {
6568
@Override
6669
public <X extends Annotation> void addAnnotationUsage(AnnotationUsage<X> annotationUsage) {
6770
assert annotationUsage.getAnnotationDescriptor().getAllowableTargets().contains( getKind() );
68-
getUsageMap().put( annotationUsage.getAnnotationType(), annotationUsage );
71+
if ( annotationUsage.getAnnotationDescriptor().isRepeatable() ) {
72+
throw new RepeatableAnnotationException( annotationUsage.getAnnotationDescriptor(), this );
73+
}
74+
75+
final AnnotationUsage<? extends Annotation> previous = getUsageMap().put(
76+
annotationUsage.getAnnotationType(),
77+
annotationUsage
78+
);
79+
if ( previous != null && MODELS_LOGGER.isDebugEnabled() ) {
80+
MODELS_LOGGER.debugf( "AnnotationUsage (%s) was replaced (%s)", annotationUsage, previous );
81+
}
6982
}
7083
}

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

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import java.lang.annotation.Annotation;
1010

11+
import org.hibernate.models.RepeatableAnnotationException;
12+
1113
/**
1214
* Extension of AnnotationTarget which allows manipulation of the annotations
1315
*
@@ -22,22 +24,38 @@ public interface MutableAnnotationTarget extends AnnotationTarget {
2224

2325
/**
2426
* Add an annotation usage to this target
27+
*
28+
* @apiNote Expects the {@linkplain AnnotationDescriptor#getRepeatableContainer() container} form instead of
29+
* {@linkplain AnnotationDescriptor#isRepeatable() repeatable} annotations.
30+
*
31+
* @throws RepeatableAnnotationException Indicates a {@linkplain AnnotationDescriptor#isRepeatable() repeatable}
32+
* annotation was passed.
2533
*/
2634
<X extends Annotation> void addAnnotationUsage(AnnotationUsage<X> annotationUsage);
2735

2836
/**
2937
* Applies a usage of the given {@code annotationType} to this target. Will return
3038
* an existing usage, if one, or create a new usage.
39+
*
40+
* @apiNote Expects the {@linkplain AnnotationDescriptor#getRepeatableContainer() container} form instead of
41+
* {@linkplain AnnotationDescriptor#isRepeatable() repeatable} annotations.
42+
*
43+
* @throws RepeatableAnnotationException Indicates a {@linkplain AnnotationDescriptor#isRepeatable() repeatable}
44+
* annotation was passed.
3145
*/
3246
default <A extends Annotation> MutableAnnotationUsage<A> applyAnnotationUsage(
33-
AnnotationDescriptor<A> annotationType,
47+
AnnotationDescriptor<A> annotationDescriptor,
3448
SourceModelBuildingContext buildingContext) {
35-
final MutableAnnotationUsage<A> existing = (MutableAnnotationUsage<A>) getAnnotationUsage( annotationType );
49+
if ( annotationDescriptor.isRepeatable() ) {
50+
throw new RepeatableAnnotationException( annotationDescriptor, this );
51+
}
52+
53+
final MutableAnnotationUsage<A> existing = (MutableAnnotationUsage<A>) getAnnotationUsage( annotationDescriptor );
3654
if ( existing != null ) {
3755
return existing;
3856
}
3957

40-
final MutableAnnotationUsage<A> usage = annotationType.createUsage( buildingContext );
58+
final MutableAnnotationUsage<A> usage = annotationDescriptor.createUsage( buildingContext );
4159
addAnnotationUsage( usage );
4260
return usage;
4361
}

0 commit comments

Comments
 (0)