public NodeMetadata GetNodeMetadata(
OperationContext context,
object targetHandle,
BrowseResultMask resultMask)
{
if (context == null) throw new ArgumentNullException("context");
// find target.
ILocalNode target = targetHandle as ILocalNode;
if (target == null)
{
return null;
}
try
{
m_lock.Enter();
// copy the default metadata.
NodeMetadata metadata = new NodeMetadata(target, target.NodeId);
// copy target attributes.
if ((resultMask & BrowseResultMask.NodeClass) != 0)
{
metadata.NodeClass = (NodeClass)target.NodeClass;
}
if ((resultMask & BrowseResultMask.BrowseName) != 0)
{
metadata.BrowseName = target.BrowseName;
}
if ((resultMask & BrowseResultMask.DisplayName) != 0)
{
metadata.DisplayName = target.DisplayName;
// check if the display name can be localized.
if (!String.IsNullOrEmpty(metadata.DisplayName.Key))
{
metadata.DisplayName = Server.ResourceManager.Translate(context.PreferredLocales, metadata.DisplayName);
}
}
metadata.WriteMask = target.WriteMask;
if (metadata.WriteMask != AttributeWriteMask.None)
{
DataValue value = new DataValue((uint)(int)target.UserWriteMask);
ServiceResult result = target.Read(context, Attributes.UserWriteMask, value);
if (ServiceResult.IsBad(result))
{
metadata.WriteMask = AttributeWriteMask.None;
}
else
{
metadata.WriteMask = (AttributeWriteMask)(int)((uint)(int)metadata.WriteMask & (uint)value.Value);
}
}
metadata.EventNotifier = EventNotifiers.None;
metadata.AccessLevel = AccessLevels.None;
metadata.Executable = false;
switch (target.NodeClass)
{
case NodeClass.Object:
{
metadata.EventNotifier = ((IObject)target).EventNotifier;
break;
}
case NodeClass.View:
{
metadata.EventNotifier = ((IView)target).EventNotifier;
break;
}
case NodeClass.Variable:
{
IVariable variable = (IVariable)target;
metadata.DataType = variable.DataType;
metadata.ValueRank = variable.ValueRank;
metadata.ArrayDimensions = variable.ArrayDimensions;
metadata.AccessLevel = variable.AccessLevel;
DataValue value = new DataValue(variable.UserAccessLevel);
ServiceResult result = variable.Read(context, Attributes.UserAccessLevel, value);
if (ServiceResult.IsBad(result))
{
metadata.AccessLevel = 0;
break;
}
metadata.AccessLevel = (byte)(metadata.AccessLevel & (byte)value.Value);
break;
}
case NodeClass.Method:
{
IMethod method = (IMethod)target;
metadata.Executable = method.Executable;
if (metadata.Executable)
{
DataValue value = new DataValue(method.UserExecutable);
ServiceResult result = method.Read(context, Attributes.UserExecutable, value);
if (ServiceResult.IsBad(result))
{
metadata.Executable = false;
break;
}
metadata.Executable = (bool)value.Value;
}
break;
}
}
// look up type definition.
if ((resultMask & BrowseResultMask.TypeDefinition) != 0)
{
if (target.NodeClass == NodeClass.Variable || target.NodeClass == NodeClass.Object)
{
metadata.TypeDefinition = target.TypeDefinitionId;
}
}
#if LEGACY_NODEMANAGER
// check if a source is defined for the node.
SourceHandle handle = target.Handle as SourceHandle;
if (handle != null)
{
// check if the metadata needs to be updated by the source.
IReadMetadataSource source = handle.Source as IReadMetadataSource;
if (source != null)
{
source.ReadMetadata(
context,
handle.Handle,
resultMask,
metadata);
}
}
#endif
// return metadata.
return metadata;
}
finally
{
m_lock.Exit();
}
}