Beispiel #1
0
        // this function fills the rest of the graph with random nodes
        private void fillNodesRecursively(NodeObject currentNode, List<int> currentPosition, int currentDepth, int maxDepth, List<PossibleNode> allPossibleNodes, ValidGraphPath[] validPaths) {

            // check if the maximal depth is reached
            if (currentDepth >= maxDepth) {
                return;
            }

            // fill all missing nodes of the current object with new random nodes
            for (int idx = 0; idx < currentNode.dimension; idx++) {

                // copy position list and add path index to the position 
                List<int> tempCurrentPosition = new List<int>(currentPosition);
                tempCurrentPosition.Add(idx);

                if (currentNode.nodeObjects[idx] == null) {

                    // get random possible node from list of all possible nodes
                    int randElement = this.prng.Next(allPossibleNodes.Count);
                    PossibleNode possibleNode = allPossibleNodes.ElementAt(randElement);
                    NamespaceTypeDefinition classToUse = possibleNode.givenClass;
                    MethodDefinition nodeConstructor = possibleNode.nodeConstructor;

                    // generate path element from chosen interface
                    PathElement pathElement = new PathElement();

                    // create new node object
                    currentNode.nodeObjects[idx] = new NodeObject(this.graphDimension, this.graphValidPathCount, classToUse, nodeConstructor, pathElement, tempCurrentPosition);


                    // search through every valid path if the new created filler node has the same attributes as the valid path node
                    // => add it to the list of possible nodes that can be used for an exchange between valid node and filler node
                    for (int validPathId = 0; validPathId < validPaths.Count(); validPathId++) {
                        for (int depth = 0; depth < validPaths[validPathId].pathElements.Count(); depth++) {

                            // check if the used class of the current filler node is in the list of possible classes of the valid path node
                            if (validPaths[validPathId].pathElements.ElementAt(depth).linkGraphObject.possibleClasses.Contains(classToUse)) {

                                // add current filler node to the list of possible exchange nodes
                                if (!validPaths[validPathId].pathElements.ElementAt(depth).linkGraphObject.possibleExchangeObjects.Contains(currentNode.nodeObjects[idx])) {
                                    validPaths[validPathId].pathElements.ElementAt(depth).linkGraphObject.possibleExchangeObjects.Add(currentNode.nodeObjects[idx]);
                                }
                            }
                        }
                    }

                }

                this.fillNodesRecursively(currentNode.nodeObjects[idx], tempCurrentPosition, currentDepth + 1, maxDepth, allPossibleNodes, validPaths);

            }
        }
