All Downloads are FREE. Search and download functionalities are using the official Maven repository.

panda.cast.Castors Maven / Gradle / Ivy

Go to download

Panda Core is the core module of Panda Framework, it contains commonly used utility classes similar to apache-commons.

There is a newer version: 1.8.0
Show newest version
package panda.cast;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import panda.bean.BeanHandler;
import panda.bean.Beans;
import panda.cast.castor.ArrayCastor;
import panda.cast.castor.ByteArrayCastor;
import panda.cast.castor.CharArrayCastor;
import panda.cast.castor.ClassCastor;
import panda.cast.castor.CollectionCastor;
import panda.cast.castor.DateTypeCastor;
import panda.cast.castor.DirectCastor;
import panda.cast.castor.EmailAddressCastor;
import panda.cast.castor.EnumCastor;
import panda.cast.castor.FileCastor;
import panda.cast.castor.FileItemCastor;
import panda.cast.castor.IterableCastor;
import panda.cast.castor.IteratorCastor;
import panda.cast.castor.JavaBeanCastor;
import panda.cast.castor.JsonArrayCastor;
import panda.cast.castor.JsonObjectCastor;
import panda.cast.castor.LocaleCastor;
import panda.cast.castor.MapCastor;
import panda.cast.castor.NumberTypeCastor;
import panda.cast.castor.PrimitiveTypeCastor;
import panda.cast.castor.PrimitiveWrapCastor;
import panda.cast.castor.StreamCastor;
import panda.cast.castor.StringTypeCastor;
import panda.cast.castor.TimeZoneCastor;
import panda.lang.Asserts;
import panda.lang.collection.MultiKey;
import panda.lang.reflect.Types;

/**
 * !! thread-safe !! 
 */
@SuppressWarnings("rawtypes")
public class Castors {
	private static Castors i = new Castors();

	/**
	 * @return instance
	 */
	public static Castors i() {
		return i;
	}

	/**
	 * @return instance
	 */
	public static Castors getInstance() {
		return i;
	}

	/**
	 * @param instance the instance to set
	 */
	public static void setInstance(Castors instance) {
		Castors.i = instance;
	}

	public static  T scast(Object value, Type toType) {
		Asserts.notNull(toType);
		return i().cast(value, toType);
	}

	public static  T scast(Object value, Type toType, boolean skipCastError) {
		Asserts.notNull(toType);
		Castors cs = i();
		return cs.cast(value, toType, cs.newCastContext(skipCastError));
	}

	public static  T scastTo(Object value, T target) {
		if (value == null) {
			return target;
		}
		
		Asserts.notNull(target);
		
		return i().castTo(value, target);
	}

	public static  T scastTo(Object value, T target, boolean skipCastError) {
		if (value == null) {
			return target;
		}
		
		Asserts.notNull(target);
		
		Castors cs = i();
		return cs.castTo(value, target, cs.newCastContext(skipCastError));
	}

	// ------------------------------------------------------------------------
	private Beans beans = Beans.i();
	private Map castors = new ConcurrentHashMap();
	
	/**
	 * Constructor
	 */
	public Castors() {
		register(new PrimitiveTypeCastor.BooleanCastor());
		register(new PrimitiveTypeCastor.ByteCastor());
		register(new PrimitiveTypeCastor.CharacterCastor());
		register(new PrimitiveTypeCastor.DoubleCastor());
		register(new PrimitiveTypeCastor.FloatCastor());
		register(new PrimitiveTypeCastor.IntegerCastor());
		register(new PrimitiveTypeCastor.LongCastor());
		register(new PrimitiveTypeCastor.ShortCastor());

		register(new PrimitiveWrapCastor.BooleanCastor());
		register(new PrimitiveWrapCastor.ByteCastor());
		register(new PrimitiveWrapCastor.CharacterCastor());
		register(new PrimitiveWrapCastor.DoubleCastor());
		register(new PrimitiveWrapCastor.FloatCastor());
		register(new PrimitiveWrapCastor.IntegerCastor());
		register(new PrimitiveWrapCastor.LongCastor());
		register(new PrimitiveWrapCastor.ShortCastor());

		register(new NumberTypeCastor.NumberCastor());
		register(new NumberTypeCastor.BigIntegerCastor());
		register(new NumberTypeCastor.BigDecimalCastor());

		register(new ByteArrayCastor());
		register(new CharArrayCastor());

		DateTypeCastor.DateCastor dc = new DateTypeCastor.DateCastor();
		register(dc);
		register(new DateTypeCastor.CalendarCastor(dc));
		register(new DateTypeCastor.GregorianCalendarCastor(dc));
		register(new DateTypeCastor.SqlDateCastor(dc));
		register(new DateTypeCastor.SqlTimeCastor(dc));
		register(new DateTypeCastor.SqlTimestampCastor(dc));
		
		register(new StringTypeCastor.StringCastor(dc));
		register(new StringTypeCastor.StringBufferCastor(dc));
		register(new StringTypeCastor.StringBuilderCastor(dc));
		
		register(new StreamCastor.InputStreamCastor());
		register(new StreamCastor.ReaderCastor());

		register(new ClassCastor());
		
		register(new IterableCastor());
		register(new IteratorCastor());

		register(new LocaleCastor());
		register(new TimeZoneCastor());
		
		register(new FileCastor());
		register(new FileItemCastor());

		register(new JsonArrayCastor());
		register(new JsonObjectCastor());

		register(new EmailAddressCastor());
	}
	
	public Beans getBeans() {
		return beans;
	}

	public void setBeans(Beans beans) {
		this.beans = beans;
	}

	/**
	 * Register (add) a castor for a class
	 * 
	 * @param castor - the castor instance
	 */
	public void register(AbstractCastor castor) {
		register(castor.getFromType(), castor.getToType(), castor);
	}

