package com.persagy.proxy.adm.service.impl; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; 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.common.constant.ValidEnum; import com.persagy.dmp.common.helper.SpringHelper; import com.persagy.dmp.common.model.entity.BaseEntity; import com.persagy.dmp.common.utils.JsonHelper; import com.persagy.dmp.digital.client.DigitalObjectFacade; import com.persagy.dmp.digital.entity.ObjectRelation; import com.persagy.proxy.adm.annotations.CascadeColumn; import com.persagy.proxy.adm.request.AdmQueryCriteria; import com.persagy.proxy.adm.request.AdmResponse; import com.persagy.proxy.adm.service.IAdmBaseService; import com.persagy.proxy.adm.service.IAdmRelationService; import com.persagy.proxy.adm.utils.AdmEntityTransferUtil; import com.persagy.proxy.adm.utils.AdmQueryCriteriaHelper; import com.persagy.proxy.common.client.DmpRwdClient; import com.persagy.proxy.common.entity.DmpResult; import com.persagy.proxy.common.entity.InstanceUrlParam; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; /** * ADM 抽象实现类 * @author Charlie Yu * @date 2021-08-16 */ @Slf4j public class AbstractAdmBaseServiceImpl implements IAdmBaseService { @Autowired private DmpRwdClient rwdClient; @Autowired private ObjectMapper objectMapper; /** * 查询 * @param request * @return */ @Override public AdmResponse doQuery(InstanceUrlParam context, AdmQueryCriteria request, Class clazz) { // 转换为数据中台查询条件 QueryCriteria dmpRequest = AdmQueryCriteriaHelper.toDmpCriteria(request); // 提供一个钩子方法用于处理已封装好的中台查询参数(因传参有buildingId而处理) processDmpCriteria(dmpRequest); // 转换参数 JSONObject para = null; try { para = JsonHelper.toJsonObject(dmpRequest); } catch (IOException e) { log.error(e.getMessage(), e); return AdmResponse.failure("参数格式有误"); } log.info("param: {}", para.toString()); // 调用中台查询 DmpResult dmpResult = rwdClient.queryObject(context, para); List admVOs = AdmEntityTransferUtil.toAdmMultiEntity(dmpResult.getData(), request.getProjection(), clazz); //List admVOs = AdmEntityTransferUtil.toAdmMultiEntityExtra(dmpResult.getData(), request.getProjection(), clazz); // 级联查询 processCascade(context, admVOs, request.getName(), request.getCascade()); // 设置返回值 AdmResponse response = AdmResponse.success(admVOs); Long total = dmpResult.getCount() == null ? null : dmpResult.getCount().longValue(); if(request.isOnlyCount()){ response.setTotal(null); response.setCount(total); }else { response.setTotal(total); } response.setPageNumber(request.getPageNumber()); response.setPageSize(request.getPageSize()); return response; } /*** * Description: 提供一个钩子方法用于处理已封装好的中台查询参数(因传参有buildingId而处理) * @param dmpRequest : 中台查询参数 * @return : void * @author : lijie * @date :2021/10/28 20:23 * Update By lijie 2021/10/28 20:23 */ protected void processDmpCriteria(QueryCriteria dmpRequest) { // 空方法,需要时子类重写 } /** * 处理级联查询 * @param context * @param admVOs * @param name * @param cascades */ private void processCascade(InstanceUrlParam context, List admVOs, String name, List cascades) { if(CollUtil.isEmpty(admVOs) || CollUtil.isEmpty(cascades)) { return; } Map voMap = CollUtil.fieldValueMap(admVOs, BaseEntity.PROP_ID); Object simpleVO = admVOs.get(0); for(AdmQueryCriteria cascade:cascades) { if(StrUtil.isBlank(cascade.getName())){ //处理 级联查询参数name首字母大写cascade": [ {"Name": "property"}] continue; } // 获取关联对象的Class Field casField = ReflectUtil.getField(simpleVO.getClass(), cascade.getName()); if(casField == null) { continue; } // 获取级联信息 CascadeColumn annotationInfo = casField.getAnnotation(CascadeColumn.class); if(annotationInfo == null) { continue; } Class clazz = getFieldRealClass(casField); // 获取关联对象的类型 String objectType = getObjTypeByClass(clazz); if(StrUtil.isBlank(objectType)) { continue; } cascade.setName(objectType); // 转换为数据中台查询条件 QueryCriteria dmpRequest = AdmQueryCriteriaHelper.toDmpCriteria(cascade); // 拼接关系条件,得到关系映射 Map> idMap = ensureRelationCond(context, dmpRequest.getCriteria(), voMap.keySet(), annotationInfo); if(MapUtil.isEmpty(idMap)) { continue; } // 查询结果 List vos = queryByCondition(context, dmpRequest, cascade.getProjection(), clazz); if(CollUtil.isEmpty(vos)) { continue; } // 写回原对象中 writeToVOs(voMap, idMap, vos, casField); // 递归继续处理 processCascade(context, vos, objectType, cascade.getCascade()); } } /** * 拼接关系条件 * @param context * @param node * @param idList * @param annotationInfo * @return */ private Map> ensureRelationCond(InstanceUrlParam context, ObjectNode node, Set idList, CascadeColumn annotationInfo) { if(CollUtil.isEmpty(idList)) { return null; } // 查询关系 List relations = queryRelations(context, idList, annotationInfo); ArrayNode array = node.putObject(BaseEntity.PROP_ID).putArray("$in"); // 拼接查询条件 if(CollUtil.isEmpty(relations)) { array.add("0"); } else { List relList = CollUtil.getFieldValues(relations, annotationInfo.selectToObj()?"objTo":"objFrom", String.class); relList.forEach(id -> array.add(id)); } if(annotationInfo.selectToObj()){ return groupMapList(relations, "objFrom", "objTo"); }else{ return groupMapList(relations, "objTo", "objFrom"); } } /** * 将集合转换为Map * @param list 集合 * @param keyField key属性名 * @param valueField value属性名 * @return */ private static Map> groupMapList(List list, String keyField, String valueField) { if(CollUtil.isEmpty(list)) { return null; } Map> groupMap = new HashMap<>(); for(Object vo:list) { String key = (String) ReflectUtil.getFieldValue(vo, keyField); String value = (String) ReflectUtil.getFieldValue(vo, valueField); if(!StrUtil.isAllNotBlank(key, value)) { continue; } List valueList = groupMap.get(key); if(CollUtil.isEmpty(valueList)) { valueList = new ArrayList<>(); groupMap.put(key, valueList); } valueList.add(value); } return groupMap; } /** * 查询关系 * @param context * @param idList * @param anno * @return */ private List queryRelations(InstanceUrlParam context, SetidList, CascadeColumn anno) { // 如果没有任何配置,不处理 if(StrUtil.isBlank(anno.graphCode()) && StrUtil.isBlank(anno.relCode()) && StrUtil.isBlank(anno.relValue())) { return null; } // 查询关系 QueryCriteria queryRequest = new QueryCriteria(); ObjectNode criteria = JsonNodeFactory.instance.objectNode(); queryRequest.setCriteria(criteria); boolean isSelectTo = anno.selectToObj(); criteria.put(BaseEntity.PROP_VALID, ValidEnum.TRUE.getType()); putString(criteria, "graphCode", anno.graphCode()); putString(criteria, "relCode", anno.relCode()); putString(criteria, "relValue", anno.relValue()); ArrayNode array = criteria.putObject(isSelectTo?"objFrom":"objTo").putArray("$in"); idList.forEach(id -> array.add(id)); return SpringHelper.getBean(IAdmRelationService.class).queryByCondition(context, queryRequest); } /** * 添加字符串条件 * @param node * @param key * @param value */ private void putString(ObjectNode node, String key, String value) { if(StrUtil.isBlank(value)) { return; } node.put(key, value); } /** * 将子集写回到对象中 * @param voMap 原始对象Map * @param idMap 主键映射> * @param vos 子对象 * @param casField 子对象对应属性 */ private void writeToVOs(Map voMap, Map> idMap, List vos, Field casField) { if(CollUtil.isEmpty(vos) || MapUtil.isEmpty(idMap)) { return; } // 转换为Map Map subVOMap = CollUtil.fieldValueMap(vos, BaseEntity.PROP_ID); // 是否为集合 boolean isList = List.class.isAssignableFrom(casField.getType()); // 按对象循环 for(String id:voMap.keySet()) { Object mainVO = voMap.get(id); List subIdList = idMap.get(id); if(CollUtil.isEmpty(subIdList)) { continue; } // 如果是集合 if(isList) { // 取出对应的对象集合 Map currVOMap = MapUtil.filter(subVOMap, subIdList.toArray(new String[0])); List voList = CollUtil.newArrayList(currVOMap.values()); ReflectUtil.setFieldValue(mainVO, casField, voList); } else { // 非集合取第一个即可 String subId = subIdList.get(0); V vo = subVOMap.get(subId); ReflectUtil.setFieldValue(mainVO, casField, vo); } } } /** * 调用Client查询 * @param context * @param criteria * @param projection * @param clazz * @return */ private List queryByCondition(InstanceUrlParam context, QueryCriteria criteria, List projection, Class clazz) { // 转换参数 if(criteria == null) { return null; } List objects = DigitalObjectFacade.query(context.getGroupCode(), context.getProjectId(), context.getAppId(), null, criteria); return AdmEntityTransferUtil.toAdmMultiEntity(objects, projection, clazz); } /** * 获取实际的Class * @param casField * @return */ private Class getFieldRealClass(Field casField) { // 取到Field Class clazz = casField.getType(); // 如果是集合,则取实际的对象 if(List.class.isAssignableFrom(clazz)) { clazz = (Class) ((ParameterizedType) casField.getGenericType()).getActualTypeArguments()[0]; } return clazz; } /** * 通过Class获取其对象类型 * @param clazz * @return */ private String getObjTypeByClass(Class clazz) { // 获取关联对象的类型 String objectType = null; try { objectType = (String) ReflectUtil.getFieldValue(clazz.newInstance(), "objectType"); } catch (Exception e) { log.error(e.getMessage(), e); } return objectType; } /** * 新增 * @param context * @param clazz * @param voList * @return */ @Override public List doInsert(InstanceUrlParam context, Class clazz, List voList) { if(CollUtil.isEmpty(voList)) { return null; } ArrayNode vos = AdmEntityTransferUtil.toDmpMultiEntity(voList); // 调用中台新增 DmpResult response = rwdClient.createObject(context, JSONArray.parseArray(vos.toString())); if(!DmpResult.SUCCESS.equals(response.getResult())) { throw new RuntimeException("调用中台查询接口出错:" + response.getMessage()); } // 转换为结果 return AdmEntityTransferUtil.toAdmMultiEntity(response.getData(), null, clazz); } /** * 修改 * @param context * @param clazz * @param voList * @return */ @Override public List doUpdate(InstanceUrlParam context, Class clazz, List voList) { if(CollUtil.isEmpty(voList)) { return null; } ArrayNode vos = AdmEntityTransferUtil.toDmpMultiEntity(voList); // 调用中台修改 DmpResult response = rwdClient.updateObject(context, JSONArray.parseArray(vos.toString())); if(!DmpResult.SUCCESS.equals(response.getResult())) { throw new RuntimeException("调用中台查询接口出错:" + response.getMessage()); } // 转换为结果 return AdmEntityTransferUtil.toAdmMultiEntity(response.getData(), null, clazz); } /** * 删除 * @param context * @param voList * @return */ @Override public void doDelete(InstanceUrlParam context, List voList) { if(CollUtil.isEmpty(voList)) { return; } List idList = CollUtil.getFieldValues(voList, "id", String.class); // 调用中台修改 DmpResult response = rwdClient.deleteObject(context, idList); if(!DmpResult.SUCCESS.equals(response.getResult())) { throw new RuntimeException("调用中台查询接口出错:" + response.getMessage()); } } /** * 根据物理世界查询条件查询对象信息 * @param context * @param dmpRequest * @param clazz * @return */ @Override public AdmResponse doQuery(InstanceUrlParam context, QueryCriteria dmpRequest, Class clazz) { // 转换参数 JSONObject para = null; try { para = JsonHelper.toJsonObject(dmpRequest); } catch (IOException e) { log.error(e.getMessage(), e); return null; } // 调用中台查询 DmpResult dmpResult = rwdClient.queryObject(context, para); List admVOs = AdmEntityTransferUtil.toAdmMultiEntity(dmpResult.getData(), null, clazz); // JSONArray data = dmpResult.getData(); // List admVOs = new ArrayList<>(); // if(CollUtil.isNotEmpty(data)){ // admVOs = data.toJavaList(clazz); // } // 设置返回值 AdmResponse response = AdmResponse.success(admVOs); Long total = dmpResult.getCount() == null ? null : dmpResult.getCount().longValue(); response.setTotal(total); return response; } /** * 查询标记计算关系 * @param context * @param dmpRequest * @param clazz * @return */ @Override public AdmResponse doQueryRelationProjectCal(InstanceUrlParam context, QueryCriteria dmpRequest, Class clazz) { // 转换参数 JSONObject para = null; try { para = JsonHelper.toJsonObject(dmpRequest); } catch (IOException e) { log.error(e.getMessage(), e); return null; } // 调用中台查询 DmpResult dmpResult = rwdClient.queryRelationProjectCal(context, para); List admVOs = AdmEntityTransferUtil.toAdmMultiEntity(dmpResult.getData(), null, clazz); // 设置返回值 AdmResponse response = AdmResponse.success(admVOs); Long total = dmpResult.getCount() == null ? null : dmpResult.getCount().longValue(); response.setTotal(total); return response; } /** * 修改 * @param context * @param clazz * @param voList * @return */ @Override public List doUpdateRelationProjectCal(InstanceUrlParam context, Class clazz, List voList) { if(CollUtil.isEmpty(voList)) { return null; } ArrayNode vos = AdmEntityTransferUtil.toDmpMultiEntity(voList); // 调用中台修改 DmpResult response = rwdClient.updateRelationProjectCal(context, JSONArray.parseArray(vos.toString())); if(!DmpResult.SUCCESS.equals(response.getResult())) { throw new RuntimeException("调用中台查询接口出错:" + response.getMessage()); } // 转换为结果 return AdmEntityTransferUtil.toAdmMultiEntity(response.getData(), null, clazz); } }