Nuiton-utils-commits
Threads by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
February 2010
- 4 participants
- 18 discussions
r1779 - in trunk/src: main/java/org/nuiton/util/beans test/java/org/nuiton/util
by tchemit@users.nuiton.org 26 Feb '10
by tchemit@users.nuiton.org 26 Feb '10
26 Feb '10
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(a)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(a)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;
1
0
Author: fdesbois
Date: 2010-02-26 18:11:54 +0100 (Fri, 26 Feb 2010)
New Revision: 1778
Modified:
trunk/src/main/java/org/nuiton/util/DateUtils.java
Log:
Remove duplicated methods + refactor strange method name
Modified: trunk/src/main/java/org/nuiton/util/DateUtils.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/DateUtils.java 2010-02-26 16:28:09 UTC (rev 1777)
+++ trunk/src/main/java/org/nuiton/util/DateUtils.java 2010-02-26 17:11:54 UTC (rev 1778)
@@ -274,61 +274,17 @@
/**
* Get the date before today (so yesterday no ?)
+ *
* @param date concerned
* @return Date before today
*/
- public static Date getLastDayDate(Date date) {
- Calendar cal = Calendar.getInstance();
- cal.setTime(date);
+ public static Date getYesterday(Date date) {
+ Calendar cal = getDefaultCalendar(date);
cal.roll(Calendar.DAY_OF_MONTH, false);
-
return cal.getTime();
}
/**
- * Get the first day of the current month
- * @param date concerned
- * @return Date of first day of current month
- */
- public static Date getBeginMonthDate(Date date) {
- Calendar cal = Calendar.getInstance();
- cal.setTime(date);
- cal.set(Calendar.DAY_OF_MONTH, 1);
-
- return cal.getTime();
- }
-
- /**
- * Get the begin date of the day
- * @param date concerned
- * @return Date of the begin of the day
- */
- public static Date getBeginOfDayDate(Date date) {
- Calendar calBegin = Calendar.getInstance();
- calBegin.setTime(date);
- calBegin.set(Calendar.HOUR, 0);
- calBegin.set(Calendar.MINUTE, 0);
- calBegin.set(Calendar.SECOND, 0);
-
- return calBegin.getTime();
- }
-
- /**
- * Get the end date of the day
- * @param date concerned
- * @return Date of the end of the day
- */
- public static Date getEndOfDayDate(Date date) {
- Calendar calEnd = Calendar.getInstance();
- calEnd.setTime(date);
- calEnd.set(Calendar.HOUR, 23);
- calEnd.set(Calendar.MINUTE, 59);
- calEnd.set(Calendar.SECOND, 59);
-
- return calEnd.getTime();
- }
-
- /**
* Get the calendar corresponding to the {@code date}. The default calendar
* will be returned (default time zone and locale).
*
1
0
r1777 - in trunk/src: main/java/org/nuiton/util test/java/org/nuiton/util
by sletellier@users.nuiton.org 26 Feb '10
by sletellier@users.nuiton.org 26 Feb '10
26 Feb '10
Author: sletellier
Date: 2010-02-26 17:28:09 +0100 (Fri, 26 Feb 2010)
New Revision: 1777
Modified:
trunk/src/main/java/org/nuiton/util/StringUtil.java
trunk/src/test/java/org/nuiton/util/StringUtilTest.java
Log:
Adding method to encode to MD5
Modified: trunk/src/main/java/org/nuiton/util/StringUtil.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/StringUtil.java 2010-02-26 15:33:18 UTC (rev 1776)
+++ trunk/src/main/java/org/nuiton/util/StringUtil.java 2010-02-26 16:28:09 UTC (rev 1777)
@@ -30,6 +30,8 @@
import java.awt.Color;
import java.lang.reflect.Field;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.ParseException;
@@ -573,4 +575,30 @@
return result;
}
+ /**
+ * Convert a String to MD5
+ *
+ * @param toEncode string concerned
+ * @return md5 corresponding
+ */
+ public static String encodeMD5(String toEncode) throws NoSuchAlgorithmException {
+
+ byte[] uniqueKey = toEncode.getBytes();
+ byte[] hash = null;
+
+ // on récupère un objet qui permettra de crypter la chaine
+ hash = MessageDigest.getInstance("MD5").digest(uniqueKey);
+
+ StringBuffer hashString = new StringBuffer();
+ for (int i = 0; i < hash.length; ++i) {
+ String hex = Integer.toHexString(hash[i]);
+ if (hex.length() == 1) {
+ hashString.append("0");
+ hashString.append(hex.charAt(hex.length() - 1));
+ } else {
+ hashString.append(hex.substring(hex.length() - 2));
+ }
+ }
+ return hashString.toString();
+ }
}
Modified: trunk/src/test/java/org/nuiton/util/StringUtilTest.java
===================================================================
--- trunk/src/test/java/org/nuiton/util/StringUtilTest.java 2010-02-26 15:33:18 UTC (rev 1776)
+++ trunk/src/test/java/org/nuiton/util/StringUtilTest.java 2010-02-26 16:28:09 UTC (rev 1777)
@@ -179,5 +179,9 @@
}
+ @Test
+ public void testEncodeMD5() throws Exception {
+ assertEquals("9c4fddff843d03cefe44421acf22c6ec", StringUtil.encodeMD5("natcho"));
+ }
} // StringUtilTest
1
0
Author: sletellier
Date: 2010-02-26 16:33:18 +0100 (Fri, 26 Feb 2010)
New Revision: 1776
Modified:
trunk/src/main/java/org/nuiton/util/DateUtils.java
Log:
Adding usefull method for date manipulations
Modified: trunk/src/main/java/org/nuiton/util/DateUtils.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/DateUtils.java 2010-02-26 13:12:42 UTC (rev 1775)
+++ trunk/src/main/java/org/nuiton/util/DateUtils.java 2010-02-26 15:33:18 UTC (rev 1776)
@@ -273,6 +273,62 @@
}
/**
+ * Get the date before today (so yesterday no ?)
+ * @param date concerned
+ * @return Date before today
+ */
+ public static Date getLastDayDate(Date date) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.roll(Calendar.DAY_OF_MONTH, false);
+
+ return cal.getTime();
+ }
+
+ /**
+ * Get the first day of the current month
+ * @param date concerned
+ * @return Date of first day of current month
+ */
+ public static Date getBeginMonthDate(Date date) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.set(Calendar.DAY_OF_MONTH, 1);
+
+ return cal.getTime();
+ }
+
+ /**
+ * Get the begin date of the day
+ * @param date concerned
+ * @return Date of the begin of the day
+ */
+ public static Date getBeginOfDayDate(Date date) {
+ Calendar calBegin = Calendar.getInstance();
+ calBegin.setTime(date);
+ calBegin.set(Calendar.HOUR, 0);
+ calBegin.set(Calendar.MINUTE, 0);
+ calBegin.set(Calendar.SECOND, 0);
+
+ return calBegin.getTime();
+ }
+
+ /**
+ * Get the end date of the day
+ * @param date concerned
+ * @return Date of the end of the day
+ */
+ public static Date getEndOfDayDate(Date date) {
+ Calendar calEnd = Calendar.getInstance();
+ calEnd.setTime(date);
+ calEnd.set(Calendar.HOUR, 23);
+ calEnd.set(Calendar.MINUTE, 59);
+ calEnd.set(Calendar.SECOND, 59);
+
+ return calEnd.getTime();
+ }
+
+ /**
* Get the calendar corresponding to the {@code date}. The default calendar
* will be returned (default time zone and locale).
*
@@ -284,5 +340,4 @@
calendar.setTime(date);
return calendar;
}
-
}
1
0
r1775 - in trunk/src: main/java/org/nuiton/util test/java/org/nuiton/util
by fdesbois@users.nuiton.org 26 Feb '10
by fdesbois@users.nuiton.org 26 Feb '10
26 Feb '10
Author: fdesbois
Date: 2010-02-26 14:12:42 +0100 (Fri, 26 Feb 2010)
New Revision: 1775
Modified:
trunk/src/main/java/org/nuiton/util/DateUtils.java
trunk/src/main/java/org/nuiton/util/PeriodDates.java
trunk/src/test/java/org/nuiton/util/DateUtilsTest.java
Log:
[DateUtils - PeriodDates]
- Refactor new GregorianCalendar() by using Calendar.getInstance().
- Add getDifferenceInMonths method
- Improve javadoc
- Add comparison methods for PeriodDates with Date parameter
Modified: trunk/src/main/java/org/nuiton/util/DateUtils.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/DateUtils.java 2010-02-25 10:27:43 UTC (rev 1774)
+++ trunk/src/main/java/org/nuiton/util/DateUtils.java 2010-02-26 13:12:42 UTC (rev 1775)
@@ -24,7 +24,6 @@
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
-import java.util.GregorianCalendar;
import java.util.Locale;
/**
@@ -45,6 +44,7 @@
/**
* Format a date using the pattern in argument. The pattern is the same using
* for DateFormat object.
+ *
* @param date the date to format
* @param pattern the pattern to use
* @return a String corresponding to the date formatted
@@ -63,6 +63,7 @@
/**
* Parse a date using the pattern in argument. The pattern is the same using
* for DateFormat object.
+ *
* @param date the String to parse
* @param pattern the pattern to use
* @return a Date corresponding to the String argument parsed
@@ -77,28 +78,33 @@
/**
* Create a new date from day, month and year (French version).
- * The month is the real month of the year and not the one which is stored in Calendar object. *
+ * The month is the real month of the year and not the one which is stored
+ * in Calendar object.
+ *
* @param dd value of the day 1-31
* @param mm value of the month 1-12
* @param yy value of the year 0-9999
* @return a new date
*/
public static Date createDate(int dd, int mm, int yy) {
- Calendar calendar = new GregorianCalendar(yy,mm-1,dd);
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(Calendar.YEAR, yy);
+ calendar.set(Calendar.MONTH, mm-1);
+ calendar.set(Calendar.DAY_OF_MONTH, dd);
return calendar.getTime();
}
/**
* Create a new date after the current date (today) with modification on day, month and year.
* You can use negative values on arguments to have a date before today.
+ *
* @param ddStep nb days you want to increase from the current date
* @param mmStep nb months you want to increase from the current date
* @param yyStep nb years you want to increase from the current date
* @return a new date from the current date increase by days, months and years.
*/
public static Date createDateAfterToday(int ddStep, int mmStep, int yyStep) {
- Calendar calendar = new GregorianCalendar();
- calendar.setTime(new Date());
+ Calendar calendar = getDefaultCalendar(new Date());
calendar.add(Calendar.DAY_OF_MONTH, ddStep);
calendar.add(Calendar.MONTH,mmStep);
calendar.add(Calendar.YEAR, yyStep);
@@ -108,12 +114,12 @@
/**
* Set the last day of month to the date in argument.
* The value depends on the month of the date. (30 april, 28 february, ...)
+ *
* @param date Date to modify
* @return the date with day of month modified
*/
public static Date setLastDayOfMonth(Date date) {
- Calendar calendar = new GregorianCalendar();
- calendar.setTime(date);
+ Calendar calendar = getDefaultCalendar(date);
int maximum = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
calendar.set(Calendar.DAY_OF_MONTH, maximum);
return calendar.getTime();
@@ -121,19 +127,53 @@
/**
* Set the first day of month to the date in argument.
+ *
* @param date Date to modify
* @return the date with day of month modified
*/
public static Date setFirstDayOfMonth(Date date) {
- Calendar calendar = new GregorianCalendar();
- calendar.setTime(date);
+ Calendar calendar = getDefaultCalendar(date);
calendar.set(Calendar.DAY_OF_MONTH, 1);
return calendar.getTime();
}
/**
- * Check if the first date in argument is included between the two other dates.
- * The argument myDate can be equals to beforeDate or afterDate to validate the includes.
+ * Set the min time of the day : 00:00:00.000.
+ *
+ * @param date to modify
+ * @return Date with the time set to the minimum in the day
+ */
+ public static Date setMinTimeOfDay(Date date) {
+ Calendar calendar = getDefaultCalendar(date);
+ calendar.set(Calendar.AM_PM, Calendar.AM);
+ calendar.set(Calendar.HOUR, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ return calendar.getTime();
+ }
+
+ /**
+ * Set the max time of the day. EUROPE : 23:59:59.999.
+ *
+ * @param date to modify
+ * @return Date with the time set to the maximum in the day
+ */
+ public static Date setMaxTimeOfDay(Date date) {
+ Calendar calendar = getDefaultCalendar(date);
+ calendar.set(Calendar.AM_PM, Calendar.PM);
+ calendar.set(Calendar.HOUR, 11);
+ calendar.set(Calendar.MINUTE, 59);
+ calendar.set(Calendar.SECOND, 59);
+ calendar.set(Calendar.MILLISECOND, 999);
+ return calendar.getTime();
+ }
+
+ /**
+ * Check if the first date in argument is included between the two other
+ * dates. The argument myDate can be equals to beforeDate or afterDate to
+ * validate the includes.
+ *
* @param myDate the date to test
* @param beforeDate the first date of the period to test
* @param afterDate the second date of the period to test
@@ -151,9 +191,11 @@
/**
* Check if the current date is between the two dates in argument.
+ *
* @param beforeDate the first date of the period
* @param afterDate the second date of the period
- * @return true if the current date is included between the two dates, false either
+ * @return true if the current date is included between the two dates,
+ * false otherwise
* @see #between(java.util.Date, java.util.Date, java.util.Date)
*/
public static boolean currentPeriod(Date beforeDate, Date afterDate) {
@@ -162,12 +204,12 @@
/**
* Get the month value from a date (between 0 and 11).
+ *
* @param date the date to extract month
* @return the month value of the date
*/
public static int getMonth(Date date) {
- Calendar calendar = new GregorianCalendar();
- calendar.setTime(date);
+ Calendar calendar = getDefaultCalendar(date);
return calendar.get(Calendar.MONTH);
}
@@ -175,6 +217,7 @@
* Do the difference between the two dates in argument. The result is a number
* of days between the two dates.
* Ex : 28/01/2009 and 08/02/2009 return 11.
+ *
* @param beginDate first date
* @param endDate second date
* @return a number of days between beginDate and endDate
@@ -187,7 +230,30 @@
}
/**
+ * Do the difference between the two dates in argument. The result is a number
+ * of months between the two dates.
+ * Ex : 01/01/2009 and 28/02/2009 return 2 months.
+ * Warning, if beginDate is inferior to endDate, the result will be 1 minimum
+ *
+ * @param beginDate first date
+ * @param endDate second date
+ * @return a number of months between beginDate and endDate
+ */
+ public static int getDifferenceInMonths(Date beginDate, Date endDate) {
+ int count = 0;
+ Calendar fromCalendar = getDefaultCalendar(beginDate);
+ Calendar thruCalendar = getDefaultCalendar(endDate);
+
+ while (fromCalendar.before(thruCalendar)) {
+ fromCalendar.add(Calendar.MONTH, 1);
+ count++;
+ }
+ return count;
+ }
+
+ /**
* Get libelle of the month corresponding to the number given in argument.
+ *
* @param monthNumber between 1-12
* @param locale Locale for language support
* @return a String corresponding to the libelle of the month
@@ -198,6 +264,7 @@
/**
* Get libelle of the month corresponding to the number given in argument.
+ *
* @param monthNumber between 1-12
* @return a String corresponding to the libelle of the month
*/
@@ -205,4 +272,17 @@
return getMonthLibelle(monthNumber, Locale.getDefault());
}
+ /**
+ * Get the calendar corresponding to the {@code date}. The default calendar
+ * will be returned (default time zone and locale).
+ *
+ * @param date used to set the calendar time
+ * @return the default calendar with time corresponding to the {@code date}
+ */
+ public static Calendar getDefaultCalendar(Date date) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date);
+ return calendar;
+ }
+
}
Modified: trunk/src/main/java/org/nuiton/util/PeriodDates.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/PeriodDates.java 2010-02-25 10:27:43 UTC (rev 1774)
+++ trunk/src/main/java/org/nuiton/util/PeriodDates.java 2010-02-26 13:12:42 UTC (rev 1775)
@@ -77,7 +77,8 @@
/**
* Create a period from the date of today. If monthAfter is negative, the current day will be
* the thruDate of the period. The period extremities will be initialized (first day of month for
- * fromDate and last day of month for thruDate)
+ * fromDate and last day of month for thruDate). Time is set to 0 for both
+ * dates.
* <pre>
* Ex 1 :
* Today = 12/05/2009
@@ -93,19 +94,13 @@
* @return a new PeriodDates
*/
public static PeriodDates createMonthsPeriodFromToday(int monthAfter) {
- Calendar calendarFrom = new GregorianCalendar();
- Calendar calendarThru = new GregorianCalendar();
+ Calendar calendarFrom = Calendar.getInstance();
+ Calendar calendarThru = Calendar.getInstance();
-// calendarFrom.set(Calendar.DAY_OF_MONTH, 1);
-//
-
// Reset time
- calendarFrom.set(Calendar.AM_PM, Calendar.AM);
- calendarFrom.set(Calendar.HOUR, 0);
- calendarFrom.set(Calendar.MINUTE, 0);
- calendarFrom.set(Calendar.SECOND, 0);
- calendarFrom.set(Calendar.MILLISECOND, 0);
- calendarThru.setTime(calendarFrom.getTime());
+ Date minTime = DateUtils.setMinTimeOfDay(new Date());
+ calendarFrom.setTime(minTime);
+ calendarThru.setTime(minTime);
if (monthAfter < 0) {
calendarFrom.add(Calendar.MONTH, monthAfter);
@@ -113,12 +108,6 @@
calendarThru.add(Calendar.MONTH, monthAfter);
}
-
-// calendarThru.setTime(calendarFrom.getTime());
-
-// int maximum = calendarThru.getActualMaximum(Calendar.DAY_OF_MONTH);
-// calendarThru.set(Calendar.DAY_OF_MONTH, maximum);
-
PeriodDates period = new PeriodDates(calendarFrom, calendarThru);
period.initDayOfMonthExtremities();
period.setPattern(DateUtils.MONTH_PATTERN);
@@ -150,7 +139,7 @@
//this.fromDate = fromDate;
if (fromDate != null) {
if (fromCalendar == null) {
- fromCalendar = new GregorianCalendar();
+ fromCalendar = Calendar.getInstance();
}
fromCalendar.setTime(fromDate);
} else {
@@ -170,7 +159,7 @@
//this.thruDate = thruDate;
if (thruDate != null) {
if (thruCalendar == null) {
- thruCalendar = new GregorianCalendar();
+ thruCalendar = Calendar.getInstance();
}
thruCalendar.setTime(thruDate);
} else {
@@ -225,13 +214,34 @@
public boolean between(Calendar calendar) {
return beforeEnd(calendar) && afterBegin(calendar);
}
+
+ public boolean beforeEnd(Date date) {
+ Calendar calendar = DateUtils.getDefaultCalendar(date);
+ return beforeEnd(calendar);
+ }
+
+ public boolean afterEnd(Date date) {
+ Calendar calendar = DateUtils.getDefaultCalendar(date);
+ return afterEnd(calendar);
+ }
+
+ public boolean afterBegin(Date date) {
+ Calendar calendar = DateUtils.getDefaultCalendar(date);
+ return afterBegin(calendar);
+ }
+
+ public boolean between(Date date) {
+ Calendar calendar = DateUtils.getDefaultCalendar(date);
+ return between(calendar);
+ }
@Override
public String toString() {
String fromStr = DateUtils.formatDate(getFromDate(), pattern);
String thruStr = DateUtils.formatDate(getThruDate(), pattern);
- return "[ " + getFromDate() + " (pattern: " + fromStr + ") -> " + getThruDate() + " (pattern: " + thruStr + ") ]";
+ return "[ " + getFromDate() + " (pattern: " + fromStr + ") -> " +
+ getThruDate() + " (pattern: " + thruStr + ") ]";
}
}
Modified: trunk/src/test/java/org/nuiton/util/DateUtilsTest.java
===================================================================
--- trunk/src/test/java/org/nuiton/util/DateUtilsTest.java 2010-02-25 10:27:43 UTC (rev 1774)
+++ trunk/src/test/java/org/nuiton/util/DateUtilsTest.java 2010-02-26 13:12:42 UTC (rev 1775)
@@ -125,6 +125,32 @@
}
@Test
+ public void testGetDifferenceInMonths() {
+ System.out.println("getDifferenceInMonths");
+
+ Date beginDate = DateUtils.createDate(3, 2, 2009);
+ Date endDate = DateUtils.createDate(8, 8, 2010);
+
+ int result = DateUtils.getDifferenceInMonths(beginDate, endDate);
+ System.out.println("result1 : " + result);
+ Assert.assertEquals(19, result);
+
+ beginDate = DateUtils.createDate(1, 1, 2009);
+ endDate = DateUtils.createDate(28, 2, 2009);
+
+ result = DateUtils.getDifferenceInMonths(beginDate, endDate);
+ System.out.println("result2 : " + result);
+ Assert.assertEquals(2, result);
+
+ beginDate = DateUtils.createDate(31, 1, 2009);
+ endDate = DateUtils.createDate(1, 2, 2009);
+
+ result = DateUtils.getDifferenceInMonths(beginDate, endDate);
+ System.out.println("result3 : " + result);
+ Assert.assertEquals(1, result);
+ }
+
+ @Test
public void testGetMonthLibelle() {
System.out.println("getMonthLibelle");
1
0
25 Feb '10
Author: echatellier
Date: 2010-02-25 11:27:43 +0100 (Thu, 25 Feb 2010)
New Revision: 1774
Modified:
trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
trunk/src/site/apt/ApplicationConfig.apt
Log:
Clarification de l'ordre de prise en compte des options
Modified: trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-23 17:30:14 UTC (rev 1773)
+++ trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-25 10:27:43 UTC (rev 1774)
@@ -626,7 +626,7 @@
}
/**
- * Replace inlclude ${xxx} suboption by their values.
+ * Replace included ${xxx} suboptions by their values.
*
* @param option option to replace into
* @return replaced option
Modified: trunk/src/site/apt/ApplicationConfig.apt
===================================================================
--- trunk/src/site/apt/ApplicationConfig.apt 2010-02-23 17:30:14 UTC (rev 1773)
+++ trunk/src/site/apt/ApplicationConfig.apt 2010-02-25 10:27:43 UTC (rev 1774)
@@ -47,24 +47,25 @@
* Les options de configuration
- Le chargement de la configuration s'effectue dans cet ordre :
+ L'ordre de prise en compte des options suivant les différentes sources est
+ le suivant :
- * Valeur par défaut (renseignés à l'init)
+ * Option renseignées par programmation
- * Fichier dans le classpath ( / + nom du fichier)
+ * Ligne de commandes
- * Fichier de configuration globale ( /etc/ + nom du fichier)
+ * Propriétés systèmes (System.getProperties())
+ * Propriétés d'envirronement (System.getenv())
+
* Fichier du dossier courant ( ./ + nom du fichier)
- * Propriétés d'envirronement (System.getenv())
+ * Fichier de configuration globale ( /etc/ + nom du fichier)
- * Propriétés systèmes (System.getProperties())
+ * Fichier dans le classpath ( / + nom du fichier)
- * Ligne de commandes
+ * Valeur par défaut (renseignés à l'init)
- * Option renseignées par programmation
-
[]
Cela signifie par exemple que si une option à une valeur par défaut, est renseignée
1
0
Author: echatellier
Date: 2010-02-23 18:30:14 +0100 (Tue, 23 Feb 2010)
New Revision: 1773
Modified:
trunk/src/site/site_fr.xml
Log:
Remove todo
Modified: trunk/src/site/site_fr.xml
===================================================================
--- trunk/src/site/site_fr.xml 2010-02-23 17:27:18 UTC (rev 1772)
+++ trunk/src/site/site_fr.xml 2010-02-23 17:30:14 UTC (rev 1773)
@@ -32,10 +32,6 @@
name="Sources (jar)"/>
</menu>
- <menu name="Développeur">
- <item name="A faire" href="Todo.html"/>
- </menu>
-
<menu ref="reports"/>
</body>
1
0
Author: echatellier
Date: 2010-02-23 18:27:18 +0100 (Tue, 23 Feb 2010)
New Revision: 1772
Added:
trunk/src/site/apt/ApplicationConfig.apt
Removed:
trunk/src/site/apt/CommandLineArgumentApplication.apt
trunk/src/site/apt/Todo.apt
Modified:
trunk/src/site/apt/nuitonUtil.apt
trunk/src/site/site_fr.xml
Log:
Add ApplicationConfig doc.
Added: trunk/src/site/apt/ApplicationConfig.apt
===================================================================
--- trunk/src/site/apt/ApplicationConfig.apt (rev 0)
+++ trunk/src/site/apt/ApplicationConfig.apt 2010-02-23 17:27:18 UTC (rev 1772)
@@ -0,0 +1,294 @@
+ ----
+ ApplicationConfig
+ ----
+ ----
+ 2010-02-23
+ ----
+
+Présentation
+
+ La classe ApplicationConfig a pour but de gérer les options et action
+ disponible au sein d'une application. Elle gère aussi bien :
+
+ * la lecture de fichier de configuration
+
+ * le parsage de la ligne de commande
+
+ * l'execution des actions
+
+ * la sauvegarde de la configuration
+
+
+Lecture/écriture
+
+* Lecture des fichiers de configuration
+
+ La lecture des fichiers de configuration est effectuées lors de l'appel
+ à la methode <<<parse(String[])>>> en utilisant la valeur de
+ <<<getConfigFileName()>>> pour trouver les fichiers à lire.
+
+* La sauvegarde
+
+ La sauvegarde des options se fait via une des trois methodes disponibles :
+
+ * <<<save>>> : sauvegarde dans un fichier specifique
+
+ * <<<saveForSystem>>> : sauvegarde les donnees dans /etc
+
+ * <<<saveForUser>>> : sauvegarde les donnees dans $HOME
+
+ []
+
+ Seules les options qui ont été modifiées par l'application (par la methode
+ <<<setOption()>>> seront sauvegardée. Les variable d'envirronement, les
+ arguments de la ligne de commandes(etc...) ne seront pas sauvegardées.
+
+Fonctionnalités
+
+* Les options de configuration
+
+ Le chargement de la configuration s'effectue dans cet ordre :
+
+ * Valeur par défaut (renseignés à l'init)
+
+ * Fichier dans le classpath ( / + nom du fichier)
+
+ * Fichier de configuration globale ( /etc/ + nom du fichier)
+
+ * Fichier du dossier courant ( ./ + nom du fichier)
+
+ * Propriétés d'envirronement (System.getenv())
+
+ * Propriétés systèmes (System.getProperties())
+
+ * Ligne de commandes
+
+ * Option renseignées par programmation
+
+ []
+
+ Cela signifie par exemple que si une option à une valeur par défaut, est renseignée
+ dans le fichier /etc et sur la ligne de commande, la valeur presente sur la
+ ligne de commande sera prise en compte.
+
+* Les actions
+
+ Les actions ne peuvent être renseignées que sur la ligne de commande. Exemple :
+
++------------------------------------------------
+--org.nuiton.test.Test#doLogin user password true
++------------------------------------------------
+
+ Une action est donc définie par le chemin complet de la methode qui traitera
+ l'action. Si la methode est statique, elle sera appelée directement. Dans le
+ cas contraire, la classe contenant la methode sera instancié à partir
+ d'un constructeur prenant en parametre seulement la configuration, ou, s'il
+ n'est pas disponible, le constructeur par defaut. La methode sera ensuite
+ appelée sur cette instance. Les divers instances sont conservés pour effectué
+ plusieurs actions.
+
+ Les arguments de la methode sont utilisé lors de l'appel. On sont convertit
+ dans le bon type. Si la méthode avec des arguments de taille variante (...)
+ tous les arguments jusqu'a la prochaine option ou à la fin de la ligne
+ seront utilisé.
+
+ Si vous avez des parametres optionnels, le seul moyen est d'utiliser des
+ arguments variant.
+
+ Par exemple, la ligne de commande précédente appelera la methode
+
++-------------------------------------------
+public class Test {
+ public goLogin(String login, String password, boolean dryRun) {
+ [...]
+ }
+}
++-------------------------------------------
+
+ Les actions ne sont pas executées, mais seulement parsées. Cela signifie
+ qu'elles seront executées seulement lorsque l'application appelera la méthode
+ <<<doAction(int)>>>.
+ Par defaut, toutes les actions sont de niveau 0 et sont executées dans leur
+ ordre d'apparition sur la ligne de commande.
+ Il est possible de differencier les differentes action en utilisant l'annotation
+ <<<@Step>>>
+
++-------------------------------------------
+doAction(0);
+... do something ...
+doAction(1);
++-------------------------------------------
+
+ Dans cet exemple, les actions 0 et 1 ne sont pas effectuées au même moment.
+ C'est très utile par exemple pour executer certaines actions avant le démarrage
+ de l'UI par exemple, et d'autre après...
+
+* Les arguments non parsées
+
+ La configuration 'consome' les arguments de la ligne de commande qu'elle a
+ réussie a traiter. Pour recuperer les autres arguments propres à l'application
+ il est possible de les obtenir grace à la méthode <<<getUnparsed()>>>.
+ Si l'on souhaite forcer la fin du parsing de la ligne de commande il est
+ possible de mettre <<<-->>>.
+
+ Par exemple, la ligne suivante :
+
++-------------------------------------------
+monApplication "mon arg" --option k1 v1 -- --option k2 v2 -- autre
++-------------------------------------------
+
+ Renvera la liste suivante via <<<getUnparsed()>>> :
+
++-------------------------------------------
+"mon arg", "--option", "k2", "v2", "--", "autre"
++-------------------------------------------
+
+* Les alias
+
+ Il est possible d'utiliser des alias pour definir les options et les actions.
+ Ces alias doivent être renseignés par la methode <<<addAlias(String, String>>>:
+
++-------------------------------------------
+addAlias("-v", "--option", "verbose", "true");
+addAlias("-o", "--option", "outputfile");
+addAlias("-i", "--mon.package.MaClass#MaMethode", "import");
++-------------------------------------------
+
+ Lors du parsing de la ligne de commande, tous les alias sont remplacé par
+ leur correspondance. Il est donc possible d'utiliser ce mecanisme pour
+ autre chose :
+
++-------------------------------------------
+addAlias("cl", "Code Lutin");
++-------------------------------------------
+
+ Dans le premier exemple on simplifie une option de flags l'option -v n'attend
+ donc plus d'argument. Dans le second exemple on simplifie une option qui
+ attend encore un argment de type File. Enfin dans le troisieme exemple
+ on simplifie la syntaxe d'une action et on force le premier argument de
+ l'action a etre "import".
+
+
+* Conversion de type
+
+ Pour convertir les types des options et arguments de methodes,
+ {{{http://commons.apache.org/beanutils/}commons-beanutils}} est utilisé.
+
+ Les types actuellement supporté sont :
+
+ * <<<java.lang.String>>>
+
+ * <<<java.io.File>>>
+
+ * <<<java.net.URL>>>
+
+ * <<<java.lang.Class>>>
+
+ * <<<java.sql.Date>>>
+
+ * <<<java.sql.Time>>>
+
+ * <<<java.sql.Timestamp>>>
+
+ * Les tableaux d'un type primitif ou {@link String}. Chaque élément doit
+ être séparé par une virgule.
+
+ []
+
+ Pour utiliser d'autre type, il suffit de le enregistrer dans beanutils via
+ la mézthode <<<ConvertUtils.register(Converter, Class)>>>
+
+* Les substitutions de variable
+
+ La configuration de variable supporte la substitution par d'autre variable
+ via la synthaxe <<<$\{xxx\}>>> où <<<xxx>>> est une autre variable de
+ la configuration
+
+ Par exemple (fichier de configuration):
+
++-------------------------------------------
+application.name = Mon Appli
+application.version = 1.2.3
+application.info = ${application.name} ${application.version} (${java.version})
++-------------------------------------------
+
+ L'appel de l'option <<<application.info>>> via la methode <<<getOption()>>>
+ retournera une chaine de la forme:
+
++-------------------------------------------
+Mon Appli 1.2.3 (1.6.0_18)
++-------------------------------------------
+
+ À noter que les substitutions ne sont remplacée qu'a leur lecture, la sauvegarde
+ de l'option <<<application.info>>> se fera sans remplacement.
+
+Mise en oeuvre
+
+* Définition
+
+ Voici l'ensemble des tâches à effectuer pour définir une configuration
+ d'application :
+
+ * Creation d'une sous classes d'<<<ApplicationConfig>>>
+
+ * Ajout des options par défaut
+
+ * Creation des classes et méthodes d'actions
+
+ * Déclaration des alias des options et actions
+
+ []
+
+ Exemple :
+
++-------------------------------------------
+public class MyConfig extends ApplicationConfig {
+
+ public final static int AFTER_LOGIN = 1;
+
+ public MyConfig () {
+ // options par defaut
+ setDefaultOption("user", "anonymous");
+ setDefaultOption("password", "");
+ // ajout des alias
+ addAlias("-u", "--user");
+ addAlias("-p", "--password");
+ addActionAlias("--login", MyConfig.class.getName + "#" + doLogin");
+ }
+
+ public void setUser(String user) {
+ setOption("user", user);
+ }
+
+ public void setUser(String user) {
+ setOption("user", user);
+ }
+
+ public void doLogin(String user, String password) {
+ [...]
+ }
+
+ @Step(AFTER_LOGIN)
+ public void doSomething() {
+ [...]
+ }
+}
++-------------------------------------------
+
+* Usage
+
+ La configuration doit principalement être initilalisée grâce à la méthode
+ <<<parse(String[])>>> avant d'être utilisé.
+
++-------------------------------------------
+public static void main(String[] args) {
+ MyConfig config = new MyConfig();
+ config.setConfigFileName("myconfig.conf");
+ config.parse(args);
+
+ System.out.println("Connecting with " : + config.getOption("user"));
+ config.doAction(0);
+ System.out.println("Connected, do something...");
+ config.doAction(MyConfig.AFTER_LOGIN);
+}
++-------------------------------------------
\ No newline at end of file
Deleted: trunk/src/site/apt/CommandLineArgumentApplication.apt
===================================================================
--- trunk/src/site/apt/CommandLineArgumentApplication.apt 2010-02-23 14:26:46 UTC (rev 1771)
+++ trunk/src/site/apt/CommandLineArgumentApplication.apt 2010-02-23 17:27:18 UTC (rev 1772)
@@ -1,133 +0,0 @@
- ----
- Argument d'application
- ----
-
-Cette documentation n'est plus maintenu, faire la documentation de
-ApplicationConfig à la place.
-
-Argument d'application
-
- Il y a deux type d'argument d'application:
-
- * les arguments permettant de modifier la configuration qui peuvent aussi
- être dans un fichier de configuration ou en variable d'environnement.
-
- * les arguments permettant d'indiquer des actions a faire a l'application
-
-Les options de configuration
-
- Les options de configuration peuvent être décrit directement par un POJO
- avec des annotations::
-
------------------------------------------------------------------------------------
- @OptionConfigOrder("resource MonApp.properties", "file /etc/MonApp.properties",
- "optionfile configFile", "env", "line")
- public class MonAppConfig extends OptionConfig {
-
- @Option
- @OptionSaveFile
- public File configFile = new File("$HOME/.MonApp");
-
- @Option(pattern [^\s]+)
- public String username = "anonyous";
-
- @Option(pattern ..)
- public String lang = "fr";
-
- @Option(pattern ..)
- public String country = "FR";
-
- @Option
- public boolean showGui = true;
-
- @Option(min=10, max=10)
- public List<Integer> value;
-
- @Unparsed
- public List<String> other;
- }
------------------------------------------------------------------------------------
-
-La classe OptionConfig
-
- La classe OptionConfig contient plusieurs méthodes:
-
- * load sans argument qui permet de charger le POJO en fonction de
- OptionConfigOrder
-
- * load(File) qui permet de charger le POJO seulement en fonction d'un
- fichier. Il bien sur possible d'appeler load() puis load(File).
-
- * save qui permet de sauver les informations du POJO, le fichier ou sauver
- les options est indiqué par l'annotation <<<@OptionSaveFile>>>
-
-Annotation OptionConfigOrder
-
- OptionConfigOrder permet de déterminer l'ordre de recherche de la bonne
- valeur des options. Le dernier indiqué sera le dernier lu et donc celui qui
- aura raison.
-
- * resource
- indique un fichier resource a rechercher dans le classpath
-
- * file
- indique un fichier sur le systeme de fichier
-
- * optionfile
- indique un fichier dont le chemin est indiqué par une option
-
- * env
- indique les variables d'environnement du processus
-
- * sline
- indique les options sur la ligne de commande
-
-Implantation
-
- * On charge dans un objet <<Properties>> chaque entre de
- <<OptionConfigOrder>> sauf <<optionfile>> s'il y en a.
-
- * On chaine tous les fichiers de proprietes pour pouvoir demander
- l'information au dernier qui recherchera lui meme dans son pere s'il n'a pas
- l'information.
-
- * Pour chaque <<optionfile>> on demande sa valeur, on crée le fichier de
- propriété et on l'ajoute dans la chaine à la bonne place
-
- * Pour chaque option trouvé dans le POJO on met a jour sa valeur avec la
- valeur trouvé dans les propriétés.
-
-Annotation Option
-
- Indique une option possible. Elle peut contenir:
-
- * description
-
- * pattern
-
- * alias
-
- * min
-
- * max
-
- Par defaut l'option sur la ligne de commande sera le nom de la variable precedé de --
-
-Annotation Unparsed
-
- Indique que toutes les options de la ligne de commande non reconnu finisse dans ce champs
- Il est possible de type la collection autrement que par String.
-
-Annotation OptionSaveFile
-
- Indique le fichier a utiliser pour sauver les options
-
-* Les actions
-
- TODO: comment différencier les actions des options ? comment reutiliser le travail de tony ?
-
-* Amélioration possible
-
- - Générer automatiquement par un plugin maven les methodes get/set sur les options
- - Gérer les options read/write et read
- - un plugin maven qui verifie la coherence des options
Deleted: trunk/src/site/apt/Todo.apt
===================================================================
--- trunk/src/site/apt/Todo.apt 2010-02-23 14:26:46 UTC (rev 1771)
+++ trunk/src/site/apt/Todo.apt 2010-02-23 17:27:18 UTC (rev 1772)
@@ -1,91 +0,0 @@
- ----
- TODO
- ----
- ----
- 2009-08-23
- ----
-
-Un nouveau parser d'argument
-
- L'idée est d'avoir une description simple des arguments et de leur type et
- que soit généré une classe à partir de cette description. Dans le
- programme il suffirat de demander à la classe généré les inforamtions.
-
- Les options sont chargées par leur valeur par defaut, puis sont surchargées
- par les valeurs des fichiers de configurations, puis surchargé
- par les valeurs des variables d'environnement, et enfin surchargé par les
- valeurs de la ligne de commande.
-
- Les fichiers de configuraiton sont lu dans l'ordre suivant: /etc/ + chemin
- indiqué, puis $HOME/. + chemin indiqué.
-
- si le chemin indiqué est titi/toto.conf et que l'on est sur un système Linux
- les fichiers de configuration seront: /etc/titi/toto.conf et
- ~/.titi/toto.conf
-
-* exemple de description
-
- Par exemple on pourrait avoir le fichier Toto.java.conf dans les sources du
- projet qui fournirait le fichier Toto.java::
-
-----------------------------------------------------------------------------
- configfile: titi/toto.conf
-
- outFile: le fichier de sortie
- short: o
- long: outfile
- default: -
- type: File
- environment: toto
-
- number: Le nombre de fichier à produire
- required: 1
- short: n
- default: 1
- long: number
- condition: 0<Number && Number<10
- type: int
-----------------------------------------------------------------------------
-
- La description commence l'option non obligatoire *configfile* qui donne le
- nom du fichier de configuration à utiliser pour l'application. Puis on
- trouve les options. Une option commence par un nom, puis sa description
- ensuite l'option peut avoir plusieurs options:
-
-
- * short: l'option courte sur la ligne de commande. Si absente pas d'option
- courte
-
- * long: l'option longue sur la ligne de commande, si pas d'option, on
- reprend le nom de l'option
-
- * type: le type de l'option (int, Float, String, char, File, ...)
-
- * default: la valeur par default, si elle n'est pas specifier sur la ligne
- de commande, ni dans les variables d'environnement ni dans le fichier de
- configuration. Pour une option de type File si default faut -, alors
- le fichier est la sortie standard.
-
- * condition: la condition que doit respecter l'option pour être valide
- la condition est une expression java contenant le nom de l'option comme
- valeur de variable.
-
- * environment: le nom de la variable d'environnement qu'il faut utiliser
- si l'option n'est pas retrouve sur la ligne de commande. Si cette option
- n'est pas indiqué alors, la variable d'environnement recherchée est le nom
- du fichier de description suivi d'un point, suivi du nom de l'option.
- par exemple toto.outfile
-
-
- L'objet résultat sera Toto placé dans le fichier Toto.java. L'extension
- java.conf est obligatoire pour détecter un fichier de configuration à
- parser. Cet objet aurai les méthodes getOutputFile():File et getNumber():int
-
-* Librairies utilisé
-
- Sans doute utilisé, le parser redwood pour le fichier de configuration
- {{http://www.isellrenohomes.com/parser/}}. Il lit directement des EBNF.
-
-* projet de parsage d'argument
-
- {{http://www.martiansoftware.com/jsap/}}
Modified: trunk/src/site/apt/nuitonUtil.apt
===================================================================
--- trunk/src/site/apt/nuitonUtil.apt 2010-02-23 14:26:46 UTC (rev 1771)
+++ trunk/src/site/apt/nuitonUtil.apt 2010-02-23 17:27:18 UTC (rev 1772)
@@ -31,59 +31,6 @@
classpath, et si elle n'est toujours pas trouvée une exception est
alors levée.
-ArgumentsParser
-
- Cette librairie permet de traiter les arguments de la ligne de commande de
- façon simple mais évoluable. Son principe de fonctionnement est que l'on
- déclare les arguements que l'on attend sur la ligne de commande avec le nombre
- de paramètre qu'ils prennent et une petite description de l'option. Ensuite
- on dispose de toutes les fonctions utiles pour le traitement de la ligne de
- commande.
-
- Voici un exemple d'utilisation
-
-------------------------------------------------------------------------------
- import org.nuiton.util.ArgumentsParser;
- ...
- ArgumentsParser parser = new ArgumentsParser("ToPIA");
-
- parser.addOption("version", "affiche le numéro de version", new String[]{"--version", "-v"}, 0).setRepetitionMax(1);
-
- parser.addOption("help", "affiche l'aide de topia", new String[]{"--help", "-h"}, 0).setRepetitionMax(1);
-
- parser.addOption("start", "Lancement d'une application", new
- String[]{"--start", "-s"}, 1).setRepetitionMax(1);
-
- System.out.println(parser.checkCoherence());
- parser.parse(args);
-
- if(parser.hasParsedOption("help")){
- System.out.println(parser.usage());
- }else if (parser.hasParsedOption("start")){
- System.out.println ("--> Executing application: ");
- String arg = parser.getParsedOption("start")
- new Application(arg);
- }else if (parser.hasParsedOption("version")){
- System.out.println( "- Topia version 0.01 - " +
- "Get new release at http://www.codelutin.com/ -" );
- }
-------------------------------------------------------------------------------
-
- Cette librairie permet d'afficher l'aide de la ligne de commande::
-
-------------------------------------------------------------------------------
- System.out.println(parser.usage());
-------------------------------------------------------------------------------
-
- Elle permet aussi de vérifier le nombre de fois qu'une option de la ligne de
- commande est présente et que ce nombre est bien compris dans l'ensemble des
- valeurs acceptées, grâce au méthode *setRepetitionMax*, et *setRepetitionMin*.
-
- Si l'implantation par défaut du parseur d'option ne convient pas pour une de vos
- option, par exemple si le nombre de paramètre de l'option varie suivant la valeur
- du premier paramètre vous pouvez alors écrire votre propre Parser pour cette
- Option et l'utilisée avec les autres.
-
Log
Cette objet permet de suivre ce que fait une application simplement. Le
@@ -313,10 +260,18 @@
MD5 dans un flux.
-** DateUtils (since 1.1.2)
+** DateUtils //(since 1.1.2)//
Boîte à outils sur les dates (plus spécialisé que org.apache.commons.lang.DateUils)
-** PeriodDates (since 1.1.2)
+** PeriodDates //(since 1.1.2)//
Objet correspondant à une période entre deux dates avec contraintes et méthodes utilitaires.
+
+** FileUtil#grep() //(since 1.1.2)//
+
+ Unix like grep command
+
+** FileUtil#sed() //(since 1.1.2)//
+
+ Unix like sed command
Modified: trunk/src/site/site_fr.xml
===================================================================
--- trunk/src/site/site_fr.xml 2010-02-23 14:26:46 UTC (rev 1771)
+++ trunk/src/site/site_fr.xml 2010-02-23 17:27:18 UTC (rev 1772)
@@ -19,7 +19,7 @@
<menu name="Utilisateur">
<item name="Accueil" href="index.html"/>
<item name="Documentation" href="/nuitonUtil.html"/>
- <item name="Application config" href="/CommandLineArgumentApplication.html"/>
+ <item name="Application config" href="/ApplicationConfig.html"/>
<item name="War launcher" href="/Warlauncher.html"/>
</menu>
1
0
Author: echatellier
Date: 2010-02-23 15:26:46 +0100 (Tue, 23 Feb 2010)
New Revision: 1771
Modified:
trunk/src/test/java/org/nuiton/util/ApplicationConfigTest.java
Log:
Add a test on unparsed options
Modified: trunk/src/test/java/org/nuiton/util/ApplicationConfigTest.java
===================================================================
--- trunk/src/test/java/org/nuiton/util/ApplicationConfigTest.java 2010-02-23 14:04:37 UTC (rev 1770)
+++ trunk/src/test/java/org/nuiton/util/ApplicationConfigTest.java 2010-02-23 14:26:46 UTC (rev 1771)
@@ -27,6 +27,7 @@
import java.util.ListIterator;
import java.util.Map;
+import junit.framework.Assert;
import junit.framework.TestCase;
import org.nuiton.util.ApplicationConfig.Action;
@@ -202,7 +203,7 @@
dummyActionCall = 0;
result.doAction();
assertEquals(1, dummyActionCall);
-}
+ }
/**
* Test of parse method, of class ApplicationConfig.
@@ -257,4 +258,20 @@
instance.setOption("notexists", "Attention ${blah.bloh.bluh} :(");
assertEquals("Attention ${blah.bloh.bluh} :(", instance.getOption("notexists"));
}
+
+ /**
+ * Test unparsed options
+ */
+ public void testUnparsed() throws Exception {
+
+ String[] args = "test --du i_am_a_test 2 --option file f1 --option verbose false -- --openui false --m coucou 10 others args".split(" ");
+ ApplicationConfig instance = new ApplicationConfig();
+ instance.addActionAlias("--du", DummyAction.class.getName() + "#" + "dummyAction");
+ instance.parse(args);
+ instance.doAction(1);
+
+ System.out.println(instance.getUnparsed());
+ Assert.assertEquals(8, instance.getUnparsed().size());
+ Assert.assertEquals("test", instance.getUnparsed().get(0));
+ }
}
1
0
Author: echatellier
Date: 2010-02-23 15:04:37 +0100 (Tue, 23 Feb 2010)
New Revision: 1770
Modified:
trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
Log:
Fix usage javadoc
Modified: trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-23 13:15:12 UTC (rev 1769)
+++ trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-23 14:04:37 UTC (rev 1770)
@@ -14,6 +14,7 @@
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%* */
+
package org.nuiton.util;
import org.apache.commons.beanutils.ConstructorUtils;
@@ -69,7 +70,8 @@
*
* <h3>Usage</h3>
* Create subclass of {@link ApplicationConfig}, where in constructor you call
- * {@link #addAlias(String, String[])}, {@link #setConfigFileName(String)}
+ * {@link #setConfigFileName(String)}, {@link #setDefaultOption(String, String)},
+ * {@link #addAlias(String, String[])}, {@link #addActionAlias(String, String)},
* to have properly value.
* <pre>
* conf = new MonAppConfig();
1
0
Author: echatellier
Date: 2010-02-23 14:15:12 +0100 (Tue, 23 Feb 2010)
New Revision: 1769
Modified:
trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
Log:
Reorder javadoc tags
Modified: trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-23 13:14:05 UTC (rev 1768)
+++ trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-23 13:15:12 UTC (rev 1769)
@@ -244,10 +244,9 @@
* </pre>
* <tt>getOption("fullname")</tt> retournera <tt>"John Doe"</tt>.
*
+ * @since 0.30
* @author poussin
* @version $Revision$
- * @since 0.30
- *
* <p/>
* Last update $Date$ by $Author$
*/
1
0
Author: echatellier
Date: 2010-02-23 14:14:05 +0100 (Tue, 23 Feb 2010)
New Revision: 1768
Modified:
trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
Log:
Add link on types
Modified: trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-23 10:38:40 UTC (rev 1767)
+++ trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-23 13:14:05 UTC (rev 1768)
@@ -218,15 +218,15 @@
* sont:
* <ul>
* <li> les primitif (byte, short, int, long, float, double, char, boolean)
- * <li> String
- * <li> File
- * <li> URL
- * <li> Class
- * <li> SqlDate
- * <li> SqlTime
- * <li> SqlTimestamps
- * <li> les tableaux d'un type primitif ou String. Chaque element doit etre
- * separe par une virgule
+ * <li> {@link String}
+ * <li> {@link File}
+ * <li> {@link URL}
+ * <li> {@link Class}
+ * <li> Sql{@link Date}
+ * <li> Sql{@link Time}
+ * <li> Sql{@link Timestamp}
+ * <li> les tableaux d'un type primitif ou {@link String}. Chaque element doit
+ * etre separe par une virgule.
* </ul>
*
* Pour suporter d'autre type, il vous suffit d'enregistrer de nouveau
1
0
Author: echatellier
Date: 2010-02-23 11:38:40 +0100 (Tue, 23 Feb 2010)
New Revision: 1767
Modified:
trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
trunk/src/main/java/org/nuiton/util/ArgumentsParserException.java
Log:
Update ApplicationConfig javadoc
Modified: trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-21 19:37:40 UTC (rev 1766)
+++ trunk/src/main/java/org/nuiton/util/ApplicationConfig.java 2010-02-23 10:38:40 UTC (rev 1767)
@@ -50,68 +50,64 @@
import java.beans.PropertyChangeListener;
/**
- * <h1>To do</h1>
- * <p/>
+ * Application configuration.
+ *
+ * <h3>TODO</h3>
* <ul>
- * <li> ajout d'annotations sur les methodes
- * pour precisser plus de chose pour les options (pattern, min/max, alias,
+ * <li>Ajout d'annotations sur les methodes
+ * pour preciser plus de chose pour les options (pattern, min/max, alias,
* description, ...)
- * <li> trouver un moyen de document les options et actions pour automatiquement
+ * <li>Trouver un moyen de document les options et actions pour automatiquement
* generer l'aide en ligne. Pour eviter de devoir maintenir une methode
* dans lequel est ecrit l'aide en plus des options.
- * <li> prise en compte du flag {@link #useOnlyAliases}
- * <li> vu qu'en java on ne peut pas pointer une methode mais seulement une classe
+ * <li>Prise en compte du flag {@link #useOnlyAliases}
+ * <li>Vu qu'en java on ne peut pas pointer une methode mais seulement une classe
* il y a un bout des actions qui sont des chaines (nom de la methode). Il faudrait
* faire un plugin maven qui check que l'action existe bien durant la compilation.
* Il est simple de le faire a l'execution mais c trop tard :(
* </ul>
- * <p/>
- * <h1>Usage</h1>
- * <li> create subclass of ApplicationConfig, where in constructor you call
- * addAliases, setConfigFileName, setDefaultActionPackage, setDefaultActionClass, setDefaultActionMethod
+ *
+ * <h3>Usage</h3>
+ * Create subclass of {@link ApplicationConfig}, where in constructor you call
+ * {@link #addAlias(String, String[])}, {@link #setConfigFileName(String)}
* to have properly value.
- * <p/>
- * <li> conf = new MonAppConfig();
- * <li> conf.parse(args);
- * <li> here you can used conf.getOption(key);
- * <li> conf.doAction(0);
- * <li> ...
- * <li> conf.doAction(n);
- * <p/>
- * <h1>Lecture des fichiers de configuration</h1>
- * <p/>
- * <p/>
+ * <pre>
+ * conf = new MonAppConfig();
+ * conf.parse(args);
+ * here you can used conf.getOption(key);
+ * conf.doAction(0);
+ * ...
+ * conf.doAction(n);
+ * </pre>
+ *
+ * <h3>Lecture des fichiers de configuration</h3>
+ *
* La lecture des fichiers de configuration se fait durant l'appel de la methode
* {@link #parse} en utilisant la valeur de {@link #getConfigFileName} pour
* trouver les fichiers (voir Les options de configuration pour l'ordre de
* chargement des fichiers)
- * <p/>
- * <h1>La sauvegarde</h1>
- * <p/>
- * <p/>
- * La sauvegarde des options se fait via une des trois methodes disponible
- * <p/>
+ *
+ * <h3>La sauvegarde</h3>
+ * La sauvegarde des options se fait via une des trois methodes disponibles :
* <ul>
* <li> {@link #save(File, boolean,String[])} sauve les données dans le fichier demandé
* <li> {@link #saveForSystem} sauvegarde les donnees dans /etc
* <li> {@link #saveForUser} sauvegarde les donnees dans $HOME
* </ul>
- * <p/>
- * Lors de l'utilisation de la methode {@link #saveForSystem(String[])} ou
- * {@link #saveForUser(String[])} seul les options lu dans un fichier ou modifier par
- * programmation ({@link #setOption} seront sauvegardees. Par exemple les
+ *
+ * Lors de l'utilisation de la methode {@link #saveForSystem} ou
+ * {@link #saveForUser} seules les options lues dans un fichier ou modifiées par
+ * programmation ({@link #setOption} seront sauvegardées. Par exemple les
* options passees sur la ligne de commande ne seront pas sauvees.
- * <p/>
- * <h1>Les options de configuration</h1>
- * <p/>
- * <p/>
+ *
+ * <h3>Les options de configuration</h3>
+ *
* Cette classe permet de lire les fichiers de configuration, utiliser les
* variable d'environnement et de parser la ligne de commande. L'ordre de prise
- * en compte des informations trouvées est la suivante (le premier le plus
- * important).
- * <p/>
+ * en compte des informations trouvées est le suivant (le premier le plus
+ * important) :
* <ul>
- * <li>options ajoutees par programmation: {@link #setOption}(key, value)</li>
+ * <li>options ajoutees par programmation: {@link #setOption(String, String)}</li>
* <li>ligne de commande</li>
* <li>variable d'environnement de la JVM: java -Dkey=value</li>
* <li>variable d'environnement; export key=value</li>
@@ -121,14 +117,14 @@
* <li>fichier de configuration trouve dans le classpath: $CLASSPATH/filename</li>
* <li>options ajoutees par programmation: {@link #defaults}.put(key, value)</li>
* </ul>
- * <p/>
- * <p/>
+ *
+ *
* Les options sur la ligne de commande sont de la forme:
* <pre>
* --option key value
* --monOption key value1 value2
* </pre>
- * <p/>
+ *
* <ul>
* <li>--option key value: est la syntaxe par defaut
* <li>--monOption key value1 value2: est la syntaxe si vous avez ajouter une
@@ -137,16 +133,15 @@
* arguments que vous souhaitez du moment qu'ils soient convertibles de la
* representation String vers le type que vous avez mis.
* </ul>
- * <p/>
- * <h1>Les actions</h1>
- * <p/>
- * Les actions ne peuvent etre que sur la ligne de commande. Ils sont de la
+ *
+ * <h3>Les actions</h3>
+ *
+ * Les actions ne peuvent etre que sur la ligne de commande. Elles sont de la
* forme:
* <pre>
* --le.package.LaClass#laMethode arg1 arg2 arg3 ... argN
* </pre>
- * <p/>
- * <p/>
+ *
* Une action est donc defini par le chemin complet vers la methode qui traitera
* l'action. Cette methode peut-etre une methode static ou non. Si la methode
* n'est pas static lors de l'instanciation de l'objet on essaie de passer en
@@ -158,40 +153,32 @@
* parties d'un meme objet utiliseront la meme instance de cette objet lors
* de leur execution.
* <p/>
- * <p/>
* Si la methode utilise les arguments variants alors tous les arguments
* jusqu'au prochain -- ou la fin de la ligne de commande sont utilises. Sinon
* Le nombre exact d'argument necessaire a la methode sont utilises.
* <p/>
- * <p/>
* Les arguments sont automatiquement converti dans le bon type reclame par la
* methode.
* <p/>
- * <p/>
* Si l'on veut des arguments optionnels le seul moyen actuellement est
* d'utiliser une methode avec des arguments variants
* <p/>
- * <p> Les actions ne sont pas execute mais seulement parsees. Pour les executer
- * il faut utiilser la methode {@link #doAction} qui prend en argument un numero
+ * Les actions ne sont pas execute mais seulement parsees. Pour les executer
+ * il faut utiliser la méthode {@link #doAction} qui prend en argument un numero
* de 'step'. Par defaut toutes les actions sont de niveau 0 et sont executee
* dans l'ordre d'apparition sur la ligne de commande. Si l'on souhaite
* distinguer les actions il est possible d'utiliser l'annotation
* {@link ApplicationConfig.Action.Step} sur la methode qui fera l'action en
* precisant une autre valeur que 0.
- * <p/>
* <pre>
* doAction(0);
* ... do something ...
* doAction(1);
* </pre>
- * <p/>
- * <p/>
* dans cette exemple on fait un traitement entre l'execution des actions
* de niveau 0 et les actions de niveau 1.
- * <p/>
- * <h1>Les arguments non parses</h1>
- * <p/>
- * <p/>
+ *
+ * <h3>Les arguments non parsées</h3>
* Tout ce qui n'est pas option ou action est considere comme non parse et peut
* etre recupere par la methode {@link #getUnparsed}. Si l'on souhaite forcer
* la fin du parsing de la ligne de commande il est possible de mettre --.
@@ -199,45 +186,36 @@
* <pre>
* monProg "mon arg" --option k1 v1 -- --option k2 v2 -- autre
* </pre>
- * <p/>
- * <p/>
* Dans cet exemple seule la premiere option sera considere comme une option.
- * On retrouvera dans unparsed: "mon arg", "--option", "k2", "v2", "--", "autre"
- * <p/>
- * <h1>Les alias</h1>
- * <p/>
+ * On retrouvera dans {@code unparsed}: "mon arg", "--option", "k2", "v2", "--",
+ * "autre"
+ *
+ * <h3>Les alias</h3>
* On voit qu'aussi bien pour les actions que pour les options, le nom de la
* methode doit etre utilise. Pour eviter ceci il est possible de definir
* des alias ce qui permet de creer des options courtes par exemple. Pour cela,
* on utilise la methode {@link #addAlias}.
- * <p/>
* <pre>
* addAlias("-v", "--option", "verbose", "true");
* addAlias("-o", "--option", "outputfile");
* addAlias("-i", "--mon.package.MaClass#MaMethode", "import");
* </pre>
- * <p/>
- * <p/>
* En faite avant le parsing de la ligne de commande tous les alias trouves sont
* automatiquement remplacer par leur correspondance. Il est donc possible
* d'utiliser ce mecanisme pour autre chose par exemple:
- * <p/>
* <pre>
* addAlias("cl", "Code Lutin");
* addAlias("bp", "Benjamin POUSSIN);
* </pre>
- * <p/>
- * <p/>
* Dans le premier exemple on simplifie une option de flags l'option -v n'attend
* donc plus d'argument. Dans le second exemple on simplifie une option qui
* attend encore un argment de type File. Enfin dans le troisieme exemple
* on simplifie la syntaxe d'une action et on force le premier argument de
* l'action a etre "import".
- * <p/>
- * <h1>Conversion de type</h1>
- * Pour la conversion de type nous utilisons common-beans. Les types supporte
+ *
+ * <h3>Conversion de type</h3>
+ * Pour la conversion de type nous utilisons common-beans. Les types supportes
* sont:
- * <p/>
* <ul>
* <li> les primitif (byte, short, int, long, float, double, char, boolean)
* <li> String
@@ -250,29 +228,44 @@
* <li> les tableaux d'un type primitif ou String. Chaque element doit etre
* separe par une virgule
* </ul>
+ *
+ * Pour suporter d'autre type, il vous suffit d'enregistrer de nouveau
+ * converter dans commons-beans.
+ *
+ * <h3>Les substitutions de variable</h3>
+ * {@link ApplicationConfig} supporte les substition de variables de la forme
+ * <tt>${xxx}</tt> où {@code xxx} est une autre variable de la configuration.
* <p/>
- * Pour suporter d'autre type, il vous suffit d'enregistrer de nouveau
- * converter dans commons-beans
- *
+ * Exemple (dans un fichier de configuration):
+ * <pre>
+ * firstname = John
+ * lastname = Doe
+ * fullname = ${firstname} ${lastname}
+ * </pre>
+ * <tt>getOption("fullname")</tt> retournera <tt>"John Doe"</tt>.
+ *
* @author poussin
* @version $Revision$
* @since 0.30
- * <p/>
- * Last update $Date$
- * by $Author$
+ *
+ * <p/>
+ * Last update $Date$ by $Author$
*/
public class ApplicationConfig {
/** to use log facility, just put in your code: log.info(\"...\"); */
static private Log log = LogFactory.getLog(ApplicationConfig.class);
- /**
- * used to know what is separator between la class et la method sur la
- * ligne de commande
- */
+
+ /** Used to know what is separator between class and method on command line. */
static final private String CLASS_METHOD_SEPARATOR = "#";
+
+ /** Configuration file key option. */
static final public String CONFIG_FILE_NAME = "config.file";
+
protected boolean useOnlyAliases = false;
+
protected Map<String, List<String>> aliases = new HashMap<String, List<String>>();
+
/** file /etc/[filename] */
String systemPath = File.separator + "etc" + File.separator;
/** file $user.home/.[filename] */
@@ -280,8 +273,10 @@
String userPath = getUserHome() + File.separator + ".";
/** file $user.home/.local/[filename] */
//String userPath2 = getUserHome() + File.separator + ".config" + File.separator;
- /** vrai si on est en train de parser les options de la ligne de commande */
+
+ /** vrai si on est en train de parser les options de la ligne de commande. */
protected boolean inParseOptionPhase = false;
+
protected Properties defaults = new Properties();
protected Properties classpath = new Properties(defaults);
protected Properties etcfile = new Properties(classpath);
@@ -296,7 +291,8 @@
/** contient apres l'appel de parse, la liste des arguments non utilises */
protected List<String> unparsed = new ArrayList<String>();
protected Map<Integer, List<Action>> actions = new HashMap<Integer, List<Action>>();
- /** suport of config modification */
+
+ /** suport of config modification. */
protected PropertyChangeSupport pcs = new PropertyChangeSupport(this);
/**
@@ -384,17 +380,31 @@
}
}
+ /**
+ * Init ApplicationConfig with current simple class name as config file.
+ *
+ * Also init converters.
+ * @see ConverterUtil#initConverters()
+ */
public ApplicationConfig() {
setConfigFileName(this.getClass().getSimpleName());
// init extra-converters
ConverterUtil.initConverters();
}
+ /**
+ * Get user home directory (system property {@code user.home}).
+ * @return user home directory
+ */
static public String getUserHome() {
String result = System.getProperty("user.home");
return result;
}
+ /**
+ * Get user name (system property {@code user.name}).
+ * @return user name
+ */
public String getUsername() {
String result = getOption("user.name");
return result;
@@ -412,7 +422,7 @@
}
/**
- * Save configuration, in specified file
+ * Save configuration, in specified file.
*
* @param file file where config will be writen
* @param forceAll if true save all config option
@@ -515,6 +525,18 @@
}
}
+ /**
+ * Do action in specified step.
+ *
+ * @param step do action only defined in this step
+ *
+ * @throws IllegalAccessException
+ * @throws IllegalArgumentException
+ * @throws InvocationTargetException
+ * @throws InstantiationException
+ *
+ * @see Action.Step
+ */
public void doAction(int step) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
List<Action> list = actions.get(step);
if (list != null) {
@@ -533,7 +555,7 @@
}
/**
- * All argument in aliases as key is substitued by target
+ * All argument in aliases as key is substitued by target.
*
* @param alias alias string as '-v'
* @param target substitution as '--option verbose true'
@@ -564,13 +586,17 @@
setDefaultOption(CONFIG_FILE_NAME, name);
}
+ /**
+ * Get name of file where options are read (in /etc, $HOME, $CURDIR).
+ * @return name of file
+ */
public String getConfigFileName() {
String result = getOption(CONFIG_FILE_NAME);
return result;
}
/**
- * Set option value
+ * Set option value.
*
* @param key property key
* @param value property value
@@ -584,7 +610,9 @@
}
/**
- * get option value as string
+ * get option value as string.
+ *
+ * Replace inner ${xxx} value.
*
* @param key the option's key
* @return String representation value
@@ -643,7 +671,7 @@
/**
* Permet de recuperer l'ensemble des options commencant par une certaine
- * chaine
+ * chaine.
*
* @param prefix debut de cle a recuperer
* @return la liste des options filtrées
@@ -661,7 +689,7 @@
}
/**
- * get option value from a option definition
+ * Get option value from a option definition.
*
* @param key the definition of the option
* @return the value for the given option
@@ -672,14 +700,13 @@
}
/**
- * get option value as typed value
+ * Get option value as typed value.
*
* @param <T> type of the object wanted as return type
* @param clazz type of object wanted as return type
* @param key the option's key
* @return typed value
*/
- @SuppressWarnings("unchecked")
public <T> T getOption(Class<T> clazz, String key) {
T result = null;
String cacheKey = key + "-" + clazz.getName();
@@ -695,7 +722,7 @@
if (cacheItem == null || cacheItem.hash != hash) {
// prefer use our convertert method (auto-register more converters)
result = ConverterUtil.convert(clazz, value);
-// result = (T) ConvertUtils.convert(value, clazz);
+ // result = (T) ConvertUtils.convert(value, clazz);
cacheItem = new CacheItem<T>(result, hash);
cacheOption.put(cacheKey, cacheItem);
} else {
@@ -706,10 +733,10 @@
}
/**
- * get option value as typed value
+ * Get option value as {@link File}.
*
* @param key the option's key
- * @return typed value
+ * @return value as file
*/
public File getOptionAsFile(String key) {
File result = getOption(File.class, key);
@@ -718,10 +745,10 @@
}
/**
- * get option value as typed value
+ * Get option value as {@link URL}.
*
* @param key the option's key
- * @return typed value
+ * @return value as URL
*/
public URL getOptionAsURL(String key) {
URL result = getOption(URL.class, key);
@@ -729,10 +756,10 @@
}
/**
- * get option value as typed value
+ * Get option value as {@link Class}.
*
* @param key the option's key
- * @return typed value
+ * @return value as Class
*/
public Class<?> getOptionAsClass(String key) {
Class<?> result = getOption(Class.class, key);
@@ -740,10 +767,10 @@
}
/**
- * get option value as typed value
+ * Get option value as {@link Date}.
*
* @param key the option's key
- * @return typed value
+ * @return value as Date
*/
public Date getOptionAsDate(String key) {
Date result = getOption(Date.class, key);
@@ -751,10 +778,10 @@
}
/**
- * get option value as typed value
+ * Get option value as {@link Time}.
*
* @param key the option's key
- * @return typed value
+ * @return value as Time
*/
public Time getOptionAsTime(String key) {
Time result = getOption(Time.class, key);
@@ -762,10 +789,10 @@
}
/**
- * get option value as typed value
+ * Get option value as {@link Timestamp}.
*
* @param key the option's key
- * @return typed value
+ * @return value as Timestamp
*/
public Timestamp getOptionAsTimestamp(String key) {
Timestamp result = getOption(Timestamp.class, key);
@@ -773,10 +800,10 @@
}
/**
- * get option value as typed value
+ * Get option value as {@code int}.
*
* @param key the option's key
- * @return typed value
+ * @return value as {@code int}
*/
public int getOptionAsInt(String key) {
Integer result = getOption(Integer.class, key);
@@ -784,10 +811,10 @@
}
/**
- * get option value as typed value
+ * Get option value as {@code double}.
*
* @param key the option's key
- * @return typed value
+ * @return value as {@code double}
*/
public double getOptionAsDouble(String key) {
Double result = getOption(Double.class, key);
@@ -795,10 +822,10 @@
}
/**
- * get option value as typed value
+ * Get option value as {@code boolean}.
*
* @param key the option's key
- * @return typed value
+ * @return value as {@code boolean}.
*/
public boolean getOptionAsBoolean(String key) {
Boolean result = getOption(Boolean.class, key);
@@ -816,7 +843,7 @@
/**
* Set manually options when you don't want to use parse method to check
- * properties file configured by setConfigFileName.
+ * properties file configured by {@link #setConfigFileName}.
*
* @param options Properties which contains all options to set
*/
@@ -825,7 +852,7 @@
}
/**
- * Get all set method on this object or super object
+ * Get all set method on this object or super object.
*
* @return map with method name without set and in lower case as key, and
* method as value
@@ -962,7 +989,6 @@
*
* @param args argument as main(String[] args)
* @throws ArgumentsParserException
- *
*/
public void parse(String[] args) throws ArgumentsParserException {
try {
Property changes on: trunk/src/main/java/org/nuiton/util/ApplicationConfig.java
___________________________________________________________________
Deleted: svn:mergeinfo
-
Added: svn:keywords
+ Author Date Id Revision HeadURL
Modified: trunk/src/main/java/org/nuiton/util/ArgumentsParserException.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/ArgumentsParserException.java 2010-02-21 19:37:40 UTC (rev 1766)
+++ trunk/src/main/java/org/nuiton/util/ArgumentsParserException.java 2010-02-23 10:38:40 UTC (rev 1767)
@@ -18,7 +18,7 @@
package org.nuiton.util;
/**
- * Argument parsing exception
+ * Argument parsing exception.
*
* @author Benjamin Poussin <poussin(a)codelutin.com>
* Copyright Code Lutin
@@ -32,10 +32,21 @@
/** serialVersionUID. */
private static final long serialVersionUID = 8265924907001359910L;
+ /**
+ * Constructs a new exception with the specified detail message.
+ *
+ * @param msg message
+ */
public ArgumentsParserException(String msg) {
super(msg);
}
+ /**
+ * Constructs a new exception with the specified detail message and cause.
+ *
+ * @param msg message
+ * @param eee cause
+ */
public ArgumentsParserException(String msg, Throwable eee) {
super(msg, eee);
}
Property changes on: trunk/src/main/java/org/nuiton/util/ArgumentsParserException.java
___________________________________________________________________
Deleted: svn:mergeinfo
-
Deleted: svn:eol-style
- native
1
0
r1766 - in trunk/src: main/java/org/nuiton/util/beans test/java/org/nuiton/util/beans
by tchemit@users.nuiton.org 21 Feb '10
by tchemit@users.nuiton.org 21 Feb '10
21 Feb '10
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
1
0
r1765 - in trunk/src: main/java/org/nuiton/util test/java/org/nuiton/util
by tchemit@users.nuiton.org 21 Feb '10
by tchemit@users.nuiton.org 21 Feb '10
21 Feb '10
Author: tchemit
Date: 2010-02-21 20:36:18 +0100 (Sun, 21 Feb 2010)
New Revision: 1765
Modified:
trunk/src/main/java/org/nuiton/util/ObjectUtil.java
trunk/src/test/java/org/nuiton/util/ObjectUtilTest.java
Log:
add GetNullValue and isNullValue methods in Objectutil to deal thim primitive types nullity (as their default value)
Modified: trunk/src/main/java/org/nuiton/util/ObjectUtil.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/ObjectUtil.java 2010-02-21 18:16:09 UTC (rev 1764)
+++ trunk/src/main/java/org/nuiton/util/ObjectUtil.java 2010-02-21 19:36:18 UTC (rev 1765)
@@ -33,6 +33,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import org.apache.commons.beanutils.MethodUtils;
import static org.nuiton.i18n.I18n._;
import org.apache.commons.logging.Log;
@@ -50,6 +51,13 @@
/** to use log facility, just put in your code: log.info(\"...\"); */
static private Log log = LogFactory.getLog(ObjectUtil.class);
+ protected static final Integer ZERO = 0;
+ protected static final Character ZEROC = (char)0;
+ protected static final Float ZEROF = 0f;
+ protected static final Long ZEROL = 0l;
+ protected static final Double ZEROD = 0.;
+ protected static final Byte ZEROB = 0;
+
/**
* ObjectUtil constructor
* private because of this class is a static class : nobody
@@ -398,5 +406,111 @@
return b?Boolean.TRUE:Boolean.FALSE;
}
+ /**
+ * Obtains the null value for the given type (works too with primitive
+ * types).
+ *
+ * @param type the type to test
+ * @return the {@code null} value or default value for primitive types
+ * @since 1.1.5
+ */
+ public static Object getNullValue(Class<?> type) {
+ if (type == null) {
+ throw new NullPointerException("parameter 'type' can not be null");
+ }
+ if (type.isPrimitive()) {
+ type = MethodUtils.getPrimitiveWrapper(type);
+ if (Boolean.class.isAssignableFrom(type)) {
+ return Boolean.FALSE;
+ }
+ if (Integer.class.isAssignableFrom(type)) {
+ return ZERO;
+ }
+ if (Character.class.isAssignableFrom(type)) {
+ return ZEROC;
+ }
+ if (Float.class.isAssignableFrom(type)) {
+ return ZEROF;
+ }
+ if (Long.class.isAssignableFrom(type)) {
+ return ZEROL;
+ }
+ if (Double.class.isAssignableFrom(type)) {
+ return ZEROD;
+ }
+ if (Byte.class.isAssignableFrom(type)) {
+ return ZEROB;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Tests if the given value is null according to default value for
+ * primitive types if nedded.
+ *
+ * @param value the value to test
+ * @return {@code true} if value is null or default value on a primitive
+ * @since 1.1.5
+ */
+ public static boolean isNullValue(Object value) {
+ if (value == null) {
+ return true;
+ }
+ Class<?> type = value.getClass();
+
+ //FIXME-TC20100212 : this case can not be, due to auto-boxing mecanism
+ if (type.isPrimitive()) {
+ type = MethodUtils.getPrimitiveWrapper(type);
+
+ if (Boolean.class.isAssignableFrom(type)) {
+ return Boolean.FALSE.equals(value);
+ }
+ if (Integer.class.isAssignableFrom(type)) {
+ return ZERO.equals(value);
+ }
+ if (Character.class.isAssignableFrom(type)) {
+ return ZEROC.equals(value);
+ }
+ if (Float.class.isAssignableFrom(type)) {
+ return ZEROF.equals(value);
+ }
+ if (Long.class.isAssignableFrom(type)) {
+ return ZEROL.equals(value);
+ }
+ if (Double.class.isAssignableFrom(type)) {
+ return ZEROD.equals(value);
+ }
+ if (Byte.class.isAssignableFrom(type)) {
+ return ZEROB.equals(value);
+ }
+ }
+ return false;
+ }
+
+ public static boolean isNullValue(boolean value) {
+ return Boolean.FALSE.equals(value);
+ }
+
+ public static boolean isNullValue(byte value) {
+ return value == ZEROB;
+ }
+
+ public static boolean isNullValue(int value) {
+ return value == ZEROB;
+ }
+
+ public static boolean isNullValue(char value) {
+ return value == ZEROC;
+ }
+
+ public static boolean isNullValue(float value) {
+ return value == ZEROF;
+ }
+
+ public static boolean isNullValue(double value) {
+ return value == ZEROD;
+ }
+
} // ObjectUtil
Modified: trunk/src/test/java/org/nuiton/util/ObjectUtilTest.java
===================================================================
--- trunk/src/test/java/org/nuiton/util/ObjectUtilTest.java 2010-02-21 18:16:09 UTC (rev 1764)
+++ trunk/src/test/java/org/nuiton/util/ObjectUtilTest.java 2010-02-21 19:36:18 UTC (rev 1765)
@@ -35,16 +35,18 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import junit.framework.TestCase;
+import org.junit.Assert;
+import org.junit.Test;
/**
* @author poussin
*
*/
-public class ObjectUtilTest extends TestCase {
+public class ObjectUtilTest extends Assert {
- public void testCall() throws Exception {
+ @Test
+ public void testCall() throws Exception {
Dummy dummy = new Dummy();
List<Method> methods = ObjectUtil.getMethod(Dummy.class, "setfile", true);
@@ -65,7 +67,8 @@
Arrays.asList(dummy.getAllFile()));
}
- public void testCreate() throws Exception {
+@Test
+ public void testCreate() throws Exception {
Object o = ObjectUtil.create("java.lang.StringBuffer");
assertTrue(o != null);
assertTrue(o instanceof StringBuffer);
@@ -78,7 +81,51 @@
assertEquals(new File("/tmp/fileTest"), dummy.getFile());
}
+ @Test
+ public void testGetNullValue() throws Exception {
+ try {
+ assertNull(ObjectUtil.getNullValue(null));
+ fail();
+ } catch (Exception e) {
+ assertTrue(true);
+ }
+
+ assertEquals(false, ObjectUtil.getNullValue(boolean.class));
+ assertEquals(0, ObjectUtil.getNullValue(int.class));
+ assertEquals((char)0, ObjectUtil.getNullValue(char.class));
+ assertEquals(0f, ObjectUtil.getNullValue(float.class));
+ assertEquals(0d, ObjectUtil.getNullValue(double.class));
+ assertEquals((byte)0, ObjectUtil.getNullValue(byte.class));
+
+ assertNull(ObjectUtil.getNullValue(Boolean.class));
+ assertNull(ObjectUtil.getNullValue(Integer.class));
+ assertNull(ObjectUtil.getNullValue(Character.class));
+ assertNull(ObjectUtil.getNullValue(Float.class));
+ assertNull(ObjectUtil.getNullValue(Double.class));
+ assertNull(ObjectUtil.getNullValue(Byte.class));
+ }
+
+ @Test
+ public void testIsNullValue() throws Exception {
+
+ assertTrue(ObjectUtil.isNullValue(null));
+
+ assertTrue(ObjectUtil.isNullValue(false));
+ assertTrue(ObjectUtil.isNullValue(0));
+ assertTrue(ObjectUtil.isNullValue((char) 0));
+ assertTrue(ObjectUtil.isNullValue(0f));
+ assertTrue(ObjectUtil.isNullValue(0d));
+ assertTrue(ObjectUtil.isNullValue((byte)0));
+
+ assertFalse(ObjectUtil.isNullValue(Boolean.FALSE));
+ assertFalse(ObjectUtil.isNullValue(Integer.valueOf(0)));
+ assertFalse(ObjectUtil.isNullValue(Character.valueOf((char) 0)));
+ assertFalse(ObjectUtil.isNullValue(Float.valueOf(0)));
+ assertFalse(ObjectUtil.isNullValue(Double.valueOf(0)));
+ assertFalse(ObjectUtil.isNullValue(Byte.valueOf((byte)0)));
+ }
+
static public class Dummy {
String name;
1
0
r1764 - in trunk/src: main/java/org/nuiton/util main/java/org/nuiton/util/beans test/java/org/nuiton/util test/java/org/nuiton/util/beans
by tchemit@users.nuiton.org 21 Feb '10
by tchemit@users.nuiton.org 21 Feb '10
21 Feb '10
Author: tchemit
Date: 2010-02-21 19:16:09 +0100 (Sun, 21 Feb 2010)
New Revision: 1764
Added:
trunk/src/main/java/org/nuiton/util/beans/
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/main/java/org/nuiton/util/beans/package-info.java
trunk/src/test/java/org/nuiton/util/beans/
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/BinderProviderTest.java
trunk/src/test/java/org/nuiton/util/beans/BinderTest.java
Log:
Evolution #309: BeanLoador
Added: trunk/src/main/java/org/nuiton/util/beans/Binder.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/beans/Binder.java (rev 0)
+++ trunk/src/main/java/org/nuiton/util/beans/Binder.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,128 @@
+/*
+ * *##% Nuiton utilities library
+ * Copyright (C) 2004 - 2010 CodeLutin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*
+ */
+
+package org.nuiton.util.beans;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * A {@code binder} permits to copy some properties from an object to another
+ * one.
+ * <p/>
+ * 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.
+ * <p/>
+ * Use the method {@link #obtainProperties(Object)} to obtain
+ *
+ * @author tchemit < chemit(a)codelutin.com >
+ * @param <I> the source bean type
+ * @param <O> the destination bean type
+ * @since 1.1.5
+ */
+public class Binder<I, O> implements java.io.Serializable {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * the model of the binder
+ */
+ protected BinderModel<I, O> model;
+
+ /**
+ * Obtain from the given object all properties registred in the binder
+ * model.
+ * <p/>
+ * <b>Note:</b> If a property's value is null, it will not be injected in
+ * the result.
+ *
+ * @param from 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) {
+ // special limit case
+ return java.util.Collections.emptyMap();
+ }
+ Map<String, Object> result = new TreeMap<String, Object>();
+ for (String srcProperty : model.getSourceDescriptors()) {
+
+ try {
+ Object read;
+ read = model.getSourceReadMethod(srcProperty).invoke(from);
+ if (read != null) {
+ result.put(srcProperty, read);
+ }
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Copy properties from a source bean to a destination one according to
+ * the model of the binder.
+ *
+ * @param from the bean to read
+ * @param dst the bean to write
+ */
+ public void copy(I from, O dst) {
+
+ for (String srcProperty : model.getSourceDescriptors()) {
+
+ String dstProperty = model.getTargetProperty(srcProperty);
+
+ try {
+ Object read =
+ model.getSourceReadMethod(srcProperty).invoke(from);
+ model.getTargetWriteMethod(dstProperty).invoke(dst, read);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * 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;
+ }
+}
\ No newline at end of file
Property changes on: trunk/src/main/java/org/nuiton/util/beans/Binder.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Added: trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java (rev 0)
+++ trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,357 @@
+/*
+ * *##% Nuiton utilities library
+ * Copyright (C) 2004 - 2010 CodeLutin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*
+ */
+package org.nuiton.util.beans;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * A builder of {@link BinderModel} and {@link Binder}.
+ * <p/>
+ * A {@code binder} permits to copy some properties from a bean to another one.
+ *
+ * @author tchemit < chemit(a)codelutin.com >
+ * @see BinderModel
+ * @see Binder
+ * @since 1.1.5
+ */
+public class BinderBuilder {
+
+ /**
+ * current model used to build the binder
+ */
+ protected BinderModel<?, ?> model;
+ protected Map<String, PropertyDescriptor> sourceDescriptors;
+ protected Map<String, PropertyDescriptor> targetDescriptors;
+
+
+ /**
+ * Creates a new binder model for a mirrored binder (source type = target
+ * type).
+ * <p/>
+ * <b>Note:</b> If a previous model was created, but not released via the
+ * method {@link #createBinder(Class)}, the method will failed.
+ *
+ * @param type the type of source and target
+ * @return the instance of the builder
+ * @throws IllegalStateException if a previous builder model was created
+ * without been released
+ * @throws NullPointerException if a parameter is null
+ */
+ public BinderBuilder createBinderModel(Class<?> type)
+ throws IllegalStateException, NullPointerException {
+ createBinderModel(type, type);
+ return this;
+ }
+
+ /**
+ * Creates a new binder model.
+ * <p/>
+ * <b>Note:</b> If a previous model was created, but not released via the
+ * method {@link #createBinder(Class)}, the method will failed.
+ *
+ * @param sourceType the type of the source
+ * @param targetType the type of the target
+ * @return the instance of the builder
+ * @throws IllegalStateException if a previous builder model was created
+ * without been released
+ * @throws NullPointerException if a parameter is null
+ */
+ public BinderBuilder createBinderModel(Class<?> sourceType,
+ Class<?> targetType)
+ throws IllegalStateException, NullPointerException {
+ if (sourceType == null) {
+ throw new NullPointerException("sourceType can not be null");
+ }
+ if (targetType == null) {
+ throw new NullPointerException("targetType can not be null");
+ }
+
+ if (model != null) {
+ throw new IllegalStateException("there is already a binderModel in " +
+ "construction, release it with the method createBinder " +
+ "before using this method.");
+ }
+
+ // init model
+ model = new BinderModel(sourceType, targetType);
+
+ // obtain src descriptors
+ try {
+ sourceDescriptors = new TreeMap<String, PropertyDescriptor>();
+
+ 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>();
+
+ 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;
+ }
+
+ /**
+ * Creates a new binder given using the {@link Binder} type of binder
+ * from the internal binder model
+ * previously created via the method {@code createBinderModel<XXX>} and
+ * then filled with methods {@code addXXX(XXX)}.
+ * <p/>
+ * <b>Note:</b> If no model is present, the method will fail.
+ *
+ * @return the instance of the new buinder.
+ * @throws IllegalStateException if no model was previously created.
+ * @throws NullPointerException if the parameter is {@code null}
+ */
+ public Binder<?, ?> createBinder()
+ throws NullPointerException, IllegalStateException {
+
+ Binder binder = createBinder(Binder.class);
+ return binder;
+ }
+
+ /**
+ * Creates a new binder given his type from the internal binder model
+ * previously created via the method {@code createBinderModel<XXX>} and
+ * then filled with methods {@code addXXX(XXX)}.
+ * <p/>
+ * <b>Note:</b> If no model is present, the method will fail.
+ *
+ * @param binderType the type of binder to instanciate
+ * @param <B> the type of binder to instanciate
+ * @return the instance of the new buinder.
+ * @throws IllegalStateException if no model was previously created.
+ * @throws NullPointerException if the parameter is {@code null}
+ */
+ public <B extends Binder<?, ?>> B createBinder(Class<B> binderType)
+ throws NullPointerException, IllegalStateException {
+ checkModelExists();
+ if (binderType == null) {
+ throw new NullPointerException("binderType can not be null");
+ }
+ try {
+ B binder = binderType.newInstance();
+ binder.setModel(model);
+ return binder;
+ } catch (Exception e) {
+ throw new IllegalStateException("could not instanciate binder " +
+ binderType, e);
+ } finally {
+ // release resources of the model
+ model = null;
+ sourceDescriptors.clear();
+ sourceDescriptors = null;
+ targetDescriptors.clear();
+ targetDescriptors = null;
+ }
+ }
+
+ /**
+ * Add to the binder model some simple properties (says source property name
+ * = target property name).
+ * <p/>
+ * <b>Note:</b> If no model is present, the method will fail.
+ *
+ * @param properties the name of mirrored property
+ * @return the instance of the builder
+ * @throws IllegalStateException if no model was previously created
+ * @throws NullPointerException if a property is {@code null}
+ */
+ public BinderBuilder addSimpleProperties(String... properties)
+ throws IllegalStateException, NullPointerException {
+ checkModelExists();
+ for (String property : properties) {
+ if (property == null) {
+ throw new NullPointerException("parameter 'properties' can " +
+ "not contains a null value");
+ }
+ addProperty0(property, property);
+ }
+ return this;
+ }
+
+ /**
+ * Add to the binder model some simple properties (says source property name
+ * = target property name).
+ * <p/>
+ * <b>Note:</b> If no model is present, the method will fail.
+ *
+ * @param sourceProperty the name of the source property to bind
+ * @param targetProperty the name of the target property to bind
+ * @return the instance of the builder
+ * @throws IllegalStateException if no model was previously created
+ * @throws NullPointerException if a parameter is {@code null}
+ */
+
+ public BinderBuilder addProperty(String sourceProperty,
+ String targetProperty)
+ throws IllegalStateException, NullPointerException {
+ if (sourceProperty == null) {
+ throw new NullPointerException("parameter 'sourceProperty' " +
+ "can not be null");
+ }
+ if (targetProperty == null) {
+ throw new NullPointerException("parameter 'targetProperty' " +
+ "can not be null");
+ }
+ checkModelExists();
+ addProperty0(sourceProperty, targetProperty);
+ return this;
+ }
+
+ /**
+ * Add to the binder model some properties.
+ * <p/>
+ * Parameter {@code sourceAndTargetProperties} must be a array of couple
+ * of {@code sourceProperty}, {@code targetProperty}.
+ * <p/>
+ * Example :
+ * <pre>
+ * builder.addProperties("name","name2","text","text");
+ * </pre>
+ * <p/>
+ * <b>Note:</b> If no model is present, the method will fail.
+ *
+ * @param sourceAndTargetProperties the couple of (sourceProperty -
+ * targetProperty) to bind
+ * @return the instance of the builder
+ * @throws IllegalStateException if no model was previously created
+ * @throws IllegalArgumentException if there is not the same number of
+ * source and target properties
+ * @throws NullPointerException if a parameter is {@code null}
+ */
+ public BinderBuilder addProperties(String... sourceAndTargetProperties)
+ throws IllegalStateException, IllegalArgumentException,
+ NullPointerException {
+ checkModelExists();
+ if (sourceAndTargetProperties.length % 2 != 0) {
+ throw new IllegalArgumentException("must have couple(s) of " +
+ "(sourceProperty,targetProperty) but had " +
+ Arrays.toString(sourceAndTargetProperties));
+ }
+ for (int i = 0, max = sourceAndTargetProperties.length / 2;
+ i < max; i++) {
+ String sourceProperty = sourceAndTargetProperties[2 * i];
+ String targetProperty = sourceAndTargetProperties[2 * i + 1];
+ if (sourceProperty == null) {
+ throw new NullPointerException("parameter " +
+ "'sourceAndTargetProperties' can not contains " +
+ "a null value");
+ }
+ if (targetProperty == null) {
+ throw new NullPointerException("parameter " +
+ "'sourceAndTargetProperties' can not contains " +
+ "a null value");
+ }
+ addProperty0(sourceProperty, targetProperty);
+ }
+ return this;
+ }
+
+
+ protected void addProperty0(String sourceProperty,
+ String targetProperty) {
+ // check srcProperty does not exist
+ if (model.containsSourceProperty(sourceProperty)) {
+ throw new IllegalArgumentException("source property '" +
+ sourceProperty + "' " + " was already registred.");
+ }
+ // check dstProperty does not exist
+ if (model.containsTargetProperty(targetProperty)) {
+ throw new IllegalArgumentException("destination property '" +
+ targetProperty + "' " + " was already registred.");
+ }
+
+ // obtain source descriptor
+ PropertyDescriptor sourceDescriptor =
+ sourceDescriptors.get(sourceProperty);
+ if (sourceDescriptor == null) {
+ throw new IllegalArgumentException("no property '" +
+ sourceProperty + "' " + "found on type " +
+ model.getSourceType());
+ }
+ // check srcProperty is readable
+ Method readMethod = sourceDescriptor.getReadMethod();
+ if (readMethod == null) {
+ throw new IllegalArgumentException("property '" + sourceProperty +
+ "' " + "is not readable on type " + model.getSourceType());
+ }
+
+ // obtain dst descriptor
+ PropertyDescriptor targetDescriptor =
+ targetDescriptors.get(targetProperty);
+ if (targetDescriptor == null) {
+ throw new IllegalArgumentException("no property '" +
+ targetProperty + "' " + "found on type " +
+ model.getTargetType());
+ }
+ // check dstProperty is writable
+ Method writeMethod = sourceDescriptor.getWriteMethod();
+ if (writeMethod == null) {
+ throw new IllegalArgumentException("property '" + targetProperty +
+ "' " + "is not writable on type " + model.getTargetType());
+ }
+
+ // check types are ok
+ Class<?> sourceType = sourceDescriptor.getPropertyType();
+ Class<?> targetType = targetDescriptor.getPropertyType();
+ //TODO-TC20100221 : should check if primitive and boxed it in such case
+ if (sourceType != targetType) {
+ throw new IllegalArgumentException("source property '" +
+ sourceProperty + "' and target property '" +
+ targetProperty + "' are not compatible ( sourceType : " +
+ sourceType + " vs targetType :" + targetType + ')');
+ }
+
+ // safe to add the binding
+ model.addBinding(sourceDescriptor, targetDescriptor);
+ }
+
+ protected void checkModelExists() throws IllegalStateException {
+ if (model == null) {
+ throw new IllegalStateException("there is not model, must " +
+ "create one with createBinderModel method");
+ }
+ }
+
+ protected BinderModel<?, ?> getModel() {
+ return model;
+ }
+}
\ No newline at end of file
Property changes on: trunk/src/main/java/org/nuiton/util/beans/BinderBuilder.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Added: trunk/src/main/java/org/nuiton/util/beans/BinderModel.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/beans/BinderModel.java (rev 0)
+++ trunk/src/main/java/org/nuiton/util/beans/BinderModel.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,231 @@
+/*
+ * *##% Nuiton utilities library
+ * Copyright (C) 2004 - 2010 CodeLutin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*
+ */
+package org.nuiton.util.beans;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+
+/**
+ * Model of a {@link Binder}.
+ *
+ * @author tchemit < chemit(a)codelutin.com >
+ * @param <S> the source type
+ * @param <T> the target type
+ * @since 1.1.5
+ */
+public class BinderModel<S, T> implements java.io.Serializable {
+
+ /**
+ * source type
+ */
+ protected final Class<S> sourceType;
+ /**
+ * destination type
+ */
+ protected final Class<T> targetType;
+
+ /**
+ * source type descriptors (key are property names)
+ */
+ protected final Map<String, PropertyDescriptor> sourceDescriptors;
+ /**
+ * destination descriptors (key are property names)
+ */
+ protected final Map<String, PropertyDescriptor> targetDescriptors;
+ /**
+ * properties mapping (key are source properties, value are destination
+ * properties)
+ */
+ protected final Map<String, String> propertiesMapping;
+
+ private static final long serialVersionUID = 1L;
+
+ public BinderModel(Class<S> sourceType, Class<T> targetType) {
+ this.sourceType = sourceType;
+ this.targetType = targetType;
+ this.sourceDescriptors = new TreeMap<String, PropertyDescriptor>();
+ this.targetDescriptors = new TreeMap<String, PropertyDescriptor>();
+ this.propertiesMapping = new TreeMap<String, String>();
+ }
+
+ /**
+ * Gets the type of the binder's source.
+ *
+ * @return the type of the source object in the binder
+ */
+ public Class<S> getSourceType() {
+ return sourceType;
+ }
+
+ /**
+ * Gets the type of the binder's destination
+ *
+ * @return the type of the destination object in the binder
+ */
+ public Class<T> getTargetType() {
+ return targetType;
+ }
+
+ /**
+ * Gets all registred property names of the binder's source type.
+ *
+ * @return the array of all source object properties names to bind
+ */
+ public String[] getSourceDescriptors() {
+ Set<String> universe = sourceDescriptors.keySet();
+ return universe.toArray(new String[sourceDescriptors.size()]);
+ }
+
+ /**
+ * Gets all registred property names of the binder's destination type.
+ *
+ * @return the array of all source object properties names to bind
+ */
+ public String[] getTargetDescriptors() {
+ Set<String> universe = targetDescriptors.keySet();
+ return universe.toArray(new String[targetDescriptors.size()]);
+ }
+
+ /**
+ * Gets the destination property name given the
+ *
+ * @param sourceProperty the name of the source property to bind
+ * @return the name of the destination object property to bind, or
+ * {@code null} if {@code propertySrc} is unknown in the model
+ */
+ public String getTargetProperty(String sourceProperty) {
+ if (!containsSourceProperty(sourceProperty)) {
+ return null;
+ }
+ String dstProperty = propertiesMapping.get(sourceProperty);
+ return dstProperty;
+ }
+
+ /**
+ * Gets the bean descriptor of the source type for the given
+ * destination property.
+ *
+ * @param sourceProperty name of the source type property name
+ * @return the descriptor or {@code null} if not found.
+ */
+ public PropertyDescriptor getSourceDescriptor(String sourceProperty) {
+ // check src property is registred
+ if (!containsSourceProperty(sourceProperty)) {
+ return null;
+ }
+ PropertyDescriptor descriptor = sourceDescriptors.get(sourceProperty);
+ return descriptor;
+ }
+
+ /**
+ * @param srcProperty the name of a property of the source object.
+ * @return the method to read in a source object for the given property.
+ */
+ public Method getSourceReadMethod(String srcProperty) {
+ PropertyDescriptor descriptor = getSourceDescriptor(srcProperty);
+ Method readMethod = null;
+ if (descriptor != null) {
+ readMethod = descriptor.getReadMethod();
+ }
+ return readMethod;
+ }
+
+ /**
+ * @param sourceProperty the name of a property of the source object.
+ * @return the method to write in a source object for the given property.
+ */
+ public Method getSourceWriteMethod(String sourceProperty) {
+ PropertyDescriptor descriptor = getSourceDescriptor(sourceProperty);
+ Method writeMethod = null;
+ if (descriptor != null) {
+ writeMethod = descriptor.getWriteMethod();
+ }
+ return writeMethod;
+ }
+
+ /**
+ * Gets the bean descriptor of the destination type for the given
+ * destination property.
+ *
+ * @param targetProperty name of the destination type property name
+ * @return the descriptor or {@code null} if not found.
+ */
+ public PropertyDescriptor getTargetDescriptor(String targetProperty) {
+ // check dst property is registred
+ if (!containsTargetProperty(targetProperty)) {
+ return null;
+ }
+ PropertyDescriptor descriptor = targetDescriptors.get(targetProperty);
+ return descriptor;
+ }
+
+ /**
+ * @param targetProperty the name of a property of the destination object.
+ * @return the method to read in a destination object for the given
+ * property.
+ */
+ public Method getTargetReadMethod(String targetProperty) {
+ PropertyDescriptor descriptor = getTargetDescriptor(targetProperty);
+ Method readMethod = null;
+ if (descriptor != null) {
+ readMethod = descriptor.getReadMethod();
+ }
+ return readMethod;
+ }
+
+ /**
+ * @param targetProperty the name of a property of the destination object.
+ * @return the method to write in a destination object for the given
+ * property.
+ */
+ public Method getTargetWriteMethod(String targetProperty) {
+ PropertyDescriptor descriptor = getTargetDescriptor(targetProperty);
+ Method writeMethod = null;
+ if (descriptor != null) {
+ writeMethod = descriptor.getWriteMethod();
+ }
+ return writeMethod;
+ }
+
+ protected boolean containsSourceProperty(String sourceProperty) {
+ return propertiesMapping.containsKey(sourceProperty);
+ }
+
+ protected boolean containsTargetProperty(String targetProperty) {
+ return propertiesMapping.containsValue(targetProperty);
+ }
+
+ protected void addBinding(PropertyDescriptor sourceDescriptor,
+ PropertyDescriptor targetDescriptor) {
+
+ String sourceProperty = sourceDescriptor.getName();
+ String targetProperty = targetDescriptor.getName();
+ sourceDescriptors.put(sourceProperty, sourceDescriptor);
+ targetDescriptors.put(targetProperty, targetDescriptor);
+ propertiesMapping.put(sourceProperty, targetProperty);
+ }
+
+ protected Map<String, String> getPropertiesMapping() {
+ return propertiesMapping;
+ }
+}
\ No newline at end of file
Property changes on: trunk/src/main/java/org/nuiton/util/beans/BinderModel.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Added: trunk/src/main/java/org/nuiton/util/beans/BinderProvider.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/beans/BinderProvider.java (rev 0)
+++ trunk/src/main/java/org/nuiton/util/beans/BinderProvider.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,320 @@
+/*
+ * *##% Nuiton utilities library
+ * Copyright (C) 2004 - 2010 CodeLutin
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*
+ */
+
+package org.nuiton.util.beans;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Manage a cache of {@link Binder} objects.
+ * <p/>
+ * You must first register some binders via the {@code registerBinder} api.
+ * <pre>
+ * Binder<User,UserDTO> mybinder = ...;
+ * registerBinder(myNewBinder);
+ * </pre>
+ * To use several binders of the the same types, you can moreover specify
+ * a context name of your binder :
+ * <pre>
+ * Binder<User,UserDTO> mybinder = ...;
+ * registerBinder(myBinder, "One");
+ * </pre>
+ * <p/>
+ * Then you can obtained them back via the api
+ * <pre>
+ * Binder<User,UserDTO> mybinder = getBinder(User.class,UserDTO);
+ * </pre>
+ * <p/>
+ * or with a context name :
+ * <pre>
+ * Binder<User,UserDTO> mybinder = getBinder(User.class,UserDTO.class, "One");
+ * </pre>
+ *
+ * @author tchemit < chemit(a)codelutin.com >
+ * @see Binder
+ * @see BinderBuilder
+ * @since 1.1.5
+ */
+public class BinderProvider {
+
+ /**
+ * Logger
+ */
+ private static final Log log = LogFactory.getLog(BinderProvider.class);
+ /**
+ * Cache of registred binders indexed by their unique entry
+ */
+ protected static Map<BinderEntry, Binder> binders;
+
+ /**
+ * Gets the registred mirror binder (source type = target type) with no
+ * context name specified.
+ *
+ * @param sourceType the type of source and target
+ * @param <S> the type of source and target
+ * @return the registred binder or {@code null} if not found.
+ */
+ public static <S> Binder<S, S> getBinder(Class<S> sourceType) {
+ return getBinder(sourceType, sourceType, null);
+ }
+
+ /**
+ * Gets the registred mirror binder (source type = target type) with the
+ * given context name.
+ *
+ * @param sourceType the type of source and target
+ * @param name the context's name of the searched binder
+ * @param <S> the type of source and target
+ * @return the registred binder or {@code null} if not found.
+ */
+ public static <S> Binder<S, S> getBinder(Class<S> sourceType,
+ String name) {
+ return getBinder(sourceType, sourceType, name);
+ }
+
+
+ /**
+ * Gets the registred binder given his types with no context name.
+ *
+ * @param sourceType the type of source
+ * @param targetType the type of target
+ * @param <S> the type of source
+ * @param <T> the type of target
+ * @return the registred binder or {@code null} if not found.
+ */
+ public static <S, T> Binder<S, T> getBinder(Class<S> sourceType,
+ Class<T> targetType) {
+ return getBinder(sourceType, targetType, null);
+ }
+
+ /**
+ * Gets the registred binder given his types and his context's name.
+ *
+ * @param sourceType the type of source
+ * @param targetType the type of target
+ * @param name the context's name of the searched binder
+ * @param <S> the type of source
+ * @param <T> the type of target
+ * @return the registred binder or {@code null} if not found.
+ */
+ public static <S, T> Binder<S, T> getBinder(Class<S> sourceType,
+ Class<T> targetType,
+ String name) {
+ BinderEntry entry = new BinderEntry(sourceType, targetType, name);
+ if (log.isDebugEnabled()) {
+ log.debug("for entry " + entry);
+ }
+ Binder<?, ?> result = getBinders().get(entry);
+ if (result == null) {
+ // binder not found
+ if (log.isWarnEnabled()) {
+ log.warn("Could not find binder " + entry);
+ }
+ }
+ return (Binder<S, T>) result;
+ }
+
+ /**
+ * Register a binder with no context name.
+ * <p/>
+ * <b>Note: </b> If a previous binder with same definition exists, it will
+ * be overriden by the new binder.
+ *
+ * @param binder the binder to register.
+ */
+ public static void registerBinder(Binder<?, ?> binder) {
+ registerBinder(binder, null);
+ }
+
+ /**
+ * Register a binder with no context's name from a {@link BinderBuilder}.
+ * <p/>
+ * <b>Note: </b> If a previous binder with same definition exists, it will
+ * be overriden by the new binder.
+ *
+ * @param builder the builder which contains builder model to use
+ * @see BinderBuilder#createBinder(Class)
+ */
+ public static <B extends Binder> void registerBinder(BinderBuilder builder) {
+ registerBinder(builder, Binder.class);
+ }
+
+ /**
+ * Register a binder with no context's name from a {@link BinderBuilder}.
+ * <p/>
+ * <b>Note: </b> If a previous binder with same definition exists, it will
+ * be overriden by the new binder.
+ *
+ * @param builder the builder which contains builder model to use
+ * @param binderType the type of binder to instanciate and register.
+ * @see BinderBuilder#createBinder(Class)
+ */
+ public static <B extends Binder> void registerBinder(BinderBuilder builder,
+ Class<B> binderType) {
+
+ registerBinder(builder, binderType, null);
+ }
+
+ /**
+ * Register a binder with a context's name from a {@link BinderBuilder}.
+ * <p/>
+ * <b>Note: </b> If a previous binder with same definition exists, it will
+ * be overriden by the new binder.
+ *
+ * @param builder the builder which contains builder model to use
+ * @param name the context's name
+ * @see BinderBuilder#createBinder(Class)
+ */
+ public static <B extends Binder> void registerBinder(BinderBuilder builder,
+ String name) {
+
+ registerBinder(builder, Binder.class, name);
+ }
+
+ /**
+ * Register a binder with a context's name from a {@link BinderBuilder}.
+ * <p/>
+ * <b>Note: </b> If a previous binder with same definition exists, it will
+ * be overriden by the new binder.
+ *
+ * @param builder the builder which contains builder model to use
+ * @param binderType the type of binder to instanciate and register.
+ * @param name the context's name
+ * @see BinderBuilder#createBinder(Class)
+ */
+ public static <B extends Binder> void registerBinder(BinderBuilder builder,
+ Class<B> binderType,
+ String name) {
+ // instanciate the binder
+ B binder = builder.createBinder(binderType);
+ // register it
+ registerBinder(binder, name);
+ }
+
+ /**
+ * Register a binder with a context name.
+ * <p/>
+ * <b>Note: </b> If a previous binder with same definition exists, it will
+ * be overriden by the new binder.
+ *
+ * @param binder the binder to register.
+ * @param name the context's name
+ */
+ public static void registerBinder(Binder<?, ?> binder, String name) {
+ BinderModel<?, ?> model = binder.getModel();
+ BinderEntry entry = new BinderEntry(
+ model.getSourceType(),
+ model.getTargetType(),
+ name
+ );
+ if (log.isDebugEnabled()) {
+ log.debug("binder to seek : " + entry);
+ }
+ Binder oldBinder = getBinders().get(entry);
+ if (oldBinder != null) {
+ // already a binder for this entry
+ if (log.isWarnEnabled()) {
+ log.warn("Binder already registred for " + entry + " : " +
+ oldBinder);
+ log.warn("Will be replace by the new binder " + binder);
+ }
+ }
+ // register the binder
+ if (log.isDebugEnabled()) {
+ log.debug("entry : " + entry + " : " + binder);
+ }
+ getBinders().put(entry, binder);
+ }
+
+ protected static Map<BinderEntry, Binder> getBinders() {
+ if (binders == null) {
+ binders = new HashMap<BinderEntry, Binder>();
+ }
+ return binders;
+ }
+
+ /**
+ * Definition of an binder entry (source and target types + context name).
+ * <p/>
+ * <b>Note :</b>When no context is specified, we always use a
+ * {@code null} context name.
+ */
+ public static class BinderEntry {
+
+ protected final Class<?> sourceType;
+ protected final Class<?> targetType;
+ protected final String name;
+
+
+ public BinderEntry(Class<?> sourceType,
+ Class<?> targetType,
+ String name) {
+ this.sourceType = sourceType;
+ this.targetType = targetType;
+ this.name = name;
+ }
+
+ public Class<?> getSourceType() {
+ return sourceType;
+ }
+
+ public Class<?> getTargetType() {
+ return targetType;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BinderEntry that = (BinderEntry) o;
+
+ return name == null ? that.name == null : name.equals(that.name) &&
+ sourceType.equals(that.sourceType) &&
+ targetType.equals(that.targetType);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = sourceType.hashCode();
+ result = 31 * result + targetType.hashCode();
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buffer = new StringBuilder("<");
+ buffer.append(super.toString());
+ buffer.append(", sourceType: ").append(getSourceType()).append(',');
+ buffer.append(" targetType: ").append(getTargetType()).append(',');
+ buffer.append(" name: ").append(getName()).append('>');
+
+ return buffer.toString();
+ }
+ }
+}
Property changes on: trunk/src/main/java/org/nuiton/util/beans/BinderProvider.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Added: trunk/src/main/java/org/nuiton/util/beans/package-info.java
===================================================================
--- trunk/src/main/java/org/nuiton/util/beans/package-info.java (rev 0)
+++ trunk/src/main/java/org/nuiton/util/beans/package-info.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,6 @@
+/**
+ * Packages for all stuff of bean transformations (binder, and others...).
+ *
+ * @since 1.1.5
+ */
+package org.nuiton.util.beans;
Property changes on: trunk/src/main/java/org/nuiton/util/beans/package-info.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Added: trunk/src/test/java/org/nuiton/util/beans/BeanA.java
===================================================================
--- trunk/src/test/java/org/nuiton/util/beans/BeanA.java (rev 0)
+++ trunk/src/test/java/org/nuiton/util/beans/BeanA.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,43 @@
+package org.nuiton.util.beans;
+
+public class BeanA {
+
+ public static final String PROPERTY_A = "a";
+ public static final String PROPERTY_B = "b";
+ public static final String PROPERTY_C = "c";
+ public static final String PROPERTY_D = "d";
+
+ String a,b,c,d;
+
+ public String getA() {
+ return a;
+ }
+
+ public void setA(String a) {
+ this.a = a;
+ }
+
+ public String getB() {
+ return b;
+ }
+
+ public void setB(String b) {
+ this.b = b;
+ }
+
+ public String getC() {
+ return c;
+ }
+
+ public void setC(String c) {
+ this.c = c;
+ }
+
+ public String getD() {
+ return d;
+ }
+
+ public void setD(String d) {
+ this.d = d;
+ }
+}
\ No newline at end of file
Property changes on: trunk/src/test/java/org/nuiton/util/beans/BeanA.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Added: trunk/src/test/java/org/nuiton/util/beans/BeanB.java
===================================================================
--- trunk/src/test/java/org/nuiton/util/beans/BeanB.java (rev 0)
+++ trunk/src/test/java/org/nuiton/util/beans/BeanB.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,43 @@
+package org.nuiton.util.beans;
+
+public class BeanB extends BeanA {
+
+ public static final String PROPERTY_A2 = "a2";
+ public static final String PROPERTY_B2 = "b2";
+ public static final String PROPERTY_C2 = "c2";
+ public static final String PROPERTY_D2 = "d2";
+
+ String a2, b2, c2, d2;
+
+ public String getA2() {
+ return a2;
+ }
+
+ public void setA2(String a2) {
+ this.a2 = a2;
+ }
+
+ public String getB2() {
+ return b2;
+ }
+
+ public void setB2(String b2) {
+ this.b2 = b2;
+ }
+
+ public String getC2() {
+ return c2;
+ }
+
+ public void setC2(String c2) {
+ this.c2 = c2;
+ }
+
+ public String getD2() {
+ return d2;
+ }
+
+ public void setD2(String d2) {
+ this.d2 = d2;
+ }
+}
\ No newline at end of file
Property changes on: trunk/src/test/java/org/nuiton/util/beans/BeanB.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Added: trunk/src/test/java/org/nuiton/util/beans/BinderBuilderTest.java
===================================================================
--- trunk/src/test/java/org/nuiton/util/beans/BinderBuilderTest.java (rev 0)
+++ trunk/src/test/java/org/nuiton/util/beans/BinderBuilderTest.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,297 @@
+package org.nuiton.util.beans;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.beans.PropertyDescriptor;
+import java.util.Map;
+
+public class BinderBuilderTest {
+
+ private BinderBuilder builder;
+ protected static final String PROPERTY_CLASS = "class";
+
+ @Before
+ public void setUp() {
+
+ builder = new BinderBuilder();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testCreateMirroredBinderModel_NPE() throws Exception {
+ builder.createBinderModel(null);
+ }
+
+ @Test
+ public void testCreateMirroredBinderModel() throws Exception {
+ builder.createBinderModel(BeanA.class);
+ Assert.assertNotNull(builder.getModel());
+ Map<String, PropertyDescriptor> sourceDescriptors;
+ Map<String, PropertyDescriptor> targetDescriptors;
+
+ sourceDescriptors = builder.sourceDescriptors;
+ Assert.assertNotNull(sourceDescriptors);
+ Assert.assertEquals(5, 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));
+
+
+ targetDescriptors = builder.targetDescriptors;
+ Assert.assertNotNull(targetDescriptors);
+ Assert.assertEquals(5, 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.assertEquals(BeanA.class, builder.getModel().getSourceType());
+ Assert.assertEquals(BeanA.class, builder.getModel().getTargetType());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testCreateMirroredBinderModel_Twice() throws Exception {
+ builder.createBinderModel(BeanA.class);
+ Assert.assertNotNull(builder.getModel());
+ Assert.assertEquals(BeanA.class, builder.getModel().getSourceType());
+ Assert.assertEquals(BeanA.class, builder.getModel().getTargetType());
+ builder.createBinderModel(BeanA.class);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testCreateBinderModel_NPE() throws Exception {
+ builder.createBinderModel(null, null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testCreateBinderModel_NPE2() throws Exception {
+ builder.createBinderModel(BeanA.class, null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testCreateBinderModel_NPE3() throws Exception {
+ builder.createBinderModel(null, BeanA.class);
+ }
+
+ @Test
+ public void testCreateBinderModel() throws Exception {
+ builder.createBinderModel(BeanA.class, BeanB.class);
+ Assert.assertNotNull(builder.getModel());
+ Map<String, PropertyDescriptor> sourceDescriptors;
+ Map<String, PropertyDescriptor> targetDescriptors;
+
+ sourceDescriptors = builder.sourceDescriptors;
+ Assert.assertNotNull(sourceDescriptors);
+ Assert.assertEquals(5, 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));
+
+ targetDescriptors = builder.targetDescriptors;
+ Assert.assertNotNull(targetDescriptors);
+ Assert.assertEquals(9, 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(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.assertEquals(BeanA.class, builder.getModel().getSourceType());
+ Assert.assertEquals(BeanB.class, builder.getModel().getTargetType());
+
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testCreateBinderModel_Twice() throws Exception {
+ builder.createBinderModel(BeanA.class, BeanB.class);
+ Assert.assertNotNull(builder.getModel());
+ Assert.assertEquals(BeanA.class, builder.getModel().getSourceType());
+ Assert.assertEquals(BeanB.class, builder.getModel().getTargetType());
+ builder.createBinderModel(BeanA.class, BeanB.class);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testCreateBinder_NO_Model() throws Exception {
+ builder.createBinder(Binder.class);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testCreateBinder_NPE() throws Exception {
+ builder.createBinderModel(BeanA.class, BeanB.class);
+ builder.createBinder(null);
+ }
+
+ @Test
+ public void testAddSimpleProperties() throws Exception {
+
+ builder.createBinderModel(BeanA.class);
+ BinderModel<?, ?> model = builder.getModel();
+
+ try {
+ builder.addSimpleProperties((String) null);
+ Assert.fail();
+ } catch (NullPointerException e) {
+ Assert.assertTrue(true);
+ }
+ builder.addSimpleProperties(BeanA.PROPERTY_A);
+ Assert.assertEquals(1, model.getSourceDescriptors().length);
+ Assert.assertEquals(1, model.getTargetDescriptors().length);
+ Map<String, String> map = model.getPropertiesMapping();
+ Assert.assertEquals(1, map.size());
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_A));
+ Assert.assertTrue(map.containsValue(BeanA.PROPERTY_A));
+ Assert.assertEquals(BeanA.PROPERTY_A, map.get(BeanA.PROPERTY_A));
+
+ try {
+ builder.addSimpleProperties(BeanA.PROPERTY_A);
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+
+ try {
+ builder.addSimpleProperties(BeanB.PROPERTY_A2);
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+
+ builder.addSimpleProperties(BeanA.PROPERTY_B);
+ Assert.assertEquals(2, model.getSourceDescriptors().length);
+ Assert.assertEquals(2, model.getTargetDescriptors().length);
+ Assert.assertEquals(2, map.size());
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_B));
+ Assert.assertTrue(map.containsValue(BeanA.PROPERTY_B));
+ Assert.assertEquals(BeanA.PROPERTY_B, map.get(BeanA.PROPERTY_B));
+
+ }
+
+ @Test
+ public void testAddProperty() throws Exception {
+ builder.createBinderModel(BeanA.class, BeanB.class);
+ BinderModel<?, ?> model = builder.getModel();
+
+ try {
+ builder.addProperty(null, null);
+ Assert.fail();
+ } catch (NullPointerException e) {
+ Assert.assertTrue(true);
+ }
+ try {
+ builder.addProperty(BeanA.PROPERTY_A, null);
+ Assert.fail();
+ } catch (NullPointerException e) {
+ Assert.assertTrue(true);
+ }
+ try {
+ builder.addProperty(null, BeanA.PROPERTY_A);
+ Assert.fail();
+ } catch (NullPointerException e) {
+ Assert.assertTrue(true);
+ }
+ builder.addProperty(BeanA.PROPERTY_A, BeanA.PROPERTY_A);
+ Assert.assertEquals(1, model.getSourceDescriptors().length);
+ Assert.assertEquals(1, model.getTargetDescriptors().length);
+ Map<String, String> map = model.getPropertiesMapping();
+ Assert.assertEquals(1, map.size());
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_A));
+ Assert.assertTrue(map.containsValue(BeanA.PROPERTY_A));
+ Assert.assertEquals(BeanA.PROPERTY_A, map.get(BeanA.PROPERTY_A));
+
+ try {
+ builder.addProperty(BeanB.PROPERTY_A, BeanB.PROPERTY_A2);
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+
+ try {
+ builder.addProperty(BeanB.PROPERTY_A2, BeanB.PROPERTY_A);
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+
+ builder.addProperty(BeanA.PROPERTY_B, BeanB.PROPERTY_B2);
+ Assert.assertEquals(2, model.getSourceDescriptors().length);
+ Assert.assertEquals(2, model.getTargetDescriptors().length);
+ Assert.assertEquals(2, map.size());
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_B));
+ Assert.assertTrue(map.containsValue(BeanB.PROPERTY_B2));
+ Assert.assertEquals(BeanB.PROPERTY_B2, map.get(BeanB.PROPERTY_B));
+ }
+
+ @Test
+ public void testAddProperties() throws Exception {
+ builder.createBinderModel(BeanA.class, BeanB.class);
+
+ try {
+ builder.addProperties(BeanB.PROPERTY_A, BeanB.PROPERTY_A2,
+ BeanB.PROPERTY_B);
+ Assert.fail();
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue(true);
+ }
+
+ try {
+ builder.addProperties(BeanB.PROPERTY_A, null,
+ BeanB.PROPERTY_B, BeanB.PROPERTY_B);
+ Assert.fail();
+ } catch (NullPointerException e) {
+ Assert.assertTrue(true);
+ }
+
+ builder.addProperties(BeanB.PROPERTY_A, BeanB.PROPERTY_A,
+ BeanB.PROPERTY_B, BeanB.PROPERTY_B2);
+
+ BinderModel<?, ?> model = builder.getModel();
+ Assert.assertEquals(2, model.getSourceDescriptors().length);
+ Assert.assertEquals(2, model.getTargetDescriptors().length);
+ Map<String, String> map = model.getPropertiesMapping();
+ Assert.assertEquals(2, map.size());
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_A));
+ Assert.assertTrue(map.containsValue(BeanA.PROPERTY_A));
+ Assert.assertEquals(BeanA.PROPERTY_A, map.get(BeanA.PROPERTY_A));
+
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_B));
+ Assert.assertTrue(map.containsValue(BeanB.PROPERTY_B2));
+ Assert.assertEquals(BeanB.PROPERTY_B2, map.get(BeanB.PROPERTY_B));
+ }
+
+ @Test
+ public void testCreateBinder() throws Exception {
+ builder.createBinderModel(BeanA.class, BeanB.class);
+ builder.addProperties(BeanB.PROPERTY_A, BeanB.PROPERTY_A,
+ BeanB.PROPERTY_B, BeanB.PROPERTY_B2);
+
+ Binder<BeanA, BeanB> binder =
+ (Binder<BeanA, BeanB>) builder.createBinder();
+
+ Assert.assertNull(builder.getModel());
+ Assert.assertNull(builder.sourceDescriptors);
+ Assert.assertNull(builder.targetDescriptors);
+
+ BeanA a = new BeanA();
+ BeanB b = new BeanB();
+
+ a.setA("a");
+ a.setB("b");
+ b.setA("a2");
+ b.setB2("b2");
+
+ binder.copy(a, b);
+ Assert.assertEquals("a", b.getA());
+ Assert.assertEquals("b", b.getB2());
+ Assert.assertNull(b.getB());
+ }
+}
\ No newline at end of file
Property changes on: trunk/src/test/java/org/nuiton/util/beans/BinderBuilderTest.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Added: trunk/src/test/java/org/nuiton/util/beans/BinderProviderTest.java
===================================================================
--- trunk/src/test/java/org/nuiton/util/beans/BinderProviderTest.java (rev 0)
+++ trunk/src/test/java/org/nuiton/util/beans/BinderProviderTest.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,166 @@
+package org.nuiton.util.beans;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class BinderProviderTest {
+
+ Binder<BeanA, BeanA> binderA;
+ Binder<BeanA, BeanB> binderB;
+ private static final String MY_BINDER_NAME = "myBinder";
+ private static final String MY_BINDER2_NAME = "myBinder2";
+
+ @Before
+ public void setUp() {
+
+ BinderProvider.binders = null;
+
+ BinderBuilder builder = new BinderBuilder();
+ binderA = (Binder<BeanA, BeanA>)
+ builder.createBinderModel(BeanA.class).
+ addSimpleProperties(BeanA.PROPERTY_A).
+ createBinder();
+ binderB = (Binder<BeanA, BeanB>)
+ builder.createBinderModel(BeanA.class, BeanB.class).
+ addSimpleProperties(BeanA.PROPERTY_A, BeanA.PROPERTY_B).
+ addProperty(BeanA.PROPERTY_C, BeanB.PROPERTY_C2).
+ createBinder();
+
+ }
+
+ @Test
+ public void testRegisterBinder() throws Exception {
+
+ Assert.assertNull(BinderProvider.binders);
+
+ try {
+ BinderProvider.registerBinder((Binder) null);
+ Assert.fail();
+ } catch (NullPointerException e) {
+
+ Assert.assertTrue(true);
+ }
+ try {
+ BinderProvider.registerBinder((BinderBuilder) null);
+ Assert.fail();
+ } catch (NullPointerException e) {
+
+ Assert.assertTrue(true);
+ }
+
+ BinderProvider.registerBinder(binderA);
+
+ Assert.assertNotNull(BinderProvider.binders);
+ Assert.assertEquals(1, BinderProvider.getBinders().size());
+ Assert.assertTrue(BinderProvider.getBinders().containsValue(binderA));
+
+ }
+
+ @Test
+ public void testRegisterBinderWithName() throws Exception {
+ Assert.assertNull(BinderProvider.binders);
+
+ try {
+ BinderProvider.registerBinder((Binder) null, null);
+ Assert.fail();
+ } catch (NullPointerException e) {
+
+ Assert.assertTrue(true);
+ }
+
+ try {
+ BinderProvider.registerBinder((Binder) null, MY_BINDER_NAME);
+ Assert.fail();
+ } catch (NullPointerException e) {
+
+ Assert.assertTrue(true);
+ }
+ try {
+ BinderProvider.registerBinder((BinderBuilder) null, (String) null);
+ Assert.fail();
+ } catch (NullPointerException e) {
+
+ Assert.assertTrue(true);
+ }
+ try {
+ BinderProvider.registerBinder((BinderBuilder) null, MY_BINDER_NAME);
+ Assert.fail();
+ } catch (NullPointerException e) {
+
+ Assert.assertTrue(true);
+ }
+
+ BinderProvider.registerBinder(binderA, MY_BINDER_NAME);
+
+ Assert.assertNotNull(BinderProvider.binders);
+ Assert.assertEquals(1, BinderProvider.getBinders().size());
+ Assert.assertTrue(BinderProvider.getBinders().containsValue(binderA));
+ }
+
+ @Test
+ public void testGetMirroredBinder() throws Exception {
+ BinderProvider.registerBinder(binderA);
+ Binder<BeanA, BeanA> aBeanABinder = BinderProvider.getBinder(BeanA.class);
+ Assert.assertNotNull(aBeanABinder);
+ Assert.assertEquals(binderA, aBeanABinder);
+ Binder<BeanB, BeanB> beanBBinder = BinderProvider.getBinder(BeanB.class);
+ Assert.assertNull(beanBBinder);
+
+
+ }
+
+ @Test
+ public void testGetMirroredBinderWithName() throws Exception {
+ BinderProvider.registerBinder(binderA, MY_BINDER_NAME);
+ Binder<BeanA, BeanA> beanABinder;
+ Binder<BeanB, BeanB> beanBBinder;
+
+ beanABinder = BinderProvider.getBinder(BeanA.class);
+ Assert.assertNull(beanABinder);
+ beanABinder = BinderProvider.getBinder(BeanA.class, MY_BINDER_NAME);
+ Assert.assertNotNull(beanABinder);
+ Assert.assertEquals(binderA, beanABinder);
+ beanBBinder = BinderProvider.getBinder(BeanB.class);
+
+ Assert.assertNull(beanBBinder);
+ beanBBinder = BinderProvider.getBinder(BeanB.class, MY_BINDER_NAME);
+
+ Assert.assertNull(beanBBinder);
+ }
+
+ @Test
+ public void testGetBinder() throws Exception {
+
+ BinderProvider.registerBinder(binderB);
+ Binder<BeanA, BeanA> beanABinder;
+ Binder<BeanA, BeanB> beanBBinder;
+
+ beanABinder = BinderProvider.getBinder(BeanA.class);
+ Assert.assertNull(beanABinder);
+
+ beanBBinder = BinderProvider.getBinder(BeanA.class, BeanB.class);
+ Assert.assertNotNull(beanBBinder);
+ Assert.assertEquals(binderB, beanBBinder);
+
+ }
+
+ @Test
+ public void testGetBinderWithName() throws Exception {
+ BinderProvider.registerBinder(binderB, MY_BINDER2_NAME);
+ Binder<BeanA, BeanA> beanABinder;
+ Binder<BeanA, BeanB> beanBBinder;
+
+ beanABinder = BinderProvider.getBinder(BeanA.class);
+ Assert.assertNull(beanABinder);
+
+ beanBBinder = BinderProvider.getBinder(BeanA.class, BeanB.class);
+ Assert.assertNull(beanBBinder);
+
+ beanBBinder = BinderProvider.getBinder(BeanA.class, BeanB.class, MY_BINDER2_NAME);
+ Assert.assertNotNull(beanBBinder);
+ Assert.assertEquals(binderB, beanBBinder);
+
+
+ }
+}
\ No newline at end of file
Property changes on: trunk/src/test/java/org/nuiton/util/beans/BinderProviderTest.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Added: trunk/src/test/java/org/nuiton/util/beans/BinderTest.java
===================================================================
--- trunk/src/test/java/org/nuiton/util/beans/BinderTest.java (rev 0)
+++ trunk/src/test/java/org/nuiton/util/beans/BinderTest.java 2010-02-21 18:16:09 UTC (rev 1764)
@@ -0,0 +1,113 @@
+package org.nuiton.util.beans;
+
+import org.junit.*;
+
+import java.util.Map;
+
+public class BinderTest {
+
+ BeanA a;
+ BeanB b;
+
+ Binder<BeanA, BeanA> binderA;
+ Binder<BeanA, BeanB> binderB;
+ private static final String VALUE_A = "a";
+ private static final String VALUE_B = "b";
+ private static final String VALUE_C = "c";
+
+ @BeforeClass
+ public static void beforeClass() {
+
+ BinderProvider.binders = null;
+
+ BinderBuilder builder = new BinderBuilder();
+ BinderProvider.registerBinder(builder.
+ createBinderModel(BeanA.class).
+ addSimpleProperties(BeanA.PROPERTY_A));
+
+
+ BinderProvider.registerBinder(builder.
+ createBinderModel(BeanA.class, BeanB.class).
+ addSimpleProperties(BeanA.PROPERTY_A, BeanA.PROPERTY_B).
+ addProperty(BeanA.PROPERTY_C, BeanB.PROPERTY_C2));
+
+ }
+
+ @AfterClass
+ public static void tearDown() {
+
+ BinderProvider.binders = null;
+
+ }
+
+ @Before
+ public void setUp() {
+
+ binderA = BinderProvider.getBinder(BeanA.class);
+ binderB = BinderProvider.getBinder(BeanA.class, BeanB.class);
+
+ a = new BeanA();
+ b = new BeanB();
+ }
+
+ @Test
+ public void testObtainProperties() throws Exception {
+ Map<String, Object> map;
+ map = binderA.obtainProperties(a);
+ Assert.assertEquals(0, map.size());
+
+ map = binderB.obtainProperties(a);
+ Assert.assertEquals(0, map.size());
+
+ a.setA(VALUE_A);
+ map = binderA.obtainProperties(a);
+ Assert.assertEquals(1, map.size());
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_A));
+ Assert.assertTrue(map.containsValue(VALUE_A));
+ Assert.assertEquals(VALUE_A, map.get(BeanA.PROPERTY_A));
+
+ map = binderB.obtainProperties(a);
+ Assert.assertEquals(1, map.size());
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_A));
+ Assert.assertTrue(map.containsValue(VALUE_A));
+ Assert.assertEquals(VALUE_A, map.get(BeanA.PROPERTY_A));
+
+ a.setB(VALUE_B);
+ map = binderA.obtainProperties(a);
+ Assert.assertEquals(1, map.size());
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_A));
+ Assert.assertFalse(map.containsKey(BeanA.PROPERTY_B));
+ Assert.assertTrue(map.containsValue(VALUE_A));
+ Assert.assertFalse(map.containsValue(VALUE_B));
+ Assert.assertEquals(VALUE_A, map.get(BeanA.PROPERTY_A));
+
+ map = binderB.obtainProperties(a);
+ Assert.assertEquals(2, map.size());
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_A));
+ Assert.assertTrue(map.containsKey(BeanA.PROPERTY_B));
+ Assert.assertTrue(map.containsValue(VALUE_A));
+ Assert.assertTrue(map.containsValue(VALUE_B));
+ Assert.assertEquals(VALUE_A, map.get(BeanA.PROPERTY_A));
+ Assert.assertEquals(VALUE_B, map.get(BeanA.PROPERTY_B));
+ }
+
+ @Test
+ public void testCopy() throws Exception {
+
+ a.setA(VALUE_A);
+ a.setB(VALUE_B);
+ a.setC(VALUE_C);
+
+ binderA.copy(a, b);
+ Assert.assertEquals(VALUE_A, b.getA());
+ Assert.assertNull(b.getB());
+ Assert.assertNull(b.getB2());
+ Assert.assertNull(b.getC());
+
+ 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());
+ }
+}
\ No newline at end of file
Property changes on: trunk/src/test/java/org/nuiton/util/beans/BinderTest.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
1
0
Author: tchemit
Date: 2010-02-21 11:27:26 +0100 (Sun, 21 Feb 2010)
New Revision: 1763
Modified:
trunk/pom.xml
Log:
Utilisation de mavenpom4redmine 2.0.5
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2010-02-09 17:00:40 UTC (rev 1762)
+++ trunk/pom.xml 2010-02-21 10:27:26 UTC (rev 1763)
@@ -10,7 +10,7 @@
<parent>
<groupId>org.nuiton</groupId>
<artifactId>mavenpom4redmine</artifactId>
- <version>2.0.4</version>
+ <version>2.0.5</version>
</parent>
<artifactId>nuiton-utils</artifactId>
1
0
Author: echatellier
Date: 2010-02-09 18:00:40 +0100 (Tue, 09 Feb 2010)
New Revision: 1762
Modified:
trunk/src/main/java/org/nuiton/i18n/I18n.java
Log:
Add a quick fix when key to translate is null.
Modified: trunk/src/main/java/org/nuiton/i18n/I18n.java
===================================================================
--- trunk/src/main/java/org/nuiton/i18n/I18n.java 2010-01-28 10:25:42 UTC (rev 1761)
+++ trunk/src/main/java/org/nuiton/i18n/I18n.java 2010-02-09 17:00:40 UTC (rev 1762)
@@ -131,6 +131,12 @@
* sinon.
*/
public static String _(String message) {
+
+ // if the key to translate is null, just return null
+ if (message == null) {
+ return null;
+ }
+
if (loader == null || loader.getLanguage() == null) {
return applyFilter(message);
}
@@ -146,6 +152,12 @@
* sinon.
*/
public static String _(String message, Object... args) {
+
+ // if the key to translate is null, just return null
+ if (message == null) {
+ return null;
+ }
+
String result = message;
Language language = loader == null ? null : loader.getLanguage();
if (language != null) {
1
0