123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- package com.persagy.proxy.adm.service.impl;
- 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 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.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 lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import java.io.IOException;
- import java.lang.reflect.Field;
- import java.lang.reflect.ParameterizedType;
- import java.util.*;
- /**
- * ADM 抽象实现类
- * @author Charlie Yu
- * @date 2021-08-16
- */
- @Slf4j
- public class AbstractAdmBaseServiceImpl<T> implements IAdmBaseService<T> {
- @Autowired
- private DmpRwdClient rwdClient;
- @Autowired
- private ObjectMapper objectMapper;
- /**
- * 查询
- * @param request
- * @return
- */
- @Override
- public AdmResponse doQuery(InstanceUrlParam context, AdmQueryCriteria request, Class<T> clazz) {
- // 转换为数据中台查询条件
- QueryCriteria dmpRequest = AdmQueryCriteriaHelper.toDmpCriteria(request);
- // 转换参数
- JSONObject para = null;
- try {
- para = JsonHelper.toJsonObject(dmpRequest);
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- return null;
- }
- // 调用中台查询
- DmpResult<JSONArray> dmpResult = rwdClient.queryObject(context, para);
- List<T> admVOs = AdmEntityTransferUtil.toAdmMultiEntity(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;
- }
- /**
- * 处理级联查询
- * @param context
- * @param admVOs
- * @param name
- * @param cascades
- */
- private void processCascade(InstanceUrlParam context, List admVOs, String name, List<AdmQueryCriteria> cascades) {
- if(CollUtil.isEmpty(admVOs) || CollUtil.isEmpty(cascades)) {
- return;
- }
- Map<String, Object> 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());
- 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<String, List<String>> 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<String, List<String>> ensureRelationCond(InstanceUrlParam context, ObjectNode node, Set<String> idList, CascadeColumn annotationInfo) {
- if(CollUtil.isEmpty(idList)) {
- return null;
- }
- // 查询关系
- List<ObjectRelation> relations = queryRelations(context, idList, annotationInfo);
- ArrayNode array = node.putObject(BaseEntity.PROP_ID).putArray("$in");
- // 拼接查询条件
- if(CollUtil.isEmpty(relations)) {
- array.add("0");
- } else {
- List<String> 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<String, List<String>> groupMapList(List<?> list, String keyField, String valueField) {
- if(CollUtil.isEmpty(list)) {
- return null;
- }
- Map<String, List<String>> 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<String> 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<ObjectRelation> queryRelations(InstanceUrlParam context, Set<String>idList, 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();
- 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 主键映射<mainId, List<subId>>
- * @param vos 子对象
- * @param casField 子对象对应属性
- */
- private <V> void writeToVOs(Map<String, Object> voMap, Map<String, List<String>> idMap, List<V> vos, Field casField) {
- if(CollUtil.isEmpty(vos) || MapUtil.isEmpty(idMap)) {
- return;
- }
- // 转换为Map
- Map<String, V> 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<String> subIdList = idMap.get(id);
- if(CollUtil.isEmpty(subIdList)) {
- continue;
- }
- // 如果是集合
- if(isList) {
- // 取出对应的对象集合
- Map<String, V> currVOMap = MapUtil.filter(subVOMap, subIdList.toArray(new String[0]));
- List<V> 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 <V> List<V> queryByCondition(InstanceUrlParam context, QueryCriteria criteria, List<String> projection, Class<V> clazz) {
- // 转换参数
- if(criteria == null) {
- return null;
- }
- List<ObjectNode> 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<T> doInsert(InstanceUrlParam context, Class<T> clazz, List<T> voList) {
- if(CollUtil.isEmpty(voList)) {
- return null;
- }
- ArrayNode vos = AdmEntityTransferUtil.toDmpMultiEntity(voList);
- // 调用中台新增
- DmpResult<JSONArray> 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<T> doUpdate(InstanceUrlParam context, Class<T> clazz, List<T> voList) {
- if(CollUtil.isEmpty(voList)) {
- return null;
- }
- ArrayNode vos = AdmEntityTransferUtil.toDmpMultiEntity(voList);
- // 调用中台修改
- DmpResult<cn.hutool.json.JSONArray> 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<T> voList) {
- if(CollUtil.isEmpty(voList)) {
- return;
- }
- List<String> 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<T> clazz) {
- // 转换参数
- JSONObject para = null;
- try {
- para = JsonHelper.toJsonObject(dmpRequest);
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- return null;
- }
- // 调用中台查询
- DmpResult<JSONArray> dmpResult = rwdClient.queryObject(context, para);
- List<T> admVOs = AdmEntityTransferUtil.toAdmMultiEntity(dmpResult.getData(), null, clazz);
- // JSONArray data = dmpResult.getData();
- // List<T> 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;
- }
- }
|