5 // Atsushi Enomoto <atsushi@ximian.com>
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
35 using System.Xml.XPath;
37 namespace System.Xml.Schema
39 [MonoTODO ("This class is unused and thus won't be finished.")]
40 public sealed class XmlAtomicValue : XPathItem, ICloneable
43 DateTime dateTimeValue;
51 XmlSchemaType schemaType;
52 XmlTypeCode xmlTypeCode;
53 ICollection valueAsList;
57 internal XmlAtomicValue (bool value, XmlSchemaType xmlType)
59 Init (value, xmlType);
62 private void Init (bool value, XmlSchemaType xmlType)
65 throw new ArgumentNullException ("xmlType");
66 xmlTypeCode = XmlTypeCode.Boolean;
67 this.booleanValue = value;
71 internal XmlAtomicValue (DateTime value, XmlSchemaType xmlType)
73 Init (value, xmlType);
76 private void Init (DateTime value, XmlSchemaType xmlType)
79 throw new ArgumentNullException ("xmlType");
80 xmlTypeCode = XmlTypeCode.DateTime;
81 this.dateTimeValue = value;
85 internal XmlAtomicValue (decimal value, XmlSchemaType xmlType)
87 Init (value, xmlType);
90 private void Init (decimal value, XmlSchemaType xmlType)
93 throw new ArgumentNullException ("xmlType");
94 xmlTypeCode = XmlTypeCode.Decimal;
95 this.decimalValue = value;
99 internal XmlAtomicValue (double value, XmlSchemaType xmlType)
101 Init (value, xmlType);
104 private void Init (double value, XmlSchemaType xmlType)
107 throw new ArgumentNullException ("xmlType");
108 xmlTypeCode = XmlTypeCode.Double;
109 this.doubleValue = value;
110 schemaType = xmlType;
113 internal XmlAtomicValue (int value, XmlSchemaType xmlType)
115 Init (value, xmlType);
118 private void Init (int value, XmlSchemaType xmlType)
121 throw new ArgumentNullException ("xmlType");
122 xmlTypeCode = XmlTypeCode.Int;
123 this.intValue = value;
124 schemaType = xmlType;
127 internal XmlAtomicValue (long value, XmlSchemaType xmlType)
129 Init (value, xmlType);
132 private void Init (long value, XmlSchemaType xmlType)
135 throw new ArgumentNullException ("xmlType");
136 xmlTypeCode = XmlTypeCode.Long;
137 this.longValue = value;
138 schemaType = xmlType;
141 internal XmlAtomicValue (float value, XmlSchemaType xmlType)
143 Init (value, xmlType);
146 private void Init (float value, XmlSchemaType xmlType)
149 throw new ArgumentNullException ("xmlType");
150 xmlTypeCode = XmlTypeCode.Float;
151 this.floatValue = value;
152 schemaType = xmlType;
155 internal XmlAtomicValue (string value, XmlSchemaType xmlType)
157 Init (value, xmlType);
160 private void Init (string value, XmlSchemaType xmlType)
163 throw new ArgumentNullException ("value");
165 throw new ArgumentNullException ("xmlType");
166 xmlTypeCode = XmlTypeCode.String;
167 this.stringValue = value;
168 schemaType = xmlType;
171 internal XmlAtomicValue (object value, XmlSchemaType xmlType)
173 Init (value, xmlType);
176 private void Init (object value, XmlSchemaType xmlType)
178 // It accepts any kind of object, but will be rejected on each value properties.
180 throw new ArgumentNullException ("value");
182 throw new ArgumentNullException ("xmlType");
184 switch (Type.GetTypeCode (value.GetType ())) {
186 case TypeCode.UInt16:
188 Init ((int) value, xmlType);
190 case TypeCode.Decimal:
191 Init ((decimal) value, xmlType);
193 case TypeCode.Double:
194 Init ((double) value, xmlType);
196 case TypeCode.Single:
197 Init ((float) value, xmlType);
200 case TypeCode.UInt32:
201 Init ((long) value, xmlType);
203 case TypeCode.String:
204 Init ((string) value, xmlType);
206 case TypeCode.DateTime:
207 Init ((DateTime) value, xmlType);
209 case TypeCode.Boolean:
210 Init ((bool) value, xmlType);
214 ICollection col = value as ICollection;
215 if (col != null && col.Count == 1) {
217 Init (((IList) col) [0], xmlType);
219 IEnumerator en = col.GetEnumerator ();
222 if (en.Current is DictionaryEntry)
223 Init (((DictionaryEntry) en.Current).Value, xmlType);
225 Init (en.Current, xmlType);
230 XmlAtomicValue another = value as XmlAtomicValue;
231 if (another != null) {
232 switch (another.xmlTypeCode) {
233 case XmlTypeCode.Boolean:
234 Init (another.booleanValue, xmlType);
236 case XmlTypeCode.DateTime:
237 Init (another.dateTimeValue, xmlType);
239 case XmlTypeCode.Decimal:
240 Init (another.decimalValue, xmlType);
242 case XmlTypeCode.Double:
243 Init (another.doubleValue, xmlType);
245 case XmlTypeCode.Int:
246 Init (another.intValue, xmlType);
248 case XmlTypeCode.Long:
249 Init (another.longValue, xmlType);
251 case XmlTypeCode.Float:
252 Init (another.floatValue, xmlType);
254 case XmlTypeCode.String:
255 Init (another.stringValue, xmlType);
258 objectValue = another.objectValue;
264 schemaType = xmlType;
271 object ICloneable.Clone ()
273 return this.Clone ();
276 public XmlAtomicValue Clone ()
278 return new XmlAtomicValue (this, schemaType);
281 public override object ValueAs (Type type, IXmlNamespaceResolver nsResolver)
283 switch (XmlTypeCodeFromRuntimeType (type, false)) {
284 case XmlTypeCode.Int:
285 case XmlTypeCode.Short:
286 case XmlTypeCode.UnsignedShort:
288 case XmlTypeCode.Double:
289 case XmlTypeCode.Float:
290 return ValueAsDouble;
291 case XmlTypeCode.Long:
292 case XmlTypeCode.UnsignedInt:
294 case XmlTypeCode.String:
296 case XmlTypeCode.DateTime:
297 return ValueAsDateTime;
298 case XmlTypeCode.Boolean:
299 return ValueAsBoolean;
300 case XmlTypeCode.Item:
302 case XmlTypeCode.QName:
303 return XmlQualifiedName.Parse (Value, nsResolver);
305 throw new NotImplementedException ();
312 // As long as I tried, neither of such XmlAtomicValue created
313 // with XmlText that contains atomic value, XmlElement that
314 // contains such XmlText, XmlDocument nor XPathNavigator
315 // created from such nodes returned false. So it won't be
316 // true on this class. Apparently this class needs more
318 public override bool IsNode {
319 get { return false; }
322 internal XmlTypeCode ResolvedTypeCode {
324 if (schemaType != XmlSchemaComplexType.AnyType)
325 return schemaType.TypeCode;
331 public override object TypedValue {
333 switch (ResolvedTypeCode) {
334 case XmlTypeCode.Boolean:
335 return ValueAsBoolean;
336 case XmlTypeCode.DateTime:
337 return ValueAsDateTime;
338 case XmlTypeCode.Float:
339 case XmlTypeCode.Double:
340 return ValueAsDouble;
341 case XmlTypeCode.Long:
343 case XmlTypeCode.Int:
345 case XmlTypeCode.String:
352 // This method works like ValueAsString.
353 public override string Value {
355 switch (ResolvedTypeCode) {
356 case XmlTypeCode.Boolean:
357 stringValue = XQueryConvert.BooleanToString (ValueAsBoolean);
359 case XmlTypeCode.DateTime:
360 stringValue = XQueryConvert.DateTimeToString (ValueAsDateTime);
362 case XmlTypeCode.Float:
363 case XmlTypeCode.Double:
364 stringValue = XQueryConvert.DoubleToString (ValueAsDouble);
366 case XmlTypeCode.Long:
367 stringValue = XQueryConvert.IntegerToString (ValueAsLong);
369 case XmlTypeCode.Int:
370 stringValue = XQueryConvert.IntToString (ValueAsInt);
372 case XmlTypeCode.String:
375 case XmlTypeCode.None:
376 case XmlTypeCode.Item:
377 case XmlTypeCode.AnyAtomicType:
378 switch (XmlTypeCodeFromRuntimeType (objectValue.GetType (), false)) {
379 case XmlTypeCode.String:
380 stringValue = (string) objectValue;
382 case XmlTypeCode.DateTime:
383 stringValue = XQueryConvert.DateTimeToString ((DateTime) objectValue);
385 case XmlTypeCode.Boolean:
386 stringValue = XQueryConvert.BooleanToString ((bool) objectValue);
388 case XmlTypeCode.Float:
389 stringValue = XQueryConvert.FloatToString ((float) objectValue);
391 case XmlTypeCode.Double:
392 stringValue = XQueryConvert.DoubleToString ((double) objectValue);
394 case XmlTypeCode.Decimal:
395 stringValue = XQueryConvert.DecimalToString ((decimal) objectValue);
397 case XmlTypeCode.Long:
398 stringValue = XQueryConvert.IntegerToString ((long) objectValue);
400 case XmlTypeCode.Int:
401 stringValue = XQueryConvert.IntToString ((int) objectValue);
406 if (stringValue != null)
409 if (objectValue != null)
410 throw new InvalidCastException (String.Format ("Conversion from runtime type {0} to {1} is not supported", objectValue.GetType (), XmlTypeCode.String));
412 throw new InvalidCastException (String.Format ("Conversion from schema type {0} (type code {1}) to {2} is not supported", schemaType.QualifiedName, xmlTypeCode, XmlTypeCode.String));
416 public override bool ValueAsBoolean {
418 switch (xmlTypeCode) {
419 case XmlTypeCode.Boolean:
421 case XmlTypeCode.Decimal:
422 return XQueryConvert.DecimalToBoolean (decimalValue);
423 case XmlTypeCode.Double:
424 return XQueryConvert.DoubleToBoolean (doubleValue);
425 case XmlTypeCode.Long:
426 return XQueryConvert.IntegerToBoolean (longValue);
427 case XmlTypeCode.Int:
428 return XQueryConvert.IntToBoolean (intValue);
429 case XmlTypeCode.Float:
430 return XQueryConvert.FloatToBoolean (floatValue);
431 case XmlTypeCode.String:
432 return XQueryConvert.StringToBoolean (stringValue);
434 case XmlTypeCode.None:
435 case XmlTypeCode.Item:
436 case XmlTypeCode.AnyAtomicType:
437 if (objectValue is bool)
438 return (bool) objectValue;
443 throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsBoolean.QualifiedName));
447 public override DateTime ValueAsDateTime {
449 switch (xmlTypeCode) {
450 case XmlTypeCode.DateTime:
451 return dateTimeValue;
452 case XmlTypeCode.String:
453 return XQueryConvert.StringToDateTime (stringValue);
454 case XmlTypeCode.None:
455 case XmlTypeCode.Item:
456 case XmlTypeCode.AnyAtomicType:
457 if (objectValue is DateTime)
458 return (DateTime) objectValue;
463 throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsDateTime.QualifiedName));
467 public override double ValueAsDouble {
469 switch (xmlTypeCode) {
470 case XmlTypeCode.Boolean:
471 return XQueryConvert.BooleanToDouble (booleanValue);
472 case XmlTypeCode.Decimal:
473 return XQueryConvert.DecimalToDouble (decimalValue);
474 case XmlTypeCode.Double:
476 case XmlTypeCode.Long:
477 return XQueryConvert.IntegerToDouble (longValue);
478 case XmlTypeCode.Int:
479 return XQueryConvert.IntToDouble (intValue);
480 case XmlTypeCode.Float:
481 return XQueryConvert.FloatToDouble (floatValue);
482 case XmlTypeCode.String:
483 return XQueryConvert.StringToDouble (stringValue);
484 case XmlTypeCode.None:
485 case XmlTypeCode.Item:
486 case XmlTypeCode.AnyAtomicType:
487 if (objectValue is double)
488 return (double) objectValue;
493 throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsDouble.QualifiedName));
497 public override int ValueAsInt {
499 switch (xmlTypeCode) {
500 case XmlTypeCode.Boolean:
501 return XQueryConvert.BooleanToInt (booleanValue);
502 case XmlTypeCode.Decimal:
503 return XQueryConvert.DecimalToInt (decimalValue);
504 case XmlTypeCode.Double:
505 return XQueryConvert.DoubleToInt (doubleValue);
506 case XmlTypeCode.Long:
507 return XQueryConvert.IntegerToInt (longValue);
508 case XmlTypeCode.Int:
510 case XmlTypeCode.Float:
511 return XQueryConvert.FloatToInt (floatValue);
512 case XmlTypeCode.String:
513 return XQueryConvert.StringToInt (stringValue);
514 case XmlTypeCode.None:
515 case XmlTypeCode.Item:
516 case XmlTypeCode.AnyAtomicType:
517 if (objectValue is int)
518 return (int) objectValue;
523 throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsInt.QualifiedName));
527 public override long ValueAsLong {
529 switch (xmlTypeCode) {
530 case XmlTypeCode.Boolean:
531 return XQueryConvert.BooleanToInteger (booleanValue);
532 case XmlTypeCode.Decimal:
533 return XQueryConvert.DecimalToInteger (decimalValue);
534 case XmlTypeCode.Double:
535 return XQueryConvert.DoubleToInteger (doubleValue);
536 case XmlTypeCode.Long:
538 case XmlTypeCode.Int:
539 return XQueryConvert.IntegerToInt (intValue);
540 case XmlTypeCode.Float:
541 return XQueryConvert.FloatToInteger (floatValue);
542 case XmlTypeCode.String:
543 return XQueryConvert.StringToInteger (stringValue);
544 case XmlTypeCode.None:
545 case XmlTypeCode.Item:
546 case XmlTypeCode.AnyAtomicType:
547 if (objectValue is long)
548 return (long) objectValue;
553 throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsLong.QualifiedName));
557 public override Type ValueType {
558 get { return schemaType.Datatype.ValueType; }
561 public override XmlSchemaType XmlType {
562 get { return schemaType; }
567 #region internal static members
569 internal static Type RuntimeTypeFromXmlTypeCode (XmlTypeCode typeCode)
572 case XmlTypeCode.Int:
574 case XmlTypeCode.Decimal:
575 return typeof (decimal);
576 case XmlTypeCode.Double:
577 return typeof (double);
578 case XmlTypeCode.Float:
579 return typeof (float);
580 case XmlTypeCode.Long:
581 return typeof (long);
582 case XmlTypeCode.Short:
583 return typeof (short);
584 case XmlTypeCode.UnsignedShort:
585 return typeof (ushort);
586 case XmlTypeCode.UnsignedInt:
587 return typeof (uint);
588 case XmlTypeCode.String:
589 return typeof (string);
590 case XmlTypeCode.DateTime:
591 return typeof (DateTime);
592 case XmlTypeCode.Boolean:
593 return typeof (bool);
594 case XmlTypeCode.Item:
595 return typeof (object);
597 throw new NotSupportedException (String.Format ("XQuery internal error: Cannot infer Runtime Type from XmlTypeCode {0}.", typeCode));
600 internal static XmlTypeCode XmlTypeCodeFromRuntimeType (Type cliType, bool raiseError)
602 switch (Type.GetTypeCode (cliType)) {
604 return XmlTypeCode.Int;
605 case TypeCode.Decimal:
606 return XmlTypeCode.Decimal;
607 case TypeCode.Double:
608 return XmlTypeCode.Double;
609 case TypeCode.Single:
610 return XmlTypeCode.Float;
612 return XmlTypeCode.Long;
614 return XmlTypeCode.Short;
615 case TypeCode.UInt16:
616 return XmlTypeCode.UnsignedShort;
617 case TypeCode.UInt32:
618 return XmlTypeCode.UnsignedInt;
619 case TypeCode.String:
620 return XmlTypeCode.String;
621 case TypeCode.DateTime:
622 return XmlTypeCode.DateTime;
623 case TypeCode.Boolean:
624 return XmlTypeCode.Boolean;
625 case TypeCode.Object:
626 return XmlTypeCode.Item;
629 throw new NotSupportedException (String.Format ("XQuery internal error: Cannot infer XmlTypeCode from Runtime Type {0}", cliType));
631 return XmlTypeCode.None;