|
@@ -0,0 +1,329 @@
|
|
|
+package com.persagy.proxy.migration.service.Impl;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.http.HttpException;
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
|
+import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
|
+import com.google.common.collect.Sets;
|
|
|
+import com.persagy.dmp.basic.model.QueryCriteria;
|
|
|
+import com.persagy.dmp.basic.utils.JsonNodeUtils;
|
|
|
+import com.persagy.dmp.common.constant.ResponseCode;
|
|
|
+import com.persagy.dmp.common.model.entity.AuditableEntity;
|
|
|
+import com.persagy.dmp.common.model.entity.BaseEntity;
|
|
|
+import com.persagy.dmp.common.model.response.CommonResult;
|
|
|
+import com.persagy.dmp.common.utils.JsonHelper;
|
|
|
+import com.persagy.proxy.common.entity.DmpResult;
|
|
|
+import com.persagy.proxy.common.entity.InstanceUrlParam;
|
|
|
+import com.persagy.proxy.migration.constant.MigrationConstant;
|
|
|
+import com.persagy.proxy.migration.model.DataMigrationExcel;
|
|
|
+import com.persagy.proxy.migration.model.DataMigrationResponse;
|
|
|
+import com.persagy.proxy.migration.model.MigrationInfo;
|
|
|
+import com.persagy.proxy.migration.service.MigrationAbstractService;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author lvxianyun
|
|
|
+ * @title: MigrationAbstractServiceImpl
|
|
|
+ * @projectName adm-middleware
|
|
|
+ * @description: 提供基础的数据操作方法 using guava
|
|
|
+ * @date 2021/12/3 10:56
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+public class MigrationAbstractServiceImpl<T> implements MigrationAbstractService<T> {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * adm交付数据(A) ∩ 现场数据(B)
|
|
|
+ * (A∩B) A
|
|
|
+ * 需要进一步对比的数据
|
|
|
+ *
|
|
|
+ * @param from
|
|
|
+ * @param to
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> doIntersectionGetFrom(Map<String, Object> from, Map<String, Object> to) {
|
|
|
+ Sets.SetView<String> intersection = Sets.intersection(from.keySet(), to.keySet());
|
|
|
+ if(CollUtil.isEmpty(intersection)){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return getValueForMapByKeys(intersection, from);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * adm交付数据(A) ∩ 现场数据(B)
|
|
|
+ * (A∩B) B
|
|
|
+ * 需要进一步对比的数据
|
|
|
+ *
|
|
|
+ * @param from
|
|
|
+ * @param to
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> doIntersectionGetTo(Map<String, Object> from, Map<String, Object> to) {
|
|
|
+ Sets.SetView<String> intersection = Sets.intersection(from.keySet(), to.keySet());
|
|
|
+ if(CollUtil.isEmpty(intersection)){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return getValueForMapByKeys(intersection, to);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * adm交付数据(From) 与 现场数据(to) 差集 返回adm数据
|
|
|
+ * (From - to)
|
|
|
+ * 新增
|
|
|
+ *
|
|
|
+ * @param from
|
|
|
+ * @param to
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> doSubtractAdd(Map<String, Object> from, Map<String, Object> to) {
|
|
|
+ Sets.SetView<String> diffA = Sets.difference(from.keySet(), to.keySet());
|
|
|
+ return getValueForMapByKeys(diffA, from);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * adm交付数据(From) 与 现场数据(to ) 差集 现场数据
|
|
|
+ * (to - From )
|
|
|
+ * 删除
|
|
|
+ *
|
|
|
+ * @param from
|
|
|
+ * @param to
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> doSubtractDel(Map<String, Object> from, Map<String, Object> to) {
|
|
|
+ Sets.SetView<String> diffB = Sets.difference(to.keySet(), from.keySet());
|
|
|
+ return getValueForMapByKeys(diffB, to);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 拼接sql
|
|
|
+ *
|
|
|
+ * @param context
|
|
|
+ * @param migrationInfo
|
|
|
+ * @param urlStart
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public String commonUrl(InstanceUrlParam context, String urlStart, MigrationInfo migrationInfo) {
|
|
|
+ if(StrUtil.isEmpty(urlStart) || StrUtil.isBlank(urlStart)){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ StringBuffer url = new StringBuffer(urlStart);
|
|
|
+ url.append("groupCode=").append(migrationInfo.getTargetGroupCode());
|
|
|
+ url.append("&projectId=").append(migrationInfo.getTargetProjectId());
|
|
|
+ if(StrUtil.isNotEmpty(context.getUserId())){
|
|
|
+ url.append("&userId=").append(context.getUserId());
|
|
|
+ }
|
|
|
+ if(StrUtil.isNotEmpty(context.getAppId())) {
|
|
|
+ url.append("&appId=").append(context.getAppId());
|
|
|
+ }
|
|
|
+ return url.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 向项目侧提交迁移数据
|
|
|
+ *
|
|
|
+ * @param url
|
|
|
+ * @param requestBody
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public String commitDataByHttp(String url, String requestBody) {
|
|
|
+ try{
|
|
|
+ return HttpUtil.post(url, requestBody, 5000);
|
|
|
+ }catch (HttpException e){
|
|
|
+ log.error(ResponseCode.C0001.getDesc()+",url:"+ url);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将list根据自定义规则转为map id为key,
|
|
|
+ * 使用 MigrationConstant.spliter 作为拼接符
|
|
|
+ *
|
|
|
+ * @param list
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> toEntityMap(List<ObjectNode> list, Class<T> clazz) {
|
|
|
+ if(CollUtil.isEmpty(list)){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Map<String, Field> fieldMap = JsonNodeUtils.getFieldMap(clazz);
|
|
|
+ Set<String> fields = fieldMap.keySet();
|
|
|
+ Map<String, Object> map = new HashMap<>(list.size());
|
|
|
+ for(ObjectNode objectNode : list){
|
|
|
+ String key = objectNode.get("id").toString();
|
|
|
+ StringBuffer value = new StringBuffer();
|
|
|
+ for(String fieldKey : fields){
|
|
|
+ if(fieldKey.equals(AuditableEntity.DO_PROP_CREATIONTIME)
|
|
|
+ || fieldKey.equals(AuditableEntity.PROP_CREATOR)
|
|
|
+ || fieldKey.equals(AuditableEntity.DO_PROP_MODIFIEDTIME)
|
|
|
+ || fieldKey.equals(AuditableEntity.PROP_MODIFIER)
|
|
|
+ || fieldKey.equals(BaseEntity.PROP_TS)){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ value.append(objectNode.get(fieldKey) == null ? "" : objectNode.get(fieldKey)).append(MigrationConstant.SPLITER);
|
|
|
+ }
|
|
|
+ map.put(key.replaceAll("\"",""), value.toString().replaceAll("\"",""));
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取项目现场交付的数据,默认全部
|
|
|
+ *
|
|
|
+ * @param queryCriteria
|
|
|
+ * @param clazz
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List getProjectData(QueryCriteria queryCriteria, Class<T> clazz, String url) {
|
|
|
+ return processProjectData(null, queryCriteria, clazz, url).getData();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public DataMigrationResponse updateBatch(List vos, Class<T> clazz, String url) {
|
|
|
+ return saveOrUpdateCommProcess(vos, clazz, url);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public DataMigrationResponse insertBatch(List vos, Class<T> clazz, String url) {
|
|
|
+ return saveOrUpdateCommProcess(vos, clazz, url);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量更新,分批次更新,大于500条,每500条提交一次
|
|
|
+ * @param vos
|
|
|
+ * @param clazz
|
|
|
+ * @param url
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private DataMigrationResponse saveOrUpdateCommProcess(List vos, Class<T> clazz, String url){
|
|
|
+ DataMigrationResponse dataMigrationResponse = DataMigrationResponse.success();
|
|
|
+ if(vos.size() <= MigrationConstant.batchSubmitDataCount){
|
|
|
+ DataMigrationResponse temp = processProjectData(vos,null, clazz, url);
|
|
|
+ if(CollUtil.isNotEmpty(temp.getData())){
|
|
|
+ dataMigrationResponse.addData(temp.getData());
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ int count= vos.size() / MigrationConstant.batchSubmitDataCount;
|
|
|
+ for(int k = 0; k< count + 1 ;k++){
|
|
|
+ int end = (k+1) * MigrationConstant.batchSubmitDataCount - 1;
|
|
|
+ if(end > vos.size()){
|
|
|
+ end = vos.size();
|
|
|
+ }
|
|
|
+ List admDataSub = vos.subList(k * MigrationConstant.batchSubmitDataCount, end);
|
|
|
+ DataMigrationResponse responseTemp = processProjectData(admDataSub,null, clazz, url);
|
|
|
+ if(CollUtil.isNotEmpty(responseTemp.getData())){
|
|
|
+ dataMigrationResponse.addData(responseTemp.getData());
|
|
|
+ }
|
|
|
+ if(CollUtil.isNotEmpty(responseTemp.getErrorMsg())){
|
|
|
+ dataMigrationResponse.addError(responseTemp.getErrorMsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return dataMigrationResponse;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public DataMigrationResponse deleteBatch(List<String> ids, Class<T> clazz, String url) {
|
|
|
+ String response = null;
|
|
|
+ try {
|
|
|
+ response = commitDataByHttp(url, JsonHelper.toJsonStr(ids));
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ return DataMigrationResponse.error(e.getMessage());
|
|
|
+ }
|
|
|
+ CommonResult<List> commonResult = JSONUtil.toBean(response, CommonResult.class);
|
|
|
+ if(commonResult.getResult().equals(DmpResult.SUCCESS)){
|
|
|
+ return DataMigrationResponse.success(ids);
|
|
|
+ }else {
|
|
|
+ log.error(commonResult.getMessage());
|
|
|
+ return DataMigrationResponse.error(commonResult.getResult());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对比需要更新的数据
|
|
|
+ *
|
|
|
+ * @param from
|
|
|
+ * @param to
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> compareData(Map<String, Object> from, Map<String, Object> to) {
|
|
|
+ if(CollUtil.isEmpty(from) || CollUtil.isEmpty(to)){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Set<String> formSets = from.entrySet().stream().map(en -> String.join(MigrationConstant.SPLITER_UNION,en.getKey(),en.getValue().toString())).collect(Collectors.toSet());
|
|
|
+ Set<String> toSets = to.entrySet().stream().map(en -> String.join(MigrationConstant.SPLITER_UNION,en.getKey(),en.getValue().toString())).collect(Collectors.toSet());
|
|
|
+
|
|
|
+ Sets.SetView<String> difference = Sets.difference(formSets, toSets);
|
|
|
+ if(CollUtil.isEmpty(difference)){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Set<String> diff = difference.stream().map(entity -> StrUtil.subBefore(entity, MigrationConstant.SPLITER_UNION, true)).collect(Collectors.toSet());
|
|
|
+ Map<String, Object> results = getValueForMapByKeys(diff, from);
|
|
|
+ return results;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<DataMigrationExcel> addErrorInfo(List<String> errorMsg) {
|
|
|
+ if(CollUtil.isEmpty(errorMsg)){
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ List<DataMigrationExcel> dataMigrationExcels = new ArrayList<>(errorMsg.size());
|
|
|
+ for(String msg : errorMsg){
|
|
|
+ DataMigrationExcel dataMigrationExcelError = new DataMigrationExcel();
|
|
|
+ dataMigrationExcelError.setId("error");
|
|
|
+ dataMigrationExcelError.setMark(msg);
|
|
|
+ dataMigrationExcels.add(dataMigrationExcelError);
|
|
|
+ }
|
|
|
+ return dataMigrationExcels;
|
|
|
+ }
|
|
|
+
|
|
|
+ private DataMigrationResponse processProjectData(List vos, QueryCriteria queryCriteria, Class<T> clazz, String url){
|
|
|
+ //处理rwd 请求返回超时
|
|
|
+ String body = null;
|
|
|
+ try {
|
|
|
+ if(CollUtil.isEmpty(vos) && queryCriteria != null){
|
|
|
+ body = JsonHelper.toJsonStr(queryCriteria);
|
|
|
+ }else{
|
|
|
+ body = JsonHelper.toJsonStr(vos);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(ResponseCode.C0001.toString());
|
|
|
+ return DataMigrationResponse.error(ResponseCode.C0001.toString());
|
|
|
+ }
|
|
|
+ String response = commitDataByHttp(url, body);
|
|
|
+ CommonResult<List> commonResult = JSONUtil.toBean(response, CommonResult.class);
|
|
|
+ if(commonResult.getResult().equals(DmpResult.SUCCESS)){
|
|
|
+ ArrayNode arrayNode = JsonNodeUtils.toArrayNode(commonResult.getData(), null, null);
|
|
|
+ if(arrayNode == null){
|
|
|
+ return DataMigrationResponse.success();
|
|
|
+ }
|
|
|
+ return DataMigrationResponse.success(JsonNodeUtils.toEntity(arrayNode, clazz, null));
|
|
|
+ }else {
|
|
|
+ log.error(commonResult.getMessage());
|
|
|
+ return DataMigrationResponse.error(commonResult.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getValueForMapByKeys(Set<String> sets, Map<String, Object> map){
|
|
|
+ if(CollUtil.isEmpty(sets) || CollUtil.isEmpty(map)){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Map<String, Object> targetsMap = new HashMap<>(sets.size());
|
|
|
+ sets.forEach(key -> targetsMap.put(key, map.get(key)));
|
|
|
+ return targetsMap;
|
|
|
+ }
|
|
|
+}
|