package com.persagy.proxy.adm.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.persagy.dmp.basic.model.QueryCriteria; import com.persagy.dmp.define.entity.ObjectTypeDefine; import com.persagy.dmp.digital.entity.ObjectRelation; import com.persagy.proxy.adm.model.*; import com.persagy.proxy.adm.request.AdmQueryCriteria; import com.persagy.proxy.adm.request.AdmResponse; import com.persagy.proxy.adm.service.IAdmEquipmentService; import com.persagy.proxy.adm.service.IAdmRelationService; import com.persagy.proxy.adm.service.IAdmSpaceService; import com.persagy.proxy.adm.service.IAdmSystemService; import com.persagy.proxy.adm.utils.AdmContextUtil; import com.persagy.proxy.common.client.DmpRwdClient; import com.persagy.proxy.common.entity.DmpResult; import com.persagy.proxy.common.entity.InstanceUrlParam; import com.persagy.proxy.common.entity.RelationDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; /** * ADM 空间 实现类 * @author lvxy * @date 2021/8/18 */ @Slf4j @Service public class AdmSpaceServiceImpl extends AbstractAdmBaseServiceImpl implements IAdmSpaceService { @Autowired private DmpRwdClient rwdClient; @Autowired private ObjectMapper objectMapper; @Autowired private IAdmRelationService relationService; @Autowired private IAdmEquipmentService equipmentService; @Autowired private IAdmSystemService systemService; @Override public AdmResponse doQuery(InstanceUrlParam context, AdmQueryCriteria request, Class clazz) { AdmResponse response = super.doQuery(context, request, clazz); // 系统需要补充分类名称属性 ensureSpecialValues(context, (List) response.getContent()); return response; } @Override public List doInsertExt(InstanceUrlParam context, Class clazz, List voList) { Map spaceMapByFlId = CollUtil.fieldValueMap(voList, "floorId"); //查询空间中floorId 对应的floor DmpResult floors = queryFloorsByFloorIds(context, spaceMapByFlId.keySet()); if(CollUtil.isNotEmpty(floors.getData())){ ArrayList floorList = CollUtil.newArrayList(JSONUtil.toList(floors.getData().toString(),AdmFloor.class)); //space.height = floor.infos.height voList = processHeight(spaceMapByFlId, floorList); } //插入空间 List vosR = doInsert(context, clazz, voList); //添加绑定关系 processRelations(vosR); //处理关系标记 //TODO 处理关系标记 //processRelationType(); return vosR; } @Override public AdmResponse doQueryType(InstanceUrlParam context, AdmDCSQueryRequest request) { //查询定义类型 ObjectNode criteriaEq = JsonNodeFactory.instance.objectNode(); criteriaEq.put("parentCode", "space"); DmpResult resultDef = queryDefineType(context, criteriaEq); List defineList = null; if(resultDef.getResult().equals(DmpResult.SUCCESS)){ defineList = JSONUtil.toList(resultDef.getData().toString(), JSONObject.class); //获取实际空间对象的数量 //根据classCode floorId 查询查询实际存在的空间 assembleDefineTypes(context, defineList, request.getFloorId()); // 设置返回值 AdmResponse response = AdmResponse.success(defineList); Long total = resultDef.getCount() == null ? null : resultDef.getCount().longValue(); response.setTotal(total); return response; }else{ return null; } } @Override public AdmResponse doQuerySpaces(InstanceUrlParam context, AdmDCSQueryRequest request) { AdmQueryCriteria admQueryCriteria = new AdmQueryCriteria(); admQueryCriteria.setCascade(request.getCascade()); admQueryCriteria.setName(AdmSpace.OBJ_TYPE); String classCodeFilter = ""; if(StrUtil.isNotEmpty(request.getZoneType())){ classCodeFilter = "classCode = '"+request.getZoneType()+"'"; }else{ StringBuffer zoneTypefilters = new StringBuffer(" classCode "); zoneTypefilters.append("in ['"); request.getZoneTypeList().stream().forEach(code ->{ zoneTypefilters.append(code).append("',"); }); classCodeFilter = StrUtil.sub(zoneTypefilters.toString(),0,-1)+"']"; } String filters = request.getFilters(); if(StrUtil.isBlank(filters)){ admQueryCriteria.setFilters(classCodeFilter); }else{ admQueryCriteria.setFilters(filters+";"+classCodeFilter); } if(StrUtil.isNotEmpty(request.getBuildingId()) && StrUtil.isNotEmpty(request.getFloorId()) && !request.getFloorId().equals("isnull")){ //明确建筑,明确楼层 ObjectNode relationTo = JsonNodeFactory.instance.objectNode(); relationTo.put("relCode", "Fl2Sp"); relationTo.put("graphCode", "MechInArch"); relationTo.put("objFrom", request.getFloorId()); admQueryCriteria.setRelationFrom(relationTo); }else if(StrUtil.isNotEmpty(request.getBuildingId()) && StrUtil.isNotEmpty(request.getFloorId()) && request.getFloorId().equals("isnull")){ //明确建筑,不明确楼层 //查询建筑下的楼层 QueryCriteria queryCriteriaRelation = new QueryCriteria(); ObjectNode criteria = JsonNodeFactory.instance.objectNode(); criteria.put("relCode", "Bd2Fl"); criteria.put("graphCode", "ArchSubset"); criteria.put("objFrom", request.getBuildingId()); queryCriteriaRelation.setCriteria(criteria); List relations = relationService.queryByCondition(AdmContextUtil.toDmpContext(), queryCriteriaRelation); if(CollUtil.isNotEmpty(relations)){ Map objectRelationMap = CollUtil.fieldValueMap(relations, "objTo"); //查询 建筑 不在楼层下 的空间 ObjectNode relationTo = JsonNodeFactory.instance.objectNode(); relationTo.put("relCode", "Fl2Sp"); relationTo.put("graphCode", "MechInArch"); ArrayNode arrayNode = relationTo.putObject("objFrom").putArray("$in"); objectRelationMap.keySet().stream().forEach(floorId -> arrayNode.add(floorId)); relationTo.put("$bindFlag", false); admQueryCriteria.setRelationFrom(relationTo); admQueryCriteria.setFilters(admQueryCriteria.getFilters() + "; buildingId = '"+request.getBuildingId()+"'"); }else{ //查询建筑下的空间 ObjectNode relationTo = JsonNodeFactory.instance.objectNode(); relationTo.put("relCode", "Bd2Sp"); relationTo.put("graphCode", "MechInArch"); relationTo.put("objFrom", request.getBuildingId()); admQueryCriteria.setRelationFrom(relationTo); } }else if(StrUtil.isNotEmpty(request.getBuildingId()) && StrUtil.isEmpty(request.getFloorId()) && !request.getBuildingId().equals("isnull")){ //查询建筑下的空间 ObjectNode relationTo = JsonNodeFactory.instance.objectNode(); relationTo.put("relCode", "Bd2Sp"); relationTo.put("graphCode", "MechInArch"); relationTo.put("objFrom", request.getBuildingId()); admQueryCriteria.setRelationFrom(relationTo); }else if(StrUtil.isNotEmpty(request.getBuildingId()) && StrUtil.isEmpty(request.getFloorId()) && request.getBuildingId().equals("isnull")){ //未明确建筑下的空间 //查询建筑下的空间 ObjectNode relationTo = JsonNodeFactory.instance.objectNode(); relationTo.put("relCode", "Bd2Sp"); relationTo.put("graphCode", "MechInArch"); relationTo.put("$bindFlag", false); admQueryCriteria.setRelationFrom(relationTo); }else if(StrUtil.isEmpty(request.getBuildingId()) && StrUtil.isEmpty(request.getFloorId())){ } AdmResponse response = doQuery(AdmContextUtil.toDmpContext(), admQueryCriteria, AdmSpace.class); //空间需要补充分类名称属性 ensureSpecialValues(context, (List) response.getContent()); return response; } @Override public void ensureSpecialValues(InstanceUrlParam context, List vos) { if(CollUtil.isEmpty(vos)) { return; } // 1. 收集空间的设备对象,扩展设备对象赋值 List equipmentList = new ArrayList<>(); for(AdmSpace vo:vos) { // 收集设备对象 if(CollUtil.isEmpty(vo.getEquipment()) && CollUtil.isEmpty(vo.getEquipmentFor())) { continue; } if(CollUtil.isNotEmpty(vo.getEquipment())) { equipmentList.addAll(vo.getEquipment()); } if(CollUtil.isEmpty(vo.getEquipmentFor())) { equipmentList.addAll(vo.getEquipmentFor()); } } // 对象扩展属性赋值 equipmentService.ensureSpecialValues(context, equipmentList); //2.收集空间的系统 扩展系统、及系统下设备对象赋值 List admSystemList = new ArrayList<>(); for(AdmSpace vo:vos) { // 收集设备对象 if(CollUtil.isEmpty(vo.getGeneralSystem())) { continue; } admSystemList.addAll(vo.getGeneralSystem()); } // 对象扩展属性赋值 systemService.ensureSpecialValues(context, admSystemList); } @Override public List querySpaceInShaft(InstanceUrlParam context, String shaftId, String spaceType) { AdmQueryCriteria request = new AdmQueryCriteria(); request.setName(AdmSpace.OBJ_TYPE); request.resetRelationCond(false, "ArchSubset", "Sh2Sp", spaceType, shaftId, true); AdmResponse rs = doQuery(context, request, AdmSpace.class); return (List) rs.getContent(); } @Override public List querySpaceInBuilding(InstanceUrlParam context, String buildingId, String spaceType) { AdmQueryCriteria request = new AdmQueryCriteria(); request.setName(AdmSpace.OBJ_TYPE); request.resetRelationCond(false, "ArchSubset", "Bd2Sp", spaceType, buildingId, true); AdmResponse rs = doQuery(context, request, AdmSpace.class); return (List) rs.getContent(); } @Override public Map> querySpaceMapInFloors(InstanceUrlParam context, List floorIds, String spaceType) { QueryCriteria queryRequest = new QueryCriteria(); ObjectNode criteriaRel = JsonNodeFactory.instance.objectNode(); criteriaRel.put("graphCode", "ArchSubset"); criteriaRel.put("relCode", "Fl2Sp"); criteriaRel.put("relValue", spaceType); ArrayNode objNode = criteriaRel.putArray("objFrom"); floorIds.forEach(floorId -> objNode.add(floorId)); queryRequest.setCriteria(criteriaRel); List relations = relationService.queryByCondition(context, queryRequest); if(CollUtil.isEmpty(relations)) { return null; } return relations.stream().collect(Collectors.groupingBy(ObjectRelation::getObjFrom, Collectors.mapping(ObjectRelation::getObjTo, Collectors.toList()))); } @Override public Map> queryTrafficSpaceMap(InstanceUrlParam context, Iterable spaceIds, String spaceType) { Map> result = new HashMap<>(); loadTrafficSpace(context, spaceIds, spaceType, true, result); loadTrafficSpace(context, spaceIds, spaceType, false, result); return result; } /** * 装载交通关系 * @param context * @param spaceIds * @param spaceType * @param isFrom * @param result */ private void loadTrafficSpace(InstanceUrlParam context, Iterable spaceIds, String spaceType, boolean isFrom, Map> result) { // 关系查询条件 QueryCriteria queryRequest = new QueryCriteria(); ObjectNode criteriaRel = JsonNodeFactory.instance.objectNode(); criteriaRel.put("graphCode", "TrafficNetwork"); criteriaRel.put("relValue", spaceType); ArrayNode objNode = criteriaRel.putArray(isFrom?"objFrom":"objTo"); spaceIds.forEach(spaceId -> objNode.add(spaceId)); queryRequest.setCriteria(criteriaRel); List relations = relationService.queryByCondition(context, queryRequest); if(CollUtil.isEmpty(relations)) { return; } // 存入Map for(ObjectRelation relation:relations) { String key = isFrom ? relation.getObjFrom() : relation.getObjTo(); String value = isFrom ? relation.getObjTo() : relation.getObjFrom(); Set valueList = result.get(key); if(CollUtil.isEmpty(valueList)) { valueList = new HashSet<>(); result.put(key, valueList); } valueList.add(value); } } /** * 空间的类型是根据项目自定义的 * 参见中心 * @Select("SELECT s.object_type as type,d.name FROM zone_space_base s * LEFT JOIN dict.dict_space_project d ON s.object_type = d.id WHERE s.project_id = #{projectId} AND d.project_id = #{projectId} * GROUP BY object_type, d.name") * @param context * @return */ @Override public List doQuerySpaceTypes(InstanceUrlParam context) { //根据项目id查询空间类型 Map codeNameMap = queryProjectDefineType(context); if(CollUtil.isNotEmpty(codeNameMap)){ //查询object JSONArray demObjs = queryAndDealObjs(context, codeNameMap.keySet()); if(CollUtil.isNotEmpty(demObjs)){ List spaceList = JSONArray.parseArray(JSONUtil.toJsonStr(demObjs), AdmSpace.class); Set classCodes = spaceList.stream().map(space -> space.getClassCode()).collect(Collectors.toSet()); if(CollUtil.isNotEmpty(classCodes)){ codeNameMap.keySet().removeIf(code -> !classCodes.contains(code)); } } } if(CollUtil.isNotEmpty(codeNameMap)){ List list = new ArrayList<>(codeNameMap.size()); codeNameMap.keySet().stream().forEach(code ->{ JSONObject jsonObject = new JSONObject(); jsonObject.put("name",codeNameMap.get(code)); jsonObject.put("code",code); list.add(jsonObject); }); return list; }else{ return null; } } private DmpResult queryObj(InstanceUrlParam context, QueryCriteria criteriaObject){ JSONObject paraPe = null; try { String paraStr = objectMapper.writeValueAsString(criteriaObject); paraPe = JSONObject.parseObject(paraStr); } catch (JsonProcessingException e) { throw new RuntimeException("转换查询条件出错:" + e.getMessage()); } return rwdClient.queryObject(context, paraPe); } private QueryCriteria ensureQueryCommParm(QueryCriteria dmpRequest, InstanceUrlParam context, Collection classCodes, String objType){ ObjectNode criteriaEq = null; if(JSONUtil.isNull(dmpRequest.getCriteria())){ criteriaEq = JsonNodeFactory.instance.objectNode(); }else{ criteriaEq = dmpRequest.getCriteria(); } if(CollUtil.isNotEmpty(classCodes)){ ArrayNode array = criteriaEq.putObject("classCode").putArray("$in"); classCodes.forEach(code -> array.add(code)); } criteriaEq.put("objType", objType); dmpRequest.setCriteria(criteriaEq); return dmpRequest; } private JSONArray queryAndDealObjs(InstanceUrlParam context, Set codes){ QueryCriteria criteriaObject = ensureQueryCommParm(new QueryCriteria(), context, codes,AdmSpace.OBJ_TYPE); criteriaObject.setSize(50L); DmpResult dmpResult = queryObj(context, criteriaObject); if(CollUtil.isEmpty(dmpResult.getData())){ return null; } JSONArray demObjs = dmpResult.getData(); if(dmpResult.getCount() > criteriaObject.getSize()){ for(int page = 2; page < dmpResult.getCount()/criteriaObject.getSize()+1; page++){ criteriaObject.setPage(page*1L); demObjs.addAll(queryObj(context, criteriaObject).getData()); } } return demObjs; } private Map queryProjectDefineType(InstanceUrlParam context){ Map codeNameMap = null; ObjectNode criteriaEq = JsonNodeFactory.instance.objectNode(); criteriaEq.put("projectId", context.getProjectId()); criteriaEq.put("objType", AdmSpace.OBJ_TYPE); DmpResult resultDef = queryDefineType(context, criteriaEq); if(resultDef.getResult().equals(DmpResult.SUCCESS) && CollUtil.isNotEmpty(resultDef.getData())){ List defineList = JSONUtil.toList(resultDef.getData().toString(), ObjectTypeDefine.class); codeNameMap = defineList.stream().collect(Collectors.toMap(ObjectTypeDefine::getCode, ObjectTypeDefine::getName, (k1,k2)->k1)); } return codeNameMap; } /** * 查询空间flooId对应的infos中height存在的 flool * @param context * @param floolIds * @return */ private DmpResult queryFloorsByFloorIds(InstanceUrlParam context, Collection floolIds){ QueryCriteria queryCriteria = ensureQueryCommParm(new QueryCriteria(),context, CollUtil.newArrayList("floor"),"floor"); ObjectNode criteriaPe = queryCriteria.getCriteria(); if(CollUtil.isNotEmpty(floolIds)){ ArrayNode array = criteriaPe.putObject("id").putArray("$in"); floolIds.forEach(floorId -> array.add(floorId)); } JSONObject height = new JSONObject(); height.put("$gt", 0f); criteriaPe.putPOJO("height", height); queryCriteria.setCriteria(criteriaPe); queryCriteria.setWithoutCount(true); return queryObj(context, queryCriteria); } /** * space.height = floor.infos.height * @param spaceMapByFlId * @param floorList * @return */ private List processHeight(Map spaceMapByFlId, List floorList){ floorList.forEach(admFloor -> { if(CollUtil.isNotEmpty(admFloor.getInfos())){ Float height = (Float) admFloor.getInfos().get("height"); AdmSpace admSpace = spaceMapByFlId.get(admFloor.getId()); admSpace.setHeight(height); } }); return (List) spaceMapByFlId.values(); } /** * 添加绑定关系 */ private void processRelations(List vosR){ if(CollUtil.isNotEmpty(vosR)) { List relationDTOS = new ArrayList<>(vosR.size()); vosR.forEach(admSpace -> { if (StrUtil.isNotEmpty(admSpace.getBuildingId())) { relationDTOS.add(new RelationDTO(null, "ArchSubset", "Bd2Sp", null, admSpace.getBuildingId(), admSpace.getId())); } if (StrUtil.isNotEmpty(admSpace.getFloorId())) { relationDTOS.add(new RelationDTO(null, "ArchSubset", "Fl2Sp", null, admSpace.getFloorId(), admSpace.getId())); } }); if (CollUtil.isNotEmpty(relationDTOS)) { relationService.doSave(AdmContextUtil.toDmpContext(), relationDTOS); } } } /** * 转换为目标实体,并增加属性 */ private void assembleDefineTypes(InstanceUrlParam context, List defineList, String floorId){ boolean needCount = true; defineList.stream().forEach(defineType -> { //查询空间数量 int count = needCount ? countSpace(context, defineType.getString("code"), floorId) : 0; //处理单个对象 assembleDefineObj(defineType, count, context.getProjectId()); }); } /** * 单个转换为目标实体,并增加属性 */ private void assembleDefineObj(JSONObject defineType, int count, String projectId){ defineType.put("count", count); defineType.put("projectId", projectId); defineType.remove("aliasName"); defineType.remove("aliasCode"); defineType.remove("valid"); defineType.remove("objType"); defineType.remove("groupCode"); defineType.remove("parentCode"); defineType.remove("id"); } private void addRelationTo(QueryCriteria rwdQueryCriteria, String objFrom, String relCode){ ObjectNode relationTO = JsonNodeFactory.instance.objectNode(); relationTO.put("relCode", relCode); relationTO.put("graphCode", "ArchSubset"); relationTO.put("objFrom", objFrom); ObjectNode criteria = rwdQueryCriteria.getCriteria(); criteria.putPOJO("relationTo", relationTO); rwdQueryCriteria.setCriteria(criteria); } private void addRelationFrom(QueryCriteria rwdQueryCriteria, String objTo, String relCode){ ObjectNode relationFrom = JsonNodeFactory.instance.objectNode(); if(StrUtil.isNotEmpty(objTo)){ relationFrom.put("objTo", objTo); } ObjectNode criteria = rwdQueryCriteria.getCriteria(); criteria.putPOJO("relationFrom", relationFrom); rwdQueryCriteria.setCriteria(criteria); } /** * 查询存在空间的数量 * @param context * @param classCode * @param objFrom * @return */ private int countSpace(InstanceUrlParam context, String classCode, String objFrom){ QueryCriteria queryCriteria = ensureQueryCommParm(new QueryCriteria(), context, CollUtil.newArrayList(classCode),"space"); addRelationTo(queryCriteria, objFrom,"Fl2Sp"); queryCriteria.setOnlyCount(true); DmpResult dmpResult = queryObj(context, queryCriteria); return dmpResult.getCount(); } private DmpResult queryDefineType(InstanceUrlParam context, ObjectNode criteriaEq){ QueryCriteria criteriaObject = new QueryCriteria(); criteriaObject.setCriteria(criteriaEq); JSONObject paraPe = null; try { String paraStr = objectMapper.writeValueAsString(criteriaObject); paraPe = JSONObject.parseObject(paraStr); } catch (JsonProcessingException e) { throw new RuntimeException("查询公共定义的空间类型,转换查询条件出错:" + e.getMessage()); } return rwdClient.queryDefClass(context, paraPe); } }