feat: MCI Request DTO example 자동 생성 및 Tool Scaffold UseCaseImpl/Client 생성 템플릿 개선
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 31s
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 31s
This commit is contained in:
@@ -133,7 +133,7 @@ public final class MciResponseScaffolder {
|
||||
Map<String, FieldMapping> mappingBySource = normalizeMappings(parsed, mappings);
|
||||
validateTargetNames(parsed, mappingBySource);
|
||||
return new GeneratedRequestSources(
|
||||
responseSource(parsed, requestPackage, requestClassName, mappingBySource),
|
||||
responseSource(parsed, requestPackage, requestClassName, mappingBySource, true),
|
||||
requestConverterSource(parsed, requestPackage, requestClassName, converterPackage,
|
||||
converterClassName, mappingBySource));
|
||||
}
|
||||
@@ -321,6 +321,11 @@ public final class MciResponseScaffolder {
|
||||
|
||||
private static String responseSource(ParsedSource parsed, String responsePackage, String responseClassName,
|
||||
Map<String, FieldMapping> mappings) {
|
||||
return responseSource(parsed, responsePackage, responseClassName, mappings, false);
|
||||
}
|
||||
|
||||
private static String responseSource(ParsedSource parsed, String responsePackage, String responseClassName,
|
||||
Map<String, FieldMapping> mappings, boolean isRequest) {
|
||||
boolean usesList = parsed.types().stream().flatMap(type -> type.fields().stream())
|
||||
.anyMatch(field -> field.type().contains("List<"));
|
||||
boolean usesBigDecimal = parsed.types().stream().flatMap(type -> type.fields().stream())
|
||||
@@ -333,31 +338,78 @@ public final class MciResponseScaffolder {
|
||||
if (usesList) source.append("import java.util.List;\n");
|
||||
source.append("\n@Data\n@JsonInclude(JsonInclude.Include.NON_NULL)\n")
|
||||
.append("public class ").append(responseClassName).append(" {\n\n")
|
||||
.append(responseFields(parsed.types().getFirst(), mappings, " "));
|
||||
.append(responseFields(parsed.types().getFirst(), mappings, " ", isRequest));
|
||||
|
||||
for (ParsedType type : parsed.types().stream().skip(1).toList()) {
|
||||
source.append(" @Data\n")
|
||||
.append(" @JsonInclude(JsonInclude.Include.NON_NULL)\n")
|
||||
.append(" public static class ").append(type.name()).append(" {\n\n")
|
||||
.append(responseFields(type, mappings, " "))
|
||||
.append(responseFields(type, mappings, " ", isRequest))
|
||||
.append(" }\n\n");
|
||||
}
|
||||
return source.append("}\n").toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String responseFields(ParsedType type, Map<String, FieldMapping> mappings, String indent) {
|
||||
return responseFields(type, mappings, indent, false);
|
||||
}
|
||||
|
||||
private static String responseFields(ParsedType type, Map<String, FieldMapping> mappings, String indent, boolean isRequest) {
|
||||
StringBuilder source = new StringBuilder();
|
||||
for (ParsedField field : type.fields()) {
|
||||
FieldMapping mapping = mappings.get(key(type.name(), field.name()));
|
||||
if (!mapping.include()) continue;
|
||||
source.append(indent).append("@Schema(description = \"")
|
||||
.append(escapeJava(field.description())).append("\")\n")
|
||||
.append(indent).append("private ").append(field.type()).append(' ')
|
||||
if (isRequest) {
|
||||
String example = exampleValue(field);
|
||||
source.append(indent).append("@Schema(description = \"")
|
||||
.append(escapeJava(field.description()))
|
||||
.append("\", example = \"").append(example).append("\")\n");
|
||||
} else {
|
||||
source.append(indent).append("@Schema(description = \"")
|
||||
.append(escapeJava(field.description())).append("\")\n");
|
||||
}
|
||||
source.append(indent).append("private ").append(field.type()).append(' ')
|
||||
.append(mapping.targetName().trim()).append(";\n\n");
|
||||
}
|
||||
return source.toString();
|
||||
}
|
||||
|
||||
private static String exampleValue(ParsedField field) {
|
||||
String type = field.type();
|
||||
int length = field.length();
|
||||
String desc = field.description() == null ? "" : field.description();
|
||||
if (type.contains("List<") || type.contains("[]")) return "";
|
||||
if (type.equals("BigDecimal") || type.equals("Long") || type.equals("Integer") || type.equals("int") || type.equals("long")) {
|
||||
return "0";
|
||||
}
|
||||
// 날짜 패턴
|
||||
if (length == 8 && (desc.contains("일자") || desc.contains("날짜") || desc.contains("생년") || desc.contains("Ymd") || field.name().toLowerCase().contains("ymd"))) {
|
||||
return "20240101";
|
||||
}
|
||||
// 년월 패턴
|
||||
if (length == 6 && (desc.contains("년월") || desc.contains("연월") || field.name().toLowerCase().contains("ym"))) {
|
||||
return "202401";
|
||||
}
|
||||
// 코드 패턴
|
||||
if (desc.contains("코드") || desc.contains("구분") || field.name().toLowerCase().contains("cd") || field.name().toLowerCase().contains("sc")) {
|
||||
return length <= 4 ? "01" : "0001";
|
||||
}
|
||||
// 번호 패턴
|
||||
if (desc.contains("번호") || field.name().toLowerCase().contains("no")) {
|
||||
return length <= 10 ? "1234567890".substring(0, Math.min(length, 10)) : "12345678901234";
|
||||
}
|
||||
// 이름 패턴
|
||||
if (desc.contains("이름") || desc.contains("명") || field.name().toLowerCase().contains("nm")) {
|
||||
return "홍길동";
|
||||
}
|
||||
// 기본 String
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String converterSource(ParsedSource parsed, String responsePackage, String responseClassName,
|
||||
String converterPackage, String converterClassName,
|
||||
Map<String, FieldMapping> mappings) {
|
||||
|
||||
@@ -228,8 +228,31 @@ public class ToolScaffolder {
|
||||
String sysCode = tool.clientSystemCode();
|
||||
if (sysCode != null && (sysCode.length() == 4 || sysCode.length() == 9)) {
|
||||
String clientCap = toPascalCase(mciClientPrefix(sysCode));
|
||||
String recSvcId = sysCode.toUpperCase();
|
||||
String itrfId = tool.interfaceId();
|
||||
writeUtf8(clientDir.resolve("Mci" + clientCap + "Client.java"),
|
||||
"package " + ioPackage + ";\n\nimport io.shinhanlife.dat.lib.integration.mci.component.AxhubMciComponent;\nimport io.shinhanlife.glow.communication.dto.Transfer;\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.stereotype.Component;\n\n@Component\n@RequiredArgsConstructor\npublic class Mci" + clientCap + "Client {\n private final AxhubMciComponent mci;\n\n public <O> Transfer<O> callTo(String interfaceId, String dummy, Object mciReq, Class<O> resType) throws Exception {\n return mci.callTo(interfaceId, dummy, mciReq, resType);\n }\n}\n");
|
||||
"package " + ioPackage + ";\n\n"
|
||||
+ "import io.shinhanlife.dat.lib.integration.mci.component.AxhubMciComponent;\n"
|
||||
+ "import io.shinhanlife.glow.communication.dto.Transfer;\n"
|
||||
+ "import " + ioPackage + ".io." + ioPrefix + "_I;\n"
|
||||
+ "import " + ioPackage + ".io." + ioPrefix + "_O;\n"
|
||||
+ "import lombok.RequiredArgsConstructor;\n"
|
||||
+ "import org.springframework.stereotype.Component;\n\n"
|
||||
+ "@Component\n"
|
||||
+ "@RequiredArgsConstructor\n"
|
||||
+ "public class Mci" + clientCap + "Client {\n\n"
|
||||
+ " private static final String INTERFACE_ID = \"" + itrfId + "\";\n"
|
||||
+ " private static final String RECEIVE_SERVICE_ID = \"" + recSvcId + "\";\n\n"
|
||||
+ " private final AxhubMciComponent mciComponent;\n\n"
|
||||
+ " public <O> Transfer<O> callTo(String interfaceId, String receiveServiceId, Object mciReq, Class<O> resType) {\n"
|
||||
+ " return mciComponent.callTo(interfaceId, receiveServiceId, mciReq, resType);\n"
|
||||
+ " }\n\n"
|
||||
+ " public " + ioPrefix + "_O call" + toPascalCase(ioPrefix) + "(" + ioPrefix + "_I request) {\n"
|
||||
+ " Transfer<" + ioPrefix + "_O> transfer = mciComponent.callTo(\n"
|
||||
+ " INTERFACE_ID, RECEIVE_SERVICE_ID, request, " + ioPrefix + "_O.class);\n"
|
||||
+ " return transfer == null ? null : transfer.getBody();\n"
|
||||
+ " }\n"
|
||||
+ "}\n");
|
||||
} else {
|
||||
writeUtf8(clientDir.resolve(baseName + "Client.java"), groupedMciClientContent(ioPackage, baseName, tool.interfaceId()));
|
||||
}
|
||||
@@ -321,12 +344,12 @@ public class ToolScaffolder {
|
||||
String ioPrefix = (tool.clientSystemCode() != null && !tool.clientSystemCode().isBlank()) ? tool.clientSystemCode().toUpperCase() : tool.interfaceId();
|
||||
if (mci) {
|
||||
clientClassName = mciClientClassName(tool.clientSystemCode());
|
||||
clientVariable = mciClientVariable(tool.clientSystemCode());
|
||||
clientVariable = "mci";
|
||||
} else {
|
||||
clientClassName = baseName + "Client";
|
||||
clientVariable = Character.toLowerCase(baseName.charAt(0)) + baseName.substring(1) + "Client";
|
||||
}
|
||||
String converterVariable = Character.toLowerCase(baseName.charAt(0)) + baseName.substring(1) + "Converter";
|
||||
String converterVariable = "converter";
|
||||
String integrationPackage = BASE_PACKAGE + (mci ? ".infra.itrf.mci." + formatClientSystemCode(tool.clientSystemCode(), ".")
|
||||
: ".infra.itrf.http." + toPackageSegment(tool.httpApiName()));
|
||||
imports.append("import ").append(bizPackage).append(".dto.").append(baseName).append("Request;\n")
|
||||
@@ -335,17 +358,23 @@ public class ToolScaffolder {
|
||||
.append("import ").append(integrationPackage).append(".").append(clientClassName).append(";\n")
|
||||
.append("import ").append(integrationPackage).append(".io.").append(mci ? ioPrefix + "_I;\n" : baseName + "HttpRequest;\n")
|
||||
.append("import ").append(integrationPackage).append(".io.").append(mci ? ioPrefix + "_O;\n" : baseName + "HttpResponse;\n");
|
||||
if (mci) imports.append("import io.shinhanlife.glow.communication.dto.Transfer;\n");
|
||||
if (mci) {
|
||||
imports.append("import io.shinhanlife.glow.communication.dto.Transfer;\n");
|
||||
imports.append("import lombok.extern.slf4j.Slf4j;\n");
|
||||
}
|
||||
if (!fields.toString().contains(" " + clientVariable + ";")) {
|
||||
fields.append(" private final ").append(clientClassName).append(" ").append(clientVariable).append(";\n");
|
||||
}
|
||||
fields.append(" private final ").append(baseName).append("Converter ").append(converterVariable).append(";\n");
|
||||
if (!fields.toString().contains(" " + converterVariable + ";")) {
|
||||
fields.append(" private final ").append(baseName).append("Converter ").append(converterVariable).append(";\n");
|
||||
}
|
||||
methods.append(groupedToolMethodContent(tool, baseName, converterVariable, clientVariable, ioPrefix, mci));
|
||||
}
|
||||
String slf4jAnno = tools.stream().anyMatch(t -> "MCI".equalsIgnoreCase(t.routingType())) ? "@Slf4j\n" : "";
|
||||
return "package " + bizPackage + ".usecase.impl;\n\n"
|
||||
+ "import " + bizPackage + ".usecase." + useCaseBaseName + "UseCase;\n"
|
||||
+ "import lombok.RequiredArgsConstructor;\nimport org.springframework.stereotype.Service;\n" + imports
|
||||
+ "\n@Service\n@RequiredArgsConstructor\npublic class " + useCaseBaseName + "UseCaseImpl implements " + useCaseBaseName + "UseCase {\n\n"
|
||||
+ "\n" + slf4jAnno + "@Service\n@RequiredArgsConstructor\npublic class " + useCaseBaseName + "UseCaseImpl implements " + useCaseBaseName + "UseCase {\n\n"
|
||||
+ fields + "\n" + methods + "}\n";
|
||||
}
|
||||
|
||||
@@ -353,35 +382,43 @@ public class ToolScaffolder {
|
||||
String converterVariable, String clientVariable,
|
||||
String ioPrefix, boolean mci) {
|
||||
if (mci) {
|
||||
String snakeToolName = (tool.group() != null && !tool.group().isBlank() ? tool.group().toLowerCase(Locale.ROOT) + "_" : "")
|
||||
+ toKebabCase(baseName).toLowerCase(Locale.ROOT).replace("-", "_");
|
||||
String receiveServiceId = tool.clientSystemCode() != null ? tool.clientSystemCode().toUpperCase() : "";
|
||||
return """
|
||||
|
||||
@Override
|
||||
public %sResponse %s(%sRequest req) {
|
||||
%s_I request = %s.toRequest(req);
|
||||
log.info("[MCI Tool] {} 요청 수신.", "%s");
|
||||
try {
|
||||
Transfer<%s_O> transfer = %s.callTo("%s", null, request, %s_O.class);
|
||||
if (transfer == null || transfer.getBody() == null) {
|
||||
%sResponse errorResponse = new %sResponse();
|
||||
errorResponse.setResultCode("ERROR");
|
||||
return errorResponse;
|
||||
// MapStruct를 이용한 자동 매핑 (AI DTO -> MCI DTO)
|
||||
%s_I mciReq = %s.toRequest(req);
|
||||
|
||||
Transfer<%s_O> resTransfer = %s.callTo(
|
||||
"%s",
|
||||
"%s",
|
||||
mciReq,
|
||||
%s_O.class
|
||||
);
|
||||
%sResponse response = new %sResponse();
|
||||
if (resTransfer != null && resTransfer.getBody() != null) {
|
||||
response = %s.toResponse(resTransfer.getBody());
|
||||
}
|
||||
%sResponse toolResponse = %s.toResponse(transfer.getBody());
|
||||
if (toolResponse == null) {
|
||||
toolResponse = new %sResponse();
|
||||
toolResponse.setResultCode("ERROR");
|
||||
return toolResponse;
|
||||
}
|
||||
toolResponse.setResultCode("SUCCESS");
|
||||
return toolResponse;
|
||||
response.setResultCode("SUCCESS");
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
log.error("[MCI Tool] 연동 중 오류 발생: {}", e.getMessage(), e);
|
||||
%sResponse errorResponse = new %sResponse();
|
||||
errorResponse.setResultCode("ERROR");
|
||||
errorResponse.setResultMessage("MCI call failed.");
|
||||
errorResponse.setResultMessage("MCI call failed: " + e.getMessage());
|
||||
return errorResponse;
|
||||
}
|
||||
}
|
||||
""".formatted(baseName, tool.methodName(), baseName, ioPrefix, converterVariable, ioPrefix,
|
||||
clientVariable, tool.interfaceId(), ioPrefix, baseName, baseName, baseName, converterVariable, baseName,
|
||||
""".formatted(baseName, tool.methodName(), baseName, snakeToolName,
|
||||
ioPrefix, converterVariable,
|
||||
ioPrefix, clientVariable, tool.interfaceId(), receiveServiceId, ioPrefix,
|
||||
baseName, baseName,
|
||||
converterVariable,
|
||||
baseName, baseName);
|
||||
}
|
||||
return """
|
||||
@@ -507,12 +544,12 @@ public class ToolScaffolder {
|
||||
String clientVariable;
|
||||
if (mci) {
|
||||
clientClassName = mciClientClassName(tool.clientSystemCode());
|
||||
clientVariable = mciClientVariable(tool.clientSystemCode());
|
||||
clientVariable = "mci";
|
||||
} else {
|
||||
clientClassName = baseName + "Client";
|
||||
clientVariable = Character.toLowerCase(baseName.charAt(0)) + baseName.substring(1) + "Client";
|
||||
}
|
||||
String converterVariable = Character.toLowerCase(baseName.charAt(0)) + baseName.substring(1) + "Converter";
|
||||
String converterVariable = "converter";
|
||||
|
||||
implementation = addImport(implementation, "import " + bizPackage + ".dto." + requestType + ";");
|
||||
implementation = addImport(implementation, "import " + bizPackage + ".dto." + responseType + ";");
|
||||
@@ -520,7 +557,13 @@ public class ToolScaffolder {
|
||||
implementation = addImport(implementation, "import " + integrationPackage + "." + clientClassName + ";");
|
||||
implementation = addImport(implementation, "import " + integrationPackage + ".io." + requestIo + ";");
|
||||
implementation = addImport(implementation, "import " + integrationPackage + ".io." + responseIo + ";");
|
||||
if (mci) implementation = addImport(implementation, "import io.shinhanlife.glow.communication.dto.Transfer;");
|
||||
if (mci) {
|
||||
implementation = addImport(implementation, "import io.shinhanlife.glow.communication.dto.Transfer;");
|
||||
implementation = addImport(implementation, "import lombok.extern.slf4j.Slf4j;");
|
||||
if (!implementation.contains("@Slf4j")) {
|
||||
implementation = implementation.replaceFirst("public class ", "@Slf4j\npublic class ");
|
||||
}
|
||||
}
|
||||
implementation = addImport(implementation, "import lombok.RequiredArgsConstructor;");
|
||||
if (!implementation.contains("@RequiredArgsConstructor")) {
|
||||
implementation = implementation.replaceFirst("public class ", "@RequiredArgsConstructor\npublic class ");
|
||||
@@ -528,7 +571,9 @@ public class ToolScaffolder {
|
||||
if (!implementation.contains(" " + clientVariable + ";")) {
|
||||
implementation = insertConstructorField(implementation, " private final " + clientClassName + " " + clientVariable + ";");
|
||||
}
|
||||
implementation = insertConstructorField(implementation, " private final " + baseName + "Converter " + converterVariable + ";");
|
||||
if (!implementation.contains(" " + converterVariable + ";")) {
|
||||
implementation = insertConstructorField(implementation, " private final " + baseName + "Converter " + converterVariable + ";");
|
||||
}
|
||||
String method = groupedToolMethodContent(tool, baseName, converterVariable, clientVariable, ioPrefix, mci);
|
||||
implementation = insertBeforeLastBrace(implementation, method);
|
||||
}
|
||||
@@ -979,7 +1024,7 @@ public class ToolScaffolder {
|
||||
if (mciReq != null) {
|
||||
resTransfer = mci.callTo(
|
||||
"%s",
|
||||
null,
|
||||
"%s",
|
||||
mciReq,
|
||||
%s_O.class
|
||||
);
|
||||
@@ -1034,6 +1079,7 @@ public class ToolScaffolder {
|
||||
ioPrefix,
|
||||
ioPrefix,
|
||||
interfaceId,
|
||||
((clientSystemCode != null && !clientSystemCode.isBlank()) ? clientSystemCode.toUpperCase() : ""),
|
||||
ioPrefix,
|
||||
baseName,
|
||||
baseName,
|
||||
@@ -1246,14 +1292,17 @@ public class ToolScaffolder {
|
||||
log.append("[MCI Converter] ").append(converterDir.resolve(baseName + "Converter.java")).append("\n");
|
||||
|
||||
if (!clientPrefixCap.isEmpty()) {
|
||||
String receiveServiceId = (clientSystemCode != null && !clientSystemCode.isBlank()) ? clientSystemCode.toUpperCase() : "";
|
||||
String mciClientContent = """
|
||||
package %s.%s;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import io.shinhanlife.dat.lib.integration.mci.component.AxhubMciComponent;
|
||||
import io.shinhanlife.glow.communication.dto.Transfer;
|
||||
|
||||
import %s.%s.io.%s_I;
|
||||
import %s.%s.io.%s_O;
|
||||
|
||||
/**
|
||||
* @package %s.%s
|
||||
* @className Mci%sClient
|
||||
@@ -1265,21 +1314,37 @@ public class ToolScaffolder {
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 최초생성
|
||||
*
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class Mci%sClient {
|
||||
private final AxhubMciComponent mci;
|
||||
|
||||
public <O> Transfer<O> callTo(String interfaceId, String dummy, Object mciReq, Class<O> resType) throws Exception {
|
||||
return mci.callTo(interfaceId, dummy, mciReq, resType);
|
||||
|
||||
private static final String INTERFACE_ID = "%s";
|
||||
private static final String RECEIVE_SERVICE_ID = "%s";
|
||||
|
||||
private final AxhubMciComponent mciComponent;
|
||||
|
||||
public <O> Transfer<O> callTo(String interfaceId, String receiveServiceId, Object mciReq, Class<O> resType) {
|
||||
return mciComponent.callTo(interfaceId, receiveServiceId, mciReq, resType);
|
||||
}
|
||||
|
||||
public %s_O call%s(%s_I request) {
|
||||
Transfer<%s_O> transfer = mciComponent.callTo(
|
||||
INTERFACE_ID, RECEIVE_SERVICE_ID, request, %s_O.class);
|
||||
return transfer == null ? null : transfer.getBody();
|
||||
}
|
||||
}
|
||||
""".formatted(
|
||||
BASE_PACKAGE, mciGroupPath.replace("/", "."),
|
||||
BASE_PACKAGE, mciGroupPath.replace("/", "."), clientPrefixCap, author, createDate, createDate, author, clientPrefixCap
|
||||
BASE_PACKAGE, mciGroupPath.replace("/", "."), ioPrefix,
|
||||
BASE_PACKAGE, mciGroupPath.replace("/", "."), ioPrefix,
|
||||
BASE_PACKAGE, mciGroupPath.replace("/", "."), clientPrefixCap, author, createDate, createDate, author,
|
||||
clientPrefixCap,
|
||||
interfaceId, receiveServiceId,
|
||||
ioPrefix, toPascalCase(ioPrefix), ioPrefix,
|
||||
ioPrefix, ioPrefix
|
||||
);
|
||||
writeUtf8(mciClientDir.resolve("Mci" + clientPrefixCap + "Client.java"), mciClientContent);
|
||||
log.append("[MCI Client] ").append(mciClientDir.resolve("Mci" + clientPrefixCap + "Client.java")).append("\n");
|
||||
|
||||
Reference in New Issue
Block a user