Author: tchemit Date: 2010-05-06 17:45:26 +0200 (Thu, 06 May 2010) New Revision: 1841 Url: http://nuiton.org/repositories/revision/nuiton-utils/1841 Log: add binding support in binder Modified: trunk/src/main/java/org/nuiton/util/beans/Binder.java trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java trunk/src/main/java/org/nuiton/util/beans/BinderModel.java Modified: trunk/src/main/java/org/nuiton/util/beans/Binder.java =================================================================== --- trunk/src/main/java/org/nuiton/util/beans/Binder.java 2010-05-06 09:53:21 UTC (rev 1840) +++ trunk/src/main/java/org/nuiton/util/beans/Binder.java 2010-05-06 15:45:26 UTC (rev 1841) @@ -36,7 +36,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -88,12 +87,20 @@ if (readValue instanceof Set<?>) { return new HashSet((Set<?>) readValue); } - if (readValue instanceof List<?>) { + // in any other cases, let says this is a ArrayList + if (readValue instanceof Collection<?>) { return new ArrayList((Collection<?>) readValue); } return readValue; - }}; + } + }; + /** + * Copy a given collection. + * + * @param readValue the collection value to copy + * @return the copied collection + */ public abstract Object copy(Object readValue); } @@ -138,19 +145,28 @@ // for primitive type case, force nullity read = null; } - if (read != null) { - + if (read == null) { + continue; + } + if (model.containsBinderProperty(sourceProperty)) { if (model.containsCollectionProperty(sourceProperty)) { - // specific collection strategy is set, must use it - read = getCollectionValue(sourceProperty, read); + read = bindCollection(sourceProperty, read); + } else { + read = bindProperty(sourceProperty, read); } + } else if (model.containsCollectionProperty(sourceProperty)) { - result.put(sourceProperty, read); + // specific collection strategy is set, must use it + read = getCollectionValue(sourceProperty, read); } + + result.put(sourceProperty, read); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); } } return result; @@ -200,6 +216,17 @@ readMethod.getReturnType() + ", value = " + read); } + if (model.containsBinderProperty(sourceProperty)) { + if (model.containsCollectionProperty(sourceProperty)) { + read = bindCollection(sourceProperty, read); + } else { + read = bindProperty(sourceProperty, read); + } + } else if (model.containsCollectionProperty(sourceProperty)) { + + // specific collection strategy is set, must use it + read = getCollectionValue(sourceProperty, read); + } if (model.containsCollectionProperty(sourceProperty)) { // specific collection strategy is set, must use it read = getCollectionValue(sourceProperty, read); @@ -209,18 +236,31 @@ throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); } } } - protected Object getCollectionValue(String sourceProperty, Object readValue) { - CollectionStrategy strategy = - model.getCollectionStrategy(sourceProperty); - Object result = strategy.copy(readValue); - return result; + /** + * Get the model of the binder. + * + * @return the model of the binder + */ + protected BinderModel<I, O> getModel() { + return model; } /** + * Set the model of the binder. + * + * @param model the model of the binder + */ + protected void setModel(BinderModel<?, ?> model) { + this.model = (BinderModel<I, O>) model; + } + + /** * Obtain the properties, if none is given in {@code propertyNames} * parameter, will use all property names defined in binder's model, * otherwise, check that all given property names are safe (registred in @@ -248,21 +288,46 @@ return propertyNames; } - /** - * Get the model of the binder. - * - * @return the model of the binder - */ - protected BinderModel<I, O> getModel() { - return model; + protected Object getCollectionValue(String sourceProperty, Object readValue) { + CollectionStrategy strategy = + model.getCollectionStrategy(sourceProperty); + Object result = strategy.copy(readValue); + return result; } - /** - * Set the model of the binder. - * - * @param model the model of the binder - */ - protected void setModel(BinderModel<?, ?> model) { - this.model = (BinderModel<I, O>) model; + protected Object bindProperty(String sourceProperty, Object read) throws IllegalAccessException, InstantiationException { + Binder binder = model.getBinder(sourceProperty); + Object result = bind(binder, read); + return result; } + + + protected Object bindCollection(String sourceProperty, Object read) throws IllegalAccessException, InstantiationException { + + Binder binder = model.getBinder(sourceProperty); + + Collection result; + + if (read instanceof Set<?>) { + result = new HashSet(); + } + // in any other cases, let says this is a ArrayList + if (read instanceof Collection<?>) { + result = new ArrayList(); + } + + result = new ArrayList<Object>(); + + for (Object o : (Collection<?>) read) { + Object r = bind(binder, o); + result.add(r); + } + return result; + } + + protected Object bind(Binder binder, Object read) throws IllegalAccessException, InstantiationException { + Object result = read.getClass().newInstance(); + binder.copy(read, result); + return result; + } } Modified: trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java =================================================================== --- trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java 2010-05-06 09:53:21 UTC (rev 1840) +++ trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java 2010-05-06 15:45:26 UTC (rev 1841) @@ -78,7 +78,8 @@ * @param targetType type of the target of the binder * @param properties simple properties to add */ - public BinderBuilder(Class<?> sourceType, Class<?> targetType, + public BinderBuilder(Class<?> sourceType, + Class<?> targetType, String... properties) { createBinderModel(sourceType, targetType); addSimpleProperties(properties); @@ -304,8 +305,35 @@ return this; } - public BinderBuilder addCollectionStrategy(String propertyName, - Binder.CollectionStrategy strategy) { + public BinderBuilder addCollectionStrategy(Binder.CollectionStrategy strategy, + String... propertyNames) { + + for (String propertyName : propertyNames) { + + // check property is registred + if (!model.containsSourceProperty(propertyName)) { + throw new IllegalArgumentException( + "source property '" + propertyName + "' " + + " is NOT registred."); + } + + // check property is collection type + PropertyDescriptor descriptor = sourceDescriptors.get(propertyName); + Class<?> type = descriptor.getPropertyType(); + if (!Collection.class.isAssignableFrom(type)) { + throw new IllegalStateException( + "source property '" + propertyName + + "' is not a collection type [" + type + "]"); + } + + // can safely add the strategy + model.addCollectionStrategy(propertyName, strategy); + } + return this; + } + + public BinderBuilder addBinder(String propertyName, Binder<?, ?> binder) { + // check property is registred if (!model.containsSourceProperty(propertyName)) { throw new IllegalArgumentException( @@ -313,17 +341,20 @@ " is NOT registred."); } - // check property is collection type + // check property is the same type of given binder PropertyDescriptor descriptor = sourceDescriptors.get(propertyName); Class<?> type = descriptor.getPropertyType(); - if (!Collection.class.isAssignableFrom(type)) { + + if (!Collection.class.isAssignableFrom(type) && + !binder.model.getSourceType().isAssignableFrom(type)) { throw new IllegalStateException( "source property '" + propertyName + - "' is not a collection type [" + type + "]"); + "' has not the same type [" + type + + "] of the binder [" + binder.model.getSourceType() + "]."); } // can safely add the strategy - model.addCollectionStrategy(propertyName, strategy); + model.addBinder(propertyName, binder); return this; } Modified: trunk/src/main/java/org/nuiton/util/beans/BinderModel.java =================================================================== --- trunk/src/main/java/org/nuiton/util/beans/BinderModel.java 2010-05-06 09:53:21 UTC (rev 1840) +++ trunk/src/main/java/org/nuiton/util/beans/BinderModel.java 2010-05-06 15:45:26 UTC (rev 1841) @@ -67,6 +67,9 @@ /** mapping of collection properties strategies */ protected Map<String, Binder.CollectionStrategy> collectionStrategies; + /** mapping of extra binders to use to copy properties */ + protected Map<String, Binder<?, ?>> binders; + private static final long serialVersionUID = 2L; public BinderModel(Class<S> sourceType, Class<T> targetType) { @@ -76,6 +79,7 @@ targetDescriptors = new TreeMap<String, PropertyDescriptor>(); propertiesMapping = new TreeMap<String, String>(); collectionStrategies = new TreeMap<String, Binder.CollectionStrategy>(); + binders = new TreeMap<String, Binder<?, ?>>(); } /** @@ -230,6 +234,15 @@ return null; } + public void addCollectionStrategy(String propertyName, + Binder.CollectionStrategy strategy) { + collectionStrategies.put(propertyName, strategy); + } + + public void addBinder(String propertyName, Binder<?, ?> binder) { + binders.put(propertyName, binder); + } + protected boolean containsSourceProperty(String sourceProperty) { return propertiesMapping.containsKey(sourceProperty); } @@ -242,9 +255,8 @@ return collectionStrategies.containsKey(propertyName); } - protected void addCollectionStrategy(String propertyName, - Binder.CollectionStrategy strategy) { - collectionStrategies.put(propertyName, strategy); + protected boolean containsBinderProperty(String propertyName) { + return binders.containsKey(propertyName); } protected void addBinding(PropertyDescriptor sourceDescriptor, @@ -260,4 +272,8 @@ protected Map<String, String> getPropertiesMapping() { return propertiesMapping; } + + public Binder<?, ?> getBinder(String sourceProperty) { + return binders.get(sourceProperty); + } }