/// <summary> /// Does any initialization required before the address space can be used. /// </summary> /// <remarks> /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// </remarks> public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences) { var alarmConfig = CreateAreaConfigurationCollection(); lock (Lock) { if (alarmConfig != null) { // Top level areas need a reference from the Server object. // These references are added to a list that is returned to the caller. // The caller will update the Objects folder node. IList <IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.Server, out references)) { externalReferences[ObjectIds.Server] = references = new List <IReference>(); } for (int ii = 0; ii < alarmConfig.Count; ii++) { // recursively process each area. AreaState area = CreateAndIndexAreas(null, alarmConfig[ii]); AddRootNotifier(area); // add an organizes reference from the ObjectsFolder to the area. references.Add(new NodeStateReference(ReferenceTypeIds.HasNotifier, false, area.NodeId)); } } // start the simulation. m_system.StartSimulation(); m_simulationTimer = new Timer(OnRaiseSystemEvents, null, 1000, 1000); } }
/// <summary> /// Creates and indexes an area defined for the server. /// </summary> private AreaState CreateAndIndexAreas(AreaState parent, AreaConfiguration configuration) { // create a unique path to the area. string areaPath = Utils.Format("{0}/{1}", (parent != null) ? parent.SymbolicName : String.Empty, configuration.Name); NodeId areaId = ModelUtils.ConstructIdForArea(areaPath, NamespaceIndex); // create the object that will be used to access the area and any variables contained within it. AreaState area = new AreaState(SystemContext, parent, areaId, configuration); m_areas[areaPath] = area; if (parent != null) { parent.AddChild(area); } // create an index any sub-areas defined for the area. if (configuration.SubAreas != null) { for (int ii = 0; ii < configuration.SubAreas.Count; ii++) { CreateAndIndexAreas(area, configuration.SubAreas[ii]); } } // add references to sources. if (configuration.SourcePaths != null) { for (int ii = 0; ii < configuration.SourcePaths.Count; ii++) { string sourcePath = configuration.SourcePaths[ii]; // check if the source already exists because it is referenced by another area. SourceState source = null; if (!m_sources.TryGetValue(sourcePath, out source)) { NodeId sourceId = ModelUtils.ConstructIdForSource(sourcePath, NamespaceIndex); m_sources[sourcePath] = source = new SourceState(this, sourceId, sourcePath); } // HasEventSource and HasNotifier control the propagation of event notifications so // they are not like other references. These calls set up a link between the source // and area that will cause events produced by the source to be automatically // propagated to the area. source.AddNotifier(SystemContext, ReferenceTypeIds.HasEventSource, true, area); area.AddNotifier(SystemContext, ReferenceTypeIds.HasEventSource, false, source); } } return(area); }
/// <summary> /// Initializes the area. /// </summary> public AreaState( ISystemContext context, AreaState parent, NodeId nodeId, AreaConfiguration configuration) : base(parent) { Initialize(context); // initialize the area with the fixed metadata. this.SymbolicName = configuration.Name; this.NodeId = nodeId; this.BrowseName = new QualifiedName(Utils.Format("{0}", configuration.Name), nodeId.NamespaceIndex); this.DisplayName = BrowseName.Name; this.Description = null; this.ReferenceTypeId = ReferenceTypeIds.HasNotifier; this.TypeDefinitionId = ObjectTypeIds.FolderType; this.EventNotifier = EventNotifiers.SubscribeToEvents; }
/// <summary> /// Verifies that the specified node exists. /// </summary> protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary <NodeId, NodeState> cache) { // not valid if no root. if (handle == null) { return(null); } // check if previously validated. if (handle.Validated) { return(handle.Node); } NodeState target = null; // check if already in the cache. if (cache != null) { if (cache.TryGetValue(handle.NodeId, out target)) { // nulls mean a NodeId which was previously found to be invalid has been referenced again. if (target == null) { return(null); } handle.Node = target; handle.Validated = true; return(handle.Node); } target = null; } try { // check if the node id has been parsed. if (handle.ParsedNodeId == null) { return(null); } NodeState root = null; // validate area. if (handle.ParsedNodeId.RootType == ModelUtils.Area) { AreaState area = null; if (!m_areas.TryGetValue(handle.ParsedNodeId.RootId, out area)) { return(null); } root = area; } // validate soucre. else if (handle.ParsedNodeId.RootType == ModelUtils.Source) { SourceState source = null; if (!m_sources.TryGetValue(handle.ParsedNodeId.RootId, out source)) { return(null); } root = source; } // unknown root type. else { return(null); } // all done if no components to validate. if (String.IsNullOrEmpty(handle.ParsedNodeId.ComponentPath)) { handle.Validated = true; handle.Node = target = root; return(handle.Node); } // validate component. NodeState component = root.FindChildBySymbolicName(context, handle.ParsedNodeId.ComponentPath); // component does not exist. if (component == null) { return(null); } // found a valid component. handle.Validated = true; handle.Node = target = component; return(handle.Node); } finally { // store the node in the cache to optimize subsequent lookups. if (cache != null) { cache.Add(handle.NodeId, target); } } }