Exemplo n.º 1
0
        private void DrainWorkflowRule(CodeBuilder result, TapestryDesignerWorkflowRule workflowRule)
        {
            /// INIT
            IEnumerable <TapestryDesignerWorkflowItem> startingItems = _context.TapestryDesignerWorkflowItems.Where(i => i.ParentSwimlane.ParentWorkflowRule.Id == workflowRule.Id && (i.TypeClass == "uiItem" || i.SymbolType == "circle-single" || i.SymbolType == "envelope-start" || i.SymbolType == "circle-event"));

            // swimlane has starting item
            if (startingItems.Count() != workflowRule.Swimlanes.Count || startingItems.Select(wfi => wfi.ParentSwimlaneId).Except(workflowRule.Swimlanes.Select(sw => sw.Id)).Any())
            {
                throw new TapestrySyntacticOmniusException("Each swimlane requires one starting item!");
            }
            // starting item should be the same
            TapestryDesignerWorkflowItem defaultStartingItem = startingItems.FirstOrDefault();

            foreach (TapestryDesignerWorkflowItem item in startingItems)
            {
                if (item.SymbolType != defaultStartingItem.SymbolType ||
                    item.ComponentName != defaultStartingItem.ComponentName)
                {
                    throw new TapestrySyntacticOmniusException("Starting items has to be same for WorkflowRule");
                }
            }

            // method name
            _methodName = workflowRule.Name.ToUpper() == "INIT"
                ? Tapestry.MethodName(null)
                : Tapestry.MethodName(defaultStartingItem.ComponentName);

            /// start build
            result.AppendLine($"public {(_methodName == Tapestry.MethodName(null) ? "override " : "")}void {_methodName}(string[] userRoleNames, Action<int, Block> _symbolAction)");
            result.StartBlock();

            /// swimlanes
            bool firstSwimlane = true;

            foreach (TapestryDesignerSwimlane swimlane in workflowRule.Swimlanes)
            {
                // roles
                if (!firstSwimlane)
                {
                    result.Append("else ");
                }
                result.AppendLine($"if ({(string.IsNullOrEmpty(swimlane.Roles) ? "true" : string.Join("||", swimlane.Roles.Split(',').Select(r => $"userRoleNames.Contains(\"{r}\")")))})");
                result.StartBlock();

                /// WF
                (var item, int count) = DrainBranch(result, startingItems.Single(si => si.ParentSwimlaneId == swimlane.Id), BranchType.Method);
                if (item != null || count != 0)
                {
                    _progressHandler.Warning("WF ends too soon");
                }

                result.EndBlock(); // end if - roles
                firstSwimlane = false;
            }
            // has no required role
            result.AppendLine("else");
            result.AppendLine($"    throw new TapestryAuthenticationOmniusException(\"Authentication error\", \"{string.Join(",", workflowRule.Swimlanes.Select(sw => sw.Roles))}\" , string.Join(\",\", userRoleNames));");

            result.EndBlock(); // end method
        }
Exemplo n.º 2
0
        private string _dictToBuildString(TapestryDesignerWorkflowItem item, Dictionary <string, string> dictionary, MethodInfo method)
        {
            List <string> result = new List <string>();

            foreach (var pair in dictionary)
            {
                string resultValue = ForInput(item, pair.Key, pair.Value, method);
                if (resultValue != null)
                {
                    result.Add($"{{ {pair.Key}, {resultValue} }}");
                }
            }

            return($"new Dictionary<string, object> {{ {string.Join(",", result)}");
        }
Exemplo n.º 3
0
        public string ForInput(TapestryDesignerWorkflowItem item, string innerParamName, string paramName, MethodInfo method)
        {
            ParameterInfo originParam = method.GetParameters().SingleOrDefault(p => p.Name == innerParamName && !p.ParameterType.IsArray);

            if (originParam == null)
            {
                ParameterInfo arrayParam = method.GetParameters().SingleOrDefault(p => p.ParameterType.IsArray && Regex.Match(innerParamName, RegexIsArray(p.Name)).Success);
                if (arrayParam == null)
                {
                    _progressHandler.Warning($"[Block:{_currentBlockCommit.Name},WF:{_currentWFRule.Name},WFItemId:{item?.Id},Label:{item?.Label}] Method[{method.Name}] has no param[{innerParamName}], skipping...");
                    return(null);
                }
            }

            return(ForInput(paramName, originParam?.ParameterType));
        }
