Commit 30dcc426 by WeiCong

1.修复多层sequence嵌套的报文解析

parent f0cf660a
......@@ -225,6 +225,9 @@ public class TagLine implements MessageArea {
}
String analyzeReg = null;
public void setAnalyzeReg(String analyzeReg){
this.analyzeReg=analyzeReg;
}
public String getAnalyzeReg()
{
if(analyzeReg==null)
......
package com.brilliace.swifteditor.tag.message;
import com.brilliace.swifteditor.tag.TagFormat;
import com.brilliace.swifteditor.tag.TagLine;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
......@@ -10,782 +13,686 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.brilliace.swifteditor.tag.TagFormat;
import com.brilliace.swifteditor.tag.TagLine;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
public class MessageAnalyzer {
/*
* @param msg:报文字符串; 传递报文字符串,将其中的文首都解析出来。 对于ACK/NCK报文,后面会附带原报,会出现文首重复的情况,将附带的原报文首的KEY添加负号做为KEY,避免覆盖。
* 如果后面附带了S等带字母的“文首”,则直接使用其Acsii码,作为KEY。
*/
public static Map<Integer, String> anlyMsgHead(String msg)
{
Map<Integer, String> headSet = new HashMap<Integer, String>();
String reg = "\\{[\\d|S]:";
Matcher m = Pattern.compile(reg).matcher(msg);
int lstEnd = -1;
int lstHead = -1;
while (m.find())
{
if (lstEnd > 0 && lstHead > 0)
{
String val = msg.substring(lstEnd, m.start() - 1);
if (!headSet.containsKey(lstHead))
{
headSet.put(lstHead, val);
}
else
{
headSet.put(-lstHead, val);
}
}
String g = m.group();
char c = g.charAt(1);
lstHead = c;
if (c >= '0' && c <= '9') // 对于是数字的,则以数字做KEY,否则以Acsii码做主键
lstHead -= '0';
lstEnd = m.end();
}
if (lstEnd > 0 && lstHead > 0) // 将最后一个文首存入Map
{
int lstidx = msg.lastIndexOf('}');
if (lstidx <= lstEnd)
return headSet;
if (!headSet.containsKey(lstHead))
headSet.put(lstHead, msg.substring(lstEnd, lstidx));
else
headSet.put(-lstHead, msg.substring(lstEnd, lstidx));
}
return headSet;
}
/*
* @param mt:对正文block 4中包含的栏位名称和栏位值切割,以换行符加“:”来切割
*/
public static List<String[]> msgTxtAnly(String mt)
{
if(mt.startsWith(":"))
mt = "\r\n"+mt;
String[] tags = mt.split("[\\r\\n]{1,2}:(?=\\d{2}[A-Z]?:)");
List<String[]> list = new ArrayList<String[]>();
for (String tv : tags)
{
if (tv.trim().length() > 0)
{
int i = tv.indexOf(':');
if (i > 0)
{
String[] arr = new String[2];
arr[0] = tv.substring(0, i);
arr[1] = tv.substring(i + 1);
list.add(arr);
}
}
}
if (list.size() > 0)
{
String[] lstOne = list.get(list.size() - 1);
String lstStr = lstOne[1].trim();
int i = lstStr.lastIndexOf("\r\n");
if (i < 0)
{
i = lstStr.lastIndexOf("\r");
}
if (i < 0)
{
i = lstStr.lastIndexOf("\n");
}
if (i > -1)
{
//清除末尾横线
String lstLine = lstStr.substring( i).trim();
if("-".equals(lstLine))
lstOne[1] = lstStr.substring(0, i);
}
}
return list;
}
/* 屏蔽不同的系统的换行符差异,获取换行符位置 */
private static int getLinePos(String str)
{
if (str == null)
return -1;
int idxr = str.indexOf("\r");
int idxn = str.indexOf("\n");
if (idxr > -1 && idxn > -1)// \r\n连接在一起
{
return idxr < idxn ? idxr : idxn;
}
else
{
return idxr <= idxn ? idxn : idxr;// 单个\r或者\n的情况,返回较大的
}
}
public static Map<String, String> getSwfMsgInfoViaMsg(Map<Integer, String> heads)
{
Map<String, String> infMap = new HashMap<String, String>();
String hd4 = heads.get(4);
boolean isNACK = false; // 是否为ACK/NCK报文
if (hd4 != null)
{
if (hd4.contains("{451:0}") || hd4.contains("{451:1}"))
{
isNACK = true;
if (hd4.contains("{451:0}"))
infMap.put("mty", "ACK");
else
infMap.put("mty", "NCK");
// infMap.put("ehf",heads.get(-4) );
int errIdx = hd4.indexOf("{405:");
if (errIdx > -1)
{
int idx2 = hd4.indexOf("}", errIdx);// 获取下一个括号
if (idx2 > -1)
infMap.put("errcod", hd4.substring(errIdx + 5, idx2));// 将错误码放进去
}
}
else
// 非ACK 或NCK报文
{
}
}
/* 处理报文或者附带的报文的文首和正文 */
String hd2 = heads.containsKey(-2) ? heads.get(-2) : heads.get(2);
String hd1 = heads.containsKey(-1) ? heads.get(-1) : heads.get(1);
String hd3 = heads.containsKey(-3) ? heads.get(-3) : heads.get(3);
hd4 = heads.containsKey(-4) ? heads.get(-4) : heads.get(4);
String hd5 = heads.containsKey(-5) ? heads.get(-5) : heads.get(5);
if (hd5 != null)
infMap.put("trl", hd5);
String msgTyp = null; // 报文类型,如果为NCK/ACK报文,则该类型值为附带的原文里面的类型
String direct = null; // 报文收发方向
if (hd2 != null) // 拆解2文首
{
// 如果2文首不为空,开始获取收发方向和报文类型
if (hd2.length() >= 4)
{
direct = hd2.substring(0, 1);
infMap.put("direct", direct);// 存储报文方向
msgTyp = hd2.substring(1, 4);
if ("I".equals(direct)) // 发出报文
{
if (hd2.length() >= 16)
{
String rcvbic = hd2.substring(4, 16); // 获取收报行
infMap.put("rcvbic", rcvbic);
}
if (hd2.length() >= 17)
infMap.put("prt", hd2.substring(16, 17));// 电报优先级
if (hd2.length() >= 18)
infMap.put("tns", hd2.substring(17, 18));
if (hd2.length() >= 21)
infMap.put("dyt", hd2.substring(18, 21));
}
else if ("O".equals(direct))
{
if (hd2.length() >= 26)
{
String sndbic = hd2.substring(14, 26);
infMap.put("sndbic", sndbic); // 获取发报行
if (hd2.length() >= 36)
{
infMap.put("mir", hd2.substring(8, 14) + " " + hd2.substring(14, 36));// 获取MIR
if (hd2.length() == 47)
infMap.put("prt", hd2.substring(46));// 电报优先级
}
}
}
}
}
if (hd1 != null) // 拆解1文首
{
if (hd1.length() >= 15)
{
String bnk1 = hd1.substring(3, 15);
if ("O".equals(direct))
{
infMap.put("rcvbic", bnk1);
}
else if ("I".equals(direct))
{
infMap.put("sndbic", bnk1);
}
if (hd2 != null && hd2.length() >= 14)
{
infMap.put("mor", hd2.substring(8, 14) + " " + hd1.substring(3));// 获取MOR
}
}
}
if (hd3 != null)
{
if (hd3.contains("{119:COV}"))
{
msgTyp = msgTyp + "COV";
}
if (hd3.contains("{FMT:"))
{
String fmt = hd3.substring(1, hd3.length() - 1);
String args[] = fmt.split(":");
infMap.put("fmttype", args[0]);
infMap.put("fmtstd", args[1]);
String strarry[] = hd3.split("\\}");
for (String substr : strarry)
{
substr = substr.substring(1);
String sp[] = substr.split(":");
if (sp.length == 2)
{
infMap.put(sp[0], sp[1]);
}
else
{
infMap.put(sp[0], null);
}
}
}
// else if(hd3.contains("{119:STP}"))
// msgTyp = msgTyp + "+";
Matcher m = Pattern.compile("\\{108:\\w+\\}").matcher(hd3);
if (m.find())
{
String gp = m.group();
int idx = gp.indexOf(":");
infMap.put("sndnum", gp.substring(idx + 1, gp.length() - 1)); /* 取发报流水号 */
}
}
infMap.put("std", "MT");
if (!isNACK)
infMap.put("mty", msgTyp);// 报文类型已经添加,存入Map中
else
infMap.put("emty", msgTyp);// 获取附带的报文类型
if (hd4 != null) // 处理4域,即正文
{
List<String[]> kv = msgTxtAnly(hd4);
for (String[] strArr : kv)
{
if(strArr[1].trim().length()==0)
continue;
if (strArr[0].endsWith("20"))// 业务编号
{
if (!infMap.containsKey("ref")) // 如果没有填入20栏,则将20栏填入,已填入则不进行覆盖。为nXX系列报文附带原报的情况
{
if (strArr[1].length() > 16)
infMap.put("ref", strArr[1].substring(0, 16).trim());
else
infMap.put("ref", strArr[1].trim());
}
}
if (strArr[0].endsWith("21"))// 相关编号
{
if (!infMap.containsKey("tscref")) // 如果没有填入21栏,则将21栏填入,已填入则不进行覆盖。为nXX系列报文附带原报的情况
{
if (strArr[1].length() > 16)
infMap.put("tscref", strArr[1].substring(0, 16));
else
infMap.put("tscref", strArr[1]);
}
}
if (strArr[0].endsWith("22C"))// 300报文的COMMON REFFERENCE
{
}
if (strArr[0].endsWith("32A"))// 金额币种起息日
{
if (strArr[1].matches("\\d{6}[A-Z]{3}\\d{1,15},\\d*"))
{
String valDat = strArr[1].substring(0, 6);
String cur = strArr[1].substring(6, 9);
String amt = strArr[1].substring(9);
infMap.put("vludat", valDat);
infMap.put("amt", amt.replace(",", "."));
infMap.put("cur", cur);
}
}
if (strArr[0].matches("62[FM]"))
{
// 950/940对账单的币种金额起息日
if (strArr[1] != null && strArr[1].matches("[DC]\\d{6}[A-Z]{3}\\d{1,15},\\d*"))
{
String valDat = strArr[1].substring(1, 7);
String cur = strArr[1].substring(7, 10);
String amt = strArr[1].substring(10).replace(",", ".");
infMap.put("vludat", valDat);
infMap.put("amt", amt.replace(",", "."));
infMap.put("cur", cur);
}
else
return infMap;
}
if (strArr[0].matches("25")) // 获取940/950里面的账号
{
String act = strArr[1];
infMap.put("act", act);
}
if ("O".equals(infMap.get("direct")) && strArr[0].matches("54A") && strArr[1] != null)
{
String actbic = strArr[1];
int secondLine = getLinePos(actbic);
if (secondLine > -1)
{
actbic = actbic.substring(secondLine);
actbic = actbic.replaceAll("\\r|\\n", "");// 去除遗留的\r\n
}
infMap.put("actbic", actbic);
}
if ("O".equals(infMap.get("direct")) && strArr[0].matches("53A") && strArr[1] != null)
{
String actbic = strArr[1];
int secondLine = getLinePos(actbic);
if (secondLine > -1)
{
actbic = actbic.substring(secondLine);
actbic = actbic.replaceAll("\\r|\\n", "");// 去除遗留的\r\n
}
infMap.put("t53bic", actbic);
}
if ("I".equals(direct) && strArr[0].matches("53A") && strArr[1] != null)
{
String actbic = strArr[1];
int secondLine = getLinePos(actbic);
if (secondLine > -1)
{
actbic = actbic.substring(secondLine);
actbic = actbic.replaceAll("\\r|\\n", "");// 去除遗留的\r\n
}
infMap.put("actbic", actbic);
}
if (strArr[0].matches("50[AK]") && strArr[1] != null)
{
int index = getLinePos(strArr[1]);
if (index > -1 && strArr[1].startsWith("/"))
infMap.put("act", strArr[1].substring(1, index));
if (strArr[0].endsWith("K"))
{
if (index > -1)
{
String nam = strArr[1].substring(index).replaceAll("^[\\r\\n]{1,2}", "");
infMap.put("ordnamadr", nam);
}
else
{
infMap.put("ordnamadr", strArr[1]);
}
}
}
if (strArr[0].matches("59") && strArr[1] != null)
{
int index = getLinePos(strArr[1]);
String nam = strArr[1];
if (index > -1 && strArr[1].startsWith("/"))
{
String act = strArr[1].substring(1, index);// 取出前面的账号
infMap.put("act", act);// 填入59域的账号,收益人账号
infMap.put("benact", act);// 查询查复使用,需区分50域的账号
nam = strArr[1].substring(index).replaceAll("^[\\r\\n]{1,2}", "");
}
infMap.put("bennamadr", nam);
}
// 下面主要对MT300起作用
if (strArr[0].endsWith("22C"))
{
if (!infMap.containsKey("comref")) // 如果没有填入22C栏
{
if (strArr[1].length() > 16)
infMap.put("comref", strArr[1].substring(0, 16));
else
infMap.put("comref", strArr[1]);
}
}
if (strArr[0].endsWith("33B") && strArr[1].length()>0)
{
String cur = strArr[1].substring(0, 3);
String amt = strArr[1].substring(3);
infMap.put("sellamt", amt.replace(",", "."));
infMap.put("sellcur", cur);
}
// 这里主要是对MT320起作用
if (strArr[0].endsWith("17R"))
{
if (!infMap.containsKey("BorL"))
infMap.put("BorL", strArr[1]);
}
if (strArr[0].endsWith("34E"))
{
String tagN = strArr[1].substring(0, 1);
String interest = "";
if ("N".equals(tagN))
interest = strArr[1].substring(4);
else
interest = strArr[1].substring(3);
infMap.put("interest", interest.replace(",", "."));
}
// 公共区域
if (strArr[0].endsWith("30V"))
{
if (!infMap.containsKey("m3xValDate"))
infMap.put("m3xValDate", strArr[1]);
}
if (strArr[0].endsWith("32B"))
{
String cur = strArr[1].substring(0, 3);
String amt = strArr[1].substring(3);
infMap.put("buyamt", amt.replace(",", "."));
infMap.put("buycur", cur);
}
}
}
return infMap;
}
/*
* @param msg:报文字符串 对报文信息的基本获取,如果是NCK/ACK报文则mty为NCK/ACK,如有附带报文,则附带的报文类型由emty记录
*/
public static Map<String, String> getSwfMsgInfoViaMsg(String msg)
{
if (msg == null || msg.trim().length() == 0)
return new HashMap<String,String>();
Map<Integer,String> headers = anlyMsgHead(msg);
return getSwfMsgInfoViaMsg(headers);
}
/***
* 解析TD的格式报文
* @param msg
* @return
*/
public static Map<String,String> getSwfMsgInfoViaTDMsg(String msg)
{
Map<String,String> bscInfo = new HashMap<String,String>();
String reg = ":MT:(\\d{3})[\\r\\n]{1,2}:IO:(\\w{2,11})[\\r\\n]{1,2}:II:(\\w{2,11})[\\r\\n]{1,2}:MP:(\\w)";
Matcher m = Pattern.compile(reg).matcher(msg);
if(!m.find())
return bscInfo ;// 错误的格式
//bscInfo.put("mty", m.group(1));
bscInfo.put("sndbic", m.group(3));
bscInfo.put("rcvbic", m.group(2));
bscInfo.put("prt", m.group(4));
int idx = msg.indexOf(":EOH:", m.end());
String tdmsgHead= msg.substring(0,idx);
int begIndex = m.end(4);
reg = ":111:(\\d{3})(?=\\r|\\n)";
String restStr = tdmsgHead.substring(begIndex);
Matcher m2 = Pattern.compile(reg).matcher(restStr);
if(m2.find())
{
bscInfo.put("t111", m2.group(1).trim());
}
reg = ":121:([\\s\\S]+)(?=\\r|\\n)";
m2 = Pattern.compile(reg).matcher(restStr);
if(m2.find())
{
bscInfo.put("t121", m2.group(1).trim());
}
bscInfo.put("tdmsgHead", tdmsgHead);//存头,方便前端组报
//取111,121
if(tdmsgHead.indexOf(":119:COV")> -1)
{
bscInfo.put("mty", m.group(1)+"COV");
}
else
bscInfo.put("mty", m.group(1));
msg = msg.substring(idx+":EOH:".length());
if(msg.endsWith("-"))
msg = msg.substring(0, msg.length()-1);
Map<Integer,String> headers = new HashMap<Integer,String>();
headers.put(4, msg);
Map<String,String> infoMap = getSwfMsgInfoViaMsg(headers);
infoMap.put("mty", bscInfo.get("mty"));
bscInfo.putAll(infoMap);
return bscInfo;
}
public static SWFMessage loadSwiftFile(String path)
{
return loadSwiftMessage(readFull(path));
}
public static SWFMessage loadSwiftMessage(String message)
{
Map<Integer,String> headers = null;
Map<String,String> bscInfo = null;
if(message.startsWith(":MT:")) // TD内部报文
{
bscInfo = getSwfMsgInfoViaTDMsg(message);
int index = message.indexOf(":EOH:")+":EOH:".length();
int lastIndex = message.lastIndexOf("-");
if(lastIndex > 0)
message = message.substring(index, lastIndex).trim();
else
message = message.substring(index);
headers = new HashMap<Integer,String>();
headers.put(4, message);
}
else
{
headers = anlyMsgHead(message);
bscInfo = getSwfMsgInfoViaMsg(headers);
}
//取出报文类型
String mty = bscInfo.get("mty");
System.out.print("---------"+mty);
SWFMessage swf = MessageFormat.getSWFMessage(mty);
swf.setHeaders(headers);
swf.setBscInfo(bscInfo);
List<String[]> tags = msgTxtAnly(headers.get(4));
String tagsCombo = getTagsStr(tags);
loadSwiftMessage(swf,tagsCombo,tags);
return swf;
}
private static int loadSwiftMessage(MessageArea area,String tagsCombo,List<String[]> tags)
{
StringBuilder buf = new StringBuilder();
generReg(area,buf);
String reg = buf.toString();
Matcher m = Pattern.compile(reg).matcher(tagsCombo);
if(!m.find() || m.start() == m.end())
return -1; //栏位格式不符
List<MessageArea> fieldList = ((AbstractMessageArea) area).getFields();
for(int i=0; i< fieldList.size();i++)
{
MessageArea item = fieldList.get(i);
if(item.getType() == MessageArea.TAG)
{
//直接捕获对应分组
TagLine tag = (TagLine)item;
String grpName = "T"+String.valueOf(tag.getTno());
String value = m.group(grpName);
if(value == null)
continue;
String[] valArr = value.split(",");
//tag.setName(valArr[0]);
if(tag.getName().endsWith("a"))
{
TagLine tag2 = TagFormat.getTagLine(valArr[0]);
tag2.setDesp(tag.getDesp());
tag2.setTno(tag.getTno());
tag2.setName(valArr[0]);
tag2.setStatus(tag.getStatus());
tag2.getSuffix().addAll(tag.getSuffix());
tag = tag2;
fieldList.set(i, tag); //置换新的栏位
}
int idx = Integer.parseInt(valArr[1].substring(0, valArr[1].length()-1));
tag.setValue(tags.get(idx)[1]);//还要考虑值分解
}else if(item.getType() == MessageArea.CYCLIST )
{
String grpName = String.valueOf("C"+item.getName());
String value = m.group(grpName); //新的块级
if(value == null || value.length() == 0)
continue;
MessageArea cp = ((AbstractMessageArea) item).getFields().get(0);//默认有一个组项
int offset = 0;
do{
offset = loadSwiftMessage(cp,value,tags);
if(offset <= 0)
break;
if(offset >= value.length())
break; //提前终止,避免不必要的空循环
cp = ((AbstractMessageArea) item).getPattern().clone();
item.addSubArea(cp);
value = value.substring(offset);
}
while(true);
}else if(item.getType() == MessageArea.SEQLIST )
{
String grpName = String.valueOf("S"+item.getName());
String value = m.group(grpName); //新的块级
if(value == null || value.length() == 0)
continue;
MessageArea cp = ((AbstractMessageArea) item).getFields().get(0);//默认有一个组项
int offset = 0;
do{
offset = loadSwiftMessage(cp,value,tags);
if(offset <= 0)
break;
if(offset >= value.length())
break; //提前终止,避免不必要的空循环
cp = ((AbstractMessageArea) item).getPattern().clone();
item.addSubArea(cp);
value = value.substring(offset);
}
while(true);
}
}
return m.end();
}
private static String getTagsStr(List<String[]> tags)
{
StringBuilder buf = new StringBuilder();
int cnt = 0;
for(String[] item:tags)
{
//System.out.println(item[0]+"-----"+item[1]);
buf.append(item[0]+","+cnt);
cnt++;
buf.append(";");
}
return buf.toString();
}
public static void generReg(MessageArea area,StringBuilder sb)
{
if(area.getType() == MessageArea.TAG)
{
TagLine tag = (TagLine)area;
sb.append("(?<T"+tag.getTno()+">");
if(tag.getSuffix().size() != 0 )
{
sb.append(tag.getName().substring(0, 2));
sb.append('[');
boolean hasOpt = false;
for(String item : tag.getSuffix())
{
if(item.length()==2)
hasOpt = true;
else
sb.append(item.charAt(2));
}
sb.append(']');
if(hasOpt)
sb.append('?');
}
else
sb.append(tag.getName());
sb.append(",\\d{1,3};)");
if("O".equals(tag.getStatus()))
sb.append('?');
return ;
}
String defaultReg = ((AbstractMessageArea) area).getAnlyReg();
if(defaultReg!=null)
{
sb.append(defaultReg);
return;
}
if(area instanceof SWFMessage)
{
for(MessageArea item : ((AbstractMessageArea) area).getFields())
{
generReg(item,sb);
}
}
else if(area.getType() == MessageArea.CYCLIST )
{
StringBuilder buf = new StringBuilder();
buf.append('(');
buf.append("?<C"+area.getName()+">");
buf.append('(');
for(MessageArea item : ((AbstractMessageArea) area).getFields())
{
generReg(item,buf);
}
buf.append(")*"); //块级区域的可选
buf.append(')');
((AbstractMessageArea) area).setAnlyReg(buf.toString());
sb.append(buf);
}
else if(area.getType() == MessageArea.SEQLIST)
{
StringBuilder buf = new StringBuilder();
buf.append('(');
buf.append("?<S"+area.getName()+">");
buf.append('(');
for(MessageArea item : ((AbstractMessageArea) area).getFields())
{
generReg(item,buf);
}
SEQList seqlst = (SEQList)area;
buf.append(')');
if(seqlst.getCyc()>0)
buf.append(")+"); //块级区域的可选
buf.append(')');
if("O".equals(seqlst.getOm()))
buf.append('?');
((AbstractMessageArea) area).setAnlyReg(buf.toString());
sb.append(buf);
}
else if(area.getType() == MessageArea.CYC || area.getType() == MessageArea.SEQ)
{
StringBuilder buf = new StringBuilder();
for(MessageArea item : ((AbstractMessageArea) area).getFields())
{
generReg(item,buf);
}
((AbstractMessageArea) area).setAnlyReg(buf.toString());
sb.append(buf);
}
}
public static String generReg(SWFMessage swf)
{
StringBuilder sb = new StringBuilder();
generReg(swf,sb);
return sb.toString();
}
public static String readFull(String path)
{
try {
FileReader reader = new FileReader(path);
char[] buf = new char[1024];
try {
StringBuilder sb = new StringBuilder();
int len = -1;
while ((len = reader.read(buf)) != -1) {
sb.append(buf, 0, len);
}
reader.close();
return sb.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
{
/*
* @param msg:报文字符串; 传递报文字符串,将其中的文首都解析出来。 对于ACK/NCK报文,后面会附带原报,会出现文首重复的情况,将附带的原报文首的KEY添加负号做为KEY,避免覆盖。
* 如果后面附带了S等带字母的“文首”,则直接使用其Acsii码,作为KEY。
*/
public static Map<Integer, String> anlyMsgHead(String msg) {
Map<Integer, String> headSet = new HashMap<Integer, String>();
String reg = "\\{[\\d|S]:";
Matcher m = Pattern.compile(reg).matcher(msg);
int lstEnd = -1;
int lstHead = -1;
while (m.find()) {
if (lstEnd > 0 && lstHead > 0) {
String val = msg.substring(lstEnd, m.start() - 1);
if (!headSet.containsKey(lstHead)) {
headSet.put(lstHead, val);
} else {
headSet.put(-lstHead, val);
}
}
String g = m.group();
char c = g.charAt(1);
lstHead = c;
if (c >= '0' && c <= '9') // 对于是数字的,则以数字做KEY,否则以Acsii码做主键
lstHead -= '0';
lstEnd = m.end();
}
if (lstEnd > 0 && lstHead > 0) // 将最后一个文首存入Map
{
int lstidx = msg.lastIndexOf('}');
if (lstidx <= lstEnd)
return headSet;
if (!headSet.containsKey(lstHead))
headSet.put(lstHead, msg.substring(lstEnd, lstidx));
else
headSet.put(-lstHead, msg.substring(lstEnd, lstidx));
}
return headSet;
}
/*
* @param mt:对正文block 4中包含的栏位名称和栏位值切割,以换行符加“:”来切割
*/
public static List<String[]> msgTxtAnly(String mt) {
if (mt.startsWith(":"))
mt = "\r\n" + mt;
String[] tags = mt.split("[\\r\\n]{1,2}:(?=\\d{2}[A-Z]?:)");
List<String[]> list = new ArrayList<String[]>();
for (String tv : tags) {
if (tv.trim().length() > 0) {
int i = tv.indexOf(':');
if (i > 0) {
String[] arr = new String[2];
arr[0] = tv.substring(0, i);
arr[1] = tv.substring(i + 1);
list.add(arr);
}
}
}
if (list.size() > 0) {
String[] lstOne = list.get(list.size() - 1);
String lstStr = lstOne[1].trim();
int i = lstStr.lastIndexOf("\r\n");
if (i < 0) {
i = lstStr.lastIndexOf("\r");
}
if (i < 0) {
i = lstStr.lastIndexOf("\n");
}
if (i > -1) {
//清除末尾横线
String lstLine = lstStr.substring(i).trim();
if ("-".equals(lstLine))
lstOne[1] = lstStr.substring(0, i);
}
}
return list;
}
/* 屏蔽不同的系统的换行符差异,获取换行符位置 */
private static int getLinePos(String str) {
if (str == null)
return -1;
int idxr = str.indexOf("\r");
int idxn = str.indexOf("\n");
if (idxr > -1 && idxn > -1)// \r\n连接在一起
{
return idxr < idxn ? idxr : idxn;
} else {
return idxr <= idxn ? idxn : idxr;// 单个\r或者\n的情况,返回较大的
}
}
public static Map<String, String> getSwfMsgInfoViaMsg(Map<Integer, String> heads) {
Map<String, String> infMap = new HashMap<String, String>();
String hd4 = heads.get(4);
boolean isNACK = false; // 是否为ACK/NCK报文
if (hd4 != null) {
if (hd4.contains("{451:0}") || hd4.contains("{451:1}")) {
isNACK = true;
if (hd4.contains("{451:0}"))
infMap.put("mty", "ACK");
else
infMap.put("mty", "NCK");
// infMap.put("ehf",heads.get(-4) );
int errIdx = hd4.indexOf("{405:");
if (errIdx > -1) {
int idx2 = hd4.indexOf("}", errIdx);// 获取下一个括号
if (idx2 > -1)
infMap.put("errcod", hd4.substring(errIdx + 5, idx2));// 将错误码放进去
}
} else
// 非ACK 或NCK报文
{
}
}
/* 处理报文或者附带的报文的文首和正文 */
String hd2 = heads.containsKey(-2) ? heads.get(-2) : heads.get(2);
String hd1 = heads.containsKey(-1) ? heads.get(-1) : heads.get(1);
String hd3 = heads.containsKey(-3) ? heads.get(-3) : heads.get(3);
hd4 = heads.containsKey(-4) ? heads.get(-4) : heads.get(4);
String hd5 = heads.containsKey(-5) ? heads.get(-5) : heads.get(5);
if (hd5 != null)
infMap.put("trl", hd5);
String msgTyp = null; // 报文类型,如果为NCK/ACK报文,则该类型值为附带的原文里面的类型
String direct = null; // 报文收发方向
if (hd2 != null) // 拆解2文首
{
// 如果2文首不为空,开始获取收发方向和报文类型
if (hd2.length() >= 4) {
direct = hd2.substring(0, 1);
infMap.put("direct", direct);// 存储报文方向
msgTyp = hd2.substring(1, 4);
if ("I".equals(direct)) // 发出报文
{
if (hd2.length() >= 16) {
String rcvbic = hd2.substring(4, 16); // 获取收报行
infMap.put("rcvbic", rcvbic);
}
if (hd2.length() >= 17)
infMap.put("prt", hd2.substring(16, 17));// 电报优先级
if (hd2.length() >= 18)
infMap.put("tns", hd2.substring(17, 18));
if (hd2.length() >= 21)
infMap.put("dyt", hd2.substring(18, 21));
} else if ("O".equals(direct)) {
if (hd2.length() >= 26) {
String sndbic = hd2.substring(14, 26);
infMap.put("sndbic", sndbic); // 获取发报行
if (hd2.length() >= 36) {
infMap.put("mir", hd2.substring(8, 14) + " " + hd2.substring(14, 36));// 获取MIR
if (hd2.length() == 47)
infMap.put("prt", hd2.substring(46));// 电报优先级
}
}
}
}
}
if (hd1 != null) // 拆解1文首
{
if (hd1.length() >= 15) {
String bnk1 = hd1.substring(3, 15);
if ("O".equals(direct)) {
infMap.put("rcvbic", bnk1);
} else if ("I".equals(direct)) {
infMap.put("sndbic", bnk1);
}
if (hd2 != null && hd2.length() >= 14) {
infMap.put("mor", hd2.substring(8, 14) + " " + hd1.substring(3));// 获取MOR
}
}
}
if (hd3 != null) {
if (hd3.contains("{119:COV}")) {
msgTyp = msgTyp + "COV";
}
if (hd3.contains("{FMT:")) {
String fmt = hd3.substring(1, hd3.length() - 1);
String args[] = fmt.split(":");
infMap.put("fmttype", args[0]);
infMap.put("fmtstd", args[1]);
String strarry[] = hd3.split("\\}");
for (String substr : strarry) {
substr = substr.substring(1);
String sp[] = substr.split(":");
if (sp.length == 2) {
infMap.put(sp[0], sp[1]);
} else {
infMap.put(sp[0], null);
}
}
}
// else if(hd3.contains("{119:STP}"))
// msgTyp = msgTyp + "+";
Matcher m = Pattern.compile("\\{108:\\w+\\}").matcher(hd3);
if (m.find()) {
String gp = m.group();
int idx = gp.indexOf(":");
infMap.put("sndnum", gp.substring(idx + 1, gp.length() - 1)); /* 取发报流水号 */
}
}
infMap.put("std", "MT");
if (!isNACK)
infMap.put("mty", msgTyp);// 报文类型已经添加,存入Map中
else
infMap.put("emty", msgTyp);// 获取附带的报文类型
if (hd4 != null) // 处理4域,即正文
{
List<String[]> kv = msgTxtAnly(hd4);
for (String[] strArr : kv) {
if (strArr[1].trim().length() == 0)
continue;
if (strArr[0].endsWith("20"))// 业务编号
{
if (!infMap.containsKey("ref")) // 如果没有填入20栏,则将20栏填入,已填入则不进行覆盖。为nXX系列报文附带原报的情况
{
if (strArr[1].length() > 16)
infMap.put("ref", strArr[1].substring(0, 16).trim());
else
infMap.put("ref", strArr[1].trim());
}
}
if (strArr[0].endsWith("21"))// 相关编号
{
if (!infMap.containsKey("tscref")) // 如果没有填入21栏,则将21栏填入,已填入则不进行覆盖。为nXX系列报文附带原报的情况
{
if (strArr[1].length() > 16)
infMap.put("tscref", strArr[1].substring(0, 16));
else
infMap.put("tscref", strArr[1]);
}
}
if (strArr[0].endsWith("22C"))// 300报文的COMMON REFFERENCE
{
}
if (strArr[0].endsWith("32A"))// 金额币种起息日
{
if (strArr[1].matches("\\d{6}[A-Z]{3}\\d{1,15},\\d*")) {
String valDat = strArr[1].substring(0, 6);
String cur = strArr[1].substring(6, 9);
String amt = strArr[1].substring(9);
infMap.put("vludat", valDat);
infMap.put("amt", amt.replace(",", "."));
infMap.put("cur", cur);
}
}
if (strArr[0].matches("62[FM]")) {
// 950/940对账单的币种金额起息日
if (strArr[1] != null && strArr[1].matches("[DC]\\d{6}[A-Z]{3}\\d{1,15},\\d*")) {
String valDat = strArr[1].substring(1, 7);
String cur = strArr[1].substring(7, 10);
String amt = strArr[1].substring(10).replace(",", ".");
infMap.put("vludat", valDat);
infMap.put("amt", amt.replace(",", "."));
infMap.put("cur", cur);
} else
return infMap;
}
if (strArr[0].matches("25")) // 获取940/950里面的账号
{
String act = strArr[1];
infMap.put("act", act);
}
if ("O".equals(infMap.get("direct")) && strArr[0].matches("54A") && strArr[1] != null) {
String actbic = strArr[1];
int secondLine = getLinePos(actbic);
if (secondLine > -1) {
actbic = actbic.substring(secondLine);
actbic = actbic.replaceAll("\\r|\\n", "");// 去除遗留的\r\n
}
infMap.put("actbic", actbic);
}
if ("O".equals(infMap.get("direct")) && strArr[0].matches("53A") && strArr[1] != null) {
String actbic = strArr[1];
int secondLine = getLinePos(actbic);
if (secondLine > -1) {
actbic = actbic.substring(secondLine);
actbic = actbic.replaceAll("\\r|\\n", "");// 去除遗留的\r\n
}
infMap.put("t53bic", actbic);
}
if ("I".equals(direct) && strArr[0].matches("53A") && strArr[1] != null) {
String actbic = strArr[1];
int secondLine = getLinePos(actbic);
if (secondLine > -1) {
actbic = actbic.substring(secondLine);
actbic = actbic.replaceAll("\\r|\\n", "");// 去除遗留的\r\n
}
infMap.put("actbic", actbic);
}
if (strArr[0].matches("50[AK]") && strArr[1] != null) {
int index = getLinePos(strArr[1]);
if (index > -1 && strArr[1].startsWith("/"))
infMap.put("act", strArr[1].substring(1, index));
if (strArr[0].endsWith("K")) {
if (index > -1) {
String nam = strArr[1].substring(index).replaceAll("^[\\r\\n]{1,2}", "");
infMap.put("ordnamadr", nam);
} else {
infMap.put("ordnamadr", strArr[1]);
}
}
}
if (strArr[0].matches("59") && strArr[1] != null) {
int index = getLinePos(strArr[1]);
String nam = strArr[1];
if (index > -1 && strArr[1].startsWith("/")) {
String act = strArr[1].substring(1, index);// 取出前面的账号
infMap.put("act", act);// 填入59域的账号,收益人账号
infMap.put("benact", act);// 查询查复使用,需区分50域的账号
nam = strArr[1].substring(index).replaceAll("^[\\r\\n]{1,2}", "");
}
infMap.put("bennamadr", nam);
}
// 下面主要对MT300起作用
if (strArr[0].endsWith("22C")) {
if (!infMap.containsKey("comref")) // 如果没有填入22C栏
{
if (strArr[1].length() > 16)
infMap.put("comref", strArr[1].substring(0, 16));
else
infMap.put("comref", strArr[1]);
}
}
if (strArr[0].endsWith("33B") && strArr[1].length() > 0) {
String cur = strArr[1].substring(0, 3);
String amt = strArr[1].substring(3);
infMap.put("sellamt", amt.replace(",", "."));
infMap.put("sellcur", cur);
}
// 这里主要是对MT320起作用
if (strArr[0].endsWith("17R")) {
if (!infMap.containsKey("BorL"))
infMap.put("BorL", strArr[1]);
}
if (strArr[0].endsWith("34E")) {
String tagN = strArr[1].substring(0, 1);
String interest = "";
if ("N".equals(tagN))
interest = strArr[1].substring(4);
else
interest = strArr[1].substring(3);
infMap.put("interest", interest.replace(",", "."));
}
// 公共区域
if (strArr[0].endsWith("30V")) {
if (!infMap.containsKey("m3xValDate"))
infMap.put("m3xValDate", strArr[1]);
}
if (strArr[0].endsWith("32B")) {
String cur = strArr[1].substring(0, 3);
String amt = strArr[1].substring(3);
infMap.put("buyamt", amt.replace(",", "."));
infMap.put("buycur", cur);
}
}
}
return infMap;
}
/*
* @param msg:报文字符串 对报文信息的基本获取,如果是NCK/ACK报文则mty为NCK/ACK,如有附带报文,则附带的报文类型由emty记录
*/
public static Map<String, String> getSwfMsgInfoViaMsg(String msg) {
if (msg == null || msg.trim().length() == 0)
return new HashMap<String, String>();
Map<Integer, String> headers = anlyMsgHead(msg);
return getSwfMsgInfoViaMsg(headers);
}
/***
* 解析TD的格式报文
* @param msg
* @return
*/
public static Map<String, String> getSwfMsgInfoViaTDMsg(String msg) {
Map<String, String> bscInfo = new HashMap<String, String>();
String reg = ":MT:(\\d{3})[\\r\\n]{1,2}:IO:(\\w{2,11})[\\r\\n]{1,2}:II:(\\w{2,11})[\\r\\n]{1,2}:MP:(\\w)";
Matcher m = Pattern.compile(reg).matcher(msg);
if (!m.find())
return bscInfo;// 错误的格式
//bscInfo.put("mty", m.group(1));
bscInfo.put("sndbic", m.group(3));
bscInfo.put("rcvbic", m.group(2));
bscInfo.put("prt", m.group(4));
int idx = msg.indexOf(":EOH:", m.end());
String tdmsgHead = msg.substring(0, idx);
int begIndex = m.end(4);
reg = ":111:(\\d{3})(?=\\r|\\n)";
String restStr = tdmsgHead.substring(begIndex);
Matcher m2 = Pattern.compile(reg).matcher(restStr);
if (m2.find()) {
bscInfo.put("t111", m2.group(1).trim());
}
reg = ":121:([\\s\\S]+)(?=\\r|\\n)";
m2 = Pattern.compile(reg).matcher(restStr);
if (m2.find()) {
bscInfo.put("t121", m2.group(1).trim());
}
bscInfo.put("tdmsgHead", tdmsgHead);//存头,方便前端组报
//取111,121
if (tdmsgHead.indexOf(":119:COV") > -1) {
bscInfo.put("mty", m.group(1) + "COV");
} else
bscInfo.put("mty", m.group(1));
msg = msg.substring(idx + ":EOH:".length());
if (msg.endsWith("-"))
msg = msg.substring(0, msg.length() - 1);
Map<Integer, String> headers = new HashMap<Integer, String>();
headers.put(4, msg);
Map<String, String> infoMap = getSwfMsgInfoViaMsg(headers);
infoMap.put("mty", bscInfo.get("mty"));
bscInfo.putAll(infoMap);
return bscInfo;
}
public static SWFMessage loadSwiftFile(String path) {
return loadSwiftMessage(readFull(path));
}
public static SWFMessage loadSwiftMessage(String message) {
Map<Integer, String> headers = null;
Map<String, String> bscInfo = null;
if (message.startsWith(":MT:")) // TD内部报文
{
bscInfo = getSwfMsgInfoViaTDMsg(message);
int index = message.indexOf(":EOH:") + ":EOH:".length();
int lastIndex = message.lastIndexOf("-");
if (lastIndex > 0)
message = message.substring(index, lastIndex).trim();
else
message = message.substring(index);
headers = new HashMap<Integer, String>();
headers.put(4, message);
} else {
headers = anlyMsgHead(message);
bscInfo = getSwfMsgInfoViaMsg(headers);
}
//取出报文类型
String mty = bscInfo.get("mty");
System.out.println("---------" + mty);
SWFMessage swf = MessageFormat.getSWFMessage(mty);
swf.setHeaders(headers);
swf.setBscInfo(bscInfo);
List<String[]> tags = msgTxtAnly(headers.get(4));
String tagsCombo = getTagsStr(tags);
loadSwiftMessage(swf, tagsCombo, tags);
return swf;
}
private static int loadSwiftMessage(MessageArea area, String tagsCombo, List<String[]> tags) {
StringBuilder buf = new StringBuilder();
generReg(area, buf);
String reg = buf.toString();
Matcher m = Pattern.compile(reg).matcher(tagsCombo);
if (!m.find() || m.start() == m.end())
return -1; //栏位格式不符
List<MessageArea> fieldList = ((AbstractMessageArea) area).getFields();
for (int i = 0; i < fieldList.size(); i++) {
MessageArea item = fieldList.get(i);
if (item.getType() == MessageArea.TAG) {
//直接捕获对应分组
TagLine tag = (TagLine) item;
String grpName = "T" + String.valueOf(tag.getTno());
String value = m.group(grpName);
if (value == null)
continue;
String[] valArr = value.split(",");
//tag.setName(valArr[0]);
if (tag.getName().endsWith("a")) {
TagLine tag2 = TagFormat.getTagLine(valArr[0]);
tag.cellList = tag2.cellList;
tag.options = tag2.options;
tag.setName(valArr[0]);
tag.setPattern(tag2.getPattern());
tag.setAnalyzeReg(tag2.getAnalyzeReg());
tag.setMaxCnt(tag2.getMaxCnt());
// tag2.setDesp(tag.getDesp());
// tag2.setTno(tag.getTno());
// tag2.setName(valArr[0]);
// tag2.setStatus(tag.getStatus());
// tag2.getSuffix().addAll(tag.getSuffix());
// tag = tag2;
// fieldList.set(i, tag); //置换新的栏位
}
int idx = Integer.parseInt(valArr[1].substring(0, valArr[1].length() - 1));
tag.setValue(tags.get(idx)[1]);//还要考虑值分解
} else if (item.getType() == MessageArea.CYCLIST) {
String grpName = String.valueOf("C" + item.getName());
String value = m.group(grpName); //新的块级
if (value == null || value.length() == 0)
continue;
MessageArea cp = ((AbstractMessageArea) item).getFields().get(0);//默认有一个组项
int offset = 0;
do {
offset = loadSwiftMessage(cp, value, tags);
if (offset <= 0)
break;
if (offset >= value.length())
break; //提前终止,避免不必要的空循环
cp = ((AbstractMessageArea) item).getPattern().clone();
item.addSubArea(cp);
value = value.substring(offset);
}
while (true);
} else if (item.getType() == MessageArea.SEQLIST) {
String grpName = String.valueOf("S" + item.getName());
String value = m.group(grpName); //新的块级
if (value == null || value.length() == 0)
continue;
MessageArea cp = ((AbstractMessageArea) item).getFields().get(0);//默认有一个组项
int offset = 0;
do {
offset = loadSwiftMessage(cp, value, tags);
if (offset <= 0)
break;
if (offset >= value.length())
break; //提前终止,避免不必要的空循环
cp = ((AbstractMessageArea) item).getPattern().clone();
item.addSubArea(cp);
value = value.substring(offset);
}
while (true);
}
}
return m.end();
}
private static String getTagsStr(List<String[]> tags) {
StringBuilder buf = new StringBuilder();
int cnt = 0;
for (String[] item : tags) {
//System.out.println(item[0]+"-----"+item[1]);
buf.append(item[0] + "," + cnt);
cnt++;
buf.append(";");
}
return buf.toString();
}
public static void generReg(MessageArea area, StringBuilder sb) {
if (area.getType() == MessageArea.TAG) {
TagLine tag = (TagLine) area;
sb.append("(?<T" + tag.getTno() + ">");
if (tag.getSuffix().size() != 0) {
sb.append(tag.getName().substring(0, 2));
sb.append('[');
boolean hasOpt = false;
for (String item : tag.getSuffix()) {
if (item.length() == 2)
hasOpt = true;
else
sb.append(item.charAt(2));
}
sb.append(']');
if (hasOpt)
sb.append('?');
} else
sb.append(tag.getName());
sb.append(",\\d{1,3};)");
if ("O".equals(tag.getStatus()))
sb.append('?');
return;
}
String defaultReg = ((AbstractMessageArea) area).getAnlyReg();
if (defaultReg != null) {
sb.append(defaultReg);
return;
}
if (area instanceof SWFMessage) {
for (MessageArea item : ((AbstractMessageArea) area).getFields()) {
generReg(item, sb);
}
} else if (area.getType() == MessageArea.CYCLIST) {
StringBuilder buf = new StringBuilder();
buf.append('(');
buf.append("?<C" + area.getName() + ">");
buf.append('(');
for (MessageArea item : ((AbstractMessageArea) area).getFields()) {
generReg(item, buf);
}
buf.append(")*"); //块级区域的可选
buf.append(')');
((AbstractMessageArea) area).setAnlyReg(buf.toString());
sb.append(buf);
} else if (area.getType() == MessageArea.SEQLIST) {
StringBuilder buf = new StringBuilder();
buf.append('(');
buf.append("?<S" + area.getName() + ">");
buf.append('(');
for (MessageArea item : ((AbstractMessageArea) area).getFields()) {
generReg(item, buf);
}
SEQList seqlst = (SEQList) area;
if (seqlst.getCyc() > 0)
buf.append(")+"); //块级区域的可选
else
buf.append(')');
buf.append(')');
if ("O".equals(seqlst.getOm()))
buf.append('?');
((AbstractMessageArea) area).setAnlyReg(buf.toString());
sb.append(buf);
} else if (area.getType() == MessageArea.CYC || area.getType() == MessageArea.SEQ) {
StringBuilder buf = new StringBuilder();
for (MessageArea item : ((AbstractMessageArea) area).getFields()) {
generReg(item, buf);
}
((AbstractMessageArea) area).setAnlyReg(buf.toString());
sb.append(buf);
}
}
public static String generReg(SWFMessage swf) {
StringBuilder sb = new StringBuilder();
generReg(swf, sb);
return sb.toString();
}
public static String readFull(String path) {
try {
FileReader reader = new FileReader(path);
char[] buf = new char[1024];
try {
StringBuilder sb = new StringBuilder();
int len = -1;
while ((len = reader.read(buf)) != -1) {
sb.append(buf, 0, len);
}
reader.close();
return sb.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
// SWFMessage swf = MessageFormat.getSWFMessage("202COV");
// System.out.println(swf.toFormatJSON());
// MessageFormat.loadSWFMessage();
String path = "/Volumes/FUKAI/00034868.txt";
String msg = readFull(path);
SWFMessage swf =loadSwiftMessage(msg);
String path = "/Volumes/FUKAI/00034868.txt";
String msg = readFull(path);
SWFMessage swf = loadSwiftMessage(msg);
// String value =((TagLine)swf.getFields().get(2)).getValue();
// System.out.println(value);
System.out.println(swf.toJSON());
//System.out.println(value.matches(TagFormat.TagMap.get("79").toAnalyzeReg()));
}
System.out.println(swf.toJSON());
//System.out.println(value.matches(TagFormat.TagMap.get("79").toAnalyzeReg()));
}
}
......@@ -46,6 +46,7 @@ public class SEQList extends AbstractMessageArea {
cp.setAnlyReg(this.getAnlyReg());
cp.setDesp(this.getDesp());
cp.setOm(this.getOm());
cp.setCyc(this.getCyc());
return cp;
}
......
package com.brilliace.swifteditor.tag.message;
import com.brilliace.swifteditor.tag.TagFormat;
import com.brilliace.swifteditor.tag.TagLine;
import com.brilliace.swifteditor.util.Assert;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.regex.Pattern;
public class SWFMessage extends AbstractMessageArea {
final Pattern CHECKPATH = Pattern.compile("^\\d+(\\.\\d)?$");
Map<String, Object> genericCache = new HashMap<>();
private String mtType;
private Map<Integer, String> headers;
private Map<Integer, TagLine> flatModel = new HashMap<>();
private Map<String, String> bscInfo;
......@@ -136,7 +136,7 @@ public class SWFMessage extends AbstractMessageArea {
}
msg.setName(this.getName());
msg.setAnlyReg(this.getAnlyReg());
generateFlatModel(msg,msg.flatModel,null);
generateFlatModel(msg, msg.flatModel, null);
return msg;
}
......@@ -183,35 +183,231 @@ public class SWFMessage extends AbstractMessageArea {
return MESSAGE;
}
final Pattern CHECKPATH=Pattern.compile("^\\d+(\\.\\d)?$");
public String getGeneric(String path){
Assert.state(path != null && path != "" && CHECKPATH.matcher(path).find(),"索引["+path+"]不符合规范");
int index=path.indexOf(".");
public Map<String, Object> getGenericCache() {
return genericCache;
}
/**
* 根据指定坐标,填充具体域或者域块的值
* 待填充的数据类型有三种:<br/>
* 1.填充唯一域数据类型是String<br/>
* 2.填充循环域数据类型是List&lt;String&gt;<br/>
* 3.填充循环Sequence域数据类型是List&lt;List&gt;
*
* @param path 坐标,格式为No(.part) No表示域的序号,part是可选部分表示获取域的某个部分
* @param val 待填充得数据
*/
public void setGeneric(String path, Object val) {
setGeneric(path, val, null);
}
/**
* 根据指定坐标,填充具体或者多选域(譬如60a)或者域块的值
* 待填充的数据类型有三种:<br/>
* 1.填充唯一域数据类型是String<br/>
* 2.填充循环域数据类型是List&lt;String&gt;<br/>
* 3.填充循环Sequence域数据类型是List&lt;List&gt;
*
* @param path 坐标,格式为No(.part) No表示域的序号,part是可选部分表示获取域的某个部分
* @param val 待填充得数据
* @param tagName 域名称,对于多选域(譬如60a),需要提供该域具体选项(譬如60F)
*/
public void setGeneric(String path, Object val, String tagName) {
checkPath(path);
Assert.notNull(val, "对坐标[" + path + "]的赋值不能为空");
int index = path.indexOf(".");
TagLine tagLine;
if (index == -1) {
tagLine = this.flatModel.get(Integer.valueOf(path));
checkTagLine(tagLine, tagName);
if (tagLine.parent != null) {
setGenericRepetitive((AbstractMessageArea) tagLine.parent, index, tagLine.getTno(), (List<Object>) val, 0);
} else {
tagLine.setValue((String) val);
}
} else {
tagLine = this.flatModel.get(Integer.valueOf(path.substring(0, index)));
checkTagLine(tagLine, tagName);
int part = Integer.parseInt(path.substring(index + 1));
Assert.state(part >= 0 && part < tagLine.cellList.size(), "索引[" + path + "]指定的域块不存在");
if (tagLine.parent != null) {
setGenericRepetitive((AbstractMessageArea) tagLine.parent, part, tagLine.getTno(), (List<Object>) val, 0);
} else {
tagLine.cellList.get(part).value = (String) val;
}
}
}
private boolean setGenericRepetitive(AbstractMessageArea parent, int index, int ano, List<Object> rs, int cnt) {
if (parent.getType() == MessageArea.CYC || parent.getType() == MessageArea.SEQ) {
for (int i = 0; i < parent.getFields().size(); i++) {
MessageArea item = parent.getFields().get(i);
if (item.getType() == MessageArea.TAG) {
if (((TagLine) item).getTno() == ano) {
if (index == -1) {
((TagLine) item).setValue((String) rs.get(cnt));
} else {
((TagLine) item).cellList.get(index).value = (String) rs.get(cnt);
}
return true;
}
} else {
if (setGenericRepetitive((AbstractMessageArea) item, index, ano, rs, cnt)) {
return true;
}
}
}
} else if (parent.getType() == MessageArea.CYCLIST) {
MessageArea cp = ((AbstractMessageArea) parent).getFields().get(0);//默认有一个组项
do {
setGenericRepetitive((AbstractMessageArea) cp, index, ano, rs, cnt++);
if (rs.size() <= cnt)
return true;
try {
cp = ((AbstractMessageArea) parent).getFields().get(cnt);
} catch (Exception e) {
cp = ((AbstractMessageArea) parent).getPattern().clone();
parent.addSubArea(cp);
}
}
while (true);
} else if (parent.getType() == MessageArea.SEQLIST) {
MessageArea cp = ((AbstractMessageArea) parent).getFields().get(0);//默认有一个组项
do {
SEQList tmp = (SEQList) parent;
setGenericRepetitive((AbstractMessageArea) cp, index, ano, tmp.getCyc() == 1 ? (List<Object>) rs.get(cnt) : rs, 0);
if (rs.size() <= ++cnt)
return true;
try {
cp = ((AbstractMessageArea) parent).getFields().get(cnt);
} catch (Exception e) {
cp = ((AbstractMessageArea) parent).getPattern().clone();
parent.addSubArea(cp);
}
}
while (true);
}
return false;
}
private void checkTagLine(TagLine tag, String tagName) {
if (tag.getName().endsWith("a")) {
Assert.notNull(tagName, "多选报文域[" + tag.getName() + "]需要提供指定域选项");
TagLine tag2 = TagFormat.getTagLine(tagName);
Assert.notNull(tag2.getName(), "多选报文域[" + tag.getName() + "]提供的指定选项[" + tagName + "]不存在");
tag.cellList = tag2.cellList;
tag.options = tag2.options;
tag.setName(tagName);
tag.setPattern(tag2.getPattern());
tag.setAnalyzeReg(tag2.getAnalyzeReg());
tag.setMaxCnt(tag2.getMaxCnt());
}
}
/**
* 根据指定坐标,获取具体域或者域块的值。举例:950的61域对应的坐标是5;而对应的第一域块是5.0
* 调用getGeneric("5")会返回类型为List&lt;Object&gt;的所有域值<br/>
* 调用getGeneric("5.0")会返回类型为List&lt;Object&gt;的所有第一域块值<br/>
*
* @param path 坐标,格式为No(.part) No表示域的序号,part是可选部分表示获取域的某个部分
* @return 1.域不再Sequence中(如950报文的20,25域)或者在不可循环的Sequence中(如101报文的20域),返回值类型是String<br/>
* 2.域在循环中(如950报文的61域),返回类型List&lt;String&gt;<br/>
* 3.域在循环的Sequence中(如101报文的21域),返回类型List&lt;List&gt;,更复杂情况是嵌套N层循环域,则List也会嵌套N层<br/>
*/
public Object getGeneric(String path) {
checkPath(path);
Object rs = genericCache.get(path);
if (rs != null) {
return rs;
}
int index = path.indexOf(".");
TagLine tagLine;
if(index==-1){
tagLine=this.flatModel.get(Integer.valueOf(path));
return tagLine.getValue();
}else{
tagLine=this.flatModel.get(Integer.valueOf(path.substring(0,index)));
int part=Integer.parseInt(path.substring(index+1));
Assert.state(part>=0 && part < tagLine.cellList.size(),"索引["+path+"]指定的域块不存在");
return tagLine.cellList.get(part).value;
if (index == -1) {
tagLine = this.flatModel.get(Integer.valueOf(path));
if (tagLine.parent != null) {
rs = new LinkedList<Object>();
getGenericRepetitive((AbstractMessageArea) tagLine.parent, index, tagLine.getTno(), (List<Object>) rs);
} else {
rs = tagLine.getSourceValue();
}
} else {
tagLine = this.flatModel.get(Integer.valueOf(path.substring(0, index)));
int part = Integer.parseInt(path.substring(index + 1));
Assert.state(part >= 0 && part < tagLine.cellList.size(), "索引[" + path + "]指定的域块不存在");
if (tagLine.parent != null) {
rs = new LinkedList<Object>();
getGenericRepetitive((AbstractMessageArea) tagLine.parent, part, tagLine.getTno(), (List<Object>) rs);
} else {
rs = tagLine.cellList.get(part).value;
}
}
genericCache.put(path, rs);
return rs;
}
/**
* 根据指定坐标和索引,获取具体域或者域块{@link com.brilliace.swifteditor.tag.message.SWFMessage#getGeneric(java.lang.String)}
* 的具体一个成员
* @param path 坐标
* @param indexes 索引
* @return 返回具体成员
*/
public Object getGenericByIndexes(String path, int... indexes) {
Object generic = getGeneric(path);
if (indexes == null || indexes.length == 0) {
return generic;
}
for (int index : indexes) {
generic=((List<Object>)generic).get(index);
}
return generic;
}
private void getGenericRepetitive(AbstractMessageArea parent, int index, int ano, List<Object> rs) {
for (int i = 0; i < parent.getFields().size(); i++) {
MessageArea item = parent.getFields().get(i);
if (item.getType() == MessageArea.TAG) {
if (((TagLine) item).getTno() == ano) {
if (index == -1) {
rs.add(((TagLine) item).getSourceValue());
} else {
rs.add(((TagLine) item).cellList.get(index).value);
}
break;
} else if (((TagLine) item).getTno() > ano) {
break;
}
} else if (item.getType() == MessageArea.SEQ) {
if (parent.getType() == MessageArea.SEQLIST && ((SEQList) parent).getCyc() == 1) {
List<Object> sec = new LinkedList<>();
rs.add(sec);
getGenericRepetitive((AbstractMessageArea) item, index, ano, sec);
} else {
getGenericRepetitive((AbstractMessageArea) item, index, ano, rs);
}
} else {
getGenericRepetitive((AbstractMessageArea) item, index, ano, rs);
}
}
}
private void checkPath(String path) {
Assert.state(path != null && path != "" && CHECKPATH.matcher(path).find(), "索引[" + path + "]不符合规范");
}
private void generateFlatModel(MessageArea area, Map<Integer, TagLine> flatModel, MessageArea parent) {
List<MessageArea> fieldList = ((AbstractMessageArea) area).getFields();
for(int i=0; i< fieldList.size();i++) {
for (int i = 0; i < fieldList.size(); i++) {
MessageArea item = fieldList.get(i);
if (item.getType() == MessageArea.TAG) {
TagLine tagLine = (TagLine) item;
tagLine.parent=parent;
tagLine.parent = parent;
flatModel.put(tagLine.getTno(), tagLine);
} else if (item.getType() == MessageArea.CYCLIST || item.getType() == MessageArea.SEQLIST) {
generateFlatModel(((AbstractMessageArea) item).getFields().get(0), flatModel, item);
}else{
System.out.println(item.getType()+" no match");
generateFlatModel(((AbstractMessageArea) item).getFields().get(0), flatModel, parent != null ? parent : item);
} else {
System.err.println(item.getType() + " no match");
continue;
}
......
......@@ -5,8 +5,8 @@ import com.brilliace.swifteditor.tag.message.MessageFormat;
import com.brilliace.swifteditor.tag.message.SWFMessage;
import junit.framework.TestCase;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.LinkedList;
import java.util.List;
public class ParseSwiftTest extends TestCase {
public void testLoadSwiftMessage() {
......@@ -16,37 +16,98 @@ public class ParseSwiftTest extends TestCase {
System.out.println(swf.toJSON());
}
public void testGetSWFMessage() {
public void testGetFlatModel() {
SWFMessage obj = MessageFormat.getSWFMessage("101");
System.out.println(obj.getFlatModel());
}
public void testRegWithName() {
String reg = "((?<S1>\\d{6})((?<S2>\\d{4}))?)?((?<S3>[A-Z]{7}))?";
String tagsCombo = "123456";
Matcher m = Pattern.compile(reg).matcher(tagsCombo);
if (m.find()) {
System.out.println(m.group("S1"));
} else {
System.out.println("no found");
}
reg="^\\d+(\\.\\d)?$";
m = Pattern.compile(reg).matcher("122.");
if(m.find()){
System.out.println("yes");
}else{
System.out.println("no");
}
public void testGetGeneric() {
String path = ParseSwiftTest.class.getClassLoader().getResource("950.sf2").getPath();
String msg = MessageAnalyzer.readFull(path);
SWFMessage swf = MessageAnalyzer.loadSwiftMessage(msg);
System.out.println("获取4域(60F)=" + swf.getGeneric("4"));
System.out.println("获取4域第二部分(60F的<DATE2>部分)=" + swf.getGeneric("4.1"));
System.out.println("获取循环域5(61)=" + swf.getGeneric("5"));
System.out.println("获取循环域5第一域块(61的6!n)=" + swf.getGeneric("5.0"));
path = path = ParseSwiftTest.class.getClassLoader().getResource("101.sf2").getPath();
msg = MessageAnalyzer.readFull(path);
swf = MessageAnalyzer.loadSwiftMessage(msg);
System.out.println("获取1域(不可循环的Sequence A的20域)=" + swf.getGeneric("1"));
System.out.println("获取10域(循环的Sequence B的21域)=" + swf.getGeneric("10"));
System.out.println("获取12域(循环的Sequence B下的循环部分的23E域)=" + swf.getGeneric("12"));
}
public void testGetTagLineValue(){
String path = "F:\\brilliance\\jkpt-pj\\task\\南洋商业银行\\接口配置\\swift标准报文\\950.sf2";
public void testGetGenericByIndexes() {
String path = ParseSwiftTest.class.getClassLoader().getResource("950.sf2").getPath();
String msg = MessageAnalyzer.readFull(path);
SWFMessage swf = MessageAnalyzer.loadSwiftMessage(msg);
//获取3域
System.out.println(swf.getGeneric("3"));
//获取3域第一部分
System.out.println(swf.getGeneric("3.0"));
System.out.println("获取循环域5(61)的第二个成员=" + swf.getGenericByIndexes("5", 1));
System.out.println("获取循环域5第一域块(61的6!n)的第二个成员=" + swf.getGenericByIndexes("5.0", 1));
path = path = ParseSwiftTest.class.getClassLoader().getResource("101.sf2").getPath();
msg = MessageAnalyzer.readFull(path);
swf = MessageAnalyzer.loadSwiftMessage(msg);
System.out.println("获取12域(循环的Sequence B下的循环部分的23E域)的第二个sequence的第三个成员="
+ swf.getGenericByIndexes("12", 1, 2));
}
public void testSetGeneric() {
SWFMessage swf = MessageFormat.getSWFMessage("950");
//填充950的20域
swf.setGeneric("1", "STMMDL129058636E");
assertEquals(swf.getGeneric("1"), "STMMDL129058636E");
//填充950的60a域
swf.setGeneric("4", "C120330GBP94854,84", "60F");
assertEquals(swf.getGeneric("4"), "C120330GBP94854,84");
//填充950的60a域的第二部分
swf.setGeneric("4.1", "120330", "60F");
assertEquals(swf.getGeneric("4.1"), "120330");
//填充950的61循环域
List<String> sixtyone = new LinkedList<String>();
sixtyone.add("1204120402DP10000,25S103CP23712040100007//GBS020420N8IM0HT\n" +
"FENG XING");
sixtyone.add("1304220402DP30000,55S103CP23712040100003//GBS02042H98IM0HS\n" +
"FENG ZZWE");
sixtyone.add("1404320402DP20115,S103CP23712040200001//GBS020428Z8IVWJK\n" +
"FENG EFFE");
swf.setGeneric("5", sixtyone);
assertEquals(swf.getGeneric("5"), sixtyone);
//填充950的61域第5部分,Amount
swf = MessageFormat.getSWFMessage("950");
List<String> sixtyone_amount = new LinkedList<String>();
sixtyone_amount.add("10000,25");
sixtyone_amount.add("30000,55");
sixtyone_amount.add("20115,");
swf.setGeneric("5.4", sixtyone_amount);
assertEquals(swf.getGeneric("5.4"), sixtyone_amount);
//填充101的不可循环的Sequence A的20域
swf = MessageFormat.getSWFMessage("101");
List<String> one = new LinkedList<>();
one.add("STMMDL129058636E");
swf.setGeneric("1", one);
assertEquals(swf.getGeneric("1"), one);
//填充101的循环的Sequence B的21域
List<Object> comList = new LinkedList<>();
one = new LinkedList<>();
one.add("101651ATT000005W");
comList.add(one);
one = new LinkedList<>();
one.add("321651ATT000005Z");
comList.add(one);
swf.setGeneric("10", comList);
assertEquals(swf.getGeneric("10"), comList);
//填充101的循环的Sequence B的23E循环域
comList = new LinkedList<>();
one = new LinkedList<>();
one.add("CHQB/HELLO");
one.add("CHQB/WORLD");
comList.add(one);
one = new LinkedList<>();
one.add("CHQB/MY");
one.add("CHQB/NAME");
one.add("CHQB/IS");
comList.add(one);
swf.setGeneric("12", comList);
assertEquals(swf.getGeneric("12"), comList);
}
}
{1:F01PSBCCNBJAXXX0216122148}{2:O1010000120403MIDLGB22AXXX00000000001204030000N}{4:
:20:STMMDL129058636E
:28D:00066/00001
:30:123456
:21:101651ATT000005W
:23E:CHQB/HELLO
:23E:CHQB/WORLD
:32B:USD80000,
:59:/22222222222
STRIX LIMITED
FORREST HOUSE RONALDSWAY BALLASALLA
ISLE OF MAN UK
:71A:BEN
:21:321651ATT000005Z
:23E:CHQB/MY
:23E:CHQB/NAME
:23E:CHQB/IS
:32B:USD12322,11
:59:/11111111111
HOLLW LSHIUHIWA
WZDESSS HOUSE WAWAZDR
DEDFFF OF EE ZK
:71A:OUR
-}
\ No newline at end of file
{1:F01PSBCCNBJAXXX0216122148}{2:O9500000120403MIDLGB22AXXX00000000001204030000N}{4:
:20:STMMDL129058636E
:25:68446375
:28C:00066/00001
:60F:C120330GBP94854,84
:61:1204120402DP10000,25S103CP23712040100007//GBS020420N8IM0HT
FENG XING
:61:1304220402DP30000,55S103CP23712040100003//GBS02042H98IM0HS
FENG ZZWE
:61:1404320402DP20115,S103CP23712040200001//GBS020428Z8IVWJK
FENG EFFE
:62F:C120402GBP14739,84
:64:C120402GBP14739,84
-}{5:{CHK:EEE63030C50C}}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment