private List<BrowseElement> LookupChildElements(Session session, BrowseElement parent)
{
List<BrowseElement> children = new List<BrowseElement>();
List<BrowseElement> childrenToFind = new List<BrowseElement>();
List<int> indexes = new List<int>();
BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection();
// create an element for each child reference.
foreach (ReferenceDescription reference in parent.ReferencesByName.Values)
{
NodeId nodeId = (NodeId)reference.NodeId;
string itemId = m_mapper.GetLocalItemId(nodeId);
BrowseElement child = null;
lock (m_lock)
{
// check if child has already been cached.
if (m_cache.TryGetValue(itemId, out child))
{
child.ParentId = parent.ItemId;
children.Add(child);
continue;
}
// create a new element.
child = new BrowseElement();
}
child.NodeId = nodeId;
child.ItemId = itemId;
child.NodeClass = reference.NodeClass;
child.BrowseName = child.UaBrowseName = m_mapper.GetLocalBrowseName(reference.BrowseName);
if (reference.DisplayName != null)
{
child.BrowseName = reference.DisplayName.Text;
}
int index = PrepareBrowseElementBrowseRequest(child.NodeId, nodesToBrowse);
childrenToFind.Add(child);
indexes.Add(index);
}
// check if nothing to do because everything was in the cache.
if (childrenToFind.Count == 0)
{
return children;
}
// browse all elements at once.
BrowseResultCollection results = Browse(session, nodesToBrowse);
// validate results and prepare read requests.
ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
for (int ii = 0; ii < childrenToFind.Count; ii++)
{
BrowseElement child = childrenToFind[ii];
// update the element with the children found.
if (!UpdateBrowseElement(child, nodesToBrowse, results, indexes[ii]))
{
children[ii] = null;
continue;
}
// all done with objects.
if (child.NodeClass == NodeClass.Object)
{
child.ParentId = parent.ItemId;
children.Add(child);
lock (m_lock)
{
child.CacheTimestamp = DateTime.UtcNow;
m_cache[child.ItemId] = child;
}
}
// prepare to read the properties from the server.
indexes[ii] = PrepareBrowseElementReadRequest(child.NodeId, child.ReferencesByName, nodesToRead, child.NodeClass, true);
}
// check if nothing to do because only objects with no properties..
if (nodesToRead.Count == 0)
{
return children;
}
// read all child properties at once.
DataValueCollection values = Read(session, nodesToRead);
// process results and build final table.
for (int ii = 0; ii < childrenToFind.Count; ii++)
{
BrowseElement child = childrenToFind[ii];
if (child == null || child.NodeClass == NodeClass.Object)
{
continue;
}
// update the browse element with the property values.
if (!UpdateBrowseElement(session.TypeTree, child, nodesToRead, values, child.NodeClass, true, indexes[ii]))
{
continue;
}
// add variables to the cache.
child.ParentId = parent.ItemId;
children.Add(child);
lock (m_lock)
{
child.CacheTimestamp = DateTime.UtcNow;
m_cache[child.ItemId] = child;
}
}
return children;
}