You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by br...@apache.org on 2014/07/20 11:15:04 UTC
svn commit: r1612063 - in /commons/proper/lang/trunk/src: changes/
main/java/org/apache/commons/lang3/reflect/
test/java/org/apache/commons/lang3/reflect/
test/java/org/apache/commons/lang3/reflect/testbed/
Author: britter
Date: Sun Jul 20 09:15:04 2014
New Revision: 1612063
URL: http://svn.apache.org/r1612063
Log:
LANG-1021: Provide methods to retrieve all fields/methods annotated with a specific type. Thanks to Alexander Müller.
Added:
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/testbed/Annotated.java
Modified:
commons/proper/lang/trunk/src/changes/changes.xml
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java
Modified: commons/proper/lang/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/changes/changes.xml?rev=1612063&r1=1612062&r2=1612063&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/changes/changes.xml [utf-8] (original)
+++ commons/proper/lang/trunk/src/changes/changes.xml [utf-8] Sun Jul 20 09:15:04 2014
@@ -22,6 +22,7 @@
<body>
<release version="3.4" date="tba" description="tba">
+ <action issue="LANG-1021" type="add" dev="britter" due-to="Alexander Müller">Provide methods to retrieve all fields/methods annotated with a specific type</action>
<action issue="LANG-1026" type="update" dev="britter" due-to="Alex Yursha">Bring static method references in StringUtils to consistent style</action>
<action issue="LANG-1016" type="add" dev="britter" due-to="Juan Pablo Santos Rodríguez">NumberUtils#isParsable method(s)</action>
<action issue="LANG-1017" type="update" dev="britter" due-to="Christoph Schneegans">Use non-ASCII digits in Javadoc examples for StringUtils.isNumeric</action>
Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java?rev=1612063&r1=1612062&r2=1612063&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java Sun Jul 20 09:15:04 2014
@@ -20,6 +20,7 @@ import org.apache.commons.lang3.ClassUti
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
@@ -223,6 +224,45 @@ public class FieldUtils {
}
/**
+ * Gets all fields of the given class and its parents (if any) that are annotated with the given annotation.
+ * @param cls
+ * the {@link Class} to query
+ * @param annotationCls
+ * the {@link Annotation} that must be present on a field to be matched
+ * @return an array of Fields (possibly empty).
+ * @throws IllegalArgumentException
+ * if the class or annotation are {@code null}
+ * @since 3.4
+ */
+ public static Field[] getFieldsWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) {
+ final List<Field> annotatedFieldsList = getFieldsListWithAnnotation(cls, annotationCls);
+ return annotatedFieldsList.toArray(new Field[annotatedFieldsList.size()]);
+ }
+
+ /**
+ * Gets all fields of the given class and its parents (if any) that are annotated with the given annotation.
+ * @param cls
+ * the {@link Class} to query
+ * @param annotationCls
+ * the {@link Annotation} that must be present on a field to be matched
+ * @return a list of Fields (possibly empty).
+ * @throws IllegalArgumentException
+ * if the class or annotation are {@code null}
+ * @since 3.4
+ */
+ public static List<Field> getFieldsListWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) {
+ Validate.isTrue(annotationCls != null, "The annotation class must not be null");
+ final List<Field> allFields = getAllFieldsList(cls);
+ final List<Field> annotatedFields = new ArrayList<Field>();
+ for (final Field field : allFields) {
+ if (field.getAnnotation(annotationCls) != null) {
+ annotatedFields.add(field);
+ }
+ }
+ return annotatedFields;
+ }
+
+ /**
* Reads an accessible {@code static} {@link Field}.
*
* @param field
Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java?rev=1612063&r1=1612062&r2=1612063&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java Sun Jul 20 09:15:04 2014
@@ -16,14 +16,17 @@
*/
package org.apache.commons.lang3.reflect;
+import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -546,4 +549,44 @@ public class MethodUtils {
return result;
}
+ /**
+ * Gets all methods of the given class that are annotated with the given annotation.
+ * @param cls
+ * the {@link Class} to query
+ * @param annotationCls
+ * the {@link java.lang.annotation.Annotation} that must be present on a method to be matched
+ * @return an array of Methods (possibly empty).
+ * @throws IllegalArgumentException
+ * if the class or annotation are {@code null}
+ * @since 3.4
+ */
+ public static Method[] getMethodsWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) {
+ final List<Method> annotatedMethodsList = getMethodsListWithAnnotation(cls, annotationCls);
+ return annotatedMethodsList.toArray(new Method[annotatedMethodsList.size()]);
+ }
+
+ /**
+ * Gets all methods of the given class that are annotated with the given annotation.
+ * @param cls
+ * the {@link Class} to query
+ * @param annotationCls
+ * the {@link Annotation} that must be present on a method to be matched
+ * @return a list of Methods (possibly empty).
+ * @throws IllegalArgumentException
+ * if the class or annotation are {@code null}
+ * @since 3.4
+ */
+ public static List<Method> getMethodsListWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) {
+ Validate.isTrue(cls != null, "The class must not be null");
+ Validate.isTrue(annotationCls != null, "The annotation class must not be null");
+ final Method[] allMethods = cls.getMethods();
+ final List<Method> annotatedMethods = new ArrayList<Method>();
+ for (final Method method : allMethods) {
+ if (method.getAnnotation(annotationCls) != null) {
+ annotatedMethods.add(method);
+ }
+ }
+ return annotatedMethods;
+ }
+
}
Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java?rev=1612063&r1=1612062&r2=1612063&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java Sun Jul 20 09:15:04 2014
@@ -43,8 +43,10 @@ public class FieldUtilsTest {
static final Double D0 = Double.valueOf(0.0);
static final Double D1 = Double.valueOf(1.0);
+ @Annotated
private PublicChild publicChild;
private PubliclyShadowedChild publiclyShadowedChild;
+ @Annotated
private PrivatelyShadowedChild privatelyShadowedChild;
private final Class<? super PublicChild> parentClass = PublicChild.class.getSuperclass();
@@ -167,6 +169,59 @@ public class FieldUtilsTest {
}
@Test
+ public void testGetFieldsWithAnnotation() throws NoSuchFieldException {
+ assertArrayEquals(new Field[0], FieldUtils.getFieldsWithAnnotation(Object.class, Annotated.class));
+ final Field[] annotatedFields = new Field[]{
+ FieldUtilsTest.class.getDeclaredField("publicChild"),
+ FieldUtilsTest.class.getDeclaredField("privatelyShadowedChild")
+ };
+ assertArrayEquals(annotatedFields, FieldUtils.getFieldsWithAnnotation(FieldUtilsTest.class, Annotated.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFieldsWithAnnotationIllegalArgumentException1() {
+ FieldUtils.getFieldsWithAnnotation(FieldUtilsTest.class, null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFieldsWithAnnotationIllegalArgumentException2() {
+ FieldUtils.getFieldsWithAnnotation(null, Annotated.class);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFieldsWithAnnotationIllegalArgumentException3() {
+ FieldUtils.getFieldsWithAnnotation(null, null);
+ }
+
+ @Test
+ public void testGetFieldsListWithAnnotation() throws NoSuchFieldException {
+ assertEquals(0, FieldUtils.getFieldsListWithAnnotation(Object.class, Annotated.class).size());
+ final List<Field> annotatedFields = Arrays.asList(
+ FieldUtilsTest.class.getDeclaredField("publicChild"),
+ FieldUtilsTest.class.getDeclaredField("privatelyShadowedChild")
+ );
+ final List<Field> fieldUtilsTestAnnotatedFields = FieldUtils.getFieldsListWithAnnotation(FieldUtilsTest.class, Annotated.class);
+ assertEquals(annotatedFields.size(),fieldUtilsTestAnnotatedFields.size());
+ assertTrue(fieldUtilsTestAnnotatedFields.contains(annotatedFields.get(0)));
+ assertTrue(fieldUtilsTestAnnotatedFields.contains(annotatedFields.get(1)));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFieldsListWithAnnotationIllegalArgumentException1() {
+ FieldUtils.getFieldsListWithAnnotation(FieldUtilsTest.class, null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFieldsListWithAnnotationIllegalArgumentException2() {
+ FieldUtils.getFieldsListWithAnnotation(null, Annotated.class);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetFieldsListWithAnnotationIllegalArgumentException3() {
+ FieldUtils.getFieldsListWithAnnotation(null, null);
+ }
+
+ @Test
public void testGetDeclaredField() {
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "VALUE"));
assertNull(FieldUtils.getDeclaredField(PublicChild.class, "s"));
@@ -818,28 +873,28 @@ public class FieldUtilsTest {
assertEquals("new", StaticContainer.getMutablePrivate());
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PUBLIC");
try {
- FieldUtils.writeStaticField(field, "new", true);
+ FieldUtils.writeStaticField(field, "new", true);
fail("Expected IllegalAccessException");
} catch (final IllegalAccessException e) {
// pass
}
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PROTECTED");
try {
- FieldUtils.writeStaticField(field, "new", true);
+ FieldUtils.writeStaticField(field, "new", true);
fail("Expected IllegalAccessException");
} catch (final IllegalAccessException e) {
// pass
}
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PACKAGE");
try {
- FieldUtils.writeStaticField(field, "new", true);
+ FieldUtils.writeStaticField(field, "new", true);
fail("Expected IllegalAccessException");
} catch (final IllegalAccessException e) {
// pass
}
field = StaticContainer.class.getDeclaredField("IMMUTABLE_PRIVATE");
try {
- FieldUtils.writeStaticField(field, "new", true);
+ FieldUtils.writeStaticField(field, "new", true);
fail("Expected IllegalAccessException");
} catch (final IllegalAccessException e) {
// pass
Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java?rev=1612063&r1=1612062&r2=1612063&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java Sun Jul 20 09:15:04 2014
@@ -16,6 +16,7 @@
*/
package org.apache.commons.lang3.reflect;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -30,6 +31,7 @@ import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.ArrayUtils;
@@ -37,6 +39,7 @@ import org.apache.commons.lang3.math.Num
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.commons.lang3.ClassUtils.Interfaces;
+import org.apache.commons.lang3.reflect.testbed.Annotated;
import org.apache.commons.lang3.reflect.testbed.GenericConsumer;
import org.apache.commons.lang3.reflect.testbed.GenericParent;
import org.apache.commons.lang3.reflect.testbed.StringParameterizedChild;
@@ -424,6 +427,61 @@ public class MethodUtilsTest {
}
assertFalse(expected.hasNext());
}
+
+ @Test
+ @Annotated
+ public void testGetMethodsWithAnnotation() throws NoSuchMethodException {
+ assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class));
+ final Method[] annotatedMethods = new Method[]{
+ MethodUtilsTest.class.getMethod("testGetMethodsWithAnnotation"),
+ MethodUtilsTest.class.getMethod("testGetMethodsListWithAnnotation")
+ };
+ assertArrayEquals(annotatedMethods, MethodUtils.getMethodsWithAnnotation(MethodUtilsTest.class, Annotated.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetMethodsWithAnnotationIllegalArgumentException1() {
+ MethodUtils.getMethodsWithAnnotation(FieldUtilsTest.class, null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetMethodsWithAnnotationIllegalArgumentException2() {
+ MethodUtils.getMethodsWithAnnotation(null, Annotated.class);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetMethodsWithAnnotationIllegalArgumentException3() {
+ MethodUtils.getMethodsWithAnnotation(null, null);
+ }
+
+ @Test
+ @Annotated
+ public void testGetMethodsListWithAnnotation() throws NoSuchMethodException {
+ assertEquals(0, MethodUtils.getMethodsListWithAnnotation(Object.class, Annotated.class).size());
+ final List<Method> annotatedMethods = Arrays.asList(
+ MethodUtilsTest.class.getMethod("testGetMethodsWithAnnotation"),
+ MethodUtilsTest.class.getMethod("testGetMethodsListWithAnnotation")
+ );
+ final List<Method> methodUtilsTestAnnotatedFields = MethodUtils.getMethodsListWithAnnotation(MethodUtilsTest.class, Annotated.class);
+ assertEquals(annotatedMethods.size(), methodUtilsTestAnnotatedFields.size());
+ assertTrue(methodUtilsTestAnnotatedFields.contains(annotatedMethods.get(0)));
+ assertTrue(methodUtilsTestAnnotatedFields.contains(annotatedMethods.get(1)));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetMethodsListWithAnnotationIllegalArgumentException1() {
+ MethodUtils.getMethodsListWithAnnotation(FieldUtilsTest.class, null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetMethodsListWithAnnotationIllegalArgumentException2() {
+ MethodUtils.getMethodsListWithAnnotation(null, Annotated.class);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetMethodsListWithAnnotationIllegalArgumentException3() {
+ MethodUtils.getMethodsListWithAnnotation(null, null);
+ }
private void expectMatchingAccessibleMethodParameterTypes(final Class<?> cls,
final String methodName, final Class<?>[] requestTypes, final Class<?>[] actualTypes) {
Added: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/testbed/Annotated.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/testbed/Annotated.java?rev=1612063&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/testbed/Annotated.java (added)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/reflect/testbed/Annotated.java Sun Jul 20 09:15:04 2014
@@ -0,0 +1,11 @@
+package org.apache.commons.lang3.reflect.testbed;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
+public @interface Annotated {
+}