/// <summary> /// Sucht im Graphen nach Knoten "myEnd" ausgehend von der Knotenmenge "myEdge", bis zur max. Tiefe "myMaxDepth". /// </summary> /// <param name="myTypeAttribute">Kante über die gesucht werden soll</param> /// <param name="myDBContext"></param> /// <param name="myStart">Startknoten</param> /// <param name="myEnd">gesuchter Knoten</param> /// <param name="myEdge">Menge an Knoten, ausgehend vom Startknoten welche mittels einer Funktion eingeschränkt wurde</param> /// <param name="myMaxDepth">max. Tiefe</param> /// <returns>true wenn gesuchter Knoten min. 1 mal gefunden, false sonst</returns> public bool Find(TypeAttribute myTypeAttribute, DBContext myDBContext, DBObjectStream myStart, DBObjectStream myEnd, IReferenceEdge myEdge, byte myMaxDepth) { #region data //queue for BFS Queue<ObjectUUID> queue = new Queue<ObjectUUID>(); //Dictionary to store visited TreeNodes BigHashSet<ObjectUUID> visitedNodes = new BigHashSet<ObjectUUID>(); //current depth byte depth = 2; //first node in path tree, the start of the select ObjectUUID root = myStart.ObjectUUID; //constrainted set of nodes, of start node HashSet<ObjectUUID> rootFriends = new HashSet<ObjectUUID>(); //target node, the target of the select ObjectUUID target = myEnd.ObjectUUID; //dummy node to check in which level the BFS is ObjectUUID dummy = null; //add root to visitedNodes visitedNodes.Add(root); //holds the actual DBObject Exceptional<DBObjectStream> currentDBObject; #endregion data #region validate root //check if root has edge var dbo = myDBContext.DBObjectCache.LoadDBObjectStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), root); if (dbo.Failed()) { throw new NotImplementedException(); } if (!dbo.Value.HasAttribute(myTypeAttribute.UUID, myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager))) { return false; } #endregion validate root #region get friends of startElement and check if they are the target and valid //instead of inserting only the startObject, we are using the startObject and the friends of the startObject (which could be restricted) var firstUUIDs = myEdge.GetAllReferenceIDs(); for (int i = 0; i < firstUUIDs.Count(); i++) { var element = firstUUIDs.ElementAt(i); if (element != null) { //create a new node and set root = parent var currentNode = element; #region check if the child is the target //start and target are conntected directly if (currentNode.Equals(myEnd.ObjectUUID)) { //add node (which coud be the target) to startFriends (if start and target are directly connected, the target in the rootFriends list is needed) rootFriends.Add(currentNode); return true; } #endregion check if the child is the target //check if element has edge var dbobject = myDBContext.DBObjectCache.LoadDBObjectStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), currentNode); if (dbobject.Failed()) { continue; } if (!dbobject.Value.HasAttribute(myTypeAttribute.UUID, myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager))) { continue; } //enqueue node to start from left side queue.Enqueue(currentNode); //add node to visitedNodes visitedNodes.Add(currentNode); //add node to startFriends rootFriends.Add(currentNode); } } #endregion get friends of startElement and check if they are the target and valid //enqueue dummy queue.Enqueue(dummy); #region BFS //if there is more than one object in the queue and the actual depth is less than MaxDepth while ((queue.Count > 1) && (depth <= myMaxDepth)) { //get the first Object of the queue ObjectUUID nodeOfQueue = queue.Dequeue(); #region check if nodeOfQueue is a dummy //if nodeOfQueue is a dummy, this level is completely worked off if (nodeOfQueue == null) { depth++; queue.Enqueue(nodeOfQueue); continue; } #endregion check if current is a dummy //load DBObject currentDBObject = myDBContext.DBObjectCache.LoadDBObjectStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), nodeOfQueue); if (currentDBObject.Failed()) { throw new NotImplementedException(); } if (currentDBObject.Value.HasAttribute(myTypeAttribute.UUID, myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager))) { #region EdgeType is ASetOfReferencesEdgeType if (myTypeAttribute.EdgeType is ASetOfReferencesEdgeType) { //get all referenced ObjectUUIDs using the given Edge var objectUUIDs = (currentDBObject.Value.GetAttribute(myTypeAttribute.UUID) as ASetOfReferencesEdgeType).GetAllReferenceIDs(); ObjectUUID currentNode; foreach (ObjectUUID obj in objectUUIDs) { #region obj is target //if the child is the target if (target.Equals(obj)) { return true; } #endregion obj is target #region never seen before else if (!visitedNodes.Contains(obj)) { //create new node and set nodeOfQueue as parent currentNode = new ObjectUUID(obj.ToString()); //mark the node as visited visitedNodes.Add(currentNode); //put created node in queue queue.Enqueue(currentNode); } #endregion never seen before } } #endregion EdgeType is ASetOfReferencesEdgeType #region EdgeType is ASingleReferenceEdgeType else if (myTypeAttribute.EdgeType is ASingleReferenceEdgeType) { //get all referenced ObjectUUIDs using the given Edge var objectUUIDs = (currentDBObject.Value.GetAttribute(myTypeAttribute.UUID) as ASingleReferenceEdgeType).GetAllReferenceIDs(); ObjectUUID objectUUID = objectUUIDs.First<ObjectUUID>(); ObjectUUID currentNode; #region obj is target //if the child is the target if (target.Equals(objectUUID)) { return true; } #endregion obj is target #region never seen before else if (!visitedNodes.Contains(objectUUID)) { //create new node and set nodeOfQueue as parent currentNode = new ObjectUUID(objectUUID.ToString()); //mark the node as visited visitedNodes.Add(currentNode); //put created node in queue queue.Enqueue(currentNode); } #endregion never seen before } #endregion EdgeType is ASingleReferenceEdgeType else { throw new NotImplementedException(); } } } #endregion BFS return false; }
protected Exceptional<Boolean> RemoveBackwardEdgesOnReferences(AAttributeAssignOrUpdate myAAttributeAssign, IReferenceEdge myReference, DBObjectStream myDBObject, DBContext myDBContext) { foreach (var item in myReference.GetAllReferenceIDs()) { var streamExcept = myDBContext.DBObjectCache.LoadDBObjectStream(myAAttributeAssign.AttributeIDChain.LastAttribute.GetDBType(myDBContext.DBTypeManager), (ObjectUUID)item); if (!streamExcept.Success()) return new Exceptional<Boolean>(streamExcept.IErrors.First()); var removeExcept = myDBContext.DBObjectManager.RemoveBackwardEdge(streamExcept.Value, myAAttributeAssign.AttributeIDChain.LastAttribute.RelatedGraphDBTypeUUID, myAAttributeAssign.AttributeIDChain.LastAttribute.UUID, myDBObject.ObjectUUID); if (!removeExcept.Success()) return new Exceptional<Boolean>(removeExcept.IErrors.First()); } return new Exceptional<Boolean>(true); }
//Logger //private static Logger //_Logger = LogManager.GetCurrentClassLogger(); /// <summary> /// Please look at the class documentation for detailed description how this algorithm works. /// </summary> /// <param name="myTypeAttribute">The Attribute representing the edge to follow (p.e. "Friends")</param> /// <param name="myDBContext">The DBContext holds the TypeManager and the ObjectCache</param> /// <param name="myStart">The start node</param> /// <param name="myEnd">The end node</param> /// <param name="shortestOnly">true, if only shortest path shall be found</param> /// <param name="findAll">if true and shortestOnly is true, all shortest paths will be found. if true, and shortest only is false, all paths will be searched</param> /// <param name="myMaxDepth">The maximum depth to search</param> /// <param name="myMaxPathLength">The maximum path length which shall be analyzed</param> /// <returns>A HashSet which contains all found paths. Every path is represented by a List of ObjectUUIDs</returns>m> public HashSet<List<ObjectUUID>> Find(TypeAttribute myTypeAttribute, DBContext myDBContext, DBObjectStream myStart, IReferenceEdge myEdge, DBObjectStream myEnd, bool shortestOnly, bool findAll, byte myMaxDepth, byte myMaxPathLength) { #region declarations //queue for BFS var queueLeft = new Queue<Node>(); var queueRight = new Queue<Node>(); //Dictionary to store visited TreeNodes var visitedNodesLeft = new BigDictionary<ObjectUUID, Node>(); var visitedNodesRight = new BigDictionary<ObjectUUID, Node>(); //set current depth left byte depthLeft = 2; //set current depth right byte depthRight = 1; //maximum depth byte maxDepthLeft = 0; byte maxDepthRight = 0; #region initialize maxDepths //if the maxDepth is greater then maxPathLength, then set maxDepth to maxPathLength if (myMaxDepth > myMaxPathLength) { myMaxDepth = myMaxPathLength; } //set depth for left side maxDepthLeft = Convert.ToByte(myMaxDepth / 2 + 1); //if myMaxDepth is 1 maxDepthRight keeps 0, just one side is searching if (myMaxDepth > 1) { //both sides have the same depth maxDepthRight = maxDepthLeft; } //if myMaxDepth is even, one side has to search in a greater depth if ((myMaxDepth % 2) == 0) { maxDepthRight = Convert.ToByte(maxDepthLeft - 1); } #endregion //shortest path length byte shortestPathLength = 0; //target node, the target of the select var target = new Node(myEnd.ObjectUUID); var root = new Node(myStart.ObjectUUID); HashSet<ObjectUUID> rootFriends = new HashSet<ObjectUUID>(); //dummy node to check in which level the BFS is var dummyLeft = new Node(); var dummyRight = new Node(); #region get friends of startElement and check if they are the target and valid //instead of inserting only the startObject, we are using the startObject and the friends of the startObject (which could be restricted) var firstUUIDs = myEdge.GetAllReferenceIDs(); foreach (var element in firstUUIDs) { if (element != null) { //create a new node and set root = parent var currentNodeLeft = new Node(element); #region check if the child is the target //start and target are conntected directly if (currentNodeLeft.Key == myEnd.ObjectUUID) { //set depthRight to zero depthRight = 0; //add node (which coud be the target) to startFriends (if start and target are directly connected, the target in the rootFriends list is needed) rootFriends.Add(currentNodeLeft.Key); shortestPathLength = Convert.ToByte(depthLeft); return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } #endregion check if the child is the target //check if element has edge var dbo = myDBContext.DBObjectCache.LoadDBObjectStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), currentNodeLeft.Key); if (dbo.Failed()) { continue; } if (!dbo.Value.HasAttribute(myTypeAttribute.UUID, myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager))) { continue; } //enqueue node to start from left side queueLeft.Enqueue(currentNodeLeft); //add node to visitedNodes visitedNodesLeft.Add(currentNodeLeft.Key, currentNodeLeft); //add node to startFriends rootFriends.Add(currentNodeLeft.Key); } } #endregion get friends of startElement and check if they are the target and valid //elements of myEdge doesn't have edge if (visitedNodesLeft.Count == 0) { return null; } //check if target already found if (shortestPathLength != 0) { return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } //enqueue dummyLeft to analyze the depth of the left side queueLeft.Enqueue(dummyLeft); //holds the key of the backwardedge var edgeKey = new EdgeKey(myTypeAttribute); //holds the actual DBObject Exceptional<DBObjectStream> currentDBObjectLeft; Exceptional<BackwardEdgeStream> currentDBObjectRight; #endregion declarations #region BidirectionalBFS //check if the EdgeType is ASetReferenceEdgeType #region EdgeType is ASetReferenceEdgeType if (myEdge is ASetOfReferencesEdgeType) { #region initialize variables //enqueue target node to start from right side queueRight.Enqueue(target); //enqueue dummyRight to analyze the depth of the right side queueRight.Enqueue(dummyRight); //add root and target to visitedNodes visitedNodesRight.Add(target.Key, target); #endregion initialize variables #region check if target has backwardedge var be = myDBContext.DBObjectCache.LoadDBBackwardEdgeStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), target.Key); if (be.Failed()) { throw new NotImplementedException(); } if (!be.Value.ContainsBackwardEdge(edgeKey)) { return null; } #endregion check if target has backwardedge //if there is more than one object in the queue and the actual depth is less than MaxDepth while (((queueLeft.Count > 0) && (queueRight.Count > 0)) && ((depthLeft <= maxDepthLeft) || (depthRight <= maxDepthRight))) { #region both queues contain objects and both depths are not reached if (((queueLeft.Count > 0) && (queueRight.Count > 0)) && ((depthLeft <= maxDepthLeft) && (depthRight <= maxDepthRight))) { //hold the actual element of the queues Node currentLeft; Node currentRight; #region check if there is a dummyNode at the beginning of a queue //first of both queues are dummies if ((queueLeft.First<Node>() == dummyLeft) && (queueRight.First<Node>() == dummyRight)) { //if maxDepth of a side is reached and there is a dummy, one level is totaly searched if (depthLeft == maxDepthLeft && depthRight == maxDepthRight) { ////_Logger.Info("going deeper in the dungeon on the left side.. current level: " + depthLeft); depthLeft++; ////_Logger.Info("going deeper in the dungeon on the right side.. current level: " + depthRight); depthRight++; continue; } else if (depthLeft == maxDepthLeft) { ////_Logger.Info("going deeper in the dungeon on the left side.. current level: " + depthLeft); depthLeft++; continue; } else if (depthRight == maxDepthRight) { ////_Logger.Info("going deeper in the dungeon on the right side.. current level: " + depthRight); depthRight++; continue; } //dequeue dummies queueLeft.Dequeue(); queueRight.Dequeue(); //increase depth's ////_Logger.Info("going deeper in the dungeon on the left side.. current level: " + depthLeft); depthLeft++; ////_Logger.Info("going deeper in the dungeon on the right side.. current level: " + depthRight); depthRight++; //if both queues are empty -> break loop if (queueLeft.Count == 0 && queueRight.Count == 0) { break; } //if left queue is empty enqueue right dummy and continue else if (queueLeft.Count == 0) { queueRight.Enqueue(dummyRight); continue; } //if right queue is empty enqueue left dummy and continue else if (queueRight.Count == 0) { queueLeft.Enqueue(dummyLeft); continue; } //enqueue both dummies else { queueLeft.Enqueue(dummyLeft); queueRight.Enqueue(dummyRight); } } //first of left queue is a dummy else if (queueLeft.First<Node>() == dummyLeft) { //if maxDepth of a side is reached and there is a dummy, one level is totaly searched if (depthLeft == maxDepthLeft) { //_Logger.Info("going deeper in the dungeon on the left side.. current level: " + depthLeft); depthLeft++; continue; } //dequeue dummy queueLeft.Dequeue(); //increase depth //_Logger.Info("going deeper in the dungeon on the left side.. current level: " + depthLeft); depthLeft++; //if left queue is empty continue if (queueLeft.Count == 0) { continue; } //enqueue dummy else { queueLeft.Enqueue(dummyLeft); } } //first of right queue is a dummy else if (queueRight.First<Node>() == dummyRight) { //if maxDepth of a side is reached and there is a dummy, one level is totaly searched if (depthRight == maxDepthRight) { //_Logger.Info("going deeper in the dungeon on the right side.. current level: " + depthRight); depthRight++; continue; } //dequeue dummy queueRight.Dequeue(); //increase depth //_Logger.Info("going deeper in the dungeon on the right side.. current level: " + depthRight); depthRight++; //if right queue is empty continue if (queueRight.Count == 0) { continue; } //enqueue dummy else { queueRight.Enqueue(dummyRight); } } #endregion check if there is a dummyNode at the beginning of a queue #region get first nodes of the queues //get the first Object of the queue currentLeft = queueLeft.Dequeue(); //get the first Object of the queue currentRight = queueRight.Dequeue(); #endregion get first nodes of the queues #region load DBObjects //load DBObject currentDBObjectLeft = myDBContext.DBObjectCache.LoadDBObjectStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), currentLeft.Key); if (currentDBObjectLeft.Failed()) { throw new NotImplementedException(); } //load DBObject currentDBObjectRight = myDBContext.DBObjectCache.LoadDBBackwardEdgeStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), new ObjectUUID(currentRight.Key.ToString().TrimStart())); if (currentDBObjectRight.Failed()) { throw new NotImplementedException(); } #endregion load DBObjects #region the edge and the backwardedge are existing if (currentDBObjectLeft.Value.HasAttribute(myTypeAttribute.UUID, myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager)) && currentDBObjectRight.Value.ContainsBackwardEdge(edgeKey)) { //get all referenced ObjectUUIDs using the given Edge var objectUUIDsLeft = (currentDBObjectLeft.Value.GetAttribute(myTypeAttribute.UUID) as ASetOfReferencesEdgeType).GetAllReferenceIDs(); Node currentNodeLeft; #region check left friends foreach (var dboLeft in objectUUIDsLeft) { #region if the child is the target if (dboLeft == myEnd.ObjectUUID) { //set currentLeft as parent of target target.addParent(currentLeft); #region check if already visited if (visitedNodesLeft.ContainsKey(dboLeft)) { //set currentLeft as parent visitedNodesLeft[dboLeft].addParent(currentLeft); //set currentNodeLeft as child currentLeft.addChild(visitedNodesLeft[dboLeft]); } else { //create a new node and set currentLeft = parent currentNodeLeft = new Node(dboLeft, currentLeft); //set currentNodeLeft as child of currentLeft currentLeft.addChild(currentNodeLeft); //never seen before //mark the node as visited visitedNodesLeft.Add(currentNodeLeft.Key, currentNodeLeft); //and put node into the queue queueLeft.Enqueue(currentNodeLeft); } #endregion check if already visited #region check how much parents are searched if (shortestOnly && !findAll) { //_Logger.Info("found shortest path..starting analyzer"); if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } //if find all shortest paths else if (shortestOnly && findAll) { //set maxDepth to actual depth maxDepthLeft = depthLeft; maxDepthRight = depthRight; if ((depthLeft + depthRight) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight); } } #endregion check how much parents are searched } #endregion if the child is the target #region already visited else if (visitedNodesLeft.ContainsKey(dboLeft)) { //set currentLeft as parent visitedNodesLeft[dboLeft].addParent(currentLeft); //set currentNodeLeft as child currentLeft.addChild(visitedNodesLeft[dboLeft]); } #endregion already visited #region set as visited else { //create a new node and set currentLeft = parent currentNodeLeft = new Node(dboLeft, currentLeft); //set currentNodeLeft as child of currentLeft currentLeft.addChild(currentNodeLeft); //never seen before //mark the node as visited visitedNodesLeft.Add(currentNodeLeft.Key, currentNodeLeft); //and put node into the queue queueLeft.Enqueue(currentNodeLeft); } #endregion set as visited } #endregion check left friends //get all referenced ObjectUUIDs using the given Edge var objectUUIDsRight = currentDBObjectRight.Value.GetBackwardEdgeUUIDs(edgeKey); Node currentNodeRight; #region check right friends foreach (ObjectUUID dboRight in objectUUIDsRight) { #region if the child is the target if (rootFriends.Contains(dboRight)) { #region check if already visited //mark node as visited if (visitedNodesRight.ContainsKey(dboRight)) { //set found children visitedNodesRight[dboRight].addChild(currentRight); currentRight.addParent(visitedNodesRight[dboRight]); } else { //create a new node and set currentRight = child currentNodeRight = new Node(dboRight); currentNodeRight.addChild(currentRight); //set currentNodeRight as parent of current Right currentRight.addParent(currentNodeRight); //never seen before //mark the node as visited visitedNodesRight.Add(currentNodeRight.Key, currentNodeRight); //and look what comes on the next level of depth queueRight.Enqueue(currentNodeRight); } #endregion check if already visited #region check how much paths are searched if (shortestOnly && !findAll) { if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } //if find all shortest paths else if (shortestOnly && findAll) { //set maxDepth to actual depth maxDepthLeft = depthLeft; maxDepthRight = depthRight; if ((depthLeft + depthRight) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight); } } #endregion check how much paths are searched } #endregion if the child is the target #region already visited else if (visitedNodesRight.ContainsKey(dboRight)) { //set found children visitedNodesRight[dboRight].addChild(currentRight); currentRight.addParent(visitedNodesRight[dboRight]); } #endregion already visited #region set as visited else { //create a new node and set currentRight = child currentNodeRight = new Node(dboRight); currentNodeRight.addChild(currentRight); //set currentNodeRight as parent of current Right currentRight.addParent(currentNodeRight); //never seen before //mark the node as visited visitedNodesRight.Add(currentNodeRight.Key, currentNodeRight); //and look what comes on the next level of depth queueRight.Enqueue(currentNodeRight); } #endregion set as visited } #endregion check right friends #region build intersection of visitedNodesLeft and visitedNodesRight //marks if intersection nodes are existing bool foundIntersect = false; foreach (var node in visitedNodesLeft) { if (visitedNodesRight[node.Key] != null) { //set nodes children and parents node.Value.addChildren(visitedNodesRight[node.Key].Children); node.Value.addParents(visitedNodesRight[node.Key].Parents); //set nodes children and parents visitedNodesRight[node.Key].addChildren(node.Value.Children); visitedNodesRight[node.Key].addParents(node.Value.Parents); foundIntersect = true; } } #endregion build intersection of visitedNodesLeft and visitedNodesRight #region analyze intersection //if intersection nodes existing if (foundIntersect) { //only shortest path if (shortestOnly && !findAll) { //_Logger.Info("found shortest path..starting analyzer"); if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } //if find all shortest paths else if (shortestOnly && findAll) { //set maxDepth to actual depth maxDepthLeft = depthLeft; maxDepthRight = depthRight; if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else if (shortestPathLength == 0) { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } } } #endregion analyze intersection } #endregion the edge and the backwardedge are existing #region only the edge exists else if (currentDBObjectLeft.Value.HasAttribute(myTypeAttribute.UUID, myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager))) { //get all referenced ObjectUUIDs using the given Edge var objectUUIDsLeft = (currentDBObjectLeft.Value.GetAttribute(myTypeAttribute.UUID) as ASetOfReferencesEdgeType).GetAllReferenceIDs(); Node currentNodeLeft; #region check left friends foreach (ObjectUUID dboLeft in objectUUIDsLeft) { #region if the child is the target if (dboLeft == myEnd.ObjectUUID) { target.addParent(currentLeft); #region check if already visited if (visitedNodesLeft.ContainsKey(dboLeft)) { //set currentLeft as parent visitedNodesLeft[dboLeft].addParent(currentLeft); //set currentNodeLeft as child currentLeft.addChild(visitedNodesLeft[dboLeft]); } else { //create a new node and set currentLeft = parent currentNodeLeft = new Node(dboLeft, currentLeft); //set currentNodeLeft as child of currentLeft currentLeft.addChild(currentNodeLeft); //never seen before //mark the node as visited visitedNodesLeft.Add(currentNodeLeft.Key, currentNodeLeft); //and put node into the queue queueLeft.Enqueue(currentNodeLeft); } #endregion check if already visited #region check how much paths are searched if (shortestOnly && !findAll) { //_Logger.Info("found shortest path..starting analyzer"); if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } else if (shortestOnly && findAll) { maxDepthLeft = depthLeft; shortestPathLength = Convert.ToByte(maxDepthLeft + maxDepthRight); } #endregion check if already visited } #endregion if the child is the target #region already visited from right side else if (visitedNodesRight.ContainsKey(dboLeft)) { //get node Node temp = visitedNodesRight[dboLeft]; //add parent new temp.addParent(currentLeft); //add as child currentLeft.addChild(temp); visitedNodesRight.Remove(temp.Key); visitedNodesRight.Add(temp.Key, temp); if (visitedNodesLeft.Remove(temp.Key)) { visitedNodesLeft.Add(temp.Key, temp); } if (shortestOnly && !findAll) { //_Logger.Info("found shortest path..starting analyzer"); if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } else if (shortestOnly && findAll) { maxDepthLeft = depthLeft; shortestPathLength = Convert.ToByte(maxDepthLeft + maxDepthRight); } } #endregion already visited from right side #region already visited else if (visitedNodesLeft.ContainsKey(dboLeft)) { //set found parents from left side as parents of matchNode //matchNode has now parents and children visitedNodesLeft[dboLeft].addParent(currentLeft); currentLeft.addChild(visitedNodesLeft[dboLeft]); } #endregion already visited #region set as visited else { //create a new node and set currentLeft = parent currentNodeLeft = new Node(dboLeft, currentLeft); //set currentNodeLeft as child of currentLeft currentLeft.addChild(currentNodeLeft); //never seen before //mark the node as visited visitedNodesLeft.Add(currentNodeLeft.Key, currentNodeLeft); //and look what comes on the next level of depth queueLeft.Enqueue(currentNodeLeft); } #endregion set as visited } #endregion check left friends } #endregion only the edge exists #region only the backwardedge exists else if (currentDBObjectRight.Value.ContainsBackwardEdge(edgeKey)) { //get all referenced ObjectUUIDs using the given Edge var objectUUIDsRight = currentDBObjectRight.Value.GetBackwardEdgeUUIDs(edgeKey); Node currentNodeRight; #region check right friends foreach (ObjectUUID dboRight in objectUUIDsRight) { #region if the child is the target if (rootFriends.Contains(dboRight)) { #region check if already visited //mark node as visited if (visitedNodesRight.ContainsKey(dboRight)) { //set found children visitedNodesRight[dboRight].addChild(currentRight); currentRight.addParent(visitedNodesRight[dboRight]); } else { //create a new node and set currentRight = child currentNodeRight = new Node(dboRight); currentNodeRight.addChild(currentRight); //set currentNodeRight as parent of current Right currentRight.addParent(currentNodeRight); //never seen before //mark the node as visited visitedNodesRight.Add(currentNodeRight.Key, currentNodeRight); //and look what comes on the next level of depth queueRight.Enqueue(currentNodeRight); } #endregion check if already visited #region check how much paths are searched if (shortestOnly && !findAll) { if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } else if (shortestOnly && findAll) { maxDepthRight = depthRight; shortestPathLength = Convert.ToByte(maxDepthLeft + maxDepthRight); } #endregion check how much paths are searched } #endregion if the child is the target #region already visited from left side else if (visitedNodesLeft.ContainsKey(dboRight)) { //get node Node temp = visitedNodesLeft[dboRight]; temp.addChild(currentRight); currentRight.addParent(temp); visitedNodesLeft.Remove(temp.Key); visitedNodesLeft.Add(temp.Key, temp); if (visitedNodesRight.Remove(temp.Key)) { visitedNodesRight.Add(temp.Key, temp); } if (shortestOnly && !findAll) { //_Logger.Info("found shortest path..starting analyzer"); if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } else if (shortestOnly && findAll) { maxDepthRight = depthRight; shortestPathLength = Convert.ToByte(maxDepthLeft + maxDepthRight); } } #endregion already visited from left side #region already visited else if (visitedNodesRight.ContainsKey(dboRight)) { //set found children visitedNodesRight[dboRight].addChild(currentRight); currentRight.addParent(visitedNodesRight[dboRight]); } #endregion already visited #region set as visited else { //create a new node and set currentRight = child currentNodeRight = new Node(dboRight); currentNodeRight.addChild(currentRight); //set currentNodeRight as parent of currentRight currentRight.addParent(currentNodeRight); //never seen before //mark the node as visited visitedNodesRight.Add(currentNodeRight.Key, currentNodeRight); //and look what comes on the next level of depth queueRight.Enqueue(currentNodeRight); } #endregion set as visited } #endregion check right friends } #endregion only the backwardedge exists } #endregion both queues contain objects and both depths are not reached #region only left queue contain objects else if ((queueLeft.Count > 0) && (depthLeft <= maxDepthLeft)) { #region check if first element of queue is a dummy //dummy if (queueLeft.First<Node>().Key == null) { queueLeft.Dequeue(); //_Logger.Info("going deeper in the dungeon on the left side.. current level: " + depthLeft); depthLeft++; if (queueLeft.Count == 0) { continue; } else if (depthLeft > maxDepthLeft) { continue; } } #endregion check if first element of queue is a dummy //get the first Object of the queue Node currentLeft = queueLeft.Dequeue(); //load DBObject currentDBObjectLeft = myDBContext.DBObjectCache.LoadDBObjectStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), currentLeft.Key); if (currentDBObjectLeft.Failed()) { throw new NotImplementedException(); } if (currentDBObjectLeft.Value.HasAttribute(myTypeAttribute.UUID, myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager))) { //get all referenced ObjectUUIDs using the given Edge var objectUUIDsLeft = (currentDBObjectLeft.Value.GetAttribute(myTypeAttribute.UUID) as ASetOfReferencesEdgeType).GetAllReferenceIDs(); Node currentNodeLeft; #region check left friends foreach (ObjectUUID dboLeft in objectUUIDsLeft) { #region if the child is the target if (dboLeft == myEnd.ObjectUUID) { target.addParent(currentLeft); #region check if already visited if (visitedNodesLeft.ContainsKey(dboLeft)) { //set currentLeft as parent visitedNodesLeft[dboLeft].addParent(currentLeft); //set currentNodeLeft as child currentLeft.addChild(visitedNodesLeft[dboLeft]); } else { //create a new node and set currentLeft = parent currentNodeLeft = new Node(dboLeft, currentLeft); //set currentNodeLeft as child of currentLeft currentLeft.addChild(currentNodeLeft); //never seen before //mark the node as visited visitedNodesLeft.Add(currentNodeLeft.Key, currentNodeLeft); //and put node into the queue queueLeft.Enqueue(currentNodeLeft); } #endregion check if already visited #region check how much paths are searched if (shortestOnly && !findAll) { //_Logger.Info("found shortest path..starting analyzer"); if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } else if (shortestOnly && findAll) { maxDepthLeft = depthLeft; shortestPathLength = Convert.ToByte(maxDepthLeft + maxDepthRight); } #endregion check how much paths are searched } #endregion if the child is the target #region already visited from right side else if (visitedNodesRight.ContainsKey(dboLeft)) { //get node Node temp = visitedNodesRight[dboLeft]; //add parent new temp.addParent(currentLeft); //add as child currentLeft.addChild(temp); visitedNodesRight.Remove(temp.Key); visitedNodesRight.Add(temp.Key, temp); if (visitedNodesLeft.Remove(temp.Key)) { visitedNodesLeft.Add(temp.Key, temp); } if (shortestOnly && !findAll) { //_Logger.Info("found shortest path..starting analyzer"); if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } else if (shortestOnly && findAll) { maxDepthLeft = depthLeft; if (shortestPathLength < (maxDepthLeft + maxDepthRight)) { shortestPathLength = Convert.ToByte(maxDepthLeft + maxDepthRight); } } } #endregion already visited from right side #region already visited else if (visitedNodesLeft.ContainsKey(dboLeft)) { //set found parents from left side as parents of matchNode //matchNode has now parents and children visitedNodesLeft[dboLeft].addParent(currentLeft); currentLeft.addChild(visitedNodesLeft[dboLeft]); } #endregion already visited #region set as visited else { //create a new node and set currentLeft = parent currentNodeLeft = new Node(dboLeft, currentLeft); currentLeft.addChild(currentNodeLeft); //never seen before //mark the node as visited visitedNodesLeft.Add(currentNodeLeft.Key, currentNodeLeft); //and look what comes on the next level of depth queueLeft.Enqueue(currentNodeLeft); } #endregion set as visited } #endregion check left friends } } #endregion only left queue contain objects #region only right queue contain objects else if ((queueRight.Count > 0) && (depthRight <= maxDepthRight)) { //get the first Object of the queue Node currentRight; #region check if first element of the queue is a dummy //dummy if (queueRight.First<Node>().Key == null) { queueRight.Dequeue(); //_Logger.Info("going deeper in the dungeon on the right side.. current level: " + depthRight); depthRight++; if (queueRight.Count == 0) { continue; } } #endregion check if first element of the queue is a dummy currentRight = queueRight.Dequeue(); //load DBObject currentDBObjectRight = myDBContext.DBObjectCache.LoadDBBackwardEdgeStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), currentRight.Key); if (currentDBObjectRight.Failed()) { throw new NotImplementedException(); } if (currentDBObjectRight.Value.ContainsBackwardEdge(edgeKey)) { //get all referenced ObjectUUIDs using the given Edge var objectUUIDsRight = currentDBObjectRight.Value.GetBackwardEdgeUUIDs(edgeKey); Node currentNodeRight; #region check right friends foreach (ObjectUUID dboRight in objectUUIDsRight) { #region if the child is the target if (rootFriends.Contains(dboRight)) { #region check if already visited //mark node as visited if (visitedNodesRight.ContainsKey(dboRight)) { //set found children visitedNodesRight[dboRight].addChild(currentRight); currentRight.addParent(visitedNodesRight[dboRight]); } else { //create a new node and set currentRight = child currentNodeRight = new Node(dboRight); currentNodeRight.addChild(currentRight); //set currentNodeRight as parent of current Right currentRight.addParent(currentNodeRight); //never seen before //mark the node as visited visitedNodesRight.Add(currentNodeRight.Key, currentNodeRight); //and look what comes on the next level of depth queueRight.Enqueue(currentNodeRight); } #endregion check if already visited #region check how much paths are searched if (shortestOnly && !findAll) { //_Logger.Info("found shortest path..starting analyzer"); shortestPathLength = Convert.ToByte(depthLeft + depthRight); return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } else if (shortestOnly && findAll) { maxDepthRight = depthRight; shortestPathLength = Convert.ToByte(maxDepthLeft + maxDepthRight); } #endregion check how much paths are searched } #endregion if the child is the target #region already visited from left side else if (visitedNodesLeft.ContainsKey(dboRight)) { //get node Node temp = visitedNodesLeft[dboRight]; temp.addChild(currentRight); currentRight.addParent(temp); visitedNodesLeft.Remove(temp.Key); visitedNodesLeft.Add(temp.Key, temp); if (visitedNodesRight.Remove(temp.Key)) { visitedNodesRight.Add(temp.Key, temp); } if (shortestOnly && !findAll) { //_Logger.Info("found shortest path..starting analyzer"); if ((depthLeft + depthRight + 1) > myMaxPathLength) { shortestPathLength = myMaxPathLength; } else { shortestPathLength = Convert.ToByte(depthLeft + depthRight + 1); } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } else if (shortestOnly && findAll) { maxDepthRight = depthRight; shortestPathLength = Convert.ToByte(maxDepthLeft + maxDepthRight); } } #endregion already visited from left side #region already visited else if (visitedNodesRight.ContainsKey(dboRight)) { //set found children visitedNodesRight[dboRight].addChild(currentRight); currentRight.addParent(visitedNodesRight[dboRight]); } #endregion already visited #region set as visited else { //create a new node and set currentRight = child currentNodeRight = new Node(dboRight); currentNodeRight.addChild(currentRight); currentRight.addParent(currentNodeRight); //never seen before //mark the node as visited visitedNodesRight.Add(currentNodeRight.Key, currentNodeRight); //and look what comes on the next level of depth queueRight.Enqueue(currentNodeRight); } #endregion set as visited } #endregion check right friends } } #endregion only right queue contain objects #region abort loop else { break; } #endregion abort loop } } #endregion EdgeType is ASetReferenceEdgeType //check if the EdgeType is ASingleReferenceEdgeType #region EdgeType is ASingleReferenceEdgeType else if (myEdge is ASingleReferenceEdgeType) { #region initialize variables //if the maxDepth is greater then maxPathLength, then set maxDepth to maxPathLength if (myMaxDepth > myMaxPathLength) { myMaxDepth = myMaxPathLength; } //set depth for left side maxDepthLeft = myMaxDepth; #endregion initialize variables #region check if friends of root node have edge foreach (var node in visitedNodesLeft) { var dbo = myDBContext.DBObjectCache.LoadDBObjectStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), node.Key); if (dbo.Failed()) { if (visitedNodesLeft.Count != 0) { visitedNodesLeft.Remove(node.Key); } else { throw new NotImplementedException(); } } if (!dbo.Value.HasAttribute(myTypeAttribute.UUID, myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager))) { if (visitedNodesLeft.Count != 0) { visitedNodesLeft.Remove(node.Key); } else { return null; } } } #endregion check if friends of root node have edge //if there is more than one object in the queue and the actual depth is less than MaxDepth while ((queueLeft.Count > 0) && (depthLeft <= maxDepthLeft)) { #region check if first element of queue is a dummy //dummy if (queueLeft.First<Node>().Key == null) { queueLeft.Dequeue(); //_Logger.Info("going deeper in the dungeon on the left side.. current level: " + depthLeft); depthLeft++; if ((queueLeft.Count == 0) || (depthLeft > maxDepthLeft)) { break; } else { queueLeft.Enqueue(dummyLeft); continue; } } #endregion check if first element of queue is a dummy #region load DBObject //get the first Object of the queue var currentLeft = queueLeft.Dequeue(); //load DBObject currentDBObjectLeft = myDBContext.DBObjectCache.LoadDBObjectStream(myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager), currentLeft.Key); if (currentDBObjectLeft.Failed()) { throw new NotImplementedException(); } #endregion load DBObject #region check if currentDBObjectLeft has attribute if (currentDBObjectLeft.Value.HasAttribute(myTypeAttribute.UUID, myTypeAttribute.GetRelatedType(myDBContext.DBTypeManager))) { //get referenced ObjectUUID using the given Edge var objectUUIDsLeft = (currentDBObjectLeft.Value.GetAttribute(myTypeAttribute.UUID) as ASingleReferenceEdgeType).GetAllReferenceIDs(); Node currentNodeLeft; #region check left friend var dboLeft = objectUUIDsLeft.First(); //create a new node and set currentLeft = parent currentNodeLeft = new Node(dboLeft, currentLeft); #region if the child is the target if (currentNodeLeft.Key == myEnd.ObjectUUID) { //set currentLeft as parent of target target.addParent(currentLeft); //shortestPathLength is actual depth of left side plus 1 (because the depth starts with zero, but the pathLength with 1) shortestPathLength = Convert.ToByte(depthLeft + 1); return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } #endregion if the child is the target #region already visited else if (visitedNodesLeft.ContainsKey(currentNodeLeft.Key)) { //set currentLeft as parent visitedNodesLeft[currentNodeLeft.Key].addParent(currentLeft); //set currentNodeLeft as child currentLeft.addChild(visitedNodesLeft[currentNodeLeft.Key]); } #endregion already visited #region set as visited else { //set currentNodeLeft as child of currentLeft currentLeft.addChild(currentNodeLeft); //never seen before //mark the node as visited visitedNodesLeft.Add(currentNodeLeft.Key, currentNodeLeft); //and put node into the queue queueLeft.Enqueue(currentNodeLeft); } #endregion set as visited #endregion check left friend } #endregion check if currentDBObjectLeft has attribute #region abort loop else { break; } #endregion abort loop } } #endregion EdgeType is ASingleReferenceEdgeType else { throw new NotImplementedException(); } #region start TargetAnalyzer if (shortestOnly && findAll) { if (shortestPathLength > myMaxPathLength) { shortestPathLength = myMaxPathLength; } return new TargetAnalyzer(root, rootFriends, target, shortestPathLength, shortestOnly, findAll).getPaths(); } else { return new TargetAnalyzer(root, rootFriends, target, myMaxPathLength, shortestOnly, findAll).getPaths(); } #endregion start TargetAnalyzer #endregion BidirectionalBFS }