
org.nuiton.util.ObjectUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nuiton-utils Show documentation
Show all versions of nuiton-utils Show documentation
Library of usefull class to be used in any project.
/*
* #%L
* Nuiton Utils
*
* $Id: ObjectUtil.java 2502 2013-02-23 13:06:57Z bpoussin $
* $HeadURL: http://svn.nuiton.org/svn/nuiton-utils/tags/nuiton-utils-2.6.10/nuiton-utils/src/main/java/org/nuiton/util/ObjectUtil.java $
* %%
* 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
* .
* #L%
*/
/* *
* ObjectUtil.java
*
* Created: 2 nov. 2004
*
* @author Benjamin Poussin
* @version $Revision: 2502 $
*
* Mise a jour: $Date: 2013-02-23 14:06:57 +0100 (Sat, 23 Feb 2013) $
* par : */
package org.nuiton.util;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.MethodUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import static org.nuiton.i18n.I18n._;
/**
* Outils pour manipuler des objets. Création d'un objet à partir d'une chaîne
* le décrivant, conversion d'un objet en Object, récupération de méthodes
* à partir de leur nom, de constructeurs à partir de leurs paramètres...
*
* Created: 4 novembre 2004
*
* @author bpoussin
* $Id: ObjectUtil.java 2502 2013-02-23 13:06:57Z bpoussin $
*/
public class ObjectUtil { // ObjectUtil
/** Logger. */
static private Log log = LogFactory.getLog(ObjectUtil.class);
/** Used to know what is separator between class and method*/
public static final String CLASS_METHOD_SEPARATOR = "#";
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
* can make an instance of this class
*/
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
*/
public static E newInstance(Class clazz,
Collection> args,
boolean nullIfMissing) {
Constructor[] constructors =
(Constructor[]) clazz.getConstructors();
if (constructors.length != 1) {
throw new IllegalArgumentException(
_("nuitonutil.error.class.with.more.than.one.constructor",
clazz));
}
// copy collection into modifiable list to add new object
List> container = new LinkedList(args);
Constructor 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], container, nullIfMissing);
params[i] = o;
}
try {
E result = constructor.newInstance(params);
return result;
} catch (Exception eee) {
throw new IllegalArgumentException(_(
_("nuitonutil.error.cant.instanciate.class",
clazz, Arrays.toString(params))), eee);
}
}
/**
* Permet de matcher un type d'argument 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 le type recherché
* @param args la liste des arguments ou des types
* @param nullIfMissing pour retourner nulle si l'argument n'est pas trouvé
* @return le type d'argument trouvé
*/
static protected Object choiceArgument(Class> clazz,
List args,
boolean nullIfMissing) {
Object result = null;
boolean addResult = false;
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);
addResult = true;
break;
} else if (clazz.isInstance(o)) {
// cas on l'on retrouve un objet assignable pour ce type
result = o;
break;
}
}
}
if (addResult) {
// on ajoute en tete pour qu'il soit retrouve dans les premiers
// et non pas reinstancier une nouvelle fois si on en a besoin
// a nouveau
args.add(0, result);
}
// si on ne retrouve rien, result est reste a null
if (result == null && !nullIfMissing) {
throw new IllegalArgumentException(_(
_("nuitonutil.error.unfound.assignable.argument",
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
*
* For String property you can use ex:
* name="my string with , in string"
* name='my string with , in string'
*
* @param classnameAndProperties
* @return the instanciated object
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
public static Object create(String classnameAndProperties) throws
ClassNotFoundException,
InstantiationException,
IllegalAccessException,
InvocationTargetException,
NoSuchMethodException {
int p = classnameAndProperties.indexOf('(');
int l = classnameAndProperties.lastIndexOf(')');
String[] properties = null;
String classname;
if (p != -1) {
String tmp = classnameAndProperties.substring(p + 1, l);
properties = StringUtil.split(tmp, ",");
classname = classnameAndProperties.substring(0, p);
} else {
classname = classnameAndProperties;
}
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class> clazz = loader.loadClass(classname);
Object o = clazz.getConstructor().newInstance();
if (properties != null) {
for (String prop : properties) {
int e = prop.indexOf('=');
String propName = prop.substring(0, e).trim();
String propValue = prop.substring(e + 1).trim();
if (propValue.charAt(0) == '"' &&
propValue.charAt(propValue.length() - 1) == '"') {
propValue = propValue.substring(1, propValue.length() - 1);
} else if (propValue.charAt(0) == '\'' &&
propValue.charAt(propValue.length() - 1) == '\'') {
propValue = propValue.substring(1, propValue.length() - 1);
}
BeanUtils.setProperty(o, propName, propValue);
}
}
return o;
}
static protected Object convert(String v, Class> clazz) {
Object t = ConvertUtils.convert(v, clazz);
if (t != null &&
!String.class.getName().equals(clazz.getName()) &&
String.class.getName().equals(t.getClass().getName())) {
throw new IllegalArgumentException(String.format(
"Can convert argument to correct type. %s can't be" +
" converted from String to %s conversion is done to %s",
v, clazz.getName(), t.getClass().getName()));
}
return t;
}
/**
* Clone object by introspection because Cloneable interface don't permit
* to call clone :(. This methode replace next code that don't work :(
*
*
* if (o instanceof Cloneable) {
* Object n = ((Cloneable)o).clone();
* }
*
*
* @param e object to clone
* @return new instance of E
* @throws CloneNotSupportedException if some error occur during clone
*/
public static E clone(E e) throws CloneNotSupportedException {
try {
E result = (E) MethodUtils.invokeExactMethod(e, "clone", null);
return result;
} catch (Exception eee) {
// on est oblige de faire un log, car CloneNotSupportedException
// ne prend pas d'exception en arguement :(
log.error("Can't clone object", eee);
throw new CloneNotSupportedException();
}
}
/**
* Use serialization/deserialization to do deep clone of object
*
* @param e object to clone
* @return new instance of E
* @throws CloneNotSupportedException if some error occur during clone
*/
public static E deepClone(E e) throws CloneNotSupportedException {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
try {
oos.writeObject(e);
} finally {
oos.close();
}
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
E result;
ObjectInputStream ois = new ObjectInputStream(bis);
try {
result = (E) ois.readObject();
} finally {
ois.close();
}
return result;
} catch (Exception eee) {
// on est oblige de faire un log, car CloneNotSupportedException
// ne prend pas d'exception en arguement :(
log.error("Can't clone object", eee);
throw new CloneNotSupportedException();
}
}
/**
* Call method m with params as String. Each param is converted to required type for
* method with beanutils converter
*
* @param o object where method must be call
* @param m method to call
* @param params parameters for method call
* @return returned method's value
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws InstantiationException
*/
public static Object call(Object o, Method m, String... params)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
Class>[] types = m.getParameterTypes();
if (!m.isVarArgs() && params.length != types.length) {
throw new IllegalArgumentException(String.format(
"Bad number params we have %1$s parameters and waiting %2$s.",
params.length, types.length));
}
int last = types.length;
if (m.isVarArgs()) {
// on traite le dernier differement
last--;
}
Object[] parameters = new Object[types.length];
for (int i = 0; i < last; i++) {
String v = params[i];
Class> clazz = types[i];
Object t = convert(v, clazz);
parameters[i] = t;
}
if (m.isVarArgs()) {
Class> clazz = types[last]; // get var args type
clazz = clazz.getComponentType(); // get array component type
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy