2004-12-01 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.XPath / XPathAtomicValue.cs
index c1dd375c82428acfaf9eb233303bc59d6267058a..f582df37eca90b6edf1774c2b29d475e0c6f16f1 100755 (executable)
@@ -36,83 +36,287 @@ using System.Xml.Schema;
 
 namespace System.Xml.XPath
 {
-       public sealed class XPathAtomicValue
+       public sealed class XPathAtomicValue : 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
 
                [MonoTODO]
                public XPathAtomicValue (bool value, XmlSchemaType xmlType)
                {
-                       throw new NotImplementedException ();
+                       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;
                }
 
                [MonoTODO]
                public XPathAtomicValue (DateTime value, XmlSchemaType xmlType)
                {
-                       throw new NotImplementedException ();
+                       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;
                }
 
                [MonoTODO]
                public XPathAtomicValue (decimal value, XmlSchemaType xmlType)
                {
-                       throw new NotImplementedException ();
+                       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;
                }
 
                [MonoTODO]
                public XPathAtomicValue (double value, XmlSchemaType xmlType)
                {
-                       throw new NotImplementedException ();
+                       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;
                }
 
                [MonoTODO]
                public XPathAtomicValue (int value, XmlSchemaType xmlType)
                {
-                       throw new NotImplementedException ();
+                       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;
                }
 
                [MonoTODO]
                public XPathAtomicValue (long value, XmlSchemaType xmlType)
                {
-                       throw new NotImplementedException ();
+                       Init (value, xmlType);
                }
-
-               [MonoTODO]
-               public XPathAtomicValue (object value, XmlSchemaType xmlType)
+               
+               private void Init (long value, XmlSchemaType xmlType)
                {
-                       throw new NotImplementedException ();
+                       if (xmlType == null)
+                               throw new ArgumentNullException ("xmlType");
+                       xmlTypeCode = XmlTypeCode.Long;
+                       this.longValue = value;
+                       schemaType = xmlType;
                }
 
                [MonoTODO]
                public XPathAtomicValue (float value, XmlSchemaType xmlType)
                {
-                       throw new NotImplementedException ();
+                       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;
                }
 
                [MonoTODO]
                public XPathAtomicValue (string value, XmlSchemaType xmlType)
                {
-                       throw new NotImplementedException ();
+                       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;
+               }
+
+               [MonoTODO]
+               public XPathAtomicValue (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;
+                       }
+
+                       XPathAtomicValue another = value as XPathAtomicValue;
+                       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
 
-               [MonoTODO]
-               public XPathAtomicValue Clone ()
+               object ICloneable.Clone ()
                {
-                       throw new NotImplementedException ();
+                       return this.Clone ();
                }
 
-               public object ValueAs (Type type)
+               [MonoTODO]
+               public XPathAtomicValue Clone ()
                {
-                       return ValueAs (type, null);
+                       return new XPathAtomicValue (this, schemaType);
                }
 
                [MonoTODO]
-               public object ValueAs (Type type, IXmlNamespaceResolver nsResolver)
+               public override object ValueAs (Type type, IXmlNamespaceResolver nsResolver)
                {
+                       switch (XmlTypeCodeFromRuntimeType (type, false)) {
+                       case XmlTypeCode.Int:
+                       case XmlTypeCode.Short:
+                       case XmlTypeCode.UnsignedShort:
+                               return ValueAsInt32;
+                       case XmlTypeCode.Decimal:
+                               return ValueAsDecimal;
+                       case XmlTypeCode.Double:
+                               return ValueAsDouble;
+                       case XmlTypeCode.Float:
+                               return ValueAsSingle;
+                       case XmlTypeCode.Long:
+                       case XmlTypeCode.UnsignedInt:
+                               return ValueAsInt64;
+                       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);
+                       }
+                       if (type.GetInterface ("System.Collections.ICollection") != null)
+                               return ValueAsList;
                        throw new NotImplementedException ();
                }
 
@@ -120,71 +324,426 @@ namespace System.Xml.XPath
 
                #region Properties
 
-               [MonoTODO]
-               public bool IsNode {
-                       get { throw new NotImplementedException (); }
+               // As long as I tried, neither of such XPathAtomicValue 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;
+                       }
                }
 
                [MonoTODO]
-               public object TypedValue {
-                       get { throw new NotImplementedException (); }
+               public override object TypedValue {
+                       get {
+                               switch (ResolvedTypeCode) {
+                               case XmlTypeCode.Boolean:
+                                       return ValueAsBoolean;
+                               case XmlTypeCode.DateTime:
+                                       return ValueAsDateTime;
+                               case XmlTypeCode.Decimal:
+                                       return ValueAsDecimal;
+                               case XmlTypeCode.Double:
+                                       return ValueAsDouble;
+                               case XmlTypeCode.Long:
+                                       return ValueAsInt64;
+                               case XmlTypeCode.Int:
+                                       return ValueAsInt32;
+                               case XmlTypeCode.Float:
+                                       return ValueAsSingle;
+                               case XmlTypeCode.String:
+                                       return Value;
+                               }
+                               return objectValue;
+                       }
                }
 
                [MonoTODO]
-               public string Value {
-                       get { throw new NotImplementedException (); }
+               // 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.Decimal:
+                                       stringValue = XQueryConvert.DecimalToString (ValueAsDecimal);
+                                       break;
+                               case XmlTypeCode.Double:
+                                       stringValue = XQueryConvert.DoubleToString (ValueAsDouble);
+                                       break;
+                               case XmlTypeCode.Long:
+                                       stringValue = XQueryConvert.IntegerToString (ValueAsInt64);
+                                       break;
+                               case XmlTypeCode.Int:
+                                       stringValue = XQueryConvert.IntToString (ValueAsInt32);
+                                       break;
+                               case XmlTypeCode.Float:
+                                       stringValue = XQueryConvert.FloatToString (ValueAsSingle);
+                                       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));
+                       }
                }
 
                [MonoTODO]
