diff --git a/src/main/java/com/kamco/cd/kamcoback/changedetection/ChangeDetectionApiController.java b/src/main/java/com/kamco/cd/kamcoback/changedetection/ChangeDetectionApiController.java index 1865e899..e8b2f533 100644 --- a/src/main/java/com/kamco/cd/kamcoback/changedetection/ChangeDetectionApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/changedetection/ChangeDetectionApiController.java @@ -5,13 +5,12 @@ import com.kamco.cd.kamcoback.changedetection.service.ChangeDetectionService; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.transaction.Transactional; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.List; - @Tag(name = "변화탐지", description = "변화탐지 API") @RequiredArgsConstructor @RestController diff --git a/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java b/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java index 9fdd54d7..ebfcec09 100644 --- a/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/changedetection/dto/ChangeDetectionDto.java @@ -2,9 +2,4 @@ package com.kamco.cd.kamcoback.changedetection.dto; import org.locationtech.jts.geom.Geometry; -public record ChangeDetectionDto( - Long id, - Geometry polygon, - double centroidX, - double centroidY -) {} +public record ChangeDetectionDto(Long id, Geometry polygon, double centroidX, double centroidY) {} diff --git a/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java b/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java index cb8cf468..4fb89cb5 100644 --- a/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java +++ b/src/main/java/com/kamco/cd/kamcoback/changedetection/service/ChangeDetectionService.java @@ -1,13 +1,11 @@ package com.kamco.cd.kamcoback.changedetection.service; import com.kamco.cd.kamcoback.changedetection.dto.ChangeDetectionDto; -import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.postgres.core.ChangeDetectionCoreService; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.List; - @Service @RequiredArgsConstructor public class ChangeDetectionService { diff --git a/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java b/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java index 0744c962..9f3c3957 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java @@ -207,7 +207,7 @@ public class GlobalExceptionHandler { @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY) @ExceptionHandler(IllegalStateException.class) public ApiResponseDto handlerIllegalStateException( - IllegalStateException e, HttpServletRequest request) { + IllegalStateException e, HttpServletRequest request) { log.warn("[IllegalStateException] resource :{} ", e.getMessage()); String codeName = "UNPROCESSABLE_ENTITY"; @@ -291,11 +291,11 @@ public class GlobalExceptionHandler { // TODO : stackTrace limit 20줄? 확인 필요 String stackTraceStr = Arrays.stream(stackTrace) -// .limit(20) + // .limit(20) .map(StackTraceElement::toString) .collect(Collectors.joining("\n")) .substring(0, Math.min(stackTrace.length, 255)); - ; + ; ErrorLogEntity errorLogEntity = new ErrorLogEntity( diff --git a/src/main/java/com/kamco/cd/kamcoback/geojson/config/GeoJsonMonitorConfig.java b/src/main/java/com/kamco/cd/kamcoback/geojson/config/GeoJsonMonitorConfig.java index e0244851..cf99cd49 100644 --- a/src/main/java/com/kamco/cd/kamcoback/geojson/config/GeoJsonMonitorConfig.java +++ b/src/main/java/com/kamco/cd/kamcoback/geojson/config/GeoJsonMonitorConfig.java @@ -1,72 +1,52 @@ package com.kamco.cd.kamcoback.geojson.config; +import jakarta.annotation.PostConstruct; import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; -import jakarta.annotation.PostConstruct; - -/** - * GeoJSON 파일 모니터링 설정 - */ +/** GeoJSON 파일 모니터링 설정 */ @Component @ConfigurationProperties(prefix = "geojson.monitor") @Getter @Setter public class GeoJsonMonitorConfig { - - /** - * 모니터링할 폴더 경로 - */ - private String watchDirectory = "~/geojson/upload"; - - /** - * 처리 완료 후 파일을 이동할 폴더 경로 - */ - private String processedDirectory = "~/geojson/processed"; - - /** - * 처리 실패 파일을 이동할 폴더 경로 - */ - private String errorDirectory = "~/geojson/error"; - - /** - * 파일 모니터링 스케줄 (cron 표현식) - * 기본값: 매 30초마다 실행 - */ - private String cronExpression = "0/30 * * * * *"; - - /** - * 지원하는 압축파일 확장자 - */ - private String[] supportedExtensions = {"zip", "tar", "tar.gz", "tgz"}; - - /** - * 처리할 최대 파일 크기 (바이트) - */ - private long maxFileSize = 100 * 1024 * 1024; // 100MB - - /** - * 임시 압축해제 폴더 - */ - private String tempDirectory = "/tmp/geojson_extract"; - - /** - * 홈 디렉토리 경로 확장 - */ - @PostConstruct - public void expandPaths() { - watchDirectory = expandPath(watchDirectory); - processedDirectory = expandPath(processedDirectory); - errorDirectory = expandPath(errorDirectory); - tempDirectory = expandPath(tempDirectory); + + /** 모니터링할 폴더 경로 */ + private String watchDirectory = "~/geojson/upload"; + + /** 처리 완료 후 파일을 이동할 폴더 경로 */ + private String processedDirectory = "~/geojson/processed"; + + /** 처리 실패 파일을 이동할 폴더 경로 */ + private String errorDirectory = "~/geojson/error"; + + /** 파일 모니터링 스케줄 (cron 표현식) 기본값: 매 30초마다 실행 */ + private String cronExpression = "0/30 * * * * *"; + + /** 지원하는 압축파일 확장자 */ + private String[] supportedExtensions = {"zip", "tar", "tar.gz", "tgz"}; + + /** 처리할 최대 파일 크기 (바이트) */ + private long maxFileSize = 100 * 1024 * 1024; // 100MB + + /** 임시 압축해제 폴더 */ + private String tempDirectory = "/tmp/geojson_extract"; + + /** 홈 디렉토리 경로 확장 */ + @PostConstruct + public void expandPaths() { + watchDirectory = expandPath(watchDirectory); + processedDirectory = expandPath(processedDirectory); + errorDirectory = expandPath(errorDirectory); + tempDirectory = expandPath(tempDirectory); + } + + private String expandPath(String path) { + if (path.startsWith("~")) { + return path.replace("~", System.getProperty("user.home")); } - - private String expandPath(String path) { - if (path.startsWith("~")) { - return path.replace("~", System.getProperty("user.home")); - } - return path; - } -} \ No newline at end of file + return path; + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/geojson/controller/GeoJsonDataController.java b/src/main/java/com/kamco/cd/kamcoback/geojson/controller/GeoJsonDataController.java index bb0cdf82..1c137ba1 100644 --- a/src/main/java/com/kamco/cd/kamcoback/geojson/controller/GeoJsonDataController.java +++ b/src/main/java/com/kamco/cd/kamcoback/geojson/controller/GeoJsonDataController.java @@ -4,200 +4,195 @@ import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataGeomEntity; import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataGeomRepository; import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataRepository; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -/** - * GeoJSON 데이터 조회 및 테스트용 API 컨트롤러 - */ +/** GeoJSON 데이터 조회 및 테스트용 API 컨트롤러 */ @Slf4j @RestController @RequestMapping("/api/geojson/data") @RequiredArgsConstructor public class GeoJsonDataController { - private final MapSheetLearnDataRepository mapSheetLearnDataRepository; - private final MapSheetLearnDataGeomRepository mapSheetLearnDataGeomRepository; + private final MapSheetLearnDataRepository mapSheetLearnDataRepository; + private final MapSheetLearnDataGeomRepository mapSheetLearnDataGeomRepository; - /** - * 학습 데이터 목록 조회 - */ - @GetMapping("/learn-data") - public ResponseEntity> getLearnDataList( - @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size, - @RequestParam(required = false) String dataState, - @RequestParam(required = false) String analState) { - try { - PageRequest pageRequest = PageRequest.of(page, size); - List learnDataList; - - if (dataState != null) { - learnDataList = mapSheetLearnDataRepository.findByDataState(dataState); - } else if (analState != null) { - learnDataList = mapSheetLearnDataRepository.findByAnalState(analState); - } else { - learnDataList = mapSheetLearnDataRepository.findAll(pageRequest).getContent(); - } - - Map response = new HashMap<>(); - response.put("data", learnDataList); - response.put("totalCount", learnDataList.size()); - response.put("page", page); - response.put("size", size); - - return ResponseEntity.ok(response); - } catch (Exception e) { - log.error("학습 데이터 목록 조회 실패", e); - return ResponseEntity.internalServerError() - .body(Map.of("error", "데이터 조회 실패: " + e.getMessage())); - } - } + /** 학습 데이터 목록 조회 */ + @GetMapping("/learn-data") + public ResponseEntity> getLearnDataList( + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam(required = false) String dataState, + @RequestParam(required = false) String analState) { + try { + PageRequest pageRequest = PageRequest.of(page, size); + List learnDataList; - /** - * 특정 학습 데이터 상세 조회 - */ - @GetMapping("/learn-data/{id}") - public ResponseEntity> getLearnDataDetail(@PathVariable Long id) { - try { - if (id == null) { - return ResponseEntity.badRequest() - .body(Map.of("error", "ID가 필요합니다.")); - } - - Optional learnDataOpt = mapSheetLearnDataRepository.findById(id); - - if (learnDataOpt.isEmpty()) { - return ResponseEntity.notFound().build(); - } - - MapSheetLearnDataEntity learnData = learnDataOpt.get(); - List geometryList = mapSheetLearnDataGeomRepository.findByDataUid(id); - - Map response = new HashMap<>(); - response.put("learnData", learnData); - response.put("geometryData", geometryList); - response.put("geometryCount", geometryList.size()); - - return ResponseEntity.ok(response); - } catch (Exception e) { - log.error("학습 데이터 상세 조회 실패: {}", id, e); - return ResponseEntity.internalServerError() - .body(Map.of("error", "데이터 조회 실패: " + e.getMessage())); - } - } + if (dataState != null) { + learnDataList = mapSheetLearnDataRepository.findByDataState(dataState); + } else if (analState != null) { + learnDataList = mapSheetLearnDataRepository.findByAnalState(analState); + } else { + learnDataList = mapSheetLearnDataRepository.findAll(pageRequest).getContent(); + } - /** - * Geometry 데이터 목록 조회 - */ - @GetMapping("/geometry") - public ResponseEntity> getGeometryDataList( - @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size, - @RequestParam(required = false) Long dataUid, - @RequestParam(required = false) String geoType) { - try { - List geometryList; - - if (dataUid != null) { - geometryList = mapSheetLearnDataGeomRepository.findByDataUid(dataUid); - } else if (geoType != null) { - geometryList = mapSheetLearnDataGeomRepository.findByGeoType(geoType); - } else { - PageRequest pageRequest = PageRequest.of(page, size); - geometryList = mapSheetLearnDataGeomRepository.findAll(pageRequest).getContent(); - } - - Map response = new HashMap<>(); - response.put("data", geometryList); - response.put("totalCount", geometryList.size()); - response.put("page", page); - response.put("size", size); - - return ResponseEntity.ok(response); - } catch (Exception e) { - log.error("Geometry 데이터 목록 조회 실패", e); - return ResponseEntity.internalServerError() - .body(Map.of("error", "데이터 조회 실패: " + e.getMessage())); - } - } + Map response = new HashMap<>(); + response.put("data", learnDataList); + response.put("totalCount", learnDataList.size()); + response.put("page", page); + response.put("size", size); - /** - * 시스템 통계 정보 조회 - */ - @GetMapping("/statistics") - public ResponseEntity> getStatistics() { - try { - long totalLearnData = mapSheetLearnDataRepository.count(); - long totalGeometryData = mapSheetLearnDataGeomRepository.count(); - - List processedData = mapSheetLearnDataRepository.findByDataState("PROCESSED"); - List pendingAnalysis = mapSheetLearnDataRepository.findByAnalState("PENDING"); - List completedAnalysis = mapSheetLearnDataRepository.findByAnalState("COMPLETED"); - List errorAnalysis = mapSheetLearnDataRepository.findByAnalState("ERROR"); - - Map statistics = new HashMap<>(); - statistics.put("totalLearnData", totalLearnData); - statistics.put("totalGeometryData", totalGeometryData); - statistics.put("processedDataCount", processedData.size()); - statistics.put("pendingAnalysisCount", pendingAnalysis.size()); - statistics.put("completedAnalysisCount", completedAnalysis.size()); - statistics.put("errorAnalysisCount", errorAnalysis.size()); - - // 처리 완료율 계산 - if (totalLearnData > 0) { - double completionRate = (double) completedAnalysis.size() / totalLearnData * 100; - statistics.put("completionRate", Math.round(completionRate * 100.0) / 100.0); - } else { - statistics.put("completionRate", 0.0); - } - - return ResponseEntity.ok(Map.of( - "statistics", statistics, - "timestamp", java.time.Instant.now() - )); - } catch (Exception e) { - log.error("통계 정보 조회 실패", e); - return ResponseEntity.internalServerError() - .body(Map.of("error", "통계 조회 실패: " + e.getMessage())); - } + return ResponseEntity.ok(response); + } catch (Exception e) { + log.error("학습 데이터 목록 조회 실패", e); + return ResponseEntity.internalServerError() + .body(Map.of("error", "데이터 조회 실패: " + e.getMessage())); } + } - /** - * 데이터 상태별 카운트 조회 - */ - @GetMapping("/status-counts") - public ResponseEntity> getStatusCounts() { - try { - Map dataStateCounts = new HashMap<>(); - Map analStateCounts = new HashMap<>(); - - // 데이터 상태별 카운트 - dataStateCounts.put("PROCESSED", mapSheetLearnDataRepository.findByDataState("PROCESSED").size() + 0L); - dataStateCounts.put("PENDING", mapSheetLearnDataRepository.findByDataStateIsNullOrDataState("PENDING").size() + 0L); - - // 분석 상태별 카운트 - analStateCounts.put("PENDING", mapSheetLearnDataRepository.findByAnalState("PENDING").size() + 0L); - analStateCounts.put("COMPLETED", mapSheetLearnDataRepository.findByAnalState("COMPLETED").size() + 0L); - analStateCounts.put("ERROR", mapSheetLearnDataRepository.findByAnalState("ERROR").size() + 0L); - - return ResponseEntity.ok(Map.of( - "dataStateCounts", dataStateCounts, - "analStateCounts", analStateCounts, - "timestamp", java.time.Instant.now() - )); - } catch (Exception e) { - log.error("상태별 카운트 조회 실패", e); - return ResponseEntity.internalServerError() - .body(Map.of("error", "카운트 조회 실패: " + e.getMessage())); - } + /** 특정 학습 데이터 상세 조회 */ + @GetMapping("/learn-data/{id}") + public ResponseEntity> getLearnDataDetail(@PathVariable Long id) { + try { + if (id == null) { + return ResponseEntity.badRequest().body(Map.of("error", "ID가 필요합니다.")); + } + + Optional learnDataOpt = mapSheetLearnDataRepository.findById(id); + + if (learnDataOpt.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + MapSheetLearnDataEntity learnData = learnDataOpt.get(); + List geometryList = + mapSheetLearnDataGeomRepository.findByDataUid(id); + + Map response = new HashMap<>(); + response.put("learnData", learnData); + response.put("geometryData", geometryList); + response.put("geometryCount", geometryList.size()); + + return ResponseEntity.ok(response); + } catch (Exception e) { + log.error("학습 데이터 상세 조회 실패: {}", id, e); + return ResponseEntity.internalServerError() + .body(Map.of("error", "데이터 조회 실패: " + e.getMessage())); } -} \ No newline at end of file + } + + /** Geometry 데이터 목록 조회 */ + @GetMapping("/geometry") + public ResponseEntity> getGeometryDataList( + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam(required = false) Long dataUid, + @RequestParam(required = false) String geoType) { + try { + List geometryList; + + if (dataUid != null) { + geometryList = mapSheetLearnDataGeomRepository.findByDataUid(dataUid); + } else if (geoType != null) { + geometryList = mapSheetLearnDataGeomRepository.findByGeoType(geoType); + } else { + PageRequest pageRequest = PageRequest.of(page, size); + geometryList = mapSheetLearnDataGeomRepository.findAll(pageRequest).getContent(); + } + + Map response = new HashMap<>(); + response.put("data", geometryList); + response.put("totalCount", geometryList.size()); + response.put("page", page); + response.put("size", size); + + return ResponseEntity.ok(response); + } catch (Exception e) { + log.error("Geometry 데이터 목록 조회 실패", e); + return ResponseEntity.internalServerError() + .body(Map.of("error", "데이터 조회 실패: " + e.getMessage())); + } + } + + /** 시스템 통계 정보 조회 */ + @GetMapping("/statistics") + public ResponseEntity> getStatistics() { + try { + long totalLearnData = mapSheetLearnDataRepository.count(); + long totalGeometryData = mapSheetLearnDataGeomRepository.count(); + + List processedData = + mapSheetLearnDataRepository.findByDataState("PROCESSED"); + List pendingAnalysis = + mapSheetLearnDataRepository.findByAnalState("PENDING"); + List completedAnalysis = + mapSheetLearnDataRepository.findByAnalState("COMPLETED"); + List errorAnalysis = + mapSheetLearnDataRepository.findByAnalState("ERROR"); + + Map statistics = new HashMap<>(); + statistics.put("totalLearnData", totalLearnData); + statistics.put("totalGeometryData", totalGeometryData); + statistics.put("processedDataCount", processedData.size()); + statistics.put("pendingAnalysisCount", pendingAnalysis.size()); + statistics.put("completedAnalysisCount", completedAnalysis.size()); + statistics.put("errorAnalysisCount", errorAnalysis.size()); + + // 처리 완료율 계산 + if (totalLearnData > 0) { + double completionRate = (double) completedAnalysis.size() / totalLearnData * 100; + statistics.put("completionRate", Math.round(completionRate * 100.0) / 100.0); + } else { + statistics.put("completionRate", 0.0); + } + + return ResponseEntity.ok( + Map.of("statistics", statistics, "timestamp", java.time.Instant.now())); + } catch (Exception e) { + log.error("통계 정보 조회 실패", e); + return ResponseEntity.internalServerError() + .body(Map.of("error", "통계 조회 실패: " + e.getMessage())); + } + } + + /** 데이터 상태별 카운트 조회 */ + @GetMapping("/status-counts") + public ResponseEntity> getStatusCounts() { + try { + Map dataStateCounts = new HashMap<>(); + Map analStateCounts = new HashMap<>(); + + // 데이터 상태별 카운트 + dataStateCounts.put( + "PROCESSED", mapSheetLearnDataRepository.findByDataState("PROCESSED").size() + 0L); + dataStateCounts.put( + "PENDING", + mapSheetLearnDataRepository.findByDataStateIsNullOrDataState("PENDING").size() + 0L); + + // 분석 상태별 카운트 + analStateCounts.put( + "PENDING", mapSheetLearnDataRepository.findByAnalState("PENDING").size() + 0L); + analStateCounts.put( + "COMPLETED", mapSheetLearnDataRepository.findByAnalState("COMPLETED").size() + 0L); + analStateCounts.put( + "ERROR", mapSheetLearnDataRepository.findByAnalState("ERROR").size() + 0L); + + return ResponseEntity.ok( + Map.of( + "dataStateCounts", dataStateCounts, + "analStateCounts", analStateCounts, + "timestamp", java.time.Instant.now())); + } catch (Exception e) { + log.error("상태별 카운트 조회 실패", e); + return ResponseEntity.internalServerError() + .body(Map.of("error", "카운트 조회 실패: " + e.getMessage())); + } + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/geojson/controller/GeoJsonMonitorController.java b/src/main/java/com/kamco/cd/kamcoback/geojson/controller/GeoJsonMonitorController.java index cc2ece32..4aa4ce15 100644 --- a/src/main/java/com/kamco/cd/kamcoback/geojson/controller/GeoJsonMonitorController.java +++ b/src/main/java/com/kamco/cd/kamcoback/geojson/controller/GeoJsonMonitorController.java @@ -2,153 +2,133 @@ package com.kamco.cd.kamcoback.geojson.controller; import com.kamco.cd.kamcoback.geojson.service.GeoJsonFileMonitorService; import com.kamco.cd.kamcoback.geojson.service.GeometryConversionService; +import java.util.List; +import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; -import java.util.Map; - -/** - * GeoJSON 파일 모니터링 및 처리 API 컨트롤러 - */ +/** GeoJSON 파일 모니터링 및 처리 API 컨트롤러 */ @Slf4j @RestController @RequestMapping("/api/geojson") @RequiredArgsConstructor public class GeoJsonMonitorController { - private final GeoJsonFileMonitorService monitorService; - private final GeometryConversionService geometryConversionService; + private final GeoJsonFileMonitorService monitorService; + private final GeometryConversionService geometryConversionService; - /** - * 모니터링 상태 조회 - */ - @GetMapping("/monitor/status") - public Map getMonitorStatus() { - return monitorService.getMonitorStatus(); - } + /** 모니터링 상태 조회 */ + @GetMapping("/monitor/status") + public Map getMonitorStatus() { + return monitorService.getMonitorStatus(); + } - /** - * 시스템 통계 정보 조회 - */ - @GetMapping("/monitor/stats") - public ResponseEntity> getSystemStats() { - try { - Map stats = monitorService.getSystemStats(); - return ResponseEntity.ok(stats); - } catch (Exception e) { - log.error("시스템 통계 조회 실패", e); - return ResponseEntity.internalServerError() - .body(Map.of( - "error", "시스템 통계 조회 실패: " + e.getMessage(), - "status", "error" - )); - } + /** 시스템 통계 정보 조회 */ + @GetMapping("/monitor/stats") + public ResponseEntity> getSystemStats() { + try { + Map stats = monitorService.getSystemStats(); + return ResponseEntity.ok(stats); + } catch (Exception e) { + log.error("시스템 통계 조회 실패", e); + return ResponseEntity.internalServerError() + .body(Map.of("error", "시스템 통계 조회 실패: " + e.getMessage(), "status", "error")); } + } - /** - * 디렉토리 초기화 (수동 실행) - */ - @PostMapping("/monitor/init-directories") - public ResponseEntity> initializeDirectories() { - try { - log.info("디렉토리 초기화 수동 실행 요청"); - monitorService.initializeDirectoriesManually(); - - return ResponseEntity.ok(Map.of( - "message", "디렉토리 초기화가 완료되었습니다.", - "status", "success" - )); - } catch (Exception e) { - log.error("디렉토리 초기화 실패", e); - return ResponseEntity.internalServerError() - .body(Map.of( - "error", "디렉토리 초기화 실패: " + e.getMessage(), - "status", "error" - )); - } - } + /** 디렉토리 초기화 (수동 실행) */ + @PostMapping("/monitor/init-directories") + public ResponseEntity> initializeDirectories() { + try { + log.info("디렉토리 초기화 수동 실행 요청"); + monitorService.initializeDirectoriesManually(); - /** - * 수동으로 특정 파일 처리 - */ - @PostMapping("/process/file") - public ResponseEntity> processFileManually(@RequestParam String filePath) { - try { - log.info("수동 파일 처리 요청: {}", filePath); - monitorService.processFileManually(filePath); - - return ResponseEntity.ok(Map.of( - "message", "파일 처리가 완료되었습니다.", - "filePath", filePath, - "status", "success" - )); - } catch (Exception e) { - log.error("수동 파일 처리 실패: {}", filePath, e); - return ResponseEntity.internalServerError() - .body(Map.of( - "error", "파일 처리 실패: " + e.getMessage(), - "filePath", filePath, - "status", "error" - )); - } + return ResponseEntity.ok( + Map.of( + "message", "디렉토리 초기화가 완료되었습니다.", + "status", "success")); + } catch (Exception e) { + log.error("디렉토리 초기화 실패", e); + return ResponseEntity.internalServerError() + .body(Map.of("error", "디렉토리 초기화 실패: " + e.getMessage(), "status", "error")); } + } - /** - * 미처리된 Geometry 데이터 수동 변환 - */ - @PostMapping("/process/geometry") - public ResponseEntity> processUnprocessedGeometry() { - try { - log.info("미처리 Geometry 변환 수동 실행 요청"); - List processedIds = geometryConversionService.processUnprocessedLearnData(); - - return ResponseEntity.ok(Map.of( - "message", "Geometry 변환이 완료되었습니다.", - "processedCount", processedIds.size(), - "processedIds", processedIds, - "status", "success" - )); - } catch (Exception e) { - log.error("Geometry 변환 실패", e); - return ResponseEntity.internalServerError() - .body(Map.of( - "error", "Geometry 변환 실패: " + e.getMessage(), - "status", "error" - )); - } - } + /** 수동으로 특정 파일 처리 */ + @PostMapping("/process/file") + public ResponseEntity> processFileManually(@RequestParam String filePath) { + try { + log.info("수동 파일 처리 요청: {}", filePath); + monitorService.processFileManually(filePath); - /** - * 특정 학습 데이터의 Geometry 변환 - */ - @PostMapping("/process/geometry/convert") - public ResponseEntity> convertSpecificGeometry(@RequestBody List learnDataIds) { - try { - if (learnDataIds == null || learnDataIds.isEmpty()) { - return ResponseEntity.badRequest() - .body(Map.of("error", "변환할 학습 데이터 ID가 없습니다.")); - } - - log.info("특정 학습 데이터 Geometry 변환 요청: {}", learnDataIds); - List geometryIds = geometryConversionService.convertToGeometryData(learnDataIds); - - return ResponseEntity.ok(Map.of( - "message", "Geometry 변환이 완료되었습니다.", - "inputCount", learnDataIds.size(), - "outputCount", geometryIds.size(), - "geometryIds", geometryIds, - "status", "success" - )); - } catch (Exception e) { - log.error("특정 Geometry 변환 실패: {}", learnDataIds, e); - return ResponseEntity.internalServerError() - .body(Map.of( - "error", "Geometry 변환 실패: " + e.getMessage(), - "status", "error" - )); - } + return ResponseEntity.ok( + Map.of( + "message", "파일 처리가 완료되었습니다.", + "filePath", filePath, + "status", "success")); + } catch (Exception e) { + log.error("수동 파일 처리 실패: {}", filePath, e); + return ResponseEntity.internalServerError() + .body( + Map.of( + "error", "파일 처리 실패: " + e.getMessage(), "filePath", filePath, "status", "error")); } -} \ No newline at end of file + } + + /** 미처리된 Geometry 데이터 수동 변환 */ + @PostMapping("/process/geometry") + public ResponseEntity> processUnprocessedGeometry() { + try { + log.info("미처리 Geometry 변환 수동 실행 요청"); + List processedIds = geometryConversionService.processUnprocessedLearnData(); + + return ResponseEntity.ok( + Map.of( + "message", + "Geometry 변환이 완료되었습니다.", + "processedCount", + processedIds.size(), + "processedIds", + processedIds, + "status", + "success")); + } catch (Exception e) { + log.error("Geometry 변환 실패", e); + return ResponseEntity.internalServerError() + .body(Map.of("error", "Geometry 변환 실패: " + e.getMessage(), "status", "error")); + } + } + + /** 특정 학습 데이터의 Geometry 변환 */ + @PostMapping("/process/geometry/convert") + public ResponseEntity> convertSpecificGeometry( + @RequestBody List learnDataIds) { + try { + if (learnDataIds == null || learnDataIds.isEmpty()) { + return ResponseEntity.badRequest().body(Map.of("error", "변환할 학습 데이터 ID가 없습니다.")); + } + + log.info("특정 학습 데이터 Geometry 변환 요청: {}", learnDataIds); + List geometryIds = geometryConversionService.convertToGeometryData(learnDataIds); + + return ResponseEntity.ok( + Map.of( + "message", + "Geometry 변환이 완료되었습니다.", + "inputCount", + learnDataIds.size(), + "outputCount", + geometryIds.size(), + "geometryIds", + geometryIds, + "status", + "success")); + } catch (Exception e) { + log.error("특정 Geometry 변환 실패: {}", learnDataIds, e); + return ResponseEntity.internalServerError() + .body(Map.of("error", "Geometry 변환 실패: " + e.getMessage(), "status", "error")); + } + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/geojson/service/ArchiveExtractorService.java b/src/main/java/com/kamco/cd/kamcoback/geojson/service/ArchiveExtractorService.java index 7f4e5aae..76ff4aa9 100644 --- a/src/main/java/com/kamco/cd/kamcoback/geojson/service/ArchiveExtractorService.java +++ b/src/main/java/com/kamco/cd/kamcoback/geojson/service/ArchiveExtractorService.java @@ -1,6 +1,9 @@ package com.kamco.cd.kamcoback.geojson.service; import com.kamco.cd.kamcoback.geojson.config.GeoJsonMonitorConfig; +import java.io.*; +import java.nio.file.*; +import java.util.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.archivers.ArchiveEntry; @@ -10,158 +13,143 @@ import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.springframework.stereotype.Service; -import java.io.*; -import java.nio.file.*; -import java.util.*; -import java.util.stream.Stream; -import java.util.zip.ZipInputStream; - -/** - * 압축파일 처리 서비스 - */ +/** 압축파일 처리 서비스 */ @Slf4j @Service @RequiredArgsConstructor public class ArchiveExtractorService { - private final GeoJsonMonitorConfig config; + private final GeoJsonMonitorConfig config; - /** - * 압축파일에서 GeoJSON 파일들을 추출 - */ - public Map extractGeoJsonFiles(Path archiveFile) throws IOException { - Map geoJsonContents = new HashMap<>(); - String fileName = archiveFile.getFileName().toString().toLowerCase(); - - log.info("압축파일 추출 시작: {}", archiveFile); - - try { - if (fileName.endsWith(".zip")) { - extractFromZip(archiveFile, geoJsonContents); - } else if (fileName.endsWith(".tar") || fileName.endsWith(".tar.gz") || fileName.endsWith(".tgz")) { - extractFromTar(archiveFile, geoJsonContents); - } else { - throw new IllegalArgumentException("지원하지 않는 압축파일 형식: " + fileName); - } - } catch (Exception e) { - log.error("압축파일 추출 실패: {}", archiveFile, e); - throw e; + /** 압축파일에서 GeoJSON 파일들을 추출 */ + public Map extractGeoJsonFiles(Path archiveFile) throws IOException { + Map geoJsonContents = new HashMap<>(); + String fileName = archiveFile.getFileName().toString().toLowerCase(); + + log.info("압축파일 추출 시작: {}", archiveFile); + + try { + if (fileName.endsWith(".zip")) { + extractFromZip(archiveFile, geoJsonContents); + } else if (fileName.endsWith(".tar") + || fileName.endsWith(".tar.gz") + || fileName.endsWith(".tgz")) { + extractFromTar(archiveFile, geoJsonContents); + } else { + throw new IllegalArgumentException("지원하지 않는 압축파일 형식: " + fileName); + } + } catch (Exception e) { + log.error("압축파일 추출 실패: {}", archiveFile, e); + throw e; + } + + log.info("압축파일에서 {}개의 GeoJSON 파일을 추출했습니다: {}", geoJsonContents.size(), archiveFile); + return geoJsonContents; + } + + /** ZIP 파일에서 GeoJSON 추출 */ + private void extractFromZip(Path zipFile, Map geoJsonContents) + throws IOException { + try (ZipFile zip = new ZipFile(zipFile.toFile())) { + Enumeration entries = zip.getEntries(); + + while (entries.hasMoreElements()) { + ZipArchiveEntry entry = entries.nextElement(); + + if (!entry.isDirectory() && isGeoJsonFile(entry.getName())) { + try (InputStream inputStream = zip.getInputStream(entry)) { + String content = readInputStream(inputStream); + geoJsonContents.put(entry.getName(), content); + log.debug("ZIP에서 추출: {}", entry.getName()); + } } - - log.info("압축파일에서 {}개의 GeoJSON 파일을 추출했습니다: {}", geoJsonContents.size(), archiveFile); - return geoJsonContents; + } } + } - /** - * ZIP 파일에서 GeoJSON 추출 - */ - private void extractFromZip(Path zipFile, Map geoJsonContents) throws IOException { - try (ZipFile zip = new ZipFile(zipFile.toFile())) { - Enumeration entries = zip.getEntries(); - - while (entries.hasMoreElements()) { - ZipArchiveEntry entry = entries.nextElement(); - - if (!entry.isDirectory() && isGeoJsonFile(entry.getName())) { - try (InputStream inputStream = zip.getInputStream(entry)) { - String content = readInputStream(inputStream); - geoJsonContents.put(entry.getName(), content); - log.debug("ZIP에서 추출: {}", entry.getName()); - } - } - } + /** TAR 파일에서 GeoJSON 추출 */ + private void extractFromTar(Path tarFile, Map geoJsonContents) + throws IOException { + String fileName = tarFile.getFileName().toString().toLowerCase(); + InputStream fileInputStream = Files.newInputStream(tarFile); + + try { + // GZIP 압축된 TAR 파일인지 확인 + if (fileName.endsWith(".gz") || fileName.endsWith(".tgz")) { + fileInputStream = new GzipCompressorInputStream(fileInputStream); + } + + try (TarArchiveInputStream tarInputStream = new TarArchiveInputStream(fileInputStream)) { + ArchiveEntry entry; + + while ((entry = tarInputStream.getNextEntry()) != null) { + if (!entry.isDirectory() && isGeoJsonFile(entry.getName())) { + String content = readInputStream(tarInputStream); + geoJsonContents.put(entry.getName(), content); + log.debug("TAR에서 추출: {}", entry.getName()); + } } + } + } finally { + try { + fileInputStream.close(); + } catch (IOException e) { + log.warn("파일 스트림 종료 실패", e); + } + } + } + + /** InputStream에서 문자열 읽기 */ + private String readInputStream(InputStream inputStream) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) { + StringBuilder content = new StringBuilder(); + String line; + + while ((line = reader.readLine()) != null) { + content.append(line).append("\n"); + } + + return content.toString(); + } + } + + /** 파일이 GeoJSON 파일인지 확인 */ + private boolean isGeoJsonFile(String fileName) { + String lowerFileName = fileName.toLowerCase(); + return lowerFileName.endsWith(".geojson") || lowerFileName.endsWith(".json"); + } + + /** 지원하는 압축파일인지 확인 */ + public boolean isSupportedArchive(Path file) { + String fileName = file.getFileName().toString().toLowerCase(); + + for (String extension : config.getSupportedExtensions()) { + if (fileName.endsWith("." + extension)) { + return true; + } } - /** - * TAR 파일에서 GeoJSON 추출 - */ - private void extractFromTar(Path tarFile, Map geoJsonContents) throws IOException { - String fileName = tarFile.getFileName().toString().toLowerCase(); - InputStream fileInputStream = Files.newInputStream(tarFile); - - try { - // GZIP 압축된 TAR 파일인지 확인 - if (fileName.endsWith(".gz") || fileName.endsWith(".tgz")) { - fileInputStream = new GzipCompressorInputStream(fileInputStream); - } - - try (TarArchiveInputStream tarInputStream = new TarArchiveInputStream(fileInputStream)) { - ArchiveEntry entry; - - while ((entry = tarInputStream.getNextEntry()) != null) { - if (!entry.isDirectory() && isGeoJsonFile(entry.getName())) { - String content = readInputStream(tarInputStream); - geoJsonContents.put(entry.getName(), content); - log.debug("TAR에서 추출: {}", entry.getName()); - } - } - } - } finally { - try { - fileInputStream.close(); - } catch (IOException e) { - log.warn("파일 스트림 종료 실패", e); - } - } - } + return false; + } - /** - * InputStream에서 문자열 읽기 - */ - private String readInputStream(InputStream inputStream) throws IOException { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) { - StringBuilder content = new StringBuilder(); - String line; - - while ((line = reader.readLine()) != null) { - content.append(line).append("\n"); - } - - return content.toString(); - } - } + /** 파일 크기가 제한 범위 내인지 확인 */ + public boolean isFileSizeValid(Path file) { + try { + long fileSize = Files.size(file); + boolean isValid = fileSize <= config.getMaxFileSize(); - /** - * 파일이 GeoJSON 파일인지 확인 - */ - private boolean isGeoJsonFile(String fileName) { - String lowerFileName = fileName.toLowerCase(); - return lowerFileName.endsWith(".geojson") || lowerFileName.endsWith(".json"); - } + if (!isValid) { + log.warn( + "파일 크기가 제한을 초과했습니다: {} ({}MB > {}MB)", + file, + fileSize / 1024 / 1024, + config.getMaxFileSize() / 1024 / 1024); + } - /** - * 지원하는 압축파일인지 확인 - */ - public boolean isSupportedArchive(Path file) { - String fileName = file.getFileName().toString().toLowerCase(); - - for (String extension : config.getSupportedExtensions()) { - if (fileName.endsWith("." + extension)) { - return true; - } - } - - return false; + return isValid; + } catch (IOException e) { + log.error("파일 크기 확인 실패: {}", file, e); + return false; } - - /** - * 파일 크기가 제한 범위 내인지 확인 - */ - public boolean isFileSizeValid(Path file) { - try { - long fileSize = Files.size(file); - boolean isValid = fileSize <= config.getMaxFileSize(); - - if (!isValid) { - log.warn("파일 크기가 제한을 초과했습니다: {} ({}MB > {}MB)", - file, fileSize / 1024 / 1024, config.getMaxFileSize() / 1024 / 1024); - } - - return isValid; - } catch (IOException e) { - log.error("파일 크기 확인 실패: {}", file, e); - return false; - } - } -} \ No newline at end of file + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeoJsonDataService.java b/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeoJsonDataService.java index 25da93b1..b508340e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeoJsonDataService.java +++ b/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeoJsonDataService.java @@ -5,241 +5,225 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataEntity; import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataRepository; import java.time.ZonedDateTime; +import java.util.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.Instant; -import java.util.*; - -/** - * GeoJSON 데이터 처리 서비스 - */ +/** GeoJSON 데이터 처리 서비스 */ @Slf4j @Service @RequiredArgsConstructor public class GeoJsonDataService { - private final MapSheetLearnDataRepository mapSheetLearnDataRepository; - private final ObjectMapper objectMapper; + private final MapSheetLearnDataRepository mapSheetLearnDataRepository; + private final ObjectMapper objectMapper; - /** - * GeoJSON 파일들을 데이터베이스에 저장 - */ - @Transactional - public List processGeoJsonFiles(Map geoJsonContents, String archiveFileName) { - List savedIds = new ArrayList<>(); + /** GeoJSON 파일들을 데이터베이스에 저장 */ + @Transactional + public List processGeoJsonFiles( + Map geoJsonContents, String archiveFileName) { + List savedIds = new ArrayList<>(); - log.info("GeoJSON 파일 처리 시작: {} ({}개 파일)", archiveFileName, geoJsonContents.size()); + log.info("GeoJSON 파일 처리 시작: {} ({}개 파일)", archiveFileName, geoJsonContents.size()); - for (Map.Entry entry : geoJsonContents.entrySet()) { - String fileName = entry.getKey(); - String geoJsonContent = entry.getValue(); + for (Map.Entry entry : geoJsonContents.entrySet()) { + String fileName = entry.getKey(); + String geoJsonContent = entry.getValue(); - try { - Long savedId = processGeoJsonFile(fileName, geoJsonContent, archiveFileName); - if (savedId != null) { - savedIds.add(savedId); - log.debug("GeoJSON 파일 저장 성공: {} (ID: {})", fileName, savedId); - } - } catch (Exception e) { - log.error("GeoJSON 파일 처리 실패: {}", fileName, e); - // 개별 파일 처리 실패는 전체 처리를 중단시키지 않음 - } + try { + Long savedId = processGeoJsonFile(fileName, geoJsonContent, archiveFileName); + if (savedId != null) { + savedIds.add(savedId); + log.debug("GeoJSON 파일 저장 성공: {} (ID: {})", fileName, savedId); } - - log.info("GeoJSON 파일 처리 완료: {} (성공: {}개, 전체: {}개)", - archiveFileName, savedIds.size(), geoJsonContents.size()); - - return savedIds; + } catch (Exception e) { + log.error("GeoJSON 파일 처리 실패: {}", fileName, e); + // 개별 파일 처리 실패는 전체 처리를 중단시키지 않음 + } } - /** - * 개별 GeoJSON 파일을 MapSheetLearnDataEntity로 변환하여 저장 - */ - private Long processGeoJsonFile(String fileName, String geoJsonContent, String archiveFileName) { + log.info( + "GeoJSON 파일 처리 완료: {} (성공: {}개, 전체: {}개)", + archiveFileName, + savedIds.size(), + geoJsonContents.size()); + + return savedIds; + } + + /** 개별 GeoJSON 파일을 MapSheetLearnDataEntity로 변환하여 저장 */ + private Long processGeoJsonFile(String fileName, String geoJsonContent, String archiveFileName) { + try { + // GeoJSON 파싱 및 검증 + JsonNode geoJsonNode = objectMapper.readTree(geoJsonContent); + validateGeoJsonStructure(geoJsonNode); + + // 파일이 이미 처리되었는지 확인 + String dataPath = generateDataPath(archiveFileName, fileName); + Optional existingData = + mapSheetLearnDataRepository.findByDataPath(dataPath); + + if (existingData.isPresent()) { + log.warn("이미 처리된 파일입니다: {}", dataPath); + return existingData.get().getId(); + } + + // 새 엔티티 생성 및 저장 + MapSheetLearnDataEntity entity = + createMapSheetLearnDataEntity(fileName, geoJsonContent, archiveFileName, geoJsonNode); + MapSheetLearnDataEntity savedEntity = mapSheetLearnDataRepository.save(entity); + + return savedEntity.getId(); + + } catch (Exception e) { + log.error("GeoJSON 파일 처리 중 오류 발생: {}", fileName, e); + throw new RuntimeException("GeoJSON 파일 처리 실패: " + fileName, e); + } + } + + /** GeoJSON 구조 검증 */ + private void validateGeoJsonStructure(JsonNode geoJsonNode) { + if (!geoJsonNode.has("type")) { + throw new IllegalArgumentException("유효하지 않은 GeoJSON: 'type' 필드가 없습니다."); + } + + String type = geoJsonNode.get("type").asText(); + if (!"FeatureCollection".equals(type) && !"Feature".equals(type) && !"Geometry".equals(type)) { + throw new IllegalArgumentException("지원하지 않는 GeoJSON type: " + type); + } + } + + /** MapSheetLearnDataEntity 생성 */ + private MapSheetLearnDataEntity createMapSheetLearnDataEntity( + String fileName, String geoJsonContent, String archiveFileName, JsonNode geoJsonNode) { + + MapSheetLearnDataEntity entity = new MapSheetLearnDataEntity(); + + // 기본 정보 설정 + entity.setDataName(fileName); + entity.setDataPath(generateDataPath(archiveFileName, fileName)); + entity.setDataType("GeoJSON"); + entity.setDataTitle(extractTitle(fileName, geoJsonNode)); + + // CRS 정보 추출 및 설정 + setCrsInformation(entity, geoJsonNode); + + // JSON 데이터 저장 + try { + @SuppressWarnings("unchecked") + Map jsonMap = objectMapper.readValue(geoJsonContent, Map.class); + entity.setDataJson(jsonMap); + } catch (Exception e) { + log.warn("JSON 파싱 실패, 원본 텍스트로 저장: {}", fileName, e); + // JSON 파싱이 실패하면 원본을 Map 형태로 저장 + Map fallbackMap = new HashMap<>(); + fallbackMap.put("raw_content", geoJsonContent); + fallbackMap.put("parse_error", e.getMessage()); + entity.setDataJson(fallbackMap); + } + + // 연도 정보 추출 (파일명에서 추출 시도) + setYearInformation(entity, fileName); + + // 상태 정보 설정 + entity.setDataState("PROCESSED"); + entity.setAnalState("PENDING"); + + // 시간 정보 설정 + ZonedDateTime now = ZonedDateTime.now(); + entity.setCreatedDttm(now); + entity.setUpdatedDttm(now); + entity.setDataStateDttm(now); + + return entity; + } + + /** CRS 정보 설정 */ + private void setCrsInformation(MapSheetLearnDataEntity entity, JsonNode geoJsonNode) { + if (geoJsonNode.has("crs")) { + JsonNode crsNode = geoJsonNode.get("crs"); + if (crsNode.has("type") && crsNode.has("properties")) { + String crsType = crsNode.get("type").asText(); + entity.setDataCrsType(crsType); + + JsonNode propertiesNode = crsNode.get("properties"); + if (propertiesNode.has("name")) { + String crsName = propertiesNode.get("name").asText(); + entity.setDataCrsTypeName(crsName); + } + } + } else { + // CRS가 명시되지 않은 경우 기본값 설정 (WGS84) + entity.setDataCrsType("EPSG"); + entity.setDataCrsTypeName("EPSG:4326"); + } + } + + /** 연도 정보 추출 */ + private void setYearInformation(MapSheetLearnDataEntity entity, String fileName) { + // 파일명에서 연도 추출 시도 (예: kamco_2021_2022_35813023.geojson) + String[] parts = fileName.split("_"); + for (String part : parts) { + if (part.matches("\\d{4}")) { // 4자리 숫자 (연도) try { - // GeoJSON 파싱 및 검증 - JsonNode geoJsonNode = objectMapper.readTree(geoJsonContent); - validateGeoJsonStructure(geoJsonNode); - - // 파일이 이미 처리되었는지 확인 - String dataPath = generateDataPath(archiveFileName, fileName); - Optional existingData = mapSheetLearnDataRepository.findByDataPath(dataPath); - - if (existingData.isPresent()) { - log.warn("이미 처리된 파일입니다: {}", dataPath); - return existingData.get().getId(); + Integer year = Integer.parseInt(part); + if (year >= 1900 && year <= 2100) { + if (entity.getDataYyyy() == null) { + entity.setDataYyyy(year); + } else { + entity.setCompareYyyy(year); + break; } - - // 새 엔티티 생성 및 저장 - MapSheetLearnDataEntity entity = createMapSheetLearnDataEntity(fileName, geoJsonContent, archiveFileName, geoJsonNode); - MapSheetLearnDataEntity savedEntity = mapSheetLearnDataRepository.save(entity); - - return savedEntity.getId(); - - } catch (Exception e) { - log.error("GeoJSON 파일 처리 중 오류 발생: {}", fileName, e); - throw new RuntimeException("GeoJSON 파일 처리 실패: " + fileName, e); + } + } catch (NumberFormatException ignored) { + // 무시 } + } + } + } + + /** 제목 추출 */ + private String extractTitle(String fileName, JsonNode geoJsonNode) { + // GeoJSON 메타데이터에서 제목 추출 시도 + if (geoJsonNode.has("properties")) { + JsonNode properties = geoJsonNode.get("properties"); + if (properties.has("title")) { + return properties.get("title").asText(); + } + if (properties.has("name")) { + return properties.get("name").asText(); + } } - /** - * GeoJSON 구조 검증 - */ - private void validateGeoJsonStructure(JsonNode geoJsonNode) { - if (!geoJsonNode.has("type")) { - throw new IllegalArgumentException("유효하지 않은 GeoJSON: 'type' 필드가 없습니다."); - } - - String type = geoJsonNode.get("type").asText(); - if (!"FeatureCollection".equals(type) && !"Feature".equals(type) && !"Geometry".equals(type)) { - throw new IllegalArgumentException("지원하지 않는 GeoJSON type: " + type); - } + // 파일명에서 확장자 제거하여 제목으로 사용 + int lastDotIndex = fileName.lastIndexOf('.'); + if (lastDotIndex > 0) { + return fileName.substring(0, lastDotIndex); } - /** - * MapSheetLearnDataEntity 생성 - */ - private MapSheetLearnDataEntity createMapSheetLearnDataEntity( - String fileName, String geoJsonContent, String archiveFileName, JsonNode geoJsonNode) { + return fileName; + } - MapSheetLearnDataEntity entity = new MapSheetLearnDataEntity(); + /** 데이터 경로 생성 */ + private String generateDataPath(String archiveFileName, String fileName) { + return archiveFileName + "/" + fileName; + } - // 기본 정보 설정 - entity.setDataName(fileName); - entity.setDataPath(generateDataPath(archiveFileName, fileName)); - entity.setDataType("GeoJSON"); - entity.setDataTitle(extractTitle(fileName, geoJsonNode)); - - // CRS 정보 추출 및 설정 - setCrsInformation(entity, geoJsonNode); - - // JSON 데이터 저장 - try { - @SuppressWarnings("unchecked") - Map jsonMap = objectMapper.readValue(geoJsonContent, Map.class); - entity.setDataJson(jsonMap); - } catch (Exception e) { - log.warn("JSON 파싱 실패, 원본 텍스트로 저장: {}", fileName, e); - // JSON 파싱이 실패하면 원본을 Map 형태로 저장 - Map fallbackMap = new HashMap<>(); - fallbackMap.put("raw_content", geoJsonContent); - fallbackMap.put("parse_error", e.getMessage()); - entity.setDataJson(fallbackMap); - } - - // 연도 정보 추출 (파일명에서 추출 시도) - setYearInformation(entity, fileName); - - // 상태 정보 설정 - entity.setDataState("PROCESSED"); - entity.setAnalState("PENDING"); - - // 시간 정보 설정 - ZonedDateTime now = ZonedDateTime.now(); - entity.setCreatedDttm(now); - entity.setUpdatedDttm(now); - entity.setDataStateDttm(now); - - return entity; + /** 처리 가능한 파일 개수 확인 */ + public boolean isProcessable(Map geoJsonContents) { + if (geoJsonContents == null || geoJsonContents.isEmpty()) { + return false; } - /** - * CRS 정보 설정 - */ - private void setCrsInformation(MapSheetLearnDataEntity entity, JsonNode geoJsonNode) { - if (geoJsonNode.has("crs")) { - JsonNode crsNode = geoJsonNode.get("crs"); - if (crsNode.has("type") && crsNode.has("properties")) { - String crsType = crsNode.get("type").asText(); - entity.setDataCrsType(crsType); - - JsonNode propertiesNode = crsNode.get("properties"); - if (propertiesNode.has("name")) { - String crsName = propertiesNode.get("name").asText(); - entity.setDataCrsTypeName(crsName); - } - } - } else { - // CRS가 명시되지 않은 경우 기본값 설정 (WGS84) - entity.setDataCrsType("EPSG"); - entity.setDataCrsTypeName("EPSG:4326"); - } + // 최대 처리 가능한 파일 수 제한 (성능 고려) + int maxFiles = 50; + if (geoJsonContents.size() > maxFiles) { + log.warn("처리 가능한 최대 파일 수를 초과했습니다: {} > {}", geoJsonContents.size(), maxFiles); + return false; } - /** - * 연도 정보 추출 - */ - private void setYearInformation(MapSheetLearnDataEntity entity, String fileName) { - // 파일명에서 연도 추출 시도 (예: kamco_2021_2022_35813023.geojson) - String[] parts = fileName.split("_"); - for (String part : parts) { - if (part.matches("\\d{4}")) { // 4자리 숫자 (연도) - try { - Integer year = Integer.parseInt(part); - if (year >= 1900 && year <= 2100) { - if (entity.getDataYyyy() == null) { - entity.setDataYyyy(year); - } else { - entity.setCompareYyyy(year); - break; - } - } - } catch (NumberFormatException ignored) { - // 무시 - } - } - } - } - - /** - * 제목 추출 - */ - private String extractTitle(String fileName, JsonNode geoJsonNode) { - // GeoJSON 메타데이터에서 제목 추출 시도 - if (geoJsonNode.has("properties")) { - JsonNode properties = geoJsonNode.get("properties"); - if (properties.has("title")) { - return properties.get("title").asText(); - } - if (properties.has("name")) { - return properties.get("name").asText(); - } - } - - // 파일명에서 확장자 제거하여 제목으로 사용 - int lastDotIndex = fileName.lastIndexOf('.'); - if (lastDotIndex > 0) { - return fileName.substring(0, lastDotIndex); - } - - return fileName; - } - - /** - * 데이터 경로 생성 - */ - private String generateDataPath(String archiveFileName, String fileName) { - return archiveFileName + "/" + fileName; - } - - /** - * 처리 가능한 파일 개수 확인 - */ - public boolean isProcessable(Map geoJsonContents) { - if (geoJsonContents == null || geoJsonContents.isEmpty()) { - return false; - } - - // 최대 처리 가능한 파일 수 제한 (성능 고려) - int maxFiles = 50; - if (geoJsonContents.size() > maxFiles) { - log.warn("처리 가능한 최대 파일 수를 초과했습니다: {} > {}", geoJsonContents.size(), maxFiles); - return false; - } - - return true; - } + return true; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeoJsonFileMonitorService.java b/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeoJsonFileMonitorService.java index 43acf2b3..2fa7ea5f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeoJsonFileMonitorService.java +++ b/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeoJsonFileMonitorService.java @@ -1,434 +1,406 @@ package com.kamco.cd.kamcoback.geojson.service; import com.kamco.cd.kamcoback.geojson.config.GeoJsonMonitorConfig; -import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataRepository; import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataGeomRepository; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; +import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataRepository; import jakarta.annotation.PostConstruct; - import java.io.IOException; import java.nio.file.*; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Stream; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; -/** - * GeoJSON 파일 모니터링 서비스 - * 지정된 폴더를 주기적으로 모니터링하여 압축파일을 자동으로 처리합니다. - */ +/** GeoJSON 파일 모니터링 서비스 지정된 폴더를 주기적으로 모니터링하여 압축파일을 자동으로 처리합니다. */ @Slf4j @Service @RequiredArgsConstructor public class GeoJsonFileMonitorService { - private final GeoJsonMonitorConfig config; - private final ArchiveExtractorService archiveExtractorService; - private final GeoJsonDataService geoJsonDataService; - private final GeometryConversionService geometryConversionService; - private final MapSheetLearnDataRepository learnDataRepository; - private final MapSheetLearnDataGeomRepository geomRepository; + private final GeoJsonMonitorConfig config; + private final ArchiveExtractorService archiveExtractorService; + private final GeoJsonDataService geoJsonDataService; + private final GeometryConversionService geometryConversionService; + private final MapSheetLearnDataRepository learnDataRepository; + private final MapSheetLearnDataGeomRepository geomRepository; - /** - * 애플리케이션 시작 시 필요한 디렉토리들을 미리 생성 - */ - @PostConstruct - public void initializeDirectories() { + /** 애플리케이션 시작 시 필요한 디렉토리들을 미리 생성 */ + @PostConstruct + public void initializeDirectories() { + try { + log.info("GeoJSON 모니터링 시스템 초기화 중..."); + log.info( + "설정된 경로 - Watch: {}, Processed: {}, Error: {}, Temp: {}", + config.getWatchDirectory(), + config.getProcessedDirectory(), + config.getErrorDirectory(), + config.getTempDirectory()); + + ensureDirectoriesExist(); + log.info("GeoJSON 모니터링 시스템 초기화 완료"); + } catch (Exception e) { + log.warn("GeoJSON 모니터링 시스템 초기화 실패 - 스케줄러 실행 시 재시도됩니다", e); + // 초기화 실패해도 애플리케이션은 시작되도록 함 (RuntimeException 던지지 않음) + } + } + + /** 스케줄러를 통한 파일 모니터링 설정된 cron 표현식에 따라 주기적으로 실행 */ + // @Scheduled(cron = "#{@geoJsonMonitorConfig.cronExpression}") + public void monitorFiles() { + log.debug("파일 모니터링 시작"); + + try { + // 모니터링 폴더 존재 확인 및 생성 + ensureDirectoriesExist(); + + // 압축파일 검색 및 처리 + processArchiveFiles(); + + // 미처리된 Geometry 변환 작업 수행 + processUnprocessedGeometryData(); + + } catch (RuntimeException e) { + log.error("파일 모니터링 중 치명적 오류 발생 - 이번 주기 건너뜀", e); + } catch (Exception e) { + log.error("파일 모니터링 중 오류 발생", e); + } + + log.debug("파일 모니터링 완료"); + } + + /** 필요한 디렉토리들이 존재하는지 확인하고 생성 */ + private void ensureDirectoriesExist() { + boolean hasError = false; + try { + createDirectoryIfNotExists(config.getWatchDirectory()); + } catch (IOException e) { + log.error("Watch 디렉토리 생성 실패: {} - {}", config.getWatchDirectory(), e.getMessage()); + hasError = true; + } + + try { + createDirectoryIfNotExists(config.getProcessedDirectory()); + } catch (IOException e) { + log.error("Processed 디렉토리 생성 실패: {} - {}", config.getProcessedDirectory(), e.getMessage()); + hasError = true; + } + + try { + createDirectoryIfNotExists(config.getErrorDirectory()); + } catch (IOException e) { + log.error("Error 디렉토리 생성 실패: {} - {}", config.getErrorDirectory(), e.getMessage()); + hasError = true; + } + + try { + createDirectoryIfNotExists(config.getTempDirectory()); + } catch (IOException e) { + log.error("Temp 디렉토리 생성 실패: {} - {}", config.getTempDirectory(), e.getMessage()); + hasError = true; + } + + if (hasError) { + log.warn("일부 디렉토리 생성에 실패했습니다. 해당 기능은 제한될 수 있습니다."); + log.info("수동으로 다음 디렉토리들을 생성해주세요:"); + log.info(" - {}", config.getWatchDirectory()); + log.info(" - {}", config.getProcessedDirectory()); + log.info(" - {}", config.getErrorDirectory()); + log.info(" - {}", config.getTempDirectory()); + } else { + log.info("모든 필요한 디렉토리가 준비되었습니다."); + } + } + + /** 디렉토리가 존재하지 않으면 생성 */ + private void createDirectoryIfNotExists(String directory) throws IOException { + if (directory == null || directory.trim().isEmpty()) { + throw new IllegalArgumentException("디렉토리 경로가 비어있습니다."); + } + + Path path = Paths.get(directory); + + if (!Files.exists(path)) { + try { + Files.createDirectories(path); + log.info("디렉토리 생성 완료: {}", directory); + + // 디렉토리 권한 설정 (Unix/Linux 환경에서) try { - log.info("GeoJSON 모니터링 시스템 초기화 중..."); - log.info("설정된 경로 - Watch: {}, Processed: {}, Error: {}, Temp: {}", - config.getWatchDirectory(), config.getProcessedDirectory(), - config.getErrorDirectory(), config.getTempDirectory()); - - ensureDirectoriesExist(); - log.info("GeoJSON 모니터링 시스템 초기화 완료"); - } catch (Exception e) { - log.warn("GeoJSON 모니터링 시스템 초기화 실패 - 스케줄러 실행 시 재시도됩니다", e); - // 초기화 실패해도 애플리케이션은 시작되도록 함 (RuntimeException 던지지 않음) + if (!System.getProperty("os.name").toLowerCase().contains("windows")) { + // rwxrwxr-x 권한 설정 + java.nio.file.attribute.PosixFilePermissions.asFileAttribute( + java.nio.file.attribute.PosixFilePermissions.fromString("rwxrwxr-x")); + } + } catch (Exception permissionException) { + log.debug("권한 설정 실패 (무시됨): {}", permissionException.getMessage()); } + + } catch (IOException e) { + log.error("디렉토리 생성 실패: {} - {}", directory, e.getMessage()); + throw new IOException("디렉토리를 생성할 수 없습니다: " + directory, e); + } + } else if (!Files.isDirectory(path)) { + throw new IOException("지정된 경로가 디렉토리가 아닙니다: " + directory); + } else if (!Files.isWritable(path)) { + log.warn("디렉토리에 쓰기 권한이 없습니다: {}", directory); + } else { + log.debug("디렉토리가 이미 존재합니다: {}", directory); + } + } + + /** 모니터링 폴더에서 압축파일들을 찾아서 처리 */ + private void processArchiveFiles() { + Path watchDir = Paths.get(config.getWatchDirectory()); + + // 디렉토리 존재 확인 + if (!Files.exists(watchDir)) { + log.debug("Watch 디렉토리가 존재하지 않습니다: {}", watchDir); + return; } - /** - * 스케줄러를 통한 파일 모니터링 - * 설정된 cron 표현식에 따라 주기적으로 실행 - */ -// @Scheduled(cron = "#{@geoJsonMonitorConfig.cronExpression}") - public void monitorFiles() { - log.debug("파일 모니터링 시작"); - - try { - // 모니터링 폴더 존재 확인 및 생성 - ensureDirectoriesExist(); - - // 압축파일 검색 및 처리 - processArchiveFiles(); - - // 미처리된 Geometry 변환 작업 수행 - processUnprocessedGeometryData(); - - } catch (RuntimeException e) { - log.error("파일 모니터링 중 치명적 오류 발생 - 이번 주기 건너뜀", e); - } catch (Exception e) { - log.error("파일 모니터링 중 오류 발생", e); - } - - log.debug("파일 모니터링 완료"); + if (!Files.isDirectory(watchDir)) { + log.warn("Watch 경로가 디렉토리가 아닙니다: {}", watchDir); + return; } - /** - * 필요한 디렉토리들이 존재하는지 확인하고 생성 - */ - private void ensureDirectoriesExist() { - boolean hasError = false; - try { - createDirectoryIfNotExists(config.getWatchDirectory()); - } catch (IOException e) { - log.error("Watch 디렉토리 생성 실패: {} - {}", config.getWatchDirectory(), e.getMessage()); - hasError = true; - } - - try { - createDirectoryIfNotExists(config.getProcessedDirectory()); - } catch (IOException e) { - log.error("Processed 디렉토리 생성 실패: {} - {}", config.getProcessedDirectory(), e.getMessage()); - hasError = true; - } - - try { - createDirectoryIfNotExists(config.getErrorDirectory()); - } catch (IOException e) { - log.error("Error 디렉토리 생성 실패: {} - {}", config.getErrorDirectory(), e.getMessage()); - hasError = true; - } - - try { - createDirectoryIfNotExists(config.getTempDirectory()); - } catch (IOException e) { - log.error("Temp 디렉토리 생성 실패: {} - {}", config.getTempDirectory(), e.getMessage()); - hasError = true; - } - - if (hasError) { - log.warn("일부 디렉토리 생성에 실패했습니다. 해당 기능은 제한될 수 있습니다."); - log.info("수동으로 다음 디렉토리들을 생성해주세요:"); - log.info(" - {}", config.getWatchDirectory()); - log.info(" - {}", config.getProcessedDirectory()); - log.info(" - {}", config.getErrorDirectory()); - log.info(" - {}", config.getTempDirectory()); - } else { - log.info("모든 필요한 디렉토리가 준비되었습니다."); - } + if (!Files.isReadable(watchDir)) { + log.warn("Watch 디렉토리에 읽기 권한이 없습니다: {}", watchDir); + return; } - /** - * 디렉토리가 존재하지 않으면 생성 - */ - private void createDirectoryIfNotExists(String directory) throws IOException { - if (directory == null || directory.trim().isEmpty()) { - throw new IllegalArgumentException("디렉토리 경로가 비어있습니다."); - } + try (Stream files = Files.list(watchDir)) { + files + .filter(Files::isRegularFile) + .filter(archiveExtractorService::isSupportedArchive) + .filter(archiveExtractorService::isFileSizeValid) + .forEach(this::processArchiveFile); - Path path = Paths.get(directory); + } catch (IOException e) { + log.error("파일 목록 조회 실패: {}", watchDir, e); + } + } - if (!Files.exists(path)) { - try { - Files.createDirectories(path); - log.info("디렉토리 생성 완료: {}", directory); + /** 개별 압축파일 처리 */ + private void processArchiveFile(Path archiveFile) { + String fileName = archiveFile.getFileName().toString(); + log.info("압축파일 처리 시작: {}", fileName); - // 디렉토리 권한 설정 (Unix/Linux 환경에서) - try { - if (!System.getProperty("os.name").toLowerCase().contains("windows")) { - // rwxrwxr-x 권한 설정 - java.nio.file.attribute.PosixFilePermissions.asFileAttribute( - java.nio.file.attribute.PosixFilePermissions.fromString("rwxrwxr-x") - ); - } - } catch (Exception permissionException) { - log.debug("권한 설정 실패 (무시됨): {}", permissionException.getMessage()); - } + try { + // 1. 압축파일에서 GeoJSON 파일들 추출 + Map geoJsonContents = + archiveExtractorService.extractGeoJsonFiles(archiveFile); - } catch (IOException e) { - log.error("디렉토리 생성 실패: {} - {}", directory, e.getMessage()); - throw new IOException("디렉토리를 생성할 수 없습니다: " + directory, e); - } - } else if (!Files.isDirectory(path)) { - throw new IOException("지정된 경로가 디렉토리가 아닙니다: " + directory); - } else if (!Files.isWritable(path)) { - log.warn("디렉토리에 쓰기 권한이 없습니다: {}", directory); - } else { - log.debug("디렉토리가 이미 존재합니다: {}", directory); - } + if (geoJsonContents.isEmpty()) { + log.warn("압축파일에서 GeoJSON 파일을 찾을 수 없습니다: {}", fileName); + moveFileToError(archiveFile, "GeoJSON 파일 없음"); + return; + } + + // 2. 처리 가능한 파일 수인지 확인 + if (!geoJsonDataService.isProcessable(geoJsonContents)) { + log.warn("처리할 수 없는 파일입니다: {}", fileName); + moveFileToError(archiveFile, "처리 불가능한 파일"); + return; + } + + // 3. GeoJSON 데이터를 데이터베이스에 저장 + List savedLearnDataIds = + geoJsonDataService.processGeoJsonFiles(geoJsonContents, fileName); + + if (savedLearnDataIds.isEmpty()) { + log.warn("저장된 학습 데이터가 없습니다: {}", fileName); + moveFileToError(archiveFile, "데이터 저장 실패"); + return; + } + + // 4. Geometry 데이터로 변환 + List geometryIds = geometryConversionService.convertToGeometryData(savedLearnDataIds); + + // 5. 처리 완료된 파일을 처리된 폴더로 이동 + moveFileToProcessed(archiveFile); + + log.info( + "압축파일 처리 완료: {} (학습 데이터: {}개, Geometry: {}개)", + fileName, + savedLearnDataIds.size(), + geometryIds.size()); + + } catch (Exception e) { + log.error("압축파일 처리 실패: {}", fileName, e); + try { + moveFileToError(archiveFile, "처리 중 오류 발생: " + e.getMessage()); + } catch (IOException moveError) { + log.error("오류 파일 이동 실패: {}", fileName, moveError); + } + } + } + + /** 미처리된 Geometry 변환 작업 수행 */ + private void processUnprocessedGeometryData() { + try { + List processedIds = geometryConversionService.processUnprocessedLearnData(); + if (!processedIds.isEmpty()) { + log.info("미처리 Geometry 변환 완료: {}개", processedIds.size()); + } + } catch (Exception e) { + log.error("미처리 Geometry 변환 작업 실패", e); + } + } + + /** 처리 완료된 파일을 processed 폴더로 이동 */ + private void moveFileToProcessed(Path sourceFile) throws IOException { + String fileName = sourceFile.getFileName().toString(); + String timestampedFileName = addTimestamp(fileName); + Path targetPath = Paths.get(config.getProcessedDirectory(), timestampedFileName); + + Files.move(sourceFile, targetPath, StandardCopyOption.REPLACE_EXISTING); + log.info("파일을 처리된 폴더로 이동: {} -> {}", fileName, timestampedFileName); + } + + /** 오류가 발생한 파일을 error 폴더로 이동 */ + private void moveFileToError(Path sourceFile, String errorReason) throws IOException { + String fileName = sourceFile.getFileName().toString(); + String errorFileName = addTimestamp(fileName) + ".error"; + Path targetPath = Paths.get(config.getErrorDirectory(), errorFileName); + + Files.move(sourceFile, targetPath, StandardCopyOption.REPLACE_EXISTING); + + // 오류 정보를 별도 파일로 저장 + String errorInfoFileName = errorFileName + ".info"; + Path errorInfoPath = Paths.get(config.getErrorDirectory(), errorInfoFileName); + String errorInfo = + String.format( + "파일: %s%n오류 시간: %s%n오류 원인: %s%n", fileName, java.time.Instant.now(), errorReason); + Files.write(errorInfoPath, errorInfo.getBytes()); + + log.warn("파일을 오류 폴더로 이동: {} (원인: {})", fileName, errorReason); + } + + /** 파일명에 타임스탬프 추가 */ + private String addTimestamp(String fileName) { + int lastDotIndex = fileName.lastIndexOf('.'); + String name = (lastDotIndex > 0) ? fileName.substring(0, lastDotIndex) : fileName; + String extension = (lastDotIndex > 0) ? fileName.substring(lastDotIndex) : ""; + + return String.format("%s_%d%s", name, System.currentTimeMillis(), extension); + } + + /** 수동으로 특정 파일 처리 (테스트/관리 목적) */ + public void processFileManually(String filePath) { + Path archiveFile = Paths.get(filePath); + + if (!Files.exists(archiveFile)) { + log.error("파일이 존재하지 않습니다: {}", filePath); + return; } - /** - * 모니터링 폴더에서 압축파일들을 찾아서 처리 - */ - private void processArchiveFiles() { - Path watchDir = Paths.get(config.getWatchDirectory()); - - // 디렉토리 존재 확인 - if (!Files.exists(watchDir)) { - log.debug("Watch 디렉토리가 존재하지 않습니다: {}", watchDir); - return; - } - - if (!Files.isDirectory(watchDir)) { - log.warn("Watch 경로가 디렉토리가 아닙니다: {}", watchDir); - return; - } - - if (!Files.isReadable(watchDir)) { - log.warn("Watch 디렉토리에 읽기 권한이 없습니다: {}", watchDir); - return; - } - - try (Stream files = Files.list(watchDir)) { - files.filter(Files::isRegularFile) - .filter(archiveExtractorService::isSupportedArchive) - .filter(archiveExtractorService::isFileSizeValid) - .forEach(this::processArchiveFile); - - } catch (IOException e) { - log.error("파일 목록 조회 실패: {}", watchDir, e); - } + if (!archiveExtractorService.isSupportedArchive(archiveFile)) { + log.error("지원하지 않는 압축파일 형식입니다: {}", filePath); + return; } - /** - * 개별 압축파일 처리 - */ - private void processArchiveFile(Path archiveFile) { - String fileName = archiveFile.getFileName().toString(); - log.info("압축파일 처리 시작: {}", fileName); + log.info("수동 파일 처리 시작: {}", filePath); + processArchiveFile(archiveFile); + } - try { - // 1. 압축파일에서 GeoJSON 파일들 추출 - Map geoJsonContents = archiveExtractorService.extractGeoJsonFiles(archiveFile); + /** 디렉토리 초기화를 수동으로 실행 (API에서 호출 가능) */ + public void initializeDirectoriesManually() { + log.info("디렉토리 수동 초기화 시작"); + try { + ensureDirectoriesExist(); + log.info("디렉토리 수동 초기화 완료"); + } catch (Exception e) { + log.error("디렉토리 수동 초기화 실패", e); + throw new RuntimeException("디렉토리 초기화 실패", e); + } + } - if (geoJsonContents.isEmpty()) { - log.warn("압축파일에서 GeoJSON 파일을 찾을 수 없습니다: {}", fileName); - moveFileToError(archiveFile, "GeoJSON 파일 없음"); - return; - } + /** 모니터링 상태 정보 반환 */ + public Map getMonitorStatus() { + return Map.of( + "watchDirectory", config.getWatchDirectory(), + "processedDirectory", config.getProcessedDirectory(), + "errorDirectory", config.getErrorDirectory(), + "cronExpression", config.getCronExpression(), + "supportedExtensions", config.getSupportedExtensions(), + "maxFileSize", config.getMaxFileSize(), + "maxFileSizeMB", config.getMaxFileSize() / 1024 / 1024); + } - // 2. 처리 가능한 파일 수인지 확인 - if (!geoJsonDataService.isProcessable(geoJsonContents)) { - log.warn("처리할 수 없는 파일입니다: {}", fileName); - moveFileToError(archiveFile, "처리 불가능한 파일"); - return; - } + /** 시스템 통계 정보 조회 */ + public Map getSystemStats() { + Map stats = new HashMap<>(); - // 3. GeoJSON 데이터를 데이터베이스에 저장 - List savedLearnDataIds = geoJsonDataService.processGeoJsonFiles(geoJsonContents, fileName); + try { + // 데이터베이스 통계 + long totalLearnData = learnDataRepository.count(); + long totalGeomData = geomRepository.count(); + long pendingAnalysis = learnDataRepository.countByAnalState("PENDING"); - if (savedLearnDataIds.isEmpty()) { - log.warn("저장된 학습 데이터가 없습니다: {}", fileName); - moveFileToError(archiveFile, "데이터 저장 실패"); - return; - } + stats.put( + "database", + Map.of( + "totalLearnData", totalLearnData, + "totalGeomData", totalGeomData, + "pendingAnalysis", pendingAnalysis)); - // 4. Geometry 데이터로 변환 - List geometryIds = geometryConversionService.convertToGeometryData(savedLearnDataIds); + // 파일 시스템 통계 + stats.put("fileSystem", getFileSystemStats()); - // 5. 처리 완료된 파일을 처리된 폴더로 이동 - moveFileToProcessed(archiveFile); + // 모니터링 설정 + stats.put( + "monitoring", + Map.of( + "isActive", true, + "cronExpression", "0/30 * * * * *", + "watchDirectory", config.getWatchDirectory(), + "processedDirectory", config.getProcessedDirectory(), + "errorDirectory", config.getErrorDirectory())); - log.info("압축파일 처리 완료: {} (학습 데이터: {}개, Geometry: {}개)", - fileName, savedLearnDataIds.size(), geometryIds.size()); - - } catch (Exception e) { - log.error("압축파일 처리 실패: {}", fileName, e); - try { - moveFileToError(archiveFile, "처리 중 오류 발생: " + e.getMessage()); - } catch (IOException moveError) { - log.error("오류 파일 이동 실패: {}", fileName, moveError); - } - } + } catch (Exception e) { + log.error("통계 정보 조회 실패", e); + stats.put("error", e.getMessage()); } - /** - * 미처리된 Geometry 변환 작업 수행 - */ - private void processUnprocessedGeometryData() { - try { - List processedIds = geometryConversionService.processUnprocessedLearnData(); - if (!processedIds.isEmpty()) { - log.info("미처리 Geometry 변환 완료: {}개", processedIds.size()); - } - } catch (Exception e) { - log.error("미처리 Geometry 변환 작업 실패", e); - } + return stats; + } + + /** 파일 시스템 통계 조회 */ + private Map getFileSystemStats() { + Map fileStats = new HashMap<>(); + + try { + // 각 디렉토리의 파일 수 계산 + Path watchDir = Paths.get(config.getWatchDirectory()); + Path processedDir = Paths.get(config.getProcessedDirectory()); + Path errorDir = Paths.get(config.getErrorDirectory()); + + fileStats.put("watchDirectoryCount", countFilesInDirectory(watchDir)); + fileStats.put("processedDirectoryCount", countFilesInDirectory(processedDir)); + fileStats.put("errorDirectoryCount", countFilesInDirectory(errorDir)); + + } catch (Exception e) { + log.warn("파일 시스템 통계 조회 실패: {}", e.getMessage()); + fileStats.put("error", e.getMessage()); } - /** - * 처리 완료된 파일을 processed 폴더로 이동 - */ - private void moveFileToProcessed(Path sourceFile) throws IOException { - String fileName = sourceFile.getFileName().toString(); - String timestampedFileName = addTimestamp(fileName); - Path targetPath = Paths.get(config.getProcessedDirectory(), timestampedFileName); + return fileStats; + } - Files.move(sourceFile, targetPath, StandardCopyOption.REPLACE_EXISTING); - log.info("파일을 처리된 폴더로 이동: {} -> {}", fileName, timestampedFileName); + /** 디렉토리 내 파일 개수 계산 */ + private long countFilesInDirectory(Path directory) { + if (!Files.exists(directory) || !Files.isDirectory(directory)) { + return 0; } - /** - * 오류가 발생한 파일을 error 폴더로 이동 - */ - private void moveFileToError(Path sourceFile, String errorReason) throws IOException { - String fileName = sourceFile.getFileName().toString(); - String errorFileName = addTimestamp(fileName) + ".error"; - Path targetPath = Paths.get(config.getErrorDirectory(), errorFileName); - - Files.move(sourceFile, targetPath, StandardCopyOption.REPLACE_EXISTING); - - // 오류 정보를 별도 파일로 저장 - String errorInfoFileName = errorFileName + ".info"; - Path errorInfoPath = Paths.get(config.getErrorDirectory(), errorInfoFileName); - String errorInfo = String.format("파일: %s%n오류 시간: %s%n오류 원인: %s%n", - fileName, java.time.Instant.now(), errorReason); - Files.write(errorInfoPath, errorInfo.getBytes()); - - log.warn("파일을 오류 폴더로 이동: {} (원인: {})", fileName, errorReason); - } - - /** - * 파일명에 타임스탬프 추가 - */ - private String addTimestamp(String fileName) { - int lastDotIndex = fileName.lastIndexOf('.'); - String name = (lastDotIndex > 0) ? fileName.substring(0, lastDotIndex) : fileName; - String extension = (lastDotIndex > 0) ? fileName.substring(lastDotIndex) : ""; - - return String.format("%s_%d%s", name, System.currentTimeMillis(), extension); - } - - /** - * 수동으로 특정 파일 처리 (테스트/관리 목적) - */ - public void processFileManually(String filePath) { - Path archiveFile = Paths.get(filePath); - - if (!Files.exists(archiveFile)) { - log.error("파일이 존재하지 않습니다: {}", filePath); - return; - } - - if (!archiveExtractorService.isSupportedArchive(archiveFile)) { - log.error("지원하지 않는 압축파일 형식입니다: {}", filePath); - return; - } - - log.info("수동 파일 처리 시작: {}", filePath); - processArchiveFile(archiveFile); - } - - /** - * 디렉토리 초기화를 수동으로 실행 (API에서 호출 가능) - */ - public void initializeDirectoriesManually() { - log.info("디렉토리 수동 초기화 시작"); - try { - ensureDirectoriesExist(); - log.info("디렉토리 수동 초기화 완료"); - } catch (Exception e) { - log.error("디렉토리 수동 초기화 실패", e); - throw new RuntimeException("디렉토리 초기화 실패", e); - } - } - - /** - * 모니터링 상태 정보 반환 - */ - public Map getMonitorStatus() { - return Map.of( - "watchDirectory", config.getWatchDirectory(), - "processedDirectory", config.getProcessedDirectory(), - "errorDirectory", config.getErrorDirectory(), - "cronExpression", config.getCronExpression(), - "supportedExtensions", config.getSupportedExtensions(), - "maxFileSize", config.getMaxFileSize(), - "maxFileSizeMB", config.getMaxFileSize() / 1024 / 1024 - ); - } - - /** - * 시스템 통계 정보 조회 - */ - public Map getSystemStats() { - Map stats = new HashMap<>(); - - try { - // 데이터베이스 통계 - long totalLearnData = learnDataRepository.count(); - long totalGeomData = geomRepository.count(); - long pendingAnalysis = learnDataRepository.countByAnalState("PENDING"); - - stats.put("database", Map.of( - "totalLearnData", totalLearnData, - "totalGeomData", totalGeomData, - "pendingAnalysis", pendingAnalysis - )); - - // 파일 시스템 통계 - stats.put("fileSystem", getFileSystemStats()); - - // 모니터링 설정 - stats.put("monitoring", Map.of( - "isActive", true, - "cronExpression", "0/30 * * * * *", - "watchDirectory", config.getWatchDirectory(), - "processedDirectory", config.getProcessedDirectory(), - "errorDirectory", config.getErrorDirectory() - )); - - } catch (Exception e) { - log.error("통계 정보 조회 실패", e); - stats.put("error", e.getMessage()); - } - - return stats; - } - - /** - * 파일 시스템 통계 조회 - */ - private Map getFileSystemStats() { - Map fileStats = new HashMap<>(); - - try { - // 각 디렉토리의 파일 수 계산 - Path watchDir = Paths.get(config.getWatchDirectory()); - Path processedDir = Paths.get(config.getProcessedDirectory()); - Path errorDir = Paths.get(config.getErrorDirectory()); - - fileStats.put("watchDirectoryCount", countFilesInDirectory(watchDir)); - fileStats.put("processedDirectoryCount", countFilesInDirectory(processedDir)); - fileStats.put("errorDirectoryCount", countFilesInDirectory(errorDir)); - - } catch (Exception e) { - log.warn("파일 시스템 통계 조회 실패: {}", e.getMessage()); - fileStats.put("error", e.getMessage()); - } - - return fileStats; - } - - /** - * 디렉토리 내 파일 개수 계산 - */ - private long countFilesInDirectory(Path directory) { - if (!Files.exists(directory) || !Files.isDirectory(directory)) { - return 0; - } - - try (Stream files = Files.list(directory)) { - return files.filter(Files::isRegularFile).count(); - } catch (IOException e) { - log.warn("디렉토리 파일 계산 실패: {}", directory, e); - return 0; - } + try (Stream files = Files.list(directory)) { + return files.filter(Files::isRegularFile).count(); + } catch (IOException e) { + log.warn("디렉토리 파일 계산 실패: {}", directory, e); + return 0; } + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeometryConversionService.java b/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeometryConversionService.java index 057ea521..18d7da00 100644 --- a/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeometryConversionService.java +++ b/src/main/java/com/kamco/cd/kamcoback/geojson/service/GeometryConversionService.java @@ -7,442 +7,430 @@ import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataGeomEntity; import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataGeomRepository; import com.kamco.cd.kamcoback.postgres.repository.MapSheetLearnDataRepository; import java.time.ZonedDateTime; +import java.util.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.locationtech.jts.geom.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.Instant; -import java.util.*; - -/** - * Geometry 데이터 변환 서비스 - */ +/** Geometry 데이터 변환 서비스 */ @Slf4j @Service @RequiredArgsConstructor public class GeometryConversionService { - private final MapSheetLearnDataRepository mapSheetLearnDataRepository; - private final MapSheetLearnDataGeomRepository mapSheetLearnDataGeomRepository; - private final ObjectMapper objectMapper; - private final GeometryFactory geometryFactory = new GeometryFactory(); + private final MapSheetLearnDataRepository mapSheetLearnDataRepository; + private final MapSheetLearnDataGeomRepository mapSheetLearnDataGeomRepository; + private final ObjectMapper objectMapper; + private final GeometryFactory geometryFactory = new GeometryFactory(); - /** - * MapSheetLearnData의 JSON 데이터를 기반으로 Geometry 테이블에 저장 - */ - @Transactional - public List convertToGeometryData(List learnDataIds) { - List processedIds = new ArrayList<>(); + /** MapSheetLearnData의 JSON 데이터를 기반으로 Geometry 테이블에 저장 */ + @Transactional + public List convertToGeometryData(List learnDataIds) { + List processedIds = new ArrayList<>(); - log.info("Geometry 변환 시작: {} 개의 학습 데이터", learnDataIds.size()); + log.info("Geometry 변환 시작: {} 개의 학습 데이터", learnDataIds.size()); - for (Long dataId : learnDataIds) { - try { - if (dataId != null) { - Optional learnDataOpt = mapSheetLearnDataRepository.findById(dataId); - if (learnDataOpt.isPresent()) { - List geometryIds = processLearnDataToGeometry(learnDataOpt.get()); - processedIds.addAll(geometryIds); - log.debug("학습 데이터 {} 에서 {} 개의 geometry 데이터 생성", dataId, geometryIds.size()); - } else { - log.warn("학습 데이터를 찾을 수 없습니다: {}", dataId); - } - } - } catch (Exception e) { - log.error("Geometry 변환 실패 - 학습 데이터 ID: {}", dataId, e); - // 개별 변환 실패는 전체 처리를 중단시키지 않음 - } + for (Long dataId : learnDataIds) { + try { + if (dataId != null) { + Optional learnDataOpt = + mapSheetLearnDataRepository.findById(dataId); + if (learnDataOpt.isPresent()) { + List geometryIds = processLearnDataToGeometry(learnDataOpt.get()); + processedIds.addAll(geometryIds); + log.debug("학습 데이터 {} 에서 {} 개의 geometry 데이터 생성", dataId, geometryIds.size()); + } else { + log.warn("학습 데이터를 찾을 수 없습니다: {}", dataId); + } } - - log.info("Geometry 변환 완료: {} 개 처리, {} 개의 geometry 생성", learnDataIds.size(), processedIds.size()); - return processedIds; + } catch (Exception e) { + log.error("Geometry 변환 실패 - 학습 데이터 ID: {}", dataId, e); + // 개별 변환 실패는 전체 처리를 중단시키지 않음 + } } - /** - * 개별 학습 데이터를 Geometry 데이터로 변환 - */ - private List processLearnDataToGeometry(MapSheetLearnDataEntity learnData) { - List geometryIds = new ArrayList<>(); + log.info( + "Geometry 변환 완료: {} 개 처리, {} 개의 geometry 생성", learnDataIds.size(), processedIds.size()); + return processedIds; + } - try { - // 기존 geometry 데이터 삭제 (재생성) - mapSheetLearnDataGeomRepository.deleteByDataUid(learnData.getId()); + /** 개별 학습 데이터를 Geometry 데이터로 변환 */ + private List processLearnDataToGeometry(MapSheetLearnDataEntity learnData) { + List geometryIds = new ArrayList<>(); - // JSON 데이터에서 GeoJSON 추출 - Map dataJson = learnData.getDataJson(); - if (dataJson == null || dataJson.isEmpty()) { - log.warn("JSON 데이터가 없습니다: {}", learnData.getId()); - return geometryIds; - } - - // JSON을 GeoJSON으로 파싱 - String geoJsonString = objectMapper.writeValueAsString(dataJson); - JsonNode geoJsonNode = objectMapper.readTree(geoJsonString); - - // GeoJSON 타입에 따라 처리 - String type = geoJsonNode.get("type").asText(); - switch (type) { - case "FeatureCollection": - geometryIds.addAll(processFeatureCollection(geoJsonNode, learnData)); - break; - case "Feature": - Long geometryId = processFeature(geoJsonNode, learnData); - if (geometryId != null) { - geometryIds.add(geometryId); - } - break; - case "Point": - case "LineString": - case "Polygon": - case "MultiPoint": - case "MultiLineString": - case "MultiPolygon": - Long directGeometryId = processDirectGeometry(geoJsonNode, learnData); - if (directGeometryId != null) { - geometryIds.add(directGeometryId); - } - break; - default: - log.warn("지원하지 않는 GeoJSON type: {} (데이터 ID: {})", type, learnData.getId()); - } - - } catch (Exception e) { - log.error("Geometry 변환 실패: 학습 데이터 ID {}", learnData.getId(), e); - throw new RuntimeException("Geometry 변환 실패", e); - } + try { + // 기존 geometry 데이터 삭제 (재생성) + mapSheetLearnDataGeomRepository.deleteByDataUid(learnData.getId()); + // JSON 데이터에서 GeoJSON 추출 + Map dataJson = learnData.getDataJson(); + if (dataJson == null || dataJson.isEmpty()) { + log.warn("JSON 데이터가 없습니다: {}", learnData.getId()); return geometryIds; + } + + // JSON을 GeoJSON으로 파싱 + String geoJsonString = objectMapper.writeValueAsString(dataJson); + JsonNode geoJsonNode = objectMapper.readTree(geoJsonString); + + // GeoJSON 타입에 따라 처리 + String type = geoJsonNode.get("type").asText(); + switch (type) { + case "FeatureCollection": + geometryIds.addAll(processFeatureCollection(geoJsonNode, learnData)); + break; + case "Feature": + Long geometryId = processFeature(geoJsonNode, learnData); + if (geometryId != null) { + geometryIds.add(geometryId); + } + break; + case "Point": + case "LineString": + case "Polygon": + case "MultiPoint": + case "MultiLineString": + case "MultiPolygon": + Long directGeometryId = processDirectGeometry(geoJsonNode, learnData); + if (directGeometryId != null) { + geometryIds.add(directGeometryId); + } + break; + default: + log.warn("지원하지 않는 GeoJSON type: {} (데이터 ID: {})", type, learnData.getId()); + } + + } catch (Exception e) { + log.error("Geometry 변환 실패: 학습 데이터 ID {}", learnData.getId(), e); + throw new RuntimeException("Geometry 변환 실패", e); } - /** - * FeatureCollection 처리 - */ - private List processFeatureCollection(JsonNode featureCollectionNode, MapSheetLearnDataEntity learnData) { - List geometryIds = new ArrayList<>(); + return geometryIds; + } - if (!featureCollectionNode.has("features")) { - log.warn("FeatureCollection에 features 배열이 없습니다: {}", learnData.getId()); - return geometryIds; - } + /** FeatureCollection 처리 */ + private List processFeatureCollection( + JsonNode featureCollectionNode, MapSheetLearnDataEntity learnData) { + List geometryIds = new ArrayList<>(); - JsonNode featuresNode = featureCollectionNode.get("features"); - if (featuresNode.isArray()) { - for (JsonNode featureNode : featuresNode) { - try { - Long geometryId = processFeature(featureNode, learnData); - if (geometryId != null) { - geometryIds.add(geometryId); - } - } catch (Exception e) { - log.error("Feature 처리 실패 (학습 데이터 ID: {})", learnData.getId(), e); - } - } - } - - return geometryIds; + if (!featureCollectionNode.has("features")) { + log.warn("FeatureCollection에 features 배열이 없습니다: {}", learnData.getId()); + return geometryIds; } - /** - * Feature 처리 - */ - private Long processFeature(JsonNode featureNode, MapSheetLearnDataEntity learnData) { + JsonNode featuresNode = featureCollectionNode.get("features"); + if (featuresNode.isArray()) { + for (JsonNode featureNode : featuresNode) { try { - if (!featureNode.has("geometry")) { - log.warn("Feature에 geometry가 없습니다: {}", learnData.getId()); - return null; - } - - JsonNode geometryNode = featureNode.get("geometry"); - JsonNode propertiesNode = featureNode.has("properties") ? featureNode.get("properties") : null; - - return createGeometryEntity(geometryNode, propertiesNode, learnData); - + Long geometryId = processFeature(featureNode, learnData); + if (geometryId != null) { + geometryIds.add(geometryId); + } } catch (Exception e) { - log.error("Feature 처리 중 오류 (학습 데이터 ID: {})", learnData.getId(), e); - return null; + log.error("Feature 처리 실패 (학습 데이터 ID: {})", learnData.getId(), e); } + } } - /** - * 직접 Geometry 처리 - */ - private Long processDirectGeometry(JsonNode geometryNode, MapSheetLearnDataEntity learnData) { - return createGeometryEntity(geometryNode, null, learnData); + return geometryIds; + } + + /** Feature 처리 */ + private Long processFeature(JsonNode featureNode, MapSheetLearnDataEntity learnData) { + try { + if (!featureNode.has("geometry")) { + log.warn("Feature에 geometry가 없습니다: {}", learnData.getId()); + return null; + } + + JsonNode geometryNode = featureNode.get("geometry"); + JsonNode propertiesNode = + featureNode.has("properties") ? featureNode.get("properties") : null; + + return createGeometryEntity(geometryNode, propertiesNode, learnData); + + } catch (Exception e) { + log.error("Feature 처리 중 오류 (학습 데이터 ID: {})", learnData.getId(), e); + return null; + } + } + + /** 직접 Geometry 처리 */ + private Long processDirectGeometry(JsonNode geometryNode, MapSheetLearnDataEntity learnData) { + return createGeometryEntity(geometryNode, null, learnData); + } + + /** GeometryEntity 생성 및 저장 */ + private Long createGeometryEntity( + JsonNode geometryNode, JsonNode propertiesNode, MapSheetLearnDataEntity learnData) { + try { + MapSheetLearnDataGeomEntity geometryEntity = new MapSheetLearnDataGeomEntity(); + + // 기본 정보 설정 + geometryEntity.setDataUid(learnData.getId()); + geometryEntity.setBeforeYyyy(learnData.getDataYyyy()); + geometryEntity.setAfterYyyy(learnData.getCompareYyyy()); + + // Geometry 변환 및 설정 + Geometry geometry = parseGeometryFromGeoJson(geometryNode); + if (geometry != null) { + geometryEntity.setGeom(geometry); + geometryEntity.setGeoType(geometry.getGeometryType()); + + // 면적 계산 (Polygon인 경우) + if (geometry instanceof Polygon || geometry.getGeometryType().contains("Polygon")) { + double area = geometry.getArea(); + geometryEntity.setArea(area); + } + } else { + log.warn("Geometry 변환 실패: {}", geometryNode); + return null; + } + + // Properties에서 추가 정보 추출 + if (propertiesNode != null) { + extractPropertiesData(geometryEntity, propertiesNode, learnData); + } + + // 시간 정보 설정 + ZonedDateTime now = ZonedDateTime.now(); + geometryEntity.setCreatedDttm(now); + geometryEntity.setUpdatedDttm(now); + + // 저장 + MapSheetLearnDataGeomEntity savedEntity = + mapSheetLearnDataGeomRepository.save(geometryEntity); + return savedEntity.getId(); + + } catch (Exception e) { + log.error("GeometryEntity 생성 실패 (학습 데이터 ID: {})", learnData.getId(), e); + return null; + } + } + + /** GeoJSON 노드에서 JTS Geometry 객체 생성 */ + private Geometry parseGeometryFromGeoJson(JsonNode geometryNode) { + try { + if (!geometryNode.has("type") || !geometryNode.has("coordinates")) { + log.warn("유효하지 않은 Geometry 형식: type 또는 coordinates가 없습니다."); + return null; + } + + String geometryType = geometryNode.get("type").asText(); + JsonNode coordinatesNode = geometryNode.get("coordinates"); + + switch (geometryType.toLowerCase()) { + case "point": + return createPoint(coordinatesNode); + case "linestring": + return createLineString(coordinatesNode); + case "polygon": + return createPolygon(coordinatesNode); + case "multipoint": + return createMultiPoint(coordinatesNode); + case "multilinestring": + return createMultiLineString(coordinatesNode); + case "multipolygon": + return createMultiPolygon(coordinatesNode); + default: + log.warn("지원하지 않는 Geometry 타입: {}", geometryType); + return null; + } + + } catch (Exception e) { + log.error("Geometry 파싱 실패", e); + return null; + } + } + + private Point createPoint(JsonNode coordinatesNode) { + if (coordinatesNode.size() < 2) return null; + double x = coordinatesNode.get(0).asDouble(); + double y = coordinatesNode.get(1).asDouble(); + return geometryFactory.createPoint(new Coordinate(x, y)); + } + + private LineString createLineString(JsonNode coordinatesNode) { + List coords = new ArrayList<>(); + for (JsonNode coordNode : coordinatesNode) { + if (coordNode.size() >= 2) { + coords.add(new Coordinate(coordNode.get(0).asDouble(), coordNode.get(1).asDouble())); + } + } + return geometryFactory.createLineString(coords.toArray(new Coordinate[0])); + } + + private Polygon createPolygon(JsonNode coordinatesNode) { + if (coordinatesNode.size() == 0) return null; + + // Exterior ring + JsonNode exteriorRing = coordinatesNode.get(0); + List coords = new ArrayList<>(); + for (JsonNode coordNode : exteriorRing) { + if (coordNode.size() >= 2) { + coords.add(new Coordinate(coordNode.get(0).asDouble(), coordNode.get(1).asDouble())); + } } - /** - * GeometryEntity 생성 및 저장 - */ - private Long createGeometryEntity(JsonNode geometryNode, JsonNode propertiesNode, MapSheetLearnDataEntity learnData) { - try { - MapSheetLearnDataGeomEntity geometryEntity = new MapSheetLearnDataGeomEntity(); + if (coords.size() < 3) return null; - // 기본 정보 설정 - geometryEntity.setDataUid(learnData.getId()); - geometryEntity.setBeforeYyyy(learnData.getDataYyyy()); - geometryEntity.setAfterYyyy(learnData.getCompareYyyy()); - - // Geometry 변환 및 설정 - Geometry geometry = parseGeometryFromGeoJson(geometryNode); - if (geometry != null) { - geometryEntity.setGeom(geometry); - geometryEntity.setGeoType(geometry.getGeometryType()); - - // 면적 계산 (Polygon인 경우) - if (geometry instanceof Polygon || geometry.getGeometryType().contains("Polygon")) { - double area = geometry.getArea(); - geometryEntity.setArea(area); - } - } else { - log.warn("Geometry 변환 실패: {}", geometryNode); - return null; - } - - // Properties에서 추가 정보 추출 - if (propertiesNode != null) { - extractPropertiesData(geometryEntity, propertiesNode, learnData); - } - - // 시간 정보 설정 - ZonedDateTime now = ZonedDateTime.now(); - geometryEntity.setCreatedDttm(now); - geometryEntity.setUpdatedDttm(now); - - // 저장 - MapSheetLearnDataGeomEntity savedEntity = mapSheetLearnDataGeomRepository.save(geometryEntity); - return savedEntity.getId(); - - } catch (Exception e) { - log.error("GeometryEntity 생성 실패 (학습 데이터 ID: {})", learnData.getId(), e); - return null; - } + // Close ring if not already closed + if (!coords.get(0).equals2D(coords.get(coords.size() - 1))) { + coords.add(new Coordinate(coords.get(0))); } - /** - * GeoJSON 노드에서 JTS Geometry 객체 생성 - */ - private Geometry parseGeometryFromGeoJson(JsonNode geometryNode) { - try { - if (!geometryNode.has("type") || !geometryNode.has("coordinates")) { - log.warn("유효하지 않은 Geometry 형식: type 또는 coordinates가 없습니다."); - return null; - } + LinearRing shell = geometryFactory.createLinearRing(coords.toArray(new Coordinate[0])); - String geometryType = geometryNode.get("type").asText(); - JsonNode coordinatesNode = geometryNode.get("coordinates"); - - switch (geometryType.toLowerCase()) { - case "point": - return createPoint(coordinatesNode); - case "linestring": - return createLineString(coordinatesNode); - case "polygon": - return createPolygon(coordinatesNode); - case "multipoint": - return createMultiPoint(coordinatesNode); - case "multilinestring": - return createMultiLineString(coordinatesNode); - case "multipolygon": - return createMultiPolygon(coordinatesNode); - default: - log.warn("지원하지 않는 Geometry 타입: {}", geometryType); - return null; - } - - } catch (Exception e) { - log.error("Geometry 파싱 실패", e); - return null; + // Interior rings (holes) + LinearRing[] holes = new LinearRing[coordinatesNode.size() - 1]; + for (int i = 1; i < coordinatesNode.size(); i++) { + JsonNode holeRing = coordinatesNode.get(i); + List holeCoords = new ArrayList<>(); + for (JsonNode coordNode : holeRing) { + if (coordNode.size() >= 2) { + holeCoords.add(new Coordinate(coordNode.get(0).asDouble(), coordNode.get(1).asDouble())); } + } + if (holeCoords.size() >= 3) { + if (!holeCoords.get(0).equals2D(holeCoords.get(holeCoords.size() - 1))) { + holeCoords.add(new Coordinate(holeCoords.get(0))); + } + holes[i - 1] = geometryFactory.createLinearRing(holeCoords.toArray(new Coordinate[0])); + } } - private Point createPoint(JsonNode coordinatesNode) { - if (coordinatesNode.size() < 2) return null; - double x = coordinatesNode.get(0).asDouble(); - double y = coordinatesNode.get(1).asDouble(); - return geometryFactory.createPoint(new Coordinate(x, y)); + return geometryFactory.createPolygon(shell, holes); + } + + private MultiPoint createMultiPoint(JsonNode coordinatesNode) { + List points = new ArrayList<>(); + for (JsonNode pointNode : coordinatesNode) { + Point point = createPoint(pointNode); + if (point != null) { + points.add(point); + } + } + return geometryFactory.createMultiPoint(points.toArray(new Point[0])); + } + + private MultiLineString createMultiLineString(JsonNode coordinatesNode) { + List lineStrings = new ArrayList<>(); + for (JsonNode lineNode : coordinatesNode) { + LineString line = createLineString(lineNode); + if (line != null) { + lineStrings.add(line); + } + } + return geometryFactory.createMultiLineString(lineStrings.toArray(new LineString[0])); + } + + private MultiPolygon createMultiPolygon(JsonNode coordinatesNode) { + List polygons = new ArrayList<>(); + for (JsonNode polygonNode : coordinatesNode) { + Polygon polygon = createPolygon(polygonNode); + if (polygon != null) { + polygons.add(polygon); + } + } + return geometryFactory.createMultiPolygon(polygons.toArray(new Polygon[0])); + } + + /** Properties에서 추가 정보 추출 */ + private void extractPropertiesData( + MapSheetLearnDataGeomEntity geometryEntity, + JsonNode propertiesNode, + MapSheetLearnDataEntity learnData) { + // CD 정확도 정보 + if (propertiesNode.has("cd_prob")) { + try { + double cdProb = propertiesNode.get("cd_prob").asDouble(); + geometryEntity.setCdProb(cdProb); + } catch (Exception e) { + log.debug("cd_prob 파싱 실패", e); + } } - private LineString createLineString(JsonNode coordinatesNode) { - List coords = new ArrayList<>(); - for (JsonNode coordNode : coordinatesNode) { - if (coordNode.size() >= 2) { - coords.add(new Coordinate(coordNode.get(0).asDouble(), coordNode.get(1).asDouble())); - } - } - return geometryFactory.createLineString(coords.toArray(new Coordinate[0])); + // Before class 정보 + if (propertiesNode.has("class_before_name")) { + geometryEntity.setClassBeforeName(propertiesNode.get("class_before_name").asText()); + } + if (propertiesNode.has("class_before_prob")) { + try { + double beforeProb = propertiesNode.get("class_before_prob").asDouble(); + geometryEntity.setClassBeforeProb(beforeProb); + } catch (Exception e) { + log.debug("class_before_prob 파싱 실패", e); + } } - private Polygon createPolygon(JsonNode coordinatesNode) { - if (coordinatesNode.size() == 0) return null; - - // Exterior ring - JsonNode exteriorRing = coordinatesNode.get(0); - List coords = new ArrayList<>(); - for (JsonNode coordNode : exteriorRing) { - if (coordNode.size() >= 2) { - coords.add(new Coordinate(coordNode.get(0).asDouble(), coordNode.get(1).asDouble())); - } - } - - if (coords.size() < 3) return null; - - // Close ring if not already closed - if (!coords.get(0).equals2D(coords.get(coords.size() - 1))) { - coords.add(new Coordinate(coords.get(0))); - } - - LinearRing shell = geometryFactory.createLinearRing(coords.toArray(new Coordinate[0])); - - // Interior rings (holes) - LinearRing[] holes = new LinearRing[coordinatesNode.size() - 1]; - for (int i = 1; i < coordinatesNode.size(); i++) { - JsonNode holeRing = coordinatesNode.get(i); - List holeCoords = new ArrayList<>(); - for (JsonNode coordNode : holeRing) { - if (coordNode.size() >= 2) { - holeCoords.add(new Coordinate(coordNode.get(0).asDouble(), coordNode.get(1).asDouble())); - } - } - if (holeCoords.size() >= 3) { - if (!holeCoords.get(0).equals2D(holeCoords.get(holeCoords.size() - 1))) { - holeCoords.add(new Coordinate(holeCoords.get(0))); - } - holes[i - 1] = geometryFactory.createLinearRing(holeCoords.toArray(new Coordinate[0])); - } - } - - return geometryFactory.createPolygon(shell, holes); + // After class 정보 + if (propertiesNode.has("class_after_name")) { + geometryEntity.setClassAfterName(propertiesNode.get("class_after_name").asText()); + } + if (propertiesNode.has("class_after_prob")) { + try { + double afterProb = propertiesNode.get("class_after_prob").asDouble(); + geometryEntity.setClassAfterProb(afterProb); + } catch (Exception e) { + log.debug("class_after_prob 파싱 실패", e); + } } - private MultiPoint createMultiPoint(JsonNode coordinatesNode) { - List points = new ArrayList<>(); - for (JsonNode pointNode : coordinatesNode) { - Point point = createPoint(pointNode); - if (point != null) { - points.add(point); - } - } - return geometryFactory.createMultiPoint(points.toArray(new Point[0])); + // 도엽 번호 + if (propertiesNode.has("map_sheet_num")) { + try { + long mapSheetNum = propertiesNode.get("map_sheet_num").asLong(); + geometryEntity.setMapSheetNum(mapSheetNum); + } catch (Exception e) { + log.debug("map_sheet_num 파싱 실패", e); + } } - private MultiLineString createMultiLineString(JsonNode coordinatesNode) { - List lineStrings = new ArrayList<>(); - for (JsonNode lineNode : coordinatesNode) { - LineString line = createLineString(lineNode); - if (line != null) { - lineStrings.add(line); - } - } - return geometryFactory.createMultiLineString(lineStrings.toArray(new LineString[0])); + // 면적 (properties에서 제공되는 경우) + if (propertiesNode.has("area")) { + try { + double area = propertiesNode.get("area").asDouble(); + geometryEntity.setArea(area); + } catch (Exception e) { + log.debug("area 파싱 실패", e); + } + } + } + + /** 미처리된 학습 데이터들을 찾아서 자동으로 geometry 변환 수행 */ + @Transactional + public List processUnprocessedLearnData() { + // 분석 상태가 PENDING인 학습 데이터 조회 + List unprocessedData = + mapSheetLearnDataRepository.findByAnalState("PENDING"); + + if (unprocessedData.isEmpty()) { + log.debug("처리할 미완료 학습 데이터가 없습니다."); + return new ArrayList<>(); } - private MultiPolygon createMultiPolygon(JsonNode coordinatesNode) { - List polygons = new ArrayList<>(); - for (JsonNode polygonNode : coordinatesNode) { - Polygon polygon = createPolygon(polygonNode); - if (polygon != null) { - polygons.add(polygon); - } - } - return geometryFactory.createMultiPolygon(polygons.toArray(new Polygon[0])); + log.info("미처리 학습 데이터 {}개에 대해 geometry 변환을 수행합니다.", unprocessedData.size()); + + List processedIds = new ArrayList<>(); + for (MapSheetLearnDataEntity data : unprocessedData) { + try { + List geometryIds = processLearnDataToGeometry(data); + processedIds.addAll(geometryIds); + + // 처리 완료 상태로 업데이트 + data.setAnalState("COMPLETED"); + mapSheetLearnDataRepository.save(data); + + } catch (Exception e) { + log.error("미처리 학습 데이터 처리 실패: {}", data.getId(), e); + // 실패한 경우 ERROR 상태로 설정 + data.setAnalState("ERROR"); + mapSheetLearnDataRepository.save(data); + } } - /** - * Properties에서 추가 정보 추출 - */ - private void extractPropertiesData(MapSheetLearnDataGeomEntity geometryEntity, JsonNode propertiesNode, MapSheetLearnDataEntity learnData) { - // CD 정확도 정보 - if (propertiesNode.has("cd_prob")) { - try { - double cdProb = propertiesNode.get("cd_prob").asDouble(); - geometryEntity.setCdProb(cdProb); - } catch (Exception e) { - log.debug("cd_prob 파싱 실패", e); - } - } - - // Before class 정보 - if (propertiesNode.has("class_before_name")) { - geometryEntity.setClassBeforeName(propertiesNode.get("class_before_name").asText()); - } - if (propertiesNode.has("class_before_prob")) { - try { - double beforeProb = propertiesNode.get("class_before_prob").asDouble(); - geometryEntity.setClassBeforeProb(beforeProb); - } catch (Exception e) { - log.debug("class_before_prob 파싱 실패", e); - } - } - - // After class 정보 - if (propertiesNode.has("class_after_name")) { - geometryEntity.setClassAfterName(propertiesNode.get("class_after_name").asText()); - } - if (propertiesNode.has("class_after_prob")) { - try { - double afterProb = propertiesNode.get("class_after_prob").asDouble(); - geometryEntity.setClassAfterProb(afterProb); - } catch (Exception e) { - log.debug("class_after_prob 파싱 실패", e); - } - } - - // 도엽 번호 - if (propertiesNode.has("map_sheet_num")) { - try { - long mapSheetNum = propertiesNode.get("map_sheet_num").asLong(); - geometryEntity.setMapSheetNum(mapSheetNum); - } catch (Exception e) { - log.debug("map_sheet_num 파싱 실패", e); - } - } - - // 면적 (properties에서 제공되는 경우) - if (propertiesNode.has("area")) { - try { - double area = propertiesNode.get("area").asDouble(); - geometryEntity.setArea(area); - } catch (Exception e) { - log.debug("area 파싱 실패", e); - } - } - } - - /** - * 미처리된 학습 데이터들을 찾아서 자동으로 geometry 변환 수행 - */ - @Transactional - public List processUnprocessedLearnData() { - // 분석 상태가 PENDING인 학습 데이터 조회 - List unprocessedData = mapSheetLearnDataRepository.findByAnalState("PENDING"); - - if (unprocessedData.isEmpty()) { - log.debug("처리할 미완료 학습 데이터가 없습니다."); - return new ArrayList<>(); - } - - log.info("미처리 학습 데이터 {}개에 대해 geometry 변환을 수행합니다.", unprocessedData.size()); - - List processedIds = new ArrayList<>(); - for (MapSheetLearnDataEntity data : unprocessedData) { - try { - List geometryIds = processLearnDataToGeometry(data); - processedIds.addAll(geometryIds); - - // 처리 완료 상태로 업데이트 - data.setAnalState("COMPLETED"); - mapSheetLearnDataRepository.save(data); - - } catch (Exception e) { - log.error("미처리 학습 데이터 처리 실패: {}", data.getId(), e); - // 실패한 경우 ERROR 상태로 설정 - data.setAnalState("ERROR"); - mapSheetLearnDataRepository.save(data); - } - } - - return processedIds; - } + return processedIds; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java index 00bba2be..2e605983 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java @@ -4,7 +4,6 @@ import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Dashboard; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Detail; -import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.SearchReq; import com.kamco.cd.kamcoback.inference.service.InferenceResultService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -29,132 +28,125 @@ public class InferenceResultApiController { private final InferenceResultService inferenceResultService; - @Operation( - summary = "추론관리 분석결과 목록 조회", - description = - "분석상태, 제목으로 분석결과를 조회 합니다.") + @Operation(summary = "추론관리 분석결과 목록 조회", description = "분석상태, 제목으로 분석결과를 조회 합니다.") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "검색 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Page.class))), - @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Page.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping("/list") public ApiResponseDto> getInferenceResultList( - @Parameter(description = "분석상태", example = "0000") - @RequestParam(required = false) - String statCode, - @Parameter(description = "제목", example = "2023_2024년도") @RequestParam(required = false) - String title, - @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") - int page, - @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") - int size, - @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") - @RequestParam(required = false) - String sort - ) { - InferenceResultDto.SearchReq searchReq = new InferenceResultDto.SearchReq(statCode, title, page, size, sort); - Page analResList = inferenceResultService.getInferenceResultList(searchReq); + @Parameter(description = "분석상태", example = "0000") @RequestParam(required = false) + String statCode, + @Parameter(description = "제목", example = "2023_2024년도") @RequestParam(required = false) + String title, + @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") + int page, + @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") + int size, + @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") + @RequestParam(required = false) + String sort) { + InferenceResultDto.SearchReq searchReq = + new InferenceResultDto.SearchReq(statCode, title, page, size, sort); + Page analResList = + inferenceResultService.getInferenceResultList(searchReq); return ApiResponseDto.ok(analResList); } - @Operation( - summary = "추론관리 분석결과 요약정보", - description = - "분석결과 요약정보를 조회합니다.") + @Operation(summary = "추론관리 분석결과 요약정보", description = "분석결과 요약정보를 조회합니다.") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "검색 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = InferenceResultDto.AnalResSummary.class))), - @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = InferenceResultDto.AnalResSummary.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping("/summary") public ApiResponseDto getInferenceResultSummary( - @Parameter(description = "목록 id", example = "1") - @RequestParam Long id) { + @Parameter(description = "목록 id", example = "1") @RequestParam Long id) { return ApiResponseDto.ok(inferenceResultService.getInferenceResultSummary(id)); } - - @Operation( - summary = "추론관리 분석결과 상세", - description = - "분석결과 상제 정보 Summary, DashBoard") + @Operation(summary = "추론관리 분석결과 상세", description = "분석결과 상제 정보 Summary, DashBoard") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "검색 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = InferenceResultDto.Detail.class))), - @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = InferenceResultDto.Detail.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping("/detail") public ApiResponseDto getInferenceDetail( - @Parameter(description = "목록 id", example = "1") - @RequestParam Long id) { + @Parameter(description = "목록 id", example = "1") @RequestParam Long id) { // summary - InferenceResultDto.AnalResSummary summary = inferenceResultService.getInferenceResultSummary(id); - //dashBoard + InferenceResultDto.AnalResSummary summary = + inferenceResultService.getInferenceResultSummary(id); + // dashBoard List dashboardList = this.getInferenceResultDashboard(id); return ApiResponseDto.ok(new Detail(summary, dashboardList)); } - @Operation( - summary = "추론관리 분석결과 상세 목록", - description = - "추론관리 분석결과 상세 목록 geojson 데이터 조회") + @Operation(summary = "추론관리 분석결과 상세 목록", description = "추론관리 분석결과 상세 목록 geojson 데이터 조회") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "검색 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Page.class))), - @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "검색 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Page.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping("/geom") public ApiResponseDto> getInferenceResultGeomList( - @Parameter(description = "기준년도 분류", example = "0001") @RequestParam(required = false) String targetClass, - @Parameter(description = "비교년도 분류", example = "0002") @RequestParam(required = false) String compareClass, - @Parameter(description = "5000:1 도협번호 37801011,37801012") @RequestParam(required = false) List mapSheetNum, - @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") int page, - @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") int size, - @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") @RequestParam(required = false) String sort - ) { - InferenceResultDto.SearchGeoReq searchGeoReq = new InferenceResultDto.SearchGeoReq(targetClass, compareClass, mapSheetNum, page, size, sort); - Page geomList = inferenceResultService.getInferenceResultGeomList(searchGeoReq); + @Parameter(description = "기준년도 분류", example = "0001") @RequestParam(required = false) + String targetClass, + @Parameter(description = "비교년도 분류", example = "0002") @RequestParam(required = false) + String compareClass, + @Parameter(description = "5000:1 도협번호 37801011,37801012") @RequestParam(required = false) + List mapSheetNum, + @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") + int page, + @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") + int size, + @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") + @RequestParam(required = false) + String sort) { + InferenceResultDto.SearchGeoReq searchGeoReq = + new InferenceResultDto.SearchGeoReq( + targetClass, compareClass, mapSheetNum, page, size, sort); + Page geomList = + inferenceResultService.getInferenceResultGeomList(searchGeoReq); return ApiResponseDto.ok(geomList); } /** * 분석결과 상세 대시보드 조회 + * * @param id * @return */ private List getInferenceResultDashboard(Long id) { return inferenceResultService.getInferenceResultBasic(id); } - - - } diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java index 0f9898a2..439bb489 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java @@ -8,7 +8,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -23,23 +22,20 @@ public class InferenceResultDto { private String dataName; private Long mapSheepNum; private Long detectingCnt; - @JsonFormatDttm - private ZonedDateTime analStrtDttm; - @JsonFormatDttm - private ZonedDateTime analEndDttm; + @JsonFormatDttm private ZonedDateTime analStrtDttm; + @JsonFormatDttm private ZonedDateTime analEndDttm; private Long analSec; private String analState; public Basic( - Long id, - String dataName, - Long mapSheepNum, - Long detectingCnt, - ZonedDateTime analStrtDttm, - ZonedDateTime analEndDttm, - Long analSec, - String analState - ) { + Long id, + String dataName, + Long mapSheepNum, + Long detectingCnt, + ZonedDateTime analStrtDttm, + ZonedDateTime analEndDttm, + Long analSec, + String analState) { this.id = id; this.dataName = dataName; this.mapSheepNum = mapSheepNum; @@ -58,10 +54,8 @@ public class InferenceResultDto { private String analTitle; private String analMapSheet; private Long detectingCnt; - @JsonFormatDttm - private ZonedDateTime analStrtDttm; - @JsonFormatDttm - private ZonedDateTime analEndDttm; + @JsonFormatDttm private ZonedDateTime analStrtDttm; + @JsonFormatDttm private ZonedDateTime analEndDttm; private Long analSec; private Long analPredSec; private String analState; @@ -69,18 +63,17 @@ public class InferenceResultDto { private String gukyuinUsed; public AnalResList( - Long id, - String analTitle, - String analMapSheet, - Long detectingCnt, - ZonedDateTime analStrtDttm, - ZonedDateTime analEndDttm, - Long analSec, - Long analPredSec, - String analState, - String analStateNm, - String gukyuinUsed - ) { + Long id, + String analTitle, + String analMapSheet, + Long detectingCnt, + ZonedDateTime analStrtDttm, + ZonedDateTime analEndDttm, + Long analSec, + Long analPredSec, + String analState, + String analStateNm, + String gukyuinUsed) { this.id = id; this.analTitle = analTitle; this.analMapSheet = analMapSheet; @@ -103,10 +96,8 @@ public class InferenceResultDto { private Integer targetYyyy; private Integer compareYyyy; private String analMapSheet; - @JsonFormatDttm - private ZonedDateTime analStrtDttm; - @JsonFormatDttm - private ZonedDateTime analEndDttm; + @JsonFormatDttm private ZonedDateTime analStrtDttm; + @JsonFormatDttm private ZonedDateTime analEndDttm; private Long analSec; private Long analPredSec; private String resultUrl; @@ -116,21 +107,20 @@ public class InferenceResultDto { private String analStateNm; public AnalResSummary( - Long id, - String modelInfo, - Integer targetYyyy, - Integer compareYyyy, - String analMapSheet, - ZonedDateTime analStrtDttm, - ZonedDateTime analEndDttm, - Long analSec, - Long analPredSec, - String resultUrl, - Long detectingCnt, - Double accuracy, - String analState, - String analStateNm - ) { + Long id, + String modelInfo, + Integer targetYyyy, + Integer compareYyyy, + String analMapSheet, + ZonedDateTime analStrtDttm, + ZonedDateTime analEndDttm, + Long analSec, + Long analPredSec, + String resultUrl, + Long detectingCnt, + Double accuracy, + String analState, + String analStateNm) { this.id = id; this.modelInfo = modelInfo; this.targetYyyy = targetYyyy; @@ -157,30 +147,27 @@ public class InferenceResultDto { String classAfterName; Long classBeforeCnt; Long classAfterCnt; - @JsonFormatDttm - ZonedDateTime createdDttm; + @JsonFormatDttm ZonedDateTime createdDttm; Long createdUid; - @JsonFormatDttm - ZonedDateTime updatedDttm; + @JsonFormatDttm ZonedDateTime updatedDttm; Long updatedUid; Long refMapSheetNum; Long dataUid; public Dashboard( - Integer compareYyyy, - Integer targetYyyy, - Long mapSheetNum, - String classBeforeName, - String classAfterName, - Long classBeforeCnt, - Long classAfterCnt, - ZonedDateTime createdDttm, - Long createdUid, - ZonedDateTime updatedDttm, - Long updatedUid, - Long refMapSheetNum, - Long dataUid - ) { + Integer compareYyyy, + Integer targetYyyy, + Long mapSheetNum, + String classBeforeName, + String classAfterName, + Long classBeforeCnt, + Long classAfterCnt, + ZonedDateTime createdDttm, + Long createdUid, + ZonedDateTime updatedDttm, + Long updatedUid, + Long refMapSheetNum, + Long dataUid) { this.compareYyyy = compareYyyy; this.targetYyyy = targetYyyy; this.mapSheetNum = mapSheetNum; @@ -202,10 +189,7 @@ public class InferenceResultDto { AnalResSummary summary; List dashboard; - public Detail( - AnalResSummary summary, - List dashboard - ) { + public Detail(AnalResSummary summary, List dashboard) { this.summary = summary; this.dashboard = dashboard; } @@ -224,16 +208,15 @@ public class InferenceResultDto { Long mapSheetNum; public Geom( - Integer compareYyyy, - Integer targetYyyy, - String classBeforeCd, - String classBeforeName, - Double classBeforeProb, - String classAfterCd, - String classAfterName, - Double classAfterProb, - Long mapSheetNum - ) { + Integer compareYyyy, + Integer targetYyyy, + String classBeforeCd, + String classBeforeName, + Double classBeforeProb, + String classAfterCd, + String classAfterName, + Double classAfterProb, + Long mapSheetNum) { this.compareYyyy = compareYyyy; this.targetYyyy = targetYyyy; this.classBeforeCd = classBeforeCd; @@ -246,9 +229,6 @@ public class InferenceResultDto { } } - - - @Schema(name = "InferenceResultSearchReq", description = "분석결과 목록 요청 정보") @Getter @Setter @@ -270,7 +250,7 @@ public class InferenceResultDto { String[] sortParams = sort.split(","); String property = sortParams[0]; Sort.Direction direction = - sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC; + sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC; return PageRequest.of(page, size, Sort.by(direction, property)); } return PageRequest.of(page, size); @@ -288,7 +268,7 @@ public class InferenceResultDto { private String targetClass; // 비교년도 private String compareClass; - //분석도엽 + // 분석도엽 private List mapSheetNum; // 페이징 파라미터 @@ -301,7 +281,7 @@ public class InferenceResultDto { String[] sortParams = sort.split(","); String property = sortParams[0]; Sort.Direction direction = - sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC; + sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC; return PageRequest.of(page, size, Sort.by(direction, property)); } return PageRequest.of(page, size); diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java index 99a538a0..4912bc19 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java @@ -1,7 +1,6 @@ package com.kamco.cd.kamcoback.inference.service; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; -import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Basic; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Dashboard; import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService; import java.util.List; @@ -19,15 +18,18 @@ public class InferenceResultService { /** * 추론관리 > 분석결과 목록 조회 + * * @param searchReq * @return */ - public Page getInferenceResultList(InferenceResultDto.SearchReq searchReq) { + public Page getInferenceResultList( + InferenceResultDto.SearchReq searchReq) { return inferenceResultCoreService.getInferenceResultList(searchReq); } /** * 분석결과 요약정보 + * * @param id * @return */ @@ -37,6 +39,7 @@ public class InferenceResultService { /** * 분석결과 대시보드 조회 + * * @param id * @return */ @@ -46,12 +49,12 @@ public class InferenceResultService { /** * 분석결과 상세 목록 + * * @param searchGeoReq * @return */ - public Page getInferenceResultGeomList(InferenceResultDto.SearchGeoReq searchGeoReq) { + public Page getInferenceResultGeomList( + InferenceResultDto.SearchGeoReq searchGeoReq) { return inferenceResultCoreService.getInferenceResultGeomList(searchGeoReq); } - - } diff --git a/src/main/java/com/kamco/cd/kamcoback/log/AuditLogApiController.java b/src/main/java/com/kamco/cd/kamcoback/log/AuditLogApiController.java index ffd02825..75b87d0b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/log/AuditLogApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/log/AuditLogApiController.java @@ -3,7 +3,6 @@ package com.kamco.cd.kamcoback.log; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.log.dto.AuditLogDto; import com.kamco.cd.kamcoback.log.service.AuditLogService; -import com.kamco.cd.kamcoback.postgres.core.AuditLogCoreService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import java.time.LocalDate; @@ -29,8 +28,7 @@ public class AuditLogApiController { @RequestParam(required = false) LocalDate endDate, @RequestParam int page, @RequestParam(defaultValue = "20") int size) { - AuditLogDto.searchReq searchReq = - new AuditLogDto.searchReq(page, size, "created_dttm,desc"); + AuditLogDto.searchReq searchReq = new AuditLogDto.searchReq(page, size, "created_dttm,desc"); Page result = auditLogService.getLogByDaily(searchReq, startDate, endDate); @@ -44,10 +42,8 @@ public class AuditLogApiController { @RequestParam LocalDate logDate, @RequestParam int page, @RequestParam(defaultValue = "20") int size) { - AuditLogDto.searchReq searchReq = - new AuditLogDto.searchReq(page, size, "created_dttm,desc"); - Page result = - auditLogService.getLogByDailyResult(searchReq, logDate); + AuditLogDto.searchReq searchReq = new AuditLogDto.searchReq(page, size, "created_dttm,desc"); + Page result = auditLogService.getLogByDailyResult(searchReq, logDate); return ApiResponseDto.ok(result); } @@ -58,8 +54,7 @@ public class AuditLogApiController { @RequestParam(required = false) String searchValue, @RequestParam int page, @RequestParam(defaultValue = "20") int size) { - AuditLogDto.searchReq searchReq = - new AuditLogDto.searchReq(page, size, "created_dttm,desc"); + AuditLogDto.searchReq searchReq = new AuditLogDto.searchReq(page, size, "created_dttm,desc"); Page result = auditLogService.getLogByMenu(searchReq, searchValue); return ApiResponseDto.ok(result); @@ -71,10 +66,8 @@ public class AuditLogApiController { @RequestParam String menuId, @RequestParam int page, @RequestParam(defaultValue = "20") int size) { - AuditLogDto.searchReq searchReq = - new AuditLogDto.searchReq(page, size, "created_dttm,desc"); - Page result = - auditLogService.getLogByMenuResult(searchReq, menuId); + AuditLogDto.searchReq searchReq = new AuditLogDto.searchReq(page, size, "created_dttm,desc"); + Page result = auditLogService.getLogByMenuResult(searchReq, menuId); return ApiResponseDto.ok(result); } @@ -85,8 +78,7 @@ public class AuditLogApiController { @RequestParam(required = false) String searchValue, @RequestParam int page, @RequestParam(defaultValue = "20") int size) { - AuditLogDto.searchReq searchReq = - new AuditLogDto.searchReq(page, size, "created_dttm,desc"); + AuditLogDto.searchReq searchReq = new AuditLogDto.searchReq(page, size, "created_dttm,desc"); Page result = auditLogService.getLogByAccount(searchReq, searchValue); @@ -99,10 +91,8 @@ public class AuditLogApiController { @RequestParam Long userUid, @RequestParam int page, @RequestParam(defaultValue = "20") int size) { - AuditLogDto.searchReq searchReq = - new AuditLogDto.searchReq(page, size, "created_dttm,desc"); - Page result = - auditLogService.getLogByAccountResult(searchReq, userUid); + AuditLogDto.searchReq searchReq = new AuditLogDto.searchReq(page, size, "created_dttm,desc"); + Page result = auditLogService.getLogByAccountResult(searchReq, userUid); return ApiResponseDto.ok(result); } diff --git a/src/main/java/com/kamco/cd/kamcoback/log/ErrorLogApiController.java b/src/main/java/com/kamco/cd/kamcoback/log/ErrorLogApiController.java index 3a7fe66d..6c56e10f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/log/ErrorLogApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/log/ErrorLogApiController.java @@ -4,7 +4,6 @@ import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.log.dto.ErrorLogDto; import com.kamco.cd.kamcoback.log.dto.EventType; import com.kamco.cd.kamcoback.log.service.ErrorLogService; -import com.kamco.cd.kamcoback.postgres.core.ErrorLogCoreService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import java.time.LocalDate; diff --git a/src/main/java/com/kamco/cd/kamcoback/log/dto/AuditLogDto.java b/src/main/java/com/kamco/cd/kamcoback/log/dto/AuditLogDto.java index 310cbb7d..52fab45e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/log/dto/AuditLogDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/log/dto/AuditLogDto.java @@ -3,8 +3,6 @@ package com.kamco.cd.kamcoback.log.dto; import com.fasterxml.jackson.annotation.JsonIgnore; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; import io.swagger.v3.oas.annotations.media.Schema; -import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.ZonedDateTime; import lombok.AllArgsConstructor; import lombok.Getter; @@ -72,7 +70,13 @@ public class AuditLogDto { public static class DailyAuditList extends AuditCommon { private final String baseDate; - public DailyAuditList(int readCount, int cudCount, int printCount, int downloadCount, Long totalCount, String baseDate) { + public DailyAuditList( + int readCount, + int cudCount, + int printCount, + int downloadCount, + Long totalCount, + String baseDate) { super(readCount, cudCount, printCount, downloadCount, totalCount); this.baseDate = baseDate; } @@ -84,7 +88,14 @@ public class AuditLogDto { private final String menuId; private final String menuName; - public MenuAuditList(String menuId, String menuName, int readCount, int cudCount, int printCount, int downloadCount, Long totalCount) { + public MenuAuditList( + String menuId, + String menuName, + int readCount, + int cudCount, + int printCount, + int downloadCount, + Long totalCount) { super(readCount, cudCount, printCount, downloadCount, totalCount); this.menuId = menuId; this.menuName = menuName; @@ -98,7 +109,15 @@ public class AuditLogDto { private final String loginId; private final String username; - public UserAuditList(Long accountId, String loginId, String username, int readCount, int cudCount, int printCount, int downloadCount, Long totalCount) { + public UserAuditList( + Long accountId, + String loginId, + String username, + int readCount, + int cudCount, + int printCount, + int downloadCount, + Long totalCount) { super(readCount, cudCount, printCount, downloadCount, totalCount); this.accountId = accountId; this.loginId = loginId; @@ -122,13 +141,20 @@ public class AuditLogDto { private final String loginId; private final String menuName; - public DailyDetail(Long logId, String userName, String loginId, String menuName, EventType eventType, LogDetail detail){ + public DailyDetail( + Long logId, + String userName, + String loginId, + String menuName, + EventType eventType, + LogDetail detail) { super(logId, eventType, detail); this.userName = userName; this.loginId = loginId; this.menuName = menuName; } } + @Schema(name = "MenuDetail", description = "메뉴별 로그 상세") @Getter public static class MenuDetail extends AuditDetail { @@ -136,20 +162,28 @@ public class AuditLogDto { private final String userName; private final String loginId; - public MenuDetail(Long logId, String logDateTime, String userName, String loginId, EventType eventType, LogDetail detail){ + public MenuDetail( + Long logId, + String logDateTime, + String userName, + String loginId, + EventType eventType, + LogDetail detail) { super(logId, eventType, detail); this.logDateTime = logDateTime; this.userName = userName; this.loginId = loginId; } } + @Schema(name = "UserDetail", description = "사용자별 로그 상세") @Getter public static class UserDetail extends AuditDetail { private final String logDateTime; private final String menuNm; - public UserDetail(Long logId, String logDateTime, String menuNm, EventType eventType, LogDetail detail){ + public UserDetail( + Long logId, String logDateTime, String menuNm, EventType eventType, LogDetail detail) { super(logId, eventType, detail); this.logDateTime = logDateTime; this.menuNm = menuNm; diff --git a/src/main/java/com/kamco/cd/kamcoback/log/service/AuditLogService.java b/src/main/java/com/kamco/cd/kamcoback/log/service/AuditLogService.java index c2f591c9..2f2e4142 100644 --- a/src/main/java/com/kamco/cd/kamcoback/log/service/AuditLogService.java +++ b/src/main/java/com/kamco/cd/kamcoback/log/service/AuditLogService.java @@ -2,13 +2,12 @@ package com.kamco.cd.kamcoback.log.service; import com.kamco.cd.kamcoback.log.dto.AuditLogDto; import com.kamco.cd.kamcoback.postgres.core.AuditLogCoreService; +import java.time.LocalDate; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDate; - @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -16,34 +15,32 @@ public class AuditLogService { private final AuditLogCoreService auditLogCoreService; public Page getLogByDaily( - AuditLogDto.searchReq searchRange, LocalDate startDate, LocalDate endDate) { + AuditLogDto.searchReq searchRange, LocalDate startDate, LocalDate endDate) { return auditLogCoreService.getLogByDaily(searchRange, startDate, endDate); } public Page getLogByMenu( - AuditLogDto.searchReq searchRange, String searchValue) { + AuditLogDto.searchReq searchRange, String searchValue) { return auditLogCoreService.getLogByMenu(searchRange, searchValue); } public Page getLogByAccount( - AuditLogDto.searchReq searchRange, String searchValue) { + AuditLogDto.searchReq searchRange, String searchValue) { return auditLogCoreService.getLogByAccount(searchRange, searchValue); } public Page getLogByDailyResult( - AuditLogDto.searchReq searchRange, LocalDate logDate) { + AuditLogDto.searchReq searchRange, LocalDate logDate) { return auditLogCoreService.getLogByDailyResult(searchRange, logDate); } public Page getLogByMenuResult( - AuditLogDto.searchReq searchRange, String menuId) { + AuditLogDto.searchReq searchRange, String menuId) { return auditLogCoreService.getLogByMenuResult(searchRange, menuId); } public Page getLogByAccountResult( - AuditLogDto.searchReq searchRange, Long accountId) { + AuditLogDto.searchReq searchRange, Long accountId) { return auditLogCoreService.getLogByAccountResult(searchRange, accountId); } - - } diff --git a/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java b/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java index 473898cc..042cb152 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java @@ -2,7 +2,6 @@ package com.kamco.cd.kamcoback.model; import com.kamco.cd.kamcoback.code.dto.CommonCodeDto; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; -import com.kamco.cd.kamcoback.log.dto.AuditLogDto; import com.kamco.cd.kamcoback.model.dto.ModelMngDto; import com.kamco.cd.kamcoback.model.dto.ModelVerDto; import com.kamco.cd.kamcoback.model.service.ModelMngService; @@ -13,13 +12,12 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.web.bind.annotation.*; - import java.time.LocalDate; import java.util.List; import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; @Tag(name = "모델 관리", description = "모델 관리 API") @RequiredArgsConstructor @@ -32,17 +30,17 @@ public class ModelMngApiController { @Operation(summary = "목록 조회", description = "모든 모델 조회") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "조회 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = CommonCodeDto.Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = CommonCodeDto.Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping public ApiResponseDto> getFindAll() { return ApiResponseDto.ok(modelMngService.findModelMngAll()); @@ -50,6 +48,7 @@ public class ModelMngApiController { /** * 최종 등록 모델 정보 + * * @return ModelMngDto.FinalModelDto */ @Operation(summary = "최종 등록 모델 조회", description = "최종 등록 모델 조회") @@ -60,6 +59,7 @@ public class ModelMngApiController { /** * 모델 등록 => 모델, 버전 동시 등록 (UI 상 따로 등록하는 곳 없음) + * * @param addReq 모델 입력 값 * @return ModelVerDto.Basic */ @@ -71,7 +71,8 @@ public class ModelMngApiController { @Operation(summary = "모델 수정", description = "모델 수정") @PutMapping("/{id}") - public ApiResponseDto update(@PathVariable Long id, @RequestBody ModelMngDto.AddReq addReq) { + public ApiResponseDto update( + @PathVariable Long id, @RequestBody ModelMngDto.AddReq addReq) { return ApiResponseDto.ok(modelMngService.update(id, addReq)); } @@ -84,19 +85,19 @@ public class ModelMngApiController { @Operation(summary = "모델 등록 이력", description = "모델 등록 이력") @GetMapping("/reg-history") public ApiResponseDto> getRegHistoryList( - @RequestParam(required = false) LocalDate startDate, - @RequestParam(required = false) LocalDate endDate, - @RequestParam int page, - @RequestParam(defaultValue = "20") int size, - @RequestParam(required = false) String searchVal, - @RequestParam(required = false) String searchColumn - ) { + @RequestParam(required = false) LocalDate startDate, + @RequestParam(required = false) LocalDate endDate, + @RequestParam int page, + @RequestParam(defaultValue = "20") int size, + @RequestParam(required = false) String searchVal, + @RequestParam(required = false) String searchColumn) { ModelMngDto.searchReq searchReq = - new ModelMngDto.searchReq(page, size, Optional.ofNullable(searchColumn).orElse("createdDate") + ",desc"); - //searchColumn:: Entity 컬럼명칭으로 -> 기본값 = 등록일 createdDate, (선택) 배포일 deployDttm + new ModelMngDto.searchReq( + page, size, Optional.ofNullable(searchColumn).orElse("createdDate") + ",desc"); + // searchColumn:: Entity 컬럼명칭으로 -> 기본값 = 등록일 createdDate, (선택) 배포일 deployDttm Page result = - modelMngService.getRegHistoryList(searchReq, startDate, endDate, searchVal); + modelMngService.getRegHistoryList(searchReq, startDate, endDate, searchVal); return ApiResponseDto.ok(result); } diff --git a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java index 05843aa1..d289b367 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java @@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.model.dto; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; +import java.time.ZonedDateTime; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -11,8 +12,6 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import java.time.ZonedDateTime; - public class ModelMngDto { @Schema(name = "ModelMng Basic", description = "모델관리 엔티티 기본 정보") @@ -24,26 +23,23 @@ public class ModelMngDto { private final String modelCate; private final String modelPath; - @JsonFormatDttm - private final ZonedDateTime createdDttm; + @JsonFormatDttm private final ZonedDateTime createdDttm; private final Long createdUid; - @JsonFormatDttm - private final ZonedDateTime updatedDttm; + @JsonFormatDttm private final ZonedDateTime updatedDttm; private final Long updatedUid; private final String modelCntnt; public Basic( - Long id, - String modelNm, - String modelCate, - String modelPath, - ZonedDateTime createdDttm, - Long createdUid, - ZonedDateTime updatedDttm, - Long updatedUid, - String modelCntnt - ) { + Long id, + String modelNm, + String modelCate, + String modelPath, + ZonedDateTime createdDttm, + Long createdUid, + ZonedDateTime updatedDttm, + Long updatedUid, + String modelCntnt) { this.id = id; this.modelNm = modelNm; this.modelCate = modelCate; @@ -70,8 +66,17 @@ public class ModelMngDto { private final String deployState; private final String modelPath; - public FinalModelDto(Long modelUid, String modelNm, String modelCate, Long modelVerUid, String modelVer, - String usedState, String modelState, Double qualityProb, String deployState, String modelPath) { + public FinalModelDto( + Long modelUid, + String modelNm, + String modelCate, + Long modelVerUid, + String modelVer, + String usedState, + String modelState, + Double qualityProb, + String deployState, + String modelPath) { this.modelUid = modelUid; this.modelNm = modelNm; this.modelCate = modelCate; @@ -117,7 +122,7 @@ public class ModelMngDto { String[] sortParams = sort.split(","); String property = sortParams[0]; Sort.Direction direction = - sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC; + sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC; return PageRequest.of(page, size, Sort.by(direction, property)); } return PageRequest.of(page, size); diff --git a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelVerDto.java b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelVerDto.java index 98ff75b2..042cdbe0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelVerDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelVerDto.java @@ -2,13 +2,8 @@ package com.kamco.cd.kamcoback.model.dto; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - import java.time.ZonedDateTime; +import lombok.Getter; public class ModelVerDto { @@ -28,29 +23,26 @@ public class ModelVerDto { private final String deployState; private final String modelPath; - @JsonFormatDttm - private final ZonedDateTime createdDttm; + @JsonFormatDttm private final ZonedDateTime createdDttm; private final Long createdUid; - @JsonFormatDttm - private final ZonedDateTime updatedDttm; + @JsonFormatDttm private final ZonedDateTime updatedDttm; private final Long updatedUid; public Basic( - Long id, - Long modelUid, - String modelCate, - String modelVer, - String usedState, - String modelState, - Double qualityProb, - String deployState, - String modelPath, - ZonedDateTime createdDttm, - Long createdUid, - ZonedDateTime updatedDttm, - Long updatedUid - ) { + Long id, + Long modelUid, + String modelCate, + String modelVer, + String usedState, + String modelState, + Double qualityProb, + String deployState, + String modelPath, + ZonedDateTime createdDttm, + Long createdUid, + ZonedDateTime updatedDttm, + Long updatedUid) { this.id = id; this.modelUid = modelUid; this.modelCate = modelCate; @@ -66,5 +58,4 @@ public class ModelVerDto { this.updatedUid = updatedUid; } } - } diff --git a/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java index 50dc47f4..d89999be 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java @@ -1,18 +1,16 @@ package com.kamco.cd.kamcoback.model.service; -import com.kamco.cd.kamcoback.log.dto.AuditLogDto; import com.kamco.cd.kamcoback.model.dto.ModelMngDto; import com.kamco.cd.kamcoback.model.dto.ModelVerDto; import com.kamco.cd.kamcoback.postgres.core.ModelMngCoreService; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDate; -import java.util.List; -import java.util.Optional; - @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -20,7 +18,7 @@ public class ModelMngService { private final ModelMngCoreService modelMngCoreService; - public List findModelMngAll(){ + public List findModelMngAll() { return modelMngCoreService.findModelMngAll(); } @@ -40,7 +38,8 @@ public class ModelMngService { return modelMngCoreService.delete(id); } - public Page getRegHistoryList(ModelMngDto.searchReq searchReq, LocalDate startDate, LocalDate endDate, String searchVal) { + public Page getRegHistoryList( + ModelMngDto.searchReq searchReq, LocalDate startDate, LocalDate endDate, String searchVal) { return modelMngCoreService.getRegHistoryList(searchReq, startDate, endDate, searchVal); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/QuerydslOrderUtil.java b/src/main/java/com/kamco/cd/kamcoback/postgres/QuerydslOrderUtil.java index 58d61da3..ecd0ad2e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/QuerydslOrderUtil.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/QuerydslOrderUtil.java @@ -8,20 +8,22 @@ import org.springframework.data.domain.Pageable; public class QuerydslOrderUtil { /** * Pageable의 Sort 정보를 QueryDSL OrderSpecifier 배열로 변환 + * * @param pageable Spring Pageable * @param entityClass 엔티티 클래스 (예: User.class) * @param alias Q 엔티티 alias (예: "user") */ - public static OrderSpecifier[] getOrderSpecifiers(Pageable pageable, Class entityClass, String alias) { + public static OrderSpecifier[] getOrderSpecifiers( + Pageable pageable, Class entityClass, String alias) { PathBuilder entityPath = new PathBuilder<>(entityClass, alias); - return pageable.getSort() - .stream() - .map(sort -> { - Order order = sort.isAscending() ? Order.ASC : Order.DESC; - // PathBuilder.get()는 컬럼명(String)을 동적 Path로 반환 - return new OrderSpecifier<>(order, entityPath.get(sort.getProperty(), String.class)); - }) - .toArray(OrderSpecifier[]::new); + return pageable.getSort().stream() + .map( + sort -> { + Order order = sort.isAscending() ? Order.ASC : Order.DESC; + // PathBuilder.get()는 컬럼명(String)을 동적 Path로 반환 + return new OrderSpecifier<>(order, entityPath.get(sort.getProperty(), String.class)); + }) + .toArray(OrderSpecifier[]::new); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/ChangeDetectionCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/ChangeDetectionCoreService.java index d893864d..382c3e54 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/ChangeDetectionCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/ChangeDetectionCoreService.java @@ -1,17 +1,15 @@ package com.kamco.cd.kamcoback.postgres.core; - import com.kamco.cd.kamcoback.changedetection.dto.ChangeDetectionDto; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; import com.kamco.cd.kamcoback.postgres.repository.changedetection.ChangeDetectionRepository; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Point; import org.springframework.stereotype.Service; -import java.util.List; -import java.util.stream.Collectors; - @Service @RequiredArgsConstructor public class ChangeDetectionCoreService { @@ -21,18 +19,15 @@ public class ChangeDetectionCoreService { public List getPolygonToPoint() { List list = changeDetectionRepository.findAll(); - return list.stream().map(p -> { - Geometry polygon = p.getGeom(); - // 중심 좌표 계산 - Point centroid = polygon.getCentroid(); + return list.stream() + .map( + p -> { + Geometry polygon = p.getGeom(); + // 중심 좌표 계산 + Point centroid = polygon.getCentroid(); - return new ChangeDetectionDto( - p.getId(), - polygon, - centroid.getX(), - centroid.getY() - ); - }) - .collect(Collectors.toList()); + return new ChangeDetectionDto(p.getId(), polygon, centroid.getX(), centroid.getY()); + }) + .collect(Collectors.toList()); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/CommonCodeCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/CommonCodeCoreService.java index 5432dec4..156a1bad 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/CommonCodeCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/CommonCodeCoreService.java @@ -75,6 +75,7 @@ public class CommonCodeCoreService /** * 공통코드 이름 조회 + * * @param parentCodeCd * @param childCodeCd * @return diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java index 6e567a75..4f4e96c0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java @@ -6,7 +6,6 @@ import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalSttcEntity; import com.kamco.cd.kamcoback.postgres.repository.Inference.InferenceResultRepository; import jakarta.persistence.EntityNotFoundException; import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; @@ -19,41 +18,49 @@ public class InferenceResultCoreService { /** * 추론관리 > 분석결과 목록 조회 + * * @param searchReq * @return */ - public Page getInferenceResultList(InferenceResultDto.SearchReq searchReq) { + public Page getInferenceResultList( + InferenceResultDto.SearchReq searchReq) { return inferenceResultRepository.getInferenceResultList(searchReq); } /** * 분석결과 요약정보 + * * @param id * @return */ public InferenceResultDto.AnalResSummary getInferenceResultSummary(Long id) { - InferenceResultDto.AnalResSummary summary = inferenceResultRepository.getInferenceResultSummary(id).orElseThrow(() -> new EntityNotFoundException("요약정보를 찾을 수 없습니다. " + id)); + InferenceResultDto.AnalResSummary summary = + inferenceResultRepository + .getInferenceResultSummary(id) + .orElseThrow(() -> new EntityNotFoundException("요약정보를 찾을 수 없습니다. " + id)); return summary; } /** * 분석결과 대시보드 조회 + * * @param id * @return */ public List getInferenceResultDashboard(Long id) { - return inferenceResultRepository.getInferenceResultDashboard(id) - .stream() - .map(MapSheetAnalSttcEntity::toDto) - .toList(); + return inferenceResultRepository.getInferenceResultDashboard(id).stream() + .map(MapSheetAnalSttcEntity::toDto) + .toList(); } /** * 분석결과 상세 목록 + * * @param searchGeoReq * @return */ - public Page getInferenceResultGeomList(InferenceResultDto.SearchGeoReq searchGeoReq) { + public Page getInferenceResultGeomList( + InferenceResultDto.SearchGeoReq searchGeoReq) { return inferenceResultRepository.getInferenceGeomList(searchGeoReq); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/ModelMngCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/ModelMngCoreService.java index 8cdd8251..8a7dd34b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/ModelMngCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/ModelMngCoreService.java @@ -7,13 +7,12 @@ import com.kamco.cd.kamcoback.postgres.entity.ModelVerEntity; import com.kamco.cd.kamcoback.postgres.repository.model.ModelMngRepository; import com.kamco.cd.kamcoback.postgres.repository.model.ModelVerRepository; import jakarta.persistence.EntityNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.stereotype.Service; - import java.time.LocalDate; import java.util.List; import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor @@ -26,37 +25,57 @@ public class ModelMngCoreService { return modelMngRepository.findModelMngAll().stream().map(ModelMngEntity::toDto).toList(); } - public Optional getFinalModelInfo(){ + public Optional getFinalModelInfo() { return modelMngRepository.getFinalModelInfo(); } public ModelVerDto.Basic save(ModelMngDto.AddReq addReq) { - ModelMngEntity modelMngEntity = new ModelMngEntity(addReq.getModelNm(), addReq.getModelCate(), addReq.getModelPath(), - 1L, 1L, addReq.getModelCntnt()); //TODO: 로그인 기능 붙이면 Uid 넣어야 함 + ModelMngEntity modelMngEntity = + new ModelMngEntity( + addReq.getModelNm(), + addReq.getModelCate(), + addReq.getModelPath(), + 1L, + 1L, + addReq.getModelCntnt()); // TODO: 로그인 기능 붙이면 Uid 넣어야 함 ModelMngEntity saved = modelMngRepository.save(modelMngEntity); - ModelVerEntity modelVerEntity = new ModelVerEntity(saved.getId(), addReq.getModelCate(), addReq.getModelVer(), "NONE", "NONE", - 0.0, "NONE", addReq.getModelPath(), 1L, 1L); + ModelVerEntity modelVerEntity = + new ModelVerEntity( + saved.getId(), + addReq.getModelCate(), + addReq.getModelVer(), + "NONE", + "NONE", + 0.0, + "NONE", + addReq.getModelPath(), + 1L, + 1L); return modelVerRepository.save(modelVerEntity).toDto(); } public Long update(Long id, ModelMngDto.AddReq addReq) { - //조회 - ModelVerEntity existData = modelVerRepository.findModelVerById(id) - .orElseThrow(EntityNotFoundException::new); //데이터 없는 경우 exception + // 조회 + ModelVerEntity existData = + modelVerRepository + .findModelVerById(id) + .orElseThrow(EntityNotFoundException::new); // 데이터 없는 경우 exception existData.update(addReq); - //TODO: 추후 수정 단계에서 도커파일 업로드하면 버전 업데이트 하는 로직 필요 + // TODO: 추후 수정 단계에서 도커파일 업로드하면 버전 업데이트 하는 로직 필요 return existData.getId(); } public Long delete(Long id) { - //조회 - ModelVerEntity verEntity = modelVerRepository.findModelVerById(id) - .orElseThrow(() -> new EntityNotFoundException("버전 id 에 대한 정보를 찾을 수 없습니다. id : " + id)); + // 조회 + ModelVerEntity verEntity = + modelVerRepository + .findModelVerById(id) + .orElseThrow(() -> new EntityNotFoundException("버전 id 에 대한 정보를 찾을 수 없습니다. id : " + id)); - //usedState가 USED 이거나 이미 삭제된 상태이면 삭제 불가 + // usedState가 USED 이거나 이미 삭제된 상태이면 삭제 불가 if (verEntity.getUsedState().equals("USED") || verEntity.isDeleted().equals(true)) { - throw new IllegalStateException("해당 모델이 사용중이라 삭제 불가"); //TODO: 추후 규칙 정의되면 수정 필요 + throw new IllegalStateException("해당 모델이 사용중이라 삭제 불가"); // TODO: 추후 규칙 정의되면 수정 필요 } // id 코드 deleted = true 업데이트 @@ -64,7 +83,8 @@ public class ModelMngCoreService { return verEntity.getId(); } - public Page getRegHistoryList(ModelMngDto.searchReq searchReq, LocalDate startDate, LocalDate endDate, String searchVal) { + public Page getRegHistoryList( + ModelMngDto.searchReq searchReq, LocalDate startDate, LocalDate endDate, String searchVal) { return modelMngRepository.getRegHistoryList(searchReq, startDate, endDate, searchVal); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataEntity.java index ec6d8925..b6319e93 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataEntity.java @@ -8,8 +8,6 @@ import jakarta.persistence.Id; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import jakarta.validation.constraints.Size; -import java.time.Instant; -import java.time.LocalTime; import java.time.ZonedDateTime; import java.util.Map; import lombok.Getter; @@ -26,7 +24,10 @@ public class MapSheetAnalDataEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_sheet_anal_data_id_gen") - @SequenceGenerator(name = "tb_map_sheet_anal_data_id_gen", sequenceName = "tb_map_sheet_learn_data_data_uid", allocationSize = 1) + @SequenceGenerator( + name = "tb_map_sheet_anal_data_id_gen", + sequenceName = "tb_map_sheet_learn_data_data_uid", + allocationSize = 1) @Column(name = "data_uid", nullable = false) private Long id; @@ -103,5 +104,4 @@ public class MapSheetAnalDataEntity { @Column(name = "detecting_cnt") private Long detectingCnt; - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataGeomEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataGeomEntity.java index 57f4d94f..0435fa08 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataGeomEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalDataGeomEntity.java @@ -2,12 +2,11 @@ package com.kamco.cd.kamcoback.postgres.entity; import jakarta.persistence.*; import jakarta.validation.constraints.Size; +import java.time.ZonedDateTime; import lombok.Getter; import lombok.Setter; import org.locationtech.jts.geom.Geometry; -import java.time.ZonedDateTime; - @Getter @Setter @Entity @@ -15,8 +14,13 @@ import java.time.ZonedDateTime; public class MapSheetAnalDataGeomEntity { @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_sheet_anal_data_geom_id_gen") - @SequenceGenerator(name = "tb_map_sheet_anal_data_geom_id_gen", sequenceName = "tb_map_sheet_learn_data_geom_geom_uid", allocationSize = 1) + @GeneratedValue( + strategy = GenerationType.SEQUENCE, + generator = "tb_map_sheet_anal_data_geom_id_gen") + @SequenceGenerator( + name = "tb_map_sheet_anal_data_geom_id_gen", + sequenceName = "tb_map_sheet_learn_data_geom_geom_uid", + allocationSize = 1) @Column(name = "geo_uid", nullable = false) private Long id; diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalEntity.java index 36e7914f..a507473c 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalEntity.java @@ -2,16 +2,12 @@ package com.kamco.cd.kamcoback.postgres.entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import jakarta.validation.constraints.Size; -import java.time.Instant; import java.time.ZonedDateTime; import lombok.Getter; import lombok.Setter; @@ -25,7 +21,10 @@ public class MapSheetAnalEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_sheet_anal_id_gen") - @SequenceGenerator(name = "tb_map_sheet_anal_id_gen", sequenceName = "tb_map_sheet_anal_anal_uid", allocationSize = 1) + @SequenceGenerator( + name = "tb_map_sheet_anal_id_gen", + sequenceName = "tb_map_sheet_anal_anal_uid", + allocationSize = 1) @Column(name = "anal_uid", nullable = false) private Long id; @@ -92,5 +91,4 @@ public class MapSheetAnalEntity { @Column(name = "detecting_cnt") private Long detectingCnt; - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalSttcEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalSttcEntity.java index a2b448d1..8e49e35a 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalSttcEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalSttcEntity.java @@ -1,13 +1,11 @@ package com.kamco.cd.kamcoback.postgres.entity; -import com.kamco.cd.kamcoback.code.dto.CommonCodeDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import jakarta.persistence.Column; import jakarta.persistence.EmbeddedId; import jakarta.persistence.Entity; import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; -import java.time.OffsetDateTime; import java.time.ZonedDateTime; import lombok.Getter; import lombok.Setter; @@ -19,8 +17,7 @@ import org.hibernate.annotations.ColumnDefault; @Table(name = "tb_map_sheet_anal_sttc") public class MapSheetAnalSttcEntity { - @EmbeddedId - private MapSheetAnalSttcEntityId id; + @EmbeddedId private MapSheetAnalSttcEntityId id; @Column(name = "class_before_cnt") private Long classBeforeCnt; @@ -52,19 +49,18 @@ public class MapSheetAnalSttcEntity { public InferenceResultDto.Dashboard toDto() { return new InferenceResultDto.Dashboard( - id.getCompareYyyy(), - id.getTargetYyyy(), - id.getMapSheetNum(), - id.getClassBeforeName(), - id.getClassAfterName(), - this.classBeforeCnt, - this.classAfterCnt, - this.createdDttm, - this.createdUid, - this.updatedDttm, - this.updatedUid, - this.refMapSheetNum, - this.dataUid - ); + id.getCompareYyyy(), + id.getTargetYyyy(), + id.getMapSheetNum(), + id.getClassBeforeName(), + id.getClassAfterName(), + this.classBeforeCnt, + this.classAfterCnt, + this.createdDttm, + this.createdUid, + this.updatedDttm, + this.updatedUid, + this.refMapSheetNum, + this.dataUid); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalSttcEntityId.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalSttcEntityId.java index 568e3533..cbebe27b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalSttcEntityId.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetAnalSttcEntityId.java @@ -16,6 +16,7 @@ import org.hibernate.Hibernate; public class MapSheetAnalSttcEntityId implements Serializable { private static final long serialVersionUID = -8630519290255405042L; + @NotNull @Column(name = "compare_yyyy", nullable = false) private Integer compareYyyy; @@ -47,16 +48,15 @@ public class MapSheetAnalSttcEntityId implements Serializable { return false; } MapSheetAnalSttcEntityId entity = (MapSheetAnalSttcEntityId) o; - return Objects.equals(this.targetYyyy, entity.targetYyyy) && - Objects.equals(this.classBeforeName, entity.classBeforeName) && - Objects.equals(this.classAfterName, entity.classAfterName) && - Objects.equals(this.compareYyyy, entity.compareYyyy) && - Objects.equals(this.mapSheetNum, entity.mapSheetNum); + return Objects.equals(this.targetYyyy, entity.targetYyyy) + && Objects.equals(this.classBeforeName, entity.classBeforeName) + && Objects.equals(this.classAfterName, entity.classAfterName) + && Objects.equals(this.compareYyyy, entity.compareYyyy) + && Objects.equals(this.mapSheetNum, entity.mapSheetNum); } @Override public int hashCode() { return Objects.hash(targetYyyy, classBeforeName, classAfterName, compareYyyy, mapSheetNum); } - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataEntity.java index 634f57f3..e49a1833 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataEntity.java @@ -5,8 +5,6 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.validation.constraints.Size; -import java.time.LocalTime; -import java.time.OffsetDateTime; import java.time.ZonedDateTime; import java.util.Map; import lombok.Getter; @@ -104,5 +102,4 @@ public class MapSheetLearnDataEntity { @Column(name = "updated_uid") private Long updatedUid; - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataGeomEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataGeomEntity.java index 36f23060..72ef0304 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataGeomEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetLearnDataGeomEntity.java @@ -2,18 +2,12 @@ package com.kamco.cd.kamcoback.postgres.entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import jakarta.validation.constraints.Size; -import java.time.OffsetDateTime; import java.time.ZonedDateTime; import lombok.Getter; import lombok.Setter; -import org.hibernate.annotations.OnDelete; -import org.hibernate.annotations.OnDeleteAction; import org.locationtech.jts.geom.Geometry; @Getter @@ -75,5 +69,4 @@ public class MapSheetLearnDataGeomEntity { @Column(name = "updated_uid") private Long updatedUid; - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelDeployHstEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelDeployHstEntity.java index de3a0b1a..70da5798 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelDeployHstEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelDeployHstEntity.java @@ -2,11 +2,10 @@ package com.kamco.cd.kamcoback.postgres.entity; import com.kamco.cd.kamcoback.postgres.CommonDateEntity; import jakarta.persistence.*; +import java.time.ZonedDateTime; import lombok.Getter; import lombok.Setter; -import java.time.ZonedDateTime; - @Getter @Setter @Entity @@ -14,7 +13,10 @@ import java.time.ZonedDateTime; public class ModelDeployHstEntity extends CommonDateEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_model_deploy_hst_id_gen") - @SequenceGenerator(name = "tb_model_deploy_hst_id_gen", sequenceName = "tb_model_deploy_hst_deploy_uid", allocationSize = 1) + @SequenceGenerator( + name = "tb_model_deploy_hst_id_gen", + sequenceName = "tb_model_deploy_hst_deploy_uid", + allocationSize = 1) @Column(name = "deploy_uid", nullable = false) private Long id; diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java index b70383ff..40cb1d97 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java @@ -8,8 +8,6 @@ import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.ColumnDefault; -import java.time.ZonedDateTime; - @Getter @Setter @Entity @@ -18,7 +16,10 @@ public class ModelMngEntity extends CommonDateEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_model_mng_id_gen") - @SequenceGenerator(name = "tb_model_mng_id_gen", sequenceName = "tb_model_mng_model_uid", allocationSize = 1) + @SequenceGenerator( + name = "tb_model_mng_id_gen", + sequenceName = "tb_model_mng_model_uid", + allocationSize = 1) @Column(name = "model_uid", nullable = false) private Long id; @@ -46,8 +47,13 @@ public class ModelMngEntity extends CommonDateEntity { @Column(name = "model_cntnt", columnDefinition = "TEXT") private String modelCntnt; - public ModelMngEntity(String modelNm, String modelCate, String modelPath, - Long createdUid, Long updatedUid, String modelCntnt) { + public ModelMngEntity( + String modelNm, + String modelCate, + String modelPath, + Long createdUid, + Long updatedUid, + String modelCntnt) { this.modelNm = modelNm; this.modelCate = modelCate; this.modelPath = modelPath; @@ -59,14 +65,14 @@ public class ModelMngEntity extends CommonDateEntity { public ModelMngDto.Basic toDto() { return new ModelMngDto.Basic( - this.id, - this.modelNm, - this.modelCate, - this.modelPath, - super.getCreatedDate(), - this.createdUid, - super.getModifiedDate(), - this.updatedUid, - this.modelCntnt); + this.id, + this.modelNm, + this.modelCate, + this.modelPath, + super.getCreatedDate(), + this.createdUid, + super.getModifiedDate(), + this.updatedUid, + this.modelCntnt); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelVerEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelVerEntity.java index ce311133..153db221 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelVerEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelVerEntity.java @@ -19,7 +19,10 @@ public class ModelVerEntity extends CommonDateEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_model_ver_id_gen") - @SequenceGenerator(name = "tb_model_ver_id_gen", sequenceName = "tb_model_ver_model_ver_uid", allocationSize = 1) + @SequenceGenerator( + name = "tb_model_ver_id_gen", + sequenceName = "tb_model_ver_model_ver_uid", + allocationSize = 1) @Column(name = "model_ver_uid", nullable = false) private Long id; @@ -62,8 +65,19 @@ public class ModelVerEntity extends CommonDateEntity { private Boolean deleted = false; - public ModelVerEntity(Long id, Long modelUid, String modelCate, String modelVer, String usedState, String modelState, - Double qualityProb, String deployState, String modelPath, Long createdUid, Long updatedUid, Boolean deleted) { + public ModelVerEntity( + Long id, + Long modelUid, + String modelCate, + String modelVer, + String usedState, + String modelState, + Double qualityProb, + String deployState, + String modelPath, + Long createdUid, + Long updatedUid, + Boolean deleted) { this.id = id; this.modelUid = modelUid; this.modelCate = modelCate; @@ -78,8 +92,17 @@ public class ModelVerEntity extends CommonDateEntity { this.deleted = deleted; } - public ModelVerEntity(Long modelUid, String modelCate, String modelVer, String usedState, String modelState, - Double qualityProb, String deployState, String modelPath, Long createdUid, Long updatedUid) { + public ModelVerEntity( + Long modelUid, + String modelCate, + String modelVer, + String usedState, + String modelState, + Double qualityProb, + String deployState, + String modelPath, + Long createdUid, + Long updatedUid) { this.modelUid = modelUid; this.modelCate = modelCate; this.modelVer = modelVer; @@ -94,19 +117,19 @@ public class ModelVerEntity extends CommonDateEntity { public ModelVerDto.Basic toDto() { return new ModelVerDto.Basic( - this.id, - this.modelUid, - this.modelCate, - this.modelVer, - this.usedState, - this.modelState, - this.qualityProb, - this.deployState, - this.modelPath, - super.getCreatedDate(), - this.createdUid, - super.getModifiedDate(), - this.updatedUid); + this.id, + this.modelUid, + this.modelCate, + this.modelVer, + this.usedState, + this.modelState, + this.qualityProb, + this.deployState, + this.modelPath, + super.getCreatedDate(), + this.createdUid, + super.getModifiedDate(), + this.updatedUid); } public void update(ModelMngDto.AddReq addReq) { @@ -119,7 +142,7 @@ public class ModelVerEntity extends CommonDateEntity { return deleted; } - public void deleted(){ + public void deleted() { this.deleted = true; } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepository.java index 1599bb25..524b462a 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepository.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepository.java @@ -3,6 +3,5 @@ package com.kamco.cd.kamcoback.postgres.repository.Inference; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalEntity; import org.springframework.data.jpa.repository.JpaRepository; -public interface InferenceResultRepository extends JpaRepository, InferenceResultRepositoryCustom { - -} +public interface InferenceResultRepository + extends JpaRepository, InferenceResultRepositoryCustom {} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryCustom.java index 1364fdd2..ebad38c5 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryCustom.java @@ -1,17 +1,18 @@ package com.kamco.cd.kamcoback.postgres.repository.Inference; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; -import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Dashboard; -import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; -import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalSttcEntity; import java.util.List; import java.util.Optional; import org.springframework.data.domain.Page; public interface InferenceResultRepositoryCustom { - Page getInferenceResultList(InferenceResultDto.SearchReq searchReq); + Page getInferenceResultList( + InferenceResultDto.SearchReq searchReq); + Optional getInferenceResultSummary(Long id); - List getInferenceResultDashboard(Long id); + + List getInferenceResultDashboard(Long id); + Page getInferenceGeomList(InferenceResultDto.SearchGeoReq searchGeoReq); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java index 416a38a5..4b6914a4 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java @@ -2,13 +2,13 @@ package com.kamco.cd.kamcoback.postgres.repository.Inference; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.SearchGeoReq; -import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalSttcEntity; import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataGeomEntity; import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalEntity; import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalSttcEntity; import com.kamco.cd.kamcoback.postgres.entity.QModelMngEntity; import com.kamco.cd.kamcoback.postgres.entity.QModelVerEntity; +import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; @@ -21,7 +21,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Repository; -import com.querydsl.core.BooleanBuilder; @Repository @RequiredArgsConstructor @@ -31,18 +30,20 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC private final QMapSheetAnalEntity mapSheetAnal = QMapSheetAnalEntity.mapSheetAnalEntity; private final QModelMngEntity tmm = QModelMngEntity.modelMngEntity; private final QModelVerEntity tmv = QModelVerEntity.modelVerEntity; - private final QMapSheetAnalSttcEntity mapSheetAnalSttc = QMapSheetAnalSttcEntity.mapSheetAnalSttcEntity; - private final QMapSheetAnalDataGeomEntity mapSheetAnalDataGeom = QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity; - - + private final QMapSheetAnalSttcEntity mapSheetAnalSttc = + QMapSheetAnalSttcEntity.mapSheetAnalSttcEntity; + private final QMapSheetAnalDataGeomEntity mapSheetAnalDataGeom = + QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity; /** * 분석결과 목록 조회 + * * @param searchReq * @return */ @Override - public Page getInferenceResultList(InferenceResultDto.SearchReq searchReq) { + public Page getInferenceResultList( + InferenceResultDto.SearchReq searchReq) { Pageable pageable = searchReq.toPageable(); // "0000" 전체조회 @@ -56,101 +57,98 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC builder.and(mapSheetAnal.analTitle.like("%" + searchReq.getTitle() + "%")); } - List content = queryFactory - .select(Projections.constructor(InferenceResultDto.AnalResList.class, - mapSheetAnal.id, - mapSheetAnal.analTitle, - mapSheetAnal.analMapSheet, - mapSheetAnal.detectingCnt, - mapSheetAnal.analStrtDttm, - mapSheetAnal.analEndDttm, - mapSheetAnal.analSec, - mapSheetAnal.analPredSec, - mapSheetAnal.analState, - Expressions.stringTemplate("fn_code_name({0}, {1})", "0002", mapSheetAnal.analState), - mapSheetAnal.gukyuinUsed - )) - .from(mapSheetAnal) - .where( - builder - ) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(mapSheetAnal.createdDttm.desc()) - .fetch(); + List content = + queryFactory + .select( + Projections.constructor( + InferenceResultDto.AnalResList.class, + mapSheetAnal.id, + mapSheetAnal.analTitle, + mapSheetAnal.analMapSheet, + mapSheetAnal.detectingCnt, + mapSheetAnal.analStrtDttm, + mapSheetAnal.analEndDttm, + mapSheetAnal.analSec, + mapSheetAnal.analPredSec, + mapSheetAnal.analState, + Expressions.stringTemplate( + "fn_code_name({0}, {1})", "0002", mapSheetAnal.analState), + mapSheetAnal.gukyuinUsed)) + .from(mapSheetAnal) + .where(builder) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(mapSheetAnal.createdDttm.desc()) + .fetch(); - long total = queryFactory - .select(mapSheetAnal.id) - .from(mapSheetAnal) - .where( - builder - ) - .fetchCount(); + long total = + queryFactory.select(mapSheetAnal.id).from(mapSheetAnal).where(builder).fetchCount(); return new PageImpl<>(content, pageable, total); - - } /** * 분석결과 요약정보 + * * @param id * @return */ @Override public Optional getInferenceResultSummary(Long id) { -// 1. 최신 버전 UID를 가져오는 서브쿼리 - JPQLQuery latestVerUidSub = JPAExpressions - .select(tmv.id.max()) - .from(tmv) - .where(tmv.modelUid.eq(tmm.id)); + // 1. 최신 버전 UID를 가져오는 서브쿼리 + JPQLQuery latestVerUidSub = + JPAExpressions.select(tmv.id.max()).from(tmv).where(tmv.modelUid.eq(tmm.id)); - Optional content = Optional.ofNullable(queryFactory - .select(Projections.constructor(InferenceResultDto.AnalResSummary.class, - mapSheetAnal.id, - tmm.modelNm.concat(" ").concat(tmv.modelVer).as("modelInfo"), - mapSheetAnal.targetYyyy, - mapSheetAnal.compareYyyy, - mapSheetAnal.analMapSheet, - mapSheetAnal.analStrtDttm, - mapSheetAnal.analEndDttm, - mapSheetAnal.analSec, - mapSheetAnal.analPredSec, - mapSheetAnal.resultUrl, - mapSheetAnal.detectingCnt, - mapSheetAnal.accuracy, - mapSheetAnal.analState, - Expressions.stringTemplate("fn_code_name({0}, {1})", "0002", mapSheetAnal.analState) - )) - .from(mapSheetAnal) - .leftJoin(tmm).on(mapSheetAnal.modelUid.eq(tmm.id)) - .leftJoin(tmv).on( - tmv.modelUid.eq(tmm.id) - .and(tmv.id.eq(latestVerUidSub)) - ) - .where(mapSheetAnal.id.eq(id)) - .fetchOne() - ); + Optional content = + Optional.ofNullable( + queryFactory + .select( + Projections.constructor( + InferenceResultDto.AnalResSummary.class, + mapSheetAnal.id, + tmm.modelNm.concat(" ").concat(tmv.modelVer).as("modelInfo"), + mapSheetAnal.targetYyyy, + mapSheetAnal.compareYyyy, + mapSheetAnal.analMapSheet, + mapSheetAnal.analStrtDttm, + mapSheetAnal.analEndDttm, + mapSheetAnal.analSec, + mapSheetAnal.analPredSec, + mapSheetAnal.resultUrl, + mapSheetAnal.detectingCnt, + mapSheetAnal.accuracy, + mapSheetAnal.analState, + Expressions.stringTemplate( + "fn_code_name({0}, {1})", "0002", mapSheetAnal.analState))) + .from(mapSheetAnal) + .leftJoin(tmm) + .on(mapSheetAnal.modelUid.eq(tmm.id)) + .leftJoin(tmv) + .on(tmv.modelUid.eq(tmm.id).and(tmv.id.eq(latestVerUidSub))) + .where(mapSheetAnal.id.eq(id)) + .fetchOne()); return content; } /** * 분석결과 상세 대시보드 조회 + * * @param id * @return */ @Override public List getInferenceResultDashboard(Long id) { return queryFactory - .select(mapSheetAnalSttc) - .from(mapSheetAnalSttc) - .where(mapSheetAnalSttc.dataUid.eq(id)) - .fetch(); + .select(mapSheetAnalSttc) + .from(mapSheetAnalSttc) + .where(mapSheetAnalSttc.dataUid.eq(id)) + .fetch(); } /** * 분석결과 상세 목록 + * * @param searchGeoReq * @return */ @@ -160,45 +158,47 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC BooleanBuilder builder = new BooleanBuilder(); // 기준년도 분류 - if(searchGeoReq.getTargetClass() != null && !searchGeoReq.getTargetClass().equals("")){ + if (searchGeoReq.getTargetClass() != null && !searchGeoReq.getTargetClass().equals("")) { builder.and(mapSheetAnalDataGeom.classAfterCd.eq(searchGeoReq.getTargetClass())); - } // 비교년도 분류 - if(searchGeoReq.getCompareClass() != null && !searchGeoReq.getCompareClass().equals("")){ + if (searchGeoReq.getCompareClass() != null && !searchGeoReq.getCompareClass().equals("")) { builder.and(mapSheetAnalDataGeom.classBeforeCd.eq(searchGeoReq.getCompareClass())); } // 분석도엽 - if(searchGeoReq.getMapSheetNum() != null && !searchGeoReq.getMapSheetNum().isEmpty()){ + if (searchGeoReq.getMapSheetNum() != null && !searchGeoReq.getMapSheetNum().isEmpty()) { List mapSheetNum = searchGeoReq.getMapSheetNum(); builder.and(mapSheetAnalDataGeom.mapSheetNum.in(mapSheetNum)); } - List content = queryFactory - .select(Projections.constructor(InferenceResultDto.Geom.class, - mapSheetAnalDataGeom.compareYyyy, - mapSheetAnalDataGeom.targetYyyy, - mapSheetAnalDataGeom.classBeforeCd, - Expressions.stringTemplate("fn_code_name({0}, {1})", "0000", mapSheetAnalDataGeom.classBeforeCd), - mapSheetAnalDataGeom.classBeforeProb, - mapSheetAnalDataGeom.classAfterCd, - Expressions.stringTemplate("fn_code_name({0}, {1})", "0000", mapSheetAnalDataGeom.classAfterCd), - mapSheetAnalDataGeom.classAfterProb, - mapSheetAnalDataGeom.mapSheetNum)) - .from(mapSheetAnalDataGeom) - .where(builder) - .fetch() - ; + List content = + queryFactory + .select( + Projections.constructor( + InferenceResultDto.Geom.class, + mapSheetAnalDataGeom.compareYyyy, + mapSheetAnalDataGeom.targetYyyy, + mapSheetAnalDataGeom.classBeforeCd, + Expressions.stringTemplate( + "fn_code_name({0}, {1})", "0000", mapSheetAnalDataGeom.classBeforeCd), + mapSheetAnalDataGeom.classBeforeProb, + mapSheetAnalDataGeom.classAfterCd, + Expressions.stringTemplate( + "fn_code_name({0}, {1})", "0000", mapSheetAnalDataGeom.classAfterCd), + mapSheetAnalDataGeom.classAfterProb, + mapSheetAnalDataGeom.mapSheetNum)) + .from(mapSheetAnalDataGeom) + .where(builder) + .fetch(); - long total = queryFactory - .select(mapSheetAnalDataGeom.id) - .from(mapSheetAnalDataGeom) - .where( - builder - ) - .fetchCount(); + long total = + queryFactory + .select(mapSheetAnalDataGeom.id) + .from(mapSheetAnalDataGeom) + .where(builder) + .fetchCount(); return new PageImpl<>(content, pageable, total); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/MapSheetLearnDataGeomRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/MapSheetLearnDataGeomRepository.java index 825665fd..fb654ded 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/MapSheetLearnDataGeomRepository.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/MapSheetLearnDataGeomRepository.java @@ -1,36 +1,27 @@ package com.kamco.cd.kamcoback.postgres.repository; import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataGeomEntity; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import java.util.List; - @Repository -public interface MapSheetLearnDataGeomRepository extends JpaRepository { - - /** - * 데이터 UID로 지오메트리 정보 조회 - */ +public interface MapSheetLearnDataGeomRepository + extends JpaRepository { + + /** 데이터 UID로 지오메트리 정보 조회 */ List findByDataUid(Long dataUid); - - /** - * 도엽 번호로 지오메트리 정보 조회 - */ + + /** 도엽 번호로 지오메트리 정보 조회 */ List findByMapSheetNum(Long mapSheetNum); - - /** - * 연도 범위로 지오메트리 정보 조회 - */ - List findByBeforeYyyyAndAfterYyyy(Integer beforeYyyy, Integer afterYyyy); - - /** - * 지오메트리 타입별 조회 - */ + + /** 연도 범위로 지오메트리 정보 조회 */ + List findByBeforeYyyyAndAfterYyyy( + Integer beforeYyyy, Integer afterYyyy); + + /** 지오메트리 타입별 조회 */ List findByGeoType(String geoType); - - /** - * 데이터 UID로 기존 지오메트리 데이터 삭제 (재생성 전에 사용) - */ + + /** 데이터 UID로 기존 지오메트리 데이터 삭제 (재생성 전에 사용) */ void deleteByDataUid(Long dataUid); -} \ No newline at end of file +} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/MapSheetLearnDataRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/MapSheetLearnDataRepository.java index 3dda40a7..5888b38e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/MapSheetLearnDataRepository.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/MapSheetLearnDataRepository.java @@ -1,47 +1,32 @@ package com.kamco.cd.kamcoback.postgres.repository; import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataEntity; +import java.util.List; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import java.util.List; -import java.util.Optional; - @Repository public interface MapSheetLearnDataRepository extends JpaRepository { - - /** - * 데이터 이름으로 조회 - */ + + /** 데이터 이름으로 조회 */ Optional findByDataName(String dataName); - - /** - * 데이터 경로로 조회 - */ + + /** 데이터 경로로 조회 */ Optional findByDataPath(String dataPath); - - /** - * 처리 상태별 조회 - */ + + /** 처리 상태별 조회 */ List findByDataState(String dataState); - - /** - * 데이터 타입별 조회 - */ + + /** 데이터 타입별 조회 */ List findByDataType(String dataType); - - /** - * 분석 상태별 조회 - */ + + /** 분석 상태별 조회 */ List findByAnalState(String analState); - - /** - * 분석 상태별 개수 조회 - */ + + /** 분석 상태별 개수 조회 */ long countByAnalState(String analState); - - /** - * 처리되지 않은 데이터 조회 (data_state가 'PENDING' 또는 null인 것들) - */ + + /** 처리되지 않은 데이터 조회 (data_state가 'PENDING' 또는 null인 것들) */ List findByDataStateIsNullOrDataState(String dataState); -} \ No newline at end of file +} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepository.java index 32ef1f20..3a7ba214 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepository.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepository.java @@ -3,4 +3,5 @@ package com.kamco.cd.kamcoback.postgres.repository.changedetection; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; import org.springframework.data.jpa.repository.JpaRepository; -public interface ChangeDetectionRepository extends JpaRepository, ChangeDetectionRepositoryCustom {} +public interface ChangeDetectionRepository + extends JpaRepository, ChangeDetectionRepositoryCustom {} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryCustom.java index dedb2181..2044ab48 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryCustom.java @@ -1,9 +1,6 @@ package com.kamco.cd.kamcoback.postgres.repository.changedetection; -import com.kamco.cd.kamcoback.config.api.ApiResponseDto; - public interface ChangeDetectionRepositoryCustom { String getPolygonToPoint(); - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java index 221b5aec..481e6379 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/changedetection/ChangeDetectionRepositoryImpl.java @@ -1,15 +1,14 @@ package com.kamco.cd.kamcoback.postgres.repository.changedetection; -import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; -import com.querydsl.jpa.impl.JPAQueryFactory; -import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; - -import java.util.List; - import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataGeomEntity.mapSheetAnalDataGeomEntity; +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; +import com.querydsl.jpa.impl.JPAQueryFactory; +import java.util.List; +import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; + public class ChangeDetectionRepositoryImpl extends QuerydslRepositorySupport - implements ChangeDetectionRepositoryCustom { + implements ChangeDetectionRepositoryCustom { private final JPAQueryFactory queryFactory; @@ -26,8 +25,8 @@ public class ChangeDetectionRepositoryImpl extends QuerydslRepositorySupport public List findAll() { return queryFactory - .selectFrom(mapSheetAnalDataGeomEntity) - .orderBy(mapSheetAnalDataGeomEntity.id.desc()) - .fetch(); + .selectFrom(mapSheetAnalDataGeomEntity) + .orderBy(mapSheetAnalDataGeomEntity.id.desc()) + .fetch(); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/code/CommonCodeRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/code/CommonCodeRepositoryImpl.java index 5bb6594a..ad0b84c5 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/code/CommonCodeRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/code/CommonCodeRepositoryImpl.java @@ -88,13 +88,13 @@ public class CommonCodeRepositoryImpl extends QuerydslRepositorySupport QCommonCodeEntity parent = QCommonCodeEntity.commonCodeEntity; QCommonCodeEntity child = new QCommonCodeEntity("child"); - String result = queryFactory - .select(child.name) - .from(child) - .join(child.parent, parent) - .where(parent.code.eq(parentCodeCd) - .and(child.code.eq(childCodeCd))) - .fetchFirst(); // 단일 결과만 + String result = + queryFactory + .select(child.name) + .from(child) + .join(child.parent, parent) + .where(parent.code.eq(parentCodeCd).and(child.code.eq(childCodeCd))) + .fetchFirst(); // 단일 결과만 return Optional.ofNullable(result); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/log/AuditLogRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/log/AuditLogRepositoryCustom.java index f8c65c95..037e2789 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/log/AuditLogRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/log/AuditLogRepositoryCustom.java @@ -18,8 +18,7 @@ public interface AuditLogRepositoryCustom { Page findLogByDailyResult( AuditLogDto.searchReq searchReq, LocalDate logDate); - Page findLogByMenuResult( - AuditLogDto.searchReq searchReq, String menuId); + Page findLogByMenuResult(AuditLogDto.searchReq searchReq, String menuId); Page findLogByAccountResult( AuditLogDto.searchReq searchReq, Long accountId); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/log/AuditLogRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/log/AuditLogRepositoryImpl.java index 09d18b9c..d7ce97d0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/log/AuditLogRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/log/AuditLogRepositoryImpl.java @@ -39,7 +39,7 @@ public class AuditLogRepositoryImpl extends QuerydslRepositorySupport public Page findLogByDaily( AuditLogDto.searchReq searchReq, LocalDate startDate, LocalDate endDate) { StringExpression groupDateTime = - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", auditLogEntity.createdDate); + Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", auditLogEntity.createdDate); Pageable pageable = searchReq.toPageable(); List foundContent = @@ -52,9 +52,7 @@ public class AuditLogRepositoryImpl extends QuerydslRepositorySupport printCount().as("printCount"), downloadCount().as("downloadCount"), auditLogEntity.count().as("totalCount"), - groupDateTime.as("baseDate") - ) - ) + groupDateTime.as("baseDate"))) .from(auditLogEntity) .where(eventEndedAtBetween(startDate, endDate)) .groupBy(groupDateTime) @@ -242,7 +240,9 @@ public class AuditLogRepositoryImpl extends QuerydslRepositorySupport Projections.constructor( AuditLogDto.MenuDetail.class, auditLogEntity.id.as("logId"), - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", auditLogEntity.createdDate).as("logDateTime"), //?? + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", auditLogEntity.createdDate) + .as("logDateTime"), // ?? userEntity.userNm.as("userName"), userEntity.userId.as("loginId"), auditLogEntity.eventType.as("eventType"), @@ -307,7 +307,9 @@ public class AuditLogRepositoryImpl extends QuerydslRepositorySupport Projections.constructor( AuditLogDto.UserDetail.class, auditLogEntity.id.as("logId"), - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", auditLogEntity.createdDate).as("logDateTime"), + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", auditLogEntity.createdDate) + .as("logDateTime"), menuEntity.menuNm.as("menuName"), auditLogEntity.eventType.as("eventType"), Projections.constructor( @@ -392,7 +394,7 @@ public class AuditLogRepositoryImpl extends QuerydslRepositorySupport private BooleanExpression eventEndedAtEqDate(LocalDate logDate) { StringExpression eventEndedDate = - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", auditLogEntity.createdDate); + Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", auditLogEntity.createdDate); LocalDateTime comparisonDate = logDate.atStartOfDay(); return eventEndedDate.eq(comparisonDate.toString()); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepository.java index 7c614da4..cef29ae0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepository.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepository.java @@ -3,4 +3,5 @@ package com.kamco.cd.kamcoback.postgres.repository.model; import com.kamco.cd.kamcoback.postgres.entity.ModelMngEntity; import org.springframework.data.jpa.repository.JpaRepository; -public interface ModelMngRepository extends JpaRepository, ModelMngRepositoryCustom {} +public interface ModelMngRepository + extends JpaRepository, ModelMngRepositoryCustom {} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java index f6c957a6..cb5f5703 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java @@ -2,11 +2,10 @@ package com.kamco.cd.kamcoback.postgres.repository.model; import com.kamco.cd.kamcoback.model.dto.ModelMngDto; import com.kamco.cd.kamcoback.postgres.entity.ModelMngEntity; -import org.springframework.data.domain.Page; - import java.time.LocalDate; import java.util.List; import java.util.Optional; +import org.springframework.data.domain.Page; public interface ModelMngRepositoryCustom { @@ -14,5 +13,6 @@ public interface ModelMngRepositoryCustom { Optional getFinalModelInfo(); - Page getRegHistoryList(ModelMngDto.searchReq searchReq, LocalDate startDate, LocalDate endDate, String searchVal); + Page getRegHistoryList( + ModelMngDto.searchReq searchReq, LocalDate startDate, LocalDate endDate, String searchVal); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java index 9b7bf8a4..80f69151 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java @@ -1,5 +1,9 @@ package com.kamco.cd.kamcoback.postgres.repository.model; +import static com.kamco.cd.kamcoback.postgres.entity.QModelDeployHstEntity.modelDeployHstEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QModelMngEntity.modelMngEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QModelVerEntity.modelVerEntity; + import com.kamco.cd.kamcoback.model.dto.ModelMngDto; import com.kamco.cd.kamcoback.postgres.QuerydslOrderUtil; import com.kamco.cd.kamcoback.postgres.entity.ModelMngEntity; @@ -10,24 +14,19 @@ import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.StringExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import io.micrometer.common.util.StringUtils; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; - import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.util.List; import java.util.Objects; import java.util.Optional; - -import static com.kamco.cd.kamcoback.postgres.entity.QModelDeployHstEntity.modelDeployHstEntity; -import static com.kamco.cd.kamcoback.postgres.entity.QModelMngEntity.modelMngEntity; -import static com.kamco.cd.kamcoback.postgres.entity.QModelVerEntity.modelVerEntity; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; public class ModelMngRepositoryImpl extends QuerydslRepositorySupport - implements ModelMngRepositoryCustom { + implements ModelMngRepositoryCustom { private final JPAQueryFactory queryFactory; private final StringExpression NULL_STRING = Expressions.stringTemplate("cast(null as text)"); @@ -39,85 +38,81 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport @Override public List findModelMngAll() { - return queryFactory - .selectFrom(modelMngEntity) - .orderBy(modelMngEntity.id.desc()) - .fetch(); + return queryFactory.selectFrom(modelMngEntity).orderBy(modelMngEntity.id.desc()).fetch(); } @Override - public Optional getFinalModelInfo(){ + public Optional getFinalModelInfo() { return queryFactory .select( - Projections.constructor( - ModelMngDto.FinalModelDto.class, - modelMngEntity.id.as("modelUid"), - modelMngEntity.modelNm, - modelMngEntity.modelCate, - modelVerEntity.id.as("modelVerUid"), - modelVerEntity.modelVer, - modelVerEntity.usedState, - modelVerEntity.modelState, - modelVerEntity.qualityProb, - modelVerEntity.deployState, - modelVerEntity.modelPath - ) - ) + Projections.constructor( + ModelMngDto.FinalModelDto.class, + modelMngEntity.id.as("modelUid"), + modelMngEntity.modelNm, + modelMngEntity.modelCate, + modelVerEntity.id.as("modelVerUid"), + modelVerEntity.modelVer, + modelVerEntity.usedState, + modelVerEntity.modelState, + modelVerEntity.qualityProb, + modelVerEntity.deployState, + modelVerEntity.modelPath)) .from(modelMngEntity) .innerJoin(modelVerEntity) .on(modelMngEntity.id.eq(modelVerEntity.modelUid)) - .where(modelVerEntity.usedState.eq("USED")) //USED 인 것 중에 - .orderBy(modelVerEntity.modelVer.desc()) //Version 높은 것 기준 + .where(modelVerEntity.usedState.eq("USED")) // USED 인 것 중에 + .orderBy(modelVerEntity.modelVer.desc()) // Version 높은 것 기준 .stream() .findFirst(); } @Override - public Page getRegHistoryList(ModelMngDto.searchReq searchReq, LocalDate startDate, LocalDate endDate, String searchVal) { + public Page getRegHistoryList( + ModelMngDto.searchReq searchReq, LocalDate startDate, LocalDate endDate, String searchVal) { Pageable pageable = searchReq.toPageable(); - List foundContent = - queryFactory + List foundContent = + queryFactory .select( - Projections.constructor( - ModelMngDto.ModelRegHistory.class, - modelMngEntity.modelNm, - modelMngEntity.modelCate, - modelVerEntity.modelVer, - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", modelVerEntity.createdDate).as("createdDttm"), - modelVerEntity.usedState, - modelVerEntity.deployState, - Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", modelDeployHstEntity.deployDttm).as("deployDttm") - ) - ) + Projections.constructor( + ModelMngDto.ModelRegHistory.class, + modelMngEntity.modelNm, + modelMngEntity.modelCate, + modelVerEntity.modelVer, + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", modelVerEntity.createdDate) + .as("createdDttm"), + modelVerEntity.usedState, + modelVerEntity.deployState, + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", modelDeployHstEntity.deployDttm) + .as("deployDttm"))) .from(modelMngEntity) .innerJoin(modelVerEntity) .on(modelMngEntity.id.eq(modelVerEntity.modelUid)) .leftJoin(modelDeployHstEntity) .on( - modelVerEntity.id.eq(modelDeployHstEntity.modelVerUid) - .and(modelDeployHstEntity.serverId.eq(1L)) //1건만 조회해야 하기에 1번 서버만 조회하기 - ) - .where( - eventEndedAtBetween(startDate, endDate), - searchModelVerLike(searchVal) - ) + modelVerEntity + .id + .eq(modelDeployHstEntity.modelVerUid) + .and(modelDeployHstEntity.serverId.eq(1L)) // 1건만 조회해야 하기에 1번 서버만 조회하기 + ) + .where(eventEndedAtBetween(startDate, endDate), searchModelVerLike(searchVal)) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) - .orderBy(QuerydslOrderUtil.getOrderSpecifiers(pageable, ModelVerEntity.class, "modelVerEntity")) + .orderBy( + QuerydslOrderUtil.getOrderSpecifiers( + pageable, ModelVerEntity.class, "modelVerEntity")) .fetch(); Long countQuery = - queryFactory - .select(modelVerEntity.id.count()) - .from(modelMngEntity) - .innerJoin(modelVerEntity) - .on(modelMngEntity.id.eq(modelVerEntity.modelUid)) - .where( - eventEndedAtBetween(startDate, endDate), - searchModelVerLike(searchVal) - ) - .fetchOne(); + queryFactory + .select(modelVerEntity.id.count()) + .from(modelMngEntity) + .innerJoin(modelVerEntity) + .on(modelMngEntity.id.eq(modelVerEntity.modelUid)) + .where(eventEndedAtBetween(startDate, endDate), searchModelVerLike(searchVal)) + .fetchOne(); return new PageImpl<>(foundContent, pageable, countQuery); } @@ -128,11 +123,13 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport } LocalDateTime startDateTime = startDate.atStartOfDay(); LocalDateTime endDateTime = endDate.plusDays(1).atStartOfDay(); - return modelMngEntity.createdDate.goe(ZonedDateTime.from(startDateTime)) - .and(modelMngEntity.modifiedDate.lt(ZonedDateTime.from(endDateTime))); + return modelMngEntity + .createdDate + .goe(ZonedDateTime.from(startDateTime)) + .and(modelMngEntity.modifiedDate.lt(ZonedDateTime.from(endDateTime))); } - private BooleanExpression searchModelVerLike(String searchVal){ + private BooleanExpression searchModelVerLike(String searchVal) { if (StringUtils.isBlank(searchVal)) { return null; } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepository.java index f78879af..90cb5758 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepository.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepository.java @@ -1,7 +1,7 @@ package com.kamco.cd.kamcoback.postgres.repository.model; -import com.kamco.cd.kamcoback.postgres.entity.ModelMngEntity; import com.kamco.cd.kamcoback.postgres.entity.ModelVerEntity; import org.springframework.data.jpa.repository.JpaRepository; -public interface ModelVerRepository extends JpaRepository, ModelVerRepositoryCustom {} +public interface ModelVerRepository + extends JpaRepository, ModelVerRepositoryCustom {} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepositoryCustom.java index b4472aa4..a109ddd0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepositoryCustom.java @@ -1,10 +1,6 @@ package com.kamco.cd.kamcoback.postgres.repository.model; -import com.kamco.cd.kamcoback.model.dto.ModelMngDto; -import com.kamco.cd.kamcoback.postgres.entity.ModelMngEntity; import com.kamco.cd.kamcoback.postgres.entity.ModelVerEntity; - -import java.util.List; import java.util.Optional; public interface ModelVerRepositoryCustom { diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepositoryImpl.java index 73c5f4af..70054d53 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelVerRepositoryImpl.java @@ -1,18 +1,17 @@ package com.kamco.cd.kamcoback.postgres.repository.model; +import static com.kamco.cd.kamcoback.postgres.entity.QModelVerEntity.modelVerEntity; + import com.kamco.cd.kamcoback.postgres.entity.ModelMngEntity; import com.kamco.cd.kamcoback.postgres.entity.ModelVerEntity; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.StringExpression; import com.querydsl.jpa.impl.JPAQueryFactory; +import java.util.Optional; import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; -import java.util.Optional; - -import static com.kamco.cd.kamcoback.postgres.entity.QModelVerEntity.modelVerEntity; - public class ModelVerRepositoryImpl extends QuerydslRepositorySupport - implements ModelVerRepositoryCustom { + implements ModelVerRepositoryCustom { private final JPAQueryFactory queryFactory; private final StringExpression NULL_STRING = Expressions.stringTemplate("cast(null as text)"); @@ -24,10 +23,10 @@ public class ModelVerRepositoryImpl extends QuerydslRepositorySupport @Override public Optional findModelVerById(Long id) { - return Optional.ofNullable(queryFactory - .selectFrom(modelVerEntity) - .where(modelVerEntity.id.eq(id)) //model_ver_uid - .fetchOne() - ); + return Optional.ofNullable( + queryFactory + .selectFrom(modelVerEntity) + .where(modelVerEntity.id.eq(id)) // model_ver_uid + .fetchOne()); } }