프러퍼티그룹 이용 함수 개발
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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