Exemplo n.º 4
0
        private bool checkBlockHasRights(TapestryDesignerWorkflowItem item)
        {
            List <TapestryDesignerWorkflowConnection> connections = item.SourceToConnection.ToList();

            if (connections.Count < 2)
            {
                return(false);
            }

            TapestryDesignerSwimlane originalSwimlane = item.ParentSwimlane;

            foreach (var connection in connections)
            {
                if (connection.Target.ParentSwimlane != originalSwimlane)
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
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);
            }
        }
Exemplo n.º 7
0
        private IEnumerable <string> transformInputParams(TapestryDesignerWorkflowItem item, string inputVariables, MethodInfo method)
        {
            /// parse
            Dictionary <string, string> pairs = new Dictionary <string, string>();
            List <string> split = inputVariables.Trim().Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List <string>();

            foreach (string pair in split)
            {
                string[] splittedPair = pair.Split('=');
                if (splittedPair.Length != 2)
                {
                    _progressHandler.Warning($"[Block:{_currentBlockCommit.Name},WF:{_currentWFRule.Name},WFItemId:{item.Id},Action:{method.Name}] WorkFlow item has incorrect InputVariables!");
                    continue;
                }

                string key   = splittedPair[0];
                string value = splittedPair[1];

                /// dict
                if (value.Length > 1 && value[1] != '$' && value.Contains("::"))
                {
                    var newDict  = new Dictionary <string, string>();
                    var newPairs = value.Split(',');
                    foreach (string newPair in newPairs)
                    {
                        var splitted = newPair.Split(':');
                        if (splitted.Length != 2)
                        {
                            _progressHandler.Warning($"[Block:{_currentBlockCommit.Name},WF:{_currentWFRule.Name},WFItemId:{item.Id},Action:{method.Name}] WorkFlow item has incorrect InputVariables for Dictionary!");
                            continue;
                        }

                        newDict.Add(splitted[0], splitted[1]);
                    }

                    // DBItem
                    if (method.GetParameters().Single(p => p.Name == key).ParameterType == typeof(Entitron.DB.DBItem))
                    {
                        value = $"new FSS.Omnius.Modules.Entitron.DB.DBItem(_core.Entitron, dict: {_dictToBuildString(item, newDict, method)})";
                    }
                    else
                    {
                        value = _dictToBuildString(item, newDict, method);
                    }
                }

                // key already exists
                if (pairs.ContainsKey(key))
                {
                    string realValue = ForInput(item, key, value, method);
                    if (pairs[key] == realValue)
                    {
                        _progressHandler.Warning($"[Block:{_currentBlockCommit.Name},WF:{_currentWFRule.Name},WFItemId:{item.Id},Name:{item.Label}] Item has variable '{key}' defined multiple times");
                        continue;
                    }
                    else
                    {
                        throw new TapestrySyntacticOmniusException($"Single variable has multiple values - WFItem[Id:{item.Id}, Name:{item.Label}, Value1:{pairs[key]}, Value2:{realValue}]");
                    }
                }

                // skip empty
                string resultParam = ForInput(item, key, value, method);
                if (resultParam != null)
                {
                    pairs.Add(key, resultParam);
                }
            }

            /// array
            // select params witch is array
            foreach (ParameterInfo param in method.GetParameters().Where(p => p.ParameterType.IsArray))
            {
                // param items
                var currentMatches = pairs.ToDictionary(pair => pair, pair => Regex.Match(pair.Key, RegexIsArray(param.Name))).Where(pair => pair.Value.Success);

                // count
                string[] list = currentMatches.Any()
                    ? new string[currentMatches.Max(p => Convert.ToInt32(p.Value.Groups[2].Value != "" ? p.Value.Groups[2].Value : "0") + 1)]
                    : new string[0];

                // fill list & remove from pairs
                foreach (var pair in currentMatches)
                {
                    list[Convert.ToInt32(pair.Value.Groups[2].Value != "" ? pair.Value.Groups[2].Value : "0")] = pair.Key.Value;
                    pairs.Remove(pair.Key.Key);
                }

                // add to pair
                pairs.Add(param.Name, $"new {param.ParameterType.Name} {{ {string.Join(",", list.Select(i => i != null ? (param.ParameterType.GetElementType() != typeof(object) ? $"Extend.ConvertTo<{_typeName(param.ParameterType.GetElementType())}>(_core, {i})" : i) : "null"))} }}");
            }

            /// return
            return(pairs.Select(pair => $"{pair.Key}:{pair.Value}"));
        }
