/// <summary> /// Returns a list of references that match the direction and reference type. /// </summary> /// <param name="referenceTypeId">The reference type identifier.</param> /// <param name="isInverse">if set to <c>true</c> this is inverse reference.</param> /// <returns>A list of references that match the direction and reference type.</returns> public IList <IReference> Find( NodeId referenceTypeId, bool isInverse) { List <IReference> hits = new List <IReference>(); // check for null. if (NodeId.IsNull(referenceTypeId)) { return(hits); } // look up the reference type. ReferenceTypeEntry entry = null; if (!m_references.TryGetValue(referenceTypeId, out entry)) { return(hits); } // find the references. Find(entry, isInverse, hits); return(hits); }
/// <summary> /// Checks the isInverse flag are returns true if a specified target exists. /// </summary> /// <param name="entry">The entry.</param> /// <param name="reference">The reference.</param> /// <returns> /// <c>true</c> if the specified entry contains key; otherwise, <c>false</c>. /// </returns> private static bool ContainsKey(ReferenceTypeEntry entry, IReference reference) { // handle reference to external targets. if (reference.TargetId.IsAbsolute) { Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (reference.IsInverse) { targets = entry.InverseExternalTargets; } else { targets = entry.ForwardExternalTargets; } if (targets == null) { return(false); } return(targets.ContainsKey(reference.TargetId)); } // handle reference to internal target. else { NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (reference.IsInverse) { targets = entry.InverseTargets; } else { targets = entry.ForwardTargets; } if (targets == null) { return(false); } return(targets.ContainsKey((NodeId)reference.TargetId)); } }
/// <summary> /// Add references to a list that match the criteria. /// </summary> /// <param name="entry">The entry.</param> /// <param name="isInverse">if set to <c>true</c> this is inverse reference.</param> /// <param name="hits">The hits.</param> private static void Find( ReferenceTypeEntry entry, bool isInverse, List <IReference> hits) { if (isInverse) { if (entry.InverseTargets != null) { foreach (LinkedListNode <KeyValuePair <IReference, T> > target in entry.InverseTargets.Values) { hits.Add(target.Value.Key); } } if (entry.InverseExternalTargets != null) { foreach (LinkedListNode <KeyValuePair <IReference, T> > target in entry.InverseExternalTargets.Values ) { hits.Add(target.Value.Key); } } } else { if (entry.ForwardTargets != null) { foreach (LinkedListNode <KeyValuePair <IReference, T> > target in entry.ForwardTargets.Values) { hits.Add(target.Value.Key); } } if (entry.ForwardExternalTargets != null) { foreach (LinkedListNode <KeyValuePair <IReference, T> > target in entry.ForwardExternalTargets.Values ) { hits.Add(target.Value.Key); } } } }
/// <summary cref="IDictionary.Remove" /> public bool Remove(IReference key) { // validate key. if (!ValidateReference(key, false)) { return(false); } m_version++; // look up the reference type. ReferenceTypeEntry entry = null; if (!m_references.TryGetValue(key.ReferenceTypeId, out entry)) { return(false); } // handle reference to external targets. if (key.TargetId.IsAbsolute) { Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { targets = entry.InverseExternalTargets; } else { targets = entry.ForwardExternalTargets; } if (targets == null) { return(false); } LinkedListNode <KeyValuePair <IReference, T> > node; if (!targets.TryGetValue(key.TargetId, out node)) { return(false); } m_list.Remove(node); targets.Remove(key.TargetId); } // handle reference to internal target. else { NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { targets = entry.InverseTargets; } else { targets = entry.ForwardTargets; } if (targets == null) { return(false); } LinkedListNode <KeyValuePair <IReference, T> > node; if (!targets.TryGetValue((NodeId)key.TargetId, out node)) { return(false); } m_list.Remove(node); targets.Remove((NodeId)key.TargetId); } // remove empty reference. if (entry.IsEmpty) { m_references.Remove(key.ReferenceTypeId); } return(true); }
/// <summary> /// Removes all of the references of the specified type and direction. /// </summary> /// <param name="referenceTypeId">The reference type identifier.</param> /// <param name="isInverse">if set to <c>true</c> this is inverse reference.</param> /// <returns>The result of removal.</returns> public bool RemoveAll(NodeId referenceTypeId, bool isInverse) { // check for null. if (NodeId.IsNull(referenceTypeId)) { return(false); } // look up the reference type. ReferenceTypeEntry entry = null; if (!m_references.TryGetValue(referenceTypeId, out entry)) { return(false); } if (isInverse) { if (entry.InverseTargets != null) { foreach (LinkedListNode <KeyValuePair <IReference, T> > node in entry.InverseTargets.Values) { if (Object.ReferenceEquals(m_list, node.List)) { m_list.Remove(node); } entry.InverseTargets = null; } } if (entry.InverseExternalTargets != null) { foreach (LinkedListNode <KeyValuePair <IReference, T> > node in entry.InverseExternalTargets.Values) { if (Object.ReferenceEquals(m_list, node.List)) { m_list.Remove(node); } } entry.InverseExternalTargets = null; } } else { if (entry.ForwardTargets != null) { foreach (LinkedListNode <KeyValuePair <IReference, T> > node in entry.ForwardTargets.Values) { if (Object.ReferenceEquals(m_list, node.List)) { m_list.Remove(node); } } entry.ForwardTargets = null; } if (entry.ForwardExternalTargets != null) { foreach (LinkedListNode <KeyValuePair <IReference, T> > node in entry.ForwardExternalTargets.Values) { if (Object.ReferenceEquals(m_list, node.List)) { m_list.Remove(node); } } entry.ForwardExternalTargets = null; } } // check for empty set. if (entry.IsEmpty) { m_references.Remove(referenceTypeId); } return(true); }
/// <summary> /// Adds or replaces a reference. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <param name="replace">if set to <c>true</c> reference is replaced.</param> private void Add(IReference key, T value, bool replace) { // validate key. ValidateReference(key, true); m_version++; // look up the reference type. ReferenceTypeEntry entry = null; if (!m_references.TryGetValue(key.ReferenceTypeId, out entry)) { entry = new ReferenceTypeEntry(); m_references.Add(key.ReferenceTypeId, entry); } // handle reference to external targets. if (key.TargetId.IsAbsolute) { Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { if (entry.InverseExternalTargets == null) { entry.InverseExternalTargets = new Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > >(); } targets = entry.InverseExternalTargets; } else { if (entry.ForwardExternalTargets == null) { entry.ForwardExternalTargets = new Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > >(); } targets = entry.ForwardExternalTargets; } // create a new target. LinkedListNode <KeyValuePair <IReference, T> > node = new LinkedListNode <KeyValuePair <IReference, T> >(new KeyValuePair <IReference, T>(key, value)); // check if target already exists. LinkedListNode <KeyValuePair <IReference, T> > existingNode = null; if (!targets.TryGetValue(key.TargetId, out existingNode)) { existingNode = node; m_list.AddLast(node); } // need to replace reference in linked linked as well as the target list. else { if (!replace) { throw new ArgumentException("Key already exists in dictionary.", "key"); } m_list.AddAfter(existingNode, node); m_list.Remove(existingNode); } targets[key.TargetId] = node; } // handle reference to internal target. else { NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { if (entry.InverseTargets == null) { entry.InverseTargets = new NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > >(); } targets = entry.InverseTargets; } else { if (entry.ForwardTargets == null) { entry.ForwardTargets = new NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > >(); } targets = entry.ForwardTargets; } NodeId targetId = (NodeId)key.TargetId; // create a new target. LinkedListNode <KeyValuePair <IReference, T> > node = new LinkedListNode <KeyValuePair <IReference, T> >(new KeyValuePair <IReference, T>(key, value)); // check if target already exists. LinkedListNode <KeyValuePair <IReference, T> > existingNode = null; if (!targets.TryGetValue(targetId, out existingNode)) { existingNode = node; m_list.AddLast(node); } // need to replace reference in linked linked as well as the target list. else { if (!replace) { throw new ArgumentException("Key already exists in dictionary.", "key"); } m_list.AddAfter(existingNode, node); m_list.Remove(existingNode); } targets[targetId] = node; } }
/// <summary> /// Returns the target entry associated with the reference. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns>The target entry associated with the reference.</returns> private bool TryGetEntry(IReference key, out KeyValuePair <IReference, T> value) { value = new KeyValuePair <IReference, T>(); // validate key. if (!ValidateReference(key, false)) { return(false); } // look up the reference type. ReferenceTypeEntry entry = null; if (!m_references.TryGetValue(key.ReferenceTypeId, out entry)) { return(false); } // handle reference to external targets. if (key.TargetId.IsAbsolute) { Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { targets = entry.InverseExternalTargets; } else { targets = entry.ForwardExternalTargets; } if (targets == null) { return(false); } LinkedListNode <KeyValuePair <IReference, T> > node; if (targets.TryGetValue(key.TargetId, out node)) { value = node.Value; return(true); } } // handle reference to internal target. else { NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { targets = entry.InverseTargets; } else { targets = entry.ForwardTargets; } if (targets == null) { return(false); } LinkedListNode <KeyValuePair <IReference, T> > node; if (targets.TryGetValue((NodeId)key.TargetId, out node)) { value = node.Value; return(true); } } return(false); }