Esempio n. 1
0
 /// <summary>
 /// Tests if a string is equal to at least one keyword associated with the specified step type.
 /// </summary>
 /// <param name="testString">The string to test.</param>
 /// <param name="stepType">The type specifying the patterns.</param>
 /// <returns>If at least one pattern for the step type matches to the test string.</returns>
 public static bool IsEqualsToAtLeastOnePatternOfStepType(this string testString, StepType stepType)
 {
     return(GraphBuilder.GetMatchingPatternForStepType(testString, stepType) != null);
 }
Esempio n. 2
0
        /// <summary>
        /// Wires an else/else if block. The block starts at <paramref name="stepIndex"/> in steps. The complete wiring is made and <paramref name="stepIndex"/> finally is set to the index of the end if step.
        /// The given lists/matrices are correctly updated.
        /// </summary>
        /// <param name="steps">See <paramref name="steps"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="edgeMatrix">See <paramref name="edgeMatrix"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="externalEdges">See <paramref name="externalEdges"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="possibleInvalidIfEdges">See <paramref name="possibleInvalidIfEdges"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="conditionMatrix">See <paramref name="conditionMatrix"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="stepIndex">On call the current index in the steps where the else/else if start step is located and after the call the index of the end if step.</param>
        public static void SetEdgesInElseElseIfStatement(
            IReadOnlyList <Node> steps,
            ref Matrix <bool> edgeMatrix,
            ref List <ExternalEdge> externalEdges,
            ref List <InternalEdge> possibleInvalidIfEdges,
            ref Matrix <Condition?> conditionMatrix,
            ref int stepIndex)
        {
            List <int> importantIfSteps = GraphBuilder.GetImportantIfStatementSteps(steps, stepIndex);

            // Handle nested blocks
            int lastBlockStartIndex = -1,
                endIfStepIndex      = importantIfSteps.Last();

            for (int blockIndex = 0; blockIndex < importantIfSteps.Count - 1; blockIndex++)
            {
                int blockStartIndex         = importantIfSteps[blockIndex],
                    blockEndIndex           = importantIfSteps[blockIndex + 1],
                    blockSize               = blockEndIndex - blockStartIndex - 1;
                StepType blockStartStepType = GraphBuilder.GetStepType(steps[blockStartIndex].StepDescription);

                // Set edge from last step to start of block
                if (blockIndex > 0)
                {
                    edgeMatrix[lastBlockStartIndex, blockStartIndex]      = true;
                    conditionMatrix[lastBlockStartIndex, blockStartIndex] = new Condition(steps[lastBlockStartIndex].StepDescription, false);
                }

                if (blockSize > 0)
                {
                    GraphBuilder.SetEdgesInNestedBlock(
                        steps,
                        ref edgeMatrix,
                        ref externalEdges,
                        ref possibleInvalidIfEdges,
                        ref conditionMatrix,
                        blockStartIndex,
                        blockEndIndex,
                        endIfStepIndex,
                        blockStartStepType == StepType.Else ? (Condition?)null : new Condition(steps[blockStartIndex].StepDescription, true));
                }
                else
                {
                    // Wire block start step to endif step
                    edgeMatrix[blockStartIndex, endIfStepIndex] = true;
                }

                lastBlockStartIndex = blockStartIndex;
            }

            // If last block is not a else block make an edge from the block start with false conditon to end if step.
            lastBlockStartIndex = importantIfSteps[importantIfSteps.Count - 2];
            int lastBlockEndIndex           = importantIfSteps[importantIfSteps.Count - 1],
                lastBlockSize               = lastBlockEndIndex - lastBlockStartIndex - 1;
            StepType lastBlockStartStepType = GraphBuilder.GetStepType(steps[lastBlockStartIndex].StepDescription);

            if (lastBlockStartStepType != StepType.Else && lastBlockSize > 0)
            {
                edgeMatrix[lastBlockStartIndex, lastBlockEndIndex]      = true;
                conditionMatrix[lastBlockStartIndex, lastBlockEndIndex] = new Condition(steps[lastBlockStartIndex].StepDescription, false);
            }

            // Set current step index to end if step.
            stepIndex = endIfStepIndex;
        }
