r1779 - in trunk/src: main/java/org/nuiton/util/beans test/java/org/nuiton/util
Author: tchemit Date: 2010-02-26 19:40:50 +0100 (Fri, 26 Feb 2010) New Revision: 1779 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 trunk/src/main/java/org/nuiton/util/beans/BinderProvider.java trunk/src/test/java/org/nuiton/util/VersionConverterTest.java Log: - can bind a subset of the binder model - search property deeply (in super classes and interfaces) - add clear method on binderProvider - add some constructors to make easier the usage of BinderBuilder for simple cases - remove IDE headers Modified: trunk/src/main/java/org/nuiton/util/beans/Binder.java =================================================================== --- trunk/src/main/java/org/nuiton/util/beans/Binder.java 2010-02-26 17:11:54 UTC (rev 1778) +++ trunk/src/main/java/org/nuiton/util/beans/Binder.java 2010-02-26 18:40:50 UTC (rev 1779) @@ -35,9 +35,9 @@ * It is based on a {@link BinderModel} which contains the mapping of properties * to transfert from the source object to the destination object. * <p/> - * Use the method {@link #copy(Object, Object)} to transfert properties. + * Use the method {@link #copy(Object, Object,String...)} to transfert properties. * <p/> - * Use the method {@link #obtainProperties(Object)} to obtain + * Use the method {@link #obtainProperties(Object,String...)} to obtain * * @author tchemit < chemit@codelutin.com > * @param <I> the source bean type @@ -65,17 +65,22 @@ * <b>Note:</b> If a property's value is null, it will not be injected in * the result. * - * @param source the bean to read + * @param source the bean to read + * @param propertyNames subset of properties to load * @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 source) { + public Map<String, Object> obtainProperties(I source, + String... propertyNames) { if (source == null) { // special limit case return java.util.Collections.emptyMap(); } + + propertyNames = getProperties(propertyNames); + Map<String, Object> result = new TreeMap<String, Object>(); - for (String sourceProperty : model.getSourceDescriptors()) { + for (String sourceProperty : propertyNames) { try { Object read; @@ -88,7 +93,7 @@ if (readMethod.getReturnType().isPrimitive() && ObjectUtil.getNullValue( readMethod.getReturnType()).equals(read)) { - // for primitive type case, force nullity + // for primitive type case, force nullity read = null; } if (read != null) { @@ -110,16 +115,23 @@ * <b>Note:</b> If {@code from} object is null, then {@code null} values * will be set to mapped properties into {@code dst} * - * @param source the bean to read - * @param target the bean to write + * @param source the bean to read + * @param target the bean to write + * @param propertyNames optional subset of properties to copy (if none is + * specifed, will use all the properties defined in + * binder) * @throws NullPointerException if target parameter is {@code null} */ - public void copy(I source, O target) throws NullPointerException { + public void copy(I source, O target, String... propertyNames) + throws NullPointerException { if (target == null) { throw new NullPointerException("parameter 'target' can no be null"); } - for (String sourceProperty : model.getSourceDescriptors()) { + propertyNames = getProperties(propertyNames); + + for (String sourceProperty : propertyNames) { + String targetProperty = model.getTargetProperty(sourceProperty); try { @@ -148,6 +160,33 @@ } /** + * 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 + * binder's model). + * + * @param propertyNames optional subset of properties to get + * @return the array of property names + */ + protected String[] getProperties(String... propertyNames) { + + if (propertyNames.length == 0) { + // use all properties in the binder + propertyNames = model.getSourceDescriptors(); + } else { + + // use a subset of properties, must check them + for (String propertyName : propertyNames) { + if (!model.containsSourceProperty(propertyName)) { + throw new IllegalArgumentException("property '" + + propertyName + "' is not known by binder"); + } + } + } + return propertyNames; + } + + /** * Get the model of the binder. * * @return the model of the binder Modified: trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java =================================================================== --- trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java 2010-02-26 17:11:54 UTC (rev 1778) +++ trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java 2010-02-26 18:40:50 UTC (rev 1779) @@ -43,11 +43,44 @@ * current model used to build the binder */ protected BinderModel<?, ?> model; + /** + * source properties descriptors + */ protected Map<String, PropertyDescriptor> sourceDescriptors; + /** + * target properties descriptors + */ protected Map<String, PropertyDescriptor> targetDescriptors; + public BinderBuilder() { + } /** + * Creates a mirrored binder for the given {@code type} and add the given + * simple properties. + * + * @param type the type of mirrored binder + * @param properties simple properties to add + */ + public BinderBuilder(Class<?> type, String... properties) { + createBinderModel(type); + addSimpleProperties(properties); + } + + /** + * Creates a binder for the given types and add the given simple properties. + * + * @param sourceType type of the source of the binder + * @param targetType type of the target of the binder + * @param properties simple properties to add + */ + public BinderBuilder(Class<?> sourceType, Class<?> targetType, + String... properties) { + createBinderModel(sourceType, targetType); + addSimpleProperties(properties); + } + + /** * Creates a new binder model for a mirrored binder (source type = target * type). * <p/> @@ -98,33 +131,36 @@ // init model model = new BinderModel(sourceType, targetType); - // obtain src descriptors - try { - sourceDescriptors = new TreeMap<String, PropertyDescriptor>(); + // obtain source descriptors + sourceDescriptors = new TreeMap<String, PropertyDescriptor>(); + loadDescriptors(model.getSourceType(), sourceDescriptors); - BeanInfo beanInfo = Introspector.getBeanInfo(model.getSourceType()); - for (PropertyDescriptor descriptor : - beanInfo.getPropertyDescriptors()) { - sourceDescriptors.put(descriptor.getName(), descriptor); - } - } catch (IntrospectionException e) { - throw new RuntimeException("Could not obtain bean properties " + - "descriptors for source type " + sourceType, e); - } - // obtain dst descriptors - try { - targetDescriptors = new TreeMap<String, PropertyDescriptor>(); +// try { +// +// BeanInfo beanInfo = Introspector.getBeanInfo(model.getSourceType()); +// for (PropertyDescriptor descriptor : +// beanInfo.getPropertyDescriptors()) { +// sourceDescriptors.put(descriptor.getName(), descriptor); +// } +// } catch (IntrospectionException e) { +// throw new RuntimeException("Could not obtain bean properties " + +// "descriptors for source type " + sourceType, e); +// } + // obtain target descriptors + targetDescriptors = new TreeMap<String, PropertyDescriptor>(); + loadDescriptors(model.getTargetType(), targetDescriptors); +// try { +// +// BeanInfo beanInfo = Introspector.getBeanInfo(model.getTargetType()); +// for (PropertyDescriptor descriptor : +// beanInfo.getPropertyDescriptors()) { +// targetDescriptors.put(descriptor.getName(), descriptor); +// } +// } catch (IntrospectionException e) { +// throw new RuntimeException("Could not obtain bean properties " + +// "descriptors for target type " + targetType, e); +// } - BeanInfo beanInfo = Introspector.getBeanInfo(model.getTargetType()); - for (PropertyDescriptor descriptor : - beanInfo.getPropertyDescriptors()) { - targetDescriptors.put(descriptor.getName(), descriptor); - } - } catch (IntrospectionException e) { - throw new RuntimeException("Could not obtain bean properties " + - "descriptors for target type " + targetType, e); - } - return this; } @@ -285,7 +321,6 @@ return this; } - protected void addProperty0(String sourceProperty, String targetProperty) { // check srcProperty does not exist @@ -344,6 +379,7 @@ model.addBinding(sourceDescriptor, targetDescriptor); } + protected void checkModelExists() throws IllegalStateException { if (model == null) { throw new IllegalStateException("there is not model, must " + @@ -354,4 +390,30 @@ protected BinderModel<?, ?> getModel() { return model; } + + protected static void loadDescriptors( + Class<?> type, + Map<String, PropertyDescriptor> descriptors) { + try { + + BeanInfo beanInfo = Introspector.getBeanInfo(type); + for (PropertyDescriptor descriptor : + beanInfo.getPropertyDescriptors()) { + if (!descriptors.containsKey(descriptor.getName())) { + descriptors.put(descriptor.getName(), descriptor); + } + } + } catch (IntrospectionException e) { + throw new RuntimeException("Could not obtain bean properties " + + "descriptors for source type " + type, e); + } + Class<?>[] interfaces = type.getInterfaces(); + for (Class<?> i : interfaces) { + loadDescriptors(i, descriptors); + } + Class<?> superClass = type.getSuperclass(); + if (superClass != null && superClass != Object.class) { + loadDescriptors(superClass, descriptors); + } + } } \ No newline at end of file Modified: trunk/src/main/java/org/nuiton/util/beans/BinderModel.java =================================================================== --- trunk/src/main/java/org/nuiton/util/beans/BinderModel.java 2010-02-26 17:11:54 UTC (rev 1778) +++ trunk/src/main/java/org/nuiton/util/beans/BinderModel.java 2010-02-26 18:40:50 UTC (rev 1779) @@ -28,6 +28,8 @@ /** * Model of a {@link Binder}. * + * TODO-TC20100225 should have special cases for collections treatment. + * * @author tchemit < chemit@codelutin.com > * @param <S> the source type * @param <T> the target type Modified: trunk/src/main/java/org/nuiton/util/beans/BinderProvider.java =================================================================== --- trunk/src/main/java/org/nuiton/util/beans/BinderProvider.java 2010-02-26 17:11:54 UTC (rev 1778) +++ trunk/src/main/java/org/nuiton/util/beans/BinderProvider.java 2010-02-26 18:40:50 UTC (rev 1779) @@ -253,6 +253,13 @@ return binders; } + public static void clear() { + if (binders!=null) { + binders.clear(); + binders = null; + } + } + /** * Definition of an binder entry (source and target types + context name). * <p/> Modified: trunk/src/test/java/org/nuiton/util/VersionConverterTest.java =================================================================== --- trunk/src/test/java/org/nuiton/util/VersionConverterTest.java 2010-02-26 17:11:54 UTC (rev 1778) +++ trunk/src/test/java/org/nuiton/util/VersionConverterTest.java 2010-02-26 18:40:50 UTC (rev 1779) @@ -16,10 +16,7 @@ * License along with this program. If not, see * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%* */ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ + package org.nuiton.util; import org.junit.After;
participants (1)
-
tchemit@users.nuiton.org