package com.shkpr.service.alambizplugin.components; import com.global.base.log.LogLevelFlag; import com.global.base.log.LogPrintMgr; import com.shkpr.service.alambizplugin.apiparam.GisSurveyThirdImportParams; import com.shkpr.service.alambizplugin.commtools.ExcelUtils; import com.shkpr.service.alambizplugin.components.checker.DuplicatePointsFinder; import com.shkpr.service.alambizplugin.components.checker.InvalidLinesFinder; import com.shkpr.service.alambizplugin.components.checker.InvalidPropertiesFinder; import com.shkpr.service.alambizplugin.constants.ExcelEnum; import com.shkpr.service.alambizplugin.constants.GisMetadataDefine; import com.shkpr.service.alambizplugin.constants.GisSurveyCheckStatusEnum; import com.shkpr.service.alambizplugin.constants.GisSurveyImportDefine; import com.shkpr.service.alambizplugin.constants.GisSurveyImportStatusEnum; import com.shkpr.service.alambizplugin.constants.LogFlagBusiType; import com.shkpr.service.alambizplugin.dbdao.services.intef.GisMetadataLayerTemplateService; import com.shkpr.service.alambizplugin.dto.GisMetadataLayerTemplate; import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportElement; import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResult; import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportResultDetail; import com.shkpr.service.alambizplugin.dto.GisSurveyThirdImportSubtask; import org.apache.commons.collections4.CollectionUtils; 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.io.InputStream; import java.time.Duration; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; import java.util.stream.Collectors; /** * 第三方导入执行器 * * @author 欧阳劲驰 * @since 1.0.0 */ @Component public class GisSurveyThirdImporter { /** * log */ private final String mStrClassName; private final String mBizType; private final GisMetadataLayerTemplateService layerTemplateService; private final DuplicatePointsFinder duplicatePointsFinder; private final InvalidLinesFinder invalidLinesFinder; private final InvalidPropertiesFinder invalidPropertiesFinder; public GisSurveyThirdImporter(GisMetadataLayerTemplateService layerTemplateService, DuplicatePointsFinder duplicatePointsFinder, InvalidLinesFinder invalidLinesFinder, InvalidPropertiesFinder invalidPropertiesFinder) { mStrClassName = "GisSurveyThirdImporter"; mBizType = LogFlagBusiType.BUSI_GIS_SURVEY.toStrValue(); this.layerTemplateService = layerTemplateService; this.duplicatePointsFinder = duplicatePointsFinder; this.invalidLinesFinder = invalidLinesFinder; this.invalidPropertiesFinder = invalidPropertiesFinder; } /** * 第三方导入任务 * * @param params 系统检查参数 * @param inputStreams 文件输入流 * @param onStartSubtask 启动子任务 * @param onDeprecatedSubtask 弃用子任务(完成数据收集/取消) * @return 系统检查返回 */ @Async public ListenableFuture thirdImportTask(GisSurveyThirdImportParams params, List inputStreams , Consumer onStartSubtask, Consumer onDeprecatedSubtask) { //构建返回 GisSurveyThirdImportResult result = GisSurveyThirdImportResult.fail(params); //无效属性任务 ListenableFuture>>> invalidPropertiesFuture = null; //重复点号任务 ListenableFuture>> duplicatePointsFuture = null; //无效线任务 ListenableFuture>> invalidLinesFuture = null; //点集合 List> points = new ArrayList<>(); //线集合 List> lines = new ArrayList<>(); try { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName , String.format( "开始执行第三方导入;任务id: %s" , params.getJobId() ) ); //解析excel parseExcel(inputStreams, points, lines); //提取图层名 List pointLayerNames = getLayerNames(points, GisSurveyImportDefine.POINT.LAYER); List listLayerNames = getLayerNames(lines, GisSurveyImportDefine.LINE.LAYER); //图层模版 List pointLayerTemplates = layerTemplateService.findByNatureAndNameIn(params.getNature(), pointLayerNames); List lineLayerTemplates = layerTemplateService.findByNatureAndNameIn(params.getNature(), listLayerNames); //无效属性检查 invalidPropertiesFuture = invalidPropertiesFinder.findInvalidProperties(points, lines, pointLayerTemplates, lineLayerTemplates); //重复点检查 duplicatePointsFuture = duplicatePointsFinder.findDuplicatePoints(points); //无效线检查 invalidLinesFuture = invalidLinesFinder.finderInvalidLines(points, lines); //返回子任务 onStartSubtask.accept( new GisSurveyThirdImportSubtask(invalidPropertiesFuture, duplicatePointsFuture, invalidLinesFuture) ); //等待结果 GisSurveyThirdImportResultDetail>> invalidPropertiesResult = invalidPropertiesFuture.get(); //存入无效属性结果 result.setInvalidLayersResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyImportDefine.RESULT.INVALID_LAYERS)); result.setMissingRequirementsResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyImportDefine.RESULT.MISSING_REQUIREMENTS)); result.setInvalidTypesResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyImportDefine.RESULT.INVALID_TYPES)); result.setOutRangesResult(untarInvalidProperties(invalidPropertiesResult, GisSurveyImportDefine.RESULT.OUT_RANGES)); //存入重复点结果 result.setDuplicatePointsResult(duplicatePointsFuture.get()); //存入无效线结果 result.setInvalidLinesResult(invalidLinesFuture.get()); //结果未通过 if (!checkResult(result)) { result.setImportStatus(GisSurveyImportStatusEnum.DATA_ERROR.getCode()); result.setCompleteTime(LocalDateTime.now()); //弃用子任务 onDeprecatedSubtask.accept(params.getJobId()); return new AsyncResult<>(result); } //格式化数据,并入库 //完成任务 result.setImportStatus(GisSurveyImportStatusEnum.SUCCESS.getCode()); result.setCompleteTime(LocalDateTime.now()); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName , String.format( "结束执行第三方导入;任务id: %s, 用时(毫秒):%d", params.getJobId(), Duration.between(result.getRequestTime(), result.getCompleteTime()).toMillis() ) ); //弃用子任务 onDeprecatedSubtask.accept(params.getJobId()); return new AsyncResult<>(result); } catch (InterruptedException | ExecutionException | IOException | RuntimeException e) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR, mBizType, mStrClassName , String.format( "监测到中断或执行异常,开始清除子任务 任务id:%s error:%s", params.getJobId(), e ) ); //清除子任务 if (invalidPropertiesFuture != null) invalidPropertiesFuture.cancel(true); if (duplicatePointsFuture != null) duplicatePointsFuture.cancel(true); if (invalidLinesFuture != null) invalidLinesFuture.cancel(true); //失败信息 result.setImportStatus(GisSurveyCheckStatusEnum.FAIL.getCode()); result.setCompleteTime(LocalDateTime.now()); //弃用子任务 onDeprecatedSubtask.accept(params.getJobId()); return new AsyncResult<>(result); } } /** * 解析excel * * @param inputStreams 输入流 * @param points 点集合 * @param lines 线集合 * @throws IOException io异常 */ private void parseExcel(List inputStreams, List> points, List> lines) throws IOException { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName, "开始执行解析excel ======>"); long begin = System.currentTimeMillis(); //解析文件 for (InputStream inputStream : inputStreams) { //解析excel Map>> excelData = ExcelUtils.parseExcelFile(inputStream, ExcelEnum.XLSX, 0, 3); //填入集合 if (excelData != null && excelData.containsKey(GisMetadataDefine.TYPE_KINE.POINT)) points.addAll(excelData.get(GisMetadataDefine.TYPE_KINE.POINT)); if (excelData != null && excelData.containsKey(GisMetadataDefine.TYPE_KINE.LINE)) lines.addAll(excelData.get(GisMetadataDefine.TYPE_KINE.LINE)); //释放流 inputStream.close(); } long end = System.currentTimeMillis(); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, mBizType, mStrClassName , String.format( "结束执行执行解析excel,用时(毫秒):%d" , (end - begin) ) ); } /** * 获取图层名称 * * @param datas 数据 * @param layerKey 图层的key * @return 图层名称集合 */ private List getLayerNames(List> datas, String layerKey) { //去重图层 return datas.parallelStream() .filter(data -> data.get(layerKey) != null) .map(data -> data.get(layerKey)) .distinct() .collect(Collectors.toList()); } /** * 解包无效属性 * * @param invalidPropertiesResult 无效属性结果 * @param resultKey 结果key * @return 具体结果 */ private GisSurveyThirdImportResultDetail> untarInvalidProperties( GisSurveyThirdImportResultDetail>> invalidPropertiesResult , String resultKey) { //获取结果 List importElements = invalidPropertiesResult.getResults().get(resultKey); return new GisSurveyThirdImportResultDetail<>(true, importElements); } /** * 检查结果 * * @param result 结果 * @return 结果通过状态 */ private Boolean checkResult(GisSurveyThirdImportResult result) { List invalidLayers = result.getInvalidLayersResult().getResults(); List missingRequirements = result.getMissingRequirementsResult().getResults(); List invalidTypesResult = result.getInvalidTypesResult().getResults(); List outRanges = result.getOutRangesResult().getResults(); List duplicatePoints = result.getDuplicatePointsResult().getResults(); List invalidLines = result.getInvalidLinesResult().getResults(); //检查是否都为空 return CollectionUtils.isEmpty(invalidLayers) && CollectionUtils.isEmpty(missingRequirements) && CollectionUtils.isEmpty(invalidTypesResult) && CollectionUtils.isEmpty(outRanges) && CollectionUtils.isEmpty(duplicatePoints) && CollectionUtils.isEmpty(invalidLines); } }