Beispiel #2
0
        // dumps the rest of the graph recursively
        // IMPORTANT: will crash if a loop exists in the graph
        private void dumpGraphRecursively(System.IO.StreamWriter dotFile, NodeObject currentNode, String nodeName, bool dumpOnlyValidPath) {

            // write current node to file but only the valid path
            if (dumpOnlyValidPath) {

                if (currentNode.elementOfValidPath.Count() == 0) {
                    return;
                }

                dotFile.WriteLine(nodeName + " [shape=record]");

                dotFile.Write(nodeName + " [label=\"{");
                dotFile.Write("Node: " + nodeName + "|");
                dotFile.Write("Class: " + this.sanitizeString(currentNode.thisClass.ToString()) + "|");

                String tempOutput = "";
                foreach (PathElement pathElement in currentNode.pathElements) {

                    tempOutput = "";
                    foreach (ITypeReference interfaceInList in pathElement.validInterfaces) {
                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                    }
                    dotFile.Write("valid Interfaces (valid ID: " + pathElement.validPathId.ToString() + "): " + tempOutput + "|");

                    tempOutput = "";
                    foreach (ITypeReference interfaceInList in pathElement.invalidInterfaces) {
                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                    }
                    dotFile.Write("invalid Interfaces (valid ID: " + pathElement.validPathId.ToString() + "): " + tempOutput + "|");

                }

                dotFile.Write("Constructor: " + this.makeFuncSigString(currentNode.constructorToUse) + "|");

                tempOutput = "";
                foreach (ITypeReference interfaceInList in currentNode.pathElements.ElementAt(0).mandatoryInterfaces) {
                    tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                }
                dotFile.Write("mandatory Interfaces: " + tempOutput + "|");

                tempOutput = "";
                foreach (ITypeReference interfaceInList in currentNode.pathElements.ElementAt(0).forbiddenInterfaces) {
                    tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                }
                dotFile.Write("forbidden Interfaces: " + tempOutput + "|");

                tempOutput = "";
                foreach (NamespaceTypeDefinition classInList in currentNode.possibleClasses) {
                    tempOutput += this.sanitizeString(classInList.ToString()) + "; ";
                }
                dotFile.Write("possible Classes: " + tempOutput + "|");

                String positionString = "";
                foreach (int position in currentNode.positionInGraph) {
                    positionString += position.ToString() + ";";
                }
                dotFile.Write("Position: " + positionString + "|");

                positionString = "";
                foreach (NodeObject possibleNode in currentNode.possibleExchangeObjects) {
                    positionString += "(";
                    foreach (int position in possibleNode.positionInGraph) {
                        positionString += position.ToString() + ";";
                    }
                    positionString += ") ";
                }
                dotFile.Write("Possible exchange nodes: " + positionString + "|");

                String validPathIdString = "";
                foreach (int validPathId in currentNode.elementOfValidPath) {
                    validPathIdString += validPathId.ToString() + ";";
                }
                dotFile.Write("Valid Path Ids: " + validPathIdString);

                dotFile.WriteLine("}\"]");

                for (int idx = 0; idx < currentNode.dimension; idx++) {

                    // check if the tree is a complete tree
                    if (currentNode.nodeObjects[idx] == null) {
                        continue;
                    }

                    if (currentNode.nodeObjects[idx].elementOfValidPath.Count() != 0) {
                        dotFile.WriteLine(nodeName + "-> " + nodeName + "_" + idx.ToString() + "[ color=\"green\" ]");

                        // dump rest of the graph recursively
                        this.dumpGraphRecursively(dotFile, currentNode.nodeObjects[idx], nodeName + "_" + idx.ToString(), true);
                    }
                }
            }

            // write current node to file with the whole graph
            else {

                dotFile.WriteLine(nodeName + " [shape=record]");

                dotFile.Write(nodeName + " [label=\"{");
                dotFile.Write("Node: " + nodeName + "|");
                dotFile.Write("Class: " + this.sanitizeString(currentNode.thisClass.ToString()) + "|");

                String tempOutput = "";
                foreach (PathElement pathElement in currentNode.pathElements) {

                    tempOutput = "";
                    foreach (ITypeReference interfaceInList in pathElement.validInterfaces) {
                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                    }
                    dotFile.Write("valid Interfaces (valid ID: " + pathElement.validPathId.ToString() + "): " + tempOutput + "|");

                    tempOutput = "";
                    foreach (ITypeReference interfaceInList in pathElement.invalidInterfaces) {
                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                    }
                    dotFile.Write("invalid Interfaces (valid ID: " + pathElement.validPathId.ToString() + "): " + tempOutput + "|");

                }

                dotFile.Write("Constructor: " + this.makeFuncSigString(currentNode.constructorToUse) + "|");

                tempOutput = "";
                foreach (ITypeReference interfaceInList in currentNode.pathElements.ElementAt(0).mandatoryInterfaces) {
                    tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                }
                dotFile.Write("mandatory Interfaces: " + tempOutput + "|");

                tempOutput = "";
                foreach (ITypeReference interfaceInList in currentNode.pathElements.ElementAt(0).forbiddenInterfaces) {
                    tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                }
                dotFile.Write("forbidden Interfaces: " + tempOutput + "|");

                tempOutput = "";
                foreach (NamespaceTypeDefinition classInList in currentNode.possibleClasses) {
                    tempOutput += this.sanitizeString(classInList.ToString()) + "; ";
                }
                dotFile.Write("possible Classes: " + tempOutput + "|");

                String positionString = "";
                foreach (int position in currentNode.positionInGraph) {
                    positionString += position.ToString() + ";";
                }
                dotFile.Write("Position: " + positionString + "|");

                positionString = "";
                foreach (NodeObject possibleNode in currentNode.possibleExchangeObjects) {
                    positionString += "(";
                    foreach (int position in possibleNode.positionInGraph) {
                        positionString += position.ToString() + ";";
                    }
                    positionString += ") ";
                }
                dotFile.Write("Possible exchange nodes: " + positionString + "|");

                String validPathIdString = "";
                foreach (int validPathId in currentNode.elementOfValidPath) {
                    validPathIdString += validPathId.ToString() + ";";
                }
                dotFile.Write("Valid Path Ids: " + validPathIdString);

                dotFile.WriteLine("}\"]");

                for (int idx = 0; idx < currentNode.dimension; idx++) {

                    // check if the tree is a complete tree
                    if (currentNode.nodeObjects[idx] == null) {
                        continue;
                    }

                    if (currentNode.nodeObjects[idx].elementOfValidPath.Count() != 0) {
                        dotFile.WriteLine(nodeName + "-> " + nodeName + "_" + idx.ToString() + "[ color=\"green\" ]");
                    }
                    else {
                        if (!dumpOnlyValidPath) {
                            dotFile.WriteLine(nodeName + "-> " + nodeName + "_" + idx.ToString() + "[ color=\"red\" ]");
                        }
                    }

                    // dump rest of the graph recursively
                    this.dumpGraphRecursively(dotFile, currentNode.nodeObjects[idx], nodeName + "_" + idx.ToString(), false);
                }
            }
        }
