init
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package com.kamco.cd.kamcoback;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
public class KamcoBackApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(KamcoBackApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.kamco.cd.kamcoback.config;
|
||||
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class QuerydslConfig {
|
||||
|
||||
@PersistenceContext private EntityManager entityManager;
|
||||
|
||||
@Bean
|
||||
public JPAQueryFactory jpaQueryFactory() {
|
||||
return new JPAQueryFactory(entityManager);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.kamco.cd.kamcoback.controller;
|
||||
|
||||
import com.kamco.cd.kamcoback.dto.ApiResponseDto;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "스캐쥴러 API", description = "스캐쥴러 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping({"/api/job"})
|
||||
public class MapSheetMngFileJobApiController {
|
||||
|
||||
private final MapSheetMngFileJobController mapSheetMngFileJobController;
|
||||
|
||||
@Operation(summary = "영상관리 파일 싱크 스캐쥴러 Start/Stop", description = "영상관리 파일 싱크 스캐쥴러 Start/Stop API")
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "조회 성공",
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = String.class))),
|
||||
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
|
||||
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||
})
|
||||
@PutMapping("/mng-sync-job")
|
||||
public ApiResponseDto<String> mngSyncOnOff(
|
||||
@RequestParam boolean jobStart, @RequestParam int pageSize) {
|
||||
|
||||
mapSheetMngFileJobController.setSchedulerEnabled(jobStart);
|
||||
mapSheetMngFileJobController.setMngSyncPageSize(pageSize);
|
||||
|
||||
return ApiResponseDto.createOK("OK");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.kamco.cd.kamcoback.controller;
|
||||
|
||||
import com.kamco.cd.kamcoback.service.MapSheetMngFileJobService;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MapSheetMngFileJobController {
|
||||
|
||||
private final MapSheetMngFileJobService mapSheetMngFileJobService;
|
||||
|
||||
// 현재 상태 확인용 Getter
|
||||
@Getter private boolean isSchedulerEnabled = true;
|
||||
@Getter private boolean isFileSyncSchedulerEnabled = false;
|
||||
@Getter private int mngSyncPageSize = 20;
|
||||
|
||||
// 파일싱크 진행여부 확인하기
|
||||
@Scheduled(fixedDelay = 1000 * 10)
|
||||
public void checkMngFileSync() {
|
||||
if (!isSchedulerEnabled) return;
|
||||
|
||||
Integer mng = 0;
|
||||
// isFileSyncSchedulerEnabled = false;
|
||||
if (mapSheetMngFileJobService.checkMngFileSync() != null) {
|
||||
mng = mapSheetMngFileJobService.checkMngFileSync();
|
||||
this.isFileSyncSchedulerEnabled = true;
|
||||
System.out.println(
|
||||
"MngFileSyncJob ON --> mngYyyy : "
|
||||
+ mng
|
||||
+ ", currentTime : "
|
||||
+ System.currentTimeMillis());
|
||||
} else {
|
||||
this.isFileSyncSchedulerEnabled = false;
|
||||
System.out.println(
|
||||
"MngFileSyncJob OFF --> mngYyyy : "
|
||||
+ mng
|
||||
+ ", currentTime : "
|
||||
+ System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 10)
|
||||
public void mngFileSyncJob00() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 00 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(0, mngSyncPageSize);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 5)
|
||||
public void mngFileSyncJob01() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 01 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(1, mngSyncPageSize);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 5)
|
||||
public void mngFileSyncJob02() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 02 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(2, mngSyncPageSize);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 5)
|
||||
public void mngFileSyncJob03() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 03 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(3, mngSyncPageSize);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 5)
|
||||
public void mngFileSyncJob04() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 04 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(4, mngSyncPageSize);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 5)
|
||||
public void mngFileSyncJob05() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 05 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(5, mngSyncPageSize);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 5)
|
||||
public void mngFileSyncJob06() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 06 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(6, mngSyncPageSize);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 5)
|
||||
public void mngFileSyncJob07() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 07 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(7, mngSyncPageSize);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 5)
|
||||
public void mngFileSyncJob08() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 08 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(8, mngSyncPageSize);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 1000 * 5)
|
||||
public void mngFileSyncJob09() {
|
||||
if (!isSchedulerEnabled || !isFileSyncSchedulerEnabled) return;
|
||||
|
||||
System.out.println("mngFileSyncJob 09 Processing currentTime : " + System.currentTimeMillis());
|
||||
mapSheetMngFileJobService.checkMapSheetFileProcess(9, mngSyncPageSize);
|
||||
}
|
||||
|
||||
// 3. 외부에서 플래그를 변경할 수 있는 Setter 메서드
|
||||
public void setSchedulerEnabled(boolean enabled) {
|
||||
this.isSchedulerEnabled = enabled;
|
||||
this.isFileSyncSchedulerEnabled = false;
|
||||
System.out.println("스케줄러 동작 상태 변경됨: " + (enabled ? "ON" : "OFF"));
|
||||
}
|
||||
|
||||
public void setMngSyncPageSize(int pageSize) {
|
||||
this.mngSyncPageSize = pageSize;
|
||||
System.out.println("스케줄러 처리 개수 변경됨: " + pageSize);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
package com.kamco.cd.kamcoback.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.kamco.cd.kamcoback.inferface.EnumType;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public class ApiResponseDto<T> {
|
||||
|
||||
private T data;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Error error;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private T errorData;
|
||||
|
||||
@JsonIgnore private HttpStatus httpStatus;
|
||||
|
||||
@JsonIgnore private Long errorLogUid;
|
||||
|
||||
public ApiResponseDto(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
private ApiResponseDto(T data, HttpStatus httpStatus) {
|
||||
this.data = data;
|
||||
this.httpStatus = httpStatus;
|
||||
}
|
||||
|
||||
public ApiResponseDto(ApiResponseCode code) {
|
||||
this.error = new Error(code.getId(), code.getMessage());
|
||||
}
|
||||
|
||||
public ApiResponseDto(ApiResponseCode code, String message) {
|
||||
this.error = new Error(code.getId(), message);
|
||||
}
|
||||
|
||||
public ApiResponseDto(ApiResponseCode code, String message, HttpStatus httpStatus) {
|
||||
this.error = new Error(code.getId(), message);
|
||||
this.httpStatus = httpStatus;
|
||||
}
|
||||
|
||||
public ApiResponseDto(
|
||||
ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) {
|
||||
this.error = new Error(code.getId(), message);
|
||||
this.httpStatus = httpStatus;
|
||||
this.errorLogUid = errorLogUid;
|
||||
}
|
||||
|
||||
public ApiResponseDto(ApiResponseCode code, String message, T errorData) {
|
||||
this.error = new Error(code.getId(), message);
|
||||
this.errorData = errorData;
|
||||
}
|
||||
|
||||
// HTTP 상태 코드가 내장된 ApiResponseDto 반환 메서드들
|
||||
public static <T> ApiResponseDto<T> createOK(T data) {
|
||||
return new ApiResponseDto<>(data, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
public static <T> ApiResponseDto<T> ok(T data) {
|
||||
return new ApiResponseDto<>(data, HttpStatus.OK);
|
||||
}
|
||||
|
||||
public static <T> ApiResponseDto<ResponseObj> okObject(ResponseObj data) {
|
||||
if (data.getCode().equals(ApiResponseCode.OK)) {
|
||||
return new ApiResponseDto<>(data, HttpStatus.NO_CONTENT);
|
||||
} else {
|
||||
return new ApiResponseDto<>(data.getCode(), data.getMessage(), HttpStatus.CONFLICT);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> ApiResponseDto<T> deleteOk(T data) {
|
||||
return new ApiResponseDto<>(data, HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
public static ApiResponseDto<String> createException(ApiResponseCode code) {
|
||||
return new ApiResponseDto<>(code);
|
||||
}
|
||||
|
||||
public static ApiResponseDto<String> createException(ApiResponseCode code, String message) {
|
||||
return new ApiResponseDto<>(code, message);
|
||||
}
|
||||
|
||||
public static ApiResponseDto<String> createException(
|
||||
ApiResponseCode code, String message, HttpStatus httpStatus) {
|
||||
return new ApiResponseDto<>(code, message, httpStatus);
|
||||
}
|
||||
|
||||
public static ApiResponseDto<String> createException(
|
||||
ApiResponseCode code, String message, HttpStatus httpStatus, Long errorLogUid) {
|
||||
return new ApiResponseDto<>(code, message, httpStatus, errorLogUid);
|
||||
}
|
||||
|
||||
public static <T> ApiResponseDto<T> createException(
|
||||
ApiResponseCode code, String message, T data) {
|
||||
return new ApiResponseDto<>(code, message, data);
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class Error {
|
||||
|
||||
private final String code;
|
||||
private final String message;
|
||||
|
||||
public Error(String code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
/** Error가 아닌 Business상 성공이거나 실패인 경우, 메세지 함께 전달하기 위한 object */
|
||||
@Getter
|
||||
public static class ResponseObj {
|
||||
|
||||
private final ApiResponseCode code;
|
||||
private final String message;
|
||||
|
||||
public ResponseObj(ApiResponseCode code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ApiResponseCode implements EnumType {
|
||||
|
||||
// @formatter:off
|
||||
OK("요청이 성공하였습니다."),
|
||||
BAD_REQUEST("요청 파라미터가 잘못되었습니다."),
|
||||
BAD_GATEWAY("네트워크 상태가 불안정합니다."),
|
||||
ALREADY_EXIST_MALL("이미 등록된 쇼핑센터입니다."),
|
||||
NOT_FOUND_MAP("지도를 찾을 수 없습니다."),
|
||||
UNAUTHORIZED("권한이 없습니다."),
|
||||
CONFLICT("이미 등록된 컨텐츠입니다."),
|
||||
NOT_FOUND("Resource를 찾을 수 없습니다."),
|
||||
NOT_FOUND_DATA("데이터를 찾을 수 없습니다."),
|
||||
NOT_FOUND_WEATHER_DATA("날씨 데이터를 찾을 수 없습니다."),
|
||||
FAIL_SEND_MESSAGE("메시지를 전송하지 못했습니다."),
|
||||
TOO_MANY_CONNECTED_MACHINES("연결된 기기가 너무 많습니다."),
|
||||
UNAUTHENTICATED("인증에 실패하였습니다."),
|
||||
INVALID_TOKEN("잘못된 토큰입니다."),
|
||||
EXPIRED_TOKEN("만료된 토큰입니다."),
|
||||
INTERNAL_SERVER_ERROR("서버에 문제가 발생 하였습니다."),
|
||||
FORBIDDEN("권한을 확인해주세요."),
|
||||
INVALID_PASSWORD("잘못된 비밀번호 입니다."),
|
||||
NOT_FOUND_CAR_IN("입차정보가 없습니다."),
|
||||
WRONG_STATUS("잘못된 상태입니다."),
|
||||
FAIL_VERIFICATION("인증에 실패하였습니다."),
|
||||
INVALID_EMAIL("잘못된 형식의 이메일입니다."),
|
||||
REQUIRED_EMAIL("이메일은 필수 항목입니다."),
|
||||
WRONG_PASSWORD("잘못된 패스워드입니다."),
|
||||
DUPLICATE_EMAIL("이미 가입된 이메일입니다."),
|
||||
DUPLICATE_DATA("이미 등록되어 있습니다."),
|
||||
DATA_INTEGRITY_ERROR("데이터 무결성이 위반되어 요청을 처리할수 없습니다."),
|
||||
FOREIGN_KEY_ERROR("참조 중인 데이터가 있어 삭제할 수 없습니다."),
|
||||
DUPLICATE_EMPLOYEEID("이미 가입된 사번입니다."),
|
||||
NOT_FOUND_USER_FOR_EMAIL("이메일로 유저를 찾을 수 없습니다."),
|
||||
NOT_FOUND_USER("사용자를 찾을 수 없습니다."),
|
||||
UNPROCESSABLE_ENTITY("이 데이터는 삭제할 수 없습니다."),
|
||||
LOGIN_ID_NOT_FOUND("아이디를 잘못 입력하셨습니다."),
|
||||
LOGIN_PASSWORD_MISMATCH("비밀번호를 잘못 입력하셨습니다."),
|
||||
LOGIN_PASSWORD_EXCEEDED("비밀번호 오류 횟수를 초과하여 이용하실 수 없습니다.\n로그인 오류에 대해 관리자에게 문의하시기 바랍니다."),
|
||||
INACTIVE_ID("사용할 수 없는 계정입니다."),
|
||||
INVALID_EMAIL_TOKEN(
|
||||
"You can only reset your password within 24 hours from when the email was sent.\n"
|
||||
+ "To reset your password again, please submit a new request through \"Forgot"
|
||||
+ " Password.\""),
|
||||
PAYLOAD_TOO_LARGE("업로드 용량 제한을 초과했습니다."),
|
||||
NOT_FOUND_TARGET_YEAR("기준년도 도엽을 찾을 수 없습니다."),
|
||||
NOT_FOUND_COMPARE_YEAR("비교년도 도엽을 찾을 수 없습니다."),
|
||||
FAIL_SAVE_MAP_SHEET("도엽 저장 중 오류가 발생했습니다."),
|
||||
FAIL_CREATE_MAP_SHEET_FILE("도엽 설정파일 생성 중 오류가 발생했습니다."),
|
||||
;
|
||||
// @formatter:on
|
||||
private final String message;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public static ApiResponseCode getCode(String name) {
|
||||
return ApiResponseCode.valueOf(name.toUpperCase());
|
||||
}
|
||||
|
||||
public static String getMessage(String name) {
|
||||
return ApiResponseCode.valueOf(name.toUpperCase()).getText();
|
||||
}
|
||||
|
||||
public static ApiResponseCode from(String codeName, HttpStatus status) {
|
||||
|
||||
if (codeName != null && !codeName.isBlank()) {
|
||||
try {
|
||||
return ApiResponseCode.valueOf(codeName.toUpperCase());
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
// fallback
|
||||
}
|
||||
}
|
||||
|
||||
if (status != null) {
|
||||
try {
|
||||
return ApiResponseCode.valueOf(status.name());
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
// fallback
|
||||
}
|
||||
}
|
||||
|
||||
return INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
159
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/dto/FileDto.java
Executable file
159
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/dto/FileDto.java
Executable file
@@ -0,0 +1,159 @@
|
||||
package com.kamco.cd.kamcoback.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
public class FileDto {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SrchFoldersDto {
|
||||
@Schema(description = "디렉토리경로(ROOT:/app/original-images)", example = "")
|
||||
@NotNull
|
||||
private String dirPath;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SrchFilesDto {
|
||||
@Schema(description = "디렉토리경로", example = "D:\\kamco\\2022\\캠코_2021_2022_34602060_D1")
|
||||
@NotNull
|
||||
private String dirPath;
|
||||
|
||||
@Schema(description = "전체(*), cpg,dbf,geojson등", example = "*")
|
||||
@NotNull
|
||||
private String extension;
|
||||
|
||||
@Schema(description = "전체(*), 3878687.tif", example = "*")
|
||||
@NotNull
|
||||
private String fileNm;
|
||||
|
||||
@Schema(description = "파일명(name), 최종수정일(date)", example = "name")
|
||||
@NotNull
|
||||
private String sortType;
|
||||
|
||||
@Schema(description = "파일시작위치", example = "1")
|
||||
@NotNull
|
||||
private Integer startPos = 0;
|
||||
|
||||
@Schema(description = "파일종료위치", example = "100")
|
||||
@NotNull
|
||||
private Integer endPos = 100;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SrchFilesDepthDto extends SrchFilesDto {
|
||||
@Schema(description = "최대폴더Depth", example = "5")
|
||||
@NotNull
|
||||
private Integer maxDepth;
|
||||
}
|
||||
|
||||
@Schema(name = "FolderDto", description = "폴더 정보")
|
||||
@Getter
|
||||
public static class FolderDto {
|
||||
private final String folderNm;
|
||||
private final String parentFolderNm;
|
||||
private final String parentPath;
|
||||
private final String fullPath;
|
||||
private final int depth;
|
||||
private final long childCnt;
|
||||
private final String lastModified;
|
||||
private final Boolean isValid;
|
||||
|
||||
public FolderDto(
|
||||
String folderNm,
|
||||
String parentFolderNm,
|
||||
String parentPath,
|
||||
String fullPath,
|
||||
int depth,
|
||||
long childCnt,
|
||||
String lastModified,
|
||||
Boolean isValid) {
|
||||
this.folderNm = folderNm;
|
||||
this.parentFolderNm = parentFolderNm;
|
||||
this.parentPath = parentPath;
|
||||
this.fullPath = fullPath;
|
||||
this.depth = depth;
|
||||
this.childCnt = childCnt;
|
||||
this.lastModified = lastModified;
|
||||
this.isValid = isValid;
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "FoldersDto", description = "폴더목록 정보")
|
||||
@Getter
|
||||
public static class FoldersDto {
|
||||
private final String dirPath;
|
||||
private final int folderTotCnt;
|
||||
private final int folderErrTotCnt;
|
||||
private final List<FolderDto> folders;
|
||||
|
||||
public FoldersDto(
|
||||
String dirPath, int folderTotCnt, int folderErrTotCnt, List<FolderDto> folders) {
|
||||
|
||||
this.dirPath = dirPath;
|
||||
this.folderTotCnt = folderTotCnt;
|
||||
this.folderErrTotCnt = folderErrTotCnt;
|
||||
this.folders = folders;
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "File Basic", description = "파일 기본 정보")
|
||||
@Getter
|
||||
public static class Basic {
|
||||
|
||||
private final String fileNm;
|
||||
private final String parentFolderNm;
|
||||
private final String parentPath;
|
||||
private final String fullPath;
|
||||
private final String extension;
|
||||
private final long fileSize;
|
||||
private final String lastModified;
|
||||
|
||||
public Basic(
|
||||
String fileNm,
|
||||
String parentFolderNm,
|
||||
String parentPath,
|
||||
String fullPath,
|
||||
String extension,
|
||||
long fileSize,
|
||||
String lastModified) {
|
||||
this.fileNm = fileNm;
|
||||
this.parentFolderNm = parentFolderNm;
|
||||
this.parentPath = parentPath;
|
||||
this.fullPath = fullPath;
|
||||
this.extension = extension;
|
||||
this.fileSize = fileSize;
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "FilesDto", description = "파일 목록 정보")
|
||||
@Getter
|
||||
public static class FilesDto {
|
||||
private final String dirPath;
|
||||
private final int fileTotCnt;
|
||||
private final long fileTotSize;
|
||||
private final List<Basic> files;
|
||||
|
||||
public FilesDto(String dirPath, int fileTotCnt, long fileTotSize, List<Basic> files) {
|
||||
|
||||
this.dirPath = dirPath;
|
||||
this.fileTotCnt = fileTotCnt;
|
||||
this.fileTotSize = fileTotSize;
|
||||
this.files = files;
|
||||
}
|
||||
}
|
||||
}
|
||||
467
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/dto/MapSheetDto.java
Executable file
467
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/dto/MapSheetDto.java
Executable file
@@ -0,0 +1,467 @@
|
||||
package com.kamco.cd.kamcoback.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.kamco.cd.kamcoback.enums.Enums;
|
||||
import com.kamco.cd.kamcoback.enums.MngStateType;
|
||||
import com.kamco.cd.kamcoback.enums.SyncStateType;
|
||||
import com.kamco.cd.kamcoback.inferface.EnumType;
|
||||
import com.kamco.cd.kamcoback.inferface.JsonFormatDttm;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
public class MapSheetDto {
|
||||
|
||||
@Schema(name = "MngSearchReq", description = "영상관리 검색 요청")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngSearchReq {
|
||||
|
||||
// 페이징 파라미터
|
||||
@Schema(description = "페이지 번호 (0부터 시작) ", example = "0")
|
||||
private int page = 0;
|
||||
|
||||
@Schema(description = "페이지 크기", example = "20")
|
||||
private int size = 20;
|
||||
|
||||
@Schema(description = "년도", example = "2025")
|
||||
private Integer mngYyyy;
|
||||
|
||||
public Pageable toPageable() {
|
||||
return PageRequest.of(page, size);
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "MngAddReq", description = "영상관리 생성 요청")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class AddReq {
|
||||
|
||||
@Schema(description = "관리년도", example = "2022")
|
||||
private int mngYyyy;
|
||||
|
||||
@Schema(description = "선택폴더경로", example = "D:\\app\\original-images\\2022")
|
||||
private String mngPath;
|
||||
|
||||
@JsonIgnore private Long createdUid;
|
||||
}
|
||||
|
||||
@Schema(name = "DeleteFileReq", description = "파일 삭제 요청")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class DeleteFileReq {
|
||||
|
||||
@Schema(description = "파일 경로", example = "/app/original-images/2024/00000001.tif")
|
||||
private String filePath;
|
||||
}
|
||||
|
||||
@Schema(name = "MngDto", description = "영상관리 검색 리턴")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngDto {
|
||||
|
||||
private int rowNum;
|
||||
private int mngYyyy;
|
||||
private String mngPath;
|
||||
private String mngState;
|
||||
private String syncState;
|
||||
private String syncDataCheckState;
|
||||
private Long syncTotCnt;
|
||||
private Long syncStateDoneCnt;
|
||||
private Long syncDataCheckDoneCnt;
|
||||
private Long syncNotPaireCnt;
|
||||
private Long syncNotPaireExecCnt;
|
||||
private Long syncDuplicateCnt;
|
||||
private Long syncDuplicateExecCnt;
|
||||
private Long syncFaultCnt;
|
||||
private Long syncFaultExecCnt;
|
||||
private Long syncNoFileCnt;
|
||||
private Long syncNoFileExecCnt;
|
||||
@JsonFormatDttm private ZonedDateTime rgstStrtDttm;
|
||||
@JsonFormatDttm private ZonedDateTime rgstEndDttm;
|
||||
|
||||
public String getSyncState() {
|
||||
|
||||
if (this.syncStateDoneCnt == 0) {
|
||||
return "NOTYET";
|
||||
} else if (this.syncStateDoneCnt < this.syncTotCnt) {
|
||||
return "PROCESSING";
|
||||
}
|
||||
|
||||
return "DONE";
|
||||
}
|
||||
|
||||
public String getDataCheckState() {
|
||||
|
||||
if (this.syncDataCheckDoneCnt == 0) {
|
||||
return "NOTYET";
|
||||
} else if (this.syncDataCheckDoneCnt < this.syncTotCnt) {
|
||||
return "PROCESSING";
|
||||
}
|
||||
|
||||
return "DONE";
|
||||
}
|
||||
|
||||
public double getSyncStateDoneRate() {
|
||||
if (this.syncTotCnt == null || this.syncTotCnt == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
return (double) this.syncStateDoneCnt / this.syncTotCnt * 100.0;
|
||||
}
|
||||
|
||||
public double getSyncDataCheckDoneRate() {
|
||||
if (this.syncTotCnt == null || this.syncTotCnt == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
return (double) this.syncDataCheckDoneCnt / this.syncTotCnt * 100.0;
|
||||
}
|
||||
|
||||
public long getSyncErrorTotCnt() {
|
||||
return this.syncNotPaireCnt + this.syncDuplicateCnt + this.syncFaultCnt;
|
||||
}
|
||||
|
||||
public long getSyncErrorExecTotCnt() {
|
||||
return this.syncNotPaireExecCnt + this.syncDuplicateExecCnt + this.syncFaultExecCnt;
|
||||
}
|
||||
|
||||
public String getMngState() {
|
||||
|
||||
String mngState = "DONE";
|
||||
|
||||
if (this.syncStateDoneCnt == 0) {
|
||||
mngState = "NOTYET";
|
||||
} else if (this.syncStateDoneCnt < this.syncTotCnt) {
|
||||
mngState = "PROCESSING";
|
||||
}
|
||||
|
||||
if ((this.syncNotPaireExecCnt + this.syncDuplicateExecCnt + this.syncFaultExecCnt) > 0) {
|
||||
mngState = "TAKINGERROR";
|
||||
}
|
||||
|
||||
return mngState;
|
||||
}
|
||||
|
||||
public String getMngStateName() {
|
||||
String enumId = this.getMngState();
|
||||
if (enumId == null || enumId.isEmpty()) {
|
||||
enumId = "NOTYET";
|
||||
}
|
||||
|
||||
MngStateType type = Enums.fromId(MngStateType.class, enumId);
|
||||
return type.getText();
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "ErrorSearchReq", description = "영상관리 오류데이터 검색 요청")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class ErrorSearchReq {
|
||||
|
||||
// 페이징 파라미터
|
||||
@Schema(description = "페이지 번호 (0부터 시작) ", example = "0")
|
||||
private int page = 0;
|
||||
|
||||
@Schema(description = "페이지 크기", example = "20")
|
||||
private int size = 20;
|
||||
|
||||
@Schema(description = "정렬", example = "id desc")
|
||||
private String sort;
|
||||
|
||||
@Schema(description = "오류종류(페어누락:NOTPAIR,중복파일:DUPLICATE,손상파일:FAULT)", example = "NOTPAIR")
|
||||
private String syncState;
|
||||
|
||||
@Schema(description = "처리유형(처리:DONE,미처리:NOTYET)", example = "DONE")
|
||||
private String syncCheckState;
|
||||
|
||||
@Schema(description = "검색어", example = "부산3959")
|
||||
private String searchValue;
|
||||
|
||||
@Schema(description = "년도", example = "2025")
|
||||
private Integer mngYyyy;
|
||||
|
||||
public Pageable toPageable() {
|
||||
if (sort != null && !sort.isEmpty()) {
|
||||
String[] sortParams = sort.split(",");
|
||||
String property = sortParams[0];
|
||||
Sort.Direction direction =
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "ErrorDataDto", description = "영상관리 오류데이터 검색 리턴")
|
||||
@Getter
|
||||
@Setter
|
||||
public static class ErrorDataDto {
|
||||
|
||||
private Long hstUid;
|
||||
private Integer mngYyyy;
|
||||
private String mapSheetNum;
|
||||
private String refMapSheetNum;
|
||||
private String map50kName;
|
||||
private String map5kName;
|
||||
private String mapSrcName;
|
||||
private Integer mapCodeSrc;
|
||||
@JsonFormatDttm private ZonedDateTime createdDttm;
|
||||
|
||||
private String syncState;
|
||||
private String syncStateName;
|
||||
private String syncTfwFileName;
|
||||
private String syncTifFileName;
|
||||
|
||||
private String errorCheckState;
|
||||
private String errorCheckStateName;
|
||||
private String errorCheckTfwFileName;
|
||||
private String errorCheckTifFileName;
|
||||
|
||||
// private List<MngFIleDto> fileArray;
|
||||
|
||||
public ErrorDataDto(
|
||||
Long hstUid,
|
||||
Integer mngYyyy,
|
||||
String mapSheetNum,
|
||||
String refMapSheetNum,
|
||||
String map50kName,
|
||||
String map5kName,
|
||||
String mapSrcName,
|
||||
Integer mapCodeSrc,
|
||||
ZonedDateTime createdDttm,
|
||||
String syncState,
|
||||
String syncTfwFileName,
|
||||
String syncTifFileName,
|
||||
String errorCheckState,
|
||||
String errorCheckTfwFileName,
|
||||
String errorCheckTifFileName) {
|
||||
this.hstUid = hstUid;
|
||||
this.mngYyyy = mngYyyy;
|
||||
this.mapSheetNum = mapSheetNum;
|
||||
this.refMapSheetNum = refMapSheetNum;
|
||||
this.map50kName = map50kName;
|
||||
this.map5kName = map5kName;
|
||||
this.mapSrcName = mapSrcName;
|
||||
this.mapCodeSrc = mapCodeSrc;
|
||||
this.createdDttm = createdDttm;
|
||||
this.syncState = syncState;
|
||||
this.syncStateName = getSyncStateName(syncState);
|
||||
this.syncTfwFileName = syncTfwFileName;
|
||||
this.syncTifFileName = syncTifFileName;
|
||||
this.errorCheckState = errorCheckState;
|
||||
this.errorCheckStateName = getSyncStateName(errorCheckState);
|
||||
this.errorCheckTfwFileName = errorCheckTfwFileName;
|
||||
this.errorCheckTifFileName = errorCheckTifFileName;
|
||||
}
|
||||
|
||||
private String getSyncStateName(String enumId) {
|
||||
if (enumId == null || enumId.isEmpty()) {
|
||||
enumId = "NOTYET";
|
||||
}
|
||||
|
||||
SyncStateType type = Enums.fromId(SyncStateType.class, enumId);
|
||||
return type.getText();
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "SyncCheckStateReqUpdateDto", description = "영상관리 오류처리 상태변경요청")
|
||||
@Getter
|
||||
@Setter
|
||||
public static class SyncCheckStateReqUpdateDto {
|
||||
|
||||
private Long hstUid;
|
||||
private String filePath;
|
||||
private String syncCheckTfwFileName;
|
||||
private String syncCheckTifFileName;
|
||||
private String syncCheckState;
|
||||
}
|
||||
|
||||
@Schema(name = "MngFIleDto", description = "관리파일정보")
|
||||
@Getter
|
||||
@Setter
|
||||
public static class MngFIleDto {
|
||||
|
||||
private Long fileUid;
|
||||
private String filePath;
|
||||
private String fileName;
|
||||
private Long fileSize;
|
||||
private String fileState;
|
||||
private Long hstUid;
|
||||
}
|
||||
|
||||
@Schema(name = "DmlReturn", description = "영상관리 DML 수행 후 리턴")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class DmlReturn {
|
||||
|
||||
private String flag;
|
||||
private String message;
|
||||
}
|
||||
|
||||
@Schema(name = "MngFileAddReq", description = "영상관리파일 등록 요청")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngFileAddReq {
|
||||
|
||||
private int mngYyyy;
|
||||
private String mapSheetNum;
|
||||
private String refMapSheetNum;
|
||||
private String filePath;
|
||||
private String fileName;
|
||||
private String fileExt;
|
||||
private Long hstUid;
|
||||
private Long fileSize;
|
||||
private String fileState;
|
||||
}
|
||||
|
||||
@Schema(name = "MngFilesDto", description = "영상파일내역 검색 리턴")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngFilesDto {
|
||||
|
||||
private long fileUid;
|
||||
private int mngYyyy;
|
||||
private String mapSheetNum;
|
||||
private String refMapSheetNum;
|
||||
private String filePath;
|
||||
private String fileName;
|
||||
private String fileExt;
|
||||
private Long hstUid;
|
||||
private Long fileSize;
|
||||
}
|
||||
|
||||
@Schema(name = "ResisterYearList", description = "영상파일 등록을 위한 연도 list")
|
||||
@Getter
|
||||
public static class ResisterYearList {
|
||||
|
||||
private Integer current;
|
||||
private List<Integer> years;
|
||||
|
||||
public ResisterYearList(Integer current, List<Integer> years) {
|
||||
this.current = current;
|
||||
this.years = years;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MapSheetState implements EnumType {
|
||||
// @formatter:off
|
||||
DONE("완료"),
|
||||
NOTYET("처리대기");
|
||||
// @formatter:on
|
||||
|
||||
private final String message;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
// 연도리스틀 조회시 사용하는 request Dto
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public static class YearSearchReq {
|
||||
|
||||
private String status;
|
||||
|
||||
// 페이징 파라미터
|
||||
private int page = 0;
|
||||
private int size = 20;
|
||||
private String sort;
|
||||
|
||||
@Builder
|
||||
public YearSearchReq(String status, int page, int size, String sort) {
|
||||
this.status = status;
|
||||
this.page = page;
|
||||
this.size = size;
|
||||
this.sort = sort;
|
||||
}
|
||||
|
||||
public Pageable toPageable() {
|
||||
if (sort != null && !sort.isEmpty()) {
|
||||
String[] sortParams = sort.split(",");
|
||||
String property = sortParams[0];
|
||||
Sort.Direction direction =
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "MngListDto", description = "영상파일내역 검색 목록")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngListDto {
|
||||
|
||||
private int mngYyyy;
|
||||
private String mapSheetNum;
|
||||
private String mapSheetName;
|
||||
private Integer beforeYear;
|
||||
private Boolean isSuccess;
|
||||
}
|
||||
|
||||
@Schema(name = "MngListDto", description = "영상파일내역 검색 목록")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngListCompareDto {
|
||||
|
||||
private String mngYyyy;
|
||||
private String mapSheetNum;
|
||||
private Integer beforeYear;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class TotalListDto {
|
||||
|
||||
private String mapSheetNum;
|
||||
private Integer beforeYear;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngYyyyDto {
|
||||
private Integer yyyy;
|
||||
private String mngPath;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.kamco.cd.kamcoback.dto;
|
||||
|
||||
import com.kamco.cd.kamcoback.inferface.JsonFormatDttm;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.ZonedDateTime;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
public class MapSheetMngDto {
|
||||
|
||||
@Schema(name = "MngSearchReq", description = "영상관리 검색 요청")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngSearchReq {
|
||||
|
||||
// 페이징 파라미터
|
||||
@Schema(description = "페이지 번호 (0부터 시작) ", example = "0")
|
||||
private int page = 0;
|
||||
|
||||
@Schema(description = "페이지 크기", example = "20")
|
||||
private int size = 20;
|
||||
|
||||
@Schema(description = "년도", example = "2025")
|
||||
private Integer mngYyyy;
|
||||
|
||||
public Pageable toPageable() {
|
||||
return PageRequest.of(page, size);
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "MngDto", description = "영상관리 검색 리턴")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngDto {
|
||||
private int rowNum;
|
||||
private int mngYyyy;
|
||||
private String mngState;
|
||||
private String syncState;
|
||||
private String syncCheckState;
|
||||
private Long syncTotCnt;
|
||||
private Long syncStateDoneCnt;
|
||||
private Long syncCheckStateDoneCnt;
|
||||
private Long syncNotFileCnt;
|
||||
private Long syncTypeErrorCnt;
|
||||
private Long syncSizeErrorCnt;
|
||||
@JsonFormatDttm private ZonedDateTime rgstStrtDttm;
|
||||
@JsonFormatDttm private ZonedDateTime rgstEndDttm;
|
||||
}
|
||||
|
||||
@Schema(name = "MngHstDto", description = "영상관리내역 검색 리턴")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngHstDto {
|
||||
private long hstUid;
|
||||
private int mngYyyy;
|
||||
private String mapSheetNum;
|
||||
private String refMapSheetNum;
|
||||
private String dataState;
|
||||
private String syncState;
|
||||
private String syncCheckState;
|
||||
@JsonFormatDttm private ZonedDateTime syncStrtDttm;
|
||||
@JsonFormatDttm private ZonedDateTime syncEndDttm;
|
||||
@JsonFormatDttm private ZonedDateTime syncCheckStrtDttm;
|
||||
@JsonFormatDttm private ZonedDateTime syncCheckEndDttm;
|
||||
|
||||
private String mapSheetPath;
|
||||
private String syncTifFileName;
|
||||
private String syncTfwFileName;
|
||||
private String useInference;
|
||||
private String syncMngPath;
|
||||
}
|
||||
|
||||
@Schema(name = "MngFileAddReq", description = "영상관리파일 등록 요청")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngFileAddReq {
|
||||
private int mngYyyy;
|
||||
private String mapSheetNum;
|
||||
private String refMapSheetNum;
|
||||
private String filePath;
|
||||
private String fileName;
|
||||
private String fileExt;
|
||||
private Long hstUid;
|
||||
private Long fileSize;
|
||||
private String fileState;
|
||||
}
|
||||
|
||||
@Schema(name = "MngFilesDto", description = "영상관리내역 검색 리턴")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngFilesDto {
|
||||
private long fileUid;
|
||||
private int mngYyyy;
|
||||
private String mapSheetNum;
|
||||
private String refMapSheetNum;
|
||||
private String filePath;
|
||||
private String fileName;
|
||||
private String fileExt;
|
||||
private Long hstUid;
|
||||
private Long fileSize;
|
||||
}
|
||||
|
||||
@Schema(name = "MngListCompareDto", description = "영상파일 비교가능 이전년도정보")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MngListCompareDto {
|
||||
|
||||
private String mngYyyy;
|
||||
private String mapSheetNum;
|
||||
private Integer beforeYear;
|
||||
}
|
||||
|
||||
@Schema(name = "DmlReturn", description = "영상관리 DML 수행 후 리턴")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class DmlReturn {
|
||||
private String flag;
|
||||
private String message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.kamco.cd.kamcoback.enums;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
public class ApiConfigEnum {
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode(of = "enumValue")
|
||||
public static class EnumDto<T> {
|
||||
|
||||
private final T enumValue;
|
||||
private final String id;
|
||||
private final String text;
|
||||
|
||||
public EnumDto(T enumValue, String id, String text) {
|
||||
this.enumValue = enumValue;
|
||||
this.id = id;
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/enums/CodeDto.java
Executable file
20
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/enums/CodeDto.java
Executable file
@@ -0,0 +1,20 @@
|
||||
package com.kamco.cd.kamcoback.enums;
|
||||
|
||||
public class CodeDto {
|
||||
|
||||
private String code;
|
||||
private String name;
|
||||
|
||||
public CodeDto(String code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.kamco.cd.kamcoback.enums;
|
||||
|
||||
import com.kamco.cd.kamcoback.enums.ApiConfigEnum.EnumDto;
|
||||
import com.kamco.cd.kamcoback.inferface.EnumType;
|
||||
import java.util.Arrays;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Common usage status used across the system.
|
||||
*
|
||||
* <p>This enum represents whether a resource is active, excluded from processing, or inactive. It
|
||||
* is commonly used for filtering, business rules, and status management.
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum CommonUseStatus implements EnumType {
|
||||
|
||||
// @formatter:off
|
||||
USE("USE", "사용중", 100)
|
||||
/** Actively used and available */
|
||||
,
|
||||
EXCEPT("EXCEPT", "영구 추론제외", 200)
|
||||
/** Explicitly excluded from use or processing */
|
||||
,
|
||||
AUTO_EXCEPT("AUTO_EXCEPT", "자동추론 제외", 300),
|
||||
NOT_USE("NOT_USE", "사용안함", 999)
|
||||
/** Not used or disabled */
|
||||
;
|
||||
// @formatter:on
|
||||
|
||||
private String id;
|
||||
private String text;
|
||||
private int ordering;
|
||||
|
||||
public static CommonUseStatus getEnumById(String id) {
|
||||
return Arrays.stream(CommonUseStatus.values())
|
||||
.filter(x -> x.getId().equals(id))
|
||||
.findFirst()
|
||||
.orElse(CommonUseStatus.NOT_USE);
|
||||
}
|
||||
|
||||
public EnumDto<CommonUseStatus> getEnumDto() {
|
||||
return new EnumDto<>(this, this.id, this.text);
|
||||
}
|
||||
}
|
||||
86
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/enums/Enums.java
Executable file
86
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/enums/Enums.java
Executable file
@@ -0,0 +1,86 @@
|
||||
package com.kamco.cd.kamcoback.enums;
|
||||
|
||||
import com.kamco.cd.kamcoback.inferface.CodeExpose;
|
||||
import com.kamco.cd.kamcoback.inferface.CodeHidden;
|
||||
import com.kamco.cd.kamcoback.inferface.EnumType;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
public class Enums {
|
||||
|
||||
private static final String BASE_PACKAGE = "com.kamco.cd.kamcoback";
|
||||
|
||||
/** 노출 가능한 enum만 모아둔 맵 key: enum simpleName (예: RoleType) value: enum Class */
|
||||
private static final Map<String, Class<? extends Enum<?>>> exposedEnumMap = scanExposedEnumMap();
|
||||
|
||||
// code로 enum 찾기
|
||||
public static <E extends Enum<E> & EnumType> E fromId(Class<E> enumClass, String id) {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (E e : enumClass.getEnumConstants()) {
|
||||
if (id.equalsIgnoreCase(e.getId())) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// enum -> CodeDto list
|
||||
public static List<CodeDto> toList(Class<? extends Enum<?>> enumClass) {
|
||||
Object[] enums = enumClass.getEnumConstants();
|
||||
|
||||
return Arrays.stream(enums)
|
||||
.map(e -> (EnumType) e)
|
||||
.filter(e -> !isHidden(enumClass, (Enum<?>) e))
|
||||
.map(e -> new CodeDto(e.getId(), e.getText()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private static boolean isHidden(Class<? extends Enum<?>> enumClass, Enum<?> e) {
|
||||
try {
|
||||
return enumClass.getField(e.name()).isAnnotationPresent(CodeHidden.class);
|
||||
} catch (NoSuchFieldException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 특정 타입(enum)만 조회 /codes/{type} -> type = RoleType 같은 값 */
|
||||
public static List<CodeDto> getCodes(String type) {
|
||||
Class<? extends Enum<?>> enumClass = exposedEnumMap.get(type);
|
||||
if (enumClass == null) {
|
||||
throw new IllegalArgumentException("지원하지 않는 코드 타입: " + type);
|
||||
}
|
||||
return toList(enumClass);
|
||||
}
|
||||
|
||||
/** 전체 enum 코드 조회 */
|
||||
public static Map<String, List<CodeDto>> getAllCodes() {
|
||||
Map<String, List<CodeDto>> result = new HashMap<>();
|
||||
for (Map.Entry<String, Class<? extends Enum<?>>> e : exposedEnumMap.entrySet()) {
|
||||
result.put(e.getKey(), toList(e.getValue()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** CodeExpose + EnumType 인 enum만 스캔해서 Map 구성 */
|
||||
private static Map<String, Class<? extends Enum<?>>> scanExposedEnumMap() {
|
||||
Reflections reflections = new Reflections(BASE_PACKAGE);
|
||||
|
||||
Set<Class<?>> types = reflections.getTypesAnnotatedWith(CodeExpose.class);
|
||||
|
||||
Map<String, Class<? extends Enum<?>>> result = new HashMap<>();
|
||||
|
||||
for (Class<?> clazz : types) {
|
||||
if (clazz.isEnum() && EnumType.class.isAssignableFrom(clazz)) {
|
||||
result.put(clazz.getSimpleName(), (Class<? extends Enum<?>>) clazz);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.kamco.cd.kamcoback.enums;
|
||||
|
||||
import com.kamco.cd.kamcoback.inferface.EnumType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MngStateType implements EnumType {
|
||||
NOTYET("동기화 시작"),
|
||||
PROCESSING("데이터 체크"),
|
||||
DONE("동기화 작업 종료"),
|
||||
TAKINGERROR("오류 데이터 처리중");
|
||||
|
||||
private final String desc;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.kamco.cd.kamcoback.enums;
|
||||
|
||||
import com.kamco.cd.kamcoback.inferface.CodeExpose;
|
||||
import com.kamco.cd.kamcoback.inferface.CodeHidden;
|
||||
import com.kamco.cd.kamcoback.inferface.EnumType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@CodeExpose
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SyncStateType implements EnumType {
|
||||
@CodeHidden
|
||||
NOTYET("미처리"),
|
||||
NOFILE("파일없음"),
|
||||
NOTPAIR("페어파일누락"),
|
||||
DUPLICATE("파일중복"),
|
||||
TYPEERROR("손상파일"),
|
||||
@CodeHidden
|
||||
DONE("완료");
|
||||
|
||||
private final String desc;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.kamco.cd.kamcoback.inferface;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CodeExpose {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.kamco.cd.kamcoback.inferface;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface CodeHidden {}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.kamco.cd.kamcoback.inferface;
|
||||
|
||||
public interface EnumType {
|
||||
|
||||
String getId();
|
||||
|
||||
String getText();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.kamco.cd.kamcoback.inferface;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@JacksonAnnotationsInside
|
||||
@JsonFormat(
|
||||
shape = JsonFormat.Shape.STRING,
|
||||
pattern = "yyyy-MM-dd'T'HH:mm:ssXXX",
|
||||
timezone = "Asia/Seoul")
|
||||
public @interface JsonFormatDttm {}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.kamco.cd.kamcoback.postgres.core;
|
||||
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngDto;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngHstDto;
|
||||
import com.kamco.cd.kamcoback.enums.CommonUseStatus;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngFileEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.repository.MapSheetMngFileJobRepository;
|
||||
import com.kamco.cd.kamcoback.postgres.repository.MapSheetMngYearRepository;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MapSheetMngFileJobCoreService {
|
||||
|
||||
private final MapSheetMngFileJobRepository mapSheetMngFileJobRepository;
|
||||
private final MapSheetMngYearRepository mapSheetMngYearRepository;
|
||||
|
||||
public Page<MngDto> findMapSheetMngList(
|
||||
MapSheetMngDto.@Valid MngSearchReq searchReq) {
|
||||
return mapSheetMngFileJobRepository.findMapSheetMngList(searchReq);
|
||||
}
|
||||
|
||||
public List<MngHstDto> findTargetMapSheetFileList(long targetNum, int pageSize) {
|
||||
return mapSheetMngFileJobRepository.findTargetMapSheetFileList(targetNum, pageSize);
|
||||
}
|
||||
|
||||
public MapSheetMngDto.DmlReturn mngHstDataSyncStateUpdate(
|
||||
@Valid MapSheetMngDto.MngHstDto updateReq) {
|
||||
|
||||
mapSheetMngFileJobRepository.mngHstDataSyncStateUpdate(updateReq);
|
||||
|
||||
return new MapSheetMngDto.DmlReturn("success", updateReq.getHstUid() + "");
|
||||
}
|
||||
|
||||
public MapSheetMngDto.DmlReturn mngFileSave(@Valid MapSheetMngDto.MngFileAddReq addReq) {
|
||||
|
||||
MapSheetMngFileEntity entity = new MapSheetMngFileEntity();
|
||||
entity.setMngYyyy(addReq.getMngYyyy());
|
||||
entity.setMapSheetNum(addReq.getMapSheetNum());
|
||||
entity.setRefMapSheetNum(addReq.getRefMapSheetNum());
|
||||
entity.setFilePath(addReq.getFilePath());
|
||||
entity.setFileName(addReq.getFileName());
|
||||
entity.setFileExt(addReq.getFileExt());
|
||||
entity.setHstUid(addReq.getHstUid());
|
||||
entity.setFileSize(addReq.getFileSize());
|
||||
entity.setFileState(addReq.getFileState());
|
||||
|
||||
MapSheetMngFileEntity saved = mapSheetMngFileJobRepository.save(entity);
|
||||
// int hstCnt = mapSheetMngRepository.insertMapSheetOrgDataToMapSheetMngHst(saved.getMngYyyy());
|
||||
|
||||
return new MapSheetMngDto.DmlReturn("success", saved.getFileUid().toString());
|
||||
}
|
||||
|
||||
public Long findByMngYyyyTargetMapSheetNotYetCount(int mngYyyy) {
|
||||
return mapSheetMngFileJobRepository.findByMngYyyyTargetMapSheetNotYetCount(mngYyyy);
|
||||
}
|
||||
|
||||
public void mngDataState(int mngYyyy, String mngState) {
|
||||
mapSheetMngFileJobRepository.mngDataState(mngYyyy, mngState);
|
||||
}
|
||||
|
||||
public Integer findNotYetMapSheetMng() {
|
||||
return mapSheetMngFileJobRepository.findNotYetMapSheetMng();
|
||||
}
|
||||
|
||||
public Long findByHstMapSheetBeforeYyyyListCount(int strtYyyy, int endYyyy, String mapSheetNum) {
|
||||
return mapSheetMngFileJobRepository.findByHstMapSheetBeforeYyyyListCount(
|
||||
strtYyyy, endYyyy, mapSheetNum);
|
||||
}
|
||||
|
||||
public void updateException5kMapSheet(String mapSheetNum, CommonUseStatus commonUseStatus) {
|
||||
mapSheetMngFileJobRepository.updateException5kMapSheet(mapSheetNum, commonUseStatus);
|
||||
}
|
||||
|
||||
public void saveSheetMngYear() {
|
||||
mapSheetMngYearRepository.saveFileInfo();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.kamco.cd.kamcoback.postgres.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.PreUpdate;
|
||||
import java.time.ZonedDateTime;
|
||||
import lombok.Getter;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
|
||||
@Getter
|
||||
@MappedSuperclass
|
||||
public class CommonDateEntity {
|
||||
|
||||
@CreatedDate
|
||||
@Column(name = "created_dttm", updatable = false, nullable = false)
|
||||
private ZonedDateTime createdDate;
|
||||
|
||||
@LastModifiedDate
|
||||
@Column(name = "updated_dttm", nullable = false)
|
||||
private ZonedDateTime modifiedDate;
|
||||
|
||||
@PrePersist
|
||||
protected void onPersist() {
|
||||
this.createdDate = ZonedDateTime.now();
|
||||
this.modifiedDate = ZonedDateTime.now();
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
protected void onUpdate() {
|
||||
this.modifiedDate = ZonedDateTime.now();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.kamco.cd.kamcoback.postgres.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.locationtech.jts.geom.Geometry;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name = "tb_map_inkx_50k")
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
public class MapInkx50kEntity extends CommonDateEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_inkx_50k_fid_seq_gen")
|
||||
@SequenceGenerator(
|
||||
name = "tb_map_inkx_50k_fid_seq_gen",
|
||||
sequenceName = "tb_map_inkx_50k_fid_seq",
|
||||
allocationSize = 1)
|
||||
private Integer fid;
|
||||
|
||||
@Column(name = "mapidcd_no")
|
||||
private String mapidcdNo;
|
||||
|
||||
@Column(name = "mapid_nm")
|
||||
private String mapidNm;
|
||||
|
||||
@Column(name = "mapid_no")
|
||||
private String mapidNo;
|
||||
|
||||
@Column(name = "geom")
|
||||
private Geometry geom;
|
||||
|
||||
public MapInkx50kEntity(String mapidcdNo, String mapidNm, String mapidNo, Geometry geom) {
|
||||
this.mapidcdNo = mapidcdNo;
|
||||
this.mapidNm = mapidNm;
|
||||
this.mapidNo = mapidNo;
|
||||
this.geom = geom;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.kamco.cd.kamcoback.postgres.entity;
|
||||
|
||||
import com.kamco.cd.kamcoback.enums.CommonUseStatus;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
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 lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.locationtech.jts.geom.Geometry;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name = "tb_map_inkx_5k")
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
public class MapInkx5kEntity extends CommonDateEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_inkx_5k_fid_seq_gen")
|
||||
@SequenceGenerator(
|
||||
name = "tb_map_inkx_5k_fid_seq_gen",
|
||||
sequenceName = "tb_map_inkx_5k_fid_seq",
|
||||
allocationSize = 1)
|
||||
private Integer fid;
|
||||
|
||||
@Column(name = "mapidcd_no")
|
||||
private String mapidcdNo;
|
||||
|
||||
@Column(name = "mapid_nm")
|
||||
private String mapidNm;
|
||||
|
||||
@Column(name = "geom")
|
||||
private Geometry geom;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "fid_k50", referencedColumnName = "fid")
|
||||
private MapInkx50kEntity mapInkx50k;
|
||||
|
||||
// 사용상태 USE,
|
||||
@Column(name = "use_inference")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private CommonUseStatus useInference;
|
||||
|
||||
// Constructor
|
||||
public MapInkx5kEntity(
|
||||
String mapidcdNo, String mapidNm, Geometry geom, MapInkx50kEntity mapInkx50k) {
|
||||
this.mapidcdNo = mapidcdNo;
|
||||
this.mapidNm = mapidNm;
|
||||
this.geom = geom;
|
||||
this.mapInkx50k = mapInkx50k;
|
||||
// 생성시 default 사용함 (사용,제외,사용안함)
|
||||
this.useInference = CommonUseStatus.USE;
|
||||
}
|
||||
|
||||
// 변경 사용상태 (추론사용여부)
|
||||
public void updateUseInference(CommonUseStatus useInference) {
|
||||
this.useInference = useInference;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.kamco.cd.kamcoback.postgres.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.ZonedDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "tb_map_sheet_mng")
|
||||
public class MapSheetMngEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = "mng_yyyy", nullable = false)
|
||||
private Integer mngYyyy;
|
||||
|
||||
@Size(max = 20)
|
||||
@ColumnDefault("'NOTYET'")
|
||||
@Column(name = "mng_state", length = 20)
|
||||
private String mngState = "NOTYET";
|
||||
|
||||
@Size(max = 20)
|
||||
@ColumnDefault("'NOTYET'")
|
||||
@Column(name = "sync_state", length = 20)
|
||||
private String syncState = "NOTYET";
|
||||
|
||||
@Column(name = "mng_state_dttm")
|
||||
private ZonedDateTime mngStateDttm = ZonedDateTime.now();
|
||||
|
||||
@Column(name = "sync_state_dttm")
|
||||
private ZonedDateTime syncStateDttm = ZonedDateTime.now();
|
||||
|
||||
@Column(name = "created_dttm")
|
||||
private ZonedDateTime createdDttm = ZonedDateTime.now();
|
||||
|
||||
@Column(name = "created_uid")
|
||||
private Long createdUid;
|
||||
|
||||
@Column(name = "updated_dttm")
|
||||
private ZonedDateTime updatedDttm = ZonedDateTime.now();
|
||||
|
||||
@Column(name = "updated_uid")
|
||||
private Long updatedUid;
|
||||
|
||||
@Size(max = 255)
|
||||
@ColumnDefault("'NULL::character varying'")
|
||||
@Column(name = "mng_path")
|
||||
private String mngPath;
|
||||
|
||||
@Size(max = 20)
|
||||
@ColumnDefault("'NOTYET'")
|
||||
@Column(name = "sync_check_state", length = 20)
|
||||
private String syncCheckState = "NOTYET";
|
||||
|
||||
@Column(name = "sync_strt_dttm")
|
||||
private ZonedDateTime syncStrtDttm;
|
||||
|
||||
@Column(name = "sync_end_dttm")
|
||||
private ZonedDateTime syncEndDttm;
|
||||
|
||||
@Column(name = "sync_check_strt_dttm")
|
||||
private ZonedDateTime syncCheckStrtDttm;
|
||||
|
||||
@Column(name = "sync_check_end_dttm")
|
||||
private ZonedDateTime syncCheckEndDttm;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.kamco.cd.kamcoback.postgres.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "tb_map_sheet_mng_files")
|
||||
public class MapSheetMngFileEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "file_uid", nullable = false)
|
||||
private Long fileUid;
|
||||
|
||||
@NotNull
|
||||
@Column(name = "mng_yyyy", nullable = false)
|
||||
private Integer mngYyyy;
|
||||
|
||||
@NotNull
|
||||
@Column(name = "map_sheet_num", nullable = false)
|
||||
private String mapSheetNum;
|
||||
|
||||
@Column(name = "ref_map_sheet_num")
|
||||
private String refMapSheetNum;
|
||||
|
||||
@Size(max = 255)
|
||||
@Column(name = "file_path")
|
||||
private String filePath;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "file_name", length = 100)
|
||||
private String fileName;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "file_ext", length = 20)
|
||||
private String fileExt;
|
||||
|
||||
@Column(name = "hst_uid")
|
||||
private Long hstUid;
|
||||
|
||||
@Column(name = "file_size")
|
||||
private Long fileSize;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "file_state", length = 20)
|
||||
private String fileState;
|
||||
|
||||
@NotNull
|
||||
@ColumnDefault("false")
|
||||
@Column(name = "file_del", nullable = false)
|
||||
private Boolean fileDel = false;
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
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.Table;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.ZonedDateTime;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* This class represents the entity for managing the history of map sheets. It is mapped to the
|
||||
* database table "tb_map_sheet_mng_hst" and contains various properties related to the 1:5k map
|
||||
* sheet information, as well as metadata for file synchronization and management.
|
||||
*
|
||||
* <p>This entity: - Includes a primary key (hstUid) for unique identification. - Maintains
|
||||
* information associated with map sheets such as code, name, scale ratio, and paths. - Tracks
|
||||
* states, timestamps, and data synchronization details. - Maintains relationships with the
|
||||
* `MapInkx5kEntity` entity through a many-to-one association. - Provides functionality to update
|
||||
* file information and sizes (`tifSizeBytes`, `tfwSizeBytes`, and `totalSizeBytes`).
|
||||
*
|
||||
* <p>It extends the `CommonDateEntity` class to include common date management fields, such as
|
||||
* creation and modification timestamps.
|
||||
*
|
||||
* <p>The `@Getter` annotation generates getter methods for all fields, while the access to setters
|
||||
* is restricted to enforce controlled modifications. The entity uses `@NoArgsConstructor` with
|
||||
* `AccessLevel.PROTECTED` to restrict direct instantiation. The `updateFileInfos` method allows
|
||||
* dynamic updates of specific file information.
|
||||
*
|
||||
* <p>Fields include: - hstUid: Unique identifier for the history record. - mngYyyy: Year associated
|
||||
* with the management record. - mapInkx5kByCode: Reference to the related `MapInkx5kEntity` object.
|
||||
* - mapSheetNum: Map sheet number identifying specific map. - mapSheetName: Name of the map sheet.
|
||||
* - mapSheetCodeSrc: Source code of the map sheet. - scaleRatio: Scale ratio of the map. -
|
||||
* dataState: State/status of the map sheet data. - dataStateDttm: Timestamp of the data state. -
|
||||
* useInference: Indicator or metadata for inference usage. - useInferenceDttm: Timestamp for
|
||||
* inference-related use. - mapSheetPath: Path or location of the map sheet file. - refMapSheetNum:
|
||||
* Reference to a related map sheet number. - createdUid: User ID of the record creator. -
|
||||
* updatedUid: User ID of the last updater. - syncState and related fields: Fields to manage
|
||||
* synchronization states and processes. - tifSizeBytes, tfwSizeBytes, totalSizeBytes: Fields to
|
||||
* track file size details. - sync file name fields: Stores names of files relevant for
|
||||
* synchronization and verification.
|
||||
*
|
||||
* <p>This entity is essential for tracking and managing map sheet revisions, status, and usage in a
|
||||
* system leveraging 1:5k map data.
|
||||
*/
|
||||
@Getter
|
||||
// entity의 접근제어를 위해 @setter를 사용 x
|
||||
// @Setter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@Entity
|
||||
// 영상관리이력
|
||||
@Table(name = "tb_map_sheet_mng_hst")
|
||||
public class MapSheetMngHstEntity extends CommonDateEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "hst_uid")
|
||||
private Long hstUid; // id
|
||||
|
||||
@Column(name = "mng_yyyy")
|
||||
private Integer mngYyyy; // 년도
|
||||
|
||||
// JPA 연관관계: MapInkx5k 참조 (PK 기반) 소속도엽번호 1:5k
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "map_sheet_code", referencedColumnName = "fid")
|
||||
private MapInkx5kEntity mapInkx5kByCode;
|
||||
|
||||
// TODO 1:5k 관련 정보 추후 제거 필요
|
||||
@Column(name = "map_sheet_num")
|
||||
private String mapSheetNum; // 도엽번호
|
||||
|
||||
@Column(name = "map_sheet_name")
|
||||
private String mapSheetName;
|
||||
|
||||
// TODO END
|
||||
|
||||
// 도엽파일이 저장된 경로
|
||||
@Column(name = "map_sheet_code_src")
|
||||
private Integer mapSheetCodeSrc;
|
||||
|
||||
// 도엽비율?
|
||||
@Column(name = "scale_ratio")
|
||||
private Integer scaleRatio;
|
||||
|
||||
@Column(name = "data_state", length = 20)
|
||||
private String dataState;
|
||||
|
||||
@Column(name = "data_state_dttm")
|
||||
private ZonedDateTime dataStateDttm;
|
||||
|
||||
@Column(name = "use_inference")
|
||||
private String useInference;
|
||||
|
||||
@Column(name = "use_inference_dttm")
|
||||
private ZonedDateTime useInferenceDttm;
|
||||
|
||||
@Column(name = "map_sheet_path")
|
||||
private String mapSheetPath;
|
||||
|
||||
@Column(name = "ref_map_sheet_num")
|
||||
private String refMapSheetNum;
|
||||
|
||||
@Column(name = "created_uid")
|
||||
private Long createdUid;
|
||||
|
||||
@Column(name = "updated_uid")
|
||||
private Long updatedUid;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "sync_state", length = 20)
|
||||
private String syncState;
|
||||
|
||||
@Size(max = 20)
|
||||
@Column(name = "sync_check_state", length = 20)
|
||||
private String syncCheckState;
|
||||
|
||||
@Column(name = "sync_strt_dttm")
|
||||
private ZonedDateTime syncStrtDttm;
|
||||
|
||||
@Column(name = "sync_end_dttm")
|
||||
private ZonedDateTime syncEndDttm;
|
||||
|
||||
@Column(name = "sync_check_strt_dttm")
|
||||
private ZonedDateTime syncCheckStrtDttm;
|
||||
|
||||
@Column(name = "sync_check_end_dttm")
|
||||
private ZonedDateTime syncCheckEndDttm;
|
||||
|
||||
@Column(name = "tif_size_bytes")
|
||||
private Long tifSizeBytes;
|
||||
|
||||
@Column(name = "tfw_size_bytes")
|
||||
private Long tfwSizeBytes;
|
||||
|
||||
@Column(name = "total_size_bytes")
|
||||
private Long totalSizeBytes;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "sync_tif_file_name", length = 100)
|
||||
private String syncTifFileName;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "sync_tfw_file_name", length = 100)
|
||||
private String syncTfwFileName;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "sync_check_tif_file_name", length = 100)
|
||||
private String syncCheckTifFileName;
|
||||
|
||||
@Size(max = 100)
|
||||
@Column(name = "sync_check_tfw_file_name", length = 100)
|
||||
private String syncCheckTfwFileName;
|
||||
|
||||
// 파일정보 업데이트
|
||||
public void updateFileInfos(Long tifSizeBytes, Long tfwSizeBytes) {
|
||||
tifSizeBytes = tifSizeBytes == null ? 0L : tifSizeBytes;
|
||||
tfwSizeBytes = tfwSizeBytes == null ? 0L : tfwSizeBytes;
|
||||
this.tifSizeBytes = tifSizeBytes;
|
||||
this.tfwSizeBytes = tfwSizeBytes;
|
||||
this.totalSizeBytes = tifSizeBytes + tfwSizeBytes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.kamco.cd.kamcoback.postgres.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.EmbeddedId;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.ZonedDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "tb_map_sheet_mng_year_yn")
|
||||
public class MapSheetMngYearYnEntity {
|
||||
|
||||
@EmbeddedId private MapSheetMngYearYnEntityId id;
|
||||
|
||||
@NotNull
|
||||
@Column(name = "yn", nullable = false, length = Integer.MAX_VALUE)
|
||||
private String yn;
|
||||
|
||||
@NotNull
|
||||
@ColumnDefault("now()")
|
||||
@Column(name = "created_dttm", nullable = false)
|
||||
private ZonedDateTime createdDttm;
|
||||
|
||||
@NotNull
|
||||
@ColumnDefault("now()")
|
||||
@Column(name = "updated_dttm", nullable = false)
|
||||
private ZonedDateTime updatedDttm;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.kamco.cd.kamcoback.postgres.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.Hibernate;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Embeddable
|
||||
public class MapSheetMngYearYnEntityId implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6282262062316057898L;
|
||||
|
||||
@Size(max = 20)
|
||||
@NotNull
|
||||
@Column(name = "map_sheet_num", nullable = false, length = 20)
|
||||
private String mapSheetNum;
|
||||
|
||||
@NotNull
|
||||
@Column(name = "mng_yyyy", nullable = false)
|
||||
private Integer mngYyyy;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) {
|
||||
return false;
|
||||
}
|
||||
MapSheetMngYearYnEntityId entity = (MapSheetMngYearYnEntityId) o;
|
||||
return Objects.equals(this.mngYyyy, entity.mngYyyy)
|
||||
&& Objects.equals(this.mapSheetNum, entity.mapSheetNum);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mngYyyy, mapSheetNum);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository;
|
||||
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngFileEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface MapSheetMngFileJobRepository
|
||||
extends JpaRepository<MapSheetMngFileEntity, Long>, MapSheetMngFileJobRepositoryCustom {}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository;
|
||||
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngDto;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngHstDto;
|
||||
import com.kamco.cd.kamcoback.enums.CommonUseStatus;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
public interface MapSheetMngFileJobRepositoryCustom {
|
||||
|
||||
Page<MngDto> findMapSheetMngList(MapSheetMngDto.MngSearchReq searchReq);
|
||||
|
||||
void mngHstDataSyncStateUpdate(MapSheetMngDto.MngHstDto updateReq);
|
||||
|
||||
List<MngHstDto> findTargetMapSheetFileList(long targetNum, int pageSize);
|
||||
|
||||
Long findByMngYyyyTargetMapSheetNotYetCount(int mngYyyy);
|
||||
|
||||
public void mngDataState(int mngYyyy, String mngState);
|
||||
|
||||
public Integer findNotYetMapSheetMng();
|
||||
|
||||
public Long findByHstMapSheetBeforeYyyyListCount(int strtYyyy, int endYyyy, String mapSheetNum);
|
||||
|
||||
public void updateException5kMapSheet(String mapSheetNum, CommonUseStatus commonUseStatus);
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository;
|
||||
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngEntity.mapSheetMngEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSheetMngHstEntity;
|
||||
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngDto;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngHstDto;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngSearchReq;
|
||||
import com.kamco.cd.kamcoback.enums.CommonUseStatus;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.CaseBuilder;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.core.types.dsl.StringExpression;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class MapSheetMngFileJobRepositoryImpl implements MapSheetMngFileJobRepositoryCustom {
|
||||
|
||||
private final JPAQueryFactory queryFactory;
|
||||
private final StringExpression NULL_STRING = Expressions.stringTemplate("cast(null as text)");
|
||||
|
||||
@PersistenceContext private EntityManager em;
|
||||
|
||||
@Override
|
||||
public Integer findNotYetMapSheetMng() {
|
||||
Integer countQuery =
|
||||
queryFactory
|
||||
.select(mapSheetMngEntity.mngYyyy)
|
||||
.from(mapSheetMngEntity)
|
||||
.where(
|
||||
mapSheetMngEntity
|
||||
.mngState
|
||||
.eq("NOTYET")
|
||||
.or(mapSheetMngEntity.mngState.eq("PROCESSING")))
|
||||
.limit(1)
|
||||
.fetchOne();
|
||||
|
||||
return countQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long findByMngYyyyTargetMapSheetNotYetCount(int mngYyyy) {
|
||||
Long countQuery =
|
||||
queryFactory
|
||||
.select(mapSheetMngHstEntity.mngYyyy.count())
|
||||
.from(mapSheetMngHstEntity)
|
||||
.where(
|
||||
mapSheetMngHstEntity
|
||||
.mngYyyy
|
||||
.eq(mngYyyy)
|
||||
.and(mapSheetMngHstEntity.syncState.eq("NOTYET")))
|
||||
.fetchOne();
|
||||
|
||||
return countQuery;
|
||||
}
|
||||
|
||||
public void mngDataState(int mngYyyy, String mngState) {
|
||||
long updateCount =
|
||||
queryFactory
|
||||
.update(mapSheetMngEntity)
|
||||
.set(mapSheetMngEntity.mngState, mngState)
|
||||
.set(mapSheetMngEntity.syncState, mngState)
|
||||
.set(mapSheetMngEntity.syncCheckState, mngState)
|
||||
.where(mapSheetMngEntity.mngYyyy.eq(mngYyyy))
|
||||
.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<MapSheetMngDto.MngDto> findMapSheetMngList(MapSheetMngDto.MngSearchReq searchReq) {
|
||||
|
||||
Pageable pageable = searchReq.toPageable();
|
||||
BooleanBuilder whereBuilder = new BooleanBuilder();
|
||||
|
||||
if (searchReq.getMngYyyy() != null) {
|
||||
whereBuilder.and(mapSheetMngEntity.mngYyyy.eq(searchReq.getMngYyyy()));
|
||||
}
|
||||
|
||||
List<MapSheetMngDto.MngDto> foundContent =
|
||||
queryFactory
|
||||
.select(
|
||||
Projections.constructor(
|
||||
MapSheetMngDto.MngDto.class,
|
||||
Expressions.numberTemplate(
|
||||
Integer.class,
|
||||
"row_number() over(order by {0} desc)",
|
||||
mapSheetMngEntity.createdDttm),
|
||||
mapSheetMngEntity.mngYyyy,
|
||||
mapSheetMngEntity.mngState,
|
||||
mapSheetMngEntity.syncState,
|
||||
mapSheetMngEntity.syncCheckState,
|
||||
mapSheetMngHstEntity.count(),
|
||||
new CaseBuilder()
|
||||
.when(mapSheetMngHstEntity.syncState.eq("DONE"))
|
||||
.then(1L)
|
||||
.otherwise(0L)
|
||||
.sum()
|
||||
.as("syncStateDoneCnt"),
|
||||
new CaseBuilder()
|
||||
.when(mapSheetMngHstEntity.syncCheckState.eq("DONE"))
|
||||
.then(1L)
|
||||
.otherwise(0L)
|
||||
.sum(),
|
||||
new CaseBuilder()
|
||||
.when(mapSheetMngHstEntity.dataState.eq("NOT"))
|
||||
.then(1L)
|
||||
.otherwise(0L)
|
||||
.sum(),
|
||||
new CaseBuilder()
|
||||
.when(mapSheetMngHstEntity.dataState.eq("TYPEERROR"))
|
||||
.then(1L)
|
||||
.otherwise(0L)
|
||||
.sum(),
|
||||
new CaseBuilder()
|
||||
.when(mapSheetMngHstEntity.dataState.eq("SIZEERROR"))
|
||||
.then(1L)
|
||||
.otherwise(0L)
|
||||
.sum(),
|
||||
mapSheetMngHstEntity.syncStrtDttm.min(),
|
||||
mapSheetMngHstEntity.syncCheckEndDttm.max()))
|
||||
.from(mapSheetMngEntity)
|
||||
.leftJoin(mapSheetMngHstEntity)
|
||||
.on(mapSheetMngEntity.mngYyyy.eq(mapSheetMngHstEntity.mngYyyy))
|
||||
.where(whereBuilder)
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize())
|
||||
.orderBy(mapSheetMngEntity.createdDttm.desc())
|
||||
.groupBy(mapSheetMngEntity.mngYyyy)
|
||||
.fetch();
|
||||
|
||||
Long countQuery =
|
||||
queryFactory
|
||||
.select(mapSheetMngEntity.mngYyyy.count())
|
||||
.from(mapSheetMngEntity)
|
||||
.where(whereBuilder)
|
||||
.fetchOne();
|
||||
|
||||
return new PageImpl<>(foundContent, pageable, countQuery);
|
||||
}
|
||||
|
||||
public void mngHstDataSyncStateUpdate(MapSheetMngDto.MngHstDto updateReq) {
|
||||
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
|
||||
if (updateReq.getDataState().equals("DONE")) {
|
||||
long updateCount =
|
||||
queryFactory
|
||||
.update(mapSheetMngHstEntity)
|
||||
.set(mapSheetMngHstEntity.dataState, updateReq.getDataState())
|
||||
.set(mapSheetMngHstEntity.dataStateDttm, now)
|
||||
.set(mapSheetMngHstEntity.syncState, updateReq.getSyncState())
|
||||
.set(mapSheetMngHstEntity.syncEndDttm, now)
|
||||
.set(mapSheetMngHstEntity.syncCheckState, "NOTYET")
|
||||
.set(mapSheetMngHstEntity.syncCheckStrtDttm, now)
|
||||
.set(mapSheetMngHstEntity.syncCheckEndDttm, now)
|
||||
.set(mapSheetMngHstEntity.mapSheetPath, updateReq.getMapSheetPath())
|
||||
.set(mapSheetMngHstEntity.syncTfwFileName, updateReq.getSyncTfwFileName())
|
||||
.set(mapSheetMngHstEntity.syncTifFileName, updateReq.getSyncTifFileName())
|
||||
.set(mapSheetMngHstEntity.useInference, updateReq.getUseInference())
|
||||
.where(mapSheetMngHstEntity.hstUid.eq(updateReq.getHstUid()))
|
||||
.execute();
|
||||
} else {
|
||||
long updateCount =
|
||||
queryFactory
|
||||
.update(mapSheetMngHstEntity)
|
||||
.set(mapSheetMngHstEntity.dataState, updateReq.getDataState())
|
||||
.set(mapSheetMngHstEntity.dataStateDttm, now)
|
||||
.set(mapSheetMngHstEntity.syncState, updateReq.getSyncState())
|
||||
.set(mapSheetMngHstEntity.syncStrtDttm, now)
|
||||
.set(mapSheetMngHstEntity.syncEndDttm, now)
|
||||
.set(mapSheetMngHstEntity.syncCheckState, "NOTYET")
|
||||
.set(mapSheetMngHstEntity.syncCheckStrtDttm, now)
|
||||
.set(mapSheetMngHstEntity.syncCheckEndDttm, now)
|
||||
.set(mapSheetMngHstEntity.mapSheetPath, updateReq.getMapSheetPath())
|
||||
.set(mapSheetMngHstEntity.syncTfwFileName, updateReq.getSyncTfwFileName())
|
||||
.set(mapSheetMngHstEntity.syncTifFileName, updateReq.getSyncTifFileName())
|
||||
.set(mapSheetMngHstEntity.useInference, updateReq.getUseInference())
|
||||
.where(mapSheetMngHstEntity.hstUid.eq(updateReq.getHstUid()))
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MngHstDto> findTargetMapSheetFileList(long targetNum, int pageSize) {
|
||||
// Pageable pageable = searchReq.toPageable();
|
||||
|
||||
List<MngHstDto> foundContent =
|
||||
queryFactory
|
||||
.select(
|
||||
Projections.constructor(
|
||||
MngHstDto.class,
|
||||
mapSheetMngHstEntity.hstUid,
|
||||
mapSheetMngHstEntity.mngYyyy,
|
||||
mapSheetMngHstEntity.mapSheetNum,
|
||||
mapSheetMngHstEntity.refMapSheetNum,
|
||||
mapSheetMngHstEntity.dataState,
|
||||
mapSheetMngHstEntity.syncState,
|
||||
mapSheetMngHstEntity.syncCheckState,
|
||||
mapSheetMngHstEntity.syncStrtDttm,
|
||||
mapSheetMngHstEntity.syncEndDttm,
|
||||
mapSheetMngHstEntity.syncCheckStrtDttm,
|
||||
mapSheetMngHstEntity.syncCheckEndDttm,
|
||||
mapSheetMngHstEntity.mapSheetPath,
|
||||
mapSheetMngHstEntity.syncCheckTfwFileName,
|
||||
mapSheetMngHstEntity.syncCheckTifFileName,
|
||||
mapSheetMngHstEntity.useInference,
|
||||
mapSheetMngEntity.mngPath))
|
||||
.from(mapSheetMngHstEntity)
|
||||
.join(mapSheetMngEntity)
|
||||
.on(mapSheetMngEntity.mngYyyy.eq(mapSheetMngHstEntity.mngYyyy))
|
||||
.where(
|
||||
mapSheetMngHstEntity.syncState.eq("NOTYET"),
|
||||
mapSheetMngHstEntity.hstUid.mod(10L).eq(targetNum))
|
||||
.limit(pageSize)
|
||||
.orderBy(mapSheetMngHstEntity.hstUid.asc())
|
||||
.fetch();
|
||||
|
||||
return foundContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long findByHstMapSheetBeforeYyyyListCount(int strtYyyy, int endYyyy, String mapSheetNum) {
|
||||
|
||||
Long countQuery =
|
||||
queryFactory
|
||||
.select(mapSheetMngHstEntity.mngYyyy.count())
|
||||
.from(mapSheetMngHstEntity)
|
||||
.where(
|
||||
mapSheetMngHstEntity
|
||||
.mngYyyy
|
||||
.goe(strtYyyy)
|
||||
.and(mapSheetMngHstEntity.mngYyyy.loe(endYyyy))
|
||||
.and(mapSheetMngHstEntity.mapSheetNum.eq(mapSheetNum))
|
||||
.and(mapSheetMngHstEntity.useInference.eq("USE"))
|
||||
.and(
|
||||
mapSheetMngHstEntity
|
||||
.syncState
|
||||
.eq("DONE")
|
||||
.or(mapSheetMngHstEntity.syncCheckState.eq("DONE"))))
|
||||
.fetchOne();
|
||||
|
||||
return countQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateException5kMapSheet(String mapSheetNum, CommonUseStatus commonUseStatus) {
|
||||
long updateCount =
|
||||
queryFactory
|
||||
.update(mapInkx5kEntity)
|
||||
.set(mapInkx5kEntity.useInference, commonUseStatus)
|
||||
.set(mapInkx5kEntity.modifiedDate, ZonedDateTime.now())
|
||||
.where(mapInkx5kEntity.mapidcdNo.eq(mapSheetNum))
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository;
|
||||
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngYearYnEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngYearYnEntityId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface MapSheetMngYearRepository
|
||||
extends JpaRepository<MapSheetMngYearYnEntity, MapSheetMngYearYnEntityId>,
|
||||
MapSheetMngYearRepositoryCustom {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository;
|
||||
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngListCompareDto;
|
||||
import java.util.List;
|
||||
|
||||
public interface MapSheetMngYearRepositoryCustom {
|
||||
void saveFileInfo();
|
||||
|
||||
List<MngListCompareDto> findByHstMapSheetCompareList(int mngYyyy, List<String> mapIds);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository;
|
||||
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngListCompareDto;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngYearYnEntity;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.core.types.dsl.StringExpression;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class MapSheetMngYearRepositoryImpl implements MapSheetMngYearRepositoryCustom {
|
||||
|
||||
private final JPAQueryFactory queryFactory;
|
||||
private final EntityManager em;
|
||||
|
||||
/** 변화탐지 실행 가능 비교년도 저장 */
|
||||
@Override
|
||||
public void saveFileInfo() {
|
||||
|
||||
em.createNativeQuery("TRUNCATE TABLE tb_map_sheet_mng_year_yn").executeUpdate();
|
||||
|
||||
String sql =
|
||||
"""
|
||||
WITH bounds AS (
|
||||
SELECT
|
||||
map_sheet_num,
|
||||
MIN(mng_yyyy::int) AS min_y,
|
||||
MAX(mng_yyyy::int) AS max_y
|
||||
FROM tb_map_sheet_mng_files
|
||||
GROUP BY map_sheet_num
|
||||
),
|
||||
years AS (
|
||||
SELECT
|
||||
b.map_sheet_num,
|
||||
gs.y AS mng_yyyy
|
||||
FROM bounds b
|
||||
CROSS JOIN LATERAL generate_series(b.min_y, b.max_y) AS gs(y)
|
||||
),
|
||||
exist AS (
|
||||
SELECT DISTINCT
|
||||
map_sheet_num,
|
||||
mng_yyyy::int AS mng_yyyy
|
||||
FROM tb_map_sheet_mng_files
|
||||
),
|
||||
src AS (
|
||||
SELECT
|
||||
y.map_sheet_num,
|
||||
y.mng_yyyy,
|
||||
CASE
|
||||
WHEN e.map_sheet_num IS NULL THEN 'N'
|
||||
ELSE 'Y'
|
||||
END AS yn
|
||||
FROM years y
|
||||
LEFT JOIN exist e
|
||||
ON e.map_sheet_num = y.map_sheet_num
|
||||
AND e.mng_yyyy = y.mng_yyyy
|
||||
)
|
||||
INSERT INTO tb_map_sheet_mng_year_yn
|
||||
(map_sheet_num, mng_yyyy, yn)
|
||||
SELECT
|
||||
map_sheet_num,
|
||||
mng_yyyy,
|
||||
yn
|
||||
FROM src
|
||||
ON CONFLICT (map_sheet_num, mng_yyyy)
|
||||
DO UPDATE SET
|
||||
yn = EXCLUDED.yn,
|
||||
updated_dttm = now()
|
||||
""";
|
||||
|
||||
em.createNativeQuery(sql).executeUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 변화탐지 실행 가능 비교년도 조회
|
||||
*
|
||||
* @param mngYyyy
|
||||
* @param mapIds
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<MngListCompareDto> findByHstMapSheetCompareList(int mngYyyy, List<String> mapIds) {
|
||||
QMapSheetMngYearYnEntity y = QMapSheetMngYearYnEntity.mapSheetMngYearYnEntity;
|
||||
|
||||
StringExpression mngYyyyStr = Expressions.stringTemplate("concat({0}, '')", mngYyyy);
|
||||
|
||||
return queryFactory
|
||||
.select(
|
||||
Projections.constructor(
|
||||
MngListCompareDto.class, mngYyyyStr, y.id.mapSheetNum, y.id.mngYyyy.max()))
|
||||
.from(y)
|
||||
.where(y.id.mapSheetNum.in(mapIds), y.yn.eq("Y"), y.id.mngYyyy.loe(mngYyyy))
|
||||
.groupBy(y.id.mapSheetNum)
|
||||
.fetch();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
package com.kamco.cd.kamcoback.service;
|
||||
|
||||
import static java.lang.String.CASE_INSENSITIVE_ORDER;
|
||||
|
||||
import com.kamco.cd.kamcoback.dto.FileDto;
|
||||
import com.kamco.cd.kamcoback.dto.FileDto.SrchFilesDepthDto;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.DmlReturn;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngFileAddReq;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto.MngHstDto;
|
||||
import com.kamco.cd.kamcoback.enums.CommonUseStatus;
|
||||
import com.kamco.cd.kamcoback.postgres.core.MapSheetMngFileJobCoreService;
|
||||
import com.kamco.cd.kamcoback.utils.FIleChecker;
|
||||
import com.kamco.cd.kamcoback.utils.FIleChecker.Basic;
|
||||
import com.kamco.cd.kamcoback.dto.MapSheetMngDto;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class MapSheetMngFileJobService {
|
||||
|
||||
private final MapSheetMngFileJobCoreService mapSheetMngFileJobCoreService;
|
||||
|
||||
@Value("${file.sync-root-dir}")
|
||||
private String syncRootDir;
|
||||
|
||||
@Value("${file.sync-tmp-dir}")
|
||||
private String syncTmpDir;
|
||||
|
||||
@Value("${file.sync-file-extention}")
|
||||
private String syncFileExtention;
|
||||
|
||||
@Value("${file.sync-auto-exception-start-year}")
|
||||
private int syncAutoExceptionStartYear;
|
||||
|
||||
@Value("${file.sync-auto-exception-before-year-cnt}")
|
||||
private int syncAutoExceptionBeforeYearCnt;
|
||||
|
||||
public Integer checkMngFileSync() {
|
||||
return mapSheetMngFileJobCoreService.findNotYetMapSheetMng();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void checkMapSheetFileProcess(long targetNum, int mngSyncPageSize) {
|
||||
|
||||
List<MngHstDto> mapSheetFileNotYetList = findTargetMapSheetFileList(targetNum, mngSyncPageSize);
|
||||
|
||||
Long hstUid = 0L;
|
||||
String syncState = "";
|
||||
String syncCheckState = "";
|
||||
String fileState = "";
|
||||
String dataState = "";
|
||||
int mngYyyy = 0;
|
||||
|
||||
SrchFilesDepthDto srchDto = new SrchFilesDepthDto();
|
||||
List<Basic> basicList = new ArrayList<>();
|
||||
|
||||
if (mapSheetFileNotYetList.size() >= 1) {
|
||||
mngYyyy = mapSheetFileNotYetList.get(0).getMngYyyy();
|
||||
}
|
||||
|
||||
for (MngHstDto item : mapSheetFileNotYetList) {
|
||||
|
||||
// 5K도엽 자동추론제외
|
||||
Long exceptCheckCnt =
|
||||
this.mapSheetAutoExceptionUpdate(item.getMngYyyy(), item.getMapSheetNum());
|
||||
|
||||
// 도엽별 파일 체크 진행중으로 변경
|
||||
item.setDataState("PROCESSING");
|
||||
item.setUseInference("USE");
|
||||
if (exceptCheckCnt == 0) {
|
||||
item.setUseInference("EXCEPT");
|
||||
}
|
||||
mngHstDataSyncStateUpdate(item);
|
||||
|
||||
// 1. MngHstDto 객체의 필드 값에 접근
|
||||
srchDto.setMaxDepth(10);
|
||||
srchDto.setDirPath(item.getSyncMngPath());
|
||||
srchDto.setExtension("tif,tfw");
|
||||
srchDto.setFileNm(item.getMapSheetNum());
|
||||
|
||||
System.out.println(
|
||||
"UID: "
|
||||
+ hstUid
|
||||
+ ", 상태: "
|
||||
+ syncState
|
||||
+ ", 관리경로: "
|
||||
+ item.getSyncMngPath()
|
||||
+ ", 파일명 "
|
||||
+ item.getMapSheetNum()
|
||||
+ " .tif,tfw");
|
||||
|
||||
// 도엽번호로 파일 찾기
|
||||
basicList =
|
||||
FIleChecker.getFilesFromAllDepth(
|
||||
srchDto.getDirPath(),
|
||||
srchDto.getFileNm(),
|
||||
srchDto.getExtension(),
|
||||
srchDto.getMaxDepth(),
|
||||
srchDto.getSortType(),
|
||||
0,
|
||||
100);
|
||||
|
||||
int tfwCnt =
|
||||
(int)
|
||||
basicList.stream().filter(dto -> dto.getExtension().toString().equals("tfw")).count();
|
||||
|
||||
int tifCnt =
|
||||
(int)
|
||||
basicList.stream().filter(dto -> dto.getExtension().toString().equals("tif")).count();
|
||||
|
||||
syncState = "";
|
||||
syncCheckState = "";
|
||||
|
||||
if (tfwCnt == 0 && tifCnt == 0) {
|
||||
syncState = "NOFILE";
|
||||
}
|
||||
|
||||
for (Basic item2 : basicList) {
|
||||
MngFileAddReq addReq = new MngFileAddReq();
|
||||
addReq.setMngYyyy(item.getMngYyyy());
|
||||
addReq.setMapSheetNum(item.getMapSheetNum());
|
||||
addReq.setRefMapSheetNum(item.getRefMapSheetNum());
|
||||
addReq.setFilePath(item2.getParentPath());
|
||||
addReq.setFileName(item2.getFileNm());
|
||||
addReq.setFileExt(item2.getExtension());
|
||||
addReq.setFileSize(item2.getFileSize());
|
||||
addReq.setHstUid(item.getHstUid());
|
||||
|
||||
fileState = "DONE";
|
||||
if ("tfw".equalsIgnoreCase(item2.getExtension())) {
|
||||
if (tifCnt == 0) {
|
||||
fileState = "NOTPAIR";
|
||||
syncState = fileState;
|
||||
} else if (tfwCnt > 1) {
|
||||
fileState = "DUPLICATE";
|
||||
syncState = fileState;
|
||||
} else if (item2.getFileSize() == 0) {
|
||||
fileState = "TYPEERROR";
|
||||
syncState = fileState;
|
||||
} else if (!FIleChecker.checkTfw(item2.getFullPath())) {
|
||||
fileState = "TYPEERROR";
|
||||
syncState = fileState;
|
||||
}
|
||||
|
||||
item.setMapSheetPath(item2.getParentPath());
|
||||
item.setSyncTfwFileName(item2.getFileNm());
|
||||
|
||||
} else if ("tif".equalsIgnoreCase(item2.getExtension())) {
|
||||
if (tfwCnt == 0) {
|
||||
fileState = "NOTPAIR";
|
||||
syncState = fileState;
|
||||
} else if (tifCnt > 1) {
|
||||
fileState = "DUPLICATE";
|
||||
syncState = fileState;
|
||||
} else if (item2.getFileSize() == 0) {
|
||||
fileState = "TYPEERROR";
|
||||
syncState = fileState;
|
||||
} else if (!FIleChecker.cmmndGdalInfo(item2.getFullPath())) {
|
||||
fileState = "TYPEERROR";
|
||||
syncState = fileState;
|
||||
}
|
||||
|
||||
item.setMapSheetPath(item2.getParentPath());
|
||||
item.setSyncTifFileName(item2.getFileNm());
|
||||
}
|
||||
|
||||
addReq.setFileState(fileState);
|
||||
DmlReturn DmlReturn = mngDataSave(addReq);
|
||||
}
|
||||
|
||||
// 도엽별 파일 체크 완료로 변경
|
||||
item.setDataState("DONE");
|
||||
|
||||
if (syncState.isEmpty()) {
|
||||
syncState = "DONE";
|
||||
}
|
||||
|
||||
item.setSyncState(syncState);
|
||||
|
||||
mngHstDataSyncStateUpdate(item);
|
||||
}
|
||||
|
||||
// 사용할 수 있는 이전 년도 도엽 테이블 저장
|
||||
mapSheetMngFileJobCoreService.saveSheetMngYear();
|
||||
|
||||
Long notyetCnt = this.mngDataStateDoneUpdate(mngYyyy);
|
||||
}
|
||||
|
||||
public int checkIsNoFile(List<FileDto.Basic> basicList) {
|
||||
if (basicList == null || basicList.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return basicList.size();
|
||||
}
|
||||
|
||||
public Long mngDataStateDoneUpdate(int mngYyyy) {
|
||||
|
||||
Long notyetCnt = 0L;
|
||||
if (mngYyyy > 0) {
|
||||
notyetCnt = findByMngYyyyTargetMapSheetNotYetCount(mngYyyy);
|
||||
if (notyetCnt == 0) {
|
||||
mapSheetMngFileJobCoreService.mngDataState(mngYyyy, "DONE");
|
||||
} else {
|
||||
mapSheetMngFileJobCoreService.mngDataState(mngYyyy, "PROCESSING");
|
||||
}
|
||||
}
|
||||
|
||||
return notyetCnt;
|
||||
}
|
||||
|
||||
public Long mapSheetAutoExceptionUpdate(int mngYyyy, String mapSheetNum) {
|
||||
|
||||
// 2025년 이전 파일싱크는 무조건 이전3년이 존재하지 않으므로 자동추론제외를 진행하지 않는다.(전년도 파일이 무조건 존재하는 것으로 리턴)
|
||||
// if (syncAutoExceptionStartYear > mngYyyy) {
|
||||
// return 1L;
|
||||
// }
|
||||
|
||||
// int strtYyyy = mngYyyy - syncAutoExceptionBeforeYearCnt + 1;
|
||||
int strtYyyy = 2020;
|
||||
int endYyyy = mngYyyy;
|
||||
|
||||
// 본년도+이전년도가 3개년인 도엽 확인 -> 2020년도부터 현재까지
|
||||
Long beforeCnt =
|
||||
mapSheetMngFileJobCoreService.findByHstMapSheetBeforeYyyyListCount(
|
||||
strtYyyy, endYyyy, mapSheetNum);
|
||||
|
||||
if (beforeCnt == 0) {
|
||||
System.out.println("mapSheetAutoExceptionUpdate inference == 자동추론제외");
|
||||
mapSheetMngFileJobCoreService.updateException5kMapSheet(
|
||||
mapSheetNum, CommonUseStatus.AUTO_EXCEPT);
|
||||
} else {
|
||||
// 하나라도 있으면 USE
|
||||
mapSheetMngFileJobCoreService.updateException5kMapSheet(mapSheetNum, CommonUseStatus.USE);
|
||||
}
|
||||
|
||||
return beforeCnt;
|
||||
}
|
||||
|
||||
public List<MngHstDto> findTargetMapSheetFileList(long targetNum, int pageSize) {
|
||||
return mapSheetMngFileJobCoreService.findTargetMapSheetFileList(targetNum, pageSize);
|
||||
}
|
||||
|
||||
public Long findByMngYyyyTargetMapSheetNotYetCount(int mngYyyy) {
|
||||
return mapSheetMngFileJobCoreService.findByMngYyyyTargetMapSheetNotYetCount(mngYyyy);
|
||||
}
|
||||
|
||||
public DmlReturn mngHstDataSyncStateUpdate(MngHstDto UpdateReq) {
|
||||
return mapSheetMngFileJobCoreService.mngHstDataSyncStateUpdate(UpdateReq);
|
||||
}
|
||||
|
||||
public DmlReturn mngDataSave(MngFileAddReq AddReq) {
|
||||
return mapSheetMngFileJobCoreService.mngFileSave(AddReq);
|
||||
}
|
||||
|
||||
public List<FileDto.Basic> getFilesDepthAll(SrchFilesDepthDto srchDto) {
|
||||
|
||||
Path startPath = Paths.get(srchDto.getDirPath());
|
||||
int maxDepth = srchDto.getMaxDepth();
|
||||
String dirPath = srchDto.getDirPath();
|
||||
String targetFileNm = srchDto.getFileNm();
|
||||
String extension = srchDto.getExtension();
|
||||
String sortType = srchDto.getSortType();
|
||||
|
||||
int startPos = srchDto.getStartPos();
|
||||
int endPos = srchDto.getEndPos();
|
||||
int limit = endPos - startPos + 1;
|
||||
|
||||
Set<String> targetExtensions = createExtensionSet(extension);
|
||||
|
||||
List<FileDto.Basic> fileDtoList = new ArrayList<>();
|
||||
SimpleDateFormat dttmFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
int fileTotCnt = 0;
|
||||
long fileTotSize = 0;
|
||||
|
||||
try (Stream<Path> stream = Files.walk(startPath, maxDepth)) {
|
||||
|
||||
fileDtoList =
|
||||
stream
|
||||
.filter(Files::isRegularFile)
|
||||
.filter(
|
||||
p ->
|
||||
extension == null
|
||||
|| extension.equals("")
|
||||
|| extension.equals("*")
|
||||
|| targetExtensions.contains(extractExtension(p)))
|
||||
.sorted(getFileComparator(sortType))
|
||||
.filter(p -> p.getFileName().toString().contains(targetFileNm))
|
||||
.skip(startPos)
|
||||
.limit(limit)
|
||||
.map(
|
||||
path -> {
|
||||
int depth = path.getNameCount();
|
||||
|
||||
String fileNm = path.getFileName().toString();
|
||||
String ext = FilenameUtils.getExtension(fileNm);
|
||||
String parentFolderNm = path.getParent().getFileName().toString();
|
||||
String parentPath = path.getParent().toString();
|
||||
String fullPath = path.toAbsolutePath().toString();
|
||||
|
||||
File file = new File(fullPath);
|
||||
long fileSize = file.length();
|
||||
String lastModified = dttmFormat.format(new Date(file.lastModified()));
|
||||
|
||||
return new FileDto.Basic(
|
||||
fileNm, parentFolderNm, parentPath, fullPath, ext, fileSize, lastModified);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// fileTotCnt = fileDtoList.size();
|
||||
// fileTotSize = fileDtoList.stream().mapToLong(FileDto.Basic::getFileSize).sum();
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("파일 I/O 오류 발생: " + e.getMessage());
|
||||
}
|
||||
|
||||
return fileDtoList;
|
||||
}
|
||||
|
||||
public Set<String> createExtensionSet(String extensionString) {
|
||||
if (extensionString == null || extensionString.isBlank()) {
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
// "java, class" -> ["java", " class"] -> [".java", ".class"]
|
||||
return Arrays.stream(extensionString.split(","))
|
||||
.map(ext -> ext.trim())
|
||||
.filter(ext -> !ext.isEmpty())
|
||||
.map(ext -> "." + ext.toLowerCase())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public String extractExtension(Path path) {
|
||||
String filename = path.getFileName().toString();
|
||||
int lastDotIndex = filename.lastIndexOf('.');
|
||||
|
||||
// 확장자가 없거나 파일명이 .으로 끝나는 경우
|
||||
if (lastDotIndex == -1 || lastDotIndex == filename.length() - 1) {
|
||||
return ""; // 빈 문자열 반환
|
||||
}
|
||||
|
||||
// 확장자 추출 및 소문자 변환
|
||||
return filename.substring(lastDotIndex).toLowerCase();
|
||||
}
|
||||
|
||||
public Comparator<Path> getFileComparator(String sortType) {
|
||||
|
||||
// 파일 이름 비교 기본 Comparator (대소문자 무시)
|
||||
Comparator<Path> nameComparator =
|
||||
Comparator.comparing(path -> path.getFileName().toString(), CASE_INSENSITIVE_ORDER);
|
||||
|
||||
Comparator<Path> dateComparator =
|
||||
Comparator.comparing(
|
||||
path -> {
|
||||
try {
|
||||
return Files.getLastModifiedTime(path);
|
||||
} catch (IOException e) {
|
||||
return FileTime.fromMillis(0);
|
||||
}
|
||||
});
|
||||
|
||||
if ("name desc".equalsIgnoreCase(sortType)) {
|
||||
return nameComparator.reversed();
|
||||
} else if ("date".equalsIgnoreCase(sortType)) {
|
||||
return dateComparator;
|
||||
} else if ("date desc".equalsIgnoreCase(sortType)) {
|
||||
return dateComparator.reversed();
|
||||
} else {
|
||||
return nameComparator;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.kamco.cd.kamcoback.service;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class NameValidator {
|
||||
|
||||
private static final String HANGUL_REGEX = ".*\\p{IsHangul}.*";
|
||||
private static final Pattern HANGUL_PATTERN = Pattern.compile(HANGUL_REGEX);
|
||||
|
||||
private static final String WHITESPACE_REGEX = ".*\\s.*";
|
||||
private static final Pattern WHITESPACE_PATTERN = Pattern.compile(WHITESPACE_REGEX);
|
||||
|
||||
public static boolean containsKorean(String str) {
|
||||
if (str == null || str.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Matcher matcher = HANGUL_PATTERN.matcher(str);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
public static boolean containsWhitespaceRegex(String str) {
|
||||
if (str == null || str.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Matcher matcher = WHITESPACE_PATTERN.matcher(str);
|
||||
// find()를 사용하여 문자열 내에서 패턴이 일치하는 부분이 있는지 확인
|
||||
return matcher.find();
|
||||
}
|
||||
|
||||
public static boolean isNullOrEmpty(String str) {
|
||||
if (str == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (str.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
751
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/utils/FIleChecker.java
Executable file
751
imagery-make-dataset/src/main/java/com/kamco/cd/kamcoback/utils/FIleChecker.java
Executable file
@@ -0,0 +1,751 @@
|
||||
package com.kamco.cd.kamcoback.utils;
|
||||
|
||||
import static java.lang.String.CASE_INSENSITIVE_ORDER;
|
||||
|
||||
import com.kamco.cd.kamcoback.service.NameValidator;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.geotools.coverage.grid.GridCoverage2D;
|
||||
import org.geotools.gce.geotiff.GeoTiffReader;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
public class FIleChecker {
|
||||
|
||||
static SimpleDateFormat dttmFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public static boolean isValidFile(String pathStr) {
|
||||
|
||||
Path path = Paths.get(pathStr);
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Files.isRegularFile(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Files.isReadable(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (Files.size(path) <= 0) {
|
||||
return false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean verifyFileIntegrity(Path path, String expectedHash)
|
||||
throws IOException, NoSuchAlgorithmException {
|
||||
|
||||
// 1. 알고리즘 선택 (SHA-256 권장, MD5는 보안상 비추천)
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
|
||||
try (InputStream fis = Files.newInputStream(path)) {
|
||||
byte[] buffer = new byte[8192]; // 8KB 버퍼
|
||||
int bytesRead;
|
||||
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||
digest.update(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 계산된 바이트 배열을 16진수 문자열로 변환
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : digest.digest()) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
String actualHash = sb.toString();
|
||||
|
||||
return actualHash.equalsIgnoreCase(expectedHash);
|
||||
}
|
||||
|
||||
public static boolean checkTfw(String filePath) {
|
||||
|
||||
File file = new File(filePath);
|
||||
|
||||
if (!file.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1. 파일의 모든 라인을 읽어옴
|
||||
List<Double> lines = new ArrayList<>();
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (!line.trim().isEmpty()) { // 빈 줄 제외
|
||||
lines.add(Double.parseDouble(line.trim()));
|
||||
}
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 6줄이 맞는지 확인
|
||||
if (lines.size() < 6) {
|
||||
// System.out.println("유효하지 않은 TFW 파일입니다. (데이터 부족)");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean checkGeoTiff(String filePath) {
|
||||
|
||||
File file = new File(filePath);
|
||||
|
||||
if (!file.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GeoTiffReader reader = null;
|
||||
try {
|
||||
// 1. 파일 포맷 및 헤더 확인
|
||||
reader = new GeoTiffReader(file);
|
||||
|
||||
// 2. 실제 데이터 로딩 (여기서 파일 깨짐 여부 확인됨)
|
||||
// null을 넣으면 전체 영역을 읽지 않고 메타데이터 위주로 체크하여 빠름
|
||||
GridCoverage2D coverage = reader.read(null);
|
||||
|
||||
if (coverage == null) return false;
|
||||
|
||||
// 3. GIS 필수 정보(좌표계)가 있는지 확인
|
||||
// if (coverage.getCoordinateReferenceSystem() == null) {
|
||||
// GeoTIFF가 아니라 일반 TIFF일 수도 있음(이미지는 정상이지만, 좌표계(CRS) 정보가 없습니다.)
|
||||
// }
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("손상된 TIF 파일입니다: " + e.getMessage());
|
||||
return false;
|
||||
} finally {
|
||||
// 리소스 해제 (필수)
|
||||
if (reader != null) reader.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean cmmndGdalInfo(String filePath) {
|
||||
|
||||
File file = new File(filePath);
|
||||
|
||||
if (!file.exists()) {
|
||||
System.err.println("파일이 존재하지 않습니다: " + filePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasDriver = false;
|
||||
|
||||
// 운영체제 감지
|
||||
String osName = System.getProperty("os.name").toLowerCase();
|
||||
boolean isWindows = osName.contains("win");
|
||||
boolean isMac = osName.contains("mac");
|
||||
boolean isUnix = osName.contains("nix") || osName.contains("nux") || osName.contains("aix");
|
||||
|
||||
// gdalinfo 경로 찾기 (일반적인 설치 경로 우선 확인)
|
||||
String gdalinfoPath = findGdalinfoPath();
|
||||
if (gdalinfoPath == null) {
|
||||
System.err.println("gdalinfo 명령어를 찾을 수 없습니다. GDAL이 설치되어 있는지 확인하세요.");
|
||||
System.err.println("macOS: brew install gdal");
|
||||
System.err.println("Ubuntu/Debian: sudo apt-get install gdal-bin");
|
||||
System.err.println("CentOS/RHEL: sudo yum install gdal");
|
||||
return false;
|
||||
}
|
||||
|
||||
List<String> command = new ArrayList<>();
|
||||
|
||||
if (isWindows) {
|
||||
// 윈도우용
|
||||
command.add("cmd.exe"); // 윈도우 명령 프롬프트 실행
|
||||
command.add("/c"); // 명령어를 수행하고 종료한다는 옵션
|
||||
command.add("gdalinfo");
|
||||
command.add(filePath);
|
||||
command.add("|");
|
||||
command.add("findstr");
|
||||
command.add("/i");
|
||||
command.add("Geo");
|
||||
} else if (isMac || isUnix) {
|
||||
// 리눅스, 맥용
|
||||
command.add("sh");
|
||||
command.add("-c");
|
||||
command.add(gdalinfoPath + " \"" + filePath + "\" | grep -i Geo");
|
||||
} else {
|
||||
System.err.println("지원하지 않는 운영체제: " + osName);
|
||||
return false;
|
||||
}
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||
processBuilder.redirectErrorStream(true);
|
||||
|
||||
Process process = null;
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
System.out.println("gdalinfo 명령어 실행 시작: " + filePath);
|
||||
process = processBuilder.start();
|
||||
|
||||
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
// System.out.println("gdalinfo 출력: " + line);
|
||||
if (line.contains("Driver: GTiff/GeoTIFF")) {
|
||||
hasDriver = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int exitCode = process.waitFor();
|
||||
System.out.println("gdalinfo 종료 코드: " + exitCode);
|
||||
|
||||
// 프로세스가 정상 종료되지 않았고 Driver를 찾지 못한 경우
|
||||
if (exitCode != 0 && !hasDriver) {
|
||||
System.err.println("gdalinfo 명령 실행 실패. Exit code: " + exitCode);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("gdalinfo 실행 중 I/O 오류 발생: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (InterruptedException e) {
|
||||
System.err.println("gdalinfo 실행 중 인터럽트 발생: " + e.getMessage());
|
||||
Thread.currentThread().interrupt();
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
System.err.println("gdalinfo 실행 중 예상치 못한 오류 발생: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} finally {
|
||||
// 리소스 정리
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
System.err.println("BufferedReader 종료 중 오류: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
if (process != null) {
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
return hasDriver;
|
||||
}
|
||||
|
||||
public static boolean mkDir(String dirPath) {
|
||||
Path uploadTargetPath = Paths.get(dirPath);
|
||||
try {
|
||||
Files.createDirectories(uploadTargetPath);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static List<Folder> getFolderAll(String dirPath, String sortType, int maxDepth) {
|
||||
|
||||
Path startPath = Paths.get(dirPath);
|
||||
|
||||
List<Folder> folderList = List.of();
|
||||
|
||||
try (Stream<Path> stream = Files.walk(startPath, maxDepth)) {
|
||||
|
||||
folderList =
|
||||
stream
|
||||
.filter(Files::isDirectory)
|
||||
.filter(p -> !p.toString().equals(dirPath))
|
||||
.map(
|
||||
path -> {
|
||||
int depth = path.getNameCount();
|
||||
|
||||
String folderNm = path.getFileName().toString();
|
||||
String parentFolderNm = path.getParent().getFileName().toString();
|
||||
String parentPath = path.getParent().toString();
|
||||
String fullPath = path.toAbsolutePath().toString();
|
||||
|
||||
boolean isValid =
|
||||
!NameValidator.containsKorean(folderNm)
|
||||
&& !NameValidator.containsWhitespaceRegex(folderNm);
|
||||
|
||||
File file = new File(fullPath);
|
||||
int childCnt = getChildFolderCount(file);
|
||||
String lastModified = getLastModified(file);
|
||||
|
||||
return new Folder(
|
||||
folderNm,
|
||||
parentFolderNm,
|
||||
parentPath,
|
||||
fullPath,
|
||||
depth,
|
||||
childCnt,
|
||||
lastModified,
|
||||
isValid);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (sortType.equals("name") || sortType.equals("name asc")) {
|
||||
folderList.sort(
|
||||
Comparator.comparing(
|
||||
Folder::getFolderNm, CASE_INSENSITIVE_ORDER // 대소문자 구분 없이
|
||||
));
|
||||
} else if (sortType.equals("name desc")) {
|
||||
folderList.sort(
|
||||
Comparator.comparing(
|
||||
Folder::getFolderNm, CASE_INSENSITIVE_ORDER // 대소문자 구분 없이
|
||||
)
|
||||
.reversed());
|
||||
} else if (sortType.equals("dttm desc")) {
|
||||
folderList.sort(
|
||||
Comparator.comparing(
|
||||
Folder::getLastModified, CASE_INSENSITIVE_ORDER // 대소문자 구분 없이
|
||||
)
|
||||
.reversed());
|
||||
} else {
|
||||
folderList.sort(
|
||||
Comparator.comparing(
|
||||
Folder::getLastModified, CASE_INSENSITIVE_ORDER // 대소문자 구분 없이
|
||||
));
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return folderList;
|
||||
}
|
||||
|
||||
public static List<Folder> getFolderAll(String dirPath) {
|
||||
return getFolderAll(dirPath, "name", 1);
|
||||
}
|
||||
|
||||
public static List<Folder> getFolderAll(String dirPath, String sortType) {
|
||||
return getFolderAll(dirPath, sortType, 1);
|
||||
}
|
||||
|
||||
public static int getChildFolderCount(String dirPath) {
|
||||
File directory = new File(dirPath);
|
||||
File[] childFolders = directory.listFiles(File::isDirectory);
|
||||
|
||||
int childCnt = 0;
|
||||
if (childFolders != null) {
|
||||
childCnt = childFolders.length;
|
||||
}
|
||||
|
||||
return childCnt;
|
||||
}
|
||||
|
||||
public static int getChildFolderCount(File directory) {
|
||||
File[] childFolders = directory.listFiles(File::isDirectory);
|
||||
|
||||
int childCnt = 0;
|
||||
if (childFolders != null) {
|
||||
childCnt = childFolders.length;
|
||||
}
|
||||
|
||||
return childCnt;
|
||||
}
|
||||
|
||||
public static String getLastModified(String dirPath) {
|
||||
File file = new File(dirPath);
|
||||
return dttmFormat.format(new Date(file.lastModified()));
|
||||
}
|
||||
|
||||
public static String getLastModified(File file) {
|
||||
return dttmFormat.format(new Date(file.lastModified()));
|
||||
}
|
||||
|
||||
public static List<Basic> getFilesFromAllDepth(
|
||||
String dir,
|
||||
String targetFileNm,
|
||||
String extension,
|
||||
int maxDepth,
|
||||
String sortType,
|
||||
int startPos,
|
||||
int endPos) {
|
||||
|
||||
Path startPath = Paths.get(dir);
|
||||
String dirPath = dir;
|
||||
|
||||
int limit = endPos - startPos + 1;
|
||||
|
||||
Set<String> targetExtensions = createExtensionSet(extension);
|
||||
|
||||
List<Basic> fileList = new ArrayList<>();
|
||||
SimpleDateFormat dttmFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
Predicate<Path> isTargetName =
|
||||
p -> {
|
||||
if (targetFileNm == null
|
||||
|| targetFileNm.trim().isEmpty()
|
||||
|| targetFileNm.trim().equals("*")) {
|
||||
return true; // 전체 파일 허용
|
||||
}
|
||||
return p.getFileName().toString().contains(targetFileNm);
|
||||
};
|
||||
|
||||
try (Stream<Path> stream = Files.walk(startPath, maxDepth)) {
|
||||
|
||||
fileList =
|
||||
stream
|
||||
.filter(Files::isRegularFile)
|
||||
.filter(
|
||||
p ->
|
||||
extension == null
|
||||
|| extension.equals("")
|
||||
|| extension.equals("*")
|
||||
|| targetExtensions.contains(extractExtension(p)))
|
||||
.sorted(getFileComparator(sortType))
|
||||
.filter(isTargetName)
|
||||
.skip(startPos)
|
||||
.limit(limit)
|
||||
.map(
|
||||
path -> {
|
||||
// int depth = path.getNameCount();
|
||||
|
||||
String fileNm = path.getFileName().toString();
|
||||
String ext = FilenameUtils.getExtension(fileNm);
|
||||
String parentFolderNm = path.getParent().getFileName().toString();
|
||||
String parentPath = path.getParent().toString();
|
||||
String fullPath = path.toAbsolutePath().toString();
|
||||
|
||||
File file = new File(fullPath);
|
||||
long fileSize = file.length();
|
||||
String lastModified = dttmFormat.format(new Date(file.lastModified()));
|
||||
|
||||
return new Basic(
|
||||
fileNm, parentFolderNm, parentPath, fullPath, ext, fileSize, lastModified);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("파일 I/O 오류 발생: " + e.getMessage());
|
||||
}
|
||||
|
||||
return fileList;
|
||||
}
|
||||
|
||||
public static List<Basic> getFilesFromAllDepth(
|
||||
String dir, String targetFileNm, String extension) {
|
||||
|
||||
return FIleChecker.getFilesFromAllDepth(dir, targetFileNm, extension, 100, "name", 0, 100);
|
||||
}
|
||||
|
||||
public static int getFileCountFromAllDepth(String dir, String targetFileNm, String extension) {
|
||||
|
||||
List<Basic> basicList = FIleChecker.getFilesFromAllDepth(dir, targetFileNm, extension);
|
||||
|
||||
return (int)
|
||||
basicList.stream().filter(dto -> dto.getExtension().toString().equals(extension)).count();
|
||||
}
|
||||
|
||||
public static Long getFileTotSize(List<Basic> files) {
|
||||
|
||||
Long fileTotSize = 0L;
|
||||
if (files != null || files.size() > 0) {
|
||||
fileTotSize = files.stream().mapToLong(Basic::getFileSize).sum();
|
||||
}
|
||||
|
||||
return fileTotSize;
|
||||
}
|
||||
|
||||
public static boolean multipartSaveTo(MultipartFile mfile, String targetPath) {
|
||||
Path tmpSavePath = Paths.get(targetPath);
|
||||
|
||||
boolean fileUpload = true;
|
||||
try {
|
||||
mfile.transferTo(tmpSavePath);
|
||||
} catch (IOException e) {
|
||||
// throw new RuntimeException(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean multipartChunkSaveTo(
|
||||
MultipartFile mfile, String targetPath, int chunkIndex) {
|
||||
File dest = new File(targetPath, String.valueOf(chunkIndex));
|
||||
|
||||
boolean fileUpload = true;
|
||||
try {
|
||||
mfile.transferTo(dest);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean deleteFolder(String path) {
|
||||
return FileSystemUtils.deleteRecursively(new File(path));
|
||||
}
|
||||
|
||||
public static boolean deleteFile(String filePath) {
|
||||
Path path = Paths.get(filePath);
|
||||
try {
|
||||
return Files.deleteIfExists(path);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean validationMultipart(MultipartFile mfile) {
|
||||
// 파일 유효성 검증
|
||||
if (mfile == null || mfile.isEmpty() || mfile.getSize() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void unzip(String fileName, String destDirectory) throws IOException {
|
||||
File destDir = new File(destDirectory);
|
||||
if (!destDir.exists()) {
|
||||
destDir.mkdirs(); // 대상 폴더가 없으면 생성
|
||||
}
|
||||
|
||||
String zipFilePath = destDirectory + "/" + fileName;
|
||||
|
||||
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFilePath))) {
|
||||
ZipEntry zipEntry = zis.getNextEntry();
|
||||
|
||||
while (zipEntry != null) {
|
||||
File newFile = newFile(destDir, zipEntry);
|
||||
|
||||
if (zipEntry.isDirectory()) {
|
||||
if (!newFile.isDirectory() && !newFile.mkdirs()) {
|
||||
throw new IOException("디렉토리 생성 실패: " + newFile);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// 상위 디렉토리가 없는 경우 생성
|
||||
File parent = newFile.getParentFile();
|
||||
if (!parent.exists() && !parent.mkdirs()) {
|
||||
throw new IOException("상위 디렉토리 생성 실패: " + parent);
|
||||
}
|
||||
|
||||
// 실제 파일 쓰기
|
||||
try (FileOutputStream fos = new FileOutputStream(newFile)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
zipEntry = zis.getNextEntry();
|
||||
}
|
||||
zis.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
|
||||
File destFile = new File(destinationDir, zipEntry.getName());
|
||||
|
||||
String destDirPath = destinationDir.getCanonicalPath();
|
||||
String destFilePath = destFile.getCanonicalPath();
|
||||
|
||||
if (!destFilePath.startsWith(destDirPath + File.separator)) {
|
||||
throw new IOException("엔트리가 대상 디렉토리를 벗어남: " + zipEntry.getName());
|
||||
}
|
||||
|
||||
return destFile;
|
||||
}
|
||||
|
||||
public static boolean checkExtensions(String fileName, String ext) {
|
||||
if (fileName == null) return false;
|
||||
|
||||
if (!fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase().equals(ext)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Set<String> createExtensionSet(String extensionString) {
|
||||
if (extensionString == null || extensionString.isBlank()) {
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
// "java, class" -> ["java", " class"] -> [".java", ".class"]
|
||||
return Arrays.stream(extensionString.split(","))
|
||||
.map(ext -> ext.trim())
|
||||
.filter(ext -> !ext.isEmpty())
|
||||
.map(ext -> "." + ext.toLowerCase())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static String extractExtension(Path path) {
|
||||
String filename = path.getFileName().toString();
|
||||
int lastDotIndex = filename.lastIndexOf('.');
|
||||
|
||||
// 확장자가 없거나 파일명이 .으로 끝나는 경우
|
||||
if (lastDotIndex == -1 || lastDotIndex == filename.length() - 1) {
|
||||
return ""; // 빈 문자열 반환
|
||||
}
|
||||
|
||||
// 확장자 추출 및 소문자 변환
|
||||
return filename.substring(lastDotIndex).toLowerCase();
|
||||
}
|
||||
|
||||
public static Comparator<Path> getFileComparator(String sortType) {
|
||||
|
||||
// 파일 이름 비교 기본 Comparator (대소문자 무시)
|
||||
Comparator<Path> nameComparator =
|
||||
Comparator.comparing(path -> path.getFileName().toString(), CASE_INSENSITIVE_ORDER);
|
||||
|
||||
Comparator<Path> dateComparator =
|
||||
Comparator.comparing(
|
||||
path -> {
|
||||
try {
|
||||
return Files.getLastModifiedTime(path);
|
||||
} catch (IOException e) {
|
||||
return FileTime.fromMillis(0);
|
||||
}
|
||||
});
|
||||
|
||||
if ("name desc".equalsIgnoreCase(sortType)) {
|
||||
return nameComparator.reversed();
|
||||
} else if ("date".equalsIgnoreCase(sortType)) {
|
||||
return dateComparator;
|
||||
} else if ("date desc".equalsIgnoreCase(sortType)) {
|
||||
return dateComparator.reversed();
|
||||
} else {
|
||||
return nameComparator;
|
||||
}
|
||||
}
|
||||
|
||||
private static String findGdalinfoPath() {
|
||||
// 일반적인 설치 경로 확인
|
||||
String[] possiblePaths = {
|
||||
"/usr/local/bin/gdalinfo", // Homebrew (macOS)
|
||||
"/opt/homebrew/bin/gdalinfo", // Homebrew (Apple Silicon macOS)
|
||||
"/usr/bin/gdalinfo", // Linux
|
||||
"gdalinfo" // PATH에 있는 경우
|
||||
};
|
||||
|
||||
for (String path : possiblePaths) {
|
||||
if (isCommandAvailable(path)) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isCommandAvailable(String command) {
|
||||
try {
|
||||
ProcessBuilder pb = new ProcessBuilder(command, "--version");
|
||||
pb.redirectErrorStream(true);
|
||||
Process process = pb.start();
|
||||
|
||||
// 프로세스 완료 대기 (최대 5초)
|
||||
boolean finished = process.waitFor(5, java.util.concurrent.TimeUnit.SECONDS);
|
||||
|
||||
if (!finished) {
|
||||
process.destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 종료 코드가 0이면 정상 (일부 명령어는 --version에서 다른 코드 반환할 수 있음)
|
||||
return process.exitValue() == 0 || process.exitValue() == 1;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "Folder", description = "폴더 정보")
|
||||
@Getter
|
||||
public static class Folder {
|
||||
private final String folderNm;
|
||||
private final String parentFolderNm;
|
||||
private final String parentPath;
|
||||
private final String fullPath;
|
||||
private final int depth;
|
||||
private final long childCnt;
|
||||
private final String lastModified;
|
||||
private final Boolean isValid;
|
||||
|
||||
public Folder(
|
||||
String folderNm,
|
||||
String parentFolderNm,
|
||||
String parentPath,
|
||||
String fullPath,
|
||||
int depth,
|
||||
long childCnt,
|
||||
String lastModified,
|
||||
Boolean isValid) {
|
||||
this.folderNm = folderNm;
|
||||
this.parentFolderNm = parentFolderNm;
|
||||
this.parentPath = parentPath;
|
||||
this.fullPath = fullPath;
|
||||
this.depth = depth;
|
||||
this.childCnt = childCnt;
|
||||
this.lastModified = lastModified;
|
||||
this.isValid = isValid;
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(name = "File Basic", description = "파일 기본 정보")
|
||||
@Getter
|
||||
public static class Basic {
|
||||
|
||||
private final String fileNm;
|
||||
private final String parentFolderNm;
|
||||
private final String parentPath;
|
||||
private final String fullPath;
|
||||
private final String extension;
|
||||
private final long fileSize;
|
||||
private final String lastModified;
|
||||
|
||||
public Basic(
|
||||
String fileNm,
|
||||
String parentFolderNm,
|
||||
String parentPath,
|
||||
String fullPath,
|
||||
String extension,
|
||||
long fileSize,
|
||||
String lastModified) {
|
||||
this.fileNm = fileNm;
|
||||
this.parentFolderNm = parentFolderNm;
|
||||
this.parentPath = parentPath;
|
||||
this.fullPath = fullPath;
|
||||
this.extension = extension;
|
||||
this.fileSize = fileSize;
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
}
|
||||
}
|
||||
4
imagery-make-dataset/src/main/resources/application.yml
Executable file
4
imagery-make-dataset/src/main/resources/application.yml
Executable file
@@ -0,0 +1,4 @@
|
||||
server:
|
||||
port: 9080
|
||||
|
||||
|
||||
67
imagery-make-dataset/src/main/resources/application_dev.yml
Executable file
67
imagery-make-dataset/src/main/resources/application_dev.yml
Executable file
@@ -0,0 +1,67 @@
|
||||
server:
|
||||
port: 9080
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: imagery-make-dataset
|
||||
profiles:
|
||||
active: dev # 사용할 프로파일 지정 (ex. dev, prod, test)
|
||||
|
||||
datasource:
|
||||
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
||||
#url: jdbc:postgresql://localhost:5432/kamco_cds
|
||||
username: kamco_cds
|
||||
password: kamco_cds_Q!W@E#R$
|
||||
hikari:
|
||||
minimum-idle: 1
|
||||
maximum-pool-size: 5
|
||||
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update # 테이블이 없으면 생성, 있으면 업데이트
|
||||
properties:
|
||||
hibernate:
|
||||
jdbc:
|
||||
batch_size: 50
|
||||
default_batch_fetch_size: 100
|
||||
logging:
|
||||
level:
|
||||
root: INFO
|
||||
org.springframework.web: DEBUG
|
||||
org.springframework.security: DEBUG
|
||||
|
||||
# 헬스체크 노이즈 핵심만 다운
|
||||
org.springframework.security.web.FilterChainProxy: INFO
|
||||
org.springframework.security.web.authentication.AnonymousAuthenticationFilter: INFO
|
||||
org.springframework.security.web.authentication.Http403ForbiddenEntryPoint: INFO
|
||||
org.springframework.web.servlet.DispatcherServlet: INFO
|
||||
# actuator
|
||||
management:
|
||||
health:
|
||||
readinessstate:
|
||||
enabled: true
|
||||
livenessstate:
|
||||
enabled: true
|
||||
endpoint:
|
||||
health:
|
||||
probes:
|
||||
enabled: true
|
||||
show-details: always
|
||||
endpoints:
|
||||
jmx:
|
||||
exposure:
|
||||
exclude: "*"
|
||||
web:
|
||||
base-path: /monitor
|
||||
exposure:
|
||||
include:
|
||||
- "health"
|
||||
|
||||
file:
|
||||
#sync-root-dir: D:/kamco-nfs/images/
|
||||
sync-root-dir: /kamco-nfs/images/
|
||||
sync-tmp-dir: ${file.sync-root-dir}/tmp
|
||||
sync-file-extention: tfw,tif
|
||||
sync-auto-exception-start-year: 2025
|
||||
sync-auto-exception-before-year-cnt: 3
|
||||
|
||||
67
imagery-make-dataset/src/main/resources/application_local.yml
Executable file
67
imagery-make-dataset/src/main/resources/application_local.yml
Executable file
@@ -0,0 +1,67 @@
|
||||
server:
|
||||
port: 9080
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: imagery-make-dataset
|
||||
profiles:
|
||||
active: local # 사용할 프로파일 지정 (ex. dev, prod, test)
|
||||
|
||||
datasource:
|
||||
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
||||
#url: jdbc:postgresql://localhost:5432/kamco_cds
|
||||
username: kamco_cds
|
||||
password: kamco_cds_Q!W@E#R$
|
||||
hikari:
|
||||
minimum-idle: 1
|
||||
maximum-pool-size: 5
|
||||
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update # 테이블이 없으면 생성, 있으면 업데이트
|
||||
properties:
|
||||
hibernate:
|
||||
jdbc:
|
||||
batch_size: 50
|
||||
default_batch_fetch_size: 100
|
||||
logging:
|
||||
level:
|
||||
root: INFO
|
||||
org.springframework.web: DEBUG
|
||||
org.springframework.security: DEBUG
|
||||
|
||||
# 헬스체크 노이즈 핵심만 다운
|
||||
org.springframework.security.web.FilterChainProxy: INFO
|
||||
org.springframework.security.web.authentication.AnonymousAuthenticationFilter: INFO
|
||||
org.springframework.security.web.authentication.Http403ForbiddenEntryPoint: INFO
|
||||
org.springframework.web.servlet.DispatcherServlet: INFO
|
||||
# actuator
|
||||
management:
|
||||
health:
|
||||
readinessstate:
|
||||
enabled: true
|
||||
livenessstate:
|
||||
enabled: true
|
||||
endpoint:
|
||||
health:
|
||||
probes:
|
||||
enabled: true
|
||||
show-details: always
|
||||
endpoints:
|
||||
jmx:
|
||||
exposure:
|
||||
exclude: "*"
|
||||
web:
|
||||
base-path: /monitor
|
||||
exposure:
|
||||
include:
|
||||
- "health"
|
||||
|
||||
file:
|
||||
#sync-root-dir: D:/kamco-nfs/images/
|
||||
sync-root-dir: /kamco-nfs/images/
|
||||
sync-tmp-dir: ${file.sync-root-dir}/tmp
|
||||
sync-file-extention: tfw,tif
|
||||
sync-auto-exception-start-year: 2025
|
||||
sync-auto-exception-before-year-cnt: 3
|
||||
|
||||
67
imagery-make-dataset/src/main/resources/application_prod.yml
Executable file
67
imagery-make-dataset/src/main/resources/application_prod.yml
Executable file
@@ -0,0 +1,67 @@
|
||||
server:
|
||||
port: 9080
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: imagery-make-dataset
|
||||
profiles:
|
||||
active: prod # 사용할 프로파일 지정 (ex. dev, prod, test)
|
||||
|
||||
datasource:
|
||||
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
||||
#url: jdbc:postgresql://localhost:5432/kamco_cds
|
||||
username: kamco_cds
|
||||
password: kamco_cds_Q!W@E#R$
|
||||
hikari:
|
||||
minimum-idle: 1
|
||||
maximum-pool-size: 5
|
||||
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update # 테이블이 없으면 생성, 있으면 업데이트
|
||||
properties:
|
||||
hibernate:
|
||||
jdbc:
|
||||
batch_size: 50
|
||||
default_batch_fetch_size: 100
|
||||
logging:
|
||||
level:
|
||||
root: INFO
|
||||
org.springframework.web: DEBUG
|
||||
org.springframework.security: DEBUG
|
||||
|
||||
# 헬스체크 노이즈 핵심만 다운
|
||||
org.springframework.security.web.FilterChainProxy: INFO
|
||||
org.springframework.security.web.authentication.AnonymousAuthenticationFilter: INFO
|
||||
org.springframework.security.web.authentication.Http403ForbiddenEntryPoint: INFO
|
||||
org.springframework.web.servlet.DispatcherServlet: INFO
|
||||
# actuator
|
||||
management:
|
||||
health:
|
||||
readinessstate:
|
||||
enabled: true
|
||||
livenessstate:
|
||||
enabled: true
|
||||
endpoint:
|
||||
health:
|
||||
probes:
|
||||
enabled: true
|
||||
show-details: always
|
||||
endpoints:
|
||||
jmx:
|
||||
exposure:
|
||||
exclude: "*"
|
||||
web:
|
||||
base-path: /monitor
|
||||
exposure:
|
||||
include:
|
||||
- "health"
|
||||
|
||||
file:
|
||||
#sync-root-dir: D:/kamco-nfs/images/
|
||||
sync-root-dir: /kamco-nfs/images/
|
||||
sync-tmp-dir: ${file.sync-root-dir}/tmp
|
||||
sync-file-extention: tfw,tif
|
||||
sync-auto-exception-start-year: 2025
|
||||
sync-auto-exception-before-year-cnt: 3
|
||||
|
||||
137
imagery-make-dataset/src/main/resources/static/chunk_upload_test.html
Executable file
137
imagery-make-dataset/src/main/resources/static/chunk_upload_test.html
Executable file
@@ -0,0 +1,137 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Chunk Upload Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>대용량 파일 청크 업로드 테스트</h2>
|
||||
|
||||
* Chunk 테스트 사이즈 10M (10 * 1024 * 1024) - 성능에 따라 변경가능<br><br>
|
||||
|
||||
* 업로드 API선택</br></br>
|
||||
<select name="apiUrl" id="apiUrl" style="width:600px;height:40px;">
|
||||
<option value="/api/model/file-chunk-upload">모델파일Chunk업로드 ( /api/model/file-chunk-upload )</option>
|
||||
<option value="/api/upload/file-chunk-upload">파일Chunk업로드(공통) ( /api/upload/file-chunk-upload )</option>
|
||||
</select>
|
||||
<br><br>
|
||||
* 파일첨부<br><br>
|
||||
<input type="file" id="chunkFile" style="height:40px;"><br><br>
|
||||
<button onclick="startUpload()" style="height:40px;">업로드 시작</button>
|
||||
<br><br><br><br>
|
||||
* 업로드시 업로드 이력을 추적하기 위해 UUID생성해서 전달(파일병합시 사용)(script 예제참고)</br></br>
|
||||
UUID : <input id="uuid" name="uuid" value="" style="width:300px;height:30px;" readonly><br><br>
|
||||
|
||||
* API 호출시 파일정보 추출해서 자동 할당해야 함.(script 예제참고)</br></br>
|
||||
chunkIndex : <input style="height:30px;" id="chunkIndex" placeholder="chunkIndex" readonly><br><br>
|
||||
chunkTotalIndex : <input style="height:30px;" id="chunkTotalIndex" placeholder="chunkTotalIndex" readonly ><br><br>
|
||||
|
||||
* API 호출시 파일정보 추출해서 자동 할당해야 함.(script 예제참고)</br></br>
|
||||
fileSize : <input style="height:30px;" id="fileSize" placeholder="fileSize" readonly><br><br>
|
||||
<!--
|
||||
fileHash : <input id="fileHash" placeholder="fileHash"><br><br> -->
|
||||
|
||||
|
||||
<br><br>
|
||||
* 진행율(%)</br></br>
|
||||
<div style="width:500px;height:30px;border:1px solid #cccccc;"><div id="prgssbar" style="width:100%;height:30px;background:#eeeeee;"></div></div>
|
||||
<br><br>
|
||||
* 결과메세지</br></br>
|
||||
<div id="status" style="padding:20px;width:1200px;height:600px;border:1px solid #000000;"></div>
|
||||
|
||||
<script>
|
||||
async function startUpload() {
|
||||
|
||||
const apiUrl = document.getElementById('apiUrl').value;
|
||||
const file = document.getElementById('chunkFile').files[0];
|
||||
const fileName = file.name;
|
||||
//const datasetUid = Number(document.getElementById('datasetUid').value);
|
||||
//const chunkIndex = document.getElementById('chunkIndex').value;
|
||||
if (!file) return alert("파일을 선택하세요.");
|
||||
|
||||
const CHUNK_SIZE = 10 * 1024 * 1024; // 5MB
|
||||
const fileSize = file.size;
|
||||
var totalChunks = Math.ceil(fileSize / CHUNK_SIZE);
|
||||
const chunkTotalIndex = totalChunks - 1;
|
||||
const uuid = crypto.randomUUID(); // 고유 ID 생성
|
||||
|
||||
//var uuid = "";
|
||||
|
||||
|
||||
document.getElementById('uuid').value = uuid;
|
||||
document.getElementById('fileSize').value = file.size;
|
||||
document.getElementById('chunkTotalIndex').value = chunkTotalIndex;
|
||||
|
||||
|
||||
for (let i = 0; i < totalChunks; i++) {
|
||||
//for (let i = 0; i < 1; i++) {
|
||||
const start = i * CHUNK_SIZE;
|
||||
const end = Math.min(start + CHUNK_SIZE, file.size);
|
||||
const chunk = file.slice(start, end);
|
||||
|
||||
document.getElementById('chunkIndex').value = i;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("uuid", uuid);
|
||||
formData.append("fileSize", fileSize);
|
||||
formData.append("fileName", fileName);
|
||||
formData.append("chunkIndex", i);
|
||||
formData.append("chunkTotalIndex", chunkTotalIndex);
|
||||
formData.append("chunkFile", chunk);
|
||||
|
||||
try {
|
||||
const response = await fetch(apiUrl, { method: 'POST', body: formData });
|
||||
|
||||
// 2. 응답 상태 확인 (200 OK 등)
|
||||
if (!response.ok) {
|
||||
throw new Error(`서버 에러: ${response.status}`);
|
||||
}
|
||||
|
||||
// 3. 서버가 보낸 데이터 읽기 (JSON 형태라고 가정)
|
||||
const result = await response.json();
|
||||
document.getElementById('status').innerText = JSON.stringify(result, null, 2);
|
||||
if( result.data.res != "success")
|
||||
{
|
||||
//오류 경고창 띄우는 것으로 처리하시면 됩니다.
|
||||
break;
|
||||
}
|
||||
|
||||
document.getElementById('prgssbar').style.width = result.data.uploadRate+"%";
|
||||
|
||||
} catch (error) {
|
||||
console.error(`${i}번째 청크 업로드 실패:`, error);
|
||||
break; // 오류 발생 시 중단
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 모든 청크 전송 후 최종 완료 요청
|
||||
//var mergeResult = await completeUpload(uuid);
|
||||
//document.getElementById('status').innerText = JSON.stringify(mergeResult, null, 2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
async function completeUpload(uuid) {
|
||||
try {
|
||||
const response = await fetch(`/api/upload/chunk-upload-complete/${uuid}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`서ver 응답 에러: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result;
|
||||
|
||||
} catch (error) {
|
||||
console.error("완료 요청 중 오류 발생:", error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user