diff --git a/src/main/java/com/eactive/eai/message/StandardItem.java b/src/main/java/com/eactive/eai/message/StandardItem.java index 8da5eec..318d336 100644 --- a/src/main/java/com/eactive/eai/message/StandardItem.java +++ b/src/main/java/com/eactive/eai/message/StandardItem.java @@ -294,7 +294,59 @@ public class StandardItem implements Serializable, Cloneable { public void setHidden(boolean 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 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) { if(svalue == null) return svalue; @@ -1007,6 +1059,15 @@ public class StandardItem implements Serializable, Cloneable { } 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; Iterator keyIter = null; try { @@ -1016,24 +1077,26 @@ public class StandardItem implements Serializable, Cloneable { while(keyIter.hasNext()) { String key = keyIter.next(); StandardItem item = childs.get(key); - totalSize +=item.getBytesDataLength(charset); + totalSize +=item.getBytesDataLength(charset, root, false); } break; case StandardType.FIELD : totalSize += getLength(); break; case StandardType.GROUP : - // skip inactive/conditional group (size==0 means not activated) - if( getSize() == 0 ) { + // ref 조건이 성립하면 size==0 이어도 출력한다(FlatReader 와 동일 기준) + if( !isFlatGroupActive(root, parentActivated) ) { break; } - if (isHidden) break; + // 출력하는 GROUP 의 하위 무조건 블록은 함께 출력한다. + // FlatReader 는 이 블록을 조건 없이 읽으므로 빼면 오프셋이 어긋난다. + boolean childActivated = true; keyIter = childs.keySet().iterator(); while(keyIter.hasNext()) { String key = keyIter.next(); StandardItem item = childs.get(key); - totalSize +=item.getBytesDataLength(charset); - } + totalSize +=item.getBytesDataLength(charset, root, childActivated); + } break; case StandardType.GRID : if( getSize() == 0 @@ -1044,14 +1107,14 @@ public class StandardItem implements Serializable, Cloneable { break; } if (isHidden) break; - for(int p=0; p group = list.get(p); keyIter = group.keySet().iterator(); while(keyIter.hasNext()) { String key = keyIter.next(); StandardItem item = group.get(key); - totalSize +=item.getBytesDataLength(charset); - } + totalSize +=item.getBytesDataLength(charset, root, false); + } } break; case StandardType.FARRAY : @@ -1086,8 +1149,17 @@ public class StandardItem implements Serializable, Cloneable { return toByteArray(true, 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(); - Iterator keyIter = null; + Iterator keyIter = null; // logger.debug("Encoding : {}", charset); try { switch(getType()) { @@ -1096,7 +1168,7 @@ public class StandardItem implements Serializable, Cloneable { while(keyIter.hasNext()) { String key = keyIter.next(); 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; case StandardType.FIELD : @@ -1118,17 +1190,19 @@ public class StandardItem implements Serializable, Cloneable { } break; case StandardType.GROUP : - // skip inactive/conditional group (size==0 means not activated) - if( getSize() == 0 ) { + // ref 조건이 성립하면 size==0 이어도 출력한다(FlatReader 와 동일 기준) + if( !isFlatGroupActive(root, parentActivated) ) { break; } - if (isHidden) break; + // 출력하는 GROUP 의 하위 무조건 블록은 함께 출력한다. + // FlatReader 는 이 블록을 조건 없이 읽으므로 빼면 오프셋이 어긋난다. + boolean childActivated = true; keyIter = childs.keySet().iterator(); while(keyIter.hasNext()) { String key = keyIter.next(); 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; case StandardType.GRID : if( getSize() == 0 @@ -1139,14 +1213,14 @@ public class StandardItem implements Serializable, Cloneable { break; } if (isHidden) break; - for(int p=0; p group = list.get(p); keyIter = group.keySet().iterator(); while(keyIter.hasNext()) { String key = keyIter.next(); 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; case StandardType.FARRAY : diff --git a/src/main/java/com/eactive/eai/message/StandardMessage.java b/src/main/java/com/eactive/eai/message/StandardMessage.java index 9b6e56f..bc720ac 100644 --- a/src/main/java/com/eactive/eai/message/StandardMessage.java +++ b/src/main/java/com/eactive/eai/message/StandardMessage.java @@ -461,7 +461,8 @@ public class StandardMessage extends StandardItem { while(keyIter.hasNext()) { String key = keyIter.next(); 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(); } catch(Exception e) { @@ -490,7 +491,7 @@ public class StandardMessage extends StandardItem { while(keyIter.hasNext()) { String key = keyIter.next(); StandardItem item = childs.get(key); - totalSize +=item.getBytesDataLength(charset); + totalSize +=item.getBytesDataLength(charset, this, false); } return totalSize; } catch(Exception e) { @@ -516,7 +517,7 @@ public class StandardMessage extends StandardItem { while (keyIter.hasNext()) { String key = keyIter.next(); StandardItem item = find.childs.get(key); - totalSize += item.getBytesDataLength(this.bizDataCharset); + totalSize += item.getBytesDataLength(this.bizDataCharset, this, false); } return totalSize; } catch (Exception e) { diff --git a/src/main/java/com/eactive/eai/message/parser/FlatReader.java b/src/main/java/com/eactive/eai/message/parser/FlatReader.java index 7bcb93b..8e644ee 100644 --- a/src/main/java/com/eactive/eai/message/parser/FlatReader.java +++ b/src/main/java/com/eactive/eai/message/parser/FlatReader.java @@ -121,24 +121,15 @@ public class FlatReader implements StandardReader { logger.debug("@GROUP name={}, getRefPath={}, refItemValue=[{}], getRefValue=[{}]" , currentItem.getName(), currentItem.getRefPath(), refItemValue, currentItem.getRefValue()); - if(refItemValue != null) refItemValue = refItemValue.trim(); - /* * 값의 경우의수 NM,EM,""(blank) * ! : NOT 조건 (예: !EM → EM이 아닌 경우) * | : OR 조건 (예: NM|EM → NM 또는 EM인 경우) * !와 | 조합 가능 (예: !NM|EM → NM도 아니고 EM도 아닌 경우) + * 판정 기준은 StandardItem.matchRefCondition 하나로 통일한다. + * (FLAT 직렬화 StandardItem.isFlatGroupActive 와 같은 기준이어야 오프셋이 어긋나지 않음) */ - String refValue = currentItem.getRefValue(); - boolean isNot = refValue.startsWith("!"); - if (isNot) { - refValue = refValue.substring(1); - } - - boolean matched = matchRefValue(refValue, refItemValue); - if (isNot) { - matched = !matched; - } + boolean matched = StandardItem.matchRefCondition(currentItem.getRefValue(), refItemValue); if (!matched) { logger.warn("@GROUP name={} SKIPPED.", currentItem.getName()); @@ -307,21 +298,4 @@ public class FlatReader implements StandardReader { } 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); - } } \ No newline at end of file