SpecManagerImpl.java
package com.mycim.server.spec.manager.impl;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.jdbc.Page;
import com.mycim.framework.utils.lang.BooleanUtils;
import com.mycim.framework.utils.lang.ObjectUtils;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.server.base.manager.NamedObjectManager;
import com.mycim.server.base.manager.TransactionLogManager;
import com.mycim.server.ctx.exec.manager.WflLinkContextValueManager;
import com.mycim.server.ctx.manager.ContextValueManager;
import com.mycim.server.prp.manager.ProcessManager;
import com.mycim.server.prp.manager.ProductProcessManager;
import com.mycim.server.prp.manager.ProductVersionManager;
import com.mycim.server.prp.manager.WorkflowManager;
import com.mycim.server.spec.manager.*;
import com.mycim.utils.WflLinkContextSetupAttributeUtil;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.TransactionLog;
import com.mycim.valueobject.consts.ContextNames;
import com.mycim.valueobject.prp.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.lang.Override;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author Qiansheng.Wang
* @version 1.0
* @since 2021-07-07
**/
@Service
@Transactional
public class SpecManagerImpl implements SpecManager {
@Autowired
TransactionLogManager transactionLogManager;
@Autowired
ProductSpecInfoManager productSpecInfoManager;
@Autowired
ProcessSpecInfoManager processSpecInfoManager;
@Autowired
ProcessSpecItemManager processSpecItemManager;
@Autowired
ProductAttributeInfoManager productAttributeInfoManager;
@Autowired
ProductAttributeItemManager productAttributeItemManager;
@Autowired
ProductVersionManager productVersionManager;
@Autowired
ProductProcessManager productProcessManager;
@Autowired
ActivationAttributeManager activationAttributeManager;
@Autowired
ProcessManager processManager;
@Autowired
NamedObjectManager namedObjectManager;
@Autowired
ContextValueManager contextValueManager;
@Autowired
WorkflowManager workflowManager;
@Autowired
WflLinkContextValueManager wflLinkContextValueManager;
@Override
public List<Integer> getProcessVersionsInSpec(Long processRrn) {
List<Integer> result = new ArrayList<>();
for (ProcessSpecInfo processSpecInfo : processSpecInfoManager.getProcessSpecItemInfos(processRrn)) {
result.add(processSpecInfo.getProcessVersion());
}
return result;
}
@Override
public Integer getLatestAvailableVersion(Long processRrn) {
List<Integer> activeVersion = processSpecInfoManager.getAllActivatedProcessVersions(processRrn);
for (Integer verion : activeVersion) {
if (CollectionUtils.isEmpty(processSpecItemManager.getProcessSpecItemsWithVariables(processRrn, verion))) {
return verion;
}
}
return 0;
}
@Override
public ProductSpecInfo getLatestActivatedProductSpecInfo(Long productRrn, Long processRrn) {
return productSpecInfoManager.getLatestActivatedProductSpecInfo(productRrn, processRrn);
}
@Override
public int getLatestActivatedProcessVersion(Long productRrn, Long processRrn) {
// 获取流程或流程产品最新可用的流程版本
ProductSpecInfo productSpecInfo = getLatestActivatedProductSpecInfo(productRrn, processRrn);
int processVer = 0;
if (productSpecInfo != null && productSpecInfo.getProcessVersion() > 0) {
// 如果有数据,表示曾经激活过对应版本的属性信息,返回对应的流程版本
processVer = productSpecInfo.getProcessVersion();
} else {
// 如果没有数据,则获取流程最新的可用版本
processVer = getLatestAvailableVersion(processRrn);
}
return processVer;
}
@Override
public void addProductAttributeWhenAddProductProcess(TransactionLog transactionLog,
ProductProcessDto productProcess) {
List<ProcessSpecInfo> specInfos = getProcessSpecInfosThatNeedsToSaveProductAttributes(
productProcess.getProcessRrn());
if (CollectionUtils.isEmpty(specInfos)) {
return;
}
List<ProductVersion> productVersions = getProductVersionsThatNeedsToSaveProductAttributes(
productProcess.getProductRrn());
if (CollectionUtils.isEmpty(productVersions)) {
return;
}
for (ProcessSpecInfo processSpecInfo : specInfos) {
List<ProcessSpecItem> willSaveProcessSpecItems = processSpecItemManager
.getProcessSpecItemsWithVariables(processSpecInfo.getProcessRrn(),
processSpecInfo.getProcessVersion());
if (CollectionUtils.isEmpty(willSaveProcessSpecItems)) {
if (BooleanUtils.toBoolean(processSpecInfo.getActiveFlag())) {
activateProduct(transactionLog, productVersions, processSpecInfo);
}
continue;
}
productAttributeItemManager
.saveProductAttribute(transactionLog, processSpecInfo, willSaveProcessSpecItems, productVersions);
}
}
@Override
public void deleteProductAttributeWhenDeleteProductProcess(TransactionLog transactionLog,
ProductProcessDto productProcess) {
deleteProductAttributeWhenProductDoDelete(transactionLog, productAttributeInfoManager
.getProductAttributeInfos(productProcess.getProductRrn(), productProcess.getProcessRrn()));
}
@Override
public void deleteProductAttributeWhenDeleteProduct(TransactionLog transactionLog, Long productRrn) {
deleteProductAttributeWhenProductDoDelete(transactionLog, productAttributeInfoManager
.getProductAttributeInfosByProduct(productRrn));
}
private void deleteProductAttributeWhenProductDoDelete(TransactionLog transactionLog,
List<ProductAttributeInfo> productAttributeInfosByProduct) {
List<ProductAttributeInfo> willDeleteAttributeInfos = new ArrayList<>();
List<ProductAttributeItem> willDeleteAttributeItems = new ArrayList<>();
for (ProductAttributeInfo attributeInfo : productAttributeInfosByProduct) {
// if (!BooleanUtils.toBoolean(attributeInfo.getActiveFlag())) {
// 在product 解绑和删除时,需要删除对应product的所有数据 包括active的数据
willDeleteAttributeInfos.add(attributeInfo);
willDeleteAttributeItems.addAll(productAttributeItemManager
.getProductAttributeItems(attributeInfo.getProcessRrn(),
attributeInfo.getProcessVersion(),
attributeInfo.getProductRrn(),
attributeInfo.getProductVersion()));
// }
}
productAttributeInfoManager.deleteProductAttributeInfos(willDeleteAttributeInfos);
productAttributeItemManager.deleteProductAttributeItems(transactionLog, willDeleteAttributeItems);
}
private void activateProduct(TransactionLog transactionLog, List<ProductVersion> productVersions,
ProcessSpecInfo processSpecInfo) {
productSpecInfoManager.activateProductSpecInfos(transactionLog, processSpecInfo, productVersions);
activateProduct(transactionLog, processSpecInfo.getProcessRrn(), processSpecInfo.getProcessVersion());
}
@Override
public void activateProduct(TransactionLog transactionLog, Long processRrn, Integer processVersion) {
Integer highestAvailableProcessVersion = processSpecInfoManager.getHighestActivatedProcessVersion(processRrn);
if (highestAvailableProcessVersion == null || highestAvailableProcessVersion <= processVersion) {
// 更新产品可用的流程版本
productProcessManager.updateAvailableProcessVersionOfAllProduct(transactionLog, processRrn, processVersion);
}
activationAttributeManager.saveActivationAttributes(processRrn, processVersion);
}
@Override
public Boolean checkMultipath(String processId, Long processRrn, Integer processVersion, List<String> productIds) {
Boolean multipathSetFlag = Boolean.FALSE;
List<Item> usedByProducts = new ArrayList<>();
if (CollectionUtils.isNotEmpty(productIds)) {
//若productIds不为空则表示536active,只check当前的product
for (String productId : productIds) {
Item item = new Item();
item.setInstanceId(productId);
item.setInstanceRrn(namedObjectManager.getNamedObjectRrn(productId, LocalContext.getFacilityRrn(),
ObjectList.PRODUCT_KEY));
usedByProducts.add(item);
}
} else {
// 若productIds为空 则表示535active,查询当前process上挂的所有product
usedByProducts = processManager.getUsedByProducts(processRrn);
}
if (CollectionUtils.isEmpty(usedByProducts)) {
return Boolean.FALSE;
}
List<Map<String, Object>> multipathOperation = getMultipath(processRrn, processVersion,
WflLinkContextSetupAttributeUtil.OPERATION_FLAG);
List<Map<String, Object>> multipathRoute = getMultipath(processRrn, processVersion,
WflLinkContextSetupAttributeUtil.ROUTE_FLAG);
for (Map<String, Object> map : multipathOperation) {
Long operationRrn = MapUtils.getLong(map, "operationRrn");
Long routeRrn = MapUtils.getLong(map, "routeRrn");
if (operationRrn.longValue() < 0 || routeRrn.longValue() < 0) {
continue;
}
for (Item product : usedByProducts) {
multipathSetFlag = Boolean.TRUE;
// 查询对应product上的Multipath设置
WflLinkContextValue wflLinkContextValue = new WflLinkContextValue();
wflLinkContextValue.setProductRrn(product.getInstanceRrn());
wflLinkContextValue.setProcessRrn(processRrn);
wflLinkContextValue.setProcessVersion(processVersion);
wflLinkContextValue.setStatus("ACTIVE");
List<WflLinkContextValue> contextValues = wflLinkContextValueManager
.getContextValues(wflLinkContextValue);
for (WflLinkContextValue ct : contextValues) {
if (operationRrn.equals(ct.getOperationRrn()) && routeRrn.equals(ct.getRouteRrn()) &&
WflLinkContextSetupAttributeUtil.isByOperationMultipath(ct)) {
multipathSetFlag = Boolean.FALSE;
break;
}
}
if (multipathSetFlag) {
return multipathSetFlag;
}
}
}
for (Map<String, Object> map : multipathRoute) {
String routeId = MapUtils.getString(map, "routeId");
Long routeRrn = namedObjectManager
.getNamedObjectRrn(routeId, LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);
if (routeRrn.longValue() > 0) {
for (Item product : usedByProducts) {
// 查询对应product上的Multipath设置
multipathSetFlag = Boolean.TRUE;
WflLinkContextValue wflLinkContextValue = new WflLinkContextValue();
wflLinkContextValue.setProductRrn(product.getInstanceRrn());
wflLinkContextValue.setProcessRrn(processRrn);
wflLinkContextValue.setProcessVersion(processVersion);
wflLinkContextValue.setStatus("ACTIVE");
List<WflLinkContextValue> contextValues = wflLinkContextValueManager
.getContextValues(wflLinkContextValue);
for (WflLinkContextValue ct : contextValues) {
if (WflLinkContextSetupAttributeUtil.isByRouteMultipath(ct) &&
routeRrn.equals(ct.getRouteRrn())) {
multipathSetFlag = Boolean.FALSE;
break;
}
}
if (multipathSetFlag) {
return multipathSetFlag;
}
}
}
}
return Boolean.FALSE;
}
private List<ProductVersion> getProductVersionsThatNeedsToSaveProductAttributes(Long productVersion) {
List<ProductVersion> productVersions = new ArrayList<>();
List<ProductVersion> allProductVersion = productVersionManager.getAllVersions(productVersion);
allProductVersion.sort((o1, o2) -> o2.getInstanceVersion() - o1.getInstanceVersion());
productVersions.add(allProductVersion.iterator().next());
return productVersions;
}
private List<ProcessSpecInfo> getProcessSpecInfosThatNeedsToSaveProductAttributes(Long processRrn) {
List<ProcessSpecInfo> processSpecInfos = processSpecInfoManager.getProcessSpecItemInfos(processRrn);
processSpecInfos.sort((o1, o2) -> o2.getProcessVersion() - o1.getProcessVersion());
List<ProcessSpecInfo> specInfos = new ArrayList<>();
for (ProcessSpecInfo processSpecInfo : processSpecInfos) {
specInfos.add(processSpecInfo);
if (BooleanUtils.toBoolean(processSpecInfo.getActiveFlag())) {
break;
}
}
return specInfos;
}
private List<Map<String, Object>> getMultipath(Long processRrn, Integer processVersion, String type) {
List<Map<String, Object>> workFlowByProcess = new ArrayList<>();
Boolean ruleFlag = Boolean.FALSE;
if (StringUtils.equalsIgnoreCase(WflLinkContextSetupAttributeUtil.OPERATION_FLAG, type)) {
workFlowByProcess = workflowManager.getWflOperationByProcess(processRrn, processVersion);
ruleFlag = Boolean.TRUE;
} else if (StringUtils.equalsIgnoreCase(WflLinkContextSetupAttributeUtil.ROUTE_FLAG, type)) {
workFlowByProcess = workflowManager.getWflRouteByProcess(processRrn, processVersion);
ruleFlag = Boolean.FALSE;
} else {
return null;
}
List<Map<String, Object>> buildWorkFlow = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
for (Map<String, Object> flowByProcess : workFlowByProcess) {
String rule = StringUtils.EMPTY;
if (ruleFlag) {
rule = MapUtils.getString(flowByProcess, "routeRrn") + StringUtils.COMMA_SIGN +
MapUtils.getString(flowByProcess, "routeVersion") + StringUtils.COMMA_SIGN +
MapUtils.getString(flowByProcess, "operationId") + StringUtils.COMMA_SIGN;
} else {
rule = MapUtils.getString(flowByProcess, "processRrn") + StringUtils.COMMA_SIGN +
MapUtils.getString(flowByProcess, "processVersion") + StringUtils.COMMA_SIGN +
MapUtils.getString(flowByProcess, "routeId") + StringUtils.COMMA_SIGN;
}
//1 检测key是否重复
if (map.containsKey(rule)) {
Integer num = map.get(rule);
if (NumberUtils.INTEGER_ONE.equals(num)) {
String operationId = MapUtils.getString(flowByProcess, "operationId");
Long instanceRrn = namedObjectManager
.getNamedObjectRrn(operationId, LocalContext.getFacilityRrn(), ObjectList.OPERATION_KEY);
flowByProcess.put("operationRrn", instanceRrn);
buildWorkFlow.add(flowByProcess);//获取重复元素
}
map.put(rule, num + 1);
} else {
map.put(rule, 1);
}
}
return buildWorkFlow;
}
@Override
public Boolean checkMultiPathHasManualForContextValue(WflLinkContextValue contextValue) {
Long routeRrn = contextValue.getRouteRrn();
Long operationRrn = contextValue.getOperationRrn();
Long processRrn = contextValue.getProcessRrn();
Integer processVersion = contextValue.getProcessVersion();
if (WflLinkContextSetupAttributeUtil.isByManualOperationMultipath(contextValue)) {
Integer routeVersion = workflowManager.getWFLVersionByProcess(processRrn, processVersion, routeRrn);
Collection operationPath = workflowManager
.getWflPath(routeRrn, routeVersion, namedObjectManager.getInstanceId(operationRrn));
if (operationPath.size() < 2) {
return Boolean.FALSE;
}
} else if (WflLinkContextSetupAttributeUtil.isByManualRouteMultipath(contextValue)) {
Collection routePath = workflowManager
.getWflPath(processRrn, processVersion, namedObjectManager.getInstanceId(routeRrn));
if (routePath.size() < 2) {
return Boolean.FALSE;
}
}
return Boolean.TRUE;
}
@Override
public List<Map<String,Object>> getMultipathAndDefaultSteps(Long processRrn, Integer processVersion,String type) {
//根据processRrn processVersion取到对应的所有operation节点信息
List<Map<String, Object>> allWflList = workflowManager.getallWflByProcess(processRrn,processVersion);
//operation multipath
if (StringUtils.equalsIgnoreCase(WflLinkContextSetupAttributeUtil.OPERATION_FLAG, type)) {
Set<Long> wflStepRrns = new HashSet<>();
List<Map<String,Object>> wflList = new ArrayList<>();
for(Map<String, Object> operation : allWflList){
if(StringUtils.isNotBlank(MapUtils.getString(operation,"operationLinkId"))){
wflStepRrns.add(MapUtils.getLong(operation, "operationStepRrn"));
}
}
//若operation存在multipath的节点(可能存在多个)
if(CollectionUtils.isNotEmpty(wflStepRrns)){
for(Long wflStepRrn : wflStepRrns){
List<Long> multiParentAndChildrenNodesList = new ArrayList<>();
List<Long> multiParentAndChildrenNodesListNoEnd = new ArrayList<>();
//拿到multipath节点的默认子节点和multipath子节点(可能存在多个)
Set<Long> multiStepRrns = new LinkedHashSet<>();
for(Map<String, Object> operation : allWflList){
if(wflStepRrn.equals(MapUtils.getLong(operation, "operationStepRrn"))){
multiStepRrns.add(MapUtils.getLong(operation, "wflNextStepRrn"));
}
}
if(CollectionUtils.isNotEmpty(multiStepRrns)){
//递归查询multipath节点作为父节点对应路径下的所有节点
for(Long wflNode : multiStepRrns){
List<Map<String, Object>> childrenNodes = getChildrenNodes(allWflList,wflNode,"wflNextStepRrn","operationStepRrn",new ArrayList<>());
for(Map<String, Object> childNode : childrenNodes){
multiParentAndChildrenNodesList.add(MapUtils.getLong(childNode, "operationStepRrn"));
}
}
if(CollectionUtils.isNotEmpty(multiParentAndChildrenNodesList)) {
//拿到对应的multipath和default路径节点(即个数不等于分支长度的节点)
multiParentAndChildrenNodesListNoEnd = multiParentAndChildrenNodesList.stream().collect(
Collectors.toMap(Function.identity(), s -> 1, Integer::sum)).entrySet().stream()
.filter(entry -> !entry.getValue().equals(multiStepRrns.size()))
.map(Map.Entry::getKey).collect(Collectors.toList());
}
}
//取multipath和default路径节点的operationRrn
if(CollectionUtils.isNotEmpty(multiParentAndChildrenNodesListNoEnd)){
for(Map<String,Object> wflInfo : allWflList){
for(Long operationStepRrn : multiParentAndChildrenNodesListNoEnd){
if(MapUtils.getLong(wflInfo,"operationStepRrn").equals(operationStepRrn)){
wflList.add(wflInfo);
}
}
}
}
}
}
return wflList;
}
//route multipath
else if (StringUtils.equalsIgnoreCase(WflLinkContextSetupAttributeUtil.ROUTE_FLAG, type)) {
List<Map<String,Object>> routeWflList = new ArrayList<>();
List<Long> routeStepRrnList = new ArrayList<>();
//获取到对应的所有route节点信息
for(Map<String, Object> wflInfo : allWflList){
if(!routeStepRrnList.contains(MapUtils.getLong(wflInfo,"routeStepRrn"))){
routeStepRrnList.add(MapUtils.getLong(wflInfo,"routeStepRrn"));
routeWflList.add(wflInfo);
}
}
List<Map<String,Object>> wflList = new ArrayList<>();
Set<Long> wflStepRrns = new HashSet<>();
for(Map<String, Object> route : routeWflList){
if(StringUtils.isNotBlank(MapUtils.getString(route,"routeLinkId"))){
wflStepRrns.add(MapUtils.getLong(route, "routeStepRrn"));
}
}
//若route存在multipath的节点(可能存在多个)
if(CollectionUtils.isNotEmpty(wflStepRrns)){
for(Long wflStepRrn : wflStepRrns){
List<Long> multiParentAndChildrenNodesList = new ArrayList<>();
List<Long> multiParentAndChildrenNodesListNoEnd = new ArrayList<>();
//拿到multipath节点的默认子节点和multipath子节点(可能存在多个)
Set<Long> multiStepRrns = new LinkedHashSet<>();
for(Map<String, Object> operation : allWflList){
if(wflStepRrn.equals(MapUtils.getLong(operation, "routeStepRrn"))){
multiStepRrns.add(MapUtils.getLong(operation, "routeWflNextStepRrn"));
}
}
if(CollectionUtils.isNotEmpty(multiStepRrns)){
//递归查询multipath节点作为父节点对应路径下的所有节点
for(Long wflNode : multiStepRrns){
List<Map<String, Object>> childrenNodes = getChildrenNodes(routeWflList,wflNode,"routeWflNextStepRrn","routeStepRrn",new ArrayList<>());
for(Map<String, Object> childNode : childrenNodes){
multiParentAndChildrenNodesList.add(MapUtils.getLong(childNode, "routeStepRrn"));
}
}
if(CollectionUtils.isNotEmpty(multiParentAndChildrenNodesList)) {
//拿到对应的end节点(个数和multipath节点个数相同的第一个节点即为end节点)
multiParentAndChildrenNodesListNoEnd = multiParentAndChildrenNodesList.stream().collect(
Collectors.toMap(Function.identity(), s -> 1, Integer::sum)).entrySet().stream()
.filter(entry -> !entry.getValue().equals(multiStepRrns.size()))
.map(Map.Entry::getKey).collect(Collectors.toList());
}
}
//取multipath和default路径节点的operationRrn
if(CollectionUtils.isNotEmpty(multiParentAndChildrenNodesListNoEnd)){
for(Map<String,Object> wflInfo : allWflList){
for(Long routeStepRrn : multiParentAndChildrenNodesListNoEnd){
if(MapUtils.getLong(wflInfo,"routeStepRrn").equals(routeStepRrn)){
wflList.add(wflInfo);
}
}
}
}
}
}
return wflList;
} else {
return null;
}
}
//递归查找父节点的所有子节点
public List<Map<String,Object>> getChildrenNodes(List<Map<String,Object>> nodesList, Long nodeRrn, String wflNextStepRrnString,String stepRrnString,List<Map<String,Object>> childNodes) {
for (Map<String,Object> node : nodesList) {
//遍历出wflNextStepRrn等于operationStepRrn,add进子节点集合
if (nodeRrn.equals(MapUtils.getLong(node,stepRrnString))) {
//递归遍历下一级
childNodes.add(node);
getChildrenNodes(nodesList,MapUtils.getLong(node,wflNextStepRrnString),wflNextStepRrnString,stepRrnString,childNodes);
}
}
return childNodes;
}
}