/// <summary> /// Returns the references for the node that meets the criteria specified. /// </summary> private ReferenceDescription GetReferenceDescription( OperationContext context, IReference reference, ContinuationPoint continuationPoint) { // create the type definition reference. ReferenceDescription description = new ReferenceDescription(); description.NodeId = reference.TargetId; description.SetReferenceType(continuationPoint.ResultMask, reference.ReferenceTypeId, !reference.IsInverse); // do not cache target parameters for remote nodes. if (reference.TargetId.IsAbsolute) { // only return remote references if no node class filter is specified. if (continuationPoint.NodeClassMask != 0) { return null; } return description; } NodeState target = null; // check for local reference. NodeStateReference referenceInfo = reference as NodeStateReference; if (referenceInfo != null) { target = referenceInfo.Target; } // check for internal reference. if (target == null) { NodeId targetId = (NodeId)reference.TargetId; if (IsNodeIdInNamespace(targetId)) { if (!PredefinedNodes.TryGetValue(targetId, out target)) { target = null; } } } // the target may be a reference to a node in another node manager. In these cases // the target attributes must be fetched by the caller. The Unfiltered flag tells the // caller to do that. if (target == null) { description.Unfiltered = true; return description; } // apply node class filter. if (continuationPoint.NodeClassMask != 0 && ((continuationPoint.NodeClassMask & (uint)target.NodeClass) == 0)) { return null; } NodeId typeDefinition = null; BaseInstanceState instance = target as BaseInstanceState; if (instance != null) { typeDefinition = instance.TypeDefinitionId; } // set target attributes. description.SetTargetAttributes( continuationPoint.ResultMask, target.NodeClass, target.BrowseName, target.DisplayName, typeDefinition); return description; }
/// <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; } }