View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.utils;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.lang.reflect.*;
23  
24  import org.apache.juneau.*;
25  import org.junit.jupiter.api.*;
26  
27  class ReflectionMapTest extends TestBase {
28  
29  	private static ReflectionMap.Builder<Number> create() {
30  		return ReflectionMap.create(Number.class);
31  	}
32  
33  	private void checkEntries(ReflectionMap<?> m, boolean hasClass, boolean hasMethods, boolean hasFields, boolean hasConstructors) {
34  		assertEquals(m.classEntries.length == 0, ! hasClass);
35  		assertEquals(m.methodEntries.length == 0, ! hasMethods);
36  		assertEquals(m.fieldEntries.length == 0, ! hasFields);
37  		assertEquals(m.constructorEntries.length == 0, ! hasConstructors);
38  	}
39  
40  	//------------------------------------------------------------------------------------------------------------------
41  	// Class names
42  	//------------------------------------------------------------------------------------------------------------------
43  
44  	static class A1 {}
45  	static class A2 {}
46  
47  	static ReflectionMap<Number>
48  		A1_SIMPLE = create().append("A1", 1).build(),
49  		A1b_SIMPLE = create().append("ReflectionMapTest$A1", 1).build(),
50  		A1_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$A1", 1).build();  // Note this could be a static field.
51  
52  	@Test void a01_classNames_checkEntries() {
53  		checkEntries(A1_SIMPLE, true, false, false, false);
54  		checkEntries(A1_FULL, true, false, true, false);
55  	}
56  
57  	private void checkA(Class<?> c, boolean match_A1_SIMPLE, boolean match_A1b_SIMPLE, boolean match_A1_FULL) {
58  		assertEquals(match_A1_SIMPLE, A1_SIMPLE.find(c, null).isPresent());
59  		assertEquals(match_A1b_SIMPLE, A1b_SIMPLE.find(c, null).isPresent());
60  		assertEquals(match_A1_FULL, A1_FULL.find(c, null).isPresent());
61  
62  		assertEquals(match_A1_SIMPLE, A1_SIMPLE.find(c, Integer.class).isPresent());
63  		assertEquals(match_A1b_SIMPLE, A1b_SIMPLE.find(c, Integer.class).isPresent());
64  		assertEquals(match_A1_FULL, A1_FULL.find(c, Integer.class).isPresent());
65  
66  		assertFalse(A1_SIMPLE.find(c, Long.class).isPresent());
67  		assertFalse(A1b_SIMPLE.find(c, Long.class).isPresent());
68  		assertFalse(A1_FULL.find(c, Long.class).isPresent());
69  
70  		assertEquals(match_A1_SIMPLE, !A1_SIMPLE.findAll(c, null).isEmpty());
71  		assertEquals(match_A1b_SIMPLE, !A1b_SIMPLE.findAll(c, null).isEmpty());
72  		assertEquals(match_A1_FULL, !A1_FULL.findAll(c, null).isEmpty());
73  
74  		assertEquals(match_A1_SIMPLE, !A1_SIMPLE.findAll(c, Integer.class).isEmpty());
75  		assertEquals(match_A1b_SIMPLE, !A1b_SIMPLE.findAll(c, Integer.class).isEmpty());
76  		assertEquals(match_A1_FULL, !A1_FULL.findAll(c, Integer.class).isEmpty());
77  
78  		assertFalse(A1_SIMPLE.find(c, Long.class).isPresent());
79  		assertFalse(A1b_SIMPLE.find(c, Long.class).isPresent());
80  		assertFalse(A1_FULL.find(c, Long.class).isPresent());
81  	}
82  
83  	@Test void a02_classNames_find() {
84  		checkA(A1.class, true, true, true);
85  		checkA(A2.class, false, false, false);
86  		checkA(null, false, false, false);
87  	}
88  
89  	//------------------------------------------------------------------------------------------------------------------
90  	// Method names
91  	//------------------------------------------------------------------------------------------------------------------
92  
93  	static class B1 {
94  		public void m1() { /* no-op */ }
95  		public void m1(int x) { /* no-op */ }
96  		public void m1(String x) { /* no-op */ }
97  		public void m1(String x, int y) { /* no-op */ }
98  		public void m2(int x) { /* no-op */ }
99  	}
100 	static class B2 {
101 		public void m1() { /* no-op */ }
102 	}
103 
104 	static ReflectionMap<Number>
105 		B1m1_SIMPLE = create().append("B1.m1", 1).build(),
106 		B1m1i_SIMPLE = create().append("B1.m1(int)", 1).build(),
107 		B1m1s_SIMPLE = create().append("B1.m1(String)", 1).build(),
108 		B1m1ss_SIMPLE = create().append("B1.m1(java.lang.String)", 1).build(),
109 		B1m1si_SIMPLE = create().append("B1.m1(String,int)", 1).build(),
110 		B1m1ssi_SIMPLE = create().append("B1.m1(java.lang.String , int)", 1).build(),
111 		B1m1_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$B1.m1", 1).build(),
112 		B1m1i_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$B1.m1(int)", 1).build(),
113 		B1m1s_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$B1.m1(String)", 1).build(),
114 		B1m1ss_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$B1.m1(java.lang.String)", 1).build(),
115 		B1m1si_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$B1.m1(String,int)", 1).build(),
116 		B1m1ssi_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$B1.m1(java.lang.String , int)", 1).build();
117 
118 	@Test void b01_methodNames_checkEntries() {
119 		checkEntries(B1m1_SIMPLE, false, true, true, false);
120 		checkEntries(B1m1i_SIMPLE, false, true, false, false);
121 		checkEntries(B1m1s_SIMPLE, false, true, false, false);
122 		checkEntries(B1m1ss_SIMPLE, false, true, false, false);
123 		checkEntries(B1m1si_SIMPLE, false, true, false, false);
124 		checkEntries(B1m1ssi_SIMPLE, false, true, false, false);
125 		checkEntries(B1m1_FULL, false, true, true, false);
126 		checkEntries(B1m1i_FULL, false, true, false, false);
127 		checkEntries(B1m1s_FULL, false, true, false, false);
128 		checkEntries(B1m1ss_FULL, false, true, false, false);
129 		checkEntries(B1m1si_FULL, false, true, false, false);
130 		checkEntries(B1m1ssi_FULL, false, true, false, false);
131 	}
132 
133 	private void checkB(Method m, boolean match_B1m1_SIMPLE, boolean match_B1m1i_SIMPLE, boolean match_B1m1s_SIMPLE, boolean match_B1m1ss_SIMPLE,
134 			boolean match_B1m1si_SIMPLE, boolean match_B1m1ssi_SIMPLE, boolean match_B1m1_FULL, boolean match_B1m1i_FULL, boolean match_B1m1s_FULL,
135 			boolean match_B1m1ss_FULL, boolean match_B1m1si_FULL, boolean match_B1m1ssi_FULL) {
136 
137 		assertEquals(match_B1m1_SIMPLE, B1m1_SIMPLE.find(m, null).isPresent());
138 		assertEquals(match_B1m1i_SIMPLE, B1m1i_SIMPLE.find(m, null).isPresent());
139 		assertEquals(match_B1m1s_SIMPLE, B1m1s_SIMPLE.find(m, null).isPresent());
140 		assertEquals(match_B1m1ss_SIMPLE, B1m1ss_SIMPLE.find(m, null).isPresent());
141 		assertEquals(match_B1m1si_SIMPLE, B1m1si_SIMPLE.find(m, null).isPresent());
142 		assertEquals(match_B1m1ssi_SIMPLE, B1m1ssi_SIMPLE.find(m, null).isPresent());
143 		assertEquals(match_B1m1_FULL, B1m1_FULL.find(m, null).isPresent());
144 		assertEquals(match_B1m1i_FULL, B1m1i_FULL.find(m, null).isPresent());
145 		assertEquals(match_B1m1s_FULL, B1m1s_FULL.find(m, null).isPresent());
146 		assertEquals(match_B1m1ss_FULL, B1m1ss_FULL.find(m, null).isPresent());
147 		assertEquals(match_B1m1si_FULL, B1m1si_FULL.find(m, null).isPresent());
148 		assertEquals(match_B1m1ssi_FULL, B1m1ssi_FULL.find(m, null).isPresent());
149 
150 		assertEquals(match_B1m1_SIMPLE, B1m1_SIMPLE.find(m, Integer.class).isPresent());
151 		assertEquals(match_B1m1i_SIMPLE, B1m1i_SIMPLE.find(m, Integer.class).isPresent());
152 		assertEquals(match_B1m1s_SIMPLE, B1m1s_SIMPLE.find(m, Integer.class).isPresent());
153 		assertEquals(match_B1m1ss_SIMPLE, B1m1ss_SIMPLE.find(m, Integer.class).isPresent());
154 		assertEquals(match_B1m1si_SIMPLE, B1m1si_SIMPLE.find(m, Integer.class).isPresent());
155 		assertEquals(match_B1m1ssi_SIMPLE, B1m1ssi_SIMPLE.find(m, Integer.class).isPresent());
156 		assertEquals(match_B1m1_FULL, B1m1_FULL.find(m, Integer.class).isPresent());
157 		assertEquals(match_B1m1i_FULL, B1m1i_FULL.find(m, Integer.class).isPresent());
158 		assertEquals(match_B1m1s_FULL, B1m1s_FULL.find(m, Integer.class).isPresent());
159 		assertEquals(match_B1m1ss_FULL, B1m1ss_FULL.find(m, Integer.class).isPresent());
160 		assertEquals(match_B1m1si_FULL, B1m1si_FULL.find(m, Integer.class).isPresent());
161 		assertEquals(match_B1m1ssi_FULL, B1m1ssi_FULL.find(m, Integer.class).isPresent());
162 
163 		assertFalse(B1m1_SIMPLE.find(m, Long.class).isPresent());
164 		assertFalse(B1m1i_SIMPLE.find(m, Long.class).isPresent());
165 		assertFalse(B1m1s_SIMPLE.find(m, Long.class).isPresent());
166 		assertFalse(B1m1ss_SIMPLE.find(m, Long.class).isPresent());
167 		assertFalse(B1m1si_SIMPLE.find(m, Long.class).isPresent());
168 		assertFalse(B1m1ssi_SIMPLE.find(m, Long.class).isPresent());
169 		assertFalse(B1m1_FULL.find(m, Long.class).isPresent());
170 		assertFalse(B1m1i_FULL.find(m, Long.class).isPresent());
171 		assertFalse(B1m1s_FULL.find(m, Long.class).isPresent());
172 		assertFalse(B1m1ss_FULL.find(m, Long.class).isPresent());
173 		assertFalse(B1m1si_FULL.find(m, Long.class).isPresent());
174 		assertFalse(B1m1ssi_FULL.find(m, Long.class).isPresent());
175 	}
176 
177 	@Test void b02_methodName_find() throws Exception {
178 		checkB(B1.class.getMethod("m1"), true, false, false, false, false, false, true, false, false, false, false, false);
179 		checkB(B1.class.getMethod("m1", int.class), true, true, false, false, false, false, true, true, false, false, false, false);
180 		checkB(B1.class.getMethod("m1", String.class), true, false, true, true, false, false, true, false, true, true, false, false);
181 		checkB(B1.class.getMethod("m1", String.class, int.class), true, false, false, false, true, true, true, false, false, false, true, true);
182 		checkB(B1.class.getMethod("m2", int.class), false, false, false, false, false, false, false, false, false, false, false, false);
183 		checkB(B2.class.getMethod("m1"), false, false, false, false, false, false, false, false, false, false, false, false);
184 		checkB(null, false, false, false, false, false, false, false, false, false, false, false, false);
185 	}
186 
187 	//------------------------------------------------------------------------------------------------------------------
188 	// Field names
189 	//------------------------------------------------------------------------------------------------------------------
190 
191 	static class C1 {
192 		public int f1;
193 		public int f2;
194 	}
195 	static class C2 {
196 		public int f1;
197 	}
198 
199 	static ReflectionMap<Number>
200 		C1f1_SIMPLE = create().append("C1.f1", 1).build(),
201 		C1f1_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$C1.f1", 1).build();
202 
203 	@Test void c01_fieldNames_checkEntries() {
204 		checkEntries(C1f1_SIMPLE, false, true, true, false);
205 		checkEntries(C1f1_FULL, false, true, true, false);
206 	}
207 
208 	private void checkC(Field f, boolean match_C1f1_SIMPLE, boolean match_C1f1_FULL) {
209 		assertEquals(match_C1f1_SIMPLE, C1f1_SIMPLE.find(f, null).isPresent());
210 		assertEquals(match_C1f1_FULL, C1f1_FULL.find(f, null).isPresent());
211 
212 		assertEquals(match_C1f1_SIMPLE, C1f1_SIMPLE.find(f, Integer.class).isPresent());
213 		assertEquals(match_C1f1_FULL, C1f1_FULL.find(f, Integer.class).isPresent());
214 
215 		assertFalse(C1f1_SIMPLE.find(f, Long.class).isPresent());
216 		assertFalse(C1f1_FULL.find(f, Long.class).isPresent());
217 	}
218 
219 	@Test void c02_fieldName_find() throws Exception {
220 		checkC(C1.class.getField("f1"), true, true);
221 		checkC(C1.class.getField("f2"), false, false);
222 		checkC(C2.class.getField("f1"), false, false);
223 		checkC(null, false, false);
224 	}
225 
226 	//------------------------------------------------------------------------------------------------------------------
227 	// Constructor names
228 	//------------------------------------------------------------------------------------------------------------------
229 
230 	static class D1 {
231 		public D1() { /* no-op */ }
232 		public D1(int x) { /* no-op */ }
233 		public D1(String x) { /* no-op */ }
234 		public D1(String x, int y) { /* no-op */ }
235 	}
236 	static class D2 {
237 		public D2() { /* no-op */ }
238 	}
239 
240 	static ReflectionMap<Number>
241 		D_SIMPLE = create().append("D1()", 1).build(),
242 		Di_SIMPLE = create().append("D1(int)", 1).build(),
243 		Ds_SIMPLE = create().append("D1(String)", 1).build(),
244 		Dss_SIMPLE = create().append("D1(java.lang.String)", 1).build(),
245 		Dsi_SIMPLE = create().append("D1(String, int)", 1).build(),
246 		Dssi_SIMPLE = create().append("D1(java.lang.String, int)", 1).build(),
247 		D_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$D1()", 1).build(),
248 		Di_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$D1(int)", 1).build(),
249 		Ds_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$D1(String)", 1).build(),
250 		Dss_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$D1(java.lang.String)", 1).build(),
251 		Dsi_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$D1(String, int)", 1).build(),
252 		Dssi_FULL = create().append("org.apache.juneau.utils.ReflectionMapTest$D1(java.lang.String, int)", 1).build();
253 
254 	@Test void d01_constructorNames_checkEntries() {
255 		checkEntries(D_SIMPLE, false, false, false, true);
256 		checkEntries(Di_SIMPLE, false, false, false, true);
257 		checkEntries(Ds_SIMPLE, false, false, false, true);
258 		checkEntries(Dss_SIMPLE, false, false, false, true);
259 		checkEntries(Dsi_SIMPLE, false, false, false, true);
260 		checkEntries(Dssi_SIMPLE, false, false, false, true);
261 		checkEntries(D_FULL, false, false, false, true);
262 		checkEntries(Di_FULL, false, false, false, true);
263 		checkEntries(Ds_FULL, false, false, false, true);
264 		checkEntries(Dss_FULL, false, false, false, true);
265 		checkEntries(Dsi_FULL, false, false, false, true);
266 		checkEntries(Dssi_FULL, false, false, false, true);
267 	}
268 
269 	private void checkD(Constructor<?> c, boolean match_D_SIMPLE, boolean match_Di_SIMPLE, boolean match_Ds_SIMPLE, boolean match_Dss_SIMPLE,
270 			boolean match_Dsi_SIMPLE, boolean match_Dssi_SIMPLE, boolean match_D_FULL, boolean match_Di_FULL, boolean match_Ds_FULL,
271 			boolean match_Dss_FULL, boolean match_Dsi_FULL, boolean match_Dssi_FULL) {
272 
273 		assertEquals(match_D_SIMPLE, D_SIMPLE.find(c, null).isPresent());
274 		assertEquals(match_Di_SIMPLE, Di_SIMPLE.find(c, null).isPresent());
275 		assertEquals(match_Ds_SIMPLE, Ds_SIMPLE.find(c, null).isPresent());
276 		assertEquals(match_Dss_SIMPLE, Dss_SIMPLE.find(c, null).isPresent());
277 		assertEquals(match_Dsi_SIMPLE, Dsi_SIMPLE.find(c, null).isPresent());
278 		assertEquals(match_Dssi_SIMPLE, Dssi_SIMPLE.find(c, null).isPresent());
279 		assertEquals(match_D_FULL, D_FULL.find(c, null).isPresent());
280 		assertEquals(match_Di_FULL, Di_FULL.find(c, null).isPresent());
281 		assertEquals(match_Ds_FULL, Ds_FULL.find(c, null).isPresent());
282 		assertEquals(match_Dss_FULL, Dss_FULL.find(c, null).isPresent());
283 		assertEquals(match_Dsi_FULL, Dsi_FULL.find(c, null).isPresent());
284 		assertEquals(match_Dssi_FULL, Dssi_FULL.find(c, null).isPresent());
285 
286 		assertEquals(match_D_SIMPLE, D_SIMPLE.find(c, Integer.class).isPresent());
287 		assertEquals(match_Di_SIMPLE, Di_SIMPLE.find(c, Integer.class).isPresent());
288 		assertEquals(match_Ds_SIMPLE, Ds_SIMPLE.find(c, Integer.class).isPresent());
289 		assertEquals(match_Dss_SIMPLE, Dss_SIMPLE.find(c, Integer.class).isPresent());
290 		assertEquals(match_Dsi_SIMPLE, Dsi_SIMPLE.find(c, Integer.class).isPresent());
291 		assertEquals(match_Dssi_SIMPLE, Dssi_SIMPLE.find(c, Integer.class).isPresent());
292 		assertEquals(match_D_FULL, D_FULL.find(c, Integer.class).isPresent());
293 		assertEquals(match_Di_FULL, Di_FULL.find(c, Integer.class).isPresent());
294 		assertEquals(match_Ds_FULL, Ds_FULL.find(c, Integer.class).isPresent());
295 		assertEquals(match_Dss_FULL, Dss_FULL.find(c, Integer.class).isPresent());
296 		assertEquals(match_Dsi_FULL, Dsi_FULL.find(c, Integer.class).isPresent());
297 		assertEquals(match_Dssi_FULL, Dssi_FULL.find(c, Integer.class).isPresent());
298 
299 		assertFalse(D_SIMPLE.find(c, Long.class).isPresent());
300 		assertFalse(Di_SIMPLE.find(c, Long.class).isPresent());
301 		assertFalse(Ds_SIMPLE.find(c, Long.class).isPresent());
302 		assertFalse(Dss_SIMPLE.find(c, Long.class).isPresent());
303 		assertFalse(Dsi_SIMPLE.find(c, Long.class).isPresent());
304 		assertFalse(Dssi_SIMPLE.find(c, Long.class).isPresent());
305 		assertFalse(D_FULL.find(c, Long.class).isPresent());
306 		assertFalse(Di_FULL.find(c, Long.class).isPresent());
307 		assertFalse(Ds_FULL.find(c, Long.class).isPresent());
308 		assertFalse(Dss_FULL.find(c, Long.class).isPresent());
309 		assertFalse(Dsi_FULL.find(c, Long.class).isPresent());
310 		assertFalse(Dssi_FULL.find(c, Long.class).isPresent());
311 	}
312 
313 	@Test void d02_constructorName_find() throws Exception {
314 		checkD(D1.class.getConstructor(), true, false, false, false, false, false, true, false, false, false, false, false);
315 		checkD(D1.class.getConstructor(int.class), false, true, false, false, false, false, false, true, false, false, false, false);
316 		checkD(D1.class.getConstructor(String.class), false, false, true, true, false, false, false, false, true, true, false, false);
317 		checkD(D1.class.getConstructor(String.class, int.class), false, false, false, false, true, true, false, false, false, false, true, true);
318 		checkD(D2.class.getConstructor(), false, false, false, false, false, false, false, false, false, false, false, false);
319 		checkD(null, false, false, false, false, false, false, false, false, false, false, false, false);
320 	}
321 
322 	//------------------------------------------------------------------------------------------------------------------
323 	// Invalid input
324 	//------------------------------------------------------------------------------------------------------------------
325 
326 	@Test void e01_blankInput() {
327 		assertThrowsWithMessage(BasicRuntimeException.class, "Invalid reflection signature: []", ()->create().append("", 1));
328 	}
329 
330 	@Test void e02_nullInput() {
331 		assertThrowsWithMessage(BasicRuntimeException.class, "Invalid reflection signature: [null]", ()->create().append(null, 1));
332 	}
333 
334 	@Test void e03_badInput() {
335 		assertThrowsWithMessage(BasicRuntimeException.class, "Invalid reflection signature: [foo)]", ()->create().append("foo)", 1));
336 	}
337 
338 	//------------------------------------------------------------------------------------------------------------------
339 	// Comma-delimited list.
340 	//------------------------------------------------------------------------------------------------------------------
341 	static class F1 {}
342 
343 	static ReflectionMap<Number> RM_F = create().append("F2, F1", 1).build();
344 
345 	@Test void f01_cdl() {
346 		assertString("1", RM_F.find(F1.class, null));
347 	}
348 
349 	//------------------------------------------------------------------------------------------------------------------
350 	// Empty reflection map.
351 	//------------------------------------------------------------------------------------------------------------------
352 
353 	static ReflectionMap<Number> RM_G = create().build();
354 
355 	@Test void g01_emptyReflectionMap() throws Exception {
356 		assertFalse(RM_G.find(A1.class, null).isPresent());
357 		assertFalse(RM_G.find(B1.class.getMethod("m1"), null).isPresent());
358 		assertFalse(RM_G.find(C1.class.getField("f1"), null).isPresent());
359 		assertFalse(RM_G.find(D1.class.getConstructor(), null).isPresent());
360 	}
361 }