	/**
	 * Register (add) a castor for a class
	 * 
	 * @param fromType the source class type 
	 * @param toType the target class type
	 * @param castor the castor instance
	 */
	public void register(Type fromType, Type toType, Castor castor) {
		castors.put(new MultiKey(fromType, toType), castor);
	}
	
	/**
	 * Unregister (remove) a castor for a class
	 * 
	 * @param fromType the source class type 
	 * @param toType the target class type
	 */
	public void unregister(Type fromType, Type toType) {
		castors.remove(new MultiKey(fromType, toType));
	}
	
	/**
	 * clear converters
	 */
	public void clear() {
		castors.clear();
	}
	
	public CastContext newCastContext() {
		return new CastContext(this);
	}
	
	public CastContext newCastContext(boolean skipCastError) {
		return new CastContext(this, skipCastError);
	}
	
	/**
	 * getCastor
	 * @param type object type
	 * @return Castor
	 */
	public  Castor getCastor(Class type) {
		return getCastor((Type)type);
	}
	
	/**
	 * getCastor
	 * @param toType object type
	 * @return Castor
	 */
	public  Castor getCastor(Type toType) {
		return getCastor(Object.class, toType);
	}
	
	/**
	 * getCastor
	 * @param fromType the source class type 
	 * @param toType the target class type
	 * @return Castor the castor instance
	 */
	@SuppressWarnings("unchecked")
	public  Castor getCastor(Type fromType, Type toType) {
		Asserts.notNull(fromType, "The from type is null");
		Asserts.notNull(toType, "The to type is null");

		// same type
		if (fromType.equals(toType)) {
			return DirectCastor.i();
		}

		// type -> type castor
		Castor castor = castors.get(new MultiKey(fromType, toType));
		if (castor != null) {
			return castor;
		}
		
		// object -> type castor
		if (!Object.class.equals(fromType)) {
			castor = castors.get(new MultiKey(Object.class, toType));
			if (castor != null) {
				return castor;
			}
		}
		
		// default castor
		if (Object.class.equals(toType)) {
			return DirectCastor.i();
		}
		
		Class toClass = Types.getRawType(toType);
		// type -> class castor
		castor = castors.get(new MultiKey(fromType, toClass));
		if (castor != null) {
			return castor;
		}
		
		// object -> class castor
		if (!Object.class.equals(fromType)) {
			castor = castors.get(new MultiKey(Object.class, toClass));
			if (castor != null) {
				return castor;
			}
		}
		
		// default castor
		if (Object.class.equals(toClass)) {
			return DirectCastor.i();
		}

		// 
		if (toClass.isEnum()) {
			return (Castor)new EnumCastor(toClass);
		}
		
		if (Types.isArrayType(toType)) {
			return new ArrayCastor(fromType, toType);
		}
		
		if (Types.isAssignable(toType, Number.class)) {
			return (Castor)new NumberTypeCastor.NumberCastor();
		}
		
		if (Types.isAssignable(toType, Map.class)) {
			return (Castor)new MapCastor(toType, this);
		}
		
		if (Types.isAbstractType(toType)) {
			if (toType instanceof ParameterizedType) {
				ParameterizedType pt = (ParameterizedType)toType;
				Type rawType = pt.getRawType();
				if (Types.isAssignable(ArrayList.class, rawType)) {
					rawType = ArrayList.class;
				}
				else if (Types.isAssignable(LinkedHashSet.class, rawType)) {
					rawType = LinkedHashSet.class;
				}
				else if (Types.isAssignable(fromType, toType)) {
					return DirectCastor.i();
				}
				else {
					throw new RuntimeException("Failed to find Castor(" + fromType + " -> " + toType + ")");
				}
				
				toType = Types.paramTypeOfOwner(pt.getOwnerType(), rawType, pt.getActualTypeArguments());
				return (Castor)getCastor(toType);
			}

			if (Types.isAssignable(fromType, toType)) {
				return DirectCastor.i();
			}

			if (Types.isAssignable(ArrayList.class, toType)) {
				return (Castor)new CollectionCastor(fromType, ArrayList.class);
			}
			
			if (Types.isAssignable(LinkedHashSet.class, toType)) {
				return (Castor)new CollectionCastor(fromType, LinkedHashSet.class);
			}
			
			throw new RuntimeException("Failed to find Castor(" + fromType + " -> " + toType + ")");
		}

		if (Types.isAssignable(toType, Collection.class)) {
			return (Castor)new CollectionCastor(fromType, toType);
		}
		
		return new JavaBeanCastor(toType, beans);
	}

	public  BeanHandler getBeanHandler(Type type) {
		return beans.getBeanHandler(type);
	}

	public  T cast(Object value, Type toType) {
		Asserts.notNull(toType);
		return cast(value, toType, newCastContext());
	}

	public  T cast(Object value, Type toType, CastContext context) {
		Asserts.notNull(toType);
		Castor c = getCastor(value == null ? Object.class : value.getClass(), toType);
		return c.cast(value, context);
	}

	public  T castTo(Object value, T target) {
		Asserts.notNull(target);
		return castTo(value, target, null, newCastContext());
	}

	public  T castTo(Object value, T target, CastContext context) {
		Asserts.notNull(target);
		return castTo(value, target, null, context);
	}

	public  T castTo(Object value, T target, Type toType) {
		Asserts.notNull(target);
		return castTo(value, target, toType, newCastContext());
	}

	public  T castTo(Object value, T target, Type toType, CastContext context) {
		Asserts.notNull(target);
		Castor c = getCastor(
			value == null ? Object.class : value.getClass(), 
			toType == null ? target.getClass() : toType);
		return c.castTo(value, target, context);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy