diff --git a/common/source/java/ch/systemsx/cisd/common/annotation/BeanNameMapping.java b/common/source/java/ch/systemsx/cisd/common/annotation/BeanNameMapping.java
new file mode 100644
index 0000000000000000000000000000000000000000..c31459ab9c5a7dcd286e3f5ae5a3fc0c46a82505
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/annotation/BeanNameMapping.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2007 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+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;
+
+/**
+ * An annotation that allows to override the name mapping of beans, i.e. that a setter requires a getter on the source
+ * bean with same name.
+ * 
+ * @author Bernd Rinn
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Inherited
+public @interface BeanNameMapping
+{
+
+    /**
+     * The names to look for among the getters instead of the setter name.
+     */
+    String[] names();
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/annotation/CollectionMapping.java b/common/source/java/ch/systemsx/cisd/common/annotation/CollectionMapping.java
new file mode 100644
index 0000000000000000000000000000000000000000..1792e6091f5a08e672943bed80564a57d7db0669
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/annotation/CollectionMapping.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2007 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+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;
+import java.util.Collection;
+
+/**
+ * An annotation that defines the type of collection and the type of elements to use when creating the collection in a
+ * bean context.
+ * 
+ * @author Bernd Rinn
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Inherited
+public @interface CollectionMapping
+{
+    /**
+     * The concrete class to use as a collection.
+     */
+    Class<? extends Collection> collectionClass();
+
+    /**
+     * The class to use as the elements of the collection (since the generics type isn't known at run time).
+     */
+    Class<?> elementClass();
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/BeanUtils.java b/common/source/java/ch/systemsx/cisd/common/utilities/BeanUtils.java
index 583c71a2b8758b72e3cc697df0e320f3631a4eea..b9e2e8002fd88b6cadb374e2b3740290dcec1e03 100644
--- a/common/source/java/ch/systemsx/cisd/common/utilities/BeanUtils.java
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/BeanUtils.java
@@ -22,11 +22,32 @@ import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+
+import ch.systemsx.cisd.common.annotation.BeanNameMapping;
+import ch.systemsx.cisd.common.annotation.CollectionMapping;
+import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel;
 
 /**
  * Some utilities around <i>Java Bean</i>s.
  * 
  * @author Christian Ribeaud
+ * @author Bernd Rinn
  */
 public final class BeanUtils
 {
@@ -68,4 +89,632 @@ public final class BeanUtils
         encoder.close();
         return result;
     }
