Skip to content

Commit e386e53

Browse files
committed
Use less confusing MergedAnnotation method names
Rename some `MergedAnnotation` methods to prevent using parent/child terminology, specifically: `getDepth()` has been renamed `getDistance()` `getParent()` has been renamed `getMetaSource()` `getTypeHierarchy()` has been renamed `getMetaTypes()` The parent child naming was particularly confusing given that the parent/child relationships were inverted from the way that a lot of users think about meta-annotations. For example, a `@RequestMapping` having a parent of `@GetMapping` feels odd given that `@GetMapping` is the thing declaring the meta-annotation relationship. The new method names are designed to align more closely with existing terms. For example, `getMetaSource` hints at the relationship with `isMetaAnnotated` and `getSource`. Closes gh-22946
1 parent 4f4427f commit e386e53

18 files changed

+173
-162
lines changed

spring-core/src/main/java/org/springframework/core/annotation/AbstractMergedAnnotation.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ abstract class AbstractMergedAnnotation<A extends Annotation> implements MergedA
4141

4242
@Override
4343
public boolean isDirectlyPresent() {
44-
return isPresent() && getDepth() == 0;
44+
return isPresent() && getDistance() == 0;
4545
}
4646

4747
@Override
4848
public boolean isMetaPresent() {
49-
return isPresent() && getDepth() > 0;
49+
return isPresent() && getDistance() > 0;
5050
}
5151

5252
@Override

spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ public static MultiValueMap<String, Object> getAllAnnotationAttributes(Annotated
502502

503503
Adapt[] adaptations = Adapt.values(classValuesAsString, nestedAnnotationsAsMap);
504504
return getAnnotations(element).stream(annotationName)
505-
.filter(MergedAnnotationPredicates.unique(MergedAnnotation::getTypeHierarchy))
505+
.filter(MergedAnnotationPredicates.unique(MergedAnnotation::getMetaTypes))
506506
.map(MergedAnnotation::withNonMergedAttributes)
507507
.collect(MergedAnnotationCollectors.toMultiValueMap(AnnotatedElementUtils::nullIfEmpty, adaptations));
508508
}

spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@
4949
final class AnnotationTypeMapping {
5050

5151
@Nullable
52-
private final AnnotationTypeMapping parent;
52+
private final AnnotationTypeMapping source;
5353

5454
private final AnnotationTypeMapping root;
5555

56-
private final int depth;
56+
private final int distance;
5757

5858
private final Class<? extends Annotation> annotationType;
5959

60-
private final List<Class<? extends Annotation>> annotationTypeHierarchy;
60+
private final List<Class<? extends Annotation>> metaTypes;
6161

6262
@Nullable
6363
private final Annotation annotation;
@@ -79,15 +79,15 @@ final class AnnotationTypeMapping {
7979
private final Set<Method> claimedAliases = new HashSet<>();
8080

8181

82-
AnnotationTypeMapping(@Nullable AnnotationTypeMapping parent,
82+
AnnotationTypeMapping(@Nullable AnnotationTypeMapping source,
8383
Class<? extends Annotation> annotationType, @Nullable Annotation annotation) {
8484

85-
this.parent = parent;
86-
this.root = (parent != null ? parent.getRoot() : this);
87-
this.depth = (parent == null ? 0 : parent.getDepth() + 1);
85+
this.source = source;
86+
this.root = (source != null ? source.getRoot() : this);
87+
this.distance = (source == null ? 0 : source.getDistance() + 1);
8888
this.annotationType = annotationType;
89-
this.annotationTypeHierarchy = merge(
90-
parent != null ? parent.getAnnotationTypeHierarchy() : null,
89+
this.metaTypes = merge(
90+
source != null ? source.getMetaTypes() : null,
9191
annotationType);
9292
this.annotation = annotation;
9393
this.attributes = AttributeMethods.forAnnotationType(annotationType);
@@ -223,7 +223,7 @@ private void collectAliases(List<Method> aliases) {
223223
aliases.addAll(additional);
224224
}
225225
}
226-
mapping = mapping.parent;
226+
mapping = mapping.source;
227227
}
228228
}
229229

@@ -250,7 +250,7 @@ private void processAliases(int attributeIndex, List<Method> aliases) {
250250
}
251251
}
252252
}
253-
mapping = mapping.parent;
253+
mapping = mapping.source;
254254
}
255255
}
256256

@@ -265,7 +265,7 @@ private int getFirstRootAttributeIndex(Collection<Method> aliases) {
265265
}
266266

