blob: 8a531f42fa3a7cba2256ff8a7fee534a4efceeaa [file] [log] [blame]
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
// * with the License. You may obtain a copy of the License at *
// * *
// * http://www.apache.org/licenses/LICENSE-2.0 *
// * *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
// * specific language governing permissions and limitations under the License. *
// ***************************************************************************************************************************
package org.apache.juneau.reflection;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import static org.junit.Assert.*;
import java.lang.annotation.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.reflect.*;
import org.junit.*;
/**
* ParamInfo tests.
*/
public class ParamInfoTest {
@Documented
@Target(METHOD)
@Retention(RUNTIME)
@Inherited
public static @interface A {
String value();
}
@Documented
@Target(METHOD)
@Retention(RUNTIME)
@Inherited
public static @interface AX {
String value();
}
private static void check(String expected, Object o) {
assertEquals(expected, TO_STRING.apply(o));
}
private static final Function<Object,String> TO_STRING = new Function<Object,String>() {
@Override
public String apply(Object t) {
if (t == null)
return null;
if (t instanceof List)
return ((List<?>)t).stream().map(this).collect(Collectors.joining(","));
if (t.getClass().isArray())
return StreamSupport.stream(ArrayUtils.toList(t, Object.class).spliterator(), false).map(this).collect(Collectors.joining(","));
if (t instanceof MethodInfo)
return ((MethodInfo)t).getDeclaringClass().getSimpleName() + '.' + ((MethodInfo)t).getShortName();
if (t instanceof CA)
return "@CA(" + ((CA)t).value() + ")";
if (t instanceof DA)
return "@DA(" + ((DA)t).value() + ")";
if (t instanceof ClassInfo)
return ((ClassInfo)t).getSimpleName();
return t.toString();
}
};
//-----------------------------------------------------------------------------------------------------------------
// Instantiation.
//-----------------------------------------------------------------------------------------------------------------
static class B {
public B(int a, String b) {}
public void a1(int a, String b) {}
void a2(int a, String b) {}
}
static ClassInfo b = ClassInfo.of(B.class);
static ParamInfo
b_b_a = b.getPublicConstructor(int.class, String.class).getParam(0),
b_b_b = b.getPublicConstructor(int.class, String.class).getParam(1),
b_a1_a = b.getMethod("a1", int.class, String.class).getParam(0),
b_a1_b = b.getMethod("a1", int.class, String.class).getParam(1),
b_a2_a = b.getMethod("a2", int.class, String.class).getParam(0),
b_a2_b = b.getMethod("a2", int.class, String.class).getParam(1);
@Test
public void getIndex() {
assertEquals(0, b_b_a.getIndex());
assertEquals(1, b_b_b.getIndex());
assertEquals(0, b_a1_a.getIndex());
assertEquals(1, b_a1_b.getIndex());
assertEquals(0, b_a2_a.getIndex());
assertEquals(1, b_a2_b.getIndex());
}
@Test
public void getMethod() {
check("B.a1(int,String)", b_a1_a.getMethod());
check("B.a1(int,String)", b_a1_b.getMethod());
check("B.a2(int,String)", b_a2_a.getMethod());
check("B.a2(int,String)", b_a2_b.getMethod());
}
@Test
public void getMethod_onConstrutor() {
check(null, b_b_a.getMethod());
check(null, b_b_b.getMethod());
}
@Test
public void getConstructor() {
check("B(int,String)", b_b_a.getConstructor());
check("B(int,String)", b_b_b.getConstructor());
}
@Test
public void getConstructor_onMethod() {
check(null, b_a1_a.getConstructor());
check(null, b_a1_b.getConstructor());
check(null, b_a2_a.getConstructor());
check(null, b_a2_b.getConstructor());
}
@Test
public void getParameterType() {
check("int", b_b_a.getParameterType());
check("String", b_b_b.getParameterType());
check("int", b_a1_a.getParameterType());
check("String", b_a1_b.getParameterType());
check("int", b_a2_a.getParameterType());
check("String", b_a2_b.getParameterType());
}
//-----------------------------------------------------------------------------------------------------------------
// Annotations.
//-----------------------------------------------------------------------------------------------------------------
@Target({PARAMETER,TYPE})
@Retention(RUNTIME)
public static @interface CA {
public String value();
}
@CA("1") public static class C1 extends C2 {}
@CA("2") public static class C2 implements C3, C4 {}
@CA("3") public static interface C3 {}
@CA("4") public static interface C4 {}
public static interface CB {
public void a1(@CA("5") C1 x);
public void a2(@CA("5") C1 x);
}
public static class CC implements CB {
public CC(@CA("9") C1 x) {}
@Override
public void a1(C1 x) {}
@Override
public void a2(@CA("6") C1 x) {}
}
static ClassInfo
cb = ClassInfo.of(CB.class),
cc = ClassInfo.of(CC.class);
static ParamInfo
cc_cc = cc.getPublicConstructor(C1.class).getParam(0),
cb_a1 = cb.getMethod("a1", C1.class).getParam(0),
cb_a2 = cb.getMethod("a2", C1.class).getParam(0),
cc_a1 = cc.getMethod("a1", C1.class).getParam(0),
cc_a2 = cc.getMethod("a2", C1.class).getParam(0);
@Test
public void getDeclaredAnnotations() throws Exception {
check("@CA(5)", cb_a1.getDeclaredAnnotations());
check("@CA(5)", cb_a2.getDeclaredAnnotations());
check("", cc_a1.getDeclaredAnnotations());
check("@CA(6)", cc_a2.getDeclaredAnnotations());
}
@Test
public void getDeclaredAnnotations_constructor() throws Exception {
check("@CA(9)", cc_cc.getDeclaredAnnotations());
}
@Test
public void getDeclaredAnnotation() throws Exception {
check("@CA(5)", cb_a1.getDeclaredAnnotation(CA.class));
check("@CA(5)", cb_a2.getDeclaredAnnotation(CA.class));
check(null, cc_a1.getDeclaredAnnotation(CA.class));
check("@CA(6)", cc_a2.getDeclaredAnnotation(CA.class));
}
@Test
public void getDeclaredAnnotation_constructor() throws Exception {
check("@CA(9)", cc_cc.getDeclaredAnnotation(CA.class));
}
@Test
public void getDeclaredAnnotation_notFound() throws Exception {
check(null, cb_a1.getDeclaredAnnotation(DA.class));
}
@Test
public void getDeclaredAnnotation_notFound_constructor() throws Exception {
check(null, cc_cc.getDeclaredAnnotation(DA.class));
}
@Test
public void getDeclaredAnnotation_null() throws Exception {
check(null, cb_a1.getDeclaredAnnotation(null));
}
@Test
public void getDeclaredAnnotation_null_constructor() throws Exception {
check(null, cc_cc.getDeclaredAnnotation(null));
}
@Test
public void getAnnotations() throws Exception {
check("@CA(5),@CA(1),@CA(2),@CA(3),@CA(4)", cb_a1.getAnnotations(CA.class));
check("@CA(5),@CA(1),@CA(2),@CA(3),@CA(4)", cb_a2.getAnnotations(CA.class));
check("@CA(5),@CA(1),@CA(2),@CA(3),@CA(4)", cc_a1.getAnnotations(CA.class));
check("@CA(6),@CA(5),@CA(1),@CA(2),@CA(3),@CA(4)", cc_a2.getAnnotations(CA.class));
}
@Test
public void getAnnotations_notFound() throws Exception {
check("", cb_a1.getAnnotations(DA.class));
}
@Test
public void getAnnotations_constructor() throws Exception {
check("@CA(9),@CA(1),@CA(2),@CA(3),@CA(4)", cc_cc.getAnnotations(CA.class));
}
@Test
public void getAnnotations_notFound_constructor() throws Exception {
check("", cc_cc.getAnnotations(DA.class));
}
@Test
public void getAnnotationsParentFirst() throws Exception {
check("@CA(4),@CA(3),@CA(2),@CA(1),@CA(5)", cb_a1.getAnnotationsParentFirst(CA.class));
check("@CA(4),@CA(3),@CA(2),@CA(1),@CA(5)", cb_a2.getAnnotationsParentFirst(CA.class));
check("@CA(4),@CA(3),@CA(2),@CA(1),@CA(5)", cc_a1.getAnnotationsParentFirst(CA.class));
check("@CA(4),@CA(3),@CA(2),@CA(1),@CA(5),@CA(6)", cc_a2.getAnnotationsParentFirst(CA.class));
}
@Test
public void getAnnotationsParentFirst_notFound() throws Exception {
check("", cb_a1.getAnnotationsParentFirst(DA.class));
}
@Test
public void getAnnotationsParentFirst_constructor() throws Exception {
check("@CA(4),@CA(3),@CA(2),@CA(1),@CA(9)", cc_cc.getAnnotationsParentFirst(CA.class));
}
@Test
public void getAnnotationsParentFirst_notFound_constructor() throws Exception {
check("", cc_cc.getAnnotationsParentFirst(DA.class));
}
@Test
public void getAnnotation() throws Exception {
check("@CA(5)", cb_a1.getAnnotation(CA.class));
check("@CA(5)", cb_a2.getAnnotation(CA.class));
check("@CA(5)", cc_a1.getAnnotation(CA.class));
check("@CA(6)", cc_a2.getAnnotation(CA.class));
}
@Test
public void getAnnotation_notFound() throws Exception {
check(null, cb_a1.getAnnotation(DA.class));
}
@Test
public void getAnnotation_constructor() throws Exception {
check("@CA(9)", cc_cc.getAnnotation(CA.class));
}
@Test
public void getAnnotation_notFound_constructor() throws Exception {
check(null, cc_cc.getAnnotation(DA.class));
}
@Test
public void getAnnotation_twice() throws Exception {
check("@CA(5)", cb_a1.getAnnotation(CA.class));
check("@CA(5)", cb_a1.getAnnotation(CA.class));
}
@Test
public void getAnnotation_twice_constructor() throws Exception {
check("@CA(9)", cc_cc.getAnnotation(CA.class));
check("@CA(9)", cc_cc.getAnnotation(CA.class));
}
@Test
public void hasAnnotation() throws Exception {
assertTrue(cb_a1.hasAnnotation(CA.class));
assertTrue(cb_a2.hasAnnotation(CA.class));
assertTrue(cc_a1.hasAnnotation(CA.class));
assertTrue(cc_a2.hasAnnotation(CA.class));
assertFalse(cb_a1.hasAnnotation(DA.class));
}
@Test
public void hasAnnotation_constructor() throws Exception {
assertTrue(cc_cc.hasAnnotation(CA.class));
assertFalse(cc_cc.hasAnnotation(DA.class));
}
@Target({PARAMETER,TYPE})
@Retention(RUNTIME)
@Inherited
public static @interface DA {
public String value();
}
@DA("1") public static class D1 extends D2 {}
@DA("2") public static class D2 implements D3, D4 {}
@DA("3") public static interface D3 {}
@DA("4") public static interface D4 {}
public static interface DB {
public void a1(@DA("0") D1 x);
}
public static class DC implements DB {
@Override
public void a1(@DA("5") D1 x) {}
}
static ClassInfo
db = ClassInfo.of(DB.class),
dc = ClassInfo.of(DC.class);
static ParamInfo
db_a1 = db.getMethod("a1", D1.class).getParam(0),
dc_a1 = dc.getMethod("a1", D1.class).getParam(0);
@Test
public void getAnnotations_inherited() throws Exception {
check("@DA(0),@DA(1),@DA(2),@DA(3),@DA(4)", db_a1.getAnnotations(DA.class));
check("@DA(5),@DA(0),@DA(1),@DA(2),@DA(3),@DA(4)", dc_a1.getAnnotations(DA.class));
}
@Test
public void getAnnotations_inherited_notFound() throws Exception {
check("", db_a1.getAnnotations(CA.class));
}
@Test
public void getAnnotationsParentFirst_inherited() throws Exception {
check("@DA(4),@DA(3),@DA(2),@DA(1),@DA(0)", db_a1.getAnnotationsParentFirst(DA.class));
check("@DA(4),@DA(3),@DA(2),@DA(1),@DA(0),@DA(5)", dc_a1.getAnnotationsParentFirst(DA.class));
}
@Test
public void getAnnotationsParentFirst_inherited_notFound() throws Exception {
check("", db_a1.getAnnotationsParentFirst(CA.class));
}
@Test
public void getAnnotation_inherited() throws Exception {
check("@DA(0)", db_a1.getAnnotation(DA.class));
check("@DA(5)", dc_a1.getAnnotation(DA.class));
}
@Test
public void getAnnotation_inherited_notFound() throws Exception {
check(null, db_a1.getAnnotation(CA.class));
}
//-----------------------------------------------------------------------------------------------------------------
// Other methods.
//-----------------------------------------------------------------------------------------------------------------
static class E {
public void a1(int a, @Name("b") int b) {}
}
static ClassInfo e = ClassInfo.of(E.class);
static ParamInfo
e_a1_a = e.getMethod("a1", int.class, int.class).getParam(0),
e_a1_b = e.getMethod("a1", int.class, int.class).getParam(1);
@Test
public void hasName() {
e_a1_a.hasName(); // This might be true or false based on the JVM compiler used.
assertTrue(e_a1_b.hasName());
}
@Test
public void getName() {
e_a1_a.getName(); // This might be null or a value based on the JVM compiler used.
assertEquals("b", e_a1_b.getName());
}
@Test
public void toString2() {
assertEquals("a1[1]", e_a1_b.toString());
}
}