Skip to content

Commit a40e247

Browse files
christophstroblodrotbohm
authored andcommitted
DATACMNS-825 - Allow usage of composed annotations using @AliasFor.
We now resolve composed annotation values using @AliasFor within AnnotationBasedPersistentProperty and BasicPersistentEntity. Nevertheless it is up to the individual store implementation to make use of this. Original pull request: #156.
1 parent ae96301 commit a40e247

File tree

6 files changed

+91
-15
lines changed

6 files changed

+91
-15
lines changed

src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2014 the original author or authors.
2+
* Copyright 2011-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
2525

2626
import org.springframework.beans.factory.annotation.Autowired;
2727
import org.springframework.beans.factory.annotation.Value;
28-
import org.springframework.core.annotation.AnnotationUtils;
28+
import org.springframework.core.annotation.AnnotatedElementUtils;
2929
import org.springframework.data.annotation.AccessType;
3030
import org.springframework.data.annotation.AccessType.Type;
3131
import org.springframework.data.annotation.Id;
@@ -223,14 +223,15 @@ public <A extends Annotation> A findAnnotation(Class<A> annotationType) {
223223
continue;
224224
}
225225

226-
A annotation = AnnotationUtils.findAnnotation(method, annotationType);
226+
A annotation = AnnotatedElementUtils.findMergedAnnotation(method, annotationType);
227227

228228
if (annotation != null) {
229229
return cacheAndReturn(annotationType, annotation);
230230
}
231231
}
232232

233-
return cacheAndReturn(annotationType, field == null ? null : AnnotationUtils.getAnnotation(field, annotationType));
233+
return cacheAndReturn(annotationType,
234+
field == null ? null : AnnotatedElementUtils.findMergedAnnotation(field, annotationType));
234235
}
235236

