QuerySelectOp.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Dispatcher / QuerySelectOp.cs / 1 / QuerySelectOp.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Dispatcher
{ 
    using System.Diagnostics;
    using System.Xml; 
    using System.Xml.XPath; 

    ///  
    /// This structure contains the criteria used to select a set of nodes from a context node
    ///
    /// Selectors select nodes with particular a relationship to a context node. Candidate nodes are first identified by
    /// traversing away from the context node along an axis of traversal. The attribute axis, for example, identifies all 
    /// attributes of a given context node as candidates for selection.
    /// 
    /// The candidate nodeset identified by axis traversal is then refined by applying node tests. 
    /// A nodeType test constructs a new nodeset by selecting only those nodes of a given type from source candidate set
    /// A qname test further refines this nodeset by selecting only those that match a given qname 
    /// 
    internal class NodeSelectCriteria
    {
        protected QueryAxis axis; 
        protected NodeQName qname;
        protected NodeQNameType qnameType; 
        protected QueryNodeType type; 

        internal NodeSelectCriteria(QueryAxisType axis, NodeQName qname, QueryNodeType nodeType) 
        {
            this.axis = QueryDataModel.GetAxis(axis);
            this.qname = qname;
            this.qnameType = qname.GetQNameType(); 
            this.type = nodeType;
        } 
 
        internal QueryAxis Axis
        { 
            get
            {
                return this.axis;
            } 
        }
 
        internal bool IsCompressable 
        {
            get 
            {
                // PERF, [....], weaken guard?
                return QueryAxisType.Self == this.axis.Type || QueryAxisType.Child == this.axis.Type;
                //return ((QueryAxisType.Self == this.axis.Type) || ((this.axis.Type != QueryAxisType.DescendantOrSelf || this.axis.Type != QueryAxisType.Descendant)&& 0 != ((QueryNodeType.Element | QueryNodeType.Root) & this.type))); 
            }
        } 
 
        internal NodeQName QName
        { 
            get
            {
                return this.qname;
            } 
        }
 
        internal QueryNodeType Type 
        {
            get 
            {
                return this.type;
            }
        } 

#if NO 
        internal static NodeSelectCriteria Create(QueryAxisType axis, NodeQName qname, QueryNodeType nodeType) 
        {
            return new NodeSelectCriteria(axis, qname, nodeType); 
        }
#endif
        public bool Equals(NodeSelectCriteria criteria)
        { 
            return (this.axis.Type == criteria.axis.Type && this.type == criteria.type && this.qname.Equals(criteria.qname));
        } 
#if NO 
        internal bool Match(SeekableXPathNavigator node)
        { 
            return (this.MatchType(node) && this.MatchQName(node));
        }
#endif
        internal bool MatchType(SeekableXPathNavigator node) 
        {
            QueryNodeType nodeType; 
            switch (node.NodeType) 
            {
                default: 
                    return false;

                case XPathNodeType.Root:
                    nodeType = QueryNodeType.Root; 
                    break;
 
                case XPathNodeType.Attribute: 
                    nodeType = QueryNodeType.Attribute;
                    break; 

                case XPathNodeType.Element:
                    nodeType = QueryNodeType.Element;
                    break; 

                case XPathNodeType.Comment: 
                    nodeType = QueryNodeType.Comment; 
                    break;
 
                case XPathNodeType.Text:
                case XPathNodeType.Whitespace:
                case XPathNodeType.SignificantWhitespace:
                    nodeType = QueryNodeType.Text; 
                    break;
 
                case XPathNodeType.ProcessingInstruction: 
                    nodeType = QueryNodeType.Processing;
                    break; 
            }

            return (nodeType == (this.type & nodeType));
        } 

        internal bool MatchQName(SeekableXPathNavigator node) 
        { 
            // Is this a standard qname test.. with known names and namespaces
            switch(this.qnameType & NodeQNameType.Standard) 
            {
                default:
                    break;
 
                case NodeQNameType.Name:
                    // Selection criteria did not specify a namespace. Then, if the node supplies a namespace, we know 
                    // that the criteria cannot possibly match 
                    return (0 == node.NamespaceURI.Length && this.qname.EqualsName(node.LocalName));
 
                case NodeQNameType.Standard:
                    string str = node.LocalName;
                    if (this.qname.name.Length == str.Length && this.qname.name == str)
                    { 
                        str = node.NamespaceURI;
                        return (this.qname.ns.Length == str.Length && this.qname.ns == str); 
                    } 
                    return false;
            } 

            if (NodeQNameType.Empty == this.qnameType)
            {
                return true; 
            }
 
            // Maybe a wildcard 
            switch(this.qnameType & NodeQNameType.Wildcard)
            { 
                default:
                    break;

                case NodeQNameType.NameWildcard: 
                    return this.qname.EqualsNamespace(node.NamespaceURI);
 
                case NodeQNameType.Wildcard: 
                    return true;
            } 

            return false;
        }
 
        internal void Select(SeekableXPathNavigator contextNode, NodeSequence destSequence)
        { 
            switch (this.type) 
            {
                default: 
                    if (QueryAxisType.Self == this.axis.Type)
                    {
                        if (this.MatchType(contextNode) && this.MatchQName(contextNode))
                        { 
                            destSequence.Add(contextNode);
                        } 
                    } 
                    else if (QueryAxisType.Descendant == this.axis.Type)
                    { 
                        SelectDescendants(contextNode, destSequence);
                    }
                    else if (QueryAxisType.DescendantOrSelf == this.axis.Type)
                    { 
                        destSequence.Add(contextNode);
                        SelectDescendants(contextNode, destSequence); 
                    } 
                    else if (QueryAxisType.Child == this.axis.Type)
                    { 
                        // Select children of arbitrary type off the context node
                        if (contextNode.MoveToFirstChild())
                        {
                            do 
                            {
                                // Select the node if its type and qname matches 
                                if (this.MatchType(contextNode) && this.MatchQName(contextNode)) 
                                {
                                    destSequence.Add(contextNode); 
                                }
                            }
                            while (contextNode.MoveToNext());
                        } 

                    } 
                    else if (QueryAxisType.Attribute == this.axis.Type) 
                    {
                        if (contextNode.MoveToFirstAttribute()) 
                        {
                            do
                            {
                                // Select the node if its type and qname matches 
                                if (this.MatchType(contextNode) && this.MatchQName(contextNode))
                                { 
                                    destSequence.Add(contextNode); 
                                    // you can't have multiple instances of an attibute with the same qname
                                    // Stop once one was found 
                                    // UNLESS WE HAVE A WILDCARD OFCOURSE!
                                    if (0 == (this.qnameType & NodeQNameType.Wildcard))
                                    {
                                        break; 
                                    }
                                } 
                            } 
                            while (contextNode.MoveToNextAttribute());
                        } 

                    }
                    else
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.Unexpected));
                    } 
                    break; 

                case QueryNodeType.Attribute: 
                    // Select attributes off the context Node
                    if (contextNode.MoveToFirstAttribute())
                    {
                        do 
                        {
                            if (this.MatchQName(contextNode)) 
                            { 
                                destSequence.Add(contextNode);
                                // you can't have multiple instances of an attibute with the same qname 
                                // Stop once one was found
                                // UNLESS WE HAVE A WILDCARD OFCOURSE!
                                if (0 == (this.qnameType & NodeQNameType.Wildcard))
                                { 
                                    break;
                                } 
                            } 
                        }
                        while (contextNode.MoveToNextAttribute()); 
                    }
                    break;

                case QueryNodeType.ChildNodes: 
                    if(QueryAxisType.Descendant == this.axis.Type)
                    { 
                        // Select descendants of arbitrary type off the context node 
                        SelectDescendants(contextNode, destSequence);
                    } 
                    else
                    {
                        // Select children of arbitrary type off the context node
                        if (contextNode.MoveToFirstChild()) 
                        {
                            do 
                            { 
                                // Select the node if its type and qname matches
                                if (this.MatchType(contextNode) && this.MatchQName(contextNode)) 
                                {
                                    destSequence.Add(contextNode);
                                }
                            } 
                            while (contextNode.MoveToNext());
                        } 
                    } 
                    break;
 
                case QueryNodeType.Element:
                    if(QueryAxisType.Descendant == this.axis.Type)
                    {
                        // Select descendants of arbitrary type off the context node 
                        SelectDescendants(contextNode, destSequence);
                    } 
                    else if (QueryAxisType.DescendantOrSelf == this.axis.Type) 
                    {
                        destSequence.Add(contextNode); 
                        SelectDescendants(contextNode, destSequence);
                    }
                    else if (contextNode.MoveToFirstChild())
                    { 
                        do
                        { 
                            // Children could have non element nodes in line 
                            // Select the node if it is an element and the qname matches
                            if (XPathNodeType.Element == contextNode.NodeType && this.MatchQName(contextNode)) 
                            {
                                destSequence.Add(contextNode);
                            }
                        } 
                        while (contextNode.MoveToNext());
                    } 
                    break; 

                case QueryNodeType.Root: 
                    contextNode.MoveToRoot();
                    destSequence.Add(contextNode);
                    break;
 
                case QueryNodeType.Text:
                    // Select child text nodes 
                    if (contextNode.MoveToFirstChild()) 
                    {
                        do 
                        {
                            // Select the node if its type matches
                            // Can't just do a comparison to XPathNodeType.Text since whitespace nodes
                            // count as text 
                            if (this.MatchType(contextNode))
                            { 
                                destSequence.Add(contextNode); 
                            }
                        } 
                        while (contextNode.MoveToNext());
                    }
                    break;
            } 
        }
 
        internal Opcode Select(SeekableXPathNavigator contextNode, NodeSequence destSequence, SelectOpcode next) 
        {
            Opcode returnOpcode = next.Next; 

            switch (this.type)
            {
                default: 
                    if (QueryAxisType.Self == this.axis.Type)
                    { 
                        if (this.MatchType(contextNode) && this.MatchQName(contextNode)) 
                        {
                            long position = contextNode.CurrentPosition; 
                            returnOpcode = next.Eval(destSequence, contextNode);
                            contextNode.CurrentPosition = position;
                        }
                    } 
                    else
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.Unexpected)); 
                    }
 
                    break;

                case QueryNodeType.ChildNodes:
                    // Select children of arbitrary type off the context node 
                    if (contextNode.MoveToFirstChild())
                    { 
                        do 
                        {
                            // Select the node if its type and qname matches 
                            if (this.MatchType(contextNode) && this.MatchQName(contextNode))
                            {
                                destSequence.Add(contextNode);
                            } 
                        }
                        while (contextNode.MoveToNext()); 
                    } 
                    break;
 
                case QueryNodeType.Element:
                    // Select child elements
                    if (contextNode.MoveToFirstChild())
                    { 
                        do
                        { 
                            // Children could have non element nodes in line 
                            // Select the node if it is an element and the qname matches
                            if (XPathNodeType.Element == contextNode.NodeType && this.MatchQName(contextNode)) 
                            {
                                long position = contextNode.CurrentPosition;
                                returnOpcode = next.Eval(destSequence, contextNode);
                                contextNode.CurrentPosition = position; 
                            }
                        } while (contextNode.MoveToNext()); 
                    } 

                    break; 

                case QueryNodeType.Root:
                    contextNode.MoveToRoot();
                    returnOpcode = next.Eval(destSequence, contextNode); 
                    break;
            } 
 
            return returnOpcode;
        } 

        void SelectDescendants(SeekableXPathNavigator contextNode, NodeSequence destSequence)
        {
            int level = 1; 
            if(!contextNode.MoveToFirstChild())
            { 
                return; 
            }
            while(level > 0) 
            {
                // Don't need type check.  All child nodes allowed.
                if (this.MatchQName(contextNode))
                { 
                    destSequence.Add(contextNode);
                } 
 
                if(contextNode.MoveToFirstChild())
                { 
                    ++level;
                }
                else if(contextNode.MoveToNext())
                { 

                } 
                else 
                {
                    while(level > 0) 
                    {
                        contextNode.MoveToParent();
                        --level;
 
                        if(contextNode.MoveToNext())
                        { 
                            break; 
                        }
                    } 
                }
            }
        }
 
