internal void    AddSequence()
        {
            ContentNode n      = (ContentNode)stack.Pop();
            ContentNode inNode = new InternalNode(n, null, ContentNode.Type.Sequence);

            n.ParentNode = inNode;
            stack.Push(inNode);
        }
        internal void    AddAny(XmlSchemaAny any)
        {
            ContentNode n = new AnyNode(any);

            if (stack.Count > 0)
            {
                InternalNode inNode = (InternalNode)stack.Pop();
                if (inNode != null)
                {
                    inNode.RightNode = n;
                    n.ParentNode     = inNode;
                    n = inNode;
                }
            }
            stack.Push(n);
            isPartial       = true;
            abnormalContent = true;
        }
        internal void    CloseGroup()
        {
            ContentNode n = (ContentNode)stack.Pop();

            if (n == null)
            {
                return;
            }
            if (stack.Count == 0)
            {
                if (n.NodeType == ContentNode.Type.Terminal)
                {
                    TerminalNode t = (TerminalNode)n;
                    if (t.Name == schemaNames.QnPCData)
                    {
                        // we had a lone (#PCDATA) which needs to be
                        // wrapped in a STAR node.
                        ContentNode n1 = new InternalNode(n, null, ContentNode.Type.Star);
                        n.ParentNode = n1;
                        n            = n1;
                    }
                }
                contentNode = n;
                isPartial   = false;
            }
            else
            {
                // some collapsing to do...
                InternalNode inNode = (InternalNode)stack.Pop();
                if (inNode != null)
                {
                    inNode.RightNode = n;
                    n.ParentNode     = inNode;
                    n         = inNode;
                    isPartial = true;
                }
                else
                {
                    isPartial = false;
                }

                stack.Push(n);
            }
        }
        internal void     MinMax(decimal min, decimal max)
        {
            ContentNode n;

            if (stack.Count > 0)
            {
                InternalNode n1;
                n = (ContentNode)stack.Pop();
                if (isPartial &&
                    n.NodeType != ContentNode.Type.Terminal &&
                    n.NodeType != ContentNode.Type.Any)
                {
                    // need to reach in and wrap _pRight hand side of element.
                    // and n remains the same.
                    InternalNode inNode = (InternalNode)n;
                    n1            = new MinMaxNode(inNode.RightNode, min, max);
                    n1.ParentNode = n;
                    if (inNode.RightNode != null)
                    {
                        inNode.RightNode.ParentNode = n1;
                    }
                    inNode.RightNode = n1;
                }
                else
                {
                    // wrap terminal or any node
                    n1           = new MinMaxNode(n, min, max);
                    n.ParentNode = n1;
                    n            = n1;
                }
                stack.Push(n);
            }
            else
            {
                // wrap whole content
                n = new MinMaxNode(contentNode, min, max);
                contentNode.ParentNode = n;
                contentNode            = n;
            }

            abnormalContent = true;
        }
        internal void AddTerminal(XmlQualifiedName qname, String prefix, ValidationEventHandler eventHandler)
        {
            if (schemaNames.QnPCData.Equals(qname))
            {
                nodeTable = new Hashtable();
            }
            else if (nodeTable != null)
            {
                if (nodeTable.ContainsKey(qname))
                {
                    if (eventHandler != null)
                    {
                        eventHandler(
                            this,
                            new ValidationEventArgs(
                                new XmlSchemaException(Res.Sch_DupElement, qname.ToString())
                                )
                            );
                    }
                    //notice: should not return here!
                }
                else
                {
                    nodeTable.Add(qname, qname);
                }
            }

            ContentNode n = NewTerminalNode(qname);

            if (stack.Count > 0)
            {
                InternalNode inNode = (InternalNode)stack.Pop();
                if (inNode != null)
                {
                    inNode.RightNode = n;
                    n.ParentNode     = inNode;
                    n = inNode;
                }
            }
            stack.Push(n);
            isPartial = true;
        }
        internal void    Closure(ContentNode.Type type)
        {
            ContentNode n;

            if (stack.Count > 0)
            {
                InternalNode n1;
                n = (ContentNode)stack.Pop();
                if (isPartial &&
                    n.NodeType != ContentNode.Type.Terminal &&
                    n.NodeType != ContentNode.Type.Any)
                {
                    // need to reach in and wrap _pRight hand side of element.
                    // and n remains the same.
                    InternalNode inNode = (InternalNode)n;
                    n1            = new InternalNode(inNode.RightNode, null, type);
                    n1.ParentNode = n;
                    if (inNode.RightNode != null)
                    {
                        inNode.RightNode.ParentNode = n1;
                    }
                    inNode.RightNode = n1;
                }
                else
                {
                    // wrap terminal or any node
                    n1           = new InternalNode(n, null, type);
                    n.ParentNode = n1;
                    n            = n1;
                }
                stack.Push(n);
            }
            else
            {
                // wrap whole content
                n = new InternalNode(contentNode, null, type);
                contentNode.ParentNode = n;
                contentNode            = n;
            }
        }
        internal bool HasMatched(ValidationState context)
        {
            if (IsAllElements)
            {
                if (isAllEmptiable && context.AllElementsSet.IsEmpty)
                {
                    return(true);
                }
                else
                {
                    return(context.AllElementsSet.HasAllBits(this.allElementsSet));
                }
            }

            if (!IsCompiled)
            {
                // MIXED or ELEMENT
                int          NodeMatched = context.HasNodeMatched;
                InternalNode inNode      = (InternalNode)context.CurrentNode;
                if (inNode == contentNode)
                {
                    return(NodeMatched == 1 || inNode.LeftNode.Nullable());
                }
                while (inNode != contentNode)
                {
                    switch (inNode.NodeType)
                    {
                    case ContentNode.Type.Sequence:
                        if (((NodeMatched == 0) && (!inNode.LeftNode.Nullable() || !inNode.RightNode.Nullable())) ||
                            ((NodeMatched == 1) && !inNode.RightNode.Nullable()))
                        {
                            return(false);
                        }
                        break;

                    case ContentNode.Type.Choice:
                        if ((NodeMatched == 0) && !inNode.LeftNode.Nullable() && !inNode.LeftNode.Nullable())
                        {
                            return(false);
                        }
                        break;

                    case ContentNode.Type.Plus:
                        if ((NodeMatched == 0) && !inNode.LeftNode.Nullable())
                        {
                            return(false);
                        }
                        break;

                    case ContentNode.Type.MinMax: {
                        int          min;
                        MinMaxValues mm = (MinMaxValues)context.MinMaxValues[inNode];
                        if (mm == null)
                        {
                            min = ((MinMaxNode)inNode).Min;
                        }
                        else
                        {
                            min = mm.Min;
                        }
                        if ((min > 0) && !inNode.LeftNode.Nullable())
                        {
                            return(false);
                        }
                        break;
                    }

                    case ContentNode.Type.Star:
                    case ContentNode.Type.Qmark:
                    default:
                        break;
                    } // switch

                    NodeMatched = (((InternalNode)inNode.ParentNode).LeftNode == inNode) ? 1 : 2;
                    inNode      = (InternalNode)inNode.ParentNode;
                }

                return(NodeMatched == 1);
            }
            else
            {
                return(context.HasMatched);
            }
        }