파일생성 추가

This commit is contained in:
2025-12-26 10:23:03 +09:00
parent 8e6b41c9ad
commit baffb147d9
15 changed files with 183 additions and 248 deletions

View File

@@ -2,7 +2,6 @@ package com.kamco.cd.kamcoback.common.utils;
import static java.lang.String.CASE_INSENSITIVE_ORDER; import static java.lang.String.CASE_INSENSITIVE_ORDER;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.DmlReturn;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
@@ -457,15 +456,13 @@ public class FIleChecker {
return FIleChecker.getFilesFromAllDepth(dir, targetFileNm, extension, 100, "name", 0, 100); return FIleChecker.getFilesFromAllDepth(dir, targetFileNm, extension, 100, "name", 0, 100);
} }
public static int getFileCountFromAllDepth( public static int getFileCountFromAllDepth(String dir, String targetFileNm, String extension) {
String dir, String targetFileNm, String extension) {
List<FIleChecker.Basic> basicList = List<FIleChecker.Basic> basicList =
FIleChecker.getFilesFromAllDepth(dir, targetFileNm, extension); FIleChecker.getFilesFromAllDepth(dir, targetFileNm, extension);
return (int) basicList.stream() return (int)
.filter(dto -> dto.getExtension().toString().equals(extension)) basicList.stream().filter(dto -> dto.getExtension().toString().equals(extension)).count();
.count();
} }
public static Long getFileTotSize(List<FIleChecker.Basic> files) { public static Long getFileTotSize(List<FIleChecker.Basic> files) {
@@ -478,8 +475,7 @@ public class FIleChecker {
return fileTotSize; return fileTotSize;
} }
public static boolean multipartSaveTo(MultipartFile mfile, String targetPath) public static boolean multipartSaveTo(MultipartFile mfile, String targetPath) {
{
Path tmpSavePath = Paths.get(targetPath); Path tmpSavePath = Paths.get(targetPath);
boolean fileUpload = true; boolean fileUpload = true;
@@ -493,8 +489,7 @@ public class FIleChecker {
return true; return true;
} }
public static boolean validationMultipart(MultipartFile mfile) public static boolean validationMultipart(MultipartFile mfile) {
{
// 파일 유효성 검증 // 파일 유효성 검증
if (mfile == null || mfile.isEmpty() || mfile.getSize() == 0) { if (mfile == null || mfile.isEmpty() || mfile.getSize() == 0) {
return false; return false;

View File

@@ -17,7 +17,6 @@ public class InferenceResultShpApiController {
private final InferenceResultShpService inferenceResultShpService; private final InferenceResultShpService inferenceResultShpService;
@Operation(summary = "추론결과 데이터 저장", description = "추론결과 데이터 저장") @Operation(summary = "추론결과 데이터 저장", description = "추론결과 데이터 저장")
@PostMapping @PostMapping
public ApiResponseDto<Void> saveInferenceResultData() { public ApiResponseDto<Void> saveInferenceResultData() {

View File

@@ -44,8 +44,7 @@ public class InferenceResultShpDto {
Float area, Float area,
ZonedDateTime createdDttm, ZonedDateTime createdDttm,
ZonedDateTime updatedDttm, ZonedDateTime updatedDttm,
Geometry geometry Geometry geometry) {
) {
this.id = id; this.id = id;
this.uuid = uuid; this.uuid = uuid;
this.stage = stage; this.stage = stage;
@@ -79,8 +78,7 @@ public class InferenceResultShpDto {
e.getArea(), e.getArea(),
e.getCreatedDttm(), e.getCreatedDttm(),
e.getUpdatedDttm(), e.getUpdatedDttm(),
e.getGeometry() e.getGeometry());
);
} }
} }
} }

View File

@@ -48,10 +48,11 @@ public class GeoToolsShpWriter implements ShpWriter {
/** /**
* SHP 파일(.shp/.shx/.dbf/.prj)을 생성한다. * SHP 파일(.shp/.shx/.dbf/.prj)을 생성한다.
* <p> *
* - shpBasePath를 기준으로 파일을 생성한다. 예) /Users/kim/export/shp/1_map_2021_2022 → 1_map_2021_2022.shp → 1_map_2021_2022.shx → 1_map_2021_2022.dbf → 1_map_2021_2022.prj * <p>- shpBasePath를 기준으로 파일을 생성한다. 예) /Users/kim/export/shp/1_map_2021_2022 → 1_map_2021_2022.shp
* <p> * → 1_map_2021_2022.shx → 1_map_2021_2022.dbf → 1_map_2021_2022.prj
* - geometry 타입은 첫 번째 유효 geometry 기준으로 스키마를 생성한다. - 좌표계는 EPSG:5186으로 설정하며, .prj 파일을 직접 생성한다. *
* <p>- geometry 타입은 첫 번째 유효 geometry 기준으로 스키마를 생성한다. - 좌표계는 EPSG:5186으로 설정하며, .prj 파일을 직접 생성한다.
* *
* @param shpBasePath 확장자를 제외한 SHP 파일 기본 경로 * @param shpBasePath 확장자를 제외한 SHP 파일 기본 경로
* @param rows 동일 그룹(stage, mapId, input1, input2)의 데이터 목록 * @param rows 동일 그룹(stage, mapId, input1, input2)의 데이터 목록
@@ -67,13 +68,11 @@ public class GeoToolsShpWriter implements ShpWriter {
// 첫 번째 유효 geometry의 "구체 타입"을 기준으로 스키마를 생성한다. // 첫 번째 유효 geometry의 "구체 타입"을 기준으로 스키마를 생성한다.
Geometry firstGeom = firstNonNullGeometry(rows); Geometry firstGeom = firstNonNullGeometry(rows);
if (firstGeom == null) { if (firstGeom == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException("SHP 생성 실패: geometry가 전부 null 입니다. path=" + shpBasePath);
"SHP 생성 실패: geometry가 전부 null 입니다. path=" + shpBasePath);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Class<? extends Geometry> geomType = Class<? extends Geometry> geomType = (Class<? extends Geometry>) firstGeom.getClass();
(Class<? extends Geometry>) firstGeom.getClass();
ShapefileDataStore dataStore = null; ShapefileDataStore dataStore = null;
@@ -91,8 +90,7 @@ public class GeoToolsShpWriter implements ShpWriter {
dataStore = createDataStore(shpFile, schema); dataStore = createDataStore(shpFile, schema);
// FeatureCollection 생성 // FeatureCollection 생성
DefaultFeatureCollection collection = DefaultFeatureCollection collection = buildFeatureCollection(schema, rows);
buildFeatureCollection(schema, rows);
// 실제 SHP 파일에 feature 쓰기 // 실제 SHP 파일에 feature 쓰기
writeFeatures(dataStore, collection); writeFeatures(dataStore, collection);
@@ -100,11 +98,7 @@ public class GeoToolsShpWriter implements ShpWriter {
// .prj 파일 직접 생성 (EPSG:5186) // .prj 파일 직접 생성 (EPSG:5186)
writePrjFile(shpBasePath, crs); writePrjFile(shpBasePath, crs);
log.info( log.info("SHP 생성 완료: {} ({} features)", shpFile.getAbsolutePath(), collection.size());
"SHP 생성 완료: {} ({} features)",
shpFile.getAbsolutePath(),
collection.size()
);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("SHP 생성 실패: " + shpBasePath, e); throw new RuntimeException("SHP 생성 실패: " + shpBasePath, e);
@@ -120,11 +114,13 @@ public class GeoToolsShpWriter implements ShpWriter {
/** /**
* GeoJSON 파일(.geojson)을 생성한다. * GeoJSON 파일(.geojson)을 생성한다.
* <p> *
* - FeatureCollection 형태로 출력한다. - 최상단에 name / crs / properties를 포함한다. - 각 Feature는 polygon 단위로 생성된다. - geometry는 GeoTools GeometryJSON을 사용하여 직렬화한다. * <p>- FeatureCollection 형태로 출력한다. - 최상단에 name / crs / properties를 포함한다. - 각 Feature는 polygon 단위로
* <p> * 생성된다. - geometry는 GeoTools GeometryJSON을 사용하여 직렬화한다.
* GeoJSON 구조 예: { "type": "FeatureCollection", "name": "stage_input1_input2_mapId", "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::5186" } }, *
* "properties": { ... }, "features": [ ... ] } * <p>GeoJSON 구조 예: { "type": "FeatureCollection", "name": "stage_input1_input2_mapId", "crs": {
* "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::5186" } }, "properties": { ...
* }, "features": [ ... ] }
* *
* @param geoJsonPath 생성할 GeoJSON 파일의 전체 경로 (.geojson 포함) * @param geoJsonPath 생성할 GeoJSON 파일의 전체 경로 (.geojson 포함)
* @param rows 동일 그룹(stage, mapId, input1, input2)의 데이터 목록 * @param rows 동일 그룹(stage, mapId, input1, input2)의 데이터 목록
@@ -151,13 +147,10 @@ public class GeoToolsShpWriter implements ShpWriter {
root.put("type", "FeatureCollection"); root.put("type", "FeatureCollection");
// name: stage_input1_input2_mapId // name: stage_input1_input2_mapId
String name = String.format( String name =
String.format(
"%d_%d_%d_%d", "%d_%d_%d_%d",
first.getStage(), first.getStage(), first.getInput1(), first.getInput2(), first.getMapId());
first.getInput1(),
first.getInput2(),
first.getMapId()
);
root.put("name", name); root.put("name", name);
// CRS (EPSG:5186) // CRS (EPSG:5186)
@@ -175,9 +168,9 @@ public class GeoToolsShpWriter implements ShpWriter {
groupProps.put("input2", first.getInput2()); groupProps.put("input2", first.getInput2());
groupProps.put("map_id", first.getMapId()); groupProps.put("map_id", first.getMapId());
// 학습서버 버전은 추후 추가 // 학습서버 버전은 추후 추가
// groupProps.put("m1", "v1.2222.251223121212"); // groupProps.put("m1", "v1.2222.251223121212");
// groupProps.put("m2", "v2.211.251223121213"); // groupProps.put("m2", "v2.211.251223121213");
// groupProps.put("m3", "v3.233.251223121214"); // groupProps.put("m3", "v3.233.251223121214");
root.set("properties", groupProps); root.set("properties", groupProps);
// features 배열 // features 배열
@@ -193,8 +186,7 @@ public class GeoToolsShpWriter implements ShpWriter {
// feature properties // feature properties
ObjectNode p = om.createObjectNode(); ObjectNode p = om.createObjectNode();
p.put("polygon_id", p.put("polygon_id", dto.getUuid() != null ? dto.getUuid().toString() : null);
dto.getUuid() != null ? dto.getUuid().toString() : null);
if (dto.getCdProb() != null) { if (dto.getCdProb() != null) {
p.put("cd_prob", dto.getCdProb()); p.put("cd_prob", dto.getCdProb());
} }
@@ -233,18 +225,11 @@ public class GeoToolsShpWriter implements ShpWriter {
// 파일 쓰기 // 파일 쓰기
try (OutputStreamWriter w = try (OutputStreamWriter w =
new OutputStreamWriter( new OutputStreamWriter(new FileOutputStream(geoJsonFile), GEOJSON_CHARSET)) {
new FileOutputStream(geoJsonFile),
GEOJSON_CHARSET
)) {
om.writerWithDefaultPrettyPrinter().writeValue(w, root); om.writerWithDefaultPrettyPrinter().writeValue(w, root);
} }
log.info( log.info("GeoJSON 생성 완료: {} ({} features)", geoJsonFile.getAbsolutePath(), features.size());
"GeoJSON 생성 완료: {} ({} features)",
geoJsonFile.getAbsolutePath(),
features.size()
);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("GeoJSON 생성 실패: " + geoJsonPath, e); throw new RuntimeException("GeoJSON 생성 실패: " + geoJsonPath, e);
@@ -253,8 +238,8 @@ public class GeoToolsShpWriter implements ShpWriter {
/** /**
* rows 목록에서 첫 번째로 발견되는 non-null Geometry를 반환한다. * rows 목록에서 첫 번째로 발견되는 non-null Geometry를 반환한다.
* <p> *
* - SHP 스키마 생성 시 geometry 타입 결정을 위해 사용된다. * <p>- SHP 스키마 생성 시 geometry 타입 결정을 위해 사용된다.
* *
* @param rows DTO 목록 * @param rows DTO 목록
* @return 첫 번째 non-null Geometry, 없으면 null * @return 첫 번째 non-null Geometry, 없으면 null
@@ -270,17 +255,15 @@ public class GeoToolsShpWriter implements ShpWriter {
/** /**
* SHP 파일에 사용할 SimpleFeatureType(schema)를 생성한다. * SHP 파일에 사용할 SimpleFeatureType(schema)를 생성한다.
* <p> *
* - geometry 컬럼은 반드시 첫 번째 컬럼이어야 한다. - DBF 컬럼은 SHP 제약(컬럼명 10자, 길이 제한)을 고려한다. * <p>- geometry 컬럼은 반드시 첫 번째 컬럼이어야 한다. - DBF 컬럼은 SHP 제약(컬럼명 10자, 길이 제한)을 고려한다.
* *
* @param geomType geometry의 구체 타입 (Polygon, MultiPolygon 등) * @param geomType geometry의 구체 타입 (Polygon, MultiPolygon 등)
* @param crs 좌표계(EPSG:5186) * @param crs 좌표계(EPSG:5186)
* @return SimpleFeatureType * @return SimpleFeatureType
*/ */
private SimpleFeatureType createSchema( private SimpleFeatureType createSchema(
Class<? extends Geometry> geomType, Class<? extends Geometry> geomType, CoordinateReferenceSystem crs) {
CoordinateReferenceSystem crs
) {
SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder(); SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
b.setName("inference_result"); b.setName("inference_result");
b.setCRS(crs); b.setCRS(crs);
@@ -305,25 +288,22 @@ public class GeoToolsShpWriter implements ShpWriter {
/** /**
* ShapefileDataStore를 생성하고 스키마를 등록한다. * ShapefileDataStore를 생성하고 스키마를 등록한다.
* <p> *
* - DBF 파일 인코딩은 EUC-KR로 설정한다. - spatial index(.qix)를 생성한다. * <p>- DBF 파일 인코딩은 EUC-KR로 설정한다. - spatial index(.qix)를 생성한다.
* *
* @param shpFile SHP 파일 객체 * @param shpFile SHP 파일 객체
* @param schema SimpleFeatureType * @param schema SimpleFeatureType
* @return 생성된 ShapefileDataStore * @return 생성된 ShapefileDataStore
*/ */
private ShapefileDataStore createDataStore( private ShapefileDataStore createDataStore(File shpFile, SimpleFeatureType schema)
File shpFile, throws Exception {
SimpleFeatureType schema
) throws Exception {
Map<String, Serializable> params = new HashMap<>(); Map<String, Serializable> params = new HashMap<>();
params.put("url", shpFile.toURI().toURL()); params.put("url", shpFile.toURI().toURL());
params.put("create spatial index", Boolean.TRUE); params.put("create spatial index", Boolean.TRUE);
ShapefileDataStoreFactory factory = new ShapefileDataStoreFactory(); ShapefileDataStoreFactory factory = new ShapefileDataStoreFactory();
ShapefileDataStore dataStore = ShapefileDataStore dataStore = (ShapefileDataStore) factory.createNewDataStore(params);
(ShapefileDataStore) factory.createNewDataStore(params);
dataStore.setCharset(DBF_CHARSET); dataStore.setCharset(DBF_CHARSET);
dataStore.createSchema(schema); dataStore.createSchema(schema);
@@ -333,17 +313,15 @@ public class GeoToolsShpWriter implements ShpWriter {
/** /**
* DTO 목록을 SimpleFeatureCollection으로 변환한다. * DTO 목록을 SimpleFeatureCollection으로 변환한다.
* <p> *
* - DTO 1건당 Feature 1개 생성 - geometry가 null인 데이터는 제외한다. * <p>- DTO 1건당 Feature 1개 생성 - geometry가 null인 데이터는 제외한다.
* *
* @param schema FeatureType * @param schema FeatureType
* @param rows DTO 목록 * @param rows DTO 목록
* @return DefaultFeatureCollection * @return DefaultFeatureCollection
*/ */
private DefaultFeatureCollection buildFeatureCollection( private DefaultFeatureCollection buildFeatureCollection(
SimpleFeatureType schema, SimpleFeatureType schema, List<InferenceResultShpDto.Basic> rows) {
List<InferenceResultShpDto.Basic> rows
) {
DefaultFeatureCollection collection = new DefaultFeatureCollection(); DefaultFeatureCollection collection = new DefaultFeatureCollection();
SimpleFeatureBuilder builder = new SimpleFeatureBuilder(schema); SimpleFeatureBuilder builder = new SimpleFeatureBuilder(schema);
@@ -360,13 +338,11 @@ public class GeoToolsShpWriter implements ShpWriter {
builder.add(dto.getMapId()); builder.add(dto.getMapId());
builder.add(dto.getArea() != null ? dto.getArea().doubleValue() : null); builder.add(dto.getArea() != null ? dto.getArea().doubleValue() : null);
builder.add(dto.getBeforeClass()); builder.add(dto.getBeforeClass());
builder.add(dto.getBeforeProbability() != null builder.add(
? dto.getBeforeProbability().doubleValue() dto.getBeforeProbability() != null ? dto.getBeforeProbability().doubleValue() : null);
: null);
builder.add(dto.getAfterClass()); builder.add(dto.getAfterClass());
builder.add(dto.getAfterProbability() != null builder.add(
? dto.getAfterProbability().doubleValue() dto.getAfterProbability() != null ? dto.getAfterProbability().doubleValue() : null);
: null);
SimpleFeature feature = builder.buildFeature(null); SimpleFeature feature = builder.buildFeature(null);
collection.add(feature); collection.add(feature);
@@ -382,14 +358,11 @@ public class GeoToolsShpWriter implements ShpWriter {
* @param dataStore ShapefileDataStore * @param dataStore ShapefileDataStore
* @param collection FeatureCollection * @param collection FeatureCollection
*/ */
private void writeFeatures( private void writeFeatures(ShapefileDataStore dataStore, DefaultFeatureCollection collection)
ShapefileDataStore dataStore, throws Exception {
DefaultFeatureCollection collection
) throws Exception {
String typeName = dataStore.getTypeNames()[0]; String typeName = dataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
dataStore.getFeatureSource(typeName);
if (!(featureSource instanceof SimpleFeatureStore store)) { if (!(featureSource instanceof SimpleFeatureStore store)) {
throw new IllegalStateException("FeatureStore 생성 실패"); throw new IllegalStateException("FeatureStore 생성 실패");
@@ -406,19 +379,12 @@ public class GeoToolsShpWriter implements ShpWriter {
* @param shpBasePath SHP 기본 경로 (확장자 제외) * @param shpBasePath SHP 기본 경로 (확장자 제외)
* @param crs 좌표계(EPSG:5186) * @param crs 좌표계(EPSG:5186)
*/ */
private void writePrjFile( private void writePrjFile(String shpBasePath, CoordinateReferenceSystem crs) throws Exception {
String shpBasePath,
CoordinateReferenceSystem crs
) throws Exception {
File prjFile = new File(shpBasePath + ".prj"); File prjFile = new File(shpBasePath + ".prj");
createDirectories(prjFile); createDirectories(prjFile);
Files.writeString( Files.writeString(prjFile.toPath(), crs.toWKT(), StandardCharsets.UTF_8);
prjFile.toPath(),
crs.toWKT(),
StandardCharsets.UTF_8
);
} }
/** /**

View File

@@ -19,7 +19,9 @@ public class InferenceResultShpService {
public void saveInferenceResultData() { public void saveInferenceResultData() {
coreService.streamGrouped(1000, (key, entities) -> { coreService.streamGrouped(
1000,
(key, entities) -> {
// Entity -> DTO // Entity -> DTO
List<InferenceResultShpDto.Basic> dtoList = List<InferenceResultShpDto.Basic> dtoList =
@@ -41,10 +43,8 @@ public class InferenceResultShpService {
String baseDir = System.getProperty("user.home") + "/export"; String baseDir = System.getProperty("user.home") + "/export";
// 파일명 stage_input1_input2_mapId // 파일명 stage_input1_input2_mapId
String baseName = String.format( String baseName =
"%d_%d_%d_%d", String.format("%d_%d_%d_%d", key.stage(), key.mapId(), key.input1(), key.input2());
key.stage(), key.mapId(), key.input1(), key.input2()
);
String shpBasePath = baseDir + "/shp/" + baseName; // 확장자 없이 String shpBasePath = baseDir + "/shp/" + baseName; // 확장자 없이
String geoJsonPath = baseDir + "/geojson/" + baseName + ".geojson"; String geoJsonPath = baseDir + "/geojson/" + baseName + ".geojson";

View File

@@ -226,8 +226,6 @@ public class MapSheetMngApiController {
return ApiResponseDto.ok(mapSheetMngService.deleteByFileUidMngFile(fileUids)); return ApiResponseDto.ok(mapSheetMngService.deleteByFileUidMngFile(fileUids));
} }
@Operation(summary = "폴더 조회", description = "폴더 조회 (ROOT:/app/original-images 이하로 경로입력)") @Operation(summary = "폴더 조회", description = "폴더 조회 (ROOT:/app/original-images 이하로 경로입력)")
@ApiResponses( @ApiResponses(
value = { value = {
@@ -265,6 +263,4 @@ public class MapSheetMngApiController {
return ApiResponseDto.createOK(mapSheetMngService.getFilesAll(srchDto)); return ApiResponseDto.createOK(mapSheetMngService.getFilesAll(srchDto));
} }
} }

View File

@@ -14,7 +14,6 @@ import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.MngDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.MngFilesDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.MngFilesDto;
import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService; import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@@ -86,7 +85,8 @@ public class MapSheetMngService {
} }
@Transactional @Transactional
public DmlReturn uploadPair(MultipartFile tfwFile, MultipartFile tifFile, Long hstUid, Boolean overwrite) { public DmlReturn uploadPair(
MultipartFile tfwFile, MultipartFile tifFile, Long hstUid, Boolean overwrite) {
String rootPath = syncRootDir; String rootPath = syncRootDir;
String tmpPath = syncTmpDir; String tmpPath = syncTmpDir;
@@ -104,26 +104,29 @@ public class MapSheetMngService {
return new DmlReturn("fail", "CREATE TEMP FOLDER ERROR"); return new DmlReturn("fail", "CREATE TEMP FOLDER ERROR");
} }
//업로드 파일 사이즈,확장자명 체크 // 업로드 파일 사이즈,확장자명 체크
dmlReturn = this.validationFile(tfwFile, tifFile); dmlReturn = this.validationFile(tfwFile, tifFile);
if( dmlReturn.getFlag().equals("fail") )return dmlReturn; if (dmlReturn.getFlag().equals("fail")) return dmlReturn;
MngDto mngDto = mapSheetMngCoreService.findMapSheetMng(errDto.getMngYyyy()); MngDto mngDto = mapSheetMngCoreService.findMapSheetMng(errDto.getMngYyyy());
String targetYearDir = mngDto.getMngPath(); String targetYearDir = mngDto.getMngPath();
// 중복체크 // 중복체크
if( !overwrite ) { if (!overwrite) {
dmlReturn = this.duplicateFile(errDto.getMngYyyy(), tfwFile.getOriginalFilename(), tifFile.getOriginalFilename()); dmlReturn =
if( dmlReturn.getFlag().equals("duplicate") )return dmlReturn; this.duplicateFile(
errDto.getMngYyyy(), tfwFile.getOriginalFilename(), tifFile.getOriginalFilename());
if (dmlReturn.getFlag().equals("duplicate")) return dmlReturn;
} }
//멀티파트 파일 tmp폴더 저장(파일형식 체크를 위해) // 멀티파트 파일 tmp폴더 저장(파일형식 체크를 위해)
String tfwTmpPath = tmpPath + tfwFile.getOriginalFilename(); String tfwTmpPath = tmpPath + tfwFile.getOriginalFilename();
String tifTmpPath = tmpPath + tifFile.getOriginalFilename(); String tifTmpPath = tmpPath + tifFile.getOriginalFilename();
if(!FIleChecker.multipartSaveTo(tfwFile, tfwTmpPath))return new DmlReturn("fail", "UPLOAD ERROR"); if (!FIleChecker.multipartSaveTo(tfwFile, tfwTmpPath))
if(!FIleChecker.multipartSaveTo(tifFile, tifTmpPath))return new DmlReturn("fail", "UPLOAD ERROR"); return new DmlReturn("fail", "UPLOAD ERROR");
if (!FIleChecker.multipartSaveTo(tifFile, tifTmpPath))
return new DmlReturn("fail", "UPLOAD ERROR");
if (!FIleChecker.cmmndGdalInfo(tifTmpPath)) return new DmlReturn("fail", "TIF TYPE ERROR"); if (!FIleChecker.cmmndGdalInfo(tifTmpPath)) return new DmlReturn("fail", "TIF TYPE ERROR");
if (!FIleChecker.checkTfw(tfwTmpPath)) return new DmlReturn("fail", "TFW TYPE ERROR"); if (!FIleChecker.checkTfw(tfwTmpPath)) return new DmlReturn("fail", "TFW TYPE ERROR");
@@ -136,7 +139,6 @@ public class MapSheetMngService {
break; break;
} }
Path tfwTmpSavePath = Paths.get(tfwTmpPath); Path tfwTmpSavePath = Paths.get(tfwTmpPath);
Path tifTmpSavePath = Paths.get(tifTmpPath); Path tifTmpSavePath = Paths.get(tifTmpPath);
Path tfwTargetPath = null; Path tfwTargetPath = null;
@@ -232,20 +234,18 @@ public class MapSheetMngService {
return new DmlReturn("success", fileUids.size() + "개 파일이 삭제되었습니다."); return new DmlReturn("success", fileUids.size() + "개 파일이 삭제되었습니다.");
} }
public DmlReturn validationFile(MultipartFile tfwFile, MultipartFile tifFile) {
if (!FIleChecker.validationMultipart(tfwFile)) return new DmlReturn("fail", "TFW SIZE 오류");
public DmlReturn validationFile(MultipartFile tfwFile, MultipartFile tifFile) else if (!FIleChecker.validationMultipart(tifFile)) return new DmlReturn("fail", "TFW SIZE 오류");
{ else if (!FIleChecker.checkExtensions(tfwFile.getOriginalFilename(), "tfw"))
if( !FIleChecker.validationMultipart(tfwFile) )return new DmlReturn("fail", "TFW SIZE 오류"); return new DmlReturn("fail", "TFW FILENAME ERROR");
else if( !FIleChecker.validationMultipart(tifFile) )return new DmlReturn("fail", "TFW SIZE 오류"); else if (!FIleChecker.checkExtensions(tifFile.getOriginalFilename(), "tif"))
else if (!FIleChecker.checkExtensions(tfwFile.getOriginalFilename(), "tfw"))return new DmlReturn("fail", "TFW FILENAME ERROR"); return new DmlReturn("fail", "TIF FILENAME ERROR");
else if (!FIleChecker.checkExtensions(tifFile.getOriginalFilename(), "tif"))return new DmlReturn("fail", "TIF FILENAME ERROR");
return new DmlReturn("success", "파일체크"); return new DmlReturn("success", "파일체크");
} }
public DmlReturn duplicateFile(int mngYyyy, String tfwFileName, String tifFileName) public DmlReturn duplicateFile(int mngYyyy, String tfwFileName, String tifFileName) {
{
int tfwCnt = mapSheetMngCoreService.findByYearFileNameFileCount(mngYyyy, tfwFileName); int tfwCnt = mapSheetMngCoreService.findByYearFileNameFileCount(mngYyyy, tfwFileName);
int tifCnt = mapSheetMngCoreService.findByYearFileNameFileCount(mngYyyy, tifFileName); int tifCnt = mapSheetMngCoreService.findByYearFileNameFileCount(mngYyyy, tifFileName);
@@ -254,14 +254,11 @@ public class MapSheetMngService {
if (tfwCnt > 0 || tifCnt > 0) { if (tfwCnt > 0 || tifCnt > 0) {
String resMsg = ""; String resMsg = "";
if (tfwCnt > 0) if (tfwCnt > 0) resMsg = tfwFileName;
resMsg = tfwFileName;
if (tifCnt > 0) { if (tifCnt > 0) {
if (tfwCnt > 0) if (tfwCnt > 0) resMsg = resMsg + "," + tifFileName;
resMsg = resMsg + "," + tifFileName; else resMsg = tifFileName;
else
resMsg = tifFileName;
} }
return new DmlReturn("duplicate", resMsg); return new DmlReturn("duplicate", resMsg);
} }

View File

@@ -16,15 +16,12 @@ public class InferenceResultShpCoreService {
private final InferenceResultRepository inferenceResultRepository; private final InferenceResultRepository inferenceResultRepository;
public record ShpKey(Integer stage, Long mapId, Integer input1, Integer input2) { public record ShpKey(Integer stage, Long mapId, Integer input1, Integer input2) {}
} /** DB를 스트리밍하면서 그룹이 완성될 때마다 handler로 넘김 handler: (key, groupRows) */
/**
* DB를 스트리밍하면서 그룹이 완성될 때마다 handler로 넘김 handler: (key, groupRows)
*/
@Transactional(readOnly = true) @Transactional(readOnly = true)
public void streamGrouped(int fetchSize, BiConsumer<ShpKey, List<InferenceResultEntity>> handler) { public void streamGrouped(
int fetchSize, BiConsumer<ShpKey, List<InferenceResultEntity>> handler) {
ScrollableResults cursor = inferenceResultRepository.scrollAllOrdered(fetchSize); ScrollableResults cursor = inferenceResultRepository.scrollAllOrdered(fetchSize);

View File

@@ -135,16 +135,12 @@ public class MapSheetAnalDataInferenceGeomEntity {
@Column(name = "file_created_yn") @Column(name = "file_created_yn")
private Boolean fileCreatedYn; private Boolean fileCreatedYn;
@Column(name = "geom", columnDefinition = "geometry") @Column(name = "geom", columnDefinition = "geometry")
private Geometry geom; private Geometry geom;
@Column(name = "geom_center", columnDefinition = "geometry") @Column(name = "geom_center", columnDefinition = "geometry")
private Geometry geomCenter; private Geometry geomCenter;
@Column(name = "before_geom", columnDefinition = "geometry") @Column(name = "before_geom", columnDefinition = "geometry")
private Geometry beforeGeom; private Geometry beforeGeom;
} }

View File

@@ -5,5 +5,4 @@ import org.hibernate.ScrollableResults;
public interface InferenceResultRepositoryCustom { public interface InferenceResultRepositoryCustom {
ScrollableResults scrollAllOrdered(int fetchSize); ScrollableResults scrollAllOrdered(int fetchSize);
} }

View File

@@ -22,13 +22,7 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
JPAQuery<InferenceResultEntity> q = JPAQuery<InferenceResultEntity> q =
queryFactory queryFactory
.selectFrom(e) .selectFrom(e)
.orderBy( .orderBy(e.stage.asc(), e.mapId.asc(), e.input1.asc(), e.input2.asc(), e.id.asc());
e.stage.asc(),
e.mapId.asc(),
e.input1.asc(),
e.input2.asc(),
e.id.asc()
);
// QueryDSL -> Hibernate Query로 unwrap 해서 커서 스트리밍 // QueryDSL -> Hibernate Query로 unwrap 해서 커서 스트리밍
Query<?> hQuery = q.createQuery().unwrap(Query.class); Query<?> hQuery = q.createQuery().unwrap(Query.class);

View File

@@ -6,6 +6,4 @@ import org.springframework.stereotype.Repository;
@Repository @Repository
@RequiredArgsConstructor @RequiredArgsConstructor
public class MapSheetAnalDataInferenceGeomRepositoryImpl public class MapSheetAnalDataInferenceGeomRepositoryImpl
implements MapSheetAnalDataInferenceGeomRepositoryCustom { implements MapSheetAnalDataInferenceGeomRepositoryCustom {}
}

View File

@@ -5,6 +5,4 @@ import org.springframework.data.jpa.repository.JpaRepository;
public interface MapSheetAnalDataInferenceRepository public interface MapSheetAnalDataInferenceRepository
extends JpaRepository<MapSheetAnalDataInferenceEntity, Long>, extends JpaRepository<MapSheetAnalDataInferenceEntity, Long>,
MapSheetAnalDataInferenceRepositoryCustom { MapSheetAnalDataInferenceRepositoryCustom {}
}

View File

@@ -661,11 +661,15 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport
} }
@Override @Override
public int findByYearFileNameFileCount(int mngYyyy, String fileName){ public int findByYearFileNameFileCount(int mngYyyy, String fileName) {
Long execCount = queryFactory Long execCount =
queryFactory
.select(mapSheetMngFileEntity.count()) .select(mapSheetMngFileEntity.count())
.from(mapSheetMngFileEntity) .from(mapSheetMngFileEntity)
.where(mapSheetMngFileEntity.mngYyyy.eq(mngYyyy) .where(
mapSheetMngFileEntity
.mngYyyy
.eq(mngYyyy)
.and(mapSheetMngFileEntity.fileName.eq(fileName))) .and(mapSheetMngFileEntity.fileName.eq(fileName)))
.fetchOne(); .fetchOne();

View File

@@ -25,7 +25,6 @@ public class MapSheetMngFileJobController {
mapSheetMngFileJobService.checkMapSheetFileProcess(0, mngSyncPageSize); mapSheetMngFileJobService.checkMapSheetFileProcess(0, mngSyncPageSize);
} }
@Scheduled(fixedDelay = 5000) @Scheduled(fixedDelay = 5000)
public void mngFileSyncJob01() { public void mngFileSyncJob01() {
if (!isSchedulerEnabled) return; if (!isSchedulerEnabled) return;
@@ -98,7 +97,6 @@ public class MapSheetMngFileJobController {
mapSheetMngFileJobService.checkMapSheetFileProcess(9, mngSyncPageSize); mapSheetMngFileJobService.checkMapSheetFileProcess(9, mngSyncPageSize);
} }
// 3. 외부에서 플래그를 변경할 수 있는 Setter 메서드 // 3. 외부에서 플래그를 변경할 수 있는 Setter 메서드
public void setSchedulerEnabled(boolean enabled) { public void setSchedulerEnabled(boolean enabled) {
this.isSchedulerEnabled = enabled; this.isSchedulerEnabled = enabled;