Beispiel #3
0
        // dump graph to a .dot file
        // IMPORTANT: will crash if a loop exists in the graph
        public void dumpGraph(NodeObject startNode, String fileName, bool dumpOnlyValidPath) {

            // shorten file name if it is too long
            fileName = fileName.Length >= 230 ? fileName.Substring(0, 230) : fileName;

            // dump graph
            System.IO.StreamWriter dotFile = new System.IO.StreamWriter(this.logPath + "\\graph_" + fileName + ".dot");

            // start .dot file graph
            dotFile.WriteLine("digraph G {");

            // write start node to file but only the valid path
            String nodeName = "Node_0";
            if (dumpOnlyValidPath) {

                if (startNode.elementOfValidPath.Count() != 0) {
                    dotFile.WriteLine(nodeName + " [shape=record]");

                    dotFile.Write(nodeName + " [label=\"{");
                    dotFile.Write("Node: " + nodeName + "|");
                    dotFile.Write("Class: " + this.sanitizeString(startNode.thisClass.ToString()) + "|");

                    String tempOutput = "";
                    foreach(PathElement pathElement in startNode.pathElements) {

                        tempOutput = "";
                        foreach (ITypeReference interfaceInList in pathElement.validInterfaces) {
                            tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                        }
                        dotFile.Write("valid Interfaces (valid ID: " + pathElement.validPathId.ToString() + "): " + tempOutput + "|");

                        tempOutput = "";
                        foreach (ITypeReference interfaceInList in pathElement.invalidInterfaces) {
                            tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                        }
                        dotFile.Write("invalid Interfaces (valid ID: " + pathElement.validPathId.ToString() + "): " + tempOutput + "|");

                    }

                    dotFile.Write("Constructor: " + this.makeFuncSigString(startNode.constructorToUse) + "|");

                    tempOutput = "";
                    foreach (ITypeReference interfaceInList in startNode.pathElements.ElementAt(0).mandatoryInterfaces) {
                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                    }
                    dotFile.Write("mandatory Interfaces: " + tempOutput + "|");

                    tempOutput = "";
                    foreach (ITypeReference interfaceInList in startNode.pathElements.ElementAt(0).forbiddenInterfaces) {
                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                    }
                    dotFile.Write("forbidden Interfaces: " + tempOutput + "|");

                    tempOutput = "";
                    foreach (NamespaceTypeDefinition classInList in startNode.possibleClasses) {
                        tempOutput += this.sanitizeString(classInList.ToString()) + "; ";
                    }
                    dotFile.Write("possible Classes: " + tempOutput + "|");

                    String positionString = "";
                    foreach (int position in startNode.positionInGraph) {
                        positionString += position.ToString() + ";";
                    }
                    dotFile.Write("Position: " + positionString + "|");

                    positionString = "";
                    foreach (NodeObject possibleNode in startNode.possibleExchangeObjects) {
                        positionString += "(";
                        foreach (int position in possibleNode.positionInGraph) {
                            positionString += position.ToString() + ";";
                        }
                        positionString += ") ";
                    }
                    dotFile.Write("Possible exchange nodes: " + positionString + "|");

                    String validPathIdString = "";
                    foreach (int validPathId in startNode.elementOfValidPath) {
                        validPathIdString += validPathId.ToString() + ";";
                    }
                    dotFile.Write("Valid Path Ids: " + validPathIdString);

                    dotFile.WriteLine("}\"]");

                    for (int idx = 0; idx < startNode.dimension; idx++) {

                        // check if the tree is a complete tree
                        if (startNode.nodeObjects[idx] == null) {
                            continue;
                        }

                        if (startNode.nodeObjects[idx].elementOfValidPath.Count() != 0) {
                            dotFile.WriteLine(nodeName + "-> " + nodeName + "_" + idx.ToString() + "[ color=\"green\" ]");

                            // dump rest of the graph recursively
                            this.dumpGraphRecursively(dotFile, startNode.nodeObjects[idx], nodeName + "_" + idx.ToString(), true);
                        }
                    }
                }
            }

            // write start node to file with the whole graph
            else {
                dotFile.WriteLine(nodeName + " [shape=record]");

                dotFile.Write(nodeName + " [label=\"{");
                dotFile.Write("Node: " + nodeName + "|");
                dotFile.Write("Class: " + this.sanitizeString(startNode.thisClass.ToString()) + "|");

                String tempOutput = "";
                foreach (PathElement pathElement in startNode.pathElements) {

                    tempOutput = "";
                    foreach (ITypeReference interfaceInList in pathElement.validInterfaces) {
                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                    }
                    dotFile.Write("valid Interfaces (valid ID: " + pathElement.validPathId.ToString() + "): " + tempOutput + "|");

                    tempOutput = "";
                    foreach (ITypeReference interfaceInList in pathElement.invalidInterfaces) {
                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                    }
                    dotFile.Write("invalid Interfaces (valid ID: " + pathElement.validPathId.ToString() + "): " + tempOutput + "|");

                }

                dotFile.Write("Constructor: " + this.makeFuncSigString(startNode.constructorToUse) + "|");

                tempOutput = "";
                foreach (ITypeReference interfaceInList in startNode.pathElements.ElementAt(0).mandatoryInterfaces) {
                    tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                }
                dotFile.Write("mandatory Interfaces: " + tempOutput + "|");

                tempOutput = "";
                foreach (ITypeReference interfaceInList in startNode.pathElements.ElementAt(0).forbiddenInterfaces) {
                    tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                }
                dotFile.Write("forbidden Interfaces: " + tempOutput + "|");

                tempOutput = "";
                foreach (NamespaceTypeDefinition classInList in startNode.possibleClasses) {
                    tempOutput += this.sanitizeString(classInList.ToString()) + "; ";
                }
                dotFile.Write("possible Classes: " + tempOutput + "|");

                String positionString = "";
                foreach (int position in startNode.positionInGraph) {
                    positionString += position.ToString() + ";";
                }
                dotFile.Write("Position: " + positionString + "|");

                positionString = "";
                foreach (NodeObject possibleNode in startNode.possibleExchangeObjects) {
                    positionString += "(";
                    foreach (int position in possibleNode.positionInGraph) {
                        positionString += position.ToString() + ";";
                    }
                    positionString += ") ";
                }
                dotFile.Write("Possible exchange nodes: " + positionString + "|");

                String validPathIdString = "";
                foreach (int validPathId in startNode.elementOfValidPath) {
                    validPathIdString += validPathId.ToString() + ";";
                }
                dotFile.Write("Valid Path Ids: " + validPathIdString);

                dotFile.WriteLine("}\"]");

                for (int idx = 0; idx < startNode.dimension; idx++) {

                    // check if the tree is a complete tree
                    if (startNode.nodeObjects[idx] == null) {
                        continue;
                    }

                    if (startNode.nodeObjects[idx].elementOfValidPath.Count() != 0) {
                        dotFile.WriteLine(nodeName + "-> " + nodeName + "_" + idx.ToString() + "[ color=\"green\" ]");
                    }
                    else {
                        dotFile.WriteLine(nodeName + "-> " + nodeName + "_" + idx.ToString() + "[ color=\"red\" ]");
                    }

                    // dump rest of the graph recursively
                    this.dumpGraphRecursively(dotFile, startNode.nodeObjects[idx], nodeName + "_" + idx.ToString(), false);

                }
            }






            // finish graph
            dotFile.WriteLine("}");

            dotFile.Close();

        }