+
+    /**
+     * Checks the list of bean objects item by item for public getters which return <code>null</code> or 0.
+     * 
+     * @param beanListToCheck The list of beans to check. Can be <code>null</code>.
+     * @return <var>beanListToCheck</var> (the parameter itself)
+     * @see #checkGettersNotNull(Object)
+     * @throws IllegalStateException If at least one of the public getters returns <code>null</code> or 0.
+     */
+    public final static <T> List<T> checkGettersNotNull(List<T> beanListToCheck)
+    {
+        if (beanListToCheck == null)
+        {
+            return beanListToCheck;
+        }
+        for (Object bean : beanListToCheck)
+        {
+            checkGettersNotNull(bean);
+        }
+        return beanListToCheck;
+    }
+
+    /**
+     * Checks bean object for public getters which return <code>null</code> or 0.
+     * 
+     * @param beanToCheck The bean to check. Can be <code>null</code>. Must not be an array type.
+     * @return <var>beanToCheck</var> (the parameter itself)
+     * @throws IllegalArgumentException If the <var>beanToCheck</var> is an array type.
+     * @throws IllegalStateException If at least one of the public getters returns <code>null</code> or 0.
+     */
+    public final static <T> T checkGettersNotNull(T beanToCheck)
+    {
+        if (beanToCheck == null)
+        {
+            return beanToCheck;
+        }
+        if (beanToCheck.getClass().isArray())
+        {
+            throw new IllegalArgumentException("Arrays are not supported.");
+        }
+        for (Method method : beanToCheck.getClass().getMethods())
+        {
+            if (method.getName().startsWith("get") && method.getParameterTypes().length == 0
+                    && Modifier.isPublic(method.getModifiers()))
+            {
+                try
+                {
+                    final Object result = method.invoke(beanToCheck, new Object[0]);
+                    if (result == null)
+                    {
+                        throw new IllegalStateException("Method '" + method.getName() + "' returns null.");
+                    } else if (isNull(result))
+                    {
+                        throw new IllegalStateException("Method '" + method.getName() + "' returns 0.");
+                    }
+                } catch (InvocationTargetException ex)
+                {
+                    final Throwable cause = ex.getCause();
+                    if (cause instanceof Error)
+                    {
+                        throw (Error) cause;
+                    }
+                    throw CheckedExceptionTunnel.wrapIfNecessary((Exception) cause);
+                } catch (IllegalAccessException ex)
+                {
+                    // Can't happen since we checked for isPublic()
+                    throw new Error("Cannot call method '" + method.getName() + "'.");
+                }
+            }
+        }
+        return beanToCheck;
+    }
+
+    private static boolean isNull(Object objectToCheck)
+    {
+        return (objectToCheck instanceof Number) && ((Number) objectToCheck).longValue() == 0;
+    }
+
+    /**
+     * A map that provides annotations for given annotation classes.
+     */
+    public interface AnnotationMap
+    {
+        /**
+         * Returns the name of the entity that this annotation stems from.
+         */
+        public String getAnnotatedEntity();
+
+        /**
+         * Returns the annotation for <var>annotationClazz</var>.
+         */
+        public <T extends Annotation> T getAnnotation(Class<T> annotationClazz);
+    }
+
+    /**
+     * An empty {@link AnnotationMap} (to be used when there are no annotations).
+     */
+    private static class EmptyAnnotationMap implements AnnotationMap
+    {
+
+        public String getAnnotatedEntity()
+        {
+            return "GENERIC";
+        }
+
+        public <T extends Annotation> T getAnnotation(Class<T> annotationClazz)
+        {
+            return null;
+        }
+
+    }
+
+    /**
+     * An {@link AnnotationMap} that gets its annotation from a (setter) method.
+     */
+    private static class SetterAnnotationMap implements AnnotationMap
+    {
+
+        private final Method setterMethod;
+
+        SetterAnnotationMap(Method setterMethod)
+        {
+            assert setterMethod != null;
+
+            this.setterMethod = setterMethod;
+        }
+
+        public String getAnnotatedEntity()
+        {
+            return setterMethod.toGenericString();
+        }
+
+        public <T extends Annotation> T getAnnotation(Class<T> annotationClazz)
+        {
+            return setterMethod.getAnnotation(annotationClazz);
+        }
+
+    }
+
+    /**
+     * Marker interface for converter classes. The real method are determined via reflection. A converter needs to match
+     * both the source and the destination bean. If the destination bean has a setter <code>setFoo(FooClass foo)</code>
+     * and the converter has a method <code>FooClass convertToFoo(SourceBeanClass sourceBean)</code>, then this will
+     * be called instead of any getter of the <var>sourceBean</var>. Note that if there is a matching method
+     * <code>convertToFoo()</code>, it needs to have an appropriate return type or else an
+     * {@link IllegalArgumentException} will be thrown.
+     */
+    public interface Converter
+    {
+    }
+
+    private static final AnnotationMap emptyAnnotationMap = new EmptyAnnotationMap();
+
+    private static final Converter nullConverter = new Converter()
+        {
+        };
+
+    @SuppressWarnings("unchecked")
+    private static final Set<Class> immutableTypes =
+            new HashSet<Class>(Arrays.asList(boolean.class, Boolean.class, byte.class, Byte.class, short.class,
+                    Short.class, int.class, Integer.class, long.class, Long.class, float.class, Float.class,
+                    double.class, Double.class, String.class, Date.class));
+
+    /**
+     * Creates a new bean of type <var>beanClass</var> and fills it with values from <var>sourceBean</var>.
+     */
+    public static <T> T fillBean(Class<T> beanClass, Object sourceBean)
+    {
+        return fillBean(beanClass, sourceBean, emptyAnnotationMap, nullConverter);
+    }
+
+    /**
+     * Creates a new bean of type <var>beanClass</var> and fills it with values from <var>sourceBean</var>, using the
+     * <var>converter</var> where appropriate.
+     */
+    public static <T> T fillBean(Class<T> beanClass, Object sourceBean, Converter converter)
+    {
+        return fillBean(beanClass, sourceBean, emptyAnnotationMap, converter);
+    }
+
+    /**
+     * Creates a new bean of type <var>beanClass</var> and fills it with values from <var>beanToFill</var>.
+     * 
+     * @param beanClass The class to create a new instance from.
+     * @param sourceBean The bean to get the values from.
+     * @param setterAnnotations The annotations attached to the setter that can be used to determine how the result
+     *            should be created.
+     */
+    private static <T> T fillBean(Class<T> beanClass, Object sourceBean, AnnotationMap setterAnnotations,
+            Converter converter)
+    {
+        assert beanClass != null;
+        assert sourceBean != null;
+        assert setterAnnotations != null;
+        assert converter != null;
+
+        try
+        {
+            final T destinationBean = instantiateBean(beanClass, sourceBean, setterAnnotations);
+            if (isArray(destinationBean))
+            {
+                if (isArray(sourceBean))
+                {
+                    copyArrayToArray(destinationBean, sourceBean, converter);
+                } else if (isCollection(sourceBean))
+                {
+                    copyCollectionToArray(destinationBean, (Collection) sourceBean, converter);
+                }
+            } else if (isCollection(destinationBean))
+            {
+                if (isArray(sourceBean))
+                {
+                    copyArrayToCollection((Collection) destinationBean, sourceBean, setterAnnotations, converter);
+                } else if (isCollection(sourceBean))
+                {
+                    copyCollectionToCollection((Collection) destinationBean, (Collection) sourceBean,
+                            setterAnnotations, converter);
+                }
+            } else
+            {
+                copyBean(destinationBean, sourceBean, converter);
+            }
+            return destinationBean;
+        } catch (InvocationTargetException ex)
+        {
+            final Throwable cause = ex.getCause();
+            if (cause instanceof Error)
+            {
+                throw (Error) cause;
+            }
+            throw CheckedExceptionTunnel.wrapIfNecessary((Exception) cause);
+        } catch (Exception ex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+        }
+    }
+
+    private static boolean isCollection(Object o)
+    {
+        return o instanceof Collection<?>;
+    }
+
+    private static boolean isCollection(Class<?> clazz)
+    {
+        return Collection.class.isAssignableFrom(clazz);
+    }
+
+    private static boolean isArray(Object o)
+    {
+        return o.getClass().isArray();
+    }
+
+    private static boolean isArray(final Class<?> clazz)
+    {
+        return clazz.isArray();
+    }
+
+    private static <T> T instantiateBean(Class<T> beanClass, Object sourceBean, AnnotationMap setterAnnotations)
+            throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
+    {
+        if (sourceBean == null)
+        {
+            return null;
+        }
+        final boolean beanIsArray = isArray(beanClass);
+        final boolean beanIsCollection = isCollection(beanClass);
+        if (beanIsArray || beanIsCollection)
+        {
+            final Integer size = getSize(sourceBean);
+            if (size == null)
+            {
+                return null;
+            }
+            if (beanIsArray)
+            {
+                return createArray(beanClass, size);
+            }
+            if (beanIsCollection)
+            {
+                return createCollection(beanClass, size, setterAnnotations);
+            }
+        }
+        return beanClass.newInstance();
+    }
+
+    private static Integer getSize(Object o)
+    {
+        if (isArray(o))
+        {
+            return Array.getLength(o);
+        } else if (isCollection(o))
+        {
+            return ((Collection) o).size();
+        } else
+        { // Don't know how to get the size of o.
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> T createArray(Class<T> beanClass, int length) throws NegativeArraySizeException
+    {
+        return (T) Array.newInstance(beanClass.getComponentType(), length);
+    }
+
+    private static <T> T createCollection(Class<T> beanClass, int size, AnnotationMap setterAnnotations)
+            throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException,
+            IllegalArgumentException, InvocationTargetException
+    {
+        final CollectionMapping mapping = setterAnnotations.getAnnotation(CollectionMapping.class);
+        if (mapping == null)
+        {
+            throw new IllegalArgumentException("No collection mapping specified for '"
+                    + setterAnnotations.getAnnotatedEntity() + "'.");
+        }
+        try
+        {
+            final Constructor<? extends Collection> constructorWithSize =
+                    mapping.collectionClass().getConstructor(new Class[]
+                        { int.class });
+            return constructCollection(constructorWithSize, size);
+        } catch (NoSuchMethodException ex)
+        { // Happens e.g. for a LinkedList
+            return constructCollection(mapping.collectionClass());
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> T constructCollection(final Constructor<? extends Collection> constructorWithSize, int size)
+            throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
+    {
+        // This conversion _can_ go wrong if the concrete collection class doesn't implement the right sub-interface of
+        // collection, e.g. when using a HashSet as concrete collection class where a List is required.
+        return (T) constructorWithSize.newInstance(new Object[]
+            { size });
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> T constructCollection(final Class<? extends Collection> collectionClazz)
+            throws InstantiationException, IllegalAccessException
+    {
+        // This conversion _can_ go wrong if the concrete collection class doesn't implement the right sub-interface of
+        // collection, e.g. when using a HashSet as concrete collection class where a List is required.
+        return (T) collectionClazz.newInstance();
+    }
+
+    private static void copyArrayToArray(Object destination, Object source, Converter converter)
+            throws IllegalAccessException, InvocationTargetException
+    {
+        if (destination == null)
+        {
+            return;
+        }
+        final Class<?> componentType = destination.getClass().getComponentType();
+        final int length = Array.getLength(destination);
+        if (immutableTypes.contains(componentType))
+        {
+            if (componentType == source.getClass().getComponentType())
+            {
+                System.arraycopy(source, 0, destination, 0, length);
+            } else
+            {
+                for (int index = 0; index < length; ++index)
+                {
+                    final Object sourceElement = Array.get(source, index);
+                    Array.set(destination, index, sourceElement);
+                }
+            }
+        } else
+        {
+            for (int index = 0; index < length; ++index)
+            {
+                final Object sourceElement = Array.get(source, index);
+                final Object destinationElement = fillBean(componentType, sourceElement, converter);
+                Array.set(destination, index, destinationElement);
+            }
+        }
+    }
+
+    private static void copyCollectionToArray(Object destination, Collection source, Converter converter)
+            throws IllegalAccessException, InvocationTargetException
+    {
+        if (destination == null)
+        {
+            return;
+        }
+        assert Array.getLength(destination) == source.size();
+        final Class<?> componentType = destination.getClass().getComponentType();
+        if (immutableTypes.contains(componentType))
+        {
+            int index = 0;
+            for (Object sourceElement : source)
+            {
+                Array.set(destination, index++, sourceElement);
+            }
+        } else
+        {
+            int index = 0;
+            for (Object sourceElement : source)
+            {
+                final Object destinationElement = fillBean(componentType, sourceElement, converter);
+                Array.set(destination, index++, destinationElement);
+            }
+        }
+    }
+
+    private static void copyArrayToCollection(Collection destination, Object source, AnnotationMap setterAnnotations,
+            Converter converter)
+    {
+        if (destination == null)
+        {
+            return;
+        }
+        final Class<?> componentType = getCollectionComponentType(setterAnnotations);
+        final int length = getSize(source);
+        if (immutableTypes.contains(componentType))
+        {
+            for (int index = 0; index < length; ++index)
+            {
+                final Object sourceElement = Array.get(source, index);
+                addToUntypedCollection(destination, sourceElement);
+            }
+        } else
+        {
+            for (int index = 0; index < length; ++index)
+            {
+                final Object sourceElement = Array.get(source, index);
+                final Object destinationElement = fillBean(componentType, sourceElement, converter);
+                addToUntypedCollection(destination, destinationElement);
+            }
+        }
+    }
+
+    private static void copyCollectionToCollection(Collection destination, Collection source,
+            AnnotationMap setterAnnotations, Converter converter)
+    {
+        if (destination == null)
+        {
+            return;
+        }
+        final Class<?> componentType = getCollectionComponentType(setterAnnotations);
+        if (immutableTypes.contains(componentType))
+        {
+            for (Object sourceElement : source)
+            {
+                addToUntypedCollection(destination, sourceElement);
+            }
+        } else
+        {
+            for (Object sourceElement : source)
+            {
+                final Object destinationElement = fillBean(componentType, sourceElement, converter);
+                addToUntypedCollection(destination, destinationElement);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void addToUntypedCollection(Collection destination, Object element)
+    {
+        destination.add(element);
+    }
+
+    private static Class<?> getCollectionComponentType(AnnotationMap setterAnnotations)
+    {
+        final CollectionMapping mapping = setterAnnotations.getAnnotation(CollectionMapping.class);
+        if (mapping == null)
+        {
+            throw new IllegalArgumentException("No collection mapping specified for '"
+                    + setterAnnotations.getAnnotatedEntity() + "'.");
+        }
+        return mapping.elementClass();
+    }
+
+    private static void copyBean(Object destination, Object source, Converter converter) throws IllegalAccessException,
+            InvocationTargetException
+    {
+        if (destination == null)
+        {
+            return;
+        }
+        final Collection<Method> destinationSetters = scanForPublicMethods(destination, "set", 1).values();
+        final Map<String, Method> sourceGetters = scanForPublicMethods(source, "get", 0);
+        scanForPublicMethods(source, sourceGetters, "is", 0, boolean.class, Boolean.class);
+        for (Method setter : destinationSetters)
+        {
+            final Object newBean = emergeNewBean(setter, source, sourceGetters, converter);
+            if (newBean != null)
+            {
+                try
+                {
+                    setter.invoke(destination, new Object[]
+                        { newBean });
+                } catch (IllegalArgumentException ex)
+                {
+                    final String defaultJavaArgumentTypeMismatchMessage = "argument type mismatch";
+                    if (defaultJavaArgumentTypeMismatchMessage.equals(ex.getMessage()))
+                    {
+                        throw new IllegalArgumentException(defaultJavaArgumentTypeMismatchMessage + ": method '"
+                                + setter.toGenericString() + "': cannot assign from '"
+                                + newBean.getClass().getCanonicalName() + "'.");
+                    } else
+                    {
+                        throw ex;
+                    }
+                }
+            }
+        }
+    }
+
+    private static Object emergeNewBean(Method setter, Object source, Map<String, Method> sourceGetters,
+            Converter converter) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        final AnnotationMap annotationMap = new SetterAnnotationMap(setter);
+        final Method converterMethod = getConverterMethod(setter, source, converter);
+        if (converterMethod != null)
+        {
+            return converterMethod.invoke(converter, new Object[]
+                { source });
+        }
+        final Method getter = getGetter(setter, sourceGetters, annotationMap);
+        if (getter == null)
+        {
+            return null;
+        }
+        final Object oldBean = getter.invoke(source, new Object[0]);
+        final Class<?> parameterType = setter.getParameterTypes()[0];
+        if (parameterType.isPrimitive() || immutableTypes.contains(parameterType))
+        {
+            return oldBean;
+        } else
+        {
+            return fillBean(parameterType, oldBean, annotationMap, converter);
+        }
+    }
+
+    private static Method getConverterMethod(Method setter, Object sourceBean, Converter converter)
+    {
+        if (converter != nullConverter)
+        {
+            try
+            {
+                final Method converterMethod =
+                        converter.getClass().getMethod("convertTo" + setter.getName().substring("set".length()),
+                                new Class[]
+                                    { sourceBean.getClass() });
+                if (converterMethod.isAccessible() == false)
+                {
+                    converterMethod.setAccessible(true);
+                }
+                return converterMethod;
+            } catch (NoSuchMethodException ex)
+            {
+                // Nothing to do here - there just isn't any converter method for this setter.
+            }
+        }
+        return null;
+    }
+
+    private static Method getGetter(Method setter, Map<String, Method> sourceGetters, AnnotationMap annotationMap)
+    {
+        final BeanNameMapping mapping = annotationMap.getAnnotation(BeanNameMapping.class);
+        if (mapping != null)
+        {
+            return getGetter(sourceGetters, getGetterPrefix(setter), mapping.names());
+        }
+        final String getterName = getGetterPrefix(setter) + setter.getName().substring("set".length());
+        final Method getter = sourceGetters.get(getterName);
+        return getter;
+    }
+
+    private static Method getGetter(Map<String, Method> sourceGetters, String prefix, String... attributeNames)
+    {
+        for (String attributeName : attributeNames)
+        {
+            final String getterName = prefix + StringUtils.capitalize(attributeName);
+            final Method getter = sourceGetters.get(getterName);
+            if (getter != null)
+            {
+                return getter;
+            }
+        }
+        return null;
+    }
+
+    private static String getGetterPrefix(final Method setter)
+    {
+        final Class<?> type = setter.getParameterTypes()[0];
+        if (type == boolean.class || type == Boolean.class)
+        {
+            return "is";
+        } else
+        {
+            return "get";
+        }
+    }
+
+    private static Map<String, Method> scanForPublicMethods(Object bean, String prefix, int numberOfParameters)
+    {
+        final Map<String, Method> methodMap = new HashMap<String, Method>();
+        scanForPublicMethods(bean, methodMap, prefix, numberOfParameters, (Set<Class<?>>) null);
+        return methodMap;
+    }
+
+    private static void scanForPublicMethods(Object bean, Map<String, Method> methodMap, String prefix,
+            int numberOfParameters, Class<?>... returnValueTypes)
+    {
+        scanForPublicMethods(bean, methodMap, prefix, numberOfParameters, new HashSet<Class<?>>(Arrays
+                .asList(returnValueTypes)));
+    }
+
+    private static void scanForPublicMethods(Object bean, Map<String, Method> methodMap, String prefix,
+            int numberOfParameters, Set<Class<?>> returnValueTypes)
+    {
+        for (Method method : bean.getClass().getMethods())
+        {
+            final String methodName = method.getName();
+            if (methodName.startsWith(prefix) && method.getParameterTypes().length == numberOfParameters
+                    && Modifier.isPublic(method.getModifiers()))
+            {
+                if (returnValueTypes == null || returnValueTypes.contains(method.getReturnType()))
+                {
+                    methodMap.put(methodName, method);
+                }
+            }
+        }
+    }
+
 }
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 1dc886c0e430bda91f7811a3701053236298e9dd..52c49a45bed355d9e0c93f45d68c9d4a3a5c968c 100644
--- a/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java
@@ -18,9 +18,7 @@ package ch.systemsx.cisd.common.utilities;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -186,81 +184,4 @@ public final class ClassUtils
                 .size()]), new ProxyingInvocationHandler(objectToProxy));
     }
 
-    private static boolean isNull(Object objectToCheck)
-    {
-        return (objectToCheck instanceof Number) && ((Number) objectToCheck).longValue() == 0;
-    }
-
-    /**
-     * Checks the list of bean objects item by item for public getters which return <code>null</code> or 0.
-     * 
-     * @param beanListToCheck The list of beans to check. Can be <code>null</code>.
-     * @return <var>beanListToCheck</var> (the parameter itself)
-     * @see #checkGettersNotNull(Object)
-     * @throws IllegalStateException If at least one of the public getters returns <code>null</code> or 0.
-     */
-    public final static <T> List<T> checkGettersNotNull(List<T> beanListToCheck)
-    {
-        if (beanListToCheck == null)
-        {
-            return beanListToCheck;
-        }
-        for (Object bean : beanListToCheck)
-        {
-            checkGettersNotNull(bean);
-        }
-        return beanListToCheck;
-    }
-
-    /**
-     * Checks bean object for public getters which return <code>null</code> or 0.
-     * 
-     * @param beanToCheck The bean to check. Can be <code>null</code>. Must not be an array type.
-     * @return <var>beanToCheck</var> (the parameter itself)
-     * @throws IllegalArgumentException If the <var>beanToCheck</var> is an array type.
-     * @throws IllegalStateException If at least one of the public getters returns <code>null</code> or 0.
-     */
-    public final static <T> T checkGettersNotNull(T beanToCheck)
-    {
-        if (beanToCheck == null)
-        {
-            return beanToCheck;
-        }
-        if (beanToCheck.getClass().isArray())
-        {
-            throw new IllegalArgumentException("Arrays are not supported.");
-        }
-        for (Method method : beanToCheck.getClass().getMethods())
-        {
-            if (method.getName().startsWith("get") && method.getParameterTypes().length == 0
-                    && Modifier.isPublic(method.getModifiers()))
-            {
-                try
-                {
-                    final Object result = method.invoke(beanToCheck, new Object[0]);
-                    if (result == null)
-                    {
-                        throw new IllegalStateException("Method '" + method.getName() + "' returns null.");
-                    } else if (isNull(result))
-                    {
-                        throw new IllegalStateException("Method '" + method.getName() + "' returns 0.");
-                    }
-                } catch (InvocationTargetException ex)
-                {
-                    final Throwable cause = ex.getCause();
-                    if (cause instanceof Error)
-                    {
-                        throw (Error) cause;
-                    }
-                    throw CheckedExceptionTunnel.wrapIfNecessary((Exception) cause);
-                } catch (IllegalAccessException ex)
-                {
-                    // Can't happen since we checked for isAccessible()
-                    throw new Error("Cannot call method '" + method.getName() + "'.");
-                }
-            }
-        }
-        return beanToCheck;
-    }
-
 }
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/BeanUtilsTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/BeanUtilsTest.java
index b2a2f7ee13c033abd5f0df5084bc83bd6ce8264d..a89f99c71adcb67cc23c671c68c31054a095274d 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/BeanUtilsTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/BeanUtilsTest.java
@@ -16,16 +16,30 @@
 
 package ch.systemsx.cisd.common.utilities;
 
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertNull;
+
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.List;
-import static org.testng.AssertJUnit.*;
 
+import org.apache.commons.lang.StringUtils;
+import org.testng.AssertJUnit;
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.common.annotation.BeanNameMapping;
+import ch.systemsx.cisd.common.annotation.CollectionMapping;
+
 /**
  * Test cases for the {@link BeanUtils} class.
  * 
  * @author Christian Ribeaud
+ * @author Bernd Rinn
  */
 public final class BeanUtilsTest
 {
@@ -48,8 +62,8 @@ public final class BeanUtilsTest
         String xml = BeanUtils.xmlEncode(list);
         List newList = (List) BeanUtils.xmlDecode(xml);
         assert newList.size() == 2;
-        assertEquals(((SimpleBean)newList.get(0)).getFirstName(), "Tanja");
-        assertEquals(((SimpleBean)newList.get(1)).getLastName(), "Ribeaud");
+        assertEquals(((SimpleBean) newList.get(0)).getFirstName(), "Tanja");
+        assertEquals(((SimpleBean) newList.get(1)).getLastName(), "Ribeaud");
     }
 
     // This MUST be public.
@@ -83,4 +97,896 @@ public final class BeanUtilsTest
             this.lastName = lastName;
         }
     }
