Merge branch 'master' of http://github.com/mono/mono
[mono.git] / mcs / class / System.XML / Mono.Xml.Schema / XsdWildcard.cs
1 //\r
2 // Mono.Xml.Schema.XsdWildcard.cs\r
3 //\r
4 // Author:\r
5 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)\r
6 //\r
7 //      (C)2003 Atsushi Enomoto\r
8 //\r
9 //\r
10 // This class represents common part of xs:any and xs:anyAttribute\r
11 //\r
12 //\r
13 \r
14 //\r
15 // Permission is hereby granted, free of charge, to any person obtaining\r
16 // a copy of this software and associated documentation files (the\r
17 // "Software"), to deal in the Software without restriction, including\r
18 // without limitation the rights to use, copy, modify, merge, publish,\r
19 // distribute, sublicense, and/or sell copies of the Software, and to\r
20 // permit persons to whom the Software is furnished to do so, subject to\r
21 // the following conditions:\r
22 // \r
23 // The above copyright notice and this permission notice shall be\r
24 // included in all copies or substantial portions of the Software.\r
25 // \r
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
33 //\r
34 using System;\r
35 using System.Collections.Specialized;\r
36 using System.Xml;\r
37 using System.Xml.Schema;\r
38 \r
39 namespace Mono.Xml.Schema\r
40 {\r
41         internal class XsdWildcard\r
42         {\r
43                 public XsdWildcard (XmlSchemaObject wildcard)\r
44                 {\r
45                         xsobj = wildcard;\r
46                 }\r
47 \r
48                 private XmlSchemaObject xsobj;\r
49 \r
50                 public XmlSchemaContentProcessing ResolvedProcessing;\r
51                 public string TargetNamespace;\r
52                 public bool SkipCompile;\r
53                 public bool HasValueAny;\r
54                 public bool HasValueLocal;\r
55                 public bool HasValueOther;\r
56                 public bool HasValueTargetNamespace;\r
57                 public StringCollection ResolvedNamespaces;\r
58 \r
59                 void Reset ()\r
60                 {\r
61                         HasValueAny = false;\r
62                         HasValueLocal = false;\r
63                         HasValueOther = false;\r
64                         HasValueTargetNamespace = false;\r
65                         ResolvedNamespaces = new StringCollection ();\r
66                 }\r
67 \r
68                 public void Compile (string nss,\r
69                         ValidationEventHandler h, XmlSchema schema)\r
70                 {\r
71                         if (SkipCompile)\r
72                                 return; // used by XmlSchemaAny.AnyTypeContent.\r
73 \r
74                         Reset ();\r
75                         int nscount = 0;\r
76                         string actualNamespace = nss == null ? "##any" : nss;\r
77                         string[] nslist = XmlSchemaUtil.SplitList(actualNamespace);\r
78                         for (int i = 0; i < nslist.Length; i++) {\r
79                                 string ns = nslist [i];\r
80                                 switch(ns) {\r
81                                 case "##any": \r
82                                         if (HasValueAny)\r
83                                                 xsobj.error (h, "Multiple specification of ##any was found.");\r
84                                         nscount |= 1;\r
85                                         HasValueAny = true;\r
86                                         break;\r
87                                 case "##other":\r
88                                         if (HasValueOther)\r
89                                                 xsobj.error (h, "Multiple specification of ##other was found.");\r
90                                         nscount |= 2;\r
91                                         HasValueOther = true;\r
92                                         break;\r
93                                 case "##targetNamespace":\r
94                                         if (HasValueTargetNamespace)\r
95                                                 xsobj.error (h, "Multiple specification of ##targetNamespace was found.");\r
96                                         nscount |= 4;\r
97                                         HasValueTargetNamespace = true;\r
98                                         break;\r
99                                 case "##local":\r
100                                         if (HasValueLocal)\r
101                                                 xsobj.error (h, "Multiple specification of ##local was found.");\r
102                                         nscount |= 8;\r
103                                         HasValueLocal = true;\r
104                                         break;\r
105                                 default:\r
106                                         if(!XmlSchemaUtil.CheckAnyUri(ns))\r
107                                                 xsobj.error(h,"the namespace is not a valid anyURI");\r
108                                         else if (ResolvedNamespaces.Contains (ns))\r
109                                                 xsobj.error (h, "Multiple specification of '" + ns + "' was found.");\r
110                                         else {\r
111                                                 nscount |= 16;\r
112                                                 ResolvedNamespaces.Add (ns);\r
113                                         }\r
114                                         break;\r
115                                 }\r
116                         }\r
117                         if((nscount&1) == 1 && nscount != 1)\r
118                                 xsobj.error (h, "##any if present must be the only namespace attribute");\r
119                         if((nscount&2) == 2 && nscount != 2)\r
120                                 xsobj.error (h, "##other if present must be the only namespace attribute");\r
121                 }\r
122 \r
123                 // 3.8.6. Attribute Wildcard Intersection\r
124                 // Only try to examine if their intersection is expressible, and\r
125                 // returns true if the result is empty.\r
126                 public bool ExamineAttributeWildcardIntersection (XmlSchemaAny other,\r
127                         ValidationEventHandler h, XmlSchema schema)\r
128                 {\r
129                         // 1.\r
130                         if (this.HasValueAny == other.HasValueAny &&\r
131                                 this.HasValueLocal == other.HasValueLocal &&\r
132                                 this.HasValueOther == other.HasValueOther &&\r
133                                 this.HasValueTargetNamespace == other.HasValueTargetNamespace &&\r
134                                 this.ResolvedProcessing == other.ResolvedProcessContents) {\r
135                                 bool notEqual = false;\r
136                                 for (int i = 0; i < this.ResolvedNamespaces.Count; i++) {\r
137                                         if (!other.ResolvedNamespaces.Contains (this.ResolvedNamespaces [i]))\r
138                                                 notEqual = true;\r
139                                 }\r
140                                 if (!notEqual)\r
141                                         return false;\r
142                         }\r
143                         // 2.\r
144                         if (this.HasValueAny)\r
145                                 return !other.HasValueAny &&\r
146                                         !other.HasValueLocal &&\r
147                                         !other.HasValueOther &&\r
148                                         !other.HasValueTargetNamespace &&\r
149                                         other.ResolvedNamespaces.Count == 0;\r
150                         if (other.HasValueAny)\r
151                                 return !this.HasValueAny &&\r
152                                         !this.HasValueLocal &&\r
153                                         !this.HasValueOther &&\r
154                                         !this.HasValueTargetNamespace &&\r
155                                         this.ResolvedNamespaces.Count == 0;\r
156                         // 5.\r
157                         if (this.HasValueOther && other.HasValueOther && this.TargetNamespace != other.TargetNamespace) {\r
158 //                              xsobj.error (h, "The Wildcard intersection is not expressible.");\r
159                                 return false;\r
160                         }\r
161                         // 3.\r
162                         if (this.HasValueOther) {\r
163                                 if (other.HasValueLocal && this.TargetNamespace != String.Empty)\r
164                                         return false;\r
165                                 if (other.HasValueTargetNamespace && this.TargetNamespace != other.TargetNamespace)\r
166                                         return false;\r
167                                 return other.ValidateWildcardAllowsNamespaceName (this.TargetNamespace, h, schema, false);\r
168                         }\r
169                         if (other.HasValueOther) {\r
170                                 if (this.HasValueLocal && other.TargetNamespace != String.Empty)\r
171                                         return false;\r
172                                 if (this.HasValueTargetNamespace && other.TargetNamespace != this.TargetNamespace)\r
173                                         return false;\r
174                                 return this.ValidateWildcardAllowsNamespaceName (other.TargetNamespace, h, schema, false);\r
175                         }\r
176                         // 4.\r
177                         if (this.ResolvedNamespaces.Count > 0) {\r
178                                 for (int i = 0; i < this.ResolvedNamespaces.Count; i++)\r
179                                         if (other.ResolvedNamespaces.Contains (this.ResolvedNamespaces [i]))\r
180                                                 return false;\r
181                         }\r
182                         return true;\r
183                 }\r
184 \r
185                 // 3.10.4 Wildcard Allows Namespace Name. (In fact it is almost copy...)\r
186                 public bool ValidateWildcardAllowsNamespaceName (string ns,\r
187                         ValidationEventHandler h, XmlSchema schema, bool raiseError)\r
188                 {\r
189                         if (HasValueAny)\r
190                                 return true;\r
191                         if (HasValueOther && ns != TargetNamespace)\r
192                                 return true;\r
193                         if (HasValueTargetNamespace && ns == TargetNamespace)\r
194                                 return true;\r
195                         if (HasValueLocal && ns == "")\r
196                                 return true;\r
197                         for (int i = 0; i < ResolvedNamespaces.Count; i++)\r
198                                 if (ns == ResolvedNamespaces [i])\r
199                                         return true;\r
200                         if (raiseError)\r
201                                 xsobj.error (h, "This wildcard does not allow the namespace: " + ns);\r
202                         return false;\r
203                 }\r
204 \r
205                 // 3.10.6 Wildcard Subset\r
206                 // Other = wider. this = restricted subset\r
207                 internal void ValidateWildcardSubset (XsdWildcard other,\r
208                         ValidationEventHandler h, XmlSchema schema)\r
209                 {\r
210                         ValidateWildcardSubset (other, h, schema, true);\r
211                 }\r
212 \r
213                 internal bool ValidateWildcardSubset (XsdWildcard other,\r
214                         ValidationEventHandler h, XmlSchema schema, bool raiseError)\r
215                 {\r
216                         // 1.\r
217                         if (other.HasValueAny)\r
218                                 return true;\r
219                         // 2.\r
220                         if (HasValueOther && other.HasValueOther) {\r
221                                 // 2.1 and 2.2\r
222                                 if (TargetNamespace == other.TargetNamespace ||\r
223                                         other.TargetNamespace == null || other.TargetNamespace == "")\r
224                                         return true;\r
225                         }\r
226                         // 3.1. (not)\r
227                         if (this.HasValueAny) {\r
228                                 if (raiseError)\r
229                                         xsobj.error (h, "Invalid wildcard subset was found.");\r
230                                 return false;\r
231                         }\r
232                         // 3.2\r
233                         if (other.HasValueOther) {\r
234                                 // 3.2.2\r
235                                 if ( (this.HasValueTargetNamespace && other.TargetNamespace == this.TargetNamespace) ||\r
236                                         (this.HasValueLocal && (other.TargetNamespace == null || other.TargetNamespace.Length == 0)) ) {\r
237                                         if (raiseError)\r
238                                                 xsobj.error (h, "Invalid wildcard subset was found.");\r
239                                         return false;\r
240                                 } else {\r
241                                         for (int i = 0; i < ResolvedNamespaces.Count; i++) {\r
242                                                 if (ResolvedNamespaces [i] == other.TargetNamespace) {\r
243                                                         if (raiseError)\r
244                                                                 xsobj.error (h, "Invalid wildcard subset was found.");\r
245                                                         return false;\r
246                                                 }\r
247                                         }\r
248                                 }\r
249                         } else {\r
250                                 // 3.2.1\r
251                                 if ((this.HasValueLocal && !other.HasValueLocal) ||\r
252                                         this.HasValueTargetNamespace && !other.HasValueTargetNamespace) {\r
253                                         if (raiseError)\r
254                                                 xsobj.error (h, "Invalid wildcard subset was found.");\r
255                                         return false;\r
256                                 } else if (this.HasValueOther) {\r
257                                         if (raiseError)\r
258                                                 xsobj.error (h, "Invalid wildcard subset was found.");\r
259                                         return false;\r
260                                 } else {\r
261                                         for (int i = 0; i < this.ResolvedNamespaces.Count; i++)\r
262                                                 if (!other.ResolvedNamespaces.Contains (this.ResolvedNamespaces [i])) {\r
263                                                         if (raiseError)\r
264                                                                 xsobj.error (h, "Invalid wildcard subset was found.");\r
265                                                         return false;\r
266                                                 }\r
267                                 }\r
268                         }\r
269                         return true;\r
270                 }\r
271         }\r
272 }\r