This commit is contained in:
wentch
2015-12-18 15:59:54 +08:00
parent 2973494bb0
commit 743955e1bd
3 changed files with 273 additions and 148 deletions

View File

@@ -6,7 +6,6 @@
package org.redkale.convert;
import java.beans.*;
import static org.redkale.convert.ObjectEncoder.TYPEZERO;
import org.redkale.util.Creator;
import java.lang.reflect.*;
import java.util.Arrays;
@@ -66,8 +65,6 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
} else {
clazz = (Class) type;
}
final Type[] virGenericTypes = this.typeClass.getTypeParameters();
final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : TYPEZERO;
this.creator = factory.loadCreator(clazz);
final Set<DeMember> list = new HashSet();
@@ -78,7 +75,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
if (Modifier.isStatic(field.getModifiers())) continue;
ref = factory.findRef(field);
if (ref != null && ref.ignore()) continue;
Type t = ObjectEncoder.makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes);
Type t = ObjectEncoder.createClassType(field.getGenericType(), this.type);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t)));
}
final boolean reversible = factory.isReversible();
@@ -100,7 +97,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
}
ref = factory.findRef(method);
if (ref != null && ref.ignore()) continue;
Type t = ObjectEncoder.makeGenericType(method.getGenericParameterTypes()[0], virGenericTypes, realGenericTypes);
Type t = ObjectEncoder.createClassType(method.getGenericParameterTypes()[0], this.type);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t)));
}
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
@@ -116,19 +113,19 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
//不存在setter方法
try {
Field f = clazz.getDeclaredField(constructorField);
Type t = ObjectEncoder.makeGenericType(f.getGenericType(), virGenericTypes, realGenericTypes);
Type t = ObjectEncoder.createClassType(f.getGenericType(), this.type);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, f, null, null), factory.loadDecoder(t)));
} catch (NoSuchFieldException nsfe) { //不存在field 可能存在getter方法
char[] fs = constructorField.toCharArray();
fs[0] = Character.toUpperCase(fs[0]);
String mn = new String(fs);
Method getter = null;
Method getter;
try {
getter = clazz.getMethod("get" + mn);
} catch (NoSuchMethodException ex) {
getter = clazz.getMethod("is" + mn);
}
Type t = ObjectEncoder.makeGenericType(getter.getGenericParameterTypes()[0], virGenericTypes, realGenericTypes);
Type t = ObjectEncoder.createClassType(getter.getGenericParameterTypes()[0], this.type);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, getter, null), factory.loadDecoder(t)));
}
}

View File