236237
/*

src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2015 by the original author(s).
2+
* Copyright 2011-2016 by the original author(s).
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
2727
import java.util.Set;
2828
import java.util.TreeSet;
2929

30-
import org.springframework.core.annotation.AnnotationUtils;
30+
import org.springframework.core.annotation.AnnotatedElementUtils;
3131
import org.springframework.data.annotation.TypeAlias;
3232
import org.springframework.data.mapping.Association;
3333
import org.springframework.data.mapping.AssociationHandler;
@@ -50,6 +50,7 @@
5050
* @author Jon Brisbin
5151
* @author Patryk Wasik
5252
* @author Thomas Darimont
53+
* @author Christoph Strobl
5354
*/
5455
public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implements MutablePersistentEntity<T, P> {
5556

@@ -284,7 +285,7 @@ public Class<T> getType() {
284285
*/
285286
public Object getTypeAlias() {
286287

287-
TypeAlias alias = getType().getAnnotation(TypeAlias.class);
288+
TypeAlias alias = AnnotatedElementUtils.findMergedAnnotation(getType(), TypeAlias.class);
288289
return alias == null ? null : StringUtils.hasText(alias.value()) ? alias.value() : null;
289290
}
290291

@@ -366,7 +367,7 @@ public <A extends Annotation> A findAnnotation(Class<A> annotationType) {
366367
return annotation;
367368
}
368369

369-
annotation = AnnotationUtils.findAnnotation(getType(), annotationType);
370+
annotation = AnnotatedElementUtils.findMergedAnnotation(getType(), annotationType);
370371
annotationCache.put(annotationType, annotation);
371372

372373
return annotation;

src/main/java/org/springframework/data/util/AnnotationDetectionFieldCallback.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2014 the original author or authors.
2+
* Copyright 2012-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
import java.lang.annotation.Annotation;
1919
import java.lang.reflect.Field;
2020

21+
import org.springframework.core.annotation.AnnotatedElementUtils;
2122
import org.springframework.util.Assert;
2223
import org.springframework.util.ReflectionUtils;
2324
import org.springframework.util.ReflectionUtils.FieldCallback;
@@ -27,6 +28,7 @@
2728
* afterwards.
2829
*
2930
* @author Oliver Gierke
31+
* @author Christoph Strobl
3032
*/
3133
public class AnnotationDetectionFieldCallback implements FieldCallback {
3234

@@ -54,7 +56,7 @@ public void doWith(Field field) throws IllegalArgumentException, IllegalAccessEx
5456
return;
5557
}
5658

57-
Annotation annotation = field.getAnnotation(annotationType);
59+
Annotation annotation = AnnotatedElementUtils.findMergedAnnotation(field, annotationType);
5860

5961
if (annotation != null) {
6062

src/main/java/org/springframework/data/util/AnnotationDetectionMethodCallback.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,14 +18,15 @@
1818
import java.lang.annotation.Annotation;
1919
import java.lang.reflect.Method;
2020

21-
import org.springframework.core.annotation.AnnotationUtils;
21+
import org.springframework.core.annotation.AnnotatedElementUtils;
2222
import org.springframework.util.Assert;
2323
import org.springframework.util.ReflectionUtils.MethodCallback;
2424

2525
/**
2626
* {@link MethodCallback} to find annotations of a given type.
2727
*
2828
* @author Oliver Gierke
29+
* @author Christoph Strobl
2930
*/
3031
public class AnnotationDetectionMethodCallback<A extends Annotation> implements MethodCallback {
3132

@@ -94,7 +95,7 @@ public void doWith(Method method) throws IllegalArgumentException, IllegalAccess
9495
return;
9596
}
9697

97-
A foundAnnotation = AnnotationUtils.findAnnotation(method, annotationType);
98+
A foundAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, annotationType);
9899

99100
if (foundAnnotation != null) {
100101

src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2014 the original author or authors.
2+
* Copyright 2013-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,6 +29,8 @@
2929

3030
import org.junit.Before;
3131
import org.junit.Test;
32+
import org.springframework.core.annotation.AliasFor;
33+
import org.springframework.core.annotation.AnnotationUtils;
3234
import org.springframework.data.annotation.AccessType;
3335
import org.springframework.data.annotation.AccessType.Type;
3436
import org.springframework.data.annotation.Id;
@@ -220,6 +222,37 @@ public void cachesNonPresenceOfAnnotationOnField() {
220222
assertThat(field.get(MyAnnotation.class), is(nullValue()));
221223
}
222224

225+
/**
226+
* @see DATACMNS-825
227+
*/
228+
@Test
229+
public void composedAnnotationWithAliasForGetCachedCorrectly() {
230+
231+
SamplePersistentProperty property = entity.getPersistentProperty("metaAliased");
232+
233+
// Assert direct annotations are cached on construction
234+
Map<Class<? extends Annotation>, Annotation> cache = getAnnotationCache(property);
235+
assertThat(cache.containsKey(MyComposedAnnotationUsingAliasFor.class), is(true));
236+
assertThat(cache.containsKey(MyAnnotation.class), is(false));
237+
238+
// Assert meta annotation is found and cached
239+
MyAnnotation annotation = property.findAnnotation(MyAnnotation.class);
240+
assertThat(annotation, is(notNullValue()));
241+
assertThat(cache.containsKey(MyAnnotation.class), is(true));
242+
}
243+
244+
/**
245+
* @see DATACMNS-825
246+
*/
247+
@Test
248+
public void composedAnnotationWithAliasShouldHaveSynthesizedAttributeValues() {
249+
250+
SamplePersistentProperty property = entity.getPersistentProperty("metaAliased");
251+
252+
MyAnnotation annotation = property.findAnnotation(MyAnnotation.class);
253+
assertThat(AnnotationUtils.getValue(annotation), is((Object) "spring"));
254+
}
255+
223256
@SuppressWarnings("unchecked")
224257
private Map<Class<? extends Annotation>, Annotation> getAnnotationCache(SamplePersistentProperty property) {
225258
return (Map<Class<? extends Annotation>, Annotation>) ReflectionTestUtils.getField(property, "annotationCache");
@@ -248,6 +281,8 @@ static class Sample {
248281

249282
@MyAnnotationAsMeta String meta;
250283

284+
@MyComposedAnnotationUsingAliasFor String metaAliased;
285+
251286
@MyAnnotation
252287
public String getGetter() {
253288
return getter;
@@ -314,6 +349,15 @@ public String getProperty() {
314349

315350
}
316351

352+
@Retention(RetentionPolicy.RUNTIME)
353+
@Target(value = { FIELD, METHOD })
354+
@MyAnnotation
355+
public static @interface MyComposedAnnotationUsingAliasFor {
356+
357+
@AliasFor(annotation = MyAnnotation.class, attribute = "value")
358+
String name() default "spring";
359+
}
360+
317361
@Retention(RetentionPolicy.RUNTIME)
318362
@Target(value = { FIELD, METHOD, ANNOTATION_TYPE })
319363
@Id

src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2015 the original author or authors.
2+
* Copyright 2011-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@
1919
import static org.junit.Assert.*;
2020
import static org.mockito.Mockito.*;
2121

22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.RetentionPolicy;
2224
import java.util.Comparator;
2325
import java.util.Iterator;
2426
import java.util.List;
@@ -30,6 +32,7 @@
3032
import org.mockito.Mock;
3133
import org.mockito.Mockito;
3234
import org.mockito.runners.MockitoJUnitRunner;
35+
import org.springframework.core.annotation.AliasFor;
3336
import org.springframework.data.annotation.CreatedBy;
3437
import org.springframework.data.annotation.CreatedDate;
3538
import org.springframework.data.annotation.LastModifiedBy;
@@ -224,6 +227,17 @@ public void supportsSubtypeInstancesOnPropertyAccessorLookup() {
224227
assertThat(entity.getPropertyAccessor(new Subtype()), is(notNullValue()));
225228
}
226229

230+
/**
231+
* @see DATACMNS-825
232+
*/
233+
@Test
234+
public void returnsTypeAliasIfAnnotatedUsingComposedAnnotation() {
235+
236+
PersistentEntity<AliasEntityUsingComposedAnnotation, T> entity = createEntity(
237+
AliasEntityUsingComposedAnnotation.class);
238+
assertThat(entity.getTypeAlias(), is((Object) "bar"));
239+
}
240+
227241
private <S> BasicPersistentEntity<S, T> createEntity(Class<S> type) {
228242
return createEntity(type, null);
229243
}
@@ -251,5 +265,18 @@ public String getProperty() {
251265
}
252266
}
253267

268+
@Retention(RetentionPolicy.RUNTIME)
269+
@TypeAlias("foo")
270+
static @interface ComposedTypeAlias {
271+
272+
@AliasFor(annotation = TypeAlias.class, attribute = "value")
273+
String name() default "bar";
274+
}
275+
276+
@ComposedTypeAlias
277+
static class AliasEntityUsingComposedAnnotation {
278+
279+
}
280+
254281
static class Subtype extends Entity {}
255282
}

0 commit comments

Comments
 (0)