Skip to content

DATACMNS-825 - Allow usage of composed annotations using @AliasFor. #156

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>1.12.0.BUILD-SNAPSHOT</version>
<version>1.12.0.DATACMNS-825-SNAPSHOT</version>

<name>Spring Data Core</name>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2014 the original author or authors.
* Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -25,7 +25,7 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.AccessType.Type;
import org.springframework.data.annotation.Id;
Expand Down Expand Up @@ -223,14 +223,15 @@ public <A extends Annotation> A findAnnotation(Class<A> annotationType) {
continue;
}

A annotation = AnnotationUtils.findAnnotation(method, annotationType);
A annotation = AnnotatedElementUtils.findMergedAnnotation(method, annotationType);

if (annotation != null) {
return cacheAndReturn(annotationType, annotation);
}
}

return cacheAndReturn(annotationType, field == null ? null : AnnotationUtils.getAnnotation(field, annotationType));
return cacheAndReturn(annotationType,
field == null ? null : AnnotatedElementUtils.findMergedAnnotation(field, annotationType));
}

/*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 by the original author(s).
* Copyright 2011-2016 by the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,7 +27,7 @@
import java.util.Set;
import java.util.TreeSet;

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
Expand All @@ -50,6 +50,7 @@
* @author Jon Brisbin
* @author Patryk Wasik
* @author Thomas Darimont
* @author Christoph Strobl
*/
public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implements MutablePersistentEntity<T, P> {

Expand Down Expand Up @@ -284,7 +285,7 @@ public Class<T> getType() {
*/
public Object getTypeAlias() {

TypeAlias alias = getType().getAnnotation(TypeAlias.class);
TypeAlias alias = AnnotatedElementUtils.findMergedAnnotation(getType(), TypeAlias.class);
return alias == null ? null : StringUtils.hasText(alias.value()) ? alias.value() : null;
}

Expand Down Expand Up @@ -366,7 +367,7 @@ public <A extends Annotation> A findAnnotation(Class<A> annotationType) {
return annotation;
}

annotation = AnnotationUtils.findAnnotation(getType(), annotationType);
annotation = AnnotatedElementUtils.findMergedAnnotation(getType(), annotationType);
annotationCache.put(annotationType, annotation);

return annotation;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;
Expand All @@ -27,6 +28,7 @@
* afterwards.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
public class AnnotationDetectionFieldCallback implements FieldCallback {

Expand Down Expand Up @@ -54,7 +56,7 @@ public void doWith(Field field) throws IllegalArgumentException, IllegalAccessEx
return;
}

Annotation annotation = field.getAnnotation(annotationType);
Annotation annotation = AnnotatedElementUtils.findMergedAnnotation(field, annotationType);

if (annotation != null) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,14 +18,15 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils.MethodCallback;

/**
* {@link MethodCallback} to find annotations of a given type.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
public class AnnotationDetectionMethodCallback<A extends Annotation> implements MethodCallback {

Expand Down Expand Up @@ -94,7 +95,7 @@ public void doWith(Method method) throws IllegalArgumentException, IllegalAccess
return;
}

A foundAnnotation = AnnotationUtils.findAnnotation(method, annotationType);
A foundAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, annotationType);

if (foundAnnotation != null) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,6 +29,8 @@

import org.junit.Before;
import org.junit.Test;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.AccessType.Type;
import org.springframework.data.annotation.Id;
Expand Down Expand Up @@ -220,6 +222,37 @@ public void cachesNonPresenceOfAnnotationOnField() {
assertThat(field.get(MyAnnotation.class), is(nullValue()));
}

/**
* @see DATACMNS-825
*/
@Test
public void composedAnnotationWithAliasForGetCachedCorrectly() {

SamplePersistentProperty property = entity.getPersistentProperty("metaAliased");

// Assert direct annotations are cached on construction
Map<Class<? extends Annotation>, Annotation> cache = getAnnotationCache(property);
assertThat(cache.containsKey(MyComposedAnnotationUsingAliasFor.class), is(true));
assertThat(cache.containsKey(MyAnnotation.class), is(false));

// Assert meta annotation is found and cached
MyAnnotation annotation = property.findAnnotation(MyAnnotation.class);
assertThat(annotation, is(notNullValue()));
assertThat(cache.containsKey(MyAnnotation.class), is(true));
}

/**
* @see DATACMNS-825
*/
@Test
public void composedAnnotationWithAliasShouldHaveSynthesizedAttributeValues() {

SamplePersistentProperty property = entity.getPersistentProperty("metaAliased");

MyAnnotation annotation = property.findAnnotation(MyAnnotation.class);
assertThat(AnnotationUtils.getValue(annotation), is((Object) "spring"));
}

@SuppressWarnings("unchecked")
private Map<Class<? extends Annotation>, Annotation> getAnnotationCache(SamplePersistentProperty property) {
return (Map<Class<? extends Annotation>, Annotation>) ReflectionTestUtils.getField(property, "annotationCache");
Expand Down Expand Up @@ -248,6 +281,8 @@ static class Sample {

@MyAnnotationAsMeta String meta;

@MyComposedAnnotationUsingAliasFor String metaAliased;

@MyAnnotation
public String getGetter() {
return getter;
Expand Down Expand Up @@ -314,6 +349,15 @@ public String getProperty() {

}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD })
@MyAnnotation
public static @interface MyComposedAnnotationUsingAliasFor {

@AliasFor(annotation = MyAnnotation.class, attribute = "value")
String name() default "spring";
}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD, ANNOTATION_TYPE })
@Id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 the original author or authors.
* Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,6 +19,8 @@
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
Expand All @@ -30,6 +32,7 @@
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
Expand Down Expand Up @@ -224,6 +227,17 @@ public void supportsSubtypeInstancesOnPropertyAccessorLookup() {
assertThat(entity.getPropertyAccessor(new Subtype()), is(notNullValue()));
}

/**
* @see DATACMNS-825
*/
@Test
public void returnsTypeAliasIfAnnotatedUsingComposedAnnotation() {

PersistentEntity<AliasEntityUsingComposedAnnotation, T> entity = createEntity(
AliasEntityUsingComposedAnnotation.class);
assertThat(entity.getTypeAlias(), is((Object) "bar"));
}

private <S> BasicPersistentEntity<S, T> createEntity(Class<S> type) {
return createEntity(type, null);
}
Expand Down Expand Up @@ -251,5 +265,18 @@ public String getProperty() {
}
}

@Retention(RetentionPolicy.RUNTIME)
@TypeAlias("foo")
static @interface ComposedTypeAlias {

@AliasFor(annotation = TypeAlias.class, attribute = "value")
String name() default "bar";
}

@ComposedTypeAlias
static class AliasEntityUsingComposedAnnotation {

}

static class Subtype extends Entity {}
}