Merge pull request #717 from mono/client_websockets_impl
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlSchemaImporter.cs
1 // 
2 // System.Xml.Serialization.XmlSchemaImporter
3 //
4 // Author:
5 //   Tim Coleman (tim@timcoleman.com)
6 //   Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // Copyright (C) Tim Coleman, 2002
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
32 using System.Xml;
33 #if !TARGET_JVM && !MOBILE
34 using System.CodeDom.Compiler;
35 #endif
36 using System.Xml.Schema;
37 using System.Collections;
38 using System.Collections.Generic;
39 #if NET_2_0 && CONFIGURATION_DEP
40 using System.Configuration;
41 using System.Xml.Serialization.Configuration;
42 #endif
43
44 namespace System.Xml.Serialization 
45 {
46         public class XmlSchemaImporter
47 #if NET_2_0 && !MOBILE
48                 : SchemaImporter
49 #endif
50         {
51                 #region Fields
52
53                 XmlSchemas schemas;
54                 CodeIdentifiers typeIdentifiers;
55                 CodeIdentifiers elemIdentifiers = new CodeIdentifiers ();
56                 Hashtable mappedTypes = new Hashtable ();
57                 Hashtable primitiveDerivedMappedTypes = new Hashtable ();
58                 Hashtable dataMappedTypes = new Hashtable ();
59                 Queue pendingMaps = new Queue ();
60                 Hashtable sharedAnonymousTypes = new Hashtable ();
61                 bool encodedFormat = false;
62                 XmlReflectionImporter auxXmlRefImporter;
63                 SoapReflectionImporter auxSoapRefImporter;
64                 bool anyTypeImported;
65
66 //              CodeGenerationOptions options;
67
68                 static readonly XmlQualifiedName anyType = new XmlQualifiedName ("anyType",XmlSchema.Namespace);
69                 static readonly XmlQualifiedName arrayType = new XmlQualifiedName ("Array",XmlSerializer.EncodingNamespace);
70                 static readonly XmlQualifiedName arrayTypeRefName = new XmlQualifiedName ("arrayType",XmlSerializer.EncodingNamespace);
71                 
72                 const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
73                 
74                 XmlSchemaElement anyElement = null;
75
76                 class MapFixup
77                 {
78                         public XmlTypeMapping Map;
79                         public XmlSchemaComplexType SchemaType;
80                         public XmlQualifiedName TypeName;
81                 }
82
83                 #endregion
84
85                 #region Constructors
86
87                 public XmlSchemaImporter (XmlSchemas schemas)
88                 {
89                         this.schemas = schemas;
90                         typeIdentifiers = new CodeIdentifiers ();
91
92                         InitializeExtensions ();
93                 }
94
95                 public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers)
96                         : this (schemas)
97                 {
98                         this.typeIdentifiers = typeIdentifiers;
99                 }
100                 
101 #if !TARGET_JVM && !MOBILE
102                 [MonoTODO]
103                 public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, CodeDomProvider codeProvider, ImportContext context)
104                 {
105                         this.schemas = schemas;
106 //                      this.options = options;
107                         if (context != null) {
108                                 typeIdentifiers = context.TypeIdentifiers;
109                                 InitSharedData (context);
110                         }
111                         else
112                                 typeIdentifiers = new CodeIdentifiers ();
113
114                         InitializeExtensions ();
115                 }
116
117                 [MonoTODO]
118                 public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, ImportContext context)
119                 {
120                         this.schemas = schemas;
121 //                      this.options = options;
122                         if (context != null) {
123                                 typeIdentifiers = context.TypeIdentifiers;
124                                 InitSharedData (context);
125                         }
126                         else
127                                 typeIdentifiers = new CodeIdentifiers ();
128
129                         InitializeExtensions ();
130                 }
131                 
132                 [MonoTODO]
133                 public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers, CodeGenerationOptions options)
134                 {
135                         this.typeIdentifiers = typeIdentifiers;
136                         this.schemas = schemas;
137 //                      this.options = options;
138
139                         InitializeExtensions ();
140                 }
141
142                 void InitSharedData (ImportContext context)
143                 {
144                         if (context.ShareTypes) {
145                                 mappedTypes = context.MappedTypes;
146                                 dataMappedTypes = context.DataMappedTypes;
147                                 sharedAnonymousTypes = context.SharedAnonymousTypes;
148                         }
149                 }
150 #endif
151                 
152                 internal bool UseEncodedFormat
153                 {
154                         get { return encodedFormat; }
155                         set { encodedFormat = value; }
156                 }
157
158                 #endregion // Constructors
159
160                 #region Methods
161
162                 void InitializeExtensions ()
163                 {
164 #if NET_2_0 && CONFIGURATION_DEP
165                         SerializationSectionGroup root = ConfigurationManager.GetSection ("system.xml.serialization") as SerializationSectionGroup;
166                         if (root == null)
167                                 return;
168
169                         foreach (SchemaImporterExtensionElement element in
170                                  root.SchemaImporterExtensions.SchemaImporterExtensions)
171                                 Extensions.Add (element.Name, element.Type);
172 #endif
173                 }
174
175                 public XmlMembersMapping ImportAnyType (XmlQualifiedName typeName, string elementName)
176                 {
177                         if (typeName == XmlQualifiedName.Empty)
178                         {
179                                 XmlTypeMapMemberAnyElement mapMem = new XmlTypeMapMemberAnyElement ();
180                                 mapMem.Name = typeName.Name;
181                                 mapMem.TypeData = TypeTranslator.GetTypeData(typeof(XmlNode));
182                                 mapMem.ElementInfo.Add (CreateElementInfo (typeName.Namespace, mapMem, typeName.Name, mapMem.TypeData, true, XmlSchemaForm.None, -1));
183                                 
184                                 XmlMemberMapping[] mm = new XmlMemberMapping [1];
185                                 mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
186                                 return new XmlMembersMapping (mm);
187                         }
188                         else
189                         {
190                                 XmlSchemaComplexType stype = (XmlSchemaComplexType) schemas.Find (typeName, typeof (XmlSchemaComplexType));
191                                 if (stype == null) 
192                                         throw new InvalidOperationException ("Referenced type '" + typeName + "' not found");
193                                 
194                                 if (!CanBeAnyElement (stype))
195                                         throw new InvalidOperationException ("The type '" + typeName + "' is not valid for a collection of any elements");
196                                         
197                                 ClassMap cmap = new ClassMap ();
198                                 CodeIdentifiers classIds = new CodeIdentifiers ();
199                                 bool isMixed = stype.IsMixed;
200                                 ImportSequenceContent (typeName, cmap, ((XmlSchemaSequence) stype.Particle).Items, classIds, false, ref isMixed);
201                                 XmlTypeMapMemberAnyElement mapMem = (XmlTypeMapMemberAnyElement) cmap.AllMembers[0];
202                                 mapMem.Name = typeName.Name;
203                                 
204                                 XmlMemberMapping[] mm = new XmlMemberMapping [1];
205                                 mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
206                                 return new XmlMembersMapping (mm);
207                         }
208                 }
209
210                 public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType)
211                 {
212                         return ImportDerivedTypeMapping (name, baseType, true);
213                 }
214                 
215                 public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType, bool baseTypeCanBeIndirect)
216                 {
217                         XmlQualifiedName qname;
218                         XmlSchemaType stype;
219                         
220                         if (encodedFormat)
221                         {
222                                 qname = name;
223                                 stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
224                                 if (stype == null) throw new InvalidOperationException ("Schema type '" + name + "' not found or not valid");
225                         }
226                         else
227                         {
228                                 if (!LocateElement (name, out qname, out stype))
229                                         return null;
230                         }
231
232                         XmlTypeMapping map = GetRegisteredTypeMapping (qname, baseType);
233                         if (map != null)
234                         {
235                                 // If the type has already been imported, make sure that the map 
236                                 // has the requested base type
237                                 
238                                 SetMapBaseType (map, baseType);
239                                 map.UpdateRoot (name);
240                                 return map;
241                         }
242                         
243                         map = CreateTypeMapping (qname, SchemaTypes.Class, name);
244                         if (stype != null) {
245                                 map.Documentation = GetDocumentation (stype);
246                                 RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
247                         } else {
248                                 ClassMap cmap = new ClassMap ();
249                                 CodeIdentifiers classIds = new CodeIdentifiers ();
250                                 map.ObjectMap = cmap;
251                                 AddTextMember (qname, cmap, classIds);
252                         }
253                         
254                         BuildPendingMaps ();
255                         SetMapBaseType (map, baseType);
256                         
257                         return map;
258                 }
259                 
260                 void SetMapBaseType (XmlTypeMapping map, Type baseType)
261                 {
262                         // This method sets the base type for a given map.
263                         // If the map already inherits from this type, it does nothing.
264                         
265                         // Fiirst of all, check if the map already inherits from baseType
266                                 
267                         XmlTypeMapping topMap = null;
268                         while (map != null)
269                         {
270                                 if (map.TypeData.Type == baseType)
271                                         return;
272                                 topMap = map;
273                                 map = map.BaseMap;
274                         }
275                         
276                         // Does not have the requested base type.
277                         // Then, get/create a map for that base type.
278
279                         XmlTypeMapping baseMap = ReflectType (baseType);
280                         
281                         // Add this map as a derived map of the base map
282
283                         topMap.BaseMap = baseMap;
284                         baseMap.DerivedTypes.Add (topMap);
285                         baseMap.DerivedTypes.AddRange (topMap.DerivedTypes);
286                         
287                         // Now add the base type fields to all derived maps
288
289                         ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
290                         
291                         ClassMap cmap = (ClassMap)topMap.ObjectMap;
292                         foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
293                                 cmap.AddMember (member);
294                                 
295                         foreach (XmlTypeMapping derivedMap in topMap.DerivedTypes)
296                         {
297                                 cmap = (ClassMap)derivedMap.ObjectMap;
298                                 foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
299                                         cmap.AddMember (member);
300                         }
301                 }
302
303                 public XmlMembersMapping ImportMembersMapping (XmlQualifiedName name)
304                 {
305                         XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
306                         if (elem == null) throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
307
308                         XmlSchemaComplexType stype;
309                         if (elem.SchemaType != null)
310                         {
311                                 stype = elem.SchemaType as XmlSchemaComplexType;
312                         }
313                         else
314                         {
315                                 if (elem.SchemaTypeName.IsEmpty) return null;
316                                 object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
317                                 if (type == null) {
318                                         if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) return null;
319                                         throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
320                                 }
321                                 stype = type as XmlSchemaComplexType;
322                         }
323                         
324                         if (stype == null) 
325                                 throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
326                         
327                         XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, name);                       
328                         return new XmlMembersMapping (name.Name, name.Namespace, mapping);
329                 }
330                 
331                 public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names)
332                 {
333                         XmlMemberMapping[] mapping = new XmlMemberMapping [names.Length];
334                         for (int n=0; n<names.Length; n++)
335                         {
336                                 XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (names[n], typeof (XmlSchemaElement));
337                                 if (elem == null) throw new InvalidOperationException ("Schema element '" + names[n] + "' not found");
338                                 
339                                 XmlQualifiedName typeQName = new XmlQualifiedName ("Message", names[n].Namespace);
340                                 XmlTypeMapping tmap;
341                                 TypeData td = GetElementTypeData (typeQName, elem, names[n], out tmap);
342                                 
343                                 mapping[n] = ImportMemberMapping (elem.Name, typeQName.Namespace, elem.IsNillable, td, tmap, n);
344                         }
345                         BuildPendingMaps ();
346                         return new XmlMembersMapping (mapping);
347                 }
348                 
349 #if NET_2_0
350                 [MonoTODO]
351                 public XmlMembersMapping ImportMembersMapping (string name, string ns, SoapSchemaMember[] members)
352                 {
353                         throw new NotImplementedException ();
354                 }
355                 
356                 public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName)
357                 {
358                         return ImportSchemaType (typeName, typeof (object));
359                 }
360                 
361                 public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType)
362                 {
363                         return ImportSchemaType (typeName, typeof (object), false);
364                 }
365                 
366                 [MonoTODO ("baseType and baseTypeCanBeIndirect are ignored")]
367                 public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType, bool baseTypeCanBeIndirect)
368                 {
369                         XmlSchemaType stype =
370                                 (XmlSchemaType) schemas.Find (typeName, typeof (XmlSchemaComplexType)) ??
371                                 (XmlSchemaType) schemas.Find (typeName, typeof (XmlSchemaSimpleType));
372                         return ImportTypeCommon (typeName, typeName, stype, true);
373                 }
374 #endif
375                 
376                 internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember[] members, bool hasWrapperElement)
377                 {
378                         XmlMemberMapping[] mapping = new XmlMemberMapping [members.Length];
379                         for (int n=0; n<members.Length; n++)
380                         {
381                                 TypeData td = GetTypeData (members[n].MemberType, null, false); // FIXME: isNullable could be true?
382                                 XmlTypeMapping tmap = GetTypeMapping (td);
383                                 mapping[n] = ImportMemberMapping (members[n].MemberName, members[n].MemberType.Namespace, true, td, tmap, n);
384                         }
385                         BuildPendingMaps ();
386                         return new XmlMembersMapping (name, ns, hasWrapperElement, false, mapping);
387                 }
388                 
389                 internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember member)
390                 {
391                         XmlSchemaComplexType stype = schemas.Find (member.MemberType, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
392                         if (stype == null) throw new InvalidOperationException ("Schema type '" + member.MemberType + "' not found or not valid");
393
394                         XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, member.MemberType);                  
395                         return new XmlMembersMapping (name, ns, mapping);
396                 }
397                 
398                 XmlMemberMapping[] ImportMembersMappingComposite (XmlSchemaComplexType stype, XmlQualifiedName refer)
399                 {
400                         if (stype.Particle == null) 
401                                 return new XmlMemberMapping [0];
402
403                         ClassMap cmap = new ClassMap ();
404                         
405                         XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
406                         if (seq == null) throw new InvalidOperationException ("Schema element '" + refer + "' cannot be imported as XmlMembersMapping");
407
408                         CodeIdentifiers classIds = new CodeIdentifiers ();
409                         ImportParticleComplexContent (refer, cmap, seq, classIds, false);
410                         ImportAttributes (refer, cmap, stype.Attributes, stype.AnyAttribute, classIds);
411
412                         BuildPendingMaps ();
413
414                         int n = 0;
415                         XmlMemberMapping[] mapping = new XmlMemberMapping [cmap.AllMembers.Count];
416                         foreach (XmlTypeMapMember mapMem in cmap.AllMembers)
417                                 mapping[n++] = new XmlMemberMapping (mapMem.Name, refer.Namespace, mapMem, encodedFormat);
418                                 
419                         return mapping;
420                 }
421                 
422                 XmlMemberMapping ImportMemberMapping (string name, string ns, bool isNullable, TypeData type, XmlTypeMapping emap, int order)
423                 {
424                         XmlTypeMapMemberElement mapMem;
425                         
426                         if (type.IsListType)
427                                 mapMem = new XmlTypeMapMemberList ();
428                         else
429                                 mapMem = new XmlTypeMapMemberElement ();
430                         
431                         mapMem.Name = name;
432                         mapMem.TypeData = type;
433                         mapMem.ElementInfo.Add (CreateElementInfo (ns, mapMem, name, type, isNullable, XmlSchemaForm.None, emap, order));
434                         return new XmlMemberMapping (name, ns, mapMem, encodedFormat);
435                 }
436                 
437                 [MonoTODO]
438                 public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names, Type baseType, bool baseTypeCanBeIndirect)
439                 {
440                         throw new NotImplementedException ();
441                 }
442
443                 public XmlTypeMapping ImportTypeMapping (XmlQualifiedName name)
444                 {
445                         XmlQualifiedName qname;
446                         XmlSchemaType stype;
447
448                         XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
449                         if (!LocateElement (elem, out qname, out stype))
450                                 throw new InvalidOperationException (String.Format ("'{0}' is missing.", name));
451                         return ImportTypeCommon (name, qname, stype, elem.IsNillable);
452                 }
453
454                 // FIXME: name and qname are confusing. Rename one either
455                 // (name is in schema itself, qname is for actual processing.
456                 //  For example simple types have qname as in xsd namespace.)
457                 private XmlTypeMapping ImportTypeCommon (XmlQualifiedName name, XmlQualifiedName qname, XmlSchemaType stype, bool isNullable)
458                 {
459                         if (stype == null) {
460                                 if (qname == anyType) {
461                                         // Importing anyType.
462                                         XmlTypeMapping xmap = GetTypeMapping (TypeTranslator.GetTypeData (typeof (object)));
463                                         // This also means, all complexTypes
464                                         // are imported as well.
465                                         BuildPendingMaps ();
466                                         return xmap;
467                                 } else {
468                                         // Importing a primitive type
469                                         TypeData td = TypeTranslator.GetPrimitiveTypeData (qname.Name);
470                                         return ReflectType (td, name.Namespace);
471                                 }
472                         }
473                         
474                         XmlTypeMapping map = GetRegisteredTypeMapping (qname);
475                         if (map != null) return map;
476                         
477                         if (stype is XmlSchemaSimpleType)
478                                 return ImportClassSimpleType (stype.QualifiedName, (XmlSchemaSimpleType) stype, name);
479                         
480                         map = CreateTypeMapping (qname, SchemaTypes.Class, name);
481                         map.Documentation = GetDocumentation (stype);
482                         map.IsNullable = isNullable;
483                         RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
484                         
485                         BuildPendingMaps ();
486                         return map;
487                 }
488
489                 bool LocateElement (XmlQualifiedName name, out XmlQualifiedName qname, out XmlSchemaType stype)
490                 {
491                         XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
492                         return LocateElement (elem, out qname, out stype);
493                 }
494
495                 bool LocateElement (XmlSchemaElement elem, out XmlQualifiedName qname, out XmlSchemaType stype)
496                 {
497                         qname = null;
498                         stype = null;
499                         
500                         if (elem == null) return false;
501
502                         // The root element must be an element with complex type
503
504                         if (elem.SchemaType != null)
505                         {
506                                 stype = elem.SchemaType;
507                                 qname = elem.QualifiedName;
508                         }
509                         else if (elem.ElementType == XmlSchemaComplexType.AnyType)
510                         {
511                                 qname = anyType;
512                                 return true;
513                         }
514                         else
515                         {
516                                 if (elem.SchemaTypeName.IsEmpty) return false;
517                                 
518                                 object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
519                                 if (type == null) type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaSimpleType));
520                                 if (type == null) {
521                                         if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) {
522                                                 qname = elem.SchemaTypeName;
523                                                 return true;
524                                         }
525                                         throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
526                                 }
527                                 stype = (XmlSchemaType) type;
528                                 qname = stype.QualifiedName;
529                                 
530                                 XmlSchemaType btype = stype.BaseSchemaType as XmlSchemaType;
531                                 if (btype != null && btype.QualifiedName == elem.SchemaTypeName)
532                                         throw new InvalidOperationException ("Cannot import schema for type '" + elem.SchemaTypeName.Name + "' from namespace '" + elem.SchemaTypeName.Namespace + "'. Redefine not supported");
533                         }
534
535                         //if (stype is XmlSchemaSimpleType) return false;
536                         return true;
537                 }
538
539                 XmlTypeMapping ImportType (XmlQualifiedName name, XmlQualifiedName root, bool throwOnError)
540                 {
541                         XmlTypeMapping map = GetRegisteredTypeMapping (name);
542                         if (map != null) {
543                                 map.UpdateRoot (root);
544                                 return map;
545                         }
546
547                         XmlSchemaType type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaComplexType));
548                         if (type == null) type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaSimpleType));
549                         
550                         if (type == null) 
551                         {
552                                 if (throwOnError) {
553                                         if (name.Namespace == XmlSerializer.EncodingNamespace)
554                                                 throw new InvalidOperationException ("Referenced type '" + name + "' valid only for encoded SOAP.");
555                                         else
556                                                 throw new InvalidOperationException ("Referenced type '" + name + "' not found.");
557                                 } else
558                                         return null;
559                         }
560
561                         return ImportType (name, type, root);
562                 }
563
564                 XmlTypeMapping ImportClass (XmlQualifiedName name)
565                 {
566                         XmlTypeMapping map = ImportType (name, null, true);
567                         if (map.TypeData.SchemaType == SchemaTypes.Class) return map;
568                         XmlSchemaComplexType stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
569                         return CreateClassMap (name, stype, new XmlQualifiedName (map.ElementName, map.Namespace));
570                 }
571                 
572                 XmlTypeMapping ImportType (XmlQualifiedName name, XmlSchemaType stype, XmlQualifiedName root)
573                 {
574                         XmlTypeMapping map = GetRegisteredTypeMapping (name);
575                         if (map != null) {
576                                 XmlSchemaComplexType ct = stype as XmlSchemaComplexType;
577                                 if (map.TypeData.SchemaType != SchemaTypes.Class || ct == null || !CanBeArray (name, ct)) {
578                                         map.UpdateRoot (root);
579                                         return map;
580                                 }
581                                         
582                                 // The map was initially imported as a class, but it turns out that it is an
583                                 // array. It has to be imported now as array.
584                         }
585                         
586                         if (stype is XmlSchemaComplexType)
587                                 return ImportClassComplexType (name, (XmlSchemaComplexType) stype, root);
588                         else if (stype is XmlSchemaSimpleType)
589                                 return ImportClassSimpleType (name, (XmlSchemaSimpleType) stype, root);
590
591                         throw new NotSupportedException ("Schema type not supported: " + stype.GetType ());
592                 }
593
594                 XmlTypeMapping ImportClassComplexType (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
595                 {
596                         // The need for fixups: If the complex type is an array, then to get the type of the
597                         // array we need first to get the type of the items of the array.
598                         // But if one of the item types or its children has a referece to this type array,
599                         // then we enter in an infinite loop. This does not happen with class types because
600                         // the class map is registered before parsing the children. We can't do the same
601                         // with the array type because to register the array map we need the type of the array.
602
603                         if (CanBeArray (typeQName, stype))
604                         {
605                                 TypeData typeData;
606                                 ListMap listMap = BuildArrayMap (typeQName, stype, out typeData);
607                                 if (listMap != null)
608                                 {
609                                         XmlTypeMapping map = CreateArrayTypeMapping (typeQName, typeData);
610                                         map.ObjectMap = listMap;
611                                         return map;
612                                 }
613
614                                 // After all, it is not an array. Create a class map then.
615                         }
616                         else if (CanBeIXmlSerializable (stype))
617                         {
618                                 return ImportXmlSerializableMapping (typeQName.Namespace);
619                         }
620
621                         // Register the map right now but do not build it,
622                         // This will avoid loops.
623
624                         return CreateClassMap (typeQName, stype, root);
625                 }
626                 
627                 XmlTypeMapping CreateClassMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
628                 {
629                         XmlTypeMapping map = CreateTypeMapping (typeQName, SchemaTypes.Class, root);
630                         map.Documentation = GetDocumentation (stype);
631                         RegisterMapFixup (map, typeQName, stype);
632                         return map;
633                 }
634
635                 ArrayList fixup_registered_types = new ArrayList ();
636
637                 void RegisterMapFixup (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
638                 {
639                         // This check is introduced for bug #650117, but might be too wide to catch erroneous cases...
640                         if (fixup_registered_types.Contains (stype))
641                                 throw new InvalidOperationException (String.Format ("Circular dependency for schema type {0} in namespace {1}", map.ElementName, map.Namespace));
642                         fixup_registered_types.Add (stype);
643                         MapFixup fixup = new MapFixup ();
644                         fixup.Map = map;
645                         fixup.SchemaType = stype;
646                         fixup.TypeName = typeQName;
647                         pendingMaps.Enqueue (fixup);
648                 }
649
650                 void BuildPendingMaps ()
651                 {
652                         while (pendingMaps.Count > 0) {
653                                 MapFixup fixup  = (MapFixup) pendingMaps.Dequeue ();
654                                 if (fixup.Map.ObjectMap == null) {
655                                         BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
656                                         if (fixup.Map.ObjectMap == null) pendingMaps.Enqueue (fixup);
657                                 }
658                         }
659                 }
660
661                 void BuildPendingMap (XmlTypeMapping map)
662                 {
663                         if (map.ObjectMap != null) return;
664
665                         foreach (MapFixup fixup in pendingMaps)
666                         {
667                                 if (fixup.Map == map) {
668                                         BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
669                                         return;
670                                 }
671                         }
672                         throw new InvalidOperationException ("Can't complete map of type " + map.XmlType + " : " + map.Namespace);
673                 }
674
675                 void BuildClassMap (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
676                 {
677                         CodeIdentifiers classIds = new CodeIdentifiers();
678                         classIds.AddReserved (map.TypeData.TypeName);
679
680                         ClassMap cmap = new ClassMap ();
681                         map.ObjectMap = cmap;
682                         bool isMixed = stype.IsMixed;
683
684                         if (stype.Particle != null)
685                                 ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, isMixed);
686                         else
687                         {
688                                 if (stype.ContentModel is XmlSchemaSimpleContent) {
689                                         ImportSimpleContent (typeQName, map, (XmlSchemaSimpleContent)stype.ContentModel, classIds, isMixed);
690                                 }
691                                 else if (stype.ContentModel is XmlSchemaComplexContent) {
692                                         ImportComplexContent (typeQName, map, (XmlSchemaComplexContent)stype.ContentModel, classIds, isMixed);
693                                 }
694                         }
695
696                         ImportAttributes (typeQName, cmap, stype.Attributes, stype.AnyAttribute, classIds);
697                         ImportExtensionTypes (typeQName);
698
699                         if (isMixed) AddTextMember (typeQName, cmap, classIds);
700                         
701                         AddObjectDerivedMap (map);
702                 }
703                 
704                 void ImportAttributes (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection atts, XmlSchemaAnyAttribute anyat, CodeIdentifiers classIds)
705                 {
706                         atts = CollectAttributeUsesNonOverlap (atts, cmap);
707
708                         if (anyat != null)
709                         {
710                         XmlTypeMapMemberAnyAttribute member = new XmlTypeMapMemberAnyAttribute ();
711                                 member.Name = classIds.AddUnique ("AnyAttribute", member);
712                                 member.TypeData = TypeTranslator.GetTypeData (typeof(XmlAttribute[]));
713                                 cmap.AddMember (member);
714                         }
715                         
716                         foreach (XmlSchemaObject at in atts)
717                         {
718                                 if (at is XmlSchemaAttribute)
719                                 {
720                                         string ns;
721                                         XmlSchemaAttribute attr = (XmlSchemaAttribute)at;
722                                         XmlSchemaAttribute refAttr = GetRefAttribute (typeQName, attr, out ns);
723                                         XmlTypeMapMemberAttribute member = new XmlTypeMapMemberAttribute ();
724                                         member.Name = classIds.AddUnique (CodeIdentifier.MakeValid (refAttr.Name), member);
725                                         member.Documentation = GetDocumentation (attr);
726                                         member.AttributeName = refAttr.Name;
727                                         member.Namespace = ns;
728                                         member.Form = refAttr.Form;
729                                         member.TypeData = GetAttributeTypeData (typeQName, attr);
730                                         
731                                         if (refAttr.DefaultValue != null) 
732                                                 member.DefaultValue = ImportDefaultValue (member.TypeData, refAttr.DefaultValue);
733                                         else if (member.TypeData.IsValueType)
734                                                 member.IsOptionalValueType = (refAttr.ValidatedUse != XmlSchemaUse.Required);
735                                                 
736                                         if (member.TypeData.IsComplexType)
737                                                 member.MappedType = GetTypeMapping (member.TypeData);
738                                         cmap.AddMember (member);
739                                 }
740                                 else if (at is XmlSchemaAttributeGroupRef)
741                                 {
742                                         XmlSchemaAttributeGroupRef gref = (XmlSchemaAttributeGroupRef)at;
743                                         XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
744                                         ImportAttributes (typeQName, cmap, grp.Attributes, grp.AnyAttribute, classIds);
745                                 }
746                         }
747                 }
748                 
749                 IEnumerable<XmlSchemaAttribute> EnumerateAttributes (XmlSchemaObjectCollection col, List<XmlSchemaAttributeGroup> recurse)
750                 {
751                         foreach (var o in col) {
752                                 if (o is XmlSchemaAttributeGroupRef) {
753                                         var gr = (XmlSchemaAttributeGroupRef) o;
754                                         var g = FindRefAttributeGroup (gr.RefName);
755                                         if (recurse.Contains (g))
756                                                 continue;
757                                         recurse.Add (g);
758                                         if (g == null)
759                                                 throw new InvalidOperationException (string.Format ("Referenced AttributeGroup '{0}' was not found.", gr.RefName));
760                                         foreach (var a in EnumerateAttributes (g.Attributes, recurse))
761                                                 yield return a;
762                                 }
763                                 else
764                                         yield return (XmlSchemaAttribute) o;
765                         }
766                 }
767
768                 // Attributes might be redefined, so there is an existing attribute for the same name, skip it.
769                 // FIXME: this is nothing more than just a hack.
770                 // Basically it should use
771                 // XmlSchemaComplexType.AttributeUses.
772                 XmlSchemaObjectCollection CollectAttributeUsesNonOverlap (
773                         XmlSchemaObjectCollection src, ClassMap map)
774                 {
775                         XmlSchemaObjectCollection atts = new XmlSchemaObjectCollection ();
776                         foreach (var a in EnumerateAttributes (src, new List<XmlSchemaAttributeGroup> ()))
777                                 if (map.GetAttribute (a.QualifiedName.Name, a.QualifiedName.Namespace) == null)
778                                         atts.Add (a);
779                         return atts;
780                 }
781
782                 ListMap BuildArrayMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, out TypeData arrayTypeData)
783                 {
784                         if (encodedFormat)
785                         {
786                                 XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
787                                 XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
788                                 XmlSchemaAttribute arrayTypeAt = FindArrayAttribute (rest.Attributes);
789                                 
790                                 if (arrayTypeAt != null)
791                                 {
792                                         XmlAttribute[] uatts = arrayTypeAt.UnhandledAttributes;
793                                         if (uatts == null || uatts.Length == 0) throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
794                                         
795                                         XmlAttribute xat = null;
796                                         foreach (XmlAttribute at in uatts)
797                                                 if (at.LocalName == "arrayType" && at.NamespaceURI == XmlSerializer.WsdlNamespace)
798                                                         { xat = at; break; }
799                                         
800                                         if (xat == null) 
801                                                 throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
802         
803                                         string name, ns, dims;
804                                         TypeTranslator.ParseArrayType (xat.Value, out name, out ns, out dims);
805                                         return BuildEncodedArrayMap (name + dims, ns, out arrayTypeData);
806                                 }
807                                 else
808                                 {
809                                         XmlSchemaElement elem = null;
810                                         XmlSchemaSequence seq = rest.Particle as XmlSchemaSequence;
811                                         if (seq != null && seq.Items.Count == 1) 
812                                                 elem = seq.Items[0] as XmlSchemaElement;
813                                         else {
814                                                 XmlSchemaAll all = rest.Particle as XmlSchemaAll;
815                                                 if (all != null && all.Items.Count == 1)
816                                                         elem = all.Items[0] as XmlSchemaElement;
817                                         }
818                                         if (elem == null)
819                                                 throw new InvalidOperationException ("Unknown array format");
820                                                 
821                                         return BuildEncodedArrayMap (elem.SchemaTypeName.Name + "[]", elem.SchemaTypeName.Namespace, out arrayTypeData);
822                                 }
823                         }
824                         else
825                         {
826                                 ClassMap cmap = new ClassMap ();
827                                 CodeIdentifiers classIds = new CodeIdentifiers();
828                                 ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, stype.IsMixed);
829
830                                 XmlTypeMapMemberFlatList list = (cmap.AllMembers.Count == 1) ? cmap.AllMembers[0] as XmlTypeMapMemberFlatList : null;
831                                 if (list != null && list.ChoiceMember == null)
832                                 {
833                                         arrayTypeData = list.TypeData;
834                                         return list.ListMap;
835                                 }
836                                 else
837                                 {
838                                         arrayTypeData = null;
839                                         return null;
840                                 }
841                         }
842                 }
843                 
844                 ListMap BuildEncodedArrayMap (string type, string ns, out TypeData arrayTypeData)
845                 {
846                         ListMap map = new ListMap ();
847                         
848                         int i = type.LastIndexOf ("[");
849                         if (i == -1) throw new InvalidOperationException ("Invalid arrayType value: " + type);
850                         if (type.IndexOf (",",i) != -1) throw new InvalidOperationException ("Multidimensional arrays are not supported");
851                         
852                         string itemType = type.Substring (0,i);
853                         
854                         TypeData itemTypeData;
855                         if (itemType.IndexOf ("[") != -1) 
856                         {
857                                 ListMap innerListMap = BuildEncodedArrayMap (itemType, ns, out itemTypeData);
858                                 
859                                 int dims = itemType.Split ('[').Length - 1;
860                                 string name = TypeTranslator.GetArrayName (type, dims);
861                                 XmlQualifiedName qname = new XmlQualifiedName (name, ns);
862                                 XmlTypeMapping tmap = CreateArrayTypeMapping (qname, itemTypeData);
863                                 tmap.ObjectMap = innerListMap;
864                         }
865                         else
866                         {
867                                 itemTypeData = GetTypeData (new XmlQualifiedName (itemType, ns), null, false);
868                         }
869                         
870                         arrayTypeData = itemTypeData.ListTypeData;
871                         
872                         map.ItemInfo = new XmlTypeMapElementInfoList();
873                         map.ItemInfo.Add (CreateElementInfo ("", null, "Item", itemTypeData, true, XmlSchemaForm.None, -1));
874                         return map;
875                 }
876                 
877                 XmlSchemaAttribute FindArrayAttribute (XmlSchemaObjectCollection atts)
878                 {
879                         foreach (object ob in atts)
880                         {
881                                 XmlSchemaAttribute att = ob as XmlSchemaAttribute;
882                                 if (att != null && att.RefName == arrayTypeRefName) return att;
883                                 
884                                 XmlSchemaAttributeGroupRef gref = ob as XmlSchemaAttributeGroupRef;
885                                 if (gref != null)
886                                 {
887                                         XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
888                                         att = FindArrayAttribute (grp.Attributes);
889                                         if (att != null) return att;
890                                 }
891                         }
892                         return null;
893                 }
894
895                 void ImportParticleComplexContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool isMixed)
896                 {
897                         ImportParticleContent (typeQName, cmap, particle, classIds, false, ref isMixed);
898                         if (isMixed) AddTextMember (typeQName, cmap, classIds);
899                 }
900                 
901                 void AddTextMember (XmlQualifiedName typeQName, ClassMap cmap, CodeIdentifiers classIds)
902                 {
903                         if (cmap.XmlTextCollector == null)
904                         {
905                                 XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
906                                 member.Name = classIds.AddUnique ("Text", member);
907                                 member.TypeData = TypeTranslator.GetTypeData (typeof(string[]));
908                                 member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData.ListItemTypeData));
909                                 member.IsXmlTextCollector = true;
910                                 member.ListMap = new ListMap ();
911                                 member.ListMap.ItemInfo = member.ElementInfo;
912                                 cmap.AddMember (member);
913                         }
914                 }
915                 
916                 void ImportParticleContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
917                 {
918                         if (particle == null) return;
919                         
920                         if (particle is XmlSchemaGroupRef)
921                                 particle = GetRefGroupParticle ((XmlSchemaGroupRef)particle);
922
923                         if (particle.MaxOccurs > 1) multiValue = true;
924                         
925                         if (particle is XmlSchemaSequence) {
926                                 ImportSequenceContent (typeQName, cmap, ((XmlSchemaSequence)particle).Items, classIds, multiValue, ref isMixed);
927                         }
928                         else if (particle is XmlSchemaChoice) {
929                                 if (((XmlSchemaChoice)particle).Items.Count == 1)
930                                         ImportSequenceContent (typeQName, cmap, ((XmlSchemaChoice)particle).Items, classIds, multiValue, ref isMixed);
931                                 else
932                                         ImportChoiceContent (typeQName, cmap, (XmlSchemaChoice)particle, classIds, multiValue);
933                         }
934                         else if (particle is XmlSchemaAll) {
935                                 ImportSequenceContent (typeQName, cmap, ((XmlSchemaAll)particle).Items, classIds, multiValue, ref isMixed);
936                         }
937                 }
938
939                 void ImportSequenceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection items, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
940                 {
941                         foreach (XmlSchemaObject item in items)
942                         {
943                                 if (item is XmlSchemaElement)
944                                 {
945                                         string ns;
946                                         XmlSchemaElement elem = (XmlSchemaElement) item;
947                                         XmlTypeMapping emap;
948                                         TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
949                                         XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
950
951                                         if (elem.MaxOccurs == 1 && !multiValue)
952                                         {
953                                                 XmlTypeMapMemberElement member = null;
954                                                 if (typeData.SchemaType != SchemaTypes.Array)
955                                                 {
956                                                         member = new XmlTypeMapMemberElement ();
957                                                         if (refElem.DefaultValue != null) member.DefaultValue = ImportDefaultValue (typeData, refElem.DefaultValue);
958                                                 }
959                                                 else if (GetTypeMapping (typeData).IsSimpleType)
960                                                 {
961                                                         // It is a simple list (space separated list).
962                                                         // Since this is not supported, map as a single item value
963                                                         member = new XmlTypeMapMemberElement ();
964 #if NET_2_0
965                                                         // In MS.NET those types are mapped to a string
966                                                         typeData = TypeTranslator.GetTypeData(typeof(string));
967 #else
968                                                         typeData = typeData.ListItemTypeData;
969 #endif
970                                                 }
971                                                 else
972                                                         member = new XmlTypeMapMemberList ();
973
974                                                 if (elem.MinOccurs == 0 && typeData.IsValueType)
975                                                         member.IsOptionalValueType = true;
976
977                                                 member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
978                                                 member.Documentation = GetDocumentation (elem);
979                                                 member.TypeData = typeData;
980                                                 member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap, items.IndexOf (item)));
981                                                 cmap.AddMember (member);
982                                         }
983                                         else
984                                         {
985                                                 XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
986                                                 member.ListMap = new ListMap ();
987                                                 member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
988                                                 member.Documentation = GetDocumentation (elem);
989                                                 member.TypeData = typeData.ListTypeData;
990                                                 member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap, items.IndexOf (item)));
991                                                 member.ListMap.ItemInfo = member.ElementInfo;
992                                                 cmap.AddMember (member);
993                                         }
994                                 }
995                                 else if (item is XmlSchemaAny)
996                                 {
997                                         XmlSchemaAny elem = (XmlSchemaAny) item;
998                                         XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement ();
999                                         member.Name = classIds.AddUnique ("Any", member);
1000                                         member.Documentation = GetDocumentation (elem);
1001                                         
1002                                         Type ctype;
1003                                         if (elem.MaxOccurs != 1 || multiValue)
1004                                                 ctype = isMixed ? typeof(XmlNode[]) : typeof(XmlElement[]);
1005                                         else
1006                                                 ctype = isMixed ? typeof(XmlNode) : typeof(XmlElement);
1007
1008                                         member.TypeData = TypeTranslator.GetTypeData (ctype);
1009                                         XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, member.TypeData);
1010                                         einfo.IsUnnamedAnyElement = true;
1011                                         member.ElementInfo.Add (einfo);
1012
1013                                         if (isMixed)
1014                                         {
1015                                                 einfo = CreateTextElementInfo (typeQName.Namespace, member, member.TypeData);
1016                                                 member.ElementInfo.Add (einfo);
1017                                                 member.IsXmlTextCollector = true;
1018                                                 isMixed = false;        //Allow only one XmlTextAttribute
1019                                         }
1020                                         
1021                                         cmap.AddMember (member);
1022                                 }
1023                                 else if (item is XmlSchemaParticle) {
1024                                         ImportParticleContent (typeQName, cmap, (XmlSchemaParticle)item, classIds, multiValue, ref isMixed);
1025                                 }
1026                         }
1027                 }
1028                 
1029                 object ImportDefaultValue (TypeData typeData, string value)
1030                 {
1031                         if (typeData.SchemaType == SchemaTypes.Enum) {
1032                                 XmlTypeMapping map = GetTypeMapping (typeData);
1033                                 EnumMap emap = (EnumMap) map.ObjectMap;
1034                                 string res = emap.GetEnumName (map.TypeFullName, value);
1035                                 if (res == null) throw new InvalidOperationException ("'" + value + "' is not a valid enumeration value");
1036                                 return res;
1037                         } else
1038                                 return XmlCustomFormatter.FromXmlString (typeData, value);
1039                 }
1040                 
1041                 void ImportChoiceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaChoice choice, CodeIdentifiers classIds, bool multiValue)
1042                 {
1043                         XmlTypeMapElementInfoList choices = new XmlTypeMapElementInfoList ();
1044                         multiValue = ImportChoices (typeQName, null, choices, choice.Items) || multiValue;
1045                         if (choices.Count == 0) return;
1046
1047                         if (choice.MaxOccurs > 1) multiValue = true;
1048
1049                         XmlTypeMapMemberElement member;
1050                         if (multiValue)
1051                         {
1052                                 member = new XmlTypeMapMemberFlatList ();
1053                                 member.Name = classIds.AddUnique ("Items", member);
1054                                 ListMap listMap = new ListMap ();
1055                                 listMap.ItemInfo = choices;
1056                                 ((XmlTypeMapMemberFlatList)member).ListMap = listMap;
1057                         }
1058                         else
1059                         {
1060                                 member = new XmlTypeMapMemberElement ();
1061                                 member.Name = classIds.AddUnique ("Item", member);
1062                         }
1063                         
1064                         // If all choices have the same type, use that type for the member.
1065                         // If not use System.Object.
1066                         // If there are at least two choices with the same type, use a choice
1067                         // identifier attribute
1068
1069                         TypeData typeData = null;
1070                         bool twoEqual = false;
1071                         bool allEqual = true;
1072                         Hashtable types = new Hashtable ();
1073
1074                         for (int n = choices.Count - 1; n >= 0; n--)
1075                         {
1076                                 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) choices [n];
1077                                 
1078                                 // In some complex schemas, we may end up with several options
1079                                 // with the same name. It is better to ignore the extra options
1080                                 // than to crash. It's the best we can do, and btw it works
1081                                 // better than in MS.NET.
1082                                 
1083                                 if (cmap.GetElement (einfo.ElementName, einfo.Namespace, einfo.ExplicitOrder) != null ||
1084                                         choices.IndexOfElement (einfo.ElementName, einfo.Namespace) != n)
1085                                 {
1086                                         choices.RemoveAt (n);
1087                                         continue;
1088                                 }
1089                                         
1090                                 if (types.ContainsKey (einfo.TypeData)) twoEqual = true;
1091                                 else types.Add (einfo.TypeData, einfo);
1092
1093                                 TypeData choiceType = einfo.TypeData;
1094                                 if (choiceType.SchemaType == SchemaTypes.Class)
1095                                 {
1096                                         // When comparing class types, use the most generic class in the
1097                                         // inheritance hierarchy
1098
1099                                         XmlTypeMapping choiceMap = GetTypeMapping (choiceType);
1100                                         BuildPendingMap (choiceMap);
1101                                         while (choiceMap.BaseMap != null) {
1102                                                 choiceMap = choiceMap.BaseMap;
1103                                                 BuildPendingMap (choiceMap);
1104                                                 choiceType = choiceMap.TypeData;
1105                                         }
1106                                 }
1107                                 
1108                                 if (typeData == null) typeData = choiceType;
1109                                 else if (typeData != choiceType) allEqual = false;
1110                         }
1111
1112                         if (!allEqual)
1113                                 typeData = TypeTranslator.GetTypeData (typeof(object));
1114
1115                         if (twoEqual)
1116                         {
1117                                 // Create the choice member
1118                                 XmlTypeMapMemberElement choiceMember = new XmlTypeMapMemberElement ();
1119                                 choiceMember.Ignore = true;
1120                                 choiceMember.Name = classIds.AddUnique (member.Name + "ElementName", choiceMember);
1121                                 member.ChoiceMember = choiceMember.Name;
1122
1123                                 // Create the choice enum
1124                                 XmlTypeMapping enumMap = CreateTypeMapping (new XmlQualifiedName (member.Name + "ChoiceType", typeQName.Namespace), SchemaTypes.Enum, null);
1125                                 enumMap.IncludeInSchema = false;
1126
1127                                 CodeIdentifiers codeIdents = new CodeIdentifiers ();
1128                                 EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [choices.Count];
1129                                 for (int n=0; n<choices.Count; n++)
1130                                 {
1131                                         XmlTypeMapElementInfo it =(XmlTypeMapElementInfo) choices[n];
1132                                         bool extraNs = (it.Namespace != null && it.Namespace != "" && it.Namespace != typeQName.Namespace);
1133                                         string xmlName = extraNs ? it.Namespace + ":" + it.ElementName : it.ElementName;
1134                                         string enumName = codeIdents.AddUnique (CodeIdentifier.MakeValid (it.ElementName), it);
1135                                         members [n] = new EnumMap.EnumMapMember (xmlName, enumName);
1136                                 }
1137                                 enumMap.ObjectMap = new EnumMap (members, false);
1138
1139                                 choiceMember.TypeData = multiValue ? enumMap.TypeData.ListTypeData : enumMap.TypeData;
1140                                 choiceMember.ElementInfo.Add (CreateElementInfo (typeQName.Namespace, choiceMember, choiceMember.Name, choiceMember.TypeData, false, XmlSchemaForm.None, -1));
1141                                 cmap.AddMember (choiceMember);
1142                         }
1143                         
1144                         if (typeData == null)
1145                                 return;
1146         
1147                         if (multiValue)
1148                                 typeData = typeData.ListTypeData;
1149
1150                         member.ElementInfo = choices;
1151                         member.Documentation = GetDocumentation (choice);
1152                         member.TypeData = typeData;
1153                         cmap.AddMember (member);
1154                 }
1155
1156                 bool ImportChoices (XmlQualifiedName typeQName, XmlTypeMapMember member, XmlTypeMapElementInfoList choices, XmlSchemaObjectCollection items)
1157                 {
1158                         bool multiValue = false;
1159                         foreach (XmlSchemaObject titem in items)
1160                         {
1161                                 XmlSchemaObject item = titem;
1162                                 if (item is XmlSchemaGroupRef)
1163                                         item = GetRefGroupParticle ((XmlSchemaGroupRef)item);
1164
1165                                 if (item is XmlSchemaElement)
1166                                 {
1167                                         string ns;
1168                                         XmlSchemaElement elem = (XmlSchemaElement) item;
1169                                         XmlTypeMapping emap;
1170                                         TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
1171                                         XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
1172                                         choices.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap, -1));
1173                                         if (elem.MaxOccurs > 1) multiValue = true;
1174                                 }
1175                                 else if (item is XmlSchemaAny)
1176                                 {
1177                                         XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
1178                                         einfo.IsUnnamedAnyElement = true;
1179                                         choices.Add (einfo);
1180                                 }
1181                                 else if (item is XmlSchemaChoice) {
1182                                         multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaChoice)item).Items) || multiValue;
1183                                 }
1184                                 else if (item is XmlSchemaSequence) {
1185                                         multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaSequence)item).Items) || multiValue;
1186                                 }
1187                         }
1188                         return multiValue;
1189                 }
1190
1191                 void ImportSimpleContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaSimpleContent content, CodeIdentifiers classIds, bool isMixed)
1192                 {
1193                         XmlSchemaSimpleContentExtension ext = content.Content as XmlSchemaSimpleContentExtension;
1194                         ClassMap cmap = (ClassMap)map.ObjectMap;
1195                         XmlQualifiedName qname = GetContentBaseType (content.Content);
1196                         TypeData simpleType = null;
1197                         
1198                         if (!IsPrimitiveTypeNamespace (qname.Namespace))
1199                         {
1200                                 // Add base map members to this map
1201         
1202                                 XmlTypeMapping baseMap = ImportType (qname, null, true);
1203                                 BuildPendingMap (baseMap);
1204                                 
1205                                 if (baseMap.IsSimpleType) {
1206                                         simpleType = baseMap.TypeData;
1207                                 } else {
1208                                         ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
1209                 
1210                                         foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
1211                                                 cmap.AddMember (member);
1212                 
1213                                         map.BaseMap = baseMap;
1214                                         baseMap.DerivedTypes.Add (map);
1215                                 }
1216                         }
1217                         else
1218                                 simpleType = FindBuiltInType (qname);
1219                                 
1220                         if (simpleType != null) {
1221                                 XmlTypeMapMemberElement member = new XmlTypeMapMemberElement ();
1222                                 member.Name = classIds.AddUnique("Value", member);
1223                                 member.TypeData = simpleType;
1224                                 member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData));
1225                                 member.IsXmlTextCollector = true;
1226                                 cmap.AddMember (member);
1227                         }
1228                         
1229                         if (ext != null)
1230                                 ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
1231                 }
1232
1233                 TypeData FindBuiltInType (XmlQualifiedName qname)
1234                 {
1235                         XmlSchemaComplexType ct = (XmlSchemaComplexType) schemas.Find (qname, typeof(XmlSchemaComplexType));
1236                         if (ct != null)
1237                         {
1238                                 XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;
1239                                 if (sc == null) throw new InvalidOperationException ("Invalid schema");
1240                                 return FindBuiltInType (GetContentBaseType (sc.Content));
1241                         }
1242                         
1243                         XmlSchemaSimpleType st = (XmlSchemaSimpleType) schemas.Find (qname, typeof(XmlSchemaSimpleType));
1244                         if (st != null)
1245                                 return FindBuiltInType (qname, st);
1246
1247                         if (IsPrimitiveTypeNamespace (qname.Namespace))
1248                                 return TypeTranslator.GetPrimitiveTypeData (qname.Name);
1249
1250                         throw new InvalidOperationException ("Definition of type '" + qname + "' not found");
1251                 }
1252
1253                 TypeData FindBuiltInType (XmlQualifiedName qname, XmlSchemaSimpleType st)
1254                 {
1255                         if (CanBeEnum (st) && qname != null)
1256                                 return ImportType (qname, null, true).TypeData;
1257
1258                         if (st.Content is XmlSchemaSimpleTypeRestriction) {
1259                                 XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction) st.Content;
1260                                 XmlQualifiedName bn = GetContentBaseType (rest);
1261                                 if (bn == XmlQualifiedName.Empty && rest.BaseType != null)
1262                                         return FindBuiltInType (qname, rest.BaseType);
1263                                 else
1264                                         return FindBuiltInType (bn);
1265                         }
1266                         else if (st.Content is XmlSchemaSimpleTypeList) {
1267                                 return FindBuiltInType (GetContentBaseType (st.Content)).ListTypeData;
1268                         }
1269                         else if (st.Content is XmlSchemaSimpleTypeUnion) {
1270                                 // MS.NET always import simple unions as string
1271                                 return FindBuiltInType (new XmlQualifiedName ("string", XmlSchema.Namespace));
1272                         }
1273                         else
1274                                 return null;
1275                 }
1276
1277                 XmlQualifiedName GetContentBaseType (XmlSchemaObject ob)
1278                 {
1279                         if (ob is XmlSchemaSimpleContentExtension)
1280                                 return ((XmlSchemaSimpleContentExtension)ob).BaseTypeName;
1281                         else if (ob is XmlSchemaSimpleContentRestriction)
1282                                 return ((XmlSchemaSimpleContentRestriction)ob).BaseTypeName;
1283                         else if (ob is XmlSchemaSimpleTypeRestriction)
1284                                 return ((XmlSchemaSimpleTypeRestriction)ob).BaseTypeName;
1285                         else if (ob is XmlSchemaSimpleTypeList)
1286                                 return ((XmlSchemaSimpleTypeList)ob).ItemTypeName;
1287                         else
1288                                 return null;
1289                 }
1290
1291                 void ImportComplexContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaComplexContent content, CodeIdentifiers classIds, bool isMixed)
1292                 {
1293                         ClassMap cmap = (ClassMap)map.ObjectMap;
1294                         XmlQualifiedName qname;
1295
1296                         XmlSchemaComplexContentExtension ext = content.Content as XmlSchemaComplexContentExtension;
1297                         if (ext != null) qname = ext.BaseTypeName;
1298                         else qname = ((XmlSchemaComplexContentRestriction)content.Content).BaseTypeName;
1299                         
1300                         if (qname == typeQName)
1301                                 throw new InvalidOperationException ("Cannot import schema for type '" + typeQName.Name + "' from namespace '" + typeQName.Namespace + "'. Redefine not supported");
1302                         
1303                         // Add base map members to this map
1304
1305                         XmlTypeMapping baseMap = ImportClass (qname);
1306                         BuildPendingMap (baseMap);
1307                         ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
1308
1309                         foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
1310                                 cmap.AddMember (member);
1311
1312                         if (baseClassMap.XmlTextCollector != null) isMixed = false;
1313                         else if (content.IsMixed) isMixed = true;
1314
1315                         map.BaseMap = baseMap;
1316                         baseMap.DerivedTypes.Add (map);
1317
1318                         if (ext != null) {
1319                                 // Add the members of this map
1320                                 ImportParticleComplexContent (typeQName, cmap, ext.Particle, classIds, isMixed);
1321                                 ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
1322                         }
1323                         else {
1324                                 if (isMixed) ImportParticleComplexContent (typeQName, cmap, null, classIds, true);
1325                         }
1326                 }
1327                 
1328                 void ImportExtensionTypes (XmlQualifiedName qname)
1329                 {
1330                         foreach (XmlSchema schema in schemas) {
1331                                 foreach (XmlSchemaObject sob in schema.Items) 
1332                                 {
1333                                         XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
1334                                         if (sct != null && sct.ContentModel is XmlSchemaComplexContent) {
1335                                                 XmlQualifiedName exqname;
1336                                                 XmlSchemaComplexContentExtension ext = sct.ContentModel.Content as XmlSchemaComplexContentExtension;
1337                                                 if (ext != null) exqname = ext.BaseTypeName;
1338                                                 else exqname = ((XmlSchemaComplexContentRestriction)sct.ContentModel.Content).BaseTypeName;
1339                                                 if (exqname == qname)
1340                                                         ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
1341                                         }
1342                                 }
1343                         }                                       
1344                 }
1345
1346                 XmlTypeMapping ImportClassSimpleType (XmlQualifiedName typeQName, XmlSchemaSimpleType stype, XmlQualifiedName root)
1347                 {
1348                         if (CanBeEnum (stype))
1349                         {
1350                                 // Create an enum map
1351
1352                                 CodeIdentifiers codeIdents = new CodeIdentifiers ();
1353                                 XmlTypeMapping enumMap = CreateTypeMapping (typeQName, SchemaTypes.Enum, root);
1354                                 enumMap.Documentation = GetDocumentation (stype);
1355                                 
1356                                 bool isFlags = false;
1357                                 if (stype.Content is XmlSchemaSimpleTypeList) {
1358                                         stype = ((XmlSchemaSimpleTypeList)stype.Content).ItemType;
1359                                         isFlags = true;
1360                                 }
1361                                 XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
1362
1363                                 codeIdents.AddReserved (enumMap.TypeData.TypeName);
1364
1365                                 EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [rest.Facets.Count];
1366                                 for (int n=0; n<rest.Facets.Count; n++)
1367                                 {
1368                                         XmlSchemaEnumerationFacet enu = (XmlSchemaEnumerationFacet) rest.Facets[n];
1369                                         string enumName = codeIdents.AddUnique(CodeIdentifier.MakeValid (enu.Value), enu);
1370                                         members [n] = new EnumMap.EnumMapMember (enu.Value, enumName);
1371                                         members [n].Documentation = GetDocumentation (enu);
1372                                 }
1373                                 enumMap.ObjectMap = new EnumMap (members, isFlags);
1374                                 enumMap.IsSimpleType = true;
1375                                 return enumMap;
1376                         }
1377
1378                         if (stype.Content is XmlSchemaSimpleTypeList)
1379                         {
1380                                 XmlSchemaSimpleTypeList slist = (XmlSchemaSimpleTypeList)stype.Content;
1381                                 TypeData arrayTypeData = FindBuiltInType (slist.ItemTypeName, stype);
1382
1383                                 ListMap listMap = new ListMap ();
1384
1385                                 listMap.ItemInfo = new XmlTypeMapElementInfoList ();
1386                                 listMap.ItemInfo.Add (CreateElementInfo (typeQName.Namespace, null, "Item", arrayTypeData.ListItemTypeData, false, XmlSchemaForm.None, -1));
1387
1388                                 XmlTypeMapping map = CreateArrayTypeMapping (typeQName, arrayTypeData);
1389                                 map.ObjectMap = listMap;
1390                                 map.IsSimpleType = true;
1391                                 return map;
1392                         }
1393
1394                         // It is an extension of a primitive or known type
1395                         
1396                         TypeData typeData = FindBuiltInType (typeQName, stype);
1397                         XmlTypeMapping rmap = GetTypeMapping (typeData);
1398                         
1399                         // The resulting map must be a simple type. It needs to be explicitely set for arrays
1400                         rmap.IsSimpleType = true;
1401                         return rmap;
1402                 }
1403
1404                 bool CanBeEnum (XmlSchemaSimpleType stype)
1405                 {
1406                         if (stype.Content is XmlSchemaSimpleTypeRestriction)
1407                         {
1408                                 XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
1409                                 if (rest.Facets.Count == 0) return false;
1410                                 foreach (object ob in rest.Facets)
1411                                         if (!(ob is XmlSchemaEnumerationFacet)) return false;
1412                                 return true;
1413                         }
1414                         else if (stype.Content is XmlSchemaSimpleTypeList)
1415                         {
1416                                 XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList) stype.Content;
1417                                 return (list.ItemType != null && CanBeEnum (list.ItemType));
1418                         }
1419                         return false;
1420                 }
1421
1422                 bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaComplexType stype)
1423                 {
1424                         if (encodedFormat)
1425                         {
1426                                 XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
1427                                 if (content == null) return false;
1428                                 XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
1429                                 if (rest == null) return false;
1430                                 return rest.BaseTypeName == arrayType;
1431                         }
1432                         else
1433                         {
1434                                 if (stype.Attributes.Count > 0 || stype.AnyAttribute != null) return false;
1435                                 else return !stype.IsMixed && CanBeArray (typeQName, stype.Particle, false);
1436                         }
1437                 }
1438
1439                 bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaParticle particle, bool multiValue)
1440                 {
1441                         // To be an array, there can't be a direct child of type typeQName
1442
1443                         if (particle == null) return false;
1444
1445                         multiValue = multiValue || particle.MaxOccurs > 1;
1446
1447                         if (particle is XmlSchemaGroupRef)
1448                                 return CanBeArray (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), multiValue);
1449
1450                         if (particle is XmlSchemaElement)
1451                         {
1452                                 XmlSchemaElement elem = (XmlSchemaElement)particle;
1453                                 if (!elem.RefName.IsEmpty)
1454                                         return CanBeArray (typeQName, FindRefElement (elem), multiValue);
1455                                 else
1456                                         return multiValue && !typeQName.Equals (((XmlSchemaElement)particle).SchemaTypeName);
1457                         }
1458
1459                         if (particle is XmlSchemaAny)
1460                                 return multiValue;
1461
1462                         if (particle is XmlSchemaSequence)
1463                         {
1464                                 XmlSchemaSequence seq = particle as XmlSchemaSequence;
1465                                 if (seq.Items.Count != 1) return false;
1466                                 return CanBeArray (typeQName, (XmlSchemaParticle)seq.Items[0], multiValue);
1467                         }
1468
1469                         if (particle is XmlSchemaChoice)
1470                         {
1471                                 // Can be array if all choices have different types
1472                                 ArrayList types = new ArrayList ();
1473                                 if(!CheckChoiceType (typeQName, particle, types, ref multiValue)) return false;
1474                                 return multiValue;
1475                         }
1476
1477                         return false;
1478                 }
1479
1480                 bool CheckChoiceType (XmlQualifiedName typeQName, XmlSchemaParticle particle, ArrayList types, ref bool multiValue)
1481                 {
1482                         XmlQualifiedName type = null;
1483
1484                         multiValue = multiValue || particle.MaxOccurs > 1;
1485
1486                         if (particle is XmlSchemaGroupRef)
1487                                 return CheckChoiceType (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), types, ref multiValue);
1488
1489                         if (particle is XmlSchemaElement) {
1490                                 string ns;
1491                                 XmlSchemaElement elem = (XmlSchemaElement)particle;
1492                                 XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
1493                                 if (refElem.SchemaType != null) return true;
1494                                 type = refElem.SchemaTypeName;
1495                         }
1496                         else if (particle is XmlSchemaAny) {
1497                                 type = anyType;
1498                         }
1499                         else if (particle is XmlSchemaSequence)
1500                         {
1501                                 XmlSchemaSequence seq = particle as XmlSchemaSequence;
1502                                 foreach (XmlSchemaParticle par in seq.Items)
1503                                         if (!CheckChoiceType (typeQName, par, types, ref multiValue)) return false;
1504                                 return true;
1505                         }
1506                         else if (particle is XmlSchemaChoice)
1507                         {
1508                                 foreach (XmlSchemaParticle choice in ((XmlSchemaChoice)particle).Items)
1509                                         if (!CheckChoiceType (typeQName, choice, types, ref multiValue)) return false;
1510                                 return true;
1511                         }
1512
1513                         if (typeQName.Equals (type)) return false;
1514
1515                         // For primitive types, compare using CLR types, since several
1516                         // xml types can be mapped to a single CLR type
1517
1518                         string t;
1519                         if (IsPrimitiveTypeNamespace (type.Namespace))
1520                                 t = TypeTranslator.GetPrimitiveTypeData (type.Name).FullTypeName + ":" + type.Namespace;
1521
1522                         else
1523                                 t = type.Name + ":" + type.Namespace;
1524
1525                         if (types.Contains (t)) return false;
1526                         types.Add (t);
1527                         return true;
1528                 }
1529                 
1530                 bool CanBeAnyElement (XmlSchemaComplexType stype)
1531                 {
1532                         XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
1533                         return (seq != null) && (seq.Items.Count == 1) && (seq.Items[0] is XmlSchemaAny);
1534                 }
1535                 
1536                 Type GetAnyElementType (XmlSchemaComplexType stype)
1537                 {
1538                         XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
1539                         
1540                         if ((seq == null) || (seq.Items.Count != 1) || !(seq.Items[0] is XmlSchemaAny))
1541                                 return null;
1542                         
1543                         if (encodedFormat) 
1544                                 return typeof(object);
1545
1546                         XmlSchemaAny any = seq.Items[0] as XmlSchemaAny;
1547                         if (any.MaxOccurs == 1)
1548                         {
1549                                 if (stype.IsMixed)
1550                                         return typeof(XmlNode);
1551                                 else
1552                                         return typeof(XmlElement);
1553                         }
1554                         else
1555                         {
1556                                 if (stype.IsMixed)
1557                                         return typeof(XmlNode[]);
1558                                 else
1559                                         return typeof(XmlElement[]);
1560                         }
1561                 }
1562
1563                 bool CanBeIXmlSerializable (XmlSchemaComplexType stype)
1564                 {
1565                         XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
1566                         if (seq == null) return false;
1567                         if (seq.Items.Count != 2) return false;
1568                         XmlSchemaElement elem = seq.Items[0] as XmlSchemaElement;
1569                         if (elem == null) return false;
1570                         if (elem.RefName != new XmlQualifiedName ("schema",XmlSchema.Namespace)) return false;
1571                         return (seq.Items[1] is XmlSchemaAny);
1572                 }
1573                 
1574                 XmlTypeMapping ImportXmlSerializableMapping (string ns)
1575                 {
1576                         XmlQualifiedName qname = new XmlQualifiedName ("System.Data.DataSet",ns);
1577                         XmlTypeMapping map = GetRegisteredTypeMapping (qname);
1578                         if (map != null) return map;
1579                         
1580                         TypeData typeData = new TypeData ("System.Data.DataSet", "System.Data.DataSet", "System.Data.DataSet", SchemaTypes.XmlSerializable, null);
1581                         map = new XmlTypeMapping ("System.Data.DataSet", "", typeData, "System.Data.DataSet", ns);
1582                         map.IncludeInSchema = true;
1583                         RegisterTypeMapping (qname, typeData, map);
1584                         return map;
1585                 }
1586                 
1587                 XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form, int order)
1588                 {
1589                         if (typeData.IsComplexType)
1590                                 return CreateElementInfo (ns, member, name, typeData, isNillable, form, GetTypeMapping (typeData), order);
1591                         else
1592                                 return CreateElementInfo (ns, member, name, typeData, isNillable, form, null, order);
1593                 }
1594                 
1595                 XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form, XmlTypeMapping emap, int order)
1596                 {
1597                         XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
1598                         einfo.ElementName = name;
1599                         einfo.Namespace = ns;
1600                         einfo.IsNullable = isNillable;
1601                         einfo.Form = GetForm (form, ns, true);
1602                         if (typeData.IsComplexType)
1603                                 einfo.MappedType = emap;
1604                         einfo.ExplicitOrder = order;
1605                         return einfo;
1606                 }
1607                 
1608                 XmlSchemaForm GetForm (XmlSchemaForm form, string ns, bool forElement)
1609                 {
1610                         // Returns the schema form for an element or attribute, taking
1611                         // into account the schema defaults. If the form has not been explicitly
1612                         // set and there is no default, use Unqualified as default.
1613                         
1614                         if (form != XmlSchemaForm.None)
1615                                 return form;
1616                         XmlSchema s = schemas [ns];
1617                         if (s == null)
1618                                 return XmlSchemaForm.Unqualified;
1619                         XmlSchemaForm schemaForm = forElement ? s.ElementFormDefault : s.AttributeFormDefault;
1620                         if (schemaForm != XmlSchemaForm.None)
1621                                 return schemaForm;
1622                         else
1623                                 return XmlSchemaForm.Unqualified;
1624                 }
1625
1626                 XmlTypeMapElementInfo CreateTextElementInfo (string ns, XmlTypeMapMember member, TypeData typeData)
1627                 {
1628                         XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
1629                         einfo.IsTextElement = true;
1630                         einfo.WrappedElement = false;
1631                         if (typeData.IsComplexType)
1632                                 einfo.MappedType = GetTypeMapping (typeData);
1633                         return einfo;
1634                 }
1635
1636                 XmlTypeMapping CreateTypeMapping (XmlQualifiedName typeQName, SchemaTypes schemaType, XmlQualifiedName root)
1637                 {
1638                         string typeName = CodeIdentifier.MakeValid (typeQName.Name);
1639                         typeName = typeIdentifiers.AddUnique (typeName, null);
1640
1641                         TypeData typeData = new TypeData (typeName, typeName, typeName, schemaType, null);
1642
1643                         string rootElem;
1644                         string rootNs;
1645                         if (root != null) {
1646                                 rootElem = root.Name;
1647                                 rootNs = root.Namespace;
1648                         }
1649                         else {
1650                                 rootElem = typeQName.Name;
1651                                 rootNs = "";
1652                         }
1653                         
1654                         XmlTypeMapping map = new XmlTypeMapping (rootElem, rootNs, typeData, typeQName.Name, typeQName.Namespace);
1655                         map.IncludeInSchema = true;
1656                         RegisterTypeMapping (typeQName, typeData, map);
1657
1658                         return map;
1659                 }
1660
1661                 XmlTypeMapping CreateArrayTypeMapping (XmlQualifiedName typeQName, TypeData arrayTypeData)
1662                 {
1663                         XmlTypeMapping map;
1664                         if (encodedFormat) map = new XmlTypeMapping ("Array", XmlSerializer.EncodingNamespace, arrayTypeData, "Array", XmlSerializer.EncodingNamespace);
1665                         else map = new XmlTypeMapping (arrayTypeData.XmlType, typeQName.Namespace, arrayTypeData, arrayTypeData.XmlType, typeQName.Namespace);
1666                         
1667                         map.IncludeInSchema = true;
1668                         RegisterTypeMapping (typeQName, arrayTypeData, map);
1669
1670                         return map;
1671                 }
1672
1673                 XmlSchemaElement GetRefElement (XmlQualifiedName typeQName, XmlSchemaElement elem, out string ns)
1674                 {
1675
1676                         if (!elem.RefName.IsEmpty)
1677                         {
1678                                 ns = elem.RefName.Namespace;
1679                                 return FindRefElement (elem);
1680                         }
1681                         else
1682                         {
1683                                 ns = typeQName.Namespace;
1684                                 return elem;
1685                         }
1686                 }
1687
1688                 XmlSchemaAttribute GetRefAttribute (XmlQualifiedName typeQName, XmlSchemaAttribute attr, out string ns)
1689                 {
1690                         if (!attr.RefName.IsEmpty)
1691                         {
1692                                 ns = attr.RefName.Namespace;
1693                                 XmlSchemaAttribute at = FindRefAttribute (attr.RefName);
1694                                 if (at == null) throw new InvalidOperationException ("The attribute " + attr.RefName + " is missing");
1695                                 return at;
1696                         }
1697                         else
1698                         {
1699                                 ns = attr.ParentIsSchema ? typeQName.Namespace : String.Empty;
1700                                 return attr;
1701                         }
1702                 }
1703
1704                 TypeData GetElementTypeData (XmlQualifiedName typeQName, XmlSchemaElement elem, XmlQualifiedName root, out XmlTypeMapping map)
1705                 {
1706                         bool sharedAnnType = false;
1707                         map = null;
1708                         
1709                         if (!elem.RefName.IsEmpty) {
1710                                 XmlSchemaElement refElem = FindRefElement (elem);
1711                                 if (refElem == null) throw new InvalidOperationException ("Global element not found: " + elem.RefName);
1712                                 root = elem.RefName;
1713                                 elem = refElem;
1714                                 sharedAnnType = true;
1715                         }
1716
1717                         TypeData td;
1718                         if (!elem.SchemaTypeName.IsEmpty) {
1719                                 td = GetTypeData (elem.SchemaTypeName, root, elem.IsNillable);
1720                                 map = GetRegisteredTypeMapping (td);
1721                         }
1722                         else if (elem.SchemaType == null) 
1723                                 td = TypeTranslator.GetTypeData (typeof(object));
1724                         else 
1725                                 td = GetTypeData (elem.SchemaType, typeQName, elem.Name, sharedAnnType, root);
1726                         
1727                         if (map == null && td.IsComplexType)
1728                                 map = GetTypeMapping (td);
1729                                 
1730                         return td;
1731                 }
1732
1733                 TypeData GetAttributeTypeData (XmlQualifiedName typeQName, XmlSchemaAttribute attr)
1734                 {
1735                         bool sharedAnnType = false;
1736
1737                         if (!attr.RefName.IsEmpty) {
1738                                 XmlSchemaAttribute refAtt = FindRefAttribute (attr.RefName);
1739                                 if (refAtt == null) throw new InvalidOperationException ("Global attribute not found: " + attr.RefName);
1740                                 attr = refAtt;
1741                                 sharedAnnType = true;
1742                         }
1743                         
1744                         if (!attr.SchemaTypeName.IsEmpty) return GetTypeData (attr.SchemaTypeName, null, false);
1745                         if (attr.SchemaType == null) return TypeTranslator.GetTypeData (typeof(string));
1746                         else return GetTypeData (attr.SchemaType, typeQName, attr.Name, sharedAnnType, null);
1747                 }
1748
1749                 TypeData GetTypeData (XmlQualifiedName typeQName, XmlQualifiedName root, bool isNullable)
1750                 {
1751                         if (IsPrimitiveTypeNamespace (typeQName.Namespace)) {
1752                                 XmlTypeMapping map = ImportType (typeQName, root, false);
1753                                 if (map != null) return map.TypeData;
1754                                 else return TypeTranslator.GetPrimitiveTypeData (typeQName.Name, isNullable);
1755                         }
1756                         
1757                         if (encodedFormat && typeQName.Namespace == "")
1758                                 return TypeTranslator.GetPrimitiveTypeData (typeQName.Name);
1759
1760                         return ImportType (typeQName, root, true).TypeData;
1761                 }
1762
1763                 TypeData GetTypeData (XmlSchemaType stype, XmlQualifiedName typeQNname, string propertyName, bool sharedAnnType, XmlQualifiedName root)
1764                 {
1765                         string baseName;
1766
1767                         if (sharedAnnType)
1768                         {
1769                                 // Anonymous types defined in root elements or attributes can be shared among all elements that
1770                                 // reference this root element or attribute
1771                                 TypeData std = sharedAnonymousTypes [stype] as TypeData;
1772                                 if (std != null) return std;
1773                                 baseName = propertyName;
1774                         }
1775                         else
1776                                 baseName = typeQNname.Name + typeIdentifiers.MakeRightCase (propertyName);
1777
1778                         baseName = elemIdentifiers.AddUnique (baseName, stype);
1779                         
1780                         XmlQualifiedName newName;
1781                         newName = new XmlQualifiedName (baseName, typeQNname.Namespace);
1782
1783                         XmlTypeMapping map = ImportType (newName, stype, root);
1784                         if (sharedAnnType) sharedAnonymousTypes [stype] = map.TypeData;
1785
1786                         return map.TypeData;
1787                 }
1788
1789                 XmlTypeMapping GetTypeMapping (TypeData typeData)
1790                 {
1791                         if (typeData.Type == typeof(object) && !anyTypeImported)
1792                                 ImportAllObjectTypes ();
1793                                 
1794                         XmlTypeMapping map = GetRegisteredTypeMapping (typeData);
1795                         if (map != null) return map;
1796                         
1797                         if (typeData.IsListType)
1798                         {
1799                                 // Create an array map for the type
1800
1801                                 XmlTypeMapping itemMap = GetTypeMapping (typeData.ListItemTypeData);
1802                                 
1803                                 map = new XmlTypeMapping (typeData.XmlType, itemMap.Namespace, typeData, typeData.XmlType, itemMap.Namespace);
1804                                 map.IncludeInSchema = true;
1805
1806                                 ListMap listMap = new ListMap ();
1807                                 listMap.ItemInfo = new XmlTypeMapElementInfoList();
1808                                 listMap.ItemInfo.Add (CreateElementInfo (itemMap.Namespace, null, typeData.ListItemTypeData.XmlType, typeData.ListItemTypeData, false, XmlSchemaForm.None, -1));
1809                                 map.ObjectMap = listMap;
1810                                 
1811                                 RegisterTypeMapping (new XmlQualifiedName(map.ElementName, map.Namespace), typeData, map);
1812                                 return map;
1813                         }
1814                         else if (typeData.SchemaType == SchemaTypes.Primitive || typeData.Type == typeof(object) || typeof(XmlNode).IsAssignableFrom(typeData.Type))
1815                         {
1816                                 return CreateSystemMap (typeData);
1817                         }
1818                         
1819                         throw new InvalidOperationException ("Map for type " + typeData.TypeName + " not found");
1820                 }
1821                 
1822                 void AddObjectDerivedMap (XmlTypeMapping map)
1823                 {
1824                         TypeData typeData = TypeTranslator.GetTypeData (typeof(object));
1825                         XmlTypeMapping omap = GetRegisteredTypeMapping (typeData);
1826                         if (omap == null)
1827                                 omap = CreateSystemMap (typeData);
1828                         omap.DerivedTypes.Add (map);
1829                 }
1830                 
1831                 XmlTypeMapping CreateSystemMap (TypeData typeData)
1832                 {
1833                         XmlTypeMapping map = new XmlTypeMapping (typeData.XmlType, XmlSchema.Namespace, typeData, typeData.XmlType, XmlSchema.Namespace);
1834                         map.IncludeInSchema = false;
1835                         map.ObjectMap = new ClassMap ();
1836                         dataMappedTypes [typeData] = map;
1837                         return map;
1838                 }
1839                 
1840                 void ImportAllObjectTypes ()
1841                 {
1842                         // All complex types are subtypes of anyType, so all of them 
1843                         // must also be imported
1844                         
1845                         anyTypeImported = true;
1846                         foreach (XmlSchema schema in schemas) {
1847                                 foreach (XmlSchemaObject sob in schema.Items) 
1848                                 {
1849                                         XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
1850                                         if (sct != null)
1851                                                 ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
1852                                 }
1853                         }                                       
1854                 }
1855                 
1856                 XmlTypeMapping GetRegisteredTypeMapping (XmlQualifiedName typeQName, Type baseType)
1857                 {
1858                         // Primitive types with a forced base class are stored in a different table.
1859                         // In this way it is possible to have two maps for primitive types: one with
1860                         // the forced base class (returned by ImportDerivedTypeMapping) and one
1861                         // with the regular primitive map.
1862                         
1863                         if (IsPrimitiveTypeNamespace (typeQName.Namespace))
1864                                 return (XmlTypeMapping) primitiveDerivedMappedTypes [typeQName];
1865                         else
1866                                 return (XmlTypeMapping) mappedTypes [typeQName];
1867                 }
1868                 
1869                 XmlTypeMapping GetRegisteredTypeMapping (XmlQualifiedName typeQName)
1870                 {
1871                         return (XmlTypeMapping) mappedTypes [typeQName];
1872                 }
1873                 
1874                 XmlTypeMapping GetRegisteredTypeMapping (TypeData typeData)
1875                 {
1876                         return (XmlTypeMapping) dataMappedTypes [typeData];
1877                 }
1878                 
1879                 void RegisterTypeMapping (XmlQualifiedName qname, TypeData typeData, XmlTypeMapping map)
1880                 {
1881                         // Primitive types with a forced base class are stored in a different table.
1882                         // In this way it is possible to have two maps for primitive types: one with
1883                         // the forced base class (returned by ImportDerivedTypeMapping) and one
1884                         // with the regular primitive map.
1885                         
1886                         dataMappedTypes [typeData] = map;
1887                         if (IsPrimitiveTypeNamespace (qname.Namespace) && !map.IsSimpleType)
1888                                 primitiveDerivedMappedTypes [qname] = map;
1889                         else
1890                                 mappedTypes [qname] = map;
1891                 }
1892
1893                 XmlSchemaParticle GetRefGroupParticle (XmlSchemaGroupRef refGroup)
1894                 {
1895                         XmlSchemaGroup grp = (XmlSchemaGroup) schemas.Find (refGroup.RefName, typeof (XmlSchemaGroup));
1896                         return grp.Particle;
1897                 }
1898
1899                 XmlSchemaElement FindRefElement (XmlSchemaElement elem)
1900                 {
1901                         XmlSchemaElement refelem = (XmlSchemaElement) schemas.Find (elem.RefName, typeof(XmlSchemaElement));
1902                         if (refelem != null) return refelem;
1903                         
1904                         if (IsPrimitiveTypeNamespace (elem.RefName.Namespace))
1905                         {
1906                                 if (anyElement != null) return anyElement;
1907                                 anyElement = new XmlSchemaElement ();
1908                                 anyElement.Name = "any";
1909                                 anyElement.SchemaTypeName = anyType;
1910                                 return anyElement;
1911                         } else
1912                                 return null;
1913                 }
1914                 
1915                 XmlSchemaAttribute FindRefAttribute (XmlQualifiedName refName)
1916                 {
1917                         if (refName.Namespace == XmlNamespace)
1918                         {
1919                                 XmlSchemaAttribute at = new XmlSchemaAttribute ();
1920                                 at.Name = refName.Name;
1921                                 at.SchemaTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace);
1922                                 return at;
1923                         }
1924                         return (XmlSchemaAttribute) schemas.Find (refName, typeof(XmlSchemaAttribute));
1925                 }
1926                 
1927                 XmlSchemaAttributeGroup FindRefAttributeGroup (XmlQualifiedName refName)
1928                 {
1929                         XmlSchemaAttributeGroup grp = (XmlSchemaAttributeGroup) schemas.Find (refName, typeof(XmlSchemaAttributeGroup));
1930                         foreach (XmlSchemaObject at in grp.Attributes)
1931                         {
1932                                 if (at is XmlSchemaAttributeGroupRef && ((XmlSchemaAttributeGroupRef)at).RefName == refName)
1933                                         throw new InvalidOperationException ("Cannot import attribute group '" + refName.Name + "' from namespace '" + refName.Namespace + "'. Redefine not supported");
1934                                         
1935                         }
1936                         return grp;
1937                 }
1938
1939                 XmlTypeMapping ReflectType (Type type)
1940                 {
1941                         TypeData typeData = TypeTranslator.GetTypeData (type);
1942                         return ReflectType (typeData, (string) null);
1943                 }
1944
1945                 XmlTypeMapping ReflectType (TypeData typeData, string ns)
1946                 {
1947                         if (!encodedFormat)
1948                         {
1949                                 if (auxXmlRefImporter == null) auxXmlRefImporter = new XmlReflectionImporter ();
1950                                 return auxXmlRefImporter.ImportTypeMapping (typeData, ns);
1951                         }
1952                         else
1953                         {
1954                                 if (auxSoapRefImporter == null) auxSoapRefImporter = new SoapReflectionImporter ();
1955                                 return auxSoapRefImporter.ImportTypeMapping (typeData, ns);
1956                         }
1957                 }
1958
1959
1960                 string GetDocumentation (XmlSchemaAnnotated elem)
1961                 {
1962                         string res = "";
1963                         XmlSchemaAnnotation anot = elem.Annotation;
1964                         if (anot == null || anot.Items == null) return null;
1965                         
1966                         foreach (object ob in anot.Items)
1967                         {
1968                                 XmlSchemaDocumentation doc = ob as XmlSchemaDocumentation;
1969                                 if (doc != null && doc.Markup != null && doc.Markup.Length > 0) {
1970                                         if (res != string.Empty) res += "\n";
1971                                         foreach (XmlNode node in doc.Markup)
1972                                                 res += node.Value;
1973                                 }
1974                         }
1975                         return res;
1976                 }
1977                 
1978                 bool IsPrimitiveTypeNamespace (string ns)
1979                 {
1980                         return (ns == XmlSchema.Namespace) || (encodedFormat && ns == XmlSerializer.EncodingNamespace);
1981                 }
1982
1983                 #endregion // Methods
1984         }
1985 }