Object o = create(context, c);
if (o != null) {
Map<String, AnnotatedElement> props = context.getSetProperties(c);
for (Map.Entry<?, ?> entry : src.entrySet()) {
String name = entry.getKey().toString();
AnnotatedElement target = props.get(name);
if (target == null) target = props.get(ClassUtil.toLowerCamel(name));
if (target == null) continue;
context.enter(name, target.getAnnotation(JSONHint.class));
if (target instanceof Method) {
Method m = (Method)target;
Type gptype = m.getGenericParameterTypes()[0];
Class<?> ptype = m.getParameterTypes()[0];
if (gptype instanceof TypeVariable<?> && type instanceof ParameterizedType) {
gptype = resolveTypeVariable((TypeVariable<?>)gptype, (ParameterizedType)type);
ptype = ClassUtil.getRawType(gptype);
}
m.invoke(o, postparse(context, entry.getValue(), ptype, gptype));
} else {
Field f = (Field)target;
Type gptype = f.getGenericType();
Class<?> ptype = f.getType();
if (gptype instanceof TypeVariable<?> && type instanceof ParameterizedType) {
gptype = resolveTypeVariable((TypeVariable<?>)gptype, (ParameterizedType)type);
ptype = ClassUtil.getRawType(gptype);
}
f.set(o, postparse(context, entry.getValue(), ptype, gptype));
}
context.exit();
}
data = o;
} else {
throw new UnsupportedOperationException();
}
}
} else if (value instanceof List) {
List<?> src = (List<?>)value;
if (Collection.class.isAssignableFrom(c)) {
Collection<Object> collection = null;
if (type instanceof ParameterizedType) {
Type[] pts = ((ParameterizedType)type).getActualTypeArguments();
Type pt = (pts != null && pts.length > 0) ? pts[0] : Object.class;
Class<?> pc = ClassUtil.getRawType(pt);
if (Object.class.equals(pc)) {
collection = (Collection<Object>)src;
} else {
collection = (Collection<Object>)create(context, c);
for (int i = 0; i < src.size(); i++) {
context.enter(i);
collection.add(postparse(context, src.get(i), pc, pt));
context.exit();
}
}
} else {
collection = (Collection<Object>)create(context, c);
collection.addAll(src);
}
data = collection;
} else if (c.isArray()) {
Object array = Array.newInstance(c.getComponentType(), src.size());
Class<?> pc = c.getComponentType();
Type pt = (type instanceof GenericArrayType) ?
((GenericArrayType)type).getGenericComponentType() : pc;
for (int i = 0; i < src.size(); i++) {
context.enter(i);
Array.set(array, i, postparse(context, src.get(i), pc, pt));
context.exit();
}
data = array;
} else if (Map.class.isAssignableFrom(c)) {
Map<Object, Object> map = (Map<Object, Object>)create(context, c);
if (Properties.class.isAssignableFrom(c)) {
flattenProperties(new StringBuilder(32), (List<Object>)value, (Properties)map);
} else if (type instanceof ParameterizedType) {
Type[] pts = ((ParameterizedType)type).getActualTypeArguments();
Type pt0 = (pts != null && pts.length > 0) ? pts[0] : Object.class;
Type pt1 = (pts != null && pts.length > 1) ? pts[1] : Object.class;
Class<?> pc0 = ClassUtil.getRawType(pt0);
Class<?> pc1 = ClassUtil.getRawType(pt1);
for (int i = 0; i < src.size(); i++) {
context.enter('.');
Object key = postparse(context, i, pc0, pt0);
context.exit();
context.enter(i);
map.put(key, postparse(context, src.get(i), pc1, pt1));
context.exit();
}
} else {
for (int i = 0; i < src.size(); i++) {
map.put(i, src.get(i));
}
}
data = map;
} else if (Locale.class.equals(c)) {
if (src.size() == 1) {
data = new Locale(src.get(0).toString());
} else if (src.size() == 2) {
data = new Locale(src.get(0).toString(), src.get(1).toString());
} else if (src.size() > 2) {
data = new Locale(src.get(0).toString(), src.get(1).toString(), src.get(2).toString());
}
} else if (!src.isEmpty()) {
data = postparse(context, src.get(0), c, type);
} else {
throw new UnsupportedOperationException();
}
} else if (Number.class.isAssignableFrom(c)) {
if (value instanceof String) {
NumberFormat f = context.format(NumberFormat.class);
if (f != null) value = f.parse((String)value);
}
if (Byte.class.equals(c)) {
if (value instanceof Boolean) {
data = (((Boolean)value).booleanValue()) ? 1 : 0;
} else if (value instanceof BigDecimal) {
data = ((BigDecimal)value).byteValueExact();
} else if (value instanceof Number) {
data = ((Number)value).byteValue();
} else {
String str = value.toString().trim().toLowerCase();
if (str.length() > 0) {
int start = 0;
if (str.charAt(0) == '+') {
start++;
}
int num = 0;
if (str.startsWith("0x", start)) {
num = Integer.parseInt(str.substring(start+2), 16);
} else {
num = Integer.parseInt(str.substring(start));
}
data = (byte)((num > 127) ? num-256 : num);
}
}
} else if (Short.class.equals(c)) {
if (value instanceof Boolean) {
data = (((Boolean)value).booleanValue()) ? 1 : 0;
} else if (value instanceof BigDecimal) {
data = ((BigDecimal)value).shortValueExact();
} else if (value instanceof Number) {
data = ((Number)value).shortValue();
} else {
String str = value.toString().trim();
if (str.length() > 0) {
int start = 0;
if (str.charAt(0) == '+') {
start++;
}
if (str.startsWith("0x", start)) {
data = (short)Integer.parseInt(str.substring(start+2), 16);
} else {
data = (short)Integer.parseInt(str.substring(start));
}
}
}
} else if (int.class.equals(c) || Integer.class.equals(c)) {
if (value instanceof Boolean) {
data = (((Boolean)value).booleanValue()) ? 1 : 0;
} else if (value instanceof BigDecimal) {
data = ((BigDecimal)value).intValueExact();
} else if (value instanceof Number) {
data = ((Number)value).intValue();
} else {
String str = value.toString().trim();
if (str.length() > 0) {
int start = 0;
if (str.charAt(0) == '+') {
start++;
}
if (str.startsWith("0x", start)) {
data = Integer.parseInt(str.substring(start+2), 16);
} else {
data = Integer.parseInt(str.substring(start));
}
}
}
} else if (Long.class.equals(c)) {
if (value instanceof Boolean) {
data = (((Boolean)value).booleanValue()) ? 1l : 0l;
} else if (value instanceof BigDecimal) {
data = ((BigDecimal)value).longValueExact();
} else if (value instanceof Number) {
data = ((Number)value).longValue();
} else {
String str = value.toString().trim();
if (str.length() > 0) {
int start = 0;
if (str.charAt(0) == '+') {
start++;
}
if (str.startsWith("0x", start)) {
data = Long.parseLong(str.substring(start+2), 16);
} else {
data = Long.parseLong(str.substring(start));
}
}
}
} else if (Float.class.equals(c)) {
if (value instanceof Boolean) {
data = (((Boolean)value).booleanValue()) ? 1.0f : Float.NaN;
} else if (value instanceof Number) {
data = ((Number)value).floatValue();
} else {
String str = value.toString().trim();
if (str.length() > 0) {
data = Float.valueOf(str);
}
}
} else if (Double.class.equals(c)) {
if (value instanceof Boolean) {
data = (((Boolean)value).booleanValue()) ? 1.0 : Double.NaN;
} else if (value instanceof Number) {
data = ((Number)value).doubleValue();
} else {
String str = value.toString().trim();
if (str.length() > 0) {
data = Double.valueOf(str);
}
}
} else if (BigInteger.class.equals(c)) {
if (value instanceof Boolean) {
data = (((Boolean)value).booleanValue()) ? BigInteger.ONE : BigInteger.ZERO;
} else if (value instanceof BigDecimal) {
data = ((BigDecimal)value).toBigIntegerExact();
} else if (value instanceof Number) {
data = BigInteger.valueOf(((Number)value).longValue());
} else {
String str = value.toString().trim();
if (str.length() > 0) {
int start = 0;
if (str.charAt(0) == '+') {
start++;
}
if (str.startsWith("0x", start)) {
data = new BigInteger(str.substring(start+2), 16);
} else {
data = new BigInteger(str.substring(start));
}
}
}
} else if (BigDecimal.class.equals(c) || Number.class.equals(c)) {
String str = value.toString().trim();
if (str.length() > 0) {
if (str.charAt(0) == '+') {
data = new BigDecimal(str.substring(1));
} else {
data = new BigDecimal(str);
}
}
} else {
throw new UnsupportedOperationException();
}
} else {
if (boolean.class.equals(c) || Boolean.class.equals(c)) {
if (value instanceof Number) {
data = !value.equals(0);
} else {
String s = value.toString().trim();
if (s.length() == 0
|| s.equalsIgnoreCase("f")
|| s.equalsIgnoreCase("false")
|| s.equalsIgnoreCase("no")
|| s.equalsIgnoreCase("off")
|| s.equals("NaN")) {
data = false;
} else {
data = true;
}
}
} else if (Character.class.equals(c)) {
if (value instanceof Boolean) {
data = (((Boolean)value).booleanValue()) ? '1' : '0';
} else if (value instanceof Number) {
data = (char)((Number)value).intValue();
} else {
String s = value.toString();
if (s.length() > 0) {
data = s.charAt(0);
}
}
} else if (CharSequence.class.isAssignableFrom(c)) {
data = value.toString();
} else if (Appendable.class.isAssignableFrom(c)) {
Appendable a = (Appendable)create(context, c);
data = a.append(value.toString());
} else if (Enum.class.isAssignableFrom(c)) {
if (value instanceof Number) {
data = c.getEnumConstants()[((Number)value).intValue()];
} else if (value instanceof Boolean) {
data = c.getEnumConstants()[((Boolean)value) ? 1 : 0];
} else {
String str = value.toString().trim();
if (str.length() == 0) {
data = null;
} else if (Character.isDigit(str.charAt(0))) {
data = c.getEnumConstants()[Integer.parseInt(str)];
} else {
data = Enum.valueOf((Class<? extends Enum>)c, str);
}
}
} else if (Pattern.class.equals(c)) {
data = Pattern.compile(value.toString());
} else if (Date.class.isAssignableFrom(c)) {
Date date = null;
long millis = -1;
if (value instanceof Number) {
millis = ((Number)value).longValue();
date = (Date)create(context, c);
} else {
String str = value.toString().trim();
if (str.length() > 0) {
millis = convertDate(str, locale);
date = (Date)create(context, c);
}
}
if (date != null) {
if (date instanceof java.sql.Date) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(millis);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
date.setTime(cal.getTimeInMillis());
} else if (date instanceof java.sql.Time) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(millis);
cal.set(Calendar.YEAR, 1970);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DATE, 1);
date.setTime(cal.getTimeInMillis());
} else {
date.setTime(millis);
}
}
data = date;
} else if (Calendar.class.isAssignableFrom(c)) {
if (value instanceof Number) {
Calendar cal = (Calendar)create(context, c);
cal.setTimeInMillis(((Number)value).longValue());
data = cal;
} else {
String str = value.toString().trim();
if (str.length() > 0) {
Calendar cal = (Calendar)create(context, c);
cal.setTimeInMillis(convertDate(str, locale));
data = cal;
}
}
} else if (TimeZone.class.equals(c)) {
data = TimeZone.getTimeZone(value.toString().trim());
} else if (Locale.class.equals(c)) {
String[] array = value.toString().split("\\p{Punct}");
if (array.length == 1) {
data = new Locale(array[0]);
} else if (array.length == 2) {
data = new Locale(array[0], array[1]);
} else if (array.length > 2) {
data = new Locale(array[0], array[1], array[2]);
}
} else if (File.class.equals(c)) {
data = new File(value.toString().trim());
} else if (URL.class.equals(c)) {
if (value instanceof File) {
data = ((File)value).toURI().toURL();
} else if (value instanceof URI) {
data = ((URI)value).toURL();
} else {
data = new URL(value.toString().trim());
}
} else if (URI.class.equals(c)) {
if (value instanceof File) {
data = ((File)value).toURI();
} else if (value instanceof URL) {
data = ((URL)value).toURI();
} else {
data = new URI(value.toString().trim());
}
} else if (ClassUtil.equals("java.net.InetAddress", c)) {
Class<?> inetAddressClass = ClassUtil.findClass("java.net.InetAddress");
data = inetAddressClass.getMethod("getByName", String.class).invoke(null, value.toString().trim());
} else if (Charset.class.equals(c)) {
data = Charset.forName(value.toString().trim());
} else if (Class.class.equals(c)) {
String s = value.toString().trim();
if (s.equals("boolean")) {
data = boolean.class;
} else if (s.equals("byte")) {
data = byte.class;
} else if (s.equals("short")) {
data = short.class;
} else if (s.equals("int")) {
data = int.class;
} else if (s.equals("long")) {
data = long.class;
} else if (s.equals("float")) {
data = float.class;
} else if (s.equals("double")) {
data = double.class;
} else {
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
data = cl.loadClass(value.toString());
} catch (ClassNotFoundException e) {
}
}
} else if (Collection.class.isAssignableFrom(c)) {
Collection<Object> collection = (Collection<Object>)create(context, c);
if (type instanceof ParameterizedType) {
Type[] pts = ((ParameterizedType)type).getActualTypeArguments();
Type pt = (pts != null && pts.length > 0) ? pts[0] : Object.class;
Class<?> pc = ClassUtil.getRawType(pt);
context.enter(0);
collection.add(postparse(context, value, pc, pt));
context.exit();
} else {
collection.add(value);
}
data = collection;
} else if (c.isArray()) {
if (value instanceof String && byte.class.equals(c.getComponentType())) {
data = Base64.decode((String)value);
} else {
Object array = Array.newInstance(c.getComponentType(), 1);
Class<?> pc = c.getComponentType();
Type pt = (type instanceof GenericArrayType) ?
((GenericArrayType)type).getGenericComponentType() : pc;
context.enter(0);
Array.set(array, 0, postparse(context, value, pc, pt));
context.exit();
data = array;
}
} else if (java.sql.Array.class.isAssignableFrom(c)
|| Struct.class.isAssignableFrom(c)) {
data = null; // ignored
} else if (Map.class.isAssignableFrom(c)) {
Map<Object, Object> map = (Map)create(context, c);
Object key = (hint != null && hint.anonym().length() > 0) ? hint.anonym() : null;
if (type instanceof ParameterizedType) {
Type[] pts = ((ParameterizedType)type).getActualTypeArguments();
Type pt0 = (pts != null && pts.length > 0) ? pts[0] : Object.class;
Type pt1 = (pts != null && pts.length > 1) ? pts[1] : Object.class;
Class<?> pc0 = ClassUtil.getRawType(pt0);
Class<?> pc1 = ClassUtil.getRawType(pt1);
context.enter('.');
key = postparse(context, key, pc0, pt0);
context.exit();
context.enter(key);
map.put(key, postparse(context, value, pc1, pt1));
context.exit();
} else {
map.put(value, null);
}
data = map;
} else if (hint != null && hint.anonym().length() > 0) {
Map<String, AnnotatedElement> props = context.getSetProperties(c);
AnnotatedElement target = props.get(hint.anonym());
if (target != null) {
Object o = create(context, c);
if (o != null) {
context.enter(hint.anonym(), target.getAnnotation(JSONHint.class));
if (target instanceof Method) {
Method m = (Method)target;
Type gptype = m.getGenericParameterTypes()[0];
Class<?> ptype = m.getParameterTypes()[0];
if (gptype instanceof TypeVariable<?> && type instanceof ParameterizedType) {