merge -r 58060:58217
[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                 
58                 XmlSchemaCollection col;
59                 ValidationEventHandler handler;
60
61                 bool isCompiled;
62
63                 internal Guid CompilationId;
64
65                 public XmlSchemaSet ()
66                         : this (new NameTable ())
67                 {
68                         handler = new ValidationEventHandler (this.OnValidationError);
69                 }
70
71                 public XmlSchemaSet (XmlNameTable nameTable)
72                 {
73                         if (nameTable == null)
74                                 throw new ArgumentNullException ("nameTable");
75
76                         this.nameTable = nameTable;
77                         schemas = new ArrayList ();
78                         CompilationId = Guid.NewGuid ();
79                 }
80
81                 public event ValidationEventHandler ValidationEventHandler;
82
83                 public int Count {
84                         get { return schemas.Count; }
85                 }
86
87                 public XmlSchemaObjectTable GlobalAttributes {
88                         get {
89                                 if (attributes == null)
90                                         attributes = new XmlSchemaObjectTable ();
91                                 return attributes;
92                         }
93                 }
94
95                 public XmlSchemaObjectTable GlobalElements {
96                         get {
97                                 if (elements == null)
98                                         elements = new XmlSchemaObjectTable ();
99                                 return elements;
100                         }
101                 }
102
103                 public XmlSchemaObjectTable GlobalTypes { 
104                         get {
105                                 if (types == null)
106                                         types = new XmlSchemaObjectTable ();
107                                 return types;
108                         }
109                 }
110
111                 public bool IsCompiled { 
112                         get { return isCompiled; }
113                 }
114
115                 public XmlNameTable NameTable { 
116                         get { return nameTable; }
117                 }
118
119                 // This is mainly used for event delegating
120                 internal XmlSchemaCollection SchemaCollection {
121                         get {
122                                 if (col == null) {
123                                         lock (this) {
124                                                 col = new XmlSchemaCollection ();
125                                                 foreach (XmlSchema s in schemas)
126                                                         col.Add (s);
127                                         }
128                                 }
129                                 return col;
130                         }
131                 }
132
133                 public XmlResolver XmlResolver {
134                         set { xmlResolver = value; }
135 #if NET_2_0
136                         internal get { return xmlResolver; }
137 #endif
138                 }
139
140                 public XmlSchema Add (string targetNamespace, string url)
141                 {
142                         targetNamespace = GetSafeNs (targetNamespace);
143                         XmlTextReader r = null;
144                         try {
145                                 r = new XmlTextReader (url, nameTable);
146                                 return Add (targetNamespace, r);
147                         } finally {
148                                 if (r != null)
149                                         r.Close ();
150                         }
151                 }
152
153                 [MonoTODO ("It has weird namespace duplication check that is different from Add(XmlSchema).")]
154                 public XmlSchema Add (string targetNamespace, XmlReader reader)
155                 {
156                         XmlSchema schema = XmlSchema.Read (reader, handler);
157                         if (targetNamespace != null
158                                 && targetNamespace.Length > 0)
159                                 schema.TargetNamespace = targetNamespace;
160                         Add (schema);
161                         return schema;
162                 }
163
164                 [MonoTODO ("Check the exact behavior when namespaces are in conflict (but it would be preferable to wait for 2.0 RTM).")]
165                 public void Add (XmlSchemaSet schemaSet)
166                 {
167                         ArrayList al = new ArrayList ();
168                         foreach (XmlSchema schema in schemaSet.schemas) {
169                                 if (!schemas.Contains (schema))
170                                         al.Add (schema);
171                                 else
172                                         AddGlobalComponents (schema);
173                         }
174                         foreach (XmlSchema schema in al)
175                                 Add (schema);
176                 }
177
178                 [MonoTODO ("We need to research more about the expected behavior")]
179                 public XmlSchema Add (XmlSchema schema)
180                 {
181                         schemas.Add (schema);
182                         AddGlobalComponents (schema);
183                         return schema;
184                 }
185
186                 [MonoTODO ("It should be the actual compilation engine.")]
187                 public void Compile ()
188                 {
189                         ClearGlobalComponents ();
190                         ArrayList al = new ArrayList ();
191                         al.AddRange (schemas);
192                         foreach (XmlSchema schema in al) {
193                                 if (!schema.IsCompiled)
194                                         schema.Compile (handler, this, xmlResolver);
195                                 AddGlobalComponents (schema);
196                         }
197                         isCompiled = true;
198                 }
199
200                 private void ClearGlobalComponents ()
201                 {
202                         GlobalElements.Clear ();
203                         GlobalAttributes.Clear ();
204                         GlobalTypes.Clear ();
205                         // GlobalAttributeGroups.Clear ();
206                         // GlobalGroups.Clear ();
207                 }
208
209                 private void AddGlobalComponents (XmlSchema schema)
210                 {
211                         foreach (XmlSchemaElement el in schema.Elements.Values)
212                                 GlobalElements.Add (el.QualifiedName, el);
213                         foreach (XmlSchemaAttribute a in schema.Attributes.Values)
214                                 GlobalAttributes.Add (a.QualifiedName, a);
215                         foreach (XmlSchemaType t in schema.SchemaTypes.Values)
216                                 GlobalTypes.Add (t.QualifiedName, t);
217                 }
218
219                 public bool Contains (string targetNamespace)
220                 {
221                         targetNamespace = GetSafeNs (targetNamespace);
222                         foreach (XmlSchema schema in schemas)
223                                 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
224                                         return true;
225                         return false;
226                 }
227
228                 public bool Contains (XmlSchema targetNamespace)
229                 {
230                         foreach (XmlSchema schema in schemas)
231                                 if (schema == targetNamespace)
232                                         return true;
233                         return false;
234                 }
235
236                 public void CopyTo (XmlSchema [] array, int index)
237                 {
238                         schemas.CopyTo (array, index);
239                 }
240
241                 internal void CopyTo (Array array, int index)
242                 {
243                         schemas.CopyTo (array, index);
244                 }
245
246                 string GetSafeNs (string ns)
247                 {
248                         return ns == null ? "" : ns;
249                 }
250
251                 internal void OnValidationError (object o, ValidationEventArgs e)
252                 {
253                         if (col != null)
254                                 col.OnValidationError (o, e);
255                         if (ValidationEventHandler != null)
256                                 ValidationEventHandler (o, e);
257                         else if (e.Severity == XmlSeverityType.Error)
258                                 throw e.Exception;
259                 }
260
261                 [MonoTODO ("Check exact behavior")]
262                 public XmlSchema Remove (XmlSchema schema)
263                 {
264                         if (schema == null)
265                                 throw new ArgumentNullException ("schema");
266                         ArrayList al = new ArrayList ();
267                         al.AddRange (schemas);
268                         if (!al.Contains (schema))
269                                 return null;
270                         // FIXME: I have no idea why Remove() might throw
271                         // XmlSchemaException, except for the case it compiles.
272                         if (!schema.IsCompiled)
273                                 schema.Compile (handler, this, xmlResolver);
274                         schemas.Remove (schema);
275                         isCompiled = false;
276                         ClearGlobalComponents ();
277                         return schema;
278                 }
279
280                 [MonoTODO ("Check exact behavior")]
281                 public bool RemoveRecursive (XmlSchema schema)
282                 {
283                         if (schema == null)
284                                 throw new ArgumentNullException ("schema");
285                         ArrayList al = new ArrayList ();
286                         al.AddRange (schemas);
287                         if (!al.Contains (schema))
288                                 return false;
289                         al.Remove (schema);
290                         schemas.Remove (schema);
291                         ClearGlobalComponents ();
292                         foreach (XmlSchema s in al) {
293                                 if (s.IsCompiled)
294                                         AddGlobalComponents (schema);
295                         }
296                         return true;
297                 }
298
299                 public XmlSchema Reprocess (XmlSchema schema)
300                 {
301                         if (schema == null)
302                                 throw new ArgumentNullException ("schema");
303                         ArrayList al = new ArrayList ();
304                         al.AddRange (schemas);
305                         if (!al.Contains (schema))
306                                 throw new ArgumentException ("Target schema is not contained in the schema set.");
307                         ClearGlobalComponents ();
308                         foreach (XmlSchema s in al) {
309                                 if (schema == s)
310                                         schema.Compile (handler, this, xmlResolver);
311                                 if (s.IsCompiled)
312                                         AddGlobalComponents (schema);
313                         }
314                         return schema.IsCompiled ? schema : null;
315                 }
316
317                 public ICollection Schemas ()
318                 {
319                         return schemas;
320                 }
321
322                 [MonoTODO]
323                 public ICollection Schemas (string targetNamespace)
324                 {
325                         targetNamespace = GetSafeNs (targetNamespace);
326                         ArrayList al = new ArrayList ();
327                         foreach (XmlSchema schema in schemas)
328                                 if (GetSafeNs (schema.TargetNamespace) == targetNamespace)
329                                         al.Add (schema);
330                         return al;
331                 }
332
333                 internal bool MissedSubComponents (string targetNamespace)
334                 {
335                         foreach (XmlSchema s in Schemas (targetNamespace))
336                                 if (s.missedSubComponents)
337                                         return true;
338                         return false;
339                 }
340         }
341 }