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.reflect;
18  
19  import static java.lang.annotation.ElementType.*;
20  import static java.lang.annotation.RetentionPolicy.*;
21  import static org.apache.juneau.TestUtils.*;
22  import static org.apache.juneau.reflect.ReflectFlags.*;
23  import static org.junit.jupiter.api.Assertions.*;
24  
25  import java.lang.annotation.*;
26  import java.lang.reflect.*;
27  import java.util.function.*;
28  
29  import org.apache.juneau.*;
30  import org.junit.jupiter.api.*;
31  
32  class FieldInfo_Test extends TestBase {
33  
34  	@Documented
35  	@Target(FIELD)
36  	@Retention(RUNTIME)
37  	@Inherited
38  	public static @interface A {
39  		String value();
40  	}
41  
42  	@Documented
43  	@Target(FIELD)
44  	@Retention(RUNTIME)
45  	@Inherited
46  	public static @interface AX {
47  		String value();
48  	}
49  
50  	private static void check(String expected, Object o) {
51  		assertEquals(expected, TO_STRING.apply(o));
52  	}
53  
54  	private static final Function<Object,String> TO_STRING = t -> {
55  		if (t == null)
56  			return null;
57  		if (t instanceof A)
58  			return "@A(" + ((A)t).value() + ")";
59  		if (t instanceof ClassInfo)
60  			return ((ClassInfo)t).getSimpleName();
61  		if (t instanceof FieldInfo)
62  			return ((FieldInfo)t).getName();
63  		if (t instanceof Field)
64  			return ((Field)t).getName();
65  		return t.toString();
66  	};
67  
68  	private static FieldInfo off(Class<?> c, String name) {
69  		try {
70  			return FieldInfo.of(c.getDeclaredField(name));
71  		} catch (SecurityException | NoSuchFieldException e) {
72  			fail(e.getLocalizedMessage());
73  		}
74  		return null;
75  	}
76  
77  	//-----------------------------------------------------------------------------------------------------------------
78  	// Instantiation.
79  	//-----------------------------------------------------------------------------------------------------------------
80  
81  	static class A1 {
82  		public int f1;
83  	}
84  	FieldInfo a1_f1 = off(A1.class, "f1");
85  
86  	@Test void of_withClass() {
87  		check("f1", FieldInfo.of(ClassInfo.of(A1.class), a1_f1.inner()));
88  	}
89  
90  	@Test void of_withoutClass() {
91  		check("f1", FieldInfo.of(a1_f1.inner()));
92  	}
93  
94  	@Test void of_null() {
95  		check(null, FieldInfo.of(null));
96  		check(null, FieldInfo.of(null, null));
97  	}
98  
99  	@Test void getDeclaringClass() {
100 		check("A1", a1_f1.getDeclaringClass());
101 		check("A1", a1_f1.getDeclaringClass());
102 	}
103 
104 	@Test void inner() {
105 		check("f1", a1_f1.inner());
106 	}
107 
108 	//-----------------------------------------------------------------------------------------------------------------
109 	// Annotations
110 	//-----------------------------------------------------------------------------------------------------------------
111 
112 	public static class B {
113 		@A("a1") public int a1;
114 		public int a2;
115 	}
116 
117 	FieldInfo
118 		b_a1 = off(B.class, "a1"),
119 		b_a2 = off(B.class, "a2");
120 
121 	@Test void getAnnotation() {
122 		check("@A(a1)", b_a1.getAnnotation(A.class));
123 		check(null, b_a2.getAnnotation(A.class));
124 	}
125 
126 	@Test void getAnnotation_null() {
127 		check(null, b_a1.getAnnotation(null));
128 	}
129 
130 	@Test void hasAnnotation_true() {
131 		assertTrue(b_a1.hasAnnotation(A.class));
132 	}
133 
134 	@Test void hasAnnotation_false() {
135 		assertFalse(b_a2.hasAnnotation(A.class));
136 	}
137 
138 	//-----------------------------------------------------------------------------------------------------------------
139 	// Characteristics
140 	//-----------------------------------------------------------------------------------------------------------------
141 
142 	abstract static class C {
143 		@Deprecated public int deprecated;
144 		public int notDeprecated;
145 		public int isPublic;
146 		protected int isNotPublic;
147 		public static int isStatic;
148 		public int isNotStatic;
149 		public transient int isTransient;
150 		public int isNotTransient;
151 	}
152 	static ClassInfo c = ClassInfo.of(C.class);
153 	static FieldInfo
154 		c_deprecated = c.getPublicField(x -> x.hasName("deprecated")),
155 		c_notDeprecated = c.getPublicField(x -> x.hasName("notDeprecated")),
156 		c_isPublic = c.getPublicField(x -> x.hasName("isPublic")),
157 		c_isNotPublic = c.getDeclaredField(x -> x.hasName("isNotPublic")),
158 		c_isStatic = c.getPublicField(x -> x.hasName("isStatic")),
159 		c_isNotStatic = c.getPublicField(x -> x.hasName("isNotStatic")),
160 		c_isTransient = c.getPublicField(x -> x.hasName("isTransient")),
161 		c_isNotTransient = c.getPublicField(x -> x.hasName("isNotTransient"))
162 	;
163 
164 	@Test void isAll() {
165 		assertTrue(c_deprecated.isAll(DEPRECATED));
166 		assertTrue(c_notDeprecated.isAll(NOT_DEPRECATED));
167 		assertTrue(c_isPublic.isAll(PUBLIC));
168 		assertTrue(c_isNotPublic.isAll(NOT_PUBLIC));
169 		assertTrue(c_isStatic.isAll(STATIC));
170 		assertTrue(c_isNotStatic.isAll(NOT_STATIC));
171 		assertTrue(c_isTransient.isAll(TRANSIENT));
172 		assertTrue(c_isNotTransient.isAll(NOT_TRANSIENT));
173 
174 		assertFalse(c_deprecated.isAll(NOT_DEPRECATED));
175 		assertFalse(c_notDeprecated.isAll(DEPRECATED));
176 		assertFalse(c_isPublic.isAll(NOT_PUBLIC));
177 		assertFalse(c_isNotPublic.isAll(PUBLIC));
178 		assertFalse(c_isStatic.isAll(NOT_STATIC));
179 		assertFalse(c_isNotStatic.isAll(STATIC));
180 		assertFalse(c_isTransient.isAll(NOT_TRANSIENT));
181 		assertFalse(c_isNotTransient.isAll(TRANSIENT));
182 	}
183 
184 	@Test void isAll_invalidFlag() {
185 		assertThrowsWithMessage(BasicRuntimeException.class, "Invalid flag for field: HAS_PARAMS", ()->c_deprecated.isAll(HAS_PARAMS));
186 	}
187 
188 	@Test void isAny() {
189 		assertTrue(c_deprecated.isAny(DEPRECATED));
190 		assertTrue(c_notDeprecated.isAny(NOT_DEPRECATED));
191 		assertTrue(c_isPublic.isAny(PUBLIC));
192 		assertTrue(c_isNotPublic.isAny(NOT_PUBLIC));
193 		assertTrue(c_isStatic.isAny(STATIC));
194 		assertTrue(c_isNotStatic.isAny(NOT_STATIC));
195 		assertTrue(c_isTransient.isAny(TRANSIENT));
196 		assertTrue(c_isNotTransient.isAny(NOT_TRANSIENT));
197 
198 		assertFalse(c_deprecated.isAny(NOT_DEPRECATED));
199 		assertFalse(c_notDeprecated.isAny(DEPRECATED));
200 		assertFalse(c_isPublic.isAny(NOT_PUBLIC));
201 		assertFalse(c_isNotPublic.isAny(PUBLIC));
202 		assertFalse(c_isStatic.isAny(NOT_STATIC));
203 		assertFalse(c_isNotStatic.isAny(STATIC));
204 		assertFalse(c_isTransient.isAny(NOT_TRANSIENT));
205 		assertFalse(c_isNotTransient.isAny(TRANSIENT));
206 	}
207 
208 	@Test void isAny_invalidFlag() {
209 		assertThrowsWithMessage(BasicRuntimeException.class, "Invalid flag for field: HAS_PARAMS", ()->c_deprecated.isAny(HAS_PARAMS));
210 	}
211 
212 	@Test void isDeprecated() {
213 		assertTrue(c_deprecated.isDeprecated());
214 		assertFalse(c_notDeprecated.isDeprecated());
215 	}
216 
217 	@Test void isNotDeprecated() {
218 		assertFalse(c_deprecated.isNotDeprecated());
219 		assertTrue(c_notDeprecated.isNotDeprecated());
220 	}
221 
222 	@Test void isTransient() {
223 		assertTrue(c_isTransient.isTransient());
224 		assertFalse(c_isNotTransient.isTransient());
225 	}
226 
227 	@Test void isNotTransient() {
228 		assertFalse(c_isTransient.isNotTransient());
229 		assertTrue(c_isNotTransient.isNotTransient());
230 	}
231 
232 	@Test void isPublic() {
233 		assertTrue(c_isPublic.isPublic());
234 		assertFalse(c_isNotPublic.isPublic());
235 	}
236 
237 	@Test void isNotPublic() {
238 		assertFalse(c_isPublic.isNotPublic());
239 		assertTrue(c_isNotPublic.isNotPublic());
240 	}
241 
242 	@Test void isStatic() {
243 		assertTrue(c_isStatic.isStatic());
244 		assertFalse(c_isNotStatic.isStatic());
245 	}
246 
247 	@Test void isNotStatic() {
248 		assertFalse(c_isStatic.isNotStatic());
249 		assertTrue(c_isNotStatic.isNotStatic());
250 	}
251 
252 	@Test void hasName() {
253 		assertTrue(b_a1.hasName("a1"));
254 		assertFalse(b_a1.hasName("a2"));
255 	}
256 
257 	@Test void hasName_null() {
258 		assertFalse(b_a1.hasName(null));
259 	}
260 
261 	//-----------------------------------------------------------------------------------------------------------------
262 	// Visibility
263 	//-----------------------------------------------------------------------------------------------------------------
264 
265 	abstract static class D {
266 		public int isPublic;
267 		protected int isProtected;
268 		@SuppressWarnings("unused")
269 		private int isPrivate;
270 		int isDefault;
271 	}
272 	static ClassInfo d = ClassInfo.of(D.class);
273 	static FieldInfo
274 		d_isPublic = d.getPublicField(x -> x.hasName("isPublic")),
275 		d_isProtected = d.getDeclaredField(x -> x.hasName("isProtected")),
276 		d_isPrivate = d.getDeclaredField(x -> x.hasName("isPrivate")),
277 		d_isDefault = d.getDeclaredField(x -> x.hasName("isDefault"));
278 
279 	@Test void setAccessible() {
280 		assertDoesNotThrow(()->d_isPublic.setAccessible());
281 		assertDoesNotThrow(()->d_isProtected.setAccessible());
282 		assertDoesNotThrow(()->d_isPrivate.setAccessible());
283 		assertDoesNotThrow(()->d_isDefault.setAccessible());
284 	}
285 
286 	@Test void isVisible() {
287 		assertTrue(d_isPublic.isVisible(Visibility.PUBLIC));
288 		assertTrue(d_isPublic.isVisible(Visibility.PROTECTED));
289 		assertTrue(d_isPublic.isVisible(Visibility.PRIVATE));
290 		assertTrue(d_isPublic.isVisible(Visibility.DEFAULT));
291 
292 		assertFalse(d_isProtected.isVisible(Visibility.PUBLIC));
293 		assertTrue(d_isProtected.isVisible(Visibility.PROTECTED));
294 		assertTrue(d_isProtected.isVisible(Visibility.PRIVATE));
295 		assertTrue(d_isProtected.isVisible(Visibility.DEFAULT));
296 
297 		assertFalse(d_isPrivate.isVisible(Visibility.PUBLIC));
298 		assertFalse(d_isPrivate.isVisible(Visibility.PROTECTED));
299 		assertTrue(d_isPrivate.isVisible(Visibility.PRIVATE));
300 		assertFalse(d_isPrivate.isVisible(Visibility.DEFAULT));
301 
302 		assertFalse(d_isDefault.isVisible(Visibility.PUBLIC));
303 		assertFalse(d_isDefault.isVisible(Visibility.PROTECTED));
304 		assertTrue(d_isDefault.isVisible(Visibility.PRIVATE));
305 		assertTrue(d_isDefault.isVisible(Visibility.DEFAULT));
306 	}
307 
308 	//-----------------------------------------------------------------------------------------------------------------
309 	// Other methods.
310 	//-----------------------------------------------------------------------------------------------------------------
311 
312 	static class E {
313 		public int a1;
314 		int a2;
315 	}
316 
317 	static ClassInfo e = ClassInfo.of(E.class);
318 	static FieldInfo
319 		e_a1 = e.getPublicField(x -> x.hasName("a1")),
320 		e_a2 = e.getDeclaredField(x -> x.hasName("a2"));
321 
322 	@Test void getType() {
323 		check("int", e_a1.getType());
324 		check("int", e_a2.getType());
325 	}
326 
327 	@Test void getType_twice() {
328 		check("int", e_a1.getType());
329 		check("int", e_a1.getType());
330 	}
331 
332 	@Test void toString2() {
333 		assertEquals("org.apache.juneau.reflect.FieldInfo_Test$E.a1", e_a1.toString());
334 	}
335 }