-               public bool ValueAsBoolean {
-                       get { throw new NotImplementedException (); }
+               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));
+                       }
                }
 
                [MonoTODO]
-               public DateTime ValueAsDateTime {
-                       get { throw new NotImplementedException (); }
+               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));
+                       }
                }
 
                [MonoTODO]
-               public decimal ValueAsDecimal {
-                       get { throw new NotImplementedException (); }
+               public override decimal ValueAsDecimal {
+                       get {
+                               switch (xmlTypeCode) {
+                               case XmlTypeCode.Boolean:
+                                       return XQueryConvert.BooleanToDecimal (booleanValue);
+                               case XmlTypeCode.Decimal:
+                                       return decimalValue;
+                               case XmlTypeCode.Double:
+                                       return XQueryConvert.DoubleToDecimal (doubleValue);
+                               case XmlTypeCode.Long:
+                                       return XQueryConvert.IntegerToDecimal (longValue);
+                               case XmlTypeCode.Int:
+                                       return XQueryConvert.IntToDecimal (intValue);
+                               case XmlTypeCode.Float:
+                                       return XQueryConvert.FloatToDecimal (floatValue);
+                               case XmlTypeCode.String:
+                                       return XQueryConvert.StringToDecimal (stringValue);
+                               case XmlTypeCode.None:
+                               case XmlTypeCode.Item:
+                               case XmlTypeCode.AnyAtomicType:
+                                       if (objectValue is decimal)
+                                               return (decimal) objectValue;
+                                       break;
+
+                               }
+
+                               throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsDecimal.QualifiedName));
+                       }
                }
 
                [MonoTODO]
-               public double ValueAsDouble {
-                       get { throw new NotImplementedException (); }
+               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));
+                       }
                }
 
                [MonoTODO]
-               public int ValueAsInt32 {
-                       get { throw new NotImplementedException (); }
+               public override int ValueAsInt32 {
+                       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));
+                       }
                }
 
                [MonoTODO]
-               public long ValueAsInt64 {
-                       get { throw new NotImplementedException (); }
+               public override long ValueAsInt64 {
+                       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));
+                       }
                }
 
                [MonoTODO]
-               public ICollection ValueAsList {
-                       get { throw new NotImplementedException (); }
+               public override float ValueAsSingle {
+                       get {
+                               switch (xmlTypeCode) {
+                               case XmlTypeCode.Boolean:
+                                       return XQueryConvert.BooleanToFloat (booleanValue);
+                               case XmlTypeCode.Decimal:
+                                       return XQueryConvert.DecimalToFloat (decimalValue);
+                               case XmlTypeCode.Double:
+                                       return XQueryConvert.DoubleToFloat (doubleValue);
+                               case XmlTypeCode.Float:
+                                       return floatValue;
+                               case XmlTypeCode.Int:
+                                       return XQueryConvert.FloatToInt (intValue);
+                               case XmlTypeCode.Long:
+                                       return XQueryConvert.IntegerToFloat (longValue);
+                               case XmlTypeCode.String:
+                                       return XQueryConvert.StringToFloat (stringValue);
+                               case XmlTypeCode.None:
+                               case XmlTypeCode.Item:
+                               case XmlTypeCode.AnyAtomicType:
+                                       if (objectValue is float)
+                                               return (float) objectValue;
+                                       break;
+
+                               }
+
+                               throw new InvalidCastException (String.Format ("Conversion from {0} to {1} is not supported", schemaType.QualifiedName, XmlSchemaSimpleType.XsFloat.QualifiedName));
+                       }
                }
 
                [MonoTODO]
-               public float ValueAsSingle {
-                       get { throw new NotImplementedException (); }
+               public override ICollection ValueAsList {
+                       get {
+                               if (valueAsList != null)
+                                       return valueAsList;
+                               if (objectValue is ICollection)
+                                       valueAsList = objectValue as ICollection;
+                               else if (objectValue is Array)
+                                       valueAsList = new ArrayList ((Array) objectValue);
+                               else if (xmlTypeCode != XmlTypeCode.None) {
+                                       ArrayList al = new ArrayList ();
+                                       al.Add (TypedValue);
+                                       valueAsList = al;
+                               }
+                               else
+                                       throw new NotImplementedException ();
+                               return valueAsList;
+                       }
                }
 
                [MonoTODO]
-               public Type ValueType {
-                       get { throw new NotImplementedException (); }
+               public override Type ValueType {
+                       get { return schemaType.Datatype.ValueType; }
                }
 
                [MonoTODO]
-               public XmlSchemaType XmlType {
-                       get { throw new NotImplementedException (); }
+               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
        }
 }