/// <summary> /// Returns a list of references to the specified target. /// </summary> /// <param name="targetId">The target identifier.</param> /// <returns>A list of references to the specified target.</returns> public IList <IReference> FindReferencesToTarget(ExpandedNodeId targetId) { List <IReference> hits = new List <IReference>(); // check for null. if (NodeId.IsNull(targetId)) { return(hits); } // go throw list of references. for (LinkedListNode <KeyValuePair <IReference, T> > node = m_list.First; node != null; node = node.Next) { if (node.Value.Key.TargetId == targetId) { hits.Add(node.Value.Key); } } return(hits); }
/// <summary> /// Returns true if the reference type is required. /// </summary> public virtual bool IsRequired(NodeId referenceType, bool isInverse) { if (NodeId.IsNull(referenceType)) { return(false); } // easiet to check inverse flag first. if (isInverse) { if (m_browseDirection == BrowseDirection.Forward) { return(false); } } else { if (m_browseDirection == BrowseDirection.Inverse) { return(false); } } // check for no filter or exact match. if (NodeId.IsNull(m_referenceType) || referenceType == m_referenceType) { return(true); } // check subtypes if possible. if (m_includeSubtypes && m_context != null) { if (m_context.TypeTable.IsTypeOf(referenceType, m_referenceType)) { return(true); } } return(false); }
/// <summary> /// Removes a view from the table. /// </summary> /// <param name="viewId">The view identifier.</param> public void Remove(NodeId viewId) { if (NodeId.IsNull(viewId)) { throw new ArgumentNullException("viewId"); } lock (m_lock) { // find view. ViewNode view = null; if (!m_views.TryGetValue(viewId, out view)) { throw new ServiceResultException( StatusCodes.BadViewIdUnknown, Utils.Format("A reference type with the node id '{0}' does not exist.", viewId)); } // remove view node. m_views.Remove(viewId); } }
/// <summary> /// Validates a read value id parameter. /// </summary> public static ServiceResult Validate(HistoryReadValueId valueId) { // check for null structure. if (valueId == null) { return(StatusCodes.BadStructureMissing); } // null node ids are always invalid. if (NodeId.IsNull(valueId.NodeId)) { return(StatusCodes.BadNodeIdInvalid); } // initialize as empty. valueId.ParsedIndexRange = NumericRange.Empty; // parse the index range if specified. if (!String.IsNullOrEmpty(valueId.IndexRange)) { try { valueId.ParsedIndexRange = NumericRange.Parse(valueId.IndexRange); } catch (Exception e) { return(ServiceResult.Create(e, StatusCodes.BadIndexRangeInvalid, String.Empty)); } } else { valueId.ParsedIndexRange = NumericRange.Empty; } // passed basic validation. return(null); }
/// <summary> /// Updates the nodeset string tables and returns a NodeId that references those tables. /// </summary> /// <param name="nodeId">The node identifier.</param> /// <param name="targetNamespaceUris">The target namespace URIs.</param> /// <param name="sourceNamespaceUris">The source namespace URIs.</param> /// <returns>A NodeId that references those tables.</returns> private static NodeId Translate( NodeId nodeId, NamespaceTable targetNamespaceUris, NamespaceTable sourceNamespaceUris) { if (targetNamespaceUris == null) { throw new ArgumentNullException("targetNamespaceUris"); } if (sourceNamespaceUris == null) { throw new ArgumentNullException("sourceNamespaceUris"); } if (NodeId.IsNull(nodeId)) { return(nodeId); } ushort namespaceIndex = 0; if (nodeId.NamespaceIndex > 0) { string uri = sourceNamespaceUris.GetString(nodeId.NamespaceIndex); int index = targetNamespaceUris.GetIndex(uri); if (index == -1) { index = targetNamespaceUris.Append(uri); } namespaceIndex = (ushort)index; } return(new NodeId(nodeId.Identifier, namespaceIndex)); }
/// <summary> /// Exports a copt of the node to a node table. /// </summary> /// <param name="context">The context.</param> /// <param name="node">The node.</param> protected override void Export(ISystemContext context, Node node) { base.Export(context, node); if (!NodeId.IsNull(this.SuperTypeId)) { node.ReferenceTable.Add(ReferenceTypeIds.HasSubtype, true, this.SuperTypeId); } switch (this.NodeClass) { case NodeClass.ObjectType: { ((ObjectTypeNode)node).IsAbstract = IsAbstract; break; } case NodeClass.VariableType: { ((VariableTypeNode)node).IsAbstract = IsAbstract; break; } case NodeClass.DataType: { ((DataTypeNode)node).IsAbstract = IsAbstract; break; } case NodeClass.ReferenceType: { ((ReferenceTypeNode)node).IsAbstract = IsAbstract; break; } } }
/// <summary> /// Adds a node to the type table if it is a type and does not already exist. If it exists references are updated. /// </summary> /// <param name="node">The node.</param> public void Add(ILocalNode node) { // ignore null. if (node == null || NodeId.IsNull(node.NodeId)) { return; } // ignore non-types. if ((node.NodeClass & (NodeClass.ObjectType | NodeClass.VariableType | NodeClass.ReferenceType | NodeClass.DataType)) == 0) { return; } NodeId localsuperTypeId = null; // find the supertype. ExpandedNodeId superTypeId = node.References.FindTarget(ReferenceTypeIds.HasSubtype, true, false, null, 0); if (superTypeId != null) { localsuperTypeId = ExpandedNodeId.ToNodeId(superTypeId, m_namespaceUris); if (localsuperTypeId == null) { throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "A valid supertype identifier is required."); } } lock (m_lock) { // lookup the supertype. TypeInfo superTypeInfo = null; if (localsuperTypeId != null) { if (!m_nodes.TryGetValue(localsuperTypeId, out superTypeInfo)) { throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "A valid supertype identifier is required."); } } // create the type info. TypeInfo typeInfo = null; if (!m_nodes.TryGetValue(node.NodeId, out typeInfo)) { typeInfo = new TypeInfo(); m_nodes.Add(node.NodeId, typeInfo); } // update the info. typeInfo.NodeId = node.NodeId; typeInfo.SuperType = superTypeInfo; typeInfo.Deleted = false; // add to supertype. if (superTypeInfo != null) { superTypeInfo.AddSubType(typeInfo); } // remove the encodings. if (typeInfo.Encodings != null) { foreach (NodeId encoding in typeInfo.Encodings) { m_encodings.Remove(encoding); } } // any new encodings. IList <IReference> encodings = node.References.Find(ReferenceTypeIds.HasEncoding, false, false, null); if (encodings.Count > 0) { typeInfo.Encodings = new NodeId[encodings.Count]; for (int ii = 0; ii < encodings.Count; ii++) { typeInfo.Encodings[ii] = ExpandedNodeId.ToNodeId(encodings[ii].TargetId, m_namespaceUris); m_encodings[typeInfo.Encodings[ii]] = typeInfo; } } // add reference type. if ((node.NodeClass & NodeClass.ReferenceType) != 0) { if (!QualifiedName.IsNull(typeInfo.BrowseName)) { m_referenceTypes.Remove(typeInfo.BrowseName); } typeInfo.BrowseName = node.BrowseName; m_referenceTypes[node.BrowseName] = typeInfo; } } }
/// <summary> /// Creates a new instance. /// </summary> /// <param name="context">The current context.</param> /// <param name="parent">The parent.</param> /// <param name="nodeClass">The node class.</param> /// <param name="browseName">The browse name.</param> /// <param name="referenceTypeId">The reference type between the parent and the node.</param> /// <param name="typeDefinitionId">The type definition.</param> /// <returns>Returns null if the type is not known.</returns> public virtual NodeState CreateInstance( ISystemContext context, NodeState parent, NodeClass nodeClass, QualifiedName browseName, NodeId referenceTypeId, NodeId typeDefinitionId) { NodeState child = null; if (m_types != null && !NodeId.IsNull(typeDefinitionId)) { Type type = null; if (m_types.TryGetValue(typeDefinitionId, out type)) { return(Activator.CreateInstance(type, parent) as NodeState); } } switch (nodeClass) { case NodeClass.Variable: { if (context.TypeTable != null && context.TypeTable.IsTypeOf(referenceTypeId, ReferenceTypeIds.HasProperty)) { child = new PropertyState(parent); break; } child = new BaseDataVariableState(parent); break; } case NodeClass.Object: { child = new BaseObjectState(parent); break; } case NodeClass.Method: { child = new MethodState(parent); break; } case NodeClass.ReferenceType: { child = new ReferenceTypeState(); break; } case NodeClass.ObjectType: { child = new BaseObjectTypeState(); break; } case NodeClass.VariableType: { child = new BaseDataVariableTypeState(); break; } case NodeClass.DataType: { child = new DataTypeState(); break; } case NodeClass.View: { child = new ViewState(); break; } default: { child = null; break; } } return(child); }
/// <summary> /// Parses a relative path formatted as a string. /// </summary> public static RelativePath Parse(string browsePath, ITypeTable typeTree) { if (typeTree == null) { throw new ArgumentNullException("typeTree"); } // parse the string. RelativePathFormatter formatter = RelativePathFormatter.Parse(browsePath); // convert the browse names to node ids. RelativePath relativePath = new RelativePath(); foreach (RelativePathFormatter.Element element in formatter.Elements) { RelativePathElement parsedElement = new RelativePathElement(); parsedElement.ReferenceTypeId = null; parsedElement.IsInverse = false; parsedElement.IncludeSubtypes = element.IncludeSubtypes; parsedElement.TargetName = element.TargetName; switch (element.ElementType) { case RelativePathFormatter.ElementType.AnyHierarchical: { parsedElement.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences; break; } case RelativePathFormatter.ElementType.AnyComponent: { parsedElement.ReferenceTypeId = ReferenceTypeIds.Aggregates; break; } case RelativePathFormatter.ElementType.ForwardReference: { parsedElement.ReferenceTypeId = typeTree.FindReferenceType(element.ReferenceTypeName); break; } case RelativePathFormatter.ElementType.InverseReference: { parsedElement.ReferenceTypeId = typeTree.FindReferenceType(element.ReferenceTypeName); parsedElement.IsInverse = true; break; } } if (NodeId.IsNull(parsedElement.ReferenceTypeId)) { throw ServiceResultException.Create( StatusCodes.BadSyntaxError, "Could not convert BrowseName to a ReferenceTypeId: {0}", element.ReferenceTypeName); } relativePath.Elements.Add(parsedElement); } return(relativePath); }
/// <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 a node to the table (takes ownership of the object passed in). /// </summary> /// <param name="node">The node.</param> /// <remarks> /// Any existing node is removed. /// </remarks> public void Attach(ILocalNode node) { // remove duplicates. if (Exists(node.NodeId)) { Remove(node.NodeId); } // check if importing a node from a XML source (must copy references from References array to ReferenceTable). Node serializedNode = node as Node; if (serializedNode != null && serializedNode.References.Count > 0 && serializedNode.ReferenceTable.Count == 0) { // index references. foreach (ReferenceNode reference in node.References) { // ignore invalid references. if (NodeId.IsNull(reference.ReferenceTypeId) || NodeId.IsNull(reference.TargetId)) { continue; } node.References.Add(reference.ReferenceTypeId, reference.IsInverse, reference.TargetId); // see if a remote node needs to be created. if (reference.TargetId.ServerIndex != 0) { RemoteNode remoteNode = Find(reference.TargetId) as RemoteNode; if (remoteNode == null) { remoteNode = new RemoteNode(this, reference.TargetId); InternalAdd(remoteNode); } remoteNode.AddRef(); } } // clear unindexed reference list. node.References.Clear(); } // add the node to the table. InternalAdd(node); // add reverse references. foreach (IReference reference in node.References) { ILocalNode targetNode = Find(reference.TargetId) as ILocalNode; if (targetNode == null) { continue; } // type definition and modelling rule references are one way. if (reference.ReferenceTypeId != ReferenceTypeIds.HasTypeDefinition && reference.ReferenceTypeId != ReferenceTypeIds.HasModellingRule) { targetNode.References.Add(reference.ReferenceTypeId, !reference.IsInverse, node.NodeId); } } // see if it is a type. if (m_typeTree != null) { m_typeTree.Add(node); } }
/// <summary> /// Adds a set of nodes to the table. /// </summary> /// <param name="nodeSet">The node set.</param> /// <param name="externalReferences">The external references.</param> /// <returns></returns> public List <Node> Import(NodeSet nodeSet, IDictionary <NodeId, IList <IReference> > externalReferences) { List <Node> importedNodes = new List <Node>(); if (nodeSet == null) { return(importedNodes); } // add the nodes. foreach (Node nodeToImport in nodeSet.Nodes) { // ignore empty nodes. if (nodeToImport == null || NodeId.IsNull(nodeToImport.NodeId)) { continue; } Node node = nodeSet.Copy(nodeToImport, m_namespaceUris, m_serverUris); // assign a browse name. if (QualifiedName.IsNull(node.BrowseName)) { node.BrowseName = new QualifiedName(node.NodeId.ToString(), 1); } // assign a display name. if (LocalizedText.IsNullOrEmpty(node.DisplayName)) { node.DisplayName = new LocalizedText(node.BrowseName.Name); } // index references (the node ids in the references were translated by the Copy() call above). foreach (ReferenceNode reference in node.References) { // ignore invalid references. if (NodeId.IsNull(reference.ReferenceTypeId) || NodeId.IsNull(reference.TargetId)) { continue; } // ignore missing targets. ExpandedNodeId targetId = reference.TargetId; if (NodeId.IsNull(targetId)) { continue; } // index reference. node.ReferenceTable.Add(reference.ReferenceTypeId, reference.IsInverse, targetId); // see if a remote node needs to be created. if (targetId.ServerIndex != 0) { RemoteNode remoteNode = Find(targetId) as RemoteNode; if (remoteNode == null) { remoteNode = new RemoteNode(this, targetId); InternalAdd(remoteNode); } remoteNode.AddRef(); } } // clear imported references. node.References.Clear(); // add the node. InternalAdd(node); importedNodes.Add(node); } // import the nodes. foreach (Node node in importedNodes) { // ignore invalid nodes. if (node == null || NodeId.IsNull(node.NodeId)) { continue; } // add reverse references. foreach (IReference reference in node.ReferenceTable) { Node targetNode = Find(reference.TargetId) as Node; if (targetNode == null) { if (reference.TargetId.ServerIndex != 0) { continue; } // return the reverse reference to a node outside the table. if (externalReferences != null) { NodeId targetId = ExpandedNodeId.ToNodeId(reference.TargetId, m_namespaceUris); if (targetId == null) { continue; } IList <IReference> referenceList = null; if (!externalReferences.TryGetValue(targetId, out referenceList)) { externalReferences[targetId] = referenceList = new List <IReference>(); } ReferenceNode reverseReference = new ReferenceNode(); reverseReference.ReferenceTypeId = reference.ReferenceTypeId; reverseReference.IsInverse = !reference.IsInverse; reverseReference.TargetId = node.NodeId; referenceList.Add(reverseReference); } continue; } // type definition and modelling rule references are one way. if (reference.ReferenceTypeId != ReferenceTypeIds.HasTypeDefinition && reference.ReferenceTypeId != ReferenceTypeIds.HasModellingRule) { targetNode.ReferenceTable.Add(reference.ReferenceTypeId, !reference.IsInverse, node.NodeId); } } // see if it is a type. if (m_typeTree != null) { m_typeTree.Add(node); } } return(importedNodes); }
/// <summary> /// Updates the nodeset string tables and returns a NodeId that references those tables. /// </summary> /// <param name="nodeId">The node identifier.</param> /// <param name="targetNamespaceUris">The target namespace URIs.</param> /// <param name="targetServerUris">The target server URIs.</param> /// <param name="sourceNamespaceUris">The source namespace URIs.</param> /// <param name="sourceServerUris">The source server URIs.</param> /// <returns>A NodeId that references those tables.</returns> private static ExpandedNodeId Translate( ExpandedNodeId nodeId, NamespaceTable targetNamespaceUris, StringTable targetServerUris, NamespaceTable sourceNamespaceUris, StringTable sourceServerUris) { if (targetNamespaceUris == null) { throw new ArgumentNullException("targetNamespaceUris"); } if (sourceNamespaceUris == null) { throw new ArgumentNullException("sourceNamespaceUris"); } if (nodeId.ServerIndex > 0) { if (targetServerUris == null) { throw new ArgumentNullException("targetServerUris"); } if (sourceServerUris == null) { throw new ArgumentNullException("sourceServerUris"); } } if (NodeId.IsNull(nodeId)) { return(nodeId); } if (!nodeId.IsAbsolute) { return(Translate((NodeId)nodeId, targetNamespaceUris, sourceNamespaceUris)); } string namespaceUri = nodeId.NamespaceUri; if (nodeId.ServerIndex > 0) { if (String.IsNullOrEmpty(namespaceUri)) { namespaceUri = sourceNamespaceUris.GetString(nodeId.NamespaceIndex); } string serverUri = sourceServerUris.GetString(nodeId.ServerIndex); int index = targetServerUris.GetIndex(serverUri); if (index == -1) { index = targetServerUris.Append(serverUri); } return(new ExpandedNodeId(new NodeId(nodeId.Identifier, 0), namespaceUri, (uint)index)); } ushort namespaceIndex = 0; if (!String.IsNullOrEmpty(namespaceUri)) { int index = targetNamespaceUris.GetIndex(namespaceUri); if (index == -1) { index = targetNamespaceUris.Append(namespaceUri); } namespaceIndex = (ushort)index; } return(new NodeId(nodeId.Identifier, namespaceIndex)); }
/// <summary> /// Returns the string representation of the embededobject. /// </summary> /// <param name="format">(Unused). Leave this as null</param> /// <param name="formatProvider">The provider of a mechanism for retrieving an object to control formatting.</param> /// <returns> /// A <see cref="T:System.String"/> containing the value of the current embeded instance in the specified format. /// </returns> /// <exception cref="FormatException">Thrown if the <i>format</i> parameter is not null</exception> public string ToString(string format, IFormatProvider formatProvider) { if (format == null) { if (m_body is byte[]) { return(String.Format(formatProvider, "Byte[{0}]", ((byte[])m_body).Length)); } if (m_body is XmlElement) { return(String.Format(formatProvider, "<{0}>", ((XmlElement)m_body).Name)); } if (m_body is IEncodeable) { StringBuilder body = new StringBuilder(); PropertyInfo[] properties = m_body.GetType().GetProperties(BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance); foreach (PropertyInfo property in properties) { object[] attributes = property.GetCustomAttributes(typeof(DataMemberAttribute), true); for (int ii = 0; ii < attributes.Length; ii++) { DataMemberAttribute contract = attributes[ii] as DataMemberAttribute; if (contract != null) { if (body.Length == 0) { body.Append("{"); } else { body.Append(" | "); } body.AppendFormat("{0}", property.GetGetMethod().Invoke(m_body, null)); } } } if (body.Length > 0) { body.Append("}"); } return(String.Format(formatProvider, "{0}", body)); } if (!NodeId.IsNull(this.m_typeId)) { return(String.Format(formatProvider, "{{{0}}}", this.m_typeId)); } return("(null)"); } throw new FormatException(Utils.Format("Invalid format string: '{0}'.", format)); }