fix typo
[mcs.git] / class / Mono.Xml.Ext / Mono.Xml.XPath2 / SequenceType.cs
blob55cb7113acee421221ef2fec4ac3c78c268d23e5
1 //
2 // SequenceType.cs - represents XPath 2.0 item type
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 //
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #if NET_2_0
31 using System;
32 using System.Collections;
33 using System.Globalization;
34 using System.Xml;
35 using System.Xml.Schema;
36 using System.Xml.Query;
37 using System.Xml.XPath;
38 using Mono.Xml;
40 namespace Mono.Xml.XPath2
42 public class SequenceType
44 static SequenceType singleItem = new SequenceType (ItemType.AnyItem, Occurence.One);
45 static SequenceType singleAnyAtomic = new SequenceType (ItemType.AnyAtomicType, Occurence.One);
47 internal static SequenceType AnyType {
48 get { return Create (InternalPool.XsAnyType, Occurence.ZeroOrMore); }
50 internal static SequenceType SingleItem {
51 get { return singleItem; }
53 internal static SequenceType SingleAnyAtomic {
54 get { return singleAnyAtomic; }
57 internal static SequenceType Node {
58 get { return Create (XmlTypeCode.Node, Occurence.One); }
60 internal static SequenceType Document {
61 get { return Create (XmlTypeCode.Document, Occurence.One); }
63 internal static SequenceType Element {
64 get { return Create (XmlTypeCode.Element, Occurence.One); }
66 internal static SequenceType Attribute {
67 get { return Create (XmlTypeCode.Attribute, Occurence.One); }
69 internal static SequenceType Namespace {
70 get { return Create (XmlTypeCode.Namespace, Occurence.One); }
72 internal static SequenceType Text {
73 get { return Create (XmlTypeCode.Text, Occurence.One); }
75 internal static SequenceType XmlPI {
76 get { return Create (XmlTypeCode.ProcessingInstruction, Occurence.One); }
78 internal static SequenceType Comment {
79 get { return Create (XmlTypeCode.Comment, Occurence.One); }
82 internal static SequenceType AtomicString {
83 get { return Create (InternalPool.XsString, Occurence.One); }
85 internal static SequenceType Boolean {
86 get { return Create (InternalPool.XsBoolean, Occurence.One); }
88 internal static SequenceType Decimal {
89 get { return Create (InternalPool.XsDecimal, Occurence.One); }
91 internal static SequenceType Integer {
92 get { return Create (InternalPool.XsInteger, Occurence.One); }
94 internal static SequenceType Int {
95 get { return Create (InternalPool.XsInt, Occurence.One); }
97 internal static SequenceType Short {
98 get { return Create (InternalPool.XsShort, Occurence.One); }
100 internal static SequenceType UnsignedInt {
101 get { return Create (InternalPool.XsUnsignedInt, Occurence.One); }
103 internal static SequenceType UnsignedShort {
104 get { return Create (InternalPool.XsUnsignedShort, Occurence.One); }
106 internal static SequenceType Double {
107 get { return Create (InternalPool.XsDouble, Occurence.One); }
109 internal static SequenceType Single {
110 get { return Create (InternalPool.XsFloat, Occurence.One); }
112 internal static SequenceType DateTime {
113 get { return Create (InternalPool.XsDateTime, Occurence.One); }
115 internal static SequenceType QName {
116 get { return Create (InternalPool.XsQName, Occurence.One); }
119 internal static SequenceType IntegerList {
120 get { return Create (XmlTypeCode.Integer, Occurence.ZeroOrMore); }
124 static Hashtable standardTypes = new Hashtable ();
126 internal static SequenceType Create (Type cliType)
128 // typed Array
129 if (cliType.IsArray)
130 return Create (InternalPool.XmlTypeCodeFromRuntimeType (cliType.GetElementType (), true), Occurence.ZeroOrMore);
131 // if (cliType.GetInterface ("System.Collections.IEnumerable") != null)
132 // return Create (XmlTypeCode.Item, Occurence.ZeroOrMore);
133 if (cliType == typeof (XmlQualifiedName))
134 return QName;
135 if (cliType == typeof (XPathNavigator) || cliType.IsSubclassOf (typeof (XPathNavigator)))
136 return Node;
137 if (cliType == typeof (XPathAtomicValue))
138 return SingleAnyAtomic;
139 if (cliType == typeof (XPathItem))
140 return SingleItem;
141 // FIXME: handle Nullable type
142 return Create (InternalPool.XmlTypeCodeFromRuntimeType (cliType, true), Occurence.One);
145 internal static SequenceType Create (XmlTypeCode typeCode, Occurence occurence)
147 switch (typeCode) {
148 case XmlTypeCode.Item:
149 case XmlTypeCode.AnyAtomicType:
150 case XmlTypeCode.Node:
151 case XmlTypeCode.Document:
152 case XmlTypeCode.Element:
153 case XmlTypeCode.Attribute:
154 case XmlTypeCode.ProcessingInstruction:
155 case XmlTypeCode.Comment:
156 case XmlTypeCode.Namespace:
157 case XmlTypeCode.Text:
158 return new SequenceType (new ItemType (typeCode), occurence);
159 default:
160 return Create (XmlSchemaType.GetBuiltInSimpleType (typeCode), occurence);
164 internal static SequenceType Create (XmlSchemaType schemaType, Occurence occurence)
166 switch (schemaType.QualifiedName.Namespace) {
167 case XmlSchema.Namespace:
168 case InternalPool.XdtNamespace:
169 break;
170 default:
171 return new SequenceType (schemaType, occurence);
174 Hashtable cacheForType = standardTypes [schemaType] as Hashtable;
175 if (cacheForType == null) {
176 cacheForType = new Hashtable ();
177 standardTypes [schemaType] = cacheForType;
178 } else {
179 SequenceType type = cacheForType [occurence] as SequenceType;
180 if (type != null)
181 return type;
183 SequenceType t = new SequenceType (schemaType, occurence);
184 cacheForType [occurence] = t;
185 return t;
188 [MonoTODO]
189 internal static SequenceType ComputeCommonBase (SequenceType t1, SequenceType t2)
191 // FIXME: implement
192 // throw new NotImplementedException ();
193 return SequenceType.AnyType;
196 internal static bool IsNumeric (XmlTypeCode code)
198 switch (code) {
199 case XmlTypeCode.Decimal:
200 case XmlTypeCode.Float:
201 case XmlTypeCode.Double:
202 case XmlTypeCode.Integer:
203 case XmlTypeCode.NonPositiveInteger:
204 case XmlTypeCode.NegativeInteger:
205 case XmlTypeCode.Long:
206 case XmlTypeCode.Int:
207 case XmlTypeCode.Short:
208 case XmlTypeCode.Byte:
209 case XmlTypeCode.NonNegativeInteger:
210 case XmlTypeCode.UnsignedLong:
211 case XmlTypeCode.UnsignedInt:
212 case XmlTypeCode.UnsignedShort:
213 case XmlTypeCode.UnsignedByte:
214 case XmlTypeCode.PositiveInteger:
215 return true;
217 return false;
220 // Instance members
222 private SequenceType (XmlSchemaType schemaType, Occurence occurence)
224 this.schemaType = schemaType;
225 this.itemType = ItemType.AnyItem;
226 this.occurence = occurence;
229 internal SequenceType (ItemType itemType, Occurence occurence)
231 this.schemaType = InternalPool.XsAnyType;
232 this.itemType = itemType;
233 this.occurence = occurence;
236 XmlSchemaType schemaType;
237 Occurence occurence;
238 ItemType itemType;
240 public XmlSchemaType SchemaType {
241 get { return schemaType; }
244 public ItemType ItemType {
245 get { return itemType; }
248 public Occurence Occurence {
249 get { return occurence; }
252 internal bool Matches (XPathSequence iter)
254 throw new NotImplementedException ();
257 [MonoTODO]
258 internal bool CanConvertTo (SequenceType other)
260 // FIXME: implement precisely
261 return this == other;
262 // throw new NotImplementedException ();
265 internal bool CanConvert (XPathSequence iter)
267 bool occured = false;
268 bool onlyOnce = (occurence == Occurence.One || occurence == Occurence.Optional);
269 bool required = (occurence == Occurence.One || occurence == Occurence.OneOrMore);
270 foreach (XPathItem item in iter) {
271 if (occured && onlyOnce)
272 return false;
273 if (!CanConvert (item))
274 return false;
276 return occured || !required;
279 public bool CanConvert (XPathItem item)
281 throw new NotImplementedException ();
284 public bool IsInstance (XPathItem item)
286 throw new NotImplementedException ();
289 public XPathItem Convert (XPathItem item)
291 throw new NotImplementedException ();
294 public object ToRuntimeType (XPathSequence seq)
296 // FIXME: handle ZeroOrMore|OneOrMore
297 switch (occurence) {
298 case Occurence.One:
299 case Occurence.Optional:
300 if (!seq.MoveNext ())
301 return null;
302 XPathItem item = seq.Current;
303 // FIXME: should check and reject two or
304 // more items??
305 return item.TypedValue;
307 ArrayList al = new ArrayList ();
308 while (seq.MoveNext ())
309 al.Add (seq.Current.TypedValue);
310 return al.ToArray (InternalPool.RuntimeTypeFromXmlTypeCode (schemaType.TypeCode));
311 // return seq;
315 public enum Occurence
317 One,
318 Optional,
319 ZeroOrMore,
320 OneOrMore,
323 #region NodeTest
325 public enum XPathAxisType
327 Child,
328 Descendant,
329 Attribute,
330 Self,
331 DescendantOrSelf,
332 FollowingSibling,
333 Following,
334 Parent,
335 Ancestor,
336 PrecedingSibling,
337 Preceding,
338 AncestorOrSelf,
339 Namespace // only applicable under XPath 2.0, not XQuery 1.0
342 public class XPathAxis
344 // FIXME: add more parameters to distinguish them
345 private XPathAxis (XPathAxisType axisType)
347 this.axisType = axisType;
348 switch (axisType) {
349 case XPathAxisType.Parent:
350 case XPathAxisType.Ancestor:
351 case XPathAxisType.AncestorOrSelf:
352 case XPathAxisType.Preceding:
353 case XPathAxisType.PrecedingSibling:
354 this.reverse = true;
355 break;
359 bool reverse;
360 XPathAxisType axisType;
362 public bool ReverseAxis {
363 get { return reverse; }
366 public XPathAxisType AxisType {
367 get { return axisType; }
370 static XPathAxis child, descendant, attribute, self,
371 descendantOrSelf, followingSibling, following,
372 parent, ancestor, precedingSibling, preceding,
373 ancestorOrSelf, namespaceAxis;
375 static XPathAxis ()
377 child = new XPathAxis (XPathAxisType.Child);
378 descendant = new XPathAxis (XPathAxisType.Descendant);
379 attribute = new XPathAxis (XPathAxisType.Attribute);
380 self = new XPathAxis (XPathAxisType.Self);
381 descendantOrSelf = new XPathAxis (XPathAxisType.DescendantOrSelf);
382 followingSibling = new XPathAxis (XPathAxisType.FollowingSibling);
383 following = new XPathAxis (XPathAxisType.Following);
384 parent = new XPathAxis (XPathAxisType.Parent);
385 ancestor = new XPathAxis (XPathAxisType.Ancestor);
386 precedingSibling = new XPathAxis (XPathAxisType.PrecedingSibling);
387 preceding = new XPathAxis (XPathAxisType.Preceding);
388 ancestorOrSelf = new XPathAxis (XPathAxisType.AncestorOrSelf);
389 namespaceAxis = new XPathAxis (XPathAxisType.Namespace);
392 public static XPathAxis Child {
393 get { return child; }
396 public static XPathAxis Descendant {
397 get { return descendant; }
400 public static XPathAxis Attribute {
401 get { return attribute; }
404 public static XPathAxis Self {
405 get { return self; }
408 public static XPathAxis DescendantOrSelf {
409 get { return descendantOrSelf; }
412 public static XPathAxis FollowingSibling {
413 get { return followingSibling; }
416 public static XPathAxis Following {
417 get { return following; }
420 public static XPathAxis NamespaceAxis {
421 get { return namespaceAxis; }
424 public static XPathAxis Parent {
425 get { return parent; }
428 public static XPathAxis Ancestor {
429 get { return ancestor; }
432 public static XPathAxis PrecedingSibling {
433 get { return precedingSibling; }
436 public static XPathAxis Preceding {
437 get { return preceding; }
440 public static XPathAxis AncestorOrSelf {
441 get { return ancestorOrSelf; }
445 // ItemType
446 public class ItemType
448 static ItemType anyItem = new ItemType (XmlTypeCode.Item);
449 static ItemType anyAtomicType = new ItemType (XmlTypeCode.AnyAtomicType);
451 public static ItemType AnyItem {
452 get { return anyItem; }
455 public static ItemType AnyAtomicType {
456 get { return anyAtomicType; }
459 XmlTypeCode typeCode;
461 public ItemType (XmlTypeCode typeCode)
463 this.typeCode = typeCode;
466 public XmlTypeCode TypeCode {
467 get { return typeCode; }
470 internal virtual void CheckReference (XQueryASTCompiler compiler)
475 // KindTest
477 public class KindTest : ItemType
479 public KindTest (XmlTypeCode type)
480 : base (type)
484 internal virtual void Compile (XQueryASTCompiler compiler)
488 public virtual bool Matches (XPathItem item)
490 XPathNavigator nav = item as XPathNavigator;
491 if (nav == null)
492 return false;
493 // FIXME: is it true? ('untyped' means 'matches with any type' ?
494 if (item.XmlType == null)
495 return true;
496 if (item.XmlType.TypeCode != TypeCode)
497 return false;
498 return true;
502 public class DocumentTest : KindTest
504 ElementTest content;
506 public DocumentTest (ElementTest content)
507 : base (XmlTypeCode.Document)
509 this.content = content;
512 public ElementTest Content {
513 get { return content; }
516 internal override void CheckReference (XQueryASTCompiler compiler)
518 content.CheckReference (compiler);
521 internal override void Compile (XQueryASTCompiler compiler)
525 public override bool Matches (XPathItem item)
527 XPathNavigator nav = item as XPathNavigator;
528 if (nav == null)
529 return false;
531 if (item.XmlType.TypeCode != XmlTypeCode.Document)
532 return false;
534 if (Content == null)
535 return true;
537 nav = nav.Clone ();
538 nav.MoveToFirstChild ();
539 while (nav.NodeType != XPathNodeType.Element)
540 if (!nav.MoveToNext ())
541 return false;
542 return Content.Matches (nav);
546 public class ElementTest : KindTest
548 XmlQualifiedName name;
549 XmlQualifiedName typeName;
550 XmlSchemaType schemaType;
551 bool nillable;
553 public ElementTest (XmlQualifiedName name)
554 : base (XmlTypeCode.Element)
556 this.name = name;
559 public ElementTest (XmlQualifiedName name, XmlQualifiedName type, bool nillable)
560 : base (XmlTypeCode.Element)
562 this.name = name;
563 this.typeName = type;
564 this.nillable = nillable;
567 public XmlQualifiedName Name {
568 get { return name; }
571 public XmlQualifiedName TypeName {
572 get { return typeName; }
575 public XmlSchemaType SchemaType {
576 get {
577 return schemaType;
581 public bool Nillable {
582 get { return nillable; }
585 internal override void CheckReference (XQueryASTCompiler compiler)
587 compiler.CheckSchemaTypeName (typeName);
590 internal override void Compile (XQueryASTCompiler compiler)
592 schemaType = compiler.ResolveSchemaType (TypeName);
593 if (schemaType == null)
594 throw new XmlQueryCompileException ("Specified schema type was not found.");
597 public override bool Matches (XPathItem item)
599 XPathNavigator nav = item as XPathNavigator;
600 if (nav == null)
601 return false;
603 if (item.XmlType.TypeCode != XmlTypeCode.Element)
604 return false;
606 if (Name != XmlQualifiedName.Empty)
607 if (nav.LocalName != Name.Name || nav.NamespaceURI != Name.Namespace)
608 return false;
610 // FIXME: it won't be XQueryConvert.CanConvert(), but other strict-matching evaluation
611 if (SchemaType != null && !XQueryConvert.CanConvert (item, SchemaType))
612 return false;
613 // FIXME: check nillable
615 return true;
619 public class AttributeTest : KindTest
621 static AttributeTest anyAttribute;
623 static AttributeTest ()
625 anyAttribute = new AttributeTest (XmlQualifiedName.Empty);
628 public static AttributeTest AnyAttribute {
629 get { return anyAttribute; }
632 public AttributeTest (XmlQualifiedName name)
633 : base (XmlTypeCode.Attribute)
635 this.name = name;
638 public AttributeTest (XmlQualifiedName name, XmlQualifiedName typeName)
639 : base (XmlTypeCode.Attribute)
641 this.name = name;
642 this.typeName = typeName;
645 XmlQualifiedName name;
646 XmlQualifiedName typeName;
647 XmlSchemaType schemaType;
649 public XmlQualifiedName Name {
650 get { return name; }
653 public XmlQualifiedName TypeName {
654 get { return typeName; }
657 public XmlSchemaType SchemaType {
658 get { return schemaType; }
661 internal override void CheckReference (XQueryASTCompiler compiler)
663 compiler.CheckSchemaTypeName (typeName);
666 internal override void Compile (XQueryASTCompiler compiler)
668 schemaType = compiler.ResolveSchemaType (TypeName);
669 if (schemaType == null)
670 throw new XmlQueryCompileException ("Specified schema type was not found.");
673 public override bool Matches (XPathItem item)
675 XPathNavigator nav = item as XPathNavigator;
676 if (nav == null)
677 return false;
679 if (item.XmlType.TypeCode != XmlTypeCode.Attribute)
680 return false;
682 if (Name != XmlQualifiedName.Empty)
683 if (nav.LocalName != Name.Name || nav.NamespaceURI != Name.Namespace)
684 return false;
686 // FIXME: it won't be XQueryConvert.CanConvert(), but other strict-matching evaluation
687 if (SchemaType != null && !XQueryConvert.CanConvert (item, SchemaType))
688 return false;
690 return true;
694 public class XmlPITest : KindTest
696 string name;
698 public XmlPITest (string nameTest)
699 : base (XmlTypeCode.ProcessingInstruction)
701 this.name = nameTest;
704 public string Name {
705 get { return name; }
708 internal override void CheckReference (XQueryASTCompiler compiler)
712 internal override void Compile (XQueryASTCompiler compiler)
716 public override bool Matches (XPathItem item)
718 XPathNavigator nav = item as XPathNavigator;
719 if (nav == null)
720 return false;
722 if (item.XmlType.TypeCode != XmlTypeCode.ProcessingInstruction)
723 return false;
724 if (Name != String.Empty && nav.LocalName != Name)
725 return false;
726 return true;
730 #endregion
733 #endif