2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaInference.cs
index 15abb419333139c634c5717c0eabb8a8479df3d6..c7defa11ea75a0ef0b17c53cd857f37d5b50b91d 100755 (executable)
@@ -65,15 +65,16 @@ using Choice = System.Xml.Schema.XmlSchemaChoice;
 
 namespace System.Xml.Schema
 {
+       [MonoTODO ("merge primitive types; infer gYearMonth too; in some cases sequence should contain element whose minOccurs=0 (no obvious rules right now); reject some non-supported schema components")]
        public class XmlSchemaInference
        {
                public enum InferenceOption {
+                       Restricted,
                        Relaxed,
-                       Rstricted
                }
 
-               InferenceOption occurrence = InferenceOption.Rstricted;
-               InferenceOption typeInference = InferenceOption.Rstricted;
+               InferenceOption occurrence = InferenceOption.Restricted;
+               InferenceOption typeInference = InferenceOption.Restricted;
 
                public XmlSchemaInference ()
                {
@@ -94,7 +95,8 @@ namespace System.Xml.Schema
                        return InferSchema (xmlReader, new XmlSchemaSet ());
                }
 
-               public XmlSchemaSet InferSchema (XmlReader xmlReader, XmlSchemaSet schemas)
+               public XmlSchemaSet InferSchema (XmlReader xmlReader,
+                       XmlSchemaSet schemas)
                {
                        return XsdInference.Process (xmlReader, schemas,
                                occurrence == InferenceOption.Relaxed,
@@ -104,7 +106,10 @@ namespace System.Xml.Schema
 
        class XsdInference
        {
-               public static XmlSchemaSet Process (XmlReader xmlReader, XmlSchemaSet schemas, bool laxOccurence, bool laxTypeInference)
+               public static XmlSchemaSet Process (XmlReader xmlReader, 
+                       XmlSchemaSet schemas,
+                       bool laxOccurence,
+                       bool laxTypeInference)
                {
                        XsdInference impl = new XsdInference (xmlReader,
                                schemas, laxOccurence, laxTypeInference);
@@ -112,20 +117,65 @@ namespace System.Xml.Schema
                        return impl.schemas;
                }
 
-               public const string NamespaceXml = "http://www.w3.org/XML/1998/namespace";
+               public const string NamespaceXml =
+                       "http://www.w3.org/XML/1998/namespace";
 
-               public const string NamespaceXmlns = "http://www.w3.org/2000/xmlns/";
+               public const string NamespaceXmlns =
+                       "http://www.w3.org/2000/xmlns/";
 
-               public const string XdtNamespace = "http://www.w3.org/2003/11/xpath-datatypes";
+               public const string XdtNamespace =
+                       "http://www.w3.org/2003/11/xpath-datatypes";
 
-               static readonly QName QNameString = new QName ("string",
-                       XmlSchema.Namespace);
+               static readonly QName QNameString = new QName (
+                       "string", XmlSchema.Namespace);
 
-               static readonly QName QNameBoolean = new QName ("boolean",
-                       XmlSchema.Namespace);
+               static readonly QName QNameBoolean = new QName (
+                       "boolean", XmlSchema.Namespace);
 
-               static readonly QName QNameAnyType = new QName ("anyType",
-                       XmlSchema.Namespace);
+               static readonly QName QNameAnyType = new QName (
+                       "anyType", XmlSchema.Namespace);
+
+               static readonly QName QNameByte = new QName (
+                       "byte", XmlSchema.Namespace);
+
+               static readonly QName QNameUByte = new QName (
+                       "unsignedByte", XmlSchema.Namespace);
+
+               static readonly QName QNameShort = new QName (
+                       "short", XmlSchema.Namespace);
+
+               static readonly QName QNameUShort = new QName (
+                       "unsignedShort", XmlSchema.Namespace);
+
+               static readonly QName QNameInt = new QName (
+                       "int", XmlSchema.Namespace);
+
+               static readonly QName QNameUInt = new QName (
+                       "unsignedInt", XmlSchema.Namespace);
+
+               static readonly QName QNameLong = new QName (
+                       "long", XmlSchema.Namespace);
+
+               static readonly QName QNameULong = new QName (
+                       "unsignedLong", XmlSchema.Namespace);
+
+               static readonly QName QNameDecimal = new QName (
+                       "decimal", XmlSchema.Namespace);
+
+               static readonly QName QNameUDecimal = new QName (
+                       "unsignedDecimal", XmlSchema.Namespace);
+
+               static readonly QName QNameDouble = new QName (
+                       "double", XmlSchema.Namespace);
+
+               static readonly QName QNameFloat = new QName (
+                       "float", XmlSchema.Namespace);
+
+               static readonly QName QNameDateTime = new QName (
+                       "dateTime", XmlSchema.Namespace);
+
+               static readonly QName QNameDuration = new QName (
+                       "duration", XmlSchema.Namespace);
 
                XmlReader source;
                XmlSchemaSet schemas;
@@ -135,7 +185,10 @@ namespace System.Xml.Schema
                Hashtable newElements = new Hashtable ();
                Hashtable newAttributes = new Hashtable ();
 
-               private XsdInference (XmlReader xmlReader, XmlSchemaSet schemas, bool laxOccurence, bool laxTypeInference)
+               private XsdInference (XmlReader xmlReader, 
+                       XmlSchemaSet schemas, 
+                       bool laxOccurence, 
+                       bool laxTypeInference)
                {
                        this.source = xmlReader;
                        this.schemas = schemas;
@@ -163,13 +216,17 @@ namespace System.Xml.Schema
                        }
                        else
                                InferElement (el, qname.Namespace, false);
+
+                       // finally compile again.
+                       schemas.Compile ();
                }
 
                private void IncludeXmlAttributes ()
                {
                        if (schemas.Schemas (NamespaceXml).Count == 0)
                                // FIXME: do it from resources.
-                               schemas.Add (NamespaceXml, "http://www.w3.org/2001/xml.xsd");
+                               schemas.Add (NamespaceXml, 
+                                       "http://www.w3.org/2001/xml.xsd");
                }
 
                private void InferElement (Element el, string ns, bool isNew)
@@ -330,17 +387,18 @@ namespace System.Xml.Schema
                                typeName);
                        if (st == null) // non-primitive type => see above.
                                return QNameString;
-                       try {
-                               st.Datatype.ParseValue (value,
-                                       source.NameTable,
-                                       source as IXmlNamespaceResolver);
-                               // the string value was value
-                               return typeName;
-                       } catch {
-                               // The types were incompatible.
-                               // FIXME: find the base common type
-                               return QNameString;
-                       }
+                       do {
+                               try {
+                                       st.Datatype.ParseValue (value,
+                                               source.NameTable,
+                                               source as IXmlNamespaceResolver);
+                                       return typeName;
+                               } catch {
+                                       st = st.BaseXmlSchemaType as XmlSchemaSimpleType;
+                                       typeName = st != null ? st.QualifiedName : QName.Empty;
+                               }
+                       } while (typeName != QName.Empty);
+                       return QNameString;
                }
 
                private SOMList GetAttributes (ComplexType ct)
@@ -921,48 +979,49 @@ namespace System.Xml.Schema
                        try {
                                long dec = XmlConvert.ToInt64 (value);
                                if (byte.MinValue <= dec && dec <= byte.MaxValue)
-                                       return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.UnsignedByte).QualifiedName;
+                                       return QNameUByte;
                                if (sbyte.MinValue <= dec && dec <= sbyte.MaxValue)
-                                       return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Byte).QualifiedName;
+                                       return QNameByte;
                                if (ushort.MinValue <= dec && dec <= ushort.MaxValue)
-                                       return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.UnsignedShort).QualifiedName;
+                                       return QNameUShort;
                                if (short.MinValue <= dec && dec <= short.MaxValue)
