context: //
  // System.Xml.Query.XQueryConvert
  //
  // Author:
  //	Atsushi Enomoto <atsushi@ximian.com>
  //
  // Copyright (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;
  using System.Globalization;
  using System.IO;
  using System.Text;
  using System.Xml;
  using System.Xml.Schema;
  using System.Xml.XPath;
  
  namespace System.Xml
  {
  	internal class XQueryConvert // Won't be public in the final stage
  	{
  		[MonoTODO]
  		public static bool ShouldCheckValueFacets (XmlSchemaType schemaTypeDest)
  		{
  			throw new NotImplementedException ();
  		}
  
  		public static XmlTypeCode GetFallbackType (XmlTypeCode type)
  		{
  			switch (type) {
  			case XmlTypeCode.AnyAtomicType:
  				return XmlTypeCode.Item;
  			case XmlTypeCode.UntypedAtomic:
  				return XmlTypeCode.String;
  			case XmlTypeCode.Notation:
  				return XmlTypeCode.QName;
  			case XmlTypeCode.NormalizedString:
  			case XmlTypeCode.Token:
  			case XmlTypeCode.Language:
  			case XmlTypeCode.NmToken:
  			case XmlTypeCode.Name:
  			case XmlTypeCode.NCName:
  			case XmlTypeCode.Id:
  			case XmlTypeCode.Idref:
  			case XmlTypeCode.Entity:
  				return XmlTypeCode.String;
  			case XmlTypeCode.NonPositiveInteger:
  				return XmlTypeCode.Decimal;
  			case XmlTypeCode.NegativeInteger:
  				return XmlTypeCode.NonPositiveInteger;
  			case XmlTypeCode.Long:
  				return XmlTypeCode.Integer;
  			case XmlTypeCode.Short:
  				return XmlTypeCode.Int;
  			case XmlTypeCode.Byte:
  				return XmlTypeCode.Int;
  			case XmlTypeCode.NonNegativeInteger:
  				return XmlTypeCode.Decimal;
  			case XmlTypeCode.UnsignedLong:
  				return XmlTypeCode.NonNegativeInteger;
  			case XmlTypeCode.UnsignedInt:
  				return XmlTypeCode.Integer;
  			case XmlTypeCode.UnsignedShort:
  				return XmlTypeCode.Int;
  			case XmlTypeCode.UnsignedByte:
  				return XmlTypeCode.UnsignedShort;
  			case XmlTypeCode.PositiveInteger:
  				return XmlTypeCode.NonNegativeInteger;
  			default:
  				return XmlTypeCode.None;
  			}
  		}
  
  		[MonoTODO]
  		// See XQuery & XPath 2.0 functions & operators section 17.
  		public static bool CanConvert (XPathItem item, XmlSchemaType schemaTypeDest)
  		{
  			if (item == null)
  				throw new ArgumentNullException ("item");
  			if (schemaTypeDest == null)
  				throw new ArgumentNullException ("schemaTypeDest");
  			XmlTypeCode src = item.XmlType.TypeCode;
  			XmlTypeCode dst = schemaTypeDest.TypeCode;
  
  			// Notation cannot be converted from other than Notation
  			if (src == XmlTypeCode.Notation && dst != XmlTypeCode.Notation)
  				return false;
  
  			// untypedAtomic and string are convertable unless source type is QName.
  			switch (dst) {
  			case XmlTypeCode.UntypedAtomic:
  			case XmlTypeCode.String:
  				return src != XmlTypeCode.QName;
  			}
  
  			switch (src) {
  			case XmlTypeCode.None:
  			case XmlTypeCode.Item:
  			case XmlTypeCode.Node:
  			case XmlTypeCode.Document:
  			case XmlTypeCode.Element:
  			case XmlTypeCode.Attribute:
  			case XmlTypeCode.Namespace:
  			case XmlTypeCode.ProcessingInstruction:
  			case XmlTypeCode.Comment:
  			case XmlTypeCode.Text:
  				throw new NotImplementedException (); // FIXME: check what happens
  
  			case XmlTypeCode.AnyAtomicType:
  				throw new NotImplementedException (); // FIXME: check what happens
  			case XmlTypeCode.UntypedAtomic:
  			case XmlTypeCode.String:
  				// 'M'
  				throw new NotImplementedException (); // FIXME: check what happens
  
  			case XmlTypeCode.Boolean:
  			case XmlTypeCode.Decimal:
  				switch (dst) {
  				case XmlTypeCode.Float:
  				case XmlTypeCode.Double:
  				case XmlTypeCode.Decimal:
  				case XmlTypeCode.Boolean:
  					return true;
  				}
  				return false;
  
  			case XmlTypeCode.Float:
  			case XmlTypeCode.Double:
  				if (dst == XmlTypeCode.Decimal)
  					// 'M'
  					throw new NotImplementedException (); // FIXME: check what happens
  				goto case XmlTypeCode.Decimal;
  
  			case XmlTypeCode.Duration:
  				switch (dst) {
  				case XmlTypeCode.Duration:
  				case XmlTypeCode.YearMonthDuration:
  				case XmlTypeCode.DayTimeDuration:
  					return true;
  				}
  				return false;
  
  			case XmlTypeCode.DateTime:
  				switch (dst) {
  				case XmlTypeCode.DateTime:
  				case XmlTypeCode.Time:
  				case XmlTypeCode.Date:
  				case XmlTypeCode.GYearMonth:
  				case XmlTypeCode.GYear:
  				case XmlTypeCode.GMonthDay:
  				case XmlTypeCode.GDay:
  				case XmlTypeCode.GMonth:
  					return true;
  				}
  				return false;
  
  			case XmlTypeCode.Time:
  				switch (dst) {
  				case XmlTypeCode.Time:
  				case XmlTypeCode.Date:
  					return true;
  				}
  				return false;
  
  			case XmlTypeCode.Date:
  				if (dst == XmlTypeCode.Time)
  					return false;
  				goto case XmlTypeCode.DateTime;
  
  			case XmlTypeCode.GYearMonth:
  			case XmlTypeCode.GYear:
  			case XmlTypeCode.GMonthDay:
  			case XmlTypeCode.GDay:
  			case XmlTypeCode.GMonth:
  				return src == dst;
  
  			case XmlTypeCode.HexBinary:
  			case XmlTypeCode.Base64Binary:
  				if (src == dst)
  					return true;
  				switch (dst) {
  				case XmlTypeCode.HexBinary:
  				case XmlTypeCode.Base64Binary:
  					return true;
  				}
  				return false;
  
  			case XmlTypeCode.AnyUri:
  			case XmlTypeCode.QName:
  			case XmlTypeCode.Notation:
  				return src == dst;
  
  			case XmlTypeCode.NormalizedString:
  			case XmlTypeCode.Token:
  			case XmlTypeCode.Language:
  			case XmlTypeCode.NmToken:
  			case XmlTypeCode.Name:
  			case XmlTypeCode.NCName:
  			case XmlTypeCode.Id:
  			case XmlTypeCode.Idref:
  			case XmlTypeCode.Entity:
  			case XmlTypeCode.Integer:
  			case XmlTypeCode.NonPositiveInteger:
  			case XmlTypeCode.NegativeInteger:
  			case XmlTypeCode.Long:
  			case XmlTypeCode.Int:
  			case XmlTypeCode.Short:
  			case XmlTypeCode.Byte:
  			case XmlTypeCode.NonNegativeInteger:
  			case XmlTypeCode.UnsignedLong:
  			case XmlTypeCode.UnsignedInt:
  			case XmlTypeCode.UnsignedShort:
  			case XmlTypeCode.UnsignedByte:
  			case XmlTypeCode.PositiveInteger:
  				throw new NotImplementedException ();
  
  			// xdt:*
  			case XmlTypeCode.YearMonthDuration:
  				if (dst == XmlTypeCode.DayTimeDuration)
  					return false;
  				goto case XmlTypeCode.Duration;
  			case XmlTypeCode.DayTimeDuration:
  				if (dst == XmlTypeCode.YearMonthDuration)
  					return false;
  				goto case XmlTypeCode.Duration;
  			}
  
  			throw new NotImplementedException ();
  		}
  
  		// Individual conversion
  
  		public static string AnyUriToString (string value)
  		{
  			return value;
  		}
  
  		public static byte [] Base64BinaryToHexBinary (byte [] value)
  		{
  			return XmlConvert.FromBinHexString (Convert.ToBase64String (value));
  		}
  
  		public static string Base64BinaryToString (byte [] value)
  		{
  			return Convert.ToBase64String (value);
  		}
  
  		public static decimal BooleanToDecimal (bool value)
  		{
  			return Convert.ToDecimal (value);
  		}
  
  		public static double BooleanToDouble (bool value)
  		{
  			return Convert.ToDouble (value);
  		}
  
  		public static float BooleanToFloat (bool value)
  		{
  			return Convert.ToSingle (value);
  		}
  
  		public static int BooleanToInt (bool value)
  		{
  			return Convert.ToInt32 (value);
  		}
  
  		public static long BooleanToInteger (bool value)
  		{
  			return Convert.ToInt64 (value);
  		}
  
  		public static string BooleanToString (bool value)
  		{
  			// It looks not returning "True"
  			return value ? "true" : "false";
  		}
  
  		[MonoTODO]
  		public static DateTime DateTimeToDate (DateTime value)
  		{
  			return value.Date;
  		}
  
  		[MonoTODO]
  		public static DateTime DateTimeToGDay (DateTime value)
  		{
  			return new DateTime (0, 0, value.Day);
  		}
  
  		[MonoTODO]
  		public static DateTime DateTimeToGMonth (DateTime value)
  		{
  			return new DateTime (0, value.Month, 0);
  		}
  
  		[MonoTODO]
  		public static DateTime DateTimeToGYear (DateTime value)
  		{
  			return new DateTime (value.Year, 0, 0);
  		}
  
  		[MonoTODO]
  		public static DateTime DateTimeToGYearMonth (DateTime value)
  		{
  			return new DateTime (value.Year, value.Month, 0);
  		}
  
  		[MonoTODO]
  		public static DateTime DateToDateTime (DateTime value)
  		{
  			return value.Date;
  		}
  
  		[MonoTODO]
  		public static DateTime DateToGDay (DateTime value)
  		{
  			return new DateTime (0, 0, value.Day);
  		}
  
  		[MonoTODO]
  		public static DateTime DateToGMonth (DateTime value)
  		{
  			return new DateTime (0, value.Month, 0);
  		}
  
  		[MonoTODO]
  		public static DateTime DateToGYear (DateTime value)
  		{
  			return new DateTime (value.Year, 0, 0);
  		}
  
  		[MonoTODO]
  		public static DateTime DateToGYearMonth (DateTime value)
  		{
  			return new DateTime (value.Year, value.Month, 0);
  		}
  
  		[MonoTODO]
  		public static string DateToString (DateTime value)
  		{
  			return XmlConvert.ToString (value);
  		}
  
  		[MonoTODO]
  		public static string DateTimeToString (DateTime value)
  		{
  			return XmlConvert.ToString (value);
  		}
  
  		[MonoTODO]
  		public static string DayTimeDurationToDuration (TimeSpan value)
  		{
  			return XmlConvert.ToString (value);
  		}
  
  		[MonoTODO]
  		public static string DayTimeDurationToString (TimeSpan value)
  		{
  			return DayTimeDurationToDuration (value);
  		}
  
  		[MonoTODO]
  		public static bool DecimalToBoolean (decimal value)
  		{
  			return value != 0;
  		}
  
  		[MonoTODO]
  		public static double DecimalToDouble (decimal value)
  		{
  			return (double) value;
  		}
  
  		[MonoTODO]
  		public static float DecimalToFloat (decimal value)
  		{
  			return (float) value;
  		}
  
  		[MonoTODO]
  		public static int DecimalToInt (decimal value)
  		{
  			return (int) value;
  		}
  
  		[MonoTODO]
  		public static long DecimalToInteger (decimal value)
  		{
  			return (long) value;
  		}
  
  		[MonoTODO] // what if value was negative?
  		public static decimal DecimalToNonNegativeInteger (decimal value)
  		{
  			throw new NotImplementedException ();
  		}
  
  		[MonoTODO] // what if value was positive?
  		public static decimal DecimalToNonPositiveInteger (decimal value)
  		{
  			throw new NotImplementedException ();
  		}
  
  		[MonoTODO]
  		public static string DecimalToString (decimal value)
  		{
  			return XmlConvert.ToString (value);
  		}
  
  		[MonoTODO]
  		public static bool DoubleToBoolean (double value)
  		{
  
gt: 			return value != 0;