2 // Commons.Xml.Relaxng.Derivative.RdpPatterns.cs
\r
5 // Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
\r
7 // 2003 Atsushi Enomoto "No rights reserved."
\r
9 // Copyright (c) 2004 Novell Inc.
\r
10 // All rights reserved
\r
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:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
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.
35 using System.Collections;
\r
37 using Commons.Xml.Relaxng;
\r
39 using LabelList = System.Collections.Hashtable;
\r
42 namespace Commons.Xml.Relaxng.Derivative
\r
44 public delegate RdpPattern RdpApplyAfterHandler (RdpPattern p);
\r
47 public abstract class RdpPattern
\r
49 internal bool nullableComputed;
\r
50 internal bool isNullable;
\r
51 Hashtable patternPool;
\r
53 internal string debug ()
\r
55 return RdpUtil.DebugRdpPattern (this, new Hashtable ());
\r
58 public abstract RelaxngPatternType PatternType { get; }
\r
60 public abstract RdpContentType ContentType { get; }
\r
62 private Hashtable setupTable (Type type, RdpPattern p)
\r
65 if (patternPool == null) {
\r
66 patternPool = new Hashtable ();
\r
69 Hashtable typePool = (Hashtable) patternPool [type];
\r
70 if (typePool == null) {
\r
71 typePool = new Hashtable ();
\r
72 patternPool [type] = typePool;
\r
74 Hashtable pTable = (Hashtable) typePool [p];
\r
75 if (pTable == null) {
\r
76 pTable = new Hashtable ();
\r
77 typePool [p] = pTable;
\r
82 public RdpChoice MakeChoice (RdpPattern p1, RdpPattern p2)
\r
84 Hashtable p1Table = setupTable (typeof (RdpChoice), p1);
\r
85 if (p1Table [p2] == null) {
\r
86 RdpChoice c = new RdpChoice (p1, p2);
\r
87 c.setInternTable (this.patternPool);
\r
90 return (RdpChoice) p1Table [p2];
\r
93 public RdpPattern MakeGroup (RdpPattern p1, RdpPattern p2)
\r
95 Hashtable p1Table = setupTable (typeof (RdpGroup), p1);
\r
96 if (p1Table [p2] == null) {
\r
97 RdpGroup g = new RdpGroup (p1, p2);
\r
98 g.setInternTable (this.patternPool);
\r
101 return (RdpGroup) p1Table [p2];
\r
104 public RdpInterleave MakeInterleave (RdpPattern p1, RdpPattern p2)
\r
106 Hashtable p1Table = setupTable (typeof (RdpInterleave), p1);
\r
107 if (p1Table [p2] == null) {
\r
108 RdpInterleave i = new RdpInterleave (p1, p2);
\r
109 i.setInternTable (this.patternPool);
\r
112 return (RdpInterleave) p1Table [p2];
\r
115 public RdpAfter MakeAfter (RdpPattern p1, RdpPattern p2)
\r
117 Hashtable p1Table = setupTable (typeof (RdpAfter), p1);
\r
118 if (p1Table [p2] == null) {
\r
119 RdpAfter a = new RdpAfter (p1, p2);
\r
120 a.setInternTable (this.patternPool);
\r
123 return (RdpAfter) p1Table [p2];
\r
126 public RdpOneOrMore MakeOneOrMore (RdpPattern p)
\r
128 Hashtable pTable = (Hashtable) patternPool [RelaxngPatternType.OneOrMore];
\r
129 if (pTable == null) {
\r
130 pTable = new Hashtable ();
\r
131 patternPool [RelaxngPatternType.OneOrMore] = pTable;
\r
133 if (pTable [p] == null)
\r
134 pTable [p] = new RdpOneOrMore (p);
\r
135 return (RdpOneOrMore) pTable [p];
\r
138 internal void setInternTable (Hashtable ht)
\r
140 this.patternPool = ht;
\r
142 Hashtable pt = ht [PatternType] as Hashtable;
\r
144 pt = new Hashtable ();
\r
145 ht [PatternType] = pt;
\r
148 RdpAbstractSingleContent single =
\r
149 this as RdpAbstractSingleContent;
\r
150 if (single != null) {
\r
151 if (pt [single.Child] == null) {
\r
152 pt [single.Child] = this;
\r
153 single.Child.setInternTable (ht);
\r
158 RdpAbstractBinary binary =
\r
159 this as RdpAbstractBinary;
\r
160 if (binary != null) {
\r
161 Hashtable lTable = setupTable (GetType (), binary.LValue);
\r
162 if (lTable [binary.RValue] == null) {
\r
163 lTable [binary.RValue] = this;
\r
164 binary.LValue.setInternTable (ht);
\r
165 binary.RValue.setInternTable (ht);
\r
170 // For rest patterns, only check recursively, without pooling.
\r
171 RdpAttribute attr = this as RdpAttribute;
\r
172 if (attr != null) {
\r
173 attr.Children.setInternTable (ht);
\r
176 RdpElement el = this as RdpElement;
\r
178 el.Children.setInternTable (ht);
\r
181 RdpDataExcept dex= this as RdpDataExcept;
\r
183 dex.Except.setInternTable (ht);
\r
187 switch (PatternType) {
\r
188 case RelaxngPatternType.Empty:
\r
189 case RelaxngPatternType.NotAllowed:
\r
190 case RelaxngPatternType.Text:
\r
191 case RelaxngPatternType.Data:
\r
192 case RelaxngPatternType.Value:
\r
196 #if REPLACE_IN_ADVANCE
\r
197 throw new InvalidOperationException ();
\r
201 internal abstract void MarkReachableDefs ();
\r
203 internal abstract void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept);
\r
205 internal abstract bool ContainsText ();
\r
207 internal virtual RdpPattern ExpandRef (Hashtable defs)
\r
212 internal virtual RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
\r
217 public abstract bool Nullable { get; }
\r
219 // fills QName collection
\r
220 public abstract void GetLabels (LabelList elements, LabelList attributes);
\r
222 internal void AddNameLabel (LabelList names, RdpNameClass nc)
\r
224 RdpName name = nc as RdpName;
\r
225 if (name != null) {
\r
226 XmlQualifiedName qname = new XmlQualifiedName (
\r
227 name.LocalName, name.NamespaceURI);
\r
228 names [qname] = qname;
\r
231 RdpNameClassChoice choice = nc as RdpNameClassChoice;
\r
232 if (choice != null) {
\r
233 AddNameLabel (names, choice.LValue);
\r
234 AddNameLabel (names, choice.RValue);
\r
237 // For NsName and AnyName, do nothing.
\r
241 public virtual RdpPattern TextDeriv (string s, XmlReader reader)
\r
243 // This is an extension to JJC algorithm.
\r
244 // Whitespace text are allowed except for Data and Value
\r
245 // (their TextDeriv are overridden)
\r
246 return Util.IsWhitespace (s) ? this : RdpNotAllowed.Instance;
\r
250 public RdpPattern ChildDeriv (RdpChildNode child)
\r
252 RdpTextChild tc = child as RdpTextChild;
\r
253 // RdpElementChild ec = child as RdpElementChild;
\r
255 return TextDeriv (tc.Text);
\r
257 // complex stuff;-(
\r
258 return StartTagOpenDeriv (ec.LocalName, ec.NamespaceURI)
\r
259 .AttsDeriv (ec.Attributes)
\r
260 .StartTagCloseDeriv ()
\r
261 .ChildrenDeriv (ec.ChildNodes)
\r
267 public RdpPattern ListDeriv (string [] list, int index, XmlReader reader)
\r
269 return listDerivInternal (list, 0, reader);
\r
272 private RdpPattern listDerivInternal (string [] list, int start, XmlReader reader)
\r
274 if (list.Length <= start)
\r
277 return this.TextDeriv (list [start], reader).listDerivInternal (list, start + 1, reader);
\r
281 public virtual RdpPattern Choice (RdpPattern p)
\r
283 if (p is RdpNotAllowed)
\r
285 else if (this is RdpNotAllowed)
\r
288 return MakeChoice (this, p);
\r
292 public virtual RdpPattern Group (RdpPattern p)
\r
294 if (p is RdpNotAllowed || this is RdpNotAllowed)
\r
295 return RdpNotAllowed.Instance;
\r
296 else if (p is RdpEmpty)
\r
298 else if (this is RdpEmpty)
\r
301 return MakeGroup (this, p);
\r
304 // Interleave(this, p)
\r
305 public virtual RdpPattern Interleave (RdpPattern p)
\r
307 if (p is RdpNotAllowed || this is RdpNotAllowed)
\r
308 return RdpNotAllowed.Instance;
\r
309 else if (p is RdpEmpty)
\r
311 else if (this is RdpEmpty)
\r
314 return MakeInterleave (this, p);
\r
318 public virtual RdpPattern After (RdpPattern p)
\r
320 if (this is RdpNotAllowed || p is RdpNotAllowed)
\r
321 return RdpNotAllowed.Instance;
\r
323 return MakeAfter (this, p);
\r
327 // applyAfter((f, p1=this), p2)
\r
328 public virtual RdpPattern ApplyAfter (RdpApplyAfterHandler h)
\r
330 return RdpNotAllowed.Instance;
\r
333 // startTagOpenDeriv (this, qname)
\r
334 // startTagOpenDeriv _ qn = NotAllowed (default)
\r
335 public virtual RdpPattern StartTagOpenDeriv (string name, string ns)
\r
337 return RdpNotAllowed.Instance;
\r
340 // attDeriv(ctx, this, att)
\r
341 // attDeriv _ _ _ = NotAllowed
\r
342 public virtual RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
\r
344 return RdpNotAllowed.Instance;
\r
347 public bool ValueMatch (string s, XmlReader reader)
\r
349 return (Nullable && RdpUtil.Whitespace (s)) ||
\r
350 TextDeriv (s, reader).Nullable;
\r
353 public virtual RdpPattern StartTagCloseDeriv ()
\r
359 public RdpPattern ChildrenDeriv (RdpChildNodes children)
\r
361 return childrenDerivInternal (children, 0);
\r
364 RdpPattern childrenDerivInternal (RdpChildNodes children, int start)
\r
366 if (children.Count == 0) {
\r
367 // childrenDeriv cx p []
\r
368 RdpChildNodes c = new RdpChildNodes ();
\r
369 c.Add (new RdpTextChild (String.Empty));
\r
370 return ChildrenDeriv (c);
\r
371 } else if (children.Count == 1 && children [0] is RdpTextChild) {
\r
372 // childrenDeriv cx p [(TextNode s)]
\r
373 RdpTextChild tc = children [0] as RdpTextChild;
\r
374 RdpPattern p1 = ChildDeriv (tc);
\r
375 return RdpUtil.Whitespace (tc.Text) ?
\r
376 RdpUtil.Choice (this, p1) : p1;
\r
378 // childrenDeriv cx p children
\r
379 return stripChildrenDerivInternal (children, start);
\r
382 RdpPattern stripChildrenDerivInternal (RdpChildNodes children, int start)
\r
384 if (children.Count == start)
\r
387 RdpChildNode firstChild =
\r
388 children [start] as RdpChildNode;
\r
390 (firstChild.IsNonWhitespaceText) ?
\r
391 this : ChildDeriv (firstChild);
\r
392 return p.childrenDerivInternal (children, start + 1);
\r
397 public RdpPattern OneOrMore ()
\r
399 if (PatternType == RelaxngPatternType.NotAllowed)
\r
400 return RdpNotAllowed.Instance;
\r
402 return MakeOneOrMore (this);
\r
405 public virtual RdpPattern EndTagDeriv ()
\r
407 return RdpNotAllowed.Instance;
\r
413 public class RdpEmpty : RdpPattern
\r
415 public RdpEmpty () {}
\r
418 instance = new RdpEmpty ();
\r
421 public override bool Nullable {
\r
422 get { return true; }
\r
425 static RdpEmpty instance;
\r
426 public static RdpEmpty Instance {
\r
427 get { return instance; }
\r
430 public override RelaxngPatternType PatternType {
\r
431 get { return RelaxngPatternType.Empty; }
\r
434 public override RdpContentType ContentType {
\r
435 get { return RdpContentType.Empty; }
\r
438 public override void GetLabels (LabelList elements, LabelList attributes)
\r
443 internal override void MarkReachableDefs ()
\r
448 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
451 throw new RelaxngException ("empty cannot appear under except of a data pattern.");
\r
454 internal override bool ContainsText()
\r
461 public class RdpNotAllowed : RdpPattern
\r
463 public RdpNotAllowed () {}
\r
464 static RdpNotAllowed ()
\r
466 instance = new RdpNotAllowed ();
\r
469 static RdpNotAllowed instance;
\r
470 public static RdpNotAllowed Instance {
\r
471 get { return instance; }
\r
474 public override bool Nullable {
\r
475 get { return false; }
\r
478 public override RdpPattern ApplyAfter (RdpApplyAfterHandler h)
\r
480 return RdpNotAllowed.Instance;
\r
483 public override RelaxngPatternType PatternType {
\r
484 get { return RelaxngPatternType.NotAllowed; }
\r
487 public override RdpContentType ContentType {
\r
488 get { return RdpContentType.Empty; }
\r
491 internal override void MarkReachableDefs ()
\r
496 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
501 internal override bool ContainsText()
\r
506 public override void GetLabels (LabelList elements, LabelList attributes)
\r
508 // FIXME: Supposed to clear something here?
\r
513 public class RdpText : RdpPattern
\r
515 static RdpText instance;
\r
516 public static RdpText Instance {
\r
517 get { return instance; }
\r
520 public RdpText () {}
\r
523 instance = new RdpText ();
\r
526 public override bool Nullable {
\r
527 get { return true; }
\r
530 public override RelaxngPatternType PatternType {
\r
531 get { return RelaxngPatternType.Text; }
\r
534 public override RdpContentType ContentType {
\r
535 get { return RdpContentType.Complex; }
\r
538 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
543 internal override void MarkReachableDefs ()
\r
548 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
551 throw new RelaxngException ("text is not allowed under a list.");
\r
553 throw new RelaxngException ("text is not allowed under except of a list.");
\r
556 internal override bool ContainsText()
\r
561 public override void GetLabels (LabelList elements, LabelList attributes)
\r
568 public abstract class RdpAbstractBinary : RdpPattern
\r
570 public RdpAbstractBinary (RdpPattern l, RdpPattern r)
\r
577 public RdpPattern LValue {
\r
583 public RdpPattern RValue {
\r
588 public override RdpContentType ContentType {
\r
590 if (l.ContentType == RdpContentType.Empty)
\r
591 return r.ContentType;
\r
592 if (r.ContentType == RdpContentType.Empty)
\r
593 return l.ContentType;
\r
595 if ((l.ContentType & RdpContentType.Simple) != 0 || ((r.ContentType & RdpContentType.Simple) != 0))
\r
596 throw new RelaxngException ("The content type of this group is invalid.");
\r
597 return RdpContentType.Complex;
\r
602 internal override RdpPattern ExpandRef (Hashtable defs)
\r
605 l = l.ExpandRef (defs);
\r
606 r = r.ExpandRef (defs);
\r
611 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
\r
613 if (visited.Contains (this))
\r
615 visited.Add (this, this);
\r
617 if (LValue.PatternType == RelaxngPatternType.NotAllowed ||
\r
618 RValue.PatternType == RelaxngPatternType.NotAllowed) {
\r
620 return RdpNotAllowed.Instance;
\r
621 } else if (LValue.PatternType == RelaxngPatternType.Empty) {
\r
623 return RValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
624 } else if (RValue.PatternType == RelaxngPatternType.Empty) {
\r
626 return LValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
628 LValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
629 RValue = RValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
634 internal override void MarkReachableDefs ()
\r
636 l.MarkReachableDefs ();
\r
637 r.MarkReachableDefs ();
\r
640 internal override bool ContainsText()
\r
642 return l.ContainsText () || r.ContainsText ();
\r
647 public class RdpChoice : RdpAbstractBinary
\r
649 public RdpChoice (RdpPattern l, RdpPattern r) : base (l, r)
\r
653 public override bool Nullable {
\r
655 if (!nullableComputed) {
\r
657 LValue.Nullable || RValue.Nullable;
\r
658 nullableComputed = true;
\r
664 public override RelaxngPatternType PatternType {
\r
665 get { return RelaxngPatternType.Choice; }
\r
668 public override RdpContentType ContentType {
\r
670 if (LValue.ContentType == RdpContentType.Simple ||
\r
671 RValue.ContentType == RdpContentType.Simple)
\r
672 return RdpContentType.Simple;
\r
673 return base.ContentType;
\r
677 public override void GetLabels (LabelList elements, LabelList attributes)
\r
679 LValue.GetLabels (elements, attributes);
\r
680 RValue.GetLabels (elements, attributes);
\r
684 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
\r
686 if (visited.Contains (this))
\r
688 visited.Add (this, this);
\r
690 if (LValue.PatternType == RelaxngPatternType.NotAllowed &&
\r
691 RValue.PatternType == RelaxngPatternType.NotAllowed) {
\r
693 return RdpNotAllowed.Instance;
\r
694 } else if (LValue.PatternType == RelaxngPatternType.NotAllowed) {
\r
696 return RValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
697 } else if (RValue.PatternType == RelaxngPatternType.NotAllowed) {
\r
699 return LValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
700 } else if (LValue.PatternType == RelaxngPatternType.Empty &&
\r
701 RValue.PatternType == RelaxngPatternType.Empty) {
\r
703 return RdpEmpty.Instance;
\r
704 } else if (RValue.PatternType == RelaxngPatternType.Empty) {
\r
706 RValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
707 LValue = RdpEmpty.Instance;
\r
710 LValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
711 RValue = RValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
716 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
718 return LValue.TextDeriv (s, reader).Choice (RValue.TextDeriv (s, reader));
\r
721 public override RdpPattern ApplyAfter (RdpApplyAfterHandler handler)
\r
723 // return handler (LValue).Choice (handler (RValue));
\r
724 return LValue.ApplyAfter (handler).Choice (RValue.ApplyAfter (handler));
\r
727 public override RdpPattern StartTagOpenDeriv (string name, string ns)
\r
730 return RdpUtil.Choice (
\r
731 RdpUtil.StartTagOpenDeriv (LValue, qname),
\r
732 RdpUtil.StartTagOpenDeriv (RValue, qname));
\r
734 RdpPattern lDeriv = LValue.StartTagOpenDeriv (name, ns);
\r
735 return lDeriv.Choice (RValue.StartTagOpenDeriv (name, ns));
\r
739 // attDeriv cx (Choice p1 p2) att =
\r
740 // choice (attDeriv cx p1 att) (attDeriv cx p2 att)
\r
741 public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
\r
743 return LValue.AttDeriv (name, ns, value, reader)
\r
744 .Choice (RValue.AttDeriv (name, ns, value, reader));
\r
747 // startTagCloseDeriv (Choice p1 p2) =
\r
748 // choice (startTagCloseDeriv p1) (startTagCloseDeriv p2)
\r
749 public override RdpPattern StartTagCloseDeriv ()
\r
751 return LValue.StartTagCloseDeriv ()
\r
752 .Choice (RValue.StartTagCloseDeriv ());
\r
755 public override RdpPattern EndTagDeriv ()
\r
757 return LValue.EndTagDeriv ().Choice (RValue.EndTagDeriv ());
\r
760 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
762 LValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, list, dataExcept);
\r
763 RValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, list, dataExcept);
\r
768 public class RdpInterleave : RdpAbstractBinary
\r
770 public RdpInterleave (RdpPattern l, RdpPattern r) : base (l, r)
\r
774 public override bool Nullable {
\r
776 if (!nullableComputed) {
\r
778 LValue.Nullable && RValue.Nullable;
\r
779 nullableComputed = true;
\r
785 public override void GetLabels (LabelList elements, LabelList attributes)
\r
787 LValue.GetLabels (elements, attributes);
\r
788 RValue.GetLabels (elements, attributes);
\r
791 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
\r
793 if (visited.Contains (this))
\r
795 visited.Add (this, this);
\r
797 if (LValue.PatternType == RelaxngPatternType.NotAllowed ||
\r
798 RValue.PatternType == RelaxngPatternType.NotAllowed) {
\r
800 return RdpNotAllowed.Instance;
\r
802 LValue = LValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
803 RValue = RValue.ReduceEmptyAndNotAllowed (ref result, visited);
\r
808 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
810 return LValue.TextDeriv (s, reader).Interleave (RValue)
\r
811 .Choice (LValue.Interleave (RValue.TextDeriv (s, reader)));
\r
814 // => choice (applyAfter (flip interleave p2) (startTagOpenDeriv p1 qn)) (applyAfter (interleave p1) (startTagOpenDeriv p2 qn)
\r
815 // => p1.startTagOpenDeriv(qn).applyAfter (flip interleave p2).choice (p2.startTagOpenDeriv(qn).applyAfter (interleave p1) )
\r
816 public override RdpPattern StartTagOpenDeriv (string name, string ns)
\r
818 RdpPattern handledL = LValue.StartTagOpenDeriv (name, ns);
\r
819 RdpPattern handledR = RValue.StartTagOpenDeriv (name, ns);
\r
820 RdpFlip flipL = new RdpFlip (new RdpBinaryFunction (RdpUtil.Interleave), RValue);
\r
821 RdpPattern choiceL = handledL.ApplyAfter (new RdpApplyAfterHandler (flipL.Apply));
\r
822 RdpPattern choiceR = handledR.ApplyAfter (new RdpApplyAfterHandler (LValue.Interleave));
\r
823 return choiceL.Choice (choiceR);
\r
826 // attDeriv cx (Interleave p1 p2) att =
\r
827 // choice (interleave (attDeriv cx p1 att) p2)
\r
828 // (interleave p1 (attDeriv cx p2 att))
\r
829 public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
\r
831 return LValue.AttDeriv (name, ns, value, reader)
\r
832 .Interleave (RValue)
\r
833 .Choice (LValue.Interleave (
\r
834 RValue.AttDeriv (name, ns, value, reader)));
\r
837 // startTagCloseDeriv (Interleave p1 p2) =
\r
838 // interleave (startTagCloseDeriv p1) (startTagCloseDeriv p2)
\r
839 public override RdpPattern StartTagCloseDeriv ()
\r
841 return LValue.StartTagCloseDeriv ()
\r
842 .Interleave (RValue.StartTagCloseDeriv ());
\r
846 // FIXME: This is not specified in James Clark's algorithm, so
\r
847 // this may raise unstable behaviour!!
\r
848 // I think this is right but not confident.
\r
850 // ... then I reminded to include it.
\r
851 public override RdpPattern EndTagDeriv ()
\r
853 return LValue.Nullable ? RValue : RdpNotAllowed.Instance;
\r
857 public override RelaxngPatternType PatternType {
\r
858 get { return RelaxngPatternType.Interleave; }
\r
861 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
864 throw new RelaxngException ("interleave is not allowed under a list.");
\r
866 throw new RelaxngException ("interleave is not allowed under except of a data.");
\r
869 LValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMore, list, dataExcept);
\r
870 RValue.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMore, list, dataExcept);
\r
873 // TODO: (1) unique name analysis
\r
874 // (2) text/text prohibited
\r
875 if (LValue.PatternType == RelaxngPatternType.Text && RValue.PatternType == RelaxngPatternType.Text)
\r
876 throw new RelaxngException ("Both branches of the interleave contains a text pattern.");
\r
881 public class RdpGroup : RdpAbstractBinary
\r
883 public RdpGroup (RdpPattern l, RdpPattern r) : base (l, r)
\r
887 public override bool Nullable {
\r
889 if (!nullableComputed) {
\r
891 LValue.Nullable && RValue.Nullable;
\r
892 nullableComputed = true;
\r
898 public override void GetLabels (LabelList elements, LabelList attributes)
\r
900 LValue.GetLabels (elements, attributes);
\r
901 if (LValue.Nullable)
\r
902 RValue.GetLabels (elements, attributes);
\r
905 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
907 RdpPattern p = LValue.TextDeriv (s, reader).Group (RValue);
\r
908 return p.Nullable ?
\r
909 p.Choice (RValue.TextDeriv(s, reader)) : p;
\r
912 // startTagOpenDeriv (Group p1 p2) qn =
\r
913 // let x = applyAfter (flip group p2) (startTagOpenDeriv p1 qn)
\r
914 // in if nullable p1 then
\r
915 // choice x (startTagOpenDeriv p2 qn)
\r
918 public override RdpPattern StartTagOpenDeriv (string name, string ns)
\r
920 RdpPattern handled = LValue.StartTagOpenDeriv (name, ns);
\r
921 RdpFlip f = new RdpFlip (new RdpBinaryFunction (RdpUtil.Group), RValue);
\r
922 RdpPattern x = handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));
\r
923 if (LValue.Nullable)
\r
924 return x.Choice (RValue.StartTagOpenDeriv (name, ns));
\r
929 // attDeriv cx (Group p1 p2) att =
\r
930 // choice (group (attDeriv cx p1 att) p2)
\r
931 // (group p1 (attDeriv cx p2 att))
\r
932 public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
\r
934 return LValue.AttDeriv (name, ns, value, reader).Group (RValue)
\r
935 .Choice (LValue.Group (
\r
936 RValue.AttDeriv (name, ns, value, reader)));
\r
939 // startTagCloseDeriv (Group p1 p2) =
\r
940 // group (startTagCloseDeriv p1) (startTagCloseDeriv p2)
\r
941 public override RdpPattern StartTagCloseDeriv ()
\r
943 return LValue.StartTagCloseDeriv ()
\r
944 .Group (RValue.StartTagCloseDeriv ());
\r
947 public override RelaxngPatternType PatternType {
\r
948 get { return RelaxngPatternType.Group; }
\r
951 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
954 throw new RelaxngException ("interleave is not allowed under except of a data.");
\r
956 LValue.CheckConstraints (attribute, oneOrMore, oneOrMore, oneOrMoreInterleave, list, dataExcept);
\r
957 RValue.CheckConstraints (attribute, oneOrMore, oneOrMore, oneOrMoreInterleave, list, dataExcept);
\r
961 public abstract class RdpAbstractSingleContent : RdpPattern
\r
966 internal override RdpPattern ExpandRef (Hashtable defs)
\r
969 child = child.ExpandRef (defs);
\r
973 public RdpAbstractSingleContent (RdpPattern p)
\r
978 public RdpPattern Child {
\r
979 get { return child; }
\r
980 set { child = value; }
\r
983 internal override void MarkReachableDefs ()
\r
985 child.MarkReachableDefs ();
\r
988 internal override bool ContainsText()
\r
990 return child.ContainsText ();
\r
995 public class RdpOneOrMore : RdpAbstractSingleContent
\r
997 public RdpOneOrMore (RdpPattern p) : base (p)
\r
1001 public override RelaxngPatternType PatternType {
\r
1002 get { return RelaxngPatternType.OneOrMore; }
\r
1005 public override RdpContentType ContentType {
\r
1007 if (Child.ContentType == RdpContentType.Simple)
\r
1008 throw new RelaxngException ("Invalid content type was found.");
\r
1009 return Child.ContentType;
\r
1013 public override bool Nullable {
\r
1014 get { return Child.Nullable; }
\r
1017 public override void GetLabels (LabelList elements, LabelList attributes)
\r
1019 Child.GetLabels (elements, attributes);
\r
1022 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
\r
1024 if (visited.Contains (this))
\r
1026 visited.Add (this, this);
\r
1028 if (Child.PatternType == RelaxngPatternType.NotAllowed) {
\r
1030 return RdpNotAllowed.Instance;
\r
1031 } else if (Child.PatternType == RelaxngPatternType.Empty)
\r
1032 return RdpEmpty.Instance;
\r
1034 Child = Child.ReduceEmptyAndNotAllowed (ref result, visited);
\r
1039 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
1041 return Child.TextDeriv (s, reader).Group (Choice (RdpEmpty.Instance));
\r
1044 // attDeriv cx (OneOrMore p) att =
\r
1045 // group (attDeriv cx p att) (choice (OneOrMore p) Empty)
\r
1046 public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
\r
1049 return RdpUtil.Group (
\r
1050 RdpUtil.AttDeriv (ctx, children, att),
\r
1051 RdpUtil.Choice (RdpUtil.OneOrMore (children), RdpEmpty.Instance));
\r
1053 return Child.AttDeriv (name, ns, value, reader)
\r
1054 .Group (Choice (RdpEmpty.Instance));
\r
1058 // startTagOpenDeriv (OneOrMore p) qn =
\r
1059 // applyAfter (flip group (choice (OneOrMore p) Empty))
\r
1060 // (startTagOpenDeriv p qn)
\r
1061 public override RdpPattern StartTagOpenDeriv (string name, string ns)
\r
1063 RdpPattern rest = RdpEmpty.Instance.Choice (Child.OneOrMore ());
\r
1064 RdpPattern handled = Child.StartTagOpenDeriv (name, ns);
\r
1065 RdpFlip f = new RdpFlip (new RdpBinaryFunction (RdpUtil.Group), rest);
\r
1066 return handled.ApplyAfter (new RdpApplyAfterHandler (f.Apply));
\r
1069 // startTagCloseDeriv (OneOrMore p) =
\r
1070 // oneOrMore (startTagCloseDeriv p)
\r
1071 public override RdpPattern StartTagCloseDeriv ()
\r
1074 return RdpUtil.OneOrMore (
\r
1075 RdpUtil.StartTagCloseDeriv (children));
\r
1077 return Child.StartTagCloseDeriv ().OneOrMore ();
\r
1081 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
1084 throw new RelaxngException ("oneOrMore is not allowed under except of a data.");
\r
1085 this.Child.CheckConstraints (attribute, true, oneOrMoreGroup, oneOrMoreInterleave, list, dataExcept);
\r
1091 public class RdpList : RdpAbstractSingleContent
\r
1093 public RdpList (RdpPattern p) : base (p)
\r
1097 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
\r
1099 if (visited.Contains (this))
\r
1101 visited.Add (this, this);
\r
1103 if (Child.PatternType == RelaxngPatternType.NotAllowed) {
\r
1105 return RdpNotAllowed.Instance;
\r
1107 Child = Child.ReduceEmptyAndNotAllowed (ref result, visited);
\r
1113 // This is not written in James Clark's derivative algorithm
\r
1114 // ( http://www.thaiopensource.com/relaxng/derivative.html ),
\r
1115 // but it looks required.
\r
1116 public override bool Nullable {
\r
1117 get { return this.Child.Nullable; }
\r
1120 // ... but it also causes different error:
\r
1121 // <list><group><data .../><data .../></group></list>
\r
1123 public override bool Nullable {
\r
1124 get { return false; }
\r
1127 public override RelaxngPatternType PatternType {
\r
1128 get { return RelaxngPatternType.List; }
\r
1131 public override RdpContentType ContentType {
\r
1132 get { return RdpContentType.Simple; }
\r
1135 public override void GetLabels (LabelList elements, LabelList attributes)
\r
1137 Child.GetLabels (elements, attributes);
\r
1140 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
1142 RdpPattern p = Child.ListDeriv (Util.NormalizeWhitespace (s).Split (RdpUtil.WhitespaceChars), 0, reader);
\r
1144 return RdpEmpty.Instance;
\r
1146 return RdpNotAllowed.Instance;
\r
1149 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
1152 throw new RelaxngException ("list is not allowed uner another list.");
\r
1154 throw new RelaxngException ("list is not allowed under except of a data.");
\r
1155 this.Child.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, true, dataExcept);
\r
1160 public class RdpData : RdpPattern
\r
1162 public RdpData (RdpDatatype dt)
\r
1168 public RdpDatatype Datatype {
\r
1169 get { return dt; }
\r
1172 // This is not written in James Clark's derivative algorithm
\r
1173 // ( http://www.thaiopensource.com/relaxng/derivative.html ),
\r
1174 // but it looks required.
\r
1175 public override bool Nullable {
\r
1177 if (dt.NamespaceURI.Length == 0)
\r
1183 public override RelaxngPatternType PatternType {
\r
1184 get { return RelaxngPatternType.Data; }
\r
1187 public override RdpContentType ContentType {
\r
1188 get { return RdpContentType.Simple; }
\r
1191 public override void GetLabels (LabelList elements, LabelList attributes)
\r
1196 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
1198 if (dt.IsAllowed (s, reader))
\r
1199 return RdpEmpty.Instance;
\r
1201 return RdpNotAllowed.Instance;
\r
1204 internal override void MarkReachableDefs ()
\r
1209 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
1214 internal override bool ContainsText()
\r
1221 public class RdpDataExcept : RdpData
\r
1223 public RdpDataExcept (RdpDatatype dt, RdpPattern except)
\r
1226 this.except = except;
\r
1229 RdpPattern except;
\r
1230 public RdpPattern Except {
\r
1231 get { return except; }
\r
1232 set { except = value; }
\r
1235 public override RelaxngPatternType PatternType {
\r
1236 get { return RelaxngPatternType.DataExcept; }
\r
1239 public override RdpContentType ContentType {
\r
1241 RdpContentType c = except.ContentType; // conformance required for except pattern.
\r
1242 return RdpContentType.Simple;
\r
1246 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
\r
1248 if (visited.Contains (this))
\r
1250 visited.Add (this, this);
\r
1252 if (except.PatternType == RelaxngPatternType.NotAllowed) {
\r
1254 return new RdpData (this.Datatype);
\r
1256 except = except.ReduceEmptyAndNotAllowed (ref result, visited);
\r
1261 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
1263 if (Datatype.IsAllowed (s, reader) && !except.TextDeriv (s, reader).Nullable)
\r
1264 return RdpEmpty.Instance;
\r
1266 return RdpNotAllowed.Instance;
\r
1269 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
1271 this.except.CheckConstraints (attribute, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, list, true);
\r
1274 internal override bool ContainsText()
\r
1276 return except.ContainsText ();
\r
1281 public class RdpValue : RdpPattern
\r
1283 public RdpValue (RdpDatatype dt, string value)
\r
1286 this.value = value;
\r
1290 public RdpDatatype Datatype {
\r
1291 get { return dt; }
\r
1295 public string Value {
\r
1296 get { return value; }
\r
1299 // This is not written in James Clark's derivative algorithm
\r
1300 // ( http://www.thaiopensource.com/relaxng/derivative.html ),
\r
1301 // but it looks required.
\r
1302 public override bool Nullable {
\r
1304 if (dt.NamespaceURI.Length == 0 && value.Length == 0)
\r
1310 public override RelaxngPatternType PatternType {
\r
1311 get { return RelaxngPatternType.Value; }
\r
1314 public override RdpContentType ContentType {
\r
1315 get { return RdpContentType.Simple; }
\r
1318 public override void GetLabels (LabelList elements, LabelList attributes)
\r
1323 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
1325 if (dt.IsTypeEqual (value, s, reader))
\r
1326 return RdpEmpty.Instance;
\r
1328 return RdpNotAllowed.Instance;
\r
1331 internal override void MarkReachableDefs ()
\r
1336 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
1338 // nothing to be checked
\r
1341 internal override bool ContainsText()
\r
1348 public class RdpAttribute : RdpPattern
\r
1350 public RdpAttribute (RdpNameClass nameClass, RdpPattern p)
\r
1352 this.nameClass = nameClass;
\r
1353 this.children = p;
\r
1356 RdpNameClass nameClass;
\r
1357 public RdpNameClass NameClass {
\r
1358 get { return nameClass; }
\r
1361 RdpPattern children;
\r
1362 public RdpPattern Children {
\r
1363 get { return children; }
\r
1364 set { children = value; }
\r
1367 public override bool Nullable {
\r
1368 get { return false; }
\r
1371 public override RelaxngPatternType PatternType {
\r
1372 get { return RelaxngPatternType.Attribute; }
\r
1375 public override RdpContentType ContentType {
\r
1376 get { return RdpContentType.Empty; }
\r
1379 public override void GetLabels (LabelList elements, LabelList attributes)
\r
1381 AddNameLabel (attributes, NameClass);
\r
1385 internal override RdpPattern ExpandRef (Hashtable defs)
\r
1387 if (!isExpanded) {
\r
1388 isExpanded = true;
\r
1389 children = children.ExpandRef (defs);
\r
1394 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
\r
1396 if (visited.Contains (this))
\r
1398 visited.Add (this, this);
\r
1400 if (children.PatternType == RelaxngPatternType.NotAllowed) {
\r
1402 return RdpNotAllowed.Instance;
\r
1404 children = children.ReduceEmptyAndNotAllowed (ref result, visited);
\r
1409 // attDeriv cx (Attribute nc p) (AttributeNode qn s) =
\r
1410 // if contains nc qn && valueMatch cx p s then Empty else NotAllowed
\r
1411 public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
\r
1413 // If value is null, then does not check ValueMatch.
\r
1415 if (RdpUtil.Contains (this.nameClass, att.QName)
\r
1416 && (value == null || RdpUtil.ValueMatch (ctx, this.children, att.Value)))
\r
1417 return RdpEmpty.Instance;
\r
1419 return RdpNotAllowed.Instance;
\r
1421 if (nameClass.Contains (name, ns) &&
\r
1422 (value == null || children.ValueMatch (value, reader)))
\r
1423 return RdpEmpty.Instance;
\r
1425 return RdpNotAllowed.Instance;
\r
1429 // startTagCloseDeriv (Attribute _ _) = NotAllowed
\r
1430 public override RdpPattern StartTagCloseDeriv ()
\r
1432 return RdpNotAllowed.Instance;
\r
1435 internal override void MarkReachableDefs ()
\r
1437 children.MarkReachableDefs ();
\r
1440 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
1442 if (attribute || oneOrMoreGroup || oneOrMoreInterleave || list || dataExcept)
\r
1443 throw new RelaxngException ("Not allowed attribute occurence was specified in the pattern.");
\r
1444 this.Children.CheckConstraints (true, oneOrMore, false, false, false, false);
\r
1447 internal override bool ContainsText()
\r
1449 return children.ContainsText ();
\r
1454 public class RdpElement : RdpPattern
\r
1456 public RdpElement (RdpNameClass nameClass, RdpPattern p)
\r
1458 this.nameClass = nameClass;
\r
1459 this.children = p;
\r
1462 RdpNameClass nameClass;
\r
1463 public RdpNameClass NameClass {
\r
1464 get { return nameClass; }
\r
1467 RdpPattern children;
\r
1468 public RdpPattern Children {
\r
1469 get { return children; }
\r
1470 set { children = value; }
\r
1473 public override bool Nullable {
\r
1474 get { return false; }
\r
1477 public override RelaxngPatternType PatternType {
\r
1478 get { return RelaxngPatternType.Element; }
\r
1481 bool contentTypeCheckDone;
\r
1482 public override RdpContentType ContentType {
\r
1484 if (!contentTypeCheckDone) {
\r
1485 contentTypeCheckDone = true;
\r
1486 RdpContentType ct = children.ContentType; // conformance required.
\r
1488 return RdpContentType.Complex;
\r
1492 public override void GetLabels (LabelList elements, LabelList attributes)
\r
1494 AddNameLabel (elements, NameClass);
\r
1499 short expanding; // FIXME: It is totally not required, but there is
\r
1500 // some bugs in simplification and without it it causes infinite loop.
\r
1501 internal override RdpPattern ExpandRef (Hashtable defs)
\r
1503 if (!isExpanded) {
\r
1504 isExpanded = true;
\r
1505 if (expanding == 100)
\r
1506 throw new RelaxngException (String.Format ("Invalid recursion was found. Name is {0}", nameClass));
\r
1508 children = children.ExpandRef (defs);
\r
1514 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
\r
1516 if (visited.Contains (this))
\r
1518 visited.Add (this, this);
\r
1520 children = children.ReduceEmptyAndNotAllowed (ref result, visited);
\r
1524 public override RdpPattern StartTagOpenDeriv (string name, string ns)
\r
1527 if (RdpUtil.Contains (this.nameClass, qname))
\r
1528 return RdpUtil.After (this.Children, RdpEmpty.Instance);
\r
1530 return RdpNotAllowed.Instance;
\r
1532 return nameClass.Contains (name, ns) ?
\r
1533 children.After (RdpEmpty.Instance) :
\r
1534 RdpNotAllowed.Instance;
\r
1538 internal override void MarkReachableDefs ()
\r
1540 children.MarkReachableDefs ();
\r
1543 bool constraintsChecked;
\r
1544 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
1546 if (constraintsChecked)
\r
1548 constraintsChecked = true;
\r
1549 if (attribute || list || dataExcept)
\r
1550 throw new RelaxngException ("Not allowed element occurence was specified in the pattern.");
\r
1551 this.Children.CheckConstraints (false, oneOrMore, oneOrMoreGroup, oneOrMoreInterleave, false, false);
\r
1554 internal override bool ContainsText()
\r
1556 return children.ContainsText ();
\r
1561 public class RdpAfter : RdpAbstractBinary
\r
1563 public RdpAfter (RdpPattern l, RdpPattern r) : base (l, r)
\r
1567 public override bool Nullable {
\r
1568 get { return false; }
\r
1571 public override void GetLabels (LabelList elements, LabelList attributes)
\r
1573 LValue.GetLabels (elements, attributes);
\r
1576 public override RdpPattern TextDeriv (string s, XmlReader reader)
\r
1578 return LValue.TextDeriv (s, reader).After (RValue);
\r
1581 // startTagOpenDeriv (After p1 p2) qn =
\r
1582 // applyAfter (flip after p2) (startTagOpenDeriv p1 qn)
\r
1583 public override RdpPattern StartTagOpenDeriv (string name, string ns)
\r
1585 RdpPattern handled = LValue.StartTagOpenDeriv (name, ns);
\r
1586 RdpFlip f = new RdpFlip (new RdpBinaryFunction (RdpUtil.After), RValue);
\r
1587 return handled.ApplyAfter (new RdpApplyAfterHandler (
\r
1591 public override RdpPattern ApplyAfter (RdpApplyAfterHandler handler)
\r
1593 return LValue.After (handler (RValue));
\r
1596 // attDeriv cx (After p1 p2) att =
\r
1597 // after (attDeriv cx p1 att) p2
\r
1598 public override RdpPattern AttDeriv (string name, string ns, string value, XmlReader reader)
\r
1600 return LValue.AttDeriv (name, ns, value, reader).After (RValue);
\r
1603 public override RdpPattern StartTagCloseDeriv ()
\r
1605 return LValue.StartTagCloseDeriv ().After (RValue);
\r
1608 public override RdpPattern EndTagDeriv ()
\r
1610 return LValue.Nullable ? RValue : RdpNotAllowed.Instance;
\r
1613 public override RelaxngPatternType PatternType {
\r
1614 get { return RelaxngPatternType.After; }
\r
1617 internal override void MarkReachableDefs ()
\r
1619 throw new InvalidOperationException ();
\r
1622 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
\r
1624 throw new InvalidOperationException ();
\r
1627 internal override bool ContainsText ()
\r
1629 throw new InvalidOperationException ();
\r