deployed 2.0.2.RELEASE,增强MapConverter,简化用户端实现。合并Convert到Field(为支持多版本Convert)

master
剑器近 2021-07-08 15:40:34 +08:00
parent 75969aa5e6
commit a2f5abb6f4
9 changed files with 66 additions and 110 deletions

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.yezhihao</groupId>
<artifactId>protostar</artifactId>
<version>2.0.1.RELEASE</version>
<version>2.0.2.RELEASE</version>
<packaging>jar</packaging>
<name>Protostar</name>

View File

@ -7,25 +7,25 @@ package io.github.yezhihao.protostar;
*/
public enum DataType {
//无符号单字节整型(字节, 8位
/** 无符号单字节整型(8位) */
BYTE(1),
//无符号双字节整型字节16位
/** 无符号双字节整型(16位) */
WORD(2),
//无符号四字节整型字节32位
/** 无符号四字节整型(32位) */
DWORD(4),
//无符号八字节整型字节64位
/** 无符号八字节整型(64位) */
QWORD(8),
//N字节字节数组
/** 字节数组 */
BYTES(-1),
//N字节BCD8421码
/** BCD8421码 */
BCD8421(-1),
//字符串,若无数据置空
/** 字符串 */
STRING(-1),
//对象
/** 对象 */
OBJ(-1),
//列表
/** 列表 */
LIST(-1),
//字典
/** 字典 */
MAP(-1);
public int length;

View File

@ -1,14 +1,11 @@
package io.github.yezhihao.protostar;
import io.github.yezhihao.protostar.annotation.Convert;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.field.BasicField;
import io.github.yezhihao.protostar.field.DynamicLengthField;
import io.github.yezhihao.protostar.field.FixedField;
import io.github.yezhihao.protostar.field.FixedLengthField;
import io.github.yezhihao.protostar.schema.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.time.LocalDateTime;
@ -19,7 +16,7 @@ import java.time.LocalDateTime;
* home https://gitee.com/yezhihao/jt808-server
*/
public abstract class FieldFactory {
protected static Logger log = LoggerFactory.getLogger(FieldFactory.class.getSimpleName());
public static boolean EXPLAIN = false;
public static BasicField create(Field field, java.lang.reflect.Field f) {
@ -59,19 +56,16 @@ public abstract class FieldFactory {
fieldSchema = StringSchema.Chars.getInstance(field.pad(), field.charset());
break;
case OBJ:
if (schema != null) {
if (schema != null)
fieldSchema = ObjectSchema.getInstance(schema);
} else {
Convert convert = f.getAnnotation(Convert.class);
fieldSchema = ConvertSchema.getInstance(convert.converter());
}
else
fieldSchema = ConvertSchema.getInstance(field.converter());
break;
case LIST:
fieldSchema = CollectionSchema.getInstance(schema);
break;
case MAP:
Convert convert = f.getAnnotation(Convert.class);
fieldSchema = ConvertSchema.getInstance(convert.converter());
fieldSchema = ConvertSchema.getInstance(field.converter());
break;
default:
throw new RuntimeException("不支持的类型转换");

View File

@ -1,21 +0,0 @@
package io.github.yezhihao.protostar.annotation;
import io.github.yezhihao.protostar.converter.Converter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author yezhihao
* home https://gitee.com/yezhihao/jt808-server
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Convert {
Class<? extends Converter> converter();
}

View File

@ -1,6 +1,7 @@
package io.github.yezhihao.protostar.annotation;
import io.github.yezhihao.protostar.DataType;
import io.github.yezhihao.protostar.converter.Converter;
import java.lang.annotation.*;
@ -23,9 +24,11 @@ public @interface Field {
String charset() default "GBK";
byte pad() default 0x00;
byte pad() default 0;
String desc() default "";
int[] version() default {-1, 0, 1};
Class<? extends Converter> converter() default Converter.class;
}

View File

@ -1,12 +1,18 @@
package io.github.yezhihao.protostar.converter;
import io.github.yezhihao.protostar.PrepareLoadStrategy;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.util.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.TreeMap;
public abstract class MapConverter<K, V> implements Converter<Map<K, V>> {
public abstract class MapConverter<K, V> extends PrepareLoadStrategy implements Converter<Map<K, V>> {
private final Logger log = LoggerFactory.getLogger(this.getClass().getSimpleName());
protected abstract K readKey(ByteBuf input);
@ -14,24 +20,31 @@ public abstract class MapConverter<K, V> implements Converter<Map<K, V>> {
protected abstract int valueSize();
protected abstract V convert(K key, ByteBuf input);
protected abstract void convert(K key, ByteBuf output, V value);
@Override
public Map<K, V> convert(ByteBuf input) {
if (!input.isReadable())
return null;
Map<K, V> map = new TreeMap<>();
do {
K id = readKey(input);
K key = readKey(input);
int len = ByteBufUtils.readInt(input, valueSize());
Object value = convert(id, input.readSlice(len));
map.put(id, (V) value);
Object value = readValue(key, input.readSlice(len));
map.put(key, (V) value);
} while (input.isReadable());
return map;
}
public Object readValue(K key, ByteBuf input) {
if (!input.isReadable())
return null;
Schema schema = getSchema(key);
if (schema != null)
return schema.readFrom(input);
byte[] bytes = new byte[input.readableBytes()];
input.readBytes(bytes);
return bytes;
}
@Override
public void convert(ByteBuf output, Map<K, V> map) {
@ -40,14 +53,22 @@ public abstract class MapConverter<K, V> implements Converter<Map<K, V>> {
for (Map.Entry<K, V> entry : map.entrySet()) {
K key = entry.getKey();
V value = entry.getValue();
writeKey(output, key);
int valueSize = valueSize();
writeValue(key, output, value);
}
}
public void writeValue(K key, ByteBuf output, Object value) {
Schema schema = getSchema(key);
if (schema != null) {
int lengthSize = valueSize();
int begin = output.writerIndex();
output.writeBytes(ByteBufUtils.BLOCKS[valueSize]);
convert(key, output, value);
int len = output.writerIndex() - begin - valueSize;
ByteBufUtils.setInt(output, valueSize, begin, len);
output.writeBytes(ByteBufUtils.BLOCKS[lengthSize]);
schema.writeTo(output, value);
int length = output.writerIndex() - begin - lengthSize;
ByteBufUtils.setInt(output, lengthSize, begin, length);
} else {
log.warn("未注册的信息:ID[{}], VALUE[{}]", key, value);
}
}
}

View File

@ -1,40 +1,21 @@
package io.github.yezhihao.protostar.convert;
import io.github.yezhihao.protostar.IdStrategy;
import io.github.yezhihao.protostar.Schema;
import io.github.yezhihao.protostar.PrepareLoadStrategy;
import io.github.yezhihao.protostar.converter.MapConverter;
import io.github.yezhihao.protostar.schema.NumberSchema;
import io.github.yezhihao.protostar.schema.StringSchema;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AttributeConverter extends MapConverter<Integer, Object> {
private static final Logger log = LoggerFactory.getLogger(AttributeConverter.class);
private static final IdStrategy INSTANCE = AttributeType.INSTANCE;
@Override
public Object convert(Integer key, ByteBuf input) {
if (!input.isReadable())
return null;
Schema schema = INSTANCE.getSchema(key);
if (schema != null)
return INSTANCE.readFrom(key, input);
byte[] bytes = new byte[input.readableBytes()];
input.readBytes(bytes);
log.warn("未识别的附加信息ID[{}], HEX[{}]", key, ByteBufUtil.hexDump(bytes));
return bytes;
}
protected void addSchemas(PrepareLoadStrategy schemaRegistry) {
schemaRegistry
.addSchema(1, NumberSchema.Int32.INSTANCE)
.addSchema(2, StringSchema.Chars.getInstance((byte) 0, "GBK"))
@Override
public void convert(Integer key, ByteBuf output, Object value) {
Schema schema = INSTANCE.getSchema(key);
if (schema != null) {
schema.writeTo(output, value);
} else {
log.warn("未注册的附加信息ID[{}], Value[{}]", key, value);
}
.addSchema(3, Attr1.class)
.addSchema(4, Attr2.Schema.INSTANCE);
}
@Override

View File

@ -1,21 +0,0 @@
package io.github.yezhihao.protostar.convert;
import io.github.yezhihao.protostar.IdStrategy;
import io.github.yezhihao.protostar.PrepareLoadStrategy;
import io.github.yezhihao.protostar.schema.NumberSchema;
import io.github.yezhihao.protostar.schema.StringSchema;
public class AttributeType extends PrepareLoadStrategy {
public static final IdStrategy INSTANCE = new AttributeType();
@Override
protected void addSchemas(PrepareLoadStrategy schemaRegistry) {
schemaRegistry
.addSchema(1, NumberSchema.Int32.INSTANCE)
.addSchema(2, StringSchema.Chars.getInstance((byte) 0, "GBK"))
.addSchema(3, Attr1.class)
.addSchema(4, Attr2.Schema.INSTANCE);
}
}

View File

@ -2,7 +2,6 @@ package io.github.yezhihao.protostar.convert;
import io.github.yezhihao.protostar.DataType;
import io.github.yezhihao.protostar.ProtostarUtil;
import io.github.yezhihao.protostar.annotation.Convert;
import io.github.yezhihao.protostar.annotation.Field;
import io.github.yezhihao.protostar.schema.RuntimeSchema;
import io.netty.buffer.ByteBuf;
@ -63,8 +62,8 @@ public class Test {
private int id;
@Field(index = 3, type = DataType.BCD8421, desc = "日期", version = {0, 1})
private LocalDateTime dateTime;
@Convert(converter = AttributeConverter.class)
@Field(index = 4, type = DataType.MAP, desc = "属性", version = {0, 1})
@Field(index = 4, type = DataType.MAP, desc = "属性", version = 0, converter = AttributeConverter.class)
@Field(index = 4, type = DataType.MAP, desc = "属性", version = 1, converter = AttributeConverterV2.class)
private Map<Integer, Object> attributes;
public String getName() {