deployed 2.0.0.RELEASE,升级相关依赖
使用RuntimeSchema 使用反射(Field)取代内省(PropertyDescriptor),以兼容android平台master
parent
a6e0e7c819
commit
c305df04b9
6
pom.xml
6
pom.xml
|
@ -3,7 +3,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>io.github.yezhihao</groupId>
|
<groupId>io.github.yezhihao</groupId>
|
||||||
<artifactId>protostar</artifactId>
|
<artifactId>protostar</artifactId>
|
||||||
<version>1.0.5.RELEASE</version>
|
<version>2.0.0.RELEASE</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>Protostar</name>
|
<name>Protostar</name>
|
||||||
|
@ -50,13 +50,13 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-simple</artifactId>
|
<artifactId>slf4j-simple</artifactId>
|
||||||
<version>1.7.30</version>
|
<version>1.7.31</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>1.7.30</version>
|
<version>1.7.31</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package io.github.yezhihao.protostar;
|
package io.github.yezhihao.protostar;
|
||||||
|
|
||||||
import io.github.yezhihao.protostar.annotation.Message;
|
import io.github.yezhihao.protostar.annotation.Message;
|
||||||
|
import io.github.yezhihao.protostar.schema.RuntimeSchema;
|
||||||
import io.github.yezhihao.protostar.util.ClassUtils;
|
import io.github.yezhihao.protostar.util.ClassUtils;
|
||||||
|
|
||||||
import java.beans.Introspector;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -14,7 +14,7 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class DefaultLoadStrategy extends LoadStrategy {
|
public class DefaultLoadStrategy extends LoadStrategy {
|
||||||
|
|
||||||
private Map<String, Map<Integer, Schema<?>>> typeClassMapping = new HashMap(140);
|
private Map<String, Map<Integer, RuntimeSchema<?>>> typeClassMapping = new HashMap(140);
|
||||||
|
|
||||||
public DefaultLoadStrategy() {
|
public DefaultLoadStrategy() {
|
||||||
}
|
}
|
||||||
|
@ -26,33 +26,32 @@ public class DefaultLoadStrategy extends LoadStrategy {
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
int[] values = message.value();
|
int[] values = message.value();
|
||||||
for (int typeId : values)
|
for (int typeId : values)
|
||||||
loadSchema(typeClassMapping, typeId, type);
|
loadRuntimeSchema(typeClassMapping, typeId, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Introspector.flushCaches();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> Schema<T> getSchema(Class<T> typeClass, Integer version) {
|
public <T> RuntimeSchema<T> getRuntimeSchema(Class<T> typeClass, Integer version) {
|
||||||
Map<Integer, Schema<?>> schemas = typeClassMapping.get(typeClass.getName());
|
Map<Integer, RuntimeSchema<?>> schemas = typeClassMapping.get(typeClass.getName());
|
||||||
if (schemas == null) {
|
if (schemas == null) {
|
||||||
schemas = loadSchema(typeClassMapping, typeClass);
|
schemas = loadRuntimeSchema(typeClassMapping, typeClass);
|
||||||
}
|
}
|
||||||
if (schemas == null) return null;
|
if (schemas == null) return null;
|
||||||
return (Schema<T>) schemas.get(version);
|
return (RuntimeSchema<T>) schemas.get(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> Map<Integer, Schema<T>> getSchema(Class<T> typeClass) {
|
public <T> Map<Integer, RuntimeSchema<T>> getRuntimeSchema(Class<T> typeClass) {
|
||||||
Map<Integer, Schema<?>> schemas = typeClassMapping.get(typeClass.getName());
|
Map<Integer, RuntimeSchema<?>> schemas = typeClassMapping.get(typeClass.getName());
|
||||||
if (schemas == null) {
|
if (schemas == null) {
|
||||||
schemas = loadSchema(typeClassMapping, typeClass);
|
schemas = loadRuntimeSchema(typeClassMapping, typeClass);
|
||||||
}
|
}
|
||||||
if (schemas == null) return null;
|
if (schemas == null) return null;
|
||||||
|
|
||||||
HashMap<Integer, Schema<T>> result = new HashMap<>(schemas.size());
|
HashMap<Integer, RuntimeSchema<T>> result = new HashMap<>(schemas.size());
|
||||||
for (Map.Entry<Integer, Schema<?>> entry : schemas.entrySet()) {
|
for (Map.Entry<Integer, RuntimeSchema<?>> entry : schemas.entrySet()) {
|
||||||
result.put(entry.getKey(), (Schema<T>) entry.getValue());
|
result.put(entry.getKey(), (RuntimeSchema<T>) entry.getValue());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import io.github.yezhihao.protostar.schema.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@ -23,13 +22,13 @@ public abstract class FieldFactory {
|
||||||
protected static Logger log = LoggerFactory.getLogger(FieldFactory.class.getSimpleName());
|
protected static Logger log = LoggerFactory.getLogger(FieldFactory.class.getSimpleName());
|
||||||
public static boolean EXPLAIN = false;
|
public static boolean EXPLAIN = false;
|
||||||
|
|
||||||
public static BasicField create(Field field, PropertyDescriptor property) {
|
public static BasicField create(Field field, java.lang.reflect.Field f) {
|
||||||
return create(field, property, null);
|
return create(field, f, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BasicField create(Field field, PropertyDescriptor property, Schema schema) {
|
public static BasicField create(Field field, java.lang.reflect.Field f, Schema schema) {
|
||||||
DataType dataType = field.type();
|
DataType dataType = field.type();
|
||||||
Class<?> typeClass = property.getPropertyType();
|
Class<?> typeClass = f.getType();
|
||||||
|
|
||||||
Schema fieldSchema;
|
Schema fieldSchema;
|
||||||
switch (dataType) {
|
switch (dataType) {
|
||||||
|
@ -63,7 +62,7 @@ public abstract class FieldFactory {
|
||||||
if (schema != null) {
|
if (schema != null) {
|
||||||
fieldSchema = ObjectSchema.getInstance(schema);
|
fieldSchema = ObjectSchema.getInstance(schema);
|
||||||
} else {
|
} else {
|
||||||
Convert convert = property.getReadMethod().getAnnotation(Convert.class);
|
Convert convert = f.getAnnotation(Convert.class);
|
||||||
fieldSchema = ConvertSchema.getInstance(convert.converter());
|
fieldSchema = ConvertSchema.getInstance(convert.converter());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -71,7 +70,7 @@ public abstract class FieldFactory {
|
||||||
fieldSchema = CollectionSchema.getInstance(schema);
|
fieldSchema = CollectionSchema.getInstance(schema);
|
||||||
break;
|
break;
|
||||||
case MAP:
|
case MAP:
|
||||||
Convert convert = property.getReadMethod().getAnnotation(Convert.class);
|
Convert convert = f.getAnnotation(Convert.class);
|
||||||
fieldSchema = ConvertSchema.getInstance(convert.converter());
|
fieldSchema = ConvertSchema.getInstance(convert.converter());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -82,19 +81,19 @@ public abstract class FieldFactory {
|
||||||
BasicField result;
|
BasicField result;
|
||||||
if (EXPLAIN) {
|
if (EXPLAIN) {
|
||||||
if (field.lengthSize() > 0) {
|
if (field.lengthSize() > 0) {
|
||||||
result = new DynamicLengthField.Logger(field, property, fieldSchema);
|
result = new DynamicLengthField.Logger(field, f, fieldSchema);
|
||||||
} else if (field.length() > 0) {
|
} else if (field.length() > 0) {
|
||||||
result = new FixedLengthField.Logger(field, property, fieldSchema);
|
result = new FixedLengthField.Logger(field, f, fieldSchema);
|
||||||
} else {
|
} else {
|
||||||
result = new FixedField.Logger(field, property, fieldSchema);
|
result = new FixedField.Logger(field, f, fieldSchema);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (field.lengthSize() > 0) {
|
if (field.lengthSize() > 0) {
|
||||||
result = new DynamicLengthField(field, property, fieldSchema);
|
result = new DynamicLengthField(field, f, fieldSchema);
|
||||||
} else if (field.length() > 0) {
|
} else if (field.length() > 0) {
|
||||||
result = new FixedLengthField(field, property, fieldSchema);
|
result = new FixedLengthField(field, f, fieldSchema);
|
||||||
} else {
|
} else {
|
||||||
result = new FixedField(field, property, fieldSchema);
|
result = new FixedField(field, f, fieldSchema);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -5,11 +5,6 @@ import io.github.yezhihao.protostar.field.BasicField;
|
||||||
import io.github.yezhihao.protostar.schema.RuntimeSchema;
|
import io.github.yezhihao.protostar.schema.RuntimeSchema;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
import java.beans.BeanInfo;
|
|
||||||
import java.beans.IntrospectionException;
|
|
||||||
import java.beans.Introspector;
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -54,11 +49,11 @@ public abstract class IdStrategy {
|
||||||
if (schema != null)
|
if (schema != null)
|
||||||
return (Schema<T>) schema;
|
return (Schema<T>) schema;
|
||||||
|
|
||||||
List<PropertyDescriptor> properties = findFieldProperties(typeClass);
|
List<java.lang.reflect.Field> fs = findFields(typeClass);
|
||||||
if (properties.isEmpty())
|
if (fs.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
List<BasicField> fieldList = findFields(root, properties);
|
List<BasicField> fieldList = findFields(root, fs);
|
||||||
BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]);
|
BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]);
|
||||||
Arrays.sort(fields);
|
Arrays.sort(fields);
|
||||||
|
|
||||||
|
@ -67,57 +62,44 @@ public abstract class IdStrategy {
|
||||||
return (Schema<T>) schema;
|
return (Schema<T>) schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static List<PropertyDescriptor> findFieldProperties(Class typeClass) {
|
protected static List<java.lang.reflect.Field> findFields(Class typeClass) {
|
||||||
BeanInfo beanInfo;
|
java.lang.reflect.Field[] fields = typeClass.getDeclaredFields();
|
||||||
try {
|
List<java.lang.reflect.Field> result = new ArrayList<>(fields.length);
|
||||||
beanInfo = Introspector.getBeanInfo(typeClass);
|
|
||||||
} catch (IntrospectionException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();
|
|
||||||
List<PropertyDescriptor> result = new ArrayList<>(properties.length);
|
|
||||||
|
|
||||||
for (PropertyDescriptor property : properties) {
|
for (java.lang.reflect.Field f : fields) {
|
||||||
Method readMethod = property.getReadMethod();
|
if (f.isAnnotationPresent(Field.class)) {
|
||||||
|
result.add(f);
|
||||||
if (readMethod != null) {
|
|
||||||
if (readMethod.isAnnotationPresent(Field.class)) {
|
|
||||||
result.add(property);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static List<BasicField> findFields(Map<Object, Schema> root, List<PropertyDescriptor> properties) {
|
protected static List<BasicField> findFields(Map<Object, Schema> root, List<java.lang.reflect.Field> fs) {
|
||||||
List<BasicField> fields = new ArrayList<>(properties.size());
|
List<BasicField> fields = new ArrayList<>(fs.size());
|
||||||
|
|
||||||
for (PropertyDescriptor property : properties) {
|
for (java.lang.reflect.Field f : fs) {
|
||||||
Method readMethod = property.getReadMethod();
|
Field field = f.getDeclaredAnnotation(Field.class);
|
||||||
|
|
||||||
Field field = readMethod.getDeclaredAnnotation(Field.class);
|
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
fillField(root, fields, property, field);
|
fillField(root, fields, f, field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void fillField(Map<Object, Schema> root, List<BasicField> fields, PropertyDescriptor propertyDescriptor, Field field) {
|
protected static void fillField(Map<Object, Schema> root, List<BasicField> fields, java.lang.reflect.Field f, Field field) {
|
||||||
Class typeClass = propertyDescriptor.getPropertyType();
|
Class typeClass = f.getType();
|
||||||
Method readMethod = propertyDescriptor.getReadMethod();
|
|
||||||
|
|
||||||
BasicField value;
|
BasicField value;
|
||||||
|
|
||||||
if (field.type() == DataType.OBJ || field.type() == DataType.LIST) {
|
if (field.type() == DataType.OBJ || field.type() == DataType.LIST) {
|
||||||
if (Collection.class.isAssignableFrom(typeClass))
|
if (Collection.class.isAssignableFrom(typeClass))
|
||||||
typeClass = (Class) ((ParameterizedType) readMethod.getGenericReturnType()).getActualTypeArguments()[0];
|
typeClass = (Class) ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0];
|
||||||
loadSchema(root, typeClass);
|
loadSchema(root, typeClass);
|
||||||
Schema schema = root.get(typeClass.getName());
|
Schema schema = root.get(typeClass.getName());
|
||||||
value = FieldFactory.create(field, propertyDescriptor, schema);
|
value = FieldFactory.create(field, f, schema);
|
||||||
fields.add(value);
|
fields.add(value);
|
||||||
} else {
|
} else {
|
||||||
value = FieldFactory.create(field, propertyDescriptor);
|
value = FieldFactory.create(field, f);
|
||||||
fields.add(value);
|
fields.add(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,55 +5,50 @@ import io.github.yezhihao.protostar.annotation.Fs;
|
||||||
import io.github.yezhihao.protostar.field.BasicField;
|
import io.github.yezhihao.protostar.field.BasicField;
|
||||||
import io.github.yezhihao.protostar.schema.RuntimeSchema;
|
import io.github.yezhihao.protostar.schema.RuntimeSchema;
|
||||||
|
|
||||||
import java.beans.BeanInfo;
|
|
||||||
import java.beans.IntrospectionException;
|
|
||||||
import java.beans.Introspector;
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schema加载策略
|
* RuntimeSchema加载策略
|
||||||
* @author yezhihao
|
* @author yezhihao
|
||||||
* home https://gitee.com/yezhihao/jt808-server
|
* home https://gitee.com/yezhihao/jt808-server
|
||||||
*/
|
*/
|
||||||
public abstract class LoadStrategy {
|
public abstract class LoadStrategy {
|
||||||
|
|
||||||
protected Map<Object, Map<Integer, Schema<?>>> typeIdMapping = new HashMap<>(64);
|
protected Map<Object, Map<Integer, RuntimeSchema<?>>> typeIdMapping = new HashMap<>(64);
|
||||||
|
|
||||||
public abstract <T> Map<Integer, Schema<T>> getSchema(Class<T> typeClass);
|
public abstract <T> Map<Integer, RuntimeSchema<T>> getRuntimeSchema(Class<T> typeClass);
|
||||||
|
|
||||||
public abstract <T> Schema<T> getSchema(Class<T> typeClass, Integer version);
|
public abstract <T> RuntimeSchema<T> getRuntimeSchema(Class<T> typeClass, Integer version);
|
||||||
|
|
||||||
public Schema getSchema(Object typeId, Integer version) {
|
public RuntimeSchema getRuntimeSchema(Object typeId, Integer version) {
|
||||||
Map<Integer, Schema<?>> schemaMap = typeIdMapping.get(typeId);
|
Map<Integer, RuntimeSchema<?>> schemaMap = typeIdMapping.get(typeId);
|
||||||
if (schemaMap == null)
|
if (schemaMap == null)
|
||||||
return null;
|
return null;
|
||||||
return schemaMap.get(version);
|
return schemaMap.get(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadSchema(Map<String, Map<Integer, Schema<?>>> root, Object typeId, Class<?> typeClass) {
|
protected void loadRuntimeSchema(Map<String, Map<Integer, RuntimeSchema<?>>> root, Object typeId, Class<?> typeClass) {
|
||||||
Map<Integer, Schema<?>> schemas = typeIdMapping.get(typeId);
|
Map<Integer, RuntimeSchema<?>> schemas = typeIdMapping.get(typeId);
|
||||||
if (schemas == null) {
|
if (schemas == null) {
|
||||||
schemas = loadSchema(root, typeClass);
|
schemas = loadRuntimeSchema(root, typeClass);
|
||||||
typeIdMapping.put(typeId, schemas);
|
typeIdMapping.put(typeId, schemas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<Integer, Schema<?>> loadSchema(Map<String, Map<Integer, Schema<?>>> root, Class<?> typeClass) {
|
protected Map<Integer, RuntimeSchema<?>> loadRuntimeSchema(Map<String, Map<Integer, RuntimeSchema<?>>> root, Class<?> typeClass) {
|
||||||
Map<Integer, Schema<?>> schemas = root.get(typeClass.getName());
|
Map<Integer, RuntimeSchema<?>> schemas = root.get(typeClass.getName());
|
||||||
//不支持循环引用
|
//不支持循环引用
|
||||||
if (schemas != null)
|
if (schemas != null)
|
||||||
return schemas;
|
return schemas;
|
||||||
|
|
||||||
List<PropertyDescriptor> properties = findFieldProperties(typeClass);
|
List<java.lang.reflect.Field> fs = findFields(typeClass);
|
||||||
if (properties.isEmpty())
|
if (fs.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
root.put(typeClass.getName(), schemas = new HashMap(4));
|
root.put(typeClass.getName(), schemas = new HashMap(4));
|
||||||
|
|
||||||
Map<Integer, List<BasicField>> multiVersionFields = findMultiVersionFields(root, properties);
|
Map<Integer, List<BasicField>> multiVersionFields = findMultiVersionFields(root, fs);
|
||||||
for (Map.Entry<Integer, List<BasicField>> entry : multiVersionFields.entrySet()) {
|
for (Map.Entry<Integer, List<BasicField>> entry : multiVersionFields.entrySet()) {
|
||||||
|
|
||||||
Integer version = entry.getKey();
|
Integer version = entry.getKey();
|
||||||
|
@ -62,79 +57,68 @@ public abstract class LoadStrategy {
|
||||||
BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]);
|
BasicField[] fields = fieldList.toArray(new BasicField[fieldList.size()]);
|
||||||
Arrays.sort(fields);
|
Arrays.sort(fields);
|
||||||
|
|
||||||
Schema schema = new RuntimeSchema(typeClass, version, fields);
|
RuntimeSchema schema = new RuntimeSchema(typeClass, version, fields);
|
||||||
schemas.put(version, schema);
|
schemas.put(version, schema);
|
||||||
}
|
}
|
||||||
return schemas;
|
return schemas;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<PropertyDescriptor> findFieldProperties(Class<?> typeClass) {
|
protected List<java.lang.reflect.Field> findFields(Class<?> typeClass) {
|
||||||
BeanInfo beanInfo;
|
java.lang.reflect.Field[] fs = typeClass.getDeclaredFields();
|
||||||
try {
|
|
||||||
beanInfo = Introspector.getBeanInfo(typeClass);
|
|
||||||
} catch (IntrospectionException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();
|
|
||||||
List<PropertyDescriptor> result = new ArrayList<>(properties.length);
|
|
||||||
|
|
||||||
for (PropertyDescriptor property : properties) {
|
List<java.lang.reflect.Field> result = new ArrayList<>(fs.length);
|
||||||
Method readMethod = property.getReadMethod();
|
|
||||||
|
|
||||||
if (readMethod != null) {
|
for (java.lang.reflect.Field f : fs) {
|
||||||
if (readMethod.isAnnotationPresent(Fs.class) || readMethod.isAnnotationPresent(Field.class)) {
|
if (f.isAnnotationPresent(Fs.class) || f.isAnnotationPresent(Field.class)) {
|
||||||
result.add(property);
|
result.add(f);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<Integer, List<BasicField>> findMultiVersionFields(Map<String, Map<Integer, Schema<?>>> root, List<PropertyDescriptor> properties) {
|
protected Map<Integer, List<BasicField>> findMultiVersionFields(Map<String, Map<Integer, RuntimeSchema<?>>> root, List<java.lang.reflect.Field> fs) {
|
||||||
Map<Integer, List<BasicField>> multiVersionFields = new TreeMap<Integer, List<BasicField>>() {
|
Map<Integer, List<BasicField>> multiVersionFields = new TreeMap<Integer, List<BasicField>>() {
|
||||||
@Override
|
@Override
|
||||||
public List<BasicField> get(Object key) {
|
public List<BasicField> get(Object key) {
|
||||||
List result = super.get(key);
|
List result = super.get(key);
|
||||||
if (result == null)
|
if (result == null)
|
||||||
super.put((Integer) key, result = new ArrayList<>(properties.size()));
|
super.put((Integer) key, result = new ArrayList<>(fs.size()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (PropertyDescriptor property : properties) {
|
for (java.lang.reflect.Field f : fs) {
|
||||||
Method readMethod = property.getReadMethod();
|
|
||||||
|
|
||||||
Field field = readMethod.getDeclaredAnnotation(Field.class);
|
Field field = f.getDeclaredAnnotation(Field.class);
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
fillField(root, multiVersionFields, property, field);
|
fillField(root, multiVersionFields, f, field);
|
||||||
} else {
|
} else {
|
||||||
Field[] fields = readMethod.getDeclaredAnnotation(Fs.class).value();
|
Field[] fields = f.getDeclaredAnnotation(Fs.class).value();
|
||||||
for (int i = 0; i < fields.length; i++)
|
for (int i = 0; i < fields.length; i++)
|
||||||
fillField(root, multiVersionFields, property, fields[i]);
|
fillField(root, multiVersionFields, f, fields[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return multiVersionFields;
|
return multiVersionFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fillField(Map<String, Map<Integer, Schema<?>>> root, Map<Integer, List<BasicField>> multiVersionFields, PropertyDescriptor propertyDescriptor, Field field) {
|
protected void fillField(Map<String, Map<Integer, RuntimeSchema<?>>> root, Map<Integer, List<BasicField>> multiVersionFields, java.lang.reflect.Field f, Field field) {
|
||||||
Class<?> typeClass = propertyDescriptor.getPropertyType();
|
Class<?> typeClass = f.getType();
|
||||||
Method readMethod = propertyDescriptor.getReadMethod();
|
|
||||||
|
|
||||||
BasicField value;
|
BasicField value;
|
||||||
int[] versions = field.version();
|
int[] versions = field.version();
|
||||||
|
|
||||||
if (field.type() == DataType.OBJ || field.type() == DataType.LIST) {
|
if (field.type() == DataType.OBJ || field.type() == DataType.LIST) {
|
||||||
if (Collection.class.isAssignableFrom(typeClass))
|
if (Collection.class.isAssignableFrom(typeClass))
|
||||||
typeClass = (Class<?>) ((ParameterizedType) readMethod.getGenericReturnType()).getActualTypeArguments()[0];
|
typeClass = (Class<?>) ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0];
|
||||||
loadSchema(root, typeClass);
|
loadRuntimeSchema(root, typeClass);
|
||||||
for (int ver : versions) {
|
for (int ver : versions) {
|
||||||
Map<Integer, Schema<?>> schemaMap = root.getOrDefault(typeClass.getName(), Collections.EMPTY_MAP);
|
Map<Integer, RuntimeSchema<?>> schemaMap = root.getOrDefault(typeClass.getName(), Collections.EMPTY_MAP);
|
||||||
Schema schema = schemaMap.get(ver);
|
RuntimeSchema schema = schemaMap.get(ver);
|
||||||
value = FieldFactory.create(field, propertyDescriptor, schema);
|
value = FieldFactory.create(field, f, schema);
|
||||||
multiVersionFields.get(ver).add(value);
|
multiVersionFields.get(ver).add(value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = FieldFactory.create(field, propertyDescriptor);
|
value = FieldFactory.create(field, f);
|
||||||
for (int ver : versions) {
|
for (int ver : versions) {
|
||||||
multiVersionFields.get(ver).add(value);
|
multiVersionFields.get(ver).add(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package io.github.yezhihao.protostar;
|
package io.github.yezhihao.protostar;
|
||||||
|
|
||||||
|
import io.github.yezhihao.protostar.schema.RuntimeSchema;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,15 +26,15 @@ public class ProtostarUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Schema getSchema(Object typeId, Integer version) {
|
public static RuntimeSchema getRuntimeSchema(Object typeId, Integer version) {
|
||||||
return LOAD_STRATEGY.getSchema(typeId, version);
|
return LOAD_STRATEGY.getRuntimeSchema(typeId, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Schema getSchema(Class<?> typeClass, Integer version) {
|
public static RuntimeSchema getRuntimeSchema(Class<?> typeClass, Integer version) {
|
||||||
return LOAD_STRATEGY.getSchema(typeClass, version);
|
return LOAD_STRATEGY.getRuntimeSchema(typeClass, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Map<Integer, Schema<T>> getSchema(Class<T> typeClass) {
|
public static <T> Map<Integer, RuntimeSchema<T>> getRuntimeSchema(Class<T> typeClass) {
|
||||||
return LOAD_STRATEGY.getSchema(typeClass);
|
return LOAD_STRATEGY.getRuntimeSchema(typeClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@ import java.lang.annotation.Target;
|
||||||
* @author yezhihao
|
* @author yezhihao
|
||||||
* home https://gitee.com/yezhihao/jt808-server
|
* home https://gitee.com/yezhihao/jt808-server
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.FIELD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Convert {
|
public @interface Convert {
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import java.lang.annotation.*;
|
||||||
* home https://gitee.com/yezhihao/jt808-server
|
* home https://gitee.com/yezhihao/jt808-server
|
||||||
*/
|
*/
|
||||||
@Repeatable(Fs.class)
|
@Repeatable(Fs.class)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.FIELD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Field {
|
public @interface Field {
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import java.lang.annotation.Target;
|
||||||
* @author yezhihao
|
* @author yezhihao
|
||||||
* home https://gitee.com/yezhihao/jt808-server
|
* home https://gitee.com/yezhihao/jt808-server
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.FIELD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Fs {
|
public @interface Fs {
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,6 @@ import io.netty.buffer.ByteBuf;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 固定长度的字段
|
* 固定长度的字段
|
||||||
* @author yezhihao
|
* @author yezhihao
|
||||||
|
@ -19,23 +16,21 @@ public abstract class BasicField<T> implements Comparable<BasicField<T>> {
|
||||||
|
|
||||||
protected final int index;
|
protected final int index;
|
||||||
protected final int length;
|
protected final int length;
|
||||||
protected final String desc;
|
|
||||||
protected final Method readMethod;
|
|
||||||
protected final Method writeMethod;
|
|
||||||
protected final PropertyDescriptor property;
|
|
||||||
protected final Field field;
|
protected final Field field;
|
||||||
|
protected final java.lang.reflect.Field f;
|
||||||
|
|
||||||
public BasicField(Field field, PropertyDescriptor property) {
|
public BasicField(Field field, java.lang.reflect.Field f) {
|
||||||
this.index = field.index();
|
this.index = field.index();
|
||||||
int length = field.length();
|
int length = field.length();
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
length = field.type().length;
|
length = field.type().length;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.desc = field.desc();
|
|
||||||
this.readMethod = property.getReadMethod();
|
|
||||||
this.writeMethod = property.getWriteMethod();
|
|
||||||
this.field = field;
|
this.field = field;
|
||||||
this.property = property;
|
this.f = f;
|
||||||
|
try {
|
||||||
|
f.setAccessible(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean readFrom(ByteBuf input, Object message) throws Exception;
|
public abstract boolean readFrom(ByteBuf input, Object message) throws Exception;
|
||||||
|
@ -62,13 +57,12 @@ public abstract class BasicField<T> implements Comparable<BasicField<T>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuilder sb = new StringBuilder(60);
|
final StringBuilder sb = new StringBuilder(50);
|
||||||
sb.append('{');
|
sb.append('{');
|
||||||
sb.append("index=").append(index);
|
sb.append("index=").append(index);
|
||||||
sb.append(", length=").append(length);
|
sb.append(", length=").append(length);
|
||||||
sb.append(", desc").append(desc);
|
sb.append(", desc").append(field.desc());
|
||||||
sb.append(", readMethod=").append(readMethod.getName());
|
sb.append(", field=").append(f.getName());
|
||||||
sb.append(", writeMethod=").append(writeMethod.getName());
|
|
||||||
sb.append('}');
|
sb.append('}');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package io.github.yezhihao.protostar.field;
|
package io.github.yezhihao.protostar.field;
|
||||||
|
|
||||||
|
import io.github.yezhihao.protostar.Schema;
|
||||||
import io.github.yezhihao.protostar.annotation.Field;
|
import io.github.yezhihao.protostar.annotation.Field;
|
||||||
|
import io.github.yezhihao.protostar.util.ByteBufUtils;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.github.yezhihao.protostar.Schema;
|
|
||||||
import io.github.yezhihao.protostar.util.ByteBufUtils;
|
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态长度的字段
|
* 动态长度的字段
|
||||||
|
@ -19,8 +17,8 @@ public class DynamicLengthField<T> extends BasicField<T> {
|
||||||
|
|
||||||
protected final int lengthSize;
|
protected final int lengthSize;
|
||||||
|
|
||||||
public DynamicLengthField(Field field, PropertyDescriptor property, Schema<T> schema) {
|
public DynamicLengthField(Field field, java.lang.reflect.Field f, Schema<T> schema) {
|
||||||
super(field, property);
|
super(field, f);
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
this.lengthSize = field.lengthSize();
|
this.lengthSize = field.lengthSize();
|
||||||
}
|
}
|
||||||
|
@ -30,12 +28,12 @@ public class DynamicLengthField<T> extends BasicField<T> {
|
||||||
if (!input.isReadable(length))
|
if (!input.isReadable(length))
|
||||||
return false;
|
return false;
|
||||||
Object value = schema.readFrom(input, length);
|
Object value = schema.readFrom(input, length);
|
||||||
writeMethod.invoke(message, value);
|
f.set(message, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(ByteBuf output, Object message) throws Exception {
|
public void writeTo(ByteBuf output, Object message) throws Exception {
|
||||||
Object value = readMethod.invoke(message);
|
Object value = f.get(message);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
int begin = output.writerIndex();
|
int begin = output.writerIndex();
|
||||||
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
|
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
|
||||||
|
@ -55,8 +53,8 @@ public class DynamicLengthField<T> extends BasicField<T> {
|
||||||
|
|
||||||
public static class Logger<T> extends DynamicLengthField<T> {
|
public static class Logger<T> extends DynamicLengthField<T> {
|
||||||
|
|
||||||
public Logger(Field field, PropertyDescriptor property, Schema<T> schema) {
|
public Logger(Field field, java.lang.reflect.Field f, Schema<T> schema) {
|
||||||
super(field, property, schema);
|
super(field, f, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
||||||
|
@ -66,18 +64,18 @@ public class DynamicLengthField<T> extends BasicField<T> {
|
||||||
if (!input.isReadable(length))
|
if (!input.isReadable(length))
|
||||||
return false;
|
return false;
|
||||||
Object value = schema.readFrom(input, length);
|
Object value = schema.readFrom(input, length);
|
||||||
writeMethod.invoke(message, value);
|
f.set(message, value);
|
||||||
|
|
||||||
int after = input.readerIndex();
|
int after = input.readerIndex();
|
||||||
String hex = ByteBufUtil.hexDump(input.slice(before, after - before));
|
String hex = ByteBufUtil.hexDump(input.slice(before, after - before));
|
||||||
println(this.index, this.desc, hex, value);
|
println(this.index, this.field.desc(), hex, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(ByteBuf output, Object message) throws Exception {
|
public void writeTo(ByteBuf output, Object message) throws Exception {
|
||||||
int before = output.writerIndex();
|
int before = output.writerIndex();
|
||||||
|
|
||||||
Object value = readMethod.invoke(message);
|
Object value = f.get(message);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
int begin = output.writerIndex();
|
int begin = output.writerIndex();
|
||||||
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
|
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
|
||||||
|
@ -88,7 +86,7 @@ public class DynamicLengthField<T> extends BasicField<T> {
|
||||||
|
|
||||||
int after = output.writerIndex();
|
int after = output.writerIndex();
|
||||||
String hex = ByteBufUtil.hexDump(output.slice(before, after - before));
|
String hex = ByteBufUtil.hexDump(output.slice(before, after - before));
|
||||||
println(this.index, this.desc, hex, value);
|
println(this.index, this.field.desc(), hex, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,9 @@
|
||||||
package io.github.yezhihao.protostar.field;
|
package io.github.yezhihao.protostar.field;
|
||||||
|
|
||||||
|
import io.github.yezhihao.protostar.Schema;
|
||||||
import io.github.yezhihao.protostar.annotation.Field;
|
import io.github.yezhihao.protostar.annotation.Field;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.github.yezhihao.protostar.Schema;
|
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 原子域
|
* 原子域
|
||||||
|
@ -16,51 +14,51 @@ public class FixedField<T> extends BasicField<T> {
|
||||||
|
|
||||||
protected final Schema<T> schema;
|
protected final Schema<T> schema;
|
||||||
|
|
||||||
public FixedField(Field field, PropertyDescriptor property, Schema<T> schema) {
|
public FixedField(Field field, java.lang.reflect.Field f, Schema<T> schema) {
|
||||||
super(field, property);
|
super(field, f);
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
||||||
Object value = schema.readFrom(input);
|
Object value = schema.readFrom(input);
|
||||||
writeMethod.invoke(message, value);
|
f.set(message, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(ByteBuf output, Object message) throws Exception {
|
public void writeTo(ByteBuf output, Object message) throws Exception {
|
||||||
Object value = readMethod.invoke(message);
|
Object value = f.get(message);
|
||||||
if (value != null)
|
if (value != null)
|
||||||
schema.writeTo(output, (T) value);
|
schema.writeTo(output, (T) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Logger<T> extends FixedField<T> {
|
public static class Logger<T> extends FixedField<T> {
|
||||||
|
|
||||||
public Logger(Field field, PropertyDescriptor property, Schema<T> schema) {
|
public Logger(Field field, java.lang.reflect.Field f, Schema<T> schema) {
|
||||||
super(field, property, schema);
|
super(field, f, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
||||||
int before = input.readerIndex();
|
int before = input.readerIndex();
|
||||||
|
|
||||||
Object value = schema.readFrom(input);
|
Object value = schema.readFrom(input);
|
||||||
writeMethod.invoke(message, value);
|
f.set(message, value);
|
||||||
|
|
||||||
int after = input.readerIndex();
|
int after = input.readerIndex();
|
||||||
String hex = ByteBufUtil.hexDump(input.slice(before, after - before));
|
String hex = ByteBufUtil.hexDump(input.slice(before, after - before));
|
||||||
println(this.index, this.desc, hex, value);
|
println(this.index, this.field.desc(), hex, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(ByteBuf output, Object message) throws Exception {
|
public void writeTo(ByteBuf output, Object message) throws Exception {
|
||||||
int before = output.writerIndex();
|
int before = output.writerIndex();
|
||||||
|
|
||||||
Object value = readMethod.invoke(message);
|
Object value = f.get(message);
|
||||||
if (value != null)
|
if (value != null)
|
||||||
schema.writeTo(output, (T) value);
|
schema.writeTo(output, (T) value);
|
||||||
|
|
||||||
int after = output.writerIndex();
|
int after = output.writerIndex();
|
||||||
String hex = ByteBufUtil.hexDump(output.slice(before, after - before));
|
String hex = ByteBufUtil.hexDump(output.slice(before, after - before));
|
||||||
println(this.index, this.desc, hex, value);
|
println(this.index, this.field.desc(), hex, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,9 @@
|
||||||
package io.github.yezhihao.protostar.field;
|
package io.github.yezhihao.protostar.field;
|
||||||
|
|
||||||
|
import io.github.yezhihao.protostar.Schema;
|
||||||
import io.github.yezhihao.protostar.annotation.Field;
|
import io.github.yezhihao.protostar.annotation.Field;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.github.yezhihao.protostar.Schema;
|
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 固定长度的字段
|
* 固定长度的字段
|
||||||
|
@ -16,51 +14,51 @@ public class FixedLengthField<T> extends BasicField<T> {
|
||||||
|
|
||||||
protected final Schema<T> schema;
|
protected final Schema<T> schema;
|
||||||
|
|
||||||
public FixedLengthField(Field field, PropertyDescriptor property, Schema<T> schema) {
|
public FixedLengthField(Field field, java.lang.reflect.Field f, Schema<T> schema) {
|
||||||
super(field, property);
|
super(field, f);
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
||||||
Object value = schema.readFrom(input, length);
|
Object value = schema.readFrom(input, length);
|
||||||
writeMethod.invoke(message, value);
|
f.set(message, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(ByteBuf output, Object message) throws Exception {
|
public void writeTo(ByteBuf output, Object message) throws Exception {
|
||||||
Object value = readMethod.invoke(message);
|
Object value = f.get(message);
|
||||||
if (value != null)
|
if (value != null)
|
||||||
schema.writeTo(output, length, (T) value);
|
schema.writeTo(output, length, (T) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Logger<T> extends FixedLengthField<T> {
|
public static class Logger<T> extends FixedLengthField<T> {
|
||||||
|
|
||||||
public Logger(Field field, PropertyDescriptor property, Schema<T> schema) {
|
public Logger(Field field, java.lang.reflect.Field f, Schema<T> schema) {
|
||||||
super(field, property, schema);
|
super(field, f, schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
public boolean readFrom(ByteBuf input, Object message) throws Exception {
|
||||||
int before = input.readerIndex();
|
int before = input.readerIndex();
|
||||||
|
|
||||||
Object value = schema.readFrom(input, length);
|
Object value = schema.readFrom(input, length);
|
||||||
writeMethod.invoke(message, value);
|
f.set(message, value);
|
||||||
|
|
||||||
int after = input.readerIndex();
|
int after = input.readerIndex();
|
||||||
String hex = ByteBufUtil.hexDump(input.slice(before, after - before));
|
String hex = ByteBufUtil.hexDump(input.slice(before, after - before));
|
||||||
println(this.index, this.desc, hex, value);
|
println(this.index, this.field.desc(), hex, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(ByteBuf output, Object message) throws Exception {
|
public void writeTo(ByteBuf output, Object message) throws Exception {
|
||||||
int before = output.writerIndex();
|
int before = output.writerIndex();
|
||||||
|
|
||||||
Object value = readMethod.invoke(message);
|
Object value = f.get(message);
|
||||||
if (value != null)
|
if (value != null)
|
||||||
schema.writeTo(output, length, (T) value);
|
schema.writeTo(output, length, (T) value);
|
||||||
|
|
||||||
int after = output.writerIndex();
|
int after = output.writerIndex();
|
||||||
String hex = ByteBufUtil.hexDump(output.slice(before, after - before));
|
String hex = ByteBufUtil.hexDump(output.slice(before, after - before));
|
||||||
println(this.index, this.desc, hex, value);
|
println(this.index, this.field.desc(), hex, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,6 +34,29 @@ public class RuntimeSchema<T> implements Schema<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T newInstance() {
|
||||||
|
try {
|
||||||
|
return constructor.newInstance((Object[]) null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("newInstance failed " + typeClass.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T mergeFrom(ByteBuf input, T result) {
|
||||||
|
BasicField field = null;
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < fields.length; i++) {
|
||||||
|
if (!input.isReadable())
|
||||||
|
break;
|
||||||
|
field = fields[i];
|
||||||
|
field.readFrom(input, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Read failed " + typeClass.getName() + field, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public T readFrom(ByteBuf input) {
|
public T readFrom(ByteBuf input) {
|
||||||
BasicField field = null;
|
BasicField field = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -5,7 +5,9 @@ import io.github.yezhihao.protostar.annotation.Field;
|
||||||
|
|
||||||
public class Attr1 {
|
public class Attr1 {
|
||||||
|
|
||||||
|
@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称")
|
||||||
private String name;
|
private String name;
|
||||||
|
@Field(index = 1, type = DataType.WORD, desc = "ID")
|
||||||
private int id;
|
private int id;
|
||||||
|
|
||||||
public Attr1() {
|
public Attr1() {
|
||||||
|
@ -16,7 +18,6 @@ public class Attr1 {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称")
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +26,6 @@ public class Attr1 {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Field(index = 1, type = DataType.WORD, desc = "ID")
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,9 @@ package io.github.yezhihao.protostar.convert;
|
||||||
|
|
||||||
import io.github.yezhihao.protostar.DataType;
|
import io.github.yezhihao.protostar.DataType;
|
||||||
import io.github.yezhihao.protostar.ProtostarUtil;
|
import io.github.yezhihao.protostar.ProtostarUtil;
|
||||||
import io.github.yezhihao.protostar.Schema;
|
|
||||||
import io.github.yezhihao.protostar.annotation.Convert;
|
import io.github.yezhihao.protostar.annotation.Convert;
|
||||||
import io.github.yezhihao.protostar.annotation.Field;
|
import io.github.yezhihao.protostar.annotation.Field;
|
||||||
import io.github.yezhihao.protostar.annotation.Fs;
|
import io.github.yezhihao.protostar.schema.RuntimeSchema;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
@ -17,9 +16,9 @@ import java.util.TreeMap;
|
||||||
public class Test {
|
public class Test {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Map<Integer, Schema<Foo>> multiVersionSchema = ProtostarUtil.getSchema(Foo.class);
|
Map<Integer, RuntimeSchema<Foo>> multiVersionSchema = ProtostarUtil.getRuntimeSchema(Foo.class);
|
||||||
Schema<Foo> schema_v0 = multiVersionSchema.get(0);
|
RuntimeSchema<Foo> schema_v0 = multiVersionSchema.get(0);
|
||||||
Schema<Foo> schema_v1 = multiVersionSchema.get(1);
|
RuntimeSchema<Foo> schema_v1 = multiVersionSchema.get(1);
|
||||||
|
|
||||||
ByteBuf buffer = Unpooled.buffer(32);
|
ByteBuf buffer = Unpooled.buffer(32);
|
||||||
schema_v0.writeTo(buffer, foo());
|
schema_v0.writeTo(buffer, foo());
|
||||||
|
@ -56,13 +55,18 @@ public class Test {
|
||||||
|
|
||||||
public static class Foo {
|
public static class Foo {
|
||||||
|
|
||||||
|
@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称", version = 0)
|
||||||
|
@Field(index = 0, type = DataType.STRING, length = 10, desc = "名称", version = 1)
|
||||||
private String name;
|
private String name;
|
||||||
|
@Field(index = 1, type = DataType.WORD, desc = "ID", version = 0)
|
||||||
|
@Field(index = 1, type = DataType.DWORD, desc = "ID", version = 1)
|
||||||
private int id;
|
private int id;
|
||||||
|
@Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1})
|
||||||
private LocalDateTime dateTime;
|
private LocalDateTime dateTime;
|
||||||
|
@Convert(converter = AttributeConverter.class)
|
||||||
|
@Field(index = 4, type = DataType.MAP, desc = "属性", version = {0, 1})
|
||||||
private Map<Integer, Object> attributes;
|
private Map<Integer, Object> attributes;
|
||||||
|
|
||||||
@Fs({@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称", version = 0),
|
|
||||||
@Field(index = 0, type = DataType.STRING, length = 10, desc = "名称", version = 1)})
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -71,8 +75,6 @@ public class Test {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Fs({@Field(index = 1, type = DataType.WORD, desc = "ID", version = 0),
|
|
||||||
@Field(index = 1, type = DataType.DWORD, desc = "ID", version = 1)})
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +83,6 @@ public class Test {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1})
|
|
||||||
public LocalDateTime getDateTime() {
|
public LocalDateTime getDateTime() {
|
||||||
return dateTime;
|
return dateTime;
|
||||||
}
|
}
|
||||||
|
@ -90,8 +91,6 @@ public class Test {
|
||||||
this.dateTime = dateTime;
|
this.dateTime = dateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Convert(converter = AttributeConverter.class)
|
|
||||||
@Field(index = 4, type = DataType.MAP, desc = "属性", version = {0, 1})
|
|
||||||
public Map<Integer, Object> getAttributes() {
|
public Map<Integer, Object> getAttributes() {
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ package io.github.yezhihao.protostar.multiversion;
|
||||||
|
|
||||||
import io.github.yezhihao.protostar.DataType;
|
import io.github.yezhihao.protostar.DataType;
|
||||||
import io.github.yezhihao.protostar.ProtostarUtil;
|
import io.github.yezhihao.protostar.ProtostarUtil;
|
||||||
import io.github.yezhihao.protostar.Schema;
|
|
||||||
import io.github.yezhihao.protostar.annotation.Field;
|
import io.github.yezhihao.protostar.annotation.Field;
|
||||||
|
import io.github.yezhihao.protostar.schema.RuntimeSchema;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
@ -14,9 +14,9 @@ import java.util.Map;
|
||||||
public class Test {
|
public class Test {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Map<Integer, Schema<Foo>> multiVersionSchema = ProtostarUtil.getSchema(Foo.class);
|
Map<Integer, RuntimeSchema<Foo>> multiVersionSchema = ProtostarUtil.getRuntimeSchema(Foo.class);
|
||||||
Schema<Foo> schema_v0 = multiVersionSchema.get(0);
|
RuntimeSchema<Foo> schema_v0 = multiVersionSchema.get(0);
|
||||||
Schema<Foo> schema_v1 = multiVersionSchema.get(1);
|
RuntimeSchema<Foo> schema_v1 = multiVersionSchema.get(1);
|
||||||
|
|
||||||
ByteBuf buffer = Unpooled.buffer(32);
|
ByteBuf buffer = Unpooled.buffer(32);
|
||||||
Foo foo = foo();
|
Foo foo = foo();
|
||||||
|
@ -48,12 +48,15 @@ public class Test {
|
||||||
|
|
||||||
public static class Foo {
|
public static class Foo {
|
||||||
|
|
||||||
private String name;
|
|
||||||
private int id;
|
|
||||||
private LocalDateTime dateTime;
|
|
||||||
|
|
||||||
@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称", version = 0)
|
@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称", version = 0)
|
||||||
@Field(index = 0, type = DataType.STRING, length = 10, desc = "名称", version = 1)
|
@Field(index = 0, type = DataType.STRING, length = 10, desc = "名称", version = 1)
|
||||||
|
private String name;
|
||||||
|
@Field(index = 1, type = DataType.WORD, desc = "ID", version = 0)
|
||||||
|
@Field(index = 1, type = DataType.DWORD, desc = "ID", version = 1)
|
||||||
|
private int id;
|
||||||
|
@Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1})
|
||||||
|
private LocalDateTime dateTime;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -62,8 +65,6 @@ public class Test {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Field(index = 1, type = DataType.WORD, desc = "ID", version = 0)
|
|
||||||
@Field(index = 1, type = DataType.DWORD, desc = "ID", version = 1)
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +73,6 @@ public class Test {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1})
|
|
||||||
public LocalDateTime getDateTime() {
|
public LocalDateTime getDateTime() {
|
||||||
return dateTime;
|
return dateTime;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ package io.github.yezhihao.protostar.simple;
|
||||||
import io.github.yezhihao.protostar.DataType;
|
import io.github.yezhihao.protostar.DataType;
|
||||||
import io.github.yezhihao.protostar.FieldFactory;
|
import io.github.yezhihao.protostar.FieldFactory;
|
||||||
import io.github.yezhihao.protostar.ProtostarUtil;
|
import io.github.yezhihao.protostar.ProtostarUtil;
|
||||||
import io.github.yezhihao.protostar.Schema;
|
|
||||||
import io.github.yezhihao.protostar.annotation.Field;
|
import io.github.yezhihao.protostar.annotation.Field;
|
||||||
|
import io.github.yezhihao.protostar.schema.RuntimeSchema;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
@ -17,16 +17,24 @@ public class Test {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
FieldFactory.EXPLAIN = true;
|
FieldFactory.EXPLAIN = true;
|
||||||
|
|
||||||
Map<Integer, Schema<Foo>> multiVersionSchema = ProtostarUtil.getSchema(Foo.class);
|
Map<Integer, RuntimeSchema<Foo>> bodySchemas = ProtostarUtil.getRuntimeSchema(Foo.class);
|
||||||
Schema<Foo> schema = multiVersionSchema.get(0);
|
RuntimeSchema<Foo> bodySchema = bodySchemas.get(0);
|
||||||
|
|
||||||
|
Map<Integer, RuntimeSchema<BaseDO>> headSchemas = ProtostarUtil.getRuntimeSchema(BaseDO.class);
|
||||||
|
RuntimeSchema<BaseDO> headSchema = headSchemas.get(0);
|
||||||
|
|
||||||
ByteBuf buffer = Unpooled.buffer(32);
|
ByteBuf buffer = Unpooled.buffer(32);
|
||||||
Foo foo = foo();
|
Foo foo = foo();
|
||||||
schema.writeTo(buffer, foo);
|
headSchema.writeTo(buffer, foo);
|
||||||
|
bodySchema.writeTo(buffer, foo);
|
||||||
|
|
||||||
String hex = ByteBufUtil.hexDump(buffer);
|
String hex = ByteBufUtil.hexDump(buffer);
|
||||||
System.out.println(hex);
|
System.out.println(hex);
|
||||||
|
|
||||||
foo = schema.readFrom(buffer);
|
|
||||||
|
Foo foo1 = new Foo();
|
||||||
|
headSchema.mergeFrom(buffer, foo1);
|
||||||
|
bodySchema.mergeFrom(buffer, foo1);
|
||||||
System.out.println(foo);
|
System.out.println(foo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,16 +43,45 @@ public class Test {
|
||||||
foo.setName("张三");
|
foo.setName("张三");
|
||||||
foo.setId(128);
|
foo.setId(128);
|
||||||
foo.setDateTime(LocalDateTime.of(2020, 7, 7, 19, 23, 59));
|
foo.setDateTime(LocalDateTime.of(2020, 7, 7, 19, 23, 59));
|
||||||
|
|
||||||
|
foo.setType(1);
|
||||||
|
foo.setClientId("123qwe");
|
||||||
return foo;
|
return foo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Foo {
|
public static class BaseDO {
|
||||||
|
|
||||||
private String name;
|
@Field(index = 0, type = DataType.WORD, desc = "ID")
|
||||||
private int id;
|
protected int type;
|
||||||
private LocalDateTime dateTime;
|
@Field(index = 1, type = DataType.STRING, length = 20, desc = "名称")
|
||||||
|
protected String clientId;
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientId() {
|
||||||
|
return clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientId(String clientId) {
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Foo extends BaseDO {
|
||||||
|
|
||||||
@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称")
|
@Field(index = 0, type = DataType.STRING, lengthSize = 1, desc = "名称")
|
||||||
|
private String name;
|
||||||
|
@Field(index = 1, type = DataType.WORD, desc = "ID")
|
||||||
|
private int id;
|
||||||
|
@Field(index = 3, type = DataType.BCD8421, desc = "日期")
|
||||||
|
private LocalDateTime dateTime;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +90,6 @@ public class Test {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Field(index = 1, type = DataType.WORD, desc = "ID")
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +98,6 @@ public class Test {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Field(index = 3, type = DataType.BCD8421, desc = "日期")
|
|
||||||
public LocalDateTime getDateTime() {
|
public LocalDateTime getDateTime() {
|
||||||
return dateTime;
|
return dateTime;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +109,9 @@ public class Test {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuilder sb = new StringBuilder("Foo{");
|
final StringBuilder sb = new StringBuilder("Foo{");
|
||||||
sb.append("name='").append(name).append('\'');
|
sb.append("type=").append(type);
|
||||||
|
sb.append(", clientId='").append(clientId).append('\'');
|
||||||
|
sb.append(", name='").append(name).append('\'');
|
||||||
sb.append(", id=").append(id);
|
sb.append(", id=").append(id);
|
||||||
sb.append(", dateTime=").append(dateTime);
|
sb.append(", dateTime=").append(dateTime);
|
||||||
sb.append('}');
|
sb.append('}');
|
||||||
|
|
Loading…
Reference in New Issue