feat(common, other): add GlowMciFieldInfo and List parsing support

This commit is contained in:
jade
2026-07-09 13:40:12 +09:00
parent 5c7f1c92a2
commit 5c0681e37e
5 changed files with 189 additions and 4 deletions

View File

@@ -0,0 +1,29 @@
package io.shinhanlife.glow;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GlowMciFieldInfo {
/**
* 필드 순서
*/
int order();
/**
* 필드 길이 (List인 경우 전체 길이로 활용될 수 있음)
*/
int length();
/**
* 필드 설명
*/
String description() default "";
/**
* List 매핑 시 대상 DTO 클래스
*/
Class<?> target() default void.class;
}

View File

@@ -0,0 +1,105 @@
package io.shinhanlife.glow.util;
import io.shinhanlife.glow.GlowMciFieldInfo;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* @package io.shinhanlife.glow.util
* @className GlowMciParser
* @description MCI 고정 길이 전문 파싱 유틸리티 (GlowMciFieldInfo 기반)
* @author 김형식
* @create 2026.09.01
*/
@Slf4j
public class GlowMciParser {
public static <T> T parse(String mciString, Class<T> clazz) {
if (mciString == null || mciString.isEmpty()) {
return null;
}
try {
T instance = clazz.getDeclaredConstructor().newInstance();
List<Field> fields = new ArrayList<>();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(GlowMciFieldInfo.class)) {
fields.add(field);
}
}
fields.sort(Comparator.comparingInt(f -> f.getAnnotation(GlowMciFieldInfo.class).order()));
int currentIndex = 0;
for (Field field : fields) {
GlowMciFieldInfo annotation = field.getAnnotation(GlowMciFieldInfo.class);
int length = annotation.length();
if (currentIndex >= mciString.length()) {
break;
}
int endIndex = Math.min(currentIndex + length, mciString.length());
String value = mciString.substring(currentIndex, endIndex);
field.setAccessible(true);
setFieldValue(instance, field, value, annotation);
currentIndex += length;
}
return instance;
} catch (Exception e) {
log.error("GlowMciFieldInfo 파싱 중 오류 발생: {}", e.getMessage(), e);
throw new RuntimeException("MCI 전문 파싱 오류", e);
}
}
private static void setFieldValue(Object instance, Field field, String value, GlowMciFieldInfo annotation) throws IllegalAccessException {
Class<?> fieldType = field.getType();
String trimmedValue = value.trim();
if (fieldType == String.class) {
field.set(instance, trimmedValue);
} else if (fieldType == int.class || fieldType == Integer.class) {
field.set(instance, trimmedValue.isEmpty() ? 0 : Integer.parseInt(trimmedValue));
} else if (fieldType == long.class || fieldType == Long.class) {
field.set(instance, trimmedValue.isEmpty() ? 0L : Long.parseLong(trimmedValue));
} else if (fieldType == boolean.class || fieldType == Boolean.class) {
field.set(instance, Boolean.parseBoolean(trimmedValue));
} else if (fieldType == double.class || fieldType == Double.class) {
field.set(instance, trimmedValue.isEmpty() ? 0.0 : Double.parseDouble(trimmedValue));
} else if (List.class.isAssignableFrom(fieldType)) {
Class<?> targetClass = annotation.target();
if (targetClass != void.class) {
List<Object> list = new ArrayList<>();
int itemLength = calculateTotalLength(targetClass);
if (itemLength > 0) {
for (int i = 0; i < value.length(); i += itemLength) {
int end = Math.min(i + itemLength, value.length());
String itemStr = value.substring(i, end);
if (itemStr.trim().isEmpty()) continue;
list.add(parse(itemStr, targetClass));
}
}
field.set(instance, list);
}
} else {
field.set(instance, trimmedValue);
}
}
private static int calculateTotalLength(Class<?> clazz) {
int total = 0;
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(GlowMciFieldInfo.class)) {
total += field.getAnnotation(GlowMciFieldInfo.class).length();
}
}
return total;
}
}