2004-09-13 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.Query / XQueryComparisonOperator.cs
1 //\r
2 // XQueryComparisonOperator.cs\r
3 //\r
4 // Author:\r
5 //      Atsushi Enomoto <atsushi@ximian.com>\r
6 //\r
7 //\r
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
9 //\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
17 // \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
20 // \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
28 //\r
29 \r
30 #if NET_2_0\r
31 using System;\r
32 using System.Collections;\r
33 using System.Reflection;\r
34 using System.Xml;\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
39 \r
40 namespace Mono.Xml.XPath2\r
41 {\r
42         // FIXME: Handle complete type promotion and subtype substitution.\r
43         // See XQuery 1.0 Appendix B.*.\r
44         public class XQueryComparisonOperator\r
45         {\r
46                 private static bool OpBooleanLessThan (bool b1, bool b2)\r
47                 {\r
48                         return !b1 && b2;\r
49                 }\r
50 \r
51                 private static bool OpBooleanGreaterThan (bool b1, bool b2)\r
52                 {\r
53                         return b1 && !b2;\r
54                 }\r
55 \r
56                 private static bool CompareEquality (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
57                 {\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
75                         }\r
76                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
77                 }\r
78 \r
79                 public static bool ValueEQ (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
80                 {\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
89 \r
90                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
91                 }\r
92 \r
93                 public static bool ValueNE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
94                 {\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
103 \r
104                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
105                 }\r
106 \r
107                 private static bool CompareLT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
108                 {\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
120                         }\r
121                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
122                 }\r
123 \r
124                 public static bool ValueLT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
125                 {\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
134 \r
135                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
136                 }\r
137 \r
138                 private static bool CompareLE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
139                 {\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
151                         }\r
152                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
153                 }\r
154 \r
155                 public static bool ValueLE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
156                 {\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
165 \r
166                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
167                 }\r
168 \r
169                 private static bool CompareGT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
170                 {\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
182                         }\r
183                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
184                 }\r
185 \r
186                 public static bool ValueGT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
187                 {\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
196 \r
197                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
198                 }\r
199 \r
200                 private static bool CompareGE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
201                 {\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
213                         }\r
214                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
215                 }\r
216 \r
217                 public static bool ValueGE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
218                 {\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
227 \r
228                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
229                 }\r
230         }\r
231 }\r
232 #endif\r