// // XmlAtomicValue.cs // // Author: // Atsushi Enomoto // // (C)2004 Novell Inc. // // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #if NET_2_0 using System.Collections; using System.Xml; using System.Xml.XPath; namespace System.Xml.Schema { [MonoTODO ("This class is unused and thus won't be finished.")] public sealed class XmlAtomicValue : XPathItem, ICloneable { bool booleanValue; DateTime dateTimeValue; decimal decimalValue; double doubleValue; int intValue; long longValue; object objectValue; float floatValue; string stringValue; XmlSchemaType schemaType; XmlTypeCode xmlTypeCode; ICollection valueAsList; #region Constructors internal XmlAtomicValue (bool value, XmlSchemaType xmlType) { Init (value, xmlType); } private void Init (bool value, XmlSchemaType xmlType) { if (xmlType == null) throw new ArgumentNullException ("xmlType"); xmlTypeCode = XmlTypeCode.Boolean; this.booleanValue = value; schemaType = xmlType; } internal XmlAtomicValue (DateTime value, XmlSchemaType xmlType) { Init (value, xmlType); } private void Init (DateTime value, XmlSchemaType xmlType) { if (xmlType == null) throw new ArgumentNullException ("xmlType"); xmlTypeCode = XmlTypeCode.DateTime; this.dateTimeValue = value; schemaType = xmlType; } internal XmlAtomicValue (decimal value, XmlSchemaType xmlType) { Init (value, xmlType); } private void Init (decimal value, XmlSchemaType xmlType) { if (xmlType == null) throw new ArgumentNullException ("xmlType"); xmlTypeCode = XmlTypeCode.Decimal; this.decimalValue = value; schemaType = xmlType; } internal XmlAtomicValue (double value, XmlSchemaType xmlType) { Init (value, xmlType); } private void Init (double value, XmlSchemaType xmlType) { if (xmlType == null) throw new ArgumentNullException ("xmlType"); xmlTypeCode = XmlTypeCode.Double; this.doubleValue = value; schemaType = xmlType; } internal XmlAtomicValue (int value, XmlSchemaType xmlType) { Init (value, xmlType); } private void Init (int value, XmlSchemaType xmlType) { if (xmlType == null) throw new ArgumentNullException ("xmlType"); xmlTypeCode = XmlTypeCode.Int; this.intValue = value; schemaType = xmlType; } internal XmlAtomicValue (long value, XmlSchemaType xmlType) { Init (value, xmlType); } private void Init (long value, XmlSchemaType xmlType) { if (xmlType == null) throw new ArgumentNullException ("xmlType"); xmlTypeCode = XmlTypeCode.Long; this.longValue = value; schemaType = xmlType; } internal XmlAtomicValue (float value, XmlSchemaType xmlType) { Init (value, xmlType); } private void Init (float value, XmlSchemaType xmlType) { if (xmlType == null) throw new ArgumentNullException ("xmlType"); xmlTypeCode = XmlTypeCode.Float; this.floatValue = value; schemaType = xmlType; } internal XmlAtomicValue (string value, XmlSchemaType xmlType) { Init (value, xmlType); } private void Init (string value, XmlSchemaType xmlType) { if (value == null) throw new ArgumentNullException ("value"); if (xmlType == null) throw new ArgumentNullException ("xmlType"); xmlTypeCode = XmlTypeCode.String; this.stringValue = value; schemaType = xmlType; } internal XmlAtomicValue (object value, XmlSchemaType xmlType) { Init (value, xmlType); } private void Init (object value, XmlSchemaType xmlType) { // It accepts any kind of object, but will be rejected on each value properties. if (value == null) throw new ArgumentNullException ("value"); if (xmlType == null) throw new ArgumentNullException ("xmlType"); switch (Type.GetTypeCode (value.GetType ())) { case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: Init ((int) value, xmlType); return; case TypeCode.Decimal: Init ((decimal) value, xmlType); return; case TypeCode.Double: Init ((double) value, xmlType); return; case TypeCode.Single: Init ((float) value, xmlType); return; case TypeCode.Int64: case TypeCode.UInt32: Init ((long) value, xmlType); return; case TypeCode.String: Init ((string) value, xmlType); return; case TypeCode.DateTime: Init ((DateTime) value, xmlType); return; case TypeCode.Boolean: Init ((bool) value, xmlType); return; } ICollection col = value as ICollection; if (col != null && col.Count == 1) { if (col is IList) Init (((IList) col) [0], xmlType); else { IEnumerator en = col.GetEnumerator (); if (!en.MoveNext ()) return; if (en.Current is DictionaryEntry) Init (((DictionaryEntry) en.Current).Value, xmlType); else Init (en.Current, xmlType); } return; } XmlAtomicValue another = value as XmlAtomicValue; if (another != null) { switch (another.xmlTypeCode) { case XmlTypeCode.Boolean: Init (another.booleanValue, xmlType); return; case XmlTypeCode.DateTime: Init (another.dateTimeValue, xmlType); return; case XmlTypeCode.Decimal: Init (another.decimalValue, xmlType); return; case XmlTypeCode.Double: Init (another.doubleValue, xmlType); return; case XmlTypeCode.Int: Init (another.intValue, xmlType); return; case XmlTypeCode.Long: Init (another.longValue, xmlType); return; case XmlTypeCode.Float: Init (another.floatValue, xmlType); return; case XmlTypeCode.String: Init (another.stringValue, xmlType); return; default: objectValue = another.objectValue; break; } } objectValue = value; schemaType = xmlType; } #endregion #region Methods object ICloneable.Clone () { return this.Clone (); } public XmlAtomicValue Clone () { return new XmlAtomicValue (this, schemaType); } public override object ValueAs (Type type, IXmlNamespaceResolver nsResolver) { switch (XmlTypeCodeFromRuntimeType (type, false)) { case XmlTypeCode.Int: case XmlTypeCode.Short: case XmlTypeCode.UnsignedShort: return ValueAsInt; case XmlTypeCode.Double: case XmlTypeCode.Float: return ValueAsDouble; case XmlTypeCode.Long: case XmlTypeCode.UnsignedInt: return ValueAsLong; case XmlTypeCode.String: return Value; case XmlTypeCode.DateTime: return ValueAsDateTime; case XmlTypeCode.Boolean: return ValueAsBoolean; case XmlTypeCode.Item: return TypedValue; case XmlTypeCode.QName: return XmlQualifiedName.Parse (Value, nsResolver); } throw new NotImplementedException (); } #endregion #region Properties // As long as I tried, neither of such XmlAtomicValue created // with XmlText that contains atomic value, XmlElement that // contains such XmlText, XmlDocument nor XPathNavigator // created from such nodes returned false. So it won't be // true on this class. Apparently this class needs more // documentation. public override bool IsNode { get { return false; } } internal XmlTypeCode ResolvedTypeCode { get { if (schemaType != XmlSchemaComplexType.AnyType) return schemaType.TypeCode; else return xmlTypeCode; } } public override object TypedValue { get { switch (ResolvedTypeCode) { case XmlTypeCode.Boolean: return ValueAsBoolean; case XmlTypeCode.DateTime: return ValueAsDateTime; case XmlTypeCode.Float: case XmlTypeCode.Double: return ValueAsDouble; case XmlTypeCode.Long: return ValueAsLong; case XmlTypeCode.Int: return ValueAsInt; case XmlTypeCode.String: return Value; } return objectValue; } } // This method works like ValueAsString. public override string Value { get { switch (ResolvedTypeCode) { case XmlTypeCode.Boolean: stringValue = XQueryConvert.BooleanToString (ValueAsBoolean); break; case XmlTypeCode.DateTime: stringValue = XQueryConvert.DateTimeToString (ValueAsDateTime); break; case XmlTypeCode.Float: case XmlTypeCode.Double: stringValue = XQueryConvert.DoubleToString (ValueAsDouble); break; case XmlTypeCode.Long: stringValue = XQueryConvert.IntegerToString (ValueAsLong); break; case XmlTypeCode.Int: stringValue = XQueryConvert.IntToString (ValueAsInt); break; case XmlTypeCode.String: return stringValue; case XmlTypeCode.None: case XmlTypeCode.Item: case XmlTypeCode.AnyAtomicType: switch (XmlTypeCodeFromRuntimeType (objectValue.GetType (), false)) { case XmlTypeCode.String: stringValue = (string) objectValue; break; case XmlTypeCode.DateTime: stringValue = XQueryConvert.DateTimeToString ((DateTime) objectValue); break; case XmlTypeCode.Boolean: stringValue = XQueryConvert.BooleanToString ((bool) objectValue); break; case XmlTypeCode.Float: stringValue = XQueryConvert.FloatToString ((float) objectValue); break; case XmlTypeCode.Double: stringValue = XQueryConvert.DoubleToString ((double) objectValue); break; case XmlTypeCode.Decimal: stringValue = XQueryConvert.DecimalToString ((decimal) objectValue); break; case XmlTypeCode.Long: stringValue = XQueryConvert.IntegerToString ((long) objectValue); break; case XmlTypeCode.Int: stringValue = XQueryConvert.IntToString ((int) objectValue); break; } break; } if (stringValue != null) return stringValue; if (objectValue != null) throw new InvalidCastException (String.Format ("Conversion from runtime type {0} to {1} is not supported", objectValue.GetType (), XmlTypeCode.String)); else throw new InvalidCastException (String.Format ("Conversion from schema type {0} (type code {1}) to {2} is not supported", schemaType.QualifiedName, xmlTypeCode, XmlTypeCode.String)); } } public override bool ValueAsBoolean { get { switch (xmlTypeCode) { case XmlTypeCode.Boolean: return booleanValue; case XmlTypeCode.Decimal: return XQueryConvert.DecimalToBoolean (decimalValue); case XmlTypeCode.Double: return XQueryConvert.DoubleToBoolean (doubleValue); case XmlTypeCode.Long: return XQueryConvert.IntegerToBoolean (longValue); case XmlTypeCode.Int: return XQueryConvert.IntToBoolean (intValue); case XmlTypeCode.Float: return XQueryConvert.FloatToBoolean (floatValue); case XmlTypeCode.String: return XQueryConvert.StringToBoolean (stringValue); case XmlTypeCode.None: case XmlTypeCode.Item: case XmlTypeCode.AnyAtomicType: if (objectValue is bool) return (bool) objectValue; break; } throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsBoolean.QualifiedName)); } } public override DateTime ValueAsDateTime { get { switch (xmlTypeCode) { case XmlTypeCode.DateTime: return dateTimeValue; case XmlTypeCode.String: return XQueryConvert.StringToDateTime (stringValue); case XmlTypeCode.None: case XmlTypeCode.Item: case XmlTypeCode.AnyAtomicType: if (objectValue is DateTime) return (DateTime) objectValue; break; } throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsDateTime.QualifiedName)); } } public override double ValueAsDouble { get { switch (xmlTypeCode) { case XmlTypeCode.Boolean: return XQueryConvert.BooleanToDouble (booleanValue); case XmlTypeCode.Decimal: return XQueryConvert.DecimalToDouble (decimalValue); case XmlTypeCode.Double: return doubleValue; case XmlTypeCode.Long: return XQueryConvert.IntegerToDouble (longValue); case XmlTypeCode.Int: return XQueryConvert.IntToDouble (intValue); case XmlTypeCode.Float: return XQueryConvert.FloatToDouble (floatValue); case XmlTypeCode.String: return XQueryConvert.StringToDouble (stringValue); case XmlTypeCode.None: case XmlTypeCode.Item: case XmlTypeCode.AnyAtomicType: if (objectValue is double) return (double) objectValue; break; } throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsDouble.QualifiedName)); } } public override int ValueAsInt { get { switch (xmlTypeCode) { case XmlTypeCode.Boolean: return XQueryConvert.BooleanToInt (booleanValue); case XmlTypeCode.Decimal: return XQueryConvert.DecimalToInt (decimalValue); case XmlTypeCode.Double: return XQueryConvert.DoubleToInt (doubleValue); case XmlTypeCode.Long: return XQueryConvert.IntegerToInt (longValue); case XmlTypeCode.Int: return intValue; case XmlTypeCode.Float: return XQueryConvert.FloatToInt (floatValue); case XmlTypeCode.String: return XQueryConvert.StringToInt (stringValue); case XmlTypeCode.None: case XmlTypeCode.Item: case XmlTypeCode.AnyAtomicType: if (objectValue is int) return (int) objectValue; break; } throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsInt.QualifiedName)); } } public override long ValueAsLong { get { switch (xmlTypeCode) { case XmlTypeCode.Boolean: return XQueryConvert.BooleanToInteger (booleanValue); case XmlTypeCode.Decimal: return XQueryConvert.DecimalToInteger (decimalValue); case XmlTypeCode.Double: return XQueryConvert.DoubleToInteger (doubleValue); case XmlTypeCode.Long: return longValue; case XmlTypeCode.Int: return XQueryConvert.IntegerToInt (intValue); case XmlTypeCode.Float: return XQueryConvert.FloatToInteger (floatValue); case XmlTypeCode.String: return XQueryConvert.StringToInteger (stringValue); case XmlTypeCode.None: case XmlTypeCode.Item: case XmlTypeCode.AnyAtomicType: if (objectValue is long) return (long) objectValue; break; } throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsLong.QualifiedName)); } } public override Type ValueType { get { return schemaType.Datatype.ValueType; } } public override XmlSchemaType XmlType { get { return schemaType; } } #endregion #region internal static members internal static Type RuntimeTypeFromXmlTypeCode (XmlTypeCode typeCode) { switch (typeCode) { case XmlTypeCode.Int: return typeof (int); case XmlTypeCode.Decimal: return typeof (decimal); case XmlTypeCode.Double: return typeof (double); case XmlTypeCode.Float: return typeof (float); case XmlTypeCode.Long: return typeof (long); case XmlTypeCode.Short: return typeof (short); case XmlTypeCode.UnsignedShort: return typeof (ushort); case XmlTypeCode.UnsignedInt: return typeof (uint); case XmlTypeCode.String: return typeof (string); case XmlTypeCode.DateTime: return typeof (DateTime); case XmlTypeCode.Boolean: return typeof (bool); case XmlTypeCode.Item: return typeof (object); } throw new NotSupportedException (String.Format ("XQuery internal error: Cannot infer Runtime Type from XmlTypeCode {0}.", typeCode)); } internal static XmlTypeCode XmlTypeCodeFromRuntimeType (Type cliType, bool raiseError) { switch (Type.GetTypeCode (cliType)) { case TypeCode.Int32: return XmlTypeCode.Int; case TypeCode.Decimal: return XmlTypeCode.Decimal; case TypeCode.Double: return XmlTypeCode.Double; case TypeCode.Single: return XmlTypeCode.Float; case TypeCode.Int64: return XmlTypeCode.Long; case TypeCode.Int16: return XmlTypeCode.Short; case TypeCode.UInt16: return XmlTypeCode.UnsignedShort; case TypeCode.UInt32: return XmlTypeCode.UnsignedInt; case TypeCode.String: return XmlTypeCode.String; case TypeCode.DateTime: return XmlTypeCode.DateTime; case TypeCode.Boolean: return XmlTypeCode.Boolean; case TypeCode.Object: return XmlTypeCode.Item; } if (raiseError) throw new NotSupportedException (String.Format ("XQuery internal error: Cannot infer XmlTypeCode from Runtime Type {0}", cliType)); else return XmlTypeCode.None; } #endregion } } #endif