2006-09-12 Lluis Sanchez Gual <lluis@novell.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;
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 ("Check the exact behavior when namespaces are in conflict (but it would be preferable to wait for 2.0 RTM).")]
174                 public void Add (XmlSchemaSet schemaSet)
175                 {
176                         ArrayList al = new ArrayList ();
177                         foreach (XmlSchema schema in schemaSet.schemas) {
178                                 if (!schemas.Contains (schema))
179                                         al.Add (schema);
180                         }
181                         foreach (XmlSchema schema in al)
182                                 Add (schema);
183                 }
184
185                 public XmlSchema Add (XmlSchema schema)
186                 {
187                         schemas.Add (schema);
188                         ResetCompile ();
189                         return schema;
190                 }
191
192                 [MonoTODO ("It should be the actual compilation engine.")]
193                 public void Compile ()
194                 {
195                         ClearGlobalComponents ();
196                         ArrayList al = new ArrayList ();
197                         al.AddRange (schemas);
198                         IDCollection.Clear ();
199                         NamedIdentities.Clear ();
200
201                         foreach (XmlSchema schema in al)
202                                 if (!schema.IsCompiled)
203                                         schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
204                         foreach (XmlSchema schema in al)
205                                 schema.Validate (ValidationEventHandler);
206
207                         foreach (XmlSchema schema in al)
208                                 AddGlobalComponents (schema);
209
210                         isCompiled = true;
211                 }
212
213                 private void ClearGlobalComponents ()
214                 {
215                         GlobalElements.Clear ();
216                         GlobalAttributes.Clear ();
217                         GlobalTypes.Clear ();
218                         // GlobalAttributeGroups.Clear ();
219                         // GlobalGroups.Clear ();
220                 }
221
222                 private void AddGlobalComponents (XmlSchema schema)
223                 {
224                         foreach (XmlSchemaElement el in schema.Elements.Values)
225                                 GlobalElements.Add (el.QualifiedName, el);
226                         foreach (XmlSchemaAttribute a in schema.Attributes.Values)
227                                 GlobalAttributes.Add (a.QualifiedName, a);
228                         foreach (XmlSchemaType t in schema.SchemaTypes.Values)
229                                 GlobalTypes.Add (t.QualifiedName, t);
230                 }
231
232                 public bool Contains (string targetNamespace)
233                 {
234                         targetNamespace = GetSafeNs (targetNamespace);
235                         foreach (XmlSchema schema in schemas)
236                                 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
237                                         return true;
238                         return false;
239                 }
240
241                 public bool Contains (XmlSchema targetNamespace)
242                 {
243                         foreach (XmlSchema schema in schemas)
244                                 if (schema == targetNamespace)
245                                         return true;
246                         return false;
247                 }
248
249                 public void CopyTo (XmlSchema [] array, int index)
250                 {
251                         schemas.CopyTo (array, index);
252                 }
253
254                 internal void CopyTo (Array array, int index)
255                 {
256                         schemas.CopyTo (array, index);
257                 }
258
259                 string GetSafeNs (string ns)
260                 {
261                         return ns == null ? "" : ns;
262                 }
263
264                 [MonoTODO ("Check exact behavior")]
265                 public XmlSchema Remove (XmlSchema schema)
266                 {
267                         if (schema == null)
268                                 throw new ArgumentNullException ("schema");
269                         ArrayList al = new ArrayList ();
270                         al.AddRange (schemas);
271                         if (!al.Contains (schema))
272                                 return null;
273                         // FIXME: I have no idea why Remove() might throw
274                         // XmlSchemaException, except for the case it compiles.
275                         if (!schema.IsCompiled)
276                                 schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
277                         schemas.Remove (schema);
278                         ResetCompile ();
279                         return schema;
280                 }
281
282                 void ResetCompile ()
283                 {
284                         isCompiled = false;
285                         ClearGlobalComponents ();
286                 }
287
288                 public bool RemoveRecursive (XmlSchema schema)
289                 {
290                         if (schema == null)
291                                 throw new ArgumentNullException ("schema");
292                         ArrayList al = new ArrayList ();
293                         al.AddRange (schemas);
294                         if (!al.Contains (schema))
295                                 return false;
296                         al.Remove (schema);
297                         schemas.Remove (schema);
298
299                         if (!IsCompiled)
300                                 return true;
301
302                         ClearGlobalComponents ();
303                         foreach (XmlSchema s in al) {
304                                 if (s.IsCompiled)
305                                         AddGlobalComponents (schema);
306                         }
307                         return true;
308                 }
309
310                 public XmlSchema Reprocess (XmlSchema schema)
311                 {
312                         if (schema == null)
313                                 throw new ArgumentNullException ("schema");
314                         ArrayList al = new ArrayList ();
315                         al.AddRange (schemas);
316                         if (!al.Contains (schema))
317                                 throw new ArgumentException ("Target schema is not contained in the schema set.");
318                         ClearGlobalComponents ();
319                         foreach (XmlSchema s in al) {
320                                 if (schema == s)
321                                         schema.CompileSubset (ValidationEventHandler, this, xmlResolver);
322                                 if (s.IsCompiled)
323                                         AddGlobalComponents (schema);
324                         }
325                         return schema.IsCompiled ? schema : null;
326                 }
327
328                 public ICollection Schemas ()
329                 {
330                         return schemas;
331                 }
332
333                 [MonoTODO]
334                 public ICollection Schemas (string targetNamespace)
335                 {
336                         targetNamespace = GetSafeNs (targetNamespace);
337                         ArrayList al = new ArrayList ();
338                         foreach (XmlSchema schema in schemas)
339                                 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
340                                         al.Add (schema);
341                         return al;
342                 }
343
344                 internal bool MissedSubComponents (string targetNamespace)
345                 {
346                         foreach (XmlSchema s in Schemas (targetNamespace))
347                                 if (s.missedSubComponents)
348                                         return true;
349                         return false;
350                 }
351         }
352 }