Esempio n. 3
0
        /// <summary>
        /// Builds the graph.
        /// </summary>
        /// <param name="basicFlow">The basic flow. It will be extended with a step, with an empty description, if the last step is a validates that or until step so that the condition does not get lost.</param>
        /// <param name="specificAlternativeFlowsUnnormalized">The specific alternative flows. Reference steps starting with 1.</param>
        /// <param name="globalAlternativeFlows">The global alternative flows.</param>
        /// <param name="boundedAlternativeFlowsUnnormalized">The bounded alternative flows. Reference steps starting with 1.</param>
        /// <param name="steps">The steps of all flows.</param>
        /// <param name="edgeMatrix">The edge matrix for the steps.</param>
        /// <param name="conditionMatrix">The condition matrix for the flows.</param>
        public static void BuildGraph(
            ref Flow basicFlow,
            IReadOnlyList <Flow> specificAlternativeFlowsUnnormalized,
            IReadOnlyList <Flow> globalAlternativeFlows,
            IReadOnlyList <Flow> boundedAlternativeFlowsUnnormalized,
            out List <Node> steps,
            out Matrix <bool> edgeMatrix,
            out Matrix <Condition?> conditionMatrix)
        {
            basicFlow = GraphBuilder.ExtendBasicFlowIfNecessary(basicFlow);

            IReadOnlyList <Flow> specificAlternativeFlows = GraphBuilder.NormalizeReferenceSteps(specificAlternativeFlowsUnnormalized);
            IReadOnlyList <Flow> boundedAlternativeFlows  = GraphBuilder.NormalizeReferenceSteps(boundedAlternativeFlowsUnnormalized);

            steps = new List <Node>();
            List <Flow> allFlows = new List <Flow>();

            allFlows.Add(basicFlow);
            allFlows.AddRange(specificAlternativeFlows);
            allFlows.AddRange(globalAlternativeFlows);
            allFlows.AddRange(boundedAlternativeFlows);

            // Wire all flows individually. The tuples have as item 1 the offset for the steps list and edge matrix and then all out parameters of SetEdgesInStepBlock.
            List <Tuple <int, Flow, Matrix <bool>, List <ExternalEdge>, List <InternalEdge>, List <Tuple <int, Condition?> >, Matrix <Condition?> > > individuallyWiredFlows =
                GraphBuilder.WireFlowListIndividually(allFlows, 0);

            // Collect all steps in the steps list
            foreach (Flow flow in allFlows)
            {
                steps.AddRange(flow.Nodes);
            }

            // Copy each flows edge/condition matrix into the global one
            edgeMatrix      = new Matrix <bool>(steps.Count, false);
            conditionMatrix = new Matrix <Condition?>(steps.Count, null);

            foreach (Tuple <int, Flow, Matrix <bool>, List <ExternalEdge>, List <InternalEdge>, List <Tuple <int, Condition?> >, Matrix <Condition?> > individuallyWiredFlow in individuallyWiredFlows)
            {
                GraphBuilder.InsertMatrix(ref edgeMatrix, individuallyWiredFlow.Item1, individuallyWiredFlow.Item1, individuallyWiredFlow.Item3);
                GraphBuilder.InsertMatrix(ref conditionMatrix, individuallyWiredFlow.Item1, individuallyWiredFlow.Item1, individuallyWiredFlow.Item7);
            }

            // Wire external edges.
            foreach (Tuple <int, Flow, Matrix <bool>, List <ExternalEdge>, List <InternalEdge>, List <Tuple <int, Condition?> >, Matrix <Condition?> > individuallyWiredFlow in individuallyWiredFlows)
            {
                List <ExternalEdge> externalEdges = individuallyWiredFlow.Item4;

                foreach (ExternalEdge externalEdge in externalEdges)
                {
                    // Get offset of target flow.
                    FlowIdentifier targetIdentifier = externalEdge.TargetStep.Identifier;

                    List <Tuple <int, Flow, Matrix <bool>, List <ExternalEdge>, List <InternalEdge>, List <Tuple <int, Condition?> >, Matrix <Condition?> > > targetFlow =
                        individuallyWiredFlows.Where((iwf) => iwf.Item2.Identifier.Equals(targetIdentifier)).ToList();

                    int targetFlowOffset = targetFlow[0].Item1,
                        targetStep       = targetFlowOffset + externalEdge.TargetStep.Step,
                        sourceStep       = individuallyWiredFlow.Item1 + externalEdge.SourceStepNumber;

                    edgeMatrix[sourceStep, targetStep] = true;
                }
            }

            // Wire alternative flows reference steps
            foreach (Tuple <int, Flow, Matrix <bool>, List <ExternalEdge>, List <InternalEdge>, List <Tuple <int, Condition?> >, Matrix <Condition?> > individuallyWiredFlow in individuallyWiredFlows)
            {
                Flow     flow       = individuallyWiredFlow.Item2;
                FlowType flowType   = flow.Identifier.Type;
                int      flowOffset = individuallyWiredFlow.Item1;

                switch (flowType)
                {
                case FlowType.Basic:
                    // Does not have reference steps.
                    break;

                case FlowType.SpecificAlternative:
                case FlowType.BoundedAlternative:
                    // The flow can be entered only at the first step or at multiple ones if it is an outsourced elseif-else statement.
                    int targetStep = flowOffset;

                    foreach (ReferenceStep referenceStep in flow.ReferenceSteps)
                    {
                        FlowIdentifier sourceIdentifier = referenceStep.Identifier;

                        List <Tuple <int, Flow, Matrix <bool>, List <ExternalEdge>, List <InternalEdge>, List <Tuple <int, Condition?> >, Matrix <Condition?> > > sourceFlow =
                            individuallyWiredFlows.Where((iwf) => iwf.Item2.Identifier.Equals(sourceIdentifier)).ToList();

                        int sourceFlowOffset = sourceFlow[0].Item1;

                        int sourceStep = sourceFlowOffset + referenceStep.Step;

                        // Remove possible invalid if edge if present
                        List <InternalEdge> invalidIfEdges = sourceFlow[0].Item5.Where((piie) => piie.SourceStep == referenceStep.Step).ToList();
                        foreach (InternalEdge invalidIfEdge in invalidIfEdges)
                        {
                            int invalidTargetStep = sourceFlowOffset + invalidIfEdge.TargetStep;

                            // If the block is empty than the edges for fulfilled and not fulfilled condition are the same.
                            // In that case the invalid edge does not have a condition and thus its condition must be set to the fulfilled condition of the if/else if statement step.
                            if (conditionMatrix[sourceStep, invalidTargetStep] != null)
                            {
                                conditionMatrix[sourceStep, invalidTargetStep] = null;
                                edgeMatrix[sourceStep, invalidTargetStep]      = false;
                            }
                            else
                            {
                                conditionMatrix[sourceStep, invalidTargetStep] = new Condition(steps[sourceStep].StepDescription, true);
                            }
                        }

                        edgeMatrix[sourceStep, targetStep]      = true;
                        conditionMatrix[sourceStep, targetStep] = new Condition(steps[sourceStep].StepDescription, false);
                    }

                    break;

                case FlowType.GlobalAlternative:
                    // Gets an edge from every step of the basic flow.
                    // Basic flow is always at offset 0.
                    for (int sourceStep = 0; sourceStep < basicFlow.Nodes.Count; sourceStep++)
                    {
                        edgeMatrix[sourceStep, flowOffset]      = true;
                        conditionMatrix[sourceStep, flowOffset] = new Condition(individuallyWiredFlow.Item2.Nodes[0].StepDescription, true);
                    }

                    break;
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Wires an if block. The if block starts at <paramref name="stepIndex"/> in steps. The complete wiring is made and <paramref name="stepIndex"/> finally is set to the index of the end if step.
        /// The given lists/matrices are correctly updated.
        /// <para/>
        /// To visualize what is assumed a block if talking about it:
        /// <para/>
        /// IF
        /// <para/>
        /// Nested block step
        /// <para/>
        /// ELSE
        /// </summary>
        /// <param name="steps">See <paramref name="steps"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="edgeMatrix">See <paramref name="edgeMatrix"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="externalEdges">See <paramref name="externalEdges"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="possibleInvalidIfEdges">See <paramref name="possibleInvalidIfEdges"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="conditionMatrix">See <paramref name="conditionMatrix"/> in <see cref="SetEdgesInstepBlock"/>.</param>
        /// <param name="stepIndex">On call the current index in the steps where the if start step is located and after the call the index of the end if step.</param>
        public static void SetEdgesInIfStatement(
            IReadOnlyList <Node> steps,
            ref Matrix <bool> edgeMatrix,
            ref List <ExternalEdge> externalEdges,
            ref List <InternalEdge> possibleInvalidIfEdges,
            ref Matrix <Condition?> conditionMatrix,
            ref int stepIndex)
        {
            List <int> importantIfSteps = GraphBuilder.GetImportantIfStatementSteps(steps, stepIndex);

            // Handle nested blocks
            int ifStepIndex         = importantIfSteps.First(),
                lastBlockStartIndex = -1,
                endIfStepIndex      = importantIfSteps.Last();

            for (int blockIndex = 0; blockIndex < importantIfSteps.Count - 1; blockIndex++)
            {
                int blockStartIndex         = importantIfSteps[blockIndex],
                    blockEndIndex           = importantIfSteps[blockIndex + 1],
                    blockSize               = blockEndIndex - blockStartIndex - 1;
                StepType blockStartStepType = GraphBuilder.GetStepType(steps[blockStartIndex].StepDescription);

                // Set edge from last step to start of block
                if (blockIndex > 0)
                {
                    edgeMatrix[lastBlockStartIndex, blockStartIndex]      = true;
                    conditionMatrix[lastBlockStartIndex, blockStartIndex] = new Condition(steps[lastBlockStartIndex].StepDescription, false);
                }

                if (blockSize > 0)
                {
                    GraphBuilder.SetEdgesInNestedBlock(
                        steps,
                        ref edgeMatrix,
                        ref externalEdges,
                        ref possibleInvalidIfEdges,
                        ref conditionMatrix,
                        blockStartIndex,
                        blockEndIndex,
                        endIfStepIndex,
                        blockStartStepType == StepType.Else ? (Condition?)null : new Condition(steps[blockStartIndex].StepDescription, true));
                }
                else
                {
                    // Wire block start step to endif step
                    edgeMatrix[blockStartIndex, endIfStepIndex] = true;

                    // If it is not the last block then the edge to the end if has a condition
                    if (blockIndex < importantIfSteps.Count - 2)
                    {
                        conditionMatrix[blockStartIndex, endIfStepIndex] = new Condition(steps[blockStartIndex].StepDescription, true);
                    }
                }

                lastBlockStartIndex = blockStartIndex;
            }

            // If last block is not a else block make an edge from the block start with false conditon to end if step.
            lastBlockStartIndex = importantIfSteps[importantIfSteps.Count - 2];
            int lastBlockEndIndex           = importantIfSteps[importantIfSteps.Count - 1],
                lastBlockSize               = lastBlockEndIndex - lastBlockStartIndex - 1;
            StepType lastBlockStartStepType = GraphBuilder.GetStepType(steps[lastBlockStartIndex].StepDescription);

            if (lastBlockStartStepType != StepType.Else && lastBlockSize > 0)
            {
                edgeMatrix[lastBlockStartIndex, lastBlockEndIndex]      = true;
                conditionMatrix[lastBlockStartIndex, lastBlockEndIndex] = new Condition(steps[lastBlockStartIndex].StepDescription, false);
            }

            // If there are no else if or else blocks it might be that they are located in alternative flows or that there are none.
            // List that edge as possible invalid as it was previously created.
            if (importantIfSteps.Count <= 2)
            {
                possibleInvalidIfEdges.Add(new InternalEdge(ifStepIndex, endIfStepIndex));
            }

            // Set current step index to end if step.
            stepIndex = endIfStepIndex;
        }
Esempio n. 5
0
        /// <summary>
        /// Sets the edges in a block of steps.
        /// </summary>
        /// <param name="steps">The steps to wire.</param>
        /// <param name="edgeMatrix">The matrix with the edges for the given steps.</param>
        /// <param name="externalEdges">A list of edges whose target is located outside the given steps.</param>
        /// <param name="possibleInvalidIfEdges">A list of edges between the given steps that may be invalid, because they represent an edge for an if statement without an else statement in this step list for the case the condition is false. These edge may be invalid if the else/else if is located in another block of steps/alternative flow.</param>
        /// <param name="exitSteps">A list of steps of the given block that whose edges lead out of the block to the next step of the outer block, with optional condition if not null. These are not abort edges!</param>
        /// <param name="conditionMatrix">A matrix that holds the conditions for edges. If a edge has a condition for being taken then its corresponding edge in the condition matrix holds the condition.</param>
        public static void SetEdgesInStepBlock(
            IReadOnlyList <Node> steps,
            out Matrix <bool> edgeMatrix,
            out List <ExternalEdge> externalEdges,
            out List <InternalEdge> possibleInvalidIfEdges,
            out List <Tuple <int, Condition?> > exitSteps,
            out Matrix <Condition?> conditionMatrix)
        {
            // Initialize out varibles
            edgeMatrix             = new Matrix <bool>(steps.Count, false);
            externalEdges          = new List <ExternalEdge>();
            possibleInvalidIfEdges = new List <InternalEdge>();
            exitSteps       = new List <Tuple <int, Condition?> >();
            conditionMatrix = new Matrix <Condition?>(steps.Count, null);

            // Cycle through all steps and handle their edges.
            int lastStepIndex = -1;

            // If this is not null then the last step had a condition to continue and therefor provides it that way. Used for do-until statements.
            Condition?conditionFromPreviousStep = null;

            for (int stepIndex = 0; stepIndex < steps.Count; stepIndex++)
            {
                if (lastStepIndex >= stepIndex)
                {
                    throw new Exception("Invalid graph description!");
                }

                lastStepIndex = stepIndex;

                string   stepDescription = steps[stepIndex].StepDescription;
                StepType stepType        = GraphBuilder.GetStepType(stepDescription);

                if (stepType == StepType.If)
                {
                    GraphBuilder.SetEdgesInIfStatement(steps, ref edgeMatrix, ref externalEdges, ref possibleInvalidIfEdges, ref conditionMatrix, ref stepIndex);

                    // Revert the step index by one to one position before the end if so that in the next cycle it points to the end if step.
                    stepIndex--;
                }
                else if (stepType == StepType.Else || stepType == StepType.ElseIf)
                {
                    GraphBuilder.SetEdgesInElseElseIfStatement(steps, ref edgeMatrix, ref externalEdges, ref possibleInvalidIfEdges, ref conditionMatrix, ref stepIndex);

                    // Revert the step index by one to one position beofre the end if so that in the next cycle it points to the end if step.
                    stepIndex--;
                }
                else if (stepType == StepType.Do)
                {
                    GraphBuilder.SetEdgesInDoUntilStatement(steps, ref edgeMatrix, ref externalEdges, ref possibleInvalidIfEdges, ref conditionMatrix, ref stepIndex, out conditionFromPreviousStep);

                    // Revert the step index by one to one position beofre the until so that in the next cycle it points to the until step.
                    stepIndex--;
                }
                else if (stepType == StepType.Resume)
                {
                    externalEdges.Add(GraphBuilder.GetExternalEdgeForResumeStep(stepDescription, stepIndex));
                    break;
                }
                else if (stepType == StepType.Abort)
                {
                    break;
                }
                else if (stepType == StepType.ValidatesThat)
                {
                    if (stepIndex < (steps.Count - 1))
                    {
                        // Not the last step.
                        edgeMatrix[stepIndex, stepIndex + 1]      = true;
                        conditionMatrix[stepIndex, stepIndex + 1] = new Condition(stepDescription, true);
                    }
                    else
                    {
                        // The last step.
                        exitSteps.Add(new Tuple <int, Condition?>(stepIndex, new Condition(stepDescription, true)));
                    }
                }
                else
                {
                    // Treat it as a normal/unmatched step
                    if (stepIndex < (steps.Count - 1))
                    {
                        // Not the last step.
                        edgeMatrix[stepIndex, stepIndex + 1]      = true;
                        conditionMatrix[stepIndex, stepIndex + 1] = conditionFromPreviousStep;
                    }
                    else
                    {
                        // The last step.
                        exitSteps.Add(new Tuple <int, Condition?>(stepIndex, conditionFromPreviousStep));
                    }

                    conditionFromPreviousStep = null;
                }
            }
        }