예제 #1
0
        private ActionRule createActionRule(TapestryDesignerWorkflowRule workflowRule, Block nonVirtualBlock, Block startBlock, TapestryDesignerWorkflowConnection connection,
                                            ref Dictionary <TapestryDesignerWorkflowItem, Block> blockMapping, Dictionary <Block, TapestryDesignerConditionGroup> conditionMapping, Dictionary <int, string> stateColumnMapping, HashSet <Block> blockHasRights,
                                            ref WorkFlow wf)
        {
            TapestryDesignerWorkflowItem item = connection.Target;

            // is there a button name?
            string init = item?.ComponentName;

            if (workflowRule.Name == "INIT" && nonVirtualBlock == startBlock)   // initial ActionRule
            {
                init = "INIT";
            }
            if (item?.TypeClass == "symbol" && (item?.SymbolType == "envelope-start" || item?.SymbolType == "circle-event"))  // emailové workflow nebo socket listener
            {
                init = item?.Label;
            }
            if (item?.TypeClass == "symbol" && item?.SymbolType == "circle-single" && workflowRule.Name != "INIT")  // REST ENDPOINT
            {
                init = workflowRule.Name;
            }

            string     ActorName = (init != null ? "Manual" : "Auto");
            ActionRule rule      = new ActionRule
            {
                Actor      = _context.Actors.Single(a => a.Name == ActorName),
                Name       = $"{workflowRule.Name}: {startBlock.DisplayName} - {(_random.Next() % 1000000).ToString()}",
                ExecutedBy = init
            };

            // condition
            if (conditionMapping.ContainsKey(startBlock))
            {
                // branch true
                if (connection.SourceSlot == 0)
                {
                    // copy condition to new db
                    if (_masterContext != _context)
                    {
                        TapestryDesignerConditionGroup originConditionGroup = conditionMapping[startBlock];
                        // new conditionGroup
                        TapestryDesignerConditionGroup conditionGroup = new TapestryDesignerConditionGroup
                        {
                            Application           = _app,
                            ResourceMappingPairId = originConditionGroup.ResourceMappingPairId
                        };
                        rule.ConditionGroup = conditionGroup;

                        // new conditionSet
                        foreach (TapestryDesignerConditionSet originConditionSet in originConditionGroup.ConditionSets)
                        {
                            TapestryDesignerConditionSet conditionSet = new TapestryDesignerConditionSet
                            {
                                SetIndex    = originConditionSet.SetIndex,
                                SetRelation = originConditionSet.SetRelation
                            };
                            conditionGroup.ConditionSets.Add(conditionSet);

                            // new condition
                            foreach (TapestryDesignerCondition originCondition in originConditionSet.Conditions)
                            {
                                TapestryDesignerCondition condition = new TapestryDesignerCondition
                                {
                                    Index    = originCondition.Index,
                                    Operator = originCondition.Operator,
                                    Relation = originCondition.Relation,
                                    Value    = originCondition.Value,
                                    Variable = originCondition.Variable,
                                };
                                conditionSet.Conditions.Add(condition);
                            }
                        }

                        _context.TapestryDesignerConditionGroups.Add(conditionGroup);
                        _context.SaveChanges();
                    }
                    // same DB
                    else
                    {
                        rule.ConditionGroup = conditionMapping[startBlock];
                    }
                }

                // branch false
                else
                {
                    rule.isDefault = true;
                }
            }
            startBlock.SourceTo_ActionRules.Add(rule);
            // rights
            if (blockHasRights.Contains(startBlock) && item != null)
            {
                AddActionRuleRights(rule, item.ParentSwimlane);
            }

            TapestryDesignerWorkflowItem prevItem = null;

            while (item != null && // end WF
                   (!blockMapping.ContainsKey(item) || // split || join
                    (prevItem == null && connection.Source == connection.Target)))    // split || join but starting action item
            {
                switch (item.TypeClass)
                {
                case "actionItem":
                    //if (item.ActionId == 181) // noAction
                    //    break;

                    string generatedInputVariables = "";
                    if (item.ActionId == 2005 || item.ActionId == 193)     // Send mail, Send mail for each
                    {
                        foreach (var relatedConnections in workflowRule.Connections.Where(c => c.TargetId == item.Id))
                        {
                            if (relatedConnections.Source.TypeClass == "templateItem")
                            {
                                generatedInputVariables = ";Template=s$" + relatedConnections.Source.Label;
                            }
                        }
                    }
                    if (item.ActionId == 3001 || item.ActionId == 3002 || item.ActionId == 3012)     // Call SOAP, Call REST
                    {
                        foreach (var relatedConnections in workflowRule.Connections.Where(c => c.TargetId == item.Id))
                        {
                            if (relatedConnections.Source.Label?.StartsWith("WS: ") ?? false)
                            {
                                generatedInputVariables = ";WSName=s$" + relatedConnections.Source.Label.Substring(4);
                            }
                        }
                    }
                    if (item.ActionId == 3004 || item.ActionId == 3005 || item.ActionId == 3006 || item.ActionId == 3007)     // ExtDB Select / Insert / Update / Delete
                    {
                        foreach (var relatedConnections in workflowRule.Connections.Where(c => c.TargetId == item.Id))
                        {
                            if (relatedConnections.Source.Label?.StartsWith("ExtDB: ") ?? false)
                            {
                                generatedInputVariables = ";dbName=s$" + relatedConnections.Source.Label.Substring(7);
                            }
                        }
                    }
                    if (item.ActionId == 3008)     // Send to RabbitMQ
                    {
                        foreach (var relatedConnections in workflowRule.Connections.Where(c => c.TargetId == item.Id))
                        {
                            if (relatedConnections.Source.Label?.StartsWith("RabbitMQ: ") ?? false)
                            {
                                generatedInputVariables = ";rabbitMQ=s$" + relatedConnections.Source.Label.Substring(10);
                            }
                        }
                    }
                    if (item.ActionId == 2007)     // DataTable Response action
                    {
                        generatedInputVariables = ";BootstrapPageId=i$" + startBlock.BootstrapPageId;
                    }

                    ActionRule_Action result = new ActionRule_Action
                    {
                        ActionId = item.ActionId.Value,
                        Order    = rule.ActionRule_Actions.Any() ? rule.ActionRule_Actions.Max(aar => aar.Order) + 1 : 1,
                        InputVariablesMapping  = item.InputVariables + generatedInputVariables,
                        OutputVariablesMapping = item.OutputVariables,
                        VirtualParentId        = item.ParentForeachId.HasValue ? item.ParentForeachId : null,
                        IsForeachStart         = item.IsForeachStart,
                        IsForeachEnd           = item.IsForeachEnd
                    };
                    rule.ActionRule_Actions.Add(result);
                    break;

                case "targetItem":
                    if (_blockMapping.ContainsKey(item.Target))
                    {
                        rule.TargetBlock = _blockMapping[item.Target];
                    }
                    else
                    {
                        _progressHandler.Error($"Block [{item.Target.Name}] not found!");
                    }
                    break;

                case "symbol":
                    // No needed now
                    //switch (item.SymbolType)
                    //{
                    //    case "gateway-x":
                    //        Block splitBlock = blockMapping[item];
                    //        // if not already in conditionMapping
                    //        if (!conditionMapping.ContainsKey(splitBlock))
                    //            conditionMapping.Add(splitBlock, item.Id);
                    //        break;
                    //}
                    break;

                case "circle-thick":
                    break;

                case "attributeItem":
                    break;

                case "templateItem":
                    break;

                case "stateItem":
                    if (stateColumnMapping.ContainsKey(item.StateId.Value))
                    {
                        string            stateColumn    = stateColumnMapping[item.StateId.Value];
                        ActionRule_Action setStateAction = new ActionRule_Action
                        {
                            ActionId = 1029,
                            Order    = rule.ActionRule_Actions.Any() ? rule.ActionRule_Actions.Max(aar => aar.Order) + 1 : 1,
                            InputVariablesMapping  = $"ColumnName=s${stateColumn};StateId=i${item.StateId.Value}",
                            OutputVariablesMapping = ""
                        };
                        rule.ActionRule_Actions.Add(setStateAction);
                    }
                    break;

                case "circle-single":
                    break;

                case "circle-single-dashed":
                    break;

                case "uiItem":
                    // DONE
                    break;

                case "database":
                    break;

                case "comment":
                    break;

                case "virtualAction":
                    switch (item.SymbolType)
                    {
                    case "foreach":
                        HashSet <TapestryDesignerWorkflowConnection> todoConnections = new HashSet <TapestryDesignerWorkflowConnection>();

                        ActionRule_Action feResult = new ActionRule_Action
                        {
                            ActionId = -1,
                            Order    = rule.ActionRule_Actions.Any() ? rule.ActionRule_Actions.Max(aar => aar.Order) + 1 : 1,
                            InputVariablesMapping  = item.InputVariables,
                            OutputVariablesMapping = item.OutputVariables,
                            VirtualAction          = "foreach",
                            VirtualItemId          = item.ParentForeachId
                        };
                        rule.ActionRule_Actions.Add(feResult);

                        // Uložíme akce uvnitř cyklu
                        var splitItems = _masterContext.TapestryDesignerWorkflowItems.Where(i => i.ParentSwimlane.ParentWorkflowRule_Id == workflowRule.Id && i.TypeClass == "symbol" && _splitGateways.Contains(i.SymbolType) && i.ParentForeachId == item.ParentForeachId && i.Id != item.Id).ToList();
                        var joinItems  = _masterContext.TapestryDesignerWorkflowItems.Where(i => i.ParentSwimlane.ParentWorkflowRule_Id == workflowRule.Id && (i.TargetToConnection.Count() > 1 || i.IsForeachStart == true) && i.ParentForeachId == item.ParentForeachId && i.Id != item.Id).ToList();

                        foreach (var splitItem in splitItems)
                        {
                            // block mapping
                            int   random   = _random.Next() % 1000000;
                            Block newBlock = new Block
                            {
                                Name                = $"split_{nonVirtualBlock.Name}_{random}",
                                DisplayName         = $"split[{nonVirtualBlock.Name}_{random}]",
                                ModelName           = nonVirtualBlock.ModelName,
                                IsVirtualForBlockId = nonVirtualBlock.Id
                            };
                            wf.Blocks.Add(newBlock);
                            blockMapping.Add(splitItem, newBlock);

                            // conditions
                            if (splitItem.SymbolType == "gateway-x")
                            {
                                try {
                                    conditionMapping.Add(newBlock, splitItem.ConditionGroups.Single());
                                }
                                catch (InvalidOperationException ex) {
                                    throw new Exception("Gateway has no condition!", ex);
                                }
                            }

                            // rights
                            if (checkBlockHasRights(splitItem))
                            {
                                blockHasRights.Add(newBlock);
                            }

                            // todo connection
                            int connectionCount = splitItem.SourceToConnection.Count;
                            if (connectionCount == 0)         // wrong WF
                            {
                                throw new Exception($"Workflow ends with gateway - {nonVirtualBlock.Name}: {workflowRule.Name}");
                            }
                            if (connectionCount == 1)         // missing way - return to real Block
                            {
                                TapestryDesignerWorkflowConnection conn = splitItem.SourceToConnection.FirstOrDefault();
                                todoConnections.Add(conn);
                                todoConnections.Add(new TapestryDesignerWorkflowConnection {
                                    SourceSlot = conn.SourceSlot == 0 ? 1 : 0, Source = splitItem
                                });
                            }
                            else         // OK
                            {
                                foreach (TapestryDesignerWorkflowConnection conn in splitItem.SourceToConnection)
                                {
                                    todoConnections.Add(conn);
                                }
                            }
                        }

                        foreach (var joinItem in joinItems)
                        {
                            if (blockMapping.ContainsKey(joinItem))         // split item & join item are same
                            {
                                continue;
                            }

                            // block mapping
                            int   random   = _random.Next() % 1000000;
                            Block newBlock = new Block
                            {
                                Name                = $"join_{nonVirtualBlock.Name}_{random}",
                                DisplayName         = $"join[{nonVirtualBlock.Name}_{random}]",
                                ModelName           = nonVirtualBlock.ModelName,
                                IsVirtualForBlockId = nonVirtualBlock.Id
                            };
                            wf.Blocks.Add(newBlock);
                            blockMapping.Add(joinItem, newBlock);

                            // todo connection
                            todoConnections.Add(new TapestryDesignerWorkflowConnection {
                                Source = joinItem, Target = joinItem
                            });
                        }

                        foreach (TapestryDesignerWorkflowConnection conn in todoConnections)
                        {
                            createActionRule(workflowRule, nonVirtualBlock, blockMapping[conn.Source], conn, ref blockMapping, conditionMapping, stateColumnMapping, blockHasRights, ref wf);
                        }

                        break;

                    default:
                        break;
                    }
                    break;

                default:
                    break;
                }

                // next item
                prevItem = item;
                item     = workflowRule.Connections.FirstOrDefault(c => c.SourceId == item.Id)?.Target;
            }

            // real block not set (TargetItem)
            if (rule.TargetBlock == null)
            {
                // continue to next virtual Block
                if (item != null && blockMapping.ContainsKey(item))
                {
                    rule.TargetBlock = blockMapping[item];
                }
                // return to origin real Block
                else
                {
                    rule.TargetBlock = nonVirtualBlock;
                }
            }

            return(rule);
        }
