2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / Commons.Xml.Relaxng / Commons.Xml.Relaxng / RelaxngPattern.cs
index 2736d72cb8fe32de0fb1970a8c38d80b8e4b3eac..99f5892a50d37e5a61ea467030c17a71009cc1cf 100644 (file)
@@ -6,12 +6,43 @@
 //\r
 // 2003 Atsushi Enomoto "No rights reserved."\r
 //\r
+// Copyright (c) 2004 Novell Inc.\r
+// All rights reserved\r
+//\r
+
+//
+// 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.
+//
 \r
 using System;\r
 using System.Collections;\r
 using System.IO;\r
 using System.Xml;\r
 using Commons.Xml.Relaxng.Derivative;\r
+using Commons.Xml.Relaxng.Rnc;\r
+\r
+#if NET_2_0\r
+using NSResolver = System.Xml.IXmlNamespaceResolver;\r
+#else\r
+using NSResolver = System.Xml.XmlNamespaceManager;\r
+#endif\r
 \r
 namespace Commons.Xml.Relaxng\r
 {\r
@@ -42,7 +73,9 @@ namespace Commons.Xml.Relaxng
                        set { baseUri = value; }\r
                }\r
 \r
-               public abstract void Write (XmlWriter write);\r
+               public abstract void Write (XmlWriter writer);\r
+\r
+               internal abstract void WriteRnc (RncWriter writer);\r
        }\r
 \r
        public abstract class RelaxngSingleContentPattern : RelaxngPattern\r
@@ -57,7 +90,7 @@ namespace Commons.Xml.Relaxng
                {\r
                        // Flatten patterns into RdpGroup. See 4.12.\r
                        if (patterns.Count == 0)\r
-                               throw new RelaxngException ("No pattern contents.");\r
+                               throw new RelaxngException (this, "No pattern contents.");\r
                        RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);\r
                        if (patterns.Count == 1)\r
                                return p;\r
@@ -87,7 +120,7 @@ namespace Commons.Xml.Relaxng
                {\r
                        // Flatten patterns. See 4.12.\r
                        if (patterns.Count == 0)\r
-                               throw new RelaxngException ("No pattern contents.");\r
+                               throw new RelaxngException (this, "No pattern contents.");\r
 \r
                        RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);\r
                        if (patterns.Count == 1)\r
@@ -153,6 +186,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteStart (this);\r
+               }\r
+\r
                internal RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return p.Compile (grammar);\r
@@ -194,6 +232,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteDefine (this);\r
+               }\r
+\r
                internal RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return makeSingle (grammar);\r
@@ -203,7 +246,7 @@ namespace Commons.Xml.Relaxng
                {\r
                        // Flatten patterns into RdpGroup. See 4.12.\r
                        if (patterns.Count == 0)\r
-                               throw new RelaxngException ("No pattern contents.");\r
+                               throw new RelaxngException (this, "No pattern contents.");\r
                        RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);\r
                        if (patterns.Count == 1)\r
                                return p;\r
@@ -262,18 +305,23 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteInclude (this);\r
+               }\r
+\r
                // compile into div\r
                internal RelaxngDiv Compile (RelaxngGrammar grammar)\r
                {\r
                        grammar.CheckIncludeRecursion (Href);\r
                        grammar.IncludedUris.Add (Href, Href);\r
-                       string url = Util.ResolveUri (BaseUri, href, grammar.Resolver);\r
                        if (grammar.Resolver == null)\r
-                               throw new RelaxngException ("To compile 'include' element, XmlResolver is required.");\r
+                               throw new RelaxngException (this, "To compile 'include' element, XmlResolver is required.");\r
+                       Uri uri = grammar.Resolver.ResolveUri (BaseUri != String.Empty ? new Uri (BaseUri) : null, Href);\r
                        XmlTextReader xtr = null;\r
                        RelaxngGrammar g = null;\r
                        try {\r
-                               xtr = new XmlTextReader (url, (Stream) grammar.Resolver.GetEntity (grammar.Resolver.ResolveUri (null, url), null, typeof (Stream)));\r
+                               xtr = new XmlTextReader (uri.AbsoluteUri, (Stream) grammar.Resolver.GetEntity (uri, null, typeof (Stream)));\r
                                RelaxngReader r = new RelaxngReader (xtr, ns);\r
                                r.MoveToContent ();\r
                                g = r.ReadPattern () as RelaxngGrammar;\r
@@ -281,7 +329,7 @@ namespace Commons.Xml.Relaxng
                                xtr.Close ();\r
                        }\r
                        if (g == null)\r
-                               throw new RelaxngException ("Included syntax must start with \"grammar\" element.");\r
+                               throw new RelaxngException (this, "Included syntax must start with \"grammar\" element.");\r
                        g.DataProvider = grammar.Provider;\r
 \r
                        // process recursive inclusions.\r
@@ -298,7 +346,7 @@ namespace Commons.Xml.Relaxng
                        // replace redifinitions into div.\r
                        // starts.\r
                        if (this.Starts.Count > 0 && g.Starts.Count == 0)\r
-                               throw new RelaxngException ("When the included grammar does not contain start components, this include component must not contain start components.");\r
+                               throw new RelaxngException (this, "When the included grammar does not contain start components, this include component must not contain start components.");\r
                        RelaxngGrammarContentList appliedStarts = (this.starts.Count > 0) ?\r
                                this.starts : g.Starts;\r
 \r
@@ -318,14 +366,16 @@ namespace Commons.Xml.Relaxng
                                div.Defines.Add (def);\r
                        }\r
                        foreach (RelaxngDefine def in g.Defines) {\r
-                               originalDefs.Add (def.Name, def.Name);\r
-                               if (overrides [def.Name] == null)\r
+                               originalDefs [def.Name] = def.Name;\r
+                               if (!overrides.ContainsKey (def.Name)) {\r
                                        div.Defines.Add (def);\r
+                               }\r
                                // else discard.\r
                        }\r
