private void UpdateEventAttributeMappings(NodeIdMappingSet mappingSet)
{
NodeIdMappingCollection mappingsToKeep = new NodeIdMappingCollection();
// collect all unique declarations.
List<AeEventAttribute> list = new List<AeEventAttribute>();
foreach (AeEventCategory type in m_eventTypes.Values)
{
for (int ii = 0; ii < type.Attributes.Count; ii++)
{
AeEventAttribute declaration = type.Attributes[ii];
// only variables can be attributes.
if (declaration.NodeClass != NodeClass.Variable)
{
continue;
}
// need to link attributes to any attributes that they override.
AeEventCategory subType = type;
AeEventCategory superType = null;
while (subType != null)
{
if (NodeId.IsNull(subType.SuperTypeId) || subType.TypeId == subType.SuperTypeId || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.BaseObjectType)
{
list.Add(declaration);
break;
}
if (!m_eventTypes.TryGetValue(subType.SuperTypeId, out superType))
{
break;
}
for (int jj = 0; jj < superType.Attributes.Count; jj++)
{
if (superType.Attributes[jj].BrowsePathDisplayText == declaration.BrowsePathDisplayText)
{
declaration.OverriddenDeclaration = superType.Attributes[jj];
declaration = declaration.OverriddenDeclaration;
break;
}
}
subType = superType;
}
}
}
// look up ids for all attributes in master list.
Dictionary<uint, AeEventAttribute> attributes = new Dictionary<uint, AeEventAttribute>();
for (int ii = 0; ii < list.Count; ii++)
{
AeEventAttribute declaration = list[ii];
for (int jj = 0; jj < mappingSet.Mappings.Count; jj++)
{
NodeIdMapping mapping = mappingSet.Mappings[jj];
try
{
// browse display paths always use local namespa indexes.
if (declaration.BrowsePathDisplayText != mapping.BrowePath)
{
continue;
}
// need to convert the cached type id to a remote id.
NodeId localId = NodeId.Parse(mapping.NodeId);
NodeId remoteId = this.GetRemoteNodeId(localId);
if (declaration.RootTypeId != remoteId)
{
continue;
}
// must update the saved integer id.
if (!attributes.ContainsKey(mapping.IntegerId))
{
declaration.LocalId = mapping.IntegerId;
attributes[declaration.LocalId] = declaration;
mappingsToKeep.Add(mapping);
}
// must assign a new one if a duplicate found.
else
{
declaration.LocalId = 0;
}
}
catch (Exception)
{
// ignore invalid mappings.
}
}
}
// assign new ids.
uint nextId = 1;
for (int ii = 0; ii < list.Count; ii++)
{
AeEventAttribute declaration = list[ii];
if (declaration.LocalId == 0)
{
// find a unique id.
while (attributes.ContainsKey(nextId)) nextId++;
// assign the id.
declaration.LocalId = nextId;
attributes[declaration.LocalId] = declaration;
// save the mapping.
NodeIdMapping mapping = new NodeIdMapping();
mapping.IntegerId = nextId;
mapping.NodeId = this.GetLocalNodeId(declaration.RootTypeId).ToString();
mapping.BrowePath = declaration.BrowsePathDisplayText;
mappingsToKeep.Add(mapping);
}
}
// update mapping set.
mappingSet.Mappings = mappingsToKeep;
m_attributes = attributes;
}
#endregion