|
@@ -0,0 +1,506 @@
|
|
|
+package com.persagy.bdtp.adm.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.date.DatePattern;
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.util.ArrayUtil;
|
|
|
+import cn.hutool.core.util.IdUtil;
|
|
|
+import cn.hutool.core.util.ReflectUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
|
+import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
|
+import com.persagy.bdtp.adm.common.AdmConst;
|
|
|
+import com.persagy.bdtp.adm.common.AdmResult;
|
|
|
+import com.persagy.bdtp.adm.dao.AdmJobSpaceMapper;
|
|
|
+import com.persagy.bdtp.adm.dao.AdmObjectMapper;
|
|
|
+import com.persagy.bdtp.adm.entity.AdmJobSpace;
|
|
|
+import com.persagy.bdtp.adm.entity.AdmObject;
|
|
|
+import com.persagy.bdtp.adm.entity.oldadm.*;
|
|
|
+import com.persagy.bdtp.adm.service.CallException;
|
|
|
+import com.persagy.bdtp.adm.service.IAdmObjectService;
|
|
|
+import com.persagy.bdtp.adm.service.IQueryFromOldAdm;
|
|
|
+import com.persagy.bdtp.adm.service.ISyncOldAdm;
|
|
|
+import com.persagy.dmp.common.constant.ResponseCode;
|
|
|
+import com.persagy.dmp.common.constant.ValidEnum;
|
|
|
+import com.persagy.dmp.common.exception.BusinessException;
|
|
|
+import com.persagy.dmp.common.helper.SpringHelper;
|
|
|
+import com.persagy.dmp.common.lang.PsDateTime;
|
|
|
+import org.locationtech.jts.geom.Coordinate;
|
|
|
+import org.locationtech.jts.geom.GeometryFactory;
|
|
|
+import org.locationtech.jts.geom.LinearRing;
|
|
|
+import org.locationtech.jts.geom.Polygon;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.util.*;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class SyncOldAdmImpl implements ISyncOldAdm {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IQueryFromOldAdm queryOldAdm;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IAdmObjectService objectService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AdmObjectMapper objectMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AdmJobSpaceMapper jobSpaceMapper;
|
|
|
+
|
|
|
+ private static GeometryFactory geometryFactory = new GeometryFactory();
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Map<String, Object> syncData(String groupCode, String projectId) {
|
|
|
+ String token = queryOldAdm.login();
|
|
|
+ if(StrUtil.isNotBlank(token)){
|
|
|
+ List<OBuilding> bdList = queryOldAdm.queryBdAnFl(token, groupCode, projectId);
|
|
|
+ List<OSpace> spList = queryOldAdm.querySpace(token, groupCode, projectId);
|
|
|
+ List<OEquip> eqList = queryOldAdm.queryEquip(token, groupCode, projectId);
|
|
|
+
|
|
|
+ List<AdmObject> bdObjs = new ArrayList<>(bdList.size());
|
|
|
+ List<AdmObject> flObjs = new ArrayList<>();
|
|
|
+ List<AdmObject> spObjs = new ArrayList<>(spList.size());
|
|
|
+ List<AdmObject> eqObjs = new ArrayList<>(eqList.size());
|
|
|
+
|
|
|
+ transEntities(bdObjs, bdList, (bdObj, oBd) -> {
|
|
|
+ setBdData(bdObj, (OBuilding) oBd);
|
|
|
+ if(((OBuilding) oBd).getFloor() != null)
|
|
|
+ transEntities(flObjs, ((OBuilding) oBd).getFloor(), (flObj, oFl) -> setFlData(flObj, (OFloor) oFl));
|
|
|
+ });
|
|
|
+
|
|
|
+ transEntities(spObjs, spList, (spObj, oSp) -> setSpData(spObj, (OSpace) oSp));
|
|
|
+ transEntities(eqObjs, eqList, (eqObj, oEq) -> setEqData(eqObj, (OEquip) oEq));
|
|
|
+
|
|
|
+ List<AdmObject> dbBds = objectService.queryM2dByObjType(projectId, AdmConst.OBJ_TYPE_BUILDING);
|
|
|
+ List<AdmObject> dbFls = objectService.queryM2dByObjType(projectId, AdmConst.OBJ_TYPE_FLOOR);
|
|
|
+ List<AdmObject> dbSps = objectService.queryM2dByObjType(projectId, AdmConst.OBJ_TYPE_SPACE);
|
|
|
+ List<AdmObject> dbEqs = objectService.queryM2dByObjType(projectId, AdmConst.OBJ_TYPE_EQUIPMENT);
|
|
|
+
|
|
|
+ List<AdmObject>[] operations = new List[]{new ArrayList<>(), new ArrayList<>()};
|
|
|
+
|
|
|
+ syncObjs(bdObjs, dbBds, operations, 1);
|
|
|
+ syncObjs(flObjs, dbFls, operations, 2);
|
|
|
+ syncObjs(spObjs, dbSps, operations, 3);
|
|
|
+ syncObjs(eqObjs, dbEqs, operations, 4);
|
|
|
+
|
|
|
+ objectService.insert(operations[0]);
|
|
|
+ objectService.update(operations[1]);
|
|
|
+
|
|
|
+ /*uploadFloorMap(flObjs, groupCode, projectId);*/
|
|
|
+ HashMap<String, Object> rtn = new HashMap<>();
|
|
|
+ rtn.put(AdmConst.OBJ_TYPE_BUILDING, bdObjs.size());
|
|
|
+ rtn.put(AdmConst.OBJ_TYPE_FLOOR, flObjs.size());
|
|
|
+ rtn.put(AdmConst.OBJ_TYPE_SPACE, spObjs.size());
|
|
|
+ rtn.put(AdmConst.OBJ_TYPE_EQUIPMENT, eqObjs.size());
|
|
|
+
|
|
|
+ return rtn;
|
|
|
+ }
|
|
|
+ throw new CallException(new AdmResult(ResponseCode.A0220.getCode(), "ADM platform: " + ResponseCode.A0220.getDesc()));
|
|
|
+ }
|
|
|
+
|
|
|
+ //TODO 设备同步时,按正逆向规则过滤
|
|
|
+ private void syncObjs(List<AdmObject> objs, List<AdmObject> dbItems, List<AdmObject>[] operations, int objMark){
|
|
|
+ HashMap<String, AdmObject> dbMap = new HashMap<>();
|
|
|
+ for (AdmObject dbItem : dbItems){
|
|
|
+ dbMap.put(dbItem.getId(), dbItem); //localId?
|
|
|
+ }
|
|
|
+
|
|
|
+ for(AdmObject obj : objs) {
|
|
|
+ AdmObject dbItem = dbMap.remove(obj.getId()); //localId?
|
|
|
+ if(dbItem == null)
|
|
|
+ operations[0].add(obj); //add
|
|
|
+ else {
|
|
|
+ AdmObject updateItem = mergeObj(obj, dbItem, objMark);
|
|
|
+ if(updateItem != null)
|
|
|
+ operations[1].add(updateItem); //modify
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dbMap.size() > 0) { //remove
|
|
|
+ for(AdmObject obj : dbMap.values()){
|
|
|
+ obj.setValid(ValidEnum.FALSE.getType());
|
|
|
+ //obj.setModifiedTime(new PsDateTime(System.currentTimeMillis()));
|
|
|
+ operations[1].add(obj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private AdmObject mergeObj(AdmObject obj, AdmObject dbItem, int objMark){
|
|
|
+ if(objNotChange(obj, dbItem))
|
|
|
+ return null;
|
|
|
+
|
|
|
+ //TODO 按交付规则,合并属性和信息点
|
|
|
+ if(objMark == 3) {//space
|
|
|
+
|
|
|
+ } else if(objMark == 4) {//equipment
|
|
|
+
|
|
|
+ }
|
|
|
+ return obj;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean objNotChange(AdmObject obj, AdmObject dbItem){
|
|
|
+ //TODO 数据无变化判断
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 暂时使用image-service
|
|
|
+ private void uploadFloorMap(ArrayList<AdmObject> flObjs, String groupCode, String projectId){
|
|
|
+ for(AdmObject obj : flObjs) {
|
|
|
+ JsonNode node = obj.getInfo("floorMap");
|
|
|
+ if(node != null){
|
|
|
+ String map = node.asText();
|
|
|
+ if(StrUtil.isNotBlank(map)) {
|
|
|
+ Response serviceResponse = admClient.getFloorMap(map, "revit");
|
|
|
+ Response.Body body = serviceResponse.body();
|
|
|
+ FileInfo fileInfo = FileInfoCreator.of(groupCode, projectId + "_floorMap", "adm", map);
|
|
|
+ try {
|
|
|
+ FileStorageHelper.uploadFile(fileInfo, body.asInputStream());
|
|
|
+ } catch (IOException e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+ private <T extends OBase> void transEntities(List<AdmObject> targetList, List<T> list, SetDataAction setDataAction){
|
|
|
+ if(list != null && list.size() > 0) {
|
|
|
+ for(T item : list) {
|
|
|
+ AdmObject obj = buildAdmObject(item);
|
|
|
+ setDataAction.setData(obj, item);
|
|
|
+ targetList.add(obj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private AdmObject buildAdmObject(OBase base){
|
|
|
+ AdmObject obj = new AdmObject();
|
|
|
+ obj.setId(base.getId());
|
|
|
+ obj.setLocalId(base.getLocalId());
|
|
|
+ obj.setName(base.getName());
|
|
|
+ obj.setLocalName(base.getLocalName());
|
|
|
+ obj.setObjType(base.getObjectType());
|
|
|
+
|
|
|
+ if (base.getInfos() != null)
|
|
|
+ obj.setInfos(mapToNode(base.getInfos()));
|
|
|
+
|
|
|
+ if(base.getCreateTime() != null)
|
|
|
+ obj.setCreationTime(new PsDateTime(base.getCreateTime()));
|
|
|
+ if(base.getLastUpdate() != null)
|
|
|
+ obj.setModifiedTime(new PsDateTime(base.getLastUpdate()));
|
|
|
+
|
|
|
+ obj.setValid(ValidEnum.TRUE.getType());
|
|
|
+
|
|
|
+ return obj;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setBdData(AdmObject obj, OBuilding bd){
|
|
|
+ obj.setProjectId(bd.getProjectId());
|
|
|
+ obj.setClassCode(bd.getObjectType());
|
|
|
+ //obj.setBuildingId(bd.getId());
|
|
|
+
|
|
|
+ if(bd.getDefaultQRCode() != null)
|
|
|
+ getInfos(obj).put("defaultQRCode", bd.getDefaultQRCode());
|
|
|
+ if(bd.getBuildQRCode() != null)
|
|
|
+ getInfos(obj).put("buildQRCode", bd.getBuildQRCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setFlData(AdmObject obj, OFloor fl){
|
|
|
+ obj.setProjectId(fl.getProjectId());
|
|
|
+ obj.setBuildingId(fl.getBuildingId());
|
|
|
+ //obj.setFloorId(fl.getId());
|
|
|
+ obj.setClassCode(fl.getObjectType());
|
|
|
+
|
|
|
+ setInfos(obj, fl, "projectId", "buildingId", "floorId");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setSpData(AdmObject obj, OSpace sp) {
|
|
|
+ obj.setProjectId(sp.getProjectId());
|
|
|
+ obj.setBuildingId(sp.getBuildingId());
|
|
|
+ obj.setFloorId(sp.getFloorId());
|
|
|
+ obj.setClassCode(sp.getClassCode());
|
|
|
+ obj.setObjType(AdmConst.OBJ_TYPE_SPACE);
|
|
|
+
|
|
|
+ setInfos(obj, sp, "projectId", "buildingId", "floorId", "classCode");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setEqData(AdmObject obj, OEquip eq) {
|
|
|
+ obj.setProjectId(eq.getProjectId());
|
|
|
+ obj.setBuildingId(eq.getBuildingId());
|
|
|
+ obj.setFloorId(eq.getFloorId());
|
|
|
+ obj.setClassCode(eq.getClassCode());
|
|
|
+
|
|
|
+ setInfos(obj, eq, "projectId", "buildingId", "floorId", "propertyId", "classCode");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setInfos(AdmObject obj, OBase oEntity, String... ignoreFields){
|
|
|
+ Field[] fields = oEntity.getClass().getDeclaredFields();
|
|
|
+ for (Field field : fields) {
|
|
|
+ if(ignoreFields.length == 0 || !ArrayUtil.contains(ignoreFields, field.getName())) {
|
|
|
+ Object val = ReflectUtil.getFieldValue(oEntity, field);
|
|
|
+ if(val != null) {
|
|
|
+ ObjectNode infos = getInfos(obj);
|
|
|
+ if(val instanceof String)
|
|
|
+ infos.put(field.getName(), (String)val);
|
|
|
+ else if(val instanceof Integer)
|
|
|
+ infos.put(field.getName(), (Integer)val);
|
|
|
+ else if(val instanceof Float)
|
|
|
+ infos.put(field.getName(), (Float)val);
|
|
|
+ else if(val instanceof Double)
|
|
|
+ infos.put(field.getName(), (Double)val);
|
|
|
+ else if(val instanceof List)
|
|
|
+ infos.putArray(field.getName()).addAll(listToNode((List)val));
|
|
|
+ else if(val instanceof Map)
|
|
|
+ infos.putObject(field.getName()).setAll(mapToNode((Map)val));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ObjectNode getInfos(AdmObject obj) {
|
|
|
+ ObjectNode objectNode = obj.getInfos();
|
|
|
+ if(objectNode == null){
|
|
|
+ ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
|
|
|
+ objectNode = objectMapper.createObjectNode();
|
|
|
+ obj.setInfos(objectNode);
|
|
|
+ }
|
|
|
+ return objectNode;
|
|
|
+ }
|
|
|
+
|
|
|
+ private ObjectNode mapToNode(Map<String, Object> map){
|
|
|
+ ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
|
|
|
+ try {
|
|
|
+ String json = objectMapper.writeValueAsString(map);
|
|
|
+ return objectMapper.readValue(json, ObjectNode.class);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ArrayNode listToNode(List<Object> list){
|
|
|
+ ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
|
|
|
+ try {
|
|
|
+ String json = objectMapper.writeValueAsString(list);
|
|
|
+ return objectMapper.readValue(json, ArrayNode.class);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new BusinessException(ResponseCode.A0427.getCode(), ResponseCode.A0427.getDesc());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ interface SetDataAction {
|
|
|
+ void setData(AdmObject obj, OBase oldAdmEntity);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建/合并任务空间数据
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void handleJobSpace(String projectId){
|
|
|
+ QueryWrapper<AdmObject> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("project_id", projectId).eq("obj_type", AdmConst.OBJ_TYPE_SPACE).eq("valid", ValidEnum.TRUE.getType()).orderByAsc("floor_id");
|
|
|
+ List<AdmObject> spaceList = objectMapper.selectList(queryWrapper);
|
|
|
+
|
|
|
+ QueryWrapper<AdmJobSpace> wrapper = new QueryWrapper<>();
|
|
|
+ wrapper.eq("project_id", projectId).eq("valid", ValidEnum.TRUE.getType());
|
|
|
+ List<AdmJobSpace> jobSpaceList = jobSpaceMapper.selectList(wrapper);
|
|
|
+
|
|
|
+ //空间按层分组,优先使用OtherZone,缺省GeneralZone
|
|
|
+ LinkedHashMap<String, List<AdmObject>> map = new LinkedHashMap<>();
|
|
|
+ String floorId = null;
|
|
|
+ List<AdmObject> generalList = null;
|
|
|
+ List<AdmObject> otherList = null;
|
|
|
+ for(AdmObject sp : spaceList){
|
|
|
+ if(floorId == null || !floorId.equals(sp.getFloorId())) {
|
|
|
+ if(floorId != null)
|
|
|
+ map.put(floorId, otherList.size() > 0 ? otherList : generalList);
|
|
|
+
|
|
|
+ floorId = sp.getFloorId();
|
|
|
+ generalList = new ArrayList<>();
|
|
|
+ otherList = new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ String zone = sp.getClassCode();
|
|
|
+ if("GeneralZone".equals(zone))
|
|
|
+ generalList.add(sp);
|
|
|
+ else if("OtherZone".equals(zone))
|
|
|
+ otherList.add(sp);
|
|
|
+ }
|
|
|
+ map.put(floorId, otherList.size() > 0 ? otherList : generalList);
|
|
|
+
|
|
|
+ List<AdmJobSpace> toCreate = new ArrayList<>();
|
|
|
+ List<AdmJobSpace> toModify = new ArrayList<>();
|
|
|
+
|
|
|
+ String time = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
|
|
|
+
|
|
|
+ //按楼层进行空间匹配操作
|
|
|
+ for (Map.Entry<String, List<AdmObject>> entry : map.entrySet()) {
|
|
|
+ floorId = entry.getKey();
|
|
|
+
|
|
|
+ HashMap<String, AdmJobSpace> jobMap = new HashMap<>();
|
|
|
+ for (int i = 0; i < jobSpaceList.size(); i++) {
|
|
|
+ AdmJobSpace jobSpace = jobSpaceList.get(i);
|
|
|
+ if(jobSpace.getFloorId().equals(floorId)){
|
|
|
+ jobMap.put(jobSpace.getSpaceId(), jobSpace);
|
|
|
+
|
|
|
+ jobSpaceList.remove(i);
|
|
|
+ i--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<AdmObject> sps = entry.getValue();
|
|
|
+ for(AdmObject sp : sps){
|
|
|
+ ArrayNode spOutline = (ArrayNode) sp.getInfo("outline");
|
|
|
+ AdmJobSpace job = jobMap.remove(sp.getId());
|
|
|
+ if(job != null) {
|
|
|
+ //id匹配,轮廓变化的空间,重置任务状态
|
|
|
+ if(!outlineMatch(job.getOutline(), spOutline)){
|
|
|
+ job.setArchState(AdmConst.JOB_STATE_TODO);
|
|
|
+ job.setEquipState(AdmConst.JOB_STATE_TODO);
|
|
|
+ job.setModifiedTime(time);
|
|
|
+ job.setModifier(AdmConst.APP_ID);
|
|
|
+ toModify.add(job);
|
|
|
+ } // else id和轮廓都匹配,不做处理
|
|
|
+ } else {
|
|
|
+ //id未匹配,轮廓完全一致的任务空间,重新设置spaceId
|
|
|
+ job = matchByOutline(jobMap, sp);
|
|
|
+ if(job != null) {
|
|
|
+ job.setSpaceId(sp.getId());
|
|
|
+ toModify.add(job);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (job == null) {
|
|
|
+ job = new AdmJobSpace();
|
|
|
+ job.setId(IdUtil.fastUUID());
|
|
|
+ job.setSpaceId(sp.getId());
|
|
|
+ job.setOutline((ArrayNode) sp.getInfo("outline"));
|
|
|
+ job.setArchState(AdmConst.JOB_STATE_TODO);
|
|
|
+ job.setEquipState(AdmConst.JOB_STATE_TODO);
|
|
|
+ job.setProjectId(projectId);
|
|
|
+ job.setBuildingId(sp.getBuildingId());
|
|
|
+ job.setFloorId(sp.getFloorId());
|
|
|
+ job.setCreationTime(time);
|
|
|
+ job.setCreator(AdmConst.APP_ID);
|
|
|
+ job.setValid(ValidEnum.TRUE.getType());
|
|
|
+
|
|
|
+ toCreate.add(job);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //楼层中未找到匹配关系的任务空间
|
|
|
+ for(AdmJobSpace job : jobMap.values()){
|
|
|
+ job.setValid(ValidEnum.FALSE.getType());
|
|
|
+ job.setModifiedTime(time);
|
|
|
+ toModify.add(job);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //项目下未找到匹配关系的任务空间
|
|
|
+ for(AdmJobSpace job : jobSpaceList){
|
|
|
+ job.setValid(ValidEnum.FALSE.getType());
|
|
|
+ job.setModifiedTime(time);
|
|
|
+ toModify.add(job);
|
|
|
+ }
|
|
|
+
|
|
|
+ for(AdmJobSpace job : toCreate) {
|
|
|
+ jobSpaceMapper.insert(job);
|
|
|
+ }
|
|
|
+ for(AdmJobSpace job : toModify) {
|
|
|
+ jobSpaceMapper.updateById(job);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private AdmJobSpace matchByOutline(HashMap<String, AdmJobSpace> jobMap, AdmObject space){
|
|
|
+ ArrayNode o1 = (ArrayNode) space.getInfo("outline");
|
|
|
+ if(!isValidOutline(o1))
|
|
|
+ return null;
|
|
|
+
|
|
|
+ Polygon[] ps = getPolygon(o1);
|
|
|
+ Map.Entry<String, AdmJobSpace> target = null;
|
|
|
+ for(Map.Entry<String, AdmJobSpace> entry : jobMap.entrySet()){
|
|
|
+ ArrayNode o2 = entry.getValue().getOutline();
|
|
|
+ if(isValidOutline(o2) && polygonsMatch(ps, getPolygon(o2))){
|
|
|
+ target = entry;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(target != null){
|
|
|
+ jobMap.remove(target.getKey());
|
|
|
+ return target.getValue();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断空间轮廓是否变化
|
|
|
+ * TODO 区分覆盖等情况
|
|
|
+ */
|
|
|
+ private boolean outlineMatch(ArrayNode o1, ArrayNode o2){
|
|
|
+ return polygonsMatch(getPolygon(o1), getPolygon(o2));
|
|
|
+ }
|
|
|
+
|
|
|
+ private Polygon[] getPolygon(ArrayNode arrayNode){
|
|
|
+ Polygon[] ps = new Polygon[arrayNode.size()];
|
|
|
+ for (int i = 0; i < ps.length; i++) {
|
|
|
+ ArrayNode arr = (ArrayNode) arrayNode.get(i);
|
|
|
+ ArrayNode shellArrNode = (ArrayNode) arr.get(0);
|
|
|
+ LinearRing shell = geometryFactory.createLinearRing(buildCoords(shellArrNode));
|
|
|
+ LinearRing[] holes = null;
|
|
|
+ if(arr.size() > 1) {
|
|
|
+ holes = new LinearRing[arr.size() - 1];
|
|
|
+ for (int n = 1; n < arr.size(); n++) {
|
|
|
+ holes[n - 1] = geometryFactory.createLinearRing(buildCoords((ArrayNode) arr.get(n)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ps[i] = geometryFactory.createPolygon(shell, holes);
|
|
|
+ }
|
|
|
+ return ps;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Coordinate[] buildCoords(ArrayNode arrayNode){
|
|
|
+ Coordinate[] coords = new Coordinate[arrayNode.size()];
|
|
|
+ for (int i = 0; i < arrayNode.size(); i++) {
|
|
|
+ JsonNode pointNode = arrayNode.get(i);
|
|
|
+ coords[i] = new Coordinate(pointNode.get("x").asDouble(), pointNode.get("y").asDouble());
|
|
|
+ }
|
|
|
+ return coords;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 轮廓匹配判断
|
|
|
+ * TODO 暂不考虑顺序
|
|
|
+ */
|
|
|
+ private boolean polygonsMatch(Polygon[] ps1, Polygon[] ps2){
|
|
|
+ if (ps1.length == ps2.length) {
|
|
|
+ for (int i = 0; i < ps2.length; i++) {
|
|
|
+ if (!ps1[i].equalsExact(ps2[i]))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isValidOutline(ArrayNode outline) {
|
|
|
+ if(outline != null && outline.size() > 0 && outline.get(0).isArray()) {
|
|
|
+ ArrayNode o1 = (ArrayNode) outline.get(0);
|
|
|
+ if (o1.size() > 0 && o1.get(0).isArray()) {
|
|
|
+ ArrayNode o2 = (ArrayNode) o1.get(0);
|
|
|
+ return o2.size() >= 3;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|