@@ -46,53 +46,178 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
this.members = new EnMember[0];
}
static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
if (type instanceof Class) {
return type;
} else if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
Type[] paramTypes = pt.getActualTypeArguments();
final Type[] newTypes = new Type[paramTypes.length];
int count = 0;
for (int i = 0; i < newTypes.length; i++) {
newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
if (paramTypes[i] == newTypes[i]) count++;
public void init(final Factory factory) {
this.factory = factory;
try {
if (type == Object.class) return;
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
final Class clazz = this.typeClass;
final Set<EnMember> list = new HashSet();
final ConstructorProperties cps = ObjectEncoder.findConstructorProperties(factory.loadCreator(this.typeClass));
try {
ConvertColumnEntry ref;
for (final Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
ref = factory.findRef(field);
if (ref != null && ref.ignore()) continue;
Type t = createClassType(field.getGenericType(), this.type);
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
}
final boolean reversible = factory.isReversible();
for (final Method method : clazz.getMethods()) {
if (Modifier.isStatic(method.getModifiers())) continue;
if (Modifier.isAbstract(method.getModifiers())) continue;
if (method.isSynthetic()) continue;
if (method.getName().length() < 3) continue;
if (method.getName().equals("getClass")) continue;
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue;
if (method.getParameterTypes().length != 0) continue;
if (method.getReturnType() == void.class) continue;
if (reversible && (cps == null || !contains(cps.value(), readGetSetFieldName(method)))) {
boolean is = method.getName().startsWith("is");
try {
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
} catch (Exception e) {
continue;
}
}
ref = factory.findRef(method);
if (ref != null && ref.ignore()) continue;
Type t = createClassType(method.getGenericReturnType(), this.type);
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
}
this.members = list.toArray(new EnMember[list.size()]);
Arrays.sort(this.members);
} catch (Exception ex) {
throw new ConvertException(ex);
}
} finally {
inited = true;
synchronized (lock) {
lock.notifyAll();
}
if (count == paramTypes.length) return pt;
return new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return newTypes;
}
@Override
public Type getRawType() {
return pt.getRawType();
}
@Override
public Type getOwnerType() {
return pt.getOwnerType();
}
};
}
if (realGenericTypes == null) return type;
if (type instanceof WildcardType) {
}
@Override
public final void convertTo(W out, T value) {
if (value == null) {
out.wirteClassName(null);
out.writeNull();
return;
}
if (!this.inited) {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (value != null && value.getClass() != this.typeClass) {
final Class clz = value.getClass();
out.wirteClassName(factory.getEntity(clz));
factory.loadEncoder(clz).convertTo(out, value);
return;
}
out.writeObjectB(members.length, value);
boolean comma = false;
for (EnMember member : members) {
comma = member.write(out, comma, value);
}
out.writeObjectE(value);
}
@Override
public final Type getType() {
return this.type;
}
@Override
public String toString() {
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
}
static Type createClassType(final Type type, final Type declaringType) {
if (TypeToken.isClassType(type)) return type;
//存在通配符则declaringType 必须是 ParameterizedType
if (!(declaringType instanceof ParameterizedType)) return Object.class;
if (type instanceof ParameterizedType) { // e.g. Map<String, String>
final ParameterizedType pt = (ParameterizedType) type;
final Type[] paramTypes = pt.getActualTypeArguments();
for (int i = 0; i < paramTypes.length; i++) {
paramTypes[i] = createClassType(paramTypes[i], declaringType);
}
return TypeToken.createParameterizedType(pt.getOwnerType(), pt.getRawType(), paramTypes);
}
final ParameterizedType declaringPType = (ParameterizedType) declaringType;
final Type[] virTypes = ((Class) declaringPType.getRawType()).getTypeParameters();
final Type[] desTypes = declaringPType.getActualTypeArguments();
if (type instanceof WildcardType) { // e.g. <? extends Serializable>
final WildcardType wt = (WildcardType) type;
for (Type f : wt.getUpperBounds()) {
for (int i = 0; i < virGenericTypes.length; i++) {
if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
for (int i = 0; i < virTypes.length; i++) {
if (virTypes[i].equals(f)) return desTypes.length <= i ? Object.class : desTypes[i];
}
}
} else if (type instanceof TypeVariable) {
for (int i = 0; i < virGenericTypes.length; i++) {
if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
} else if (type instanceof TypeVariable) { // e.g. <? extends E>
for (int i = 0; i < virTypes.length; i++) {
if (virTypes[i].equals(type)) return desTypes.length <= i ? Object.class : desTypes[i];
}
}
return type;
}
//
// static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
// if (type instanceof Class) { //e.g. String
// return type;
// } else if (type instanceof ParameterizedType) { //e.g. Map<String, String>
// final ParameterizedType pt = (ParameterizedType) type;
// Type[] paramTypes = pt.getActualTypeArguments();
// final Type[] newTypes = new Type[paramTypes.length];
// int count = 0;
// for (int i = 0; i < newTypes.length; i++) {
// newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
// if (paramTypes[i] == newTypes[i]) count++;
// }
// if (count == paramTypes.length) return pt;
// return new ParameterizedType() {
//
// @Override
// public Type[] getActualTypeArguments() {
// return newTypes;
// }
//
// @Override
// public Type getRawType() {
// return pt.getRawType();
// }
//
// @Override
// public Type getOwnerType() {
// return pt.getOwnerType();
// }
//
// };
// }
// if (realGenericTypes == null) return type;
// if (type instanceof WildcardType) { // e.g. <? extends Serializable>
// final WildcardType wt = (WildcardType) type;
// for (Type f : wt.getUpperBounds()) {
// for (int i = 0; i < virGenericTypes.length; i++) {
// if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
// }
// }
// } else if (type instanceof TypeVariable) { // e.g. <? extends E>
// for (int i = 0; i < virGenericTypes.length; i++) {
// if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
// }
// }
// return type;
// }
static boolean contains(String[] values, String value) {
for (String str : values) {
@@ -151,102 +276,4 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
return Attribute.create(clazz, fieldalias, field, getter, setter);
}
public void init(final Factory factory) {
this.factory = factory;
try {
if (type == Object.class) return;
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
final Class clazz = this.typeClass;
final Set<EnMember> list = new HashSet();
final Type[] virGenericTypes = this.typeClass.getTypeParameters();
final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : null;
if (realGenericTypes != null) {
// println(type + "," + Arrays.toString(virGenericTypes) + ", " + Arrays.toString(realGenericTypes));
}
final ConstructorProperties cps = ObjectEncoder.findConstructorProperties(factory.loadCreator(this.typeClass));
try {
ConvertColumnEntry ref;
for (final Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
ref = factory.findRef(field);
if (ref != null && ref.ignore()) continue;
Type t = makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes);
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
}
final boolean reversible = factory.isReversible();
for (final Method method : clazz.getMethods()) {
if (Modifier.isStatic(method.getModifiers())) continue;
if (Modifier.isAbstract(method.getModifiers())) continue;
if (method.isSynthetic()) continue;
if (method.getName().length() < 3) continue;
if (method.getName().equals("getClass")) continue;
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue;
if (method.getParameterTypes().length != 0) continue;
if (method.getReturnType() == void.class) continue;
if (reversible && (cps == null || !contains(cps.value(), readGetSetFieldName(method)))) {
boolean is = method.getName().startsWith("is");
try {
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
} catch (Exception e) {
continue;
}
}
ref = factory.findRef(method);
if (ref != null && ref.ignore()) continue;
Type t = makeGenericType(method.getGenericReturnType(), virGenericTypes, realGenericTypes);
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
}
this.members = list.toArray(new EnMember[list.size()]);
Arrays.sort(this.members);
} catch (Exception ex) {
throw new ConvertException(ex);
}
} finally {
inited = true;
synchronized (lock) {
lock.notifyAll();
}
}
}
@Override
public final void convertTo(W out, T value) {
if (value == null) {
out.wirteClassName(null);
out.writeNull();
return;
}
if (!this.inited) {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (value != null && value.getClass() != this.typeClass) {
final Class clz = value.getClass();
out.wirteClassName(factory.getEntity(clz));
factory.loadEncoder(clz).convertTo(out, value);
return;
}
out.writeObjectB(members.length, value);
boolean comma = false;
for (EnMember member : members) {
comma = member.write(out, comma, value);
}
out.writeObjectE(value);
}
@Override
public final Type getType() {
return this.type;
}
@Override
public String toString() {
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
}
}

View File

@@ -4,8 +4,9 @@
*/
package org.redkale.util;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.*;
import java.util.*;
import jdk.internal.org.objectweb.asm.*;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
@@ -29,7 +30,107 @@ public abstract class TypeToken<T> {
return type;
}
public static Type createParameterizedType(final Type ownerType, final Type rawType, final Type... actualTypeArguments) {
/**
* 判断Type是否能确定最终的class 是则返回true存在通配符或者不确定类型则返回false。
* 例如: Map&#60; String, String &#62; 返回 ture; Map&#60; ? extends Serializable, String &#62; 返回false;
*
* @param type
* @return
*/
public final static boolean isClassType(final Type type) {
if (type instanceof Class) return true;
if (type instanceof WildcardType) return false;
if (type instanceof TypeVariable) return false;
if (type instanceof GenericArrayType) return isClassType(((GenericArrayType) type).getGenericComponentType());
if (!(type instanceof ParameterizedType)) return false; //只能是null了
final ParameterizedType ptype = (ParameterizedType) type;
if (ptype.getOwnerType() != null && !isClassType(ptype.getOwnerType())) return false;
if (!isClassType(ptype.getRawType())) return false;
for (Type t : ptype.getActualTypeArguments()) {
if (!isClassType(t)) return false;
}
return true;
}
/**
* 动态创建 ParameterizedType
*
* @param ownerType0
* @param rawType0
* @param actualTypeArguments0
* @return
*/
public static Type createParameterizedType(final Type ownerType0, final Type rawType0, final Type... actualTypeArguments0) {
if (ownerType0 == null && rawType0 instanceof Class) {
final Class[] actualClassArguments = new Class[actualTypeArguments0.length];
int count = 0;
for (int i = 0; i < actualTypeArguments0.length; i++) {
if (actualTypeArguments0[i] instanceof Class) {
actualClassArguments[i] = (Class) actualTypeArguments0[i];
count++;
}
}
if (count == actualClassArguments.length) return createParameterizedType((Class) rawType0, actualClassArguments);
}
return new ParameterizedType() {
private final Class<?> rawType = (Class<?>) rawType0;
private final Type ownerType = ownerType0;
private final Type[] argTypes = actualTypeArguments0;
@Override
public Type[] getActualTypeArguments() {
return argTypes.clone();
}
@Override
public Type getRawType() {
return rawType;
}
@Override
public Type getOwnerType() {
return ownerType;
}
@Override
public int hashCode() {
return Arrays.hashCode(argTypes) ^ Objects.hashCode(rawType) ^ Objects.hashCode(ownerType);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ParameterizedType)) return false;
final ParameterizedType that = (ParameterizedType) o;
if (this == that) return true;
return Objects.equals(ownerType, that.getOwnerType())
&& Objects.equals(rawType, that.getRawType())
&& Arrays.equals(argTypes, that.getActualTypeArguments());
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (ownerType != null) sb.append((ownerType instanceof Class) ? (((Class) ownerType).getName()) : ownerType.toString()).append(".");
sb.append(rawType.getName());
if (argTypes != null && argTypes.length > 0) {
sb.append("<");
boolean first = true;
for (Type t : argTypes) {
if (!first) sb.append(", ");
sb.append(t.getTypeName());
first = false;
}
sb.append(">");
}
return sb.toString();
}
};
}
private static Type createParameterizedType(final Class rawType, final Class... actualTypeArguments) {
ClassLoader loader = TypeToken.class.getClassLoader();
String newDynName = TypeToken.class.getName().replace('.', '/') + "_Dyn" + System.currentTimeMillis();
for (;;) {
@@ -44,11 +145,11 @@ public abstract class TypeToken<T> {
FieldVisitor fv;
MethodVisitor mv;
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, "java/lang/Object", null);
String rawTypeDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor((Class) rawType);
String rawTypeDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(rawType);
StringBuilder sb = new StringBuilder();
sb.append(rawTypeDesc.substring(0, rawTypeDesc.length() - 1)).append('<');
for (Type c : actualTypeArguments) {
sb.append(jdk.internal.org.objectweb.asm.Type.getDescriptor((Class) c));
for (Class c : actualTypeArguments) {
sb.append(jdk.internal.org.objectweb.asm.Type.getDescriptor(c));
}
sb.append(">;");
{