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