Beispiel #1
0
        /// <summary>
        /// Validates a read value id parameter.
        /// </summary>
        public static ServiceResult Validate(ReadValueId valueId)
        {
            // check for null structure.
            if (valueId == null)
            {
                return(StatusCodes.BadStructureMissing);
            }

            // null node ids are always invalid.
            if (valueId.NodeId == null)
            {
                return(StatusCodes.BadNodeIdInvalid);
            }

            // must be a legimate attribute value.
            if (!Attributes.IsValid(valueId.AttributeId))
            {
                return(StatusCodes.BadAttributeIdInvalid);
            }

            // data encoding and index range is only valid for value attributes.
            if (valueId.AttributeId != Attributes.Value)
            {
                if (!String.IsNullOrEmpty(valueId.IndexRange))
                {
                    return(StatusCodes.BadIndexRangeNoData);
                }

                if (!QualifiedName.IsNull(valueId.DataEncoding))
                {
                    return(StatusCodes.BadDataEncodingInvalid);
                }
            }

            // 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>
        /// Adds type to the table. A browse name is only required if it is a ReferenceType.
        /// </summary>
        /// <param name="subTypeId">The sub type identifier.</param>
        /// <param name="superTypeId">The super type identifier.</param>
        /// <param name="browseName">Name of the browse.</param>
        /// <remarks>
        /// Updates the any existing entry.
        /// </remarks>
        private void AddSubtype(NodeId subTypeId, NodeId superTypeId, QualifiedName browseName)
        {
            lock (m_lock)
            {
                // lookup the supertype.
                TypeInfo superTypeInfo = null;

                if (!NodeId.IsNull(superTypeId))
                {
                    if (!m_nodes.TryGetValue(superTypeId, out superTypeInfo))
                    {
                        throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "A valid supertype identifier is required.");
                    }
                }

                // create the type info.
                TypeInfo typeInfo = null;

                if (!m_nodes.TryGetValue(subTypeId, out typeInfo))
                {
                    typeInfo = new TypeInfo();
                    m_nodes.Add(subTypeId, typeInfo);
                }

                // update the info.
                typeInfo.NodeId    = subTypeId;
                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);
                    }
                }

                // add reference type.
                if (!QualifiedName.IsNull(browseName))
                {
                    typeInfo.BrowseName          = browseName;
                    m_referenceTypes[browseName] = typeInfo;
                }
            }
        }
        /// <summary>
        /// Removes a subtype.
        /// </summary>
        /// <param name="typeId">The type identifier.</param>
        public void Remove(ExpandedNodeId typeId)
        {
            if (NodeId.IsNull(typeId) || typeId.ServerIndex != 0)
            {
                return;
            }

            NodeId localId = ExpandedNodeId.ToNodeId(typeId, m_namespaceUris);

            if (localId == null)
            {
                return;
            }

            lock (m_lock)
            {
                // remove type.
                TypeInfo typeInfo = null;

                if (!m_nodes.TryGetValue(localId, out typeInfo))
                {
                    return;
                }

                m_nodes.Remove(localId);

                // setting the flag to deleted ensures references from subtypes are not broken.
                typeInfo.Deleted = true;

                // remove from subtype list.
                if (typeInfo.SuperType != null)
                {
                    typeInfo.SuperType.RemoveSubType(localId);
                }

                // remove encodings.
                if (typeInfo.Encodings != null)
                {
                    for (int ii = 0; ii < typeInfo.Encodings.Length; ii++)
                    {
                        m_encodings.Remove(typeInfo.Encodings[ii]);
                    }
                }

                // remove reference type.
                if (!QualifiedName.IsNull(typeInfo.BrowseName))
                {
                    m_referenceTypes.Remove(typeInfo.BrowseName);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Adds a reference to target entity.
        /// </summary>
        /// <remarks>
        /// Will not add the reference if the browse name does not match the browse name filter.
        /// </remarks>
        public virtual void Add(NodeId referenceTypeId, bool isInverse, NodeState target)
        {
            lock (DataLock) {
                // do not return add target unless the browse name matches.
                if (!QualifiedName.IsNull(m_browseName))
                {
                    if (target.BrowseName != m_browseName)
                    {
                        return;
                    }
                }

                m_references.Add(new NodeStateReference(referenceTypeId, isInverse, target));
            }
        }
Beispiel #5
0
        /// <summary>
        /// Initializes a new event.
        /// </summary>
        /// <param name="context">The current system context.</param>
        /// <param name="source">The source of the event.</param>
        /// <param name="severity">The severity for the event.</param>
        /// <param name="message">The default message.</param>
        public virtual void Initialize(
            ISystemContext context, 
            NodeState source, 
            EventSeverity severity,
            LocalizedText message)
        {
            m_eventId = new PropertyState<byte[]>(this);
            m_eventId.Value = Guid.NewGuid().ToByteArray();

            m_eventType = new PropertyState<NodeId>(this);
            m_eventType.Value = GetDefaultTypeDefinitionId(context.NamespaceUris);

            TypeDefinitionId = m_eventType.Value;

            if (source != null)
            {
                if (!NodeId.IsNull(source.NodeId))
                {
                    m_sourceNode = new PropertyState<NodeId>(this);
                    m_sourceNode.Value = source.NodeId;
                    m_sourceNode.RolePermissions = source.RolePermissions;
                    m_sourceNode.UserRolePermissions = source.UserRolePermissions;
                    m_sourceNode.NodeId = source.NodeId;
                }

                if (!QualifiedName.IsNull(source.BrowseName))
                {
                    m_sourceName = new PropertyState<string>(this);
                    m_sourceName.Value = source.BrowseName.Name;
                }
            }

            m_time = new PropertyState<DateTime>(this);
            m_time.Value = DateTime.UtcNow;

            m_receiveTime = new PropertyState<DateTime>(this);
            m_receiveTime.Value = DateTime.UtcNow;

            m_severity = new PropertyState<ushort>(this);
            m_severity.Value = (ushort)severity;

            m_message = new PropertyState<LocalizedText>(this);
            m_message.Value = message;
        }
Beispiel #6
0
        /// <summary>
        /// Returns the string representation of the object.
        /// </summary>
        public string ToString(string format, IFormatProvider formatProvider)
        {
            if (format == null)
            {
                if (m_displayName != null && !String.IsNullOrEmpty(m_displayName.Text))
                {
                    return(m_displayName.Text);
                }

                if (!QualifiedName.IsNull(m_browseName))
                {
                    return(m_browseName.Name);
                }

                return(Utils.Format("(unknown {0})", ((NodeClass)m_nodeClass).ToString().ToLower()));
            }

            throw new FormatException(Utils.Format("Invalid format string: '{0}'.", format));
        }
Beispiel #7
0
        /// <summary cref="ITypeTable.FindReferenceType" />
        public NodeId FindReferenceType(QualifiedName browseName)
        {
            // check for empty name.
            if (QualifiedName.IsNull(browseName))
            {
                return(null);
            }

            lock (m_lock) {
                TypeInfo typeInfo = null;

                if (!m_referenceTypes.TryGetValue(browseName, out typeInfo))
                {
                    return(null);
                }

                return(typeInfo.NodeId);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Updates the nodeset string tables and returns a NodeId that references those tables.
        /// </summary>
        /// <param name="qname">The qualified name.</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 QualifiedName Translate(
            QualifiedName qname,
            NamespaceTable targetNamespaceUris,
            NamespaceTable sourceNamespaceUris)
        {
            if (targetNamespaceUris == null)
            {
                throw new ArgumentNullException("targetNamespaceUris");
            }
            if (sourceNamespaceUris == null)
            {
                throw new ArgumentNullException("sourceNamespaceUris");
            }

            if (QualifiedName.IsNull(qname))
            {
                return(qname);
            }

            ushort namespaceIndex = 0;

            if (qname.NamespaceIndex > 0)
            {
                string uri = sourceNamespaceUris.GetString(qname.NamespaceIndex);

                if (uri == null)
                {
                    return(qname);
                }

                int index = targetNamespaceUris.GetIndex(uri);

                if (index == -1)
                {
                    index = targetNamespaceUris.Append(uri);
                }

                namespaceIndex = (ushort)index;
            }

            return(new QualifiedName(qname.Name, namespaceIndex));
        }
Beispiel #9
0
        /// <summary>
        /// Formats a browse path.
        /// </summary>
        public static string Format(IList <QualifiedName> browsePath)
        {
            if (browsePath == null || browsePath.Count == 0)
            {
                return(String.Empty);
            }

            StringBuilder buffer = new StringBuilder();

            for (int ii = 0; ii < browsePath.Count; ii++)
            {
                QualifiedName browseName = browsePath[ii];

                if (QualifiedName.IsNull(browseName))
                {
                    throw ServiceResultException.Create(StatusCodes.BadBrowseNameInvalid, "BrowseName cannot be null");
                }

                buffer.Append('/');

                if (browseName.NamespaceIndex != 0)
                {
                    buffer.AppendFormat("{0}:", browseName.NamespaceIndex);
                }

                for (int jj = 0; jj < browseName.Name.Length; jj++)
                {
                    char ch = browseName.Name[jj];

                    if (ch == '&' || ch == '/')
                    {
                        buffer.Append('&');
                    }

                    buffer.Append(ch);
                }
            }

            return(buffer.ToString());
        }
Beispiel #10
0
        /// <summary>
        /// Applies the data encoding to the value.
        /// </summary>
        public static ServiceResult ApplyDataEncoding(ServiceMessageContext context, QualifiedName dataEncoding, ref object value)
        {
            // check if nothing to do.
            if (QualifiedName.IsNull(dataEncoding) || value == null)
            {
                return(ServiceResult.Good);
            }

            // check for supported encoding type.
            if (dataEncoding.NamespaceIndex != 0)
            {
                return(StatusCodes.BadDataEncodingUnsupported);
            }

            bool useXml = dataEncoding.Name == DefaultXml;

            if (!useXml && dataEncoding.Name != DefaultBinary)
            {
                return(StatusCodes.BadDataEncodingUnsupported);
            }

            try
            {
                // check for array of encodeables.
                IList <IEncodeable> encodeables = value as IList <IEncodeable>;

                if (encodeables == null)
                {
                    // check for array of extension objects.
                    IList <ExtensionObject> extensions = value as IList <ExtensionObject>;

                    if (extensions != null)
                    {
                        // convert extension objects to encodeables.
                        encodeables = new IEncodeable[extensions.Count];

                        for (int ii = 0; ii < encodeables.Count; ii++)
                        {
                            if (ExtensionObject.IsNull(extensions[ii]))
                            {
                                encodeables[ii] = null;
                                continue;
                            }

                            IEncodeable element = extensions[ii].Body as IEncodeable;

                            if (element == null)
                            {
                                return(StatusCodes.BadTypeMismatch);
                            }

                            encodeables[ii] = element;
                        }
                    }
                }

                // apply data encoding to the array.
                if (encodeables != null)
                {
                    ExtensionObject[] extensions = new ExtensionObject[encodeables.Count];

                    for (int ii = 0; ii < extensions.Length; ii++)
                    {
                        extensions[ii] = Encode(context, encodeables[ii], useXml);
                    }

                    value = extensions;
                    return(ServiceResult.Good);
                }

                // check for scalar value.
                IEncodeable encodeable = value as IEncodeable;

                if (encodeable == null)
                {
                    ExtensionObject extension = value as ExtensionObject;

                    if (extension == null)
                    {
                        return(StatusCodes.BadDataEncodingUnsupported);
                    }

                    encodeable = extension.Body as IEncodeable;
                }

                if (encodeable == null)
                {
                    return(StatusCodes.BadDataEncodingUnsupported);
                }

                // do conversion.
                value = Encode(context, encodeable, useXml);
                return(ServiceResult.Good);
            }
            catch (Exception e)
            {
                return(ServiceResult.Create(e, StatusCodes.BadTypeMismatch, "Could not convert value to requested format."));
            }
        }
        /// <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>
        /// 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>
        /// Initializes the instance from an event notification.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="fields">The fields selected for the event notification.</param>
        /// <param name="e">The event notification.</param>
        /// <remarks>
        /// This method creates components based on the browse paths in the event field and sets
        /// the NodeId or Value based on values in the event notification.
        /// </remarks>
        public void Update(
            ISystemContext context,
            SimpleAttributeOperandCollection fields,
            EventFieldList e)
        {
            for (int ii = 0; ii < fields.Count; ii++)
            {
                SimpleAttributeOperand field = fields[ii];
                object value = e.EventFields[ii].Value;

                // check if value provided.
                if (value == null)
                {
                    continue;
                }

                // extract the NodeId for the event.
                if (field.BrowsePath.Count == 0)
                {
                    if (field.AttributeId == Attributes.NodeId)
                    {
                        this.NodeId = value as NodeId;
                        continue;
                    }
                }

                // extract the type definition for the event.
                if (field.BrowsePath.Count == 1)
                {
                    if (field.AttributeId == Attributes.Value)
                    {
                        if (field.BrowsePath[0] == BrowseNames.EventType)
                        {
                            m_typeDefinitionId = value as NodeId;
                            continue;
                        }
                    }
                }

                // save value for child node.
                NodeState parent = this;

                for (int jj = 0; jj < field.BrowsePath.Count; jj++)
                {
                    // find a predefined child identified by the browse name.
                    BaseInstanceState child = parent.CreateChild(context, field.BrowsePath[jj]);

                    // create a placeholder for unknown children.
                    if (child == null)
                    {
                        if (field.AttributeId == Attributes.Value)
                        {
                            child = new BaseDataVariableState(parent);
                        }
                        else
                        {
                            child = new BaseObjectState(parent);
                        }

                        parent.AddChild(child);
                    }

                    // ensure the browse name is set.
                    if (QualifiedName.IsNull(child.BrowseName))
                    {
                        child.BrowseName = field.BrowsePath[jj];
                    }

                    // ensure the display name is set.
                    if (LocalizedText.IsNullOrEmpty(child.DisplayName))
                    {
                        child.DisplayName = child.BrowseName.Name;
                    }

                    // process next element in path.
                    if (jj < field.BrowsePath.Count - 1)
                    {
                        parent = child;
                        continue;
                    }

                    // save the variable value.
                    if (field.AttributeId == Attributes.Value)
                    {
                        BaseVariableState variable = child as BaseVariableState;

                        if (variable != null && field.AttributeId == Attributes.Value)
                        {
                            try
                            {
                                variable.WrappedValue = e.EventFields[ii];
                            }
                            catch (Exception)
                            {
                                variable.Value = null;
                            }
                        }

                        break;
                    }

                    // save the node id.
                    child.NodeId = value as NodeId;
                }
            }
        }
Beispiel #14
0
        /// <summary>
        /// Finds the child with the specified browse name.
        /// </summary>
        protected override BaseInstanceState FindChild(
            ISystemContext context,
            QualifiedName browseName,
            bool createOrReplace,
            BaseInstanceState replacement)
        {
            if (QualifiedName.IsNull(browseName))
            {
                return(null);
            }

            BaseInstanceState instance = null;

            switch (browseName.Name)
            {
            case BrowseNames.InputArguments:
            {
                if (createOrReplace)
                {
                    if (InputArguments == null)
                    {
                        if (replacement == null)
                        {
                            InputArguments = new PropertyState <Argument[]>(this);
                        }
                        else
                        {
                            InputArguments = (PropertyState <Argument[]>)replacement;
                        }
                    }
                }

                instance = InputArguments;
                break;
            }

            case BrowseNames.OutputArguments:
            {
                if (createOrReplace)
                {
                    if (OutputArguments == null)
                    {
                        if (replacement == null)
                        {
                            OutputArguments = new PropertyState <Argument[]>(this);
                        }
                        else
                        {
                            OutputArguments = (PropertyState <Argument[]>)replacement;
                        }
                    }
                }

                instance = OutputArguments;
                break;
            }
            }

            if (instance != null)
            {
                return(instance);
            }

            return(base.FindChild(context, browseName, createOrReplace, replacement));
        }