/// <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)
        {
            lock (Lock)
            {
                // ensure the namespace used by the node manager is in the server's namespace table.
                m_typeNamespaceIndex = Server.NamespaceUris.GetIndexOrAppend(Namespaces.TestData);
                m_namespaceIndex     = Server.NamespaceUris.GetIndexOrAppend(Namespaces.TestData + "/Instance");

                base.CreateAddressSpace(externalReferences);

                // start monitoring the system status.
                m_systemStatusCondition = (TestSystemConditionState)FindPredefinedNode(
                    new NodeId(Objects.Data_Conditions_SystemStatus, m_typeNamespaceIndex),
                    typeof(TestSystemConditionState));

                if (m_systemStatusCondition != null)
                {
                    m_systemStatusTimer = new Timer(OnCheckSystemStatus, null, 5000, 5000);
                    m_systemStatusCondition.Retain.Value = true;
                }

                // link all conditions to the conditions folder.
                NodeState conditionsFolder = (NodeState)FindPredefinedNode(
                    new NodeId(Objects.Data_Conditions, m_typeNamespaceIndex),
                    typeof(NodeState));

                foreach (NodeState node in PredefinedNodes.Values)
                {
                    ConditionState condition = node as ConditionState;

                    if (condition != null && !Object.ReferenceEquals(condition.Parent, conditionsFolder))
                    {
                        condition.AddNotifier(SystemContext, null, true, conditionsFolder);
                        conditionsFolder.AddNotifier(SystemContext, null, false, condition);
                    }
                }

                // enable history for all numeric scalar values.
                ScalarValueObjectState scalarValues = (ScalarValueObjectState)FindPredefinedNode(
                    new NodeId(Objects.Data_Dynamic_Scalar, m_typeNamespaceIndex),
                    typeof(ScalarValueObjectState));

                scalarValues.Int32Value.Historizing = true;
                scalarValues.Int32Value.AccessLevel = (byte)(scalarValues.Int32Value.AccessLevel | AccessLevels.HistoryRead);

                m_system.EnableHistoryArchiving(scalarValues.Int32Value);
            }
        }
        /// <summary>
        /// Replaces the generic node with a node specific to the model.
        /// </summary>
        protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context, NodeState predefinedNode)
        {
            BaseObjectState passiveNode = predefinedNode as BaseObjectState;

            if (passiveNode == null)
            {
                return(predefinedNode);
            }

            NodeId typeId = passiveNode.TypeDefinitionId;

            if (!IsNodeIdInNamespace(typeId) || typeId.IdType != IdType.Numeric)
            {
                return(predefinedNode);
            }

            switch ((uint)typeId.Identifier)
            {
            case ObjectTypes.TestSystemConditionType:
            {
                if (passiveNode is TestSystemConditionState)
                {
                    break;
                }

                TestSystemConditionState activeNode = new TestSystemConditionState(passiveNode.Parent);
                activeNode.Create(context, passiveNode);

                if (passiveNode.Parent != null)
                {
                    passiveNode.Parent.ReplaceChild(context, activeNode);
                }

                return(activeNode);
            }

            case ObjectTypes.ScalarValueObjectType:
            {
                if (passiveNode is ScalarValueObjectState)
                {
                    break;
                }

                ScalarValueObjectState activeNode = new ScalarValueObjectState(passiveNode.Parent);
                activeNode.Create(context, passiveNode);

                if (passiveNode.Parent != null)
                {
                    passiveNode.Parent.ReplaceChild(context, activeNode);
                }

                return(activeNode);
            }

            case ObjectTypes.AnalogScalarValueObjectType:
            {
                if (passiveNode is AnalogScalarValueObjectState)
                {
                    break;
                }

                AnalogScalarValueObjectState activeNode = new AnalogScalarValueObjectState(passiveNode.Parent);
                activeNode.Create(context, passiveNode);

                if (passiveNode.Parent != null)
                {
                    passiveNode.Parent.ReplaceChild(context, activeNode);
                }

                return(activeNode);
            }

            case ObjectTypes.ArrayValueObjectType:
            {
                if (passiveNode is ArrayValueObjectState)
                {
                    break;
                }

                ArrayValueObjectState activeNode = new ArrayValueObjectState(passiveNode.Parent);
                activeNode.Create(context, passiveNode);

                if (passiveNode.Parent != null)
                {
                    passiveNode.Parent.ReplaceChild(context, activeNode);
                }

                return(activeNode);
            }

            case ObjectTypes.AnalogArrayValueObjectType:
            {
                if (passiveNode is AnalogArrayValueObjectState)
                {
                    break;
                }

                AnalogArrayValueObjectState activeNode = new AnalogArrayValueObjectState(passiveNode.Parent);
                activeNode.Create(context, passiveNode);

                if (passiveNode.Parent != null)
                {
                    passiveNode.Parent.ReplaceChild(context, activeNode);
                }

                return(activeNode);
            }

            case ObjectTypes.UserScalarValueObjectType:
            {
                if (passiveNode is UserScalarValueObjectState)
                {
                    break;
                }

                UserScalarValueObjectState activeNode = new UserScalarValueObjectState(passiveNode.Parent);
                activeNode.Create(context, passiveNode);

                if (passiveNode.Parent != null)
                {
                    passiveNode.Parent.ReplaceChild(context, activeNode);
                }

                return(activeNode);
            }

            case ObjectTypes.UserArrayValueObjectType:
            {
                if (passiveNode is UserArrayValueObjectState)
                {
                    break;
                }

                UserArrayValueObjectState activeNode = new UserArrayValueObjectState(passiveNode.Parent);
                activeNode.Create(context, passiveNode);

                if (passiveNode.Parent != null)
                {
                    passiveNode.Parent.ReplaceChild(context, activeNode);
                }

                return(activeNode);
            }

            case ObjectTypes.MethodTestType:
            {
                if (passiveNode is MethodTestState)
                {
                    break;
                }

                MethodTestState activeNode = new MethodTestState(passiveNode.Parent);
                activeNode.Create(context, passiveNode);

                if (passiveNode.Parent != null)
                {
                    passiveNode.Parent.ReplaceChild(context, activeNode);
                }

                return(activeNode);
            }
            }

            return(predefinedNode);
        }
        /// <summary>
        /// Replaces the generic node with a node specific to the model.
        /// </summary>
        protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context, NodeState predefinedNode)
        {
            BaseObjectState passiveNode = predefinedNode as BaseObjectState;

            if (passiveNode == null)
            {
                return predefinedNode;
            }

            NodeId typeId = passiveNode.TypeDefinitionId;

            if (!IsNodeIdInNamespace(typeId) || typeId.IdType != IdType.Numeric)
            {
                return predefinedNode;
            }

            switch ((uint)typeId.Identifier)
            {
                case ObjectTypes.TestSystemConditionType:
                {
                    if (passiveNode is TestSystemConditionState)
                    {
                        break;
                    }

                    TestSystemConditionState activeNode = new TestSystemConditionState(passiveNode.Parent);
                    activeNode.Create(context, passiveNode);

                    if (passiveNode.Parent != null)
                    {
                        passiveNode.Parent.ReplaceChild(context, activeNode);
                    }

                    return activeNode;
                }

                case ObjectTypes.ScalarValueObjectType:
                {
                    if (passiveNode is ScalarValueObjectState)
                    {
                        break;
                    }

                    ScalarValueObjectState activeNode = new ScalarValueObjectState(passiveNode.Parent);
                    activeNode.Create(context, passiveNode);

                    if (passiveNode.Parent != null)
                    {
                        passiveNode.Parent.ReplaceChild(context, activeNode);
                    }

                    return activeNode;
                }

                case ObjectTypes.AnalogScalarValueObjectType:
                {
                    if (passiveNode is AnalogScalarValueObjectState)
                    {
                        break;
                    }

                    AnalogScalarValueObjectState activeNode = new AnalogScalarValueObjectState(passiveNode.Parent);
                    activeNode.Create(context, passiveNode);

                    if (passiveNode.Parent != null)
                    {
                        passiveNode.Parent.ReplaceChild(context, activeNode);
                    }

                    return activeNode;
                }

                case ObjectTypes.ArrayValueObjectType:
                {
                    if (passiveNode is ArrayValueObjectState)
                    {
                        break;
                    }

                    ArrayValueObjectState activeNode = new ArrayValueObjectState(passiveNode.Parent);
                    activeNode.Create(context, passiveNode);

                    if (passiveNode.Parent != null)
                    {
                        passiveNode.Parent.ReplaceChild(context, activeNode);
                    }

                    return activeNode;
                }

                case ObjectTypes.AnalogArrayValueObjectType:
                {
                    if (passiveNode is AnalogArrayValueObjectState)
                    {
                        break;
                    }

                    AnalogArrayValueObjectState activeNode = new AnalogArrayValueObjectState(passiveNode.Parent);
                    activeNode.Create(context, passiveNode);

                    if (passiveNode.Parent != null)
                    {
                        passiveNode.Parent.ReplaceChild(context, activeNode);
                    }

                    return activeNode;
                }

                case ObjectTypes.UserScalarValueObjectType:
                {
                    if (passiveNode is UserScalarValueObjectState)
                    {
                        break;
                    }

                    UserScalarValueObjectState activeNode = new UserScalarValueObjectState(passiveNode.Parent);
                    activeNode.Create(context, passiveNode);

                    if (passiveNode.Parent != null)
                    {
                        passiveNode.Parent.ReplaceChild(context, activeNode);
                    }

                    return activeNode;
                }

                case ObjectTypes.UserArrayValueObjectType:
                {
                    if (passiveNode is UserArrayValueObjectState)
                    {
                        break;
                    }

                    UserArrayValueObjectState activeNode = new UserArrayValueObjectState(passiveNode.Parent);
                    activeNode.Create(context, passiveNode);

                    if (passiveNode.Parent != null)
                    {
                        passiveNode.Parent.ReplaceChild(context, activeNode);
                    }

                    return activeNode;
                }

                case ObjectTypes.MethodTestType:
                {
                    if (passiveNode is MethodTestState)
                    {
                        break;
                    }

                    MethodTestState activeNode = new MethodTestState(passiveNode.Parent);
                    activeNode.Create(context, passiveNode);

                    if (passiveNode.Parent != null)
                    {
                        passiveNode.Parent.ReplaceChild(context, activeNode);
                    }

                    return activeNode;
                }
            }

            return predefinedNode;
        }