Skip to content
Snippets Groups Projects
Commit d3b408fe authored by ribeaudc's avatar ribeaudc
Browse files

change: - Annotation 'Mandatory' renamed to 'BeanProperty'.

SVN: 4615
parent 46a37708
No related branches found
No related tags found
No related merge requests found
......@@ -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;
}
......@@ -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();
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment