Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5f91ec4

Browse files
committed
Merge pull request #134 from NagyGa1/feature/field_annotations_checking
Allow for checking field level annotations from DiffNode
2 parents 741520d + fd2da3f commit 5f91ec4

File tree

5 files changed

+243
-0
lines changed

5 files changed

+243
-0
lines changed

‎src/main/java/de/danielbechler/diff/access/PropertyAwareAccessor.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ public interface PropertyAwareAccessor extends TypeAwareAccessor, CategoryAware,
2626
{
2727
String getPropertyName();
2828

29+
Set<Annotation> getFieldAnnotations();
30+
31+
<T extends Annotation> T getFieldAnnotation(Class<T> annotationClass);
32+
2933
Set<Annotation> getReadMethodAnnotations();
3034

3135
<T extends Annotation> T getReadMethodAnnotation(Class<T> annotationClass);

‎src/main/java/de/danielbechler/diff/introspection/PropertyAccessor.java‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,58 @@ public String getPropertyName()
8383
return this.propertyName;
8484
}
8585

86+
/**
87+
* Private function to allow looking for the field recursively up the superclasses.
88+
*
89+
* @param clazz
90+
* @return
91+
*/
92+
private Set<Annotation> getFieldAnnotations(final Class<?> clazz)
93+
{
94+
try
95+
{
96+
return new LinkedHashSet<Annotation>(asList(clazz.getDeclaredField(propertyName).getAnnotations()));
97+
} catch (NoSuchFieldException e)
98+
{
99+
if (clazz.getSuperclass() != null)
100+
{
101+
return getFieldAnnotations(clazz.getSuperclass());
102+
}
103+
else
104+
{
105+
logger.debug("Cannot find propertyName: {}, declaring class: {}", propertyName, clazz);
106+
return new LinkedHashSet<Annotation>(0);
107+
}
108+
}
109+
}
110+
111+
/**
112+
* @return The annotations of the field, or an empty set if there is no field with the name derived from the getter.
113+
*/
114+
public Set<Annotation> getFieldAnnotations()
115+
{
116+
return getFieldAnnotations(readMethod.getDeclaringClass());
117+
}
118+
119+
/**
120+
* @return The given annotation of the field, or null if not annotated or if there is no field with the name derived
121+
* from the getter.
122+
*/
123+
public <T extends Annotation> T getFieldAnnotation(final Class<T> annotationClass)
124+
{
125+
final Set<? extends Annotation> annotations = getFieldAnnotations();
126+
assert (annotations != null) : "Something is wrong here. " +
127+
"The contract of getReadAnnotations() guarantees a non-null return value.";
128+
for (final Annotation annotation : annotations)
129+
{
130+
if (annotationClass.isAssignableFrom(annotation.annotationType()))
131+
{
132+
return annotationClass.cast(annotation);
133+
}
134+
}
135+
return null;
136+
}
137+
86138
/**
87139
* @return The annotations of the getter used to access this property.
88140
*/

‎src/main/java/de/danielbechler/diff/node/DiffNode.java‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,37 @@ public final void visitParents(final Visitor visitor)
443443
}
444444
}
445445

