Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
flexjson.ObjectBinder Maven / Gradle / Ivy
package flexjson;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import flexjson.factories.ArrayObjectFactory;
import flexjson.factories.BeanObjectFactory;
import flexjson.factories.BooleanObjectFactory;
import flexjson.factories.ByteObjectFactory;
import flexjson.factories.CharacterObjectFactory;
import flexjson.factories.ClassLocatorObjectFactory;
import flexjson.factories.ClassObjectFactory;
import flexjson.factories.DoubleObjectFactory;
import flexjson.factories.EnumObjectFactory;
import flexjson.factories.FloatObjectFactory;
import flexjson.factories.IntegerObjectFactory;
import flexjson.factories.ListObjectFactory;
import flexjson.factories.LongObjectFactory;
import flexjson.factories.MapObjectFactory;
import flexjson.factories.SetObjectFactory;
import flexjson.factories.ShortObjectFactory;
import flexjson.factories.StringObjectFactory;
public class ObjectBinder
{
private Stack objectStack= new Stack();
private Stack jsonStack= new Stack();
private Path currentPath= new Path();
private Map factories;
private Map pathFactories= new HashMap();
public Map references= new HashMap();
public Map getReferences()
{
return references;
}
public ObjectBinder()
{
factories= new HashMap();
factories.put(Class.class, new ClassObjectFactory());
factories.put(Object.class, new BeanObjectFactory());
factories.put(Collection.class, new ListObjectFactory());
factories.put(List.class, new ListObjectFactory());
factories.put(Set.class, new SetObjectFactory());
// factories.put( SortedSet.class, new SortedSetObjectFactory() );
factories.put(Map.class, new MapObjectFactory());
factories.put(Integer.class, new IntegerObjectFactory());
factories.put(int.class, new IntegerObjectFactory());
factories.put(Float.class, new FloatObjectFactory());
factories.put(float.class, new FloatObjectFactory());
factories.put(Double.class, new DoubleObjectFactory());
factories.put(double.class, new DoubleObjectFactory());
factories.put(Short.class, new ShortObjectFactory());
factories.put(short.class, new ShortObjectFactory());
factories.put(Long.class, new LongObjectFactory());
factories.put(long.class, new LongObjectFactory());
factories.put(Byte.class, new ByteObjectFactory());
factories.put(byte.class, new ByteObjectFactory());
factories.put(Boolean.class, new BooleanObjectFactory());
factories.put(boolean.class, new BooleanObjectFactory());
factories.put(Character.class, new CharacterObjectFactory());
factories.put(char.class, new CharacterObjectFactory());
factories.put(Enum.class, new EnumObjectFactory());
// factories.put( Date.class, new DateObjectFactory() );
factories.put(String.class, new StringObjectFactory());
factories.put(Array.class, new ArrayObjectFactory());
// factories.put( BigDecimal.class, new BigDecimalFactory() );
// factories.put( BigInteger.class, new BigIntegerFactory() );
}
public ObjectBinder use(Path path, ObjectFactory factory)
{
pathFactories.put(path, factory);
return this;
}
public ObjectBinder use(Object clazz, ObjectFactory factory)
{
factories.put(clazz, factory);
return this;
}
public Path getCurrentPath()
{
return currentPath;
}
public Object bind(Object input)
{
return this.bind(input, null);
}
public Object bind(Object source, Object target)
{
if (target instanceof Map)
{
bindIntoMap((Map) source, (Map) target, null, null);
}
else if (target instanceof Collection)
{
bindIntoCollection((Collection) source, (Collection) target, null);
}
else
{
bindIntoObject((Map) source, target, target.getClass());
}
return target;
}
public Object bind(Object input, Type targetType)
{
jsonStack.add(input);
try
{
if (input == null)
return null;
Class targetClass= findClassName(input, getTargetClass(targetType));
ObjectFactory factory= findFactoryFor(targetClass);
if (factory == null)
throw new JSONException(currentPath + ": + Could not find a suitable ObjectFactory for " + targetClass);
return factory.instantiate(this, input, targetType, targetClass);
}
finally
{
jsonStack.pop();
}
}
public > T bindIntoCollection(Collection value, T target, Type targetType)
{
Type valueType= null;
if (targetType instanceof ParameterizedType)
{
valueType= ((ParameterizedType) targetType).getActualTypeArguments()[0];
}
jsonStack.add(value);
objectStack.add(target);
getCurrentPath().enqueue("values");
for (Object obj : value)
{
target.add(bind(obj, valueType));
}
getCurrentPath().pop();
objectStack.pop();
jsonStack.pop();
return target;
}
public Object bindIntoMap(Map input, Map result, Type keyType, Type valueType)
{
jsonStack.add(input);
objectStack.add(result);
for (Object inputKey : input.keySet())
{
currentPath.enqueue("keys");
Object key= bind(inputKey, keyType);
currentPath.pop();
currentPath.enqueue("values");
Object value= bind(input.get(inputKey), valueType);
currentPath.pop();
result.put(key, value);
}
objectStack.pop();
jsonStack.pop();
return result;
}
public Object bindIntoObject(Map jsonOwner, Object target, Type targetType)
{
try
{
objectStack.add(target);
BeanAnalyzer analyzer= BeanAnalyzer.analyze(target.getClass());
for (BeanProperty descriptor : analyzer.getProperties())
{
Object value= findFieldInJson(jsonOwner, descriptor);
if (value != null)
{
currentPath.enqueue(descriptor.getName());
Method setMethod= descriptor.getWriteMethod();
if (setMethod != null)
{
Type[] types= setMethod.getGenericParameterTypes();
if (types.length == 1)
{
Type paramType= types[0];
setMethod.invoke(objectStack.peek(), bind(value, resolveParameterizedTypes(paramType, targetType)));
}
else
{
throw new JSONException(currentPath + ": Expected a single parameter for method " + target.getClass().getName() + "." + setMethod.getName() + " but got " + types.length);
}
}
else
{
Field field= descriptor.getProperty();
if (field != null)
{
field.setAccessible(true);
field.set(target, bind(value, field.getGenericType()));
}
}
currentPath.pop();
}
}
return objectStack.pop();
}
catch (IllegalAccessException e)
{
throw new JSONException(currentPath + ": Could not access the no-arg constructor for " + target.getClass().getName(), e);
}
catch (InvocationTargetException ex)
{
throw new JSONException(currentPath + ": Exception while trying to invoke setter method.", ex);
}
}
public JSONException cannotConvertValueToTargetType(Object value, Class targetType)
{
return new JSONException(String.format("%s: Can not convert %s into %s", currentPath, value.getClass().getName(), targetType.getName()));
}
private Class getTargetClass(Type targetType)
{
if (targetType == null)
{
return null;
}
else if (targetType instanceof Class)
{
return (Class) targetType;
}
else if (targetType instanceof ParameterizedType)
{
return (Class) ((ParameterizedType) targetType).getRawType();
}
else if (targetType instanceof GenericArrayType)
{
return Array.class;
}
else if (targetType instanceof WildcardType)
{
return null; // nothing you can do about these. User will have to specify this with use()
}
else if (targetType instanceof TypeVariable)
{
return null; // nothing you can do about these. User will have to specify this with use()
}
else
{
throw new JSONException(currentPath + ": Unknown type " + targetType);
}
}
private Type resolveParameterizedTypes(Type genericType, Type targetType)
{
if (genericType instanceof Class)
{
return genericType;
}
else if (genericType instanceof ParameterizedType)
{
return genericType;
}
else if (genericType instanceof TypeVariable)
{
return targetType;
}
else if (genericType instanceof WildcardType)
{
return targetType;
}
else if (genericType instanceof GenericArrayType)
{
return ((GenericArrayType) genericType).getGenericComponentType();
}
else
{
throw new JSONException(currentPath + ": Unknown generic type " + genericType + ".");
}
}
private Class findClassName(Object map, Class targetType) throws JSONException
{
if (!pathFactories.containsKey(currentPath))
{
Class mostSpecificType= useMostSpecific(targetType, map instanceof Map ? findClassInMap((Map) map, null) : null);
if (mostSpecificType == null)
{
return map.getClass();
}
else
{
return mostSpecificType;
}
}
else
{
return null;
}
}
protected Class useMostSpecific(Class classFromTarget, Class typeFound)
{
if (classFromTarget != null && typeFound != null)
{
return typeFound.isAssignableFrom(classFromTarget) ? classFromTarget : typeFound;
}
else if (typeFound != null)
{
return typeFound;
}
else if (classFromTarget != null)
{
return classFromTarget;
}
else
{
return null;
}
}
protected Class findClassInMap(Map map, Class override)
{
if (override == null)
{
Integer reference= (Integer) map.get("@ref");
if (reference != null)
return getReferences().get(reference).getClass();
String classname= (String) map.remove("class");
try
{
if (classname != null)
{
return Class.forName(classname);
}
else
{
return null;
}
}
catch (ClassNotFoundException e)
{
throw new JSONException( /*String.format( "%s: Could not load %s", currentPath, classname ), */e);
}
}
else
{
return override;
}
}
private ObjectFactory findFactoryFor(Class targetType)
{
ObjectFactory factory= pathFactories.get(currentPath);
if (factory == null)
{
if (targetType != null && targetType.isArray())
return factories.get(Array.class);
return findFactoryByTargetClass(targetType);
}
return factory;
}
private ObjectFactory findFactoryByTargetClass(Class targetType)
{
ObjectFactory factory;
factory= factories.get(targetType);
if (factory == null && targetType != null && targetType.getSuperclass() != null)
{
for (Class intf : targetType.getInterfaces())
{
factory= findFactoryByTargetClass(intf);
if (factory != null)
return factory;
}
return findFactoryByTargetClass(targetType.getSuperclass());
}
else
{
return factory;
}
}
protected Object instantiate(Class clazz)
{
try
{
Constructor constructor= clazz.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
}
catch (InstantiationException e)
{
throw new JSONException(currentPath + ":There was an exception trying to instantiate an instance of " + clazz.getName(), e);
}
catch (IllegalAccessException e)
{
throw new JSONException(currentPath + ":There was an exception trying to instantiate an instance of " + clazz.getName(), e);
}
catch (InvocationTargetException e)
{
throw new JSONException(currentPath + ":There was an exception trying to instantiate an instance of " + clazz.getName(), e);
}
catch (NoSuchMethodException e)
{
throw new JSONException(currentPath + ": " + clazz.getName() + " lacks a no argument constructor. Flexjson will instantiate any protected, private, or public no-arg constructor.", e);
}
}
private Object findFieldInJson(Map map, BeanProperty property)
{
Object value= map.get(property.getName());
if (value == null)
{
String field= property.getName();
value= map.get(upperCase(field));
}
return value;
}
private String upperCase(String field)
{
return Character.toUpperCase(field.charAt(0)) + field.substring(1);
}
public Object getTarget()
{
return objectStack.peek();
}
public Object getSource()
{
return jsonStack.peek();
}
public Object bindPrimitive(Object value, Class clazz)
{
if (value.getClass() == clazz)
{
return value;
}
else if (value instanceof Number && clazz.equals(Double.class))
{
return ((Number) value).doubleValue();
}
else if (value instanceof Number && clazz.equals(Integer.class))
{
return ((Number) value).intValue();
}
else if (value instanceof Number && clazz.equals(Long.class))
{
return ((Number) value).longValue();
}
else if (value instanceof Number && clazz.equals(Short.class))
{
return ((Number) value).shortValue();
}
else if (value instanceof Number && clazz.equals(Byte.class))
{
return ((Number) value).byteValue();
}
else if (value instanceof Number && clazz.equals(Float.class))
{
return ((Number) value).floatValue();
}
else if (value instanceof Boolean && clazz.equals(Boolean.class))
{
return value;
}
else if (value instanceof Long && clazz == Date.class)
{
return new Date((Long) value);
}
else
{
throw new JSONException(String.format("%s: Don't know how to bind %s into class %s. You might need to use an ObjectFactory instead of a plain class.", getCurrentPath().toString(), value, clazz.getName()));
}
}
public Class findClassAtPath(Path currentPath) throws ClassNotFoundException
{
ObjectFactory factory= pathFactories.get(currentPath);
if (factory instanceof ClassLocatorObjectFactory)
{
return ((ClassLocatorObjectFactory) factory).getLocator().locate(this, currentPath);
}
else
{
return null;
}
}
}