2004-02-16 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaSimpleTypeUnion.cs
1 // Author: Dwivedi, Ajay kumar\r
2 //            Adwiv@Yahoo.com\r
3 using System;\r
4 using System.Collections;\r
5 using System.Xml;\r
6 using System.Xml.Serialization;\r
7 \r
8 namespace System.Xml.Schema\r
9 {\r
10         /// <summary>\r
11         /// Summary description for XmlSchemaSimpleTypeUnion.\r
12         /// </summary>\r
13         public class XmlSchemaSimpleTypeUnion : XmlSchemaSimpleTypeContent\r
14         {\r
15                 private XmlSchemaObjectCollection baseTypes;\r
16                 private XmlQualifiedName[] memberTypes;\r
17                 private static string xmlname = "union";\r
18                 private object [] validatedTypes;\r
19 \r
20                 public XmlSchemaSimpleTypeUnion()\r
21                 {\r
22                         baseTypes = new XmlSchemaObjectCollection();\r
23                 }\r
24 \r
25                 [XmlElement("simpleType",typeof(XmlSchemaSimpleType),Namespace=XmlSchema.Namespace)]\r
26                 public XmlSchemaObjectCollection BaseTypes \r
27                 {\r
28                         get{ return baseTypes; }\r
29                 }\r
30 \r
31                 [System.Xml.Serialization.XmlAttribute("memberTypes")]\r
32                 public XmlQualifiedName[] MemberTypes\r
33                 {\r
34                         get{ return  memberTypes; } \r
35                         set{ memberTypes = value; }\r
36                 }\r
37 \r
38                 internal object [] ValidatedTypes\r
39                 {\r
40                         get { return validatedTypes; }\r
41                 }\r
42 \r
43                 /// <remarks>\r
44                 /// 1. Circular union type definition is disallowed. (WTH is this?)\r
45                 /// 2. id must be a valid ID\r
46                 /// </remarks>\r
47                 internal override int Compile(ValidationEventHandler h, XmlSchema schema)\r
48                 {\r
49                         // If this is already compiled this time, simply skip.\r
50                         if (this.IsComplied (schema.CompilationId))\r
51                                 return 0;\r
52 \r
53                         errorCount = 0;\r
54 \r
55                         int count = BaseTypes.Count;\r
56 \r
57                         foreach(XmlSchemaObject obj in baseTypes)\r
58                         {\r
59                                 if(obj != null && obj is XmlSchemaSimpleType)\r
60                                 {\r
61                                         XmlSchemaSimpleType stype = (XmlSchemaSimpleType) obj;\r
62                                         errorCount += stype.Compile(h, schema);\r
63                                 }\r
64                                 else\r
65                                 {\r
66                                         error(h, "baseTypes can't have objects other than a simpletype");\r
67                                 }\r
68                         }\r
69                         \r
70                         if(memberTypes!=null)\r
71                         {\r
72                                 for(int i=0; i< memberTypes.Length; i++)\r
73                                 {\r
74                                         if(memberTypes[i] == null || !XmlSchemaUtil.CheckQName(MemberTypes[i]))\r
75                                         {\r
76                                                 error (h,"Invalid membertype");\r
77                                                 memberTypes[i] = XmlQualifiedName.Empty;\r
78                                         }\r
79                                         else\r
80                                         {\r
81                                                 count += MemberTypes.Length;\r
82                                         }\r
83                                 }\r
84                         }\r
85 \r
86                         if(count == 0)\r
87                                 error(h, "Atleast one simpletype or membertype must be present");\r
88 \r
89                         XmlSchemaUtil.CompileID(Id,this,schema.IDCollection,h);\r
90 \r
91                         this.CompilationId = schema.CompilationId;\r
92                         return errorCount;\r
93                 }\r
94                 \r
95                 internal override int Validate(ValidationEventHandler h, XmlSchema schema)\r
96                 {\r
97                         if (IsValidated (schema.ValidationId))\r
98                                 return errorCount;\r
99 \r
100                         ArrayList al = new ArrayList ();\r
101                         // Validate MemberTypes\r
102                         if (MemberTypes != null) {\r
103                                 foreach (XmlQualifiedName memberTypeName in MemberTypes) {\r
104                                         object type = null;\r
105                                         XmlSchemaType xstype = schema.SchemaTypes [memberTypeName] as XmlSchemaSimpleType;\r
106                                         if (xstype != null) {\r
107                                                 errorCount += xstype.Validate (h, schema);\r
108                                                 type = xstype;\r
109                                         } else if (memberTypeName == XmlSchemaComplexType.AnyTypeName) {\r
110                                                 type = XmlSchemaSimpleType.AnySimpleType;
111                                         } else if (memberTypeName.Namespace == XmlSchema.Namespace) {\r
112                                                 type = XmlSchemaDatatype.FromName (memberTypeName);\r
113                                                 if (type == null)\r
114                                                         error (h, "Invalid schema type name was specified: " + memberTypeName);\r
115                                         }\r
116                                         // otherwise, it might be missing sub components.\r
117                                         else if (!schema.IsNamespaceAbsent (memberTypeName.Namespace))\r
118                                                 error (h, "Referenced base schema type " + memberTypeName + " was not found in the corresponding schema.");\r
119 \r
120                                         al.Add (type);\r
121                                 }\r
122                         }\r
123                         if (BaseTypes != null) {\r
124                                 foreach (XmlSchemaSimpleType st in BaseTypes) {\r
125                                         st.Validate (h, schema);\r
126                                         al.Add (st);\r
127                                 }\r
128                         }\r
129                         this.validatedTypes = al.ToArray ();\r
130 \r
131                         ValidationId = schema.ValidationId;\r
132                         return errorCount;\r
133                 }\r
134 \r
135                 //<union \r
136                 //  id = ID \r
137                 //  memberTypes = List of QName \r
138                 //  {any attributes with non-schema namespace . . .}>\r
139                 //  Content: (annotation?, (simpleType*))\r
140                 //</union>\r
141                 internal static XmlSchemaSimpleTypeUnion Read(XmlSchemaReader reader, ValidationEventHandler h)\r
142                 {\r
143                         XmlSchemaSimpleTypeUnion union = new XmlSchemaSimpleTypeUnion();\r
144                         reader.MoveToElement();\r
145 \r
146                         if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)\r
147                         {\r
148                                 error(h,"Should not happen :1: XmlSchemaSimpleTypeUnion.Read, name="+reader.Name,null);\r
149                                 reader.Skip();\r
150                                 return null;\r
151                         }\r
152 \r
153                         union.LineNumber = reader.LineNumber;\r
154                         union.LinePosition = reader.LinePosition;\r
155                         union.SourceUri = reader.BaseURI;\r
156 \r
157                         //Read Attributes\r
158                         while(reader.MoveToNextAttribute())\r
159                         {\r
160                                 if(reader.Name == "id")\r
161                                 {\r
162                                         union.Id = reader.Value;\r
163                                 }\r
164                                 else if(reader.Name == "memberTypes")\r
165                                 {\r
166                                         Exception innerEx;\r
167                                         string[] names = XmlSchemaUtil.SplitList(reader.Value);\r
168                                         union.memberTypes = new XmlQualifiedName[names.Length];\r
169                                         for(int i=0;i<names.Length;i++)\r
170                                         {\r
171                                                 union.memberTypes[i] = XmlSchemaUtil.ToQName(reader,names[i],out innerEx);\r
172                                                 if(innerEx != null)\r
173                                                         error(h,"'"+names[i] + "' is not a valid memberType",innerEx);\r
174                                         }\r
175                                 }\r
176                                 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)\r
177                                 {\r
178                                         error(h,reader.Name + " is not a valid attribute for union",null);\r
179                                 }\r
180                                 else\r
181                                 {\r
182                                         XmlSchemaUtil.ReadUnhandledAttribute(reader,union);\r
183                                 }\r
184                         }\r
185                         \r
186                         reader.MoveToElement();\r
187                         if(reader.IsEmptyElement)\r
188                                 return union;\r
189 \r
190                         //  Content: annotation?, simpleType*\r
191                         int level = 1;\r
192                         while(reader.ReadNextElement())\r
193                         {\r
194                                 if(reader.NodeType == XmlNodeType.EndElement)\r
195                                 {\r
196                                         if(reader.LocalName != xmlname)\r
197                                                 error(h,"Should not happen :2: XmlSchemaSimpleTypeUnion.Read, name="+reader.Name,null);\r
198                                         break;\r
199                                 }\r
200                                 if(level <= 1 && reader.LocalName == "annotation")\r
201                                 {\r
202                                         level = 2; //Only one annotation\r
203                                         XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
204                                         if(annotation != null)\r
205                                                 union.Annotation = annotation;\r
206                                         continue;\r
207                                 }\r
208                                 if(level <=2 && reader.LocalName == "simpleType")\r
209                                 {\r
210                                         level = 2;\r
211                                         XmlSchemaSimpleType stype = XmlSchemaSimpleType.Read(reader,h);\r
212                                         if(stype != null)\r
213                                                 union.baseTypes.Add(stype);\r
214                                         continue;\r
215                                 }\r
216                                 reader.RaiseInvalidElementError();\r
217                         }\r
218                         return union;\r
219                 }\r
220 \r
221         }\r
222 }\r