/// <summary> /// Creates an Object node in the address space. /// </summary> public NodeId CreateObject( NodeId parentId, NodeId referenceTypeId, NodeId nodeId, QualifiedName browseName, ObjectAttributes attributes, ExpandedNodeId typeDefinitionId) { try { m_lock.Enter(); // validate browse name. if (QualifiedName.IsNull(browseName)) { throw ServiceResultException.Create(StatusCodes.BadBrowseNameInvalid, "BrowsName must not be empty."); } // check for null node id. if (NodeId.IsNull(nodeId)) { nodeId = CreateUniqueNodeId(); } // check if node id exists. if (m_nodes.Exists(nodeId)) { throw ServiceResultException.Create(StatusCodes.BadNodeIdExists, "NodeId '{0}' already exists.", nodeId); } // find parent. ILocalNode parent = null; if (!NodeId.IsNull(parentId)) { parent = GetManagerHandle(parentId) as ILocalNode; if (parent == null) { throw ServiceResultException.Create(StatusCodes.BadParentNodeIdInvalid, "Parent node '{0}' does not exist.", parentId); } // validate reference. ValidateReference(parent, referenceTypeId, false, NodeClass.Object); } // find type definition. if (NodeId.IsNull(typeDefinitionId)) { typeDefinitionId = ObjectTypes.BaseObjectType; } IObjectType objectType = GetManagerHandle(typeDefinitionId) as IObjectType; if (objectType == null) { throw ServiceResultException.Create(StatusCodes.BadTypeDefinitionInvalid, "Type definition '{0}' does not exist or is not an ObjectType.", typeDefinitionId); } // verify instance declarations. ILocalNode instanceDeclaration = FindInstanceDeclaration(parent, browseName); if (instanceDeclaration != null) { if (instanceDeclaration.NodeClass != NodeClass.Object) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The type model requires that node with a browse name of {0} have a NodeClass of {1}.", browseName, instanceDeclaration.NodeClass); } if (!m_server.TypeTree.IsTypeOf(typeDefinitionId, instanceDeclaration.TypeDefinitionId)) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The type model requires that node have a type definition of {0}.", instanceDeclaration.TypeDefinitionId); } } // get the variable. IObject objectd = instanceDeclaration as IObject; // create node. ObjectNode node = new ObjectNode(); // set defaults from type definition. node.NodeId = nodeId; node.NodeClass = NodeClass.Object; node.BrowseName = browseName; node.DisplayName = browseName.Name; node.Description = null; node.WriteMask = 0; node.UserWriteMask = 0; node.EventNotifier = EventNotifiers.None; // set defaults from instance declaration. if (objectd != null) { node.DisplayName = objectd.DisplayName; node.Description = objectd.Description; node.WriteMask = (uint)objectd.WriteMask; node.UserWriteMask = (uint)objectd.UserWriteMask; node.EventNotifier = objectd.EventNotifier; } // update with attributes provided. UpdateAttributes(node, attributes); // EventNotifier if (attributes != null && (attributes.SpecifiedAttributes & (uint)NodeAttributesMask.EventNotifier) != 0) { node.EventNotifier = attributes.EventNotifier; } // add references with parent. if (parent != null) { AddReference(parent, referenceTypeId, false, node, true); } // add type definition. AddReference(node, ReferenceTypeIds.HasTypeDefinition, false, objectType, false); // add to address space. AddNode(node); // apply modelling rules. NodeFactory factory = new NodeFactory(m_nodes); IList<ILocalNode> nodesToAdd = factory.ApplyModellingRules(node, objectType.NodeId, ref m_lastId, 1); // add the nodes. foreach (Node nodeToAdd in nodesToAdd) { AddNode(nodeToAdd); } // find the top level parent that must be used to apply the modelling rules. if (instanceDeclaration != null) { ILocalNode toplevelParent = FindTopLevelModelParent(parent); // add modelling rule. AddReference(node, ReferenceTypeIds.HasModelParent, false, parent, true); // update the hierarchy. nodesToAdd = factory.ApplyModellingRules(toplevelParent, (NodeId)toplevelParent.TypeDefinitionId, ref m_lastId, 1); // add the nodes. foreach (Node nodeToAdd in nodesToAdd) { AddNode(nodeToAdd); } } // return the new node id. return node.NodeId; } finally { m_lock.Exit(); } }
public NodeId CreateVariable( NodeId parentId, NodeId referenceTypeId, NodeId nodeId, QualifiedName browseName, VariableAttributes attributes, ExpandedNodeId typeDefinitionId) { try { m_lock.Enter(); // check browse name. if (QualifiedName.IsNull(browseName)) { throw new ServiceResultException(StatusCodes.BadBrowseNameInvalid); } // user default type definition. if (NodeId.IsNull(typeDefinitionId)) { typeDefinitionId = VariableTypes.BaseDataVariableType; } // find type definition. IVariableType variableType = GetManagerHandle(typeDefinitionId) as IVariableType; if (variableType == null) { throw ServiceResultException.Create(StatusCodes.BadTypeDefinitionInvalid, "Type definition '{0}' does not exist or is not an VariableType.", typeDefinitionId); } // check if node id exists. if (!NodeId.IsNull(nodeId)) { if (m_nodes.Exists(nodeId)) { throw ServiceResultException.Create(StatusCodes.BadNodeIdExists, "NodeId '{0}' already exists.", nodeId); } } // create a unique id. else { nodeId = CreateUniqueNodeId(); } // find parent. ILocalNode parent = null; if (!NodeId.IsNull(parentId)) { parent = GetManagerHandle(parentId) as ILocalNode; if (parent == null) { throw ServiceResultException.Create(StatusCodes.BadParentNodeIdInvalid, "Parent node '{0}' does not exist.", parentId); } // validate reference. ValidateReference(parent, referenceTypeId, false, NodeClass.Variable); } // verify instance declarations. ILocalNode instanceDeclaration = FindInstanceDeclaration(parent, browseName); if (instanceDeclaration != null) { if (instanceDeclaration.NodeClass != NodeClass.Variable) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The type model requires that node with a browse name of {0} have a NodeClass of {1}.", browseName, instanceDeclaration.NodeClass); } if (!m_server.TypeTree.IsTypeOf(typeDefinitionId, instanceDeclaration.TypeDefinitionId)) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The type model requires that node have a type definition of {0}.", instanceDeclaration.TypeDefinitionId); } } // get the variable. IVariable variable = instanceDeclaration as IVariable; // create node. VariableNode node = new VariableNode(); // set defaults from type definition. node.NodeId = nodeId; node.NodeClass = NodeClass.Variable; node.BrowseName = browseName; node.DisplayName = browseName.Name; node.Description = null; node.WriteMask = 0; node.UserWriteMask = 0; node.Value = (variable == null)?new Variant(Utils.Clone(variableType.Value)):Variant.Null; node.DataType = variableType.DataType; node.ValueRank = variableType.ValueRank; node.ArrayDimensions = new UInt32Collection(variableType.ArrayDimensions); node.AccessLevel = AccessLevels.CurrentReadOrWrite; node.UserAccessLevel = node.AccessLevel; node.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; node.Historizing = false; // set defaults from instance declaration. if (variable != null) { node.DisplayName = variable.DisplayName; node.Description = variable.Description; node.WriteMask = (uint)variable.WriteMask; node.UserWriteMask = (uint)variable.UserWriteMask; node.Value = new Variant(Utils.Clone(variable.Value)); node.DataType = variable.DataType; node.ValueRank = variable.ValueRank; node.ArrayDimensions = new UInt32Collection(variable.ArrayDimensions); node.AccessLevel = variable.AccessLevel; node.UserAccessLevel = variable.UserAccessLevel; node.MinimumSamplingInterval = variable.MinimumSamplingInterval; node.Historizing = variable.Historizing; } // update attributes. UpdateAttributes(node, attributes); // Value if (attributes != null && (attributes.SpecifiedAttributes & (uint)NodeAttributesMask.Value) != 0) { node.Value = attributes.Value; } // DataType if (attributes != null && (attributes.SpecifiedAttributes & (uint)NodeAttributesMask.DataType) != 0) { if (!m_server.TypeTree.IsTypeOf(attributes.DataType, variableType.DataType)) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The type definition requires a DataType of {0}.", variableType.DataType); } if (variable != null) { if (!m_server.TypeTree.IsTypeOf(attributes.DataType, variable.DataType)) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The instance declaration requires a DataType of {0}.", variable.DataType); } } node.DataType = attributes.DataType; } // ValueRank if (attributes != null && (attributes.SpecifiedAttributes & (uint)NodeAttributesMask.ValueRank) != 0) { if (!ValueRanks.IsValid(attributes.ValueRank, variableType.ValueRank)) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The type definition requires a ValueRank of {0}.", variableType.ValueRank); } if (variable != null) { if (!ValueRanks.IsValid(attributes.ValueRank, variable.ValueRank)) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The instance declaration requires a ValueRank of {0}.", variable.ValueRank); } } node.ValueRank = attributes.ValueRank; } // ArrayDimensions if (attributes != null && (attributes.SpecifiedAttributes & (uint)NodeAttributesMask.ArrayDimensions) != 0) { if (!ValueRanks.IsValid(attributes.ArrayDimensions, node.ValueRank, variableType.ArrayDimensions)) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The ArrayDimensions do not meet the requirements for the type definition: {0}.", variableType.NodeId); } if (variable != null) { if (!ValueRanks.IsValid(attributes.ArrayDimensions, node.ValueRank, variable.ArrayDimensions)) { throw ServiceResultException.Create( StatusCodes.BadNodeClassInvalid, "The ArrayDimensions do not meet the requirements for the instance declaration: {0}.", variable.ValueRank); } } node.ArrayDimensions = attributes.ArrayDimensions; } // AccessLevel if (attributes != null && (attributes.SpecifiedAttributes & (uint)NodeAttributesMask.AccessLevel) != 0) { node.AccessLevel = attributes.AccessLevel; } // AccessLevel if (attributes != null && (attributes.SpecifiedAttributes & (uint)NodeAttributesMask.UserAccessLevel) != 0) { node.UserAccessLevel = attributes.UserAccessLevel; } // MinimumSamplingInterval if (attributes != null && (attributes.SpecifiedAttributes & (uint)NodeAttributesMask.MinimumSamplingInterval) != 0) { node.MinimumSamplingInterval = attributes.MinimumSamplingInterval; } // Historizing if (attributes != null && (attributes.SpecifiedAttributes & (uint)NodeAttributesMask.Historizing) != 0) { node.Historizing = attributes.Historizing; } // add references with parent. if (parent != null) { AddReference(parent, referenceTypeId, false, node, true); } // add type definition. AddReference(node, ReferenceTypeIds.HasTypeDefinition, false, variableType, false); // add to address space. AddNode(node); // apply modelling rules. NodeFactory factory = new NodeFactory(m_nodes); IList<ILocalNode> nodesToAdd = factory.ApplyModellingRules(node, variableType.NodeId, ref m_lastId, 1); // add the nodes. foreach (Node nodeToAdd in nodesToAdd) { AddNode(nodeToAdd); } // add references with parent. if (parent != null) { AddReference(parent, referenceTypeId, false, node, true); } // find the top level parent that must be used to apply the modelling rules. if (instanceDeclaration != null) { ILocalNode toplevelParent = FindTopLevelModelParent(parent); // add modelling rule. AddReference(node, ReferenceTypeIds.HasModelParent, false, parent, true); // update the hierarchy. nodesToAdd = factory.ApplyModellingRules(toplevelParent, (NodeId)toplevelParent.TypeDefinitionId, ref m_lastId, 1); // add the nodes. foreach (Node nodeToAdd in nodesToAdd) { AddNode(nodeToAdd); } } // return the new node id. return node.NodeId; } finally { m_lock.Exit(); } }
/// <summary> /// Changes the type definition for an instance. /// </summary> public void ChangeTypeDefinition( NodeId instanceId, NodeId typeDefinitionId) { try { m_lock.Enter(); // find the instance. ILocalNode instance = GetLocalNode(instanceId) as ILocalNode; if (instance == null) { throw ServiceResultException.Create(StatusCodes.BadNodeIdUnknown, "NodeId ({0}) does not exist.", instanceId); } // check node class. if (instance.NodeClass != NodeClass.Object && instance.NodeClass != NodeClass.Variable) { throw ServiceResultException.Create(StatusCodes.BadNodeClassInvalid, "Node (NodeClass={0}) cannot have a type definition.", instance.NodeClass); } // get current type definition. ExpandedNodeId existingTypeId = instance.TypeDefinitionId; if (existingTypeId == typeDefinitionId) { return; } // can only change to a subtype of the existing type definition. if (!m_server.TypeTree.IsTypeOf(typeDefinitionId, existingTypeId)) { throw ServiceResultException.Create(StatusCodes.BadTypeDefinitionInvalid, "Type definition ({0}) must be a must subtype of the existing type definition ({1}).", typeDefinitionId, existingTypeId); } // find the type definition node. ILocalNode typeDefinition = GetLocalNode(typeDefinitionId) as ILocalNode; if (typeDefinition == null) { throw ServiceResultException.Create(StatusCodes.BadTypeDefinitionInvalid, "TypeDefinitionId ({0}) does not exist.", typeDefinitionId); } // apply modelling rules. NodeFactory factory = new NodeFactory(m_nodes); IList<ILocalNode> nodesToAdd = factory.ApplyModellingRules(instance, typeDefinition.NodeId, ref m_lastId, 1); // add the nodes. foreach (Node nodeToAdd in nodesToAdd) { AddNode(nodeToAdd); } } finally { m_lock.Exit(); } }