package org.nutz.castor;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import org.nutz.lang.Lang;
import org.nutz.lang.Mirror;
/**
* 抽象转换器,所有的转换器必须继承自它
*
* @author zozoh(zozohtnt@gmail.com)
* @param <FROM>
* 从什么类型
* @param <TO>
* 转到什么类型
*/
public abstract class Castor<FROM, TO> {
protected Castor() {
Class<?> myType = getClass();
Class<?> mySuper = myType.getSuperclass();
Type[] myParams = Mirror.getTypeParams(myType);
Type[] superParams = Mirror.getTypeParams(mySuper);
if (null != superParams && superParams.length == 2) {
Class<?>[] args = new Class<?>[2];
int n = 0;
for (int i = 0; i < superParams.length; i++) {
if (superParams[i] instanceof Class<?>)
args[i] = (Class<?>) superParams[i];
else
args[i] = (Class<?>) myParams[n++];
}
fromClass = args[0];
toClass = args[1];
} else {
fromClass = (Class<?>) myParams[0];
toClass = (Class<?>) myParams[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())) {
if (toType.isAssignableFrom(ArrayList.class)) {
coll = new ArrayList<Object>(Array.getLength(src));
} else if (toType.isAssignableFrom(HashSet.class)) {
coll = new HashSet<Object>();
}
}
if (null == coll)
throw new FailToCastObjectException(String.format("Castors don't know how to implement '%s'",
toType.getName()),
Lang.unwrapThrow(e));
}
return coll;
}
public int hashCode() {
return toString().hashCode();
}
public boolean equals(Object obj) {
if (!(obj instanceof Castor)) {
return false;
}
Castor<?, ?> castor = (Castor<?, ?>) obj;
return toString().equals(castor.toString());
}
public String toString() {
return fromClass.getName() + "2" + toClass.getName();
}
public static final String key(Class<?> fromClass, Class<?> toClass) {
return fromClass.getName() + "2" + toClass.getName();
}
}