123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- package com.shkpr.service.alambizplugin.components;
- import com.fasterxml.jackson.core.type.TypeReference;
- import com.global.base.log.LogLevelFlag;
- import com.global.base.log.LogPrintMgr;
- import com.shkpr.service.alambizplugin.apiparam.GisSurveyThirdExportParams;
- import com.shkpr.service.alambizplugin.commtools.CRSUtil;
- import com.shkpr.service.alambizplugin.commtools.ThirdImportTemplateUtils;
- import com.shkpr.service.alambizplugin.constants.CommAsyncStatusEnum;
- import com.shkpr.service.alambizplugin.constants.CommCRSDefine;
- import com.shkpr.service.alambizplugin.constants.FileTypeEnum;
- import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
- import com.shkpr.service.alambizplugin.constants.GisSurveyExcelDefine;
- import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
- import com.shkpr.service.alambizplugin.dbdao.services.intef.GisMetadataLayerTemplateService;
- import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyJobInfoService;
- import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyService;
- import com.shkpr.service.alambizplugin.dto.CommAsyncResult;
- import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
- import com.shkpr.service.alambizplugin.dto.GisMetadataPropertyTemplate;
- import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApply;
- import com.shkpr.service.alambizplugin.dto.GisSurveyPropertyValue;
- import org.apache.commons.compress.archivers.ArchiveException;
- import org.apache.commons.lang3.StringUtils;
- import org.geotools.data.DataUtilities;
- import org.geotools.feature.SchemaException;
- import org.locationtech.jts.geom.Coordinate;
- import org.locationtech.jts.geom.Geometry;
- import org.opengis.feature.simple.SimpleFeatureType;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.scheduling.annotation.AsyncResult;
- import org.springframework.stereotype.Component;
- import org.springframework.util.concurrent.ListenableFuture;
- import java.io.IOException;
- import java.math.BigDecimal;
- import java.nio.file.Files;
- import java.nio.file.Path;
- import java.time.Duration;
- import java.time.LocalDateTime;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.HashMap;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Objects;
- import java.util.stream.Collectors;
- /**
- * 第三方导出执行器
- *
- * @author 欧阳劲驰
- * @since 1.0.0
- */
- @Component
- public class GisSurveyThirdExporter {
- /**
- * 结果前缀
- */
- public final static String RESULT_PREFIX = "third-export-";
- /**
- * log
- */
- private final String mStrClassName;
- private final String mBizType;
- private final AsyncResultManager asyncResultManager;
- private final GisSurveyJobInfoService jobInfoService;
- private final GisMetadataLayerTemplateService layerTemplateService;
- private final GisSurveyLayerApplyService gisSurveyLayerApplyService;
- public GisSurveyThirdExporter(AsyncResultManager asyncResultManager, GisSurveyJobInfoService jobInfoService
- , GisMetadataLayerTemplateService layerTemplateService, GisSurveyLayerApplyService gisSurveyLayerApplyService) {
- mStrClassName = "GisSurveyThirdExporter";
- mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
- this.asyncResultManager = asyncResultManager;
- this.jobInfoService = jobInfoService;
- this.layerTemplateService = layerTemplateService;
- this.gisSurveyLayerApplyService = gisSurveyLayerApplyService;
- }
- /**
- * 第三方导出任务
- *
- * @param params 导出参数
- * @return 导出结果
- */
- @Async
- public ListenableFuture<CommAsyncResult<Map<String, String>>> thirdExportTask(GisSurveyThirdExportParams params) {
- //参数
- String jobId = params.getJobId();
- FileTypeEnum fileType = params.getFileTypeEnum();
- String targetCRSCode = params.getTargetCRSCode();
- String operator = params.getOperator();
- //构建返回
- CommAsyncResult<Map<String, String>> result = CommAsyncResult.fail(params.getJobId());
- result.setOperator(operator);
- try {
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
- , String.format(
- "开始执行第三方导出;任务id: %s"
- , jobId
- )
- );
- //查询元素更新时间
- LocalDateTime refreshTime = jobInfoService.findRefreshTime(jobId);
- //查询点线数据
- List<GisSurveyLayerApply> points = gisSurveyLayerApplyService.findAllByJobIdAndKind(jobId, GisMetadataDefine.TYPE_KINE.POINT);
- List<GisSurveyLayerApply> lines = gisSurveyLayerApplyService.findAllByJobIdAndKind(jobId, GisMetadataDefine.TYPE_KINE.LINE);
- //处理坐标系
- if (!Objects.equals(targetCRSCode, CommCRSDefine.CGCS2000)) transformGeom(targetCRSCode, points, lines);
- //获取图层key
- List<String> pointLayer = getLayerKeys(points);
- List<String> lineLayer = getLayerKeys(lines);
- //查询点图层模版
- List<GisMetadataLayerTemplate> pointLayerTemplates = layerTemplateService.findByKeyIn(pointLayer);
- //查询线图层模版
- List<GisMetadataLayerTemplate> lineLayerTemplates = layerTemplateService.findByKeyIn(lineLayer);
- //结果flag
- final String FLAG = RESULT_PREFIX + jobId;
- //创建临时文件夹
- if (!asyncResultManager.createTempDirectory(FLAG))
- return new AsyncResult<>(result);
- //根据文件类型导出
- Path outputPath = null;
- if (fileType == FileTypeEnum.EXCEL)
- outputPath = exportExcel(points, lines, pointLayerTemplates, lineLayerTemplates, FLAG);
- if (fileType == FileTypeEnum.SHAPE_FILE)
- outputPath = exportShape(points, lines, pointLayerTemplates, lineLayerTemplates, FLAG);
- if (outputPath == null || !Files.exists(outputPath)) {
- //打印报错信息
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
- , String.format("第三方导出文件写入失败, 任务id:%s", jobId)
- );
- return new AsyncResult<>(result);
- }
- //获取上次结果
- CommAsyncResult<Map<String, String>> lastResult = asyncResultManager.getResult(FLAG, new TypeReference<CommAsyncResult<Map<String, String>>>() {
- });
- //设置数据
- Map<String, String> data = new HashMap<>();
- if (lastResult != null && lastResult.getData() != null) data = lastResult.getData();
- data.put(fileType.getName(), FLAG + "/" + outputPath.getFileName().toString());
- //设置数据时间
- Map<String, LocalDateTime> refreshTimes = new HashMap<>();
- if (lastResult != null && lastResult.getRefreshTimes() != null) refreshTimes = lastResult.getRefreshTimes();
- refreshTimes.put(fileType.getName(), refreshTime);
- //导出完成
- result.setStatus(CommAsyncStatusEnum.SUCCESS.getCode());
- result.setCompleteTime(LocalDateTime.now());
- result.setData(data);
- result.setRefreshTimes(refreshTimes);
- result.setSubitemKeys(Collections.singletonList(fileType.getName()));
- //写入结果
- Path resultPath = asyncResultManager.writeJson(result, FLAG, AsyncResultManager.RESULT_FILE_NAME);
- if (resultPath == null || !Files.exists(resultPath)) {
- //打印报错信息
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
- , String.format("第三方导出文件写入失败, 任务id:%s", jobId)
- );
- return new AsyncResult<>(CommAsyncResult.fail(jobId));
- }
- //替换结果
- if (!asyncResultManager.replaceResult(FLAG)) return new AsyncResult<>(CommAsyncResult.fail(jobId));
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
- , String.format(
- "结束第三方导出;任务id: %s, 用时(毫秒):%d"
- , jobId
- , Duration.between(result.getRequestTime(), result.getCompleteTime()).toMillis()
- )
- );
- return new AsyncResult<>(result);
- } catch (InterruptedException | IOException | ArchiveException | SchemaException e) {
- //打印报错信息
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
- , String.format("第三方导出异常 任务id:%s error:%s", jobId, e)
- );
- return new AsyncResult<>(CommAsyncResult.fail(jobId));
- }
- }
- /**
- * 转换geom
- *
- * @param targetCRSCode 目标坐标系
- * @param points 点集合
- * @param lines 线结合
- */
- private void transformGeom(String targetCRSCode, List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines) {
- //处理点
- points.parallelStream().forEach(point -> {
- //获取geom
- Geometry geometry = point.getGis();
- if (geometry == null) return;
- //转换geom
- Geometry transform = CRSUtil.transform(geometry, CommCRSDefine.CGCS2000, targetCRSCode);
- if (transform == null) return;
- //回填元素
- point.setGis(transform);
- //获取解析后的经纬度
- Coordinate coordinate = transform.getCoordinate();
- String lngStr = BigDecimal.valueOf(coordinate.getX()).toPlainString();
- String latStr = BigDecimal.valueOf(coordinate.getY()).toPlainString();
- //回填经纬度属性
- List<GisSurveyPropertyValue> propertyValues = point.getPropertyValues();
- propertyValues.stream()
- .filter(it -> Objects.equals(it.getProperty(), GisSurveyExcelDefine.TEMPLATE.LAT))
- .forEach(it -> it.setValue(latStr));
- propertyValues.stream()
- .filter(it -> Objects.equals(it.getProperty(), GisSurveyExcelDefine.TEMPLATE.LNG))
- .forEach(it -> it.setValue(lngStr));
- });
- //处理线
- lines.parallelStream().forEach(line -> {
- //获取geom
- Geometry geometry = line.getGis();
- if (geometry == null) return;
- //转换geom
- Geometry transform = CRSUtil.transform(geometry, CommCRSDefine.CGCS2000, targetCRSCode);
- if (transform == null) return;
- //回填元素
- line.setGis(transform);
- });
- }
- /**
- * 导出excel
- *
- * @param points 点
- * @param lines 线
- * @param pointLayerTemplates 点图层模版
- * @param lineLayerTemplates 线图层模版
- * @param FLAG 结果flag
- * @return excel路径
- * @throws IOException io异常
- */
- private Path exportExcel(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines, List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates, String FLAG) throws IOException {
- //构建excel头
- Map<String, Map<String, String>> excelHeader = buildExcelHeader(pointLayerTemplates, lineLayerTemplates);
- //构建excel数据
- Map<String, List<Map<String, Object>>> excelData = buildExcelData(points, lines, pointLayerTemplates, lineLayerTemplates);
- //导出excel
- return asyncResultManager.writeExcel(excelHeader, excelData, FLAG, "third-export.xlsx");
- }
- /**
- * 导出shape
- *
- * @param points 点
- * @param lines 线
- * @param pointLayerTemplates 点图层模版
- * @param lineLayerTemplates 线图层模版
- * @param FLAG 结果flag
- * @return shape路径
- * @throws IOException io异常
- * @throws ArchiveException 压缩异常
- */
- private Path exportShape(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines, List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates, String FLAG) throws IOException, ArchiveException, SchemaException {
- //构建shape数据
- Map<SimpleFeatureType, List<Map<String, Object>>> shapeData = buildShapeData(points, lines, pointLayerTemplates, lineLayerTemplates);
- //导出shape
- return asyncResultManager.writeShape(shapeData, FLAG, "third-export.zip");
- }
- /**
- * 获取图层key
- *
- * @param datas 数据
- * @return 图层key集合
- */
- private List<String> getLayerKeys(List<GisSurveyLayerApply> datas) {
- //去重图层
- return datas.parallelStream()
- .map(GisSurveyLayerApply::getLayer)
- .filter(StringUtils::isNotBlank)
- .distinct()
- .collect(Collectors.toList());
- }
- /**
- * 构建excel表头
- *
- * @param pointLayerTemplates 点图层模版
- * @param lineLayerTemplates 线图层模版
- * @return excel数据
- */
- private Map<String, Map<String, String>> buildExcelHeader(List<GisMetadataLayerTemplate> pointLayerTemplates
- , List<GisMetadataLayerTemplate> lineLayerTemplates) {
- //点excel表头
- Map<String, String> pointExcelHeader = new LinkedHashMap<>();
- //线excel表头
- Map<String, String> lineExcelHeader = new LinkedHashMap<>();
- //点模版表头
- Map<String, String> pointTemplateHeader = pointLayerTemplates.stream()
- .flatMap(it -> it.getPropertyTemplates().stream())
- .sorted(Comparator.comparing(GisMetadataPropertyTemplate::getOrdering))
- .collect(Collectors.toMap(GisMetadataPropertyTemplate::getKey, GisMetadataPropertyTemplate::getName
- , (it1, it2) -> it1, LinkedHashMap::new));
- //线模版表头
- Map<String, String> lineTemplateHeader = lineLayerTemplates.stream()
- .flatMap(it -> it.getPropertyTemplates().stream())
- .collect(Collectors.toMap(GisMetadataPropertyTemplate::getKey, GisMetadataPropertyTemplate::getName
- , (it1, it2) -> it1, LinkedHashMap::new));
- //加入图层表头
- pointExcelHeader.put(GisSurveyExcelDefine.TEMPLATE.LAYER, GisSurveyExcelDefine.FILE.POINT_LAYER);
- lineExcelHeader.put(GisSurveyExcelDefine.TEMPLATE.LAYER, GisSurveyExcelDefine.FILE.LINE_LAYER);
- //加入模版表头
- pointExcelHeader.putAll(pointTemplateHeader);
- lineExcelHeader.putAll(lineTemplateHeader);
- //excel表头
- Map<String, Map<String, String>> excelHeader = new HashMap<>();
- excelHeader.put(GisMetadataDefine.TYPE_KINE.POINT, pointExcelHeader);
- excelHeader.put(GisMetadataDefine.TYPE_KINE.LINE, lineExcelHeader);
- return excelHeader;
- }
- /**
- * 构建excel数据
- *
- * @param points 点元素
- * @param lines 线元素
- * @param pointLayerTemplates 点图层模版
- * @param lineLayerTemplates 线图层模版
- * @return excel数据
- */
- private Map<String, List<Map<String, Object>>> buildExcelData(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines
- , List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates) {
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始构建excel数据 ======>");
- long begin = System.currentTimeMillis();
- //excel数据
- Map<String, List<Map<String, Object>>> excelData = new HashMap<>();
- excelData.put(GisMetadataDefine.TYPE_KINE.POINT, buildExcelSheetData(points, pointLayerTemplates));
- excelData.put(GisMetadataDefine.TYPE_KINE.LINE, buildExcelSheetData(lines, lineLayerTemplates));
- long end = System.currentTimeMillis();
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
- , String.format(
- "结束构建excel数据,用时(毫秒):%d"
- , (end - begin)
- )
- );
- return excelData;
- }
- /**
- * 构建excel页数据
- *
- * @param layerApplies 采集元素集合
- * @param layerTemplates 图层模版
- * @return excel数据
- */
- private List<Map<String, Object>> buildExcelSheetData(List<GisSurveyLayerApply> layerApplies, List<GisMetadataLayerTemplate> layerTemplates) {
- return layerApplies.parallelStream()
- .map(it -> {
- //处理模版数据
- Map<String, Object> rowData = it.getPropertyValues().stream()
- .filter(it1 -> !StringUtils.isAnyBlank(it1.getProperty(), it1.getValue()))
- .collect(Collectors.toMap(GisSurveyPropertyValue::getProperty, GisSurveyPropertyValue::getValue
- , (i1, i2) -> i1));
- //处理图层数据
- if (StringUtils.isNotBlank(it.getLayer())) {
- //获取模版
- GisMetadataLayerTemplate gisMetadataLayerTemplate = layerTemplates.stream()
- .filter(it1 -> Objects.equals(it1.getKey(), it.getLayer()))
- .findFirst().orElse(null);
- //存入图层
- if (gisMetadataLayerTemplate != null)
- rowData.put(GisSurveyExcelDefine.TEMPLATE.LAYER, gisMetadataLayerTemplate.getName());
- }
- return rowData;
- }).collect(Collectors.toList());
- }
- /**
- * 构建shape数据
- *
- * @param points 点元素
- * @param lines 线元素
- * @param pointLayerTemplates 点图层模版
- * @param lineLayerTemplates 线图层模版
- * @return excel数据
- */
- private Map<SimpleFeatureType, List<Map<String, Object>>> buildShapeData(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines
- , List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates) throws SchemaException {
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始构建shape属性头和数据 ======>");
- long begin = System.currentTimeMillis();
- //点模版规格
- String pointTemplateSpec = pointLayerTemplates.stream()
- .flatMap(it -> it.getPropertyTemplates().stream())
- .sorted(Comparator.comparing(GisMetadataPropertyTemplate::getOrdering))
- .map(it ->
- String.format("%s%s"
- , StringUtils.substring(it.getName(), 0, 5)
- , GisSurveyExcelDefine.FILE_HANDLE.COL_SPEC)
- )
- .distinct()
- .collect(Collectors.joining(","));
- //线模版规格
- String lineTemplateSpec = lineLayerTemplates.stream()
- .flatMap(it -> it.getPropertyTemplates().stream())
- .sorted(Comparator.comparing(GisMetadataPropertyTemplate::getOrdering))
- .map(it ->
- String.format("%s%s"
- , StringUtils.substring(it.getName(), 0, 5)
- , GisSurveyExcelDefine.FILE_HANDLE.COL_SPEC)
- )
- .distinct()
- .collect(Collectors.joining(","));
- //创建点类型
- final SimpleFeatureType POINT_TYPE = DataUtilities.createType(
- "point",
- String.format("%s%s", GisSurveyExcelDefine.FILE_HANDLE.POINT_SPEC, pointTemplateSpec)
- );
- //创建线类型
- final SimpleFeatureType LINE_TYPE = DataUtilities.createType(
- "line",
- String.format("%s%s", GisSurveyExcelDefine.FILE_HANDLE.LINE_SPEC, lineTemplateSpec)
- );
- //shape数据
- Map<SimpleFeatureType, List<Map<String, Object>>> shapeData = new HashMap<>();
- shapeData.put(POINT_TYPE, buildShapeItemData(points, pointLayerTemplates));
- shapeData.put(LINE_TYPE, buildShapeItemData(lines, lineLayerTemplates));
- long end = System.currentTimeMillis();
- LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
- , String.format(
- "结束构建shape属性头和数据,用时(毫秒):%d"
- , (end - begin)
- )
- );
- return shapeData;
- }
- /**
- * 构建shape项数据
- *
- * @param layerApplies 采集元素集合
- * @param layerTemplates 图层模版
- * @return excel数据
- */
- private List<Map<String, Object>> buildShapeItemData(List<GisSurveyLayerApply> layerApplies, List<GisMetadataLayerTemplate> layerTemplates) {
- return layerApplies.parallelStream()
- .map(it -> {
- Map<String, Object> rowData = new HashMap<>();
- //获取图层模版
- GisMetadataLayerTemplate layerTemplate = ThirdImportTemplateUtils.getLayerTemplate(it, layerTemplates);
- //处理图层数据
- if (layerTemplate != null) {
- //存入图层
- if (GisMetadataDefine.TYPE_KINE.POINT.equals(it.getKind()))
- rowData.put(GisSurveyExcelDefine.FILE.POINT_LAYER, layerTemplate.getName());
- if (GisMetadataDefine.TYPE_KINE.LINE.equals(it.getKind()))
- rowData.put(GisSurveyExcelDefine.FILE.LINE_LAYER, layerTemplate.getName());
- //遍历属性
- it.getPropertyValues().forEach(propertyValue -> {
- //获取属性模版
- GisMetadataPropertyTemplate propertyTemplate = ThirdImportTemplateUtils
- .getPropertyTemplate(layerTemplate, propertyValue.getProperty());
- //填入属性数据
- if (propertyTemplate != null)
- rowData.put(StringUtils.substring(propertyTemplate.getName(), 0, 5)
- , propertyValue.getValue());
- });
- }
- //存入geom
- rowData.put(GisSurveyExcelDefine.FILE.THE_GEOM, it.getGis());
- return rowData;
- }).collect(Collectors.toList());
- }
- }
|