2004-05-06 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaAny.cs
1 //\r
2 // System.Xml.Schema.XmlSchemaAny.cs\r
3 //\r
4 // Author:\r
5 //      Dwivedi, Ajay kumar  Adwiv@Yahoo.com\r
6 //      Atsushi Enomoto  ginga@kit.hi-ho.ne.jp\r
7 //\r
8 using System;\r
9 using System.Collections;\r
10 using System.Collections.Specialized;\r
11 using System.Xml;\r
12 using System.Xml.Serialization;\r
13 using System.ComponentModel;\r
14 using Mono.Xml.Schema;\r
15 \r
16 namespace System.Xml.Schema\r
17 {\r
18         /// <summary>\r
19         /// Summary description for XmlSchemaAny.\r
20         /// </summary>\r
21         public class XmlSchemaAny : XmlSchemaParticle\r
22         {\r
23                 static XmlSchemaAny anyTypeContent;\r
24                 internal static XmlSchemaAny AnyTypeContent {\r
25                         get {\r
26                                 if (anyTypeContent == null) {\r
27                                         anyTypeContent = new XmlSchemaAny ();\r
28                                         anyTypeContent.MaxOccursString = "unbounded";\r
29                                         anyTypeContent.MinOccurs = 0;\r
30                                         anyTypeContent.CompileOccurence (null, null);\r
31                                         anyTypeContent.Namespace = "##any";\r
32                                         anyTypeContent.wildcard.HasValueAny = true;\r
33                                         anyTypeContent.wildcard.ResolvedNamespaces = new StringCollection ();\r
34                                         // Although it is not documented by W3C, but it should be.\r
35                                         anyTypeContent.wildcard.ResolvedProcessing =\r
36                                         anyTypeContent.ProcessContents = XmlSchemaContentProcessing.Lax;\r
37                                 }\r
38                                 return anyTypeContent;\r
39                         }\r
40                 }\r
41 \r
42                 private string nameSpace;\r
43                 private XmlSchemaContentProcessing processing;\r
44                 const string xmlname = "any";\r
45 \r
46                 private XsdWildcard wildcard;\r
47 \r
48                 public XmlSchemaAny()\r
49                 {\r
50                         wildcard = new XsdWildcard (this);\r
51                 }\r
52 \r
53                 [System.Xml.Serialization.XmlAttribute("namespace")]\r
54                 public string Namespace \r
55                 {\r
56                         get{ return  nameSpace; } \r
57                         set{ nameSpace = value; }\r
58                 }\r
59                 \r
60                 [DefaultValue(XmlSchemaContentProcessing.None)]\r
61                 [System.Xml.Serialization.XmlAttribute("processContents")]\r
62                 public XmlSchemaContentProcessing ProcessContents\r
63                 { \r
64                         get{ return processing; } \r
65                         set{ processing = value; }\r
66                 }\r
67 \r
68                 // Post Compilation Schema Infoset\r
69                 internal bool HasValueAny {\r
70                         get { return wildcard.HasValueAny; }\r
71                 }\r
72 \r
73                 internal bool HasValueLocal {\r
74                         get { return wildcard.HasValueLocal; }\r
75                 }\r
76 \r
77                 internal bool HasValueOther {\r
78                         get { return wildcard.HasValueOther; }\r
79                 }\r
80 \r
81                 internal bool HasValueTargetNamespace {\r
82                         get { return wildcard.HasValueTargetNamespace; }\r
83                 }\r
84 \r
85                 internal StringCollection ResolvedNamespaces {\r
86                         get { return wildcard.ResolvedNamespaces; }\r
87                 }\r
88 \r
89                 internal XmlSchemaContentProcessing ResolvedProcessContents \r
90                 { \r
91                         get{ return wildcard.ResolvedProcessing; } \r
92                 }\r
93 \r
94                 internal string TargetNamespace\r
95                 {\r
96                         get { return wildcard.TargetNamespace; }\r
97                 }\r
98 \r
99                 /// <remarks>\r
100                 /// 1. id must be of type ID\r
101                 /// 2. namespace can have one of the following values:\r
102                 ///             a) ##any or ##other\r
103                 ///             b) list of anyURI and ##targetNamespace and ##local\r
104                 /// </remarks>\r
105                 internal override int Compile(ValidationEventHandler h, XmlSchema schema)\r
106                 {\r
107                         // If this is already compiled this time, simply skip.\r
108                         if (this.IsComplied (schema.CompilationId))\r
109                                 return 0;\r
110 \r
111                         errorCount = 0;\r
112 \r
113                         XmlSchemaUtil.CompileID(Id,this, schema.IDCollection,h);\r
114                         wildcard.TargetNamespace = schema.TargetNamespace;\r
115                         if (wildcard.TargetNamespace == null)\r
116                                 wildcard.TargetNamespace = "";\r
117                         CompileOccurence (h, schema);\r
118 \r
119                         wildcard.Compile (Namespace, h, schema);\r
120 \r
121                         if (processing == XmlSchemaContentProcessing.None)\r
122                                 wildcard.ResolvedProcessing = XmlSchemaContentProcessing.Strict;\r
123                         else\r
124                                 wildcard.ResolvedProcessing = processing;\r
125 \r
126                         this.CompilationId = schema.CompilationId;\r
127                         return errorCount;\r
128                 }\r
129 \r
130                 internal override XmlSchemaParticle GetOptimizedParticle (bool isTop)\r
131                 {\r
132                         if (OptimizedParticle != null)\r
133                                 return OptimizedParticle;\r
134                         // Uncommenting this causes incorrect validation. \r
135                         // It will prevent UPA e.g. msxsdtest/Particles/particlesJf006.xsd\r
136 //                      if (ValidatedMaxOccurs == 0) {\r
137 //                              OptimizedParticle = XmlSchemaParticle.Empty;\r
138 //                              return OptimizedParticle;\r
139 //                      }\r
140 \r
141                         XmlSchemaAny any = new XmlSchemaAny ();\r
142                         CopyInfo (any);\r
143                         any.CompileOccurence (null, null);\r
144                         any.wildcard = this.wildcard;\r
145                         OptimizedParticle = any;\r
146 \r
147                         // properties which never contribute to validation\r
148                         any.Namespace = Namespace;\r
149                         any.ProcessContents = ProcessContents;\r
150                         any.Annotation = Annotation;\r
151                         any.UnhandledAttributes = UnhandledAttributes;\r
152 \r
153                         return OptimizedParticle;\r
154                 }\r
155                 \r
156                 internal override int Validate(ValidationEventHandler h, XmlSchema schema)\r
157                 {\r
158                         return errorCount;\r
159                 }\r
160 \r
161                 internal override bool ParticleEquals (XmlSchemaParticle other)\r
162                 {\r
163                         XmlSchemaAny any = other as XmlSchemaAny;\r
164                         if (any == null)\r
165                                 return false;\r
166                         if (this.HasValueAny != any.HasValueAny ||\r
167                                 this.HasValueLocal != any.HasValueLocal ||\r
168                                 this.HasValueOther != any.HasValueOther ||\r
169                                 this.HasValueTargetNamespace != any.HasValueTargetNamespace ||\r
170                                 this.ResolvedProcessContents != any.ResolvedProcessContents ||\r
171                                 this.ValidatedMaxOccurs != any.ValidatedMaxOccurs ||\r
172                                 this.ValidatedMinOccurs != any.ValidatedMinOccurs ||\r
173                                 this.ResolvedNamespaces.Count != any.ResolvedNamespaces.Count)\r
174                                 return false;\r
175                         for (int i = 0; i < ResolvedNamespaces.Count; i++)\r
176                                 if (ResolvedNamespaces [i] != any.ResolvedNamespaces [i])\r
177                                         return false;\r
178                         return true;\r
179                 }\r
180 \r
181 \r
182                 // 3.8.6. Attribute Wildcard Intersection\r
183                 // Only try to examine if their intersection is expressible, and\r
184                 // returns if the result is empty.\r
185                 internal bool ExamineAttributeWildcardIntersection (XmlSchemaAny other,\r
186                         ValidationEventHandler h, XmlSchema schema)\r
187                 {\r
188                         return wildcard.ExamineAttributeWildcardIntersection (other, h, schema);\r
189                 }\r
190 \r
191                 internal override bool ValidateDerivationByRestriction (XmlSchemaParticle baseParticle, \r
192                         ValidationEventHandler h, XmlSchema schema, bool raiseError)\r
193                 {\r
194                         XmlSchemaAny baseAny = baseParticle as XmlSchemaAny;\r
195                         if (baseAny == null) {\r
196                                 if (raiseError)\r
197                                         error (h, "Invalid particle derivation by restriction was found.");\r
198                                 return false;\r
199                         }\r
200                         // 3.9.6 Particle Derivation OK (Any:Any - NSSubset)\r
201                         if (!ValidateOccurenceRangeOK (baseParticle, h, schema, raiseError))\r
202                                 return false;\r
203                         return wildcard.ValidateWildcardSubset (baseAny.wildcard, h, schema, raiseError);\r
204                 }\r
205 \r
206 \r
207                 internal override void CheckRecursion (int depth, ValidationEventHandler h, XmlSchema schema)\r
208                 {\r
209                         // do nothing\r
210                 }\r
211 \r
212                 internal override void ValidateUniqueParticleAttribution (\r
213                         XmlSchemaObjectTable qnames, ArrayList nsNames,\r
214                         ValidationEventHandler h, XmlSchema schema)\r
215                 {\r
216                         // Wildcard Intersection check.\r
217                         foreach (XmlSchemaAny other in nsNames)\r
218                                 if (!ExamineAttributeWildcardIntersection (other, h, schema))\r
219                                         error (h, "Ambiguous -any- particle was found.");\r
220                         nsNames.Add (this);\r
221                 }\r
222 \r
223                 internal override void ValidateUniqueTypeAttribution (XmlSchemaObjectTable labels,\r
224                         ValidationEventHandler h, XmlSchema schema)\r
225                 {\r
226                         // do nothing\r
227                 }\r
228 \r
229                 // 3.10.4 Wildcard Allows Namespace Name. (In fact it is almost copy...)\r
230                 internal bool ValidateWildcardAllowsNamespaceName (string ns,\r
231                         ValidationEventHandler h, XmlSchema schema, bool raiseError)\r
232                 {\r
233                         return wildcard.ValidateWildcardAllowsNamespaceName (ns, h, schema, raiseError);
234                 }\r
235 \r
236                 //<any\r
237                 //  id = ID\r
238                 //  maxOccurs =  (nonNegativeInteger | unbounded)  : 1\r
239                 //  minOccurs = nonNegativeInteger : 1\r
240                 //  namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )  : ##any\r
241                 //  processContents = (lax | skip | strict) : strict\r
242                 //  {any attributes with non-schema namespace . . .}>\r
243                 //  Content: (annotation?)\r
244                 //</any>\r
245                 internal static XmlSchemaAny Read(XmlSchemaReader reader, ValidationEventHandler h)\r
246                 {\r
247                         XmlSchemaAny any = new XmlSchemaAny();\r
248                         reader.MoveToElement();\r
249 \r
250                         if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)\r
251                         {\r
252                                 error(h,"Should not happen :1: XmlSchemaAny.Read, name="+reader.Name,null);\r
253                                 reader.SkipToEnd();\r
254                                 return null;\r
255                         }\r
256 \r
257                         any.LineNumber = reader.LineNumber;\r
258                         any.LinePosition = reader.LinePosition;\r
259                         any.SourceUri = reader.BaseURI;\r
260 \r
261                         while(reader.MoveToNextAttribute())\r
262                         {\r
263                                 if(reader.Name == "id")\r
264                                 {\r
265                                         any.Id = reader.Value;\r
266                                 }\r
267                                 else if(reader.Name == "maxOccurs")\r
268                                 {\r
269                                         try\r
270                                         {\r
271                                                 any.MaxOccursString = reader.Value;\r
272                                         }\r
273                                         catch(Exception e)\r
274                                         {\r
275                                                 error(h,reader.Value + " is an invalid value for maxOccurs",e);\r
276                                         }\r
277                                 }\r
278                                 else if(reader.Name == "minOccurs")\r
279                                 {\r
280                                         try\r
281                                         {\r
282                                                 any.MinOccursString = reader.Value;\r
283                                         }\r
284                                         catch(Exception e)\r
285                                         {\r
286                                                 error(h,reader.Value + " is an invalid value for minOccurs", e);\r
287                                         }\r
288                                 }\r
289                                 else if(reader.Name == "namespace")\r
290                                 {\r
291                                         any.nameSpace = reader.Value;\r
292                                 }\r
293                                 else if(reader.Name == "processContents")\r
294                                 {\r
295                                         Exception innerex;\r
296                                         any.processing = XmlSchemaUtil.ReadProcessingAttribute(reader,out innerex);\r
297                                         if(innerex != null)\r
298                                                 error(h, reader.Value + " is not a valid value for processContents",innerex);\r
299                                 }\r
300                                 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)\r
301                                 {\r
302                                         error(h,reader.Name + " is not a valid attribute for any",null);\r
303                                 }\r
304                                 else\r
305                                 {\r
306                                         XmlSchemaUtil.ReadUnhandledAttribute(reader,any);\r
307                                 }\r
308                         }\r
309                         \r
310                         reader.MoveToElement();\r
311                         if(reader.IsEmptyElement)\r
312                                 return any;\r
313                         \r
314                         //  Content: (annotation?)\r
315                         int level = 1;\r
316                         while(reader.ReadNextElement())\r
317                         {\r
318                                 if(reader.NodeType == XmlNodeType.EndElement)\r
319                                 {\r
320                                         if(reader.LocalName != xmlname)\r
321                                                 error(h,"Should not happen :2: XmlSchemaAny.Read, name="+reader.Name,null);\r
322                                         break;\r
323                                 }\r
324                                 if(level <= 1 && reader.LocalName == "annotation")\r
325                                 {\r
326                                         level = 2;      //Only one annotation\r
327                                         XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
328                                         if(annotation != null)\r
329                                                 any.Annotation = annotation;\r
330                                         continue;\r
331                                 }\r
332                                 reader.RaiseInvalidElementError();\r
333                         }                       \r
334                         return any;\r
335                 }\r
336         }\r
337 }\r