LANG-1021: Provide methods to retrieve all fields/methods annotated with a specific type. Thanks to Alexander Müller.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1612063 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
03aa1e7078
commit
de67dec077
|
@ -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>
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.apache.commons.lang3.ClassUtils;
|
|||
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;
|
||||
|
@ -222,6 +223,45 @@ public class FieldUtils {
|
|||
return allFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
@ -166,6 +168,59 @@ public class FieldUtilsTest {
|
|||
assertEquals(5, FieldUtils.getAllFieldsList(PublicChild.class).size());
|
||||
}
|
||||
|
||||
@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"));
|
||||
|
@ -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
|
||||
|
|
|
@ -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.NumberUtils;
|
|||
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) {
|
||||
|
|
|
@ -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 {
|
||||
}
|
Loading…
Reference in New Issue