Opc.Ua.Server.CoreNodeManager.ValidateReference C# (CSharp) Method

ValidateReference() private method

Verifies that the source and the target meet the restrictions imposed by the reference type.
private ValidateReference ( ILocalNode source, NodeId referenceTypeId, bool isInverse, NodeClass targetNodeClass ) : void
source ILocalNode
referenceTypeId NodeId
isInverse bool
targetNodeClass NodeClass
return void
        private void ValidateReference(
            ILocalNode source,
            NodeId     referenceTypeId,
            bool       isInverse,
            NodeClass  targetNodeClass)
        {
            // find reference type.
            IReferenceType referenceType = GetLocalNode(referenceTypeId) as IReferenceType;

            if (referenceType == null)
            {
                throw ServiceResultException.Create(StatusCodes.BadReferenceTypeIdInvalid, "Reference type '{0}' does not exist.", referenceTypeId);
            }

            // swap the source and target for inverse references.
            NodeClass sourceNodeClass = source.NodeClass;

            if (isInverse)
            {
                sourceNodeClass = targetNodeClass;
                targetNodeClass = source.NodeClass;
            }

            // check HasComponent references.
            if (m_server.TypeTree.IsTypeOf(referenceTypeId, ReferenceTypeIds.HasComponent))
            {
                if ((sourceNodeClass & (NodeClass.Object | NodeClass.Variable | NodeClass.ObjectType | NodeClass.VariableType)) == 0)
                {
                    throw ServiceResultException.Create(StatusCodes.BadReferenceNotAllowed, "Source node cannot be used with HasComponent references.");
                }

                if ((targetNodeClass & (NodeClass.Object | NodeClass.Variable | NodeClass.Method)) == 0)
                {
                    throw ServiceResultException.Create(StatusCodes.BadReferenceNotAllowed, "Target node cannot be used with HasComponent references.");
                }
                
                if (targetNodeClass == NodeClass.Variable)
                {
                    if ((targetNodeClass & (NodeClass.Variable | NodeClass.VariableType)) == 0)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadReferenceNotAllowed, "A Variable must be a component of an Variable or VariableType.");
                    }
                }

                if (targetNodeClass == NodeClass.Method)
                {
                    if ((sourceNodeClass & (NodeClass.Object | NodeClass.ObjectType)) == 0)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadReferenceNotAllowed, "A Method must be a component of an Object or ObjectType.");
                    }
                }
            }
            
            // check HasProperty references.
            if (m_server.TypeTree.IsTypeOf(referenceTypeId, ReferenceTypes.HasProperty))
            {
                if (targetNodeClass != NodeClass.Variable)
                {
                    throw ServiceResultException.Create(StatusCodes.BadReferenceNotAllowed, "Targets of HasProperty references must be Variables.");
                }                
            }

            // check HasSubtype references.
            if (m_server.TypeTree.IsTypeOf(referenceTypeId, ReferenceTypeIds.HasSubtype))
            {
                if ((sourceNodeClass & (NodeClass.DataType | NodeClass.ReferenceType | NodeClass.ObjectType | NodeClass.VariableType)) == 0)
                {
                    throw ServiceResultException.Create(StatusCodes.BadReferenceNotAllowed, "Source node cannot be used with HasSubtype references.");
                }

                if (targetNodeClass != sourceNodeClass)
                {
                    throw ServiceResultException.Create(StatusCodes.BadReferenceNotAllowed, "The source and target cannot be connected by a HasSubtype reference.");
                }
            }                      

            // TBD - check rules for other reference types.
        }
        #endregion