// 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); } }
// 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; }