关闭

fix协议封装挑战-将一个消息实体编码为协议字符串

1227人阅读 评论(1) 收藏 举报
分类:

消息实体如下:

package cs.test;

import java.text.SimpleDateFormat;
import java.util.Date;

import cs.mina.SeqenceNum;
import cs.mina.codec.msg.BaseMsg;
import cs.mina.codec.msg.DisclosureInstructionGrp;
import cs.mina.codec.msg.DisclosureInstructionGrpTag;
import cs.mina.codec.msg.InstrumentTag;
import cs.mina.codec.msg.NewOrderSingleMsg;
import cs.mina.codec.msg.OrderQtyDataTag;
import cs.mina.codec.msg.PartiesTag;
import cs.mina.codec.msg.Party;

/*
 *@author(huangxiaoping)
 *@date 2013-11-29
 */
public class TC_OM_04Test {
	public static BaseMsg createMsg(){
		 NewOrderSingleMsg msg=new NewOrderSingleMsg();
		 msg.getHeadEntity().getMsgSeqNum().setTagValue(SeqenceNum.getSeqence()+"");
	   	 msg.getClOrdID().setTagValue("13");
	   	 msg.getParties().setTagValue("1");
	   	 Party party=new Party();
	   	 party.getPartyID().setTagValue("1122");
	   	 party.getPartyIDSource().setTagValue("D");
	   	 party.getPartyRole().setTagValue("1");
	   	 ((PartiesTag)msg.getParties()).getChildren().add(party);
	   	 ((InstrumentTag)msg.getInstrument()).getSecurityID().setTagValue("36");
	   	 ((InstrumentTag)msg.getInstrument()).getSecurityIDSource().setTagValue("8");
	   	 ((InstrumentTag)msg.getInstrument()).getSecurityExchange().setTagValue("XHKG");
	   	 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss.SSS"); 
	   	 msg.getTransactTime().setTagValue(sdf.format(new Date()));
	   	 msg.getSide().setTagValue("2");
	   	 msg.getOrdType().setTagValue("2");
	   	 msg.getPrice().setTagValue("30.05");
	   	 ((OrderQtyDataTag)msg.getOrderQtyData()).getOrderQty().setTagValue("4000");
	   	 msg.getTimeInForce().setTagValue("0");
	   	 msg.getMaxPriceLevels().setTagValue("1");
	   	 msg.getExecInst().setTagValue("c x");
	   	 
	   	 DisclosureInstructionGrp dis=new DisclosureInstructionGrp();
	   	 dis.getDisclosureType().setTagValue("100");
	   	 dis.getDisclosureInstruction().setTagValue("1");
	   	((DisclosureInstructionGrpTag)msg.getDisclosureInstructionGrp()).setTagValue("1");
	   	 ((DisclosureInstructionGrpTag)msg.getDisclosureInstructionGrp()).getChildren().add(dis);
	   	 return msg;
	   	 
	   }
}



消息如下:

测试案例TC_OM_04
测试数据1
发送:
8=FIXT.1.1_9=206_35=D_49=CO99999901_56=HKEXCO_34=3_52=20131129-15:07:00.902_11=13_453=1_448=1122_447=D_452=1_18=c x_1090=1_48=36_22=8_207=XHKG_60=20131129-15:07:00.903_54=2_40=2_44=30.05_38=4000_59=0_1812=1_1813=100_1814=1_10=146_
响应:
8=FIXT.1.1_9=239_35=8_49=HKEXCO_56=CO99999901_34=3_52=20131129-07:07:01.327_1128=9_11=13_14=0_17=20701315_150=0_151=4000_1093=2_1090=1_453=1_448=1122_447=D_452=1_37=30701209_38=4000_39=0_40=2_44=30.05_207=XHKG_48=36_22=8_54=2_59=0_60=20131129-07:07:01.317_10=027_

说明:

消息的构造很简单,就是javabean,关键是如何把这个javabean解析为消息字符串。

解析原理如下:

package cs.mina.codec.msg;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import cs.mina.exception.InValidDataException;

/*
 *@author(huangxiaoping)
 *@date 2013-10-24
 */
public abstract class BaseMsg {
	public static final String SOH = "\u0001";
	protected String head;
	protected String body;
	protected String tailer;
	protected Head headEntity=new Head();
	protected Body bodyEntity=new Body();
	protected Tailer tailerEntity=new Tailer();
	
	public abstract void validate();
	
	public String encode(){
		String result="";
		List<Tag> headTagList=this.headEntity.getHeadTagList();
		for(int i=0;i<headTagList.size();i++){
			Tag headTag=headTagList.get(i);
			result+=headTag.encode();
		}
		List<Tag> bodyTagList=this.bodyEntity.getBodyTagList();
		for(int i=0;i<bodyTagList.size();i++){
			Tag bodyTag=bodyTagList.get(i);
			result+=bodyTag.encode();
		}
		List<Tag> tailerTagList=this.tailerEntity.getTailerTagList();
		for(int i=0;i<tailerTagList.size();i++){
			Tag tailerTag=tailerTagList.get(i);
			result+=tailerTag.encode();
		}
		return result;
	}
	
	public void decode(){
		decodeHead();
		decodeBody();
		decodeTailer();
	}
	
	public abstract void decodeBody();
	
