in juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java [493:917]
protected final <T> T convertToMemberType(Object outer, Object value, ClassMeta<T> to) throws InvalidDataConversionException {
if (to == null)
to = (ClassMeta<T>)object();
try {
// Handle the case of a null value.
if (value == null) {
// If it's a primitive, then use the converters to get the default value for the primitive type.
if (to.isPrimitive())
return to.getPrimitiveDefault();
// Otherwise, just return null.
return to.isOptional() ? (T)to.getOptionalDefault() : null;
}
if (to.isOptional() && (! (value instanceof Optional)))
return (T) optional(convertToMemberType(outer, value, to.getElementType()));
Class<T> tc = to.getInnerClass();
// If no conversion needed, then just return the value.
// Don't include maps or collections, because child elements may need conversion.
if (tc.isInstance(value))
if (! ((to.isMap() && to.getValueType().isNotObject()) || ((to.isCollection() || to.isOptional()) && to.getElementType().isNotObject())))
return (T)value;
ObjectSwap swap = to.getSwap(this);
if (swap != null) {
ClassInfo nc = swap.getNormalClass(), fc = swap.getSwapClass();
if (nc.isParentOf(tc) && fc.isParentOf(value.getClass()))
return (T)swap.unswap(this, value, to);
ClassMeta fcm = getClassMeta(fc.inner());
if (fcm.isNumber() && value instanceof Number) {
value = convertToMemberType(null, value, fc.inner());
return (T)swap.unswap(this, value, to);
}
}
ClassMeta<?> from = getClassMetaForObject(value);
swap = from.getSwap(this);
if (swap != null) {
ClassInfo nc = swap.getNormalClass(), fc = swap.getSwapClass();
if (nc.isParentOf(from.getInnerClass()) && fc.isParentOf(tc))
return (T)swap.swap(this, value);
}
if (to.isPrimitive()) {
if (to.isNumber()) {
if (from.isNumber()) {
Number n = (Number)value;
if (tc == Integer.TYPE)
return (T)Integer.valueOf(n.intValue());
if (tc == Short.TYPE)
return (T)Short.valueOf(n.shortValue());
if (tc == Long.TYPE)
return (T)Long.valueOf(n.longValue());
if (tc == Float.TYPE)
return (T)Float.valueOf(n.floatValue());
if (tc == Double.TYPE)
return (T)Double.valueOf(n.doubleValue());
if (tc == Byte.TYPE)
return (T)Byte.valueOf(n.byteValue());
} else if (from.isBoolean()) {
Boolean b = (Boolean)value;
if (tc == Integer.TYPE)
return (T)(Integer.valueOf(b ? 1 : 0));
if (tc == Short.TYPE)
return (T)(Short.valueOf(b ? (short)1 : 0));
if (tc == Long.TYPE)
return (T)(Long.valueOf(b ? 1L : 0));
if (tc == Float.TYPE)
return (T)(Float.valueOf(b ? 1f : 0));
if (tc == Double.TYPE)
return (T)(Double.valueOf(b ? 1d : 0));
if (tc == Byte.TYPE)
return (T)(Byte.valueOf(b ? (byte)1 : 0));
} else if (isNullOrEmpty(value)) {
return (T)to.info.getPrimitiveDefault();
} else {
String s = value.toString();
int multiplier = (tc == Integer.TYPE || tc == Short.TYPE || tc == Long.TYPE) ? getMultiplier(s) : 1;
if (multiplier != 1) {
s = s.substring(0, s.length()-1).trim();
Long l = Long.valueOf(s) * multiplier;
if (tc == Integer.TYPE)
return (T)Integer.valueOf(l.intValue());
if (tc == Short.TYPE)
return (T)Short.valueOf(l.shortValue());
if (tc == Long.TYPE)
return (T)Long.valueOf(l.longValue());
} else {
if (tc == Integer.TYPE)
return (T)Integer.valueOf(s);
if (tc == Short.TYPE)
return (T)Short.valueOf(s);
if (tc == Long.TYPE)
return (T)Long.valueOf(s);
if (tc == Float.TYPE)
return (T)Float.valueOf(s);
if (tc == Double.TYPE)
return (T)Double.valueOf(s);
if (tc == Byte.TYPE)
return (T)Byte.valueOf(s);
}
}
} else if (to.isChar()) {
if (isNullOrEmpty(value))
return (T)to.info.getPrimitiveDefault();
return (T)parseCharacter(value);
} else if (to.isBoolean()) {
if (from.isNumber()) {
int i = ((Number)value).intValue();
return (T)(i == 0 ? Boolean.FALSE : Boolean.TRUE);
} else if (isNullOrEmpty(value)) {
return (T)to.info.getPrimitiveDefault();
} else {
return (T)Boolean.valueOf(value.toString());
}
}
}
if (to.isNumber()) {
if (from.isNumber()) {
Number n = (Number)value;
if (tc == Integer.class)
return (T)Integer.valueOf(n.intValue());
if (tc == Short.class)
return (T)Short.valueOf(n.shortValue());
if (tc == Long.class)
return (T)Long.valueOf(n.longValue());
if (tc == Float.class)
return (T)Float.valueOf(n.floatValue());
if (tc == Double.class)
return (T)Double.valueOf(n.doubleValue());
if (tc == Byte.class)
return (T)Byte.valueOf(n.byteValue());
if (tc == AtomicInteger.class)
return (T)new AtomicInteger(n.intValue());
if (tc == AtomicLong.class)
return (T)new AtomicLong(n.intValue());
} else if (from.isBoolean()) {
Boolean b = (Boolean)value;
if (tc == Integer.class)
return (T)Integer.valueOf(b ? 1 : 0);
if (tc == Short.class)
return (T)Short.valueOf(b ? (short)1 : 0);
if (tc == Long.class)
return (T)Long.valueOf(b ? 1 : 0);
if (tc == Float.class)
return (T)Float.valueOf(b ? 1 : 0);
if (tc == Double.class)
return (T)Double.valueOf(b ? 1 : 0);
if (tc == Byte.class)
return (T)Byte.valueOf(b ? (byte)1 : 0);
if (tc == AtomicInteger.class)
return (T)new AtomicInteger(b ? 1 : 0);
if (tc == AtomicLong.class)
return (T)new AtomicLong(b ? 1 : 0);
} else if (isNullOrEmpty(value)) {
return null;
} else if (! hasMutater(from, to)) {
String s = value.toString();
int multiplier = (tc == Integer.class || tc == Short.class || tc == Long.class) ? getMultiplier(s) : 1;
if (multiplier != 1) {
s = s.substring(0, s.length()-1).trim();
Long l = Long.valueOf(s) * multiplier;
if (tc == Integer.TYPE)
return (T)Integer.valueOf(l.intValue());
if (tc == Short.TYPE)
return (T)Short.valueOf(l.shortValue());
if (tc == Long.TYPE)
return (T)Long.valueOf(l.longValue());
} else {
if (tc == Integer.class)
return (T)Integer.valueOf(s);
if (tc == Short.class)
return (T)Short.valueOf(s);
if (tc == Long.class)
return (T)Long.valueOf(s);
if (tc == Float.class)
return (T)Float.valueOf(s);
if (tc == Double.class)
return (T)Double.valueOf(s);
if (tc == Byte.class)
return (T)Byte.valueOf(s);
if (tc == AtomicInteger.class)
return (T)new AtomicInteger(Integer.valueOf(s));
if (tc == AtomicLong.class)
return (T)new AtomicLong(Long.valueOf(s));
if (tc == Number.class)
return (T)StringUtils.parseNumber(s, Number.class);
}
}
}
if (to.isChar()) {
if (isNullOrEmpty(value))
return null;
String s = value.toString();
if (s.length() == 1)
return (T)Character.valueOf(s.charAt(0));
}
if (to.isByteArray()) {
if (from.isInputStream())
return (T)readBytes((InputStream)value);
if (from.isReader())
return (T)read((Reader)value).getBytes();
if (to.hasMutaterFrom(from))
return to.mutateFrom(value);
if (from.hasMutaterTo(to))
return from.mutateTo(value, to);
return (T) value.toString().getBytes(Charset.forName("UTF-8"));
}
// Handle setting of array properties
if (to.isArray()) {
if (from.isCollection())
return (T)toArray(to, (Collection)value);
else if (from.isArray())
return (T)toArray(to, alist((Object[])value));
else if (startsWith(value.toString(), '['))
return (T)toArray(to, JsonList.ofJson(value.toString()).setBeanSession(this));
else if (to.hasMutaterFrom(from))
return to.mutateFrom(value);
else if (from.hasMutaterTo(to))
return from.mutateTo(value, to);
else
return (T)toArray(to, new JsonList((Object[])StringUtils.split(value.toString())).setBeanSession(this));
}
// Target type is some sort of Map that needs to be converted.
if (to.isMap()) {
try {
if (from.isMap()) {
Map m = to.canCreateNewInstance(outer) ? (Map)to.newInstance(outer) : newGenericMap(to);
ClassMeta keyType = to.getKeyType(), valueType = to.getValueType();
((Map<?,?>)value).forEach((k,v) -> {
Object k2 = k;
if (keyType.isNotObject()) {
if (keyType.isString() && k.getClass() != Class.class)
k2 = k.toString();
else
k2 = convertToMemberType(m, k, keyType);
}
Object v2 = v;
if (valueType.isNotObject())
v2 = convertToMemberType(m, v, valueType);
m.put(k2, v2);
});
return (T)m;
} else if (!to.canCreateNewInstanceFromString(outer)) {
JsonMap m = JsonMap.ofJson(value.toString());
m.setBeanSession(this);
return convertToMemberType(outer, m, to);
}
} catch (Exception e) {
throw new InvalidDataConversionException(value.getClass(), to, e);
}
}
// Target type is some sort of Collection
if (to.isCollection()) {
try {
Collection l = to.canCreateNewInstance(outer) ? (Collection)to.newInstance(outer) : to.isSet() ? set() : new JsonList(this);
ClassMeta elementType = to.getElementType();
if (from.isArray()) {
for (int i = 0; i < Array.getLength(value); i++) {
Object o = Array.get(value, i);
l.add(elementType.isObject() ? o : convertToMemberType(l, o, elementType));
}
}
else if (from.isCollection())
((Collection)value).forEach(x -> l.add(elementType.isObject() ? x : convertToMemberType(l, x, elementType)));
else if (from.isMap())
l.add(elementType.isObject() ? value : convertToMemberType(l, value, elementType));
else if (isNullOrEmpty(value))
return null;
else if (from.isString()) {
String s = value.toString();
if (isJsonArray(s, false)) {
JsonList l2 = JsonList.ofJson(s);
l2.setBeanSession(this);
l2.forEach(x -> l.add(elementType.isObject() ? x : convertToMemberType(l, x, elementType)));
} else {
throw new InvalidDataConversionException(value.getClass(), to, null);
}
}
else
throw new InvalidDataConversionException(value.getClass(), to, null);
return (T)l;
} catch (InvalidDataConversionException e) {
throw e;
} catch (Exception e) {
throw new InvalidDataConversionException(value.getClass(), to, e);
}
}
if (to.isEnum()) {
return to.newInstanceFromString(outer, value.toString());
}
if (to.isString()) {
if (from.isByteArray()) {
return (T) new String((byte[])value);
} else if (from.isMapOrBean() || from.isCollectionOrArrayOrOptional()) {
WriterSerializer ws = ctx.getBeanToStringSerializer();
if (ws != null)
return (T)ws.serialize(value);
} else if (from.isClass()) {
return (T)((Class<?>)value).getName();
}
return (T)value.toString();
}
if (to.isCharSequence()) {
Class<?> c = value.getClass();
if (c.isArray()) {
if (c.getComponentType().isPrimitive()) {
JsonList l = new JsonList(this);
int size = Array.getLength(value);
for (int i = 0; i < size; i++)
l.add(Array.get(value, i));
value = l;
}
value = new JsonList((Object[])value).setBeanSession(this);
}
return to.newInstanceFromString(outer, value.toString());
}
if (to.isBoolean()) {
if (from.isNumber())
return (T)(Boolean.valueOf(((Number)value).intValue() != 0));
if (isNullOrEmpty(value))
return null;
if (! hasMutater(from, to))
return (T)Boolean.valueOf(value.toString());
}
// It's a bean being initialized with a Map
if (to.isBean() && value instanceof Map) {
BuilderSwap<T,Object> builder = (BuilderSwap<T,Object>)to.getBuilderSwap(this);
if (value instanceof JsonMap && builder == null) {
JsonMap m2 = (JsonMap)value;
String typeName = m2.getString(getBeanTypePropertyName(to));
if (typeName != null) {
ClassMeta cm = to.getBeanRegistry().getClassMeta(typeName);
if (cm != null && to.info.isParentOf(cm.innerClass))
return (T)m2.cast(cm);
}
}
if (builder != null) {
BeanMap m = toBeanMap(builder.create(this, to));
m.load((Map<?,?>) value);
return builder.build(this, m.getBean(), to);
}
return newBeanMap(tc).load((Map<?,?>) value).getBean();
}
if (to.isInputStream()) {
if (from.isByteArray()) {
byte[] b = (byte[])value;
return (T) new ByteArrayInputStream(b, 0, b.length);
}
byte[] b = value.toString().getBytes();
return (T)new ByteArrayInputStream(b, 0, b.length);
}
if (to.isReader()) {
if (from.isByteArray()) {
byte[] b = (byte[])value;
return (T) new StringReader(new String(b));
}
return (T)new StringReader(value.toString());
}
if (to.isCalendar()) {
if (from.isCalendar()) {
Calendar c = (Calendar)value;
if (value instanceof GregorianCalendar) {
GregorianCalendar c2 = new GregorianCalendar(c.getTimeZone());
c2.setTime(c.getTime());
return (T)c2;
}
}
if (from.isDate()) {
Date d = (Date)value;
if (value instanceof GregorianCalendar) {
GregorianCalendar c2 = new GregorianCalendar(TimeZone.getDefault());
c2.setTime(d);
return (T)c2;
}
}
return (T)DatatypeConverter.parseDateTime(DateUtils.toValidISO8601DT(value.toString()));
}
if (to.isDate() && to.getInnerClass() == Date.class) {
if (from.isCalendar())
return (T)((Calendar)value).getTime();
return (T)DatatypeConverter.parseDateTime(DateUtils.toValidISO8601DT(value.toString())).getTime();
}
if (to.hasMutaterFrom(from))
return to.mutateFrom(value);
if (from.hasMutaterTo(to))
return from.mutateTo(value, to);
if (to.isBean())
return newBeanMap(to.getInnerClass()).load(value.toString()).getBean();
if (to.canCreateNewInstanceFromString(outer))
return to.newInstanceFromString(outer, value.toString());
} catch (Exception e) {
throw new InvalidDataConversionException(value, to, e);
}
throw new InvalidDataConversionException(value, to, null);
}