From d3b408fe0fa9bb10776ebbe94ecac47572cad7d2 Mon Sep 17 00:00:00 2001 From: ribeaudc <ribeaudc> Date: Sat, 1 Mar 2008 02:24:56 +0000 Subject: [PATCH] change: - Annotation 'Mandatory' renamed to 'BeanProperty'. SVN: 4615 --- .../{Mandatory.java => BeanProperty.java} | 18 +++++-- .../parser/AbstractParserObjectFactory.java | 21 +++++++- .../cisd/common/utilities/ClassUtils.java | 48 +++++-------------- .../AbstractParserObjectFactoryTest.java | 4 +- .../cisd/common/utilities/ClassUtilsTest.java | 39 +++++++++++++++ 5 files changed, 85 insertions(+), 45 deletions(-) rename common/source/java/ch/systemsx/cisd/common/annotation/{Mandatory.java => BeanProperty.java} (69%) diff --git a/common/source/java/ch/systemsx/cisd/common/annotation/Mandatory.java b/common/source/java/ch/systemsx/cisd/common/annotation/BeanProperty.java similarity index 69% rename from common/source/java/ch/systemsx/cisd/common/annotation/Mandatory.java rename to common/source/java/ch/systemsx/cisd/common/annotation/BeanProperty.java index 0cbeaf0d3cd..fb33ba2cb22 100644 --- a/common/source/java/ch/systemsx/cisd/common/annotation/Mandatory.java +++ b/common/source/java/ch/systemsx/cisd/common/annotation/BeanProperty.java @@ -17,20 +17,28 @@ package ch.systemsx.cisd.common.annotation; import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Marks a field (typically a JavaBean field) as being 'mandatory'. + * Marks a field that will be set via the parser. + * <p> + * By default, each property annotated with <code>BeanProperty</code> is mandatory. + * </p> * + * @see ch.systemsx.cisd.common.parser * @author Christian Ribeaud */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) -@Inherited -public @interface Mandatory +public @interface BeanProperty { - + /** + * Whether this bean property is optional or not. + * <p> + * Default is <code>false</code>. + * </p> + */ + public boolean optional() default false; } diff --git a/common/source/java/ch/systemsx/cisd/common/parser/AbstractParserObjectFactory.java b/common/source/java/ch/systemsx/cisd/common/parser/AbstractParserObjectFactory.java index fbe1a80ba6c..ab3c52f09ff 100644 --- a/common/source/java/ch/systemsx/cisd/common/parser/AbstractParserObjectFactory.java +++ b/common/source/java/ch/systemsx/cisd/common/parser/AbstractParserObjectFactory.java @@ -17,12 +17,16 @@ package ch.systemsx.cisd.common.parser; import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.HashSet; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; +import ch.systemsx.cisd.common.annotation.BeanProperty; import ch.systemsx.cisd.common.converter.Converter; import ch.systemsx.cisd.common.converter.ConverterPool; import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel; @@ -59,13 +63,28 @@ public abstract class AbstractParserObjectFactory<E> implements IParserObjectFac assert beanClass != null : "Given bean class can not be null."; assert propertyMapper != null : "Given property mapper can not be null."; propertyDescriptors = BeanUtils.getPropertyDescriptors(beanClass); - mandatoryFields = ClassUtils.getMandatoryFields(beanClass, true); + mandatoryFields = createMandatoryFields(beanClass); checkPropertyMapper(beanClass, propertyMapper); this.propertyMapper = propertyMapper; converterPool = createConverterPool(); this.beanClass = beanClass; } + private final static Set<String> createMandatoryFields(final Class<?> beanClass) + { + final List<Field> annotatedFields = ClassUtils.getAnnotatedFieldList(beanClass, BeanProperty.class); + final Set<String> mandatoryFields = new HashSet<String>(); + for (final Field field : annotatedFields) + { + final BeanProperty annotation = field.getAnnotation(BeanProperty.class); + if (annotation.optional() == false) + { + mandatoryFields.add(field.getName().toLowerCase()); + } + } + return mandatoryFields; + } + private final static ConverterPool createConverterPool() { return new ConverterPool(); 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 df1facee4ed..a79a5bdaf4e 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java @@ -22,13 +22,11 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.apache.commons.lang.StringUtils; -import ch.systemsx.cisd.common.annotation.Mandatory; +import ch.systemsx.cisd.common.annotation.BeanProperty; import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel; /** @@ -44,47 +42,23 @@ public final class ClassUtils } /** - * For given <code>Class</code> returns a set of field names that are annotated with {@link Mandatory}. - * <p> - * Never returns <code>null</code> but could return an empty set. - * </p> - * - * @param clazz The class to return the mandatory fields for. - * @param convertToLowerCase If <code>true</code>, all field names are converted to lower case in the set - * returned. - */ - public final static Set<String> getMandatoryFields(final Class<?> clazz, final boolean convertToLowerCase) - { - final Set<String> set = new HashSet<String>(); - final List<Field> fields = ClassUtils.getMandatoryFieldsList(clazz); - for (final Field field : fields) - { - if (convertToLowerCase) - { - set.add(field.getName().toLowerCase()); - } else - { - set.add(field.getName()); - } - } - return set; - } - - /** - * For given <code>Class</code> returns a list of fields that are annotated with {@link Mandatory}. + * For given <code>Class</code> returns a list of fields that are annotated with given <var>annotationClass</var>. */ - private final static List<Field> getMandatoryFieldsList(final Class<?> clazz) + public final static List<Field> getAnnotatedFieldList(final Class<?> clazz, final Class<?> annotationClass) { - return getMandatoryFields(clazz, null); + return getAnnotatedFieldList(clazz, annotationClass, null); } /** - * For given <code>Class</code> returns a list of fields that are annotated with {@link Mandatory}. + * For given <code>Class</code> returns a list of fields that are annotated with {@link BeanProperty}. * * @param fields if <code>null</code>, then a new <code>List</code> is created. */ - private final static List<Field> getMandatoryFields(final Class<?> clazz, final List<Field> fields) + private final static List<Field> getAnnotatedFieldList(final Class<?> clazz, final Class<?> annotationClass, + final List<Field> fields) { + assert clazz != null : "Unspecified class."; + assert annotationClass != null && annotationClass.isAnnotation() : "Unspecified or not an annotation class."; List<Field> list = fields; if (list == null) { @@ -92,7 +66,7 @@ public final class ClassUtils } for (final Field field : clazz.getDeclaredFields()) { - if (field.getAnnotation(Mandatory.class) != null) + if (field.getAnnotation(BeanProperty.class) != null) { list.add(field); } @@ -100,7 +74,7 @@ public final class ClassUtils final Class<?> superclass = clazz.getSuperclass(); if (superclass != null) { - return getMandatoryFields(superclass, list); + return getAnnotatedFieldList(superclass, annotationClass, list); } return list; } diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/parser/AbstractParserObjectFactoryTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/parser/AbstractParserObjectFactoryTest.java index d0196406ce4..f2e139487fd 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/parser/AbstractParserObjectFactoryTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/parser/AbstractParserObjectFactoryTest.java @@ -22,7 +22,7 @@ import static org.testng.AssertJUnit.fail; import org.apache.commons.lang.ArrayUtils; import org.testng.annotations.Test; -import ch.systemsx.cisd.common.annotation.Mandatory; +import ch.systemsx.cisd.common.annotation.BeanProperty; /** * Test cases for corresponding {@link AbstractParserObjectFactory} class. @@ -150,7 +150,7 @@ public final class AbstractParserObjectFactoryTest public final static class Bean { - @Mandatory + @BeanProperty private String nAme; private String description; 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 44ca0f90ef5..6caf2b14dd1 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java @@ -25,12 +25,15 @@ import static org.testng.AssertJUnit.assertTrue; import static org.testng.AssertJUnit.fail; import java.io.IOException; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.testng.annotations.Test; +import ch.systemsx.cisd.common.annotation.BeanProperty; + /** * Test cases for the {@link ClassUtils} class. * @@ -177,6 +180,22 @@ public final class ClassUtilsTest assertSame(object, myExtendedClass.finalObject); } + @Test + public final void testGetAnnotatedFieldList() + { + try + { + ClassUtils.getAnnotatedFieldList(A.class, String.class); + fail("Not an annotation class."); + } catch (final AssertionError e) + { + } + List<Field> fields = ClassUtils.getAnnotatedFieldList(A.class, BeanProperty.class); + assertEquals(1, fields.size()); + fields = ClassUtils.getAnnotatedFieldList(B.class, BeanProperty.class); + assertEquals(2, fields.size()); + } + // // Helper Classes // @@ -234,4 +253,24 @@ public final class ClassUtilsTest } } + + private static class A + { + + @BeanProperty + Object a; + + Object b; + + } + + private final static class B extends A + { + + @SuppressWarnings("hiding") + @BeanProperty + Object a; + + Object c; + } } -- GitLab