91c37b719a80d6fd3545f9a3e3b6011ea3ef13a9
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / XPath / Internal / BaseAxisQuery.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="baseaxisquery.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7
8 namespace MS.Internal.Xml.XPath {
9     using System;
10     using System.Xml;
11     using System.Xml.XPath;
12     using System.Diagnostics;
13     using System.Globalization;
14     using System.Xml.Xsl;
15     using System.Collections;
16
17     internal abstract class BaseAxisQuery : Query {
18         internal Query qyInput;
19         bool nameTest;
20         string name;
21         string prefix;
22         string nsUri;
23         XPathNodeType typeTest;
24
25         // these two things are the state of this class
26         // that need to be reset whenever the context changes.
27         protected XPathNavigator currentNode;
28         protected int position;
29
30         protected BaseAxisQuery(Query qyInput) {
31             this.name = string.Empty;
32             this.prefix = string.Empty;
33             this.nsUri = string.Empty;
34             this.qyInput = qyInput;
35         }
36         protected BaseAxisQuery(Query qyInput, string name, string prefix, XPathNodeType typeTest) {
37             Debug.Assert(qyInput != null);
38             this.qyInput  = qyInput;
39             this.name     = name;
40             this.prefix   = prefix;
41             this.typeTest = typeTest;
42             this.nameTest = prefix.Length != 0 || name.Length != 0;
43             this.nsUri    = string.Empty;
44         }
45         protected BaseAxisQuery(BaseAxisQuery other) : base(other) {
46             this.qyInput  = Clone(other.qyInput);
47             this.name     = other.name;
48             this.prefix   = other.prefix;
49             this.nsUri    = other.nsUri;
50             this.typeTest = other.typeTest;
51             this.nameTest = other.nameTest;
52             this.position = other.position;
53             this.currentNode = other.currentNode;
54         }
55
56         public override void Reset() {
57             position = 0;
58             currentNode = null; // After this current will not point to context node from Evaluate() call
59                                 // But this is ok, becuase there is no public Reset() on XPathNodeIterator
60             qyInput.Reset();
61         }
62
63         public override void SetXsltContext(XsltContext context) {
64             Debug.Assert(context != null);
65             nsUri = context.LookupNamespace(prefix);
66             qyInput.SetXsltContext(context);
67         }
68
69         protected string        Name      { get { return name;     } }
70         protected string        Prefix    { get { return prefix;   } }
71         protected string        Namespace { get { return nsUri;    } }
72         protected bool          NameTest  { get { return nameTest; } }
73         protected XPathNodeType TypeTest  { get { return typeTest; } }
74
75         public override int CurrentPosition { get { return position; } }
76         public override XPathNavigator Current { get { return currentNode; } }
77
78         public virtual bool matches(XPathNavigator e) {
79             if (
80                 TypeTest == e.NodeType || 
81                 TypeTest == XPathNodeType.All ||
82                 TypeTest == XPathNodeType.Text && (e.NodeType == XPathNodeType.Whitespace || e.NodeType == XPathNodeType.SignificantWhitespace)
83             ) {
84                 if (NameTest) {
85                     if (name.Equals(e.LocalName) || name.Length == 0) {
86                         if (nsUri.Equals(e.NamespaceURI)){
87                             return true;
88                         }
89                     }
90                 } else {
91                     return true;
92                 }
93             }
94             return false;       
95         }
96
97         public override object Evaluate(XPathNodeIterator nodeIterator) {
98             ResetCount();
99             Reset();
100             qyInput.Evaluate(nodeIterator);
101             AssertQuery(qyInput);
102             return this;
103         }
104         
105         public override double XsltDefaultPriority { get {
106             if (qyInput.GetType() != typeof(ContextQuery)) {
107                 return 0.5;   // a/b a[b] id('s')/a
108             }
109             Debug.Assert(this is AttributeQuery || this is ChildrenQuery);
110             if (name.Length != 0) {
111                 return 0; // p:foo, foo, processing-instruction("foo")
112             }
113             if (prefix.Length != 0) {
114                 return -0.25; // p:*
115             }
116             return -0.5; // *, text(), node()
117         } }
118
119         public override XPathResultType StaticType { get { return XPathResultType.NodeSet; } }
120
121         public override void PrintQuery(XmlWriter w) {
122             w.WriteStartElement(this.GetType().Name);
123             if (NameTest) {
124                 w.WriteAttributeString("name", Prefix.Length != 0 ? Prefix + ':' + Name : Name);
125             }
126             if (TypeTest != XPathNodeType.Element) {
127                 w.WriteAttributeString("nodeType", TypeTest.ToString());
128             }
129             qyInput.PrintQuery(w);
130             w.WriteEndElement();
131         }
132     }
133 }