/// <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;
}
}