deployed 2.0.2.RELEASE,增强MapConverter,简化用户端实现。合并Convert到Field(为支持多版本Convert)
parent
75969aa5e6
commit
a2f5abb6f4
2
pom.xml
2
pom.xml
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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("不支持的类型转换");
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue