作者 xudada

Merge remote-tracking branch 'origin/forWechatService' into forWechatService

@@ -459,7 +459,7 @@ public class FFMInfo implements Serializable { @@ -459,7 +459,7 @@ public class FFMInfo implements Serializable {
459 459
460 private FFMInfo WayBillParse(String line,String uld) throws FFMResolveException { 460 private FFMInfo WayBillParse(String line,String uld) throws FFMResolveException {
461 //运单格式适配,这里注意空格字符 与连字符"-" 461 //运单格式适配,这里注意空格字符 与连字符"-"
462 - String pattern = "^(\\d{3}-\\d{8})([A-Z]{3})([A-Z]{3})/(T|P|S|M|D)(\\d+)(K)([0-9\\.]+)(MC)?([0-9\\.]+)?(DG)?([0-9\\.]+)?(T)?([0-9]+)?/.{1,15}"; 462 + String pattern = "^(\\d{3}-\\d{8})([A-Z]{3})([A-Z]{3})/(T|P|S|M|D)(\\d+)(K|L)([0-9\\.]+)([MCFI]{2})?([0-9\\.]+)?(DG)?([0-9\\.]+)?(T)?([0-9]+)?/.{1,15}";
463 // 创建 Pattern 对象 463 // 创建 Pattern 对象
464 Pattern r = Pattern.compile(pattern); 464 Pattern r = Pattern.compile(pattern);
465 // 现在创建 matcher 对象 465 // 现在创建 matcher 对象
@@ -473,6 +473,7 @@ public class FFMInfo implements Serializable { @@ -473,6 +473,7 @@ public class FFMInfo implements Serializable {
473 String waybillSplit = m.group(4); 473 String waybillSplit = m.group(4);
474 String waybillPiece = m.group(5); 474 String waybillPiece = m.group(5);
475 String waybillWeight = m.group(7); 475 String waybillWeight = m.group(7);
  476 + String waybillWeightCode = m.group(6);
476 String waybillVolume = m.group(9); 477 String waybillVolume = m.group(9);
477 String waybillDensity = m.group(11); 478 String waybillDensity = m.group(11);
478 String waybillTotalPiece = m.group(13); 479 String waybillTotalPiece = m.group(13);
@@ -2,9 +2,13 @@ @@ -2,9 +2,13 @@
2 import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ; 2 import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
3 import com.tianbo.analysis.NmmsAdminApplication; 3 import com.tianbo.analysis.NmmsAdminApplication;
4 import com.tianbo.analysis.exception.FFMResolveException; 4 import com.tianbo.analysis.exception.FFMResolveException;
  5 +import com.tianbo.analysis.model.FFMInfo;
  6 +import com.tianbo.analysis.model.ResultJson;
  7 +import com.tianbo.analysis.service.FFMResolve;
5 import com.tianbo.util.Date.DateUtil; 8 import com.tianbo.util.Date.DateUtil;
6 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
7 import org.junit.platform.commons.util.StringUtils; 10 import org.junit.platform.commons.util.StringUtils;
  11 +import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.boot.test.context.SpringBootTest; 12 import org.springframework.boot.test.context.SpringBootTest;
9 13
10 import javax.validation.constraints.NotNull; 14 import javax.validation.constraints.NotNull;
@@ -20,6 +24,9 @@ import java.util.regex.Pattern; @@ -20,6 +24,9 @@ import java.util.regex.Pattern;
20 @SpringBootTest(classes = NmmsAdminApplication.class) 24 @SpringBootTest(classes = NmmsAdminApplication.class)
21 @Slf4j 25 @Slf4j
22 public class FFMTest { 26 public class FFMTest {
  27 +
  28 + @Autowired
  29 + FFMResolve ffmResolve;
23 private String ffm = "ZCZC\n" + 30 private String ffm = "ZCZC\n" +
24 "QD SELKTCR SELKTCR ICNKO5X \n" + 31 "QD SELKTCR SELKTCR ICNKO5X \n" +
25 ".CGOFD1E 101732\n" + 32 ".CGOFD1E 101732\n" +
@@ -66,352 +73,14 @@ public class FFMTest { @@ -66,352 +73,14 @@ public class FFMTest {
66 "\n" + 73 "\n" +
67 "=\n" + 74 "=\n" +
68 "NNNN"; 75 "NNNN";
69 - private String flightNo;  
70 - private Date flightDate;  
71 - private String order;  
72 - private String originStation;  
73 - private String destinationStation="UNKONW";  
74 - private String planeNo;  
75 - private int currentLine = 0;  
76 - private static final String KEY_WORD_3 = "FFM,ULD,OSI,COR,OCI,DEG,DIM";  
77 - private static final String KEY_WORD_4 = "CONT,LAST";  
78 - private List<String> lineList = new ArrayList<>();  
79 76
80 77
81 78
82 @org.junit.jupiter.api.Test 79 @org.junit.jupiter.api.Test
83 public void send(){ 80 public void send(){
84 - try{  
85 -  
86 - if (StringUtils.isNotBlank(ffm)){  
87 - /**  
88 - * 检查报文是否包含尾部标识  
89 - */  
90 -  
91 - if(ffm.contains("CONT")|| ffm.contains("LAST")){  
92 - BufferedReader reader = new BufferedReader(new StringReader(ffm));  
93 - for ( String lineStr = reader.readLine();  
94 - lineStr != null;  
95 - lineStr = reader.readLine()){  
96 -// log.info("已读取行{}-{}",i,lineStr);  
97 - lineList.add(lineStr);  
98 - }  
99 - }else {  
100 - throw new FFMResolveException("报文尾部缺少文件结束标识LAST或者CONT");  
101 - }  
102 -  
103 -  
104 - resolve();  
105 - }  
106 - }catch (IOException ignored){  
107 - log.error(ignored.toString());  
108 - ignored.printStackTrace();  
109 - }catch (FFMResolveException ex){  
110 - log.error(ex.toString());  
111 - ex.printStackTrace();  
112 - }catch (ParseException e){  
113 - log.error("航班日期解析错误");  
114 - }  
115 - }  
116 -  
117 - /**  
118 - * 寻找FFM节点并解析航班信息以及航班第一目的站信息  
119 - * 找到FFM节点后,开始根据currentLine的值逐步一行一行解析  
120 - */  
121 - public void resolve() throws FFMResolveException,ParseException{  
122 - if (!lineList.isEmpty()){  
123 - int keyword_i = 0;  
124 - for (int i = 0; i < lineList.size(); i++) {  
125 - //根据行关键字走相应的解析逻辑  
126 - String line = lineList.get(i);  
127 - log.info("1.开始处理行[{}]-[{}]",i,line);  
128 - String keyword = keyword(line);  
129 - if (!"NOT_KEYWORD".equals(keyword)){  
130 - log.info("2.行[{}]包含关键字,开始处理",i);  
131 - if ("FFM".equals(keyword)){  
132 - currentLine = i;  
133 - //ffm版本  
134 - String ver = line.split("/")[1];  
135 - log.info("报文版本{}",ver.trim());  
136 -  
137 - //处理航班信息  
138 - currentLine++;  
139 - flight(lineList.get(currentLine).trim());  
140 -  
141 - /**  
142 - * 取第一目的站  
143 - * 这里注意,有的错误报文的航班节点后面没带或者忘了带目的站节点,  
144 - * 所以这里需要加个校验  
145 - */  
146 - currentLine++;  
147 - destination(lineList.get(currentLine).trim());  
148 - currentLine++;  
149 - }else if ("CONT".equals(keyword) || "LAST".equals(keyword) ){  
150 - keyword_i++;  
151 - }  
152 -  
153 - }  
154 - }  
155 - if (keyword_i==0){  
156 - throw new FFMResolveException("报文尾部缺少文件结束标识LAST或者CONT");  
157 - }  
158 - resolve_ULD_Waybill();  
159 - }  
160 -  
161 - }  
162 -  
163 - /**  
164 - * 判断是否有散舱  
165 - * 有BUP散舱先处理散舱,没有则进入ULD及ULD货物解析阶段  
166 - * 假设默认航班有散舱,将散舱的ULD号默认为 "BUP"  
167 - * 设置当前的ULD 为 散舱ULD "BUP"  
168 - * 那么散舱下的运单直到解析到真正的板箱号后,uld变成真正的货物板箱  
169 - */  
170 - public void resolve_ULD_Waybill() throws FFMResolveException{  
171 - log.info("5. 开始解析舱单列表");  
172 - String uld = "BUP";  
173 - for (int i = currentLine; i < lineList.size(); i++) {  
174 - String line = lineList.get(i);  
175 - log.info("5.1 开始解析行[{}]-[{}]",i,line);  
176 -  
177 - //行尾部结束标识检查  
178 - String keyword = keyword(line);  
179 - if ("CONT".equals(keyword) || "LAST".equals(keyword)){  
180 - log.info("[END] 已解析到文件结束标识[{}],解析完毕",keyword);  
181 - break;  
182 - }  
183 -  
184 - /**  
185 - * 多航班目的站解析  
186 - */  
187 - //校验正则1,取前三位验证是否是机场代码  
188 - String pattern_f = "^[A-Z]{3}$|^[A-Z]{3}/\\d{2}[A-Z]{3}\\d{4}";  
189 - // 创建 Pattern 对象  
190 - Pattern r_f = Pattern.compile(pattern_f);  
191 - // 现在创建 matcher 对象  
192 - Matcher mF = r_f.matcher(line);  
193 - if (mF.find()){  
194 - log.info("5-[FLIGHT] 适配到航班其他目的站");  
195 - String flightDes = line.substring(0,3);  
196 - if (!KEY_WORD_3.contains(flightDes)){  
197 - destinationStation = flightDes;  
198 - log.info("5-[FLIGHT] 新航班目的站为[{}]",destinationStation);  
199 - }  
200 - }  
201 - if ("UNKONW".equals(destinationStation)){  
202 - throw new FFMResolveException("航班目的站节点校验不通过.");  
203 - }  
204 -  
205 - if ("ULD".equals(keyword)){  
206 - log.info("5-[ULD] 此行为ULD信息行");  
207 - //板箱格式适配  
208 - String patternULD = "^ULD/([A-Z]{3}\\S{5}\\S{2})";  
209 - Pattern rULD = Pattern.compile(patternULD);  
210 - // 现在创建 matcher 对象  
211 - Matcher mULD = rULD.matcher(line);  
212 - if (mULD.find()){  
213 - log.info("5-[ULD] 查到分组{}",mULD.groupCount());  
214 -// for (int j1 = 1; j1 < mULD.groupCount()+1; j1++) {  
215 -// log.info("5-[ULD] 分组{}内容为:{}",j1,mULD.group(j1));  
216 -// }  
217 - uld= mULD.group(1);  
218 - log.info("5-[ULD] 当前ULD已变更为{}",uld);  
219 -  
220 - }else {  
221 - throw new FFMResolveException("ULD节点格式错误,无法适配正则(^ULD/([A-Z]{3})(\\S{5})(\\S{2})");  
222 - }  
223 - }  
224 -  
225 - //运单格式适配  
226 - String pattern = "^(\\d{3}-\\d{8})([A-Z]{3})([A-Z]{3})/(T|P|S|M)(\\d+)(K)([0-9\\.]+)(MC)?([0-9\\.]+)?(T)?([0-9]+)?/(\\S+)";  
227 - // 创建 Pattern 对象  
228 - Pattern r = Pattern.compile(pattern);  
229 - // 现在创建 matcher 对象  
230 - Matcher m = r.matcher(line);  
231 - if(m.find()){  
232 - log.info("5-[AWB] 行[{}]属于运单行,开始解析,当前板箱号为:{}",i,uld);  
233 - log.info("5-[AWB] 查到分组{}",m.groupCount());  
234 - String waybillNo = m.group(1);  
235 - String waybillOrigin = m.group(2);  
236 - String waybillDes = m.group(3);  
237 - String waybillSplit = m.group(4);  
238 - String waybillPiece = m.group(5);  
239 - String waybillWeight = m.group(7);  
240 - String waybillVolume = m.group(9);  
241 - String waybillTotalPiece = m.group(11);  
242 - String waybillGoodsDes = m.group(12);  
243 -  
244 -// for (int j = 1; j < m.groupCount()+1; j++) {  
245 -// log.info("5-[AWB] 分组{}内容为:{}",j,m.group(j));  
246 -// }  
247 -  
248 - if(model7Check(waybillNo)){  
249 - log.info("5-[AWB] 运单-({})模七校验通过",waybillNo);  
250 - }else {  
251 - log.error("{}运单模七校验不通过",waybillNo);  
252 - throw new FFMResolveException(waybillNo+"运单模七校验不通过");  
253 - }  
254 -  
255 - log.info("5-[AWB-INFO] 运单信息:报文序号:{} 所属航班:{}/{} 航班起始站/目的站:{}/{} 所属板箱:{} 运单号:{} 起始站/目的站:{}/{} 分批标识:{} 分批件重:{}/{} 体积:{} 总件数:{} 货物描述:{}",  
256 - order,  
257 - flightNo,  
258 - flightDate,  
259 - originStation,  
260 - destinationStation,  
261 - uld,  
262 - waybillNo,  
263 - waybillOrigin,  
264 - waybillDes,  
265 - waybillSplit,  
266 - waybillPiece,  
267 - waybillWeight,  
268 - waybillVolume,  
269 - waybillTotalPiece,  
270 - waybillGoodsDes);  
271 - }  
272 - }  
273 -  
274 - }  
275 -  
276 - /**  
277 - * 关键字识别  
278 - * @param text 每行的内容  
279 - * @return 识别为关键字的返回关键字,未被识别为关键字的返回NOT_KEYWORD;  
280 - * 返回的关键字 三字码关键字 机场代码关键字 文件结尾关键字 CONT,LAST  
281 - */  
282 - public String keyword(@NotNull String text){  
283 - //取每行前三位  
284 - if (StringUtils.isNotBlank(text) && text.length()>3){  
285 - String s_3 = text.substring(0,3);  
286 - String s_4 = text.substring(0,4);  
287 - if(KEY_WORD_3.contains(s_3)){  
288 - return s_3;  
289 - }  
290 - if(KEY_WORD_4.contains(s_4)){  
291 - return s_4;  
292 - }  
293 - }else if(text.length()==3){  
294 - log.info("{}很大可能是机场目的站",text);  
295 - }  
296 -  
297 - return "NOT_KEYWORD";  
298 - }  
299 -  
300 - /**  
301 - * 解析航班第一目的站  
302 - *  
303 - */  
304 - public void destination(String text) throws FFMResolveException{  
305 - log.info("4.开始校验处理航班目的站节点信息");  
306 - if (text.length()>=3){  
307 - //校验是否空货机  
308 - String pattern_nil = "[A-Z]{3}/NIL";  
309 - Pattern r_nil = Pattern.compile(pattern_nil);  
310 - // 现在创建 matcher 对象  
311 - Matcher m_nil = r_nil.matcher(text);  
312 - if (m_nil.find()){  
313 - log.info("4.1 航班目的站货物为空");  
314 - throw new FFMResolveException("航班第一目的站货物为空,解析结束");  
315 - }  
316 -  
317 - //校验是否是目的站节点  
318 - //校验正则1,取前三位验证是否是机场代码  
319 - String pattern = "^[A-Z]{3}$|^[A-Z]{3}/\\d{2}[A-Z]{3}\\d{4}";  
320 - // 创建 Pattern 对象  
321 - Pattern r = Pattern.compile(pattern);  
322 - // 现在创建 matcher 对象  
323 - Matcher m = r.matcher(text);  
324 - if (m.find()){  
325 - log.info("4.1 航班目的站节点校验通过");  
326 -  
327 - destinationStation = text.substring(0,3);  
328 - log.info("4.2 航班目的站一为[{}]",destinationStation);  
329 - }else {  
330 - log.error("4.1[ERROR] !!航班目的站节点校验不通过!!");  
331 - throw new FFMResolveException("航班目的站节点校验不通过.");  
332 - }  
333 - }else {  
334 - throw new FFMResolveException("航班目的站节点长度不对.");  
335 - }  
336 -  
337 -  
338 - }  
339 -  
340 -  
341 - public void flight(String text) throws FFMResolveException, ParseException {  
342 - log.info("3.开始处理航班信息");  
343 - String[] flight = text.split("/");  
344 - if (flight.length>3){  
345 - order = flight[0];  
346 - log.info("3.1 报文序号为{}",order);  
347 - flightNo = flight[1];  
348 - log.info("3.2 航班号为[{}]",flightNo);  
349 -  
350 -  
351 - //航班日期取出来的格式为10SEP或者10SEP1022,带时间的注意  
352 - String flightDateStr = flight[2];  
353 - log.info("3.3 航班日期信息为[{}]",flightDate);  
354 - String flightDateDay = flightDateStr.substring(0,2);  
355 - String flightDateMonth = flightDateStr.substring(2,5);  
356 -  
357 -  
358 - /**  
359 - * FFM跨年问题  
360 - * FFM报文中的月份为12月,当前服务器时间月份为1月,视为跨年.  
361 - * 跨年问题需要设置FFM报文的航班年份为当前年份-1  
362 - */  
363 - Calendar cal = Calendar.getInstance();  
364 - //当前年份  
365 - int yearNow = cal.get(Calendar.YEAR);  
366 - int monthNow = cal.get(Calendar.MONTH);  
367 -  
368 - if (monthNow == 1 && "DEC".equals(flightDateMonth)){  
369 - log.info("3.3.1 航班日期跨年");  
370 - yearNow = yearNow-1;  
371 - }  
372 -  
373 - flightDateStr = flightDateStr+yearNow;  
374 - flightDate = DateUtil.dateFormatFlight(flightDateStr);  
375 -  
376 -  
377 - originStation = flight[3];  
378 - log.info("3.4 航班起始站为[{}]",originStation);  
379 - if (flight.length>4){  
380 - planeNo = flight[4];  
381 - log.info("3.4 航班飞机号为[{}]",planeNo);  
382 - }  
383 - }else {  
384 - log.error("航班信息节点不正确");  
385 - throw new FFMResolveException("航班信息节点不正确");  
386 - }  
387 - }  
388 -  
389 -  
390 - /**  
391 - * 模七校验  
392 - * @param waybillNo  
393 - * @return  
394 - */  
395 - public boolean model7Check(String waybillNo){  
396 - String pattern = "\\d{3}-\\d{8}";  
397 - // 创建 Pattern 对象  
398 - Pattern r = Pattern.compile(pattern);  
399 - // 现在创建 matcher 对象  
400 - Matcher m = r.matcher(waybillNo);  
401 - if (m.find()){  
402 - String num = waybillNo.split("-")[1];  
403 - String num_7 = num.substring(0,7);  
404 - String num_end = num.substring(7,8);  
405 - if (Integer.parseInt(num_7)% 7 == Integer.parseInt(num_end)){  
406 - return true;  
407 - }else {  
408 - log.error("{}模七不通过",waybillNo);  
409 - }  
410 -  
411 - }else {  
412 - log.error("{}运单格式不正确",waybillNo);  
413 - }  
414 -  
415 - return false; 81 + FFMInfo ffmInfo = new FFMInfo();
  82 + ffmInfo.text = ffm;
  83 + ResultJson result = ffmResolve.resolve(ffmInfo);
  84 + return;
416 } 85 }
417 } 86 }