切换导航条
此项目
正在载入...
登录
wlxxpt
/
customAnalysis
·
提交
转到一个项目
GitLab
转到群组
项目
活动
文件
提交
管道
0
构建
0
图表
里程碑
问题
0
合并请求
0
成员
标记
维基
派生
网络
创建新的问题
下载为
差异文件
浏览文件
作者
xudada
3 years ago
提交
e02c061d5b0ad4f40c00a68bfe0d484f4135d96c
2 个父辈
00dcb591
1bef7d2a
Merge remote-tracking branch 'origin/forWechatService' into forWechatService
显示空白字符变更
内嵌
并排对比
正在显示
2 个修改的文件
包含
13 行增加
和
343 行删除
src/main/java/com/tianbo/analysis/model/FFMInfo.java
src/test/java/FFMTest.java
src/main/java/com/tianbo/analysis/model/FFMInfo.java
查看文件 @
e02c061
...
...
@@ -459,7 +459,7 @@ public class FFMInfo implements Serializable {
private
FFMInfo
WayBillParse
(
String
line
,
String
uld
)
throws
FFMResolveException
{
//运单格式适配,这里注意空格字符 与连字符"-"
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}"
;
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}"
;
// 创建 Pattern 对象
Pattern
r
=
Pattern
.
compile
(
pattern
);
// 现在创建 matcher 对象
...
...
@@ -473,6 +473,7 @@ public class FFMInfo implements Serializable {
String
waybillSplit
=
m
.
group
(
4
);
String
waybillPiece
=
m
.
group
(
5
);
String
waybillWeight
=
m
.
group
(
7
);
String
waybillWeightCode
=
m
.
group
(
6
);
String
waybillVolume
=
m
.
group
(
9
);
String
waybillDensity
=
m
.
group
(
11
);
String
waybillTotalPiece
=
m
.
group
(
13
);
...
...
src/test/java/FFMTest.java
查看文件 @
e02c061
...
...
@@ -2,9 +2,13 @@
import
com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ
;
import
com.tianbo.analysis.NmmsAdminApplication
;
import
com.tianbo.analysis.exception.FFMResolveException
;
import
com.tianbo.analysis.model.FFMInfo
;
import
com.tianbo.analysis.model.ResultJson
;
import
com.tianbo.analysis.service.FFMResolve
;
import
com.tianbo.util.Date.DateUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.junit.platform.commons.util.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
javax.validation.constraints.NotNull
;
...
...
@@ -20,6 +24,9 @@ import java.util.regex.Pattern;
@SpringBootTest
(
classes
=
NmmsAdminApplication
.
class
)
@Slf4j
public
class
FFMTest
{
@Autowired
FFMResolve
ffmResolve
;
private
String
ffm
=
"ZCZC\n"
+
"QD SELKTCR SELKTCR ICNKO5X \n"
+
".CGOFD1E 101732\n"
+
...
...
@@ -66,352 +73,14 @@ public class FFMTest {
"\n"
+
"=\n"
+
"NNNN"
;
private
String
flightNo
;
private
Date
flightDate
;
private
String
order
;
private
String
originStation
;
private
String
destinationStation
=
"UNKONW"
;
private
String
planeNo
;
private
int
currentLine
=
0
;
private
static
final
String
KEY_WORD_3
=
"FFM,ULD,OSI,COR,OCI,DEG,DIM"
;
private
static
final
String
KEY_WORD_4
=
"CONT,LAST"
;
private
List
<
String
>
lineList
=
new
ArrayList
<>();
@org
.
junit
.
jupiter
.
api
.
Test
public
void
send
(){
try
{
if
(
StringUtils
.
isNotBlank
(
ffm
)){
/**
* 检查报文是否包含尾部标识
*/
if
(
ffm
.
contains
(
"CONT"
)||
ffm
.
contains
(
"LAST"
)){
BufferedReader
reader
=
new
BufferedReader
(
new
StringReader
(
ffm
));
for
(
String
lineStr
=
reader
.
readLine
();
lineStr
!=
null
;
lineStr
=
reader
.
readLine
()){
// log.info("已读取行{}-{}",i,lineStr);
lineList
.
add
(
lineStr
);
}
}
else
{
throw
new
FFMResolveException
(
"报文尾部缺少文件结束标识LAST或者CONT"
);
}
resolve
();
}
}
catch
(
IOException
ignored
){
log
.
error
(
ignored
.
toString
());
ignored
.
printStackTrace
();
}
catch
(
FFMResolveException
ex
){
log
.
error
(
ex
.
toString
());
ex
.
printStackTrace
();
}
catch
(
ParseException
e
){
log
.
error
(
"航班日期解析错误"
);
}
}
/**
* 寻找FFM节点并解析航班信息以及航班第一目的站信息
* 找到FFM节点后,开始根据currentLine的值逐步一行一行解析
*/
public
void
resolve
()
throws
FFMResolveException
,
ParseException
{
if
(!
lineList
.
isEmpty
()){
int
keyword_i
=
0
;
for
(
int
i
=
0
;
i
<
lineList
.
size
();
i
++)
{
//根据行关键字走相应的解析逻辑
String
line
=
lineList
.
get
(
i
);
log
.
info
(
"1.开始处理行[{}]-[{}]"
,
i
,
line
);
String
keyword
=
keyword
(
line
);
if
(!
"NOT_KEYWORD"
.
equals
(
keyword
)){
log
.
info
(
"2.行[{}]包含关键字,开始处理"
,
i
);
if
(
"FFM"
.
equals
(
keyword
)){
currentLine
=
i
;
//ffm版本
String
ver
=
line
.
split
(
"/"
)[
1
];
log
.
info
(
"报文版本{}"
,
ver
.
trim
());
//处理航班信息
currentLine
++;
flight
(
lineList
.
get
(
currentLine
).
trim
());
/**
* 取第一目的站
* 这里注意,有的错误报文的航班节点后面没带或者忘了带目的站节点,
* 所以这里需要加个校验
*/
currentLine
++;
destination
(
lineList
.
get
(
currentLine
).
trim
());
currentLine
++;
}
else
if
(
"CONT"
.
equals
(
keyword
)
||
"LAST"
.
equals
(
keyword
)
){
keyword_i
++;
}
}
}
if
(
keyword_i
==
0
){
throw
new
FFMResolveException
(
"报文尾部缺少文件结束标识LAST或者CONT"
);
}
resolve_ULD_Waybill
();
}
}
/**
* 判断是否有散舱
* 有BUP散舱先处理散舱,没有则进入ULD及ULD货物解析阶段
* 假设默认航班有散舱,将散舱的ULD号默认为 "BUP"
* 设置当前的ULD 为 散舱ULD "BUP"
* 那么散舱下的运单直到解析到真正的板箱号后,uld变成真正的货物板箱
*/
public
void
resolve_ULD_Waybill
()
throws
FFMResolveException
{
log
.
info
(
"5. 开始解析舱单列表"
);
String
uld
=
"BUP"
;
for
(
int
i
=
currentLine
;
i
<
lineList
.
size
();
i
++)
{
String
line
=
lineList
.
get
(
i
);
log
.
info
(
"5.1 开始解析行[{}]-[{}]"
,
i
,
line
);
//行尾部结束标识检查
String
keyword
=
keyword
(
line
);
if
(
"CONT"
.
equals
(
keyword
)
||
"LAST"
.
equals
(
keyword
)){
log
.
info
(
"[END] 已解析到文件结束标识[{}],解析完毕"
,
keyword
);
break
;
}
/**
* 多航班目的站解析
*/
//校验正则1,取前三位验证是否是机场代码
String
pattern_f
=
"^[A-Z]{3}$|^[A-Z]{3}/\\d{2}[A-Z]{3}\\d{4}"
;
// 创建 Pattern 对象
Pattern
r_f
=
Pattern
.
compile
(
pattern_f
);
// 现在创建 matcher 对象
Matcher
mF
=
r_f
.
matcher
(
line
);
if
(
mF
.
find
()){
log
.
info
(
"5-[FLIGHT] 适配到航班其他目的站"
);
String
flightDes
=
line
.
substring
(
0
,
3
);
if
(!
KEY_WORD_3
.
contains
(
flightDes
)){
destinationStation
=
flightDes
;
log
.
info
(
"5-[FLIGHT] 新航班目的站为[{}]"
,
destinationStation
);
}
}
if
(
"UNKONW"
.
equals
(
destinationStation
)){
throw
new
FFMResolveException
(
"航班目的站节点校验不通过."
);
}
if
(
"ULD"
.
equals
(
keyword
)){
log
.
info
(
"5-[ULD] 此行为ULD信息行"
);
//板箱格式适配
String
patternULD
=
"^ULD/([A-Z]{3}\\S{5}\\S{2})"
;
Pattern
rULD
=
Pattern
.
compile
(
patternULD
);
// 现在创建 matcher 对象
Matcher
mULD
=
rULD
.
matcher
(
line
);
if
(
mULD
.
find
()){
log
.
info
(
"5-[ULD] 查到分组{}"
,
mULD
.
groupCount
());
// for (int j1 = 1; j1 < mULD.groupCount()+1; j1++) {
// log.info("5-[ULD] 分组{}内容为:{}",j1,mULD.group(j1));
// }
uld
=
mULD
.
group
(
1
);
log
.
info
(
"5-[ULD] 当前ULD已变更为{}"
,
uld
);
}
else
{
throw
new
FFMResolveException
(
"ULD节点格式错误,无法适配正则(^ULD/([A-Z]{3})(\\S{5})(\\S{2})"
);
}
}
//运单格式适配
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+)"
;
// 创建 Pattern 对象
Pattern
r
=
Pattern
.
compile
(
pattern
);
// 现在创建 matcher 对象
Matcher
m
=
r
.
matcher
(
line
);
if
(
m
.
find
()){
log
.
info
(
"5-[AWB] 行[{}]属于运单行,开始解析,当前板箱号为:{}"
,
i
,
uld
);
log
.
info
(
"5-[AWB] 查到分组{}"
,
m
.
groupCount
());
String
waybillNo
=
m
.
group
(
1
);
String
waybillOrigin
=
m
.
group
(
2
);
String
waybillDes
=
m
.
group
(
3
);
String
waybillSplit
=
m
.
group
(
4
);
String
waybillPiece
=
m
.
group
(
5
);
String
waybillWeight
=
m
.
group
(
7
);
String
waybillVolume
=
m
.
group
(
9
);
String
waybillTotalPiece
=
m
.
group
(
11
);
String
waybillGoodsDes
=
m
.
group
(
12
);
// for (int j = 1; j < m.groupCount()+1; j++) {
// log.info("5-[AWB] 分组{}内容为:{}",j,m.group(j));
// }
if
(
model7Check
(
waybillNo
)){
log
.
info
(
"5-[AWB] 运单-({})模七校验通过"
,
waybillNo
);
}
else
{
log
.
error
(
"{}运单模七校验不通过"
,
waybillNo
);
throw
new
FFMResolveException
(
waybillNo
+
"运单模七校验不通过"
);
}
log
.
info
(
"5-[AWB-INFO] 运单信息:报文序号:{} 所属航班:{}/{} 航班起始站/目的站:{}/{} 所属板箱:{} 运单号:{} 起始站/目的站:{}/{} 分批标识:{} 分批件重:{}/{} 体积:{} 总件数:{} 货物描述:{}"
,
order
,
flightNo
,
flightDate
,
originStation
,
destinationStation
,
uld
,
waybillNo
,
waybillOrigin
,
waybillDes
,
waybillSplit
,
waybillPiece
,
waybillWeight
,
waybillVolume
,
waybillTotalPiece
,
waybillGoodsDes
);
}
}
}
/**
* 关键字识别
* @param text 每行的内容
* @return 识别为关键字的返回关键字,未被识别为关键字的返回NOT_KEYWORD;
* 返回的关键字 三字码关键字 机场代码关键字 文件结尾关键字 CONT,LAST
*/
public
String
keyword
(
@NotNull
String
text
){
//取每行前三位
if
(
StringUtils
.
isNotBlank
(
text
)
&&
text
.
length
()>
3
){
String
s_3
=
text
.
substring
(
0
,
3
);
String
s_4
=
text
.
substring
(
0
,
4
);
if
(
KEY_WORD_3
.
contains
(
s_3
)){
return
s_3
;
}
if
(
KEY_WORD_4
.
contains
(
s_4
)){
return
s_4
;
}
}
else
if
(
text
.
length
()==
3
){
log
.
info
(
"{}很大可能是机场目的站"
,
text
);
}
return
"NOT_KEYWORD"
;
}
/**
* 解析航班第一目的站
*
*/
public
void
destination
(
String
text
)
throws
FFMResolveException
{
log
.
info
(
"4.开始校验处理航班目的站节点信息"
);
if
(
text
.
length
()>=
3
){
//校验是否空货机
String
pattern_nil
=
"[A-Z]{3}/NIL"
;
Pattern
r_nil
=
Pattern
.
compile
(
pattern_nil
);
// 现在创建 matcher 对象
Matcher
m_nil
=
r_nil
.
matcher
(
text
);
if
(
m_nil
.
find
()){
log
.
info
(
"4.1 航班目的站货物为空"
);
throw
new
FFMResolveException
(
"航班第一目的站货物为空,解析结束"
);
}
//校验是否是目的站节点
//校验正则1,取前三位验证是否是机场代码
String
pattern
=
"^[A-Z]{3}$|^[A-Z]{3}/\\d{2}[A-Z]{3}\\d{4}"
;
// 创建 Pattern 对象
Pattern
r
=
Pattern
.
compile
(
pattern
);
// 现在创建 matcher 对象
Matcher
m
=
r
.
matcher
(
text
);
if
(
m
.
find
()){
log
.
info
(
"4.1 航班目的站节点校验通过"
);
destinationStation
=
text
.
substring
(
0
,
3
);
log
.
info
(
"4.2 航班目的站一为[{}]"
,
destinationStation
);
}
else
{
log
.
error
(
"4.1[ERROR] !!航班目的站节点校验不通过!!"
);
throw
new
FFMResolveException
(
"航班目的站节点校验不通过."
);
}
}
else
{
throw
new
FFMResolveException
(
"航班目的站节点长度不对."
);
}
}
public
void
flight
(
String
text
)
throws
FFMResolveException
,
ParseException
{
log
.
info
(
"3.开始处理航班信息"
);
String
[]
flight
=
text
.
split
(
"/"
);
if
(
flight
.
length
>
3
){
order
=
flight
[
0
];
log
.
info
(
"3.1 报文序号为{}"
,
order
);
flightNo
=
flight
[
1
];
log
.
info
(
"3.2 航班号为[{}]"
,
flightNo
);
//航班日期取出来的格式为10SEP或者10SEP1022,带时间的注意
String
flightDateStr
=
flight
[
2
];
log
.
info
(
"3.3 航班日期信息为[{}]"
,
flightDate
);
String
flightDateDay
=
flightDateStr
.
substring
(
0
,
2
);
String
flightDateMonth
=
flightDateStr
.
substring
(
2
,
5
);
/**
* FFM跨年问题
* FFM报文中的月份为12月,当前服务器时间月份为1月,视为跨年.
* 跨年问题需要设置FFM报文的航班年份为当前年份-1
*/
Calendar
cal
=
Calendar
.
getInstance
();
//当前年份
int
yearNow
=
cal
.
get
(
Calendar
.
YEAR
);
int
monthNow
=
cal
.
get
(
Calendar
.
MONTH
);
if
(
monthNow
==
1
&&
"DEC"
.
equals
(
flightDateMonth
)){
log
.
info
(
"3.3.1 航班日期跨年"
);
yearNow
=
yearNow
-
1
;
}
flightDateStr
=
flightDateStr
+
yearNow
;
flightDate
=
DateUtil
.
dateFormatFlight
(
flightDateStr
);
originStation
=
flight
[
3
];
log
.
info
(
"3.4 航班起始站为[{}]"
,
originStation
);
if
(
flight
.
length
>
4
){
planeNo
=
flight
[
4
];
log
.
info
(
"3.4 航班飞机号为[{}]"
,
planeNo
);
}
}
else
{
log
.
error
(
"航班信息节点不正确"
);
throw
new
FFMResolveException
(
"航班信息节点不正确"
);
}
}
/**
* 模七校验
* @param waybillNo
* @return
*/
public
boolean
model7Check
(
String
waybillNo
){
String
pattern
=
"\\d{3}-\\d{8}"
;
// 创建 Pattern 对象
Pattern
r
=
Pattern
.
compile
(
pattern
);
// 现在创建 matcher 对象
Matcher
m
=
r
.
matcher
(
waybillNo
);
if
(
m
.
find
()){
String
num
=
waybillNo
.
split
(
"-"
)[
1
];
String
num_7
=
num
.
substring
(
0
,
7
);
String
num_end
=
num
.
substring
(
7
,
8
);
if
(
Integer
.
parseInt
(
num_7
)%
7
==
Integer
.
parseInt
(
num_end
)){
return
true
;
}
else
{
log
.
error
(
"{}模七不通过"
,
waybillNo
);
}
}
else
{
log
.
error
(
"{}运单格式不正确"
,
waybillNo
);
}
return
false
;
FFMInfo
ffmInfo
=
new
FFMInfo
();
ffmInfo
.
text
=
ffm
;
ResultJson
result
=
ffmResolve
.
resolve
(
ffmInfo
);
return
;
}
}
...
...
请
注册
或
登录
后发表评论