|
@@ -1,14 +1,26 @@
|
|
|
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.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.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.QueryCriteria;
|
|
|
+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;
|
|
@@ -17,7 +29,10 @@ import com.persagy.proxy.common.entity.InstanceUrlParam;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
|
-import java.util.List;
|
|
|
+import java.io.IOException;
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.lang.reflect.ParameterizedType;
|
|
|
+import java.util.*;
|
|
|
|
|
|
/**
|
|
|
* ADM 抽象实现类
|
|
@@ -38,20 +53,254 @@ public class AbstractAdmBaseServiceImpl<T> implements IAdmBaseService<T> {
|
|
|
* @return
|
|
|
*/
|
|
|
@Override
|
|
|
- public DmpResult<JSONArray> doQuery(InstanceUrlParam context, AdmQueryCriteria request) {
|
|
|
+ public AdmResponse doQuery(InstanceUrlParam context, AdmQueryCriteria request, Class<T> clazz) {
|
|
|
// 转换为数据中台查询条件
|
|
|
QueryCriteria dmpRequest = AdmQueryCriteriaHelper.toDmpCriteria(request);
|
|
|
// 转换参数
|
|
|
JSONObject para = null;
|
|
|
try {
|
|
|
- String paraStr = objectMapper.writeValueAsString(dmpRequest);
|
|
|
- para = JSONObject.parseObject(paraStr);
|
|
|
- } catch (JsonProcessingException e) {
|
|
|
+ para = JsonHelper.toJSONObject(dmpRequest);
|
|
|
+ } catch (IOException e) {
|
|
|
log.error(e.getMessage(), e);
|
|
|
return null;
|
|
|
}
|
|
|
// 调用中台查询
|
|
|
- return rwdClient.queryObject(context, para);
|
|
|
+ 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();
|
|
|
+ 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) {
|
|
|
+ // 获取关联对象的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, "objTo", String.class);
|
|
|
+ relList.forEach(id -> array.add(id));
|
|
|
+ }
|
|
|
+ return groupMapList(relations, "objFrom", "objTo");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将集合转换为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;
|
|
|
}
|
|
|
|
|
|
/**
|