/// <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>
        /// 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);
                }
            }
        }