/* This file is part of Cyclos (www.cyclos.org). A project of the Social Trade Organisation (www.socialtrade.org). Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.utils.binding; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import nl.strohalm.cyclos.utils.ClassHelper; import nl.strohalm.cyclos.utils.PropertyHelper; import nl.strohalm.cyclos.utils.conversion.CoercionConverter; import nl.strohalm.cyclos.utils.conversion.CoercionHelper; import nl.strohalm.cyclos.utils.conversion.Converter; import org.apache.commons.collections.IteratorUtils; /** * A binder for collections of a single type * @author luis */ public class SimpleCollectionBinder<T> extends DataBinder<Collection<T>> { private static final long serialVersionUID = -2345152330629764092L; public static <T> SimpleCollectionBinder<T> instance(final Class<T> elementType) { return instance(elementType, null, null, null); } public static <T> SimpleCollectionBinder<T> instance(final Class<T> elementType, final Class<?> collectionType) { return instance(elementType, collectionType, null, null); } public static <T> SimpleCollectionBinder<T> instance(final Class<T> elementType, final Class<?> collectionType, final Converter<T> converter) { return instance(elementType, collectionType, null, converter); } public static <T> SimpleCollectionBinder<T> instance(final Class<T> elementType, final Class<?> collectionType, final String path) { return instance(elementType, collectionType, path, null); } public static <T> SimpleCollectionBinder<T> instance(final Class<T> elementType, final Class<?> collectionType, final String path, final Converter<T> converter) { final SimpleCollectionBinder<T> binder = new SimpleCollectionBinder<T>(); binder.setElementType(elementType); binder.setCollectionType(collectionType); binder.setPath(path); binder.setConverter(converter); return binder; } public static <T> SimpleCollectionBinder<T> instance(final Class<T> elementType, final Converter<T> converter) { return instance(elementType, null, null, converter); } public static <T> SimpleCollectionBinder<T> instance(final Class<T> elementType, final String path) { return instance(elementType, null, path, null); } public static <T> SimpleCollectionBinder<T> instance(final Class<T> elementType, final String path, final Converter<T> converter) { return instance(elementType, null, path, converter); } private Class<T> elementType; private Class<?> collectionType = ArrayList.class; private Converter<T> converter; public SimpleCollectionBinder() { } public Class<?> getCollectionType() { return collectionType; } public Converter<T> getConverter() { return converter; } public Class<T> getElementType() { return elementType; } @Override public Class<Collection<T>> getType() { final Class<Collection<T>> clazz = ClassHelper.cast(collectionType == null ? Collection.class : collectionType); return clazz; } @Override public Collection<T> read(final Object object) { final Collection<T> ret = instantiateCollection(); readInto(ret, object, false); return ret; } @Override public String readAsString(final Object object) { final StringBuilder sb = new StringBuilder(); sb.append('['); final Converter<T> converter = resolveConverter(); for (final Iterator<?> it = IteratorUtils.getIterator(object); it.hasNext();) { final Object value = it.next(); final T baseValue = CoercionHelper.coerce(elementType, value); sb.append('"').append(converter.toString(baseValue)).append('"'); if (it.hasNext()) { sb.append(','); } } sb.append(']'); return sb.toString(); } @Override public Collection<T> readFromString(final Object object) { final Collection<T> ret = instantiateCollection(); readInto(ret, object, true); return ret; } @SuppressWarnings({ "rawtypes" }) public void readInto(final Collection<T> collection, final Object object, final boolean asString) { // Read each element on the list final List list = CoercionHelper.coerce(List.class, PropertyHelper.get(object, getPath())); if (list != null) { final Converter<T> converter = resolveConverter(); for (final Object current : list) { if (current == null) { continue; } T value; if (asString) { value = converter.valueOf(current.toString()); } else { value = CoercionHelper.coerce(elementType, current); } if (value != null) { collection.add(value); } } } } public void setCollectionType(final Class<?> collectionType) { this.collectionType = collectionType == null ? ArrayList.class : collectionType; } public void setConverter(final Converter<T> converter) { this.converter = converter; } public void setElementType(final Class<T> elementType) { this.elementType = elementType; } @Override public void write(final Object object, final Collection<T> values) { doWrite(object, values, false); } @Override public void writeAsString(final Object object, final Object value) { doWrite(object, CoercionHelper.coerce(List.class, value), true); } @SuppressWarnings("unchecked") private void doWrite(final Object object, final Collection<?> values, final boolean asString) { if (values == null) { return; } final Collection<Object> collection = instantiateCollection(); final Converter<T> converter = resolveConverter(); for (final Object value : values) { Object result; if (asString) { result = converter.toString((T) value); } else { result = CoercionHelper.coerce(elementType, value); } if (result != null) { collection.add(result); } } PropertyHelper.set(object, getPath(), collection); } @SuppressWarnings("unchecked") private <E> Collection<E> instantiateCollection() { return (Collection<E>) ClassHelper.instantiate(collectionType); } private Converter<T> resolveConverter() { final Converter<T> converter = this.converter == null ? CoercionConverter.instance(elementType) : this.converter; return converter; } }