Beispiel #4
0
        // builds a graph
        public void buildGraph(ValidGraphPath[] validPaths) {

            // check if at least one valid path is given
            int countValidPath = validPaths.Count();
            if (countValidPath < 1) {
                throw new ArgumentException("At least 1 valid path have to be given.");
            }
           
            // check if the path has enough elements
            int maxDepth = this.graphDepth;
            if (maxDepth <= 1) {
                throw new ArgumentException("Path has to have at least 2 elements.");
            }

            // set needed attributes
            this.graphValidPathCount = countValidPath;

            // a list of all possible nodes for all graph elements
            List<PossibleNode> allPossibleNodes = new List<PossibleNode>();

            // get a list of possible nodes that implement the first valid interface of the first node of the first valid path 
            ITypeReference tempInterface = validPaths[0].pathElements[0].mandatoryInterfaces.ElementAt(0);
            List<PossibleNode> possibleNodes = new List<PossibleNode>((List<PossibleNode>)this.graphInterfaces[tempInterface]);

            List<PossibleNode> copiedList = new List<PossibleNode>(possibleNodes);
            foreach (PossibleNode possibleNode in copiedList) {

                // check if all needed interfaces (by all valid paths) are contained by the possible node
                // if not => remove if from the list of possible nodes
                bool validNode = true;
                foreach (ITypeReference neededInterface in validPaths[0].pathElements[0].mandatoryInterfaces) {
                    if(!possibleNode.givenClass.Interfaces.Contains(neededInterface)) {
                        validNode = false;
                        break;
                    }
                }
                if(!validNode) {
                    possibleNodes.Remove(possibleNode);
                }

                // check if all forbidden interfaces (by all valid paths) are NOT contained by the possible node
                // if the possible node contains it => remove it from the list of possible nodes
                foreach (ITypeReference forbiddenInterface in validPaths[0].pathElements[0].forbiddenInterfaces) {
                    if(possibleNode.givenClass.Interfaces.Contains(forbiddenInterface)) {
                        validNode = false;
                        break;
                    }
                }
                if(!validNode) {
                    possibleNodes.Remove(possibleNode);
                }

            }

            if (possibleNodes.Count() == 0) {
                throw new ArgumentException("No class was found which satisfies the given requirements.");
            }

            // add all possible nodes for this graph element to the list of all possible nodes
            allPossibleNodes.AddRange(possibleNodes);


            // get first random node of graph            
            int randElement = this.prng.Next(possibleNodes.Count());
            NamespaceTypeDefinition classToUse = possibleNodes.ElementAt(randElement).givenClass;
            MethodDefinition nodeConstructor = possibleNodes.ElementAt(randElement).nodeConstructor;

            // create start node of graph
            List<int> startPosition = new List<int>();
            NodeObject startNode = new NodeObject(this.graphDimension, this.graphValidPathCount, classToUse, nodeConstructor, validPaths[0].pathElements[0], startPosition, 0);
            validPaths[0].pathElements[0].linkGraphObject = startNode;
            for (int validPathId = 1; validPathId < countValidPath; validPathId++) {
                startNode.elementOfValidPath.Add(validPathId);
                startNode.pathElements.Add(validPaths[validPathId].pathElements[0]);
                validPaths[validPathId].pathElements[0].linkGraphObject = startNode;
            }

            // add possible nodes to list of possible classes
            foreach (PossibleNode possibleNode in possibleNodes) {
                startNode.possibleClasses.Add(possibleNode.givenClass);
            }


            // build all valid paths
            for (int validPathId = 0; validPathId < countValidPath; validPathId++) {

                NodeObject currentNode = startNode;
                List<int> positionInGraph = new List<int>();

                // build a random valid path
                for (int idx = 1; idx < maxDepth; idx++) {

                    // get a list of possible nodes that implement the first valid interface of the first node of the first valid path 
                    tempInterface = validPaths[validPathId].pathElements[idx].mandatoryInterfaces.ElementAt(0);
                    possibleNodes = new List<PossibleNode>((List<PossibleNode>)this.graphInterfaces[tempInterface]);

                    // sort out nodes that do not satisfy all valid and invalid interface requirements of the node
                    copiedList = new List<PossibleNode>(possibleNodes);
                    foreach (PossibleNode possibleNode in copiedList) {

                        // check if all needed interfaces (by all valid paths) are contained by the possible node
                        // if not => remove if from the list of possible nodes
                        bool validNode = true;
                        foreach (ITypeReference neededInterface in validPaths[validPathId].pathElements[idx].mandatoryInterfaces) {
                            if (!possibleNode.givenClass.Interfaces.Contains(neededInterface)) {
                                validNode = false;
                                break;
                            }
                        }
                        if (!validNode) {
                            possibleNodes.Remove(possibleNode);
                        }

                        // check if all forbidden interfaces (by all valid paths) are NOT contained by the possible node
                        // if the possible node contains it => remove it from the list of possible nodes
                        foreach (ITypeReference forbiddenInterface in validPaths[validPathId].pathElements[idx].forbiddenInterfaces) {
                            if (possibleNode.givenClass.Interfaces.Contains(forbiddenInterface)) {
                                validNode = false;
                                break;
                            }
                        }
                        if (!validNode) {
                            possibleNodes.Remove(possibleNode);
                        }

                    }
                    if (possibleNodes.Count() == 0) {
                        throw new ArgumentException("No class was found which satisfies the given requirements.");
                    }


                    // add all distinct possible nodes for this graph element to the list of all possible nodes
                    foreach (PossibleNode possibleNode in possibleNodes) {
                        if (!allPossibleNodes.Contains(possibleNode)) {
                            allPossibleNodes.Add(possibleNode);
                        }
                    }


                    int pathIdx = validPaths[validPathId].pathIndices[idx];

                    if (currentNode.nodeObjects[pathIdx] != null) {

                        // check if the used class of the node satisfy both paths
                        NamespaceTypeDefinition usedClass = currentNode.nodeObjects[pathIdx].thisClass;
                        bool validNode = false; 
                        foreach (PossibleNode possibleNode in possibleNodes) {
                            if (usedClass == possibleNode.givenClass) {
                                validNode = true;
                                break;
                            }
                        }
                        if (!validNode) {
                            throw new ArgumentException("Node does not satisfy both valid paths.");
                        }


                        currentNode.nodeObjects[pathIdx].pathElements.Add(validPaths[validPathId].pathElements[idx]);
                        currentNode.nodeObjects[pathIdx].elementOfValidPath.Add(validPathId);
                        positionInGraph.Add(pathIdx);

                        validPaths[validPathId].pathElements[idx].linkGraphObject = currentNode.nodeObjects[pathIdx];

                    }

                    else {

                        // add path index to the position and copy position list
                        positionInGraph.Add(pathIdx);
                        List<int> tempPositionInGraph = new List<int>(positionInGraph);

                        // get random node for graph
                        randElement = this.prng.Next(possibleNodes.Count());
                        classToUse = possibleNodes.ElementAt(randElement).givenClass;
                        nodeConstructor = possibleNodes.ElementAt(randElement).nodeConstructor;

                        currentNode.nodeObjects[pathIdx] = new NodeObject(this.graphDimension, this.graphValidPathCount, classToUse, nodeConstructor, validPaths[validPathId].pathElements[idx], tempPositionInGraph, validPathId);
                        validPaths[validPathId].pathElements[idx].linkGraphObject = currentNode.nodeObjects[pathIdx];

                        // add possible nodes to list of possible classes
                        foreach (PossibleNode possibleNode in possibleNodes) {
                            currentNode.nodeObjects[pathIdx].possibleClasses.Add(possibleNode.givenClass);
                        }

                    }

                    currentNode = currentNode.nodeObjects[pathIdx];

                }

            }

            // fill the rest of the graph
            this.fillNodesRecursively(startNode, startPosition, 1, maxDepth, allPossibleNodes, validPaths);

            this.startingNode = startNode;

        }
        // this functions creates metadata for the given basic block and adds it
        private bool createAndAddMetadata(BasicBlock currentBasicBlock) {

            // get metadata of entry basic block (if exists)
            IGraphTransformerMetadata previousMetadata = null;
            BasicBlock previousBasicBlock = null;
            IBranchTarget previousExitBranch = null;
            for (int i = 0; i < currentBasicBlock.entryBranches.Count(); i++) {

                previousBasicBlock = currentBasicBlock.entryBranches.ElementAt(i).sourceBasicBlock;

                for (int j = 0; j < previousBasicBlock.transformationMetadata.Count(); j++) {
                    // get graph transformer metadata for basic blocks
                    if ((previousBasicBlock.transformationMetadata.ElementAt(j) as IGraphTransformerMetadata) == null) {
                        continue;
                    }
                    previousMetadata = (previousBasicBlock.transformationMetadata.ElementAt(j) as IGraphTransformerMetadata);
                    previousExitBranch = currentBasicBlock.entryBranches.ElementAt(i);
                    break;
                }
                if (previousMetadata != null) {
                    break;
                }
            }
            // skip basic block if there is no metadata in one of the entry basic blocks
            if (previousMetadata == null) { // TODO: here is room for optimization => do not skip it
                return false;
            }
            List<BasicBlockGraphNodeLink> previousLinks = previousMetadata.correspondingGraphNodes;

            // choose the next nodes of the obfuscation graph for the current basic block
            NodeObject[] currentNodes = new NodeObject[this.graph.graphValidPathCount];

            // check if previous basic block has links to the obfuscation graph for all existing valid paths
            // (if previous basic block for example was a "state change" basic block it can only have one link to the obfuscation graph)
            // => just copy obfuscation graph nodes of previous basic block if it contains all valid paths
            if (previousLinks.Count() == this.graph.graphValidPathCount) {
                for (int currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {
                    bool found = false;
                    for (int i = 0; i < previousLinks.Count(); i++) {
                        if (previousLinks.ElementAt(i).validPathId == currentValidPathId) {
                            currentNodes[currentValidPathId] = previousLinks.ElementAt(i).graphNode;
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        throw new ArgumentException("Was not able to find link to obfuscation graph in previous basic block for at least one valid path.");
                    }
                }
            }

            // previous basic block does not contain all valid paths
            // => copy all existing valid paths links and choose random links for the missing ones
            else {

                for (int currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {
                    bool found = false;
                    for (int i = 0; i < previousLinks.Count(); i++) {
                        if (previousLinks.ElementAt(i).validPathId == currentValidPathId) {
                            currentNodes[currentValidPathId] = previousLinks.ElementAt(i).graphNode;
                            found = true;
                            break;
                        }
                    }

                    // if a link for the current valid path does not exist
                    // => choose randomly a node in the obfuscation graph on the current valid path
                    if (!found) {
                        int moveCount = this.prng.Next(this.graphDepth);
                        NodeObject nextNode = this.graph.startingNode;
                        for (int move = 0; move < moveCount; move++) {
                            for (int i = 0; i < nextNode.nodeObjects.Count(); i++) {

                                // if the child node does not belong to a valid path
                                // => skip it
                                if (nextNode.nodeObjects[i].elementOfValidPath.Count() == 0) {
                                    continue;
                                }

                                // the child node belongs to a valid path
                                // => check if it is the correct valid path
                                else {
                                    // if the child node belongs to the correct valid path
                                    // => set next node to it
                                    if (nextNode.nodeObjects[i].elementOfValidPath.Contains(currentValidPathId)) {
                                        nextNode = nextNode.nodeObjects[i];
                                        break;
                                    }
                                }
                            }
                            if (nextNode == null) {
                                throw new ArgumentException("Not able to find correct child node.");
                            }
                        }

                        currentNodes[currentValidPathId] = nextNode;

                    }
                }
            }

            NodeObject[] nextNodes = new NodeObject[this.graph.graphValidPathCount];
            for (int currentValidPathId = 0; currentValidPathId < currentNodes.Count(); currentValidPathId++) {

                // choose randomly if the pointer of the current valid path should be moved forward
                // => move the pointer of the current valid path forward
                if (this.prng.Next(2) == 0) {

                    // get the next node of the valid path
                    NodeObject nextNode = null;
                    int nextNodeIdx = 0;
                    this.getNextNode(ref nextNode, ref nextNodeIdx, currentNodes, currentValidPathId);
                    nextNodes[currentValidPathId] = nextNode;

                }

                // => do not move the pointer of the current valid path forward
                else {

                    // set next node in the graph to the current one (it was not changed)
                    nextNodes[currentValidPathId] = currentNodes[currentValidPathId];

                }
            }

            // create transformation metadata for the current basic block
            GraphTransformerMetadataBasicBlock metadata = new GraphTransformerMetadataBasicBlock();

            for (int currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {
                BasicBlockGraphNodeLink link = new BasicBlockGraphNodeLink(nextNodes[currentValidPathId], currentValidPathId);
                metadata.correspondingGraphNodes.Add(link);
            }

            currentBasicBlock.transformationMetadata.Add(metadata);

            return true;

        }
        // this function searches for the next node of the given valid path id and the node idx for this node
        private void getNextNode(ref NodeObject nextNode, ref int nextNodeIdx, NodeObject[] currentNodes, int currentValidPathId) {

            // check if a child node exists
            // => if not set next node to starting node
            if (currentNodes[currentValidPathId].nodeObjects[0] == null) {
                nextNode = this.graph.startingNode;
                nextNodeIdx = this.prng.Next(this.graphDimension);
            }
            else {
                for (int i = 0; i < currentNodes[currentValidPathId].nodeObjects.Count(); i++) {

                    // if the child node does not belong to a valid path
                    // => skip it
                    if (currentNodes[currentValidPathId].nodeObjects[i].elementOfValidPath.Count() == 0) {
                        continue;
                    }

                    // the child node belongs to a valid path
                    // => check if it is the correct valid path
                    else {
                        // if the child node belongs to the correct valid path
                        // => set next node to it
                        if (currentNodes[currentValidPathId].nodeObjects[i].elementOfValidPath.Contains(currentValidPathId)) {
                            nextNode = currentNodes[currentValidPathId].nodeObjects[i];
                            nextNodeIdx = i;
                            break;
                        }
                    }
                }
                if (nextNode == null) {
                    throw new ArgumentException("Not able to find correct child node.");
                }
            }

        }
        // this function generates and injects code into the given entry branch that moves the pointer from the source node to the target node
        private void injectMovePointerCode(CfgManipulator cfgManipulator, NodeObject sourceNode, BasicBlockGraphNodeLink targetLink, IBranchTarget entryBranch, LocalDefinition currentNodeLocal) {

            NodeObject targetNode = targetLink.graphNode;
            NodeObject currentNode = sourceNode;
            UnconditionalBranchTarget branchToManipulate = null;

            if ((entryBranch as UnconditionalBranchTarget) != null) {
                branchToManipulate = (entryBranch as UnconditionalBranchTarget);
            }
            else {
                throw new ArgumentException("Not yet implemented."); // TODO at the moment we assume unconditional branches as entry
            }

            // do nothing if the source node is already the same as the target node
            if (sourceNode == targetNode) {
                return;
            }

            // check if the pointer have to be moved to the start pointer before it can be moved to the target element
            bool goToStart = false;
            if (sourceNode.positionInGraph.Count() >= targetNode.positionInGraph.Count()) {
                goToStart = true;
            }
            else {
                for (int idx = 0; idx < sourceNode.positionInGraph.Count(); idx++) {
                    if (sourceNode.positionInGraph.ElementAt(idx) != targetNode.positionInGraph.ElementAt(idx)) {
                        goToStart = true;
                        break;
                    }
                }
            }

            // check how to move the pointer to the target element
            // => first go to the start pointer
            if (goToStart) {

                // generate and inject code that moves the pointer on a random path forward until the start node of the graph is reached
                while (currentNode != this.graph.startingNode) {

                    // generate code to move the pointer to the next node in the graph and inject it
                    int nextNodeIdx = this.prng.Next(this.graphDimension);
                    UnconditionalBranchTarget injectedExitBranch = new UnconditionalBranchTarget();
                    BasicBlock injectedBasicBlock = this.createCodeNextNode(injectedExitBranch, targetLink, currentNodeLocal, nextNodeIdx, true);
                    cfgManipulator.insertBasicBlockBetweenBranch(branchToManipulate, injectedBasicBlock, injectedExitBranch);

                    // set the next branch to manipulate as the newly created exit branch
                    branchToManipulate = injectedExitBranch;

                    // move pointer to the next node in the graph or to the start node if it does not exist
                    if (currentNode.nodeObjects[nextNodeIdx] == null) {
                        currentNode = this.graph.startingNode;
                    }
                    else {
                        currentNode = currentNode.nodeObjects[nextNodeIdx];
                    }
                }

                // generate and inject code that moves the pointer to the correct position of the given graph node
                foreach (int nextNodeIdx in targetNode.positionInGraph) {

                    // generate code to move the pointer to the next node in the graph and inject it
                    UnconditionalBranchTarget injectedExitBranch = new UnconditionalBranchTarget();
                    BasicBlock injectedBasicBlock = this.createCodeNextNode(injectedExitBranch, targetLink, currentNodeLocal, nextNodeIdx, true);
                    cfgManipulator.insertBasicBlockBetweenBranch(branchToManipulate, injectedBasicBlock, injectedExitBranch);

                    // set the next branch to manipulate as the newly created exit branch
                    branchToManipulate = injectedExitBranch;

                    // move pointer to the next node in the graph or to the start node if it does not exist
                    if (currentNode.nodeObjects[nextNodeIdx] == null) {
                        currentNode = this.graph.startingNode;
                    }
                    else {
                        currentNode = currentNode.nodeObjects[nextNodeIdx];
                    }
                }
            }

            // => go on a direct path to the target element
            else {

                // generate and inject code that moves the pointer to the correct position of the given graph node
                for (int idx = sourceNode.positionInGraph.Count(); idx < targetNode.positionInGraph.Count(); idx++) {

                    // generate code to move the pointer to the next node in the graph and inject it
                    UnconditionalBranchTarget injectedExitBranch = new UnconditionalBranchTarget();
                    BasicBlock injectedBasicBlock = this.createCodeNextNode(injectedExitBranch, targetLink, currentNodeLocal, targetNode.positionInGraph.ElementAt(idx), true);
                    cfgManipulator.insertBasicBlockBetweenBranch(branchToManipulate, injectedBasicBlock, injectedExitBranch);

                    // set the next branch to manipulate as the newly created exit branch
                    branchToManipulate = injectedExitBranch;

                    // move pointer to the next node in the graph or to the start node if it does not exist
                    if (currentNode.nodeObjects[targetNode.positionInGraph.ElementAt(idx)] == null) {
                        currentNode = this.graph.startingNode;
                    }
                    else {
                        currentNode = currentNode.nodeObjects[targetNode.positionInGraph.ElementAt(idx)];
                    }
                }

            }

            // check if the final reached node is the same as the target node
            if (currentNode != targetNode) {
                throw new ArgumentException("Current node and target node are not the same.");
            }

        }
        // this function adds recursively methods that adds the left and the right node to the current node in the graph
        // (and calls the next method that adds the left and right node)
        private MethodDefinition addNodeRecursively(NodeObject currentNode, int currentDepth, String newMethodName) {

            // create first parameter that is the current node in the graph
            List<IParameterDefinition> parameters = new List<IParameterDefinition>();
            ParameterDefinition parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = this.nodeInterface;
            parameters.Add(parameter);

            // create second parameter that is the current depth in the graph
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = host.PlatformType.SystemInt32;
            parameters.Add(parameter);

            // create method to add left and right node to the graph
            MethodDefinition newAddNodeMethod = this.helperClass.createNewMethod(newMethodName, this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name

            // create body of method
            ILGenerator ilGenerator = new ILGenerator(this.host, newAddNodeMethod);

            // check if max depth of tree is reached
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldc_I4, this.graph.graphDepth);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Ceq);
            ILGeneratorLabel depthReachedBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Brfalse, depthReachedBranch);

            // set child nodes of this node
            MethodDefinition constructorToUse;

            for (int i = 0; i < this.graphDimension; i++) {

                // get constructor of the child node element
                constructorToUse = null;

                // check if the child node exists in the graph and the max depth is not yet reached
                if (currentNode.nodeObjects[i] == null
                    && currentDepth != this.graph.graphDepth) {
                    throw new ArgumentException("Given depth of graph is larger than the actual graph.");
                }
                else {
                    // check if the child node does not exist
                    // => use a random constructor node
                    if (currentNode.nodeObjects[i] == null) {
                        constructorToUse = currentNode.constructorToUse; // TODO: use random node constructor here
                    }
                    // else use constructor of given graph node
                    else {
                        constructorToUse = currentNode.nodeObjects[i].constructorToUse;
                    }
                }

                // set child node
                ilGenerator.Emit(OperationCode.Ldarg_1); // current node from which the function is called
                ilGenerator.Emit(OperationCode.Ldarg_0); // needed as argument for the constructor
                ilGenerator.Emit(OperationCode.Newobj, constructorToUse); // iNode parameter
                ilGenerator.Emit(OperationCode.Ldc_I4, i); // index parameter
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

                // get child node and set it recursively
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Ldarg_1); // current node from which the function is called
                ilGenerator.Emit(OperationCode.Ldc_I4, i); // index parameter
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);

                ilGenerator.Emit(OperationCode.Ldarg_2); // arg2 (current depth) + 1
                ilGenerator.Emit(OperationCode.Ldc_I4_1);
                ilGenerator.Emit(OperationCode.Add);

                MethodDefinition newMethodToCall = null;
                if (currentDepth == this.graph.graphDepth) {
                    newMethodToCall = newAddNodeMethod; // TODO: call random node generation method here
                }
                else {
                    newMethodToCall = this.addNodeRecursively(currentNode.nodeObjects[i], currentDepth + 1, newMethodName + "_" + i.ToString()); // TODO: method name
                }

                ilGenerator.Emit(OperationCode.Callvirt, newMethodToCall);
            }

            ilGenerator.Emit(OperationCode.Ret);

            // set child nodes of this node to null
            ilGenerator.MarkLabel(depthReachedBranch);
            for (int i = 0; i < this.graphDimension; i++) {
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet); // iNode parameter
                ilGenerator.Emit(OperationCode.Ldc_I4, i); // index parameter
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            }
            ilGenerator.Emit(OperationCode.Ret);

            // generate body
            IMethodBody body = new ILGeneratorMethodBody(ilGenerator, true, 8, newAddNodeMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            newAddNodeMethod.Body = body;

            return newAddNodeMethod;
        }
 public BasicBlockGraphNodeLink(NodeObject graphNode, int validPathId) {
     this.validPathId = validPathId;
     this.graphNode = graphNode;
 }