/**
* 2017-03-27 增加对直接传入数据的处理 张明伟
* 如果是DOC,则每次只传入一个
* 放入返回报文和原报文键值对
* @param filename
* @return
*/
public HashMap<String,String> parserXml(String filename) {
String returnValue = null;
HashMap<String,String> hm=new HashMap<String,String>();//放入返回报文和原报文键值对
String tb = null,dtb=null,msgid=null,md5str=null; //表,明细表,MSGID声明
String xmlOrder = null;
File file = null;
String filepath = "";
String longfilename = "";
String tmpfilename = "",tmpresult="PR00";
SqlEntityStatment sestmp0 = null,sestmp1=null;
SqlEntityStatment[] sestmps1=null, sestmps2=null;
String msgtype=null;
String workdate=null;
Document doc = null;
String sql;
String msghead=schemaPrefix1.trim() + "PUB_MSGHEAD";
String preclassname="com.citic.msgutil.xmlback.Create";
SAXReader sax = new SAXReader();
fileFlag = Boolean.parseBoolean(ConfigFileUtil.getValue("fileFlag"));
//修正
fileFlag=filename.length()>200?false:true;
CommFun.log(debuglevel, "fileFlag:" + fileFlag + ",filename:["
+ (fileFlag ? filename : filename.substring(0, 200)) + "]");
try {
if (fileFlag) {
CommFun.log(filename);
file = new File(filename);
filepath = file.getParent() + File.separator;
CommFun.log(INFO, "file:[" + file + "],path:[" + filepath + "]");
// 因为MQ接收的文件前缘是SUPIS,所以为了和原报文核对,保留原来的名字,除去SUPIS
// 请参见MQFileReceiver getGroupMessages方法
tmpfilename = file.getName();
int len = tmpfilename.length();
if (len > 9 && !tmpfilename.startsWith("PSIS")) {
tmpfilename = tmpfilename.substring(5, len - 4);
}
try {
doc = sax.read(file);
CommFun.log(debuglevel, "文件解析成功装入DOC!");
} catch (DocumentException e) {
CommFun.log(ERR, "解析文件失败:" + file+",尝试使用GBK编码再次解析!");
// e.printStackTrace();
try {
FileInputStream in=new FileInputStream(file);
doc = sax.read(new InputStreamReader(in, "GBK"));
CommFun.log(debuglevel, "文件以GBK编码解析成功装入DOC!");
} catch (DocumentException e1) {
CommFun.log(ERR, "解析文件尝试使用GBK编码再次解析失败:" + file+"!");
e.printStackTrace();
tmpresult = "PR21";
throw new RuntimeException(e1);
}
}
} else {
try {
doc = DocumentHelper.parseText(filename);
filepath = ConfigFileUtil.getInstance().getPathName()
+ "receive" + File.separator;
CommFun.log(debuglevel, "文件解析成功转换DOC!");
} catch (DocumentException e) {
CommFun.log(ERR,"解析文件失败,文件前200字:"+filename.substring(0, 200));
e.printStackTrace();
tmpresult="PR21";
throw new RuntimeException(e);
}
}
CommFun.log(debuglevel, "继续文件解析DOC!");
// Document doc = sax.read(new File(filepth + filename));
// sax.read(filename);
Element rootElement = doc.getRootElement();
String nameURI = rootElement.getNamespaceURI();
HashMap nsMap = new HashMap();
nsMap.put("ns", nameURI);
msgid = rootElement.element(msgHeader).element("MsgID")
.getTextTrim();
msgtype = rootElement.element(msgHeader).element("MsgType")
.getTextTrim();
xmlOrder = msgtype.substring(4, 7);
workdate = rootElement.element(msgHeader)
.element("Workdate").getTextTrim();
tb = ConfigFileUtil.getValue("T" + xmlOrder);
String[] strMsgtbs = { schemaPrefix1.trim() + "PUB_MSGHEAD",
schemaPrefix1.trim() + tb };
dtb = ConfigFileUtil.getValue("T" + xmlOrder + "D");
dtb=(dtb==null || "".equals(dtb)?"":schemaPrefix1.trim()+dtb);
CommFun.log(tb, "============","["+xmlOrder+"]", "============",dtb);
// System.out.println("workdate:"+workdate);
longfilename = filepath + "PSIS" + xmlOrder + "_";
// 非回送报文,只获取报文头内容,否则还需要原报文类型
if ("900".equals(xmlOrder)) {
longfilename += rootElement.element(msgBody)
.element("OriMsgType").getTextTrim().substring(4, 7)
+ "_";
}
// 通过String来的需要创建规则文件,以保持和原来的兼容
// 如果传入文件解析,则保留原来的文件名后缀(原文件名为SUPIS.....)
longfilename += workdate + "_"
+ (fileFlag ? tmpfilename : CommFun.strNowRand())
+ "_R.xml";
//如果传入的是文件名,则需要判断是否是正常的文件名还是加工后的
//,加工后的就不需要用新文件名了
//IF.1
if(tmpfilename.startsWith("PSIS")){
longfilename=filename;
}
//如果数据重复,则不需要进行创建
//IF.2 与IF.1对应,减少文件创建
//2017-06-13修改,因为有些支付机构把MSGID做为非唯一值了
//我们改为msgid和文件的md5值做唯一
if(!tmpfilename.startsWith("PSIS")){
XMLUtil.xmlCreate(doc, longfilename);
}
CommFun.log(debuglevel, longfilename);
md5str=MD5Util.getMD5String(longfilename);
//如果没有找到对应表,也需要进行解析,此步应该放到解析前
sestmp0 = XMLUtil.dispElementshead(doc, nsMap, msgHeader);
sql = "INSERT INTO " + strMsgtbs[0] + "(" + sestmp0.getSqlfileds()
+ ",FILENAME,FILEMD5STR)" + " VALUES (" + sestmp0.getSqlstr() + ",'"
+ longfilename + "','"+md5str+"')";
// 1.插入头
CommFun.log(DATA,sql);
DBOperation.executeSql(sql);
if ("".equals(tb)) {
String errormsg = "接收文件:[" +longfilename /*+ (fileFlag ? filename : filename.substring(0, 200))*/
+ "],报文号为:[" + xmlOrder
+ "]对应配置中对应的表不存在,请配置表名!";
throw new RuntimeException(errormsg);
}
int xoder=Integer.parseInt(xmlOrder);
String listtag="TxList";
//解析中所遇到的List tag需要与上层数据合并操作
switch (xoder) {
case 503:
listtag="DiffList"; // 503报文
break;
case 200:
listtag="ApplyList";
break;
default:
listtag="TxList";
break;
}
sestmp1 = XMLUtil.dispElementshead(doc, nsMap, msgBody);
sestmps1 = XMLUtil.dispElements1(doc, nsMap, listtag);
//CommFun.log(ALL,doc.asXML()+"--->"+nsMap.toString()+"--->"+listtag);
//CommFun.log(ALL,sestmps1.toString());
String[] bodytables=null;
//如果无明细数据表,则List和MsgBody混编成一组数据,否则分开存储(PSIS106)
if("".equals(dtb)){
//sestmps2中包含了merge后的混编数据,有N*1的关系
sestmps2 = XMLUtil.mergedata(sestmp1, sestmps1);
bodytables=new String[sestmps2.length];
for(int i=0;i<bodytables.length;i++){
bodytables[i]=strMsgtbs[1];
}
}else{
int seslen=0;
if(sestmps1!=null){
seslen=sestmps1.length;
}
CommFun.log(ALL, "解析出"+listtag+"个数为:"+seslen+"个!");
//sestmps2中包含了merge后的混合组成数据,有N+1的关系
sestmps2=new SqlEntityStatment[seslen+1];
//System.arraycopy(sestmps1, 0, sestmps2, 0, sestmps1.length-1); //明细表数据
for(int i=0;i<seslen;i++){
sestmps2[i]=sestmps1[i].clone();
}
CommFun.log(debuglevel,"sestmps2':"+sestmps2.length);
//PSIS106报文需要在插入明细数据中添加当前包序号
//20170502改为对所有的明细表都添加CurrentPkg字段
//if ("106".equals(xmlOrder)) {
sestmps2 = XMLUtil.mergedata(new SqlEntityStatment(
"CurrentPkg", sestmp1.getValue("CurrentPkg")),
sestmps2);
//}
sestmps2[seslen]=XMLUtil.mergedata(sestmp1, null)[0]; //插入汇总表
bodytables=new String[sestmps2.length];
for(int i=0;i<bodytables.length;i++){
bodytables[i]=dtb;
}
bodytables[bodytables.length-1]=strMsgtbs[1];
}
StringBuffer[] stb = null;
int sqllimit=30;
// 2.插入内容,可能是多条,也可以是多条
if (sestmps2 != null && sestmps2.length >= 1) {
stb = new StringBuffer[sestmps2.length];
// 多记录的msgbody
// 多条记录防止频繁对数据库进行操作,插入条数定为30
int cycle = (int) Math.ceil(sestmps2.length*1.0 / sqllimit);
int icycle=0;
int remainder = sestmps2.length % sqllimit;
//对于正好整除的情况,最后一次是sqllimit的个数
remainder = (remainder == 0 && cycle * sqllimit == sestmps2.length) ? sqllimit
: remainder;
CommFun.log(INFO, "总数量为:"+sestmps2.length+",批量总执行次数为:"+cycle+"次,"+sqllimit+"/次"+",最后一次条数为:"+remainder);
String[] sqlstr=null;
int j=0;
for (int i = 0; i < sestmps2.length && icycle<cycle; i++,j++) {
//分批执行,减少提交数据库的次数,一批SQL为30次
if(i%sqllimit==0){
sqlstr=null;
sqlstr=new String[(i>=(cycle-1)*sqllimit)?remainder:sqllimit];
j=0;
}
sqlstr[j]="INSERT INTO " + bodytables[i] + "(MSGID,DATADATE,"
+ sestmps2[i].getSqlfileds() + ")" + " VALUES ('"
+ msgid + "','" + workdate + "',"
+ sestmps2[i].getSqlstr() + ")";
//CommFun.log(DATA,"sqlstr["+sestmps2.length+":"+(icycle+1)+":"+(i+1)+":"+(j+1)+"]:"+sqlstr[j]);
//节约日志时间及空间,不再写,如果需要写,请直接把0改为DATA
CommFun.log(0,"sqlstr["+sestmps2.length+":"+(icycle+1)+":"+(i+1)+":"+(j+1)+"]:"+sqlstr[j]);
//执行批量插入
//如果
/*if ((i + 1) % sqllimit == 0
|| ((i >= (cycle - 1) * sqllimit) && (i + 1)
% remainder == 0))*/
if ((j + 1) % sqllimit == 0
|| ((i >= (cycle - 1) * sqllimit) && (j + 1)
% remainder == 0)) {
CommFun.log(debuglevel, "调用批量处理SQL,i's value:["
+ (i + 1) + "] and sqlstr.length:"
+ sqlstr.length);
DBOperation.executeBatchSql(sqlstr);
icycle++;
}
}
/*
for (int i = 0; i < sestmps2.length; i++) {
//分批执行,减少提交数据库的次数,一批SQL为30次
sql = "INSERT INTO " + strMsgtbs[1] + "(MSGID,DATADATE,"
+ sestmps2[i].getSqlfileds() + ")" + " VALUES ('"
+ msgid + "','" + workdate + "',"
+ sestmps2[i].getSqlstr() + ")";
CommFun.log(sql);
DBOperation.executeSql(sql);
}
*/
}/* else {
// 单记录的msgbody
sql = "INSERT INTO " + strMsgtbs[1] + "(MSGID,DATADATE,"
+ sestmp1.getSqlfileds() + ")" + " VALUES ('" + msgid
+ "','" + workdate + "'," + sestmp1.getSqlstr() + ")";
CommFun.log(sql);
DBOperation.executeSql(sql);
}*/
// 如果是901日切报文,则对日切进行更新
if ("901".equals(xmlOrder)) {
CommFun.log(INFO, "处理日切!");
DBOperation.setWorkdate();
}
/** 执行成功,需返回1 */
tmpresult="PR00";
sql="update "+msghead
+" set FILEDELSTAT = '"+"文件处理完毕"
+"' where msgid='"+msgid+"' and FILEMD5STR='"+md5str+"'";
} catch(SQLException se){
CommFun.log(debuglevel);
se.printStackTrace();
CommFun.log(debuglevel,
"" + se.getErrorCode() + ",--" + se.getSQLState());
if (se.getErrorCode() == -803) {
CommFun.log(debuglevel, se.getMessage());
tmpresult="MSGID:"+msgid+"的报文数据重复";
tmpresult="PR40";
} else {
tmpresult=se.getMessage();
tmpresult="PR41";
// throw new RuntimeException(se);
}
sql="update "+msghead
+" set FILEDELSTAT = '文件处理出错:SQLCODE:"+se.getErrorCode() /*+",SQLMESSAGE:"+se.getMessage()*/
+"' where msgid='"+msgid+"' and FILEMD5STR='"+md5str+"'";
} catch (Exception e) {
e.printStackTrace();
CommFun.log(ERR, e.getStackTrace().toString());
CommFun.log(ERR, e.getMessage());
sql="update "+msghead
+" set FILEDELSTAT = '"+"文件处理其它错:"+e.getMessage()
+"' where msgid='"+msgid+"' and FILEMD5STR='"+md5str+"'";
// throw new RuntimeException(e);
} finally{
}
CommFun.log(DATA, sql);
try {
DBOperation.executeSql(sql);
} catch (SQLException e) {
CommFun.log(ERR, e.getStackTrace().toString());
e.printStackTrace();
}
//需要回复的报文,才会做前后及900报文处理
//如100报文,则只需要入库后对入库数据进行校验,并根据数据是否存在返回900报文(100报文不需要事后处理)
//如803报文,则只需要入库后根据操作类型或变更类型进行后续处理,并返回900报文(不需要事前处理)
//20170425针对批量数据进行处理,可能在preexecute返回多条记录,生成900报文
CommFun.log(debuglevel, "xmlOrder:"+xmlOrder+","+Errors.getvalue("PSIS"+xmlOrder));
if (Errors.getvalue("PSIS"+xmlOrder).startsWith("Y") && !"".equals(tb)) {
//0.对数据入库前进行处理,如果有返回且不为空,CODE和MESSAGE可以做依据
HashMap<String,String[]> hm1=ReflectUtil.preexecute((Object)preclassname+xmlOrder+"xml",xmlOrder, msgid);
String rettext[]=null;
if (hm1 != null && hm1.size() > 0) {
String t1=(String) hm1.keySet().toArray()[0];
if(t1.startsWith("PR")){
tmpresult = t1;
CommFun.log(debuglevel, tmpresult);
}
rettext=hm1.get(t1);
}
CommFun.log(debuglevel, "hm1:"+hm1+",and tmpresult:"+tmpresult+",rettext:"+rettext);
if(rettext!=null && rettext.length>1){
for(String st:rettext){
returnValue = create900Msg(sestmp0, tmpresult, st);
hm.put(returnValue, longfilename);
}
}else{
returnValue = create900Msg(sestmp0, tmpresult, null);
hm.put(returnValue, longfilename);
}
//同时利用反射技术实现生成与本报文类型有关的业务回执
hm1 = ReflectUtil.execute((Object) preclassname + xmlOrder + "xml",
xmlOrder, msgid);
if(hm1!=null && hm1.size()>0){
for (String str : hm1.keySet()) {
hm.put(str, hm1.get(str)[0]);
}
}
CommFun.log(debuglevel, ""+hm);
}else{
CommFun.log(debuglevel,"因不需要回执或者没有对应配置表,不需要回执处理!");
}
return hm;
}