-                                       return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Short).QualifiedName;
+                                       return QNameShort;
                                if (uint.MinValue <= dec && dec <= uint.MaxValue)
-                                       return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.UnsignedInt).QualifiedName;
+                                       return QNameUInt;
                                if (int.MinValue <= dec && dec <= int.MaxValue)
-                                       return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Int).QualifiedName;
-                               return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Long).QualifiedName;
+                                       return QNameInt;
+                               return QNameLong;
                        } catch (Exception) {
                        }
                        try {
                                XmlConvert.ToUInt64 (value);
-                               return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.UnsignedLong).QualifiedName;
+                               return QNameULong;
                        } catch (Exception) {
                        }
                        try {
                                XmlConvert.ToDecimal (value);
-                               return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Decimal).QualifiedName;
+                               return QNameDecimal;
                        } catch (Exception) {
                        }
                        try {
                                double dbl = XmlConvert.ToDouble (value);
-                               if (float.MinValue <= dbl && dbl <= float.MaxValue)
-                                       return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Float).QualifiedName;
+                               if (float.MinValue <= dbl &&
+                                       dbl <= float.MaxValue)
+                                       return QNameFloat;
                                else
-                                       return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Double).QualifiedName;
+                                       return QNameDouble;
                        } catch (Exception) {
                        }
                        try {
                                // FIXME: also try DateTimeSerializationMode
                                // and gYearMonth
                                XmlConvert.ToDateTime (value);
-                               return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.DateTime).QualifiedName;
+                               return QNameDateTime;
                        } catch (Exception) {
                        }
                        try {
                                XmlConvert.ToTimeSpan (value);
-                               return XmlSchemaType.GetBuiltInSimpleType (XmlTypeCode.Duration).QualifiedName;
+                               return QNameDuration;
                        } catch (Exception) {
                        }