GisSurveyThirdExporter.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. package com.shkpr.service.alambizplugin.components;
  2. import com.fasterxml.jackson.core.type.TypeReference;
  3. import com.global.base.log.LogLevelFlag;
  4. import com.global.base.log.LogPrintMgr;
  5. import com.shkpr.service.alambizplugin.commtools.ThirdImportTemplateUtils;
  6. import com.shkpr.service.alambizplugin.constants.CommAsyncStatusEnum;
  7. import com.shkpr.service.alambizplugin.constants.FileTypeEnum;
  8. import com.shkpr.service.alambizplugin.constants.GisMetadataDefine;
  9. import com.shkpr.service.alambizplugin.constants.GisSurveyExcelDefine;
  10. import com.shkpr.service.alambizplugin.constants.LogFlagBusiType;
  11. import com.shkpr.service.alambizplugin.dbdao.services.intef.GisMetadataLayerTemplateService;
  12. import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyJobInfoService;
  13. import com.shkpr.service.alambizplugin.dbdao.services.intef.GisSurveyLayerApplyService;
  14. import com.shkpr.service.alambizplugin.dto.CommAsyncResult;
  15. import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate;
  16. import com.shkpr.service.alambizplugin.dto.GisMetadataPropertyTemplate;
  17. import com.shkpr.service.alambizplugin.dto.GisSurveyLayerApply;
  18. import com.shkpr.service.alambizplugin.dto.GisSurveyPropertyValue;
  19. import org.apache.commons.compress.archivers.ArchiveException;
  20. import org.apache.commons.lang3.StringUtils;
  21. import org.geotools.data.DataUtilities;
  22. import org.geotools.feature.SchemaException;
  23. import org.opengis.feature.simple.SimpleFeatureType;
  24. import org.springframework.scheduling.annotation.Async;
  25. import org.springframework.scheduling.annotation.AsyncResult;
  26. import org.springframework.stereotype.Component;
  27. import org.springframework.util.concurrent.ListenableFuture;
  28. import java.io.IOException;
  29. import java.nio.file.Files;
  30. import java.nio.file.Path;
  31. import java.time.Duration;
  32. import java.time.LocalDateTime;
  33. import java.util.Collections;
  34. import java.util.Comparator;
  35. import java.util.HashMap;
  36. import java.util.LinkedHashMap;
  37. import java.util.List;
  38. import java.util.Map;
  39. import java.util.Objects;
  40. import java.util.stream.Collectors;
  41. /**
  42. * 第三方导出执行器
  43. *
  44. * @author 欧阳劲驰
  45. * @since 1.0.0
  46. */
  47. @Component
  48. public class GisSurveyThirdExporter {
  49. /**
  50. * 结果前缀
  51. */
  52. public final static String RESULT_PREFIX = "third-export-";
  53. /**
  54. * log
  55. */
  56. private final String mStrClassName;
  57. private final String mBizType;
  58. private final AsyncResultManager asyncResultManager;
  59. private final GisSurveyJobInfoService jobInfoService;
  60. private final GisMetadataLayerTemplateService layerTemplateService;
  61. private final GisSurveyLayerApplyService gisSurveyLayerApplyService;
  62. public GisSurveyThirdExporter(AsyncResultManager asyncResultManager, GisSurveyJobInfoService jobInfoService
  63. , GisMetadataLayerTemplateService layerTemplateService, GisSurveyLayerApplyService gisSurveyLayerApplyService) {
  64. mStrClassName = "GisSurveyThirdExporter";
  65. mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue();
  66. this.asyncResultManager = asyncResultManager;
  67. this.jobInfoService = jobInfoService;
  68. this.layerTemplateService = layerTemplateService;
  69. this.gisSurveyLayerApplyService = gisSurveyLayerApplyService;
  70. }
  71. /**
  72. * 第三方导出任务
  73. *
  74. * @param jobId 任务id
  75. * @param fileType 导出文件类型
  76. * @param operator 操作人
  77. * @return 导出结果
  78. */
  79. @Async
  80. public ListenableFuture<CommAsyncResult<Map<String, String>>> thirdExportTask(String jobId, FileTypeEnum fileType, String operator) {
  81. //构建返回
  82. CommAsyncResult<Map<String, String>> result = CommAsyncResult.fail(jobId);
  83. result.setOperator(operator);
  84. try {
  85. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  86. , String.format(
  87. "开始执行第三方导出;任务id: %s"
  88. , jobId
  89. )
  90. );
  91. //查询元素更新时间
  92. LocalDateTime refreshTime = jobInfoService.findRefreshTime(jobId);
  93. //查询点线数据
  94. List<GisSurveyLayerApply> points = gisSurveyLayerApplyService.findAllByJobIdAndKind(jobId, GisMetadataDefine.TYPE_KINE.POINT);
  95. List<GisSurveyLayerApply> lines = gisSurveyLayerApplyService.findAllByJobIdAndKind(jobId, GisMetadataDefine.TYPE_KINE.LINE);
  96. //获取图层key
  97. List<String> pointLayer = getLayerKeys(points);
  98. List<String> lineLayer = getLayerKeys(lines);
  99. //查询点图层模版
  100. List<GisMetadataLayerTemplate> pointLayerTemplates = layerTemplateService.findByKeyIn(pointLayer);
  101. //查询线图层模版
  102. List<GisMetadataLayerTemplate> lineLayerTemplates = layerTemplateService.findByKeyIn(lineLayer);
  103. //结果flag
  104. final String FLAG = RESULT_PREFIX + jobId;
  105. //创建临时文件夹
  106. if (!asyncResultManager.createTempDirectory(FLAG))
  107. return new AsyncResult<>(result);
  108. //根据文件类型导出
  109. Path outputPath = null;
  110. if (fileType == FileTypeEnum.EXCEL)
  111. outputPath = exportExcel(points, lines, pointLayerTemplates, lineLayerTemplates, FLAG);
  112. if (fileType == FileTypeEnum.SHAPE_FILE)
  113. outputPath = exportShape(points, lines, pointLayerTemplates, lineLayerTemplates, FLAG);
  114. if (outputPath == null || !Files.exists(outputPath)) {
  115. //打印报错信息
  116. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
  117. , String.format("第三方导出文件写入失败, 任务id:%s", jobId)
  118. );
  119. return new AsyncResult<>(result);
  120. }
  121. //获取上次结果
  122. CommAsyncResult<Map<String, String>> lastResult = asyncResultManager.getResult(FLAG, new TypeReference<CommAsyncResult<Map<String, String>>>() {
  123. });
  124. //设置数据
  125. Map<String, String> data = new HashMap<>();
  126. if (lastResult != null && lastResult.getData() != null) data = lastResult.getData();
  127. data.put(fileType.getName(), FLAG + "/" + outputPath.getFileName().toString());
  128. //设置数据时间
  129. Map<String, LocalDateTime> refreshTimes = new HashMap<>();
  130. if (lastResult != null && lastResult.getRefreshTimes() != null) refreshTimes = lastResult.getRefreshTimes();
  131. refreshTimes.put(fileType.getName(), refreshTime);
  132. //导出完成
  133. result.setStatus(CommAsyncStatusEnum.SUCCESS.getCode());
  134. result.setCompleteTime(LocalDateTime.now());
  135. result.setData(data);
  136. result.setRefreshTimes(refreshTimes);
  137. result.setSubitemKeys(Collections.singletonList(fileType.getName()));
  138. //写入结果
  139. Path resultPath = asyncResultManager.writeJson(result, FLAG, AsyncResultManager.RESULT_FILE_NAME);
  140. if (resultPath == null || !Files.exists(resultPath)) {
  141. //打印报错信息
  142. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
  143. , String.format("第三方导出文件写入失败, 任务id:%s", jobId)
  144. );
  145. return new AsyncResult<>(CommAsyncResult.fail(jobId));
  146. }
  147. //替换结果
  148. if (!asyncResultManager.replaceResult(FLAG)) return new AsyncResult<>(CommAsyncResult.fail(jobId));
  149. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  150. , String.format(
  151. "结束第三方导出;任务id: %s, 用时(毫秒):%d"
  152. , jobId
  153. , Duration.between(result.getRequestTime(), result.getCompleteTime()).toMillis()
  154. )
  155. );
  156. return new AsyncResult<>(result);
  157. } catch (InterruptedException | IOException | ArchiveException | SchemaException e) {
  158. //打印报错信息
  159. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName
  160. , String.format("第三方导出异常 任务id:%s error:%s", jobId, e)
  161. );
  162. return new AsyncResult<>(CommAsyncResult.fail(jobId));
  163. }
  164. }
  165. /**
  166. * 导出excel
  167. *
  168. * @param points 点
  169. * @param lines 线
  170. * @param pointLayerTemplates 点图层模版
  171. * @param lineLayerTemplates 线图层模版
  172. * @param FLAG 结果flag
  173. * @return excel路径
  174. * @throws IOException io异常
  175. */
  176. private Path exportExcel(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines, List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates, String FLAG) throws IOException {
  177. //构建excel头
  178. Map<String, Map<String, String>> excelHeader = buildExcelHeader(pointLayerTemplates, lineLayerTemplates);
  179. //构建excel数据
  180. Map<String, List<Map<String, Object>>> excelData = buildExcelData(points, lines, pointLayerTemplates, lineLayerTemplates);
  181. //导出excel
  182. return asyncResultManager.writeExcel(excelHeader, excelData, FLAG, "third-export.xlsx");
  183. }
  184. /**
  185. * 导出shape
  186. *
  187. * @param points 点
  188. * @param lines 线
  189. * @param pointLayerTemplates 点图层模版
  190. * @param lineLayerTemplates 线图层模版
  191. * @param FLAG 结果flag
  192. * @return shape路径
  193. * @throws IOException io异常
  194. * @throws ArchiveException 压缩异常
  195. */
  196. private Path exportShape(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines, List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates, String FLAG) throws IOException, ArchiveException, SchemaException {
  197. //构建shape数据
  198. Map<SimpleFeatureType, List<Map<String, Object>>> shapeData = buildShapeData(points, lines, pointLayerTemplates, lineLayerTemplates);
  199. //导出shape
  200. return asyncResultManager.writeShape(shapeData, FLAG, "third-export.zip");
  201. }
  202. /**
  203. * 获取图层key
  204. *
  205. * @param datas 数据
  206. * @return 图层key集合
  207. */
  208. private List<String> getLayerKeys(List<GisSurveyLayerApply> datas) {
  209. //去重图层
  210. return datas.parallelStream()
  211. .map(GisSurveyLayerApply::getLayer)
  212. .filter(StringUtils::isNotBlank)
  213. .distinct()
  214. .collect(Collectors.toList());
  215. }
  216. /**
  217. * 构建excel表头
  218. *
  219. * @param pointLayerTemplates 点图层模版
  220. * @param lineLayerTemplates 线图层模版
  221. * @return excel数据
  222. */
  223. private Map<String, Map<String, String>> buildExcelHeader(List<GisMetadataLayerTemplate> pointLayerTemplates
  224. , List<GisMetadataLayerTemplate> lineLayerTemplates) {
  225. //点excel表头
  226. Map<String, String> pointExcelHeader = new LinkedHashMap<>();
  227. //线excel表头
  228. Map<String, String> lineExcelHeader = new LinkedHashMap<>();
  229. //点模版表头
  230. Map<String, String> pointTemplateHeader = pointLayerTemplates.stream()
  231. .flatMap(it -> it.getPropertyTemplates().stream())
  232. .sorted(Comparator.comparing(GisMetadataPropertyTemplate::getOrdering))
  233. .collect(Collectors.toMap(GisMetadataPropertyTemplate::getKey, GisMetadataPropertyTemplate::getName
  234. , (it1, it2) -> it1, LinkedHashMap::new));
  235. //线模版表头
  236. Map<String, String> lineTemplateHeader = lineLayerTemplates.stream()
  237. .flatMap(it -> it.getPropertyTemplates().stream())
  238. .collect(Collectors.toMap(GisMetadataPropertyTemplate::getKey, GisMetadataPropertyTemplate::getName
  239. , (it1, it2) -> it1, LinkedHashMap::new));
  240. //加入图层表头
  241. pointExcelHeader.put(GisSurveyExcelDefine.TEMPLATE.LAYER, GisSurveyExcelDefine.FILE.POINT_LAYER);
  242. lineExcelHeader.put(GisSurveyExcelDefine.TEMPLATE.LAYER, GisSurveyExcelDefine.FILE.LINE_LAYER);
  243. //加入模版表头
  244. pointExcelHeader.putAll(pointTemplateHeader);
  245. lineExcelHeader.putAll(lineTemplateHeader);
  246. //excel表头
  247. Map<String, Map<String, String>> excelHeader = new HashMap<>();
  248. excelHeader.put(GisMetadataDefine.TYPE_KINE.POINT, pointExcelHeader);
  249. excelHeader.put(GisMetadataDefine.TYPE_KINE.LINE, lineExcelHeader);
  250. return excelHeader;
  251. }
  252. /**
  253. * 构建excel数据
  254. *
  255. * @param points 点元素
  256. * @param lines 线元素
  257. * @param pointLayerTemplates 点图层模版
  258. * @param lineLayerTemplates 线图层模版
  259. * @return excel数据
  260. */
  261. private Map<String, List<Map<String, Object>>> buildExcelData(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines
  262. , List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates) {
  263. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始构建excel数据 ======>");
  264. long begin = System.currentTimeMillis();
  265. //excel数据
  266. Map<String, List<Map<String, Object>>> excelData = new HashMap<>();
  267. excelData.put(GisMetadataDefine.TYPE_KINE.POINT, buildExcelSheetData(points, pointLayerTemplates));
  268. excelData.put(GisMetadataDefine.TYPE_KINE.LINE, buildExcelSheetData(lines, lineLayerTemplates));
  269. long end = System.currentTimeMillis();
  270. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  271. , String.format(
  272. "结束构建excel数据,用时(毫秒):%d"
  273. , (end - begin)
  274. )
  275. );
  276. return excelData;
  277. }
  278. /**
  279. * 构建excel页数据
  280. *
  281. * @param layerApplies 采集元素集合
  282. * @param layerTemplates 图层模版
  283. * @return excel数据
  284. */
  285. private List<Map<String, Object>> buildExcelSheetData(List<GisSurveyLayerApply> layerApplies, List<GisMetadataLayerTemplate> layerTemplates) {
  286. return layerApplies.parallelStream()
  287. .map(it -> {
  288. //处理模版数据
  289. Map<String, Object> rowData = it.getPropertyValues().stream()
  290. .filter(it1 -> !StringUtils.isAnyBlank(it1.getProperty(), it1.getValue()))
  291. .collect(Collectors.toMap(GisSurveyPropertyValue::getProperty, GisSurveyPropertyValue::getValue
  292. , (i1, i2) -> i1));
  293. //处理图层数据
  294. if (StringUtils.isNotBlank(it.getLayer())) {
  295. //获取模版
  296. GisMetadataLayerTemplate gisMetadataLayerTemplate = layerTemplates.stream()
  297. .filter(it1 -> Objects.equals(it1.getKey(), it.getLayer()))
  298. .findFirst().orElse(null);
  299. //存入图层
  300. if (gisMetadataLayerTemplate != null)
  301. rowData.put(GisSurveyExcelDefine.TEMPLATE.LAYER, gisMetadataLayerTemplate.getName());
  302. }
  303. return rowData;
  304. }).collect(Collectors.toList());
  305. }
  306. /**
  307. * 构建shape数据
  308. *
  309. * @param points 点元素
  310. * @param lines 线元素
  311. * @param pointLayerTemplates 点图层模版
  312. * @param lineLayerTemplates 线图层模版
  313. * @return excel数据
  314. */
  315. private Map<SimpleFeatureType, List<Map<String, Object>>> buildShapeData(List<GisSurveyLayerApply> points, List<GisSurveyLayerApply> lines
  316. , List<GisMetadataLayerTemplate> pointLayerTemplates, List<GisMetadataLayerTemplate> lineLayerTemplates) throws SchemaException {
  317. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始构建shape属性头和数据 ======>");
  318. long begin = System.currentTimeMillis();
  319. //点模版规格
  320. String pointTemplateSpec = pointLayerTemplates.stream()
  321. .flatMap(it -> it.getPropertyTemplates().stream())
  322. .sorted(Comparator.comparing(GisMetadataPropertyTemplate::getOrdering))
  323. .map(it ->
  324. String.format("%s%s"
  325. , StringUtils.substring(it.getName(), 0, 5)
  326. , GisSurveyExcelDefine.FILE_HANDLE.COL_SPEC)
  327. )
  328. .distinct()
  329. .collect(Collectors.joining(","));
  330. //线模版规格
  331. String lineTemplateSpec = lineLayerTemplates.stream()
  332. .flatMap(it -> it.getPropertyTemplates().stream())
  333. .sorted(Comparator.comparing(GisMetadataPropertyTemplate::getOrdering))
  334. .map(it ->
  335. String.format("%s%s"
  336. , StringUtils.substring(it.getName(), 0, 5)
  337. , GisSurveyExcelDefine.FILE_HANDLE.COL_SPEC)
  338. )
  339. .distinct()
  340. .collect(Collectors.joining(","));
  341. //创建点类型
  342. final SimpleFeatureType POINT_TYPE = DataUtilities.createType(
  343. "point",
  344. String.format("%s%s", GisSurveyExcelDefine.FILE_HANDLE.POINT_SPEC, pointTemplateSpec)
  345. );
  346. //创建线类型
  347. final SimpleFeatureType LINE_TYPE = DataUtilities.createType(
  348. "line",
  349. String.format("%s%s", GisSurveyExcelDefine.FILE_HANDLE.LINE_SPEC, lineTemplateSpec)
  350. );
  351. //shape数据
  352. Map<SimpleFeatureType, List<Map<String, Object>>> shapeData = new HashMap<>();
  353. shapeData.put(POINT_TYPE, buildShapeItemData(points, pointLayerTemplates));
  354. shapeData.put(LINE_TYPE, buildShapeItemData(lines, lineLayerTemplates));
  355. long end = System.currentTimeMillis();
  356. LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName
  357. , String.format(
  358. "结束构建shape属性头和数据,用时(毫秒):%d"
  359. , (end - begin)
  360. )
  361. );
  362. return shapeData;
  363. }
  364. /**
  365. * 构建shape项数据
  366. *
  367. * @param layerApplies 采集元素集合
  368. * @param layerTemplates 图层模版
  369. * @return excel数据
  370. */
  371. private List<Map<String, Object>> buildShapeItemData(List<GisSurveyLayerApply> layerApplies, List<GisMetadataLayerTemplate> layerTemplates) {
  372. return layerApplies.parallelStream()
  373. .map(it -> {
  374. Map<String, Object> rowData = new HashMap<>();
  375. //获取图层模版
  376. GisMetadataLayerTemplate layerTemplate = ThirdImportTemplateUtils.getLayerTemplate(it, layerTemplates);
  377. //处理图层数据
  378. if (layerTemplate != null) {
  379. //存入图层
  380. if (GisMetadataDefine.TYPE_KINE.POINT.equals(it.getKind()))
  381. rowData.put(GisSurveyExcelDefine.FILE.POINT_LAYER, layerTemplate.getName());
  382. if (GisMetadataDefine.TYPE_KINE.LINE.equals(it.getKind()))
  383. rowData.put(GisSurveyExcelDefine.FILE.LINE_LAYER, layerTemplate.getName());
  384. //遍历属性
  385. it.getPropertyValues().forEach(propertyValue -> {
  386. //获取属性模版
  387. GisMetadataPropertyTemplate propertyTemplate = ThirdImportTemplateUtils
  388. .getPropertyTemplate(layerTemplate, propertyValue.getProperty());
  389. //填入属性数据
  390. if (propertyTemplate != null)
  391. rowData.put(StringUtils.substring(propertyTemplate.getName(), 0, 5)
  392. , propertyValue.getValue());
  393. });
  394. }
  395. //存入geom
  396. rowData.put(GisSurveyExcelDefine.FILE.THE_GEOM, it.getGis());
  397. return rowData;
  398. }).collect(Collectors.toList());
  399. }
  400. }