EZDATA 없는데, Ref필드에는 'ERP'로 되어 있는 경우, flat 전문 파싱 오류 처리
This commit is contained in:
@@ -295,6 +295,58 @@ public class StandardItem implements Serializable, Cloneable {
|
|||||||
this.isHidden = isHidden;
|
this.isHidden = isHidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 조건부 블록의 refValue 와 실제 필드값을 비교한다.
|
||||||
|
* FlatReader / StandardMessageCoordinator 와 동일한 기준을 쓰기 위한 공용 판정 로직이다.
|
||||||
|
* - '!' 접두사 : NOT 조건 (예: !S → S가 아닌 경우)
|
||||||
|
* - '|' 구분자 : OR 조건 (예: NM|EM → NM 또는 EM인 경우)
|
||||||
|
* - '!' 와 '|' 조합 가능 (예: !NM|EM → NM도 EM도 아닌 경우)
|
||||||
|
*/
|
||||||
|
public static boolean matchRefCondition(String refValue, String actualValue) {
|
||||||
|
if(refValue == null) return false;
|
||||||
|
String expect = refValue;
|
||||||
|
boolean negate = expect.startsWith("!");
|
||||||
|
if(negate) {
|
||||||
|
expect = expect.substring(1);
|
||||||
|
}
|
||||||
|
String actual = (actualValue == null) ? null : actualValue.trim();
|
||||||
|
boolean matched = false;
|
||||||
|
String[] expectValues = expect.split("\\|");
|
||||||
|
for(int i=0; i<expectValues.length; i++) {
|
||||||
|
if(expectValues[i].equals(actual)) {
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return negate ? !matched : matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FLAT 직렬화 시 이 GROUP 블록의 바이트를 출력할지 판단한다.
|
||||||
|
* FlatReader.traverse() 의 GROUP 처리와 같은 기준을 쓰기 위한 것으로,
|
||||||
|
* ref 조건이 성립하면 size==0(전문에 블록이 없어 미활성) 이어도 레이아웃 기본값으로 출력한다.
|
||||||
|
* 조건이 성립하는데 출력하지 않으면, 파서는 블록이 있다고 보고 읽어 오프셋이 어긋난다.
|
||||||
|
*
|
||||||
|
* @param root 조건 평가 기준이 되는 최상위 메시지. null 이면 조건 평가 없이 기존 규칙만 적용
|
||||||
|
* @param parentActivated 조건 성립으로 활성화된 상위 GROUP 하위인지 여부
|
||||||
|
*/
|
||||||
|
protected boolean isFlatGroupActive(StandardMessage root, boolean parentActivated) {
|
||||||
|
if(isHidden) return false;
|
||||||
|
if(getSize() > 0) return true;
|
||||||
|
if(root != null
|
||||||
|
&& StringUtils.isNotBlank(getRefPath())
|
||||||
|
&& StringUtils.isNotBlank(getRefValue())
|
||||||
|
&& matchRefCondition(getRefValue(), root.findItemValue(getRefPath())) ) {
|
||||||
|
if(logger.isDebugEnabled()) {
|
||||||
|
logger.debug("@GROUP name={} ACTIVATED by ref condition({}=[{}]). size=0 이지만 FLAT 출력 대상"
|
||||||
|
, getName(), getRefPath(), getRefValue());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 조건 성립으로 활성화된 상위 GROUP 하위의 무조건 블록은 함께 출력한다.
|
||||||
|
return parentActivated;
|
||||||
|
}
|
||||||
|
|
||||||
protected String toTypeValue(String svalue) {
|
protected String toTypeValue(String svalue) {
|
||||||
if(svalue == null) return svalue;
|
if(svalue == null) return svalue;
|
||||||
|
|
||||||
@@ -1007,6 +1059,15 @@ public class StandardItem implements Serializable, Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getBytesDataLength(String charset) {
|
public int getBytesDataLength(String charset) {
|
||||||
|
return getBytesDataLength(charset, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param root 조건부 블록(refPath/refValue) 평가 기준이 되는 최상위 메시지
|
||||||
|
* @param parentActivated 조건 성립으로 활성화된 상위 GROUP 하위인지 여부
|
||||||
|
* @see #isFlatGroupActive(StandardMessage, boolean)
|
||||||
|
*/
|
||||||
|
public int getBytesDataLength(String charset, StandardMessage root, boolean parentActivated) {
|
||||||
int totalSize = 0;
|
int totalSize = 0;
|
||||||
Iterator<String> keyIter = null;
|
Iterator<String> keyIter = null;
|
||||||
try {
|
try {
|
||||||
@@ -1016,23 +1077,25 @@ public class StandardItem implements Serializable, Cloneable {
|
|||||||
while(keyIter.hasNext()) {
|
while(keyIter.hasNext()) {
|
||||||
String key = keyIter.next();
|
String key = keyIter.next();
|
||||||
StandardItem item = childs.get(key);
|
StandardItem item = childs.get(key);
|
||||||
totalSize +=item.getBytesDataLength(charset);
|
totalSize +=item.getBytesDataLength(charset, root, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StandardType.FIELD :
|
case StandardType.FIELD :
|
||||||
totalSize += getLength();
|
totalSize += getLength();
|
||||||
break;
|
break;
|
||||||
case StandardType.GROUP :
|
case StandardType.GROUP :
|
||||||
// skip inactive/conditional group (size==0 means not activated)
|
// ref 조건이 성립하면 size==0 이어도 출력한다(FlatReader 와 동일 기준)
|
||||||
if( getSize() == 0 ) {
|
if( !isFlatGroupActive(root, parentActivated) ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isHidden) break;
|
// 출력하는 GROUP 의 하위 무조건 블록은 함께 출력한다.
|
||||||
|
// FlatReader 는 이 블록을 조건 없이 읽으므로 빼면 오프셋이 어긋난다.
|
||||||
|
boolean childActivated = true;
|
||||||
keyIter = childs.keySet().iterator();
|
keyIter = childs.keySet().iterator();
|
||||||
while(keyIter.hasNext()) {
|
while(keyIter.hasNext()) {
|
||||||
String key = keyIter.next();
|
String key = keyIter.next();
|
||||||
StandardItem item = childs.get(key);
|
StandardItem item = childs.get(key);
|
||||||
totalSize +=item.getBytesDataLength(charset);
|
totalSize +=item.getBytesDataLength(charset, root, childActivated);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StandardType.GRID :
|
case StandardType.GRID :
|
||||||
@@ -1050,7 +1113,7 @@ public class StandardItem implements Serializable, Cloneable {
|
|||||||
while(keyIter.hasNext()) {
|
while(keyIter.hasNext()) {
|
||||||
String key = keyIter.next();
|
String key = keyIter.next();
|
||||||
StandardItem item = group.get(key);
|
StandardItem item = group.get(key);
|
||||||
totalSize +=item.getBytesDataLength(charset);
|
totalSize +=item.getBytesDataLength(charset, root, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1086,6 +1149,15 @@ public class StandardItem implements Serializable, Cloneable {
|
|||||||
return toByteArray(true, charset);
|
return toByteArray(true, charset);
|
||||||
}
|
}
|
||||||
public byte[] toByteArray(boolean withBizData, String charset) {
|
public byte[] toByteArray(boolean withBizData, String charset) {
|
||||||
|
return toByteArray(withBizData, charset, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param root 조건부 블록(refPath/refValue) 평가 기준이 되는 최상위 메시지
|
||||||
|
* @param parentActivated 조건 성립으로 활성화된 상위 GROUP 하위인지 여부
|
||||||
|
* @see #isFlatGroupActive(StandardMessage, boolean)
|
||||||
|
*/
|
||||||
|
public byte[] toByteArray(boolean withBizData, String charset, StandardMessage root, boolean parentActivated) {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
Iterator<String> keyIter = null;
|
Iterator<String> keyIter = null;
|
||||||
// logger.debug("Encoding : {}", charset);
|
// logger.debug("Encoding : {}", charset);
|
||||||
@@ -1096,7 +1168,7 @@ public class StandardItem implements Serializable, Cloneable {
|
|||||||
while(keyIter.hasNext()) {
|
while(keyIter.hasNext()) {
|
||||||
String key = keyIter.next();
|
String key = keyIter.next();
|
||||||
StandardItem item = childs.get(key);
|
StandardItem item = childs.get(key);
|
||||||
bos.write(item.toByteArray(withBizData,charset)); //하위로 내려갈때 withBizDat 값이 없어져서 추가 jun's 20231101
|
bos.write(item.toByteArray(withBizData, charset, root, false)); //하위로 내려갈때 withBizDat 값이 없어져서 추가 jun's 20231101
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StandardType.FIELD :
|
case StandardType.FIELD :
|
||||||
@@ -1118,16 +1190,18 @@ public class StandardItem implements Serializable, Cloneable {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StandardType.GROUP :
|
case StandardType.GROUP :
|
||||||
// skip inactive/conditional group (size==0 means not activated)
|
// ref 조건이 성립하면 size==0 이어도 출력한다(FlatReader 와 동일 기준)
|
||||||
if( getSize() == 0 ) {
|
if( !isFlatGroupActive(root, parentActivated) ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isHidden) break;
|
// 출력하는 GROUP 의 하위 무조건 블록은 함께 출력한다.
|
||||||
|
// FlatReader 는 이 블록을 조건 없이 읽으므로 빼면 오프셋이 어긋난다.
|
||||||
|
boolean childActivated = true;
|
||||||
keyIter = childs.keySet().iterator();
|
keyIter = childs.keySet().iterator();
|
||||||
while(keyIter.hasNext()) {
|
while(keyIter.hasNext()) {
|
||||||
String key = keyIter.next();
|
String key = keyIter.next();
|
||||||
StandardItem item = childs.get(key);
|
StandardItem item = childs.get(key);
|
||||||
bos.write(item.toByteArray(withBizData,charset)); //하위로 내려갈때 withBizDat 값이 없어져서 추가 jun's 20231101
|
bos.write(item.toByteArray(withBizData, charset, root, childActivated)); //하위로 내려갈때 withBizDat 값이 없어져서 추가 jun's 20231101
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StandardType.GRID :
|
case StandardType.GRID :
|
||||||
@@ -1145,7 +1219,7 @@ public class StandardItem implements Serializable, Cloneable {
|
|||||||
while(keyIter.hasNext()) {
|
while(keyIter.hasNext()) {
|
||||||
String key = keyIter.next();
|
String key = keyIter.next();
|
||||||
StandardItem item = group.get(key);
|
StandardItem item = group.get(key);
|
||||||
bos.write(item.toByteArray(withBizData, charset)); //하위로 내려갈때 withBizDat 값이 없어져서 추가 jun's 20231101
|
bos.write(item.toByteArray(withBizData, charset, root, false)); //하위로 내려갈때 withBizDat 값이 없어져서 추가 jun's 20231101
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -461,7 +461,8 @@ public class StandardMessage extends StandardItem {
|
|||||||
while(keyIter.hasNext()) {
|
while(keyIter.hasNext()) {
|
||||||
String key = keyIter.next();
|
String key = keyIter.next();
|
||||||
StandardItem item = childs.get(key);
|
StandardItem item = childs.get(key);
|
||||||
bos.write(item.toByteArray(withBizData, charset));
|
// this 를 root 로 넘겨 조건부 블록(refPath/refValue)을 평가하게 한다
|
||||||
|
bos.write(item.toByteArray(withBizData, charset, this, false));
|
||||||
}
|
}
|
||||||
return bos.toByteArray();
|
return bos.toByteArray();
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
@@ -490,7 +491,7 @@ public class StandardMessage extends StandardItem {
|
|||||||
while(keyIter.hasNext()) {
|
while(keyIter.hasNext()) {
|
||||||
String key = keyIter.next();
|
String key = keyIter.next();
|
||||||
StandardItem item = childs.get(key);
|
StandardItem item = childs.get(key);
|
||||||
totalSize +=item.getBytesDataLength(charset);
|
totalSize +=item.getBytesDataLength(charset, this, false);
|
||||||
}
|
}
|
||||||
return totalSize;
|
return totalSize;
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
@@ -516,7 +517,7 @@ public class StandardMessage extends StandardItem {
|
|||||||
while (keyIter.hasNext()) {
|
while (keyIter.hasNext()) {
|
||||||
String key = keyIter.next();
|
String key = keyIter.next();
|
||||||
StandardItem item = find.childs.get(key);
|
StandardItem item = find.childs.get(key);
|
||||||
totalSize += item.getBytesDataLength(this.bizDataCharset);
|
totalSize += item.getBytesDataLength(this.bizDataCharset, this, false);
|
||||||
}
|
}
|
||||||
return totalSize;
|
return totalSize;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -121,24 +121,15 @@ public class FlatReader implements StandardReader {
|
|||||||
logger.debug("@GROUP name={}, getRefPath={}, refItemValue=[{}], getRefValue=[{}]"
|
logger.debug("@GROUP name={}, getRefPath={}, refItemValue=[{}], getRefValue=[{}]"
|
||||||
, currentItem.getName(), currentItem.getRefPath(), refItemValue, currentItem.getRefValue());
|
, currentItem.getName(), currentItem.getRefPath(), refItemValue, currentItem.getRefValue());
|
||||||
|
|
||||||
if(refItemValue != null) refItemValue = refItemValue.trim();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 값의 경우의수 NM,EM,""(blank)
|
* 값의 경우의수 NM,EM,""(blank)
|
||||||
* ! : NOT 조건 (예: !EM → EM이 아닌 경우)
|
* ! : NOT 조건 (예: !EM → EM이 아닌 경우)
|
||||||
* | : OR 조건 (예: NM|EM → NM 또는 EM인 경우)
|
* | : OR 조건 (예: NM|EM → NM 또는 EM인 경우)
|
||||||
* !와 | 조합 가능 (예: !NM|EM → NM도 아니고 EM도 아닌 경우)
|
* !와 | 조합 가능 (예: !NM|EM → NM도 아니고 EM도 아닌 경우)
|
||||||
|
* 판정 기준은 StandardItem.matchRefCondition 하나로 통일한다.
|
||||||
|
* (FLAT 직렬화 StandardItem.isFlatGroupActive 와 같은 기준이어야 오프셋이 어긋나지 않음)
|
||||||
*/
|
*/
|
||||||
String refValue = currentItem.getRefValue();
|
boolean matched = StandardItem.matchRefCondition(currentItem.getRefValue(), refItemValue);
|
||||||
boolean isNot = refValue.startsWith("!");
|
|
||||||
if (isNot) {
|
|
||||||
refValue = refValue.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean matched = matchRefValue(refValue, refItemValue);
|
|
||||||
if (isNot) {
|
|
||||||
matched = !matched;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!matched) {
|
if (!matched) {
|
||||||
logger.warn("@GROUP name={} SKIPPED.", currentItem.getName());
|
logger.warn("@GROUP name={} SKIPPED.", currentItem.getName());
|
||||||
@@ -307,21 +298,4 @@ public class FlatReader implements StandardReader {
|
|||||||
}
|
}
|
||||||
return refItemValue;
|
return refItemValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* refValue와 refItemValue를 비교하여 일치 여부를 반환
|
|
||||||
* | 구분자로 OR 조건 지원 (예: "NM|EM" → "NM" 또는 "EM"과 일치하면 true)
|
|
||||||
*/
|
|
||||||
private boolean matchRefValue(String refValue, String refItemValue) {
|
|
||||||
if (refValue.contains("|")) {
|
|
||||||
String[] values = refValue.split("\\|");
|
|
||||||
for (String val : values) {
|
|
||||||
if (val.equals(refItemValue)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return refValue.equals(refItemValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user