Author: bpoussin Date: 2010-12-02 02:03:40 +0100 (Thu, 02 Dec 2010) New Revision: 1961 Url: http://nuiton.org/repositories/revision/nuiton-utils/1961 Log: add new method newInstance that try to find argument for constructor in collection of object and class Modified: trunk/src/main/java/org/nuiton/util/ObjectUtil.java Modified: trunk/src/main/java/org/nuiton/util/ObjectUtil.java =================================================================== --- trunk/src/main/java/org/nuiton/util/ObjectUtil.java 2010-11-29 20:12:17 UTC (rev 1960) +++ trunk/src/main/java/org/nuiton/util/ObjectUtil.java 2010-12-02 01:03:40 UTC (rev 1961) @@ -53,6 +53,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.ConvertUtils; @@ -77,6 +78,73 @@ private ObjectUtil() {} /** + * Invoke constructor on clazz to create new instance. Try to find argument + * for constructor in args parameter. + * + * @param clazz class of object to instanciate + * @param args all possible parameter that constructor can used + * @param nullIfMissing if no suitable class or object found in args, + * use null value (no exception) + * @return new instance + * @throws IllegalArgumentException if something is wrong during instanciation + */ + static public <E> E newInstance(Class<E> clazz, Collection args, boolean nullIfMissing) { + Constructor<E>[] constructors = (Constructor<E>[])clazz.getConstructors(); + if (constructors.length != 1) { + throw new IllegalArgumentException(_("Your class %s has more than one constructor", clazz)); + } + Constructor<E> constructor = constructors[0]; + Class[] paramTypes = constructor.getParameterTypes(); + Object[] params = new Object[paramTypes.length]; + + for (int i=0; i<paramTypes.length; i++) { + Object o = choiceArgument(paramTypes[i], args, nullIfMissing); + params[i] = o; + } + + try { + E result = constructor.newInstance(params); + return result; + } catch (Exception eee) { + throw new IllegalArgumentException(_( + "Class %s can't be instanciated with %s", + clazz, Arrays.toString(params)), eee); + } + } + + /** + * Permet de matcher un type d'agument attendu clazz parmi un ensemble + * possible de candidat. Les candidats peuvent etre des classes qu'il faudra + * instancier pour satisfaire le type demande. + * + * @param clazz + * @param args + * @param nullIfMissing + * @return + */ + static protected Object choiceArgument(Class clazz, Collection args, boolean nullIfMissing) { + Object result = null; + for (Object o : args) { + if (o != null) { + if ((o instanceof Class) && clazz.isAssignableFrom((Class) o)) { + // cas on l'on trouve une class dans arg qui une fois instancier convient + result = newInstance((Class) o, args, nullIfMissing); + } else if (clazz.isInstance(o)) { + // cas on l'on retrouve un objet assignable pour ce type + result = o; + } + } + } + + // si on ne retrouve rien, result est reste a null + if (result == null && !nullIfMissing) { + throw new IllegalArgumentException(_( + "Can't find assignable argument for %s in %s", clazz, args)); + } + return result; + } + + /** * Create new object from string like org.nuiton.Toto(name=machine, int=10) * where machine and int is properties on org.nuiton.Toto object. * Conversion between 10 in string and 10 as integer as automaticaly done
participants (1)
-
bpoussin@users.nuiton.org