Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 229156d51d | |||
| f9e6522b8f | |||
| cd5cb4c0b5 |
@@ -0,0 +1,107 @@
|
|||||||
|
package com.eactive.eai.transformer.function.generic;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import org.nfunk.jep.ParseException;
|
||||||
|
import org.nfunk.jep.function.PostfixMathCommand;
|
||||||
|
|
||||||
|
import com.eactive.eai.common.property.PropManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JEP 커스텀 함수 - PropManager 프러퍼티 그룹 기반 값 매핑
|
||||||
|
*
|
||||||
|
* <p>고정된 변환 룰이 아닌, PropManager의 프러퍼티 그룹(예: 공통코드 매핑 테이블)을
|
||||||
|
* 동적으로 조회하여 입력값을 매핑된 값으로 변환한다.
|
||||||
|
* 매핑 정보는 {@code 1000 -> AAAAA}, {@code 1001 -> BBBBB} 처럼 그룹의 key/value로 관리된다.
|
||||||
|
*
|
||||||
|
* <p>사용법:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code getmapping(group, value)} - group 프러퍼티 그룹에서 value에 매핑된 값을 반환.
|
||||||
|
* 매핑이 없으면 <b>원본 value를 그대로 반환</b>(passthrough)</li>
|
||||||
|
* <li>{@code getmapping(group, value, default)} - 매핑이 없으면 <b>default</b>를 반환</li>
|
||||||
|
* </ul>
|
||||||
|
* 파라미터:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code group} - PropManager 프러퍼티 그룹명 (문자열)</li>
|
||||||
|
* <li>{@code value} - 매핑 대상 값. 숫자여도 되며 조회 시 문자열 key로 변환된다
|
||||||
|
* (정수형 숫자는 {@code 1000.0}이 아닌 {@code "1000"}으로 조회)</li>
|
||||||
|
* <li>{@code default} - (선택) 매핑이 없을 때 반환할 기본값</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>예: 그룹 "COMMON_CODE"에 {@code 1000=AAAAA}가 있을 때
|
||||||
|
* {@code getmapping("COMMON_CODE", "1000")} → {@code "AAAAA"}
|
||||||
|
*/
|
||||||
|
public class GetMapping extends PostfixMathCommand {
|
||||||
|
public GetMapping() {
|
||||||
|
numberOfParameters = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 스택에서 (group, value) 또는 (group, value, default)를 꺼내 매핑값을 조회한다.
|
||||||
|
*
|
||||||
|
* @param inStack JEP 후위 연산 스택
|
||||||
|
* @throws ParseException 파라미터 개수가 2 또는 3이 아니거나 group이 문자열이 아닌 경우
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void run(Stack inStack) throws ParseException {
|
||||||
|
checkStack(inStack);
|
||||||
|
|
||||||
|
int n = curNumberOfParameters;
|
||||||
|
if (n != 2 && n != 3) {
|
||||||
|
throw new ParseException(
|
||||||
|
"getmapping() requires 2 or 3 parameters: getmapping(group, value [, default])");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasDefault = (n == 3);
|
||||||
|
Object defaultValue = hasDefault ? inStack.pop() : null;
|
||||||
|
Object value = inStack.pop();
|
||||||
|
Object groupObj = inStack.pop();
|
||||||
|
|
||||||
|
if (!(groupObj instanceof String)) {
|
||||||
|
throw new ParseException("getmapping(): first parameter (group name) must be a string");
|
||||||
|
}
|
||||||
|
|
||||||
|
String group = (String) groupObj;
|
||||||
|
String key = toKey(value);
|
||||||
|
|
||||||
|
String mapped = (key == null) ? null : lookup(group, key);
|
||||||
|
|
||||||
|
if (mapped != null) {
|
||||||
|
inStack.push(mapped);
|
||||||
|
} else if (hasDefault) {
|
||||||
|
inStack.push(defaultValue);
|
||||||
|
} else {
|
||||||
|
inStack.push(value); // 매핑 없음 → 원본값 그대로 반환
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PropManager 프러퍼티 그룹에서 key에 해당하는 값을 조회한다.
|
||||||
|
* 매핑이 없거나 그룹이 존재하지 않으면 null을 반환한다.
|
||||||
|
*
|
||||||
|
* <p>단위 테스트에서는 이 메서드를 오버라이드하여 Spring 컨텍스트 없이 매핑을 주입할 수 있다.
|
||||||
|
*/
|
||||||
|
protected String lookup(String group, String key) {
|
||||||
|
return PropManager.getInstance().getProperty(group, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 매핑 조회에 사용할 문자열 key로 변환한다.
|
||||||
|
* 정수형 숫자(JEP는 숫자를 Double로 처리)는 {@code "1000.0"}이 아닌 {@code "1000"}으로 변환한다.
|
||||||
|
*/
|
||||||
|
private String toKey(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (value instanceof String) {
|
||||||
|
return (String) value;
|
||||||
|
}
|
||||||
|
if (value instanceof Number) {
|
||||||
|
double d = ((Number) value).doubleValue();
|
||||||
|
if (!Double.isInfinite(d) && !Double.isNaN(d) && d == Math.rint(d)) {
|
||||||
|
return Long.toString((long) d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import java.io.Serializable;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.eactive.eai.common.util.MaskingUtils;
|
||||||
import com.eactive.eai.transformer.message.InvalidAccessException;
|
import com.eactive.eai.transformer.message.InvalidAccessException;
|
||||||
import com.eactive.eai.transformer.message.Message;
|
import com.eactive.eai.transformer.message.Message;
|
||||||
import com.eactive.eai.transformer.message.MessageException;
|
import com.eactive.eai.transformer.message.MessageException;
|
||||||
@@ -934,6 +935,9 @@ abstract public class Item implements Serializable, Cloneable {
|
|||||||
else
|
else
|
||||||
str = val.toString();
|
str = val.toString();
|
||||||
|
|
||||||
|
if(maskLength == 0 && maskOffset > 0)
|
||||||
|
return MaskingUtils.mask(str, maskOffset);
|
||||||
|
|
||||||
int len = str.length();
|
int len = str.length();
|
||||||
if( len <= maskOffset ) return str;
|
if( len <= maskOffset ) return str;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
|
|
||||||
import com.eactive.eai.transformer.SystemKeys;
|
import com.eactive.eai.transformer.SystemKeys;
|
||||||
import com.eactive.eai.transformer.layout.Converter;
|
import com.eactive.eai.transformer.layout.Converter;
|
||||||
|
import com.eactive.eai.transformer.layout.Group;
|
||||||
import com.eactive.eai.transformer.layout.InvalidNodeException;
|
import com.eactive.eai.transformer.layout.InvalidNodeException;
|
||||||
import com.eactive.eai.transformer.layout.Item;
|
import com.eactive.eai.transformer.layout.Item;
|
||||||
import com.eactive.eai.transformer.layout.Types;
|
import com.eactive.eai.transformer.layout.Types;
|
||||||
@@ -18,6 +19,7 @@ import com.eactive.eai.transformer.util.Logger;
|
|||||||
import com.fasterxml.jackson.core.JsonFactory;
|
import com.fasterxml.jackson.core.JsonFactory;
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.core.json.JsonReadFeature;
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
@@ -37,7 +39,7 @@ public class JSONMessage extends Message {
|
|||||||
protected JsonNode data;
|
protected JsonNode data;
|
||||||
protected ObjectMapper mapper = null;
|
protected ObjectMapper mapper = null;
|
||||||
protected JsonFactory factory = null;
|
protected JsonFactory factory = null;
|
||||||
protected boolean bStaled = false;
|
protected boolean bStaled = true;
|
||||||
|
|
||||||
public JSONMessage() {
|
public JSONMessage() {
|
||||||
super();
|
super();
|
||||||
@@ -48,11 +50,13 @@ public class JSONMessage extends Message {
|
|||||||
mapper.setNodeFactory(JsonNodeFactory.withExactBigDecimals(true));
|
mapper.setNodeFactory(JsonNodeFactory.withExactBigDecimals(true));
|
||||||
|
|
||||||
factory = mapper.getFactory();
|
factory = mapper.getFactory();
|
||||||
|
factory.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createObject() {
|
public void createObject() {
|
||||||
data = mapper.createObjectNode();
|
// data = mapper.createObjectNode();
|
||||||
|
data = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -99,13 +103,7 @@ public class JSONMessage extends Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.data == null) {
|
ObjectNode node = (ObjectNode) this.data.get(getName());
|
||||||
logger.error("Parsed data is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ObjectNode node = (ObjectNode) this.data.get(getName());
|
|
||||||
/*
|
|
||||||
if(node == null) {
|
if(node == null) {
|
||||||
// if layoutname not appended
|
// if layoutname not appended
|
||||||
setValue(this.data, getName());
|
setValue(this.data, getName());
|
||||||
@@ -113,36 +111,12 @@ public class JSONMessage extends Message {
|
|||||||
else {
|
else {
|
||||||
setValue(node, getName());
|
setValue(node, getName());
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
ObjectNode node = null;
|
|
||||||
|
|
||||||
// 변경된 부분: NullNode 검사 추가
|
|
||||||
if (this.data.has(getName()) && !this.data.get(getName()).isNull()) {
|
|
||||||
JsonNode nameNode = this.data.get(getName());
|
|
||||||
if (nameNode.isObject()) {
|
|
||||||
node = (ObjectNode) nameNode;
|
|
||||||
|
|
||||||
// 배열 데이터 처리 개선
|
|
||||||
processArrayNodes(this.data);
|
|
||||||
|
|
||||||
// 값 설정
|
|
||||||
setValue(node, getName());
|
|
||||||
} else {
|
|
||||||
logger.warn("Node with name '" + getName() + "' is not an object, skipping setValue operation");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// layoutname이 추가되지 않은 경우
|
|
||||||
setValue(this.data, getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new MessageSetDataException(e.getMessage(), this, data, e);
|
throw new MessageSetDataException(e.getMessage(), this, data, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValue(JsonNode node, String itempPath) throws InvalidAccessException {
|
public void setValue(JsonNode node, String itempPath) throws InvalidAccessException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// this.value = Converter.convert(value, getDataTypeId());
|
// this.value = Converter.convert(value, getDataTypeId());
|
||||||
/**
|
/**
|
||||||
@@ -150,7 +124,6 @@ public class JSONMessage extends Message {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HashMap validationTargets = new HashMap();
|
HashMap validationTargets = new HashMap();
|
||||||
|
|
||||||
doSetValue(node, validationTargets, itempPath);
|
doSetValue(node, validationTargets, itempPath);
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
@@ -176,18 +149,29 @@ public class JSONMessage extends Message {
|
|||||||
|
|
||||||
protected void doSetValue(JsonNode node, HashMap validationTargets, String parentPath) {
|
protected void doSetValue(JsonNode node, HashMap validationTargets, String parentPath) {
|
||||||
Item item = null;
|
Item item = null;
|
||||||
|
if (node.isNull()) {
|
||||||
|
// null이면 타겟 형식에서 Grid인지 확인 해 봄
|
||||||
|
String itemPath = parentPath + "[-1]";
|
||||||
|
item = this.getItem(itemPath);
|
||||||
|
if (item != null && item instanceof Group && StringUtils.equalsAny(item.getOccType(), "*", "+")) {
|
||||||
|
item = getOrCreateItem(denomalizeXPath(parentPath));
|
||||||
|
if (item != null) {
|
||||||
|
item.setIndex(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if( node.isObject()) {
|
if( node.isObject()) {
|
||||||
Iterator<String> fieldNames = node.fieldNames();
|
Iterator<String> fieldNames = node.fieldNames();
|
||||||
if(StringUtils.isNotEmpty(parentPath)) {
|
if(StringUtils.isNotEmpty(parentPath)) {
|
||||||
item = getOrCreateItem(denomalizeXPath(parentPath));
|
item = getOrCreateItem(denomalizeXPath(parentPath));
|
||||||
|
|
||||||
if(SystemKeys.isValidationEnabled() && StringUtils.isNotEmpty(item.getOccRef())) {
|
if(SystemKeys.isValidationEnabled() && StringUtils.isNotEmpty(item.getOccRef())) {
|
||||||
validationTargets.put(item.getParent().getItemPath() + Types.FIELD_SEPARATOR + item.getOccRef(), item);
|
validationTargets.put(item.getParent().getItemPath() + Types.FIELD_SEPARATOR + item.getOccRef(), item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(fieldNames.hasNext()) {
|
while(fieldNames.hasNext()) {
|
||||||
String fieldName = fieldNames.next();
|
String fieldName = fieldNames.next();
|
||||||
|
|
||||||
JsonNode fieldValue = node.get(fieldName);
|
JsonNode fieldValue = node.get(fieldName);
|
||||||
try {
|
try {
|
||||||
String path = null;
|
String path = null;
|
||||||
@@ -206,37 +190,23 @@ public class JSONMessage extends Message {
|
|||||||
}
|
}
|
||||||
else if( node.isArray() ) {
|
else if( node.isArray() ) {
|
||||||
ArrayNode arrayNode = (ArrayNode) node;
|
ArrayNode arrayNode = (ArrayNode) node;
|
||||||
|
if(arrayNode.size() == 0 && StringUtils.isNotEmpty(parentPath)) {
|
||||||
// 배열이 문자열 값만 포함하는지 확인
|
|
||||||
boolean isSimpleArray = true;
|
|
||||||
for (int i = 0; i < arrayNode.size(); i++) {
|
|
||||||
if (!arrayNode.get(i).isValueNode()) {
|
|
||||||
isSimpleArray = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSimpleArray) {
|
|
||||||
// 문자열 배열은 직접 값 설정
|
|
||||||
try {
|
try {
|
||||||
setString(parentPath, arrayNode.toString());
|
// 아직 clone 되지 않았으면 생성 안함.
|
||||||
} catch (Exception e) {
|
item = this.getItem(denomalizeXPath(parentPath));
|
||||||
logger.error("Error setting simple array: " + parentPath, e);
|
if (item != null) {
|
||||||
// 개별 요소 설정
|
// clone 후에는 -1로
|
||||||
for (int i = 0; i < arrayNode.size(); i++) {
|
item = getOrCreateItem(denomalizeXPath(parentPath));
|
||||||
try {
|
if (item != null) {
|
||||||
String itemPath = parentPath + "[" + i + "]";
|
item.setIndex(-1);
|
||||||
setString(itemPath, arrayNode.get(i).asText());
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logger.error("Error setting array item: " + parentPath + "[" + i + "]", ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (InvalidNodeException ie) {
|
||||||
|
// continue silently
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// 복잡한 배열 구조 처리
|
|
||||||
for(int i = 0; i < arrayNode.size(); i++) {
|
for(int i = 0; i < arrayNode.size(); i++) {
|
||||||
JsonNode arrayItem = arrayNode.get(i);
|
JsonNode arrayItem = arrayNode.get(i);
|
||||||
|
|
||||||
if(StringUtils.isNotEmpty(parentPath)) {
|
if(StringUtils.isNotEmpty(parentPath)) {
|
||||||
try {
|
try {
|
||||||
item = getOrCreateItem(denomalizeXPath(parentPath + "[" + i + "]"));
|
item = getOrCreateItem(denomalizeXPath(parentPath + "[" + i + "]"));
|
||||||
@@ -247,17 +217,15 @@ public class JSONMessage extends Message {
|
|||||||
doSetValue(arrayItem, validationTargets, parentPath + "[" + i + "]");
|
doSetValue(arrayItem, validationTargets, parentPath + "[" + i + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
String itemPath = parentPath;
|
String itemPath = parentPath;
|
||||||
item = getOrCreateItem(denomalizeXPath(itemPath));
|
item = getOrCreateItem(denomalizeXPath(itemPath));
|
||||||
String value = node.asText();
|
String value = node.asText();
|
||||||
|
if (node.isNull()) return;
|
||||||
if(node == null || node.isNull()) {
|
if(value == null || value.length() == 0) {
|
||||||
setObject(itemPath, null); // 실제 null 값 설정
|
|
||||||
} else if(value == null || value.length() == 0) {
|
|
||||||
setObject( itemPath, value );
|
setObject( itemPath, value );
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
int itemType = item.getDataTypeId();
|
int itemType = item.getDataTypeId();
|
||||||
try {
|
try {
|
||||||
switch(itemType) {
|
switch(itemType) {
|
||||||
@@ -372,7 +340,6 @@ public class JSONMessage extends Message {
|
|||||||
|
|
||||||
String val = getStringValue(item.getValue(),item);
|
String val = getStringValue(item.getValue(),item);
|
||||||
int itemType = item.getDataTypeId();
|
int itemType = item.getDataTypeId();
|
||||||
|
|
||||||
if (isMask && "Y".equals(item.getMask()) && (Types.TYPE_STRING == itemType )){
|
if (isMask && "Y".equals(item.getMask()) && (Types.TYPE_STRING == itemType )){
|
||||||
val = maskString2(val, item.getMaskLength(), item.getMaskOffset());
|
val = maskString2(val, item.getMaskLength(), item.getMaskOffset());
|
||||||
item.setValue(val);
|
item.setValue(val);
|
||||||
@@ -386,7 +353,8 @@ public class JSONMessage extends Message {
|
|||||||
setJsonArrayValue(arr, item);
|
setJsonArrayValue(arr, item);
|
||||||
obj.set(prefix+item.getName(), arr);
|
obj.set(prefix+item.getName(), arr);
|
||||||
}else{
|
}else{
|
||||||
arr.add(value);
|
// arr.add(value);
|
||||||
|
setJsonArrayValue(arr, item); //IBK에서 사용.
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { //FIELD
|
} else { //FIELD
|
||||||
@@ -448,33 +416,6 @@ public class JSONMessage extends Message {
|
|||||||
node.putNull(fieldName);
|
node.putNull(fieldName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(value instanceof JsonNode) {
|
|
||||||
node.set(fieldName, (JsonNode) value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// New code to check if string is JSON array
|
|
||||||
if (itemType == Types.TYPE_STRING && value instanceof String) {
|
|
||||||
String strValue = (String) value;
|
|
||||||
if ((strValue.startsWith("[") && strValue.endsWith("]")) ||
|
|
||||||
(strValue.startsWith("{") && strValue.endsWith("}"))) {
|
|
||||||
try {
|
|
||||||
// Try to parse as JSON
|
|
||||||
JsonNode jsonNode = mapper.readTree(strValue);
|
|
||||||
node.set(fieldName, jsonNode);
|
|
||||||
return;
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Not valid JSON, continue with normal processing
|
|
||||||
logger.debug("Failed to parse as JSON, using as string: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(value instanceof byte[])) {
|
|
||||||
logger.info("value : " + value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(itemType) {
|
switch(itemType) {
|
||||||
case Types.TYPE_INT :
|
case Types.TYPE_INT :
|
||||||
case Types.TYPE_SHORT :
|
case Types.TYPE_SHORT :
|
||||||
@@ -484,8 +425,9 @@ public class JSONMessage extends Message {
|
|||||||
node.put(fieldName, (long) value);
|
node.put(fieldName, (long) value);
|
||||||
break;
|
break;
|
||||||
case Types.TYPE_BIGDECIMAL :
|
case Types.TYPE_BIGDECIMAL :
|
||||||
BigDecimal bd = (BigDecimal)value;
|
// BigDecimal bd = (BigDecimal)value;
|
||||||
node.put(fieldName, bd);
|
// node.put(fieldName, bd.floatValue());
|
||||||
|
node.put(fieldName, (BigDecimal)value);
|
||||||
break;
|
break;
|
||||||
case Types.TYPE_DOUBLE :
|
case Types.TYPE_DOUBLE :
|
||||||
node.put(fieldName, (double) value);
|
node.put(fieldName, (double) value);
|
||||||
@@ -497,12 +439,7 @@ public class JSONMessage extends Message {
|
|||||||
node.put(fieldName, (boolean) value);
|
node.put(fieldName, (boolean) value);
|
||||||
break;
|
break;
|
||||||
case Types.TYPE_STRING :
|
case Types.TYPE_STRING :
|
||||||
|
|
||||||
node.put(fieldName, (String) value);
|
node.put(fieldName, (String) value);
|
||||||
if (value instanceof JsonNode) {
|
|
||||||
logger.info("value : " + (String) value );
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
node.put(fieldName, (String) value);
|
node.put(fieldName, (String) value);
|
||||||
@@ -524,7 +461,7 @@ public class JSONMessage extends Message {
|
|||||||
arrayNode.add( (long) value);
|
arrayNode.add( (long) value);
|
||||||
break;
|
break;
|
||||||
case Types.TYPE_BIGDECIMAL :
|
case Types.TYPE_BIGDECIMAL :
|
||||||
arrayNode.add( (float) value);
|
arrayNode.add( (BigDecimal)value);
|
||||||
break;
|
break;
|
||||||
case Types.TYPE_DOUBLE :
|
case Types.TYPE_DOUBLE :
|
||||||
arrayNode.add( (double) value);
|
arrayNode.add( (double) value);
|
||||||
@@ -583,8 +520,7 @@ public class JSONMessage extends Message {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Object getData() {
|
public Object getData() {
|
||||||
|
if (bStaled || this.data == null) {
|
||||||
if (bStaled) {
|
|
||||||
try {
|
try {
|
||||||
this.data = getJSONData();
|
this.data = getJSONData();
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
@@ -604,7 +540,6 @@ public class JSONMessage extends Message {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if(this.data == null) return null;
|
if(this.data == null) return null;
|
||||||
|
|
||||||
if(isPretty) return data.toPrettyString();
|
if(isPretty) return data.toPrettyString();
|
||||||
else return data.toString();
|
else return data.toString();
|
||||||
}
|
}
|
||||||
@@ -703,6 +638,36 @@ public class JSONMessage extends Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isValid(String value,int length,int pointLength){
|
||||||
|
String[] data = value.replaceAll(" ", "").split("[.]");
|
||||||
|
if (pointLength > 0 ){
|
||||||
|
if (data.length ==1){
|
||||||
|
if (data[0].length() > length - pointLength - 1 ){ //정수부 오류
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}else if (data.length ==2){
|
||||||
|
if (data[0].length() > length - pointLength - 1 ){ //정수부 오류
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (data[1].length() > pointLength ){ //실수부 오류
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//오류
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
if (data.length != 1){ //소수점이 들어와서 오류
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (data[0].length() > length - pointLength - 1){ //정수부 오류
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// private Object toJsonObjectType(int itemType, String value) {
|
// private Object toJsonObjectType(int itemType, String value) {
|
||||||
// Object jsonValueObject = null;
|
// Object jsonValueObject = null;
|
||||||
//
|
//
|
||||||
@@ -736,70 +701,11 @@ public class JSONMessage extends Message {
|
|||||||
return getName() + " (" + MESSAGE_NAME + ")";
|
return getName() + " (" + MESSAGE_NAME + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 배열 처리 메소드
|
|
||||||
private void processArrayNodes(JsonNode rootNode) {
|
|
||||||
Iterator<String> fieldNames = rootNode.fieldNames();
|
|
||||||
while (fieldNames.hasNext()) {
|
|
||||||
String fieldName = fieldNames.next();
|
|
||||||
JsonNode node = rootNode.get(fieldName);
|
|
||||||
|
|
||||||
// data_part와 같은 객체 노드 처리
|
|
||||||
if (node.isObject()) {
|
|
||||||
processArrayNodes(node);
|
|
||||||
}
|
|
||||||
// 배열 노드 처리
|
|
||||||
else if (node.isArray()) {
|
|
||||||
ArrayNode arrayNode = (ArrayNode) node;
|
|
||||||
|
|
||||||
// 배열 노드 처리
|
|
||||||
if (arrayNode.size() > 0) {
|
|
||||||
// 배열 데이터 설정
|
|
||||||
try {
|
|
||||||
|
|
||||||
if(this.data instanceof ObjectNode) {
|
|
||||||
ObjectNode objNode = (ObjectNode) this.data;
|
|
||||||
objNode.set(fieldName, arrayNode);
|
|
||||||
} else if (rootNode instanceof ObjectNode) {
|
|
||||||
((ObjectNode) rootNode).set(fieldName, arrayNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i=0; i < arrayNode.size(); i++) {
|
|
||||||
JsonNode itemNode = arrayNode.get(i);
|
|
||||||
|
|
||||||
String itemPath = fieldName + "[" + i + "]";
|
|
||||||
|
|
||||||
if(itemNode.isObject()) {
|
|
||||||
processArrayNodes(itemNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Error setting array data for field: " + fieldName, e);
|
|
||||||
// 배열 요소를 개별적으로 처리
|
|
||||||
for (int i = 0; i < arrayNode.size(); i++) {
|
|
||||||
try {
|
|
||||||
String itemPath = fieldName + "[" + i + "]";
|
|
||||||
JsonNode itemNode = arrayNode.get(i);
|
|
||||||
if (itemNode.isTextual()) {
|
|
||||||
setString(itemPath, itemNode.asText());
|
|
||||||
} else {
|
|
||||||
setString(itemPath, itemNode.toString());
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logger.error("Error setting array item [" + i + "] for field: " + fieldName, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString(){
|
public String toString(){
|
||||||
// if staled -> reorganize data
|
// if staled -> reorganize data
|
||||||
String jsonString = null;
|
String jsonString = null;
|
||||||
try {
|
try {
|
||||||
jsonString = (String)getData();
|
jsonString = toLogString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("[JSONMessage] " + e.getMessage(), e);
|
logger.error("[JSONMessage] " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
package com.eactive.eai.transformer;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.nfunk.jep.JEP;
|
||||||
|
|
||||||
|
import com.eactive.eai.transformer.function.generic.GetMapping;
|
||||||
|
|
||||||
|
@DisplayName("GetMapping 프러퍼티 그룹 매핑 함수 테스트")
|
||||||
|
class GetMappingFunctionTest {
|
||||||
|
|
||||||
|
private JEP jep;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PropManager(Spring 컨텍스트) 없이 테스트하기 위해 lookup()을 로컬 맵으로 대체한 스텁.
|
||||||
|
* groups: 그룹명 → (key → value) 매핑 테이블
|
||||||
|
*/
|
||||||
|
static class StubGetMapping extends GetMapping {
|
||||||
|
private final Map<String, Map<String, String>> groups;
|
||||||
|
|
||||||
|
StubGetMapping(Map<String, Map<String, String>> groups) {
|
||||||
|
this.groups = groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String lookup(String group, String key) {
|
||||||
|
Map<String, String> g = groups.get(group);
|
||||||
|
if (g == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return g.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
// 프러퍼티 그룹 "COMMON_CODE": 1000->AAAAA, 1001->BBBBB
|
||||||
|
Map<String, String> commonCode = new HashMap<>();
|
||||||
|
commonCode.put("1000", "AAAAA");
|
||||||
|
commonCode.put("1001", "BBBBB");
|
||||||
|
|
||||||
|
// 한글 그룹명/값도 지원하는지 확인용
|
||||||
|
Map<String, String> bankCode = new HashMap<>();
|
||||||
|
bankCode.put("081", "하나은행");
|
||||||
|
bankCode.put("088", "신한은행");
|
||||||
|
|
||||||
|
Map<String, Map<String, String>> groups = new HashMap<>();
|
||||||
|
groups.put("COMMON_CODE", commonCode);
|
||||||
|
groups.put("BANK_CODE", bankCode);
|
||||||
|
|
||||||
|
jep = new JEP();
|
||||||
|
jep.addStandardFunctions();
|
||||||
|
jep.addStandardConstants();
|
||||||
|
jep.setAllowUndeclared(true);
|
||||||
|
jep.addFunction("getmapping", new StubGetMapping(groups));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object eval(String expr) {
|
||||||
|
jep.parseExpression(expr);
|
||||||
|
assertFalse(jep.hasError(), "파싱 오류: " + jep.getErrorInfo());
|
||||||
|
Object result = jep.getValueAsObject();
|
||||||
|
assertFalse(jep.hasError(), "평가 오류: " + jep.getErrorInfo());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("2-인자 매핑 성공 — 1000 → AAAAA")
|
||||||
|
void testMappingFound() {
|
||||||
|
assertEquals("AAAAA", eval("getmapping(\"COMMON_CODE\", \"1000\")"));
|
||||||
|
assertEquals("BBBBB", eval("getmapping(\"COMMON_CODE\", \"1001\")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("2-인자 매핑 없음 — 원본값 그대로 반환(passthrough)")
|
||||||
|
void testMappingNotFoundPassthrough() {
|
||||||
|
assertEquals("9999", eval("getmapping(\"COMMON_CODE\", \"9999\")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("2-인자 그룹 자체가 없음 — 원본값 그대로 반환")
|
||||||
|
void testGroupNotFoundPassthrough() {
|
||||||
|
assertEquals("1000", eval("getmapping(\"NO_SUCH_GROUP\", \"1000\")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("3-인자 매핑 성공 — default 무시하고 매핑값 반환")
|
||||||
|
void testMappingFoundWithDefault() {
|
||||||
|
assertEquals("AAAAA", eval("getmapping(\"COMMON_CODE\", \"1000\", \"UNKNOWN\")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("3-인자 매핑 없음 — default 반환")
|
||||||
|
void testMappingNotFoundWithDefault() {
|
||||||
|
assertEquals("UNKNOWN", eval("getmapping(\"COMMON_CODE\", \"9999\", \"UNKNOWN\")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("3-인자 그룹 자체가 없음 — default 반환")
|
||||||
|
void testGroupNotFoundWithDefault() {
|
||||||
|
assertEquals("UNKNOWN", eval("getmapping(\"NO_SUCH_GROUP\", \"1000\", \"UNKNOWN\")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("숫자 리터럴 값 — 1000.0이 아닌 \"1000\"으로 조회")
|
||||||
|
void testNumericValueLookup() {
|
||||||
|
// JEP는 1000 리터럴을 Double로 처리하므로 toKey에서 "1000"으로 변환되어야 매핑됨
|
||||||
|
assertEquals("AAAAA", eval("getmapping(\"COMMON_CODE\", 1000)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("숫자 리터럴 값 매핑 없음 — 원본 숫자값 그대로 반환")
|
||||||
|
void testNumericValueNotFoundPassthrough() {
|
||||||
|
Object result = eval("getmapping(\"COMMON_CODE\", 9999)");
|
||||||
|
assertEquals(9999.0, ((Number) result).doubleValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("변수 바인딩 값 매핑 — 필드값 변환")
|
||||||
|
void testVariableValueMapping() {
|
||||||
|
jep.addVariable("code", "1001");
|
||||||
|
assertEquals("BBBBB", eval("getmapping(\"COMMON_CODE\", code)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("한글 그룹/값 매핑 — 081 → 하나은행")
|
||||||
|
void testKoreanGroupAndValue() {
|
||||||
|
assertEquals("하나은행", eval("getmapping(\"BANK_CODE\", \"081\")"));
|
||||||
|
assertEquals("신한은행", eval("getmapping(\"BANK_CODE\", \"088\")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("첫 번째 파라미터(group)가 문자열이 아니면 오류")
|
||||||
|
void testNonStringGroupCausesError() {
|
||||||
|
jep.parseExpression("getmapping(1000, \"1000\")");
|
||||||
|
if (!jep.hasError()) {
|
||||||
|
jep.getValueAsObject();
|
||||||
|
assertTrue(jep.hasError(), "숫자 group 파라미터는 오류가 발생해야 합니다");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("파라미터 개수가 1개면 오류")
|
||||||
|
void testTooFewParamsCausesError() {
|
||||||
|
jep.parseExpression("getmapping(\"COMMON_CODE\")");
|
||||||
|
if (!jep.hasError()) {
|
||||||
|
jep.getValueAsObject();
|
||||||
|
assertTrue(jep.hasError(), "파라미터 1개는 오류가 발생해야 합니다");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user