Merge pull request '이노펨 목업 수정' (#129) from feat/dev_251201 into develop

Reviewed-on: https://kamco.gitea.gs.dabeeo.com/dabeeo/kamco-dabeeo-backoffice/pulls/129
This commit is contained in:
2025-12-31 11:08:01 +09:00
2 changed files with 72 additions and 40 deletions

View File

@@ -4,6 +4,7 @@ import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto;
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.Basic;
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastReq;
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch;
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto;
import com.kamco.cd.kamcoback.Innopam.service.DetectMastService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
@@ -126,20 +127,26 @@ public class InnopamApiController {
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping("/pnu/{cprsBfYr}/{cprsAfYr}/{dtctSno}")
public void selectPnuList(
public List<FeaturePnuDto> selectPnuList(
@PathVariable String cprsBfYr, @PathVariable String cprsAfYr, @PathVariable String dtctSno) {
DetectMastSearch detectMastSearch = new DetectMastSearch();
detectMastSearch.setCprsAdYr(cprsAfYr);
detectMastSearch.setCprsBfYr(cprsBfYr);
detectMastSearch.setDtctSno(Integer.parseInt(dtctSno));
detectMastService.findPnuData(detectMastSearch);
return detectMastService.findPnuData(detectMastSearch);
}
/**
* 탐지객체 PNU 단건 조회
*
* @param detectMast
*/
@GetMapping("/pnu/{cprsBfYr}/{cprsAfYr}/{dtctSno}/{featureId}")
public void selectPnuDetail(@RequestBody DetectMastDto detectMast) {}
public FeaturePnuDto selectPnuDetail(
@PathVariable String cprsBfYr,
@PathVariable String cprsAfYr,
@PathVariable String dtctSno,
@PathVariable String featureId) {
DetectMastSearch detectMastSearch = new DetectMastSearch();
detectMastSearch.setCprsAdYr(cprsAfYr);
detectMastSearch.setCprsBfYr(cprsBfYr);
detectMastSearch.setDtctSno(Integer.parseInt(dtctSno));
detectMastSearch.setFeatureId(featureId);
return detectMastService.findPnuDataDetail(detectMastSearch);
}
}

View File

@@ -1,17 +1,23 @@
package com.kamco.cd.kamcoback.Innopam.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.Basic;
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastReq;
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch;
import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto;
import com.kamco.cd.kamcoback.Innopam.postgres.core.DetectMastCoreService;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -21,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
public class DetectMastService {
private final JsonFactory factory = new JsonFactory();
private final DetectMastCoreService detectMastCoreService;
@Transactional
@@ -36,11 +43,15 @@ public class DetectMastService {
return detectMastCoreService.selectDetectMast(id);
}
public void findPnuData(DetectMastSearch detectMast) {
// String pathNm = detectMastCoreService.findPnuData(detectMast);
String pathNm = "/Users/bokmin/detect/result/2023_2024/4";
File geoJson = new File(pathNm);
List<FeaturePnuDto> list = this.extractFeaturePnus(geoJson);
public List<FeaturePnuDto> findPnuData(DetectMastSearch detectMast) {
String pathNm = detectMastCoreService.findPnuData(detectMast);
return this.extractFeaturePnusFast(pathNm);
}
public FeaturePnuDto findPnuDataDetail(DetectMastSearch detectMast) {
String pathNm = detectMastCoreService.findPnuData(detectMast);
List<FeaturePnuDto> pnu = this.extractFeaturePnusFast(pathNm);
return pnu.get(0);
}
private String randomPnu() {
@@ -54,37 +65,51 @@ public class DetectMastService {
return lawCode + sanFlag + bon + bu;
}
private List<FeaturePnuDto> extractFeaturePnus(File geoJsonFile) {
public List<FeaturePnuDto> extractFeaturePnusFast(String dirPath) {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = null;
try {
mapper.readTree(geoJsonFile);
} catch (IOException e) {
throw new RuntimeException(e);
Path basePath = Paths.get(dirPath);
if (!Files.isDirectory(basePath)) {
System.err.println("유효하지 않은 디렉터리: " + dirPath);
return List.of();
}
JsonNode features = root.get("features");
List<FeaturePnuDto> result = new ArrayList<>();
// 병렬로 모으기 위한 thread-safe 컬렉션
Queue<FeaturePnuDto> out = new ConcurrentLinkedQueue<>();
if (features != null && features.isArray()) {
for (JsonNode feature : features) {
JsonNode properties = feature.get("properties");
if (properties == null) {
continue;
}
try (Stream<Path> stream = Files.walk(basePath)) {
stream
.filter(Files::isRegularFile)
.filter(p -> p.toString().toLowerCase().endsWith(".geojson"))
.parallel() // 병렬
.forEach(
p -> {
try (InputStream in = Files.newInputStream(p);
JsonParser parser = factory.createParser(in)) {
String polygonId = properties.path("polygon_id").asText(null);
if (polygonId == null) {
continue;
}
// "polygon_id" 키를 만나면 다음 토큰 값을 읽어서 저장
while (parser.nextToken() != null) {
if (parser.currentToken() == JsonToken.FIELD_NAME
&& "polygon_id".equals(parser.getCurrentName())) {
String pnu = this.randomPnu();
JsonToken next = parser.nextToken(); // 값으로 이동
if (next == JsonToken.VALUE_STRING) {
String polygonId = parser.getValueAsString();
out.add(new FeaturePnuDto(polygonId, this.randomPnu()));
}
}
}
result.add(new FeaturePnuDto(polygonId, pnu));
}
} catch (Exception e) {
// 파일별 에러 로그는 최소화
System.err.println("파싱 실패: " + p.getFileName() + " / " + e.getMessage());
}
});
} catch (Exception e) {
System.err.println("디렉터리 탐색 실패: " + e.getMessage());
return List.of();
}
return result;
return new ArrayList<>(out);
}
}