2004-12-09 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / Mono.Xml.Schema / XsdKeyTable.cs
1 //
2 // Mono.Xml.Schema.XsdKeyTable.cs
3 //
4 // Author:
5 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
6 //
7 //      (C)2003 Atsushi Enomoto
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 using System;\r
31 using System.Collections;\r
32 using System.Collections.Specialized;\r
33 using System.Xml;\r
34 using System.Xml.Schema;\r
35 \r
36 namespace Mono.Xml.Schema\r
37 {\r
38         internal class XsdKeyEntryCollection : CollectionBase\r
39         {\r
40                 public void Add (XsdKeyEntry entry)\r
41                 {\r
42                         List.Add (entry);\r
43                 }\r
44 \r
45                 public XsdKeyEntry this [int i] {\r
46                         get { return (XsdKeyEntry) List [i]; }\r
47                         set { List [i] = value; }\r
48                 }\r
49         }\r
50 \r
51         // Created per constraining element.\r
52         internal class XsdKeyTable\r
53         {\r
54                 // FIXME: no need after #70419\r
55                 public readonly bool alwaysTrue = true;\r
56 \r
57                 private XsdIdentitySelector selector;\r
58                 private XmlSchemaIdentityConstraint source;\r
59                 private XmlQualifiedName qname;\r
60                 private XmlQualifiedName refKeyName;\r
61 \r
62                 public XsdKeyEntryCollection Entries =\r
63                         new XsdKeyEntryCollection ();\r
64                 public XsdKeyEntryCollection FinishedEntries =\r
65                         new XsdKeyEntryCollection ();\r
66 \r
67                 public int StartDepth;\r
68                 public XsdKeyTable ReferencedKey;\r
69 \r
70                 public XsdKeyTable (XmlSchemaIdentityConstraint source, XmlReader reader)\r
71                 {\r
72                         Reset (source, reader);\r
73                 }\r
74 \r
75                 public XmlQualifiedName QualifiedName {\r
76                         get { return qname; }\r
77                 }\r
78 \r
79                 public XmlQualifiedName RefKeyName {\r
80                         get { return refKeyName; }\r
81                 }\r
82 \r
83                 public XmlSchemaIdentityConstraint SourceSchemaIdentity {\r
84                         get { return source; }\r
85                 }\r
86 \r
87                 public XsdIdentitySelector Selector {\r
88                         get { return selector; }\r
89                 }\r
90 \r
91                 public void Reset (XmlSchemaIdentityConstraint source, XmlReader reader)\r
92                 {\r
93                         this.source = source;\r
94                         this.selector = source.CompiledSelector;\r
95                         this.qname = source.QualifiedName;\r
96                         XmlSchemaKeyref kr = source as XmlSchemaKeyref;\r
97                         if (kr != null)\r
98                                 this.refKeyName = kr.Refer;\r
99                         StartDepth = 0;\r
100                 }\r
101 \r
102                 // In this method, attributes are ignored.\r
103                 public XsdIdentityPath SelectorMatches (ArrayList qnameStack, XmlReader reader)\r
104                 {\r
105                         for (int i = 0; i < Selector.Paths.Length; i++) {\r
106                                 XsdIdentityPath path = Selector.Paths [i];\r
107                                 // Only "." hits.\r
108                                 if (reader.Depth == this.StartDepth) {\r
109                                         if (path.OrderedSteps.Length == 0)\r
110                                                 return path;\r
111                                         else\r
112                                                 continue;\r
113                                 }\r
114                                 // It does not hit as yet (too shallow to hit).\r
115                                 if (reader.Depth - this.StartDepth < path.OrderedSteps.Length - 1)\r
116                                         continue;\r
117 \r
118                                 int iter = path.OrderedSteps.Length;\r
119                                 if (path.OrderedSteps [iter-1].IsAttribute)\r
120                                         iter--;\r
121 \r
122                                 if (path.Descendants && reader.Depth < this.StartDepth + iter)\r
123                                         continue;\r
124                                 else if (!path.Descendants && reader.Depth != this.StartDepth + iter)\r
125                                         continue;\r
126 \r
127                                 iter--;\r
128 \r
129                                 XsdIdentityStep step;\r
130                                 for (int x = 0; 0 <= iter; x++, iter--) {\r
131                                         step = path.OrderedSteps [iter];\r
132                                         if (step.IsAnyName)\r
133                                                 continue;\r
134                                         XmlQualifiedName qname = (XmlQualifiedName) qnameStack [qnameStack.Count - x - 1];\r
135                                         if (step.NsName != null && qname.Namespace == step.NsName)\r
136                                                 continue;\r
137                                         if (step.Name == qname.Name && step.Namespace == qname.Namespace)\r
138                                                 continue;\r
139                                         if (alwaysTrue)\r
140                                                 break;\r
141                                 }\r
142                                 if (iter >= 0)  // i.e. did not match against the path.\r
143                                         continue;\r
144                                 return path;\r
145                         }\r
146                         return null;\r
147                 }\r
148         }\r
149 }\r