fix: preserve Korean text in scaffold output
All checks were successful
Deploy to OCIWP / deploy (push) Successful in 2m28s
All checks were successful
Deploy to OCIWP / deploy (push) Successful in 2m28s
This commit is contained in:
@@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@@ -72,7 +73,7 @@ public class PodScaffolder {
|
||||
implementation project(':dap-was-lib')
|
||||
}
|
||||
""";
|
||||
Files.writeString(modulePath.resolve("build.gradle"), buildGradle);
|
||||
writeUtf8(modulePath.resolve("build.gradle"), buildGradle);
|
||||
|
||||
log.append("[3/6] Dockerfile 생성 중...\n");
|
||||
String dockerfile = """
|
||||
@@ -84,7 +85,7 @@ public class PodScaffolder {
|
||||
EXPOSE %s
|
||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||
""".formatted(moduleName, portStr);
|
||||
Files.writeString(modulePath.resolve("Dockerfile"), dockerfile);
|
||||
writeUtf8(modulePath.resolve("Dockerfile"), dockerfile);
|
||||
|
||||
log.append("[4/6] Application 클래스 및 설정 파일 생성 중...\n");
|
||||
Path srcPath = modulePath.resolve("src/main/java/io/shinhanlife/dap/mcc/" + shortName);
|
||||
@@ -121,7 +122,7 @@ public class PodScaffolder {
|
||||
}
|
||||
}
|
||||
""".formatted(shortName, shortName, capitalize(shortName), author, createDate, createDate, author, capitalize(shortName), capitalize(shortName));
|
||||
Files.writeString(srcPath.resolve("DapWas" + capitalize(shortName) + "Application.java"), appClass);
|
||||
writeUtf8(srcPath.resolve("DapWas" + capitalize(shortName) + "Application.java"), appClass);
|
||||
|
||||
Path resPath = modulePath.resolve("src/main/resources");
|
||||
Files.createDirectories(resPath);
|
||||
@@ -145,7 +146,7 @@ public class PodScaffolder {
|
||||
tenant-domains:
|
||||
TESTER-DEV: ALL
|
||||
""".formatted(portStr, moduleName, moduleName.replace("dap-", ""));
|
||||
Files.writeString(resPath.resolve("application.yml"), applicationYml);
|
||||
writeUtf8(resPath.resolve("application.yml"), applicationYml);
|
||||
|
||||
String applicationLocalYml = """
|
||||
# Local 환경 전용 설정 (H2 메모리 DB 등)
|
||||
@@ -194,7 +195,7 @@ public class PodScaffolder {
|
||||
tool:
|
||||
url: ${AXHUB_TOOL_URL:http://localhost:${server.port}}
|
||||
""";
|
||||
Files.writeString(resPath.resolve("application-local.yml"), applicationLocalYml);
|
||||
writeUtf8(resPath.resolve("application-local.yml"), applicationLocalYml);
|
||||
|
||||
String applicationDevYml = """
|
||||
# OCI 클라우드 환경 전용 설정
|
||||
@@ -244,7 +245,7 @@ public class PodScaffolder {
|
||||
externalMci:
|
||||
url: http://10.176.32.176
|
||||
""".formatted(portStr, portStr);
|
||||
Files.writeString(resPath.resolve("application-dev.yml"), applicationDevYml);
|
||||
writeUtf8(resPath.resolve("application-dev.yml"), applicationDevYml);
|
||||
|
||||
String applicationTestYml = """
|
||||
server:
|
||||
@@ -264,7 +265,7 @@ public class PodScaffolder {
|
||||
tool:
|
||||
url: ${AXHUB_TOOL_URL}
|
||||
""".formatted(portStr);
|
||||
Files.writeString(resPath.resolve("application-test.yml"), applicationTestYml);
|
||||
writeUtf8(resPath.resolve("application-test.yml"), applicationTestYml);
|
||||
|
||||
String applicationProdYml = """
|
||||
server:
|
||||
@@ -284,7 +285,7 @@ public class PodScaffolder {
|
||||
tool:
|
||||
url: ${AXHUB_TOOL_URL}
|
||||
""".formatted(portStr);
|
||||
Files.writeString(resPath.resolve("application-prod.yml"), applicationProdYml);
|
||||
writeUtf8(resPath.resolve("application-prod.yml"), applicationProdYml);
|
||||
|
||||
String logbackXml = """
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -312,21 +313,21 @@ public class PodScaffolder {
|
||||
<logger name="io.shinhanlife" level="DEBUG" />
|
||||
</configuration>
|
||||
""".formatted(moduleName, moduleName);
|
||||
Files.writeString(resPath.resolve("logback-spring.xml"), logbackXml);
|
||||
writeUtf8(resPath.resolve("logback-spring.xml"), logbackXml);
|
||||
|
||||
log.append("[5/6] settings.gradle 에 모듈 등록 중...\n");
|
||||
Path settingsPath = rootDir.resolve(Paths.get("settings.gradle"));
|
||||
if (Files.exists(settingsPath)) {
|
||||
String settings = Files.readString(settingsPath);
|
||||
String settings = Files.readString(settingsPath, StandardCharsets.UTF_8);
|
||||
if (!settings.contains("include '" + moduleName + "'")) {
|
||||
Files.writeString(settingsPath, System.lineSeparator() + "include '" + moduleName + "'" + System.lineSeparator(), StandardOpenOption.APPEND);
|
||||
Files.writeString(settingsPath, System.lineSeparator() + "include '" + moduleName + "'" + System.lineSeparator(), StandardCharsets.UTF_8, StandardOpenOption.APPEND);
|
||||
}
|
||||
}
|
||||
|
||||
log.append("[6/6] docker-compose.yml 에 서비스 추가 중...\n");
|
||||
Path dockerComposePath = rootDir.resolve(Paths.get("docker-compose.yml"));
|
||||
if (Files.exists(dockerComposePath)) {
|
||||
String compose = Files.readString(dockerComposePath);
|
||||
String compose = Files.readString(dockerComposePath, StandardCharsets.UTF_8);
|
||||
String serviceName = moduleName.replace("dap-", ""); // e.g. tool-payment
|
||||
if (!compose.contains(" " + serviceName + ":")) {
|
||||
String newService = """
|
||||
@@ -352,7 +353,7 @@ public class PodScaffolder {
|
||||
- GLOW_COMMUNICATION_EAI_HOST=http://mci-mock
|
||||
- GLOW_COMMUNICATION_EAI_PORT=8080
|
||||
""".formatted(serviceName, moduleName, portStr, portStr, serviceName, portStr);
|
||||
Files.writeString(dockerComposePath, System.lineSeparator() + newService, StandardOpenOption.APPEND);
|
||||
Files.writeString(dockerComposePath, System.lineSeparator() + newService, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,6 +366,10 @@ public class PodScaffolder {
|
||||
return log.toString();
|
||||
}
|
||||
|
||||
private static void writeUtf8(Path path, String content) throws IOException {
|
||||
Files.writeString(path, content, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static String capitalize(String str) {
|
||||
if (str == null || str.isEmpty()) return str;
|
||||
return str.substring(0, 1).toUpperCase() + str.substring(1);
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -14,28 +15,28 @@ import java.util.Set;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* MCP Tool 肄붾뱶瑜??먮룞 ?앹꽦(Scaffolding)?섎뒗 ?좏떥由ы떚 ?대옒??
|
||||
* MCP Tool 코드를 자동 생성(Scaffolding)하는 유틸리티 클래스입니다.
|
||||
*
|
||||
* [?ㅽ뻾 諛⑸쾿]
|
||||
* 諛⑸쾿 1. IDE(IntelliJ ???먯꽌 吏곸젒 ?ㅽ뻾 (??뷀삎 紐⑤뱶 異붿쿇 狩?
|
||||
* - ???대옒??ToolScaffolder.java)瑜??닿퀬 main 硫붿꽌?쒕? 吏곸젒 ?ㅽ뻾(Run)?⑸땲??
|
||||
* - 肄섏넄 李쎌뿉 ?⑤뒗 吏덈Ц??李⑤??濡?媛믪쓣 ?낅젰?섍린留??섎㈃ ?뚯씪???앹꽦?⑸땲??
|
||||
* [실행 방법]
|
||||
* 방법 1. IDE(IntelliJ 등)에서 직접 실행
|
||||
* - ToolScaffolder.java의 main 메서드를 실행합니다.
|
||||
* - 콘솔 질문에 차례대로 값을 입력하면 파일이 생성됩니다.
|
||||
*
|
||||
* 諛⑸쾿 2. 而ㅻ㎤?쒕씪???곕????먯꽌 ?ㅽ뻾 (紐낅졊??湲곕컲)
|
||||
* - 而댄뙆?? javac -encoding UTF-8 dap-was-lib/src/main/java/io/shinhanlife/dap/mcc/util/ToolScaffolder.java
|
||||
* - ?ㅽ뻾: java -cp dap-was-lib/src/main/java io.shinhanlife.dap.lib.util.ToolScaffolder [?대쫫] [ID] "[?ㅻ챸]" "[洹몃9]" "[?듭떊諛⑹떇]" "[紐⑤뱢紐?"
|
||||
* 방법 2. 명령줄에서 실행
|
||||
* - 컴파일: javac -encoding UTF-8 dap-was-lib/src/main/java/io/shinhanlife/dap/lib/util/ToolScaffolder.java
|
||||
* - 실행: java -cp dap-was-lib/src/main/java io.shinhanlife.dap.lib.util.ToolScaffolder [이름] [ID] "[설명]" "[그룹]" "[통신방식]" "[모듈명]"
|
||||
*/
|
||||
/**
|
||||
* @package io.shinhanlife.dap.lib.util
|
||||
* @className ToolScaffolder
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author 0986406
|
||||
* @create 2026.09.01
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.09.01 0986406 理쒖큹?앹꽦
|
||||
* 2026.09.01 0986406 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -65,8 +66,8 @@ public class ToolScaffolder {
|
||||
System.out.println(" MCP Tool Scaffolder (Java CLI) ");
|
||||
System.out.println("=========================================\n");
|
||||
|
||||
String baseName = getOrAsk(args, 0, scanner, "1. ?앹꽦??Tool??湲곕낯 ?대쫫 (?? ExchangeRate) [?곷Ц PascalCase]: ");
|
||||
String interfaceId = getOrAsk(args, 1, scanner, "2. ?덇굅??API ?명꽣?섏씠??ID (?? EXCH_001): ");
|
||||
String baseName = getOrAsk(args, 0, scanner, "1. 생성할 Tool의 기본 이름 (예: ExchangeRate) [영문 PascalCase]: ");
|
||||
String interfaceId = getOrAsk(args, 1, scanner, "2. 레거시 API 인터페이스 ID (예: EXCH_001): ");
|
||||
String title = getOrAsk(args, 2, scanner, "3. Tool title: ");
|
||||
String description = getOrAsk(args, 3, scanner, "4. Tool description for LLM: ");
|
||||
String group = getOrAsk(args, 4, scanner, "5. Tool category: ");
|
||||
@@ -83,12 +84,12 @@ public class ToolScaffolder {
|
||||
String defaultAuthor = System.getProperty("user.name");
|
||||
String defaultDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy.MM.dd"));
|
||||
|
||||
String author = getOrAsk(args, 7, scanner, "7. ?묒꽦??(?뷀꽣 ?낅젰 ??'" + defaultAuthor + "'): ");
|
||||
String author = getOrAsk(args, 7, scanner, "8. 작성자(Enter 입력 시 '" + defaultAuthor + "'): ");
|
||||
if (author.trim().isEmpty()) author = defaultAuthor;
|
||||
String createDate = getOrAsk(args, 8, scanner, "8. ?묒꽦??(?뷀꽣 ?낅젰 ??'" + defaultDate + "'): ");
|
||||
String createDate = getOrAsk(args, 8, scanner, "9. 작성일(Enter 입력 시 '" + defaultDate + "'): ");
|
||||
if (createDate.trim().isEmpty()) createDate = defaultDate;
|
||||
|
||||
String useSchemaResourceStr = getOrAsk(args, 9, scanner, "9. input/output JSON Schema ?뚯씪 ?먮룞 ?앹꽦 ?щ? (y/N): ");
|
||||
String useSchemaResourceStr = getOrAsk(args, 9, scanner, "10. input/output JSON Schema 파일 자동 생성 여부 (y/N): ");
|
||||
boolean useSchemaResource = "y".equalsIgnoreCase(useSchemaResourceStr.trim());
|
||||
|
||||
String schemaResourceDirectory = "classpath:tool-schemas/" + group.toLowerCase() + "/";
|
||||
@@ -161,7 +162,7 @@ public class ToolScaffolder {
|
||||
Path legacyDtoDir = rootDir.resolve(Paths.get(moduleName, BASE_PACKAGE_PATH, "biz", group.toLowerCase(), "legacy"));
|
||||
Path converterDir = rootDir.resolve(Paths.get(moduleName, BASE_PACKAGE_PATH, "biz", group.toLowerCase(), "converter"));
|
||||
|
||||
// schema resource ?뚯씪 寃쎈줈 (useSchemaResource=true ???뚮쭔 ?앹꽦)
|
||||
// Schema Resource 파일 경로(useSchemaResource=true일 때만 생성)
|
||||
boolean useSchemaResource = (inputSchemaResource != null && !inputSchemaResource.trim().isEmpty()) || (outputSchemaResource != null && !outputSchemaResource.trim().isEmpty());
|
||||
String schemaBaseName = toKebabCase(baseName);
|
||||
String inputSchemaFileName = schemaBaseName + "-resource-input-schema.json";
|
||||
@@ -222,25 +223,25 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.dto
|
||||
* @className %sRequest
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class %sRequest {
|
||||
@McpToolParam(description = "?섏떊???꾪솕踰덊샇", required = true)
|
||||
@McpToolParam(description = "수신자 전화번호", required = true)
|
||||
-(?:\\\\d{3}|\\\\d{4})-\\\\d{4}$", examples = {"010-1234-5678"})
|
||||
private String phoneNumber;
|
||||
|
||||
@McpToolParam(description = "?꾩넚??硫붿떆吏 ?댁슜", required = true)
|
||||
@McpToolParam(description = "전송할 메시지 내용", required = true)
|
||||
private String message;
|
||||
}
|
||||
""".formatted(bizPackage, bizPackage, baseName, author, createDate, createDate, author, baseName);
|
||||
@@ -250,9 +251,9 @@ public class ToolScaffolder {
|
||||
.replaceAll("(?m)^\\s*@McpToolParam\\([^\\r\\n]*\\)\\R", "")
|
||||
.replaceAll("(?m)^\\s*-\\(\\?:[^\\r\\n]*\\R", "")
|
||||
.replace("private String phoneNumber;", "@Schema(example = \"01012345678\")\n private String phoneNumber;")
|
||||
.replace("private String message;", "@Schema(example = \"?뚯뒪??硫붿떆吏?낅땲??\")\n private String message;");
|
||||
.replace("private String message;", "@Schema(example = \"테스트 메시지입니다.\")\n private String message;");
|
||||
reqContent = dtoContent(bizPackage + ".dto", baseName + "Request", inputFields, author, createDate, true);
|
||||
Files.writeString(dtoDir.resolve(baseName + "Request.java"), reqContent);
|
||||
writeUtf8(dtoDir.resolve(baseName + "Request.java"), reqContent);
|
||||
|
||||
// Generate Response DTO
|
||||
String resContent = """
|
||||
@@ -264,14 +265,14 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.dto
|
||||
* @className %sResponse
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -286,7 +287,7 @@ public class ToolScaffolder {
|
||||
}
|
||||
""".formatted(bizPackage, bizPackage, baseName, author, createDate, createDate, author, baseName);
|
||||
resContent = dtoContent(bizPackage + ".dto", baseName + "Response", outputFields, author, createDate, false);
|
||||
Files.writeString(dtoDir.resolve(baseName + "Response.java"), resContent);
|
||||
writeUtf8(dtoDir.resolve(baseName + "Response.java"), resContent);
|
||||
|
||||
String toolName = toToolName(moduleName, group, baseName);
|
||||
|
||||
@@ -310,14 +311,14 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.usecase
|
||||
* @className %sUseCase
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -338,7 +339,7 @@ public class ToolScaffolder {
|
||||
baseName, baseName
|
||||
);
|
||||
|
||||
Files.writeString(usecaseDir.resolve(baseName + "UseCase.java"), serviceInterfaceContent);
|
||||
writeUtf8(usecaseDir.resolve(baseName + "UseCase.java"), serviceInterfaceContent);
|
||||
|
||||
String serviceImplContent;
|
||||
|
||||
@@ -361,14 +362,14 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.usecase.impl
|
||||
* @className %sUseCaseImpl
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -382,9 +383,9 @@ public class ToolScaffolder {
|
||||
|
||||
@Override
|
||||
public %sResponse execute(%sRequest req) {
|
||||
log.info("[MCI Tool] {} ?붿껌 ?섏떊.", "%s");
|
||||
log.info("[MCI Tool] {} 요청 수신.", "%s");
|
||||
try {
|
||||
// MapStruct瑜??댁슜???먮룞 留ㅽ븨 (AI DTO -> MCI DTO)
|
||||
// MapStruct를 이용한 자동 매핑 (AI DTO -> MCI DTO)
|
||||
%s_I mciReq = converter.toLegacyRequest(req);
|
||||
|
||||
Transfer<Object> resTransfer = mci.callTo(
|
||||
@@ -400,7 +401,7 @@ public class ToolScaffolder {
|
||||
: "MCI call completed without a response body.");
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
log.error("[MCI Tool] ?곕룞 以??ㅻ쪟 諛쒖깮: {}", e.getMessage(), e);
|
||||
log.error("[MCI Tool] 연동 중 오류 발생: {}", e.getMessage(), e);
|
||||
%sResponse response = new %sResponse();
|
||||
response.setResultCode("ERROR");
|
||||
response.setResultMessage(e.getMessage() != null ? e.getMessage() : "Unknown error");
|
||||
@@ -460,14 +461,14 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.usecase.impl
|
||||
* @className %sUseCaseImpl
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -513,7 +514,7 @@ public class ToolScaffolder {
|
||||
);
|
||||
}
|
||||
|
||||
Files.writeString(usecaseImplDir.resolve(baseName + "UseCaseImpl.java"), serviceImplContent);
|
||||
writeUtf8(usecaseImplDir.resolve(baseName + "UseCaseImpl.java"), serviceImplContent);
|
||||
|
||||
if (isMci) {
|
||||
String mciReqContent = """
|
||||
@@ -524,32 +525,32 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.%s.io
|
||||
* @className %s_I
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Data
|
||||
public class %s_I {
|
||||
/**
|
||||
* EAI ?쒖뒪?쒖씠 ?붽뎄?섎뒗 ?섏떊??踰덊샇 ?뚮씪誘명꽣紐?
|
||||
* EAI 시스템이 요구하는 수신자 번호 파라미터명
|
||||
*/
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* EAI ?쒖뒪?쒖씠 ?붽뎄?섎뒗 硫붿떆吏 ?댁슜 ?뚮씪誘명꽣紐?
|
||||
* EAI 시스템이 요구하는 메시지 내용 파라미터명
|
||||
*/
|
||||
private String content;
|
||||
}
|
||||
""".formatted(BASE_PACKAGE, mciGroupPath.replace("/", "."), BASE_PACKAGE, mciGroupPath.replace("/", "."), interfaceId, author, createDate, createDate, author, interfaceId);
|
||||
mciReqContent = mciIoContent(mciGroupPath.replace("/", "."), interfaceId + "_I", inputFields, author, createDate);
|
||||
Files.writeString(mciIoDir.resolve(interfaceId + "_I.java"), mciReqContent);
|
||||
writeUtf8(mciIoDir.resolve(interfaceId + "_I.java"), mciReqContent);
|
||||
|
||||
String mciResContent = """
|
||||
package %s.%s.io;
|
||||
@@ -559,14 +560,14 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.%s.io
|
||||
* @className %s_O
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -576,7 +577,7 @@ public class ToolScaffolder {
|
||||
}
|
||||
""".formatted(BASE_PACKAGE, mciGroupPath.replace("/", "."), BASE_PACKAGE, mciGroupPath.replace("/", "."), interfaceId, author, createDate, createDate, author, interfaceId);
|
||||
mciResContent = mciIoContent(mciGroupPath.replace("/", "."), interfaceId + "_O", outputFields, author, createDate);
|
||||
Files.writeString(mciIoDir.resolve(interfaceId + "_O.java"), mciResContent);
|
||||
writeUtf8(mciIoDir.resolve(interfaceId + "_O.java"), mciResContent);
|
||||
|
||||
String converterContent = """
|
||||
package %s.converter;
|
||||
@@ -592,14 +593,14 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.converter
|
||||
* @className %sConverter
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -628,7 +629,7 @@ public class ToolScaffolder {
|
||||
baseName, interfaceId
|
||||
);
|
||||
converterContent = mciConverterContent(bizPackage, baseName, mciGroupPath.replace("/", "."), interfaceId);
|
||||
Files.writeString(converterDir.resolve(baseName + "Converter.java"), converterContent);
|
||||
writeUtf8(converterDir.resolve(baseName + "Converter.java"), converterContent);
|
||||
|
||||
log.append("\n=========================================\n");
|
||||
log.append(" Scaffolding Complete! (Routing: " + routingType + ")\n");
|
||||
@@ -653,14 +654,14 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.%s
|
||||
* @className Mci%sClient
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -677,7 +678,7 @@ public class ToolScaffolder {
|
||||
BASE_PACKAGE, mciGroupPath.replace("/", "."),
|
||||
BASE_PACKAGE, mciGroupPath.replace("/", "."), clientPrefixCap, author, createDate, createDate, author, clientPrefixCap
|
||||
);
|
||||
Files.writeString(mciClientDir.resolve("Mci" + clientPrefixCap + "Client.java"), mciClientContent);
|
||||
writeUtf8(mciClientDir.resolve("Mci" + clientPrefixCap + "Client.java"), mciClientContent);
|
||||
log.append("[MCI Client] ").append(mciClientDir.resolve("Mci" + clientPrefixCap + "Client.java")).append("\n");
|
||||
}
|
||||
|
||||
@@ -687,13 +688,13 @@ public class ToolScaffolder {
|
||||
String httpResponseClass = baseName + "HttpResponse";
|
||||
String httpClientClass = httpApiClass + "Client";
|
||||
|
||||
Files.writeString(httpIoDir.resolve(httpRequestClass + ".java"),
|
||||
writeUtf8(httpIoDir.resolve(httpRequestClass + ".java"),
|
||||
dtoContent(httpPackage + ".io", httpRequestClass, inputFields, author, createDate, true));
|
||||
Files.writeString(httpIoDir.resolve(httpResponseClass + ".java"),
|
||||
writeUtf8(httpIoDir.resolve(httpResponseClass + ".java"),
|
||||
dtoContent(httpPackage + ".io", httpResponseClass, outputFields, author, createDate, false));
|
||||
Files.writeString(httpClientDir.resolve(httpClientClass + ".java"),
|
||||
writeUtf8(httpClientDir.resolve(httpClientClass + ".java"),
|
||||
httpClientContent(httpPackage, httpClientClass, httpApiName));
|
||||
Files.writeString(converterDir.resolve(baseName + "Converter.java"),
|
||||
writeUtf8(converterDir.resolve(baseName + "Converter.java"),
|
||||
httpConverterContent(bizPackage, baseName, httpPackage));
|
||||
|
||||
log.append("\n=========================================\n");
|
||||
@@ -716,32 +717,32 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.legacy
|
||||
* @className %sLegacyRequest
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Data
|
||||
public class %sLegacyRequest {
|
||||
/**
|
||||
* EAI ?쒖뒪?쒖씠 ?붽뎄?섎뒗 ?섏떊??踰덊샇 ?뚮씪誘명꽣紐?
|
||||
* EAI 시스템이 요구하는 수신자 번호 파라미터명
|
||||
*/
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* EAI ?쒖뒪?쒖씠 ?붽뎄?섎뒗 硫붿떆吏 ?댁슜 ?뚮씪誘명꽣紐?
|
||||
* EAI 시스템이 요구하는 메시지 내용 파라미터명
|
||||
*/
|
||||
private String content;
|
||||
}
|
||||
""".formatted(bizPackage, bizPackage, baseName, author, createDate, createDate, author, baseName);
|
||||
legacyReqContent = dtoContent(bizPackage + ".legacy", baseName + "LegacyRequest", inputFields, author, createDate, true);
|
||||
Files.writeString(legacyDtoDir.resolve(baseName + "LegacyRequest.java"), legacyReqContent);
|
||||
writeUtf8(legacyDtoDir.resolve(baseName + "LegacyRequest.java"), legacyReqContent);
|
||||
|
||||
String legacyResContent = """
|
||||
package %s.legacy;
|
||||
@@ -751,14 +752,14 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.legacy
|
||||
* @className %sLegacyResponse
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -768,7 +769,7 @@ public class ToolScaffolder {
|
||||
}
|
||||
""".formatted(bizPackage, bizPackage, baseName, author, createDate, createDate, author, baseName);
|
||||
legacyResContent = dtoContent(bizPackage + ".legacy", baseName + "LegacyResponse", outputFields, author, createDate, true);
|
||||
Files.writeString(legacyDtoDir.resolve(baseName + "LegacyResponse.java"), legacyResContent);
|
||||
writeUtf8(legacyDtoDir.resolve(baseName + "LegacyResponse.java"), legacyResContent);
|
||||
|
||||
String converterContent = """
|
||||
package %s.converter;
|
||||
@@ -784,14 +785,14 @@ public class ToolScaffolder {
|
||||
/**
|
||||
* @package %s.converter
|
||||
* @className %sConverter
|
||||
* @description AX HUB ?쒖뒪??泥섎━ ?대옒??
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author %s
|
||||
* @create %s
|
||||
* <pre>
|
||||
* ---------- 媛쒖젙?대젰 ----------
|
||||
* ?섏젙?? ?섏젙?? ?섏젙?댁슜
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* %s %s 理쒖큹?앹꽦
|
||||
* %s %s 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@@ -818,7 +819,7 @@ public class ToolScaffolder {
|
||||
baseName, baseName, baseName, baseName, baseName, baseName, baseName
|
||||
);
|
||||
converterContent = legacyConverterContent(bizPackage, baseName);
|
||||
Files.writeString(converterDir.resolve(baseName + "Converter.java"), converterContent);
|
||||
writeUtf8(converterDir.resolve(baseName + "Converter.java"), converterContent);
|
||||
|
||||
log.append("\n=========================================\n");
|
||||
log.append(" Scaffolding Complete! (Routing: " + routingType + ")\n");
|
||||
@@ -831,7 +832,7 @@ public class ToolScaffolder {
|
||||
log.append("[Legacy Response DTO] ").append(legacyDtoDir.resolve(baseName + "LegacyResponse.java")).append("\n");
|
||||
log.append("[Legacy Converter] ").append(converterDir.resolve(baseName + "Converter.java")).append("\n");
|
||||
}
|
||||
// schema resource ?뚯씪 ?앹꽦 (useSchemaResource=true ????
|
||||
// Schema Resource 파일 생성(useSchemaResource=true일 때)
|
||||
if (useSchemaResource) {
|
||||
Files.createDirectories(schemaDir);
|
||||
String inputSchema = """
|
||||
@@ -841,7 +842,7 @@ public class ToolScaffolder {
|
||||
"properties": {
|
||||
"TODO_FIELD": {
|
||||
"type": "string",
|
||||
"description": "TODO: ?뚮씪誘명꽣 ?ㅻ챸???낅젰?섏꽭??"
|
||||
"description": "TODO: 파라미터 설명을 입력하세요."
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
@@ -854,19 +855,19 @@ public class ToolScaffolder {
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "泥섎━ 寃곌낵 ?곹깭 (SUCCESS / FAILURE)",
|
||||
"description": "처리 결과 상태 (SUCCESS / FAILURE)",
|
||||
"enum": ["SUCCESS", "FAILURE"]
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "泥섎━ 寃곌낵 硫붿떆吏"
|
||||
"description": "처리 결과 메시지"
|
||||
}
|
||||
},
|
||||
"required": ["status"]
|
||||
}
|
||||
""";
|
||||
Files.writeString(schemaDir.resolve(inputSchemaFileName), inputSchema);
|
||||
Files.writeString(schemaDir.resolve(outputSchemaFileName), outputSchema);
|
||||
writeUtf8(schemaDir.resolve(inputSchemaFileName), inputSchema);
|
||||
writeUtf8(schemaDir.resolve(outputSchemaFileName), outputSchema);
|
||||
log.append("[Input Schema] ").append(schemaDir.resolve(inputSchemaFileName)).append("\n");
|
||||
log.append("[Output Schema] ").append(schemaDir.resolve(outputSchemaFileName)).append("\n");
|
||||
}
|
||||
@@ -881,9 +882,9 @@ public class ToolScaffolder {
|
||||
Files.createDirectories(wireMockBodyPath.getParent());
|
||||
Files.createDirectories(wireMockMappingPath.getParent());
|
||||
Files.createDirectories(podMockResponsePath.getParent());
|
||||
Files.writeString(wireMockBodyPath, mockResponse);
|
||||
Files.writeString(wireMockMappingPath, wireMockMappingContent(interfaceId, wireMockBodyPath.getFileName().toString()));
|
||||
Files.writeString(podMockResponsePath, mockResponse);
|
||||
writeUtf8(wireMockBodyPath, mockResponse);
|
||||
writeUtf8(wireMockMappingPath, wireMockMappingContent(interfaceId, wireMockBodyPath.getFileName().toString()));
|
||||
writeUtf8(podMockResponsePath, mockResponse);
|
||||
ensureLocalHttpApiConfiguration(projectRoot, httpApiName, toolName);
|
||||
log.append("[WireMock Response] ").append(wireMockBodyPath).append("\n");
|
||||
log.append("[WireMock Mapping] ").append(wireMockMappingPath).append("\n");
|
||||
@@ -891,19 +892,19 @@ public class ToolScaffolder {
|
||||
} else {
|
||||
Path mockResponsePath = rootDir.resolve(Paths.get(moduleName, "src/main/resources/mock-responses", toolName + ".json"));
|
||||
Files.createDirectories(mockResponsePath.getParent());
|
||||
Files.writeString(mockResponsePath, mockResponse);
|
||||
writeUtf8(mockResponsePath, mockResponse);
|
||||
log.append("[Mock Response] ").append(mockResponsePath).append("\n");
|
||||
}
|
||||
|
||||
Path generatedTestDir = rootDir.resolve(Paths.get(moduleName, "src/test/java/io/shinhanlife/dap/mcc/biz", group.toLowerCase(), "usecase"));
|
||||
Files.createDirectories(generatedTestDir);
|
||||
Path generatedTestPath = generatedTestDir.resolve(baseName + "UseCaseTest.java");
|
||||
Files.writeString(generatedTestPath, useCaseTestContent(bizPackage, baseName));
|
||||
writeUtf8(generatedTestPath, useCaseTestContent(bizPackage, baseName));
|
||||
log.append("[Unit Test] ").append(generatedTestPath).append("\\n");
|
||||
log.append("[Test Command] .\\gradlew.bat :").append(moduleName.substring(moduleName.lastIndexOf(java.io.File.separator) + 1)).append(":test --tests \"*").append(baseName).append("UseCaseTest\"\\n");
|
||||
Files.createDirectories(definitionDir);
|
||||
Path definitionPath = definitionDir.resolve(toolName + ".yml");
|
||||
Files.writeString(definitionPath, toolDefinitionContentV17(toolName, title, description, group,
|
||||
writeUtf8(definitionPath, toolDefinitionContentV17(toolName, title, description, group,
|
||||
interfaceId, inputFields, isMutationTool(baseName), definitionOptions));
|
||||
log.append("[V17 Tool Definition] ").append(definitionPath).append("\n");
|
||||
log.append("\n Tip: HTTP Tool은 WireMock 실행 후 생성된 mapping URL로 호출을 확인하세요.\n");
|
||||
@@ -1089,7 +1090,7 @@ public class ToolScaffolder {
|
||||
private static void ensureLocalHttpApiConfiguration(Path projectRoot, String httpApiName, String toolName) throws IOException {
|
||||
Path localConfigPath = projectRoot.resolve("dap-was-lib/src/main/resources/glow/application-glow-local.yml");
|
||||
Files.createDirectories(localConfigPath.getParent());
|
||||
String existing = Files.exists(localConfigPath) ? Files.readString(localConfigPath) : "";
|
||||
String existing = Files.exists(localConfigPath) ? Files.readString(localConfigPath, StandardCharsets.UTF_8) : "";
|
||||
if (java.util.regex.Pattern.compile("(?m)^\\s*-\\s+name:\\s*"
|
||||
+ java.util.regex.Pattern.quote(httpApiName) + "\\s*$").matcher(existing).find()) {
|
||||
return;
|
||||
@@ -1133,7 +1134,11 @@ public class ToolScaffolder {
|
||||
enabled: true
|
||||
""";
|
||||
}
|
||||
Files.writeString(localConfigPath, existing);
|
||||
writeUtf8(localConfigPath, existing);
|
||||
}
|
||||
|
||||
private static void writeUtf8(Path path, String content) throws IOException {
|
||||
Files.writeString(path, content, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static String dtoContent(String packageName, String className, List<FieldDefinition> fields,
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Comparator;
|
||||
|
||||
/** Updates MCP SDK and project-owned metadata in a generated tool source file. */
|
||||
@@ -27,10 +28,10 @@ public final class ToolSourceUpdater {
|
||||
throw new IllegalArgumentException("Tool source not found: " + toolName);
|
||||
}
|
||||
|
||||
String content = Files.readString(targetFile);
|
||||
String content = Files.readString(targetFile, StandardCharsets.UTF_8);
|
||||
content = updateMcpTool(content, toolName, description);
|
||||
content = updateToolHint(content, categoryKey, register, requiresApproval);
|
||||
Files.writeString(targetFile, content);
|
||||
Files.writeString(targetFile, content, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static Path findToolSource(Path rootDirectory, String toolName) throws IOException {
|
||||
@@ -47,7 +48,7 @@ public final class ToolSourceUpdater {
|
||||
|
||||
private static boolean containsMcpTool(Path path, String toolName) {
|
||||
try {
|
||||
return annotationArguments(Files.readString(path), "McpTool", toolName) != null;
|
||||
return annotationArguments(Files.readString(path, StandardCharsets.UTF_8), "McpTool", toolName) != null;
|
||||
} catch (IOException exception) {
|
||||
throw new IllegalStateException("Failed to read tool source: " + path, exception);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user