TMC-LANG: Code clean-up, added tests and fixed issues.

This commit is contained in:
Harald Kuhr
2013-06-06 19:51:07 +02:00
parent f5b5e818c5
commit cdce0aebff
5 changed files with 182 additions and 97 deletions
@@ -36,7 +36,7 @@ import java.util.Map;
/**
* The converter (singleton). Converts strings to objects and back.
* This is the entrypoint to the converter framework.
* This is the entry point to the converter framework.
* <p/>
* By default, converters for {@link com.twelvemonkeys.util.Time}, {@link Date}
* and {@link Object}
@@ -53,17 +53,17 @@ import java.util.Map;
*/
// TODO: Get rid of singleton stuff
// Can probably be a pure static class, but is that a good idea?
// Maybe have BeanUtil act as a "proxy", and hide this class alltogheter?
// Maybe have BeanUtil act as a "proxy", and hide this class all together?
// TODO: ServiceRegistry for registering 3rd party converters
// TODO: URI scheme, for implicit typing? Is that a good idea?
// TODO: Array converters?
public abstract class Converter implements PropertyConverter {
/** Our singleton instance */
protected static Converter sInstance = new ConverterImpl(); // Thread safe & EASY
protected static final Converter sInstance = new ConverterImpl(); // Thread safe & EASY
/** The conveters Map */
protected Map converters = new Hashtable();
/** The converters Map */
protected final Map<Class, PropertyConverter> converters = new Hashtable<Class, PropertyConverter>();
// Register our predefined converters
static {
@@ -115,20 +115,21 @@ public abstract class Converter implements PropertyConverter {
*
* @see #unregisterConverter(Class)
*/
public static void registerConverter(Class pType, PropertyConverter pConverter) {
public static void registerConverter(final Class<?> pType, final PropertyConverter pConverter) {
getInstance().converters.put(pType, pConverter);
}
/**
* Unregisters a converter for a given type. That is, making it unavailable
* Un-registers a converter for a given type. That is, making it unavailable
* for the converter framework, and making it (potentially) available for
* garbabe collection.
* garbage collection.
*
* @param pType the (super) type to remove converter for
*
* @see #registerConverter(Class,PropertyConverter)
*/
public static void unregisterConverter(Class pType) {
@SuppressWarnings("UnusedDeclaration")
public static void unregisterConverter(final Class<?> pType) {
getInstance().converters.remove(pType);
}
@@ -143,8 +144,7 @@ public abstract class Converter implements PropertyConverter {
* @throws ConversionException if the string cannot be converted for any
* reason.
*/
public Object toObject(String pString, Class pType)
throws ConversionException {
public Object toObject(final String pString, final Class pType) throws ConversionException {
return toObject(pString, pType, null);
}
@@ -174,7 +174,7 @@ public abstract class Converter implements PropertyConverter {
* @throws ConversionException if the object cannot be converted to a
* string for any reason.
*/
public String toString(Object pObject) throws ConversionException {
public String toString(final Object pObject) throws ConversionException {
return toString(pObject, null);
}
@@ -67,9 +67,9 @@ public final class DefaultConverter implements PropertyConverter {
*
* @throws ConversionException if the type is null, or if the string cannot
* be converted into the given type, using a string constructor or static
* {@code valueof} method.
* {@code valueOf} method.
*/
public Object toObject(String pString, final Class pType, String pFormat) throws ConversionException {
public Object toObject(final String pString, final Class pType, final String pFormat) throws ConversionException {
if (pString == null) {
return null;
}
@@ -87,13 +87,7 @@ public final class DefaultConverter implements PropertyConverter {
// But what about generic type?! It's erased...
// Primitive -> wrapper
Class type;
if (pType == Boolean.TYPE) {
type = Boolean.class;
}
else {
type = pType;
}
Class type = unBoxType(pType);
try {
// Try to create instance from <Constructor>(String)
@@ -101,13 +95,15 @@ public final class DefaultConverter implements PropertyConverter {
if (value == null) {
// createInstance failed for some reason
// Try to invoke the static method valueof(String)
// Try to invoke the static method valueOf(String)
value = BeanUtil.invokeStaticMethod(type, "valueOf", pString);
if (value == null) {
// If the value is still null, well, then I cannot help...
throw new ConversionException("Could not convert String to " + pType.getName() + ": No constructor " + type.getName() + "(String) or static " + type.getName() + ".valueof(String) method found!");
throw new ConversionException(String.format(
"Could not convert String to %1$s: No constructor %1$s(String) or static %1$s.valueOf(String) method found!",
type.getName()
));
}
}
@@ -116,12 +112,15 @@ public final class DefaultConverter implements PropertyConverter {
catch (InvocationTargetException ite) {
throw new ConversionException(ite.getTargetException());
}
catch (ConversionException ce) {
throw ce;
}
catch (RuntimeException rte) {
throw new ConversionException(rte);
}
}
private Object toArray(String pString, Class pType, String pFormat) {
private Object toArray(final String pString, final Class pType, final String pFormat) {
String[] strings = StringUtil.toStringArray(pString, pFormat != null ? pFormat : StringUtil.DELIMITER_STRING);
Class type = pType.getComponentType();
if (type == String.class) {
@@ -152,10 +151,9 @@ public final class DefaultConverter implements PropertyConverter {
* @param pObject the object to convert.
* @param pFormat ignored.
*
* @return the string representation of the object, or {@code null} if
* {@code pObject == null}
* @return the string representation of the object, or {@code null} if {@code pObject == null}
*/
public String toString(Object pObject, String pFormat)
public String toString(final Object pObject, final String pFormat)
throws ConversionException {
try {
@@ -170,7 +168,7 @@ public final class DefaultConverter implements PropertyConverter {
return pFormat == null ? StringUtil.toCSVString(pArray) : StringUtil.toCSVString(pArray, pFormat);
}
private Object[] toObjectArray(Object pObject) {
private Object[] toObjectArray(final Object pObject) {
// TODO: Extract util method for wrapping/unwrapping native arrays?
Object[] array;
Class<?> componentType = pObject.getClass().getComponentType();
@@ -232,4 +230,37 @@ public final class DefaultConverter implements PropertyConverter {
}
return array;
}
private Class<?> unBoxType(final Class<?> pType) {
if (pType.isPrimitive()) {
if (pType == boolean.class) {
return Boolean.class;
}
if (pType == byte.class) {
return Byte.class;
}
if (pType == char.class) {
return Character.class;
}
if (pType == short.class) {
return Short.class;
}
if (pType == int.class) {
return Integer.class;
}
if (pType == float.class) {
return Float.class;
}
if (pType == long.class) {
return Long.class;
}
if (pType == double.class) {
return Double.class;
}
throw new IllegalArgumentException("Unknown type: " + pType);
}
return pType;
}
}