1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht.reflect.internal;
21
22 import org.grouplens.grapht.annotation.AnnotationBuilder;
23 import org.grouplens.grapht.annotation.Attribute;
24 import org.grouplens.grapht.reflect.Desire;
25 import org.grouplens.grapht.reflect.InjectionPoint;
26 import org.grouplens.grapht.reflect.internal.types.RoleA;
27 import org.grouplens.grapht.reflect.internal.types.RoleB;
28 import org.grouplens.grapht.reflect.internal.types.RoleD;
29 import org.junit.Assert;
30 import org.junit.Test;
31
32 import javax.annotation.Nullable;
33 import javax.inject.Inject;
34 import javax.inject.Named;
35 import java.lang.annotation.Annotation;
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 import java.lang.reflect.Constructor;
39 import java.lang.reflect.Field;
40 import java.lang.reflect.Method;
41 import java.util.HashSet;
42 import java.util.List;
43 import java.util.Set;
44
45 import static org.hamcrest.Matchers.*;
46
47 public class InjectionPointTest {
48 private static <T extends Annotation> Annotation named(String name) {
49 return AnnotationBuilder.of(Named.class).setValue(name).build();
50 }
51
52 @Test
53 public void testAttributesLookup() throws Exception {
54 Constructor<CtorType> ctor = CtorType.class.getConstructor(Object.class, String.class);
55 ConstructorParameterInjectionPoint p1 = new ConstructorParameterInjectionPoint(ctor, 0);
56 ConstructorParameterInjectionPoint p2 = new ConstructorParameterInjectionPoint(ctor, 1);
57
58
59 Assert.assertNotNull(p1.getAttribute(Transient.class));
60 Assert.assertNull(p2.getAttribute(Transient.class));
61 Assert.assertEquals(1, p1.getAttributes().size());
62 Assert.assertEquals(0, p2.getAttributes().size());
63 }
64
65 @Test
66 public void testConstructorParameterInjectionPoint() throws Exception {
67
68 Constructor<CtorType> ctor = CtorType.class.getConstructor(Object.class, String.class);
69 ConstructorParameterInjectionPoint p1 = new ConstructorParameterInjectionPoint(ctor, 0);
70 ConstructorParameterInjectionPoint p2 = new ConstructorParameterInjectionPoint(ctor, 1);
71
72 Set<InjectionPoint> expected = new HashSet<InjectionPoint>();
73 expected.add(p1);
74 expected.add(p2);
75
76
77 Assert.assertThat(p1.getQualifier(), instanceOf(RoleA.class));
78 Assert.assertThat(p2.getQualifier(), instanceOf(RoleB.class));
79 Assert.assertThat(p1.getAttribute(Transient.class), notNullValue());
80 Assert.assertThat(p1.getAttributes(), contains(instanceOf(Transient.class)));
81 Assert.assertThat(p2.getAttributes(), hasSize(0));
82 Assert.assertThat(p2.getAttribute(Transient.class), nullValue());
83
84 Assert.assertEquals(Object.class, p1.getType());
85 Assert.assertEquals(String.class, p2.getType());
86
87
88 Assert.assertFalse(p1.isNullable());
89 Assert.assertTrue(p2.isNullable());
90
91 Assert.assertEquals(expected, getInjectionPoints(CtorType.class));
92 }
93
94 @Test
95 public void testSetterMethodInjectionPoint() throws Exception {
96
97 Method m1 = SetterType.class.getMethod("setA", Object.class);
98 Method m2 = SetterType.class.getMethod("setB", String.class);
99 Method m3 = SetterType.class.getMethod("setMulti", Object.class, String.class);
100 SetterInjectionPoint p1 = new SetterInjectionPoint(m1, 0);
101 SetterInjectionPoint p2 = new SetterInjectionPoint(m2, 0);
102 SetterInjectionPoint p3 = new SetterInjectionPoint(m3, 0);
103 SetterInjectionPoint p4 = new SetterInjectionPoint(m3, 1);
104
105 Set<InjectionPoint> expected = new HashSet<InjectionPoint>();
106 expected.add(p1);
107 expected.add(p2);
108 expected.add(p3);
109 expected.add(p4);
110
111
112 Assert.assertThat(p1.getQualifier(), instanceOf(RoleA.class));
113 Assert.assertThat(p1.getAttribute(Transient.class), notNullValue());
114 Assert.assertThat(p1.getAttributes(), contains(instanceOf(Transient.class)));
115
116 Assert.assertThat(p2.getQualifier(), instanceOf(RoleB.class));
117 Assert.assertThat(p2.getAttributes(), hasSize(0));
118 Assert.assertThat(p2.getAttribute(Transient.class), nullValue());
119
120 Assert.assertThat(p3.getQualifier(), nullValue());
121 Assert.assertThat(p3.getAttributes(), hasSize(0));
122
123 Assert.assertThat(p4.getQualifier(), instanceOf(RoleD.class));
124 Assert.assertThat(p4.getAttributes(), hasSize(0));
125 Assert.assertThat(p4.getAttribute(Transient.class), nullValue());
126
127 Assert.assertEquals(Object.class, p1.getType());
128 Assert.assertEquals(String.class, p2.getType());
129 Assert.assertEquals(Object.class, p3.getType());
130 Assert.assertEquals(String.class, p4.getType());
131
132
133 Assert.assertFalse(p1.isNullable());
134 Assert.assertFalse(p2.isNullable());
135 Assert.assertFalse(p3.isNullable());
136 Assert.assertTrue(p4.isNullable());
137
138 Assert.assertEquals(expected, getInjectionPoints(SetterType.class));
139 }
140
141 @Test
142 public void testPrimitiveBoxing() throws Exception {
143 Method m1 = PrimitiveType.class.getMethod("setUnboxed", int.class);
144 Method m2 = PrimitiveType.class.getMethod("setBoxed", Integer.class);
145
146 SetterInjectionPoint p1 = new SetterInjectionPoint(m1, 0);
147 SetterInjectionPoint p2 = new SetterInjectionPoint(m2, 0);
148
149
150 Assert.assertEquals(Integer.class, p1.getType());
151 Assert.assertEquals(Integer.class, p2.getType());
152 }
153
154 @Test
155 public void testNamedQualifiers() throws Exception {
156 Constructor<NamedType> ctor = NamedType.class.getConstructor(String.class, Integer.class);
157 ConstructorParameterInjectionPoint p1 = new ConstructorParameterInjectionPoint(ctor, 0);
158 ConstructorParameterInjectionPoint p2 = new ConstructorParameterInjectionPoint(ctor, 1);
159
160 Set<InjectionPoint> expected = new HashSet<InjectionPoint>();
161 expected.add(p1);
162 expected.add(p2);
163
164
165 Assert.assertThat(p1.getQualifier(), equalTo(named("test1")));
166 Assert.assertThat(p2.getQualifier(), equalTo(named("test2")));
167
168 Assert.assertEquals(String.class, p1.getType());
169 Assert.assertEquals(Integer.class, p2.getType());
170
171 Assert.assertEquals(expected, getInjectionPoints(NamedType.class));
172 }
173
174 @Test
175 public void testFieldInjectionPoints() throws Exception {
176 Field f1 = FieldType.class.getField("field");
177 FieldInjectionPoint p1 = new FieldInjectionPoint(f1);
178
179 Set<InjectionPoint> expected = new HashSet<InjectionPoint>();
180 expected.add(p1);
181
182 Assert.assertEquals(expected, getInjectionPoints(FieldType.class));
183 }
184
185 @Test
186 public void testCombinedDesires() throws Exception {
187
188 Constructor<AllTypes> ctor = AllTypes.class.getConstructor(Object.class, String.class);
189 ConstructorParameterInjectionPoint p1 = new ConstructorParameterInjectionPoint(ctor, 0);
190 ConstructorParameterInjectionPoint p2 = new ConstructorParameterInjectionPoint(ctor, 1);
191 Method m1 = AllTypes.class.getMethod("setC", Object.class);
192 Method m2 = AllTypes.class.getMethod("setD", String.class);
193 Field f1 = AllTypes.class.getField("field");
194 FieldInjectionPoint p3 = new FieldInjectionPoint(f1);
195 SetterInjectionPoint p4 = new SetterInjectionPoint(m1, 0);
196 SetterInjectionPoint p5 = new SetterInjectionPoint(m2, 0);
197
198 Set<InjectionPoint> expected = new HashSet<InjectionPoint>();
199 expected.add(p1);
200 expected.add(p2);
201 expected.add(p3);
202 expected.add(p4);
203 expected.add(p5);
204
205 Assert.assertEquals(expected, getInjectionPoints(AllTypes.class));
206 }
207
208 @Test
209 public void testSubclassOverrides() throws Exception {
210 Method m1 = SubType.class.getMethod("injectMethod", Object.class);
211 SetterInjectionPoint p1 = new SetterInjectionPoint(m1, 0);
212
213 Set<InjectionPoint> expected = new HashSet<InjectionPoint>();
214 expected.add(p1);
215
216 Assert.assertEquals(expected, getInjectionPoints(SubType.class));
217 }
218
219 private Set<InjectionPoint> getInjectionPoints(Class<?> types) {
220 List<Desire> desires = ReflectionDesire.getDesires(types);
221 Set<InjectionPoint> points = new HashSet<InjectionPoint>();
222 for (Desire rd: desires) {
223 points.add(rd.getInjectionPoint());
224 }
225 return points;
226 }
227
228 @Attribute
229 @Retention(RetentionPolicy.RUNTIME)
230 public static @interface Transient { }
231
232 public static class CtorType {
233 @Inject
234 public CtorType(@Transient @RoleA Object a, @Nullable @RoleB String b) { }
235
236
237 public CtorType() { }
238 }
239
240 public static class SetterType {
241 @Inject
242 public void setA(@Transient @RoleA Object a) { }
243
244 @Inject
245 public void setB(@RoleB String b) { }
246
247 @Inject
248 public boolean setMulti(Object a, @Nullable @RoleD String c) {
249 return false;
250 }
251
252
253 public void setX(Object c) { }
254 }
255
256 public static class FieldType {
257 @Inject public String field;
258 }
259
260 public static class AllTypes {
261 @Inject public String field;
262
263 @Inject
264 public AllTypes(@RoleA Object a, @RoleB String b) { }
265
266 @Inject
267 public void setC(Object c) { }
268
269 @Inject
270 public void setD(@RoleD String d) { }
271 }
272
273 public static class PrimitiveType {
274 @Inject
275 public void setUnboxed(int a) { }
276
277 @Inject
278 public void setBoxed(Integer a) { }
279 }
280
281 public static class NamedType {
282 @Inject
283 public NamedType(@Named("test1") String a, @Named("test2") Integer b) { }
284 }
285
286 public static class SuperType {
287 @Inject
288 public void nonInjectMethod(Object o) { }
289
290 public void injectMethod(Object o) { }
291 }
292
293 public static class SubType extends SuperType {
294 public void nonInjectMethod(Object o) { }
295
296 @Inject
297 public void injectMethod(Object o) { }
298 }
299 }