2 // XQueryComparisonOperator.cs
\r
5 // Atsushi Enomoto <atsushi@ximian.com>
\r
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
\r
10 // Permission is hereby granted, free of charge, to any person obtaining
\r
11 // a copy of this software and associated documentation files (the
\r
12 // "Software"), to deal in the Software without restriction, including
\r
13 // without limitation the rights to use, copy, modify, merge, publish,
\r
14 // distribute, sublicense, and/or sell copies of the Software, and to
\r
15 // permit persons to whom the Software is furnished to do so, subject to
\r
16 // the following conditions:
\r
18 // The above copyright notice and this permission notice shall be
\r
19 // included in all copies or substantial portions of the Software.
\r
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
32 using System.Collections;
\r
33 using System.Reflection;
\r
35 using System.Xml.Schema;
\r
36 using System.Xml.Query;
\r
37 using System.Xml.XPath;
\r
38 using System.Xml.Xsl;
\r
40 namespace Mono.Xml.XPath2
\r
42 // FIXME: Handle complete type promotion and subtype substitution.
\r
43 // See XQuery 1.0 Appendix B.*.
\r
44 public class XQueryComparisonOperator
\r
46 private static bool OpBooleanLessThan (bool b1, bool b2)
\r
51 private static bool OpBooleanGreaterThan (bool b1, bool b2)
\r
56 private static bool CompareEquality (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
58 switch (lvalue.XmlType.TypeCode) {
\r
59 case XmlTypeCode.Boolean:
\r
60 return lvalue.ValueAsBoolean == rvalue.ValueAsBoolean;
\r
61 case XmlTypeCode.String:
\r
62 return lvalue.Value == rvalue.Value;
\r
63 case XmlTypeCode.Date:
\r
64 case XmlTypeCode.Time:
\r
65 case XmlTypeCode.DateTime:
\r
66 case XmlTypeCode.YearMonthDuration:
\r
67 case XmlTypeCode.DayTimeDuration:
\r
68 return lvalue.ValueAsDateTime == rvalue.ValueAsDateTime;
\r
69 case XmlTypeCode.HexBinary:
\r
70 case XmlTypeCode.Base64Binary:
\r
71 case XmlTypeCode.AnyUri:
\r
72 case XmlTypeCode.QName:
\r
73 case XmlTypeCode.Notation:
\r
74 throw new NotImplementedException ();
\r
76 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
79 public static bool ValueEQ (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
81 if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
\r
82 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
\r
83 return lvalue.ValueAsDecimal == rvalue.ValueAsDecimal;
\r
84 if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
\r
85 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
\r
86 return lvalue.ValueAsDouble == rvalue.ValueAsDouble;
\r
87 if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
\r
88 return CompareEquality (lvalue, rvalue);
\r
90 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
93 public static bool ValueNE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
95 if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
\r
96 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
\r
97 return lvalue.ValueAsDecimal != rvalue.ValueAsDecimal;
\r
98 if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
\r
99 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
\r
100 return lvalue.ValueAsDouble != rvalue.ValueAsDouble;
\r
101 if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
\r
102 return !CompareEquality (lvalue, rvalue);
\r
104 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
107 private static bool CompareLT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
109 switch (lvalue.XmlType.TypeCode) {
\r
110 case XmlTypeCode.Boolean:
\r
111 return OpBooleanLessThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);
\r
112 case XmlTypeCode.String:
\r
113 return lvalue.Value == rvalue.Value;
\r
114 case XmlTypeCode.Date:
\r
115 case XmlTypeCode.Time:
\r
116 case XmlTypeCode.DateTime:
\r
117 case XmlTypeCode.YearMonthDuration:
\r
118 case XmlTypeCode.DayTimeDuration:
\r
119 return lvalue.ValueAsDateTime < rvalue.ValueAsDateTime;
\r
121 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
124 public static bool ValueLT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
126 if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
\r
127 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
\r
128 return lvalue.ValueAsDecimal < rvalue.ValueAsDecimal;
\r
129 if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
\r
130 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
\r
131 return lvalue.ValueAsDouble < rvalue.ValueAsDouble;
\r
132 if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
\r
133 return CompareLT (lvalue, rvalue);
\r
135 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
138 private static bool CompareLE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
140 switch (lvalue.XmlType.TypeCode) {
\r
141 case XmlTypeCode.Boolean:
\r
142 return !OpBooleanGreaterThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);
\r
143 case XmlTypeCode.String:
\r
144 return lvalue.Value == rvalue.Value;
\r
145 case XmlTypeCode.Date:
\r
146 case XmlTypeCode.Time:
\r
147 case XmlTypeCode.DateTime:
\r
148 case XmlTypeCode.YearMonthDuration:
\r
149 case XmlTypeCode.DayTimeDuration:
\r
150 return lvalue.ValueAsDateTime <= rvalue.ValueAsDateTime;
\r
152 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
155 public static bool ValueLE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
157 if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
\r
158 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
\r
159 return lvalue.ValueAsDecimal <= rvalue.ValueAsDecimal;
\r
160 if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
\r
161 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
\r
162 return lvalue.ValueAsDouble <= rvalue.ValueAsDouble;
\r
163 if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
\r
164 return CompareLE (lvalue, rvalue);
\r
166 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
169 private static bool CompareGT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
171 switch (lvalue.XmlType.TypeCode) {
\r
172 case XmlTypeCode.Boolean:
\r
173 return OpBooleanGreaterThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);
\r
174 case XmlTypeCode.String:
\r
175 return lvalue.Value == rvalue.Value;
\r
176 case XmlTypeCode.Date:
\r
177 case XmlTypeCode.Time:
\r
178 case XmlTypeCode.DateTime:
\r
179 case XmlTypeCode.YearMonthDuration:
\r
180 case XmlTypeCode.DayTimeDuration:
\r
181 return lvalue.ValueAsDateTime > rvalue.ValueAsDateTime;
\r
183 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
186 public static bool ValueGT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
188 if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
\r
189 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
\r
190 return lvalue.ValueAsDecimal > rvalue.ValueAsDecimal;
\r
191 if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
\r
192 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
\r
193 return lvalue.ValueAsDouble > rvalue.ValueAsDouble;
\r
194 if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
\r
195 return CompareGT (lvalue, rvalue);
\r
197 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
200 private static bool CompareGE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
202 switch (lvalue.XmlType.TypeCode) {
\r
203 case XmlTypeCode.Boolean:
\r
204 return !OpBooleanLessThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);
\r
205 case XmlTypeCode.String:
\r
206 return lvalue.Value == rvalue.Value;
\r
207 case XmlTypeCode.Date:
\r
208 case XmlTypeCode.Time:
\r
209 case XmlTypeCode.DateTime:
\r
210 case XmlTypeCode.YearMonthDuration:
\r
211 case XmlTypeCode.DayTimeDuration:
\r
212 return lvalue.ValueAsDateTime >= rvalue.ValueAsDateTime;
\r
214 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r
217 public static bool ValueGE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)
\r
219 if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&
\r
220 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)
\r
221 return lvalue.ValueAsDecimal >= rvalue.ValueAsDecimal;
\r
222 if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&
\r
223 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))
\r
224 return lvalue.ValueAsDouble >= rvalue.ValueAsDouble;
\r
225 if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)
\r
226 return CompareGE (lvalue, rvalue);
\r
228 throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));
\r