This commit is contained in:
redkale
2024-09-19 12:45:21 +08:00
parent 2cf74bedca
commit f4c4bfda70
4 changed files with 396 additions and 153 deletions

View File

@@ -553,6 +553,127 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
return fname;
}
public String readGetSetFieldName(AccessibleObject element) {
if (element instanceof Field) {
return ((Field) element).getName();
}
return readGetSetFieldName((Method) element);
}
public boolean isSimpleMemberType(Class declaringClass, Type type, Class clazz) {
if (type == String.class) {
return true;
}
if (clazz.isPrimitive()) {
return true;
}
if (clazz.isEnum()) {
return true;
}
if (type == Boolean.class) {
return true;
}
if (type == Byte.class) {
return true;
}
if (type == Short.class) {
return true;
}
if (type == Character.class) {
return true;
}
if (type == Integer.class) {
return true;
}
if (type == Float.class) {
return true;
}
if (type == Long.class) {
return true;
}
if (type == Double.class) {
return true;
}
if (type == boolean[].class) {
return true;
}
if (type == byte[].class) {
return true;
}
if (type == short[].class) {
return true;
}
if (type == char[].class) {
return true;
}
if (type == int[].class) {
return true;
}
if (type == float[].class) {
return true;
}
if (type == long[].class) {
return true;
}
if (type == double[].class) {
return true;
}
if (type == Boolean[].class) {
return true;
}
if (type == Byte[].class) {
return true;
}
if (type == Short[].class) {
return true;
}
if (type == Character[].class) {
return true;
}
if (type == Integer[].class) {
return true;
}
if (type == Float[].class) {
return true;
}
if (type == Long[].class) {
return true;
}
if (type == Double[].class) {
return true;
}
if (type == String[].class) {
return true;
}
if (rootFactory().findEncoder(type) != null) {
return true;
}
if (declaringClass == clazz) {
return false;
}
if (Collection.class.isAssignableFrom(clazz) && type instanceof ParameterizedType) {
Type[] ts = ((ParameterizedType) type).getActualTypeArguments();
if (ts.length == 1) {
Type t = ts[0];
if (t == Boolean.class
|| t == Byte.class
|| t == Short.class
|| t == Character.class
|| t == Integer.class
|| t == Float.class
|| t == Long.class
|| t == Double.class
|| t == String.class
|| rootFactory().findEncoder(t) != null
|| ((t instanceof Class) && ((Class) t).isEnum())) {
return true;
}
return false;
}
}
return false;
}
final String getEntityAlias(Class clazz) {
if (clazz == String.class) {
return "A";

View File

@@ -42,121 +42,6 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
return false;
}
private static boolean checkMemberType(
final JsonFactory factory, final Class declaringClass, Type type, Class clazz) {
if (type == String.class) {
return true;
}
if (clazz.isPrimitive()) {
return true;
}
if (clazz.isEnum()) {
return true;
}
if (type == Boolean.class) {
return true;
}
if (type == Byte.class) {
return true;
}
if (type == Short.class) {
return true;
}
if (type == Character.class) {
return true;
}
if (type == Integer.class) {
return true;
}
if (type == Float.class) {
return true;
}
if (type == Long.class) {
return true;
}
if (type == Double.class) {
return true;
}
if (type == boolean[].class) {
return true;
}
if (type == byte[].class) {
return true;
}
if (type == short[].class) {
return true;
}
if (type == char[].class) {
return true;
}
if (type == int[].class) {
return true;
}
if (type == float[].class) {
return true;
}
if (type == long[].class) {
return true;
}
if (type == double[].class) {
return true;
}
if (type == Boolean[].class) {
return true;
}
if (type == Byte[].class) {
return true;
}
if (type == Short[].class) {
return true;
}
if (type == Character[].class) {
return true;
}
if (type == Integer[].class) {
return true;
}
if (type == Float[].class) {
return true;
}
if (type == Long[].class) {
return true;
}
if (type == Double[].class) {
return true;
}
if (type == String[].class) {
return true;
}
if (factory.rootFactory().findEncoder(type) != null) {
return true;
}
if (declaringClass == clazz) {
return false;
}
if (Collection.class.isAssignableFrom(clazz) && type instanceof ParameterizedType) {
Type[] ts = ((ParameterizedType) type).getActualTypeArguments();
if (ts.length == 1) {
Type t = ts[0];
if (t == Boolean.class
|| t == Byte.class
|| t == Short.class
|| t == Character.class
|| t == Integer.class
|| t == Float.class
|| t == Long.class
|| t == Double.class
|| t == String.class
|| factory.rootFactory().findEncoder(t) != null
|| ((t instanceof Class) && ((Class) t).isEnum())) {
return true;
}
return false;
}
}
return false;
}
// 字段全部是primitive或String类型且没有泛型的类才能动态生成JsonDynEncoder 不支持的返回null
public static JsonDynEncoder createDyncEncoder(final JsonFactory factory, final Type type) {
if (!(type instanceof Class)) {
@@ -239,7 +124,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
if (factory.findFieldCoder(clazz, field.getName()) != null) {
return null;
}
if (!(checkMemberType(factory, clazz, field.getGenericType(), field.getType()))) {
if (!factory.isSimpleMemberType(clazz, field.getGenericType(), field.getType())) {
return null;
}
String name = convertFieldName(factory, clazz, field);
@@ -290,7 +175,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
if (ref != null && ref.fieldFunc() != null) {
return null;
}
if (!(checkMemberType(factory, clazz, method.getGenericReturnType(), method.getReturnType()))) {
if (!factory.isSimpleMemberType(clazz, method.getGenericReturnType(), method.getReturnType())) {
return null;
}
String name = convertFieldName(factory, clazz, method);
@@ -319,8 +204,8 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
return idx1 - idx2;
}
}
String n1 = ref1 == null || ref1.name().isEmpty() ? readGetSetFieldName(o1) : ref1.name();
String n2 = ref2 == null || ref2.name().isEmpty() ? readGetSetFieldName(o2) : ref2.name();
String n1 = ref1 == null || ref1.name().isEmpty() ? factory.readGetSetFieldName(o1) : ref1.name();
String n2 = ref2 == null || ref2.name().isEmpty() ? factory.readGetSetFieldName(o2) : ref2.name();
if (n1 == null && n2 == null) {
return 0;
}
@@ -341,11 +226,11 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
protected static String convertFieldName(final JsonFactory factory, Class clazz, AccessibleObject element) {
ConvertColumnEntry ref = factory.findRef(clazz, element);
String name = ref == null || ref.name().isEmpty() ? readGetSetFieldName(element) : ref.name();
String name = ref == null || ref.name().isEmpty() ? factory.readGetSetFieldName(element) : ref.name();
return name;
}
protected static ConvertSmallString readConvertSmallString(AccessibleObject element) {
protected static ConvertSmallString readConvertSmallString(JsonFactory factory, AccessibleObject element) {
if (element instanceof Field) {
return ((Field) element).getAnnotation(ConvertSmallString.class);
}
@@ -353,7 +238,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
ConvertSmallString small = method.getAnnotation(ConvertSmallString.class);
if (small == null) {
try {
Field f = method.getDeclaringClass().getDeclaredField(readGetSetFieldName(method));
Field f = method.getDeclaringClass().getDeclaredField(factory.readGetSetFieldName(method));
if (f != null) {
small = f.getAnnotation(ConvertSmallString.class);
}
@@ -371,26 +256,6 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
return ((Method) element).getReturnType();
}
protected static String readGetSetFieldName(AccessibleObject element) {
if (element instanceof Field) {
return ((Field) element).getName();
}
Method method = (Method) element;
String fname = method.getName();
if (!(fname.startsWith("is") && fname.length() > 2)
&& !(fname.startsWith("get") && fname.length() > 3)
&& !(fname.startsWith("set") && fname.length() > 3)) {
return fname;
}
fname = fname.substring(fname.startsWith("is") ? 2 : 3);
if (fname.length() > 1 && !(fname.charAt(1) >= 'A' && fname.charAt(1) <= 'Z')) {
fname = Character.toLowerCase(fname.charAt(0)) + fname.substring(1);
} else if (fname.length() == 1) {
fname = "" + Character.toLowerCase(fname.charAt(0));
}
return fname;
}
protected static JsonDynEncoder generateDyncEncoder(
final JsonFactory factory, final Class clazz, final List<AccessibleObject> members) {
final ObjectEncoder selfObjEncoder = factory.createObjectEncoder(clazz);
@@ -415,7 +280,8 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
StringBuilder memberb = new StringBuilder();
for (AccessibleObject element : members) {
ConvertColumnEntry ref1 = factory.findRef(clazz, element);
final String fieldname = ref1 == null || ref1.name().isEmpty() ? readGetSetFieldName(element) : ref1.name();
final String fieldname =
ref1 == null || ref1.name().isEmpty() ? factory.readGetSetFieldName(element) : ref1.name();
memberb.append(fieldname).append(',');
final Class fieldType = readGetSetFieldType(element);
if (fieldType != String.class && !fieldType.isPrimitive()) {
@@ -478,7 +344,8 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
int intFieldCount = 0;
for (AccessibleObject element : members) {
ConvertColumnEntry ref1 = factory.findRef(clazz, element);
final String fieldname = ref1 == null || ref1.name().isEmpty() ? readGetSetFieldName(element) : ref1.name();
final String fieldname =
ref1 == null || ref1.name().isEmpty() ? factory.readGetSetFieldName(element) : ref1.name();
fv = cw.visitField(ACC_PROTECTED + ACC_FINAL, fieldname + "FieldBytes", "[B", null, null);
fv.visitEnd();
fv = cw.visitField(ACC_PROTECTED + ACC_FINAL, fieldname + "CommaFieldBytes", "[B", null, null);
@@ -499,12 +366,12 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
if (fieldType == int.class) {
intFieldCount++;
}
if (fieldType == String.class && membersSize == 1 && readConvertSmallString(element) != null) {
if (fieldType == String.class && membersSize == 1 && readConvertSmallString(factory, element) != null) {
onlyOneLatin1FieldObjectFlag = true;
} else if (fieldType != short.class
&& fieldType != int.class
&& fieldType != long.class
&& !(fieldType == String.class && readConvertSmallString(element) != null)) {
&& !(fieldType == String.class && readConvertSmallString(factory, element) != null)) {
onlyShotIntLongLatin1MoreFieldObjectFlag = false;
}
}
@@ -525,7 +392,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
for (AccessibleObject element : members) {
ConvertColumnEntry ref1 = factory.findRef(clazz, element);
final String fieldname =
ref1 == null || ref1.name().isEmpty() ? readGetSetFieldName(element) : ref1.name();
ref1 == null || ref1.name().isEmpty() ? factory.readGetSetFieldName(element) : ref1.name();
// xxxFieldBytes
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn("\"" + fieldname + "\":");
@@ -610,7 +477,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
AccessibleObject element = members.get(elementIndex);
ConvertColumnEntry ref1 = factory.findRef(clazz, element);
final String fieldName =
ref1 == null || ref1.name().isEmpty() ? readGetSetFieldName(element) : ref1.name();
ref1 == null || ref1.name().isEmpty() ? factory.readGetSetFieldName(element) : ref1.name();
final Class fieldtype = readGetSetFieldType(element);
mv.visitVarInsn(ALOAD, 1);
@@ -646,14 +513,14 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
AccessibleObject element1 = members.get(elementIndex);
ConvertColumnEntry ref1 = factory.findRef(clazz, element1);
final String fieldName1 =
ref1 == null || ref1.name().isEmpty() ? readGetSetFieldName(element1) : ref1.name();
ref1 == null || ref1.name().isEmpty() ? factory.readGetSetFieldName(element1) : ref1.name();
final Class fieldType1 = readGetSetFieldType(element1);
elementIndex++;
AccessibleObject element2 = members.get(elementIndex);
ConvertColumnEntry ref2 = factory.findRef(clazz, element2);
final String fieldName2 =
ref2 == null || ref2.name().isEmpty() ? readGetSetFieldName(element2) : ref2.name();
ref2 == null || ref2.name().isEmpty() ? factory.readGetSetFieldName(element2) : ref2.name();
final Class fieldtype2 = readGetSetFieldType(element2);
mv.visitVarInsn(ALOAD, 1);
@@ -710,7 +577,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
elementIndex++;
ConvertColumnEntry ref1 = factory.findRef(clazz, element);
final String fieldname =
ref1 == null || ref1.name().isEmpty() ? readGetSetFieldName(element) : ref1.name();
ref1 == null || ref1.name().isEmpty() ? factory.readGetSetFieldName(element) : ref1.name();
final Class fieldtype = readGetSetFieldType(element);
mv.visitVarInsn(ALOAD, 1);
@@ -793,7 +660,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
elementIndex++;
ConvertColumnEntry ref1 = factory.findRef(clazz, element);
final String fieldname =
ref1 == null || ref1.name().isEmpty() ? readGetSetFieldName(element) : ref1.name();
ref1 == null || ref1.name().isEmpty() ? factory.readGetSetFieldName(element) : ref1.name();
final Class fieldtype = readGetSetFieldType(element);
int storeid = ASTORE;
int loadid = ALOAD;
@@ -972,7 +839,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
mv.visitVarInsn(loadid, maxLocals);
mv.visitMethodInsn(INVOKEVIRTUAL, writerName, "writeDouble", "(D)V", false);
} else if (fieldtype == String.class) {
if (readConvertSmallString(element) == null) {
if (readConvertSmallString(factory, element) == null) {
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(loadid, maxLocals);
mv.visitMethodInsn(

View File

@@ -0,0 +1,250 @@
/*
* Copyright (c) 2016-2116 Redkale
* All rights reserved.
*/
package org.redkale.convert.pb;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.redkale.convert.ConvertColumnEntry;
import org.redkale.convert.Encodeable;
import org.redkale.convert.ObjectEncoder;
import org.redkale.convert.ext.BoolArraySimpledCoder;
import org.redkale.convert.ext.BoolSimpledCoder;
import org.redkale.convert.ext.ByteArraySimpledCoder;
import org.redkale.convert.ext.ByteSimpledCoder;
import org.redkale.convert.ext.CharArraySimpledCoder;
import org.redkale.convert.ext.CharSimpledCoder;
import org.redkale.convert.ext.DoubleArraySimpledCoder;
import org.redkale.convert.ext.DoubleSimpledCoder;
import org.redkale.convert.ext.FloatArraySimpledCoder;
import org.redkale.convert.ext.FloatSimpledCoder;
import org.redkale.convert.ext.IntArraySimpledCoder;
import org.redkale.convert.ext.IntSimpledCoder;
import org.redkale.convert.ext.LongArraySimpledCoder;
import org.redkale.convert.ext.LongSimpledCoder;
import org.redkale.convert.ext.ShortArraySimpledCoder;
import org.redkale.convert.ext.ShortSimpledCoder;
import org.redkale.convert.ext.StringArraySimpledCoder;
import org.redkale.convert.ext.StringSimpledCoder;
import org.redkale.util.RedkaleClassLoader;
/**
* 简单对象的PROTOBUF序列化操作类
*
* <p>详情见: https://redkale.org
*
* @author zhangjx
* @since 2.8.0
* @param <T> 序列化的数据类型
*/
public abstract class ProtobufDynEncoder<T> implements Encodeable<ProtobufWriter, T> {
public abstract void init(final ProtobufFactory factory);
// 字段全部是primitive或String类型且没有泛型的类才能动态生成ProtobufDynEncoder 不支持的返回null
public static ProtobufDynEncoder createDyncEncoder(final ProtobufFactory factory, final Type type) {
if (!(type instanceof Class)) {
return null;
}
// 发现有自定义的基础数据类型Encoder就不动态生成ProtobufDynEncoder了
if (factory.loadEncoder(boolean.class) != BoolSimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(byte.class) != ByteSimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(short.class) != ShortSimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(char.class) != CharSimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(int.class) != IntSimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(float.class) != FloatSimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(long.class) != LongSimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(double.class) != DoubleSimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(String.class) != StringSimpledCoder.instance) {
return null;
}
// array
if (factory.loadEncoder(boolean[].class) != BoolArraySimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(byte[].class) != ByteArraySimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(short[].class) != ShortArraySimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(char[].class) != CharArraySimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(int[].class) != IntArraySimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(float[].class) != FloatArraySimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(long[].class) != LongArraySimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(double[].class) != DoubleArraySimpledCoder.instance) {
return null;
}
if (factory.loadEncoder(String[].class) != StringArraySimpledCoder.instance) {
return null;
}
final Class clazz = (Class) type;
List<AccessibleObject> members = null;
Set<String> names = new HashSet<>();
try {
ConvertColumnEntry ref;
RedkaleClassLoader.putReflectionPublicFields(clazz.getName());
for (final Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (factory.isConvertDisabled(field)) {
continue;
}
ref = factory.findRef(clazz, field);
if (ref != null && ref.ignore()) {
continue;
}
if (factory.findFieldCoder(clazz, field.getName()) != null) {
return null;
}
if (!factory.isSimpleMemberType(clazz, field.getGenericType(), field.getType())) {
return null;
}
String name = convertFieldName(factory, clazz, field);
if (names.contains(name)) {
continue;
}
names.add(name);
if (members == null) {
members = new ArrayList<>();
}
members.add(field);
}
RedkaleClassLoader.putReflectionPublicMethods(clazz.getName());
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().length() > 2)
&& !(method.getName().startsWith("get")
&& method.getName().length() > 3)) {
continue;
}
if (factory.isConvertDisabled(method)) {
continue;
}
if (method.getParameterTypes().length != 0) {
continue;
}
if (method.getReturnType() == void.class) {
continue;
}
ref = factory.findRef(clazz, method);
if (ref != null && ref.ignore()) {
continue;
}
if (ref != null && ref.fieldFunc() != null) {
return null;
}
if (!factory.isSimpleMemberType(clazz, method.getGenericReturnType(), method.getReturnType())) {
return null;
}
String name = convertFieldName(factory, clazz, method);
if (names.contains(name)) {
continue;
}
if (factory.findFieldCoder(clazz, name) != null) {
return null;
}
names.add(name);
if (members == null) {
members = new ArrayList<>();
}
members.add(method);
}
if (members == null) {
return null;
}
Collections.sort(members, (o1, o2) -> {
ConvertColumnEntry ref1 = factory.findRef(clazz, o1);
ConvertColumnEntry ref2 = factory.findRef(clazz, o2);
if ((ref1 != null && ref1.getIndex() > 0) || (ref2 != null && ref2.getIndex() > 0)) {
int idx1 = ref1 == null ? Integer.MAX_VALUE / 2 : ref1.getIndex();
int idx2 = ref2 == null ? Integer.MAX_VALUE / 2 : ref2.getIndex();
if (idx1 != idx2) {
return idx1 - idx2;
}
}
String n1 = ref1 == null || ref1.name().isEmpty() ? factory.readGetSetFieldName(o1) : ref1.name();
String n2 = ref2 == null || ref2.name().isEmpty() ? factory.readGetSetFieldName(o2) : ref2.name();
if (n1 == null && n2 == null) {
return 0;
}
if (n1 == null) {
return -1;
}
if (n2 == null) {
return 1;
}
return n1.compareTo(n2);
});
return generateDyncEncoder(factory, clazz, members);
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
protected static String convertFieldName(final ProtobufFactory factory, Class clazz, AccessibleObject element) {
ConvertColumnEntry ref = factory.findRef(clazz, element);
String name = ref == null || ref.name().isEmpty() ? factory.readGetSetFieldName(element) : ref.name();
return name;
}
protected static ProtobufDynEncoder generateDyncEncoder(
final ProtobufFactory factory, final Class clazz, final List<AccessibleObject> members) {
final ObjectEncoder selfObjEncoder = factory.createObjectEncoder(clazz);
selfObjEncoder.init(factory);
if (selfObjEncoder.getMembers().length != members.size()) {
return null; // 存在ignore等定制配置
}
return null;
}
}

View File

@@ -91,6 +91,11 @@ public class ProtobufFactory extends ConvertFactory<ProtobufReader, ProtobufWrit
return new ProtobufFactory(null, instance.features, instance.enumtostring);
}
@Override
protected <E> Encodeable<ProtobufWriter, E> createDyncEncoder(Type type) {
return ProtobufDynEncoder.createDyncEncoder(this, type);
}
@Override
protected SimpledCoder createEnumSimpledCoder(Class enumClass) {
return new ProtobufEnumSimpledCoder(enumClass, this.enumtostring);