+
+    private static class SimpleBean2
+    {
+        private final int number;
+
+        private final String string;
+
+        SimpleBean2(int number, String string)
+        {
+            this.number = number;
+            this.string = string;
+        }
+
+        public int getNumber()
+        {
+            return number;
+        }
+
+        public String getString()
+        {
+            return string;
+        }
+
+        String getIgnoreThisBecauseItIsNotPublic()
+        {
+            AssertJUnit.fail("Should be ignore because not public");
+            return null;
+        }
+    }
+
+    @Test
+    public void testCheckGettersForNullOK()
+    {
+        final SimpleBean2 bean = new SimpleBean2(1, "");
+        assert BeanUtils.checkGettersNotNull(bean) == bean;
+    }
+
+    @Test
+    public void testCheckGettersForNullOKNullBean()
+    {
+        assertNull(BeanUtils.checkGettersNotNull(null));
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testCheckGettersForNullStringNull()
+    {
+        final SimpleBean2 bean = new SimpleBean2(1, null);
+        BeanUtils.checkGettersNotNull(bean);
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testCheckGettersForNullInt0()
+    {
+        final SimpleBean2 bean = new SimpleBean2(0, "test");
+        BeanUtils.checkGettersNotNull(bean);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testCheckGettersForNullForbiddenArray()
+    {
+        BeanUtils.checkGettersNotNull(new Object[0]);
+    }
+
+    @Test
+    public void testCheckGettersForNullListOK()
+    {
+        final SimpleBean2 bean1 = new SimpleBean2(1, "test");
+        final SimpleBean2 bean2 = new SimpleBean2(5, "test2");
+        final List<SimpleBean2> beanList = Arrays.asList(bean1, bean2);
+        assert BeanUtils.checkGettersNotNull(beanList) == beanList;
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testCheckGettersForNullListInt0()
+    {
+        final SimpleBean2 bean1 = new SimpleBean2(1, "test");
+        final SimpleBean2 bean2 = new SimpleBean2(0, "test2");
+        BeanUtils.checkGettersNotNull(Arrays.asList(bean1, bean2));
+    }
+
+    public static class Bean1a
+    {
+        private int i;
+
+        private String s;
+
+        private boolean b;
+
+        private float f;
+
+        public boolean isB()
+        {
+            return b;
+        }
+
+        public void setB(boolean b)
+        {
+            this.b = b;
+        }
+
+        public float getF()
+        {
+            return f;
+        }
+
+        public void setF(float f)
+        {
+            this.f = f;
+        }
+
+        public int getI()
+        {
+            return i;
+        }
+
+        public void setI(int i)
+        {
+            this.i = i;
+        }
+
+        public String getS()
+        {
+            return s;
+        }
+
+        public void setS(String s)
+        {
+            this.s = s;
+        }
+    }
+
+    public static class Bean1b
+    {
+        private Integer i;
+
+        private String s;
+
+        private Boolean b;
+
+        private Float f;
+
+        public Boolean isB()
+        {
+            return b;
+        }
+
+        public void setB(Boolean b)
+        {
+            this.b = b;
+        }
+
+        public Float getF()
+        {
+            return f;
+        }
+
+        public void setF(Float f)
+        {
+            this.f = f;
+        }
+
+        public Integer getI()
+        {
+            return i;
+        }
+
+        public void setI(Integer i)
+        {
+            this.i = i;
+        }
+
+        public String getS()
+        {
+            return s;
+        }
+
+        public void setS(String s)
+        {
+            this.s = s;
+        }
+    }
+
+    public static class Bean2a
+    {
+        private int i;
+
+        private String s;
+
+        private boolean b;
+
+        private float f;
+
+        public boolean isB()
+        {
+            return b;
+        }
+
+        public void setB(boolean b)
+        {
+            this.b = b;
+        }
+
+        public float getF()
+        {
+            return f;
+        }
+
+        public void setF(float f)
+        {
+            this.f = f;
+        }
+
+        public int getI()
+        {
+            return i;
+        }
+
+        public void setI(int i)
+        {
+            this.i = i;
+        }
+
+        public String getS()
+        {
+            return s;
+        }
+
+        public void setS(String s)
+        {
+            this.s = s;
+        }
+    }
+
+    public static class Bean2b
+    {
+        private Integer i;
+
+        private String s;
+
+        private Boolean b;
+
+        private Float f;
+
+        public Boolean isB()
+        {
+            return b;
+        }
+
+        public void setB(Boolean b)
+        {
+            this.b = b;
+        }
+
+        public Float getF()
+        {
+            return f;
+        }
+
+        public void setF(Float f)
+        {
+            this.f = f;
+        }
+
+        public Integer getI()
+        {
+            return i;
+        }
+
+        public void setI(Integer i)
+        {
+            this.i = i;
+        }
+
+        public String getS()
+        {
+            return s;
+        }
+
+        public void setS(String s)
+        {
+            this.s = s;
+        }
+    }
+
+    @Test
+    public void testFillSimpleBean()
+    {
+        final Bean1a b1 = new Bean1a();
+        b1.setB(true);
+        b1.setF(0.2f);
+        b1.setI(17);
+        b1.setS("test");
+        final Bean2a b2 = BeanUtils.fillBean(Bean2a.class, b1);
+        assertBeansAreEqual("Beans are not equal", b1, b2);
+    }
+
+    @Test
+    public void testFillSimpleBeanWithNativeWrapper1()
+    {
+        final Bean1b b1 = new Bean1b();
+        b1.setB(true);
+        b1.setF(0.2f);
+        b1.setI(17);
+        b1.setS("test");
+        final Bean2a b2 = BeanUtils.fillBean(Bean2a.class, b1);
+        assertEquals(b1.isB().booleanValue(), b2.isB());
+        assertEquals(b1.getF().floatValue(), b2.getF());
+        assertEquals(b1.getI().intValue(), b2.getI());
+        assertEquals(b1.getS(), b2.getS());
+    }
+
+    @Test
+    public void testFillSimpleBeanWithNativeWrapper2()
+    {
+        final Bean1a b1 = new Bean1a();
+        b1.setB(true);
+        b1.setF(0.2f);
+        b1.setI(17);
+        b1.setS("test");
+        final Bean2b b2 = BeanUtils.fillBean(Bean2b.class, b1);
+        assertEquals(b1.isB(), b2.isB().booleanValue());
+        assertEquals(b1.getF(), b2.getF().floatValue());
+        assertEquals(b1.getI(), b2.getI().intValue());
+        assertEquals(b1.getS(), b2.getS());
+    }
+
+    @Test
+    public void testFillSimpleBeanWithNativeWrapper3()
+    {
+        final Bean1b b1 = new Bean1b();
+        b1.setB(true);
+        b1.setF(0.2f);
+        b1.setI(17);
+        b1.setS("test");
+        final Bean2b b2 = BeanUtils.fillBean(Bean2b.class, b1);
+        assertEquals(b1.isB().booleanValue(), b2.isB().booleanValue());
+        assertEquals(b1.getF().floatValue(), b2.getF().floatValue());
+        assertEquals(b1.getI().intValue(), b2.getI().intValue());
+        assertEquals(b1.getS(), b2.getS());
+    }
+
+    @Test
+    public void testFillSimpleBeanArray()
+    {
+        final Bean1a b1a = new Bean1a();
+        b1a.setB(true);
+        b1a.setF(0.2f);
+        b1a.setI(17);
+        b1a.setS("test");
+        final Bean1a b1b = new Bean1a();
+        b1b.setB(false);
+        b1b.setF(0.3f);
+        b1b.setI(42);
+        b1b.setS("ttt");
+        final Bean1a[] b1Array = new Bean1a[]
+            { b1a, b1b };
+        final Bean2a[] b2Array = BeanUtils.fillBean(Bean2a[].class, b1Array);
+        assertEquals(b1Array.length, b2Array.length);
+        for (int i = 0; i < b1Array.length; ++i)
+        {
+            final Bean1a b1 = b1Array[i];
+            final Bean2a b2 = b2Array[i];
+            assertNotNull("Element " + i, b2);
+            assertEquals("Element " + i, b1.isB(), b2.isB());
+            assertEquals("Element " + i, b1.getF(), b2.getF());
+            assertEquals("Element " + i, b1.getI(), b2.getI());
+            assertEquals("Element " + i, b1.getS(), b2.getS());
+        }
+    }
+
+    @Test
+    public void testFillPrimitiveArray()
+    {
+        final int[] array = new int[]
+            { -5, 17, 0, 88 };
+        final int[] array2 = BeanUtils.fillBean(int[].class, array);
+        assert Arrays.equals(array, array2);
+    }
+
+    @Test
+    public void testFillPrimitiveArrayToWrapper()
+    {
+        final int[] array = new int[]
+            { -5, 17, 0, 88 };
+        final Integer[] array2 = BeanUtils.fillBean(Integer[].class, array);
+        for (int i = 0; i < array.length; ++i)
+        {
+            assertEquals("Element " + i, array[i], array2[i].intValue());
+        }
+    }
+
+    @Test
+    public void testFillPrimitiveArrayFromWrapper()
+    {
+        final Integer[] array = new Integer[]
+            { -5, 17, 0, 88 };
+        final int[] array2 = BeanUtils.fillBean(int[].class, array);
+        for (int i = 0; i < array.length; ++i)
+        {
+            assertEquals("Element " + i, array[i].intValue(), array2[i]);
+        }
+    }
+
+    @Test
+    public void testFillImmutableArray()
+    {
+        final String[] array = new String[]
+            { "apple", "orange", "banana" };
+        final String[] array2 = BeanUtils.fillBean(String[].class, array);
+        for (int i = 0; i < array.length; ++i)
+        {
+            assertEquals("Element " + i, array[i], array2[i]);
+        }
+    }
+
+    public static class ArrayWrapper1
+    {
+        private byte[] array;
+
+        public byte[] getArray()
+        {
+            return array;
+        }
+
+        public void setArray(byte[] array)
+        {
+            this.array = array;
+        }
+    }
+
+    public static class ArrayWrapper2
+    {
+        private Byte[] array;
+
+        public Byte[] getArray()
+        {
+            return array;
+        }
+
+        public void setArray(Byte[] array)
+        {
+            this.array = array;
+        }
+    }
+
+    public static class ArrayWrapper3
+    {
+        private String[] array;
+
+        public String[] getArray()
+        {
+            return array;
+        }
+
+        public void setArray(String[] array)
+        {
+            this.array = array;
+        }
+    }
+
+    @Test
+    public void testFillBeanWithPrimitiveArray()
+    {
+        final ArrayWrapper1 awrapper = new ArrayWrapper1();
+        awrapper.setArray(new byte[]
+            { -1, 0, 100, -88 });
+        final ArrayWrapper1 awrapper2 = BeanUtils.fillBean(ArrayWrapper1.class, awrapper);
+        final byte[] array = awrapper.getArray();
+        final byte[] array2 = awrapper2.getArray();
+        assertNotNull(array2);
+        assertEquals(array.length, array.length);
+        for (int i = 0; i < array.length; ++i)
+        {
+            assertEquals("Element " + i, array[i], array2[i]);
+        }
+    }
+
+    @Test
+    public void testFillBeanWithPrimitiveWrapperArray()
+    {
+        final ArrayWrapper1 awrapper = new ArrayWrapper1();
+        awrapper.setArray(new byte[]
+            { -1, 0, 100, -88 });
+        final ArrayWrapper2 awrapper2 = BeanUtils.fillBean(ArrayWrapper2.class, awrapper);
+        final byte[] array = awrapper.getArray();
+        final Byte[] array2 = awrapper2.getArray();
+        assertNotNull(array2);
+        assertEquals(array.length, array.length);
+        for (int i = 0; i < array.length; ++i)
+        {
+            assertEquals("Element " + i, array[i], array2[i].byteValue());
+        }
+    }
+
+    public static class CollectionWrapper1
+    {
+        private List<String> array;
+
+        public List<String> getArray()
+        {
+            return array;
+        }
+
+        @CollectionMapping(collectionClass = ArrayList.class, elementClass = String.class)
+        public void setArray(List<String> array)
+        {
+            this.array = array;
+        }
+    }
+
+    @Test
+    public void testFillArrayBeanFromCollectionBean()
+    {
+        final CollectionWrapper1 colWrapper = new CollectionWrapper1();
+        final List<String> list = Arrays.asList("blue", "yellow", "green");
+        colWrapper.setArray(list);
+        final ArrayWrapper3 aWrapper = BeanUtils.fillBean(ArrayWrapper3.class, colWrapper);
+        final String[] array = aWrapper.getArray();
+        assertNotNull(array);
+        assertEquals(list.size(), array.length);
+        for (int i = 0; i < array.length; ++i)
+        {
+            assertEquals("Element " + i, list.get(i), array[i]);
+        }
+    }
+
+    @Test
+    public void testFillCollectionBeanFromArrayBean()
+    {
+        final ArrayWrapper3 aWrapper = new ArrayWrapper3();
+        final String[] array = new String[]
+            { "hot", "warm", "cool", "icy" };
+        aWrapper.setArray(array);
+        final CollectionWrapper1 colWrapper = BeanUtils.fillBean(CollectionWrapper1.class, aWrapper);
+        List<String> list = colWrapper.getArray();
+        assertNotNull(list);
+        assertEquals(array.length, list.size());
+        for (int i = 0; i < array.length; ++i)
+        {
+            assertEquals("Element " + i, array[i], list.get(i));
+        }
+    }
+
+    @Test
+    public void testFillCollectionBeanFromCollectionBean()
+    {
+        final CollectionWrapper1 colWrapper = new CollectionWrapper1();
+        final List<String> list = new ArrayList<String>(Arrays.asList(new String[]
+            { "hot", "warm", "cool", "icy" }));
+        colWrapper.setArray(list);
+        final CollectionWrapper1 colWrapper2 = BeanUtils.fillBean(CollectionWrapper1.class, colWrapper);
+        List<String> list2 = colWrapper2.getArray();
+        assertNotNull(list2);
+        assertEquals(list.size(), list2.size());
+        for (int i = 0; i < list.size(); ++i)
+        {
+            assertEquals("Element " + i, list.get(i), list2.get(i));
+        }
+    }
+
+    public static class BeanWithBean1
+    {
+        private Bean1a bean;
+
+        public Bean1a getBean()
+        {
+            return bean;
+        }
+
+        public void setBean(Bean1a bean)
+        {
+            this.bean = bean;
+        }
+    }
+
+    public static class BeanWithBean2
+    {
+        private Bean2a bean;
+
+        public Bean2a getBean()
+        {
+            return bean;
+        }
+
+        public void setBean(Bean2a bean)
+        {
+            this.bean = bean;
+        }
+    }
+
+    @Test
+    public void testFillComplexBean()
+    {
+        final Bean1a b1 = new Bean1a();
+        b1.setB(true);
+        b1.setF(0.2f);
+        b1.setI(17);
+        b1.setS("test");
+        final BeanWithBean1 b3 = new BeanWithBean1();
+        b3.setBean(b1);
+        final BeanWithBean2 b4 = BeanUtils.fillBean(BeanWithBean2.class, b3);
+        final Bean2a b2 = b4.getBean();
+        assertBeansAreEqual("Bean comparison", b1, b2);
+    }
+
+    public static class BeanWithBeanArray1
+    {
+        private Bean1a[] bean;
+
+        public Bean1a[] getBeanArray()
+        {
+            return bean;
+        }
+
+        public void setBeanArray(Bean1a[] bean)
+        {
+            this.bean = bean;
+        }
+    }
+
+    public static class BeanWithBeanArray2
+    {
+        private Bean2a[] bean;
+
+        public Bean2a[] getBeanArray()
+        {
+            return bean;
+        }
+
+        public void setBeanArray(Bean2a[] bean)
+        {
+            this.bean = bean;
+        }
+    }
+
+    public static class BeanWithBeanCollection1
+    {
+        private Collection<Bean1a> bean;
+
+        public Collection<Bean1a> getBeanArray()
+        {
+            return bean;
+        }
+
+        @CollectionMapping(collectionClass = LinkedHashSet.class, elementClass = Bean1a.class)
+        public void setBeanArray(Collection<Bean1a> bean)
+        {
+            this.bean = bean;
+        }
+    }
+
+    public static class BeanWithBeanCollection2
+    {
+        private Collection<Bean2a> bean;
+
+        public Collection<Bean2a> getBeanArray()
+        {
+            return bean;
+        }
+
+        @CollectionMapping(collectionClass = LinkedList.class, elementClass = Bean2a.class)
+        public void setBeanArray(Collection<Bean2a> bean)
+        {
+            this.bean = bean;
+        }
+    }
+
+    @Test
+    public void testFillBeanWithBeanCollectionFromBeanWithBeanArray1()
+    {
+        final Bean1a b1a = new Bean1a();
+        b1a.setB(true);
+        b1a.setF(0.2f);
+        b1a.setI(17);
+        b1a.setS("test");
+        final Bean1a b1b = new Bean1a();
+        b1b.setB(false);
+        b1b.setF(1.1f);
+        b1b.setI(31);
+        b1b.setS("test2");
+        final BeanWithBeanArray1 b1Array = new BeanWithBeanArray1();
+        final Bean1a[] arrayb1 = new Bean1a[]
+            { b1a, b1b };
+        b1Array.setBeanArray(arrayb1);
+        final BeanWithBeanCollection2 b2Collection = BeanUtils.fillBean(BeanWithBeanCollection2.class, b1Array);
+        final Collection<Bean2a> colb2 = b2Collection.getBeanArray();
+        assertNotNull(colb2);
+        assertEquals(arrayb1.length, colb2.size());
+        final Iterator<Bean2a> itb2 = colb2.iterator();
+        for (int i = 0; i < arrayb1.length; ++i)
+        {
+            assertBeansAreEqual("Element " + i, arrayb1[i], itb2.next());
+        }
+    }
+
+    @Test
+    public void testFillBeanWithBeanCollectionFromBeanWithBeanArray2()
+    {
+        final Bean2a b2a = new Bean2a();
+        b2a.setB(true);
+        b2a.setF(0.2f);
+        b2a.setI(17);
+        b2a.setS("test");
+        final Bean2a b2b = new Bean2a();
+        b2b.setB(false);
+        b2b.setF(1.1f);
+        b2b.setI(31);
+        b2b.setS("test2");
+        final BeanWithBeanArray2 b2Array = new BeanWithBeanArray2();
+        final Bean2a[] arrayb2 = new Bean2a[]
+            { b2a, b2b };
+        b2Array.setBeanArray(arrayb2);
+        final BeanWithBeanCollection1 b1Collection = BeanUtils.fillBean(BeanWithBeanCollection1.class, b2Array);
+        final Collection<Bean1a> colb1 = b1Collection.getBeanArray();
+        assertNotNull(colb1);
+        assertEquals(arrayb2.length, colb1.size());
+        final Iterator<Bean1a> itb1 = colb1.iterator();
+        for (int i = 0; i < arrayb2.length; ++i)
+        {
+            assertBeansAreEqual("Element " + i, arrayb2[i], itb1.next());
+        }
+    }
+
+    @Test
+    public void testFillBeanWithBeanArrayFromBeanWithBeanCollection()
+    {
+        final Bean1a b1a = new Bean1a();
+        b1a.setB(true);
+        b1a.setF(0.2f);
+        b1a.setI(17);
+        b1a.setS("test");
+        final Bean1a b1b = new Bean1a();
+        b1b.setB(false);
+        b1b.setF(1.1f);
+        b1b.setI(31);
+        b1b.setS("test2");
+        final BeanWithBeanCollection1 b1Collection = new BeanWithBeanCollection1();
+        final Collection<Bean1a> colb1 = new LinkedHashSet<Bean1a>(Arrays.asList(new Bean1a[]
+            { b1a, b1b }));
+        b1Collection.setBeanArray(colb1);
+        final BeanWithBeanArray2 b2Array = BeanUtils.fillBean(BeanWithBeanArray2.class, b1Collection);
+        final Bean2a[] arrayb2 = b2Array.getBeanArray();
+        assertNotNull(arrayb2);
+        assertEquals(colb1.size(), arrayb2.length);
+        int i = 0;
+        for (Bean1a b1 : colb1)
+        {
+            assertBeansAreEqual("Element " + i, b1, arrayb2[i]);
+            ++i;
+        }
+    }
+
+    @Test
+    public void testFillBeanWithBeanArrayFromBeanWithBeanArray()
+    {
+        final Bean1a b1a = new Bean1a();
+        b1a.setB(true);
+        b1a.setF(0.2f);
+        b1a.setI(17);
+        b1a.setS("test");
+        final Bean1a b1b = new Bean1a();
+        b1b.setB(false);
+        b1b.setF(1.1f);
+        b1b.setI(31);
+        b1b.setS("test2");
+        final BeanWithBeanArray1 b1Array = new BeanWithBeanArray1();
+        final Bean1a[] arrayb1 = new Bean1a[]
+            { b1a, b1b };
+        b1Array.setBeanArray(arrayb1);
+        final BeanWithBeanArray2 b2Array = BeanUtils.fillBean(BeanWithBeanArray2.class, b1Array);
+        final Bean2a[] arrayb2 = b2Array.getBeanArray();
+        assertNotNull(arrayb2);
+        assertEquals(arrayb1.length, arrayb2.length);
+        for (int i = 0; i < arrayb1.length; ++i)
+        {
+            assertBeansAreEqual("Element " + i, arrayb1[i], arrayb2[i]);
+        }
+    }
+
+    @Test
+    public void testFillBeanWithBeanCollectionFromBeanWithBeanCollection()
+    {
+        final Bean1a b1a = new Bean1a();
+        b1a.setB(true);
+        b1a.setF(0.2f);
+        b1a.setI(17);
+        b1a.setS("test");
+        final Bean1a b1b = new Bean1a();
+        b1b.setB(false);
+        b1b.setF(1.1f);
+        b1b.setI(31);
+        b1b.setS("test2");
+        final BeanWithBeanCollection1 b1Collection = new BeanWithBeanCollection1();
+        final Collection<Bean1a> colb1 = new LinkedHashSet<Bean1a>(Arrays.asList(new Bean1a[]
+            { b1a, b1b }));
+        b1Collection.setBeanArray(colb1);
+        final BeanWithBeanCollection2 b2Collection = BeanUtils.fillBean(BeanWithBeanCollection2.class, b1Collection);
+        final Collection<Bean2a> colb2 = b2Collection.getBeanArray();
+        assertNotNull(colb2);
+        assertEquals(colb1.size(), colb2.size());
+        final Iterator<Bean2a> itb2 = colb2.iterator();
+        int i = 0;
+        for (Bean1a b1 : colb1)
+        {
+            assertBeansAreEqual("Element " + (i++), b1, itb2.next());
+        }
+    }
+
+    private void assertBeansAreEqual(String msg, Bean1a b1, Bean2a b2)
+    {
+        assertNotNull(msg, b1);
+        assertNotNull(msg, b2);
+        assertEquals(msg, b1.isB(), b2.isB());
+        assertEquals(msg, b1.getF(), b2.getF());
+        assertEquals(msg, b1.getI(), b2.getI());
+        assertEquals(msg, b1.getS(), b2.getS());
+    }
+
+    private void assertBeansAreEqual(String msg, Bean2a b2, Bean1a b1)
+    {
+        assertNotNull(msg, b1);
+        assertNotNull(msg, b2);
+        assertEquals(msg, b2.isB(), b1.isB());
+        assertEquals(msg, b2.getF(), b1.getF());
+        assertEquals(msg, b2.getI(), b1.getI());
+        assertEquals(msg, b2.getS(), b1.getS());
+    }
+    
+    public static class FooBean
+    {
+        private String foo;
+
+        public String getFoo()
+        {
+            return foo;
+        }
+
+        public void setFoo(String foo)
+        {
+            this.foo = foo;
+        }
+    }
+
+    public static class BarBean
+    {
+        private String bar;
+
+        public String getBar()
+        {
+            return bar;
+        }
+
+        @BeanNameMapping(names = {"bar", "foo"})
+        public void setBar(String bar)
+        {
+            this.bar = bar;
+        }
+    }
+    
+    @Test
+    public void testNameMapping1()
+    {
+        final FooBean fooBean = new FooBean();
+        fooBean.setFoo("foo is now bar");
+        final BarBean barBean = BeanUtils.fillBean(BarBean.class, fooBean);
+        assertEquals(fooBean.getFoo(), barBean.getBar());
+    }
+    
+    @Test
+    public void testNameMapping2()
+    {
+        final BarBean barBean = new BarBean();
+        barBean.setBar("bar is still bar");
+        final BarBean barBean2 = BeanUtils.fillBean(BarBean.class, barBean);
+        assertEquals(barBean.getBar(), barBean2.getBar());
+    }
+    
+    @Test
+    public void testConverter()
+    {
+        final FooBean tofuBean = new FooBean();
+        tofuBean.setFoo("some tofu");
+        final BarBean toFooBean = BeanUtils.fillBean(BarBean.class, tofuBean, new BeanUtils.Converter()
+        {
+            @SuppressWarnings("unused")
+            public String convertToBar(FooBean foo)
+            {
+                return StringUtils.replace(foo.getFoo(), "tofu", "to Foo");
+            }
+        });
+        assertEquals("some to Foo", toFooBean.getBar());
+    }
 }
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 a18b8f1864149cc113045f2b496beea0de5e9380..ebaa9f1cd0662aaebbbc83a31cbfc54ec8f7d054 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java
@@ -16,12 +16,8 @@
 
 package ch.systemsx.cisd.common.utilities;
 
-import static org.testng.AssertJUnit.*;
+import static org.testng.AssertJUnit.assertEquals;
 
-import java.util.Arrays;
-import java.util.List;
-
-import org.testng.AssertJUnit;
 import org.testng.annotations.Test;
 
 /**
@@ -59,83 +55,4 @@ public final class ClassUtilsTest
         }
     }
 
-    private static class SimpleBean
-    {
-        private final int number;
-
-        private final String string;
-
-        SimpleBean(int number, String string)
-        {
-            this.number = number;
-            this.string = string;
-        }
-
-        public int getNumber()
-        {
-            return number;
-        }
-
-        public String getString()
-        {
-            return string;
-        }
-
-        String getIgnoreThisBecauseItIsNotPublic()
-        {
-            AssertJUnit.fail("Should be ignore because not public");
-            return null;
-        }
-    }
-
-    @Test
-    public void testCheckGettersForNullOK()
-    {
-        final SimpleBean bean = new SimpleBean(1, "");
-        assert ClassUtils.checkGettersNotNull(bean) == bean;
-    }
-
-    @Test
-    public void testCheckGettersForNullOKNullBean()
-    {
-        assertNull(ClassUtils.checkGettersNotNull(null));
-    }
-
-    @Test(expectedExceptions = IllegalStateException.class)
-    public void testCheckGettersForNullStringNull()
-    {
-        final SimpleBean bean = new SimpleBean(1, null);
-        ClassUtils.checkGettersNotNull(bean);
-    }
-
-    @Test(expectedExceptions = IllegalStateException.class)
-    public void testCheckGettersForNullInt0()
-    {
-        final SimpleBean bean = new SimpleBean(0, "test");
-        ClassUtils.checkGettersNotNull(bean);
-    }
-
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testCheckGettersForNullForbiddenArray()
-    {
-        ClassUtils.checkGettersNotNull(new Object[0]);
-    }
-
-    @Test
-    public void testCheckGettersForNullListOK()
-    {
-        final SimpleBean bean1 = new SimpleBean(1, "test");
-        final SimpleBean bean2 = new SimpleBean(5, "test2");
-        final List<SimpleBean> beanList = Arrays.asList(bean1, bean2);
-        assert ClassUtils.checkGettersNotNull(beanList) == beanList;
-    }
-
-    @Test(expectedExceptions = IllegalStateException.class)
-    public void testCheckGettersForNullListInt0()
-    {
-        final SimpleBean bean1 = new SimpleBean(1, "test");
-        final SimpleBean bean2 = new SimpleBean(0, "test2");
-        ClassUtils.checkGettersNotNull(Arrays.asList(bean1, bean2));
-    }
-
 }