지수형 부동소수점 validation 정규화 flag 추가 (transformer.scientific.normalize)
- SystemKeys: TRANSFROMER_SCIENTIFIC_NORMALIZE 키 및 isScientificNormalizeEnabled() 추가 - JSONMessage.isValid(): flag ON 시 toPlainString()으로 정규화 후 검증 - false positive 방지: 1.23e5(=123000)가 자릿수 제한을 우회하는 문제 차단 - false negative 방지: pointLength=0 필드에서 유효한 지수형 값이 거부되는 문제 해결 - JSONMessageValidationTest: 지수형 시나리오 4개 추가 (정규화 ON/OFF 각 케이스)
This commit is contained in:
@@ -7,6 +7,7 @@ public class SystemKeys {
|
||||
public static final String TRANSFROMER_STRING_TRIMEND = "transformer.string.trimend";
|
||||
public static final String TRANSFROMER_VALIDATION = "transformer.validation";
|
||||
public static final String TRANSFROMER_DECIMALPOINT_ADD = "transformer.decimalpoint.add";
|
||||
public static final String TRANSFROMER_SCIENTIFIC_NORMALIZE = "transformer.scientific.normalize";
|
||||
|
||||
public static final String TRANSFROMER_LAYOUT_CACHE_INIT_ONSTARTUP = "transformer.layout.cache.init.onstartup";
|
||||
public static final String TRANSFROMER_LAYOUT_CACHE_SIZE = "transformer.layout.cache.size";
|
||||
@@ -30,6 +31,7 @@ public class SystemKeys {
|
||||
private static boolean stringTrimEnd = true;
|
||||
private static boolean validationEnabled = true;
|
||||
private static boolean addDecimalpoint = false;
|
||||
private static boolean scientificNormalize = true;
|
||||
|
||||
private static boolean layoutCacheOnStartup = false;
|
||||
|
||||
@@ -64,7 +66,14 @@ public class SystemKeys {
|
||||
} catch (Exception ex) {
|
||||
addDecimalpoint = false;
|
||||
}
|
||||
|
||||
|
||||
sBoolean = System.getProperty(TRANSFROMER_SCIENTIFIC_NORMALIZE, "false");
|
||||
try {
|
||||
scientificNormalize = Boolean.valueOf(sBoolean);
|
||||
} catch (Exception ex) {
|
||||
scientificNormalize = false;
|
||||
}
|
||||
|
||||
sBoolean = System.getProperty(TRANSFROMER_LAYOUT_CACHE_INIT_ONSTARTUP, "false");
|
||||
try {
|
||||
layoutCacheOnStartup = Boolean.valueOf(sBoolean);
|
||||
@@ -93,6 +102,10 @@ public class SystemKeys {
|
||||
return addDecimalpoint;
|
||||
}
|
||||
|
||||
public static boolean isScientificNormalizeEnabled() {
|
||||
return scientificNormalize;
|
||||
}
|
||||
|
||||
public static boolean isLayoutCacheOnStartup() {
|
||||
return layoutCacheOnStartup;
|
||||
}
|
||||
|
||||
@@ -703,7 +703,15 @@ public class JSONMessage extends Message {
|
||||
}
|
||||
|
||||
private boolean isValid(String value,int length,int pointLength){
|
||||
String[] data = value.replaceAll(" ", "").split("[.]");
|
||||
String normalized = value.replaceAll(" ", "");
|
||||
if (SystemKeys.isScientificNormalizeEnabled()) {
|
||||
try {
|
||||
normalized = new BigDecimal(normalized).toPlainString();
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
String[] data = normalized.split("[.]");
|
||||
if (pointLength > 0 ){
|
||||
if (data.length ==1){
|
||||
if (data[0].length() > length - pointLength - 1 ){ //정수부 오류
|
||||
|
||||
@@ -65,6 +65,7 @@ class JSONMessageValidationTest {
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
System.setProperty(SystemKeys.TRANSFROMER_VALIDATION, "false");
|
||||
System.setProperty(SystemKeys.TRANSFROMER_SCIENTIFIC_NORMALIZE, "false");
|
||||
SystemKeys.reload();
|
||||
}
|
||||
|
||||
@@ -355,6 +356,81 @@ class JSONMessageValidationTest {
|
||||
assertTrue(result.contains("STR_VALUE"), "STR_VALUE가 결과에 포함되어야 합니다");
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
// 4. 지수 표현(Scientific Notation) 정규화 테스트
|
||||
// transformer.scientific.normalize=true 일 때만 적용
|
||||
// 4-a) 정규화 ON + validation ON
|
||||
// 4-b) 정규화 OFF → 기존 동작(false positive / false negative) 확인
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
@DisplayName("[정규화 ON] 지수형 정수부 초과(1.23e5=123000 > 4자리 제한) → MessageSetDataException")
|
||||
void testScientificNotationIntegerOverflow_withNormalize() {
|
||||
enableValidation();
|
||||
enableScientificNormalize();
|
||||
|
||||
// 1.23e5 = 123000, 정수부 6자리 > 4자리 제한
|
||||
String data = "{\"EAI_UJSONTYPE_REQ1\":{\"BIG_VALUE\":1.23e5}}";
|
||||
Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1");
|
||||
|
||||
MessageSetDataException ex = assertThrows(
|
||||
MessageSetDataException.class,
|
||||
() -> msg.setData(data)
|
||||
);
|
||||
assertTrue(containsMessage(ex, "Invalid decimal point format"),
|
||||
"'Invalid decimal point format' 메시지가 포함되어야 합니다");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("[정규화 ON] 지수형 문자열 정수부 초과(\"1.23e5\" > 4자리 제한) → MessageSetDataException")
|
||||
void testScientificNotationStringOverflow_withNormalize() {
|
||||
enableValidation();
|
||||
enableScientificNormalize();
|
||||
|
||||
String data = "{\"EAI_UJSONTYPE_REQ1\":{\"BIG_VALUE\":\"1.23e5\"}}";
|
||||
Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1");
|
||||
|
||||
MessageSetDataException ex = assertThrows(
|
||||
MessageSetDataException.class,
|
||||
() -> msg.setData(data)
|
||||
);
|
||||
assertTrue(containsMessage(ex, "Invalid decimal point format"),
|
||||
"'Invalid decimal point format' 메시지가 포함되어야 합니다");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("[정규화 ON] 지수형 BIG15_VALUE 정상 범위(1.23e5=123000 ≤ 15자리) → 정상 처리")
|
||||
void testScientificNotationBig15Valid_withNormalize() throws Exception {
|
||||
enableValidation();
|
||||
enableScientificNormalize();
|
||||
|
||||
// 1.23e5 = 123000, 6자리 ≤ 15자리 제한 → 정상
|
||||
String data = "{\"EAI_UJSONTYPE_REQ1\":{\"BIG15_VALUE\":1.23e5}}";
|
||||
Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1");
|
||||
msg.setData(data);
|
||||
|
||||
String result = (String) msg.getData();
|
||||
assertNotNull(result, "결과값이 null이 아니어야 합니다");
|
||||
assertTrue(result.contains("BIG15_VALUE"), "BIG15_VALUE가 결과에 포함되어야 합니다");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("[정규화 OFF] 지수형 BIG15_VALUE 정상값(1.23e5)이 false negative로 거부됨 → MessageSetDataException")
|
||||
void testScientificNotationBig15Valid_withoutNormalize() {
|
||||
enableValidation();
|
||||
disableScientificNormalize();
|
||||
|
||||
// 1.23e5 = 123000, 유효값(6자리 ≤ 15자리)이지만 정규화 없이는 "1.23E+5".split(".")=[2개] → 거부
|
||||
String data = "{\"EAI_UJSONTYPE_REQ1\":{\"BIG15_VALUE\":1.23e5}}";
|
||||
Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1");
|
||||
|
||||
assertThrows(
|
||||
MessageSetDataException.class,
|
||||
() -> msg.setData(data),
|
||||
"정규화 OFF 시 false negative로 예외가 발생해야 합니다"
|
||||
);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
// 유틸 메서드
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
@@ -364,6 +440,16 @@ class JSONMessageValidationTest {
|
||||
SystemKeys.reload();
|
||||
}
|
||||
|
||||
private void enableScientificNormalize() {
|
||||
System.setProperty(SystemKeys.TRANSFROMER_SCIENTIFIC_NORMALIZE, "true");
|
||||
SystemKeys.reload();
|
||||
}
|
||||
|
||||
private void disableScientificNormalize() {
|
||||
System.setProperty(SystemKeys.TRANSFROMER_SCIENTIFIC_NORMALIZE, "false");
|
||||
SystemKeys.reload();
|
||||
}
|
||||
|
||||
private boolean containsCause(Throwable e, Class<?> causeClass) {
|
||||
Throwable t = e;
|
||||
while (t != null) {
|
||||
|
||||
Reference in New Issue
Block a user