mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-05-22 18:27:01 +00:00
Merge pull request #72 from veione/feat_storage
fix[storage]:修复storage加入record生成协议报错
This commit is contained in:
@@ -30,6 +30,7 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 对应于ProtocolRegistration
|
||||
@@ -181,6 +182,9 @@ public abstract class EnhanceUtils {
|
||||
var fieldRegistrations = registration.getFieldRegistrations();
|
||||
|
||||
var packetClazz = constructor.getDeclaringClass();
|
||||
if (packetClazz.isRecord()) {
|
||||
fields = registration.getOriginalFields();
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
builder.append("{").append(packetClazz.getCanonicalName() + " packet = (" + packetClazz.getCanonicalName() + ")$2;");
|
||||
@@ -204,28 +208,46 @@ public abstract class EnhanceUtils {
|
||||
// see: ProtocolRegistration.read()
|
||||
private static String readMethodBody(ProtocolRegistration registration) {
|
||||
var constructor = registration.getConstructor();
|
||||
var fields = registration.getFields();
|
||||
var fieldRegistrations = registration.getFieldRegistrations();
|
||||
|
||||
var builder = new StringBuilder();
|
||||
builder.append("{").append("if(!" + EnhanceUtils.byteBufUtilsReadBoolean + "){").append("return null;}");
|
||||
var packetClazz = constructor.getDeclaringClass();
|
||||
builder.append(packetClazz.getCanonicalName() + " packet=new " + packetClazz.getCanonicalName() + "();");
|
||||
if (packetClazz.isRecord()) {
|
||||
var fields = registration.getOriginalFields();
|
||||
List<String> constructorParam = new ArrayList<>(fields.length);
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
var field = fields[i];
|
||||
var fieldRegistration = fieldRegistrations[i];
|
||||
// protocol backwards compatibility,协议向后兼容
|
||||
if (field.isAnnotationPresent(Compatible.class)) {
|
||||
builder.append("if(!$1.isReadable()){ return packet; }");
|
||||
}
|
||||
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
var field = fields[i];
|
||||
var fieldRegistration = fieldRegistrations[i];
|
||||
// protocol backwards compatibility,协议向后兼容
|
||||
if (field.isAnnotationPresent(Compatible.class)) {
|
||||
builder.append("if(!$1.isReadable()){ return packet; }");
|
||||
var readObject = enhanceSerializer(fieldRegistration.serializer()).readObject(builder, field, fieldRegistration);
|
||||
constructorParam.add(readObject);
|
||||
}
|
||||
|
||||
var readObject = enhanceSerializer(fieldRegistration.serializer()).readObject(builder, field, fieldRegistration);
|
||||
builder.append(packetClazz.getCanonicalName() + " packet=new " + packetClazz.getCanonicalName() + "(" + constructorParam.stream().collect(Collectors.joining(StringUtils.COMMA)) + ");");
|
||||
} else {
|
||||
var fields = registration.getFields();
|
||||
builder.append(packetClazz.getCanonicalName() + " packet=new " + packetClazz.getCanonicalName() + "();");
|
||||
|
||||
if (Modifier.isPublic(field.getModifiers())) {
|
||||
builder.append(StringUtils.format("packet.{}={};", field.getName(), readObject));
|
||||
} else {
|
||||
builder.append(StringUtils.format("packet.{}({});", ReflectionUtils.fieldToSetMethod(packetClazz, field), readObject));
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
var field = fields[i];
|
||||
var fieldRegistration = fieldRegistrations[i];
|
||||
// protocol backwards compatibility,协议向后兼容
|
||||
if (field.isAnnotationPresent(Compatible.class)) {
|
||||
builder.append("if(!$1.isReadable()){ return packet; }");
|
||||
}
|
||||
|
||||
var readObject = enhanceSerializer(fieldRegistration.serializer()).readObject(builder, field, fieldRegistration);
|
||||
|
||||
if (Modifier.isPublic(field.getModifiers())) {
|
||||
builder.append(StringUtils.format("packet.{}={};", field.getName(), readObject));
|
||||
} else {
|
||||
builder.append(StringUtils.format("packet.{}({});", ReflectionUtils.fieldToSetMethod(packetClazz, field), readObject));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import javassist.NotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static com.zfoo.protocol.ProtocolManager.*;
|
||||
|
||||
@@ -311,6 +312,7 @@ public class ProtocolAnalysis {
|
||||
enhanceProtocolRegistration(enhanceList);
|
||||
enhanceProtocolAfter(generateOperation);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new UnknownException(e);
|
||||
}
|
||||
}
|
||||
@@ -377,15 +379,16 @@ public class ProtocolAnalysis {
|
||||
GenerateProtobufUtils.clear();
|
||||
}
|
||||
|
||||
private static List<Field> customFieldOrder(Class<?> clazz) {
|
||||
private static Entry<ArrayList<Field>, List<Field>> customFieldOrder(Class<?> clazz) {
|
||||
var notCompatibleFields = new ArrayList<Field>();
|
||||
var compatibleFieldMap = new HashMap<Integer, Field>();
|
||||
List<Field> originalFields = new ArrayList<>();
|
||||
for (var field : clazz.getDeclaredFields()) {
|
||||
var modifiers = field.getModifiers();
|
||||
if (Modifier.isTransient(modifiers) || Modifier.isStatic(modifiers)) {
|
||||
continue;
|
||||
}
|
||||
if (Modifier.isFinal(modifiers)) {
|
||||
if (!clazz.isRecord() && Modifier.isFinal(modifiers)) {
|
||||
throw new RunException("[{}]协议号中的[field:{}]属性的访问修饰符不能为final", clazz.getCanonicalName(), field.getName());
|
||||
}
|
||||
if (!Modifier.isPublic(modifiers) && !Modifier.isPrivate(modifiers)) {
|
||||
@@ -400,6 +403,7 @@ public class ProtocolAnalysis {
|
||||
throw new RunException("[{}]协议号中的[field:{}]和[field:{}]不能有相同的Compatible顺序[order:{}]", clazz.getCanonicalName(), oldField.getName(), field.getName(), oldField, order);
|
||||
}
|
||||
} else {
|
||||
originalFields.add(field);
|
||||
notCompatibleFields.add(field);
|
||||
}
|
||||
}
|
||||
@@ -415,26 +419,37 @@ public class ProtocolAnalysis {
|
||||
.map(Map.Entry::getValue)
|
||||
.toList();
|
||||
notCompatibleFields.addAll(compatibleFields);
|
||||
return notCompatibleFields;
|
||||
return Map.entry(notCompatibleFields, originalFields);
|
||||
}
|
||||
|
||||
private static ProtocolRegistration parseProtocolRegistration(Class<?> clazz, ProtocolModule module) {
|
||||
var protocolId = ProtocolManager.protocolId(clazz);
|
||||
// 对象需要被序列化的属性
|
||||
var fields = customFieldOrder(clazz);
|
||||
var fieldsEntry = customFieldOrder(clazz);
|
||||
|
||||
try {
|
||||
var registrationList = new ArrayList<IFieldRegistration>();
|
||||
List<Field> fields = fieldsEntry.getKey();
|
||||
if (clazz.isRecord()) {
|
||||
fields = fieldsEntry.getValue();
|
||||
}
|
||||
for (var field : fields) {
|
||||
registrationList.add(toRegistration(clazz, field));
|
||||
}
|
||||
|
||||
var constructor = clazz.getDeclaredConstructor();
|
||||
Constructor constructor;
|
||||
if (clazz.isRecord()) {
|
||||
constructor = ReflectionUtils.getConstructor(clazz, fields.stream().map(p -> p.getType()).toList().toArray(new Class[]{}));
|
||||
} else {
|
||||
constructor = clazz.getDeclaredConstructor();
|
||||
}
|
||||
|
||||
ReflectionUtils.makeAccessible(constructor);
|
||||
var protocol = new ProtocolRegistration();
|
||||
protocol.setId(protocolId);
|
||||
protocol.setConstructor(constructor);
|
||||
protocol.setFields(ArrayUtils.listToArray(fields, Field.class));
|
||||
protocol.setFields(ArrayUtils.listToArray(fieldsEntry.getKey(), Field.class));
|
||||
protocol.setOriginalFields(ArrayUtils.listToArray(fieldsEntry.getValue(), Field.class));
|
||||
protocol.setFieldRegistrations(ArrayUtils.listToArray(registrationList, IFieldRegistration.class));
|
||||
protocol.setModule(module.getId());
|
||||
return protocol;
|
||||
@@ -630,8 +645,10 @@ public class ProtocolAnalysis {
|
||||
// 不能是泛型类
|
||||
AssertionUtils.isTrue(ArrayUtils.isEmpty(clazz.getTypeParameters()), "[class:{}]不能是泛型类", clazz.getCanonicalName());
|
||||
|
||||
// 必须要有一个空的构造器
|
||||
Constructor<?> constructor = ReflectionUtils.publicEmptyConstructor(clazz);
|
||||
// 普通Pojo必须要有一个空的构造器
|
||||
if (!clazz.isRecord()) {
|
||||
Constructor<?> constructor = ReflectionUtils.publicEmptyConstructor(clazz);
|
||||
}
|
||||
|
||||
var protocolAnnotation = clazz.getDeclaredAnnotation(Protocol.class);
|
||||
short protocolId = -1;
|
||||
|
||||
@@ -38,6 +38,8 @@ public class ProtocolRegistration implements IProtocolRegistration {
|
||||
*/
|
||||
private IFieldRegistration[] fieldRegistrations;
|
||||
|
||||
private Field[] originalFields;
|
||||
|
||||
public ProtocolRegistration() {
|
||||
|
||||
}
|
||||
@@ -122,6 +124,14 @@ public class ProtocolRegistration implements IProtocolRegistration {
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
public Field[] getOriginalFields() {
|
||||
return originalFields;
|
||||
}
|
||||
|
||||
public void setOriginalFields(Field[] originalFields) {
|
||||
this.originalFields = originalFields;
|
||||
}
|
||||
|
||||
public IFieldRegistration[] getFieldRegistrations() {
|
||||
return fieldRegistrations;
|
||||
}
|
||||
|
||||
@@ -393,8 +393,10 @@ public abstract class ClassUtils {
|
||||
ReflectionUtils.assertIsPojoClass(clazz);
|
||||
// 不能是泛型类
|
||||
AssertionUtils.isTrue(ArrayUtils.isEmpty(clazz.getTypeParameters()), "[class:{}]不能是泛型类", clazz.getCanonicalName());
|
||||
// 必须要有一个空的构造器
|
||||
ReflectionUtils.publicEmptyConstructor(clazz);
|
||||
// 普通Pojo必须要有一个空的构造器
|
||||
if (!clazz.isRecord()) {
|
||||
ReflectionUtils.publicEmptyConstructor(clazz);
|
||||
}
|
||||
|
||||
var filedList = ReflectionUtils.notStaticAndTransientFields(clazz);
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ public abstract class ReflectionUtils {
|
||||
}
|
||||
|
||||
public static boolean isPojoClass(Class<?> clazz) {
|
||||
return clazz.getSuperclass().equals(Object.class);
|
||||
return clazz.getSuperclass().equals(Object.class) || clazz.isRecord();
|
||||
}
|
||||
|
||||
public static void assertIsPojoClass(Class<?> clazz) {
|
||||
@@ -322,11 +322,14 @@ public abstract class ReflectionUtils {
|
||||
|
||||
public static String fieldToGetMethod(Class<?> clazz, Field field) {
|
||||
var fieldName = field.getName();
|
||||
|
||||
assertIsStandardFieldName(field);
|
||||
|
||||
var methodName = "get" + StringUtils.capitalize(fieldName);
|
||||
|
||||
if (clazz.isRecord()) {
|
||||
methodName = fieldName;
|
||||
}
|
||||
|
||||
try {
|
||||
clazz.getDeclaredMethod(methodName);
|
||||
return methodName;
|
||||
@@ -358,6 +361,11 @@ public abstract class ReflectionUtils {
|
||||
assertIsStandardFieldName(field);
|
||||
|
||||
var methodName = "set" + StringUtils.capitalize(fieldName);
|
||||
|
||||
if (clazz.isRecord()) {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
try {
|
||||
clazz.getDeclaredMethod(methodName, field.getType());
|
||||
return methodName;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
package com.zfoo.storage.export;
|
||||
|
||||
import com.zfoo.protocol.ProtocolManager;
|
||||
import com.zfoo.protocol.buffer.ByteBufUtils;
|
||||
import com.zfoo.protocol.generate.GenerateOperation;
|
||||
import com.zfoo.protocol.serializer.CodeLanguage;
|
||||
@@ -102,12 +103,12 @@ public class ExportBinaryTesting {
|
||||
var operation = new GenerateOperation();
|
||||
operation.setProtocolPath("D:\\github\\godot-bird\\test\\storage\\protocol");
|
||||
operation.getGenerateLanguages().add(CodeLanguage.GdScript);
|
||||
//ProtocolManager.initProtocolAuto(protocols, operation);
|
||||
ProtocolManager.initProtocolAuto(protocols, operation);
|
||||
|
||||
// 生成数据
|
||||
var resourceData = ExportUtils.autoWrapData(ResourceData.class, storageManager.storageMap());
|
||||
var buffer = new UnpooledHeapByteBuf(ByteBufAllocator.DEFAULT, 100, Integer.MAX_VALUE);
|
||||
//ProtocolManager.write(buffer, resourceData);
|
||||
ProtocolManager.write(buffer, resourceData);
|
||||
var bytes = ByteBufUtils.readAllBytes(buffer);
|
||||
FileUtils.writeInputStreamToFile(new File("D:/github/godot-bird/binary_data.cfg"), new ByteArrayInputStream(bytes));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user