Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / Schema / SchemaInfo.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="SchemaInfo.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>  
5 // <owner current="true" primary="true">[....]</owner>                                                              
6 //------------------------------------------------------------------------------
7
8 using System;
9 using System.Xml;
10 using System.Diagnostics;
11 using System.Collections.Generic;
12     
13 namespace System.Xml.Schema {
14
15 #if !SILVERLIGHT
16     internal enum AttributeMatchState {
17         AttributeFound,
18         AnyIdAttributeFound,
19         UndeclaredElementAndAttribute,
20         UndeclaredAttribute,
21         AnyAttributeLax,
22         AnyAttributeSkip,
23         ProhibitedAnyAttribute,
24         ProhibitedAttribute,
25         AttributeNameMismatch,
26         ValidateAttributeInvalidCall,
27     }
28 #endif
29
30     internal class SchemaInfo : IDtdInfo {
31         Dictionary<XmlQualifiedName, SchemaElementDecl> elementDecls = new Dictionary<XmlQualifiedName, SchemaElementDecl>();
32         Dictionary<XmlQualifiedName, SchemaElementDecl> undeclaredElementDecls = new Dictionary<XmlQualifiedName, SchemaElementDecl>();
33
34         Dictionary<XmlQualifiedName, SchemaEntity> generalEntities;
35         Dictionary<XmlQualifiedName, SchemaEntity> parameterEntities;
36
37         XmlQualifiedName docTypeName = XmlQualifiedName.Empty;
38         string internalDtdSubset = string.Empty;
39         bool hasNonCDataAttributes = false;
40         bool hasDefaultAttributes = false;
41
42 #if !SILVERLIGHT
43         Dictionary<string, bool> targetNamespaces = new Dictionary<string, bool>();
44         Dictionary<XmlQualifiedName, SchemaAttDef> attributeDecls = new Dictionary<XmlQualifiedName, SchemaAttDef>();
45         int errorCount;
46         SchemaType schemaType;
47         Dictionary<XmlQualifiedName, SchemaElementDecl> elementDeclsByType = new Dictionary<XmlQualifiedName, SchemaElementDecl>();
48         Dictionary<string, SchemaNotation> notations;
49 #endif
50
51
52         internal SchemaInfo() {
53 #if !SILVERLIGHT
54             schemaType = SchemaType.None;
55 #endif
56         }
57
58         public XmlQualifiedName DocTypeName {
59             get { return docTypeName; }
60             set { docTypeName = value; }
61         }
62
63         internal string InternalDtdSubset {
64             get { return internalDtdSubset; }
65             set { internalDtdSubset = value; }
66         }
67
68         internal Dictionary<XmlQualifiedName, SchemaElementDecl> ElementDecls {
69             get { return elementDecls; }
70         }
71
72         internal Dictionary<XmlQualifiedName, SchemaElementDecl> UndeclaredElementDecls {
73             get { return undeclaredElementDecls; }
74         }
75
76         internal Dictionary<XmlQualifiedName, SchemaEntity> GeneralEntities {
77             get {
78                 if (this.generalEntities == null) {
79                     this.generalEntities = new Dictionary<XmlQualifiedName, SchemaEntity>();
80                 }
81                 return this.generalEntities;
82             }
83         }
84
85         internal Dictionary<XmlQualifiedName, SchemaEntity> ParameterEntities {
86             get {
87                 if (this.parameterEntities == null) {
88                     this.parameterEntities = new Dictionary<XmlQualifiedName, SchemaEntity>();
89                 }
90                 return this.parameterEntities;
91             }
92         }
93
94 #if !SILVERLIGHT
95         internal SchemaType SchemaType {
96             get { return schemaType;}
97             set { schemaType = value;}
98         }
99
100         internal Dictionary<string, bool> TargetNamespaces {
101             get { return targetNamespaces; }
102         }
103
104         internal Dictionary<XmlQualifiedName, SchemaElementDecl> ElementDeclsByType {
105             get { return elementDeclsByType; }
106         }
107
108         internal Dictionary<XmlQualifiedName, SchemaAttDef> AttributeDecls {
109             get { return attributeDecls; }
110         }
111
112         internal Dictionary<string, SchemaNotation> Notations {
113             get {
114                 if (this.notations == null) {
115                     this.notations = new Dictionary<string, SchemaNotation>();
116                 }
117                 return this.notations; 
118             }
119         }
120
121         internal int ErrorCount {
122             get { return errorCount; }
123             set { errorCount = value; }
124         }
125
126         internal SchemaElementDecl GetElementDecl(XmlQualifiedName qname) {
127             SchemaElementDecl elemDecl;
128             if (elementDecls.TryGetValue(qname, out elemDecl)) {
129                 return elemDecl;
130             }
131             return null;
132         }
133         
134         internal SchemaElementDecl GetTypeDecl(XmlQualifiedName qname) {
135             SchemaElementDecl elemDecl;
136             if (elementDeclsByType.TryGetValue(qname, out elemDecl)) {
137                 return elemDecl;
138             }
139             return null;
140         }
141
142         
143         internal XmlSchemaElement GetElement(XmlQualifiedName qname) {
144             SchemaElementDecl ed = GetElementDecl(qname);
145             if (ed != null) {
146                 return ed.SchemaElement;
147             }
148             return null;
149         }
150         
151         internal XmlSchemaAttribute GetAttribute(XmlQualifiedName qname) {
152             SchemaAttDef attdef = (SchemaAttDef)attributeDecls[qname];
153             if (attdef != null) {
154                 return attdef.SchemaAttribute;
155             }
156             return null;
157         }
158         
159         internal XmlSchemaElement GetType(XmlQualifiedName qname) {
160             SchemaElementDecl ed = GetElementDecl(qname);
161             if (ed != null) {
162                 return ed.SchemaElement;
163             }
164             return null;
165         }
166
167         internal bool HasSchema(string ns) {
168             return targetNamespaces.ContainsKey(ns);
169         }
170         
171         internal bool Contains(string ns) {
172             return targetNamespaces.ContainsKey(ns);
173         }
174
175         internal SchemaAttDef GetAttributeXdr(SchemaElementDecl ed, XmlQualifiedName qname) {
176             SchemaAttDef attdef = null;
177             if (ed != null) {
178                 attdef = ed.GetAttDef(qname);;
179                 if (attdef == null) {
180                     if (!ed.ContentValidator.IsOpen || qname.Namespace.Length == 0) {
181                         throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, qname.ToString());
182                     }
183                     if (!attributeDecls.TryGetValue(qname, out attdef) && targetNamespaces.ContainsKey(qname.Namespace)) {
184                         throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, qname.ToString());
185                     }
186                 }
187             }
188             return attdef;
189         }
190
191
192         internal SchemaAttDef GetAttributeXsd(SchemaElementDecl ed, XmlQualifiedName qname, XmlSchemaObject partialValidationType, out AttributeMatchState attributeMatchState) {
193             SchemaAttDef attdef = null;
194             attributeMatchState = AttributeMatchState.UndeclaredAttribute;
195             if (ed != null) {
196                 attdef = ed.GetAttDef(qname);
197                 if (attdef != null) {
198                     attributeMatchState = AttributeMatchState.AttributeFound;
199                     return attdef;
200                 }
201                 XmlSchemaAnyAttribute any = ed.AnyAttribute;
202                 if (any != null) {
203                     if (!any.NamespaceList.Allows(qname)) {
204                         attributeMatchState = AttributeMatchState.ProhibitedAnyAttribute;
205                     }
206                     else if (any.ProcessContentsCorrect != XmlSchemaContentProcessing.Skip) {
207                         if (attributeDecls.TryGetValue(qname, out attdef)) {
208                             if (attdef.Datatype.TypeCode == XmlTypeCode.Id) { //anyAttribute match whose type is ID
209                                 attributeMatchState = AttributeMatchState.AnyIdAttributeFound;
210                             }
211                             else {
212                                 attributeMatchState = AttributeMatchState.AttributeFound;
213                             }
214                         }
215                         else if (any.ProcessContentsCorrect == XmlSchemaContentProcessing.Lax) {
216                             attributeMatchState = AttributeMatchState.AnyAttributeLax;
217                         }
218                     }
219                     else {
220                         attributeMatchState = AttributeMatchState.AnyAttributeSkip;
221                     }
222                 }
223                 else if (ed.ProhibitedAttributes.ContainsKey(qname)) {
224                     attributeMatchState = AttributeMatchState.ProhibitedAttribute;
225                 }
226             }
227             else if (partialValidationType != null) {
228                 XmlSchemaAttribute attr = partialValidationType as XmlSchemaAttribute;
229                 if (attr != null) {
230                     if (qname.Equals(attr.QualifiedName)) {
231                         attdef = attr.AttDef;
232                         attributeMatchState = AttributeMatchState.AttributeFound;
233                     }
234                     else {
235                         attributeMatchState = AttributeMatchState.AttributeNameMismatch;
236                     }
237                 }
238                 else {
239                     attributeMatchState = AttributeMatchState.ValidateAttributeInvalidCall;
240                 }
241             }
242             else {
243                 if (attributeDecls.TryGetValue(qname, out attdef)) {
244                     attributeMatchState = AttributeMatchState.AttributeFound;
245                 }
246                 else {
247                     attributeMatchState = AttributeMatchState.UndeclaredElementAndAttribute;
248                 }
249             }
250             return attdef;
251         }
252
253         internal SchemaAttDef GetAttributeXsd(SchemaElementDecl ed, XmlQualifiedName qname, ref bool skip) {
254             AttributeMatchState attributeMatchState;
255
256             SchemaAttDef attDef = GetAttributeXsd(ed, qname, null, out attributeMatchState);
257             switch(attributeMatchState) {
258                 case AttributeMatchState.UndeclaredAttribute:
259                     throw new XmlSchemaException(Res.Sch_UndeclaredAttribute, qname.ToString());
260
261                 case AttributeMatchState.ProhibitedAnyAttribute:
262                 case AttributeMatchState.ProhibitedAttribute:
263                     throw new XmlSchemaException(Res.Sch_ProhibitedAttribute, qname.ToString());
264
265                 case AttributeMatchState.AttributeFound:
266                 case AttributeMatchState.AnyIdAttributeFound:
267                 case AttributeMatchState.AnyAttributeLax:
268                 case AttributeMatchState.UndeclaredElementAndAttribute:
269                     break;
270
271                 case AttributeMatchState.AnyAttributeSkip:
272                     skip = true;
273                     break;
274
275                 default:
276                     Debug.Assert(false);
277                     break;
278             }
279             return attDef;
280         }
281             
282         internal void Add(SchemaInfo sinfo, ValidationEventHandler eventhandler) {
283             if (schemaType == SchemaType.None) {
284                 schemaType = sinfo.SchemaType;
285             }
286             else if (schemaType != sinfo.SchemaType) {
287                 if (eventhandler != null) {
288                     eventhandler(this, new ValidationEventArgs(new XmlSchemaException(Res.Sch_MixSchemaTypes, string.Empty)));
289                 }
290                 return;
291             }
292
293             foreach(string tns in sinfo.TargetNamespaces.Keys) {
294                 if (!targetNamespaces.ContainsKey(tns)) {
295                     targetNamespaces.Add(tns, true);
296                 }
297             }
298
299             foreach(KeyValuePair<XmlQualifiedName, SchemaElementDecl> entry in sinfo.elementDecls) {
300                 if (!elementDecls.ContainsKey(entry.Key)) {
301                     elementDecls.Add(entry.Key, entry.Value);
302                 }
303             }
304             foreach(KeyValuePair<XmlQualifiedName, SchemaElementDecl> entry in sinfo.elementDeclsByType) {
305                 if (!elementDeclsByType.ContainsKey(entry.Key)) {
306                     elementDeclsByType.Add(entry.Key, entry.Value);
307                 }   
308             }
309             foreach (SchemaAttDef attdef in sinfo.AttributeDecls.Values) {
310                 if (!attributeDecls.ContainsKey(attdef.Name)) {
311                     attributeDecls.Add(attdef.Name, attdef);
312                 }
313             }
314             foreach (SchemaNotation notation in sinfo.Notations.Values) {
315                 if (!Notations.ContainsKey(notation.Name.Name)) {
316                     Notations.Add(notation.Name.Name, notation);
317                 }
318             }
319
320         }
321 #endif
322
323         internal void Finish() {
324             Dictionary<XmlQualifiedName, SchemaElementDecl> elements = elementDecls;
325             for ( int i = 0; i < 2; i++ ) {
326                 foreach ( SchemaElementDecl e in elements.Values ) {
327                     if ( e.HasNonCDataAttribute ) {
328                         hasNonCDataAttributes = true;
329                     }
330                     if ( e.DefaultAttDefs != null ) {
331                         hasDefaultAttributes = true;
332                     }
333                 }
334                 elements = undeclaredElementDecls;
335             }
336         }
337 //
338 // IDtdInfo interface
339 //
340 #region IDtdInfo Members
341         bool IDtdInfo.HasDefaultAttributes {
342             get {
343                 return hasDefaultAttributes;
344             }
345         }
346
347         bool IDtdInfo.HasNonCDataAttributes {
348             get {
349                 return hasNonCDataAttributes;
350             }
351         }
352
353         IDtdAttributeListInfo IDtdInfo.LookupAttributeList(string prefix, string localName) {
354             XmlQualifiedName qname = new XmlQualifiedName(prefix, localName);
355             SchemaElementDecl elementDecl;
356             if (!elementDecls.TryGetValue(qname, out elementDecl)) {
357                 undeclaredElementDecls.TryGetValue(qname, out elementDecl);
358             }
359             return elementDecl;
360         }
361
362         IEnumerable<IDtdAttributeListInfo> IDtdInfo.GetAttributeLists() {
363             foreach (SchemaElementDecl elemDecl in elementDecls.Values) {
364                 IDtdAttributeListInfo eleDeclAsAttList = (IDtdAttributeListInfo)elemDecl;
365                 yield return eleDeclAsAttList;
366             }
367         }
368
369         IDtdEntityInfo IDtdInfo.LookupEntity(string name) {
370             if (generalEntities == null) {
371                 return null;
372             }
373             XmlQualifiedName qname = new XmlQualifiedName(name);
374             SchemaEntity entity;
375             if (generalEntities.TryGetValue(qname, out entity)) {
376                 return entity;
377             }
378             return null;
379         }
380
381         XmlQualifiedName IDtdInfo.Name {
382             get { return docTypeName; }
383         }
384
385         string IDtdInfo.InternalDtdSubset {
386             get { return internalDtdSubset; }
387         }
388 #endregion
389     }
390 }