Exemplo n.º 8
0
        private (TapestryDesignerWorkflowItem, int) DrainBranch(CodeBuilder result, TapestryDesignerWorkflowItem startItem, BranchType branchType)
        {
            /// INIT
            int branchGoesThrought = 1;
            TapestryDesignerWorkflowItem currentItem = startItem;

            /// foreach in branch
            while (currentItem != null)
            {
                try
                {
                    // join
                    int targetToCount = currentItem.TargetToConnection.Count(c => c.Source.TypeClass != "integrationItem" && c.Source.TypeClass != "templateItem");
                    if (targetToCount > branchGoesThrought)
                    {
                        return(currentItem, branchGoesThrought);
                    }
                    else
                    {
                        branchGoesThrought = 1;
                    }

                    // compile symbol
                    result.AppendLine($"_symbolAction({currentItem.Id}, this);");

                    // lock
                    if (currentItem.HasParallelLock)
                    {
                        result.AppendLine($"lock (_core.Lock({currentItem.Id}))");
                        result.StartBlock();
                    }

                    string inputVariables = currentItem.InputVariables ?? "";
                    switch (currentItem.TypeClass)
                    {
                    // action
                    // action with params
                    case "actionItem":
                        // params
                        var paramItem = currentItem.TargetToConnection.SingleOrDefault(c => c.Source.TypeClass == "integrationItem" || c.Source.TypeClass == "templateItem")?.Source;
                        if (paramItem != null)
                        {
                            switch (paramItem.TypeClass)
                            {
                            case "integrationItem":
                                inputVariables = $"{currentItem.InputVariables.Trim().TrimEnd(';')};WSName=s${paramItem.Label.Substring(4)}";         // remove 'WS: ' from beginning
                                break;

                            case "templateItem":
                                inputVariables = $"{currentItem.InputVariables.Trim().TrimEnd(';')};Template=s${paramItem.Label}";
                                break;

                            default:
                                throw new NotImplementedException();
                            }
                        }

                        // Action
                        if (!ActionManager.All.ContainsKey(currentItem.ActionId.Value))
                        {
                            throw new TapestrySyntacticOmniusException($"Action[Id:{currentItem.ActionId.Value},Name:{currentItem.Label}] not found");
                        }
                        TapestryAction action = ActionManager.All[currentItem.ActionId.Value];
                        result.AppendLine($"{ForOutput(currentItem.OutputVariables?.Trim(), action)}{action.Repository}.{action.Method.Name}(_core{string.Join("", transformInputParams(currentItem, inputVariables, action.Method).Select(p => $",{p}"))});");
                        break;

                    // target
                    case "targetItem":
                        result.AppendLine($"this.TargetName = \"{currentItem.Target.Name.RemoveDiacritics()}\";");
                        result.AppendLine("return;");
                        break;

                    // gw x
                    // gw +
                    case "symbol":
                        switch (currentItem.SymbolType)
                        {
                        case "gateway-x":
                            branchGoesThrought--;         // removes current
                            result.AppendLine($"if ({currentItem.ConditionGroups.SingleOrDefault()?.ToString(this) ?? "true"})");
                            result.StartBlock();
                            (var joinItem, int returnedBranchCount) = DrainBranch(result, currentItem.SourceToConnection.SingleOrDefault(c => c.SourceSlot == 0)?.Target, branchType);
                            branchGoesThrought += returnedBranchCount;         // add if
                            result.Else();
                            (currentItem, returnedBranchCount) = DrainBranch(result, currentItem.SourceToConnection.SingleOrDefault(c => c.SourceSlot == 1)?.Target, branchType);
                            branchGoesThrought += returnedBranchCount;         // add else
                            result.EndBlock();
                            // wrong syntactic - branch has to meet, if it not end
                            if (joinItem != null && currentItem != null && joinItem != currentItem)
                            {
                                throw new TapestrySyntacticOmniusException($"Gateway ends on different items[{joinItem.Id}:{joinItem.Label}, {currentItem.Id}:{currentItem.Label}]");
                            }
                            // 'else' ends with return -> continue with 'if'
                            if (currentItem == null)
                            {
                                currentItem = joinItem;
                            }
                            continue;

                        case "gateway-plus":
                            branchGoesThrought--;         // removes current
                            TapestryDesignerWorkflowItem gatewayItem = currentItem;
                            result.AppendLine($"_ParallelRun({gatewayItem.Id}, () => ThreadMethod_{gatewayItem.Id}(_symbolAction));");
                            (currentItem, returnedBranchCount) = DrainBranch(result, gatewayItem.SourceToConnection.Single(c => c.SourceSlot == 0).Target, branchType);
                            branchGoesThrought += returnedBranchCount;

                            _threadMethods.AppendLine($"private void ThreadMethod_{gatewayItem.Id}(Action<int, Block> _symbolAction)");
                            _threadMethods.StartBlock();
                            (joinItem, returnedBranchCount) = DrainBranch(_threadMethods, gatewayItem.SourceToConnection.Single(c => c.SourceSlot == 1).Target, BranchType.Method);
                            branchGoesThrought += returnedBranchCount;
                            _threadMethods.EndBlock();

                            // wrong syntactic - branch has to meet, if it not end
                            if (joinItem != null && currentItem != null && joinItem != currentItem)
                            {
                                throw new TapestrySyntacticOmniusException($"Gateway ends on different items[{joinItem.Id}:{joinItem.Label}, {currentItem.Id}:{currentItem.Label}]");
                            }

                            // merge
                            if (joinItem != null && currentItem != null)
                            {
                                result.AppendLine($"_WaitForParallel({gatewayItem.Id});");
                            }
                            continue;

                        case "circle-single":
                            // wf beginning
                            // DONE
                            break;
                        }
                        break;

                    case "stateItem":
                        break;

                    // foreach
                    case "virtualAction":
                        string itemName = currentItem.ParentForeach.ItemName ?? "__item__";
                        switch (currentItem.SymbolType)
                        {
                        case "foreach":
                            if (currentItem.ParentForeach.IsParallel)
                            {
                                result.AppendLine($"Parallel.ForEach((IEnumerable<dynamic>){_realGlobalVarName(currentItem.ParentForeach.DataSource)}, ({itemName}) => ");
                                result.StartBlock();
                                _varNames.Add("__item__");
                                DrainBranch(result, _context.TapestryDesignerWorkflowItems.Single(i => i.ParentForeachId == currentItem.ParentForeachId && i.IsForeachStart == true), BranchType.Method);
                                _varNames.Remove("__item__");
                                result.EndBlock(");");         // end foreach
                            }
                            else
                            {
                                result.AppendLine($"foreach (object {itemName} in (IEnumerable<dynamic>){_realGlobalVarName(currentItem.ParentForeach.DataSource)})");
                                result.StartBlock();
                                _varNames.Add(itemName);
                                DrainBranch(result, _context.TapestryDesignerWorkflowItems.Single(i => i.ParentForeachId == currentItem.ParentForeachId && i.IsForeachStart == true), BranchType.ForeachLoop);
                                _varNames.Remove(itemName);
                                result.EndBlock();         // end foreach
                            }
                            break;
                        }
                        break;


                    case "uiItem":          // button - wf beginning
                    case "integrationItem": // integration - param
                    case "templateItem":    // email template - param
                        break;

                    case "attributeItem":
                    case "circle-single":
                    default:
                        throw new NotImplementedException();
                    }

                    // lock
                    if (currentItem.HasParallelLock)
                    {
                        result.EndBlock();
                    }

                    /// next
                    // foreach
                    if (currentItem?.IsForeachEnd == true)
                    {
                        return(null, 0);
                    }

                    // ok
                    currentItem = currentItem?.SourceToConnection.SingleOrDefault()?.Target;
                }
                catch (Exception ex)
                {
                    throw new TapestrySyntacticOmniusException(ex.Message, currentItem?.Id, ex);
                }
            }

            /// END of thread, foreach or WF
            switch (branchType)
            {
            case BranchType.ForeachLoop:
                // compile end symbol
                result.AppendLine($"_symbolAction(-2, this);");
                // next
                result.AppendLine("continue;");
                break;

            case BranchType.Method:
                // compile end symbol
                result.AppendLine($"_symbolAction(-1, this);");
                // end
                result.AppendLine("return;");
                break;

            default:
                throw new Exception("Unknown branchType");
            }
            return(null, 0);
        }