/// <summary> /// Browses the references from a node managed by the node manager. /// </summary> /// <remarks> /// The continuation point is created for every browse operation and contains the browse parameters. /// The node manager can store its state information in the Data and Index properties. /// </remarks> public virtual void Browse( OperationContext context, ref ContinuationPoint continuationPoint, IList<ReferenceDescription> references) { if (continuationPoint == null) throw new ArgumentNullException("continuationPoint"); if (references == null) throw new ArgumentNullException("references"); ServerSystemContext systemContext = m_systemContext.Copy(context); // check for valid view. ValidateViewDescription(systemContext, continuationPoint.View); INodeBrowser browser = null; lock (Lock) { // check for valid handle. NodeHandle handle = IsHandleInNamespace(continuationPoint.NodeToBrowse); if (handle == null) { throw new ServiceResultException(StatusCodes.BadNodeIdUnknown); } // validate node. NodeState source = ValidateNode(systemContext, handle, null); if (source == null) { throw new ServiceResultException(StatusCodes.BadNodeIdUnknown); } // check if node is in the view. if (!IsNodeInView(systemContext, continuationPoint, source)) { throw new ServiceResultException(StatusCodes.BadNodeNotInView); } // check for previous continuation point. browser = continuationPoint.Data as INodeBrowser; // fetch list of references. if (browser == null) { // create a new browser. continuationPoint.Data = browser = source.CreateBrowser( systemContext, continuationPoint.View, continuationPoint.ReferenceTypeId, continuationPoint.IncludeSubtypes, continuationPoint.BrowseDirection, null, null, false); } } // prevent multiple access the browser object. lock (browser) { // apply filters to references. Dictionary<NodeId, NodeState> cache = new Dictionary<NodeId, NodeState>(); for (IReference reference = browser.Next(); reference != null; reference = browser.Next()) { // create the type definition reference. ReferenceDescription description = GetReferenceDescription(systemContext, cache, reference, continuationPoint); if (description == null) { continue; } // check if limit reached. if (continuationPoint.MaxResultsToReturn != 0 && references.Count >= continuationPoint.MaxResultsToReturn) { browser.Push(reference); return; } references.Add(description); } // release the continuation point if all done. continuationPoint.Dispose(); continuationPoint = null; } }
/// <summary> /// Browses the references from a node managed by the node manager. /// </summary> /// <remarks> /// The continuation point is created for every browse operation and contains the browse parameters. /// The node manager can store its state information in the Data and Index properties. /// </remarks> public virtual void Browse( OperationContext context, ref ContinuationPoint continuationPoint, IList<ReferenceDescription> references) { if (continuationPoint == null) throw new ArgumentNullException("continuationPoint"); if (references == null) throw new ArgumentNullException("references"); // check for view. if (!ViewDescription.IsDefault(continuationPoint.View)) { throw new ServiceResultException(StatusCodes.BadViewIdUnknown); } ServerSystemContext systemContext = m_systemContext.Copy(context); lock (Lock) { // verify that the node exists. NodeState source = IsHandleInNamespace(continuationPoint.NodeToBrowse); if (source == null) { throw new ServiceResultException(StatusCodes.BadNodeIdUnknown); } // validate node. if (!ValidateNode(systemContext, source)) { throw new ServiceResultException(StatusCodes.BadNodeIdUnknown); } // check for previous continuation point. INodeBrowser browser = continuationPoint.Data as INodeBrowser; // fetch list of references. if (browser == null) { // create a new browser. browser = source.CreateBrowser( systemContext, continuationPoint.View, continuationPoint.ReferenceTypeId, continuationPoint.IncludeSubtypes, continuationPoint.BrowseDirection, null, null, false); } // apply filters to references. for (IReference reference = browser.Next(); reference != null; reference = browser.Next()) { // create the type definition reference. ReferenceDescription description = GetReferenceDescription(context, reference, continuationPoint); if (description == null) { continue; } // check if limit reached. if (continuationPoint.MaxResultsToReturn != 0 && references.Count >= continuationPoint.MaxResultsToReturn) { browser.Push(reference); continuationPoint.Data = browser; return; } references.Add(description); } // release the continuation point if all done. continuationPoint.Dispose(); continuationPoint = null; } }
/// <see cref="INodeManager.Browse" /> public void Browse( OperationContext context, ref ContinuationPoint continuationPoint, IList<ReferenceDescription> references) { if (context == null) throw new ArgumentNullException("context"); if (continuationPoint == null) throw new ArgumentNullException("continuationPoint"); if (references == null) throw new ArgumentNullException("references"); // check for valid handle. ILocalNode source = continuationPoint.NodeToBrowse as ILocalNode; if (source == null) { throw new ServiceResultException(StatusCodes.BadNodeIdUnknown); } // check for view. if (!ViewDescription.IsDefault(continuationPoint.View)) { throw new ServiceResultException(StatusCodes.BadViewIdUnknown); } lock (m_lock) { // construct list of references. uint maxResultsToReturn = continuationPoint.MaxResultsToReturn; // get previous enumerator. IEnumerator<IReference> enumerator = continuationPoint.Data as IEnumerator<IReference>; // fetch a snapshot all references for node. if (enumerator == null) { List<IReference> copy = new List<IReference>(source.References); enumerator = copy.GetEnumerator(); enumerator.MoveNext(); } do { IReference reference = enumerator.Current; // silently ignore bad values. if (reference == null || NodeId.IsNull(reference.ReferenceTypeId) || NodeId.IsNull(reference.TargetId)) { continue; } // apply browse filters. bool include = ApplyBrowseFilters( reference, continuationPoint.BrowseDirection, continuationPoint.ReferenceTypeId, continuationPoint.IncludeSubtypes); if (include) { ReferenceDescription description = new ReferenceDescription(); description.NodeId = reference.TargetId; description.SetReferenceType(continuationPoint.ResultMask, reference.ReferenceTypeId, !reference.IsInverse); // only fetch the metadata if it is requested. if (continuationPoint.TargetAttributesRequired) { // get the metadata for the node. NodeMetadata metadata = GetNodeMetadata(context, GetManagerHandle(reference.TargetId), continuationPoint.ResultMask); // update description with local node metadata. if (metadata != null) { description.SetTargetAttributes( continuationPoint.ResultMask, metadata.NodeClass, metadata.BrowseName, metadata.DisplayName, metadata.TypeDefinition); // check node class mask. if (!CheckNodeClassMask(continuationPoint.NodeClassMask, description.NodeClass)) { continue; } } // any target that is not remote must be owned by another node manager. else if (!reference.TargetId.IsAbsolute) { description.Unfiltered = true; } } // add reference to list. references.Add(description); // construct continuation point if max results reached. if (maxResultsToReturn > 0 && references.Count >= maxResultsToReturn) { continuationPoint.Index = 0; continuationPoint.Data = enumerator; enumerator.MoveNext(); return; } } } while (enumerator.MoveNext()); // nothing more to browse if it exits from the loop normally. continuationPoint.Dispose(); continuationPoint = null; } }