System.XML: Partial implementation of XmlSchemaDatatype::ChangeType
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaInference.cs
old mode 100755 (executable)
new mode 100644 (file)
index c7defa1..381ea3a
@@ -40,6 +40,7 @@ using Form = System.Xml.Schema.XmlSchemaForm;
 using Use = System.Xml.Schema.XmlSchemaUse;
 using SOMList = System.Xml.Schema.XmlSchemaObjectCollection;
 using SOMObject = System.Xml.Schema.XmlSchemaObject;
+using Import = System.Xml.Schema.XmlSchemaImport;
 using Element = System.Xml.Schema.XmlSchemaElement;
 using Attr = System.Xml.Schema.XmlSchemaAttribute;
 using AttrGroup = System.Xml.Schema.XmlSchemaAttributeGroup;
@@ -65,8 +66,14 @@ 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
+       [MonoTODO]
+       // FIXME:
+       // - 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 sealed class XmlSchemaInference
        {
                public enum InferenceOption {
                        Restricted,
@@ -86,19 +93,19 @@ namespace System.Xml.Schema
                }
 
                public InferenceOption TypeInference {
-                       get { return TypeInference; }
+                       get { return typeInference; }
                        set { typeInference = value; }
                }
 
-               public XmlSchemaSet InferSchema (XmlReader xmlReader)
+               public XmlSchemaSet InferSchema (XmlReader instanceDocument)
                {
-                       return InferSchema (xmlReader, new XmlSchemaSet ());
+                       return InferSchema (instanceDocument, new XmlSchemaSet ());
                }
 
-               public XmlSchemaSet InferSchema (XmlReader xmlReader,
+               public XmlSchemaSet InferSchema (XmlReader instanceDocument,
                        XmlSchemaSet schemas)
                {
-                       return XsdInference.Process (xmlReader, schemas,
+                       return XsdInference.Process (instanceDocument, schemas,
                                occurrence == InferenceOption.Relaxed,
                                typeInference == InferenceOption.Relaxed);
                }
@@ -108,11 +115,11 @@ namespace System.Xml.Schema
        {
                public static XmlSchemaSet Process (XmlReader xmlReader, 
                        XmlSchemaSet schemas,
-                       bool laxOccurence,
+                       bool laxOccurrence,
                        bool laxTypeInference)
                {
                        XsdInference impl = new XsdInference (xmlReader,
-                               schemas, laxOccurence, laxTypeInference);
+                               schemas, laxOccurrence, laxTypeInference);
                        impl.Run ();
                        return impl.schemas;
                }
@@ -162,9 +169,6 @@ namespace System.Xml.Schema
                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);
 
@@ -179,7 +183,7 @@ namespace System.Xml.Schema
 
                XmlReader source;
                XmlSchemaSet schemas;
-               bool laxOccurence;
+               bool laxOccurrence;
                bool laxTypeInference;
 
                Hashtable newElements = new Hashtable ();
@@ -187,12 +191,12 @@ namespace System.Xml.Schema
 
                private XsdInference (XmlReader xmlReader, 
                        XmlSchemaSet schemas, 
-                       bool laxOccurence, 
+                       bool laxOccurrence, 
                        bool laxTypeInference)
                {
                        this.source = xmlReader;
                        this.schemas = schemas;
-                       this.laxOccurence = laxOccurence;
+                       this.laxOccurrence = laxOccurrence;
                        this.laxTypeInference = laxTypeInference;
                }
 
@@ -203,7 +207,6 @@ namespace System.Xml.Schema
 
                        // move to top-level element
                        source.MoveToContent ();
-                       int depth = source.Depth;
                        if (source.NodeType != XmlNodeType.Element)
                                throw new ArgumentException ("Argument XmlReader content is expected to be an element.");
 
@@ -217,8 +220,27 @@ namespace System.Xml.Schema
                        else
                                InferElement (el, qname.Namespace, false);
 
-                       // finally compile again.
-                       schemas.Compile ();
+                       // FIXME: compile again.
+//                     foreach (XmlSchema schema in schemas.Schemas ())
+//                             schemas.Reprocess (schema);
+               }
+
+               private void AddImport (string current, string import)
+               {
+                       foreach (XmlSchema schema in schemas.Schemas (current)) {
+                               bool exists = false;
+                               foreach (XmlSchemaExternal e in schema.Includes) {
+                                       Import imp = e as Import;
+                                       if (imp != null &&
+                                               imp.Namespace == import)
+                                               exists = true;
+                               }
+                               if (exists)
+                                       continue;
+                               Import newimp = new Import ();
+                               newimp.Namespace = import;
+                               schema.Includes.Add (newimp);
+                       }
                }
 
                private void IncludeXmlAttributes ()
@@ -317,7 +339,7 @@ namespace System.Xml.Schema
                                Attr attr = table [attrName] as Attr;
                                if (attr == null) {
                                        attList.Add (InferNewAttribute (
-                                               attrName, isNew));
+                                               attrName, isNew, ns));
                                } else {
                                        table.Remove (attrName);
                                        if (attr.RefName != null &&
@@ -335,7 +357,7 @@ namespace System.Xml.Schema
                }
 
                private XmlSchemaAttribute InferNewAttribute (
-                       QName attrName, bool isNewTypeDefinition)
+                       QName attrName, bool isNewTypeDefinition, string ns)
                {
                        Attr attr = null;
                        bool mergedRequired = false;
@@ -353,6 +375,7 @@ namespace System.Xml.Schema
                                }
                                attr = new Attr ();
                                attr.RefName = attrName;
