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);
}
try
{
m_lock.Enter();
// 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;
}
finally
{
m_lock.Exit();
}
}