/// <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);
        }
예제 #3
0
        /// <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);
                }
            }
        }