这个是真正的有挑战的,我的方法还是递归解析。
举个例子:
比如下面返回消息:
响应: 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_
他的实体如下:
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-11-29 */ public class ExecutionReportMsg extends BaseMsg { private Tag clOrdID=new Tag("11","String",false); private Tag cumQty=new Tag("14","Qty",true); private Tag execID=new Tag("17","String",true); private Tag execType=new Tag("150","char",true); private Tag leavesQty=new Tag("151","Qty",true); private Tag lotType=new Tag("1093","char",false); private Tag maxPriceLevels=new Tag("1090","int",false); private Tag parties=new PartiesTag(false); private Tag orderID=new Tag("37","String",true); private Tag orderQtyData=new OrderQtyDataTag(false); private Tag ordStatus=new Tag("39","char",true); private Tag ordType=new Tag("40","char",false); private Tag price=new Tag("44","Price",false); private Tag instrument=new InstrumentTag(true); private Tag side=new Tag("54","char",true); private Tag timeInForce=new Tag("59","char",false); private Tag transactTime=new Tag("60","UTCTimestamp",false); private Tag ordRejReason=new Tag("103","int",false); private Tag rejectText=new Tag("1328","String",false); private Tag lastPx=new Tag("31","Price",false); private Tag lastQty=new Tag("32","Qty",false); private Tag matchType=new Tag("574","String",false); private Tag trdMatchID=new Tag("880","String",false); private Tag execRefID=new Tag("19","String",false); private Tag execRestatementReason=new Tag("378","int",false); private Tag origClOrdID=new Tag("41","String",false); private Set<String> tagIdsSet=new HashSet<String>(); public ExecutionReportMsg(){ this.getHeadEntity().getMsgType().setTagValue("8"); tagIdsSet.add("11"); tagIdsSet.add("14"); tagIdsSet.add("17"); tagIdsSet.add("150"); tagIdsSet.add("151"); tagIdsSet.add("1093"); tagIdsSet.add("1090"); tagIdsSet.add("37"); tagIdsSet.add("39"); tagIdsSet.add("40"); tagIdsSet.add("44"); tagIdsSet.add("54"); tagIdsSet.add("59"); tagIdsSet.add("60"); tagIdsSet.add("103"); tagIdsSet.add("1328"); tagIdsSet.add("31"); tagIdsSet.add("32"); tagIdsSet.add("574"); tagIdsSet.add("880"); tagIdsSet.add("19"); tagIdsSet.add("378"); tagIdsSet.add("41"); this.bodyEntity.getBodyTagList().add(clOrdID); this.bodyEntity.getBodyTagList().add(cumQty); this.bodyEntity.getBodyTagList().add(execID); this.bodyEntity.getBodyTagList().add(execType); this.bodyEntity.getBodyTagList().add(leavesQty); this.bodyEntity.getBodyTagList().add(lotType); this.bodyEntity.getBodyTagList().add(maxPriceLevels); this.bodyEntity.getBodyTagList().add(parties); this.bodyEntity.getBodyTagList().add(orderID); this.bodyEntity.getBodyTagList().add(orderQtyData); this.bodyEntity.getBodyTagList().add(ordStatus); this.bodyEntity.getBodyTagList().add(ordType); this.bodyEntity.getBodyTagList().add(price); this.bodyEntity.getBodyTagList().add(instrument); this.bodyEntity.getBodyTagList().add(side); this.bodyEntity.getBodyTagList().add(timeInForce); this.bodyEntity.getBodyTagList().add(transactTime); this.bodyEntity.getBodyTagList().add(ordRejReason); this.bodyEntity.getBodyTagList().add(rejectText); this.bodyEntity.getBodyTagList().add(lastPx); this.bodyEntity.getBodyTagList().add(lastQty); this.bodyEntity.getBodyTagList().add(matchType); this.bodyEntity.getBodyTagList().add(trdMatchID); this.bodyEntity.getBodyTagList().add(execRefID); this.bodyEntity.getBodyTagList().add(execRestatementReason); this.bodyEntity.getBodyTagList().add(origClOrdID); } public void decodeBody() { Set<String> already=new HashSet<String>(); String input=this.body; while(input.length()!=0){ String firstTagId=input.substring(0, input.indexOf("=")); if(firstTagId.equals("453")){ input=this.getParties().decode(input, already); }else if(OrderQtyDataTag.tagIdsSet.contains(firstTagId)){ input=this.orderQtyData.decode(input, already); }else if(InstrumentTag.tagIdsSet.contains(firstTagId)){ input=this.instrument.decode(input, already); }else{ List<Tag> tagList=this.bodyEntity.getBodyTagList(); boolean exist=false; for(int j=0;j<tagList.size();j++){ Tag tag=tagList.get(j); if(tag.getTagId().equals(firstTagId)){ input=tag.decode(input, already); exist=true; break; } } if(!exist){ throw new InValidDataException(firstTagId+"不在消息字段中"); } } } } @Override public void validate() { this.headEntity.validate(); List<Tag> bodyTagList=this.bodyEntity.getBodyTagList(); for(int i=0;i<bodyTagList.size();i++){ bodyTagList.get(i).validate(); } this.tailerEntity.validate(); if(execType.getTagValue()!=null){ if(!MsgUtil.execType.contains(execType.getTagValue())){ throw new InValidDataException("execType错误["+execType.getTagId()+"="+execType.getTagValue()+"]"); } } if(lotType.getTagValue()!=null){ if(!MsgUtil.lotType.contains(lotType.getTagValue())){ throw new InValidDataException("lotType错误["+lotType.getTagId()+"="+lotType.getTagValue()+"]"); } } if(ordStatus.getTagValue()!=null){ if(!MsgUtil.ordStatus.contains(ordStatus.getTagValue())){ throw new InValidDataException("ordStatus错误["+ordStatus.getTagId()+"="+ordStatus.getTagValue()+"]"); } } if(ordType.getTagValue()!=null){ if(!MsgUtil.ordType.contains(ordType.getTagValue())){ throw new InValidDataException("ordType错误["+ordType.getTagId()+"="+ordType.getTagValue()+"]"); } } if(side.getTagValue()!=null){ if(!MsgUtil.side.contains(side.getTagValue())){ throw new InValidDataException("side错误["+side.getTagId()+"="+side.getTagValue()+"]"); } } if(timeInForce.getTagValue()!=null){ if(!MsgUtil.timeInForce.contains(timeInForce.getTagValue())){ throw new InValidDataException("timeInForce错误["+timeInForce.getTagId()+"="+timeInForce.getTagValue()+"]"); } } if(ordRejReason.getTagValue()!=null){ if(!((Integer.parseInt(ordRejReason.getTagValue())>=0&&Integer.parseInt(ordRejReason.getTagValue())<=19)||Integer.parseInt(ordRejReason.getTagValue())==99)){ throw new InValidDataException("ordRejReason错误["+ordRejReason.getTagId()+"="+ordRejReason.getTagValue()+"]"); } } if(matchType.getTagValue()!=null){ if(!MsgUtil.matchType.contains(matchType.getTagValue())){ throw new InValidDataException("matchType错误["+matchType.getTagId()+"="+matchType.getTagValue()+"]"); } } } public Tag getClOrdID() { return clOrdID; } public void setClOrdID(Tag clOrdID) { this.clOrdID = clOrdID; } public Tag getCumQty() { return cumQty; } public void setCumQty(Tag cumQty) { this.cumQty = cumQty; } public Tag getExecID() { return execID; } public void setExecID(Tag execID) { this.execID = execID; } public Tag getExecType() { return execType; } public void setExecType(Tag execType) { this.execType = execType; } public Tag getLeavesQty() { return leavesQty; } public void setLeavesQty(Tag leavesQty) { this.leavesQty = leavesQty; } public Tag getLotType() { return lotType; } public void setLotType(Tag lotType) { this.lotType = lotType; } public Tag getMaxPriceLevels() { return maxPriceLevels; } public void setMaxPriceLevels(Tag maxPriceLevels) { this.maxPriceLevels = maxPriceLevels; } public Tag getParties() { return parties; } public void setParties(Tag parties) { this.parties = parties; } public Tag getOrderID() { return orderID; } public void setOrderID(Tag orderID) { this.orderID = orderID; } public Tag getOrderQtyData() { return orderQtyData; } public void setOrderQtyData(Tag orderQtyData) { this.orderQtyData = orderQtyData; } public Tag getOrdStatus() { return ordStatus; } public void setOrdStatus(Tag ordStatus) { this.ordStatus = ordStatus; } public Tag getOrdType() { return ordType; } public void setOrdType(Tag ordType) { this.ordType = ordType; } public Tag getPrice() { return price; } public void setPrice(Tag price) { this.price = price; } public Tag getInstrument() { return instrument; } public void setInstrument(Tag instrument) { this.instrument = instrument; } public Tag getSide() { return side; } public void setSide(Tag side) { this.side = side; } public Tag getTimeInForce() { return timeInForce; } public void setTimeInForce(Tag timeInForce) { this.timeInForce = timeInForce; } public Tag getTransactTime() { return transactTime; } public void setTransactTime(Tag transactTime) { this.transactTime = transactTime; } public Set<String> getTagIdsSet() { return tagIdsSet; } public void setTagIdsSet(Set<String> tagIdsSet) { this.tagIdsSet = tagIdsSet; } public Tag getOrdRejReason() { return ordRejReason; } public void setOrdRejReason(Tag ordRejReason) { this.ordRejReason = ordRejReason; } public Tag getRejectText() { return rejectText; } public void setRejectText(Tag rejectText) { this.rejectText = rejectText; } public Tag getLastPx() { return lastPx; } public void setLastPx(Tag lastPx) { this.lastPx = lastPx; } public Tag getLastQty() { return lastQty; } public void setLastQty(Tag lastQty) { this.lastQty = lastQty; } public Tag getMatchType() { return matchType; } public void setMatchType(Tag matchType) { this.matchType = matchType; } public Tag getTrdMatchID() { return trdMatchID; } public void setTrdMatchID(Tag trdMatchID) { this.trdMatchID = trdMatchID; } public Tag getExecRefID() { return execRefID; } public void setExecRefID(Tag execRefID) { this.execRefID = execRefID; } public Tag getExecRestatementReason() { return execRestatementReason; } public void setExecRestatementReason(Tag execRestatementReason) { this.execRestatementReason = execRestatementReason; } public Tag getOrigClOrdID() { return origClOrdID; } public void setOrigClOrdID(Tag origClOrdID) { this.origClOrdID = origClOrdID; } }
CsFixProtocolDecoder类的指令:
baseMessage.setHead(msgArray[0]); baseMessage.setBody(msgArray[1]); baseMessage.setTailer(msgArray[2]); baseMessage.decode();BaseMsg的方法:
public void decode(){ decodeHead(); decodeBody(); decodeTailer(); }
ExecutionReportMsg类的decodeBody方法,依次将输入流解析,如果是组合Tag,会吧流传入组合tag依次依稀,值到遇到最简单的tag直接解析
Tag类的方法:
public String decode(String input,Set<String> already){ String myItem=input.substring(0, input.indexOf(BaseMsg.SOH)); String returnStr=input.substring(input.indexOf(BaseMsg.SOH)+1); String [] tagItems=myItem.split("="); if(tagItems.length!=2){ throw new InValidDataException("消息格式错误"); } if(already.contains(tagId)){ throw new InValidDataException(tagId+"消息已被解析"); } if(this.getTagId().equals(tagItems[0])){ this.tagValue=tagItems[1]; already.add(tagItems[0]); return returnStr; }else{ throw new InValidDataException("解析错误["+tagId+"-"+tagItems[0]+"]"); } }