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 fieldDefines = new HashMap<>(); protected List 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); 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()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())); } } // System.out.println(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 fieldDefineList = new ArrayList<>(); List 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() { @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() { @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(); } }