- Controller는 항상 재생성 (모든 엔드포인트 합산 파일) - Service/DTO는 이미 존재하면 스킵, force=true면 재생성 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
517 lines
23 KiB
Java
517 lines
23 KiB
Java
package com.snp.batch.service;
|
|
|
|
import com.snp.batch.global.dto.CodeGenerationResult;
|
|
import com.snp.batch.global.model.BypassApiConfig;
|
|
import com.snp.batch.global.model.BypassApiField;
|
|
import com.snp.batch.global.model.BypassApiParam;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.ArrayList;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* BYPASS API Java 소스 코드를 자동 생성하는 서비스.
|
|
* 같은 도메인의 N개 설정을 받아 N개의 DTO + Service와 1개의 Controller를 생성합니다.
|
|
*/
|
|
@Slf4j
|
|
@Service
|
|
public class BypassCodeGenerator {
|
|
|
|
private static final String BASE_PACKAGE = "com.snp.batch.jobs.web";
|
|
|
|
/**
|
|
* 같은 도메인의 BYPASS API 코드를 생성합니다.
|
|
* 엔드포인트별 DTO/Service를 각각 생성하고, Controller 1개에 모든 엔드포인트 메서드를 합칩니다.
|
|
*
|
|
* @param configs 같은 domainName을 가진 설정 목록
|
|
* @param force 기존 파일 덮어쓰기 여부
|
|
* @return 생성 결과
|
|
*/
|
|
public CodeGenerationResult generate(List<BypassApiConfig> configs, boolean force) {
|
|
if (configs == null || configs.isEmpty()) {
|
|
throw new IllegalArgumentException("생성할 설정이 없습니다.");
|
|
}
|
|
|
|
String projectRoot = System.getProperty("user.dir");
|
|
String domain = configs.get(0).getDomainName();
|
|
String basePath = projectRoot + "/src/main/java/com/snp/batch/jobs/web/" + domain;
|
|
|
|
List<String> dtoPaths = new ArrayList<>();
|
|
List<String> servicePaths = new ArrayList<>();
|
|
|
|
for (BypassApiConfig config : configs) {
|
|
String endpointName = config.getEndpointName();
|
|
|
|
String dtoPath = basePath + "/dto/" + endpointName + "Dto.java";
|
|
String servicePath = basePath + "/service/" + endpointName + "Service.java";
|
|
|
|
// Service/DTO: 이미 존재하면 스킵 (force=true면 재생성)
|
|
if (!force && Files.exists(Path.of(dtoPath))) {
|
|
log.info("DTO 파일 이미 존재, 스킵: {}", dtoPath);
|
|
dtoPaths.add(dtoPath);
|
|
} else {
|
|
String dtoCode = generateDtoCode(domain, endpointName, config.getFields());
|
|
Path dtoFilePath = writeFile(dtoPath, dtoCode, true);
|
|
dtoPaths.add(dtoFilePath.toString());
|
|
}
|
|
|
|
if (!force && Files.exists(Path.of(servicePath))) {
|
|
log.info("Service 파일 이미 존재, 스킵: {}", servicePath);
|
|
servicePaths.add(servicePath);
|
|
} else {
|
|
String serviceCode = generateServiceCode(domain, endpointName, config, config.getParams());
|
|
Path serviceFilePath = writeFile(servicePath, serviceCode, true);
|
|
servicePaths.add(serviceFilePath.toString());
|
|
}
|
|
}
|
|
|
|
// Controller: 모든 엔드포인트를 합치므로 항상 재생성
|
|
String controllerCode = generateControllerCode(domain, configs);
|
|
String domainCapitalized = capitalize(domain);
|
|
Path controllerFilePath = writeFile(
|
|
basePath + "/controller/" + domainCapitalized + "Controller.java", controllerCode, true);
|
|
|
|
log.info("코드 생성 완료 - domain: {}, endpoints: {}, controller: {}",
|
|
domain, configs.stream().map(BypassApiConfig::getEndpointName).toList(), controllerFilePath);
|
|
|
|
return CodeGenerationResult.builder()
|
|
.controllerPath(controllerFilePath.toString())
|
|
.servicePaths(servicePaths)
|
|
.dtoPaths(dtoPaths)
|
|
.message("코드 생성 완료. 서버를 재시작하면 새 API가 활성화됩니다.")
|
|
.build();
|
|
}
|
|
|
|
/**
|
|
* DTO 코드 생성.
|
|
* endpointName 기반 클래스명: {EndpointName}Dto
|
|
*/
|
|
private String generateDtoCode(String domain, String endpointName, List<BypassApiField> fields) {
|
|
String packageName = BASE_PACKAGE + "." + domain + ".dto";
|
|
boolean needsLocalDateTime = fields.stream()
|
|
.anyMatch(f -> "LocalDateTime".equals(f.getFieldType()));
|
|
|
|
StringBuilder imports = new StringBuilder();
|
|
imports.append("import com.fasterxml.jackson.annotation.JsonProperty;\n");
|
|
imports.append("import lombok.AllArgsConstructor;\n");
|
|
imports.append("import lombok.Builder;\n");
|
|
imports.append("import lombok.Getter;\n");
|
|
imports.append("import lombok.NoArgsConstructor;\n");
|
|
imports.append("import lombok.Setter;\n");
|
|
if (needsLocalDateTime) {
|
|
imports.append("import java.time.LocalDateTime;\n");
|
|
}
|
|
|
|
StringBuilder fieldLines = new StringBuilder();
|
|
for (BypassApiField field : fields) {
|
|
String jsonProp = field.getJsonProperty() != null ? field.getJsonProperty() : field.getFieldName();
|
|
fieldLines.append(" @JsonProperty(\"").append(jsonProp).append("\")\n");
|
|
fieldLines.append(" private ").append(field.getFieldType()).append(" ").append(field.getFieldName()).append(";\n\n");
|
|
}
|
|
|
|
return """
|
|
package {{PACKAGE}};
|
|
|
|
{{IMPORTS}}
|
|
@Getter
|
|
@Setter
|
|
@Builder
|
|
@NoArgsConstructor
|
|
@AllArgsConstructor
|
|
public class {{CLASS_NAME}} {
|
|
|
|
{{FIELDS}}}
|
|
"""
|
|
.replace("{{PACKAGE}}", packageName)
|
|
.replace("{{IMPORTS}}", imports.toString())
|
|
.replace("{{CLASS_NAME}}", endpointName + "Dto")
|
|
.replace("{{FIELDS}}", fieldLines.toString());
|
|
}
|
|
|
|
/**
|
|
* Service 코드 생성.
|
|
* endpointName 기반 클래스명: {EndpointName}Service
|
|
* BaseBypassService<{EndpointName}Dto>를 상속합니다.
|
|
*/
|
|
private String generateServiceCode(String domain, String endpointName,
|
|
BypassApiConfig config, List<BypassApiParam> params) {
|
|
String packageName = BASE_PACKAGE + "." + domain + ".service";
|
|
String dtoPackage = BASE_PACKAGE + "." + domain + ".dto";
|
|
String dtoClass = endpointName + "Dto";
|
|
String serviceClass = endpointName + "Service";
|
|
boolean isList = "LIST".equalsIgnoreCase(config.getResponseType());
|
|
boolean isPost = "POST".equalsIgnoreCase(config.getHttpMethod());
|
|
|
|
String returnType = isList ? "List<" + dtoClass + ">" : dtoClass;
|
|
String methodName = "get" + endpointName + "Data";
|
|
String fetchMethod = buildFetchMethodCall(config, params, isList, isPost);
|
|
String methodParams = buildMethodParams(params);
|
|
|
|
String listImport = isList ? "import java.util.List;\n" : "";
|
|
|
|
return """
|
|
package {{PACKAGE}};
|
|
|
|
import {{DTO_IMPORT}};
|
|
import com.snp.batch.common.web.service.BaseBypassService;
|
|
{{LIST_IMPORT}}import org.springframework.beans.factory.annotation.Qualifier;
|
|
import org.springframework.core.ParameterizedTypeReference;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.web.reactive.function.client.WebClient;
|
|
|
|
/**
|
|
* {{DISPLAY_NAME}} bypass 서비스
|
|
* 외부 Maritime API에서 데이터를 실시간 조회하여 그대로 반환
|
|
*/
|
|
@Service
|
|
public class {{SERVICE_CLASS}} extends BaseBypassService<{{DTO_CLASS}}> {
|
|
|
|
public {{SERVICE_CLASS}}(
|
|
@Qualifier("{{WEBCLIENT_BEAN}}") WebClient webClient) {
|
|
super(webClient, "{{EXTERNAL_PATH}}", "{{DISPLAY_NAME}}",
|
|
new ParameterizedTypeReference<>() {},
|
|
new ParameterizedTypeReference<>() {});
|
|
}
|
|
|
|
/**
|
|
* {{DISPLAY_NAME}} 데이터를 조회합니다.
|
|
*
|
|
* @return {{DISPLAY_NAME}}
|
|
*/
|
|
public {{RETURN_TYPE}} {{METHOD_NAME}}({{METHOD_PARAMS}}) {
|
|
{{FETCH_METHOD}}
|
|
}
|
|
}
|
|
"""
|
|
.replace("{{PACKAGE}}", packageName)
|
|
.replace("{{DTO_IMPORT}}", dtoPackage + "." + dtoClass)
|
|
.replace("{{LIST_IMPORT}}", listImport)
|
|
.replace("{{DISPLAY_NAME}}", config.getDisplayName())
|
|
.replace("{{SERVICE_CLASS}}", serviceClass)
|
|
.replace("{{DTO_CLASS}}", dtoClass)
|
|
.replace("{{WEBCLIENT_BEAN}}", config.getWebclientBean())
|
|
.replace("{{EXTERNAL_PATH}}", config.getExternalPath())
|
|
.replace("{{RETURN_TYPE}}", returnType)
|
|
.replace("{{METHOD_NAME}}", methodName)
|
|
.replace("{{METHOD_PARAMS}}", methodParams)
|
|
.replace("{{FETCH_METHOD}}", fetchMethod);
|
|
}
|
|
|
|
/**
|
|
* Controller 코드 생성.
|
|
* 같은 도메인의 모든 설정을 합쳐 하나의 Controller에 N개의 엔드포인트 메서드를 생성합니다.
|
|
*/
|
|
private String generateControllerCode(String domain, List<BypassApiConfig> configs) {
|
|
String packageName = BASE_PACKAGE + "." + domain + ".controller";
|
|
String servicePackage = BASE_PACKAGE + "." + domain + ".service";
|
|
String dtoPackage = BASE_PACKAGE + "." + domain + ".dto";
|
|
String domainCap = capitalize(domain);
|
|
String requestMappingPath = "/api/" + domain;
|
|
|
|
// imports 합산 (중복 제거)
|
|
Set<String> importSet = new LinkedHashSet<>();
|
|
importSet.add("import com.snp.batch.common.web.ApiResponse;");
|
|
importSet.add("import com.snp.batch.common.web.controller.BaseBypassController;");
|
|
importSet.add("import io.swagger.v3.oas.annotations.Operation;");
|
|
importSet.add("import io.swagger.v3.oas.annotations.Parameter;");
|
|
importSet.add("import io.swagger.v3.oas.annotations.tags.Tag;");
|
|
importSet.add("import lombok.RequiredArgsConstructor;");
|
|
importSet.add("import org.springframework.http.ResponseEntity;");
|
|
importSet.add("import org.springframework.web.bind.annotation.RequestMapping;");
|
|
importSet.add("import org.springframework.web.bind.annotation.RestController;");
|
|
|
|
boolean anyList = configs.stream().anyMatch(c -> "LIST".equalsIgnoreCase(c.getResponseType()));
|
|
boolean anyPost = configs.stream().anyMatch(c -> "POST".equalsIgnoreCase(c.getHttpMethod()));
|
|
boolean anyGet = configs.stream().anyMatch(c -> !"POST".equalsIgnoreCase(c.getHttpMethod()));
|
|
boolean anyPath = configs.stream()
|
|
.anyMatch(c -> c.getParams().stream().anyMatch(p -> "PATH".equalsIgnoreCase(p.getParamIn())));
|
|
boolean anyQuery = configs.stream()
|
|
.anyMatch(c -> c.getParams().stream().anyMatch(p -> "QUERY".equalsIgnoreCase(p.getParamIn())));
|
|
boolean anyBody = configs.stream()
|
|
.anyMatch(c -> c.getParams().stream().anyMatch(p -> "BODY".equalsIgnoreCase(p.getParamIn())));
|
|
|
|
if (anyList) {
|
|
importSet.add("import java.util.List;");
|
|
}
|
|
if (anyPost) {
|
|
importSet.add("import org.springframework.web.bind.annotation.PostMapping;");
|
|
}
|
|
if (anyGet) {
|
|
importSet.add("import org.springframework.web.bind.annotation.GetMapping;");
|
|
}
|
|
if (anyPath) {
|
|
importSet.add("import org.springframework.web.bind.annotation.PathVariable;");
|
|
}
|
|
if (anyQuery) {
|
|
importSet.add("import org.springframework.web.bind.annotation.RequestParam;");
|
|
}
|
|
if (anyBody) {
|
|
importSet.add("import org.springframework.web.bind.annotation.RequestBody;");
|
|
}
|
|
|
|
for (BypassApiConfig config : configs) {
|
|
String endpointName = config.getEndpointName();
|
|
importSet.add("import " + dtoPackage + "." + endpointName + "Dto;");
|
|
importSet.add("import " + servicePackage + "." + endpointName + "Service;");
|
|
}
|
|
|
|
String importsStr = importSet.stream().collect(Collectors.joining("\n"));
|
|
|
|
// 필드 선언부
|
|
StringBuilder fields = new StringBuilder();
|
|
for (BypassApiConfig config : configs) {
|
|
String endpointName = config.getEndpointName();
|
|
String serviceClass = endpointName + "Service";
|
|
String serviceField = Character.toLowerCase(serviceClass.charAt(0)) + serviceClass.substring(1);
|
|
fields.append(" private final ").append(serviceClass).append(" ").append(serviceField).append(";\n");
|
|
}
|
|
|
|
// 태그 description은 첫 번째 config의 webclientBean 기준
|
|
String tagPrefix = getTagPrefix(configs.get(0).getWebclientBean());
|
|
String tagDescription = tagPrefix + " " + domainCap + " bypass API";
|
|
|
|
// 엔드포인트 메서드 목록
|
|
StringBuilder methods = new StringBuilder();
|
|
for (BypassApiConfig config : configs) {
|
|
String endpointName = config.getEndpointName();
|
|
String dtoClass = endpointName + "Dto";
|
|
String serviceClass = endpointName + "Service";
|
|
String serviceField = Character.toLowerCase(serviceClass.charAt(0)) + serviceClass.substring(1);
|
|
boolean isList = "LIST".equalsIgnoreCase(config.getResponseType());
|
|
boolean isPost = "POST".equalsIgnoreCase(config.getHttpMethod());
|
|
|
|
String responseGeneric = isList ? "List<" + dtoClass + ">" : dtoClass;
|
|
String mappingAnnotation = isPost ? "@PostMapping" : "@GetMapping";
|
|
String mappingPath = buildMappingPath(config.getParams(), config.getExternalPath());
|
|
String paramAnnotations = buildControllerParamAnnotations(config.getParams());
|
|
String serviceCallArgs = buildServiceCallArgs(config.getParams());
|
|
String methodName = "get" + endpointName + "Data";
|
|
|
|
methods.append("\n");
|
|
methods.append(" @Operation(\n");
|
|
methods.append(" summary = \"").append(config.getDisplayName()).append(" 조회\",\n");
|
|
methods.append(" description = \"S&P API에서 ").append(config.getDisplayName())
|
|
.append(" 데이터를 요청하고 응답을 그대로 반환합니다.\"\n");
|
|
methods.append(" )\n");
|
|
methods.append(" ").append(mappingAnnotation).append(mappingPath).append("\n");
|
|
methods.append(" public ResponseEntity<ApiResponse<").append(responseGeneric).append(">> ")
|
|
.append(methodName).append("(");
|
|
if (!paramAnnotations.isEmpty()) {
|
|
methods.append(paramAnnotations);
|
|
}
|
|
methods.append(") {\n");
|
|
methods.append(" return execute(() -> ").append(serviceField)
|
|
.append(".").append(methodName).append("(").append(serviceCallArgs).append("));\n");
|
|
methods.append(" }\n");
|
|
}
|
|
|
|
return "package " + packageName + ";\n\n"
|
|
+ importsStr + "\n\n"
|
|
+ "/**\n"
|
|
+ " * " + domainCap + " bypass API\n"
|
|
+ " * S&P Maritime API에서 데이터를 실시간 조회하여 그대로 반환\n"
|
|
+ " */\n"
|
|
+ "@RestController\n"
|
|
+ "@RequestMapping(\"" + requestMappingPath + "\")\n"
|
|
+ "@RequiredArgsConstructor\n"
|
|
+ "@Tag(name = \"" + domainCap + "\", description = \"" + tagDescription + "\")\n"
|
|
+ "public class " + domainCap + "Controller extends BaseBypassController {\n\n"
|
|
+ fields
|
|
+ methods
|
|
+ "}\n";
|
|
}
|
|
|
|
/**
|
|
* fetch 메서드 호출 코드 생성
|
|
*/
|
|
private String buildFetchMethodCall(BypassApiConfig config, List<BypassApiParam> params,
|
|
boolean isList, boolean isPost) {
|
|
List<BypassApiParam> queryParams = params.stream()
|
|
.filter(p -> "QUERY".equalsIgnoreCase(p.getParamIn()))
|
|
.sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
|
|
.toList();
|
|
|
|
StringBuilder uriBuilder = new StringBuilder();
|
|
uriBuilder.append("uri -> uri.path(getApiPath())");
|
|
for (BypassApiParam p : queryParams) {
|
|
uriBuilder.append("\n .queryParam(\"")
|
|
.append(p.getParamName()).append("\", ").append(p.getParamName()).append(")");
|
|
}
|
|
uriBuilder.append("\n .build()");
|
|
|
|
String fetchName;
|
|
if (isPost) {
|
|
fetchName = isList ? "fetchPostList" : "fetchPostOne";
|
|
BypassApiParam bodyParam = params.stream()
|
|
.filter(p -> "BODY".equalsIgnoreCase(p.getParamIn()))
|
|
.findFirst().orElse(null);
|
|
String bodyArg = bodyParam != null ? bodyParam.getParamName() : "null";
|
|
return "return " + fetchName + "(" + bodyArg + ", " + uriBuilder + ");";
|
|
} else {
|
|
fetchName = isList ? "fetchGetList" : "fetchGetOne";
|
|
return "return " + fetchName + "(" + uriBuilder + ");";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 메서드 파라미터 목록 생성 (Java 타입 + 이름)
|
|
*/
|
|
private String buildMethodParams(List<BypassApiParam> params) {
|
|
return params.stream()
|
|
.sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
|
|
.map(p -> toJavaType(p.getParamType()) + " " + p.getParamName())
|
|
.collect(Collectors.joining(", "));
|
|
}
|
|
|
|
/**
|
|
* 서비스 호출 인자 목록 생성
|
|
*/
|
|
private String buildServiceCallArgs(List<BypassApiParam> params) {
|
|
return params.stream()
|
|
.sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
|
|
.map(BypassApiParam::getParamName)
|
|
.collect(Collectors.joining(", "));
|
|
}
|
|
|
|
/**
|
|
* Controller 메서드 파라미터 어노테이션 포함 목록 생성
|
|
*/
|
|
private String buildControllerParamAnnotations(List<BypassApiParam> params) {
|
|
if (params.isEmpty()) {
|
|
return "";
|
|
}
|
|
return params.stream()
|
|
.sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
|
|
.map(p -> {
|
|
String description = p.getDescription() != null ? p.getDescription() : p.getParamName();
|
|
String javaType = toJavaType(p.getParamType());
|
|
String paramName = p.getParamName();
|
|
String example = getDefaultExample(p.getParamType());
|
|
return switch (p.getParamIn().toUpperCase()) {
|
|
case "PATH" -> "@Parameter(description = \"" + description + "\", example = \"" + example + "\")\n"
|
|
+ " @PathVariable " + javaType + " " + paramName;
|
|
case "BODY" -> "@Parameter(description = \"" + description + "\", example = \"" + example + "\")\n"
|
|
+ " @RequestBody " + javaType + " " + paramName;
|
|
default -> {
|
|
String required = Boolean.TRUE.equals(p.getRequired()) ? "true" : "false";
|
|
yield "@Parameter(description = \"" + description + "\", example = \"" + example + "\")\n"
|
|
+ " @RequestParam(required = " + required + ") " + javaType + " " + paramName;
|
|
}
|
|
};
|
|
})
|
|
.collect(Collectors.joining(",\n "));
|
|
}
|
|
|
|
/**
|
|
* @GetMapping / @PostMapping에 붙는 경로 생성
|
|
* externalPath의 마지막 세그먼트를 내부 경로로 사용 + PATH 파라미터 추가
|
|
* 예: /RiskAndCompliance/CompliancesByImos → ("/CompliancesByImos")
|
|
* PATH 파라미터 imo 추가 시 → ("/CompliancesByImos/{imo}")
|
|
*/
|
|
private String buildMappingPath(List<BypassApiParam> params, String externalPath) {
|
|
String endpointSegment = "";
|
|
if (externalPath != null && !externalPath.isEmpty()) {
|
|
String[] segments = externalPath.split("/");
|
|
if (segments.length > 0) {
|
|
endpointSegment = "/" + segments[segments.length - 1];
|
|
}
|
|
}
|
|
|
|
List<BypassApiParam> pathParams = params.stream()
|
|
.filter(p -> "PATH".equalsIgnoreCase(p.getParamIn()))
|
|
.sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
|
|
.toList();
|
|
String pathSuffix = pathParams.stream()
|
|
.map(p -> "{" + p.getParamName() + "}")
|
|
.collect(Collectors.joining("/", pathParams.isEmpty() ? "" : "/", ""));
|
|
|
|
String fullPath = endpointSegment + pathSuffix;
|
|
if (fullPath.isEmpty()) {
|
|
return "";
|
|
}
|
|
return "(\"" + fullPath + "\")";
|
|
}
|
|
|
|
/**
|
|
* 파일을 지정 경로에 씁니다.
|
|
*
|
|
* @param path 파일 경로
|
|
* @param content 파일 내용
|
|
* @param force 덮어쓰기 허용 여부
|
|
* @return 생성된 파일 경로
|
|
*/
|
|
private Path writeFile(String path, String content, boolean force) {
|
|
Path filePath = Path.of(path);
|
|
if (Files.exists(filePath) && !force) {
|
|
throw new IllegalStateException("파일이 이미 존재합니다: " + path + " (덮어쓰려면 force 옵션을 사용하세요)");
|
|
}
|
|
try {
|
|
Files.createDirectories(filePath.getParent());
|
|
Files.writeString(filePath, content, StandardCharsets.UTF_8);
|
|
log.info("파일 생성: {}", filePath);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("파일 쓰기 실패: " + path, e);
|
|
}
|
|
return filePath;
|
|
}
|
|
|
|
/**
|
|
* webclientBean 이름 → Swagger @Tag description 접두사 변환
|
|
*/
|
|
private String getTagPrefix(String webclientBean) {
|
|
if (webclientBean == null) {
|
|
return "[Ship API]";
|
|
}
|
|
return switch (webclientBean) {
|
|
case "maritimeAisApiWebClient" -> "[AIS API]";
|
|
case "maritimeServiceApiWebClient" -> "[Service API]";
|
|
default -> "[Ship API]";
|
|
};
|
|
}
|
|
|
|
/**
|
|
* paramType → Swagger @Parameter example 기본값 결정
|
|
*/
|
|
private String getDefaultExample(String paramType) {
|
|
if (paramType == null) {
|
|
return "9876543";
|
|
}
|
|
return switch (paramType.toUpperCase()) {
|
|
case "INTEGER" -> "0";
|
|
case "LONG" -> "0";
|
|
case "BOOLEAN" -> "true";
|
|
default -> "9876543";
|
|
};
|
|
}
|
|
|
|
private String capitalize(String s) {
|
|
if (s == null || s.isEmpty()) {
|
|
return s;
|
|
}
|
|
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
|
|
}
|
|
|
|
/**
|
|
* param_type → Java 타입 변환
|
|
*/
|
|
private String toJavaType(String paramType) {
|
|
if (paramType == null) {
|
|
return "String";
|
|
}
|
|
return switch (paramType.toUpperCase()) {
|
|
case "INTEGER" -> "Integer";
|
|
case "LONG" -> "Long";
|
|
case "BOOLEAN" -> "Boolean";
|
|
default -> "String";
|
|
};
|
|
}
|
|
}
|