This is an automated email from the ASF dual-hosted git repository. jamesbognar pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/juneau.git
commit 9a7244898192302d6293c5d2944e2492c6a83a1c Author: JamesBognar <[email protected]> AuthorDate: Sun Apr 21 21:11:17 2019 -0400 New org.apache.juneau.reflect package and @Name annotation. --- .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../java/org/apache/juneau/PojoExamplesTest.java | 4 +- ...ructorInfoTest.java => AnnotationInfoTest.java} | 81 ++-- .../apache/juneau/reflection/ClassInfoTest.java | 158 ++++++-- .../juneau/reflection/ConstructorInfoTest.java | 111 ++++-- .../juneau/reflection/ExecutableInfoTest.java | 180 +++++++-- .../apache/juneau/reflection/FieldInfoTest.java | 353 ++++++++++++++++++ .../apache/juneau/reflection/MethodInfoTest.java | 406 +++++++++++++++----- .../apache/juneau/reflection/ParamInfoTest.java | 409 +++++++++++++++++++++ .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../src/main/java/org/apache/juneau/BeanMeta.java | 35 +- .../src/main/java/org/apache/juneau/ClassMeta.java | 12 +- .../main/java/org/apache/juneau/UriContext.java | 4 +- .../apache/juneau/annotation/BeanConstructor.java | 16 +- .../org/apache/juneau/annotation/BeanProperty.java | 2 + .../AnnotationInfo.java => annotation/Name.java} | 123 +++---- .../juneau/httppart/HttpPartSchemaBuilder.java | 2 +- .../httppart/bean/RequestBeanPropertyMeta.java | 2 +- .../juneau/httppart/bean/ResponseBeanMeta.java | 2 +- .../org/apache/juneau/internal/ClassUtils.java | 5 +- .../org/apache/juneau/reflect/AnnotationInfo.java | 2 +- .../java/org/apache/juneau/reflect/ClassInfo.java | 69 +++- .../org/apache/juneau/reflect/ExecutableInfo.java | 5 + .../java/org/apache/juneau/reflect/FieldInfo.java | 59 ++- .../java/org/apache/juneau/reflect/MethodInfo.java | 76 ++-- .../java/org/apache/juneau/reflect/ParamInfo.java | 99 ++--- .../.settings/org.eclipse.jdt.core.prefs | 3 +- juneau-doc/docs/ReleaseNotes/8.0.1.html | 2 + .../10.Transforms/08.BeanAnnotation.html | 2 +- .../10.Transforms/09.BeanPropertyAnnotation.html | 11 +- .../10.BeanConstructorAnnotation.html | 16 +- .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../org/apache/juneau/examples/core/pojo/Pojo.java | 6 +- .../juneau/examples/core/pojo/PojoComplex.java | 4 +- .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../.settings/org.eclipse.jdt.core.prefs | 3 +- juneau-releng/juneau-all/.project | 6 - .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../.settings/org.eclipse.jdt.core.prefs | 3 +- .../org/apache/juneau/rest/RestJavaMethod.java | 2 +- .../org/apache/juneau/rest/SwaggerGenerator.java | 16 +- 45 files changed, 1819 insertions(+), 497 deletions(-) diff --git a/juneau-core/juneau-core-test/.settings/org.eclipse.jdt.core.prefs b/juneau-core/juneau-core-test/.settings/org.eclipse.jdt.core.prefs index 4b04196..bb79aba 100644 --- a/juneau-core/juneau-core-test/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-core/juneau-core-test/.settings/org.eclipse.jdt.core.prefs @@ -1,6 +1,6 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -10,6 +10,7 @@ org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PojoExamplesTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PojoExamplesTest.java index 2e4db72..d0bd98f 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PojoExamplesTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PojoExamplesTest.java @@ -204,12 +204,12 @@ public class PojoExamplesTest { try { bs.getClassMeta(F1.class); } catch (Exception e) { - assertContains(e.getMessage(), "@Example used on invalid method 'org.apache.juneau.PojoExamplesTest$F1.example(String)'"); + assertContains(e.getMessage(), "@Example used on invalid method 'example(String)'"); } try { bs.getClassMeta(F2.class); } catch (Exception e) { - assertContains(e.getMessage(), "@Example used on invalid method 'org.apache.juneau.PojoExamplesTest$F2.example()'"); + assertContains(e.getMessage(), "@Example used on invalid method 'example()'"); } try { bs.getClassMeta(F3.class); diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ConstructorInfoTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/AnnotationInfoTest.java similarity index 53% copy from juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ConstructorInfoTest.java copy to juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/AnnotationInfoTest.java index 32ac2cd..3d6bf13 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ConstructorInfoTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/AnnotationInfoTest.java @@ -12,73 +12,37 @@ // *************************************************************************************************************************** package org.apache.juneau.reflection; -import static org.apache.juneau.reflect.ConstructorInfo.*; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; import static org.junit.Assert.*; -import java.lang.reflect.*; -import java.util.*; +import java.lang.annotation.*; import java.util.function.*; -import java.util.stream.*; import org.apache.juneau.reflect.*; import org.junit.*; -public class ConstructorInfoTest { +public class AnnotationInfoTest { private static void check(String expected, Object o) { - if (o instanceof List) { - List<?> l = (List<?>)o; - String actual = l - .stream() - .map(TO_STRING) - .collect(Collectors.joining(",")); - assertEquals(expected, actual); - } else if (o instanceof Iterable) { - String actual = StreamSupport.stream(((Iterable<?>)o).spliterator(), false) - .map(TO_STRING) - .collect(Collectors.joining(",")); - assertEquals(expected, actual); - } else { - assertEquals(expected, TO_STRING.apply(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 Class) - return ((Class<?>)t).getSimpleName(); - if (t instanceof Constructor) { - Constructor<?> x = (Constructor<?>)t; - return x.getDeclaringClass().getSimpleName() + '(' + argTypes(x.getParameterTypes()) + ')'; - } -// if (t instanceof Package) -// return ((Package)t).getName(); + if (t instanceof A) + return "@A(" + ((A)t).value() + ")"; if (t instanceof ClassInfo) return ((ClassInfo)t).getSimpleName(); -// if (t instanceof MethodInfo) -// return ((MethodInfo)t).getDeclaringClass().getSimpleName() + '.' + ((MethodInfo)t).getLabel(); -// if (t instanceof ConstructorInfo) -// return ((ConstructorInfo)t).getLabel(); -// if (t instanceof FieldInfo) -// return ((FieldInfo)t).getDeclaringClass().getSimpleName() + '.' + ((FieldInfo)t).getLabel(); -// if (t instanceof AnnotationInfo) -// return apply(((AnnotationInfo<?>)t).getAnnotation()); return t.toString(); } }; - private static String argTypes(Class<?>[] t) { - return Arrays.asList(t).stream().map(x -> x.getSimpleName()).collect(Collectors.joining(",")); - } - - private static ConstructorInfo ofc(Class<?> c, Class<?>...pt) { + private static ClassInfo of(Class<?> c) { try { - return of(c.getConstructor(pt)); - } catch (NoSuchMethodException | SecurityException e) { - e.printStackTrace(); + return ClassInfo.of(c); + } catch (SecurityException e) { fail(e.getLocalizedMessage()); } return null; @@ -88,20 +52,25 @@ public class ConstructorInfoTest { // Instantiation. //----------------------------------------------------------------------------------------------------------------- - static class A { - public A() {} + @Documented + @Target(TYPE) + @Retention(RUNTIME) + @Inherited + public static @interface A { + int value(); } - ConstructorInfo a = ofc(A.class); + + @A(1) + static class B {} + static ClassInfo b = of(B.class); @Test - public void of_noDeclaringClass() throws Exception { - check("A()", a.inner()); + public void getClassOn() { + check("B", b.getAnnotationInfos(A.class).get(0).getClassOn()); } @Test - public void getDeclaringClass() throws Exception { - check("A", a.getDeclaringClass()); + public void getAnnotation() { + check("@A(1)", b.getAnnotationInfos(A.class).get(0).getAnnotation()); } - - -} +} \ No newline at end of file diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java index 60cbbfa..640b1c0 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java @@ -101,8 +101,8 @@ public class ClassInfoTest { public class A2 extends Value<A1>{}; public class A3 extends Value<Map<String,List<String>>>{}; public class A4 extends Value<Map<String,String[][]>>{}; - public Type aType, pType, pTypeDimensional, pTypeGeneric, pTypeGenericArg; - { + public static Type aType, pType, pTypeDimensional, pTypeGeneric, pTypeGenericArg; + static { aType = ((ParameterizedType)A2.class.getGenericSuperclass()).getActualTypeArguments()[0]; pType = ((ParameterizedType)A3.class.getGenericSuperclass()).getActualTypeArguments()[0]; pTypeDimensional = ((ParameterizedType)A4.class.getGenericSuperclass()).getActualTypeArguments()[0]; @@ -111,8 +111,8 @@ public class ClassInfoTest { pTypeGenericArg = ((ParameterizedType)pTypeGeneric).getActualTypeArguments()[1]; } - public ClassInfo aTypeInfo=of(aType), pTypeInfo=of(pType), pTypeDimensionalInfo=of(pTypeDimensional), pTypeGenericInfo=of(pTypeGeneric), pTypeGenericArgInfo=of(pTypeGenericArg); - public ClassInfo aClass=of(AClass.class), aInterface=of(AInterface.class); + static ClassInfo aTypeInfo=of(aType), pTypeInfo=of(pType), pTypeDimensionalInfo=of(pTypeDimensional), pTypeGenericInfo=of(pTypeGeneric), pTypeGenericArgInfo=of(pTypeGenericArg); + static ClassInfo aClass=of(AClass.class), aInterface=of(AInterface.class); @Test public void ofType() { @@ -161,7 +161,7 @@ public class ClassInfoTest { static class BC2 extends BC1 implements BI3 {} static class BC3 extends BC2 {} - ClassInfo bi1=of(BI1.class), bi2=of(BI2.class), bi3=of(BI3.class), bi4=of(BI4.class), bc1=of(BC1.class), bc2=of(BC2.class), bc3=of(BC3.class), object=of(Object.class); + static ClassInfo bi1=of(BI1.class), bi2=of(BI2.class), bi3=of(BI3.class), bi4=of(BI4.class), bc1=of(BC1.class), bc2=of(BC2.class), bc3=of(BC3.class), object=of(Object.class); @Test public void getDeclaredInterfaces() { @@ -289,7 +289,7 @@ public class ClassInfoTest { public void c3a() {} protected void c3b() {} } - ClassInfo cc3 = of(CC3.class), ci2 = of(CI2.class); + static ClassInfo cc3 = of(CC3.class), ci2 = of(CI2.class); @Test public void getPublicMethods() throws Exception { @@ -350,6 +350,46 @@ public class ClassInfoTest { check("", pTypeGenericArgInfo.getDeclaredMethods()); } + static class C2 { + public void a1() {} + public void a2(int x){} + void b1() {} + void b2(int x){} + } + static ClassInfo c2 = ClassInfo.of(C2.class); + + @Test + public void getPublicMethod_noArgs() { + check("C2.a1()", c2.getPublicMethod("a1")); + check(null, c2.getPublicMethod("a2")); + check(null, c2.getPublicMethod("b1")); + check(null, c2.getPublicMethod("b2")); + } + + @Test + public void getPublicMethod_withArgs() { + check(null, c2.getPublicMethod("a1", int.class)); + check("C2.a2(int)", c2.getPublicMethod("a2", int.class)); + check(null, c2.getPublicMethod("b1", int.class)); + check(null, c2.getPublicMethod("b2", int.class)); + } + + @Test + public void getMethod_noArgs() { + check("C2.a1()", c2.getMethod("a1")); + check(null, c2.getMethod("a2")); + check("C2.b1()", c2.getMethod("b1")); + check(null, c2.getMethod("b2")); + } + + @Test + public void getMethod_withArgs() { + check(null, c2.getMethod("a1", int.class)); + check("C2.a2(int)", c2.getMethod("a2", int.class)); + check(null, c2.getMethod("b1", int.class)); + check("C2.b2(int)", c2.getMethod("b2", int.class)); + } + //----------------------------------------------------------------------------------------------------------------- // Special methods //----------------------------------------------------------------------------------------------------------------- @@ -379,7 +419,7 @@ public class ClassInfoTest { static class DA8 { public static DA8 create2(String s1) {return null;} } - ClassInfo da1=of(DA1.class), da2=of(DA2.class), da3=of(DA3.class), da4=of(DA4.class), da5=of(DA5.class), da6=of(DA6.class), da7=of(DA7.class), da8=of(DA8.class); + static ClassInfo da1=of(DA1.class), da2=of(DA2.class), da3=of(DA3.class), da4=of(DA4.class), da5=of(DA5.class), da6=of(DA6.class), da7=of(DA7.class), da8=of(DA8.class); @Test public void getFromStringMethod() throws Exception { @@ -434,7 +474,7 @@ public class ClassInfoTest { static class DB11 { public static DB11 fromFoo(DBx x) {return null;} } - ClassInfo db1=of(DB1.class), db2=of(DB2.class), db3=of(DB3.class), db4=of(DB4.class), db5=of(DB5.class), db6=of(DB6.class), db7=of(DB7.class), db8=of(DB8.class), db9=of(DB9.class), db10=of(DB10.class), db11=of(DB11.class); + static ClassInfo db1=of(DB1.class), db2=of(DB2.class), db3=of(DB3.class), db4=of(DB4.class), db5=of(DB5.class), db6=of(DB6.class), db7=of(DB7.class), db8=of(DB8.class), db9=of(DB9.class), db10=of(DB10.class), db11=of(DB11.class); @Test public void getStaticCreateMethod() throws Exception { @@ -473,7 +513,7 @@ public class ClassInfoTest { static class DC5 { public static DCx createFoo() {return null;} } - ClassInfo dc1=of(DC1.class), dc2=of(DC2.class), dc3=of(DC3.class), dc4=of(DC4.class), dc5=of(DC5.class); + static ClassInfo dc1=of(DC1.class), dc2=of(DC2.class), dc3=of(DC3.class), dc4=of(DC4.class), dc5=of(DC5.class); @Test public void getBuilderCreateMethod() throws Exception { @@ -500,7 +540,7 @@ public class ClassInfoTest { static class DD5 { public DDx build(String x) {return null;} } - ClassInfo dd1=of(DD1.class), dd2=of(DD2.class), dd3=of(DD3.class), dd4=of(DD4.class), dd5=of(DD5.class); + static ClassInfo dd1=of(DD1.class), dd2=of(DD2.class), dd3=of(DD3.class), dd4=of(DD4.class), dd5=of(DD5.class); @Test public void getBuilderBuildMethod() throws Exception { @@ -539,7 +579,7 @@ public class ClassInfoTest { class E6 { public E6(String a) {} } - ClassInfo e1=of(E1.class), e2=of(E2.class), e3=of(E3.class), e4=of(E4.class), e5=of(E5.class), e6=of(E6.class); + static ClassInfo e1=of(E1.class), e2=of(E2.class), e3=of(E3.class), e4=of(E4.class), e5=of(E5.class), e6=of(E6.class); @Test public void getPublicConstructors() { @@ -636,6 +676,13 @@ public class ClassInfoTest { check("E5()", e5.getConstructor(Visibility.PUBLIC)); } + @Test + public void getDeclaredConstructor() { + check("E1()", e1.getDeclaredConstructor()); + check("E1(int)", e1.getDeclaredConstructor(int.class)); + check(null, e1.getDeclaredConstructor(Object.class)); + } + //----------------------------------------------------------------------------------------------------------------- // Fields //----------------------------------------------------------------------------------------------------------------- @@ -650,7 +697,7 @@ public class ClassInfoTest { @Deprecated int f2c; protected int f2d; } - ClassInfo f1=of(F1.class), f2=of(F2.class); + static ClassInfo f1=of(F1.class), f2=of(F2.class); @Test public void getPublicFields() { @@ -719,6 +766,26 @@ public class ClassInfoTest { check("F1.f1a,F1.f1b,F2.f1a,F2.f2b,F2.f2c,F2.f2d", f2.getAllFieldsParentFirst()); } + static class F3 { + public int a1; + int a2; + } + static ClassInfo f3=of(F3.class); + + @Test + public void getPublicField() { + check("F3.a1", f3.getPublicField("a1")); + check(null, f3.getPublicField("a2")); + check(null, f3.getPublicField("a3")); + } + + @Test + public void getDeclaredField() { + check("F3.a1", f3.getDeclaredField("a1")); + check("F3.a2", f3.getDeclaredField("a2")); + check(null, f3.getDeclaredField("a3")); + } + //----------------------------------------------------------------------------------------------------------------- // Annotations //----------------------------------------------------------------------------------------------------------------- @@ -742,7 +809,7 @@ public class ClassInfoTest { static class G5 implements GI3 {} - ClassInfo g3=of(G3.class), g4=of(G4.class), g5=of(G5.class); + static ClassInfo g3=of(G3.class), g4=of(G4.class), g5=of(G5.class); @Test public void getAnnotation() { @@ -795,6 +862,11 @@ public class ClassInfoTest { } @Test + public void getDeclaredAnnotation_null() { + check(null, g3.getDeclaredAnnotation(null)); + } + + @Test public void getDeclaredAnnotation_twice() { check("@A(7)", g3.getDeclaredAnnotation(A.class)); check("@A(7)", g3.getDeclaredAnnotation(A.class)); @@ -858,7 +930,7 @@ public class ClassInfoTest { public abstract class H_AbstractPublic {} @Deprecated public class H_PublicDeprecated {} - ClassInfo hPublic=of(H_Public.class), hPackage=of(H_Package.class), hProtected=of(H_Protected.class), hPrivate=of(H_Private.class), hPublicMember=of(H_PublicMember.class), hAbstractPublic=of(H_AbstractPublic.class), hPublicDeprecated=of(H_PublicDeprecated.class); + static ClassInfo hPublic=of(H_Public.class), hPackage=of(H_Package.class), hProtected=of(H_Protected.class), hPrivate=of(H_Private.class), hPublicMember=of(H_PublicMember.class), hAbstractPublic=of(H_AbstractPublic.class), hPublicDeprecated=of(H_PublicDeprecated.class); @Test public void isDeprecated() { @@ -1165,7 +1237,7 @@ public class ClassInfoTest { abstract class H2_Abstract {} class H2_NotAbstract {} - ClassInfo h2a=of(H2a.class), h2b=of(H2b.class), h2Deprecated=of(H2_Deprecated.class), h2NotDeprecated=of(H2_NotDeprecated.class), h2Public=of(H2_Public.class), h2NotPublic=of(H2_NotPublic.class), h2Static=of(H2_Static.class), h2NotStatic=of(H2_NotStatic.class), h2Member=of(H2_Member.class), h2StaticMember=of(H2_StaticMember.class), h2Abstract=of(H2_Abstract.class), h2NotAbstract=of(H2_NotAbstract.class); + static ClassInfo h2a=of(H2a.class), h2b=of(H2b.class), h2Deprecated=of(H2_Deprecated.class), h2NotDeprecated=of(H2_NotDeprecated.class), h2Public=of(H2_Public.class), h2NotPublic=of(H2_NotPublic.class), h2Static=of(H2_Static.class), h2NotStatic=of(H2_NotStatic.class), h2Member=of(H2_Member.class), h2StaticMember=of(H2_StaticMember.class), h2Abstract=of(H2_Abstract.class), h2NotAbstract=of(H2_NotAbstract.class); @Test public void isAll() { @@ -1399,9 +1471,9 @@ public class ClassInfoTest { // Primitive wrappers //----------------------------------------------------------------------------------------------------------------- - List<Class<?>> primitives = AList.create(boolean.class,byte.class,short.class,char.class,int.class,long.class,float.class,double.class); - List<Class<?>> primitiveWrappers = AList.create(Boolean.class,Byte.class,Short.class,Character.class,Integer.class,Long.class,Float.class,Double.class); - List<Object> primitiveDefaults = AList.create(false,(byte)0,(short)0,(char)0,0,0l,0f,0d); + static List<Class<?>> primitives = AList.create(boolean.class,byte.class,short.class,char.class,int.class,long.class,float.class,double.class); + static List<Class<?>> primitiveWrappers = AList.create(Boolean.class,Byte.class,Short.class,Character.class,Integer.class,Long.class,Float.class,Double.class); + static List<Object> primitiveDefaults = AList.create(false,(byte)0,(short)0,(char)0,0,0l,0f,0d); @Test public void hasPrimitiveWrapper() { @@ -1466,6 +1538,7 @@ public class ClassInfoTest { @Test public void getWrapperInfoIfPrimitive_onType() { assertEquals(aTypeInfo.getWrapperInfoIfPrimitive().innerType(), aType); + check("V", pTypeGenericArgInfo.getWrapperInfoIfPrimitive()); } @Test @@ -1487,7 +1560,7 @@ public class ClassInfoTest { public class J1 {} public static class J2 {} - ClassInfo j1=of(J1.class), j2=of(J2.class), j1_3d=of(J1[][].class), j2_3d=of(J2[][].class); + static ClassInfo j1=of(J1.class), j2=of(J2.class), j1_3d=of(J1[][].class), j2_3d=of(J2[][].class); @Test public void getFullName_simple() { @@ -1700,6 +1773,14 @@ public class ClassInfoTest { assertEquals("LocalClass", of(LocalClass.class).getSimpleName()); } + @Test + public void getName() { + assertEquals("org.apache.juneau.reflection.AClass", aClass.getName()); + assertEquals("java.util.AbstractMap", pTypeGenericInfo.getName()); + assertEquals("V", pTypeGenericArgInfo.getName()); + } + + //----------------------------------------------------------------------------------------------------------------- // Hierarchy //----------------------------------------------------------------------------------------------------------------- @@ -1708,7 +1789,7 @@ public class ClassInfoTest { public static class KB implements KA {} public static class KC extends KB {} - public ClassInfo ka=of(KA.class), kb=of(KB.class), kc=of(KC.class); + static ClassInfo ka=of(KA.class), kb=of(KB.class), kc=of(KC.class); @Test @@ -1840,6 +1921,39 @@ public class ClassInfoTest { } @Test + public void is_ClassInfo() { + assertTrue(ka.is(of(KA.class))); + assertFalse(ka.is(of(KB.class))); + assertFalse(ka.is(of(KC.class))); + assertFalse(kb.is(of(KA.class))); + assertTrue(kb.is(of(KB.class))); + assertFalse(kb.is(of(KC.class))); + assertFalse(kc.is(of(KA.class))); + assertFalse(kc.is(of(KB.class))); + assertTrue(kc.is(of(KC.class))); + } + + @Test + public void is_ClassInfo_genType() { + assertFalse(pTypeGenericArgInfo.is(of(KA.class))); + } + + @Test + public void isAnyType() { + assertTrue(ka.isAny(KA.class)); + assertTrue(ka.isAny(KA.class, KB.class)); + assertFalse(ka.isAny(KB.class)); + assertFalse(ka.isAny(KC.class)); + assertFalse(kb.isAny(KA.class)); + assertTrue(kb.isAny(KB.class)); + assertFalse(kb.isAny(KC.class)); + assertFalse(kc.isAny(KA.class)); + assertFalse(kc.isAny(KB.class)); + assertTrue(kc.isAny(KC.class)); + } + + + @Test public void is_type() { assertFalse(aTypeInfo.is(KA.class)); assertFalse(pTypeInfo.is(KA.class)); @@ -1918,7 +2032,7 @@ public class ClassInfoTest { public static class LA {} - ClassInfo la=of(LA.class); + static ClassInfo la=of(LA.class); @Test public void newInstance() { @@ -1998,7 +2112,7 @@ public class ClassInfoTest { } - ClassInfo ma=of(MA.class), mb=of(MB.class), mc=of(MC.class), md=of(MD.class), me=of(ME.class), mf=of(MF.class), mg=of(MG.class), mh=of(MH.class), mi=of(MI.class), mj=of(MJ.class), ml=of(ML.class), mn=of(MM.MN.class); + static ClassInfo ma=of(MA.class), mb=of(MB.class), mc=of(MC.class), md=of(MD.class), me=of(ME.class), mf=of(MF.class), mg=of(MG.class), mh=of(MH.class), mi=of(MI.class), mj=of(MJ.class), ml=of(ML.class), mn=of(MM.MN.class); @Test public void getParameterType_simpleMap() { diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ConstructorInfoTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ConstructorInfoTest.java index 32ac2cd..9712a30 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ConstructorInfoTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ConstructorInfoTest.java @@ -20,27 +20,14 @@ import java.util.*; import java.util.function.*; import java.util.stream.*; +import org.apache.juneau.*; import org.apache.juneau.reflect.*; import org.junit.*; public class ConstructorInfoTest { private static void check(String expected, Object o) { - if (o instanceof List) { - List<?> l = (List<?>)o; - String actual = l - .stream() - .map(TO_STRING) - .collect(Collectors.joining(",")); - assertEquals(expected, actual); - } else if (o instanceof Iterable) { - String actual = StreamSupport.stream(((Iterable<?>)o).spliterator(), false) - .map(TO_STRING) - .collect(Collectors.joining(",")); - assertEquals(expected, actual); - } else { - assertEquals(expected, TO_STRING.apply(o)); - } + assertEquals(expected, TO_STRING.apply(o)); } private static final Function<Object,String> TO_STRING = new Function<Object,String>() { @@ -48,37 +35,22 @@ public class ConstructorInfoTest { public String apply(Object t) { if (t == null) return null; - if (t instanceof Class) - return ((Class<?>)t).getSimpleName(); - if (t instanceof Constructor) { - Constructor<?> x = (Constructor<?>)t; - return x.getDeclaringClass().getSimpleName() + '(' + argTypes(x.getParameterTypes()) + ')'; - } -// if (t instanceof Package) -// return ((Package)t).getName(); + if (t instanceof Iterable) + return StreamSupport.stream(((Iterable<?>)t).spliterator(), false).map(this).collect(Collectors.joining(",")); if (t instanceof ClassInfo) return ((ClassInfo)t).getSimpleName(); -// if (t instanceof MethodInfo) -// return ((MethodInfo)t).getDeclaringClass().getSimpleName() + '.' + ((MethodInfo)t).getLabel(); -// if (t instanceof ConstructorInfo) -// return ((ConstructorInfo)t).getLabel(); -// if (t instanceof FieldInfo) -// return ((FieldInfo)t).getDeclaringClass().getSimpleName() + '.' + ((FieldInfo)t).getLabel(); -// if (t instanceof AnnotationInfo) -// return apply(((AnnotationInfo<?>)t).getAnnotation()); + if (t instanceof ConstructorInfo) + return ((ConstructorInfo)t).getShortName(); + if (t instanceof Constructor) + return ConstructorInfo.of((Constructor<?>)t).getShortName(); return t.toString(); } }; - private static String argTypes(Class<?>[] t) { - return Arrays.asList(t).stream().map(x -> x.getSimpleName()).collect(Collectors.joining(",")); - } - private static ConstructorInfo ofc(Class<?> c, Class<?>...pt) { try { return of(c.getConstructor(pt)); } catch (NoSuchMethodException | SecurityException e) { - e.printStackTrace(); fail(e.getLocalizedMessage()); } return null; @@ -91,7 +63,12 @@ public class ConstructorInfoTest { static class A { public A() {} } - ConstructorInfo a = ofc(A.class); + static ConstructorInfo a = ofc(A.class); + + @Test + public void of_withDeclaringClass() throws Exception { + check("A()", ConstructorInfo.of(ClassInfo.of(A.class), a.inner())); + } @Test public void of_noDeclaringClass() throws Exception { @@ -103,5 +80,63 @@ public class ConstructorInfoTest { check("A", a.getDeclaringClass()); } + @Test + public void of_null() throws Exception { + check(null, ConstructorInfo.of(null)); + check(null, ConstructorInfo.of(null, null)); + } + + //----------------------------------------------------------------------------------------------------------------- + // Other methods + //----------------------------------------------------------------------------------------------------------------- + + public static class B { + private String f; + public B() {} + public B(String f) { + this.f = f; + } + public B(String f, String f2) { + this.f = f; + } + protected B(int f) {} + @Override + public String toString() { + return f; + } + } + static ClassInfo b = ClassInfo.of(B.class); + static ConstructorInfo + b_c1 = b.getPublicConstructor(), + b_c2 = b.getPublicConstructor(String.class), + b_c3 = b.getDeclaredConstructor(int.class), + b_c4 = b.getPublicConstructor(String.class, String.class); -} + + @Test + public void invoke() { + try { + assertEquals(null, b_c1.invoke().toString()); + assertEquals("foo", b_c2.invoke("foo").toString()); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + public void makeAccessible() { + b_c3.makeAccessible(Visibility.PROTECTED); + try { + assertEquals(null, b_c3.invoke(123).toString()); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + public void compareTo() { + Set<ConstructorInfo> s = new TreeSet<>(Arrays.asList(b_c1, b_c2, b_c3, b_c4, a)); + check("A(),B(),B(int),B(String),B(String,String)", s); + + } +} \ No newline at end of file diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ExecutableInfoTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ExecutableInfoTest.java index b2f4817..0284bdb 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ExecutableInfoTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ExecutableInfoTest.java @@ -14,6 +14,8 @@ package org.apache.juneau.reflection; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; +import static org.apache.juneau.reflect.ReflectFlags.*; + import static org.junit.Assert.*; import java.io.*; @@ -22,6 +24,7 @@ import java.util.*; import java.util.function.*; import java.util.stream.*; +import org.apache.juneau.*; import org.apache.juneau.internal.*; import org.apache.juneau.reflect.*; import org.junit.*; @@ -39,26 +42,16 @@ public class ExecutableInfoTest { return null; if (t instanceof List) return ((List<?>)t).stream().map(this).collect(Collectors.joining(",")); - if (t instanceof Iterable) - return StreamSupport.stream(((Iterable<?>)t).spliterator(), false).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 Annotation) return t.toString().replaceAll("\\@[^\\$]*\\$(.*)", "@$1"); if (t instanceof Class) return ((Class<?>)t).getSimpleName(); - if (t instanceof Package) - return ((Package)t).getName(); if (t instanceof ClassInfo) return ((ClassInfo)t).getSimpleName(); - if (t instanceof MethodInfo) - return ((MethodInfo)t).getDeclaringClass().getSimpleName() + '.' + ((MethodInfo)t).getShortName(); if (t instanceof ConstructorInfo) return ((ConstructorInfo)t).getShortName(); - if (t instanceof FieldInfo) - return ((FieldInfo)t).getDeclaringClass().getSimpleName() + '.' + ((FieldInfo)t).getName(); - if (t instanceof AnnotationInfo) - return apply(((AnnotationInfo<?>)t).getAnnotation()); if (t instanceof ParamInfo) return apply(((ParamInfo)t).toString()); return t.toString(); @@ -381,71 +374,214 @@ public class ExecutableInfoTest { // Characteristics //----------------------------------------------------------------------------------------------------------------- + static abstract class E { + @Deprecated public void deprecated() {} + public void notDeprecated() {} + public void hasParams(int foo) {} + public void hasNoParams() {} + public void isPublic() {} + protected void isNotPublic() {} + public static void isStatic() {} + public void isNotStatic() {} + public abstract void isAbstract(); + public void isNotAbstract() {} + } + static ClassInfo e = ClassInfo.of(E.class); + static ExecutableInfo + e_deprecated = e.getPublicMethod("deprecated"), + e_notDeprecated = e.getPublicMethod("notDeprecated"), + e_hasParams = e.getPublicMethod("hasParams", int.class), + e_hasNoParams = e.getPublicMethod("hasNoParams"), + e_isPublic = e.getPublicMethod("isPublic"), + e_isNotPublic = e.getMethod("isNotPublic"), + e_isStatic = e.getPublicMethod("isStatic"), + e_isNotStatic = e.getPublicMethod("isNotStatic"), + e_isAbstract = e.getPublicMethod("isAbstract"), + e_isNotAbstract = e.getPublicMethod("isNotAbstract") + ; + @Test public void isAll() { + assertTrue(e_deprecated.isAll(DEPRECATED)); + assertTrue(e_notDeprecated.isAll(NOT_DEPRECATED)); + assertTrue(e_hasParams.isAll(HAS_PARAMS)); + assertTrue(e_hasNoParams.isAll(HAS_NO_PARAMS)); + assertTrue(e_isPublic.isAll(PUBLIC)); + assertTrue(e_isNotPublic.isAll(NOT_PUBLIC)); + assertTrue(e_isStatic.isAll(STATIC)); + assertTrue(e_isNotStatic.isAll(NOT_STATIC)); + assertTrue(e_isAbstract.isAll(ABSTRACT)); + assertTrue(e_isNotAbstract.isAll(NOT_ABSTRACT)); + + assertFalse(e_deprecated.isAll(NOT_DEPRECATED)); + assertFalse(e_notDeprecated.isAll(DEPRECATED)); + assertFalse(e_hasParams.isAll(HAS_NO_PARAMS)); + assertFalse(e_hasNoParams.isAll(HAS_PARAMS)); + assertFalse(e_isPublic.isAll(NOT_PUBLIC)); + assertFalse(e_isNotPublic.isAll(PUBLIC)); + assertFalse(e_isStatic.isAll(NOT_STATIC)); + assertFalse(e_isNotStatic.isAll(STATIC)); + assertFalse(e_isAbstract.isAll(NOT_ABSTRACT)); + assertFalse(e_isNotAbstract.isAll(ABSTRACT)); + } + + @Test + public void isAll_invalidFlag() { + try { + e_deprecated.isAll(TRANSIENT); + } catch (RuntimeException e) { + assertEquals("Invalid flag for executable: TRANSIENT", e.getLocalizedMessage()); + } } @Test public void isAny() { + assertTrue(e_deprecated.isAny(DEPRECATED)); + assertTrue(e_notDeprecated.isAny(NOT_DEPRECATED)); + assertTrue(e_hasParams.isAny(HAS_PARAMS)); + assertTrue(e_hasNoParams.isAny(HAS_NO_PARAMS)); + assertTrue(e_isPublic.isAny(PUBLIC)); + assertTrue(e_isNotPublic.isAny(NOT_PUBLIC)); + assertTrue(e_isStatic.isAny(STATIC)); + assertTrue(e_isNotStatic.isAny(NOT_STATIC)); + assertTrue(e_isAbstract.isAny(ABSTRACT)); + assertTrue(e_isNotAbstract.isAny(NOT_ABSTRACT)); + + assertFalse(e_deprecated.isAny(NOT_DEPRECATED)); + assertFalse(e_notDeprecated.isAny(DEPRECATED)); + assertFalse(e_hasParams.isAny(HAS_NO_PARAMS)); + assertFalse(e_hasNoParams.isAny(HAS_PARAMS)); + assertFalse(e_isPublic.isAny(NOT_PUBLIC)); + assertFalse(e_isNotPublic.isAny(PUBLIC)); + assertFalse(e_isStatic.isAny(NOT_STATIC)); + assertFalse(e_isNotStatic.isAny(STATIC)); + assertFalse(e_isAbstract.isAny(NOT_ABSTRACT)); + assertFalse(e_isNotAbstract.isAny(ABSTRACT)); + } + + @Test + public void isAny_invalidFlag() { + try { + e_deprecated.isAny(TRANSIENT); + } catch (RuntimeException e) { + assertEquals("Invalid flag for executable: TRANSIENT", e.getLocalizedMessage()); + } } @Test public void hasArgs() { + assertTrue(e_hasParams.hasArgs(int.class)); + assertFalse(e_hasParams.hasArgs()); + assertFalse(e_hasParams.hasArgs(long.class)); + assertTrue(e_hasNoParams.hasArgs()); + assertFalse(e_hasNoParams.hasArgs(long.class)); } @Test public void hasFuzzyArgs() { + assertTrue(e_hasParams.hasFuzzyArgs(int.class)); + assertTrue(e_hasParams.hasFuzzyArgs(int.class, long.class)); + assertFalse(e_hasParams.hasFuzzyArgs(long.class)); + assertTrue(e_hasNoParams.hasFuzzyArgs()); + assertTrue(e_hasNoParams.hasFuzzyArgs(long.class)); } @Test public void isDeprecated() { + assertTrue(e_deprecated.isDeprecated()); + assertFalse(e_notDeprecated.isDeprecated()); } @Test public void isNotDeprecated() { + assertFalse(e_deprecated.isNotDeprecated()); + assertTrue(e_notDeprecated.isNotDeprecated()); } @Test public void isAbstract() { + assertTrue(e_isAbstract.isAbstract()); + assertFalse(e_isNotAbstract.isAbstract()); } @Test public void isNotAbstract() { + assertFalse(e_isAbstract.isNotAbstract()); + assertTrue(e_isNotAbstract.isNotAbstract()); } @Test public void isPublic() { + assertTrue(e_isPublic.isPublic()); + assertFalse(e_isNotPublic.isPublic()); } @Test public void isNotPublic() { + assertFalse(e_isPublic.isNotPublic()); + assertTrue(e_isNotPublic.isNotPublic()); } @Test public void isStatic() { + assertTrue(e_isStatic.isStatic()); + assertFalse(e_isNotStatic.isStatic()); } @Test public void isNotStatic() { + assertFalse(e_isStatic.isNotStatic()); + assertTrue(e_isNotStatic.isNotStatic()); } + //----------------------------------------------------------------------------------------------------------------- + // Visibility + //----------------------------------------------------------------------------------------------------------------- + static abstract class F { + public void isPublic() {} + protected void isProtected() {} + @SuppressWarnings("unused") + private void isPrivate() {} + void isDefault() {} + } + static ClassInfo f = ClassInfo.of(F.class); + static ExecutableInfo + f_isPublic = f.getPublicMethod("isPublic"), + f_isProtected = f.getMethod("isProtected"), + f_isPrivate = f.getMethod("isPrivate"), + f_isDefault = f.getMethod("isDefault"); + @Test + public void setAccessible() { + f_isPublic.setAccessible(); + f_isProtected.setAccessible(); + f_isPrivate.setAccessible(); + f_isDefault.setAccessible(); + } + @Test + public void isVisible() { + assertTrue(f_isPublic.isVisible(Visibility.PUBLIC)); + assertTrue(f_isPublic.isVisible(Visibility.PROTECTED)); + assertTrue(f_isPublic.isVisible(Visibility.PRIVATE)); + assertTrue(f_isPublic.isVisible(Visibility.DEFAULT)); + assertFalse(f_isProtected.isVisible(Visibility.PUBLIC)); + assertTrue(f_isProtected.isVisible(Visibility.PROTECTED)); + assertTrue(f_isProtected.isVisible(Visibility.PRIVATE)); + assertTrue(f_isProtected.isVisible(Visibility.DEFAULT)); + assertFalse(f_isPrivate.isVisible(Visibility.PUBLIC)); + assertFalse(f_isPrivate.isVisible(Visibility.PROTECTED)); + assertTrue(f_isPrivate.isVisible(Visibility.PRIVATE)); + assertFalse(f_isPrivate.isVisible(Visibility.DEFAULT)); - - - - - - - - - - - + assertFalse(f_isDefault.isVisible(Visibility.PUBLIC)); + assertFalse(f_isDefault.isVisible(Visibility.PROTECTED)); + assertTrue(f_isDefault.isVisible(Visibility.PRIVATE)); + assertTrue(f_isDefault.isVisible(Visibility.DEFAULT)); + } //----------------------------------------------------------------------------------------------------------------- // Labels @@ -459,7 +595,7 @@ public class ExecutableInfoTest { public void foo(String foo){} public void foo(Map<String,Object> foo){} } - ClassInfo x = ClassInfo.of(X.class); + static ClassInfo x = ClassInfo.of(X.class); @Test public void getFullName_method() { diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/FieldInfoTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/FieldInfoTest.java index 8967082..509386e 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/FieldInfoTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/FieldInfoTest.java @@ -12,6 +12,359 @@ // *************************************************************************************************************************** package org.apache.juneau.reflection; +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; +import static org.apache.juneau.reflect.ReflectFlags.*; +import static org.junit.Assert.*; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.function.*; + +import org.apache.juneau.*; +import org.apache.juneau.reflect.*; +import org.junit.*; + public class FieldInfoTest { + @Documented + @Target(FIELD) + @Retention(RUNTIME) + @Inherited + public static @interface A { + String value(); + } + + @Documented + @Target(FIELD) + @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 A) + return "@A(" + ((A)t).value() + ")"; + if (t instanceof ClassInfo) + return ((ClassInfo)t).getSimpleName(); + if (t instanceof FieldInfo) + return ((FieldInfo)t).getName(); + if (t instanceof Field) + return ((Field)t).getName(); + return t.toString(); + } + }; + + private static FieldInfo off(Class<?> c, String name) { + try { + return FieldInfo.of(c.getDeclaredField(name)); + } catch (SecurityException | NoSuchFieldException e) { + fail(e.getLocalizedMessage()); + } + return null; + } + + //----------------------------------------------------------------------------------------------------------------- + // Instantiation. + //----------------------------------------------------------------------------------------------------------------- + + static class A1 { + public int f1; + } + FieldInfo a1_f1 = off(A1.class, "f1"); + + @Test + public void of_withClass() { + check("f1", FieldInfo.of(ClassInfo.of(A1.class), a1_f1.inner())); + } + + @Test + public void of_withoutClass() { + check("f1", FieldInfo.of(a1_f1.inner())); + } + + @Test + public void of_null() { + check(null, FieldInfo.of(null)); + check(null, FieldInfo.of(null, null)); + } + + @Test + public void getDeclaringClass() { + check("A1", a1_f1.getDeclaringClass()); + check("A1", a1_f1.getDeclaringClass()); + } + + @Test + public void inner() { + check("f1", a1_f1.inner()); + } + + //----------------------------------------------------------------------------------------------------------------- + // Annotations + //----------------------------------------------------------------------------------------------------------------- + + public static class B { + @A("a1") public int a1; + public int a2; + } + + FieldInfo + b_a1 = off(B.class, "a1"), + b_a2 = off(B.class, "a2"); + + @Test + public void getAnnotation() { + check("@A(a1)", b_a1.getAnnotation(A.class)); + check(null, b_a2.getAnnotation(A.class)); + } + + @Test + public void getAnnotation_null() { + check(null, b_a1.getAnnotation(null)); + } + + @Test + public void hasAnnotation_true() { + assertTrue(b_a1.hasAnnotation(A.class)); + } + + @Test + public void hasAnnotation_false() { + assertFalse(b_a2.hasAnnotation(A.class)); + } + + //----------------------------------------------------------------------------------------------------------------- + // Characteristics + //----------------------------------------------------------------------------------------------------------------- + + static abstract class C { + @Deprecated public int deprecated; + public int notDeprecated; + public int isPublic; + protected int isNotPublic; + public static int isStatic; + public int isNotStatic; + public transient int isTransient; + public int isNotTransient; + } + static ClassInfo c = ClassInfo.of(C.class); + static FieldInfo + c_deprecated = c.getPublicField("deprecated"), + c_notDeprecated = c.getPublicField("notDeprecated"), + c_isPublic = c.getPublicField("isPublic"), + c_isNotPublic = c.getDeclaredField("isNotPublic"), + c_isStatic = c.getPublicField("isStatic"), + c_isNotStatic = c.getPublicField("isNotStatic"), + c_isTransient = c.getPublicField("isTransient"), + c_isNotTransient = c.getPublicField("isNotTransient") + ; + + @Test + public void isAll() { + assertTrue(c_deprecated.isAll(DEPRECATED)); + assertTrue(c_notDeprecated.isAll(NOT_DEPRECATED)); + assertTrue(c_isPublic.isAll(PUBLIC)); + assertTrue(c_isNotPublic.isAll(NOT_PUBLIC)); + assertTrue(c_isStatic.isAll(STATIC)); + assertTrue(c_isNotStatic.isAll(NOT_STATIC)); + assertTrue(c_isTransient.isAll(TRANSIENT)); + assertTrue(c_isNotTransient.isAll(NOT_TRANSIENT)); + + assertFalse(c_deprecated.isAll(NOT_DEPRECATED)); + assertFalse(c_notDeprecated.isAll(DEPRECATED)); + assertFalse(c_isPublic.isAll(NOT_PUBLIC)); + assertFalse(c_isNotPublic.isAll(PUBLIC)); + assertFalse(c_isStatic.isAll(NOT_STATIC)); + assertFalse(c_isNotStatic.isAll(STATIC)); + assertFalse(c_isTransient.isAll(NOT_TRANSIENT)); + assertFalse(c_isNotTransient.isAll(TRANSIENT)); + } + + @Test + public void isAll_invalidFlag() { + try { + c_deprecated.isAll(HAS_PARAMS); + } catch (RuntimeException e) { + assertEquals("Invalid flag for field: HAS_PARAMS", e.getLocalizedMessage()); + } + } + + @Test + public void isAny() { + assertTrue(c_deprecated.isAny(DEPRECATED)); + assertTrue(c_notDeprecated.isAny(NOT_DEPRECATED)); + assertTrue(c_isPublic.isAny(PUBLIC)); + assertTrue(c_isNotPublic.isAny(NOT_PUBLIC)); + assertTrue(c_isStatic.isAny(STATIC)); + assertTrue(c_isNotStatic.isAny(NOT_STATIC)); + assertTrue(c_isTransient.isAny(TRANSIENT)); + assertTrue(c_isNotTransient.isAny(NOT_TRANSIENT)); + + assertFalse(c_deprecated.isAny(NOT_DEPRECATED)); + assertFalse(c_notDeprecated.isAny(DEPRECATED)); + assertFalse(c_isPublic.isAny(NOT_PUBLIC)); + assertFalse(c_isNotPublic.isAny(PUBLIC)); + assertFalse(c_isStatic.isAny(NOT_STATIC)); + assertFalse(c_isNotStatic.isAny(STATIC)); + assertFalse(c_isTransient.isAny(NOT_TRANSIENT)); + assertFalse(c_isNotTransient.isAny(TRANSIENT)); + } + + @Test + public void isAny_invalidFlag() { + try { + c_deprecated.isAny(HAS_PARAMS); + } catch (RuntimeException e) { + assertEquals("Invalid flag for field: HAS_PARAMS", e.getLocalizedMessage()); + } + } + + @Test + public void isDeprecated() { + assertTrue(c_deprecated.isDeprecated()); + assertFalse(c_notDeprecated.isDeprecated()); + } + + @Test + public void isNotDeprecated() { + assertFalse(c_deprecated.isNotDeprecated()); + assertTrue(c_notDeprecated.isNotDeprecated()); + } + + @Test + public void isTransient() { + assertTrue(c_isTransient.isTransient()); + assertFalse(c_isNotTransient.isTransient()); + } + + @Test + public void isNotTransient() { + assertFalse(c_isTransient.isNotTransient()); + assertTrue(c_isNotTransient.isNotTransient()); + } + + @Test + public void isPublic() { + assertTrue(c_isPublic.isPublic()); + assertFalse(c_isNotPublic.isPublic()); + } + + @Test + public void isNotPublic() { + assertFalse(c_isPublic.isNotPublic()); + assertTrue(c_isNotPublic.isNotPublic()); + } + + @Test + public void isStatic() { + assertTrue(c_isStatic.isStatic()); + assertFalse(c_isNotStatic.isStatic()); + } + + @Test + public void isNotStatic() { + assertFalse(c_isStatic.isNotStatic()); + assertTrue(c_isNotStatic.isNotStatic()); + } + + @Test + public void hasName() { + assertTrue(b_a1.hasName("a1")); + assertFalse(b_a1.hasName("a2")); + } + + @Test + public void hasName_null() { + assertFalse(b_a1.hasName(null)); + } + + //----------------------------------------------------------------------------------------------------------------- + // Visibility + //----------------------------------------------------------------------------------------------------------------- + + static abstract class D { + public int isPublic; + protected int isProtected; + @SuppressWarnings("unused") + private int isPrivate; + int isDefault; + } + static ClassInfo d = ClassInfo.of(D.class); + static FieldInfo + d_isPublic = d.getPublicField("isPublic"), + d_isProtected = d.getDeclaredField("isProtected"), + d_isPrivate = d.getDeclaredField("isPrivate"), + d_isDefault = d.getDeclaredField("isDefault"); + + @Test + public void setAccessible() { + d_isPublic.setAccessible(); + d_isProtected.setAccessible(); + d_isPrivate.setAccessible(); + d_isDefault.setAccessible(); + } + + @Test + public void isVisible() { + assertTrue(d_isPublic.isVisible(Visibility.PUBLIC)); + assertTrue(d_isPublic.isVisible(Visibility.PROTECTED)); + assertTrue(d_isPublic.isVisible(Visibility.PRIVATE)); + assertTrue(d_isPublic.isVisible(Visibility.DEFAULT)); + + assertFalse(d_isProtected.isVisible(Visibility.PUBLIC)); + assertTrue(d_isProtected.isVisible(Visibility.PROTECTED)); + assertTrue(d_isProtected.isVisible(Visibility.PRIVATE)); + assertTrue(d_isProtected.isVisible(Visibility.DEFAULT)); + + assertFalse(d_isPrivate.isVisible(Visibility.PUBLIC)); + assertFalse(d_isPrivate.isVisible(Visibility.PROTECTED)); + assertTrue(d_isPrivate.isVisible(Visibility.PRIVATE)); + assertFalse(d_isPrivate.isVisible(Visibility.DEFAULT)); + + assertFalse(d_isDefault.isVisible(Visibility.PUBLIC)); + assertFalse(d_isDefault.isVisible(Visibility.PROTECTED)); + assertTrue(d_isDefault.isVisible(Visibility.PRIVATE)); + assertTrue(d_isDefault.isVisible(Visibility.DEFAULT)); + } + + //----------------------------------------------------------------------------------------------------------------- + // Other methods. + //----------------------------------------------------------------------------------------------------------------- + + static class E { + public int a1; + int a2; + } + + static ClassInfo e = ClassInfo.of(E.class); + static FieldInfo + e_a1 = e.getPublicField("a1"), + e_a2 = e.getDeclaredField("a2"); + + @Test + public void getType() { + check("int", e_a1.getType()); + check("int", e_a2.getType()); + } + + @Test + public void getType_twice() { + check("int", e_a1.getType()); + check("int", e_a1.getType()); + } + + @Test + public void toString2() { + assertEquals("org.apache.juneau.reflection.FieldInfoTest$E.a1", e_a1.toString()); + } } diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/MethodInfoTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/MethodInfoTest.java index 1f11fba..88ebecf 100644 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/MethodInfoTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/MethodInfoTest.java @@ -14,136 +14,110 @@ package org.apache.juneau.reflection; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; -import static org.apache.juneau.testutils.TestUtils.*; import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; -import org.apache.juneau.*; import org.apache.juneau.reflect.*; import org.junit.*; public class MethodInfoTest { - //==================================================================================================== - // getMethodAnnotation - //==================================================================================================== - @Test - public void getMethodAnnotations() throws Exception { - assertEquals("a1", MethodInfo.of(CI3.class.getMethod("a1")).getAnnotation(TestAnnotation.class).value()); - assertEquals("a2b", MethodInfo.of(CI3.class.getMethod("a2")).getAnnotation(TestAnnotation.class).value()); - assertEquals("a3", MethodInfo.of(CI3.class.getMethod("a3", CharSequence.class)).getAnnotation(TestAnnotation.class).value()); - assertEquals("a4", MethodInfo.of(CI3.class.getMethod("a4")).getAnnotation(TestAnnotation.class).value()); - } - - public static interface CI1 { - @TestAnnotation("a1") - void a1(); - @TestAnnotation("a2a") - void a2(); - @TestAnnotation("a3") - void a3(CharSequence foo); - - void a4(); - } - - public static class CI2 implements CI1 { - @Override - public void a1() {} - @Override - @TestAnnotation("a2b") - public void a2() {} - @Override - public void a3(CharSequence s) {} - @Override - public void a4() {} - } - - public static class CI3 extends CI2 { - @Override - public void a1() {} - @Override public void a2() {} - @Override - @TestAnnotation("a4") - public void a4() {} - } - + @Documented @Target(METHOD) @Retention(RUNTIME) - public @interface TestAnnotation { - String value() default ""; + @Inherited + public static @interface A { + String value(); } - //==================================================================================================== - // getAnnotations() - //==================================================================================================== - - @Target({PARAMETER,TYPE}) + @Documented + @Target(METHOD) @Retention(RUNTIME) - public static @interface HI1 { - public String value(); + @Inherited + public static @interface AX { + String value(); } - public static interface HA { - public void doX(@HI1("0") HA01 x); + private static void check(String expected, Object o) { + assertEquals(expected, TO_STRING.apply(o)); } - @HI1("1") public static class HA01 extends HA02 {} - @HI1("2") public static class HA02 implements HA03, HA04 {} - @HI1("3") public static interface HA03 {} - @HI1("4") public static interface HA04 {} + 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 MethodInfo) + return ((MethodInfo)t).getDeclaringClass().getSimpleName() + '.' + ((MethodInfo)t).getShortName(); + if (t instanceof Method) + return ((Method)t).getDeclaringClass().getSimpleName() + '.' + MethodInfo.of((Method)t).getShortName(); + if (t instanceof List) + return ((List<?>)t).stream().map(this).collect(Collectors.joining(",")); + if (t instanceof A) + return "@A(" + ((A)t).value() + ")"; + if (t instanceof ClassInfo) + return ((ClassInfo)t).getSimpleName(); + return t.toString(); + } + }; - @Test - public void getAnnotationsOnParameter() throws Exception { - ObjectList l = new ObjectList(); - ParamInfo mpi = MethodInfo.of(HA.class.getMethod("doX", HA01.class)).getParam(0); - for (HI1 ia : mpi.getAnnotations(HI1.class)) { - l.add(ia.value()); + private static MethodInfo ofm(Class<?> c, String name, Class<?>...pt) { + try { + return MethodInfo.of(c.getDeclaredMethod(name, pt)); + } catch (NoSuchMethodException | SecurityException e) { + fail(e.getLocalizedMessage()); } - assertEquals("['0','1','2','3','4']", l.toString()); + return null; } - @Target({PARAMETER,TYPE}) - @Retention(RUNTIME) - @Inherited - public static @interface HI2 { - public String value(); + //----------------------------------------------------------------------------------------------------------------- + // Instantiation. + //----------------------------------------------------------------------------------------------------------------- + + public static class A1 { + public void m() {} } + static MethodInfo a_m = ofm(A1.class, "m"); - public static interface HB { - public void doX(@HI2("0") HB01 x); + @Test + public void of_withDeclaringClass() { + check("A1.m()", a_m); + check("A1.m()", MethodInfo.of(ClassInfo.of(A1.class), a_m.inner())); } - @HI2("1") public static class HB01 extends HB02 {} - @HI2("2") public static class HB02 implements HB03, HB04 {} - @HI2("3") public static interface HB03 {} - @HI2("4") public static interface HB04 {} + @Test + public void of_withoutDeclaringClass() { + MethodInfo mi = MethodInfo.of(a_m.inner()); + check("A1.m()", mi); + } @Test - public void getAnnotationsOnParameterInherited() throws Exception { - ObjectList l = new ObjectList(); - ParamInfo mpi = MethodInfo.of(HB.class.getMethod("doX", HB01.class)).getParam(0); - for (HI2 ib : mpi.getAnnotations(HI2.class)) { - l.add(ib.value()); - } - assertEquals("['0','1','2','3','4']", l.toString()); + public void of_null() { + check(null, MethodInfo.of(null)); + check(null, MethodInfo.of(null, null)); } - //==================================================================================================== - // findMatchingMethods() - //==================================================================================================== + //----------------------------------------------------------------------------------------------------------------- + // Matching methods. + //----------------------------------------------------------------------------------------------------------------- - public static interface I1 { + public static interface B1 { public int foo(int x); public int foo(String x); public int foo(); } - public static class I2 { + public static class B2 { public int foo(int x) { return 0; } public int foo(String x) {return 0;} public int foo() {return 0;} } - public static class I3 extends I2 implements I1 { + public static class B3 extends B2 implements B1 { @Override public int foo(int x) {return 0;} @Override @@ -154,7 +128,253 @@ public class MethodInfoTest { @Test public void findMatchingMethods() throws Exception { - MethodInfo mi = MethodInfo.of(I3.class.getMethod("foo", int.class)); - assertObjectEquals("['public int org.apache.juneau.reflection.MethodInfoTest$I3.foo(int)','public int org.apache.juneau.reflection.MethodInfoTest$I2.foo(int)','public abstract int org.apache.juneau.reflection.MethodInfoTest$I1.foo(int)']", mi.getMatching()); + MethodInfo mi = MethodInfo.of(B3.class.getMethod("foo", int.class)); + check("B3.foo(int),B2.foo(int),B1.foo(int)", mi.getMatching()); + } + + + //----------------------------------------------------------------------------------------------------------------- + // Annotations + //----------------------------------------------------------------------------------------------------------------- + + public static interface C1 { + @A("a1") void a1(); + @A("a2a") void a2(); + @A("a3") void a3(CharSequence foo); + void a4(); + void a5(); + } + + public static class C2 implements C1 { + @Override public void a1() {} + @Override @A("a2b") public void a2() {} + @Override public void a3(CharSequence s) {} + @Override public void a4() {} + @Override public void a5() {} + } + + public static class C3 extends C2 { + @Override public void a1() {} + @Override public void a2() {} + @Override public void a3(CharSequence foo) {} + @Override @A("a4") public void a4() {} + @Override public void a5() {} + } + + static MethodInfo + c_a1 = ofm(C3.class, "a1"), + c_a2 = ofm(C3.class, "a2"), + c_a3 = ofm(C3.class, "a3", CharSequence.class), + c_a4 = ofm(C3.class, "a4"), + c_a5 = ofm(C3.class, "a5"); + + @Test + public void getAnnotations() { + check("@A(a1)", c_a1.getAnnotations(A.class)); + check("@A(a2b),@A(a2a)", c_a2.getAnnotations(A.class)); + check("@A(a3)", c_a3.getAnnotations(A.class)); + check("@A(a4)", c_a4.getAnnotations(A.class)); + check("", c_a5.getAnnotations(A.class)); + } + + @Test + public void getAnnotations_notExistent() { + check("", c_a1.getAnnotations(AX.class)); + check("", c_a2.getAnnotations(AX.class)); + check("", c_a3.getAnnotations(AX.class)); + check("", c_a4.getAnnotations(AX.class)); + check("", c_a5.getAnnotations(AX.class)); + } + + @Test + public void getAnnotationsParentFirst() { + check("@A(a1)", c_a1.getAnnotationsParentFirst(A.class)); + check("@A(a2a),@A(a2b)", c_a2.getAnnotationsParentFirst(A.class)); + check("@A(a3)", c_a3.getAnnotationsParentFirst(A.class)); + check("@A(a4)", c_a4.getAnnotationsParentFirst(A.class)); + check("", c_a5.getAnnotationsParentFirst(A.class)); + } + + @Test + public void appendAnnotations() { + check("@A(a1)", c_a1.appendAnnotations(new ArrayList<>(), A.class)); + check("@A(a2b),@A(a2a)", c_a2.appendAnnotations(new ArrayList<>(), A.class)); + check("@A(a3)", c_a3.appendAnnotations(new ArrayList<>(), A.class)); + check("@A(a4)", c_a4.appendAnnotations(new ArrayList<>(), A.class)); + check("", c_a5.appendAnnotations(new ArrayList<>(), A.class)); + } + + @Test + public void appendAnnotationsParentFirst() { + check("@A(a1)", c_a1.appendAnnotationsParentFirst(new ArrayList<>(), A.class)); + check("@A(a2a),@A(a2b)", c_a2.appendAnnotationsParentFirst(new ArrayList<>(), A.class)); + check("@A(a3)", c_a3.appendAnnotationsParentFirst(new ArrayList<>(), A.class)); + check("@A(a4)", c_a4.appendAnnotationsParentFirst(new ArrayList<>(), A.class)); + check("", c_a5.appendAnnotationsParentFirst(new ArrayList<>(), A.class)); + } + + @Test + public void getAnnotation() { + check("@A(a1)", c_a1.getAnnotation(A.class)); + check("@A(a2b)", c_a2.getAnnotation(A.class)); + check("@A(a3)", c_a3.getAnnotation(A.class)); + check("@A(a4)", c_a4.getAnnotation(A.class)); + check(null, c_a5.getAnnotation(A.class)); + } + + @Test + public void getAnnotationAny() { + check("@A(a1)", c_a1.getAnnotation(AX.class, A.class)); + check("@A(a2b)", c_a2.getAnnotation(AX.class, A.class)); + check("@A(a3)", c_a3.getAnnotation(AX.class, A.class)); + check("@A(a4)", c_a4.getAnnotation(AX.class, A.class)); + check(null, c_a5.getAnnotation(AX.class, A.class)); + } + + //----------------------------------------------------------------------------------------------------------------- + // Return type. + //----------------------------------------------------------------------------------------------------------------- + + public static class D { + public void a1() {} + public Integer a2() {return null;} + } + static MethodInfo + d_a1 = ofm(D.class, "a1"), + d_a2 = ofm(D.class, "a2"); + + @Test + public void getReturnType() { + check("void", d_a1.getReturnType()); + check("Integer", d_a2.getReturnType()); + } + + @Test + public void hasReturnType() { + assertTrue(d_a1.hasReturnType(void.class)); + assertFalse(d_a1.hasReturnType(Integer.class)); + assertTrue(d_a2.hasReturnType(Integer.class)); + assertFalse(d_a2.hasReturnType(Number.class)); + } + + @Test + public void hasReturnTypeParent() { + assertTrue(d_a1.hasReturnTypeParent(void.class)); + assertFalse(d_a1.hasReturnTypeParent(Integer.class)); + assertTrue(d_a2.hasReturnTypeParent(Integer.class)); + assertTrue(d_a2.hasReturnTypeParent(Number.class)); + } + + //----------------------------------------------------------------------------------------------------------------- + // Other methods + //----------------------------------------------------------------------------------------------------------------- + + public static class E { + private String f; + public void a1(CharSequence foo) { + f = foo == null ? null : foo.toString(); + } + public void a2(int f1, int f2) {} + public void a3() {} + } + static MethodInfo + e_a1 = ofm(E.class, "a1", CharSequence.class), + e_a2 = ofm(E.class, "a2", int.class, int.class), + e_a3 = ofm(E.class, "a3"); + + @Test + public void invoke() { + try { + E e = new E(); + e_a1.invoke(e, "foo"); + assertEquals("foo", e.f); + e_a1.invoke(e, (CharSequence)null); + assertNull(e.f); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + public void invokeFuzzy() { + try { + E e = new E(); + e_a1.invokeFuzzy(e, "foo", 123); + assertEquals("foo", e.f); + e_a1.invokeFuzzy(e, 123, "bar"); + assertEquals("bar", e.f); + } catch (Exception e) { + fail(e.getLocalizedMessage()); + } + } + + @Test + public void getSignature() { + assertEquals("a1(java.lang.CharSequence)", e_a1.getSignature()); + assertEquals("a2(int,int)", e_a2.getSignature()); + assertEquals("a3", e_a3.getSignature()); + } + + @Test + public void argsOnlyOfType() { + assertTrue(e_a1.argsOnlyOfType(CharSequence.class)); + assertTrue(e_a1.argsOnlyOfType(CharSequence.class, Map.class)); + assertFalse(e_a1.argsOnlyOfType()); + } + + public static class F { + public void isA() {} + public void is() {} + public void getA() {} + public void get() {} + public void setA() {} + public void set() {} + public void foo() {} + } + static MethodInfo + f_isA = ofm(F.class, "isA"), + f_is = ofm(F.class, "is"), + f_getA = ofm(F.class, "getA"), + f_get = ofm(F.class, "get"), + f_setA = ofm(F.class, "setA"), + f_set = ofm(F.class, "set"), + f_foo = ofm(F.class, "foo"); + + @Test + public void getPropertyName() { + assertEquals("a", f_isA.getPropertyName()); + assertEquals("is", f_is.getPropertyName()); + assertEquals("a", f_getA.getPropertyName()); + assertEquals("get", f_get.getPropertyName()); + assertEquals("a", f_setA.getPropertyName()); + assertEquals("set", f_set.getPropertyName()); + assertEquals("foo", f_foo.getPropertyName()); + } + + @Test + public void isBridge() { + assertFalse(f_foo.isBridge()); + } + + public static class G { + public void a1() {} + public void a1(int a1) {} + public void a1(int a1, int a2) {} + public void a1(String a1) {} + public void a2() {} + public void a3() {} + } + static MethodInfo + g_a1a = ofm(G.class, "a1"), + g_a1b = ofm(G.class, "a1", int.class), + g_a1c = ofm(G.class, "a1", int.class, int.class), + g_a1d = ofm(G.class, "a1", String.class), + g_a2 = ofm(G.class, "a2"), + g_a3 = ofm(G.class, "a3"); + + @Test + public void compareTo() { + Set<MethodInfo> s = new TreeSet<>(Arrays.asList(g_a1a, g_a1b, g_a1c, g_a1d, g_a2, g_a3)); + check("[a1(), a1(int), a1(String), a1(int,int), a2(), a3()]", s); } } diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ParamInfoTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ParamInfoTest.java new file mode 100644 index 0000000..8a531f4 --- /dev/null +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/reflection/ParamInfoTest.java @@ -0,0 +1,409 @@ +// *************************************************************************************************************************** +// * 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()); + } +} diff --git a/juneau-core/juneau-dto/.settings/org.eclipse.jdt.core.prefs b/juneau-core/juneau-dto/.settings/org.eclipse.jdt.core.prefs index 1a5f6d5..dbc47bf 100644 --- a/juneau-core/juneau-dto/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-core/juneau-dto/.settings/org.eclipse.jdt.core.prefs @@ -6,7 +6,7 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -112,6 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-core/juneau-marshall-rdf/.settings/org.eclipse.jdt.core.prefs b/juneau-core/juneau-marshall-rdf/.settings/org.eclipse.jdt.core.prefs index 1a5f6d5..dbc47bf 100644 --- a/juneau-core/juneau-marshall-rdf/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-core/juneau-marshall-rdf/.settings/org.eclipse.jdt.core.prefs @@ -6,7 +6,7 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -112,6 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-core/juneau-marshall/.settings/org.eclipse.jdt.core.prefs b/juneau-core/juneau-marshall/.settings/org.eclipse.jdt.core.prefs index 4a82b56..d16a260 100644 --- a/juneau-core/juneau-marshall/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-core/juneau-marshall/.settings/org.eclipse.jdt.core.prefs @@ -9,7 +9,7 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul org.eclipse.jdt.core.compiler.annotation.nullable.secondary= org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -122,6 +122,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java index a7e70a9..9dcaeef 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java @@ -224,8 +224,18 @@ public class BeanMeta<T> { throw new BeanRuntimeException(c, "Multiple instances of '@BeanConstructor' found."); constructor = x; constructorArgs = split(x.getAnnotation(BeanConstructor.class).properties()); - if (constructorArgs.length != x.getParamCount()) - throw new BeanRuntimeException(c, "Number of properties defined in '@BeanConstructor' annotation does not match number of parameters in constructor."); + if (constructorArgs.length != x.getParamCount()) { + if (constructorArgs.length != 0) + throw new BeanRuntimeException(c, "Number of properties defined in '@BeanConstructor' annotation does not match number of parameters in constructor."); + constructorArgs = new String[x.getParamCount()]; + int i = 0; + for (ParamInfo pi : x.getParams()) { + String pn = pi.getName(); + if (pn == null) + throw new BeanRuntimeException(c, "Could not find name for parameter #{0} of constructor ''{1}''", i, x.getFullName()); + constructorArgs[i++] = pn; + } + } constructor.setAccessible(); } } @@ -477,7 +487,8 @@ public class BeanMeta<T> { */ private String findPropertyName(Field f, Set<String> fixedBeanProps) { BeanProperty bp = f.getAnnotation(BeanProperty.class); - String name = bpName(bp); + Name n = f.getAnnotation(Name.class); + String name = bpName(bp, n); if (isNotEmpty(name)) { if (fixedBeanProps.isEmpty() || fixedBeanProps.contains(name)) return name; @@ -615,7 +626,8 @@ public class BeanMeta<T> { continue; BeanProperty bp = m.getAnnotation(BeanProperty.class); - if (! (m.isVisible(v) || bp != null)) + Name n2 = m.getAnnotation(Name.class); + if (! (m.isVisible(v) || bp != null || n2 != null)) continue; String n = m.getSimpleName(); @@ -623,7 +635,7 @@ public class BeanMeta<T> { List<ClassInfo> pt = m.getParamTypes(); ClassInfo rt = m.getReturnType(); MethodType methodType = UNKNOWN; - String bpName = bpName(bp); + String bpName = bpName(bp, n2); if (! (isEmpty(bpName) || filterProps.isEmpty() || filterProps.contains(bpName))) throw new BeanRuntimeException(c, "Found @BeanProperty(\"{0}\") but name was not found in @Bean(properties)", bpName); @@ -714,11 +726,12 @@ public class BeanMeta<T> { for (FieldInfo f : c2.getDeclaredFields()) { if (f.isAny(STATIC, TRANSIENT)) continue; - if (f.isAnnotationPresent(BeanIgnore.class)) + if (f.hasAnnotation(BeanIgnore.class)) continue; BeanProperty bp = f.getAnnotation(BeanProperty.class); - String bpName = bpName(bp); + Name n = f.getAnnotation(Name.class); + String bpName = bpName(bp, n); if (! (v.isVisible(f.inner()) || bp != null)) continue; @@ -737,7 +750,7 @@ public class BeanMeta<T> { for (FieldInfo f : c2.getDeclaredFields()) { if (f.isAny(STATIC, TRANSIENT)) continue; - if (f.isAnnotationPresent(BeanIgnore.class)) + if (f.hasAnnotation(BeanIgnore.class)) continue; if (f.hasName(name)) return f.inner(); @@ -897,7 +910,11 @@ public class BeanMeta<T> { } } - static final String bpName(BeanProperty bp) { + static final String bpName(BeanProperty bp, Name n) { + if (bp == null && n == null) + return null; + if (n != null) + return n.value(); if (bp == null) return null; if (! bp.name().isEmpty()) diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java index bc985d0..8f7365c 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java @@ -519,25 +519,25 @@ public final class ClassMeta<T> implements Type { } for (FieldInfo f : ci.getAllFieldsParentFirst()) { - if (f.isAnnotationPresent(ParentProperty.class)) { + if (f.hasAnnotation(ParentProperty.class)) { if (f.isStatic()) throw new ClassMetaRuntimeException("@ParentProperty used on invalid field ''{0}''. Must be static.", f); - f.setAccessible(false); + f.setAccessible(); parentPropertyMethod = new Setter.FieldSetter(f.inner()); } - if (f.isAnnotationPresent(NameProperty.class)) { + if (f.hasAnnotation(NameProperty.class)) { if (f.isStatic()) throw new ClassMetaRuntimeException("@NameProperty used on invalid field ''{0}''. Must be static.", f); - f.setAccessible(false); + f.setAccessible(); namePropertyMethod = new Setter.FieldSetter(f.inner()); } } for (FieldInfo f : ci.getDeclaredFields()) { - if (f.isAnnotationPresent(Example.class)) { + if (f.hasAnnotation(Example.class)) { if (! (f.isStatic() && ci.isParentOf(f.getType().inner()))) throw new ClassMetaRuntimeException("@Example used on invalid field ''{0}''. Must be static and an instance of the type.", f); - f.setAccessible(false); + f.setAccessible(); exampleField = f.inner(); } } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java index ba5f503..6779244 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java @@ -68,8 +68,8 @@ public class UriContext { * @param pathInfo * The path info (e.g. <js>"/path-info"</js>, or <js>"path-info"</js>) */ - @BeanConstructor(properties="authority,contextRoot,servletPath,pathInfo") - public UriContext(String authority, String contextRoot, String servletPath, String pathInfo) { + @BeanConstructor + public UriContext(@Name("authority") String authority, @Name("contextRoot") String contextRoot, @Name("servletPath") String servletPath, @Name("pathInfo") String pathInfo) { this.authority = nullIfEmpty(trimSlashes(authority)); this.contextRoot = nullIfEmpty(trimSlashes(contextRoot)); this.servletPath = nullIfEmpty(trimSlashes(servletPath)); diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConstructor.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConstructor.java index cded7e1..60ad50d 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConstructor.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConstructor.java @@ -56,14 +56,14 @@ public @interface BeanConstructor { /** * The names of the properties of the constructor arguments. * <p> - * The {@link org.apache.juneau.annotation.BeanConstructor @BeanConstructor} annotation is used to + * The {@link org.apache.juneau.annotation.BeanConstructor @BeanConstructor} annotation is used to * map constructor arguments to property names on bean with read-only properties. - * <br>Since method parameter names are lost during compilation, this annotation essentially redefines + * <br>Since method parameter names are lost during compilation, this annotation essentially redefines * them so that they are available at runtime. * </p> * <p> * The definition of a read-only bean is a bean with properties with only getters, like shown below: - * </p> + * </p> * <p class='bpcode w800'> * <jc>// Our read-only bean.</jc> * <jk>public class</jk> Person { @@ -86,7 +86,7 @@ public @interface BeanConstructor { * <jk>public int</jk> getAge() { * <jk>return</jk> <jf>age</jf>; * } - * } + * } * </p> * <p class='bpcode w800'> * <jc>// Parsing into a read-only bean.</jc> @@ -95,7 +95,11 @@ public @interface BeanConstructor { * String name = p.getName(); <jc>// "John Smith"</jc> * <jk>int</jk> age = p.getAge(); <jc>// 45</jc> * </p> - */ - + * <p> + * Note that the {@link Name @Name} annotation can also be used to identify bean property names on constructor + * arguments. If neither this annotation or {@link Name @Name} is used, then we try to get the property names + * from the parameter names if they are available in the bytecode. + * </p> + */ String properties() default ""; } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanProperty.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanProperty.java index 84a5b9d..42cf6b6 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanProperty.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanProperty.java @@ -143,6 +143,8 @@ public @interface BeanProperty { * Note that if you're not interested in these additional properties, you can also use the * {@link BeanContext#BEAN_ignoreUnknownBeanProperties} setting to ignore values that don't fit into existing * properties. + * <li class='info'> + * Note that the {@link Name @Name} annotation can also be used for identifying a property name. * </ul> */ String name() default ""; diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Name.java similarity index 54% copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Name.java index 499578b..5e1c411 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Name.java @@ -1,66 +1,57 @@ -// *************************************************************************************************************************** -// * 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.reflect; - -import java.lang.annotation.*; - -/** - * Represents an annotation instance on a class and the class it was found on. - * - * @param <T> The annotation type. - */ -public class AnnotationInfo<T extends Annotation> { - - private ClassInfo c; - private T a; - - /** - * Constructor. - * - * @param c The class where the annotation was found. - * @param a The annotation found. - */ - public AnnotationInfo(ClassInfo c, T a) { - this.c = c; - this.a = a; - } - - /** - * Convenience constructor. - * - * @param c The class where the annotation was found. - * @param a The annotation found. - * @return A new {@link AnnotationInfo} object. - */ - public static <T extends Annotation> AnnotationInfo<T> of(ClassInfo c, T a) { - return new AnnotationInfo<>(c, a); - } - - /** - * Returns the class where the annotation was found. - * - * @return the class where the annotation was found. - */ - public ClassInfo getClassOn() { - return c; - } - - /** - * Returns the annotation found. - * - * @return The annotation found. - */ - public T getAnnotation() { - return a; - } -} +// *************************************************************************************************************************** +// * 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.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +/** + * Annotation that can be used on method parameters to identify their name. + * + * <p> + * Can be used in the following locations: + * <ul> + * <li>In place of <code><ja>@BeanProperty</ja>(name=<js>"foo"</js>)</code> when just the name is specified. + * <li>On constructor and method arguments when the parameter names are not in the compiled bytecode. + * </ul> + * + * <h5 class='figure'>Examples:</h5> + * <p class='bcode w800'> + * <jc>// Identifying bean property names. + * // The field name can be anything.</jc> + * <jk>public class</jk> MyBean { + * + * <jc>// Same as @BeanProperty(properties="bar")</jc> + * <jk>public</jk> MyBean(@Name("bar") <jk>int</jk> foo) {} + * + * <ja>@Name</ja>(<js>"bar"</js>) <jc>// Same as @BeanProperty(name="bar")</jc> + * <jk>public int</jk> foo; + * + * <ja>@Name</ja>(<js>"*"</js>) <jc>// Same as @BeanProperty(name="*")</jc> + * <jk>public</jk> Map<String,Object> extraStuff = <jk>new</jk> LinkedHashMap<String,Object>(); + * } + * </p> + */ +@Documented +@Target({PARAMETER,METHOD,FIELD}) +@Retention(RUNTIME) +@Inherited +public @interface Name { + + /** + * The bean property or parameter name. + */ + String value(); +} diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java index 6503d4e..a70d27d 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchemaBuilder.java @@ -67,7 +67,7 @@ public class HttpPartSchemaBuilder { HttpPartSchemaBuilder apply(Class<? extends Annotation> c, ParamInfo mpi) { apply(c, mpi.getParameterType().innerType()); - for (Annotation a : mpi.getParameterAnnotations()) + for (Annotation a : mpi.getDeclaredAnnotations()) if (c.isInstance(a)) apply(a); return this; diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java index fc34ad2..c08948b 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java @@ -29,7 +29,7 @@ public class RequestBeanPropertyMeta { static RequestBeanPropertyMeta.Builder create(HttpPartType partType, Class<? extends Annotation> c, MethodInfo m) { HttpPartSchemaBuilder sb = HttpPartSchema.create().name(m.getPropertyName()); - for (Annotation a : m.getAnnotations(c, true)) + for (Annotation a : m.getAnnotationsParentFirst(c)) sb.apply(a); return new Builder().partType(partType).schema(sb.build()).getter(m.inner()); } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java index 9b5ce6a..2f23850 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/ResponseBeanMeta.java @@ -71,7 +71,7 @@ public class ResponseBeanMeta { return null; Builder b = new Builder(ps); b.apply(m.getReturnType().resolved().innerType()); - for (Response r : m.getAnnotations(Response.class, true)) + for (Response r : m.getAnnotationsParentFirst(Response.class)) b.apply(r); return b.build(); } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java index a915537..5138591 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java @@ -131,9 +131,10 @@ public final class ClassUtils { public static int fuzzyArgsMatch(Class<?>[] paramTypes, Class<?>... argTypes) { int matches = 0; outer: for (Class<?> p : paramTypes) { - p = getClassInfo(p).getWrapperIfPrimitive(); + ClassInfo pi = getClassInfo(p).getWrapperInfoIfPrimitive(); for (Class<?> a : argTypes) { - if (getClassInfo(p).isParentOf(a)) { + ClassInfo ai = getClassInfo(a).getWrapperInfoIfPrimitive(); + if (pi.isParentOf(ai.inner())) { matches++; continue outer; } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java index 499578b..f427275 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/AnnotationInfo.java @@ -30,7 +30,7 @@ public class AnnotationInfo<T extends Annotation> { * @param c The class where the annotation was found. * @param a The annotation found. */ - public AnnotationInfo(ClassInfo c, T a) { + protected AnnotationInfo(ClassInfo c, T a) { this.c = c; this.a = a; } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java index df50bea..04c7870 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java @@ -327,6 +327,21 @@ public final class ClassInfo { } /** + * Returns the method with the specified method name and argument types. + * + * @param name The method name (e.g. <js>"toString"</js>). + * @param args The exact argument types. + * @return + * The method with the specified method name and argument types, or <jk>null</jk> if not found. + */ + public MethodInfo getMethod(String name, Class<?>...args) { + for (MethodInfo mi : getAllMethods()) + if (mi.hasName(name) && mi.hasArgs(args)) + return mi; + return null; + } + + /** * Returns all methods declared on this class. * * @return @@ -506,6 +521,20 @@ public final class ClassInfo { } /** + * Returns the declared constructor with the specified argument types. + * + * @param args The exact argument types. + * @return + * The declared constructor with the specified argument types, or <jk>null</jk> if not found. + */ + public ConstructorInfo getDeclaredConstructor(Class<?>...args) { + for (ConstructorInfo ci : getDeclaredConstructors()) + if (ci.hasArgs(args)) + return ci; + return null; + } + + /** * Same as {@link #getPublicConstructor(Class...)} but allows for inexact arg type matching. * * <p> @@ -720,6 +749,33 @@ public final class ClassInfo { return m; } + + /** + * Returns the public field with the specified name. + * + * @param name The field name. + * @return The public field, or <jk>null</jk> if not found. + */ + public FieldInfo getPublicField(String name) { + for (FieldInfo f : getPublicFields()) + if (f.getName().equals(name)) + return f; + return null; + } + + /** + * Returns the declared field with the specified name. + * + * @param name The field name. + * @return The declared field, or <jk>null</jk> if not found. + */ + public FieldInfo getDeclaredField(String name) { + for (FieldInfo f : getDeclaredFields()) + if (f.getName().equals(name)) + return f; + return null; + } + //----------------------------------------------------------------------------------------------------------------- // Annotations //----------------------------------------------------------------------------------------------------------------- @@ -774,6 +830,8 @@ public final class ClassInfo { */ @SuppressWarnings("unchecked") public <T extends Annotation> T getDeclaredAnnotation(Class<T> a) { + if (a == null) + return null; Optional<Annotation> o = declaredAnnotationMap().get(a); if (o == null) { o = Optional.ofNullable(findDeclaredAnnotation(a)); @@ -995,10 +1053,9 @@ public final class ClassInfo { @SuppressWarnings("unchecked") private <T extends Annotation> T findDeclaredAnnotation(Class<T> a) { - if (c != null) - for (Annotation a2 : c.getDeclaredAnnotations()) - if (a2.annotationType() == a) - return (T)a2; + for (Annotation a2 : c.getDeclaredAnnotations()) + if (a2.annotationType() == a) + return (T)a2; return null; } @@ -1654,7 +1711,9 @@ public final class ClassInfo { * @return <jk>true</jk> if the specified class is the same as this one. */ public boolean is(ClassInfo c) { - return this.c != null && this.c.equals(c.inner()); + if (this.c != null) + return this.c.equals(c.inner()); + return t.equals(c.t); } /** diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java index 06b93e0..0753487 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java @@ -721,4 +721,9 @@ public abstract class ExecutableInfo { public final String getSimpleName() { return isConstructor ? e.getDeclaringClass().getSimpleName() : e.getName(); } + + @Override + public String toString() { + return getShortName(); + } } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java index 3913e27..055641a 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java @@ -98,9 +98,21 @@ public final class FieldInfo implements Comparable<FieldInfo> { * @return The annotation, or <jk>null</jk> if not found. */ public <T extends Annotation> T getAnnotation(Class<T> a) { + if (a == null) + return null; return f.getAnnotation(a); } + /** + * Returns <jk>true</jk> if the specified annotation is present. + * + * @param a The annotation to check for. + * @return <jk>true</jk> if the specified annotation is present. + */ + public boolean hasAnnotation(Class<? extends Annotation> a) { + return f.isAnnotationPresent(a); + } + //----------------------------------------------------------------------------------------------------------------- // Characteristics //----------------------------------------------------------------------------------------------------------------- @@ -122,10 +134,6 @@ public final class FieldInfo implements Comparable<FieldInfo> { if (isDeprecated()) return false; break; - case HAS_PARAMS: - break; - case HAS_NO_PARAMS: - break; case PUBLIC: if (isNotPublic()) return false; @@ -287,49 +295,40 @@ public final class FieldInfo implements Comparable<FieldInfo> { return f.getName().equals(name); } - /** - * Identifies if the specified visibility matches this field. - * - * @param v The visibility to validate against. - * @return <jk>true</jk> if this visibility matches the modifier attribute of this field. - */ - public boolean isVisible(Visibility v) { - return v.isVisible(f); - } - //----------------------------------------------------------------------------------------------------------------- - // Annotations. + // Visibility //----------------------------------------------------------------------------------------------------------------- /** - * Returns <jk>true</jk> if the specified annotation is present. - * - * @param a The annotation to check for. - * @return <jk>true</jk> if the specified annotation is present. - */ - public boolean isAnnotationPresent(Class<? extends Annotation> a) { - return f.isAnnotationPresent(a); - } - - /** * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. * - * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown. * @return <jk>true</jk> if call was successful. */ - public boolean setAccessible(boolean ignoreExceptions) { + public boolean setAccessible() { try { if (! (f.isAccessible())) f.setAccessible(true); return true; } catch (SecurityException e) { - if (ignoreExceptions) - return false; - throw new ClassMetaRuntimeException("Could not set accessibility to true on field ''{0}''", f); + return false; } } /** + * Identifies if the specified visibility matches this field. + * + * @param v The visibility to validate against. + * @return <jk>true</jk> if this visibility matches the modifier attribute of this field. + */ + public boolean isVisible(Visibility v) { + return v.isVisible(f); + } + + //----------------------------------------------------------------------------------------------------------------- + // Other methods. + //----------------------------------------------------------------------------------------------------------------- + + /** * Returns the type of this field. * * @return The type of this field. diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java index 11d098e..62c8ad1 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java @@ -127,24 +127,23 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho * A list of all matching annotations found in child-to-parent order, or an empty list if none found. */ public <T extends Annotation> List<T> getAnnotations(Class<T> a) { - return getAnnotations(a, false); + return appendAnnotations(new ArrayList<>(), a, false); } /** - * Identical to {@link #getAnnotations(Class)} but optionally returns the list in reverse (parent-to-child) order. + * Identical to {@link #getAnnotations(Class)} but returns the list in reverse (parent-to-child) order. * * @param a * The annotation to search for. - * @param parentFirst If <jk>true</jk>, results are in parent-to-child order. * @return * A list of all matching annotations found or an empty list if none found. */ - public <T extends Annotation> List<T> getAnnotations(Class<T> a, boolean parentFirst) { - return appendAnnotations(new ArrayList<>(), a, parentFirst); + public <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a) { + return appendAnnotations(new ArrayList<>(), a, true); } /** - * Finds and appends the specified annotation on the specified method and methods onsuperclasses/interfaces to the specified + * Finds and appends the specified annotation on the specified method and methods on superclasses/interfaces to the specified * list. * * <p> @@ -164,11 +163,14 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho * * @param l The list of annotations. * @param a The annotation. - * @param parentFirst If <jk>true</jk>, results are ordered in parent-to-child order. * @return The same list. */ + public <T extends Annotation> List<T> appendAnnotationsParentFirst(List<T> l, Class<T> a) { + return appendAnnotations(l, a, true); + } + @SuppressWarnings("unchecked") - public <T extends Annotation> List<T> appendAnnotations(List<T> l, Class<T> a, boolean parentFirst) { + private <T extends Annotation> List<T> appendAnnotations(List<T> l, Class<T> a, boolean parentFirst) { List<Method> methods = getMatching(); for (Method m2 : iterable(methods, parentFirst)) for (Annotation a2 : m2.getAnnotations()) @@ -209,6 +211,17 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho //----------------------------------------------------------------------------------------------------------------- /** + * Returns the generic return type of this method as a {@link ClassInfo} object. + * + * @return The generic return type of this method. + */ + public ClassInfo getReturnType() { + if (returnType == null) + returnType = ClassInfo.of(m.getReturnType(), m.getGenericReturnType()); + return returnType; + } + + /** * Returns <jk>true</jk> if this method has this return type. * * @param c The return type to test for. @@ -322,9 +335,9 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho * <jc>// Example method:</jc> * <jk>public void</jk> foo(String bar, Integer baz); * - * isArgsOnlyOfType(fooMethod, String.<jk>class</jk>, Integer.<jk>class</jk>); <jc>// True.</jc> - * isArgsOnlyOfType(fooMethod, String.<jk>class</jk>, Integer.<jk>class</jk>, Map.<jk>class</jk>); <jc>// True.</jc> - * isArgsOnlyOfType(fooMethod, String.<jk>class</jk>); <jc>// False.</jc> + * argsOnlyOfType(fooMethod, String.<jk>class</jk>, Integer.<jk>class</jk>); <jc>// True.</jc> + * argsOnlyOfType(fooMethod, String.<jk>class</jk>, Integer.<jk>class</jk>, Map.<jk>class</jk>); <jc>// True.</jc> + * argsOnlyOfType(fooMethod, String.<jk>class</jk>); <jc>// False.</jc> * </p> * * @param args The valid class types (exact) for the arguments. @@ -342,29 +355,6 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho return true; } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(m.getDeclaringClass().getName() + "." + m.getName() + "("); - for (int i = 0; i < rawParamTypes().length; i++) { - if (i > 0) - sb.append(","); - sb.append(rawParamTypes()[i].getSimpleName()); - } - sb.append(")"); - return sb.toString(); - } - - /** - * Returns the generic return type of this method as a {@link ClassInfo} object. - * - * @return The generic return type of this method. - */ - public ClassInfo getReturnType() { - if (returnType == null) - returnType = ClassInfo.of(m.getReturnType(), m.getGenericReturnType()); - return returnType; - } - /** * Returns <jk>true</jk> if this method is a bridge method. * @@ -387,22 +377,4 @@ public final class MethodInfo extends ExecutableInfo implements Comparable<Metho } return i; } - - /** - * Returns a readable representation of this method. - * - * @return A readable representation of this method. - */ - public Object getReadableName() { - StringBuilder sb = new StringBuilder(128); - sb.append(m.getDeclaringClass().getName()).append('.').append(m.getName()).append('('); - List<ParamInfo> mpis = getParams(); - for (int i = 0; i < mpis.size(); i++) { - if (i > 0) - sb.append(','); - mpis.get(i).getParameterType().appendFullName(sb); - } - sb.append(')'); - return sb.toString(); - } } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java index 57d3066..bc0c6e5 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ParamInfo.java @@ -30,7 +30,7 @@ public final class ParamInfo { private final ExecutableInfo eInfo; private final Parameter p; private final int index; - private Map<Class<?>,Optional<Annotation>> annotationMap = new ConcurrentHashMap<>(); + private volatile Map<Class<?>,Optional<Annotation>> annotationMap; //----------------------------------------------------------------------------------------------------------------- // Instantiation. @@ -61,19 +61,19 @@ public final class ParamInfo { /** * Returns the method that this parameter belongs to. * - * @return The method that this parameter belongs to. + * @return The method that this parameter belongs to, or <jk>null</jk> if it belongs to a constructor. */ public MethodInfo getMethod() { - return (MethodInfo)eInfo; + return eInfo.isConstructor() ? null : (MethodInfo)eInfo; } /** - * Returns the method that this parameter belongs to. + * Returns the constructor that this parameter belongs to. * - * @return The method that this parameter belongs to. + * @return The constructor that this parameter belongs to, or <jk>null</jk> if it belongs to a method. */ public ConstructorInfo getConstructor() { - return (ConstructorInfo)eInfo; + return eInfo.isConstructor() ? (ConstructorInfo)eInfo : null; } /** @@ -85,16 +85,37 @@ public final class ParamInfo { return eInfo.getParamType(index); } + //----------------------------------------------------------------------------------------------------------------- + // Annotations. + //----------------------------------------------------------------------------------------------------------------- + /** - * Returns the parameter annotations defined on this parameter. + * Returns the parameter annotations declared on this parameter. * - * @return The parameter annotations defined on this parameter. + * @return The parameter annotations declared on this parameter, or an empty array if none found. */ - public Annotation[] getParameterAnnotations() { + public Annotation[] getDeclaredAnnotations() { return eInfo.getParameterAnnotations(index); } /** + * Returns the specified parameter annotation declared on this parameter. + * + * @param a + * The annotation to search for. + * @param <T> + * @return The specified parameter annotation declared on this parameter, or <jk>null</jk> if not found. + */ + @SuppressWarnings("unchecked") + public <T extends Annotation> T getDeclaredAnnotation(Class<T> a) { + if (a != null) + for (Annotation aa : eInfo.getParameterAnnotations(index)) + if (a.isInstance(aa)) + return (T)aa; + return null; + } + + /** * Finds the annotation of the specified type defined on this method parameter. * * <p> @@ -161,48 +182,23 @@ public final class ParamInfo { * A list of all matching annotations found in child-to-parent order, or an empty list if none found. */ public <T extends Annotation> List<T> getAnnotations(Class<T> a) { - return getAnnotations(a, false); + return appendAnnotations(new ArrayList<>(), a, false); } /** - * Identical to {@link #getAnnotations(Class)} but optionally returns the list in reverse (parent-to-child) order. + * Identical to {@link #getAnnotations(Class)} but returns the list in reverse (parent-to-child) order. * * @param a * The annotation to search for. - * @param parentFirst If <jk>true</jk>, results are in parent-to-child order. * @return * A list of all matching annotations found or an empty list if none found. */ - public <T extends Annotation> List<T> getAnnotations(Class<T> a, boolean parentFirst) { - return appendAnnotations(new ArrayList<>(), a, parentFirst); - } - - /** - * Finds and appends the specified annotation on the specified method and methods onsuperclasses/interfaces to the specified - * list. - * - * <p> - * Results are ordered in child-to-parent order. - * - * @param l The list of annotations. - * @param a The annotation. - * @return The same list. - */ - public <T extends Annotation> List<T> appendAnnotations(List<T> l, Class<T> a) { - return appendAnnotations(l, a, false); + public <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a) { + return appendAnnotations(new ArrayList<>(), a, true); } - /** - * Finds and appends the specified annotation on the specified class and superclasses/interfaces to the specified - * list. - * - * @param l The list of annotations. - * @param a The annotation. - * @param parentFirst If <jk>true</jk>, results are ordered in parent-to-child order. - * @return The same list. - */ @SuppressWarnings("unchecked") - public <T extends Annotation> List<T> appendAnnotations(List<T> l, Class<T> a, boolean parentFirst) { + private <T extends Annotation> List<T> appendAnnotations(List<T> l, Class<T> a, boolean parentFirst) { if (eInfo.isConstructor) { ClassInfo ci = eInfo.getParamType(index).resolved(); Annotation[] annotations = eInfo.getParameterAnnotations(index); @@ -238,13 +234,23 @@ public final class ParamInfo { return l; } + private synchronized Map<Class<?>,Optional<Annotation>> annotationMap() { + if (annotationMap == null) + annotationMap = new ConcurrentHashMap<>(); + return annotationMap; + } + + //----------------------------------------------------------------------------------------------------------------- + // Other methods. + //----------------------------------------------------------------------------------------------------------------- + /** * Returns <jk>true</jk> if the parameter has a name provided by the class file. * * @return <jk>true</jk> if the parameter has a name provided by the class file. */ public boolean hasName() { - return p.isNamePresent(); + return p.isNamePresent() || p.isAnnotationPresent(Name.class); } /** @@ -258,13 +264,12 @@ public final class ParamInfo { * @see Parameter#getName() */ public String getName() { - return p.getName(); - } - - private synchronized Map<Class<?>,Optional<Annotation>> annotationMap() { - if (annotationMap == null) - annotationMap = new ConcurrentHashMap<>(); - return annotationMap; + Name n = p.getAnnotation(Name.class); + if (n != null) + return n.value(); + if (p.isNamePresent()) + return p.getName(); + return null; } @Override diff --git a/juneau-core/juneau-svl/.settings/org.eclipse.jdt.core.prefs b/juneau-core/juneau-svl/.settings/org.eclipse.jdt.core.prefs index 72d13e9..5b789dd 100644 --- a/juneau-core/juneau-svl/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-core/juneau-svl/.settings/org.eclipse.jdt.core.prefs @@ -6,7 +6,7 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -112,6 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-doc/docs/ReleaseNotes/8.0.1.html b/juneau-doc/docs/ReleaseNotes/8.0.1.html index 36e1acf..f587c2f 100644 --- a/juneau-doc/docs/ReleaseNotes/8.0.1.html +++ b/juneau-doc/docs/ReleaseNotes/8.0.1.html @@ -23,6 +23,8 @@ <ul class='spaced-list'> <li> New utility class for diffing beans: {@link oaj.utils.BeanDiff} + <li> + New annotation for defining bean property names: {@link oaj.annotation.Name} </ul> <h5 class='topic w800'>juneau-config</h5> diff --git a/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/08.BeanAnnotation.html b/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/08.BeanAnnotation.html index aea79ec..7ff9999 100644 --- a/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/08.BeanAnnotation.html +++ b/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/08.BeanAnnotation.html @@ -13,7 +13,7 @@ ***************************************************************************************************************************/ --> -@BeanProperty Annotation +@Bean Annotation <p> The {@link oaj.annotation.Bean @Bean} annotation is used to tailor how beans are diff --git a/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/09.BeanPropertyAnnotation.html b/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/09.BeanPropertyAnnotation.html index f78a5bc..8bdef83 100644 --- a/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/09.BeanPropertyAnnotation.html +++ b/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/09.BeanPropertyAnnotation.html @@ -13,7 +13,7 @@ ***************************************************************************************************************************/ --> -@BeanProperty Annotation +{updated} @BeanProperty Annotation <p> The {@link oaj.annotation.BeanProperty @BeanProperty} annotation is used to tailor how @@ -30,6 +30,15 @@ } </p> <p> + The {@link oaj.annoation.Name @Name} annotation is a shortcut for specifying a bean property name: +</p> +<p class='bpcode w800'> + <jk>public class</jk> MyBean { + <ja>@Name</ja>(<js>"Bar"</js>) + <jk>public</jk> String getFoo() {...} + } +</p> +<p> If the {@link oaj.BeanContext#BEAN_beanFieldVisibility} setting on the bean context excludes this field (e.g. the visibility is set to the default of PUBLIC, but the field is PROTECTED), this annotation can be used to force the field to be identified as a property. diff --git a/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/10.BeanConstructorAnnotation.html b/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/10.BeanConstructorAnnotation.html index ee796d3..768fb54 100644 --- a/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/10.BeanConstructorAnnotation.html +++ b/juneau-doc/docs/Topics/02.juneau-marshall/10.Transforms/10.BeanConstructorAnnotation.html @@ -13,7 +13,7 @@ ***************************************************************************************************************************/ --> -@BeanConstructor Annotation +{updated} @BeanConstructor Annotation <p> The {@link oaj.annotation.BeanConstructor @BeanConstructor} annotation is used to @@ -58,3 +58,17 @@ <p> Beans can also be defined with a combination of read-only and read-write properties. </p> +<p> + The {@link oaj.annotation.Name @Name} annotation can also be used instead of <code><ja>@BeanConstructor</ja>(properties)</code>: +</p> +<p class='bpcode w800'> + <ja>@BeanConstructor</ja> + <jk>public</jk> Person(<ja>@Name</ja>(<js>"name"</js>) String name, <ja>@Name</ja>(<js>"age"</js>) <jk>int</jk> age) { + <jk>this</jk>.<jf>name</jf> = name; + <jk>this</jk>.<jf>age</jf> = age; + } +</p> +<p> + If neither <code><ja>@BeanConstructor</ja>(properties)</code> or <ja>@Name</ja> is used to identify the bean property names, + we will try to use the parameter names if they are available in the bytecode. +</p> diff --git a/juneau-examples/juneau-examples-core/.settings/org.eclipse.jdt.core.prefs b/juneau-examples/juneau-examples-core/.settings/org.eclipse.jdt.core.prefs index 0721a8a..3bfcb67 100644 --- a/juneau-examples/juneau-examples-core/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-examples/juneau-examples-core/.settings/org.eclipse.jdt.core.prefs @@ -6,7 +6,7 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -112,6 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/pojo/Pojo.java b/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/pojo/Pojo.java index 8980396..d30621c 100644 --- a/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/pojo/Pojo.java +++ b/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/pojo/Pojo.java @@ -19,7 +19,7 @@ package org.apache.juneau.examples.core.pojo; -import org.apache.juneau.annotation.BeanConstructor; +import org.apache.juneau.annotation.*; /** * Sample pojo class. @@ -33,8 +33,8 @@ public class Pojo { private final String id; private final String name; - @BeanConstructor(properties = "id,name") - public Pojo(String id, String name) { + @BeanConstructor + public Pojo(@Name("id") String id, @Name("name") String name) { this.id = id; this.name = name; } diff --git a/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/pojo/PojoComplex.java b/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/pojo/PojoComplex.java index 302af32..869afd5 100644 --- a/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/pojo/PojoComplex.java +++ b/juneau-examples/juneau-examples-core/src/main/java/org/apache/juneau/examples/core/pojo/PojoComplex.java @@ -38,8 +38,8 @@ public class PojoComplex { * @param innerPojo * @param values */ - @BeanConstructor(properties = "id,innerPojo,values") - public PojoComplex(String id, Pojo innerPojo, HashMap<String, List<Pojo>> values) { + @BeanConstructor + public PojoComplex(@Name("id") String id, @Name("innerPojo") Pojo innerPojo, @Name("values") HashMap<String, List<Pojo>> values) { this.id = id; this.innerPojo = innerPojo; this.values = values; diff --git a/juneau-examples/juneau-examples-rest-springboot/.settings/org.eclipse.jdt.core.prefs b/juneau-examples/juneau-examples-rest-springboot/.settings/org.eclipse.jdt.core.prefs index 0721a8a..3bfcb67 100644 --- a/juneau-examples/juneau-examples-rest-springboot/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-examples/juneau-examples-rest-springboot/.settings/org.eclipse.jdt.core.prefs @@ -6,7 +6,7 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -112,6 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-examples/juneau-examples-rest/.settings/org.eclipse.jdt.core.prefs b/juneau-examples/juneau-examples-rest/.settings/org.eclipse.jdt.core.prefs index 0721a8a..3bfcb67 100644 --- a/juneau-examples/juneau-examples-rest/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-examples/juneau-examples-rest/.settings/org.eclipse.jdt.core.prefs @@ -6,7 +6,7 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -112,6 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-microservice/juneau-microservice-test/.settings/org.eclipse.jdt.core.prefs b/juneau-microservice/juneau-microservice-test/.settings/org.eclipse.jdt.core.prefs index 4b04196..bb79aba 100644 --- a/juneau-microservice/juneau-microservice-test/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-microservice/juneau-microservice-test/.settings/org.eclipse.jdt.core.prefs @@ -1,6 +1,6 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -10,6 +10,7 @@ org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-releng/juneau-all/.project b/juneau-releng/juneau-all/.project index 5ba7b4e..a9599a8 100644 --- a/juneau-releng/juneau-all/.project +++ b/juneau-releng/juneau-all/.project @@ -6,18 +6,12 @@ </projects> <buildSpec> <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> <name>org.eclipse.m2e.core.maven2Builder</name> <arguments> </arguments> </buildCommand> </buildSpec> <natures> - <nature>org.eclipse.jdt.core.javanature</nature> <nature>org.eclipse.m2e.core.maven2Nature</nature> </natures> </projectDescription> diff --git a/juneau-rest/juneau-rest-client/.settings/org.eclipse.jdt.core.prefs b/juneau-rest/juneau-rest-client/.settings/org.eclipse.jdt.core.prefs index 1a5f6d5..dbc47bf 100644 --- a/juneau-rest/juneau-rest-client/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-rest/juneau-rest-client/.settings/org.eclipse.jdt.core.prefs @@ -6,7 +6,7 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -112,6 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-rest/juneau-rest-server-jaxrs/.settings/org.eclipse.jdt.core.prefs b/juneau-rest/juneau-rest-server-jaxrs/.settings/org.eclipse.jdt.core.prefs index 1a5f6d5..dbc47bf 100644 --- a/juneau-rest/juneau-rest-server-jaxrs/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-rest/juneau-rest-server-jaxrs/.settings/org.eclipse.jdt.core.prefs @@ -6,7 +6,7 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -112,6 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-rest/juneau-rest-server/.settings/org.eclipse.jdt.core.prefs b/juneau-rest/juneau-rest-server/.settings/org.eclipse.jdt.core.prefs index 1a5f6d5..dbc47bf 100644 --- a/juneau-rest/juneau-rest-server/.settings/org.eclipse.jdt.core.prefs +++ b/juneau-rest/juneau-rest-server/.settings/org.eclipse.jdt.core.prefs @@ -6,7 +6,7 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 @@ -112,6 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java index bc54f8f..c033bf5 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java @@ -593,7 +593,7 @@ public class RestJavaMethod implements Comparable<RestJavaMethod> { } catch (IllegalArgumentException e) { throw new BadRequest(e, "Invalid argument type passed to the following method: ''{0}''.\n\tArgument types: {1}", - info.toString(), info.getReadableName() + info.toString(), info.getFullName() ); } catch (InvocationTargetException e) { Throwable e2 = e.getTargetException(); // Get the throwable thrown from the doX() method. diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java index 8b76cb6..1097428 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java @@ -344,19 +344,19 @@ final class SwaggerGenerator { try { if (mpi != null) { if (in == BODY) { - for (Body a : mpi.getAnnotations(Body.class, true)) + for (Body a : mpi.getAnnotationsParentFirst(Body.class)) merge(param, a); } else if (in == QUERY) { - for (Query a : mpi.getAnnotations(Query.class, true)) + for (Query a : mpi.getAnnotationsParentFirst(Query.class)) merge(param, a); } else if (in == FORM_DATA) { - for (FormData a : mpi.getAnnotations(FormData.class, true)) + for (FormData a : mpi.getAnnotationsParentFirst(FormData.class)) merge(param, a); } else if (in == HEADER) { - for (Header a : mpi.getAnnotations(Header.class, true)) + for (Header a : mpi.getAnnotationsParentFirst(Header.class)) merge(param, a); } else if (in == PATH) { - for (Path a : mpi.getAnnotations(Path.class, true)) + for (Path a : mpi.getAnnotationsParentFirst(Path.class)) merge(param, a); } } @@ -410,7 +410,7 @@ final class SwaggerGenerator { } if (mi.hasAnnotation(Response.class)) { - List<Response> la = mi.getAnnotations(Response.class, true); + List<Response> la = mi.getAnnotationsParentFirst(Response.class); Set<Integer> codes = getCodes(la, 200); for (Response a : la) { for (Integer code : codes) { @@ -448,7 +448,7 @@ final class SwaggerGenerator { ParamInfo mpi = mp.getMethodParamInfo(); if (in == RESPONSE_HEADER) { - List<ResponseHeader> la = mpi.getAnnotations(ResponseHeader.class, true); + List<ResponseHeader> la = mpi.getAnnotationsParentFirst(ResponseHeader.class); Set<Integer> codes = getCodes2(la, 200); for (ResponseHeader a : la) { for (Integer code : codes) { @@ -459,7 +459,7 @@ final class SwaggerGenerator { } } else if (in == RESPONSE) { - List<Response> la = mpi.getAnnotations(Response.class, true); + List<Response> la = mpi.getAnnotationsParentFirst(Response.class); Set<Integer> codes = getCodes(la, 200); for (Response a : la) { for (Integer code : codes) {
