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