package org.nutz.castor;

import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;

import org.nutz.lang.Mirror;

/**
 * 抽象转换器，所有的转换器必须继承自它
 * 
 * @author zozoh(zozohtnt@gmail.com)
 * @param <FROM>
 *            从什么类型
 * @param <TO>
 *            转到什么类型
 */
public abstract class Castor<FROM, TO> {

	protected Castor() {
		fromClass = (Class<?>) Mirror.getTypeParams(getClass())[0];
		toClass = (Class<?>) Mirror.getTypeParams(getClass())[1];
	}

	protected Class<?> fromClass;
	protected Class<?> toClass;

	public Class<?> getFromClass() {

		return fromClass;
	}

	public Class<?> getToClass() {
		return toClass;
	}

	public abstract TO cast(FROM src, Class<?> toType, String... args)
			throws FailToCastObjectException;

	@SuppressWarnings({"unchecked"})
	protected static Collection<?> createCollection(Object src, Class<?> toType)
			throws FailToCastObjectException {
		Collection<?> coll = null;
		try {
			coll = (Collection<Object>) toType.newInstance();
		}
		catch (Exception e) {
			if (Modifier.isAbstract(toType.getModifiers())
				&& toType.isAssignableFrom(ArrayList.class)) {
				coll = new ArrayList<Object>(Array.getLength(src));
			}
			if (null == coll)
				throw new FailToCastObjectException(String.format(	"Castors don't know how to implement '%s'",
																	toType.getName()),
													e);
		}
		return coll;
	}
	
	public int hashCode() {
	    return fetchHash(fromClass.getName() ,toClass.getName());
	}
	
	public boolean equals(Object obj) {
	    if(!(obj instanceof Castor)){
	        return false;
	    }
	    Castor<?, ?> castor = (Castor<?, ?>) obj;
	    return toString().equals(castor.toString());
	}
	/**
	 * 取得hash值
	 * @param from
	 * @param to
	 * @return
	 */
	public static int fetchHash(Class<?> from, Class<?> to){
	    return fetchHash(from.getName(), to.getName());
	}
	/**
	 * 取得Hash值
	 * @param from
	 * @param to
	 * @return
	 */
	public static int fetchHash(String from, String to){
	    return (from + "2" + to).hashCode();
	}
	
	public String toString() {
	    return fromClass.getName() + "2" + toClass.getName();
	}
}

@@ -148,16 +148,70 @@
 ection;%0D
+%0Aimport java.util.HashMap;%0D%0Aimport java.util.HashSet;%0D
 %0A%0D%0Aimpor
@@ -1211,17 +1211,21 @@
 s())
+) %7B
 %0D%0A%09%09%09%09
-&& 
+if (
 toTy
@@ -1261,24 +1261,25 @@
 .class)) %7B%0D%0A
+%09
 %09%09%09%09coll = n
@@ -1323,16 +1323,117 @@
 src));%0D%0A
+%09%09%09%09%7D else if (toType.isAssignableFrom(HashSet.class)) %7B%0D%0A%09%09%09%09%09coll = new HashSet%3CObject%3E();%0D%0A%09%09%09%09%7D%0D%0A
 %09%09%09%7D%0D%0A%09%09

fix issue #194