Merge remote-tracking branch 'origin/forWechatService' into forWechatService
正在显示
2 个修改的文件
包含
13 行增加
和
343 行删除
@@ -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 | } |
-
请 注册 或 登录 后发表评论