示例#1
0
        /// <summary>
        /// Searches the important steps in an if statement starting in <paramref name="steps"/> at index <paramref name="startStep"/>.
        /// The important steps are if, else if, else and end if. The given <paramref name="startStep"/> is assumed a valid if statement step and added automatically to the start of the list.
        /// It ends with the first end if that does not belong to a nested if statement.
        /// </summary>
        /// <param name="steps">The steps containing the if statement.</param>
        /// <param name="startStep">The index of the step in <paramref name="steps"/> where to start the search. Must be an if, else if, else step!</param>
        /// <returns>The indices of the important steps. Index 0 is the <paramref name="startStep"/> and the following are else if and else steps and an end if step as last index.</returns>
        public static List <int> GetImportantIfStatementSteps(IReadOnlyList <Node> steps, int startStep)
        {
            List <int> importantSteps = new List <int>();

            importantSteps.Add(startStep);

            // If this number is greater than 0 the index is currently in a nested if of the given depth.
            int numberNestedIfStatements = 0;

            for (int stepIndex = startStep + 1; stepIndex < steps.Count; stepIndex++)
            {
                StepType stepType = GraphBuilder.GetStepType(steps[stepIndex].StepDescription);

                if (stepType == StepType.If)
                {
                    numberNestedIfStatements++;
                    continue;
                }

                if (numberNestedIfStatements > 0)
                {
                    // In nested if statement.
                    if (stepType == StepType.EndIf)
                    {
                        numberNestedIfStatements--;
                    }
                }
                else
                {
                    // In root if statment.
                    if (stepType == StepType.ElseIf || stepType == StepType.Else || stepType == StepType.EndIf)
                    {
                        importantSteps.Add(stepIndex);
                    }

                    if (stepType == StepType.EndIf)
                    {
                        break;
                    }
                }
            }

            return(importantSteps);
        }
示例#2
0
        /// <summary>
        /// Extends the basic flow with a step at the end if it ends with a validates that or until step.
        /// This is because otherwise that last condition would get lost.
        /// The added step will have an empty string as description.
        /// </summary>
        /// <param name="basicFlow">The basic flow to check the last step of.</param>
        /// <returns>The extended basic flow like described above.</returns>
        public static Flow ExtendBasicFlowIfNecessary(Flow basicFlow)
        {
            StepType lastStepType = GraphBuilder.GetStepType(basicFlow.Nodes.LastOrDefault().StepDescription ?? string.Empty);

            if (lastStepType == StepType.Until || lastStepType == StepType.ValidatesThat)
            {
                List <Node> extendedNodes = new List <Node>();
                extendedNodes.AddRange(basicFlow.Nodes);
                extendedNodes.Add(new Node(string.Empty, basicFlow.Identifier));

                return(new Flow(
                           basicFlow.Identifier,
                           basicFlow.Postcondition,
                           extendedNodes,
                           basicFlow.ReferenceSteps));
            }

            return(basicFlow);
        }
示例#3
0
        /// <summary>
        /// Searches the important steps in an do-until statement starting in <paramref name="steps"/> at index <paramref name="startStep"/>.
        /// The important steps are do and until. The given <paramref name="startStep"/> is assumed a valid do statement step and added automatically to the start of the list.
        /// It ends with the first until that does not belong to a nested do-until statement.
        /// </summary>
        /// <param name="steps">The steps containing the do-until statement.</param>
        /// <param name="startStep">The index of the step in <paramref name="steps"/> where to start the search. Must be a do step!</param>
        /// <returns>The indices of the important steps. Item 1 is the do step index and item 2 the until step index.</returns>
        public static Tuple <int, int> GetImportantDoUntilStatementSteps(IReadOnlyList <Node> steps, int startStep)
        {
            // If this number is greater than 0 the index is currently in a nested do-until of the given depth.
            int numberNestedDoUntilStatements = 0,
                endStep = -1;

            for (int stepIndex = startStep + 1; stepIndex < steps.Count; stepIndex++)
            {
                StepType stepType = GraphBuilder.GetStepType(steps[stepIndex].StepDescription);

                if (stepType == StepType.Do)
                {
                    numberNestedDoUntilStatements++;
                    continue;
                }

                if (numberNestedDoUntilStatements > 0)
                {
                    // In nested if statement.
                    if (stepType == StepType.Until)
                    {
                        numberNestedDoUntilStatements--;
                    }
                }
                else
                {
                    // In root if statment.
                    if (stepType == StepType.Until)
                    {
                        endStep = stepIndex;
                        break;
                    }
                }
            }

            return(new Tuple <int, int>(startStep, endStep));
        }
示例#4
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;
        }
示例#5
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;
        }
示例#6
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;
                }
            }
        }