SyncSpaceImpl.java 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. package com.persagy.bdtp.adm.service.impl;
  2. import cn.hutool.core.date.DatePattern;
  3. import cn.hutool.core.date.DateUtil;
  4. import cn.hutool.core.util.IdUtil;
  5. import cn.hutool.core.util.StrUtil;
  6. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  7. import com.fasterxml.jackson.databind.JsonNode;
  8. import com.fasterxml.jackson.databind.ObjectMapper;
  9. import com.fasterxml.jackson.databind.node.ArrayNode;
  10. import com.fasterxml.jackson.databind.node.ObjectNode;
  11. import com.fasterxml.jackson.databind.node.TextNode;
  12. import com.persagy.bdtp.adm.common.AdmConst;
  13. import com.persagy.bdtp.adm.dao.AdmJobSpaceMapper;
  14. import com.persagy.bdtp.adm.entity.Pagination;
  15. import com.persagy.bdtp.adm.entity.db.AdmJobSpace;
  16. import com.persagy.bdtp.adm.entity.db.AdmObject;
  17. import com.persagy.bdtp.adm.service.ISyncSpace;
  18. import com.persagy.bdtp.adm.service.ServiceUtil;
  19. import com.persagy.bdtp.adm.util.GeomUtil;
  20. import com.persagy.dmp.basic.model.QueryCriteria;
  21. import com.persagy.dmp.common.constant.ValidEnum;
  22. import com.persagy.dmp.digital.client.DigitalObjectClient;
  23. import org.locationtech.jts.geom.Polygon;
  24. import org.springframework.beans.factory.annotation.Autowired;
  25. import org.springframework.stereotype.Service;
  26. import org.springframework.transaction.annotation.Transactional;
  27. import java.io.IOException;
  28. import java.util.*;
  29. @Service
  30. public class SyncSpaceImpl implements ISyncSpace {
  31. @Autowired
  32. private ObjectMapper objectMapper;
  33. @Autowired
  34. private DigitalObjectClient objectClient;
  35. @Autowired
  36. private AdmJobSpaceMapper jobSpaceMapper;
  37. @Override
  38. @Transactional(rollbackFor = Exception.class)
  39. public Map<String, Object> sync(String groupCode, String projectId, String userId, String floorId, String zone) {
  40. if(StrUtil.isBlank(floorId))
  41. floorId = null;
  42. //查询bdtp的空间数据
  43. QueryCriteria criteria = ServiceUtil.getQueryCriteria(objectMapper, AdmConst.OBJ_TYPE_SPACE);
  44. criteria.getCriteria().put("classCode", zone); //默认工作空间为物业分区
  45. //按楼层查询
  46. if (floorId != null) {
  47. ObjectNode rt = criteria.getCriteria().putObject("relationTo");
  48. rt.put("graphCode", "ArchSubset");
  49. rt.put("relCode", "Fl2Sp");
  50. rt.put("objFrom", floorId);
  51. }
  52. List<ObjectNode> spList = ServiceUtil.queryAllPage(() -> objectClient.query(groupCode, projectId, AdmConst.APP_ID, userId, criteria), criteria, new Pagination(500));
  53. List<AdmJobSpace> toCreate = new ArrayList<>();
  54. List<AdmJobSpace> toModify = new ArrayList<>();
  55. if(floorId == null){
  56. HashMap<String, List<ObjectNode>> floorMap = new HashMap<>();
  57. for(ObjectNode sp : spList) {
  58. JsonNode fId = sp.get("floorId");
  59. if(fId != null) {
  60. String flId = fId.asText();
  61. List<ObjectNode> flSps = floorMap.get(flId);
  62. if(flSps == null)
  63. floorMap.put(flId, flSps = new ArrayList<>());
  64. flSps.add(sp);
  65. }
  66. }
  67. for (Map.Entry<String, List<ObjectNode>> entry : floorMap.entrySet()) {
  68. syncByFloor(projectId, entry.getKey(), entry.getValue(), toCreate, toModify);
  69. }
  70. } else {
  71. syncByFloor(projectId, floorId, spList, toCreate, toModify);
  72. }
  73. String time = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
  74. for(AdmJobSpace job : toCreate) {
  75. job.setCreationTime(time);
  76. job.setCreator(AdmConst.CREATOR_SYNC);
  77. jobSpaceMapper.insert(job);
  78. }
  79. for(AdmJobSpace job : toModify) {
  80. job.setModifiedTime(time);
  81. job.setModifier(AdmConst.CREATOR_SYNC);
  82. jobSpaceMapper.updateById(job);
  83. }
  84. HashMap<String, Object> rtn = new HashMap<>();
  85. rtn.put("syncSpaces", toCreate.size() + toModify.size());
  86. return rtn;
  87. }
  88. private void syncByFloor(String projectId, String floorId, List<ObjectNode> spList, List<AdmJobSpace> toCreate, List<AdmJobSpace> toModify){
  89. //查询任务空间数据
  90. QueryWrapper<AdmJobSpace> wrapper = new QueryWrapper<>();
  91. wrapper.eq("project_id", projectId).eq("floor_id", floorId).eq("valid", ValidEnum.TRUE.getType());
  92. List<AdmJobSpace> jobSpaceList = jobSpaceMapper.selectList(wrapper);
  93. HashMap<String, AdmJobSpace> jobMap = new HashMap<>(jobSpaceList.size());
  94. jobSpaceList.forEach(job -> jobMap.put(job.getBimId() != null ? job.getBimId() : job.getSpaceId(), job));
  95. //同步操作
  96. for(ObjectNode sp : spList){
  97. String spId = sp.get("id").asText();
  98. String bimId = sp.get("bimId") != null ? sp.get("bimId").asText() : null;
  99. ArrayNode spOutline = null;
  100. Object o1 = sp.get("outline");
  101. if(o1 instanceof TextNode) {
  102. try {
  103. spOutline = objectMapper.readValue(((TextNode) o1).asText().toLowerCase(), ArrayNode.class); //暂时toLowerCase()处理
  104. } catch (IOException e) {
  105. }
  106. }
  107. if(!GeomUtil.checkPolygon(spOutline))
  108. continue;
  109. AdmJobSpace job = jobMap.remove(bimId != null ? bimId : spId);
  110. if(job != null) { //id匹配
  111. boolean change = false;
  112. //轮廓变化的空间,重置任务状态
  113. if(!outlineMatch(job.getOutline(), spOutline)){
  114. job.setArchState(AdmConst.JOB_STATE_PROCESSING);
  115. job.setEquipState(AdmConst.JOB_STATE_PROCESSING);
  116. job.setOutline(spOutline);
  117. change = true;
  118. }
  119. //重置空间id
  120. if(!Objects.equals(spId, job.getSpaceId()) || !Objects.equals(bimId, job.getBimId())) {
  121. job.setBimId(bimId);
  122. job.setSpaceId(spId);
  123. change = true;
  124. }
  125. //轮廓和空间id都一致的,不需要做处理
  126. if(change)
  127. toModify.add(job);
  128. } else { //bimId未匹配
  129. job = matchByOutline(jobMap, sp);
  130. if(job != null) { //轮廓完全一致的任务空间,重新设置bimId和spaceId
  131. job.setBimId(bimId);
  132. job.setSpaceId(spId);
  133. toModify.add(job);
  134. }
  135. }
  136. if (job == null) {
  137. job = new AdmJobSpace();
  138. job.setId(IdUtil.fastSimpleUUID());
  139. job.setSpaceId(spId);
  140. job.setBimId(bimId);
  141. job.setOutline(spOutline);
  142. job.setArchState(AdmConst.JOB_STATE_PROCESSING);
  143. job.setEquipState(AdmConst.JOB_STATE_PROCESSING);
  144. job.setProjectId(projectId);
  145. job.setBuildingId(sp.get("buildingId").asText());
  146. job.setFloorId(floorId != null ? floorId : sp.get("floorId").asText());
  147. job.setValid(ValidEnum.TRUE.getType());
  148. toCreate.add(job);
  149. }
  150. }
  151. //未找到匹配关系的任务空间,删除
  152. for(AdmJobSpace job : jobMap.values()){
  153. job.setValid(ValidEnum.FALSE.getType());
  154. toModify.add(job);
  155. }
  156. }
  157. @Override
  158. public Map<String, Object> sync(String groupCode, String projectId, String userId, String zone) {
  159. return sync(groupCode, projectId, userId, null, zone);
  160. }
  161. private AdmJobSpace matchByOutline(HashMap<String, AdmJobSpace> jobMap, ObjectNode space){
  162. if(jobMap.size() == 0)
  163. return null;
  164. ArrayNode o1 = (ArrayNode) space.get("outline");
  165. if(!isValidOutline(o1))
  166. return null;
  167. Polygon[] ps = GeomUtil.getPolygon(o1);
  168. Map.Entry<String, AdmJobSpace> target = null;
  169. for(Map.Entry<String, AdmJobSpace> entry : jobMap.entrySet()){
  170. ArrayNode o2 = entry.getValue().getOutline();
  171. if(isValidOutline(o2) && polygonsMatch(ps, GeomUtil.getPolygon(o2))){
  172. target = entry;
  173. break;
  174. }
  175. }
  176. if(target != null){
  177. jobMap.remove(target.getKey());
  178. return target.getValue();
  179. }
  180. return null;
  181. }
  182. /**
  183. * 判断空间轮廓是否变化
  184. * TODO 区分覆盖等情况
  185. */
  186. private boolean outlineMatch(ArrayNode o1, ArrayNode o2){
  187. return polygonsMatch(GeomUtil.getPolygon(o1), GeomUtil.getPolygon(o2));
  188. }
  189. /**
  190. * 轮廓匹配判断
  191. * TODO 暂不考虑顺序
  192. */
  193. private boolean polygonsMatch(Polygon[] ps1, Polygon[] ps2){
  194. if (ps1.length == ps2.length) {
  195. for (int i = 0; i < ps2.length; i++) {
  196. if (!ps1[i].equalsExact(ps2[i]))
  197. return false;
  198. }
  199. return true;
  200. }
  201. return false;
  202. }
  203. private boolean isValidOutline(ArrayNode outline) {
  204. if(outline != null && outline.size() > 0 && outline.get(0).isArray()) {
  205. ArrayNode o1 = (ArrayNode) outline.get(0);
  206. if (o1.size() > 0 && o1.get(0).isArray()) {
  207. ArrayNode o2 = (ArrayNode) o1.get(0);
  208. return o2.size() >= 3;
  209. }
  210. }
  211. return false;
  212. }
  213. }