446+
/**
447+
* If this node represents a bean property this method returns all annotations of its field.
448+
*
449+
* Only works for fields having a name that matches the name derived from the getter.
450+
*
451+
* @return The annotations of the field, or an empty set if there is no field with the name derived from the getter.
452+
*/
453+
public Set<Annotation> getFieldAnnotations()
454+
{
455+
if (accessor instanceof PropertyAwareAccessor)
456+
{
457+
return unmodifiableSet(((PropertyAwareAccessor) accessor).getFieldAnnotations());
458+
}
459+
return unmodifiableSet(Collections.<Annotation>emptySet());
460+
}
461+
462+
/**
463+
* @param annotationClass the annotation we are looking for
464+
* @param <T>
465+
* @return The given annotation of the field, or null if not annotated or if there is no field with the name derived
466+
* from the getter.
467+
*/
468+
public <T extends Annotation> T getFieldAnnotation(final Class<T> annotationClass)
469+
{
470+
if (accessor instanceof PropertyAwareAccessor)
471+
{
472+
return ((PropertyAwareAccessor) accessor).getFieldAnnotation(annotationClass);
473+
}
474+
return null;
475+
}
476+
446477
/**
447478
* If this node represents a bean property this method returns all annotations of its getter.
448479
*
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright 2014 Daniel Bechler
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package de.danielbechler.diff.node
18+
19+
import de.danielbechler.diff.access.Accessor
20+
import de.danielbechler.diff.introspection.PropertyAccessor
21+
import de.danielbechler.diff.selector.BeanPropertyElementSelector
22+
import spock.lang.Specification
23+
24+
class DiffNodeFieldAnnotationsTest extends Specification {
25+
26+
def 'getFieldAnnotation(): returns null if not PropertyAwareAccessor'() {
27+
given:
28+
def accessor = Mock(Accessor) {
29+
getElementSelector() >> new BeanPropertyElementSelector('f')
30+
}
31+
def diffNode = new DiffNode(null, accessor, A)
32+
expect:
33+
diffNode.fieldAnnotations.size() == 0
34+
diffNode.getFieldAnnotation(SomeFieldAnnotation) == null
35+
}
36+
37+
def 'getFieldAnnotation(): class has the field and annotated'() {
38+
given:
39+
def accessor = new PropertyAccessor("f", A.getMethod("getF"), A.getMethod("setF", String))
40+
def diffNode = new DiffNode(null, accessor, A)
41+
expect:
42+
diffNode.fieldAnnotations.size() == 1
43+
diffNode.getFieldAnnotation(SomeFieldAnnotation) != null
44+
diffNode.getFieldAnnotation(SomeFieldAnnotation).annotationType() == SomeFieldAnnotation
45+
}
46+
47+
def 'getFieldAnnotation(): class does not have the field, or different name'() {
48+
given:
49+
def accessor = new PropertyAccessor("F", ADiffName.getMethod("getF"), null)
50+
def diffNode = new DiffNode(null, accessor, ADiffName)
51+
expect:
52+
diffNode.fieldAnnotations.size() == 0
53+
diffNode.getFieldAnnotation(SomeFieldAnnotation) == null
54+
}
55+
56+
def 'getFieldAnnotation(): inheritance'() {
57+
given:
58+
def accessor = new PropertyAccessor("f", AB.getMethod("getF"), AB.getMethod("setF", String))
59+
def diffNode = new DiffNode(null, accessor, AB)
60+
expect:
61+
diffNode.fieldAnnotations.size() == 1
62+
diffNode.getFieldAnnotation(SomeFieldAnnotation) != null
63+
diffNode.getFieldAnnotation(SomeFieldAnnotation).annotationType() == SomeFieldAnnotation
64+
}
65+
66+
def 'getFieldAnnotation(): inheritance, overridden getter'() {
67+
given:
68+
def accessor = new PropertyAccessor("f", ABGetter.getMethod("getF"), ABGetter.getMethod("setF", String))
69+
def diffNode = new DiffNode(null, accessor, ABGetter)
70+
expect:
71+
diffNode.fieldAnnotations.size() == 1
72+
diffNode.getFieldAnnotation(SomeFieldAnnotation) != null
73+
diffNode.getFieldAnnotation(SomeFieldAnnotation).annotationType() == SomeFieldAnnotation
74+
}
75+
76+
def 'getFieldAnnotation(): inheritance, not annotated'() {
77+
given:
78+
def accessor = new PropertyAccessor("f", NAB.getMethod("getF"), NAB.getMethod("setF", String))
79+
def diffNode = new DiffNode(null, accessor, NAB)
80+
expect:
81+
diffNode.fieldAnnotations.size() == 0
82+
diffNode.getFieldAnnotation(SomeFieldAnnotation) == null
83+
}
84+
85+
def 'getFieldAnnotation(): inheritance, overridden getter, not annotated'() {
86+
given:
87+
def accessor = new PropertyAccessor("f", NABGetter.getMethod("getF"), NABGetter.getMethod("setF", String))
88+
def diffNode = new DiffNode(null, accessor, NABGetter)
89+
expect:
90+
diffNode.fieldAnnotations.size() == 0
91+
diffNode.getFieldAnnotation(SomeFieldAnnotation) == null
92+
}
93+
94+
public static class A {
95+
@SomeFieldAnnotation
96+
String f;
97+
}
98+
99+
public static class NA {
100+
String f;
101+
}
102+
103+
public static class ADiffName {
104+
public String getF() {
105+
return null;
106+
}
107+
}
108+
109+
public static class AB extends A {
110+
}
111+
112+
public static class ABGetter extends A {
113+
@Override
114+
public String getF() {
115+
return null;
116+
}
117+
}
118+
119+
public static class NAB extends NA {
120+
}
121+
122+
public static class NABGetter extends NA {
123+
@Override
124+
public String getF() {
125+
return null;
126+
}
127+
}
128+
129+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2013 Daniel Bechler
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package de.danielbechler.diff.node;
18+
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
@Retention(RetentionPolicy.RUNTIME)
25+
@Target(ElementType.FIELD)
26+
public @interface SomeFieldAnnotation {
27+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /