// Copyright (c) 2006 - 2008, Markus Strauch.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
package net.sf.sdedit.util;
import java.awt.Font;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
/**
* Utility class for creating objects from strings.
*
* @author Markus Strauch
*
*/
public final class ObjectFactory {
private static final Map<Class<?>, Constructor<?>> stringConstructorMap;
private static final Map<Class<?>, Class<?>> primitives;
static {
primitives = new HashMap<Class<?>, Class<?>>();
primitives.put(Integer.TYPE, Integer.class);
primitives.put(Float.TYPE, Float.class);
primitives.put(Double.TYPE, Double.class);
primitives.put(Character.TYPE, Character.class);
primitives.put(Long.TYPE, Long.class);
primitives.put(Boolean.TYPE, Boolean.class);
stringConstructorMap = new HashMap<Class<?>, Constructor<?>>();
}
private ObjectFactory() {
/* empty */
}
/**
* Creates an instance of some class from a string by calling the string
* constructor of the class with the string as a parameter.
*
* @param cls
* the class of which an instance is to be created, if it is a
* primitive type, an instance of the corresponding class will be
* created
* @param string
* the string from which the instance is to be created or<tt>null</tt>,
* then an instance resulting from an invokation of the
* no-argument constructor will be returned
* @return an instance of <tt>cls</tt>, created from <tt>string</tt>
*/
public static Object createFromString(Class<?> cls, final String string) {
if (cls == String.class) {
return string == null ? "" : string;
}
if (cls == Integer.TYPE && string.length() == 1) {
return string.charAt(0) - '0';
}
if (cls == Font.class) {
return Font.decode(string);
}
final Class<?> nonPrimitive = primitives.get(cls);
if (nonPrimitive != null) {
cls = nonPrimitive;
}
try {
if (string == null) {
return cls.newInstance();
}
Constructor<?> constructor = stringConstructorMap.get(cls);
if (constructor == null) {
constructor = cls.getConstructor(new Class[] { String.class });
stringConstructorMap.put(cls, constructor);
}
return constructor.newInstance(string);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(cls.getName() + " has no"
+ " constructor with a single string as a parameter");
} catch (InstantiationException e) {
throw new IllegalArgumentException(cls.getName() + " has no"
+ " constructor with an empty parameter list");
} catch (Throwable e) {
throw new IllegalArgumentException(cls.getName() + " has a"
+ " constructor with a single string as a parameter, but"
+ " it cannot be invoked with the argument \"" + string
+ "\", which led to an exception/error of type "
+ e.getClass().getSimpleName() + " with the message: "
+ e.getMessage());
}
}
}