package com.safeluck.aykj.message;
|
|
import android.util.Log;
|
|
import com.safeluck.aykj.annotation.AnnotationRegister;
|
import com.safeluck.aykj.annotation.FromEnd;
|
import com.safeluck.aykj.annotation.Length;
|
import com.safeluck.aykj.annotation.Order;
|
import com.safeluck.aykj.decoder.IMessageCoder;
|
import com.safeluck.aykj.utils.BytesUtils;
|
|
import java.lang.annotation.Annotation;
|
import java.lang.reflect.Field;
|
import java.lang.reflect.Modifier;
|
import java.util.ArrayList;
|
import java.util.Collections;
|
import java.util.Comparator;
|
import java.util.HashMap;
|
import java.util.List;
|
|
import io.netty.util.internal.PlatformDependent;
|
|
@SuppressWarnings("Since15")
|
public class BinMessageBase {
|
|
static short m_messageNo;
|
protected synchronized short getMessageNo()
|
{
|
m_messageNo++;
|
if(m_messageNo>=Short.MAX_VALUE-1)
|
{
|
m_messageNo = 0;
|
}
|
return m_messageNo;
|
}
|
|
static HashMap<Class,FieldDefine[]> fieldDefines = new HashMap<>();
|
|
protected List<String> disabledFields = new ArrayList<>();
|
|
public void parse(String hex)
|
{
|
try {
|
FieldDefine[] fields = this.getFieldDefines();
|
|
int total = hex.length();
|
int used = 0;
|
int dynamic_len_field_count = 0;
|
int relative_len_field_count = 0;
|
|
//如果有为动态长度的,计算出长度
|
for (FieldDefine fieldDefine : fields) {
|
if (this.disabledFields.contains(fieldDefine.field.getName())) {
|
continue;
|
}
|
//计算依赖长度字段数量
|
if (fieldDefine.relativeLengthField != null) {
|
relative_len_field_count++;
|
}
|
if (fieldDefine.relativeLengthField == null && fieldDefine.getFieldLen() == 0) {
|
dynamic_len_field_count++;
|
}
|
//动态长度,去掉其他所有字段的长度,剩余的为此字段长度
|
if (fieldDefine.getFieldLen() > 0) {
|
// System.out.println(fieldDefine.field.getName() + "长度=" + fieldDefine.getFieldLen() * 2);
|
used += (fieldDefine.getFieldLen() * 2);
|
}
|
|
}
|
if (dynamic_len_field_count > 1) {
|
buildException("动态长度字段只能有一个");
|
}
|
if (dynamic_len_field_count > 0 && relative_len_field_count > 0) {
|
buildException("动态长度字段和依赖长度字段只能有一个");
|
}
|
int dynamic_len = (total - used);
|
|
int start = 0;
|
for (FieldDefine fieldDefine : fields) {
|
if (this.disabledFields.contains(fieldDefine.field.getName())) {
|
continue;
|
}
|
//解析依赖长度
|
if (fieldDefine.relativeLengthField != null) {
|
try {
|
Field lengthField = this.getClass().getField(fieldDefine.length.lengthField());
|
int len = (int) lengthField.get(this);
|
System.out.println(fieldDefine.field.getName() + ":依赖长度=" + len);
|
|
fieldDefine.setFieldLen(len);
|
;
|
} catch (Exception e) {
|
buildException(e.getMessage());
|
}
|
}
|
int str_hex_len = fieldDefine.getFieldLen() * 2;
|
if (str_hex_len <= 0) {
|
str_hex_len = dynamic_len;
|
}
|
String field_hex = null;
|
Object value = null;
|
if (fieldDefine.from_end_index >= 0) {
|
field_hex = hex.substring(hex.length() - str_hex_len - fieldDefine.from_end_index, hex.length() - fieldDefine.from_end_index);
|
value = fieldDefine.coder.decode(field_hex);
|
} else {
|
field_hex = hex.substring(start, start + str_hex_len);
|
start += str_hex_len;
|
value = fieldDefine.coder.decode(field_hex);
|
}
|
try {
|
fieldDefine.field.set(this, value);
|
// Object val = fieldDefine.field.get(this);
|
// System.out.println(fieldDefine.field.getName()+":get="+val);
|
|
} catch (IllegalAccessException e) {
|
this.buildException(e.getMessage());
|
}
|
}
|
}
|
catch (ParseException ex)
|
{
|
throw ex;
|
}
|
catch (Exception ex)
|
{
|
this.buildException(ex.getMessage());
|
}
|
}
|
|
public void registerDisableField(String field)
|
{
|
if(!this.disabledFields.contains(field)) {
|
this.disabledFields.add(field);
|
}
|
}
|
public void removeDisableField(String field)
|
{
|
this.disabledFields.remove(field);
|
}
|
|
|
protected void buildException(String error)
|
{
|
throw new ParseException(error,this);
|
}
|
|
public byte[] toBytes()
|
{
|
String hex = this.toString();
|
|
return BytesUtils.hexStringToBytes(hex);
|
|
}
|
|
@Override
|
public String toString()
|
{
|
StringBuilder sb = new StringBuilder();
|
FieldDefine[] fields = this.getFieldDefines();
|
//写动态长度字段长度
|
for (FieldDefine fieldDefine:fields) {
|
|
if (this.disabledFields.contains(fieldDefine.field.getName())) {
|
continue;
|
}
|
if(fieldDefine.relativeLengthField==null)
|
continue;
|
try {
|
Object value = fieldDefine.field.get(this);
|
String hex = fieldDefine.coder.encode(value);
|
// Log.i("PlatformMessage", "FieldName: "+fieldDefine.field.getName()+" hex:"+hex);
|
if (hex == null) {
|
fieldDefine.relativeLengthField.set(this, 0);
|
} else {
|
fieldDefine.relativeLengthField.set(this, hex.length() / 2);
|
}
|
}
|
catch(IllegalAccessException e)
|
{
|
this.buildException(e.getMessage());
|
}
|
}
|
|
for (FieldDefine fieldDefine:fields)
|
{
|
if(this.disabledFields.contains(fieldDefine.field.getName()))
|
{
|
continue;
|
}
|
try {
|
Object obj = fieldDefine.field.get(this);
|
String hex = fieldDefine.coder.encode(obj);
|
if(hex==null)
|
{
|
hex = "";
|
}
|
|
int defineLen = fieldDefine.getFieldLen();
|
if(hex.length()>defineLen*2&&defineLen>0)
|
{
|
this.buildException("字段"+fieldDefine.field.getName()+"长度超过限制");
|
}
|
if(hex.length()<defineLen*2&&defineLen>0)
|
{
|
if(fieldDefine.length.paddingWay()== Length.PaddingWay.RIGHT)
|
{
|
hex = this.getPaddingRightString(hex,fieldDefine.getFieldLen()*2, BytesUtils.toHexString(fieldDefine.length.paddingByte()));
|
}
|
else
|
{
|
hex = this.getPaddingLeftString(hex,fieldDefine.getFieldLen()*2, BytesUtils.toHexString(fieldDefine.length.paddingByte()));
|
}
|
}
|
// Log.i("PlatformMessage value", "FieldName: "+fieldDefine.field.getName()+" hex:"+hex);
|
sb.append(hex);
|
} catch (IllegalAccessException e) {
|
this.buildException(e.getMessage());
|
}
|
}
|
|
return sb.toString();
|
}
|
String getPaddingLeftString(String str, int total_len,String padding) {
|
while (str.length() < total_len) {
|
str = padding + str;
|
}
|
return str;
|
}
|
String getPaddingRightString(String str, int total_len,String padding) {
|
while (str.length() < total_len) {
|
str = str+padding;
|
}
|
return str;
|
}
|
|
public synchronized FieldDefine[] getFieldDefines()
|
{
|
if(!fieldDefines.containsKey(this.getClass()))
|
{
|
Field[] fields = this.getClass().getFields();
|
List<FieldDefine> fieldDefineList = new ArrayList<>();
|
List<Class> baseClassList = new ArrayList<>();
|
for (Field field:fields)
|
{
|
if(Modifier.isStatic(field.getModifiers()))
|
continue;
|
if(Modifier.isPrivate(field.getModifiers()))
|
continue;
|
|
if(field.getAnnotation(Order.class)==null)
|
continue;
|
|
|
FieldDefine fieldDefine = new FieldDefine(field);
|
if(fieldDefine.coder!=null) {
|
|
fieldDefineList.add(fieldDefine);
|
if(baseClassList.indexOf(field.getDeclaringClass())<0)
|
{
|
baseClassList.add(field.getDeclaringClass());
|
}
|
}
|
if(fieldDefine.length.lengthField()!=null&&!"".equals(fieldDefine.length.lengthField()))
|
{
|
try {
|
fieldDefine.relativeLengthField = this.getClass().getField(fieldDefine.length.lengthField());
|
} catch (NoSuchFieldException e) {
|
this.buildException(e.getMessage());
|
}
|
}
|
|
}
|
//排序出基类
|
Collections.sort(baseClassList,new Comparator<Class>() {
|
@Override
|
public int compare(Class c1, Class c2) {
|
if(c2.isAssignableFrom(c1))
|
{
|
return 1;
|
}
|
return -1;
|
}
|
});
|
|
//重新排序
|
int sort = 0;
|
for(Class c:baseClassList)
|
{
|
sort+=100;
|
for(FieldDefine fieldDefine:fieldDefineList)
|
{
|
if(fieldDefine.field.getDeclaringClass().equals(c))//&&fieldDefine.order==0)
|
{
|
if(fieldDefine.order+sort>0) {
|
fieldDefine.order += sort;
|
}
|
}
|
}
|
}
|
Collections.sort(fieldDefineList,new Comparator<FieldDefine>() {
|
@Override
|
public int compare(FieldDefine t0, FieldDefine t1) {
|
int order0 = t0.order;//+(pos0+1);
|
int order1 = t1.order;//+(pos1+1);
|
|
|
if(order0>order1)
|
return 1;
|
if(order0==order1)
|
return 0;
|
|
return -1;
|
}
|
});
|
fieldDefines.put(this.getClass(),fieldDefineList.toArray(new FieldDefine[0]));
|
}
|
FieldDefine[] result = fieldDefines.get(this.getClass());
|
for(FieldDefine fieldDefine:result)
|
{
|
fieldDefine.setFieldLen(0);
|
}
|
return result;
|
}
|
|
class FieldDefine
|
{
|
public FieldDefine(Field field)
|
{
|
Annotation[] annotations = field.getAnnotations();
|
for (Annotation annotation:annotations) {
|
IMessageCoder decoder = AnnotationRegister.getCoder(annotation.annotationType());
|
if(decoder!=null) {
|
decoder.setFieldClass(field.getType());
|
coder = decoder;
|
this.length = annotation.annotationType().getAnnotation(Length.class);
|
break;
|
}
|
}
|
this.field = field;
|
if(this.length==null) {
|
this.length = field.getAnnotation(Length.class);
|
}
|
if(this.length==null)
|
{
|
buildException(field.getName()+"未定义长度");
|
}
|
Order orderAnnotation = field.getAnnotation(Order.class);
|
if(orderAnnotation!=null)
|
{
|
this.order = orderAnnotation.value();
|
}
|
|
FromEnd fromEnd = field.getAnnotation(FromEnd.class);
|
if(fromEnd!=null)
|
{
|
from_end_index = fromEnd.value();
|
}
|
|
}
|
public Field relativeLengthField;
|
public IMessageCoder coder;
|
public Length length;
|
public Field field;
|
public int order;
|
public int from_end_index = -1;
|
private int field_len;
|
public int getFieldLen()
|
{
|
if(this.length.value()>0)
|
return this.length.value();
|
return field_len;
|
}
|
|
public void setFieldLen(int len)
|
{
|
this.field_len = len;
|
}
|
|
@Override
|
public String toString() {
|
return this.field.toString();
|
}
|
|
|
}
|
|
public String getDescription()
|
{
|
return this.toString();
|
}
|
}
|