+                               AddImport (ns, attrName.Namespace);
                        } else {
                                // local attribute
                                attr = new Attr ();
@@ -360,7 +383,7 @@ namespace System.Xml.Schema
                                attr.SchemaTypeName =
                                        InferSimpleType (source.Value);
                        }
-                       if (!laxOccurence &&
+                       if (!laxOccurrence &&
                                (isNewTypeDefinition || mergedRequired))
                                attr.Use = Use.Required;
                        else
@@ -780,9 +803,11 @@ namespace System.Xml.Schema
                        Element nel = new Element ();
                        if (source.NamespaceURI == ns)
                                nel.Name = source.LocalName;
-                       else
+                       else {
                                nel.RefName = new QName (source.LocalName,
                                        source.NamespaceURI);
+                               AddImport (ns, source.NamespaceURI);
+                       }
                        InferElement (nel, source.NamespaceURI, true);
                        c.Items.Add (nel);
                }
@@ -822,12 +847,17 @@ namespace System.Xml.Schema
                                QName name = new QName (source.LocalName,
                                        source.NamespaceURI);
                                Element nel = CreateElement (name);
+                               if (laxOccurrence)
+                                       nel.MinOccurs = 0;
                                InferElement (nel, ns, true);
                                if (ns == name.Namespace)
                                        s.Items.Add (nel);
                                else {
                                        Element re = new Element ();
+                                       if (laxOccurrence)
+                                               re.MinOccurs = 0;
                                        re.RefName = name;
+                                       AddImport (ns, name.Namespace);
                                        s.Items.Add (re);
                                }
                                consumed = true;
@@ -888,7 +918,7 @@ namespace System.Xml.Schema
                private Choice ToSequenceOfChoice (Sequence s)
                {
                        Choice c = new Choice ();
-                       if (laxOccurence)
+                       if (laxOccurrence)
                                c.MinOccurs = 0;
                        c.MaxOccursString = "unbounded";
                        foreach (Particle p in s.Items)
@@ -927,7 +957,7 @@ namespace System.Xml.Schema
                private Sequence CreateSequence ()
                {
                        Sequence s = new Sequence ();
-                       if (laxOccurence)
+                       if (laxOccurrence)
                                s.MinOccurs = 0;
                        return s;
                }
@@ -969,7 +999,7 @@ namespace System.Xml.Schema
                                return QNameString;
 
                        switch (value) {
-                       // 0 and 1 are not infered as byte unlike MS.XSDInfer
+                       // 0 and 1 are not inferred as byte unlike MS.XSDInfer
 //                     case "0":
 //                     case "1":
                        case "true":