/// <summary>
        /// Recursively indexes the node and its children.
        /// </summary>
        protected virtual void RemovePredefinedNode(
            ISystemContext context, 
            NodeState node, 
            List<LocalReference> referencesToRemove)
        {
            m_predefinedNodes.Remove(node.NodeId);
            node.UpdateChangeMasks(NodeStateChangeMasks.Deleted);
            node.ClearChangeMasks(context, false);
            OnNodeRemoved(node);

            // remove from the parent.
            BaseInstanceState instance = node as BaseInstanceState;

            if (instance != null && instance.Parent != null)
            {
                instance.Parent.RemoveChild(instance);
            }

            // remove children.
            List<BaseInstanceState> children = new List<BaseInstanceState>();
            node.GetChildren(context, children);

            for (int ii = 0; ii < children.Count; ii++)
            {
                node.RemoveChild(children[ii]);
            }

            for (int ii = 0; ii < children.Count; ii++)
            {
                RemovePredefinedNode(context, children[ii], referencesToRemove);
            }
                        
            // remove from type table.
            BaseTypeState type = node as BaseTypeState;

            if (type != null)
            {
                m_server.TypeTree.Remove(type.NodeId);
            }
            
            // remove inverse references.
            List<IReference> references = new List<IReference>();
            node.GetReferences(context, references);

            for (int ii = 0; ii < references.Count; ii++)
            {
                IReference reference = references[ii];

                if (reference.TargetId.IsAbsolute)
                {
                    continue;
                }

                LocalReference referenceToRemove = new LocalReference(
                    (NodeId)reference.TargetId,
                    reference.ReferenceTypeId,
                    reference.IsInverse,
                    node.NodeId);

                referencesToRemove.Add(referenceToRemove);
            }
        }
        /// <summary>
        /// Convert to service object
        /// </summary>
        /// <param name="state"></param>
        /// <param name="context"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        public static BaseNodeModel ToNodeModel(this NodeState state, ISystemContext context,
                                                BaseNodeModel parent = null)
        {
            BaseNodeModel nodeModel;

            switch (state)
            {
            case ViewState viewState:
                nodeModel = new ViewNodeModel {
                    ContainsNoLoops = viewState.ContainsNoLoops.ToNullable(false),
                    EventNotifier   = viewState.EventNotifier.ToNullable(EventNotifiers.None),
                };
                break;

            case BaseTypeState typeState:
                switch (typeState)
                {
                case BaseVariableTypeState variableType:
                    switch (variableType)
                    {
                    case BaseDataVariableTypeState data:
                        nodeModel = new DataVariableTypeNodeModel();
                        break;

                    case PropertyTypeState property:
                        nodeModel = new PropertyTypeNodeModel();
                        break;

                    default:
                        return(null);
                    }
                    var baseVariableTypeState = nodeModel as VariableTypeNodeModel;
                    baseVariableTypeState.ArrayDimensions =
                        variableType.ArrayDimensions?.ToArray();
                    baseVariableTypeState.DataType =
                        variableType.DataType;
                    baseVariableTypeState.ValueRank =
                        variableType.ValueRank.ToNullable(ValueRanks.Scalar);
                    baseVariableTypeState.Value =
                        variableType.WrappedValue;
                    break;

                case BaseObjectTypeState objectType:
                    nodeModel = new ObjectTypeNodeModel();
                    break;

                case ReferenceTypeState referenceType:
                    nodeModel = new ReferenceTypeNodeModel {
                        Symmetric   = referenceType.Symmetric.ToNullable(false),
                        InverseName = referenceType.InverseName
                    };
                    break;

                case DataTypeState dataType:
                    nodeModel = new DataTypeNodeModel {
                        //  Definition = dataType.Definition.ToDataTypeDefinition(),
                        Purpose = Schema.DataTypePurpose.Normal
                    };
                    break;

                default:
                    return(null);
                }
                var baseTypeState = nodeModel as TypeNodeModel;
                baseTypeState.IsAbstract = typeState.IsAbstract.ToNullable(false);
                break;

            case BaseInstanceState instanceState:
                switch (instanceState)
                {
                case BaseVariableState variable:
                    switch (variable)
                    {
                    case BaseDataVariableState data:
                        nodeModel = new DataVariableNodeModel(parent);
                        break;

                    case PropertyState property:
                        nodeModel = new PropertyNodeModel(parent);
                        break;

                    default:
                        return(null);
                    }
                    var baseVariableState = nodeModel as VariableNodeModel;
                    baseVariableState.ArrayDimensions =
                        variable.ArrayDimensions.ToArray();
                    baseVariableState.DataType =
                        variable.DataType;
                    baseVariableState.ValueRank =
                        variable.ValueRank.ToNullable(ValueRanks.Scalar);
                    baseVariableState.Value =
                        variable.WrappedValue;
                    baseVariableState.AccessLevel =
                        variable.AccessLevel.ToNullable(AccessLevels.CurrentRead);
                    baseVariableState.UserAccessLevel =
                        variable.UserAccessLevel.ToNullable(AccessLevels.CurrentRead);
                    baseVariableState.IsValueType =
                        variable.IsValueType;
                    baseVariableState.Historizing =
                        variable.Historizing.ToNullable(false);
                    baseVariableState.MinimumSamplingInterval =
                        variable.MinimumSamplingInterval.ToNullable(0.0);
                    baseVariableState.ModellingRuleId =
                        variable.ModellingRuleId;
                    baseVariableState.NumericId =
                        variable.NumericId;
                    baseVariableState.ReferenceTypeId =
                        variable.ReferenceTypeId;
                    baseVariableState.StatusCode =
                        variable.StatusCode.ToNullable(StatusCodes.Good);
                    baseVariableState.Timestamp =
                        variable.Timestamp.ToNullable(DateTime.MinValue);
                    baseVariableState.TypeDefinitionId =
                        variable.TypeDefinitionId;
                    break;

                case BaseObjectState obj:
                    nodeModel = new ObjectNodeModel(parent)
                    {
                        EventNotifier = obj.EventNotifier.ToNullable(EventNotifiers.None)
                    };
                    break;

                case MethodState method:
                    nodeModel = new MethodNodeModel(parent)
                    {
                        UserExecutable      = method.UserExecutable,
                        Executable          = method.Executable,
                        MethodDeclarationId = method.MethodDeclarationId,
                    };
                    break;

                default:
                    return(null);
                }
                break;

            default:
                return(null);
            }
            nodeModel.BrowseName    = state.BrowseName;
            nodeModel.Description   = state.Description;
            nodeModel.DisplayName   = state.DisplayName;
            nodeModel.Handle        = state.Handle;
            nodeModel.NodeId        = state.NodeId;
            nodeModel.SymbolicName  = state.SymbolicName;
            nodeModel.WriteMask     = state.WriteMask.ToNullable(AttributeWriteMask.None);
            nodeModel.UserWriteMask = state.UserWriteMask.ToNullable(AttributeWriteMask.None);
            var children = new List <BaseInstanceState>();

            state.GetChildren(context, children);
            foreach (var child in children)
            {
                nodeModel.AddChild(child.ToNodeModel(context, nodeModel) as InstanceNodeModel);
            }
            var references = new List <IReference>();

            state.GetReferences(context, references);
            foreach (var reference in references)
            {
                nodeModel.AddReference(reference.ReferenceTypeId, reference.IsInverse,
                                       reference.TargetId);
            }
            return(nodeModel);
        }