aQute.lib.converter.Converter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bnd Show documentation
Show all versions of bnd Show documentation
A command line utility and Ant plugin to wrap, build, or examine bundles.
package aQute.lib.converter;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;
import aQute.lib.base64.*;
/**
* General Java type converter from an object to any type. Supports number
* conversion
*
* @author aqute
*/
@SuppressWarnings({
"unchecked", "rawtypes"
})
public class Converter {
public interface Hook {
Object convert(Type dest, Object o) throws Exception;
}
boolean fatal = true;
Map hooks;
List allHooks;
public T convert(Class type, Object o) throws Exception {
// Is it a compatible type?
if (type.isAssignableFrom(o.getClass()))
return (T) o;
return (T) convert((Type) type, o);
}
public T convert(TypeReference type, Object o) throws Exception {
return (T) convert(type.getType(), o);
}
public Object convert(Type type, Object o) throws Exception {
Class resultType = getRawClass(type);
if (o == null) {
if (resultType.isPrimitive() || Number.class.isAssignableFrom(resultType))
return convert(type, 0);
return null; // compatible with any
}
if (allHooks != null) {
for (Hook hook : allHooks) {
Object r = hook.convert(type, o);
if (r != null)
return r;
}
}
if (hooks != null) {
Hook hook = hooks.get(type);
if (hook != null) {
Object value = hook.convert(type, o);
if (value != null)
return value;
}
}
Class< ? > actualType = o.getClass();
// We can always make a string
if (resultType == String.class) {
if (actualType.isArray()) {
if (actualType == char[].class)
return new String((char[]) o);
if (actualType == byte[].class)
return Base64.encodeBase64((byte[]) o);
int l = Array.getLength(o);
StringBuilder sb = new StringBuilder("[");
String del = "";
for (int i = 0; i < l; i++) {
sb.append(del);
del = ",";
sb.append(convert(String.class, Array.get(o, i)));
}
sb.append("]");
return sb.toString();
}
return o.toString();
}
if (Collection.class.isAssignableFrom(resultType))
return collection(type, resultType, o);
if (Map.class.isAssignableFrom(resultType))
return map(type, resultType, o);
if (type instanceof GenericArrayType) {
GenericArrayType gType = (GenericArrayType) type;
return array(gType.getGenericComponentType(), o);
}
if (resultType.isArray()) {
if (actualType == String.class) {
String s = (String) o;
if (byte[].class == resultType)
return Base64.decodeBase64(s);
if (char[].class == resultType)
return s.toCharArray();
}
if (byte[].class == resultType) {
// Sometimes classes implement toByteArray
try {
Method m = actualType.getMethod("toByteArray");
if (m.getReturnType() == byte[].class)
return m.invoke(o);
}
catch (Exception e) {
// Ignore
}
}
return array(resultType.getComponentType(), o);
}
if (resultType.isAssignableFrom(o.getClass()))
return o;
if (Map.class.isAssignableFrom(actualType) && resultType.isInterface()) {
return proxy(resultType, (Map) o);
}
// Simple type coercion
if (resultType == boolean.class || resultType == Boolean.class) {
if (actualType == boolean.class || actualType == Boolean.class)
return o;
Number n = number(o);
if (n != null)
return n.longValue() == 0 ? false : true;
resultType = Boolean.class;
} else if (resultType == byte.class || resultType == Byte.class) {
Number n = number(o);
if (n != null)
return n.byteValue();
resultType = Byte.class;
} else if (resultType == char.class || resultType == Character.class) {
Number n = number(o);
if (n != null)
return (char) n.shortValue();
resultType = Character.class;
} else if (resultType == short.class || resultType == Short.class) {
Number n = number(o);
if (n != null)
return n.shortValue();
resultType = Short.class;
} else if (resultType == int.class || resultType == Integer.class) {
Number n = number(o);
if (n != null)
return n.intValue();
resultType = Integer.class;
} else if (resultType == long.class || resultType == Long.class) {
Number n = number(o);
if (n != null)
return n.longValue();
resultType = Long.class;
} else if (resultType == float.class || resultType == Float.class) {
Number n = number(o);
if (n != null)
return n.floatValue();
resultType = Float.class;
} else if (resultType == double.class || resultType == Double.class) {
Number n = number(o);
if (n != null)
return n.doubleValue();
resultType = Double.class;
}
assert !resultType.isPrimitive();
if (actualType == String.class) {
String input = (String) o;
if (resultType == char[].class)
return input.toCharArray();
if (resultType == byte[].class)
return Base64.decodeBase64(input);
if (Enum.class.isAssignableFrom(resultType)) {
try {
return Enum.valueOf((Class) resultType, input);
} catch( Exception e) {
input = input.toUpperCase();
return Enum.valueOf((Class) resultType, input);
}
}
if (resultType == Pattern.class) {
return Pattern.compile(input);
}
try {
Constructor< ? > c = resultType.getConstructor(String.class);
return c.newInstance(o.toString());
}
catch (Throwable t) {}
try {
Method m = resultType.getMethod("valueOf", String.class);
if (Modifier.isStatic(m.getModifiers()))
return m.invoke(null, o.toString());
}
catch (Throwable t) {}
if (resultType == Character.class && input.length() == 1)
return input.charAt(0);
}
Number n = number(o);
if (n != null) {
if (Enum.class.isAssignableFrom(resultType)) {
try {
Method values = resultType.getMethod("values");
Enum[] vs = (Enum[]) values.invoke(null);
int nn = n.intValue();
if (nn > 0 && nn < vs.length)
return vs[nn];
}
catch (Exception e) {
// Ignore
}
}
}
// Translate arrays with length 1 by picking the single element
if (actualType.isArray() && Array.getLength(o) == 1) {
return convert(type, Array.get(o, 0));
}
// Translate collections with size 1 by picking the single element
if (o instanceof Collection) {
Collection col = (Collection) o;
if (col.size() == 1)
return convert(type, col.iterator().next());
}
if (o instanceof Map) {
String key = null;
try {
Map
© 2015 - 2024 Weber Informatics LLC | Privacy Policy