	public void decodeHead(){
		Set<String> already=new HashSet<String>();
		String[] headItems=this.head.split(SOH);
		for(int i=0;i<headItems.length;i++){
			String headItem=headItems[i];
			String[] headTagItems=headItem.split("=");
			if(headTagItems.length!=2){
				throw new InValidDataException("消息格式错误");
			}
			if(already.contains(headTagItems[0])){
				throw new InValidDataException("消息格式错误");
			}
			already.add(headTagItems[0]);
			if(headTagItems[0].equals("627")){
				int skip=decodeGroup627();
				i=i+skip-1;
			}else{
				List<Tag> headTags=this.headEntity.getHeadTagList();
				for(int j=0;j<headTags.size();j++){
					Tag headTag=headTags.get(j);
					if(headTag.getTagId().equals(headTagItems[0])){
						headTag.setTagValue(headTagItems[1]);
					}
				}
			}
		}
	}
	
	private int decodeGroup627(){
		int index=head.indexOf("627=");
		String rest=head.substring(index);
		String[]tagItems=rest.split(BaseMsg.SOH);
		String[] numTagItems=tagItems[0].split("=");
		if(numTagItems.length!=2){
			throw new InValidDataException("消息格式错误");
		}
		if(!"627".equals(numTagItems[0])){
			throw new InValidDataException("消息格式错误");
		}
		int num=Integer.parseInt(numTagItems[1]);
		int count=1;
		int whileCount=0;
		((HopGrpTag)this.headEntity.getHopGrpTag()).setTagValue(num+"");
		boolean end=false;
		for(int i=0;i<num;i++){
			if(end){
				if(i!=num){
					throw new InValidDataException("消息格式错误");
				}else{
					break;
				}
			}
			HopGrp hopGrp=new HopGrp();
			((HopGrpTag)this.getHeadEntity().getHopGrpTag()).getChildren().add(hopGrp);
			while(true){
				if(whileCount>=3){
					whileCount=0;
					break;
				}
				if(tagItems.length==count){
					break;
				}
				String[] tagIt=tagItems[count].split("=");
				if(tagIt.length!=2){
					throw new InValidDataException("消息格式错误");
				}
				if(whileCount==0){
					if(!HopGrpTag.first.equals(tagIt[0])){
						throw new InValidDataException("消息格式错误");
					}
				}
				
				if(HopGrp.tagIdsSet.contains(tagIt[0])){
					List<Tag> tagList=hopGrp.getTagList();
					for(int j=0;j<tagList.size();j++){
						Tag groupTag=tagList.get(j);
						if(groupTag.getTagId().equals(tagIt[0])){
							groupTag.setTagValue(tagIt[1]);
							break;
						} 
					}
					if(tagItems.length>count+1){
						String[] nextTagIt=tagItems[count+1].split("=");
						if(nextTagIt.length!=2){
							throw new InValidDataException("消息格式错误");
						}
						if(HopGrpTag.first.equals(nextTagIt[0])){
							whileCount=0;
							count++;
							break;
						}
					}
					
					count++;
					whileCount++;
					
				}else{
					end=true;
					break;
				}
				
			}
			
		}
		
		return count;
	}
	
	public void decodeTailer(){
		Set<String> already=new HashSet<String>();
		String[] tailerItems=this.tailer.split(SOH);
		for(int i=0;i<tailerItems.length;i++){
			String tailerItem=tailerItems[i];
			String[] tailerTagItems=tailerItem.split("=");
			if(tailerTagItems.length!=2){
				throw new InValidDataException("消息格式错误");
			}
			if(already.contains(tailerTagItems[0])){
				throw new InValidDataException("消息格式错误");
			}
			already.add(tailerTagItems[0]);
			List<Tag> tailerTags=this.tailerEntity.getTailerTagList();
			for(int j=0;j<tailerTags.size();j++){
				Tag tailerTag=tailerTags.get(j);
				if(tailerTag.getTagId().equals(tailerTagItems[0])){
					tailerTag.setTagValue(tailerTagItems[1]);
				}
			}
			
		}
	}
	
	public String getHead() {
		return head;
	}

	public void setHead(String head) {
		this.head = head;
	}

	public String getBody() {
		return body;
	}

	public void setBody(String body) {
		this.body = body;
	}

	public String getTailer() {
		return tailer;
	}

	public void setTailer(String tailer) {
		this.tailer = tailer;
	}

	public Head getHeadEntity() {
		return headEntity;
	}

	public void setHeadEntity(Head headEntity) {
		this.headEntity = headEntity;
	}

	public Body getBodyEntity() {
		return bodyEntity;
	}

	public void setBodyEntity(Body bodyEntity) {
		this.bodyEntity = bodyEntity;
	}

	public Tailer getTailerEntity() {
		return tailerEntity;
	}

	public void setTailerEntity(Tailer tailerEntity) {
		this.tailerEntity = tailerEntity;
	}

	

}



消息头和消息尾是共用的,用通用的方法解析就可以了。关键是消息体,每个消息的消息体不一样,但是我们还是可以用递归的方式解析。

注意encode 方法



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:602000次
    • 积分:8661
    • 等级:
    • 排名:第2207名
    • 原创:289篇
    • 转载:334篇
    • 译文:1篇
    • 评论:122条
    博客专栏
    文章分类
    最新评论