+\r
                        foreach (string name in overrides.Values)\r
-                               if (!originalDefs.Contains (name))\r
-                                       throw new RelaxngException ("The include component must not contain define components whose name does not appear in the included grammar component.");\r
+                               if (!originalDefs.ContainsKey (name))\r
+                                       throw new RelaxngException (this, "The include component must not contain define components whose name does not appear in the included grammar component.");\r
 \r
                        grammar.IncludedUris.Remove (Href);\r
                        return div;\r
@@ -373,6 +423,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteDiv (this);\r
+               }\r
+\r
                internal void Compile (RelaxngGrammar grammar)\r
                {\r
                        foreach (RelaxngDiv div in divs)\r
@@ -411,11 +466,15 @@ namespace Commons.Xml.Relaxng
                // Private Fields\r
                RdpPattern startRelaxngPattern;\r
                RelaxngDatatypeProvider provider;\r
-               XmlResolver resolver = new XmlUrlResolver ();\r
+               XmlResolver resolver;\r
+               bool nullResolver;\r
 \r
                // Public\r
                public XmlResolver XmlResolver {\r
-                       set { resolver = value; }\r
+                       set {\r
+                               nullResolver = value == null;\r
+                               resolver = value;\r
+                       }\r
                }\r
 \r
                public abstract RelaxngPatternType PatternType { get; }\r
@@ -451,10 +510,25 @@ namespace Commons.Xml.Relaxng
                        this.IsCompiled = true;\r
                }\r
 \r
+               public void WriteCompact (TextWriter writer)\r
+               {\r
+                       WriteRnc (new RncWriter (writer));\r
+               }\r
+\r
+               public void WriteCompact (TextWriter writer, NSResolver res)\r
+               {\r
+                       WriteRnc (new RncWriter (writer, res));\r
+               }\r
 \r
                // Internal\r
                internal XmlResolver Resolver {\r
-                       get { return resolver; }\r
+                       get {\r
+                               if (nullResolver)\r
+                                       return null;\r
+                               if (resolver == null)\r
+                                       resolver = new XmlUrlResolver ();\r
+                               return resolver;\r
+                       }\r
                }\r
 \r
                internal abstract void CheckConstraints ();\r