267267
private void addConventionMappings() {
268-
if (this.depth == 0) {
268+
if (this.distance == 0) {
269269
return;
270270
}
271271
AttributeMethods rootAttributes = this.root.getAttributes();
@@ -290,13 +290,13 @@ private void addConventionAnnotationValues() {
290290
Method attribute = this.attributes.get(i);
291291
boolean isValueAttribute = MergedAnnotation.VALUE.equals(attribute.getName());
292292
AnnotationTypeMapping mapping = this;
293-
while (mapping != null && mapping.depth > 0) {
293+
while (mapping != null && mapping.distance > 0) {
294294
int mapped = mapping.getAttributes().indexOf(attribute.getName());
295295
if (mapped != -1 && isBetterConventionAnnotationValue(i, isValueAttribute, mapping)) {
296296
this.annotationValueMappings[i] = mapped;
297297
this.annotationValueSource[i] = mapping;
298298
}
299-
mapping = mapping.parent;
299+
mapping = mapping.source;
300300
}
301301
}
302302
}
@@ -306,8 +306,8 @@ private boolean isBetterConventionAnnotationValue(int index, boolean isValueAttr
306306
if (this.annotationValueMappings[index] == -1) {
307307
return true;
308308
}
309-
int existingDepth = this.annotationValueSource[index].depth;
310-
return !isValueAttribute && existingDepth > mapping.depth;
309+
int existingDistance = this.annotationValueSource[index].distance;
310+
return !isValueAttribute && existingDistance > mapping.distance;
311311
}
312312

313313
/**
@@ -363,20 +363,20 @@ AnnotationTypeMapping getRoot() {
363363
}
364364

365365
/**
366-
* Get the parent mapping or {@code null}.
367-
* @return the parent mapping
366+
* Get the source of the mapping or {@code null}.
367+
* @return the source of the mapping
368368
*/
369369
@Nullable
370-
AnnotationTypeMapping getParent() {
371-
return this.parent;
370+
AnnotationTypeMapping getSource() {
371+
return this.source;
372372
}
373373

374374
/**
375-
* Get the depth of this mapping.
376-
* @return the depth of the mapping
375+
* Get the distance of this mapping.
376+
* @return the distance of the mapping
377377
*/
378-
int getDepth() {
379-
return this.depth;
378+
int getDistance() {
379+
return this.distance;
380380
}
381381

382382
/**
@@ -387,8 +387,8 @@ Class<? extends Annotation> getAnnotationType() {
387387
return this.annotationType;
388388
}
389389

390-
List<Class<? extends Annotation>> getAnnotationTypeHierarchy() {
391-
return this.annotationTypeHierarchy;
390+
List<Class<? extends Annotation>> getMetaTypes() {
391+
return this.metaTypes;
392392
}
393393

394394
/**

spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMappings.java

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,64 +73,66 @@ private void addAllMappings(Class<? extends Annotation> annotationType) {
7373
}
7474
}
7575

76-
private void addMetaAnnotationsToQueue(Deque<AnnotationTypeMapping> queue, AnnotationTypeMapping parent) {
76+
private void addMetaAnnotationsToQueue(Deque<AnnotationTypeMapping> queue, AnnotationTypeMapping source) {
7777
Annotation[] metaAnnotations =
78-
AnnotationsScanner.getDeclaredAnnotations(parent.getAnnotationType(), false);
78+
AnnotationsScanner.getDeclaredAnnotations(source.getAnnotationType(), false);
7979
for (Annotation metaAnnotation : metaAnnotations) {
80-
if (!isMappable(parent, metaAnnotation)) {
80+
if (!isMappable(source, metaAnnotation)) {
8181
continue;
8282
}
8383
Annotation[] repeatedAnnotations = RepeatableContainers.standardRepeatables()
8484
.findRepeatedAnnotations(metaAnnotation);
8585
if (repeatedAnnotations != null) {
8686
for (Annotation repeatedAnnotation : repeatedAnnotations) {
87-
if (!isMappable(parent, metaAnnotation)) {
87+
if (!isMappable(source, metaAnnotation)) {
8888
continue;
8989
}
90-
addIfPossible(queue, parent, repeatedAnnotation);
90+
addIfPossible(queue, source, repeatedAnnotation);
9191
}
9292
}
9393
else {
94-
addIfPossible(queue, parent, metaAnnotation);
94+
addIfPossible(queue, source, metaAnnotation);
9595
}
9696
}
9797
}
9898

99-
private void addIfPossible(Deque<AnnotationTypeMapping> queue, AnnotationTypeMapping parent, Annotation ann) {
100-
addIfPossible(queue, parent, ann.annotationType(), ann);
99+
private void addIfPossible(Deque<AnnotationTypeMapping> queue,
100+
AnnotationTypeMapping source, Annotation ann) {
101+
102+
addIfPossible(queue, source, ann.annotationType(), ann);
101103
}
102104

103-
private void addIfPossible(Deque<AnnotationTypeMapping> queue, @Nullable AnnotationTypeMapping parent,
105+
private void addIfPossible(Deque<AnnotationTypeMapping> queue, @Nullable AnnotationTypeMapping source,
104106
Class<? extends Annotation> annotationType, @Nullable Annotation ann) {
105107

106108
try {
107-
queue.addLast(new AnnotationTypeMapping(parent, annotationType, ann));
109+
queue.addLast(new AnnotationTypeMapping(source, annotationType, ann));
108110
}
109111
catch (Exception ex) {
110112
if (ex instanceof AnnotationConfigurationException) {
111113
throw (AnnotationConfigurationException) ex;
112114
}
113115
if (failureLogger.isEnabled()) {
114116
failureLogger.log("Failed to introspect meta-annotation " + annotationType.getName(),
115-
(parent != null ? parent.getAnnotationType() : null), ex);
117+
(source != null ? source.getAnnotationType() : null), ex);
116118
}
117119
}
118120
}
119121

120-
private boolean isMappable(AnnotationTypeMapping parent, @Nullable Annotation metaAnnotation) {
122+
private boolean isMappable(AnnotationTypeMapping source, @Nullable Annotation metaAnnotation) {
121123
return (metaAnnotation != null && !this.filter.matches(metaAnnotation) &&
122-
!AnnotationFilter.PLAIN.matches(parent.getAnnotationType()) &&
123-
!isAlreadyMapped(parent, metaAnnotation));
124+
!AnnotationFilter.PLAIN.matches(source.getAnnotationType()) &&
125+
!isAlreadyMapped(source, metaAnnotation));
124126
}
125127

126-
private boolean isAlreadyMapped(AnnotationTypeMapping parent, Annotation metaAnnotation) {
128+
private boolean isAlreadyMapped(AnnotationTypeMapping source, Annotation metaAnnotation) {
127129
Class<? extends Annotation> annotationType = metaAnnotation.annotationType();
128-
AnnotationTypeMapping mapping = parent;
130+
AnnotationTypeMapping mapping = source;
129131
while (mapping != null) {
130132
if (mapping.getAnnotationType() == annotationType) {
131133
return true;
132134
}
133-
mapping = mapping.getParent();
135+
mapping = mapping.getSource();
134136
}
135137
return false;
136138
}

spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ public static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedE
229229
}
230230

231231
private static <A extends Annotation> boolean isSingleLevelPresent(MergedAnnotation<A> mergedAnnotation) {
232-
int depth = mergedAnnotation.getDepth();
233-
return (depth == 0 || depth == 1);
232+
int distance = mergedAnnotation.getDistance();
233+
return (distance == 0 || distance == 1);
234234
}
235235

236236
/**

spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,6 @@ public interface MergedAnnotation<A extends Annotation> {
7373
*/
7474
Class<A> getType();
7575

76-
/**
77-
* Return a complete type hierarchy from this annotation to the
78-
* {@link #getRoot() root}. Provides a useful way to uniquely identify a
79-
* merged annotation instance.
80-
* @return the type hierarchy for the annotation
81-
* @see MergedAnnotationPredicates#unique(Function)
82-
*/
83-
List<Class<? extends Annotation>> getTypeHierarchy();
84-
8576
/**
8677
* Determine if the annotation is present on the source. Considers
8778
* {@linkplain #isDirectlyPresent() directly present} and
@@ -109,14 +100,14 @@ public interface MergedAnnotation<A extends Annotation> {
109100
boolean isMetaPresent();
110101

111102
/**
112-
* Get the depth of this annotation related to its use as a
113-
* meta-annotation. A directly declared annotation has a depth of {@code 0},
114-
* a meta-annotation has a depth of {@code 1}, a meta-annotation on a
115-
* meta-annotation has a depth of {@code 2}, etc. A {@linkplain #missing()
116-
* missing} annotation will always return a depth of {@code -1}.
117-
* @return the annotation depth or {@code -1} if the annotation is missing
103+
* Get the distance of this annotation related to its use as a
104+
* meta-annotation. A directly declared annotation has a distance of {@code 0},
105+
* a meta-annotation has a distance of {@code 1}, a meta-annotation on a
106+
* meta-annotation has a distance of {@code 2}, etc. A {@linkplain #missing()
107+
* missing} annotation will always return a distance of {@code -1}.
108+
* @return the annotation distance or {@code -1} if the annotation is missing
118109
*/
119-
int getDepth();
110+
int getDistance();
120111

121112
/**
122113
* Get the index of the aggregate collection containing this annotation.
@@ -130,33 +121,50 @@ public interface MergedAnnotation<A extends Annotation> {
130121
int getAggregateIndex();
131122

132123
/**
133-
* Get the source that ultimately declared the annotation, or
124+
* Get the source that ultimately declared the root annotation, or
134125
* {@code null} if the source is not known. If this merged annotation was
135126
* created {@link MergedAnnotations#from(java.lang.reflect.AnnotatedElement)
136127
* from} an {@link AnnotatedElement} then this source will be an element of
137128
* the same type. If the annotation was loaded without using reflection, the
138129
* source can be of any type, but should have a sensible {@code toString()}.
139-
* Meta-annotations will return the same source as the {@link #getParent()}.
130+
* Meta-annotations will always return the same source as the
131+
* {@link #getRoot() root}.
140132
* @return the source, or {@code null}
141133
*/
142134
@Nullable
143135
Object getSource();
144136

145137
/**
146-
* Get the parent of the meta-annotation, or {@code null} if the
147-
* annotation is not {@linkplain #isMetaPresent() meta-present}.
148-
* @return the parent annotation or {@code null}
138+
* Get the source of the meta-annotation, or {@code null} if the
139+
* annotation is not {@linkplain #isMetaPresent() meta-present}. The
140+
* meta-source is the annotation that was meta-annotated with this
141+
* annotation.
142+
* @return the meta-annotation source or {@code null}
143+
* @see #getRoot()
149144
*/
150145
@Nullable
151-
MergedAnnotation<?> getParent();
146+
MergedAnnotation<?> getMetaSource();
152147

153148
/**
154-
* Get the root annotation, i.e. the {@link #getDepth() depth} {@code 0}
149+
* Get the root annotation, i.e. the {@link #getDistance() distance} {@code 0}
155150
* annotation as directly declared on the source.
156151
* @return the root annotation
152+
* @see #getMetaSource()
157153
*/
158154
MergedAnnotation<?> getRoot();
159155

156+
/**
157+
* Return the complete list of annotation types from this annotation to the
158+
* {@link #getRoot() root}. Provides a useful way to uniquely identify a
159+
* merged annotation instance.
160+
* @return the meta types for the annotation
161+
* @see MergedAnnotationPredicates#unique(Function)
162+
* @see #getRoot()
163+
* @see #getMetaSource()
164+
*/
165+
List<Class<? extends Annotation>> getMetaTypes();
166+
167+
160168
/**
161169
* Determine if the specified attribute name has a non-default value when
162170
* compared to the annotation declaration.
@@ -433,7 +441,8 @@ <T extends Annotation> MergedAnnotation<T>[] getAnnotationArray(String attribute
433441
/**
434442
* Create a new view of the annotation that exposes non-merged attribute values.
435443
* <p>Methods from this view will return attribute values with only alias mirroring
436-
* rules applied. Aliases to parent attributes will not be applied.
444+
* rules applied. Aliases to {@link #getMetaSource() meta-source} attributes will
445+
* not be applied.
437446
* @return a non-merged view of the annotation
438447
*/
439448
MergedAnnotation<A> withNonMergedAttributes();

spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationPredicates.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ public static <A extends Annotation> Predicate<MergedAnnotation<? extends A>> ty
8181
/**
8282
* Create a new stateful, single use {@link Predicate} that matches only
8383
* the first run of an extracted value. For example,
84-
* {@code MergedAnnotationPredicates.firstRunOf(MergedAnnotation::depth)}
85-
* will return the first annotation and a subsequent run of the same depth.
84+
* {@code MergedAnnotationPredicates.firstRunOf(MergedAnnotation::distance)}
85+
* will return the first annotation and a subsequent run of the same distance.
8686
* <p>NOTE: This predicate only matches the first first run. Once the extracted
8787
* value changes, the predicate always returns {@code false}.
8888
* @param valueExtractor function used to extract the value to check

0 commit comments

Comments
 (0)