package com.brilliance.isc.swift.swifteditor.tag.message;

import com.brilliance.isc.swift.swifteditor.tag.TagCell;
import com.brilliance.isc.swift.swifteditor.tag.TagFormat;
import com.brilliance.isc.swift.swifteditor.tag.TagLine;
import com.brilliance.isc.swift.swifteditor.util.Assert;
import com.google.gson.Gson;

import java.io.*;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;
import java.util.regex.Pattern;

import static java.util.Arrays.asList;

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, Integer> tag2No = new HashMap<>();
    private Map<String, String> bscInfo;
    private volatile String body;
    private List<String[]> tags;

    public List<String[]> getTags() {
        return tags;
    }

    public void setTags(List<String[]> tags) {
        this.tags = tags;
    }

    protected SWFMessage() {
    }

    public static SWFMessage loadSwiftMessage(String message) {
        return MessageAnalyzer.loadSwiftMessage(message);
    }

    public static SWFMessage getSWFMessage(String mtType) {
        return MessageFormat.getSWFMessage(mtType);
    }

    public static SWFMessage loadMTTemp(String mt) {
        return null;
    }

    private static void toSubJson(AbstractMessageArea ma, StringBuilder sb) {
        sb.append("[\r\n");
        for (MessageArea sma : ma.getFields()) {
            if (sma.getType() == TAG) {
                TagLine tag = (TagLine) sma;
                if (tag.getName().startsWith("50")) {
                    //System.out.println(111);
                }
                sb.append(String.format("\t{\"tag\":\"%s\",\"status\":\"%s\",\"tno\":%d,\"letter\":%s,\"label\":\"%s\",\"tagValue\":%s},\r\n", tag
                                .getSuffix().size() > 0 && tag.getName().endsWith("a") ? tag.getSuffix().get(0) : tag.getName(), tag.getStatus(),
                        tag.getTno(), new Gson().toJson(tag.getSuffix()), tag.getDesp(),
                        new Gson().toJson(new Object[]{tag.getIndexMap(), tag.getSourceValue()})));
            } else if (sma.getType() == CYCLIST) {

                StringBuilder buff = new StringBuilder();
                // int first = 9999;
                for (MessageArea ssma : ((AbstractMessageArea) sma).getFields()) {
                    AbstractMessageArea temp = (AbstractMessageArea) ssma;
                    toSubJson(temp, buff);
                    buff.append(',');
                }
                sb.append(String.format("\t{\"cyclist\":\"%s\",\"cycs\":[", sma.getName()));
                // String temp = buff.toString().trim();
                sb.append(buff.subSequence(0, buff.length() - 1));
                sb.append("],\r\n\t\"pattern\":");
                buff = new StringBuilder();
                toSubJson((AbstractMessageArea) ((AbstractMessageArea) sma).getPattern(), buff);
                sb.append(buff);
                sb.append("\t},\r\n");
            } else if (sma.getType() == SEQLIST) {
                StringBuilder buff = new StringBuilder();
                // int first = 9999;
                for (MessageArea ssma : ((AbstractMessageArea) sma).getFields()) {
                    AbstractMessageArea temp = (AbstractMessageArea) ssma;
                    toSubJson(temp, buff);
                    buff.append(',');
                }
                SEQList seqlst = (SEQList) sma;
                sb.append(String.format("\t{\"seqlist\":\"%s\",\"cyccnt\":%d,\"status\":\"%s\",\"seqs\":[", sma.getName(), seqlst.getCyc(),
                        seqlst.getOm()));
                // String temp = buff.toString().trim();
                sb.append(buff.subSequence(0, buff.length() - 1));
                sb.append("],\r\n\t\"pattern\":");
                buff = new StringBuilder();
                toSubJson((AbstractMessageArea) ((AbstractMessageArea) sma).getPattern(), buff);
                sb.append(buff);
                sb.append(String.format(",\r\n\t\"desp\":\"%s\"", seqlst.getDesp()));
                sb.append("\t},\r\n");
            }

        }
        if (sb.length() > 3 && sb.charAt(sb.length() - 3) == ',')
            sb.setCharAt(sb.length() - 3, ' ');
        sb.append("]");
    }

    public Map<Integer, String> getHeaders() {
        return headers;
    }

    public void setHeaders(Map<Integer, String> headers) {
        Map<Integer, String> clone = new HashMap<Integer, String>();
        clone.putAll(headers);
        clone.remove(4);
        this.headers = clone;
    }

    public Map<Integer, TagLine> getFlatModel() {
        return this.flatModel;
    }

    public Map<String, String> getBscInfo() {
        return bscInfo;
    }

    public void setBscInfo(Map<String, String> bscInfo) {
        this.bscInfo = bscInfo;
    }

    public String getMtType() {
        return mtType;
    }

    public void setMtType(String mtType) {
        this.mtType = mtType;
    }

    /***
     *
     * @param sb
     *            缓存4文首域名
     */
    public void toSwfMessage(StringBuilder sb) {
        sb.append("{4:\r\n");
        for (MessageArea sub : this.getFields())
            sub.toSwfMessage(sb);
        sb.append("\r\n}");
    }

    public String toSwfMessage() {
        StringBuilder sb = new StringBuilder();
        toSwfMessage(sb);
        return sb.toString();
    }

    public SWFMessage clone() {
        SWFMessage msg = new SWFMessage();
        msg.mtType = this.mtType;
        for (MessageArea field : this.getFields()) {
            msg.addSubArea(field.clone());
        }
        msg.setName(this.getName());
        msg.setAnlyReg(this.getAnlyReg());
        generateFlatModel(msg, msg.flatModel, msg.tag2No, null, false);
        return msg;
    }

    public String toJSON() {
        Map<String, Object> rs = new HashMap<String, Object>();
        rs.put("title", this.getName());
        rs.put("mty", this.mtType);
        rs.put("snd_bic", bscInfo.get("sndbic"));
        rs.put("rcv_bic", bscInfo.get("rcvbic"));
        if (bscInfo.containsKey("t111"))
            rs.put("t111", bscInfo.get("t111"));
        if (bscInfo.containsKey("t121"))
            rs.put("t121", bscInfo.get("t121"));
        rs.put("tdheaders", bscInfo.get("tdmsgHead"));
        rs.put("headers", headers);
        rs.put("swift_message", toFormatJSON());
        return new Gson().toJson(rs);
        // return
        // String.format("{\r\ntitle:\"%s\",\r\nmty:'%s',\r\nrcv_bic:'%s',\r\ntdheader:'%s',\r\nheaders:%s,\r\nswift_message:%s\r\n}",
        // this.getName(),
        // this.mtType,
        // this.bscInfo.get("rcvbic"),
        // this.bscInfo.get("tdmsgHead")==null?null:URLEncoder.encode(this.bscInfo.get("tdmsgHead")),
        // new Gson().toJson( headers),
        // this.toFormatJSON()
        // );
    }

    public String toFormatJSON() {
        StringBuilder sb = new StringBuilder();
        // sb.append("const M='M' \r\n");
        // sb.append("const O='O' \r\n");
        // sb.append("const Tags=");

        toSubJson(this, sb);

        // sb.append("\r\nconst Title=\""+this.getName()+"\"");
        // sb.append("\r\n\r\nexport default { Tags,Title}");
        return sb.toString();
    }

    @Override
    public int getType() {
        return MESSAGE;
    }


    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 setGenericByNo(String path, Object val) {
        setGenericByNo(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 setGenericByNo(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) {
                if (val instanceof String && tagLine.onlyOne) {
                    if (tagLine.onlyOne) {
                        val = Collections.singletonList(val);
                    } else {
                        throw new IllegalArgumentException("域" + tagLine.getName() + "需要填充List集合类型的数据");
                    }
                }
                setGenericRepetitive((AbstractMessageArea) tagLine.parent, index, tagLine.getTno(), (List<Object>) val, 0, tagName);
            } 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)) + 1;
            Assert.state(part > 0, "索引[" + path + "]指定的域块不存在");
            if (tagLine.parent != null) {
                if (val instanceof String && tagLine.onlyOne) {
                    if (tagLine.onlyOne) {
                        val = Collections.singletonList(val);
                    } else {
                        throw new IllegalArgumentException("域" + tagLine.getName() + "需要填充List集合类型的数据");
                    }
                }
                setGenericRepetitive((AbstractMessageArea) tagLine.parent, part, tagLine.getTno(), (List<Object>) val, 0, tagName);
            } else {
                for (TagCell cell : tagLine.cellList) {
                    if (cell.cnt == part) {
                        cell.setValue((String) val);
                        break;
                    }
                }
            }
        }
    }

    /**
     * 根据指定域名(.域块号)表达式，填充具体域或者域块的值
     *
     * @param tagExp 域名(.域块号)表达式
     * @param val    待填充得数据
     *               待填充的数据类型有三种:<br/>
     *               1.填充唯一域数据类型是String<br/>
     *               2.填充循环域数据类型是List&lt;String&gt;<br/>
     *               3.填充循环Sequence域数据类型是List&lt;List&gt;
     */
    public void setGenericByTag(String tagExp, Object val) {
        String path = checkTag(tagExp);
        int index = tagExp.indexOf(".");
        setGenericByNo(path, val, index == -1 ? tagExp : tagExp.substring(0, index));
    }


    private boolean setGenericRepetitive(AbstractMessageArea parent, int index, int ano, List<Object> rs, int cnt, String tagName) {
        if (parent.getType() == CYC || parent.getType() == SEQ) {
            for (int i = 0; i < parent.getFields().size(); i++) {
                MessageArea item = parent.getFields().get(i);
                if (item.getType() == TAG) {
                    if (((TagLine) item).getTno() == ano) {
                        checkTagLine((TagLine) item, tagName);
                        if (index == -1) {
                            ((TagLine) item).setValue((String) rs.get(cnt));
                        } else {
                            for (TagCell cell : ((TagLine) item).cellList) {
                                if (cell.cnt == index) {
                                    cell.setValue((String) rs.get(cnt));
                                    break;
                                }
                            }
                        }
                        return true;
                    }
                } else {
                    if ((item.getType() == CYCLIST || item.getType() == SEQLIST) && !((AbstractMessageArea) item).withIn(ano)) {
                        continue;
                    }
                    if (parent.getType() == SEQ ?
                            setGenericRepetitive((AbstractMessageArea) item, index, ano, (List) rs.get(cnt), 0, tagName)
                            : setGenericRepetitive((AbstractMessageArea) item, index, ano, rs, cnt, tagName)) {
                        return true;
                    }
                }
            }
        } else if (parent.getType() == CYCLIST || parent.getType() == SEQLIST) {
            if (((AbstractMessageArea) parent).withIn(ano)) {
                MessageArea cp = ((AbstractMessageArea) parent).getFields().get(0);//默认有一个组项
                do {
                    setGenericRepetitive((AbstractMessageArea) cp, index, ano, rs, cnt++, tagName);
                    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;
    }

    /**
     * 根据指定域名(.域块号)表达式和索引,进行值得填充
     *
     * @param tagExp  域名(.域块号)表达式
     * @param val     待填充的值
     * @param indexes 索引
     */
    public void setGenericByTag(String tagExp, String val, Integer... indexes) {
        Assert.notNull(tagExp, "域名(.域块号)表达式不能为空");
        Assert.notNull(val, "待填充的值不能为空");
        if (indexes == null || indexes.length == 0) {
            //兼容接口平台EL调用setGenericByTag方法
            setGenericByTag(tagExp, val);
            return;
        }
        Object item = findMessageAreaByTag(tagExp, indexes);
        if (item instanceof TagLine) {
            TagLine tmp = (TagLine) item;
            tmp.setValue(val);
        } else {
            TagCell tmp = (TagCell) item;
            tmp.setValue(val);
        }
    }

    /**
     * 根据指定域名(.域块号)和索引,获取指定的域或域块对象
     *
     * @param tagExp  域名(.域块号)表达式
     * @param indexes 索引
     * @return 域或域块对象
     */
    public Object findMessageAreaByTag(String tagExp, Integer... indexes) {
        String path = checkTag(tagExp);
        int index = tagExp.indexOf(".");
        return findMessageArea(path, index == -1 ? tagExp : tagExp.substring(0, index), indexes);
    }

    private Object findMessageArea(String path, String tagName, Integer... indexes) {
        checkPath(path);
        int index = path.indexOf(".");
        TagLine tagLine = this.flatModel.get(index != -1 ? Integer.valueOf(path.substring(0, index)) : Integer.valueOf(path));
        Assert.notNull(tagLine, "不存在[" + tagName + "]对应的域");
        Object rs = null;
        if (tagLine.parent != null) {
            rs = findTagLine((AbstractMessageArea) tagLine.parent, tagLine.getTno(), asList(indexes), tagName, 0);
        }
        if (index != -1) {
            int part = Integer.parseInt(path.substring(index + 1)) + 1;
            tagLine = (TagLine) rs;
            for (TagCell cell : tagLine.cellList) {
                if (cell.cnt == part) {
                    rs = cell;
                    break;
                }
            }
        }
        return rs;
    }

    private TagLine findTagLine(AbstractMessageArea parent, int ano, List<Integer> cntLst, String tagName, int num) {
        if (parent.getType() == CYC || parent.getType() == SEQ) {
            for (int i = 0; i < parent.getFields().size(); i++) {
                MessageArea item = parent.getFields().get(i);
                if (item.getType() == TAG) {
                    if (((TagLine) item).getTno() == ano) {
                        checkTagLine((TagLine) item, tagName);
                        return (TagLine) item;
                    }
                } else {
                    if ((item.getType() == CYCLIST || item.getType() == SEQLIST) && !((AbstractMessageArea) item).withIn(ano)) {
                        continue;
                    }
                    return findTagLine((AbstractMessageArea) item, ano, cntLst, tagName, num);
                }
            }
        } else if (parent.getType() == CYCLIST || parent.getType() == SEQLIST) {
            if (((AbstractMessageArea) parent).withIn(ano)) {
                Integer cnt = cntLst.get(num++);
                if (parent.getType() == SEQLIST && ((SEQList) parent).getCyc() == 0) {
                    Assert.state(cnt == 0, "不能从非循环型Sequence获取索引大于0的对象");
                }
                MessageArea cp = null;
                for (int i = 0; i <= cnt; i++) {
                    try {
                        cp = ((AbstractMessageArea) parent).getFields().get(i);
                    } catch (Exception e) {
                        cp = ((AbstractMessageArea) parent).getPattern().clone();
                        parent.addSubArea(cp);
                    }
                }
                return findTagLine((AbstractMessageArea) cp, ano, cntLst, tagName, num);
            }
        }
        return null;
    }

    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());
        }
    }

    /**
     * 根据指定域名(.域块号)，获取域或者域块的值
     *
     * @param tagExp 域名(.域块号)
     * @return 域或者域块的值
     */
    public Object getGenericByTag(String tagExp) {
        String path = checkTag(tagExp);
        return getGenericByNo(path);
    }

    /**
     * 根据指定域名(.域块号)和索引，获取具体域或者域块的具体成员
     *
     * @param tagExp  域名(.域块号)
     * @param indexes 索引
     * @return 返回具体成员
     */
    public Object getGenericByTag(String tagExp, int... indexes) {
        String path = checkTag(tagExp);
        return getGenericByNo(path, indexes);
    }

    /**
     * 根据指定坐标，获取具体域或者域块的值。举例：950的61域对应的坐标是5;而对应的第一域块是5.0
     * 调用getGeneric("5")会返回类型为List&lt;Object&gt;的所有域值<br/>
     * 调用getGeneric("5.1")会返回类型为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 getGenericByNo(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));
            if (tagLine.parent != null) {
                rs = new LinkedList<Object>();
                getGenericRepetitive((AbstractMessageArea) tagLine.parent, index, tagLine.getTno(), (List<Object>) rs);
            } else {
                rs = tagLine.getValueForHuman();
            }
        } else {
            tagLine = this.flatModel.get(Integer.valueOf(path.substring(0, index)));
            int part = Integer.parseInt(path.substring(index + 1)) + 1;
            if (tagLine.parent != null) {
                rs = new LinkedList<Object>();
                getGenericRepetitive((AbstractMessageArea) tagLine.parent, part, tagLine.getTno(), (List<Object>) rs);
            } else {
                for (TagCell cell : tagLine.cellList) {
                    if (cell.cnt == part) {
                        rs = cell.value;
                        break;
                    }
                }
            }
        }
        if (rs instanceof List && tagLine.onlyOne) {
            rs = ((List<Object>) rs).get(0);
        }
        genericCache.put(path, rs);
        return rs;
    }

    /**
     * 根据指定坐标和索引，获取具体域或者域块{@link SWFMessage#getGenericByNo(java.lang.String)}
     * 的具体一个成员
     *
     * @param path    坐标
     * @param indexes 索引
     * @return 返回具体成员
     */
    public Object getGenericByNo(String path, int... indexes) {
        Object generic = getGenericByNo(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() == TAG) {
                if (((TagLine) item).getTno() == ano) {
                    if (index == -1) {
                        rs.add(((TagLine) item).getValueForHuman());
                    } else {
                        for (TagCell cell : ((TagLine) item).cellList) {
                            if (cell.cnt == index) {
                                rs.add(cell.value);
                                break;
                            }
                        }
                    }
                    break;
                } else if (((TagLine) item).getTno() > ano) {
                    break;
                }
            } else if (item.getType() == CYCLIST || item.getType() == SEQLIST) {
                if (!((AbstractMessageArea) item).withIn(ano)) {
                    continue;
                }
                if (parent.getType() == SEQ) {
                    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 String checkTag(String tagEXp) {
        String tag = tagEXp;
        int index = tagEXp.indexOf(".");
        if (index != -1) {
            tag = tagEXp.substring(0, index);
        }
        Assert.state(tag != null && tag != "" && tag2No.containsKey(tag),
                this.getMtType() + "类型报文不存在域[" + tag + "]");
        return index == -1 ? tag2No.get(tag).toString() : (tag2No.get(tag) + tagEXp.substring(index));
    }

    private void checkPath(String pathExp) {
        String path = pathExp;
        int index = pathExp.indexOf(".");
        if (index != -1) {
            path = pathExp.substring(0, index);
        }
        Assert.state(path != null && path != "" && CHECKPATH.matcher(path).find(), "索引[" + path + "]不符合规范");
        Assert.state(flatModel.containsKey(Integer.valueOf(path)),
                this.getMtType() + "类型报文不存在序号[" + path + "]对应的域");
    }

    public List<TagLine> collectAllTagLine() {
        List<TagLine> tagLines = new ArrayList<>();
        collectAllTagLine(this,tagLines);
        return tagLines;
    }

    public void collectAllTagLine(MessageArea area, List<TagLine> rs) {
        List<MessageArea> fieldList = ((AbstractMessageArea) area).getFields();
        for (int i = 0; i < fieldList.size(); i++) {
            MessageArea item = fieldList.get(i);
            if (item.getType() == TAG) {
                TagLine tagLine = (TagLine) item;
                rs.add(tagLine);
            } else if (item.getType() == CYCLIST || item.getType() == SEQLIST) {
                for(MessageArea field : ((AbstractMessageArea) item).getFields()){
                    collectAllTagLine(field, rs);
                }
            } else {
                continue;
            }

        }
    }

    private void generateFlatModel(MessageArea area, Map<Integer, TagLine> flatModel, Map<String, Integer> tag2No, MessageArea parent, boolean onlyOne) {
        List<MessageArea> fieldList = ((AbstractMessageArea) area).getFields();
        for (int i = 0; i < fieldList.size(); i++) {
            MessageArea item = fieldList.get(i);
            if (item.getType() == TAG) {
                TagLine tagLine = (TagLine) item;
                String tagNam = tagLine.getName();
                tagLine.parent = parent;
                tagLine.onlyOne = onlyOne;
                flatModel.put(tagLine.getTno(), tagLine);
                if (tagNam.endsWith("a") && tagLine.getSuffix().size() > 0) {
                    for (String tgn : tagLine.getSuffix()) {
                        tag2No.put(tgn, tagLine.getTno());
                    }
                } else {
                    tag2No.put(tagNam, tagLine.getTno());
                }
            } else if (item.getType() == CYCLIST || item.getType() == SEQLIST) {
                onlyOne = item.getType() == CYCLIST ? false :
                        ((item.getType() == SEQLIST && ((SEQList) item).getCyc() == 1) ? false : true);
                generateFlatModel(((AbstractMessageArea) item).getFields().get(0), flatModel, tag2No, parent != null ? parent : item, onlyOne);
            } else {
                // System.err.println(item.getType() + " no match");
                continue;
            }

        }
    }

    /**
     * 获取swift报文体
     * @param sndbic 发报行BIC
     * @param rcvbic 收报行BIC
     * @return
     */
    public String getMsg(String sndbic,String rcvbic) {
        if (body != null) {
            return body;
        }
        StringWriter sw = null;
        SwtBufferedWriter sb = null;
        try {
            Assert.notNull(sndbic, "发报行不能为空");
            Assert.notNull(rcvbic, "收报行不能为空");
            sw = new StringWriter();
            sb = this.new SwtBufferedWriter(sw);
            sb.write("{1:F01");
            sb.write(getLogicalTerminalAddress(sndbic, "1") + "0000000000");
            sb.write("}");
            sb.write("{2:I" + mtType.substring(0, 3));
            sb.write(getLogicalTerminalAddress(rcvbic, "2"));
            sb.write("N");
            sb.write("}");
            if (mtType.endsWith("COV")) {
                sb.write("{3:{119:COV}}");
            }
            sb.write("{4:");
            sb.newLine();
            printMsgBody(this, sb);
            sb.write("-}");
            sb.flush();
            body = sw.toString();
        } catch (Exception e) {
            return "获取报文体异常:" + e.getMessage();
        } finally {
            try {
                if (sb != null)
                    sb.close();
            } catch (IOException ioe) {
            }
        }
        return body;
    }

    /**
     * 获取swift报文体
     * @param sndbic 发报行BIC
     * @param rcvbic 收报行BIC
     * @return
     */
    public String getMsgCheck(String sndbic,String rcvbic) {
        if (body != null) {
            return body;
        }
        StringWriter sw = null;
        SwtBufferedWriter sb = null;
        try {
            Assert.notNull(sndbic, "发报行不能为空");
            Assert.notNull(rcvbic, "收报行不能为空");
            sw = new StringWriter();
            sb = this.new SwtBufferedWriter(sw);
            sb.write("{1:F01");
            sb.write(getLogicalTerminalAddress(sndbic, "1") + "0000000000");
            sb.write("}");
            sb.write("{2:I" + mtType.substring(0, 3));
            sb.write(getLogicalTerminalAddress(rcvbic, "2"));
            sb.write("N");
            sb.write("}");
            if (mtType.endsWith("COV")) {
                sb.write("{3:{119:COV}}");
            }
            sb.write("{4:");
            sb.newLine();

            // 写入 msg
            printCheckMsgBody(this, sb,getTags());


            sb.write("-}");
            sb.flush();
            body = sw.toString();
        } catch (Exception e) {
            return "正则匹配存在问题:" + e.getMessage();
        } finally {
            try {
                if (sb != null)
                    sb.close();
            } catch (IOException ioe) {
            }
        }
        return body;
    }

    private String getLogicalTerminalAddress(String bic, String field) {
        if (bic == null) {
            return null;
        }
        if ((bic.length() == 8) || (bic.length() == 11) || (bic.length() == 12)) {
            if (bic.length() == 11) {
                if ("1".equals(field)) {
                    return bic.substring(0, 8) + "A" + bic.substring(8, 11);
                }
                return bic.substring(0, 8) + "X" + bic.substring(8, 11);
            }

            if (bic.length() == 8) {
                if ("1".equals(field)) {
                    return bic.substring(0, 8) + "AXXX";
                }
                return bic.substring(0, 8) + "XXXX";
            }

            return bic;
        }
        throw new IllegalStateException("第" + field + "部分的bic码[" + bic + "]不符合规范，需满足8、11或12位长度");
    }

    private void printMsgBody(AbstractMessageArea ma, SwtBufferedWriter sb) throws IOException {
        for (MessageArea sma : ma.getFields()) {
            if (sma.getType() == TAG) {
                sb.write((TagLine) sma);
            } else {
                for (MessageArea ssma : ((AbstractMessageArea) sma).getFields()) {
                    AbstractMessageArea temp = (AbstractMessageArea) ssma;
                    printMsgBody(temp, sb);
                }
            }
        }
    }

    private void printCheckMsgBody(AbstractMessageArea ma, SwtBufferedWriter sb, List<String[]> tags) throws IOException {
        for (MessageArea sma : ma.getFields()) {
            if (sma.getType() == TAG) {
                sb.write((TagLine) sma);
            } else {
                for (MessageArea ssma : ((AbstractMessageArea) sma).getFields()) {
                    AbstractMessageArea temp = (AbstractMessageArea) ssma;
                    printMsgBody(temp, sb);
                }
            }
        }
    }

    class SwtBufferedWriter extends BufferedWriter {
        public static final String NEW_LINE = "\r\n";

        public SwtBufferedWriter(Writer arg0) {
            super(arg0);
        }

        public void newLine() throws IOException {
            write(NEW_LINE);
        }

        public void write(TagLine tagLine) throws IOException {
            checkNullForNeedField(tagLine);
            String val = tagLine.getValue();
            if (!val.equals("")) {
                write(":" + tagLine.getName() + ":");
                write(val);
                write(NEW_LINE);
            }
        }

        private void checkNullForNeedField(TagLine tagLine) {

            List<String[]> tags = getTags();

            boolean flag = "M".equals(tagLine.getStatus()) && "".equals(tagLine.getValue()) ? true : false;

            for(String[] tag:tags){
                if(tag[0].equals(tagLine.getName()))
                    Assert.state(!flag, "域[" + tagLine.getName() + "]存在问题   正则格式为：  "+ tagLine.getPattern() +
                            "   输入值为：" + tag[1]);
            }



        }

        // 检查Check规则
        private void checkCheckForNeedField(TagLine tagLine) {
            // boolean flag = "M".equals(tagLine.getStatus()) && "".equals(tagLine.getValue()) ? true : false;

            boolean flag = tagLine.getPattern().equals("");
            Assert.state(!flag, "域[" + tagLine.getName() + "]不符合正则校验规则");
        }
    }


    // 校验sf2文件,已读取tags.properties文件
    public String checkAll() throws IOException {

        ResultSet resultSet_FROM = null;
        Statement Statement_FROM = null;
        List<List<String>> list = null;

        // 循环查询 tags.properties文件，加载校验规则到map中，在校验报文时去匹配
        File f1 = new File("./resources/tags.properties");
        FileReader fr = new FileReader(f1);
        BufferedReader br = new BufferedReader(fr);

        String tagName = br.readLine();
        //每次读取文本文件中一行，返回字符串

        Map map = new HashMap();


        while (tagName != null) {

            // 按照读取的每行TagName去读取，生成类GetMsgBodyFor

            map.keySet();
            //每次读取文本文件中一行，返回字符串
            // 提取建立连接的文件
            StringBuilder str = new StringBuilder();

            // Tag形式
//            str.append("tagCreateList.add(new Tag"+tagName+"Creator(this));");




            tagName = br.readLine();
        }





        return null;
    }

}
