/// <summary> /// Updates the event types in cache with the most recent info fetched from the AE server. /// </summary> public void UpdateCache(ServerSystemContext context, ushort namespaceIndex) { // clear the existing nodes. EventTypeNodes = new NodeIdDictionary<BaseObjectTypeState>(); Attributes = new Dictionary<int,int[]>(); TypeTable typeTable = context.TypeTable as TypeTable; // rebuild from the recently fetched list. for (int ii = 0; ii < EventTypes.Count; ii++) { // save the attributes for use when creating filters. if (EventTypes[ii].EventTypeMapping != EventTypeMapping.ConditionClassType && !Attributes.ContainsKey(EventTypes[ii].CategoryId)) { EventType eventType = EventTypes[ii]; int[] attributeIds = new int[eventType.Attributes.Count]; for (int jj = 0; jj < attributeIds.Length; jj++) { attributeIds[jj] = eventType.Attributes[jj].Id; } Attributes.Add(EventTypes[ii].CategoryId, attributeIds); } AeEventTypeState node = new AeEventTypeState(EventTypes[ii], namespaceIndex); BaseObjectTypeState mappingNode = null; if (!EventTypeNodes.TryGetValue(node.SuperTypeId, out mappingNode)) { mappingNode = new AeEventTypeMappingState(node.EventType.EventTypeMapping, namespaceIndex); EventTypeNodes.Add(mappingNode.NodeId, mappingNode); // ensure the mapping node is in the type table. if (typeTable != null) { if (!typeTable.IsKnown(mappingNode.NodeId)) { typeTable.AddSubtype(mappingNode.NodeId, mappingNode.SuperTypeId); } } } EventTypeNodes.Add(node.NodeId, node); // ensure the type node is in the type table. if (typeTable != null) { if (!typeTable.IsKnown(node.NodeId)) { typeTable.AddSubtype(node.NodeId, mappingNode.NodeId); } } } }
/// <summary> /// Indexes the well known subtypes. /// </summary> private void IndexWellKnownTypes() { SystemContext context = new SystemContext(); context.EncodeableFactory = m_session.MessageContext.Factory; context.NamespaceUris = m_session.NamespaceUris; context.ServerUris = m_session.ServerUris; NodeStateCollection predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.Stack.Generated.Opc.Ua.PredefinedNodes.uanodes", typeof(NodeState).Assembly, true); NodeIdDictionary <BaseTypeState> types = new NodeIdDictionary <BaseTypeState>(); // collect the instance declarations for all types. for (int ii = 0; ii < predefinedNodes.Count; ii++) { BaseTypeState type = predefinedNodes[ii] as BaseTypeState; if (type != null) { types.Add(type.NodeId, type); } } // index only those types which are subtypes of BaseEventType. foreach (BaseTypeState type in types.Values) { BaseTypeState subType = type; BaseTypeState superType = null; int eventType = 0; while (subType != null) { if (subType.NodeId == Opc.Ua.ObjectTypeIds.ConditionType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.ConditionType) { eventType = OpcRcw.Ae.Constants.CONDITION_EVENT; } else if (subType.NodeId == Opc.Ua.ObjectTypeIds.AuditEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.AuditEventType) { eventType = OpcRcw.Ae.Constants.TRACKING_EVENT; } else if (subType.NodeId == Opc.Ua.ObjectTypeIds.BaseEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.BaseEventType) { eventType = OpcRcw.Ae.Constants.SIMPLE_EVENT; } // found an event, collect the attribute and index it. if (eventType != 0) { List <AeEventAttribute> declarations = new List <AeEventAttribute>(); Dictionary <string, AeEventAttribute> map = new Dictionary <string, AeEventAttribute>(); ComAeUtils.CollectInstanceDeclarations( m_session, this, type, null, declarations, map); AeEventCategory declaration = new AeEventCategory(); declaration.TypeId = type.NodeId; declaration.SuperTypeId = type.SuperTypeId; declaration.EventType = eventType; declaration.Description = (LocalizedText.IsNullOrEmpty(type.DisplayName))?type.BrowseName.Name:type.DisplayName.Text; declaration.Attributes = declarations; m_eventTypes[declaration.TypeId] = declaration; break; } // follow the tree to the parent. if (!types.TryGetValue(subType.SuperTypeId, out superType)) { break; } subType = superType; } } // hide the built in attributes. AeEventCategory category = GetCategory(Opc.Ua.ObjectTypeIds.BaseEventType); if (category != null) { for (int ii = 0; ii < category.Attributes.Count; ii++) { switch (category.Attributes[ii].BrowsePathDisplayText) { case Opc.Ua.BrowseNames.Message: case Opc.Ua.BrowseNames.Severity: case Opc.Ua.BrowseNames.SourceName: case Opc.Ua.BrowseNames.Time: case Opc.Ua.BrowseNames.ReceiveTime: case Opc.Ua.BrowseNames.LocalTime: { category.Attributes[ii].Hidden = true; break; } } } } }
/// <summary cref="IDictionary.Remove" /> public bool Remove(IReference key) { // validate key. if (!ValidateReference(key, false)) { return(false); } m_version++; // look up the reference type. ReferenceTypeEntry entry = null; if (!m_references.TryGetValue(key.ReferenceTypeId, out entry)) { return(false); } // handle reference to external targets. if (key.TargetId.IsAbsolute) { Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { targets = entry.InverseExternalTargets; } else { targets = entry.ForwardExternalTargets; } if (targets == null) { return(false); } LinkedListNode <KeyValuePair <IReference, T> > node; if (!targets.TryGetValue(key.TargetId, out node)) { return(false); } m_list.Remove(node); targets.Remove(key.TargetId); } // handle reference to internal target. else { NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { targets = entry.InverseTargets; } else { targets = entry.ForwardTargets; } if (targets == null) { return(false); } LinkedListNode <KeyValuePair <IReference, T> > node; if (!targets.TryGetValue((NodeId)key.TargetId, out node)) { return(false); } m_list.Remove(node); targets.Remove((NodeId)key.TargetId); } // remove empty reference. if (entry.IsEmpty) { m_references.Remove(key.ReferenceTypeId); } return(true); }
/// <summary> /// Adds or replaces a reference. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <param name="replace">if set to <c>true</c> reference is replaced.</param> private void Add(IReference key, T value, bool replace) { // validate key. ValidateReference(key, true); m_version++; // look up the reference type. ReferenceTypeEntry entry = null; if (!m_references.TryGetValue(key.ReferenceTypeId, out entry)) { entry = new ReferenceTypeEntry(); m_references.Add(key.ReferenceTypeId, entry); } // handle reference to external targets. if (key.TargetId.IsAbsolute) { Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { if (entry.InverseExternalTargets == null) { entry.InverseExternalTargets = new Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > >(); } targets = entry.InverseExternalTargets; } else { if (entry.ForwardExternalTargets == null) { entry.ForwardExternalTargets = new Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > >(); } targets = entry.ForwardExternalTargets; } // create a new target. LinkedListNode <KeyValuePair <IReference, T> > node = new LinkedListNode <KeyValuePair <IReference, T> >(new KeyValuePair <IReference, T>(key, value)); // check if target already exists. LinkedListNode <KeyValuePair <IReference, T> > existingNode = null; if (!targets.TryGetValue(key.TargetId, out existingNode)) { existingNode = node; m_list.AddLast(node); } // need to replace reference in linked linked as well as the target list. else { if (!replace) { throw new ArgumentException("Key already exists in dictionary.", "key"); } m_list.AddAfter(existingNode, node); m_list.Remove(existingNode); } targets[key.TargetId] = node; } // handle reference to internal target. else { NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { if (entry.InverseTargets == null) { entry.InverseTargets = new NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > >(); } targets = entry.InverseTargets; } else { if (entry.ForwardTargets == null) { entry.ForwardTargets = new NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > >(); } targets = entry.ForwardTargets; } NodeId targetId = (NodeId)key.TargetId; // create a new target. LinkedListNode <KeyValuePair <IReference, T> > node = new LinkedListNode <KeyValuePair <IReference, T> >(new KeyValuePair <IReference, T>(key, value)); // check if target already exists. LinkedListNode <KeyValuePair <IReference, T> > existingNode = null; if (!targets.TryGetValue(targetId, out existingNode)) { existingNode = node; m_list.AddLast(node); } // need to replace reference in linked linked as well as the target list. else { if (!replace) { throw new ArgumentException("Key already exists in dictionary.", "key"); } m_list.AddAfter(existingNode, node); m_list.Remove(existingNode); } targets[targetId] = node; } }
/// <summary> /// Returns the target entry associated with the reference. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns>The target entry associated with the reference.</returns> private bool TryGetEntry(IReference key, out KeyValuePair <IReference, T> value) { value = new KeyValuePair <IReference, T>(); // validate key. if (!ValidateReference(key, false)) { return(false); } // look up the reference type. ReferenceTypeEntry entry = null; if (!m_references.TryGetValue(key.ReferenceTypeId, out entry)) { return(false); } // handle reference to external targets. if (key.TargetId.IsAbsolute) { Dictionary <ExpandedNodeId, LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { targets = entry.InverseExternalTargets; } else { targets = entry.ForwardExternalTargets; } if (targets == null) { return(false); } LinkedListNode <KeyValuePair <IReference, T> > node; if (targets.TryGetValue(key.TargetId, out node)) { value = node.Value; return(true); } } // handle reference to internal target. else { NodeIdDictionary <LinkedListNode <KeyValuePair <IReference, T> > > targets = null; if (key.IsInverse) { targets = entry.InverseTargets; } else { targets = entry.ForwardTargets; } if (targets == null) { return(false); } LinkedListNode <KeyValuePair <IReference, T> > node; if (targets.TryGetValue((NodeId)key.TargetId, out node)) { value = node.Value; return(true); } } return(false); }
/// <summary> /// Indexes the well known subtypes. /// </summary> private void IndexWellKnownTypes() { SystemContext context = new SystemContext(); context.EncodeableFactory = m_session.MessageContext.Factory; context.NamespaceUris = m_session.NamespaceUris; context.ServerUris = m_session.ServerUris; NodeStateCollection predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, "Opc.Ua.Stack.Generated.Opc.Ua.PredefinedNodes.uanodes", typeof(NodeState).Assembly, true); NodeIdDictionary<BaseTypeState> types = new NodeIdDictionary<BaseTypeState>(); // collect the instance declarations for all types. for (int ii = 0; ii < predefinedNodes.Count; ii++) { BaseTypeState type = predefinedNodes[ii] as BaseTypeState; if (type != null) { types.Add(type.NodeId, type); } } // index only those types which are subtypes of BaseEventType. foreach (BaseTypeState type in types.Values) { BaseTypeState subType = type; BaseTypeState superType = null; int eventType = 0; while (subType != null) { if (subType.NodeId == Opc.Ua.ObjectTypeIds.ConditionType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.ConditionType) { eventType = OpcRcw.Ae.Constants.CONDITION_EVENT; } else if (subType.NodeId == Opc.Ua.ObjectTypeIds.AuditEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.AuditEventType) { eventType = OpcRcw.Ae.Constants.TRACKING_EVENT; } else if (subType.NodeId == Opc.Ua.ObjectTypeIds.BaseEventType || subType.SuperTypeId == Opc.Ua.ObjectTypeIds.BaseEventType) { eventType = OpcRcw.Ae.Constants.SIMPLE_EVENT; } // found an event, collect the attribute and index it. if (eventType != 0) { List<AeEventAttribute> declarations = new List<AeEventAttribute>(); Dictionary<string, AeEventAttribute> map = new Dictionary<string, AeEventAttribute>(); ComAeUtils.CollectInstanceDeclarations( m_session, this, type, null, declarations, map); AeEventCategory declaration = new AeEventCategory(); declaration.TypeId = type.NodeId; declaration.SuperTypeId = type.SuperTypeId; declaration.EventType = eventType; declaration.Description = (LocalizedText.IsNullOrEmpty(type.DisplayName))?type.BrowseName.Name:type.DisplayName.Text; declaration.Attributes = declarations; m_eventTypes[declaration.TypeId] = declaration; break; } // follow the tree to the parent. if (!types.TryGetValue(subType.SuperTypeId, out superType)) { break; } subType = superType; } } // hide the built in attributes. AeEventCategory category = GetCategory(Opc.Ua.ObjectTypeIds.BaseEventType); if (category != null) { for (int ii = 0; ii < category.Attributes.Count; ii++) { switch (category.Attributes[ii].BrowsePathDisplayText) { case Opc.Ua.BrowseNames.Message: case Opc.Ua.BrowseNames.Severity: case Opc.Ua.BrowseNames.SourceName: case Opc.Ua.BrowseNames.Time: case Opc.Ua.BrowseNames.ReceiveTime: case Opc.Ua.BrowseNames.LocalTime: { category.Attributes[ii].Hidden = true; break; } } } } }