Author: tchemit Date: 2010-02-21 20:37:40 +0100 (Sun, 21 Feb 2010) New Revision: 1766 Modified: trunk/src/main/java/org/nuiton/util/beans/Binder.java trunk/src/test/java/org/nuiton/util/beans/BeanA.java trunk/src/test/java/org/nuiton/util/beans/BeanB.java trunk/src/test/java/org/nuiton/util/beans/BinderBuilderTest.java trunk/src/test/java/org/nuiton/util/beans/BinderTest.java Log: - Binder : if copy from a null source, just reset target properties - Binder : treate primitive type case nullity Modified: trunk/src/main/java/org/nuiton/util/beans/Binder.java =================================================================== --- trunk/src/main/java/org/nuiton/util/beans/Binder.java 2010-02-21 19:36:18 UTC (rev 1765) +++ trunk/src/main/java/org/nuiton/util/beans/Binder.java 2010-02-21 19:37:40 UTC (rev 1766) @@ -19,7 +19,12 @@ package org.nuiton.util.beans; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.ObjectUtil; + import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Map; import java.util.TreeMap; @@ -41,6 +46,10 @@ */ public class Binder<I, O> implements java.io.Serializable { + /** + * Logger + */ + private static final Log log = LogFactory.getLog(Binder.class); private static final long serialVersionUID = 1L; @@ -56,23 +65,34 @@ * <b>Note:</b> If a property's value is null, it will not be injected in * the result. * - * @param from the bean to read + * @param source the bean to read * @return the map of properties obtained indexed by their property name, * or an empty map is the given {@code from} is {@code null}. */ - public Map<String, Object> obtainProperties(I from) { - if (from == null) { + public Map<String, Object> obtainProperties(I source) { + if (source == null) { // special limit case return java.util.Collections.emptyMap(); } Map<String, Object> result = new TreeMap<String, Object>(); - for (String srcProperty : model.getSourceDescriptors()) { + for (String sourceProperty : model.getSourceDescriptors()) { try { Object read; - read = model.getSourceReadMethod(srcProperty).invoke(from); + Method readMethod = model.getSourceReadMethod(sourceProperty); + read = readMethod.invoke(source); + if (log.isDebugEnabled()) { + log.debug("property " + sourceProperty + ", type : " + + readMethod.getReturnType() + ", value = " + read); + } + if (readMethod.getReturnType().isPrimitive() && + ObjectUtil.getNullValue( + readMethod.getReturnType()).equals(read)) { + // for primitive type case, force nullity + read = null; + } if (read != null) { - result.put(srcProperty, read); + result.put(sourceProperty, read); } } catch (IllegalAccessException e) { throw new RuntimeException(e); @@ -86,20 +106,39 @@ /** * Copy properties from a source bean to a destination one according to * the model of the binder. + * <p/> + * <b>Note:</b> If {@code from} object is null, then {@code null} values + * will be set to mapped properties into {@code dst} * - * @param from the bean to read - * @param dst the bean to write + * @param source the bean to read + * @param target the bean to write + * @throws NullPointerException if target parameter is {@code null} */ - public void copy(I from, O dst) { + public void copy(I source, O target) throws NullPointerException { + if (target == null) { + throw new NullPointerException("parameter 'target' can no be null"); + } + for (String sourceProperty : model.getSourceDescriptors()) { - for (String srcProperty : model.getSourceDescriptors()) { + String targetProperty = model.getTargetProperty(sourceProperty); - String dstProperty = model.getTargetProperty(srcProperty); - try { - Object read = - model.getSourceReadMethod(srcProperty).invoke(from); - model.getTargetWriteMethod(dstProperty).invoke(dst, read); + Object read = null; + Method readMethod = model.getSourceReadMethod(sourceProperty); + if (source != null) { + // obtain value from source + read = readMethod.invoke(source); + } + // obtain acceptable null value (for primitive types, use + // default values). + if (read == null) { + read = ObjectUtil.getNullValue(readMethod.getReturnType()); + } + if (log.isDebugEnabled()) { + log.debug("property " + sourceProperty + ", type : " + + readMethod.getReturnType() + ", value = " + read); + } + model.getTargetWriteMethod(targetProperty).invoke(target, read); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { Modified: trunk/src/test/java/org/nuiton/util/beans/BeanA.java =================================================================== --- trunk/src/test/java/org/nuiton/util/beans/BeanA.java 2010-02-21 19:36:18 UTC (rev 1765) +++ trunk/src/test/java/org/nuiton/util/beans/BeanA.java 2010-02-21 19:37:40 UTC (rev 1766) @@ -6,9 +6,14 @@ public static final String PROPERTY_B = "b"; public static final String PROPERTY_C = "c"; public static final String PROPERTY_D = "d"; + public static final String PROPERTY_E = "e"; + public static final String PROPERTY_F = "f"; - String a,b,c,d; + String a, b, c, d; + + int e, f; + public String getA() { return a; } @@ -40,4 +45,20 @@ public void setD(String d) { this.d = d; } + + public int getE() { + return e; + } + + public void setE(int e) { + this.e = e; + } + + public int getF() { + return f; + } + + public void setF(int f) { + this.f = f; + } } \ No newline at end of file Modified: trunk/src/test/java/org/nuiton/util/beans/BeanB.java =================================================================== --- trunk/src/test/java/org/nuiton/util/beans/BeanB.java 2010-02-21 19:36:18 UTC (rev 1765) +++ trunk/src/test/java/org/nuiton/util/beans/BeanB.java 2010-02-21 19:37:40 UTC (rev 1766) @@ -6,9 +6,12 @@ public static final String PROPERTY_B2 = "b2"; public static final String PROPERTY_C2 = "c2"; public static final String PROPERTY_D2 = "d2"; - + public static final String PROPERTY_E2 = "e2"; + public static final String PROPERTY_F2 = "f2"; String a2, b2, c2, d2; + int e2,f2; + public String getA2() { return a2; } @@ -40,4 +43,20 @@ public void setD2(String d2) { this.d2 = d2; } + + public int getE2() { + return e2; + } + + public void setE2(int e2) { + this.e2 = e2; + } + + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } } \ No newline at end of file Modified: trunk/src/test/java/org/nuiton/util/beans/BinderBuilderTest.java =================================================================== --- trunk/src/test/java/org/nuiton/util/beans/BinderBuilderTest.java 2010-02-21 19:36:18 UTC (rev 1765) +++ trunk/src/test/java/org/nuiton/util/beans/BinderBuilderTest.java 2010-02-21 19:37:40 UTC (rev 1766) @@ -32,22 +32,26 @@ sourceDescriptors = builder.sourceDescriptors; Assert.assertNotNull(sourceDescriptors); - Assert.assertEquals(5, sourceDescriptors.size()); + Assert.assertEquals(7, sourceDescriptors.size()); Assert.assertTrue(sourceDescriptors.containsKey(PROPERTY_CLASS)); Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_A)); Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_B)); Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_C)); Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_D)); + Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_E)); + Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_F)); targetDescriptors = builder.targetDescriptors; Assert.assertNotNull(targetDescriptors); - Assert.assertEquals(5, targetDescriptors.size()); + Assert.assertEquals(7, targetDescriptors.size()); Assert.assertTrue(targetDescriptors.containsKey(PROPERTY_CLASS)); Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_A)); Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_B)); Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_C)); Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_D)); + Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_F)); + Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_F)); Assert.assertEquals(BeanA.class, builder.getModel().getSourceType()); Assert.assertEquals(BeanA.class, builder.getModel().getTargetType()); @@ -86,25 +90,31 @@ sourceDescriptors = builder.sourceDescriptors; Assert.assertNotNull(sourceDescriptors); - Assert.assertEquals(5, sourceDescriptors.size()); + Assert.assertEquals(7, sourceDescriptors.size()); Assert.assertTrue(sourceDescriptors.containsKey(PROPERTY_CLASS)); Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_A)); Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_B)); Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_C)); Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_D)); + Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_E)); + Assert.assertTrue(sourceDescriptors.containsKey(BeanA.PROPERTY_F)); targetDescriptors = builder.targetDescriptors; Assert.assertNotNull(targetDescriptors); - Assert.assertEquals(9, targetDescriptors.size()); + Assert.assertEquals(13, targetDescriptors.size()); Assert.assertTrue(targetDescriptors.containsKey(PROPERTY_CLASS)); Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_A)); Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_B)); Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_C)); Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_D)); + Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_E)); + Assert.assertTrue(targetDescriptors.containsKey(BeanA.PROPERTY_F)); Assert.assertTrue(targetDescriptors.containsKey(BeanB.PROPERTY_A2)); Assert.assertTrue(targetDescriptors.containsKey(BeanB.PROPERTY_B2)); Assert.assertTrue(targetDescriptors.containsKey(BeanB.PROPERTY_C2)); Assert.assertTrue(targetDescriptors.containsKey(BeanB.PROPERTY_D2)); + Assert.assertTrue(targetDescriptors.containsKey(BeanB.PROPERTY_E2)); + Assert.assertTrue(targetDescriptors.containsKey(BeanB.PROPERTY_F2)); Assert.assertEquals(BeanA.class, builder.getModel().getSourceType()); Assert.assertEquals(BeanB.class, builder.getModel().getTargetType()); Modified: trunk/src/test/java/org/nuiton/util/beans/BinderTest.java =================================================================== --- trunk/src/test/java/org/nuiton/util/beans/BinderTest.java 2010-02-21 19:36:18 UTC (rev 1765) +++ trunk/src/test/java/org/nuiton/util/beans/BinderTest.java 2010-02-21 19:37:40 UTC (rev 1766) @@ -14,6 +14,7 @@ private static final String VALUE_A = "a"; private static final String VALUE_B = "b"; private static final String VALUE_C = "c"; + private static final int VALUE_E = 10; @BeforeClass public static void beforeClass() { @@ -29,7 +30,9 @@ BinderProvider.registerBinder(builder. createBinderModel(BeanA.class, BeanB.class). addSimpleProperties(BeanA.PROPERTY_A, BeanA.PROPERTY_B). - addProperty(BeanA.PROPERTY_C, BeanB.PROPERTY_C2)); + addProperty(BeanA.PROPERTY_C, BeanB.PROPERTY_C2). + addProperty(BeanA.PROPERTY_E, BeanB.PROPERTY_E2) + ); } @@ -97,17 +100,27 @@ a.setA(VALUE_A); a.setB(VALUE_B); a.setC(VALUE_C); + a.setE(VALUE_E); binderA.copy(a, b); Assert.assertEquals(VALUE_A, b.getA()); Assert.assertNull(b.getB()); Assert.assertNull(b.getB2()); Assert.assertNull(b.getC()); + Assert.assertEquals(0,b.getE2()); binderB.copy(a, b); Assert.assertEquals(VALUE_A, b.getA()); Assert.assertEquals(VALUE_B, b.getB()); Assert.assertNull(b.getC()); Assert.assertEquals(VALUE_C, b.getC2()); + Assert.assertEquals(VALUE_E, b.getE2()); + + binderB.copy(null, b); + Assert.assertNull(b.getA()); + Assert.assertNull(b.getB()); + Assert.assertNull(b.getC2()); + Assert.assertEquals(0,b.getE2()); + } } \ No newline at end of file