Copied remotely
[mono.git] / mcs / class / Mono.Xml.Ext / Mono.Xml.XPath2 / 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.UntypedAtomic:\r
62                         case XmlTypeCode.String:\r
63                                 return lvalue.Value == rvalue.Value;\r
64                         case XmlTypeCode.Date:\r
65                         case XmlTypeCode.Time:\r
66                         case XmlTypeCode.DateTime:\r
67                         case XmlTypeCode.YearMonthDuration:\r
68                         case XmlTypeCode.DayTimeDuration:\r
69                                 return lvalue.ValueAsDateTime == rvalue.ValueAsDateTime;\r
70                         case XmlTypeCode.HexBinary:\r
71                         case XmlTypeCode.Base64Binary:\r
72                         case XmlTypeCode.AnyUri:\r
73                         case XmlTypeCode.QName:\r
74                         case XmlTypeCode.Notation:\r
75                                 throw new NotImplementedException ();\r
76                         }\r
77                         XmlQualifiedName nameL = lvalue.XmlType.QualifiedName != XmlQualifiedName.Empty ? lvalue.XmlType.QualifiedName : new XmlQualifiedName ("anyType", XmlSchema.Namespace);\r
78                         XmlQualifiedName nameR = rvalue.XmlType.QualifiedName != XmlQualifiedName.Empty ? rvalue.XmlType.QualifiedName : new XmlQualifiedName ("anyType", XmlSchema.Namespace);\r
79                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", nameL, nameR));\r
80                 }\r
81 \r
82                 public static bool ValueEQ (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
83                 {\r
84                         if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&\r
85                                 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)\r
86                                 return lvalue.ValueAsDecimal == rvalue.ValueAsDecimal;\r
87                         if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&\r
88                                 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))\r
89                                 return lvalue.ValueAsDouble == rvalue.ValueAsDouble;\r
90                         if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)\r
91                                 return CompareEquality (lvalue, rvalue);\r
92 \r
93                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
94                 }\r
95 \r
96                 public static bool ValueNE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
97                 {\r
98                         if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&\r
99                                 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)\r
100                                 return lvalue.ValueAsDecimal != rvalue.ValueAsDecimal;\r
101                         if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&\r
102                                 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))\r
103                                 return lvalue.ValueAsDouble != rvalue.ValueAsDouble;\r
104                         if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)\r
105                                 return !CompareEquality (lvalue, rvalue);\r
106 \r
107                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
108                 }\r
109 \r
110                 private static bool CompareLT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
111                 {\r
112                         switch (lvalue.XmlType.TypeCode) {\r
113                         case XmlTypeCode.Boolean:\r
114                                 return OpBooleanLessThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);\r
115                         case XmlTypeCode.String:\r
116                                 return lvalue.Value == rvalue.Value;\r
117                         case XmlTypeCode.Date:\r
118                         case XmlTypeCode.Time:\r
119                         case XmlTypeCode.DateTime:\r
120                         case XmlTypeCode.YearMonthDuration:\r
121                         case XmlTypeCode.DayTimeDuration:\r
122                                 return lvalue.ValueAsDateTime < rvalue.ValueAsDateTime;\r
123                         }\r
124                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
125                 }\r
126 \r
127                 public static bool ValueLT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
128                 {\r
129                         if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&\r
130                                 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)\r
131                                 return lvalue.ValueAsDecimal < rvalue.ValueAsDecimal;\r
132                         if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&\r
133                                 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))\r
134                                 return lvalue.ValueAsDouble < rvalue.ValueAsDouble;\r
135                         if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)\r
136                                 return CompareLT (lvalue, rvalue);\r
137 \r
138                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
139                 }\r
140 \r
141                 private static bool CompareLE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
142                 {\r
143                         switch (lvalue.XmlType.TypeCode) {\r
144                         case XmlTypeCode.Boolean:\r
145                                 return !OpBooleanGreaterThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);\r
146                         case XmlTypeCode.String:\r
147                                 return lvalue.Value == rvalue.Value;\r
148                         case XmlTypeCode.Date:\r
149                         case XmlTypeCode.Time:\r
150                         case XmlTypeCode.DateTime:\r
151                         case XmlTypeCode.YearMonthDuration:\r
152                         case XmlTypeCode.DayTimeDuration:\r
153                                 return lvalue.ValueAsDateTime <= rvalue.ValueAsDateTime;\r
154                         }\r
155                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
156                 }\r
157 \r
158                 public static bool ValueLE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
159                 {\r
160                         if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&\r
161                                 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)\r
162                                 return lvalue.ValueAsDecimal <= rvalue.ValueAsDecimal;\r
163                         if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&\r
164                                 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))\r
165                                 return lvalue.ValueAsDouble <= rvalue.ValueAsDouble;\r
166                         if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)\r
167                                 return CompareLE (lvalue, rvalue);\r
168 \r
169                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
170                 }\r
171 \r
172                 private static bool CompareGT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
173                 {\r
174                         switch (lvalue.XmlType.TypeCode) {\r
175                         case XmlTypeCode.Boolean:\r
176                                 return OpBooleanGreaterThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);\r
177                         case XmlTypeCode.String:\r
178                                 return lvalue.Value == rvalue.Value;\r
179                         case XmlTypeCode.Date:\r
180                         case XmlTypeCode.Time:\r
181                         case XmlTypeCode.DateTime:\r
182                         case XmlTypeCode.YearMonthDuration:\r
183                         case XmlTypeCode.DayTimeDuration:\r
184                                 return lvalue.ValueAsDateTime > rvalue.ValueAsDateTime;\r
185                         }\r
186                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
187                 }\r
188 \r
189                 public static bool ValueGT (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
190                 {\r
191                         if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&\r
192                                 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)\r
193                                 return lvalue.ValueAsDecimal > rvalue.ValueAsDecimal;\r
194                         if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&\r
195                                 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))\r
196                                 return lvalue.ValueAsDouble > rvalue.ValueAsDouble;\r
197                         if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)\r
198                                 return CompareGT (lvalue, rvalue);\r
199 \r
200                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
201                 }\r
202 \r
203                 private static bool CompareGE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
204                 {\r
205                         switch (lvalue.XmlType.TypeCode) {\r
206                         case XmlTypeCode.Boolean:\r
207                                 return !OpBooleanLessThan (lvalue.ValueAsBoolean, rvalue.ValueAsBoolean);\r
208                         case XmlTypeCode.String:\r
209                                 return lvalue.Value == rvalue.Value;\r
210                         case XmlTypeCode.Date:\r
211                         case XmlTypeCode.Time:\r
212                         case XmlTypeCode.DateTime:\r
213                         case XmlTypeCode.YearMonthDuration:\r
214                         case XmlTypeCode.DayTimeDuration:\r
215                                 return lvalue.ValueAsDateTime >= rvalue.ValueAsDateTime;\r
216                         }\r
217                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
218                 }\r
219 \r
220                 public static bool ValueGE (XPathAtomicValue lvalue, XPathAtomicValue rvalue)\r
221                 {\r
222                         if (lvalue.XmlType.TypeCode == XmlTypeCode.Decimal &&\r
223                                 rvalue.XmlType.TypeCode == XmlTypeCode.Decimal)\r
224                                 return lvalue.ValueAsDecimal >= rvalue.ValueAsDecimal;\r
225                         if (SequenceType.IsNumeric (lvalue.XmlType.TypeCode) &&\r
226                                 SequenceType.IsNumeric (lvalue.XmlType.TypeCode))\r
227                                 return lvalue.ValueAsDouble >= rvalue.ValueAsDouble;\r
228                         if (lvalue.XmlType.TypeCode == rvalue.XmlType.TypeCode)\r
229                                 return CompareGE (lvalue, rvalue);\r
230 \r
231                         throw new XmlQueryException (String.Format ("Not allowed value comparison between {0} and {1}.", lvalue.XmlType.QualifiedName, rvalue.XmlType.QualifiedName));\r
232                 }\r
233         }\r
234 }\r
235 #endif\r