2005-12-27 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / Commons.Xml.Relaxng / Commons.Xml.Relaxng / RelaxngPattern.cs
1 //
2 // Commons.Xml.Relaxng.RelaxngPattern.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
6 //
7 // 2003 Atsushi Enomoto "No rights reserved."
8 //
9 // Copyright (c) 2004 Novell Inc.
10 // All rights reserved
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System;
35 using System.Collections;
36 using System.IO;
37 using System.Xml;
38 using Commons.Xml.Relaxng.Derivative;
39 using Commons.Xml.Relaxng.Rnc;
40
41 #if NET_2_0
42 using NSResolver = System.Xml.IXmlNamespaceResolver;
43 #else
44 using NSResolver = System.Xml.XmlNamespaceManager;
45 #endif
46
47 namespace Commons.Xml.Relaxng
48 {
49         #region Common abstract
50         public abstract class RelaxngElementBase
51         {
52                 bool isCompiled;
53                 int lineNumber, linePosition;
54                 string baseUri;
55
56                 internal bool IsCompiled {
57                         get { return isCompiled; }
58                         set { isCompiled = value; }
59                 }
60
61                 public int LineNumber {
62                         get { return lineNumber; }
63                         set { lineNumber = value; }
64                 }
65
66                 public int LinePosition {
67                         get { return linePosition; }
68                         set { linePosition = value; }
69                 }
70
71                 public string BaseUri {
72                         get { return baseUri; }
73                         set { baseUri = value; }
74                 }
75
76                 public abstract void Write (XmlWriter writer);
77
78                 internal abstract void WriteRnc (RncWriter writer);
79         }
80
81         public abstract class RelaxngSingleContentPattern : RelaxngPattern
82         {
83                 private RelaxngPatternList patterns = new RelaxngPatternList ();
84
85                 public RelaxngPatternList Patterns {
86                         get { return patterns; }
87                 }
88
89                 internal RdpPattern makeSingle (RelaxngGrammar g)
90                 {
91                         // Flatten patterns into RdpGroup. See 4.12.
92                         if (patterns.Count == 0)
93                                 throw new RelaxngException (this, "No pattern contents.");
94                         RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);
95                         if (patterns.Count == 1)
96                                 return p;
97                         for (int i=1; i<patterns.Count; i++) {
98                                 p = new RdpGroup (p,
99                                         ((RelaxngPattern) patterns [i]).Compile (g));
100                         }
101                         return p;
102                 }
103
104                 internal override void CheckConstraints () 
105                 {
106                         foreach (RelaxngPattern p in Patterns)
107                                 p.CheckConstraints ();
108                 }
109         }
110
111         public abstract class RelaxngBinaryContentPattern : RelaxngPattern
112         {
113                 private RelaxngPatternList patterns = new RelaxngPatternList ();
114
115                 public RelaxngPatternList Patterns {
116                         get { return patterns; }
117                 }
118
119                 internal RdpPattern makeBinary (RelaxngGrammar g)
120                 {
121                         // Flatten patterns. See 4.12.
122                         if (patterns.Count == 0)
123                                 throw new RelaxngException (this, "No pattern contents.");
124
125                         RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);
126                         if (patterns.Count == 1)
127                                 return p;
128
129                         for (int i=1; i<patterns.Count; i++) {
130                                 RdpPattern cp =
131                                         ((RelaxngPattern) patterns [i]).Compile (g);
132                                 switch (this.PatternType) {
133                                 case RelaxngPatternType.Choice:
134                                         p = new RdpChoice (p, cp);
135                                         break;
136                                 case RelaxngPatternType.Group:
137                                         p = new RdpGroup (p, cp);
138                                         break;
139                                 case RelaxngPatternType.Interleave:
140                                         p = new RdpInterleave (p, cp);
141                                         break;
142                                 }
143                         }
144
145                         return p;
146                 }
147
148                 internal override void CheckConstraints () 
149                 {
150                         foreach (RelaxngPattern p in Patterns)
151                                 p.CheckConstraints ();
152                 }
153         }
154         #endregion
155
156         #region Grammatical elements
157         public interface IGrammarContent
158         {
159         }
160
161         public class RelaxngStart : RelaxngElementBase, IGrammarContent
162         {
163                 RelaxngPattern p;
164                 string combine;
165
166                 public RelaxngStart ()
167                 {
168                 }
169
170                 public string Combine {
171                         get { return combine; }
172                         set { combine = value; }
173                 }
174
175                 public RelaxngPattern Pattern {
176                         get { return p; }
177                         set { p = value; }
178                 }
179
180                 public override void Write (XmlWriter writer)
181                 {
182                         writer.WriteStartElement ("", "start", RelaxngGrammar.NamespaceURI);
183                         if (combine != null)
184                                 writer.WriteAttributeString ("combine", combine);
185                         p.Write (writer);
186                         writer.WriteEndElement ();
187                 }
188
189                 internal override void WriteRnc (RncWriter writer)
190                 {
191                         writer.WriteStart (this);
192                 }
193
194                 internal RdpPattern Compile (RelaxngGrammar grammar)
195                 {
196                         return p.Compile (grammar);
197                 }
198         }
199
200         public class RelaxngDefine : RelaxngElementBase, IGrammarContent
201         {
202                 string name;
203                 private RelaxngPatternList patterns = new RelaxngPatternList ();
204                 string combine;
205
206                 public RelaxngDefine ()
207                 {
208                 }
209
210                 public RelaxngPatternList Patterns {
211                         get { return patterns; }
212                 }
213
214                 public string Combine {
215                         get { return combine; }
216                         set { combine = value; }
217                 }
218
219                 public string Name {
220                         get { return name; }
221                         set { name = value; }
222                 }
223
224                 public override void Write (XmlWriter writer)
225                 {
226                         writer.WriteStartElement ("", "define", RelaxngGrammar.NamespaceURI);
227                         writer.WriteAttributeString ("name", name);
228                         if (combine != null)
229                                 writer.WriteAttributeString ("combine", combine);
230                         foreach (RelaxngPattern p in Patterns)
231                                 p.Write (writer);
232                         writer.WriteEndElement ();
233                 }
234
235                 internal override void WriteRnc (RncWriter writer)
236                 {
237                         writer.WriteDefine (this);
238                 }
239
240                 internal RdpPattern Compile (RelaxngGrammar grammar)
241                 {
242                         return makeSingle (grammar);
243                 }
244
245                 private RdpPattern makeSingle (RelaxngGrammar g)
246                 {
247                         // Flatten patterns into RdpGroup. See 4.12.
248                         if (patterns.Count == 0)
249                                 throw new RelaxngException (this, "No pattern contents.");
250                         RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);
251                         if (patterns.Count == 1)
252                                 return p;
253                         for (int i=1; i<patterns.Count; i++) {
254                                 p = new RdpGroup (p,
255                                         ((RelaxngPattern) patterns [i]).Compile (g));
256                         }
257                         return p;
258                 }
259         }
260
261         public class RelaxngInclude : RelaxngElementBase, IGrammarContent
262         {
263                 string href;
264                 RelaxngGrammarContentList starts = new RelaxngGrammarContentList ();
265                 RelaxngGrammarContentList defines = new RelaxngGrammarContentList ();
266                 RelaxngGrammarContentList divs = new RelaxngGrammarContentList ();
267                 string ns;
268
269                 public RelaxngInclude ()
270                 {
271                 }
272
273                 public string Href {
274                         get { return href; }
275                         set { href = value; }
276                 }
277
278                 public RelaxngGrammarContentList Starts {
279                         get { return starts; }
280                 }
281
282                 public RelaxngGrammarContentList Defines {
283                         get { return defines; }
284                 }
285
286                 public RelaxngGrammarContentList Divs {
287                         get { return divs; }
288                 }
289
290                 public string NSContext {
291                         get { return ns; }
292                         set { ns = value; }
293                 }
294
295                 public override void Write (XmlWriter writer)
296                 {
297                         writer.WriteStartElement ("", "include", RelaxngGrammar.NamespaceURI);
298                         writer.WriteAttributeString ("href", href);
299                         foreach (RelaxngStart start in Starts)
300                                 start.Write (writer);
301                         foreach (RelaxngDefine define in Defines)
302                                 define.Write (writer);
303                         foreach (RelaxngDiv div in Divs)
304                                 div.Write (writer);
305                         writer.WriteEndElement ();
306                 }
307
308                 internal override void WriteRnc (RncWriter writer)
309                 {
310                         writer.WriteInclude (this);
311                 }
312
313                 // compile into div
314                 internal RelaxngDiv Compile (RelaxngGrammar grammar)
315                 {
316                         grammar.CheckIncludeRecursion (Href);
317                         grammar.IncludedUris.Add (Href, Href);
318                         if (grammar.Resolver == null)
319                                 throw new RelaxngException (this, "To compile 'include' element, XmlResolver is required.");
320                         Uri uri = grammar.Resolver.ResolveUri (BaseUri != String.Empty ? new Uri (BaseUri) : null, Href);
321                         XmlTextReader xtr = null;
322                         RelaxngGrammar g = null;
323                         try {
324                                 xtr = new XmlTextReader (uri.AbsoluteUri, (Stream) grammar.Resolver.GetEntity (uri, null, typeof (Stream)));
325                                 RelaxngReader r = new RelaxngReader (xtr, ns);
326                                 r.MoveToContent ();
327                                 g = r.ReadPattern () as RelaxngGrammar;
328                         } finally {
329                                 xtr.Close ();
330                         }
331                         if (g == null)
332                                 throw new RelaxngException (this, "Included syntax must start with \"grammar\" element.");
333                         g.DataProvider = grammar.Provider;
334
335                         // process recursive inclusions.
336                         foreach (RelaxngInclude inc in g.Includes)
337                                 g.Divs.Add (inc.Compile (grammar));
338
339                         // process this own div children.
340                         // each div subelements are also compiled.
341                         foreach (RelaxngDiv cdiv in divs)
342                                 cdiv.Compile (g);
343                         foreach (RelaxngDiv cdiv in g.Divs)
344                                 cdiv.Compile (g);
345
346                         // replace redifinitions into div.
347                         // starts.
348                         if (this.Starts.Count > 0 && g.Starts.Count == 0)
349                                 throw new RelaxngException (this, "When the included grammar does not contain start components, this include component must not contain start components.");
350                         RelaxngGrammarContentList appliedStarts = (this.starts.Count > 0) ?
351                                 this.starts : g.Starts;
352
353                         RelaxngDiv div = new RelaxngDiv ();
354                         div.BaseUri = this.BaseUri;
355                         div.LinePosition = this.LinePosition;
356                         div.LineNumber = this.LineNumber;
357
358                         foreach (RelaxngStart start in appliedStarts)
359                                 div.Starts.Add (start);
360
361                         // defines.
362                         Hashtable overrides = new Hashtable ();
363                         Hashtable originalDefs = new Hashtable ();
364                         foreach (RelaxngDefine def in defines) {
365                                 overrides.Add (def.Name, def.Name);
366                                 div.Defines.Add (def);
367                         }
368                         foreach (RelaxngDefine def in g.Defines) {
369                                 originalDefs [def.Name] = def.Name;
370                                 if (!overrides.ContainsKey (def.Name)) {
371                                         div.Defines.Add (def);
372                                 }
373                                 // else discard.
374                         }
375
376                         foreach (string name in overrides.Values)
377                                 if (!originalDefs.ContainsKey (name))
378                                         throw new RelaxngException (this, "The include component must not contain define components whose name does not appear in the included grammar component.");
379
380                         grammar.IncludedUris.Remove (Href);
381                         return div;
382                 }
383         }
384
385         public class RelaxngDiv : RelaxngElementBase, IGrammarContent
386         {
387                 RelaxngGrammarContentList starts = new RelaxngGrammarContentList ();
388                 RelaxngGrammarContentList defines = new RelaxngGrammarContentList ();
389                 RelaxngGrammarContentList includes = new RelaxngGrammarContentList ();
390                 RelaxngGrammarContentList divs = new RelaxngGrammarContentList ();
391
392                 public RelaxngDiv ()
393                 {
394                 }
395
396                 public RelaxngGrammarContentList Starts {
397                         get { return starts; }
398                 }
399
400                 public RelaxngGrammarContentList Defines {
401                         get { return defines; }
402                 }
403
404                 public RelaxngGrammarContentList Includes {
405                         get { return includes; }
406                 }
407
408                 public RelaxngGrammarContentList Divs {
409                         get { return divs; }
410                 }
411
412                 public override void Write (XmlWriter writer)
413                 {
414                         writer.WriteStartElement ("", "div", RelaxngGrammar.NamespaceURI);
415                         foreach (RelaxngStart start in Starts)
416                                 start.Write (writer);
417                         foreach (RelaxngDefine define in Defines)
418                                 define.Write (writer);
419                         foreach (RelaxngInclude include in Includes)
420                                 include.Write (writer);
421                         foreach (RelaxngDiv div in Divs)
422                                 div.Write (writer);
423                         writer.WriteEndElement ();
424                 }
425
426                 internal override void WriteRnc (RncWriter writer)
427                 {
428                         writer.WriteDiv (this);
429                 }
430
431                 internal void Compile (RelaxngGrammar grammar)
432                 {
433                         foreach (RelaxngDiv div in divs)
434                                 div.Compile (grammar);
435                         foreach (RelaxngInclude inc in includes)
436                                 inc.Compile (grammar).Compile (grammar); // compile compiled divs
437                         foreach (RelaxngStart start in starts)
438                                 grammar.Starts.Add (start);
439                         foreach (RelaxngDefine define in defines)
440                                 grammar.Defines.Add (define);
441                 }
442         }
443         #endregion
444
445         #region RelaxngPatterns
446         public abstract class RelaxngPattern : RelaxngElementBase
447         {
448                 // static
449
450                 public static RelaxngPattern Read (XmlReader xmlReader)
451                 {
452                         return Read (xmlReader, null);
453                 }
454
455                 public static RelaxngPattern Read (XmlReader xmlReader, RelaxngDatatypeProvider provider)
456                 {
457                         RelaxngReader r = new RelaxngReader (xmlReader, null);
458                         if (r.ReadState == ReadState.Initial)
459                                 r.Read ();
460                         r.MoveToContent ();
461                         RelaxngPattern p = r.ReadPattern ();
462                         p.DataProvider = provider;
463                         return p;
464                 }
465
466                 // Private Fields
467                 RdpPattern startRelaxngPattern;
468                 RelaxngDatatypeProvider provider;
469                 XmlResolver resolver;
470                 bool nullResolver;
471
472                 // Public
473                 public XmlResolver XmlResolver {
474                         set {
475                                 nullResolver = value == null;
476                                 resolver = value;
477                         }
478                 }
479
480                 public abstract RelaxngPatternType PatternType { get; }
481                 public RelaxngDatatypeProvider DataProvider {
482                         get {
483                                 return provider; 
484                         }
485                         set { 
486                                 provider = value; 
487                         }
488                 }
489
490                 public void Compile ()
491                 {
492                         RelaxngGrammar g = null;
493                         if (this is RelaxngGrammar)
494                                 g = (RelaxngGrammar) this;
495                         else {
496                                 g = new RelaxngGrammar ();
497                                 g.XmlResolver = this.Resolver;
498                                 g.BaseUri = this.BaseUri;
499                                 g.LineNumber = this.LineNumber;
500                                 g.LinePosition = this.LinePosition;
501                                 RelaxngStart st = new RelaxngStart ();
502                                 st.BaseUri = this.BaseUri;
503                                 st.LineNumber = this.LineNumber;
504                                 st.LinePosition = this.LinePosition;
505                                 st.Pattern = this;
506                                 g.Starts.Add (st);
507                                 g.Provider = provider;
508                         }
509                         startRelaxngPattern = g.Compile (null);
510                         this.IsCompiled = true;
511                 }
512
513                 public void WriteCompact (TextWriter writer)
514                 {
515                         WriteCompact (new RncWriter (writer));
516                 }
517
518                 public void WriteCompact (TextWriter writer, NSResolver res)
519                 {
520                         WriteCompact (new RncWriter (writer, res));
521                 }
522
523                 void WriteCompact (RncWriter writer)
524                 {
525                         RelaxngGrammar g = this as RelaxngGrammar;
526                         string ns = (g != null ? g.DefaultNamespace : null);
527                         writer.WriteNamespaces (ns);
528                         WriteRnc (writer);
529                 }
530
531                 // Internal
532                 internal XmlResolver Resolver {
533                         get {
534                                 if (nullResolver)
535                                         return null;
536                                 if (resolver == null)
537                                         resolver = new XmlUrlResolver ();
538                                 return resolver;
539                         }
540                 }
541
542                 internal abstract void CheckConstraints ();
543
544                 protected RelaxngPattern () 
545                 {
546                 }
547
548                 internal abstract RdpPattern Compile (RelaxngGrammar grammar);
549
550                 internal RdpPattern StartPattern {
551                         get { return startRelaxngPattern; }
552                 }
553         }
554
555         public class RelaxngPatternList : CollectionBase
556         {
557                 public RelaxngPatternList ()
558                 {
559                 }
560
561                 public void Add (RelaxngPattern p)
562                 {
563                         List.Add (p);
564                 }
565
566                 public RelaxngPattern this [int i] {
567                         get { return this.List [i] as RelaxngPattern; }
568                         set { this.List [i] = value; }
569                 }
570
571                 public void Insert (int pos, RelaxngPattern p)
572                 {
573                         List.Insert (pos, p);
574                 }
575
576                 public void Remove (RelaxngPattern p)
577                 {
578                         List.Remove (p);
579                 }
580         }
581
582         public class RelaxngGrammarContentList : CollectionBase
583         {
584                 public RelaxngGrammarContentList ()
585                 {
586                 }
587
588                 public void Add (IGrammarContent p)
589                 {
590                         List.Add (p);
591                 }
592
593                 public IGrammarContent this [int i] {
594                         get { return this.List [i] as IGrammarContent; }
595                         set { this.List [i] = value; }
596                 }
597
598                 public void Insert (int pos, IGrammarContent p)
599                 {
600                         List.Insert (pos, p);
601                 }
602
603                 public void Remove (IGrammarContent p)
604                 {
605                         List.Remove (p);
606                 }
607         }
608
609         // strict to say, it's not a pattern ;)
610         public class RelaxngNotAllowed : RelaxngPattern
611         {
612                 public RelaxngNotAllowed () 
613                 {
614                 }
615
616                 public override RelaxngPatternType PatternType {
617                         get { return RelaxngPatternType.NotAllowed; }
618                 }
619
620                 public override void Write (XmlWriter writer)
621                 {
622                         writer.WriteStartElement ("", "notAllowed", RelaxngGrammar.NamespaceURI);
623                         writer.WriteEndElement ();
624                 }
625
626                 internal override void WriteRnc (RncWriter writer)
627                 {
628                         writer.WriteNotAllowed (this);
629                 }
630
631                 internal override RdpPattern Compile (RelaxngGrammar grammar)
632                 {
633                         return RdpNotAllowed.Instance;
634                 }
635
636                 internal override void CheckConstraints () 
637                 {
638                         // nothing to check
639                 }
640         }
641
642         public class RelaxngEmpty : RelaxngPattern
643         {
644                 public RelaxngEmpty ()
645                 {
646                 }
647
648                 public override RelaxngPatternType PatternType {
649                         get { return RelaxngPatternType.Empty; }
650                 }
651
652                 public override void Write (XmlWriter writer)
653                 {
654                         writer.WriteStartElement ("", "empty", RelaxngGrammar.NamespaceURI);
655                         writer.WriteEndElement ();
656                 }
657
658                 internal override void WriteRnc (RncWriter writer)
659                 {
660                         writer.WriteEmpty (this);
661                 }
662
663                 internal override RdpPattern Compile (RelaxngGrammar grammar)
664                 {
665                         return RdpEmpty.Instance;
666                 }
667
668                 internal override void CheckConstraints () 
669                 {
670                         // nothing to check
671                 }
672         }
673
674         public class RelaxngText : RelaxngPattern
675         {
676                 public RelaxngText () 
677                 {
678                 }
679
680                 public override RelaxngPatternType PatternType {
681                         get { return RelaxngPatternType.Text; }
682                 }
683
684                 public override void Write (XmlWriter writer)
685                 {
686                         writer.WriteStartElement ("", "text", RelaxngGrammar.NamespaceURI);
687                         writer.WriteEndElement ();
688                 }
689
690                 internal override void WriteRnc (RncWriter writer)
691                 {
692                         writer.WriteText (this);
693                 }
694
695                 internal override RdpPattern Compile (RelaxngGrammar grammar)
696                 {
697                         return RdpText.Instance;
698                 }
699
700                 internal override void CheckConstraints () 
701                 {
702                         // nothing to check
703                 }
704         }
705
706         public abstract class RelaxngDataSupport : RelaxngPattern
707         {
708                 string type;
709                 string datatypeLibrary;
710
711                 public string Type {
712                         get { return type; }
713                         set { type = value; }
714                 }
715
716                 public string DatatypeLibrary {
717                         get { return datatypeLibrary; }
718                         set { datatypeLibrary = value; }
719                 }
720
721                 internal void CheckDatatypeName ()
722                 {
723                         // Data type name check is done in RdpData(Except) derivative creation.
724                 }
725         }
726
727         public class RelaxngData : RelaxngDataSupport
728         {
729                 RelaxngParamList paramList = new RelaxngParamList ();
730                 RelaxngExcept except;
731
732                 public RelaxngData ()
733                 {
734                 }
735
736                 public override RelaxngPatternType PatternType {
737                         get { return RelaxngPatternType.Data; }
738                 }
739
740                 public RelaxngParamList ParamList {
741                         get { return paramList; }
742                 }
743
744                 public RelaxngExcept Except {
745                         get { return except; }
746                         set { except = value; }
747                 }
748
749                 public override void Write (XmlWriter writer)
750                 {
751                         writer.WriteStartElement ("", "data", RelaxngGrammar.NamespaceURI);
752                         if (DatatypeLibrary != null && DatatypeLibrary != String.Empty)
753                                 writer.WriteAttributeString ("datatypeLibrary", DatatypeLibrary);
754                         writer.WriteAttributeString ("type", Type);
755
756                         foreach (RelaxngParam p in ParamList)
757                                 p.Write (writer);
758
759                         if (Except != null)
760                                 Except.Write (writer);
761
762                         writer.WriteEndElement ();
763                 }
764
765                 internal override void WriteRnc (RncWriter writer)
766                 {
767                         writer.WriteData (this);
768                 }
769
770                 internal override RdpPattern Compile (RelaxngGrammar grammar)
771                 {
772 //                      RdpParamList rdpl = new RdpParamList ();
773 //                      foreach (RelaxngParam prm in this.paramList)
774 //                              rdpl.Add (prm.Compile (grammar));
775                         RdpPattern p = null;
776                         if (this.except != null) {
777                                 if (except.Patterns.Count == 0)
778                                         throw new RelaxngException (this, "data except pattern have no children.");
779                                 p = except.Patterns [0].Compile (grammar);
780                                 for (int i=1; i<except.Patterns.Count; i++)
781                                         p = new RdpChoice (p,
782                                                 except.Patterns [i].Compile (grammar));
783                         }
784
785                         IsCompiled = true;
786                         if (this.except != null)
787                                 return new RdpDataExcept (new RdpDatatype (DatatypeLibrary, Type, ParamList, grammar.Provider), p);
788                         else
789                                 return new RdpData (new RdpDatatype (DatatypeLibrary, Type, ParamList, grammar.Provider));
790                 }
791
792                 internal override void CheckConstraints () 
793                 {
794                         CheckDatatypeName ();
795                 }
796         }
797
798         public class RelaxngValue : RelaxngDataSupport
799         {
800                 string value;
801
802                 public override RelaxngPatternType PatternType {
803                         get { return RelaxngPatternType.Value; }
804                 }
805
806                 public string Value {
807                         get { return value; }
808                         set { this.value = value; }
809                 }
810
811                 public override void Write (XmlWriter writer)
812                 {
813                         writer.WriteStartElement ("", "value", RelaxngGrammar.NamespaceURI);
814                         if (Type != null) {
815                                 writer.WriteStartAttribute ("type", String.Empty);
816                                 if (DatatypeLibrary != null && DatatypeLibrary != String.Empty)
817                                         writer.WriteAttributeString ("datatypeLibrary", DatatypeLibrary);
818                                 writer.WriteAttributeString ("type", Type);
819                         }
820                         writer.WriteString (Value);
821                         writer.WriteEndElement ();
822                 }
823
824                 internal override void WriteRnc (RncWriter writer)
825                 {
826                         writer.WriteValue (this);
827                 }
828
829                 internal override RdpPattern Compile (RelaxngGrammar grammar)
830                 {
831                         IsCompiled = true;
832                         return new RdpValue (new RdpDatatype (DatatypeLibrary,
833                                 Type, null, grammar.Provider), value);
834                 }
835
836                 internal override void CheckConstraints () 
837                 {
838                         CheckDatatypeName ();
839                 }
840         }
841
842         public class RelaxngList : RelaxngSingleContentPattern
843         {
844                 internal RelaxngList ()
845                 {
846                 }
847
848                 public override RelaxngPatternType PatternType {
849                         get { return RelaxngPatternType.List; }
850                 }
851
852                 public override void Write (XmlWriter writer)
853                 {
854                         writer.WriteStartElement ("", "list", RelaxngGrammar.NamespaceURI);
855                         foreach (RelaxngPattern p in Patterns)
856                                 p.Write (writer);
857                         writer.WriteEndElement ();
858                 }
859
860                 internal override void WriteRnc (RncWriter writer)
861                 {
862                         writer.WriteList (this);
863                 }
864
865                 internal override RdpPattern Compile (RelaxngGrammar grammar)
866                 {
867
868                         IsCompiled = true;
869                         return new RdpList (makeSingle (grammar));
870                 }
871
872                 internal override void CheckConstraints () 
873                 {
874                         // nothing to check
875                 }
876         }
877
878         public class RelaxngElement : RelaxngSingleContentPattern
879         {
880                 RelaxngNameClass nc;
881
882                 public RelaxngElement ()
883                 {
884                 }
885
886                 public RelaxngNameClass NameClass {
887                         get { return nc; }
888                         set { nc = value; }
889                 }
890
891                 public override RelaxngPatternType PatternType {
892                         get { return RelaxngPatternType.Element; }
893                 }
894
895                 public override void Write (XmlWriter writer)
896                 {
897                         writer.WriteStartElement ("", "element", RelaxngGrammar.NamespaceURI);
898                         nc.Write (writer);
899                         foreach (RelaxngPattern p in Patterns)
900                                 p.Write (writer);
901                         writer.WriteEndElement ();
902                 }
903
904                 internal override void WriteRnc (RncWriter writer)
905                 {
906                         writer.WriteElement (this);
907                 }
908
909                 internal override RdpPattern Compile (RelaxngGrammar grammar)
910                 {
911                         return new RdpElement (
912                                 nc.Compile (grammar), this.makeSingle (grammar));
913                 }
914
915                 internal override void CheckConstraints () 
916                 {
917                         NameClass.CheckConstraints (false, false);
918
919                         foreach (RelaxngPattern p in Patterns)
920                                 p.CheckConstraints ();
921                 }
922         }
923
924         public class RelaxngAttribute : RelaxngPattern
925         {
926                 RelaxngNameClass nc;
927                 RelaxngPattern p;
928
929                 public RelaxngAttribute ()
930                 {
931                 }
932
933                 public RelaxngPattern Pattern {
934                         get { return p; }
935                         set { p = value; }
936                 }
937
938                 public RelaxngNameClass NameClass {
939                         get { return nc; }
940                         set { nc = value; }
941                 }
942
943                 public override RelaxngPatternType PatternType {
944                         get { return RelaxngPatternType.Attribute; }
945                 }
946
947                 public override void Write (XmlWriter writer)
948                 {
949                         writer.WriteStartElement ("", "attribute", RelaxngGrammar.NamespaceURI);
950                         nc.Write (writer);
951                         if (p != null)
952                                 p.Write (writer);
953                         writer.WriteEndElement ();
954                 }
955
956                 internal override void WriteRnc (RncWriter writer)
957                 {
958                         writer.WriteAttribute (this);
959                 }
960
961                 private void checkInvalidAttrNameClass (RdpNameClass nc)
962                 {
963                         string xmlnsNS = "http://www.w3.org/2000/xmlns";
964                         RdpNameClassChoice choice = nc as RdpNameClassChoice;
965                         if (choice != null) {
966                                 checkInvalidAttrNameClass (choice.LValue);
967                                 checkInvalidAttrNameClass (choice.RValue);
968                                 return;
969                         }
970                         RdpAnyNameExcept except = nc as RdpAnyNameExcept;
971                         if (except != null) {
972                                 checkInvalidAttrNameClass (except.ExceptNameClass);
973                                 return;
974                         }
975                         if (nc is RdpAnyName)
976                                 return;
977
978                         RdpName n = nc as RdpName;
979                         if (n != null) {
980                                 if (n.NamespaceURI == xmlnsNS)
981                                         throw new RelaxngException (this, "cannot specify \"" + xmlnsNS + "\" for name of attribute.");
982                                 if (n.LocalName == "xmlns" && n.NamespaceURI == "")
983                                         throw new RelaxngException (this, "cannot specify \"xmlns\" inside empty ns context.");
984                         } else {
985                                 RdpNsName nn = nc as RdpNsName;
986                                 if (nn.NamespaceURI == "http://www.w3.org/2000/xmlns")
987                                         throw new RelaxngException (this, "cannot specify \"" + xmlnsNS + "\" for name of attribute.");
988                                 RdpNsNameExcept x = nc as RdpNsNameExcept;
989                                 if (x != null)
990                                         checkInvalidAttrNameClass (x.ExceptNameClass);
991                         }
992                 }
993
994                 internal override RdpPattern Compile (RelaxngGrammar grammar)
995                 {
996                         IsCompiled = true;
997                         RdpNameClass cnc = nc.Compile (grammar);
998                         this.checkInvalidAttrNameClass (cnc);
999
1000                         return new RdpAttribute (cnc,
1001                                 (p != null) ?
1002                                         p.Compile (grammar) :
1003                                         RdpText.Instance);
1004                 }
1005
1006                 internal override void CheckConstraints () 
1007                 {
1008                         NameClass.CheckConstraints (false, false);
1009
1010                         if (p != null)
1011                                 p.CheckConstraints ();
1012                 }
1013         }
1014
1015         internal class RdpUnresolvedRef : RdpPattern
1016         {
1017                 string name;
1018 //              bool parentRef;
1019                 RelaxngGrammar targetGrammar;
1020                 RdpPattern referencedPattern;
1021
1022                 public RdpUnresolvedRef (string name, RelaxngGrammar g)
1023                 {
1024                         this.name = name;
1025 //                      this.parentRef = parentRef;
1026                         targetGrammar = g;
1027                 }
1028
1029                 public string Name {
1030                         get { return name; }
1031                         set { name = value; }
1032                 }
1033
1034                 public RdpPattern RefPattern {
1035                         get { return referencedPattern; }
1036                         set { referencedPattern = value; }
1037                 }
1038
1039 //              public bool IsParentRef {
1040 //                      get { return parentRef; }
1041 //              }
1042
1043                 public RelaxngGrammar TargetGrammar {
1044                         get { return targetGrammar; }
1045                 }
1046
1047                 public override RelaxngPatternType PatternType {
1048                         get { return RelaxngPatternType.Ref; }
1049                 }
1050
1051                 public override RdpContentType ContentType {
1052                         get { return RdpContentType.Empty; }
1053                 }
1054
1055
1056                 public override bool Nullable {
1057                         get {
1058                                 throw new InvalidOperationException ("Internal error: should not reach.");
1059                         }
1060                 }
1061
1062                 public override void GetLabels (Hashtable elements, Hashtable attributes, bool collectNameClass)
1063                 {
1064                         // Now it could reach (CheckNameOverlap) so comment out here.
1065 //                      throw new InvalidOperationException ("Internal error: should not reach.");
1066                 }
1067
1068                 internal override RdpPattern ExpandRef (Hashtable defs)
1069                 {
1070                         return referencedPattern.ExpandRef (defs);
1071                 }
1072
1073                 internal override void MarkReachableDefs () 
1074                 {
1075                         TargetGrammar.MarkReacheableDefine (this.name);
1076                 }
1077
1078                 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
1079                 {
1080                         referencedPattern =
1081                                 referencedPattern.ReduceEmptyAndNotAllowed (
1082                                 ref result, visited);
1083                         return this;
1084                 }
1085
1086                 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept) 
1087                 {
1088 //                      throw new InvalidOperationException ();
1089                 }
1090
1091                 internal override bool ContainsText ()
1092                 {
1093                         return false;
1094 //                      throw new InvalidOperationException ();
1095                 }
1096         }
1097
1098         public class RelaxngRef : RelaxngPattern
1099         {
1100                 string name;
1101
1102                 public RelaxngRef ()
1103                 {
1104                 }
1105
1106                 public string Name {
1107                         get { return name; }
1108                         set { name = value; }
1109                 }
1110
1111                 public override RelaxngPatternType PatternType {
1112                         get { return RelaxngPatternType.Ref; }
1113                 }
1114
1115                 public override void Write (XmlWriter writer)
1116                 {
1117                         writer.WriteStartElement ("", "ref", RelaxngGrammar.NamespaceURI);
1118                         writer.WriteAttributeString ("name", name);
1119                         writer.WriteEndElement ();
1120                 }
1121
1122                 internal override void WriteRnc (RncWriter writer)
1123                 {
1124                         writer.WriteRef (this);
1125                 }
1126
1127                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1128                 {
1129                         // Important!! This compile method only generates stub.
1130                         IsCompiled = false;
1131                         return new RdpUnresolvedRef (name, grammar);
1132                 }
1133
1134                 internal override void CheckConstraints () 
1135                 {
1136                         // nothing to check
1137                 }
1138         }
1139
1140         public class RelaxngParentRef : RelaxngPattern
1141         {
1142                 string name;
1143
1144                 public RelaxngParentRef ()
1145                 {
1146                 }
1147
1148                 public string Name {
1149                         get { return name; }
1150                         set { name = value; }
1151                 }
1152
1153                 public override RelaxngPatternType PatternType {
1154                         get { return RelaxngPatternType.ParentRef; }
1155                 }
1156
1157                 public override void Write (XmlWriter writer)
1158                 {
1159                         writer.WriteStartElement ("", "parentRef", RelaxngGrammar.NamespaceURI);
1160                         writer.WriteAttributeString ("name", name);
1161                         writer.WriteEndElement ();
1162                 }
1163
1164                 internal override void WriteRnc (RncWriter writer)
1165                 {
1166                         writer.WriteParentRef (this);
1167                 }
1168
1169                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1170                 {
1171                         IsCompiled = false;
1172                         return new RdpUnresolvedRef (name, grammar.ParentGrammar);
1173                 }
1174
1175                 internal override void CheckConstraints () 
1176                 {
1177                         // nothing to check
1178                 }
1179         }
1180
1181         public class RelaxngExternalRef : RelaxngPattern
1182         {
1183                 string href;
1184                 string ns;
1185
1186                 public RelaxngExternalRef ()
1187                 {
1188                 }
1189
1190                 public string Href {
1191                         get { return href; }
1192                         set { href = value; }
1193                 }
1194
1195                 public string NSContext {
1196                         get { return ns; }
1197                         set { ns = value; }
1198                 }
1199
1200                 public override RelaxngPatternType PatternType {
1201                         get { return RelaxngPatternType.ExternalRef; }
1202                 }
1203
1204                 public override void Write (XmlWriter writer)
1205                 {
1206                         writer.WriteStartElement ("", "externalRef", RelaxngGrammar.NamespaceURI);
1207                         writer.WriteAttributeString ("href", Href);
1208                         writer.WriteEndElement ();
1209                 }
1210
1211                 internal override void WriteRnc (RncWriter writer)
1212                 {
1213                         writer.WriteExternalRef (this);
1214                 }
1215
1216                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1217                 {
1218                         grammar.CheckIncludeRecursion (Href);
1219                         grammar.IncludedUris.Add (Href, Href);
1220                         if (grammar.Resolver == null)
1221                                 throw new RelaxngException (this, "To compile 'include' element, XmlResolver is required.");
1222                         Uri uri = grammar.Resolver.ResolveUri (BaseUri != String.Empty ? new Uri (BaseUri) : null, Href);
1223                         XmlTextReader xtr = null;
1224                         try {
1225                                 xtr = new XmlTextReader (uri.AbsoluteUri, (Stream) grammar.Resolver.GetEntity (uri, null, typeof (Stream)));
1226                                 RelaxngReader r = new RelaxngReader (xtr, ns);
1227                                 r.MoveToContent ();
1228                                 RelaxngPattern p = r.ReadPattern ();
1229                                 p.DataProvider = grammar.Provider;
1230
1231                                 RdpPattern ret = p.Compile (grammar);
1232
1233                                 grammar.IncludedUris.Remove (Href);
1234
1235                                 return ret;
1236                         } finally {
1237                                 if (xtr != null)
1238                                         xtr.Close ();
1239                         }
1240
1241                 }
1242
1243                 internal override void CheckConstraints () 
1244                 {
1245                         // nothing to check
1246                 }
1247         }
1248
1249         public class RelaxngOneOrMore : RelaxngSingleContentPattern
1250         {
1251                 public RelaxngOneOrMore ()
1252                 {
1253                 }
1254
1255                 public override RelaxngPatternType PatternType {
1256                         get { return RelaxngPatternType.OneOrMore; }
1257                 }
1258
1259                 public override void Write (XmlWriter writer)
1260                 {
1261                         writer.WriteStartElement ("", "oneOrMore", RelaxngGrammar.NamespaceURI);
1262                         foreach (RelaxngPattern p in Patterns)
1263                                 p.Write (writer);
1264                         writer.WriteEndElement ();
1265                 }
1266
1267                 internal override void WriteRnc (RncWriter writer)
1268                 {
1269                         writer.WriteOneOrMore (this);
1270                 }
1271
1272                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1273                 {
1274                         IsCompiled = true;
1275                         return new RdpOneOrMore (makeSingle (grammar));
1276                 }
1277         }
1278
1279         public class RelaxngZeroOrMore : RelaxngSingleContentPattern
1280         {
1281                 public RelaxngZeroOrMore ()
1282                 {
1283                 }
1284
1285                 public override RelaxngPatternType PatternType {
1286                         get { return RelaxngPatternType.ZeroOrMore; }
1287                 }
1288
1289                 public override void Write (XmlWriter writer)
1290                 {
1291                         writer.WriteStartElement ("", "zeroOrMore", RelaxngGrammar.NamespaceURI);
1292                         foreach (RelaxngPattern p in Patterns)
1293                                 p.Write (writer);
1294                         writer.WriteEndElement ();
1295                 }
1296
1297                 internal override void WriteRnc (RncWriter writer)
1298                 {
1299                         writer.WriteZeroOrMore (this);
1300                 }
1301
1302                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1303                 {
1304                         IsCompiled = true;
1305                         return new RdpChoice (
1306                                 new RdpOneOrMore (makeSingle (grammar)),
1307                                 RdpEmpty.Instance);
1308                 }
1309         }
1310
1311         public class RelaxngOptional : RelaxngSingleContentPattern
1312         {
1313                 public RelaxngOptional ()
1314                 {
1315                 }
1316
1317                 public override RelaxngPatternType PatternType {
1318                         get { return RelaxngPatternType.Optional; }
1319                 }
1320
1321                 public override void Write (XmlWriter writer)
1322                 {
1323                         writer.WriteStartElement ("", "optional", RelaxngGrammar.NamespaceURI);
1324                         foreach (RelaxngPattern p in Patterns)
1325                                 p.Write (writer);
1326                         writer.WriteEndElement ();
1327                 }
1328
1329                 internal override void WriteRnc (RncWriter writer)
1330                 {
1331                         writer.WriteOptional (this);
1332                 }
1333
1334                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1335                 {
1336                         IsCompiled = true;
1337                         return new RdpChoice (
1338                                 makeSingle (grammar), RdpEmpty.Instance);
1339                 }
1340         }
1341
1342         public class RelaxngMixed : RelaxngSingleContentPattern
1343         {
1344                 public RelaxngMixed ()
1345                 {
1346                 }
1347
1348                 public override RelaxngPatternType PatternType {
1349                         get { return RelaxngPatternType.Mixed; }
1350                 }
1351
1352                 public override void Write (XmlWriter writer)
1353                 {
1354                         writer.WriteStartElement ("", "mixed", RelaxngGrammar.NamespaceURI);
1355                         foreach (RelaxngPattern p in Patterns)
1356                                 p.Write (writer);
1357                         writer.WriteEndElement ();
1358                 }
1359
1360                 internal override void WriteRnc (RncWriter writer)
1361                 {
1362                         writer.WriteMixed (this);
1363                 }
1364
1365                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1366                 {
1367                         IsCompiled = true;
1368                         return new RdpInterleave (makeSingle (grammar), RdpText.Instance);
1369                 }
1370         }
1371
1372         public class RelaxngChoice : RelaxngBinaryContentPattern
1373         {
1374                 public RelaxngChoice ()
1375                 {
1376                 }
1377
1378                 public override RelaxngPatternType PatternType {
1379                         get { return RelaxngPatternType.Choice; }
1380                 }
1381
1382                 public override void Write (XmlWriter writer)
1383                 {
1384                         writer.WriteStartElement ("", "choice", RelaxngGrammar.NamespaceURI);
1385                         foreach (RelaxngPattern p in Patterns)
1386                                 p.Write (writer);
1387                         writer.WriteEndElement ();
1388                 }
1389
1390                 internal override void WriteRnc (RncWriter writer)
1391                 {
1392                         writer.WriteChoice (this);
1393                 }
1394
1395                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1396                 {
1397                         IsCompiled = true;
1398                         return makeBinary (grammar);
1399                 }
1400         }
1401
1402         public class RelaxngGroup : RelaxngBinaryContentPattern
1403         {
1404                 public RelaxngGroup ()
1405                 {
1406                 }
1407
1408                 public override RelaxngPatternType PatternType {
1409                         get { return RelaxngPatternType.Group; }
1410                 }
1411
1412                 public override void Write (XmlWriter writer)
1413                 {
1414                         writer.WriteStartElement ("", "group", RelaxngGrammar.NamespaceURI);
1415                         foreach (RelaxngPattern p in Patterns)
1416                                 p.Write (writer);
1417                         writer.WriteEndElement ();
1418                 }
1419
1420                 internal override void WriteRnc (RncWriter writer)
1421                 {
1422                         writer.WriteGroup (this);
1423                 }
1424
1425                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1426                 {
1427                         IsCompiled = true;
1428                         return makeBinary (grammar);
1429                 }
1430         }
1431
1432         public class RelaxngInterleave : RelaxngBinaryContentPattern
1433         {
1434                 public RelaxngInterleave ()
1435                 {
1436                 }
1437
1438                 public override RelaxngPatternType PatternType {
1439                         get { return RelaxngPatternType.Interleave; }
1440                 }
1441
1442                 public override void Write (XmlWriter writer)
1443                 {
1444                         writer.WriteStartElement ("", "interleave", RelaxngGrammar.NamespaceURI);
1445                         foreach (RelaxngPattern p in Patterns)
1446                                 p.Write (writer);
1447                         writer.WriteEndElement ();
1448                 }
1449
1450                 internal override void WriteRnc (RncWriter writer)
1451                 {
1452                         writer.WriteInterleave (this);
1453                 }
1454
1455                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1456                 {
1457                         IsCompiled = true;
1458                         return makeBinary (grammar);
1459                 }
1460         }
1461
1462         public class RelaxngParam : RelaxngElementBase
1463         {
1464                 string name;
1465                 string value;
1466
1467                 public RelaxngParam ()
1468                 {
1469                 }
1470
1471                 public RelaxngParam (string name, string value)
1472                 {
1473                         this.name = name;
1474                         this.value = value;
1475                 }
1476
1477                 public string Name {
1478                         get { return name; }
1479                         set { name = value; }
1480                 }
1481
1482                 public string Value {
1483                         get { return value; }
1484                         set { this.value = value; }
1485                 }
1486
1487                 public override void Write (XmlWriter writer)
1488                 {
1489                         writer.WriteStartElement ("", "param", RelaxngGrammar.NamespaceURI);
1490                         writer.WriteAttributeString ("name", name);
1491                         writer.WriteString (Value);
1492                         writer.WriteEndElement ();
1493                 }
1494
1495                 internal override void WriteRnc (RncWriter writer)
1496                 {
1497                         writer.WriteParam (this);
1498                 }
1499
1500                 internal RdpParam Compile (RelaxngGrammar grammar)
1501                 {
1502                         IsCompiled = true;
1503                         return new RdpParam (name, value);
1504                 }
1505         }
1506
1507         public class RelaxngParamList : CollectionBase
1508         {
1509                 public RelaxngParamList ()
1510                 {
1511                 }
1512
1513                 public void Add (RelaxngParam p)
1514                 {
1515                         List.Add (p);
1516                 }
1517
1518                 public RelaxngParam this [int i] {
1519                         get { return this.List [i] as RelaxngParam; }
1520                         set { this.List [i] = value; }
1521                 }
1522
1523                 public void Insert (int pos, RelaxngParam p)
1524                 {
1525                         List.Insert (pos, p);
1526                 }
1527
1528                 public void Remove (RelaxngParam p)
1529                 {
1530                         List.Remove (p);
1531                 }
1532         }
1533
1534         public class RelaxngExcept : RelaxngElementBase
1535         {
1536                 RelaxngPatternList patterns = new RelaxngPatternList ();
1537
1538                 public RelaxngExcept ()
1539                 {
1540                 }
1541
1542                 public RelaxngPatternList Patterns {
1543                         get { return patterns; }
1544                 }
1545
1546                 public override void Write (XmlWriter writer)
1547                 {
1548                         writer.WriteStartElement ("", "except", RelaxngGrammar.NamespaceURI);
1549                         foreach (RelaxngPattern p in Patterns)
1550                                 p.Write (writer);
1551                         writer.WriteEndElement ();
1552                 }
1553
1554                 internal override void WriteRnc (RncWriter writer)
1555                 {
1556                         writer.WriteDataExcept (this);
1557                 }
1558         }
1559
1560         internal class RelaxngRefPattern
1561         {
1562                 RelaxngPattern patternRef;
1563                 string name;
1564
1565                 // When we found ref, use it.
1566                 public RelaxngRefPattern (string name)
1567                 {
1568                         this.name = name;
1569                 }
1570
1571                 // When we found define, use it.
1572                 public RelaxngRefPattern (RelaxngPattern patternRef)
1573                 {
1574                         this.patternRef = patternRef;
1575                 }
1576
1577                 public string Name {
1578                         get { return name; }
1579                 }
1580
1581                 public RelaxngPattern PatternRef {
1582                         get { return patternRef; }
1583                         set { patternRef = value; }
1584                 }
1585         }
1586         #endregion
1587 }