2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.XML / System.Xml.Schema / XmlSchemaSet.cs
blobc304f4cb17322a1280e6093efb6b77109a9703ad
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 //
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.
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;
40 namespace System.Xml.Schema
42 #if NET_2_0
43 public class XmlSchemaSet
44 #else
45 internal sealed class XmlSchemaSet
46 #endif
48 XmlNameTable nameTable;
49 XmlResolver xmlResolver = new XmlUrlResolver ();
51 ArrayList schemas;
52 XmlSchemaObjectTable attributes;
53 XmlSchemaObjectTable elements;
54 XmlSchemaObjectTable types;
55 // XmlSchemaObjectTable attributeGroups;
56 // XmlSchemaObjectTable groups;
57 Hashtable idCollection;
58 XmlSchemaObjectTable namedIdentities;
60 XmlSchemaCompilationSettings settings =
61 new XmlSchemaCompilationSettings ();
63 bool isCompiled;
65 internal Guid CompilationId;
67 public XmlSchemaSet ()
68 : this (new NameTable ())
72 public XmlSchemaSet (XmlNameTable nameTable)
74 if (nameTable == null)
75 throw new ArgumentNullException ("nameTable");
77 this.nameTable = nameTable;
78 schemas = new ArrayList ();
79 CompilationId = Guid.NewGuid ();
82 public event ValidationEventHandler ValidationEventHandler;
84 public int Count {
85 get { return schemas.Count; }
88 public XmlSchemaObjectTable GlobalAttributes {
89 get {
90 if (attributes == null)
91 attributes = new XmlSchemaObjectTable ();
92 return attributes;
96 public XmlSchemaObjectTable GlobalElements {
97 get {
98 if (elements == null)
99 elements = new XmlSchemaObjectTable ();
100 return elements;
104 public XmlSchemaObjectTable GlobalTypes {
105 get {
106 if (types == null)
107 types = new XmlSchemaObjectTable ();
108 return types;
112 public bool IsCompiled {
113 get { return isCompiled; }
116 public XmlNameTable NameTable {
117 get { return nameTable; }
120 public XmlSchemaCompilationSettings CompilationSettings {
121 get { return settings; }
122 set { settings = value; }
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
134 internal Hashtable IDCollection {
135 get {
136 if (idCollection == null)
137 idCollection = new Hashtable ();
138 return idCollection;
142 internal XmlSchemaObjectTable NamedIdentities {
143 get {
144 if (namedIdentities == null)
145 namedIdentities = new XmlSchemaObjectTable();
146 return namedIdentities;
150 public XmlSchema Add (string targetNamespace, string url)
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 ();
162 public XmlSchema Add (string targetNamespace, XmlReader reader)
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;
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)
177 ArrayList al = new ArrayList ();
178 foreach (XmlSchema schema in schemaSet.schemas) {
179 if (!schemas.Contains (schema))
180 al.Add (schema);
182 foreach (XmlSchema schema in al)
183 Add (schema);
186 public XmlSchema Add (XmlSchema schema)
188 schemas.Add (schema);
189 ResetCompile ();
190 return schema;
193 // FIXME: It should be the actual compilation engine.
194 public void Compile ()
196 ClearGlobalComponents ();
197 ArrayList al = new ArrayList ();
198 al.AddRange (schemas);
199 IDCollection.Clear ();
200 NamedIdentities.Clear ();
202 Hashtable handledUris = new Hashtable ();
203 foreach (XmlSchema schema in al)
204 if (!schema.IsCompiled)
205 schema.CompileSubset (ValidationEventHandler, this, xmlResolver, handledUris);
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 ();
216 foreach (XmlSchema schema in al)
217 schema.Validate (ValidationEventHandler);
219 foreach (XmlSchema schema in al)
220 AddGlobalComponents (schema);
222 isCompiled = true;
225 private void ClearGlobalComponents ()
227 GlobalElements.Clear ();
228 GlobalAttributes.Clear ();
229 GlobalTypes.Clear ();
230 // GlobalAttributeGroups.Clear ();
231 // GlobalGroups.Clear ();
234 private void AddGlobalComponents (XmlSchema schema)
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);
244 public bool Contains (string targetNamespace)
246 targetNamespace = GetSafeNs (targetNamespace);
247 foreach (XmlSchema schema in schemas)
248 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
249 return true;
250 return false;
253 public bool Contains (XmlSchema targetNamespace)
255 foreach (XmlSchema schema in schemas)
256 if (schema == targetNamespace)
257 return true;
258 return false;
261 public void CopyTo (XmlSchema [] array, int index)
263 schemas.CopyTo (array, index);
266 internal void CopyTo (Array array, int index)
268 schemas.CopyTo (array, index);
271 string GetSafeNs (string ns)
273 return ns == null ? "" : ns;
276 [MonoTODO]
277 // FIXME: Check exact behavior
278 public XmlSchema Remove (XmlSchema schema)
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;
295 void ResetCompile ()
297 isCompiled = false;
298 ClearGlobalComponents ();
301 public bool RemoveRecursive (XmlSchema schema)
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);
312 if (!IsCompiled)
313 return true;
315 ClearGlobalComponents ();
316 foreach (XmlSchema s in al) {
317 if (s.IsCompiled)
318 AddGlobalComponents (schema);
320 return true;
323 public XmlSchema Reprocess (XmlSchema schema)
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);
338 return schema.IsCompiled ? schema : null;
341 public ICollection Schemas ()
343 return schemas;
346 public ICollection Schemas (string targetNamespace)
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;
356 internal bool MissedSubComponents (string targetNamespace)
358 foreach (XmlSchema s in Schemas (targetNamespace))
359 if (s.missedSubComponents)
360 return true;
361 return false;