예제 #2
0
        private void saveWFRule(TapestryDesignerWorkflowRule workflowRule, Block block, WorkFlow wf, Dictionary <int, string> stateColumnMapping)
        {
            HashSet <TapestryDesignerWorkflowConnection>       todoConnections  = new HashSet <TapestryDesignerWorkflowConnection>();
            Dictionary <TapestryDesignerWorkflowItem, Block>   BlockMapping     = new Dictionary <TapestryDesignerWorkflowItem, Block>();
            Dictionary <Block, TapestryDesignerConditionGroup> conditionMapping = new Dictionary <Block, TapestryDesignerConditionGroup>();
            HashSet <Block> blockHasRights = new HashSet <Block> {
                block
            };

            // create virtual starting items
            TapestryDesignerWorkflowItem virtualBeginItem = new TapestryDesignerWorkflowItem();

            BlockMapping.Add(virtualBeginItem, block);
            foreach (TapestryDesignerWorkflowItem item in _masterContext.TapestryDesignerWorkflowItems.Where(i => i.ParentSwimlane.ParentWorkflowRule.Id == workflowRule.Id && (i.TypeClass == "uiItem" || i.SymbolType == "circle-single" || i.SymbolType == "envelope-start" || i.SymbolType == "circle-event")))
            {
                TapestryDesignerWorkflowConnection conn = new TapestryDesignerWorkflowConnection
                {
                    Source = virtualBeginItem,
                    Target = item
                };

                todoConnections.Add(conn);
            }

            //
            var splitItems = _masterContext.TapestryDesignerWorkflowItems.Where(i => i.ParentSwimlane.ParentWorkflowRule_Id == workflowRule.Id && i.TypeClass == "symbol" && _splitGateways.Contains(i.SymbolType) && (i.ParentForeach == null || i.SymbolType == "foreach")).ToList();
            var joinItems  = _masterContext.TapestryDesignerWorkflowItems.Where(i => i.ParentSwimlane.ParentWorkflowRule_Id == workflowRule.Id && i.TargetToConnection.Count() > 1 && (i.ParentForeach == null || i.SymbolType == "foreach")).ToList();

            foreach (var splitItem in splitItems)
            {
                // block mapping
                int   random   = _random.Next() % 1000000;
                Block newBlock = new Block
                {
                    Name                = $"split_{block.Name}_{random}",
                    DisplayName         = $"split[{block.Name}_{random}]",
                    ModelName           = block.ModelName,
                    IsVirtualForBlockId = block.Id
                };
                wf.Blocks.Add(newBlock);
                BlockMapping.Add(splitItem, newBlock);

                // conditions
                if (splitItem.SymbolType == "gateway-x")
                {
                    try
                    {
                        conditionMapping.Add(newBlock, splitItem.ConditionGroups.Single());
                    }
                    catch (InvalidOperationException ex)
                    {
                        throw new Exception("Gateway has no condition!", ex);
                    }
                }

                // rights
                if (checkBlockHasRights(splitItem))
                {
                    blockHasRights.Add(newBlock);
                }

                // todo connection
                int connectionCount = splitItem.SourceToConnection.Count;
                if (connectionCount == 0) // wrong WF
                {
                    throw new Exception($"Workflow ends with gateway - {block.Name}: {workflowRule.Name}");
                }
                if (connectionCount == 1) // missing way - return to real Block
                {
                    TapestryDesignerWorkflowConnection connection = splitItem.SourceToConnection.FirstOrDefault();
                    todoConnections.Add(connection);
                    todoConnections.Add(new TapestryDesignerWorkflowConnection {
                        SourceSlot = connection.SourceSlot == 0 ? 1 : 0, Source = splitItem
                    });
                }
                else // OK
                {
                    foreach (TapestryDesignerWorkflowConnection connection in splitItem.SourceToConnection)
                    {
                        todoConnections.Add(connection);
                    }
                }
            }

            foreach (var joinItem in joinItems)
            {
                if (BlockMapping.ContainsKey(joinItem)) // split item & join item are same
                {
                    continue;
                }

                // block mapping
                int   random   = _random.Next() % 1000000;
                Block newBlock = new Block
                {
                    Name                = $"join_{block.Name}_{random}",
                    DisplayName         = $"join[{block.Name}_{random}]",
                    ModelName           = block.ModelName,
                    IsVirtualForBlockId = block.Id
                };
                wf.Blocks.Add(newBlock);
                BlockMapping.Add(joinItem, newBlock);

                // todo connection
                todoConnections.Add(new TapestryDesignerWorkflowConnection {
                    Source = joinItem, Target = joinItem
                });
            }

            //// ACTIONS ////
            foreach (TapestryDesignerWorkflowConnection connection in todoConnections)
            {
                createActionRule(workflowRule, block, BlockMapping[connection.Source], connection, ref BlockMapping, conditionMapping, stateColumnMapping, blockHasRights, ref wf);
            }
        }