New test.
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaSimpleTypeUnion.cs
1 // Author: Dwivedi, Ajay kumar
2 //            Adwiv@Yahoo.com
3
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 // 
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 // 
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 using System;
25 using System.Collections;
26 using System.Xml;
27 using System.Xml.Serialization;
28
29 namespace System.Xml.Schema
30 {
31         /// <summary>
32         /// Summary description for XmlSchemaSimpleTypeUnion.
33         /// </summary>
34         public class XmlSchemaSimpleTypeUnion : XmlSchemaSimpleTypeContent
35         {
36                 private XmlSchemaObjectCollection baseTypes;
37                 private XmlQualifiedName[] memberTypes;
38                 const string xmlname = "union";
39                 private object [] validatedTypes;
40 #if NET_2_0
41                 private XmlSchemaSimpleType [] validatedSchemaTypes;
42 #endif
43
44                 public XmlSchemaSimpleTypeUnion()
45                 {
46                         baseTypes = new XmlSchemaObjectCollection();
47                 }
48
49                 [XmlElement("simpleType",typeof(XmlSchemaSimpleType))]
50                 public XmlSchemaObjectCollection BaseTypes 
51                 {
52                         get{ return baseTypes; }
53                 }
54
55                 [System.Xml.Serialization.XmlAttribute("memberTypes")]
56                 public XmlQualifiedName[] MemberTypes
57                 {
58                         get{ return  memberTypes; } 
59                         set{ memberTypes = value; }
60                 }
61
62 #if NET_2_0
63                 [XmlIgnore]
64                 public XmlSchemaSimpleType [] BaseMemberTypes {
65                         get { return validatedSchemaTypes; }
66                 }
67 #endif
68
69                 internal object [] ValidatedTypes
70                 {
71                         get { return validatedTypes; }
72                 }
73
74                 /// <remarks>
75                 /// 1. Circular union type definition is disallowed. (WTH is this?)
76                 /// 2. id must be a valid ID
77                 /// </remarks>
78                 internal override int Compile(ValidationEventHandler h, XmlSchema schema)
79                 {
80                         // If this is already compiled this time, simply skip.
81                         if (CompilationId == schema.CompilationId)
82                                 return 0;
83
84 #if NET_2_0
85                         foreach (XmlSchemaObject obj in BaseTypes)
86                                 obj.Parent = this;
87 #endif
88
89                         errorCount = 0;
90
91                         int count = BaseTypes.Count;
92
93                         foreach(XmlSchemaObject obj in baseTypes)
94                         {
95                                 if(obj != null && obj is XmlSchemaSimpleType)
96                                 {
97                                         XmlSchemaSimpleType stype = (XmlSchemaSimpleType) obj;
98                                         errorCount += stype.Compile(h, schema);
99                                 }
100                                 else
101                                 {
102                                         error(h, "baseTypes can't have objects other than a simpletype");
103                                 }
104                         }
105                         
106                         if(memberTypes!=null)
107                         {
108                                 for(int i=0; i< memberTypes.Length; i++)
109                                 {
110                                         if(memberTypes[i] == null || !XmlSchemaUtil.CheckQName(MemberTypes[i]))
111                                         {
112                                                 error (h,"Invalid membertype");
113                                                 memberTypes[i] = XmlQualifiedName.Empty;
114                                         }
115                                         else
116                                         {
117                                                 count += MemberTypes.Length;
118                                         }
119                                 }
120                         }
121
122                         if(count == 0)
123                                 error(h, "Atleast one simpletype or membertype must be present");
124
125                         XmlSchemaUtil.CompileID(Id,this,schema.IDCollection,h);
126
127                         
128
129                         this.CompilationId = schema.CompilationId;
130                         return errorCount;
131                 }
132                 
133                 internal override int Validate(ValidationEventHandler h, XmlSchema schema)
134                 {
135                         if (IsValidated (schema.ValidationId))
136                                 return errorCount;
137
138                         ArrayList al = new ArrayList ();
139                         // Validate MemberTypes
140                         if (MemberTypes != null) {
141                                 foreach (XmlQualifiedName memberTypeName in MemberTypes) {
142                                         object type = null;
143                                         XmlSchemaType xstype = schema.FindSchemaType (memberTypeName) as XmlSchemaSimpleType;
144                                         if (xstype != null) {
145                                                 errorCount += xstype.Validate (h, schema);
146                                                 type = xstype;
147                                         } else if (memberTypeName == XmlSchemaComplexType.AnyTypeName) {
148                                                 type = XmlSchemaSimpleType.AnySimpleType;
149                                         } else if (memberTypeName.Namespace == XmlSchema.Namespace ||
150                                                 memberTypeName.Namespace == XmlSchema.XdtNamespace) {
151                                                 type = XmlSchemaDatatype.FromName (memberTypeName);
152                                                 if (type == null)
153                                                         error (h, "Invalid schema type name was specified: " + memberTypeName);
154                                         }
155                                         // otherwise, it might be missing sub components.
156                                         else if (!schema.IsNamespaceAbsent (memberTypeName.Namespace))
157                                                 error (h, "Referenced base schema type " + memberTypeName + " was not found in the corresponding schema.");
158
159                                         al.Add (type);
160                                 }
161                         }
162                         if (BaseTypes != null) {
163                                 foreach (XmlSchemaSimpleType st in BaseTypes) {
164                                         st.Validate (h, schema);
165                                         al.Add (st);
166                                 }
167                         }
168                         this.validatedTypes = al.ToArray ();
169
170 #if NET_2_0
171                         if (validatedTypes != null) {
172                                 validatedSchemaTypes = new XmlSchemaSimpleType [validatedTypes.Length];
173                                 for (int i = 0; i < validatedTypes.Length; i++) {
174                                         object t = validatedTypes [i];
175                                         XmlSchemaSimpleType st = t as XmlSchemaSimpleType;
176                                         if (st == null && t != null)
177                                                 st = XmlSchemaType.GetBuiltInSimpleType (((XmlSchemaDatatype) t).TypeCode);
178                                         validatedSchemaTypes [i] = st;
179                                 }
180                         }
181 #endif
182
183                         ValidationId = schema.ValidationId;
184                         return errorCount;
185                 }
186
187                 //<union 
188                 //  id = ID 
189                 //  memberTypes = List of QName 
190                 //  {any attributes with non-schema namespace . . .}>
191                 //  Content: (annotation?, (simpleType*))
192                 //</union>
193                 internal static XmlSchemaSimpleTypeUnion Read(XmlSchemaReader reader, ValidationEventHandler h)
194                 {
195                         XmlSchemaSimpleTypeUnion union = new XmlSchemaSimpleTypeUnion();
196                         reader.MoveToElement();
197
198                         if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)
199                         {
200                                 error(h,"Should not happen :1: XmlSchemaSimpleTypeUnion.Read, name="+reader.Name,null);
201                                 reader.Skip();
202                                 return null;
203                         }
204
205                         union.LineNumber = reader.LineNumber;
206                         union.LinePosition = reader.LinePosition;
207                         union.SourceUri = reader.BaseURI;
208
209                         //Read Attributes
210                         while(reader.MoveToNextAttribute())
211                         {
212                                 if(reader.Name == "id")
213                                 {
214                                         union.Id = reader.Value;
215                                 }
216                                 else if(reader.Name == "memberTypes")
217                                 {
218                                         Exception innerEx;
219                                         string[] names = XmlSchemaUtil.SplitList(reader.Value);
220                                         union.memberTypes = new XmlQualifiedName[names.Length];
221                                         for(int i=0;i<names.Length;i++)
222                                         {
223                                                 union.memberTypes[i] = XmlSchemaUtil.ToQName(reader,names[i],out innerEx);
224                                                 if(innerEx != null)
225                                                         error(h,"'"+names[i] + "' is not a valid memberType",innerEx);
226                                         }
227                                 }
228                                 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
229                                 {
230                                         error(h,reader.Name + " is not a valid attribute for union",null);
231                                 }
232                                 else
233                                 {
234                                         XmlSchemaUtil.ReadUnhandledAttribute(reader,union);
235                                 }
236                         }
237                         
238                         reader.MoveToElement();
239                         if(reader.IsEmptyElement)
240                                 return union;
241
242                         //  Content: annotation?, simpleType*
243                         int level = 1;
244                         while(reader.ReadNextElement())
245                         {
246                                 if(reader.NodeType == XmlNodeType.EndElement)
247                                 {
248                                         if(reader.LocalName != xmlname)
249                                                 error(h,"Should not happen :2: XmlSchemaSimpleTypeUnion.Read, name="+reader.Name,null);
250                                         break;
251                                 }
252                                 if(level <= 1 && reader.LocalName == "annotation")
253                                 {
254                                         level = 2; //Only one annotation
255                                         XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
256                                         if(annotation != null)
257                                                 union.Annotation = annotation;
258                                         continue;
259                                 }
260                                 if(level <=2 && reader.LocalName == "simpleType")
261                                 {
262                                         level = 2;
263                                         XmlSchemaSimpleType stype = XmlSchemaSimpleType.Read(reader,h);
264                                         if(stype != null)
265                                                 union.baseTypes.Add(stype);
266                                         continue;
267                                 }
268                                 reader.RaiseInvalidElementError();
269                         }
270                         return union;
271                 }
272
273         }
274 }