@@ -541,6 +615,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteNotAllowed (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return RdpNotAllowed.Instance;\r
@@ -568,6 +647,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteEmpty (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return RdpEmpty.Instance;\r
@@ -595,6 +679,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteText (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return RdpText.Instance;\r
@@ -667,6 +756,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteData (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
 //                     RdpParamList rdpl = new RdpParamList ();\r
@@ -675,7 +769,7 @@ namespace Commons.Xml.Relaxng
                        RdpPattern p = null;\r
                        if (this.except != null) {\r
                                if (except.Patterns.Count == 0)\r
-                                       throw new RelaxngException ("data except pattern have no children.");\r
+                                       throw new RelaxngException (this, "data except pattern have no children.");\r
                                p = except.Patterns [0].Compile (grammar);\r
                                for (int i=1; i<except.Patterns.Count; i++)\r
                                        p = new RdpChoice (p,\r
@@ -722,6 +816,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteValue (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -753,6 +852,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteList (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
 \r
@@ -792,6 +896,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteElement (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return new RdpElement (\r
@@ -839,6 +948,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteAttribute (this);\r
+               }\r
+\r
                private void checkInvalidAttrNameClass (RdpNameClass nc)\r
                {\r
                        string xmlnsNS = "http://www.w3.org/2000/xmlns";\r
@@ -859,13 +973,13 @@ namespace Commons.Xml.Relaxng
                        RdpName n = nc as RdpName;\r
                        if (n != null) {\r
                                if (n.NamespaceURI == xmlnsNS)\r
-                                       throw new RelaxngException ("cannot specify \"" + xmlnsNS + "\" for name of attribute.");\r
+                                       throw new RelaxngException (this, "cannot specify \"" + xmlnsNS + "\" for name of attribute.");\r
                                if (n.LocalName == "xmlns" && n.NamespaceURI == "")\r
-                                       throw new RelaxngException ("cannot specify \"xmlns\" inside empty ns context.");\r
+                                       throw new RelaxngException (this, "cannot specify \"xmlns\" inside empty ns context.");\r
                        } else {\r
                                RdpNsName nn = nc as RdpNsName;\r
                                if (nn.NamespaceURI == "http://www.w3.org/2000/xmlns")\r
-                                       throw new RelaxngException ("cannot specify \"" + xmlnsNS + "\" for name of attribute.");\r
+                                       throw new RelaxngException (this, "cannot specify \"" + xmlnsNS + "\" for name of attribute.");\r
                                RdpNsNameExcept x = nc as RdpNsNameExcept;\r
                                if (x != null)\r
                                        checkInvalidAttrNameClass (x.ExceptNameClass);\r
@@ -930,28 +1044,24 @@ namespace Commons.Xml.Relaxng
                }\r
 \r
                public override RdpContentType ContentType {\r
-#if REPLACE_IN_ADVANCE\r
-                       get { throw new InvalidOperationException (); }\r
-#else\r
                        get { return RdpContentType.Empty; }\r
-#endif\r
                }\r
 \r
 \r
                public override bool Nullable {\r
                        get {\r
-                               throw new InvalidOperationException ();\r
+                               throw new InvalidOperationException ("Internal error: should not reach.");\r
                        }\r
                }\r
 \r
+               public override void GetLabels (Hashtable elements, Hashtable attributes)\r
+               {\r
+                       throw new InvalidOperationException ("Internal error: should not reach.");\r
+               }\r
+\r
                internal override RdpPattern ExpandRef (Hashtable defs)\r
                {\r
-                       RdpPattern target = (RdpPattern) defs [this.name];\r
-                       if (target == null)\r
-                               throw new RelaxngException ("Target definition " + name + " not found.");\r
-                       if (target == this)\r
-                               throw new RelaxngException (String.Format ("Illegal recursion was found. Definition is '{0}'.", name));\r
-                       return target.ExpandRef (defs);\r
+                       return referencedPattern.ExpandRef (defs);\r
                }\r
 \r
                internal override void MarkReachableDefs () \r
@@ -995,6 +1105,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteRef (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        // Important!! This compile method only generates stub.\r
@@ -1032,6 +1147,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteParentRef (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = false;\r
@@ -1074,16 +1194,21 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteExternalRef (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        grammar.CheckIncludeRecursion (Href);\r
                        grammar.IncludedUris.Add (Href, Href);\r
-                       string uri = Util.ResolveUri (this.BaseUri, href, grammar.Resolver);\r
                        if (grammar.Resolver == null)\r
-                               throw new RelaxngException ("To compile 'include' element, XmlResolver is required.");\r
+                               throw new RelaxngException (this, "To compile 'include' element, XmlResolver is required.");\r
+                       Uri uri = grammar.Resolver.ResolveUri (BaseUri != String.Empty ? new Uri (BaseUri) : null, Href);\r
                        XmlTextReader xtr = null;\r
                        try {\r
-                               xtr = new XmlTextReader (uri, (Stream) grammar.Resolver.GetEntity (grammar.Resolver.ResolveUri (null, uri), null, typeof (Stream)));\r
+                               xtr = new XmlTextReader (uri.AbsoluteUri, (Stream) grammar.Resolver.GetEntity (uri, null, typeof (Stream)));\r
                                RelaxngReader r = new RelaxngReader (xtr, ns);\r
                                r.MoveToContent ();\r
                                RelaxngPattern p = r.ReadPattern ();\r
@@ -1125,6 +1250,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteOneOrMore (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1150,6 +1280,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteZeroOrMore (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1177,6 +1312,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteOptional (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1203,6 +1343,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteMixed (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1228,6 +1373,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteChoice (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1253,6 +1403,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteGroup (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1278,6 +1433,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteInterleave (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1318,6 +1478,11 @@ namespace Commons.Xml.Relaxng
                        writer.WriteEndElement ();\r
                }\r
 \r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteParam (this);\r
+               }\r
+\r
                internal RdpParam Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1371,6 +1536,11 @@ namespace Commons.Xml.Relaxng
                                p.Write (writer);\r
                        writer.WriteEndElement ();\r
                }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteDataExcept (this);\r
+               }\r
        }\r
 \r
        internal class RelaxngRefPattern\r