#if DEBUG_FILTER
        public override string ToString() 
        { 
            return string.Format("{0}, {1}:{2}", this.type, this.qname.ns, this.qname.name);
        } 
#endif

    }
 
    // General purpose selector
    // Pops all parameters from the value stack 
    internal class SelectOpcode : Opcode 
    {
        protected NodeSelectCriteria criteria; 

        internal SelectOpcode(NodeSelectCriteria criteria)
            : this(OpcodeID.Select, criteria)
        { 
        }
 
        internal SelectOpcode(OpcodeID id, NodeSelectCriteria criteria) 
            : this(id, criteria, OpcodeFlags.None)
        { 
        }

        internal SelectOpcode(OpcodeID id, NodeSelectCriteria criteria, OpcodeFlags flags)
            : base(id) 
        {
            this.criteria = criteria; 
            this.flags |= (flags | OpcodeFlags.Select); 
            if (criteria.IsCompressable && (0 == (this.flags & OpcodeFlags.InitialSelect)))
            { 
                this.flags |= OpcodeFlags.CompressableSelect;
            }
        }
 
        internal NodeSelectCriteria Criteria
        { 
            get 
            {
                return this.criteria; 
            }
        }

        internal override bool Equals(Opcode op) 
        {
            if (base.Equals(op)) 
            { 
                return this.criteria.Equals(((SelectOpcode) op).criteria);
            } 

            return false;
        }
 
        internal override Opcode Eval(ProcessingContext context)
        { 
            StackFrame topFrame = context.TopSequenceArg; 
            SeekableXPathNavigator node = null;
            Value[] sequences = context.Sequences; 

            for (int i = topFrame.basePtr; i <= topFrame.endPtr; ++i)
            {
                // Each NodeSequence will generate a new one, but only if the source FilterSequence isn't empty 
                // If the source FilterSequence is empty, release it and replace it with an empty sequence
                NodeSequence sourceSeq = sequences[i].Sequence; 
                int sourceSeqCount = sourceSeq.Count; 
                if (sourceSeqCount == 0)
                { 
                    context.ReplaceSequenceAt(i, NodeSequence.Empty);
                    context.ReleaseSequence(sourceSeq);
                }
                else 
                {
                    NodeSequenceItem[] items = sourceSeq.Items; 
                    if (sourceSeq.CanReuse(context)) 
                    {
                        node = items[0].GetNavigator(); 
                        sourceSeq.Clear();
                        sourceSeq.StartNodeset();

                        this.criteria.Select(node, sourceSeq); 

                        sourceSeq.StopNodeset(); 
                    } 
                    else
                    { 
                        NodeSequence newSeq = null;
                        for (int item = 0; item < sourceSeqCount; ++item)
                        {
                            node = items[item].GetNavigator(); 
                            DiagnosticUtility.DebugAssert(null != node, "");
                            if (null == newSeq) 
                            { 
                                newSeq = context.CreateSequence();
                            } 
                            newSeq.StartNodeset();
                            this.criteria.Select(node, newSeq);
                            newSeq.StopNodeset();
                        } 
                        context.ReplaceSequenceAt(i, (null != newSeq) ? newSeq : NodeSequence.Empty);
                        context.ReleaseSequence(sourceSeq); 
                    } 
                }
            } 

            return this.next;
        }
 
        internal override Opcode Eval(NodeSequence sequence, SeekableXPathNavigator node)
        { 
            if (this.next == null || 0 == (this.next.Flags & OpcodeFlags.CompressableSelect)) 
            {
                // The next opcode is not a compressible select. Complete the select operation and return the next opcode 
                sequence.StartNodeset();
                this.criteria.Select(node, sequence);
                sequence.StopNodeset();
                return this.next; 
            }
 
            return this.criteria.Select(node, sequence, (SelectOpcode) this.next); 
        }
 
#if DEBUG_FILTER
        public override string ToString()
        {
            return string.Format("{0} {1}", base.ToString(), this.criteria.ToString()); 
        }
#endif 
    } 

    internal class InitialSelectOpcode : SelectOpcode 
    {
        internal InitialSelectOpcode(NodeSelectCriteria criteria)
            : base(OpcodeID.InitialSelect, criteria, OpcodeFlags.InitialSelect)
        { 
        }
 
        internal override Opcode Eval(ProcessingContext context) 
        {
            StackFrame topFrame = context.TopSequenceArg; 
            Value[] sequences = context.Sequences;

            bool wasInUse = context.SequenceStackInUse;
            context.PushSequenceFrame(); 
            for (int i = topFrame.basePtr; i <= topFrame.endPtr; ++i)
            { 
                NodeSequence sourceSeq = sequences[i].Sequence; 
                int count = sourceSeq.Count;
                if (count == 0) 
                {
                    // Empty sequence.
                    // Since there are no nodes in the sequence, we will track this sequence also
                    // using an empty sequence 
                    if (!wasInUse)
                        context.PushSequence(NodeSequence.Empty); 
                } 
                else
                { 
                    NodeSequenceItem[] items = sourceSeq.Items;
                    for (int item = 0; item < sourceSeq.Count; ++item)
                    {
                        SeekableXPathNavigator node = items[item].GetNavigator(); 
                        DiagnosticUtility.DebugAssert(null != node, "");
 
                        NodeSequence newSeq = context.CreateSequence(); 
                        newSeq.StartNodeset();
 
                        this.criteria.Select(node, newSeq);

                        newSeq.StopNodeset();
 
                        context.PushSequence(newSeq);
                    } 
                } 
            }
            return this.next; 
        }
    }

    internal class SelectRootOpcode : Opcode 
    {
        internal SelectRootOpcode() 
            : base(OpcodeID.SelectRoot) 
        {
        } 

        internal override Opcode Eval(ProcessingContext context)
        {
            // The query processor object also serves as the query document root 
            int iterationCount = context.IterationCount;
            Opcode returnOpcode = this.next; 
 
            // A root is always an initial step
            context.PushSequenceFrame(); 
            NodeSequence seq = context.CreateSequence();
            if (this.next != null && 0 != (this.next.Flags & OpcodeFlags.CompressableSelect))
            {
                SeekableXPathNavigator node = context.Processor.ContextNode; 
                node.MoveToRoot();
                returnOpcode = this.next.Eval(seq, node); 
                while(returnOpcode != null && 0 != (returnOpcode.Flags & OpcodeFlags.CompressableSelect)) 
                {
                    returnOpcode = returnOpcode.Next; 
                }
            }
            else
            { 
                // Roots do not have any qnames..
                seq.StartNodeset(); 
                SeekableXPathNavigator node = context.Processor.ContextNode; 
                node.MoveToRoot();
                seq.Add(node); 
                seq.StopNodeset();
            }

            if (seq.Count == 0) 
            {
                context.ReleaseSequence(seq); 
                seq = NodeSequence.Empty; 
            }
 
            for (int i = 0; i < iterationCount; ++i)
            {
                context.PushSequence(seq);
            } 
            if (iterationCount > 1)
                seq.refCount += iterationCount - 1; 
 
            return returnOpcode;
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK