Wed Feb 24 15:47:16 CET 2010 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaSet.cs
1 //
2 // XmlSchemaSet.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
6 //
7 // (C)2003 Atsushi Enomoto
8 // (C)2004 Novell Inc.
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 using System;
32 using System.Collections;
33 using System.Collections.Specialized;
34 using System.ComponentModel;
35 using System.IO;
36 using System.Security.Policy;
37 using System.Xml.Schema;
38 using System.Xml.XPath;
39
40 namespace System.Xml.Schema
41 {
42 #if NET_2_0
43         public class XmlSchemaSet
44 #else
45         internal sealed class XmlSchemaSet
46 #endif
47         {
48                 XmlNameTable nameTable;
49                 XmlResolver xmlResolver = new XmlUrlResolver ();
50
51                 ArrayList schemas;
52                 XmlSchemaObjectTable attributes;
53                 XmlSchemaObjectTable elements;
54                 XmlSchemaObjectTable types;
55 //              XmlSchemaObjectTable attributeGroups;
56 //              XmlSchemaObjectTable groups;
57                 Hashtable idCollection;
58                 XmlSchemaObjectTable namedIdentities;
59
60                 XmlSchemaCompilationSettings settings =
61                         new XmlSchemaCompilationSettings ();
62
63                 bool isCompiled;
64
65                 internal Guid CompilationId;
66
67                 public XmlSchemaSet ()
68                         : this (new NameTable ())
69                 {
70                 }
71
72                 public XmlSchemaSet (XmlNameTable nameTable)
73                 {
74                         if (nameTable == null)
75                                 throw new ArgumentNullException ("nameTable");
76
77                         this.nameTable = nameTable;
78                         schemas = new ArrayList ();
79                         CompilationId = Guid.NewGuid ();
80                 }
81
82                 public event ValidationEventHandler ValidationEventHandler;
83
84                 public int Count {
85                         get { return schemas.Count; }
86                 }
87
88                 public XmlSchemaObjectTable GlobalAttributes {
89                         get {
90                                 if (attributes == null)
91                                         attributes = new XmlSchemaObjectTable ();
92                                 return attributes;
93                         }
94                 }
95
96                 public XmlSchemaObjectTable GlobalElements {
97                         get {
98                                 if (elements == null)
99                                         elements = new XmlSchemaObjectTable ();
100                                 return elements;
101                         }
102                 }
103
104                 public XmlSchemaObjectTable GlobalTypes { 
105                         get {
106                                 if (types == null)
107                                         types = new XmlSchemaObjectTable ();
108                                 return types;
109                         }
110                 }
111
112                 public bool IsCompiled { 
113                         get { return isCompiled; }
114                 }
115
116                 public XmlNameTable NameTable { 
117                         get { return nameTable; }
118                 }
119
120                 public XmlSchemaCompilationSettings CompilationSettings {
121                         get { return settings; }
122                         set { settings = value; }
123                 }
124
125                 public XmlResolver XmlResolver {
126                         set { xmlResolver = value; }
127 #if NET_2_0
128                         internal get { return xmlResolver; }
129 #else
130                         get { return xmlResolver; }
131 #endif
132                 }
133
134                 internal Hashtable IDCollection {
135                         get {
136                                 if (idCollection == null)
137                                         idCollection = new Hashtable ();
138                                 return idCollection;
139                         }
140                 }
141
142                 internal XmlSchemaObjectTable NamedIdentities {
143                         get {
144                                 if (namedIdentities == null)
145                                         namedIdentities = new XmlSchemaObjectTable();
146                                 return namedIdentities;
147                         }
148                 }
149
150                 public XmlSchema Add (string targetNamespace, string url)
151                 {
152                         XmlTextReader r = null;
153                         try {
154                                 r = new XmlTextReader (url, nameTable);
155                                 return Add (targetNamespace, r);
156                         } finally {
157                                 if (r != null)
158                                         r.Close ();
159                         }
160                 }
161
162                 public XmlSchema Add (string targetNamespace, XmlReader reader)
163                 {
164                         XmlSchema schema = XmlSchema.Read (reader, ValidationEventHandler);
165                         if (schema.TargetNamespace == null)
166                                 schema.TargetNamespace = targetNamespace == String.Empty ? null : targetNamespace; // this weirdness is due to bug #571660.
167                         else if (targetNamespace != null && schema.TargetNamespace != targetNamespace)
168                                 throw new XmlSchemaException ("The actual targetNamespace in the schema does not match the parameter.");
169                         Add (schema);
170                         return schema;
171                 }
172
173                 [MonoTODO]
174                 // FIXME: Check the exact behavior when namespaces are in conflict (but it would be preferable to wait for 2.0 RTM)
175                 public void Add (XmlSchemaSet schemaSet)
176                 {
177                         ArrayList al = new ArrayList ();
178                         foreach (XmlSchema schema in schemaSet.schemas) {
179                                 if (!schemas.Contains (schema))
180                                         al.Add (schema);
181                         }
182                         foreach (XmlSchema schema in al)
183                                 Add (schema);
184                 }
185
186                 public XmlSchema Add (XmlSchema schema)
187                 {
188                         schemas.Add (schema);
189                         ResetCompile ();
190                         return schema;
191                 }
192
193                 // FIXME: It should be the actual compilation engine.
194                 public void Compile ()
195                 {
196                         ClearGlobalComponents ();
197                         ArrayList al = new ArrayList ();
198                         al.AddRange (schemas);
199                         IDCollection.Clear ();
200                         NamedIdentities.Clear ();
201
202                         Hashtable handledUris = new Hashtable ();
203                         foreach (XmlSchema schema in al)
204                                 if (!schema.IsCompiled)
205                                         schema.CompileSubset (ValidationEventHandler, this, xmlResolver, handledUris);
206
207                         // Process substitutionGroup first, as this process
208                         // involves both substituted and substituting elements
209                         // and hence it needs to be done before actual
210                         // validation (by current design of conformance checker).
211                         foreach (XmlSchema schema in al)
212                                 foreach (XmlSchemaElement elem in schema.Elements.Values)
213                                         elem.FillSubstitutionElementInfo ();
214
215
216                         foreach (XmlSchema schema in al)
217                                 schema.Validate (ValidationEventHandler);
218
219                         foreach (XmlSchema schema in al)
220                                 AddGlobalComponents (schema);
221
222                         isCompiled = true;
223                 }
224
225                 private void ClearGlobalComponents ()
226                 {
227                         GlobalElements.Clear ();
228                         GlobalAttributes.Clear ();
229                         GlobalTypes.Clear ();
230                         // GlobalAttributeGroups.Clear ();
231                         // GlobalGroups.Clear ();
232                 }
233
234                 private void AddGlobalComponents (XmlSchema schema)
235                 {
236                         foreach (XmlSchemaElement el in schema.Elements.Values)
237                                 GlobalElements.Add (el.QualifiedName, el);
238                         foreach (XmlSchemaAttribute a in schema.Attributes.Values)
239                                 GlobalAttributes.Add (a.QualifiedName, a);
240                         foreach (XmlSchemaType t in schema.SchemaTypes.Values)
241                                 GlobalTypes.Add (t.QualifiedName, t);
242                 }
243
244                 public bool Contains (string targetNamespace)
245                 {
246                         targetNamespace = GetSafeNs (targetNamespace);
247                         foreach (XmlSchema schema in schemas)
248                                 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
249                                         return true;
250                         return false;
251                 }
252
253                 public bool Contains (XmlSchema targetNamespace)
254                 {
255                         foreach (XmlSchema schema in schemas)
256                                 if (schema == targetNamespace)
257                                         return true;
258                         return false;
259                 }
260
261                 public void CopyTo (XmlSchema [] array, int index)
262                 {
263                         schemas.CopyTo (array, index);
264                 }
265
266                 internal void CopyTo (Array array, int index)
267                 {
268                         schemas.CopyTo (array, index);
269                 }
270
271                 string GetSafeNs (string ns)
272                 {
273                         return ns == null ? "" : ns;
274                 }
275
276                 [MonoTODO]
277                 // FIXME: Check exact behavior
278                 public XmlSchema Remove (XmlSchema schema)
279                 {
280                         if (schema == null)
281                                 throw new ArgumentNullException ("schema");
282                         ArrayList al = new ArrayList ();
283                         al.AddRange (schemas);
284                         if (!al.Contains (schema))
285                                 return null;
286                         // FIXME: I have no idea why Remove() might throw
287                         // XmlSchemaException, except for the case it compiles.
288                         if (!schema.IsCompiled)
289                                 schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
290                         schemas.Remove (schema);
291                         ResetCompile ();
292                         return schema;
293                 }
294
295                 void ResetCompile ()
296                 {
297                         isCompiled = false;
298                         ClearGlobalComponents ();
299                 }
300
301                 public bool RemoveRecursive (XmlSchema schema)
302                 {
303                         if (schema == null)
304                                 throw new ArgumentNullException ("schema");
305                         ArrayList al = new ArrayList ();
306                         al.AddRange (schemas);
307                         if (!al.Contains (schema))
308                                 return false;
309                         al.Remove (schema);
310                         schemas.Remove (schema);
311
312                         if (!IsCompiled)
313                                 return true;
314
315                         ClearGlobalComponents ();
316                         foreach (XmlSchema s in al) {
317                                 if (s.IsCompiled)
318                                         AddGlobalComponents (schema);
319                         }
320                         return true;
321                 }
322
323                 public XmlSchema Reprocess (XmlSchema schema)
324                 {
325                         if (schema == null)
326                                 throw new ArgumentNullException ("schema");
327                         ArrayList al = new ArrayList ();
328                         al.AddRange (schemas);
329                         if (!al.Contains (schema))
330                                 throw new ArgumentException ("Target schema is not contained in the schema set.");
331                         ClearGlobalComponents ();
332                         foreach (XmlSchema s in al) {
333                                 if (schema == s)
334                                         schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
335                                 if (s.IsCompiled)
336                                         AddGlobalComponents (schema);
337                         }
338                         return schema.IsCompiled ? schema : null;
339                 }
340
341                 public ICollection Schemas ()
342                 {
343                         return schemas;
344                 }
345
346                 public ICollection Schemas (string targetNamespace)
347                 {
348                         targetNamespace = GetSafeNs (targetNamespace);
349                         ArrayList al = new ArrayList ();
350                         foreach (XmlSchema schema in schemas)
351                                 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
352                                         al.Add (schema);
353                         return al;
354                 }
355
356                 internal bool MissedSubComponents (string targetNamespace)
357                 {
358                         foreach (XmlSchema s in Schemas (targetNamespace))
359                                 if (s.missedSubComponents)
360                                         return true;
361                         return false;
362                 }
363         }
364 }