diff --git a/common/source/java/ch/systemsx/cisd/common/annotation/Mandatory.java b/common/source/java/ch/systemsx/cisd/common/annotation/Mandatory.java index 0cbeaf0d3cd5b2874bd488a64b05d4fdfb453155..286a9b7a8bf56e568f32a1ec1365deac475b147f 100644 --- a/common/source/java/ch/systemsx/cisd/common/annotation/Mandatory.java +++ b/common/source/java/ch/systemsx/cisd/common/annotation/Mandatory.java @@ -28,9 +28,9 @@ import java.lang.annotation.Target; * @author Christian Ribeaud */ @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) +@Target(ElementType.TYPE) @Inherited public @interface Mandatory { - + public String[] value(); } diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java b/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java index 52c49a45bed355d9e0c93f45d68c9d4a3a5c968c..3d152769a6258c0708b496cc826d837836bb0ae6 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java @@ -24,6 +24,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.apache.commons.lang.ArrayUtils; + import ch.systemsx.cisd.common.annotation.Mandatory; import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel; @@ -41,10 +43,21 @@ public final class ClassUtils /** * For given <code>Class</code> returns a list of fields that are annotated with {@link Mandatory}. + */ + public final static List<Field> getMandatoryFields(Class<?> clazz) + { + final Mandatory mandatory = clazz.getAnnotation(Mandatory.class); + return getFields(clazz, null, mandatory == null ? null : mandatory.value()); + } + + /** + * For given <code>Class</code> (and eventually its superclasses) return a list of <code>Field</code> objects + * that matches the ones defined in <code>strFields</code>. * * @param fields if <code>null</code>, then a new <code>List</code> is created. + * @return never <code>null</code> but could return an empty <code>List</code>. */ - public final static List<Field> getMandatoryFields(Class clazz, List<Field> fields) + public final static List<Field> getFields(Class<?> clazz, List<Field> fields, String... strFields) { List<Field> list = fields; if (list == null) @@ -53,7 +66,7 @@ public final class ClassUtils } for (Field field : clazz.getDeclaredFields()) { - if (field.getAnnotation(Mandatory.class) != null) + if (ArrayUtils.indexOf(strFields, field.getName()) > -1) { list.add(field); } @@ -61,7 +74,7 @@ public final class ClassUtils Class superclass = clazz.getSuperclass(); if (superclass != null) { - return getMandatoryFields(superclass, list); + return getFields(superclass, list, strFields); } return list; } diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java index ebaa9f1cd0662aaebbbc83a31cbfc54ec8f7d054..a36999f2b7161efb251468f4645829ed81ac67ee 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java @@ -16,10 +16,15 @@ package ch.systemsx.cisd.common.utilities; -import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.*; + +import java.lang.reflect.Field; +import java.util.List; import org.testng.annotations.Test; +import ch.systemsx.cisd.common.annotation.Mandatory; + /** * Test cases for the {@link ClassUtils} class. * @@ -28,17 +33,50 @@ import org.testng.annotations.Test; public final class ClassUtilsTest { - /** - * Test method for {@link ch.systemsx.cisd.common.utilities.ClassUtils#getCurrentMethod()}. - */ @Test public final void testGetCurrentMethod() { assertEquals("testGetCurrentMethod", ClassUtils.getCurrentMethod().getName()); // Border cases - assertEquals(new SameMethodName().getMethodName(), new SameMethodName().getMethodName(new Object(), new Object())); + assertEquals(new SameMethodName().getMethodName(), new SameMethodName().getMethodName(new Object(), + new Object())); + } + + @Test + public final void testGetFields() + { + List<Field> fields = ClassUtils.getFields(A.class, null, "otherField"); + assertNotNull(fields); + assert fields.size() == 0; + // A + fields = ClassUtils.getFields(A.class, null, "someField"); + assertNotNull(fields); + assert fields.size() == 1; + // B + fields = ClassUtils.getFields(B.class, null, "someField"); + assertNotNull(fields); + assert fields.size() == 1; + // C + fields = ClassUtils.getFields(C.class, null, "someField"); + assertNotNull(fields); + assert fields.size() == 1; } + @Test + public final void testGetMandatoryFields() + { + List<Field> fields = ClassUtils.getMandatoryFields(A.class); + assertNotNull(fields); + assert fields.size() == 0; + fields = ClassUtils.getMandatoryFields(C.class); + assertNotNull(fields); + assert fields.size() == 2; + } + + // + // Helper classes + // + private final static class SameMethodName { @@ -55,4 +93,24 @@ public final class ClassUtilsTest } } + @SuppressWarnings("unused") + private static class A + { + private Object someField; + + private Object mandatoryField; + } + + private static class B extends A + { + + } + + @Mandatory( + { "mandatoryField", "otherMandatoryField", "notPresentField" }) + private final static class C extends B + { + @SuppressWarnings("unused") + private Object otherMandatoryField; + } }