Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / Serialization / XmlSchemaImporter.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSchemaImporter.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7
8 namespace System.Xml.Serialization  {
9
10     using System;
11     using System.Xml.Schema;
12     using System.Collections;
13     using System.Collections.Generic;
14     using System.ComponentModel;
15     using System.Reflection;
16     using System.Xml.Serialization.Configuration;
17     using System.CodeDom;
18     using System.CodeDom.Compiler;
19     using System.Collections.Specialized;
20     using System.Globalization;
21     using System.Security.Permissions;
22     using System.Xml.Serialization.Advanced;
23
24 #if DEBUG
25     using System.Diagnostics;
26 #endif
27
28     /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter"]/*' />
29     ///<internalonly/>
30     /// <devdoc>
31     ///    <para>[To be supplied.]</para>
32     /// </devdoc>
33     public class XmlSchemaImporter : SchemaImporter {
34
35         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter"]/*' />
36         /// <devdoc>
37         ///    <para>[To be supplied.]</para>
38         /// </devdoc>
39         public XmlSchemaImporter(XmlSchemas schemas) : base(schemas, CodeGenerationOptions.GenerateProperties, null, new ImportContext()) {}
40
41         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter1"]/*' />
42         /// <devdoc>
43         ///    <para>[To be supplied.]</para>
44         /// </devdoc>
45         public XmlSchemaImporter(XmlSchemas schemas, CodeIdentifiers typeIdentifiers) : base(schemas, CodeGenerationOptions.GenerateProperties, null, new ImportContext(typeIdentifiers, false)) {}
46
47         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter2"]/*' />
48         /// <devdoc>
49         ///    <para>[To be supplied.]</para>
50         /// </devdoc>
51         public XmlSchemaImporter(XmlSchemas schemas, CodeIdentifiers typeIdentifiers, CodeGenerationOptions options) : base(schemas, options, null, new ImportContext(typeIdentifiers, false)) {}
52
53         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter3"]/*' />
54         /// <devdoc>
55         ///    <para>[To be supplied.]</para>
56         /// </devdoc>
57         public XmlSchemaImporter(XmlSchemas schemas, CodeGenerationOptions options, ImportContext context) : base(schemas, options, null, context){}
58
59         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter4"]/*' />
60         /// <devdoc>
61         ///    <para>[To be supplied.]</para>
62         /// </devdoc>
63         public XmlSchemaImporter(XmlSchemas schemas, CodeGenerationOptions options, CodeDomProvider codeProvider, ImportContext context) : base(schemas, options, codeProvider, context){
64         }
65
66         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportDerivedTypeMapping"]/*' />
67         /// <devdoc>
68         ///    <para>[To be supplied.]</para>
69         /// </devdoc>
70         public XmlTypeMapping ImportDerivedTypeMapping(XmlQualifiedName name, Type baseType) {
71             return ImportDerivedTypeMapping(name, baseType, false);
72         }
73
74         internal bool GenerateOrder {
75             get { return (Options & CodeGenerationOptions.GenerateOrder) != 0; }
76         }
77
78         internal TypeMapping GetDefaultMapping(TypeFlags flags) {
79             PrimitiveMapping mapping = new PrimitiveMapping();
80             mapping.TypeDesc = Scope.GetTypeDesc("string", XmlSchema.Namespace, flags);
81             mapping.TypeName = mapping.TypeDesc.DataType.Name;
82             mapping.Namespace = XmlSchema.Namespace;
83             return mapping;
84         }
85
86         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportDerivedTypeMapping1"]/*' />
87         /// <devdoc>
88         ///    <para>[To be supplied.]</para>
89         /// </devdoc>
90         public XmlTypeMapping ImportDerivedTypeMapping(XmlQualifiedName name, Type baseType, bool baseTypeCanBeIndirect) {
91             ElementAccessor element = ImportElement(name, typeof(TypeMapping), baseType);
92
93             if (element.Mapping is StructMapping) {
94                 MakeDerived((StructMapping)element.Mapping, baseType, baseTypeCanBeIndirect);
95             }
96             else if (baseType != null) {
97                 if (element.Mapping is ArrayMapping) {
98                     // in the case of the ArrayMapping we can use the top-level StructMapping, because it does not have base base type
99                     element.Mapping = ((ArrayMapping)element.Mapping).TopLevelMapping;
100                     MakeDerived((StructMapping)element.Mapping, baseType, baseTypeCanBeIndirect);
101                 }
102                 else {
103                     // Element '{0}' from namespace '{1}' is not a complex type and cannot be used as a {2}.
104                     throw new InvalidOperationException(Res.GetString(Res.XmlBadBaseElement, name.Name, name.Namespace, baseType.FullName));
105                 }
106             }
107             return new XmlTypeMapping(Scope, element);
108         }
109
110         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportSchemaType"]/*' />
111         /// <devdoc>
112         ///    <para>[To be supplied.]</para>
113         /// </devdoc>
114         public XmlTypeMapping ImportSchemaType(XmlQualifiedName typeName) {
115             return ImportSchemaType(typeName, null, false);
116         }
117                                           
118
119         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportSchemaType1"]/*' />
120         /// <devdoc>
121         ///    <para>[To be supplied.]</para>
122         /// </devdoc>
123         public XmlTypeMapping ImportSchemaType(XmlQualifiedName typeName, Type baseType) {
124             return ImportSchemaType(typeName, baseType, false);
125         }
126
127         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportSchemaType2"]/*' />
128         /// <devdoc>
129         ///    <para>[To be supplied.]</para>
130         /// </devdoc>
131         public XmlTypeMapping ImportSchemaType(XmlQualifiedName typeName, Type baseType, bool baseTypeCanBeIndirect) {
132             TypeMapping typeMapping = ImportType(typeName, typeof(TypeMapping), baseType, TypeFlags.CanBeElementValue, true);
133             typeMapping.ReferencedByElement = false;
134
135             ElementAccessor accessor = new ElementAccessor();
136             accessor.IsTopLevelInSchema = true; // false
137             accessor.Name = typeName.Name;
138             accessor.Namespace = typeName.Namespace;
139             accessor.Mapping = typeMapping;
140
141             if (typeMapping is SpecialMapping && ((SpecialMapping)typeMapping).NamedAny)
142                 accessor.Any = true;
143             accessor.IsNullable = typeMapping.TypeDesc.IsNullable;
144             accessor.Form = XmlSchemaForm.Qualified;
145
146             if (accessor.Mapping is StructMapping) {
147                 MakeDerived((StructMapping)accessor.Mapping, baseType, baseTypeCanBeIndirect);
148             }
149             else if (baseType != null) {
150                 if (accessor.Mapping is ArrayMapping) {
151                     // in the case of the ArrayMapping we can use the top-level StructMapping, because it does not have base base type
152                     accessor.Mapping = ((ArrayMapping)accessor.Mapping).TopLevelMapping;
153                     MakeDerived((StructMapping)accessor.Mapping, baseType, baseTypeCanBeIndirect);
154                 }
155                 else {
156                     // Type '{0}' from namespace '{1}' is not a complex type and cannot be used as a {2}.
157                     throw new InvalidOperationException(Res.GetString(Res.XmlBadBaseType, typeName.Name, typeName.Namespace, baseType.FullName));
158                 }
159             }
160             return new XmlTypeMapping(Scope, accessor);
161         }
162
163         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportTypeMapping"]/*' />
164         /// <devdoc>
165         ///    <para>[To be supplied.]</para>
166         /// </devdoc>
167         public XmlTypeMapping ImportTypeMapping(XmlQualifiedName name) {
168             return ImportDerivedTypeMapping(name, null);
169         }
170
171         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportMembersMapping"]/*' />
172         /// <devdoc>
173         ///    <para>[To be supplied.]</para>
174         /// </devdoc>
175         public XmlMembersMapping ImportMembersMapping(XmlQualifiedName name) {
176             return new XmlMembersMapping(Scope, ImportElement(name, typeof(MembersMapping), null), XmlMappingAccess.Read | XmlMappingAccess.Write);
177         }
178
179         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportAnyType"]/*' />
180         public XmlMembersMapping ImportAnyType(XmlQualifiedName typeName, string elementName) {
181             TypeMapping typeMapping = ImportType(typeName, typeof(MembersMapping), null, TypeFlags.CanBeElementValue, true);
182             MembersMapping mapping = typeMapping as MembersMapping;
183
184             if (mapping == null) {
185                 XmlSchemaComplexType type = new XmlSchemaComplexType();
186                 XmlSchemaSequence seq = new XmlSchemaSequence();
187                 type.Particle = seq;
188                 XmlSchemaElement element = new XmlSchemaElement();
189                 element.Name = elementName;
190                 element.SchemaTypeName = typeName;
191                 seq.Items.Add(element);
192                 mapping = ImportMembersType(type, typeName.Namespace, elementName);
193             }
194
195             if (mapping.Members.Length != 1 || !mapping.Members[0].Accessor.Any)
196                 return null;
197             mapping.Members[0].Name = elementName;
198             ElementAccessor accessor = new ElementAccessor();
199             accessor.Name = elementName;
200             accessor.Namespace = typeName.Namespace;
201             accessor.Mapping = mapping;
202             accessor.Any = true;
203
204             XmlSchemaObject xso = Schemas.SchemaSet.GlobalTypes[typeName];
205             if (xso != null) {
206                 XmlSchema schema = xso.Parent as XmlSchema;
207                 if (schema != null) {
208                     accessor.Form = schema.ElementFormDefault == XmlSchemaForm.None ? XmlSchemaForm.Unqualified : schema.ElementFormDefault;
209                 }
210             }
211             XmlMembersMapping members = new XmlMembersMapping(Scope, accessor, XmlMappingAccess.Read | XmlMappingAccess.Write);
212             return members;
213         }
214
215         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportMembersMapping1"]/*' />
216         /// <devdoc>
217         ///    <para>[To be supplied.]</para>
218         /// </devdoc>
219         public XmlMembersMapping ImportMembersMapping(XmlQualifiedName[] names) {
220             return ImportMembersMapping(names, null, false);
221         }
222
223         /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportMembersMapping2"]/*' />
224         /// <devdoc>
225         ///    <para>[To be supplied.]</para>
226         /// </devdoc>
227         public XmlMembersMapping ImportMembersMapping(XmlQualifiedName[] names, Type baseType, bool baseTypeCanBeIndirect) {
228             CodeIdentifiers memberScope = new CodeIdentifiers();
229             memberScope.UseCamelCasing = true;
230             MemberMapping[] members = new MemberMapping[names.Length];
231             for (int i = 0; i < names.Length; i++) {
232                 XmlQualifiedName name = names[i];
233                 ElementAccessor accessor =  ImportElement(name, typeof(TypeMapping), baseType);
234                 if (baseType != null && accessor.Mapping is StructMapping)
235                     MakeDerived((StructMapping)accessor.Mapping, baseType, baseTypeCanBeIndirect);
236
237                 MemberMapping member = new MemberMapping();
238                 member.Name = CodeIdentifier.MakeValid(Accessor.UnescapeName(accessor.Name));
239                 member.Name = memberScope.AddUnique(member.Name, member);
240                 member.TypeDesc = accessor.Mapping.TypeDesc;
241                 member.Elements = new ElementAccessor[] { accessor };
242                 members[i] = member;
243             }
244             MembersMapping mapping = new MembersMapping();
245             mapping.HasWrapperElement = false;
246             mapping.TypeDesc = Scope.GetTypeDesc(typeof(object[]));
247             mapping.Members = members;
248             ElementAccessor element = new ElementAccessor();
249             element.Mapping = mapping;
250             return new XmlMembersMapping(Scope, element, XmlMappingAccess.Read | XmlMappingAccess.Write);
251         }
252
253         public XmlMembersMapping ImportMembersMapping(string name, string ns, SoapSchemaMember[] members) {
254             XmlSchemaComplexType type = new XmlSchemaComplexType();
255             XmlSchemaSequence seq = new XmlSchemaSequence();
256             type.Particle = seq;
257             foreach (SoapSchemaMember member in members) {
258                 XmlSchemaElement element = new XmlSchemaElement();
259                 element.Name = member.MemberName;
260                 element.SchemaTypeName = member.MemberType;
261                 seq.Items.Add(element);
262             }
263             MembersMapping mapping = ImportMembersType(type, null, name);
264
265             ElementAccessor accessor = new ElementAccessor();
266             accessor.Name = Accessor.EscapeName(name);
267             accessor.Namespace = ns;
268             accessor.Mapping = mapping;
269             accessor.IsNullable = false;
270             accessor.Form = XmlSchemaForm.Qualified;
271             return new XmlMembersMapping(Scope, accessor, XmlMappingAccess.Read | XmlMappingAccess.Write);
272         }
273
274         ElementAccessor ImportElement(XmlQualifiedName name, Type desiredMappingType, Type baseType) {
275             XmlSchemaElement element = FindElement(name);
276             ElementAccessor accessor = (ElementAccessor)ImportedElements[element];
277             if (accessor != null) return accessor;
278             accessor = ImportElement(element, string.Empty, desiredMappingType, baseType, name.Namespace, true);
279             ElementAccessor existing = (ElementAccessor)ImportedElements[element];
280             if (existing != null) {
281                 return existing;
282             }
283             ImportedElements.Add(element, accessor);
284             return accessor;
285         }
286
287         ElementAccessor ImportElement(XmlSchemaElement element, string identifier, Type desiredMappingType, Type baseType, string ns, bool topLevelElement) {
288             if (!element.RefName.IsEmpty) {
289                 // we cannot re-use the accessor for the element refs
290                 ElementAccessor topAccessor = ImportElement(element.RefName, desiredMappingType, baseType);
291                 if (element.IsMultipleOccurrence && topAccessor.Mapping is ArrayMapping) {
292                     ElementAccessor refAccessor = topAccessor.Clone();
293                     refAccessor.IsTopLevelInSchema = false;
294                     refAccessor.Mapping.ReferencedByElement = true;
295                     return refAccessor;
296                 }
297                 return topAccessor;
298             }
299
300             if (element.Name.Length == 0) {
301                 XmlQualifiedName parentType = XmlSchemas.GetParentName(element);
302                 throw new InvalidOperationException(Res.GetString(Res.XmlElementHasNoName, parentType.Name, parentType.Namespace));
303             }
304             string unescapedName = Accessor.UnescapeName(element.Name);
305             if (identifier.Length == 0)
306                 identifier = CodeIdentifier.MakeValid(unescapedName);
307             else
308                 identifier += CodeIdentifier.MakePascal(unescapedName);
309             TypeMapping mapping = ImportElementType(element, identifier, desiredMappingType, baseType, ns);
310             ElementAccessor accessor = new ElementAccessor();
311             accessor.IsTopLevelInSchema = element.Parent is XmlSchema;
312             accessor.Name = element.Name;
313             accessor.Namespace = ns;
314             accessor.Mapping = mapping;
315             accessor.IsOptional = element.MinOccurs == 0m;
316
317             if (element.DefaultValue != null) {
318                 accessor.Default = element.DefaultValue;
319             }
320             else if (element.FixedValue != null) {
321                 accessor.Default = element.FixedValue;
322                 accessor.IsFixed = true;
323             }
324
325             if (mapping is SpecialMapping && ((SpecialMapping)mapping).NamedAny)
326                 accessor.Any = true;
327             accessor.IsNullable = element.IsNillable;
328             if (topLevelElement) {
329                 accessor.Form = XmlSchemaForm.Qualified;
330             }
331             else {
332                 accessor.Form = ElementForm(ns, element);
333             }
334             return accessor;
335         }
336
337         TypeMapping ImportElementType(XmlSchemaElement element, string identifier, Type desiredMappingType, Type baseType, string ns) {
338             TypeMapping mapping;
339             if (!element.SchemaTypeName.IsEmpty) {
340                 mapping = ImportType(element.SchemaTypeName, desiredMappingType, baseType, TypeFlags.CanBeElementValue, false);
341                 if (!mapping.ReferencedByElement) {
342                     object type = FindType(element.SchemaTypeName, TypeFlags.CanBeElementValue);
343                     XmlSchemaObject parent = element;
344                     while (parent.Parent != null && type != parent) {
345                         parent = parent.Parent;
346                     }
347                     mapping.ReferencedByElement = (type != parent);
348                 }
349             }
350             else if (element.SchemaType != null) {
351                 if (element.SchemaType is XmlSchemaComplexType)
352                     mapping = ImportType((XmlSchemaComplexType)element.SchemaType, ns, identifier, desiredMappingType, baseType, TypeFlags.CanBeElementValue);
353                 else
354                     mapping = ImportDataType((XmlSchemaSimpleType)element.SchemaType, ns, identifier, baseType, TypeFlags.CanBeElementValue | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeTextValue, false);
355                 mapping.ReferencedByElement = true;
356             }
357             else if (!element.SubstitutionGroup.IsEmpty)
358                 mapping = ImportElementType(FindElement(element.SubstitutionGroup), identifier, desiredMappingType, baseType, ns);
359             else {
360                 if (desiredMappingType == typeof(MembersMapping)) {
361                     mapping = ImportMembersType(new XmlSchemaType(), ns, identifier);
362                 }
363                 else {
364                     mapping = ImportRootMapping();
365                 }
366             }
367             if (!(desiredMappingType.IsAssignableFrom(mapping.GetType())))
368                 throw new InvalidOperationException(Res.GetString(Res.XmlElementImportedTwice, element.Name, ns, mapping.GetType().Name, desiredMappingType.Name));
369
370             // let the extensions to run
371             if (!mapping.TypeDesc.IsMappedType) {
372                 RunSchemaExtensions(mapping, element.SchemaTypeName, element.SchemaType, element, TypeFlags.CanBeElementValue);
373             }
374             return mapping;
375         }
376
377         void RunSchemaExtensions(TypeMapping mapping, XmlQualifiedName qname, XmlSchemaType type, XmlSchemaObject context, TypeFlags flags) {
378             string typeName = null;
379             SchemaImporterExtension typeOwner = null;
380             CodeCompileUnit compileUnit = new CodeCompileUnit();
381             CodeNamespace mainNamespace = new CodeNamespace();
382             compileUnit.Namespaces.Add(mainNamespace);
383
384             if (!qname.IsEmpty) {
385                 typeName = FindExtendedType(qname.Name, qname.Namespace, context, compileUnit, mainNamespace, out typeOwner);
386             }
387             else if (type != null) {
388                 typeName = FindExtendedType(type, context, compileUnit, mainNamespace, out typeOwner);
389             }
390             else if (context is XmlSchemaAny) {
391                 typeName = FindExtendedAnyElement((XmlSchemaAny)context, ((flags & TypeFlags.CanBeTextValue) != 0), compileUnit, mainNamespace, out typeOwner);
392             }
393
394             if (typeName != null && typeName.Length > 0) {
395                 // check if the type name is valid 
396                 typeName = typeName.Replace('+', '.');
397                 try {
398                     CodeGenerator.ValidateIdentifiers(new CodeTypeReference(typeName));
399                 }
400                 catch (ArgumentException) {
401                     if (qname.IsEmpty) {
402                         throw new InvalidOperationException(Res.GetString(Res.XmlImporterExtensionBadLocalTypeName, typeOwner.GetType().FullName, typeName));
403                     }
404                     else {
405                         throw new InvalidOperationException(Res.GetString(Res.XmlImporterExtensionBadTypeName, typeOwner.GetType().FullName, qname.Name, qname.Namespace, typeName)); 
406                     }
407                 }
408                 // 
409
410
411                 foreach (CodeNamespace ns in compileUnit.Namespaces) {
412                     CodeGenerator.ValidateIdentifiers(ns);
413                 }
414                 // 
415
416                 mapping.TypeDesc = mapping.TypeDesc.CreateMappedTypeDesc(new MappedTypeDesc(typeName, qname.Name, qname.Namespace, type, context, typeOwner, mainNamespace, compileUnit.ReferencedAssemblies));
417
418                 if (mapping is ArrayMapping) {
419                     TypeMapping top = ((ArrayMapping)mapping).TopLevelMapping;
420                     top.TypeName =  mapping.TypeName;
421                     top.TypeDesc = mapping.TypeDesc;
422                 }
423                 else {
424                     mapping.TypeName = qname.IsEmpty ? null : typeName;
425                 }
426             }
427         }
428         string GenerateUniqueTypeName(string desiredName, string ns) {
429             int i = 1;
430
431             string typeName = desiredName;
432             while (true) {
433                 XmlQualifiedName qname = new XmlQualifiedName(typeName, ns);
434
435                 object type = Schemas.Find(qname, typeof(XmlSchemaType));
436                 if (type == null) {
437                     break;
438                 }
439                 typeName = desiredName + i.ToString(CultureInfo.InvariantCulture);
440                 i++;
441             }
442             typeName = CodeIdentifier.MakeValid(typeName);
443             return TypeIdentifiers.AddUnique(typeName, typeName);
444         }
445
446         [PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")]
447         internal override void ImportDerivedTypes(XmlQualifiedName baseName) {
448             foreach (XmlSchema schema in Schemas) {
449                 if (Schemas.IsReference(schema)) continue;
450                 if (XmlSchemas.IsDataSet(schema)) continue;
451                 XmlSchemas.Preprocess(schema);
452                 foreach (object item in schema.SchemaTypes.Values) {
453                     if (item is XmlSchemaType) {
454                         XmlSchemaType type = (XmlSchemaType)item;
455                         if (type.DerivedFrom == baseName && TypesInUse[type.Name, schema.TargetNamespace] == null) {
456                             ImportType(type.QualifiedName, typeof(TypeMapping), null, TypeFlags.CanBeElementValue, false);
457                         }
458                     }
459                 }
460             }
461         }
462
463         TypeMapping ImportType(XmlQualifiedName name, Type desiredMappingType, Type baseType, TypeFlags flags, bool addref) {
464             if (name.Name == Soap.UrType && name.Namespace == XmlSchema.Namespace)
465                 return ImportRootMapping();
466             object type = FindType(name, flags);
467
468             TypeMapping mapping = (TypeMapping)ImportedMappings[type];
469             if (mapping != null && desiredMappingType.IsAssignableFrom(mapping.GetType()))
470                 return mapping;
471
472             if (addref)
473                 AddReference(name, TypesInUse, Res.XmlCircularTypeReference);
474             if (type is XmlSchemaComplexType) {
475                 mapping = ImportType((XmlSchemaComplexType)type, name.Namespace, name.Name, desiredMappingType, baseType, flags);
476             }
477             else if (type is XmlSchemaSimpleType)
478                 mapping = ImportDataType((XmlSchemaSimpleType)type, name.Namespace, name.Name, baseType, flags, false);
479             else
480                 throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
481
482             if (addref && name.Namespace != XmlSchema.Namespace)
483                 RemoveReference(name, TypesInUse);
484
485             return mapping;
486         }
487
488         TypeMapping ImportType(XmlSchemaComplexType type, string typeNs, string identifier, Type desiredMappingType, Type baseType, TypeFlags flags) {
489             if (type.Redefined != null) {
490                 // we do not support redefine in the current version
491                 throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedRedefine, type.Name, typeNs));
492             }   
493             if (desiredMappingType == typeof(TypeMapping)) {
494                 TypeMapping mapping = null;
495
496                 if (baseType == null) {
497                     if ((mapping = ImportArrayMapping(type, identifier, typeNs, false)) == null) {
498                         mapping = ImportAnyMapping(type, identifier, typeNs, false);
499                     }
500                 }
501                 if (mapping == null) {
502                     mapping = ImportStructType(type, typeNs, identifier, baseType, false);
503
504                     if (mapping != null && type.Name != null && type.Name.Length != 0)
505                         ImportDerivedTypes(new XmlQualifiedName(identifier, typeNs));
506                 }
507                 return mapping;
508             }
509             else if (desiredMappingType == typeof(MembersMapping))
510                 return ImportMembersType(type, typeNs, identifier);
511             else
512                 throw new ArgumentException(Res.GetString(Res.XmlInternalError), "desiredMappingType");
513         }
514
515         MembersMapping ImportMembersType(XmlSchemaType type, string typeNs, string identifier) {
516             if (!type.DerivedFrom.IsEmpty) throw new InvalidOperationException(Res.GetString(Res.XmlMembersDeriveError));
517             CodeIdentifiers memberScope = new CodeIdentifiers();
518             memberScope.UseCamelCasing = true;
519             bool needExplicitOrder = false;
520             MemberMapping[] members = ImportTypeMembers(type, typeNs, identifier, memberScope, new CodeIdentifiers(), new NameTable(), ref needExplicitOrder, false, false);
521             MembersMapping mappings = new MembersMapping();
522             mappings.HasWrapperElement = true;
523             mappings.TypeDesc = Scope.GetTypeDesc(typeof(object[]));
524             mappings.Members = members;
525             return mappings;
526         }
527
528         StructMapping ImportStructType(XmlSchemaType type, string typeNs, string identifier, Type baseType, bool arrayLike) {
529             TypeDesc baseTypeDesc = null;
530             TypeMapping baseMapping = null;
531
532             bool isRootType = false;
533             if (!type.DerivedFrom.IsEmpty) {
534                 baseMapping = ImportType(type.DerivedFrom, typeof(TypeMapping), null, TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue, false);
535
536                 if (baseMapping is StructMapping)
537                     baseTypeDesc = ((StructMapping)baseMapping).TypeDesc;
538                 else if (baseMapping is ArrayMapping) {
539                     baseMapping = ((ArrayMapping)baseMapping).TopLevelMapping;
540                     if (baseMapping != null) {
541                         baseMapping.ReferencedByTopLevelElement = false;
542                         baseMapping.ReferencedByElement = true;
543                         baseTypeDesc = baseMapping.TypeDesc;
544                     }
545                 }
546                 else
547                     baseMapping = null;
548             }
549             if (baseTypeDesc == null && baseType != null)
550                 baseTypeDesc = Scope.GetTypeDesc(baseType);
551             if (baseMapping == null) 
552             {
553                 baseMapping = GetRootMapping();
554                 isRootType = true;
555             }
556             Mapping previousMapping = (Mapping)ImportedMappings[type];
557             if (previousMapping != null) {
558                 if (previousMapping is StructMapping) {
559                     return (StructMapping)previousMapping;
560                 }
561                 else if (arrayLike && previousMapping is ArrayMapping){
562                     ArrayMapping arrayMapping = (ArrayMapping)previousMapping;
563                     if (arrayMapping.TopLevelMapping != null) {
564                         return arrayMapping.TopLevelMapping;
565                     }
566                 }
567                 else {
568                     throw new InvalidOperationException(Res.GetString(Res.XmlTypeUsedTwice, type.QualifiedName.Name, type.QualifiedName.Namespace));
569                 }
570             }
571             StructMapping structMapping = new StructMapping();
572             structMapping.IsReference = Schemas.IsReference(type);
573             TypeFlags flags = TypeFlags.Reference;
574             if (type is XmlSchemaComplexType) {
575                 if (((XmlSchemaComplexType)type).IsAbstract) 
576                     flags |= TypeFlags.Abstract;
577             }
578
579             identifier = Accessor.UnescapeName(identifier);
580             string typeName = type.Name == null || type.Name.Length == 0 ? GenerateUniqueTypeName(identifier, typeNs) : GenerateUniqueTypeName(identifier);
581             structMapping.TypeDesc = new TypeDesc(typeName, typeName, TypeKind.Struct, baseTypeDesc, flags);
582             structMapping.Namespace = typeNs;
583             structMapping.TypeName = type.Name == null || type.Name.Length == 0 ? null : identifier;
584             structMapping.BaseMapping = (StructMapping)baseMapping;
585             if (!arrayLike)
586                 ImportedMappings.Add(type, structMapping);
587             CodeIdentifiers members = new CodeIdentifiers();
588             CodeIdentifiers membersScope = structMapping.BaseMapping.Scope.Clone();
589             members.AddReserved(typeName);
590             membersScope.AddReserved(typeName);
591             AddReservedIdentifiersForDataBinding(members);
592             if (isRootType)
593                 AddReservedIdentifiersForDataBinding(membersScope);
594             bool needExplicitOrder = false;
595             structMapping.Members = ImportTypeMembers(type, typeNs, identifier, members, membersScope, structMapping, ref needExplicitOrder, true, true);
596
597             if (!IsAllGroup(type)) {
598                 if (needExplicitOrder && !GenerateOrder) {
599                     structMapping.SetSequence();
600                 }
601                 else if (GenerateOrder) {
602                     structMapping.IsSequence = true;
603                 }
604             }
605
606             for (int i = 0; i < structMapping.Members.Length; i++) {
607                 StructMapping declaringMapping;
608                 MemberMapping baseMember = ((StructMapping)baseMapping).FindDeclaringMapping(structMapping.Members[i], out declaringMapping, structMapping.TypeName);
609                 if (baseMember != null && baseMember.TypeDesc != structMapping.Members[i].TypeDesc)
610                     throw new InvalidOperationException(Res.GetString(Res.XmlIllegalOverride, type.Name, baseMember.Name, baseMember.TypeDesc.FullName, structMapping.Members[i].TypeDesc.FullName, declaringMapping.TypeDesc.FullName));
611             }
612             structMapping.Scope = membersScope;
613             Scope.AddTypeMapping(structMapping);
614             return structMapping;
615         }
616
617         bool IsAllGroup(XmlSchemaType type) {
618             TypeItems items = GetTypeItems(type);
619             return (items.Particle != null) && (items.Particle is XmlSchemaAll);
620         }
621
622         StructMapping ImportStructDataType(XmlSchemaSimpleType dataType, string typeNs, string identifier, Type baseType) {
623             identifier = Accessor.UnescapeName(identifier);
624             string typeName = GenerateUniqueTypeName(identifier);
625             StructMapping structMapping = new StructMapping();
626             structMapping.IsReference = Schemas.IsReference(dataType);
627             TypeFlags flags = TypeFlags.Reference;
628             TypeDesc baseTypeDesc = Scope.GetTypeDesc(baseType);
629             structMapping.TypeDesc = new TypeDesc(typeName, typeName, TypeKind.Struct, baseTypeDesc, flags);
630             structMapping.Namespace = typeNs;
631             structMapping.TypeName = identifier;
632             CodeIdentifiers members = new CodeIdentifiers();
633             members.AddReserved(typeName);
634             AddReservedIdentifiersForDataBinding(members);
635             ImportTextMember(members, new CodeIdentifiers(), null);
636             structMapping.Members = (MemberMapping[])members.ToArray(typeof(MemberMapping));
637             structMapping.Scope = members;
638             Scope.AddTypeMapping(structMapping);
639             return structMapping;
640         }
641
642         class TypeItems {
643             internal XmlSchemaObjectCollection Attributes = new XmlSchemaObjectCollection();
644             internal XmlSchemaAnyAttribute AnyAttribute;
645             internal XmlSchemaGroupBase Particle;
646             internal XmlQualifiedName baseSimpleType;
647             internal bool IsUnbounded;
648         }
649
650         MemberMapping[] ImportTypeMembers(XmlSchemaType type, string typeNs, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, INameScope elementsScope, ref bool needExplicitOrder, bool order, bool allowUnboundedElements) {
651             TypeItems items = GetTypeItems(type);
652             bool mixed = IsMixed(type);
653
654             if (mixed) {
655                 // check if we can transfer the attribute to the base class
656                 XmlSchemaType t = type;
657                 while (!t.DerivedFrom.IsEmpty) {
658                     t = FindType(t.DerivedFrom, TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue);
659                     if (IsMixed(t)) {
660                         // keep the mixed attribute on the base class
661                         mixed = false;
662                         break;
663                     }
664                 }
665             }
666
667             if (items.Particle != null) {
668                 ImportGroup(items.Particle, identifier, members, membersScope, elementsScope, typeNs, mixed, ref needExplicitOrder, order, items.IsUnbounded, allowUnboundedElements);
669             }
670             for (int i = 0; i < items.Attributes.Count; i++) {
671                 object item = items.Attributes[i];
672                 if (item is XmlSchemaAttribute) {
673                     ImportAttributeMember((XmlSchemaAttribute)item, identifier, members, membersScope, typeNs);
674                 }
675                 else if (item is XmlSchemaAttributeGroupRef) {
676                     XmlQualifiedName groupName = ((XmlSchemaAttributeGroupRef)item).RefName;
677                     ImportAttributeGroupMembers(FindAttributeGroup(groupName), identifier, members, membersScope, groupName.Namespace);
678                 }
679             }
680             if (items.AnyAttribute != null) {
681                 ImportAnyAttributeMember(items.AnyAttribute, members, membersScope);
682             }
683             
684             if (items.baseSimpleType != null || (items.Particle == null && mixed)) {
685                 ImportTextMember(members, membersScope, mixed ? null : items.baseSimpleType);
686             }
687
688             ImportXmlnsDeclarationsMember(type, members, membersScope);
689             MemberMapping[] typeMembers = (MemberMapping[])members.ToArray(typeof(MemberMapping));
690             return typeMembers;
691         }
692
693         internal static bool IsMixed(XmlSchemaType type) {
694             if (!(type is XmlSchemaComplexType))
695                 return false;
696
697             XmlSchemaComplexType ct = (XmlSchemaComplexType)type;
698             bool mixed = ct.IsMixed;
699
700             // check the mixed attribute on the complexContent
701             if (!mixed) {
702                 if (ct.ContentModel != null && ct.ContentModel is XmlSchemaComplexContent) {
703                     mixed = ((XmlSchemaComplexContent)ct.ContentModel).IsMixed;
704                 }
705             }
706             return mixed;
707         }
708
709         TypeItems GetTypeItems(XmlSchemaType type) {
710             TypeItems items = new TypeItems();
711             if (type is XmlSchemaComplexType) {
712                 XmlSchemaParticle particle = null;
713                 XmlSchemaComplexType ct = (XmlSchemaComplexType)type;
714                 if (ct.ContentModel != null) {
715                     XmlSchemaContent content = ct.ContentModel.Content;
716                     if (content is XmlSchemaComplexContentExtension) {
717                         XmlSchemaComplexContentExtension extension = (XmlSchemaComplexContentExtension)content;
718                         items.Attributes = extension.Attributes;
719                         items.AnyAttribute = extension.AnyAttribute;
720                         particle = extension.Particle;
721                     }
722                     else if (content is XmlSchemaSimpleContentExtension) {
723                         XmlSchemaSimpleContentExtension extension = (XmlSchemaSimpleContentExtension)content;
724                         items.Attributes = extension.Attributes;
725                         items.AnyAttribute = extension.AnyAttribute;
726                         items.baseSimpleType = extension.BaseTypeName;
727                     }
728                 }
729                 else {
730                     items.Attributes = ct.Attributes;
731                     items.AnyAttribute = ct.AnyAttribute;
732                     particle = ct.Particle;
733                 }
734                 if (particle is XmlSchemaGroupRef) {
735                     XmlSchemaGroupRef refGroup = (XmlSchemaGroupRef)particle;
736                     items.Particle = FindGroup(refGroup.RefName).Particle;
737                     items.IsUnbounded = particle.IsMultipleOccurrence;
738                 }
739                 else if (particle is XmlSchemaGroupBase) {
740                     items.Particle = (XmlSchemaGroupBase)particle;
741                     items.IsUnbounded = particle.IsMultipleOccurrence;
742                 }
743             }
744             return items;
745         }
746
747         void ImportGroup(XmlSchemaGroupBase group, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, INameScope elementsScope, string ns, bool mixed, ref bool needExplicitOrder, bool allowDuplicates, bool groupRepeats, bool allowUnboundedElements) {
748             if (group is XmlSchemaChoice)
749                 ImportChoiceGroup((XmlSchemaChoice)group, identifier, members, membersScope, elementsScope, ns, groupRepeats, ref needExplicitOrder, allowDuplicates);
750             else
751                 ImportGroupMembers(group, identifier, members, membersScope, elementsScope, ns, groupRepeats, ref mixed, ref needExplicitOrder, allowDuplicates, allowUnboundedElements);
752
753             if (mixed) {
754                 ImportTextMember(members, membersScope, null);
755             }
756         }
757
758         MemberMapping ImportChoiceGroup(XmlSchemaGroupBase group, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, INameScope elementsScope, string ns, bool groupRepeats, ref bool needExplicitOrder, bool allowDuplicates) {
759             NameTable choiceElements = new NameTable();
760             if (GatherGroupChoices(group, choiceElements, identifier, ns, ref needExplicitOrder, allowDuplicates))
761                 groupRepeats = true;
762             MemberMapping member = new MemberMapping();
763             member.Elements = (ElementAccessor[])choiceElements.ToArray(typeof(ElementAccessor));
764             Array.Sort(member.Elements, new ElementComparer());
765
766             AddScopeElements(elementsScope, member.Elements, ref needExplicitOrder, allowDuplicates);
767             bool duplicateTypes = false;
768             bool nullableMismatch = false;
769             Hashtable uniqueTypeDescs = new Hashtable(member.Elements.Length);
770
771             for (int i = 0; i < member.Elements.Length; i++) {
772                 ElementAccessor element = member.Elements[i];
773                 string tdFullName = element.Mapping.TypeDesc.FullName;
774                 object val = uniqueTypeDescs[tdFullName];
775                 if (val != null) {
776                     duplicateTypes = true;
777                     ElementAccessor existingElement = (ElementAccessor)val;
778                     if (!nullableMismatch && existingElement.IsNullable != element.IsNullable)
779                         nullableMismatch = true;
780                 }
781                 else {
782                     uniqueTypeDescs.Add(tdFullName, element);
783                 }
784
785                 ArrayMapping arrayMapping = element.Mapping as ArrayMapping;
786                 if (arrayMapping != null) {
787                     if (IsNeedXmlSerializationAttributes(arrayMapping)) {
788                         // we cannot use ArrayMapping in choice if additional custom 
789                         // serialization attributes are needed to serialize it
790                         element.Mapping = arrayMapping.TopLevelMapping;
791                         element.Mapping.ReferencedByTopLevelElement = false;
792                         element.Mapping.ReferencedByElement = true;
793                     }
794                 }
795             }
796             if (nullableMismatch)
797                 member.TypeDesc = Scope.GetTypeDesc(typeof(object));
798             else
799             {
800                 TypeDesc[] typeDescs = new TypeDesc[uniqueTypeDescs.Count];
801                 IEnumerator enumerator = uniqueTypeDescs.Values.GetEnumerator();
802                 for (int i = 0; i < typeDescs.Length; i++)
803                 {
804                     if (!enumerator.MoveNext())
805                         break;
806                     typeDescs[i] = ((ElementAccessor)enumerator.Current).Mapping.TypeDesc;
807                 }
808                 member.TypeDesc = TypeDesc.FindCommonBaseTypeDesc(typeDescs);
809                 if (member.TypeDesc == null) member.TypeDesc = Scope.GetTypeDesc(typeof(object));
810             }
811
812             if (groupRepeats)
813                 member.TypeDesc = member.TypeDesc.CreateArrayTypeDesc();
814
815             if (membersScope != null) {
816                 member.Name = membersScope.AddUnique(groupRepeats ? "Items" : "Item", member);
817                 if (members != null) {
818                     members.Add(member.Name, member);
819                 }
820             }
821
822             if (duplicateTypes) {
823                 member.ChoiceIdentifier = new ChoiceIdentifierAccessor();
824                 member.ChoiceIdentifier.MemberName = member.Name + "ElementName";
825                 // we need to create the EnumMapping to store all of the element names
826                 member.ChoiceIdentifier.Mapping = ImportEnumeratedChoice(member.Elements, ns, member.Name + "ChoiceType");
827                 member.ChoiceIdentifier.MemberIds = new string[member.Elements.Length];
828                 ConstantMapping[] constants = ((EnumMapping)member.ChoiceIdentifier.Mapping).Constants;
829                 for (int i = 0; i < member.Elements.Length; i++) {
830                     member.ChoiceIdentifier.MemberIds[i] = constants[i].Name;
831                 }
832                 MemberMapping choiceIdentifier = new MemberMapping();
833                 choiceIdentifier.Ignore = true;
834                 choiceIdentifier.Name = member.ChoiceIdentifier.MemberName;
835                 if (groupRepeats) {
836                     choiceIdentifier.TypeDesc = member.ChoiceIdentifier.Mapping.TypeDesc.CreateArrayTypeDesc();
837                 }
838                 else {
839                     choiceIdentifier.TypeDesc = member.ChoiceIdentifier.Mapping.TypeDesc;
840                 }
841
842                 // create element accessor for the choiceIdentifier
843
844                 ElementAccessor choiceAccessor = new ElementAccessor();
845                 choiceAccessor.Name = choiceIdentifier.Name;
846                 choiceAccessor.Namespace = ns;
847                 choiceAccessor.Mapping =  member.ChoiceIdentifier.Mapping;
848                 choiceIdentifier.Elements  = new ElementAccessor[] {choiceAccessor};
849
850                 if (membersScope != null) {
851                     choiceAccessor.Name = choiceIdentifier.Name = member.ChoiceIdentifier.MemberName = membersScope.AddUnique(member.ChoiceIdentifier.MemberName, choiceIdentifier);
852                     if (members != null) {
853                         members.Add(choiceAccessor.Name, choiceIdentifier);
854                     }
855                 }
856             }
857             return member;
858         }
859
860         bool IsNeedXmlSerializationAttributes(ArrayMapping arrayMapping) {
861             if (arrayMapping.Elements.Length != 1)
862                 return true;
863
864             ElementAccessor item = arrayMapping.Elements[0];
865             TypeMapping itemMapping = item.Mapping;
866
867             if (item.Name != itemMapping.DefaultElementName)
868                 return true;
869
870             if (item.Form != XmlSchemaForm.None && item.Form != XmlSchemaExporter.elementFormDefault)
871                 return true;
872
873             if (item.Mapping.TypeDesc != null)
874             {
875                 if (item.IsNullable != item.Mapping.TypeDesc.IsNullable)
876                     return true;
877
878                 if (item.Mapping.TypeDesc.IsAmbiguousDataType)
879                     return true;
880             }
881             return false;
882         }
883
884         bool GatherGroupChoices(XmlSchemaGroup group, NameTable choiceElements, string identifier, string ns, ref bool needExplicitOrder, bool allowDuplicates) {
885             return GatherGroupChoices(group.Particle, choiceElements, identifier, ns, ref needExplicitOrder, allowDuplicates);
886         }
887
888         bool GatherGroupChoices(XmlSchemaParticle particle, NameTable choiceElements, string identifier, string ns, ref bool needExplicitOrder, bool allowDuplicates) {
889             if (particle is XmlSchemaGroupRef) {
890                 XmlSchemaGroupRef refGroup = (XmlSchemaGroupRef)particle;
891                 if (!refGroup.RefName.IsEmpty) {
892                     AddReference(refGroup.RefName, GroupsInUse, Res.XmlCircularGroupReference);
893                     if (GatherGroupChoices(FindGroup(refGroup.RefName), choiceElements, identifier, refGroup.RefName.Namespace, ref needExplicitOrder, allowDuplicates)) {
894                         RemoveReference(refGroup.RefName, GroupsInUse);
895                         return true;
896                     }
897                     RemoveReference(refGroup.RefName, GroupsInUse);
898                 }
899             }
900             else if (particle is XmlSchemaGroupBase) {
901                 XmlSchemaGroupBase group = (XmlSchemaGroupBase)particle;
902                 bool groupRepeats = group.IsMultipleOccurrence;
903                 XmlSchemaAny any = null;
904                 bool duplicateElements = false;
905                 for (int i = 0; i < group.Items.Count; i++) {
906                     object item = group.Items[i];
907                     if (item is XmlSchemaGroupBase || item is XmlSchemaGroupRef) {
908                         if (GatherGroupChoices((XmlSchemaParticle)item, choiceElements, identifier, ns, ref needExplicitOrder, allowDuplicates))
909                             groupRepeats = true;
910                     }
911                     else if (item is XmlSchemaAny) {
912                         if (GenerateOrder) {
913                             AddScopeElements(choiceElements, ImportAny((XmlSchemaAny)item, true, ns), ref duplicateElements, allowDuplicates);
914                         }
915                         else {
916                             any = (XmlSchemaAny)item;
917                         }
918                     }
919                     else if (item is XmlSchemaElement) {
920                         XmlSchemaElement element = (XmlSchemaElement)item;
921                         XmlSchemaElement headElement = GetTopLevelElement(element);
922                         if (headElement != null) {
923                             XmlSchemaElement[] elements = GetEquivalentElements(headElement);
924                             for (int j = 0; j < elements.Length; j++) {
925                                 if (elements[j].IsMultipleOccurrence) groupRepeats = true;
926                                 AddScopeElement(choiceElements, ImportElement(elements[j], identifier, typeof(TypeMapping), null, elements[j].QualifiedName.Namespace, true), ref duplicateElements, allowDuplicates);
927                             }
928                         }
929                         if (element.IsMultipleOccurrence) groupRepeats = true;
930                         AddScopeElement(choiceElements, ImportElement(element, identifier, typeof(TypeMapping), null, element.QualifiedName.Namespace, false), ref duplicateElements, allowDuplicates);
931                     }
932                 }
933                 if (any != null) {
934                     AddScopeElements(choiceElements, ImportAny(any, true, ns), ref duplicateElements, allowDuplicates);
935                 }
936                 if (!groupRepeats && !(group is XmlSchemaChoice) && group.Items.Count > 1) {
937                     groupRepeats = true;
938                 }
939                 return groupRepeats;
940             }
941             return false;
942         }
943
944         void AddScopeElement(INameScope scope, ElementAccessor element, ref bool duplicateElements, bool allowDuplicates) {
945             if (scope == null)
946                 return; 
947
948             ElementAccessor scopeElement = (ElementAccessor)scope[element.Name, element.Namespace];
949             if (scopeElement != null) {
950                 if (!allowDuplicates) {
951                     throw new InvalidOperationException(Res.GetString(Res.XmlDuplicateElementInScope, element.Name, element.Namespace));
952                 }
953                 if (scopeElement.Mapping.TypeDesc != element.Mapping.TypeDesc) {
954                     throw new InvalidOperationException(Res.GetString(Res.XmlDuplicateElementInScope1, element.Name, element.Namespace));
955                 }
956                 duplicateElements = true;
957             }
958             else {
959                 scope[element.Name, element.Namespace] = element;
960             }
961         }
962
963         void AddScopeElements(INameScope scope, ElementAccessor[] elements, ref bool duplicateElements, bool allowDuplicates) {
964             for (int i = 0; i < elements.Length; i++) {
965                 AddScopeElement(scope, elements[i], ref duplicateElements, allowDuplicates);
966             }
967         }
968
969         void ImportGroupMembers(XmlSchemaParticle particle, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, INameScope elementsScope, string ns, bool groupRepeats, ref bool mixed, ref bool needExplicitOrder, bool allowDuplicates, bool allowUnboundedElements) {
970
971             if (particle is XmlSchemaGroupRef) {
972                 XmlSchemaGroupRef refGroup = (XmlSchemaGroupRef)particle;
973                 if (!refGroup.RefName.IsEmpty) {
974                     AddReference(refGroup.RefName, GroupsInUse, Res.XmlCircularGroupReference);
975                     ImportGroupMembers(FindGroup(refGroup.RefName).Particle, identifier, members, membersScope, elementsScope, refGroup.RefName.Namespace, groupRepeats | refGroup.IsMultipleOccurrence, ref mixed, ref needExplicitOrder, allowDuplicates, allowUnboundedElements);
976                     RemoveReference(refGroup.RefName, GroupsInUse);
977                 }
978             }
979             else if (particle is XmlSchemaGroupBase) {
980                 XmlSchemaGroupBase group = (XmlSchemaGroupBase)particle;
981
982                 if (group.IsMultipleOccurrence)
983                     groupRepeats = true;
984
985                 if (GenerateOrder && groupRepeats && group.Items.Count > 1) {
986                     ImportChoiceGroup(group, identifier, members, membersScope, elementsScope, ns, groupRepeats, ref needExplicitOrder, allowDuplicates);
987                 }
988                 else {
989                     for (int i = 0; i < group.Items.Count; i++) {
990                         object item = group.Items[i];
991                         if (item is XmlSchemaChoice)
992                             ImportChoiceGroup((XmlSchemaGroupBase)item, identifier, members, membersScope, elementsScope, ns, groupRepeats, ref needExplicitOrder, allowDuplicates);
993                         else if (item is XmlSchemaElement)
994                             ImportElementMember((XmlSchemaElement)item, identifier, members, membersScope, elementsScope, ns, groupRepeats, ref needExplicitOrder, allowDuplicates, allowUnboundedElements);
995                         else if (item is XmlSchemaAny) {
996                             ImportAnyMember((XmlSchemaAny)item, identifier, members, membersScope, elementsScope, ns, ref mixed, ref needExplicitOrder, allowDuplicates);
997                         }
998                         else if (item is XmlSchemaParticle) {
999                             ImportGroupMembers((XmlSchemaParticle)item, identifier, members, membersScope, elementsScope, ns, groupRepeats, ref mixed, ref needExplicitOrder, allowDuplicates, true);
1000                         }
1001                     }
1002                 }
1003             }
1004         }
1005
1006         XmlSchemaElement GetTopLevelElement(XmlSchemaElement element) {
1007             if (!element.RefName.IsEmpty)
1008                 return FindElement(element.RefName);
1009             return null;
1010         }
1011
1012         XmlSchemaElement[] GetEquivalentElements(XmlSchemaElement element) {
1013             ArrayList equivalentElements = new ArrayList();
1014
1015             foreach (XmlSchema schema in Schemas.SchemaSet.Schemas()) {
1016                 for (int j = 0; j < schema.Items.Count; j++) {
1017                     object item = schema.Items[j];
1018                     if (item is XmlSchemaElement) {
1019                         XmlSchemaElement equivalentElement = (XmlSchemaElement)item;
1020                         if (!equivalentElement.IsAbstract &&
1021                             equivalentElement.SubstitutionGroup.Namespace == schema.TargetNamespace &&
1022                             equivalentElement.SubstitutionGroup.Name == element.Name) {
1023                             equivalentElements.Add(equivalentElement);
1024                         }
1025                     }
1026                 }
1027             }
1028
1029             return (XmlSchemaElement[])equivalentElements.ToArray(typeof(XmlSchemaElement));
1030         }
1031
1032         bool ImportSubstitutionGroupMember(XmlSchemaElement element, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, string ns, bool repeats, ref bool needExplicitOrder, bool allowDuplicates) {
1033             XmlSchemaElement[] elements = GetEquivalentElements(element);
1034             if (elements.Length == 0)
1035                 return false;
1036             XmlSchemaChoice choice = new XmlSchemaChoice();
1037             for (int i = 0; i < elements.Length; i++)
1038                 choice.Items.Add(elements[i]);
1039             if (!element.IsAbstract)
1040                 choice.Items.Add(element);
1041             if (identifier.Length == 0)
1042                 identifier = CodeIdentifier.MakeValid(Accessor.UnescapeName(element.Name));
1043             else
1044                 identifier += CodeIdentifier.MakePascal(Accessor.UnescapeName(element.Name));
1045             ImportChoiceGroup(choice, identifier, members, membersScope, null, ns, repeats, ref needExplicitOrder, allowDuplicates);
1046
1047             return true;
1048         }
1049
1050         void ImportTextMember(CodeIdentifiers members, CodeIdentifiers membersScope, XmlQualifiedName simpleContentType) {
1051             TypeMapping mapping;
1052             bool isMixed = false;
1053
1054             if (simpleContentType != null) {
1055                 // allow to use all primitive types
1056                 mapping = ImportType(simpleContentType, typeof(TypeMapping), null, TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue, false);
1057                 if (!(mapping is PrimitiveMapping || mapping.TypeDesc.CanBeTextValue)) {
1058                     return;
1059                 }
1060             }
1061             else {
1062                 // this is a case of the mixed content type, just generate string typeDesc
1063                 isMixed = true;
1064                 mapping = GetDefaultMapping(TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue);
1065             }
1066
1067             TextAccessor accessor = new TextAccessor();
1068             accessor.Mapping = mapping;
1069
1070             MemberMapping member = new MemberMapping();
1071             member.Elements = new ElementAccessor[0];
1072             member.Text = accessor;
1073             if (isMixed) {
1074                 // just generate code for the standard mixed case (string[] text)
1075                 member.TypeDesc = accessor.Mapping.TypeDesc.CreateArrayTypeDesc();
1076                 member.Name = members.MakeRightCase("Text");
1077             }
1078             else {
1079                 // import mapping for the simpleContent
1080                 PrimitiveMapping pm = (PrimitiveMapping)accessor.Mapping;
1081                 if (pm.IsList) {
1082                     member.TypeDesc = accessor.Mapping.TypeDesc.CreateArrayTypeDesc();
1083                     member.Name = members.MakeRightCase("Text");
1084                 }
1085                 else {
1086                     member.TypeDesc = accessor.Mapping.TypeDesc;
1087                     member.Name = members.MakeRightCase("Value");
1088                 }
1089             }
1090             member.Name = membersScope.AddUnique(member.Name, member);
1091             members.Add(member.Name, member);
1092         }
1093
1094         MemberMapping ImportAnyMember(XmlSchemaAny any, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, INameScope elementsScope, string ns, ref bool mixed, ref bool needExplicitOrder, bool allowDuplicates) {
1095             ElementAccessor[] accessors = ImportAny(any, !mixed, ns);
1096             AddScopeElements(elementsScope, accessors, ref needExplicitOrder, allowDuplicates);
1097             MemberMapping member = new MemberMapping();
1098             member.Elements = accessors;
1099             member.Name = membersScope.MakeRightCase("Any");
1100             member.Name = membersScope.AddUnique(member.Name, member);
1101             members.Add(member.Name, member);
1102             member.TypeDesc = ((TypeMapping)accessors[0].Mapping).TypeDesc;
1103
1104             bool repeats = any.IsMultipleOccurrence;
1105
1106             if (mixed) {
1107                 SpecialMapping textMapping = new SpecialMapping();
1108                 textMapping.TypeDesc = Scope.GetTypeDesc(typeof(XmlNode));
1109                 textMapping.TypeName = textMapping.TypeDesc.Name;
1110                 member.TypeDesc = textMapping.TypeDesc;
1111                 TextAccessor text = new TextAccessor();
1112                 text.Mapping = textMapping;
1113                 member.Text = text;
1114                 repeats = true;
1115                 mixed = false;
1116             }
1117
1118             if (repeats) {
1119                 member.TypeDesc = member.TypeDesc.CreateArrayTypeDesc();
1120             }
1121             return member;
1122         }
1123         ElementAccessor[] ImportAny(XmlSchemaAny any, bool makeElement, string targetNamespace) {
1124             SpecialMapping mapping = new SpecialMapping();
1125
1126             mapping.TypeDesc = Scope.GetTypeDesc(makeElement ? typeof(XmlElement) : typeof(XmlNode));
1127             mapping.TypeName = mapping.TypeDesc.Name;
1128
1129            
1130             TypeFlags flags = TypeFlags.CanBeElementValue;
1131             if (makeElement)
1132                 flags |= TypeFlags.CanBeTextValue;
1133
1134             // let the extensions to run
1135             RunSchemaExtensions(mapping, XmlQualifiedName.Empty, null, any, flags);
1136
1137             if (GenerateOrder && any.Namespace != null) {
1138                 NamespaceList list = new NamespaceList(any.Namespace, targetNamespace);
1139
1140                 if (list.Type == NamespaceList.ListType.Set) {
1141                     ICollection namespaces = list.Enumerate;
1142                     ElementAccessor[] accessors = new ElementAccessor[namespaces.Count == 0 ? 1 : namespaces.Count];
1143                     int count = 0;
1144                     foreach(string ns in list.Enumerate) {
1145                         ElementAccessor accessor = new ElementAccessor();
1146                         accessor.Mapping = mapping;
1147                         accessor.Any = true;
1148                         accessor.Namespace = ns;
1149                         accessors[count++] = accessor;
1150                     }
1151                     if (count > 0) {
1152                         return accessors;
1153                     }
1154                 }
1155             }
1156
1157             ElementAccessor anyAccessor = new ElementAccessor();
1158             anyAccessor.Mapping = mapping;
1159             anyAccessor.Any = true;
1160             return new ElementAccessor[] {anyAccessor};
1161         }
1162
1163         ElementAccessor ImportArray(XmlSchemaElement element, string identifier, string ns, bool repeats) {
1164             if (repeats) return null;
1165             if (element.SchemaType == null) return null;
1166             if (element.IsMultipleOccurrence) return null;
1167             XmlSchemaType type = element.SchemaType;
1168             ArrayMapping arrayMapping = ImportArrayMapping(type, identifier, ns, repeats);
1169             if (arrayMapping == null) return null;
1170             ElementAccessor arrayAccessor = new ElementAccessor();
1171             arrayAccessor.Name = element.Name;
1172             arrayAccessor.Namespace = ns;
1173             arrayAccessor.Mapping = arrayMapping;
1174             if (arrayMapping.TypeDesc.IsNullable)
1175                 arrayAccessor.IsNullable = element.IsNillable;
1176             arrayAccessor.Form = ElementForm(ns, element);
1177             return arrayAccessor;
1178         }
1179
1180         ArrayMapping ImportArrayMapping(XmlSchemaType type, string identifier, string ns, bool repeats) {
1181             if (!(type is XmlSchemaComplexType)) return null;
1182             if (!type.DerivedFrom.IsEmpty) return null;
1183             if (IsMixed(type)) return null;
1184
1185             Mapping previousMapping = (Mapping)ImportedMappings[type];
1186             if (previousMapping != null) {
1187                 if (previousMapping is ArrayMapping)
1188                     return (ArrayMapping)previousMapping;
1189                 else
1190                     return null;
1191             }
1192
1193             TypeItems items = GetTypeItems(type);
1194
1195             if (items.Attributes != null && items.Attributes.Count > 0) return null;
1196             if (items.AnyAttribute != null) return null;
1197             if (items.Particle == null) return null;
1198
1199             XmlSchemaGroupBase item = items.Particle;
1200             ArrayMapping arrayMapping = new ArrayMapping();
1201
1202             arrayMapping.TypeName = identifier;
1203             arrayMapping.Namespace = ns;
1204
1205             if (item is XmlSchemaChoice) {
1206                 XmlSchemaChoice choice = (XmlSchemaChoice)item;
1207                 if (!choice.IsMultipleOccurrence)
1208                     return null;
1209                 bool needExplicitOrder = false;
1210                 MemberMapping choiceMember = ImportChoiceGroup(choice, identifier, null, null, null, ns, true, ref needExplicitOrder, false);
1211                 if (choiceMember.ChoiceIdentifier != null) return null;
1212                 arrayMapping.TypeDesc = choiceMember.TypeDesc;
1213                 arrayMapping.Elements = choiceMember.Elements;
1214                 arrayMapping.TypeName = (type.Name == null || type.Name.Length == 0) ? "ArrayOf" + CodeIdentifier.MakePascal(arrayMapping.TypeDesc.Name) : type.Name;
1215             }
1216             else if (item is XmlSchemaAll || item is XmlSchemaSequence) {
1217                 if (item.Items.Count != 1 || !(item.Items[0] is XmlSchemaElement)) return null;
1218                 XmlSchemaElement itemElement = (XmlSchemaElement)item.Items[0];
1219                 if (!itemElement.IsMultipleOccurrence) return null;
1220                 if (IsCyclicReferencedType(itemElement, new List<string>(1){identifier}))
1221                 {
1222                     return null;
1223                 }
1224                
1225                 ElementAccessor itemAccessor = ImportElement(itemElement, identifier, typeof(TypeMapping), null, ns, false);
1226                 if (itemAccessor.Any)
1227                     return null;
1228                 arrayMapping.Elements = new ElementAccessor[] { itemAccessor };
1229                 arrayMapping.TypeDesc = ((TypeMapping)itemAccessor.Mapping).TypeDesc.CreateArrayTypeDesc();
1230                 arrayMapping.TypeName = (type.Name == null || type.Name.Length == 0) ? "ArrayOf" + CodeIdentifier.MakePascal(itemAccessor.Mapping.TypeDesc.Name) : type.Name;
1231             }            
1232             else {
1233                 return null;
1234             }
1235
1236             ImportedMappings[type] = arrayMapping;
1237             Scope.AddTypeMapping(arrayMapping);
1238             // for the array-like mappings we need to create a struct mapping for the case when it referenced by the top-level element
1239             arrayMapping.TopLevelMapping = ImportStructType(type, ns, identifier, null, true);
1240             arrayMapping.TopLevelMapping.ReferencedByTopLevelElement = true;
1241             if (type.Name != null && type.Name.Length != 0)
1242                 ImportDerivedTypes(new XmlQualifiedName(identifier, ns));
1243
1244             return arrayMapping;
1245         }
1246         
1247         bool IsCyclicReferencedType(XmlSchemaElement element, List<string> identifiers)
1248         {
1249             if (!element.RefName.IsEmpty)
1250             {
1251                 XmlSchemaElement refElement = FindElement(element.RefName);
1252                 string refElementIdentifier = CodeIdentifier.MakeValid(Accessor.UnescapeName(refElement.Name));
1253                 foreach (string identifier in identifiers)
1254                 {
1255                     if (refElementIdentifier == identifier)
1256                     {
1257                         return true;
1258                     }
1259                 }
1260                 identifiers.Add(refElementIdentifier);
1261
1262                 XmlSchemaType refType = refElement.SchemaType;
1263                 if (refType is XmlSchemaComplexType)
1264                 {                    
1265                     TypeItems items = GetTypeItems(refType);
1266                     if ((items.Particle is XmlSchemaSequence || items.Particle is XmlSchemaAll) && items.Particle.Items.Count == 1 && items.Particle.Items[0] is XmlSchemaElement)
1267                     {
1268                         XmlSchemaElement innerRefElement = (XmlSchemaElement)items.Particle.Items[0];
1269                         if (innerRefElement.IsMultipleOccurrence)
1270                         {
1271                             return IsCyclicReferencedType(innerRefElement, identifiers);
1272                         }
1273                     }
1274                 }
1275             }
1276             return false;
1277         }
1278         
1279         SpecialMapping ImportAnyMapping(XmlSchemaType type, string identifier, string ns, bool repeats) {
1280             if (type == null) return null;
1281             if (!type.DerivedFrom.IsEmpty) return null;
1282
1283             bool mixed = IsMixed(type);
1284             TypeItems items = GetTypeItems(type);
1285             if (items.Particle == null) return null;
1286             if (!(items.Particle is XmlSchemaAll || items.Particle is XmlSchemaSequence)) return null;
1287             if (items.Attributes != null && items.Attributes.Count > 0) return null;
1288             XmlSchemaGroupBase group = (XmlSchemaGroupBase) items.Particle;
1289
1290             if (group.Items.Count != 1 || !(group.Items[0] is XmlSchemaAny)) return null;
1291             XmlSchemaAny any = (XmlSchemaAny)group.Items[0];
1292
1293             SpecialMapping mapping = new SpecialMapping();
1294             // check for special named any case
1295             if (items.AnyAttribute != null && any.IsMultipleOccurrence && mixed) {
1296                 mapping.NamedAny = true;
1297                 mapping.TypeDesc = Scope.GetTypeDesc(typeof(XmlElement));
1298             }
1299             else if (items.AnyAttribute != null || any.IsMultipleOccurrence) {
1300                 // these only work for named any case -- otherwise import as struct
1301                 return null;
1302             }
1303             else {
1304                 mapping.TypeDesc = Scope.GetTypeDesc(mixed ? typeof(XmlNode) : typeof(XmlElement));
1305             }
1306
1307             TypeFlags flags = TypeFlags.CanBeElementValue;
1308             if (items.AnyAttribute != null || mixed)
1309                 flags |= TypeFlags.CanBeTextValue;
1310
1311             // let the extensions to run
1312             RunSchemaExtensions(mapping, XmlQualifiedName.Empty, null, any, flags);
1313             
1314             mapping.TypeName = mapping.TypeDesc.Name;
1315             if (repeats)
1316                 mapping.TypeDesc = mapping.TypeDesc.CreateArrayTypeDesc();
1317
1318             return mapping;
1319         }
1320
1321         void ImportElementMember(XmlSchemaElement element, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, INameScope elementsScope, string ns, bool repeats, ref bool needExplicitOrder, bool allowDuplicates, bool allowUnboundedElements) {
1322             repeats = repeats | element.IsMultipleOccurrence;
1323             XmlSchemaElement headElement = GetTopLevelElement(element);
1324             if (headElement != null && ImportSubstitutionGroupMember(headElement, identifier, members, membersScope, ns, repeats, ref needExplicitOrder, allowDuplicates)) {
1325                 return;
1326             }
1327             ElementAccessor accessor;
1328             if ((accessor = ImportArray(element, identifier, ns, repeats)) == null) {
1329                 accessor = ImportElement(element, identifier, typeof(TypeMapping), null, ns, false);
1330             }
1331
1332             MemberMapping member = new MemberMapping();
1333             string name = CodeIdentifier.MakeValid(Accessor.UnescapeName(accessor.Name));
1334             member.Name = membersScope.AddUnique(name, member);
1335
1336             if (member.Name.EndsWith("Specified", StringComparison.Ordinal)) {
1337                 name = member.Name;
1338                 member.Name = membersScope.AddUnique(member.Name, member);
1339                 membersScope.Remove(name);
1340             }
1341             members.Add(member.Name, member);
1342             // we do not support lists for elements
1343             if (accessor.Mapping.IsList) {
1344                 accessor.Mapping = GetDefaultMapping(TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue);
1345                 member.TypeDesc = accessor.Mapping.TypeDesc;
1346             }
1347             else {
1348                 member.TypeDesc = accessor.Mapping.TypeDesc;
1349             }
1350
1351             AddScopeElement(elementsScope, accessor, ref needExplicitOrder, allowDuplicates);
1352             member.Elements = new ElementAccessor[] { accessor };
1353
1354             if (element.IsMultipleOccurrence || repeats) {
1355                 if (!allowUnboundedElements && accessor.Mapping is ArrayMapping) {
1356                     accessor.Mapping = ((ArrayMapping)accessor.Mapping).TopLevelMapping;
1357                     accessor.Mapping.ReferencedByTopLevelElement = false;
1358                     accessor.Mapping.ReferencedByElement = true;
1359                 }
1360                 member.TypeDesc = accessor.Mapping.TypeDesc.CreateArrayTypeDesc();
1361             }
1362
1363             if (element.MinOccurs == 0 && member.TypeDesc.IsValueType && !element.HasDefault && !member.TypeDesc.HasIsEmpty) {
1364                 member.CheckSpecified = SpecifiedAccessor.ReadWrite;
1365             }
1366         }
1367
1368         void ImportAttributeMember(XmlSchemaAttribute attribute, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, string ns) {
1369             AttributeAccessor accessor = ImportAttribute(attribute, identifier, ns, attribute);
1370             if (accessor == null) return;
1371             MemberMapping member = new MemberMapping();
1372             member.Elements = new ElementAccessor[0];
1373             member.Attribute = accessor;
1374             member.Name = CodeIdentifier.MakeValid(Accessor.UnescapeName(accessor.Name));
1375             member.Name = membersScope.AddUnique(member.Name, member);
1376             if (member.Name.EndsWith("Specified", StringComparison.Ordinal)) {
1377                 string name = member.Name;
1378                 member.Name = membersScope.AddUnique(member.Name, member);
1379                 membersScope.Remove(name);
1380             }
1381             members.Add(member.Name, member);
1382             member.TypeDesc = accessor.IsList ? accessor.Mapping.TypeDesc.CreateArrayTypeDesc() : accessor.Mapping.TypeDesc;
1383
1384             if ((attribute.Use == XmlSchemaUse.Optional || attribute.Use == XmlSchemaUse.None) && member.TypeDesc.IsValueType && !attribute.HasDefault && !member.TypeDesc.HasIsEmpty) {
1385                 member.CheckSpecified = SpecifiedAccessor.ReadWrite;
1386             }
1387         }
1388
1389         void ImportAnyAttributeMember(XmlSchemaAnyAttribute any, CodeIdentifiers members, CodeIdentifiers membersScope) {
1390             SpecialMapping mapping = new SpecialMapping();
1391             mapping.TypeDesc = Scope.GetTypeDesc(typeof(XmlAttribute));
1392             mapping.TypeName = mapping.TypeDesc.Name;
1393
1394             AttributeAccessor accessor = new AttributeAccessor();
1395             accessor.Any = true;
1396             accessor.Mapping = mapping;
1397
1398             MemberMapping member = new MemberMapping();
1399             member.Elements = new ElementAccessor[0];
1400             member.Attribute = accessor;
1401             member.Name = membersScope.MakeRightCase("AnyAttr");
1402             member.Name = membersScope.AddUnique(member.Name, member);
1403             members.Add(member.Name, member);
1404             member.TypeDesc = ((TypeMapping)accessor.Mapping).TypeDesc;
1405             member.TypeDesc = member.TypeDesc.CreateArrayTypeDesc();
1406         }
1407
1408         bool KeepXmlnsDeclarations(XmlSchemaType type, out string xmlnsMemberName) {
1409             xmlnsMemberName = null;
1410             if (type.Annotation == null)
1411                 return false;
1412             if (type.Annotation.Items == null || type.Annotation.Items.Count == 0)
1413                 return false;
1414
1415             foreach(XmlSchemaObject o in type.Annotation.Items) {
1416                 if (o is XmlSchemaAppInfo) {
1417                     XmlNode[] nodes = ((XmlSchemaAppInfo)o).Markup;
1418                     if (nodes != null && nodes.Length > 0) {
1419                         foreach(XmlNode node in nodes) {
1420                             if (node is XmlElement) {
1421                                 XmlElement e = (XmlElement)node;
1422                                 if (e.Name == "keepNamespaceDeclarations") {
1423                                     if (e.LastNode is XmlText) {
1424                                         xmlnsMemberName = (((XmlText)e.LastNode).Value).Trim(null);
1425                                     }
1426                                     return true;
1427                                 }
1428                             }
1429                         }
1430                     }
1431                 }
1432             }
1433             return false; 
1434         }
1435
1436         void ImportXmlnsDeclarationsMember(XmlSchemaType type, CodeIdentifiers members, CodeIdentifiers membersScope) {
1437             string xmlnsMemberName;
1438             if (!KeepXmlnsDeclarations(type, out xmlnsMemberName))
1439                 return;
1440             TypeDesc xmlnsTypeDesc = Scope.GetTypeDesc(typeof(XmlSerializerNamespaces));
1441             StructMapping xmlnsMapping = new StructMapping();
1442
1443             xmlnsMapping.TypeDesc = xmlnsTypeDesc;
1444             xmlnsMapping.TypeName = xmlnsMapping.TypeDesc.Name;
1445             xmlnsMapping.Members = new MemberMapping[0];
1446             xmlnsMapping.IncludeInSchema = false;
1447             xmlnsMapping.ReferencedByTopLevelElement = true;
1448          
1449             ElementAccessor xmlns = new ElementAccessor();
1450             xmlns.Mapping = xmlnsMapping;
1451             
1452             MemberMapping member = new MemberMapping();
1453             member.Elements = new ElementAccessor[] {xmlns};
1454             member.Name = CodeIdentifier.MakeValid(xmlnsMemberName == null ? "Namespaces" : xmlnsMemberName);
1455             member.Name = membersScope.AddUnique(member.Name, member);
1456             members.Add(member.Name, member);
1457             member.TypeDesc = xmlnsTypeDesc;
1458             member.Xmlns = new XmlnsAccessor();
1459             member.Ignore = true;
1460         }
1461
1462         void ImportAttributeGroupMembers(XmlSchemaAttributeGroup group, string identifier, CodeIdentifiers members, CodeIdentifiers membersScope, string ns) {
1463             for (int i = 0; i < group.Attributes.Count; i++) {
1464                 object item = group.Attributes[i];
1465                 if (item is XmlSchemaAttributeGroup)
1466                     ImportAttributeGroupMembers((XmlSchemaAttributeGroup)item, identifier, members, membersScope, ns);
1467                 else if (item is XmlSchemaAttribute)
1468                     ImportAttributeMember((XmlSchemaAttribute)item, identifier, members, membersScope, ns);
1469             }
1470             if (group.AnyAttribute != null)
1471                 ImportAnyAttributeMember(group.AnyAttribute, members, membersScope);
1472         }
1473
1474         AttributeAccessor ImportSpecialAttribute(XmlQualifiedName name, string identifier) {
1475             PrimitiveMapping mapping = new PrimitiveMapping();
1476             mapping.TypeDesc = Scope.GetTypeDesc(typeof(string));
1477             mapping.TypeName = mapping.TypeDesc.DataType.Name;
1478             AttributeAccessor accessor = new AttributeAccessor();
1479             accessor.Name = name.Name;
1480             accessor.Namespace = XmlReservedNs.NsXml;
1481             accessor.CheckSpecial();
1482             accessor.Mapping = mapping;
1483             return accessor;
1484         }
1485
1486         AttributeAccessor ImportAttribute(XmlSchemaAttribute attribute, string identifier, string ns, XmlSchemaAttribute defaultValueProvider) {
1487             if (attribute.Use == XmlSchemaUse.Prohibited) return null;
1488             if (!attribute.RefName.IsEmpty) {
1489                 if (attribute.RefName.Namespace == XmlReservedNs.NsXml)
1490                     return ImportSpecialAttribute(attribute.RefName, identifier);
1491                 else
1492                     return ImportAttribute(FindAttribute(attribute.RefName), identifier, attribute.RefName.Namespace, defaultValueProvider);
1493             }
1494             TypeMapping mapping;
1495             if (attribute.Name.Length == 0) throw new InvalidOperationException(Res.GetString(Res.XmlAttributeHasNoName));
1496             if (identifier.Length == 0)
1497                 identifier = CodeIdentifier.MakeValid(attribute.Name);
1498             else
1499                 identifier += CodeIdentifier.MakePascal(attribute.Name);
1500             if (!attribute.SchemaTypeName.IsEmpty)
1501                 mapping = (TypeMapping)ImportType(attribute.SchemaTypeName, typeof(TypeMapping), null, TypeFlags.CanBeAttributeValue, false);
1502             else if (attribute.SchemaType != null)
1503                 mapping = ImportDataType((XmlSchemaSimpleType)attribute.SchemaType, ns, identifier, null, TypeFlags.CanBeAttributeValue, false);
1504             else {
1505                 mapping = GetDefaultMapping(TypeFlags.CanBeAttributeValue);
1506             }
1507
1508             // let the extensions to run
1509             if (mapping != null && !mapping.TypeDesc.IsMappedType) {
1510                 RunSchemaExtensions(mapping, attribute.SchemaTypeName, attribute.SchemaType, attribute, TypeFlags.CanBeElementValue | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeTextValue);
1511             }
1512             AttributeAccessor accessor = new AttributeAccessor();
1513             accessor.Name = attribute.Name;
1514             accessor.Namespace = ns;
1515             accessor.Form = AttributeForm(ns, attribute);
1516             accessor.CheckSpecial();
1517             accessor.Mapping = mapping;
1518             accessor.IsList = mapping.IsList;
1519             accessor.IsOptional = attribute.Use != XmlSchemaUse.Required;
1520
1521             if (defaultValueProvider.DefaultValue != null) {
1522                 accessor.Default = defaultValueProvider.DefaultValue;
1523             }
1524             else if (defaultValueProvider.FixedValue != null) {
1525                 accessor.Default = defaultValueProvider.FixedValue;
1526                 accessor.IsFixed = true;
1527             }
1528             else if (attribute != defaultValueProvider) {
1529                 if (attribute.DefaultValue != null) {
1530                     accessor.Default = attribute.DefaultValue;
1531                 }
1532                 else if (attribute.FixedValue != null) {
1533                     accessor.Default = attribute.FixedValue;
1534                     accessor.IsFixed = true;
1535                 }
1536             }
1537             return accessor;
1538         }
1539
1540         TypeMapping ImportDataType(XmlSchemaSimpleType dataType, string typeNs, string identifier, Type baseType, TypeFlags flags, bool isList) {
1541             if (baseType != null)
1542                 return ImportStructDataType(dataType, typeNs, identifier, baseType);
1543
1544             TypeMapping mapping = ImportNonXsdPrimitiveDataType(dataType, typeNs, flags);
1545             if (mapping != null)
1546                 return mapping;
1547
1548             if (dataType.Content is XmlSchemaSimpleTypeRestriction) {
1549                 XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)dataType.Content;
1550                 foreach (object o in restriction.Facets) {
1551                     if (o is XmlSchemaEnumerationFacet) {
1552                         return ImportEnumeratedDataType(dataType, typeNs, identifier, flags, isList);
1553                     }
1554                 }
1555                 if (restriction.BaseType != null) {
1556                     return ImportDataType(restriction.BaseType, typeNs, identifier, null, flags, false);
1557                 }
1558                 else {
1559                     AddReference(restriction.BaseTypeName, TypesInUse, Res.XmlCircularTypeReference);
1560                     mapping = ImportDataType(FindDataType(restriction.BaseTypeName, flags), restriction.BaseTypeName.Namespace, identifier, null, flags, false);
1561                     if (restriction.BaseTypeName.Namespace != XmlSchema.Namespace)
1562                         RemoveReference(restriction.BaseTypeName, TypesInUse);
1563                     return mapping;
1564                 }
1565             }
1566             else if (dataType.Content is XmlSchemaSimpleTypeList || dataType.Content is XmlSchemaSimpleTypeUnion) {
1567                 if (dataType.Content is XmlSchemaSimpleTypeList) {
1568                     // check if we have enumeration list
1569                     XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)dataType.Content;
1570                     if (list.ItemType != null) {
1571                         mapping = ImportDataType(list.ItemType, typeNs, identifier, null, flags, true);
1572                         if (mapping != null) {
1573                             mapping.TypeName = dataType.Name;
1574                             return mapping;
1575                         }
1576                     }
1577                     else if (list.ItemTypeName != null && !list.ItemTypeName.IsEmpty) {
1578                         mapping = ImportType(list.ItemTypeName, typeof(TypeMapping), null, TypeFlags.CanBeAttributeValue, true);
1579                         if (mapping != null && mapping is PrimitiveMapping) {
1580                             ((PrimitiveMapping)mapping).IsList = true;
1581                             return mapping;
1582                         }
1583                     }
1584                 }
1585                 return GetDefaultMapping(flags);
1586             }
1587             return ImportPrimitiveDataType(dataType, flags);
1588         }
1589
1590         TypeMapping ImportEnumeratedDataType(XmlSchemaSimpleType dataType, string typeNs, string identifier, TypeFlags flags, bool isList) {
1591             TypeMapping mapping = (TypeMapping)ImportedMappings[dataType];
1592             if (mapping != null)
1593                 return mapping;
1594
1595             XmlSchemaType sourceType = dataType;
1596             while (!sourceType.DerivedFrom.IsEmpty) {
1597                 sourceType = FindType(sourceType.DerivedFrom, TypeFlags.CanBeElementValue | TypeFlags.CanBeAttributeValue);
1598             }
1599             if (sourceType is XmlSchemaComplexType) return null;
1600             TypeDesc sourceTypeDesc = Scope.GetTypeDesc((XmlSchemaSimpleType)sourceType);
1601             if (sourceTypeDesc != null && sourceTypeDesc.FullName != typeof(string).FullName)
1602                 return ImportPrimitiveDataType(dataType, flags);
1603             identifier = Accessor.UnescapeName(identifier);
1604             string typeName = GenerateUniqueTypeName(identifier);
1605             EnumMapping enumMapping = new EnumMapping();
1606             enumMapping.IsReference = Schemas.IsReference(dataType);
1607             enumMapping.TypeDesc = new TypeDesc(typeName, typeName, TypeKind.Enum, null, 0);
1608             if (dataType.Name != null && dataType.Name.Length > 0)
1609                 enumMapping.TypeName = identifier;
1610             enumMapping.Namespace = typeNs;
1611             enumMapping.IsFlags = isList;
1612
1613             CodeIdentifiers constants = new CodeIdentifiers();
1614             XmlSchemaSimpleTypeContent content = dataType.Content;
1615
1616             if (content is XmlSchemaSimpleTypeRestriction) {
1617                 XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)content;
1618                 for (int i = 0; i < restriction.Facets.Count; i++) {
1619                     object facet = restriction.Facets[i];
1620                     if (!(facet is XmlSchemaEnumerationFacet)) continue;
1621                     XmlSchemaEnumerationFacet enumeration = (XmlSchemaEnumerationFacet)facet;
1622                     // validate the enumeration value
1623                     if (sourceTypeDesc != null && sourceTypeDesc.HasCustomFormatter) {
1624                         XmlCustomFormatter.ToDefaultValue(enumeration.Value, sourceTypeDesc.FormatterName);
1625                     }
1626                     ConstantMapping constant = new ConstantMapping();
1627                     string constantName = CodeIdentifier.MakeValid(enumeration.Value);
1628                     constant.Name = constants.AddUnique(constantName, constant);
1629                     constant.XmlName = enumeration.Value;
1630                     constant.Value = i;
1631                 }
1632             }
1633             enumMapping.Constants = (ConstantMapping[])constants.ToArray(typeof(ConstantMapping));
1634             if (isList && enumMapping.Constants.Length > 63) {
1635                 // if we have 64+ flag constants we cannot map the type to long enum, we will use string mapping instead.
1636                 mapping = GetDefaultMapping(TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.CanBeAttributeValue);
1637                 ImportedMappings.Add(dataType, mapping);
1638                 return mapping;
1639             }
1640             ImportedMappings.Add(dataType, enumMapping);
1641             Scope.AddTypeMapping(enumMapping);
1642             return enumMapping;
1643         }
1644
1645         internal class ElementComparer : IComparer {
1646             public int Compare(object o1, object o2) {
1647                 ElementAccessor e1 = (ElementAccessor)o1;
1648                 ElementAccessor e2 = (ElementAccessor)o2;
1649                 return String.Compare(e1.ToString(string.Empty), e2.ToString(string.Empty), StringComparison.Ordinal);
1650             }
1651         }
1652
1653         EnumMapping ImportEnumeratedChoice(ElementAccessor[] choice, string typeNs, string typeName) {
1654             typeName = GenerateUniqueTypeName(Accessor.UnescapeName(typeName), typeNs);
1655             EnumMapping enumMapping = new EnumMapping();
1656             enumMapping.TypeDesc = new TypeDesc(typeName, typeName, TypeKind.Enum, null, 0);
1657             enumMapping.TypeName = typeName;
1658             enumMapping.Namespace = typeNs;
1659             enumMapping.IsFlags = false;
1660             enumMapping.IncludeInSchema = false;
1661
1662             if (GenerateOrder) {
1663                 Array.Sort(choice, new ElementComparer());
1664             }
1665             CodeIdentifiers constants = new CodeIdentifiers();
1666             for (int i = 0; i < choice.Length; i++) {
1667                 ElementAccessor element = choice[i];
1668                 ConstantMapping constant = new ConstantMapping();
1669                 string constantName = CodeIdentifier.MakeValid(element.Name);
1670                 constant.Name = constants.AddUnique(constantName, constant);
1671                 constant.XmlName = element.ToString(typeNs);
1672                 constant.Value = i;
1673             }
1674             enumMapping.Constants = (ConstantMapping[])constants.ToArray(typeof(ConstantMapping));
1675             Scope.AddTypeMapping(enumMapping);
1676             return enumMapping;
1677         }
1678
1679         PrimitiveMapping ImportPrimitiveDataType(XmlSchemaSimpleType dataType, TypeFlags flags) {
1680             TypeDesc sourceTypeDesc = GetDataTypeSource(dataType, flags);
1681             PrimitiveMapping mapping = new PrimitiveMapping();
1682             mapping.TypeDesc = sourceTypeDesc;
1683             mapping.TypeName = sourceTypeDesc.DataType.Name;
1684             mapping.Namespace = mapping.TypeDesc.IsXsdType ? XmlSchema.Namespace : UrtTypes.Namespace;
1685             return mapping;
1686         }
1687
1688         PrimitiveMapping ImportNonXsdPrimitiveDataType(XmlSchemaSimpleType dataType, string ns, TypeFlags flags) {
1689             PrimitiveMapping mapping = null;
1690             TypeDesc typeDesc = null;
1691             if (dataType.Name != null && dataType.Name.Length != 0) {
1692                 typeDesc = Scope.GetTypeDesc(dataType.Name, ns, flags);
1693                 if (typeDesc != null) {
1694                     mapping = new PrimitiveMapping();
1695                     mapping.TypeDesc = typeDesc;
1696                     mapping.TypeName = typeDesc.DataType.Name;
1697                     mapping.Namespace = mapping.TypeDesc.IsXsdType ? XmlSchema.Namespace : ns;
1698                 }
1699             }
1700             return mapping;
1701         }
1702
1703         XmlSchemaGroup FindGroup(XmlQualifiedName name) {
1704             XmlSchemaGroup group = (XmlSchemaGroup)Schemas.Find(name, typeof(XmlSchemaGroup));
1705             if (group == null)
1706                 throw new InvalidOperationException(Res.GetString(Res.XmlMissingGroup, name.Name));
1707
1708             return group;
1709         }
1710
1711         XmlSchemaAttributeGroup FindAttributeGroup(XmlQualifiedName name) {
1712             XmlSchemaAttributeGroup group = (XmlSchemaAttributeGroup)Schemas.Find(name, typeof(XmlSchemaAttributeGroup));
1713             if (group == null)
1714                 throw new InvalidOperationException(Res.GetString(Res.XmlMissingAttributeGroup, name.Name));
1715
1716             return group;
1717         }
1718
1719         internal static XmlQualifiedName BaseTypeName(XmlSchemaSimpleType dataType) {
1720             XmlSchemaSimpleTypeContent content = dataType.Content;
1721             if (content is XmlSchemaSimpleTypeRestriction) {
1722                 return ((XmlSchemaSimpleTypeRestriction)content).BaseTypeName;
1723             }
1724             else if (content is XmlSchemaSimpleTypeList) {
1725                 XmlSchemaSimpleTypeList list  = (XmlSchemaSimpleTypeList)content;
1726                 if (list.ItemTypeName != null && !list.ItemTypeName.IsEmpty)
1727                     return list.ItemTypeName;
1728                 if (list.ItemType != null) {
1729                     return BaseTypeName(list.ItemType);
1730                 }
1731             }
1732             return new XmlQualifiedName("string", XmlSchema.Namespace);
1733         }
1734
1735         TypeDesc GetDataTypeSource(XmlSchemaSimpleType dataType, TypeFlags flags) {
1736             TypeDesc typeDesc = null;
1737             if (dataType.Name != null && dataType.Name.Length != 0) {
1738                 typeDesc = Scope.GetTypeDesc(dataType);
1739                 if (typeDesc != null) return typeDesc;
1740             }
1741             XmlQualifiedName qname = BaseTypeName(dataType);
1742             AddReference(qname, TypesInUse, Res.XmlCircularTypeReference);
1743             typeDesc = GetDataTypeSource(FindDataType(qname, flags), flags);
1744             if (qname.Namespace != XmlSchema.Namespace)
1745                 RemoveReference(qname, TypesInUse);
1746
1747             return typeDesc;
1748         }
1749
1750         XmlSchemaSimpleType FindDataType(XmlQualifiedName name, TypeFlags flags) {
1751             if (name == null || name.IsEmpty) {
1752                 return (XmlSchemaSimpleType)Scope.GetTypeDesc(typeof(string)).DataType;
1753             }
1754             TypeDesc typeDesc = Scope.GetTypeDesc(name.Name, name.Namespace, flags);
1755             if (typeDesc != null && typeDesc.DataType is XmlSchemaSimpleType)
1756                 return (XmlSchemaSimpleType)typeDesc.DataType;
1757             XmlSchemaSimpleType dataType = (XmlSchemaSimpleType)Schemas.Find(name, typeof(XmlSchemaSimpleType));
1758             if (dataType != null) {
1759                 return dataType;
1760             }
1761             if (name.Namespace == XmlSchema.Namespace)
1762                 return (XmlSchemaSimpleType)Scope.GetTypeDesc("string", XmlSchema.Namespace, flags).DataType;
1763             else {
1764                 if (name.Name == Soap.Array && name.Namespace == Soap.Encoding) {
1765                     throw new InvalidOperationException(Res.GetString(Res.XmlInvalidEncoding, name.ToString()));
1766                 }
1767                 else {
1768                     throw new InvalidOperationException(Res.GetString(Res.XmlMissingDataType, name.ToString()));
1769                 }
1770             }
1771         }
1772
1773         XmlSchemaType FindType(XmlQualifiedName name, TypeFlags flags) {
1774             if (name == null || name.IsEmpty) {
1775                 return Scope.GetTypeDesc(typeof(string)).DataType;
1776             }
1777             object type = Schemas.Find(name, typeof(XmlSchemaComplexType));
1778             if (type != null) {
1779                 return (XmlSchemaComplexType)type;
1780             }
1781             return FindDataType(name, flags);
1782         }
1783
1784         XmlSchemaElement FindElement(XmlQualifiedName name) {
1785             XmlSchemaElement element = (XmlSchemaElement)Schemas.Find(name, typeof(XmlSchemaElement));
1786             if (element == null) 
1787                 throw new InvalidOperationException(Res.GetString(Res.XmlMissingElement, name.ToString()));
1788             return element;
1789         }
1790
1791         XmlSchemaAttribute FindAttribute(XmlQualifiedName name) {
1792             XmlSchemaAttribute attribute = (XmlSchemaAttribute)Schemas.Find(name, typeof(XmlSchemaAttribute));
1793             if (attribute == null) 
1794                 throw new InvalidOperationException(Res.GetString(Res.XmlMissingAttribute, name.Name));
1795
1796             return attribute;
1797         }
1798
1799         XmlSchemaForm ElementForm(string ns, XmlSchemaElement element) {
1800             if (element.Form == XmlSchemaForm.None) {
1801                 XmlSchemaObject parent = element;
1802                 while (parent.Parent != null) {
1803                     parent = parent.Parent;
1804                 }
1805                 XmlSchema schema = parent as XmlSchema;
1806
1807                 if (schema != null) {
1808                     if (ns == null || ns.Length == 0) {
1809                         return schema.ElementFormDefault == XmlSchemaForm.None ? XmlSchemaForm.Unqualified : schema.ElementFormDefault;
1810                     }
1811                     else {
1812                         XmlSchemas.Preprocess(schema);
1813                         return element.QualifiedName.Namespace == null || element.QualifiedName.Namespace.Length == 0 ? XmlSchemaForm.Unqualified : XmlSchemaForm.Qualified;
1814                     }
1815                 }
1816                 return XmlSchemaForm.Qualified;
1817             }
1818             return element.Form;
1819         }
1820
1821         internal string FindExtendedAnyElement(XmlSchemaAny any, bool mixed, CodeCompileUnit compileUnit, CodeNamespace mainNamespace, out SchemaImporterExtension extension) {
1822             extension = null;
1823             foreach (SchemaImporterExtension ex in Extensions) {
1824                 string typeName = ex.ImportAnyElement(any, mixed, Schemas, this, compileUnit, mainNamespace, Options, CodeProvider);
1825                 if (typeName != null && typeName.Length > 0) {
1826                     extension = ex;
1827                     return typeName; 
1828                 }
1829             }
1830             return null;
1831         }
1832
1833         internal string FindExtendedType(string name, string ns, XmlSchemaObject context, CodeCompileUnit compileUnit, CodeNamespace mainNamespace, out SchemaImporterExtension extension ) {
1834             extension = null;
1835             foreach (SchemaImporterExtension ex in Extensions) {
1836                 string typeName = ex.ImportSchemaType(name, ns, context, Schemas, this, compileUnit, mainNamespace, Options, CodeProvider);
1837                 if (typeName != null && typeName.Length > 0) {
1838                     extension = ex;
1839                     return typeName; 
1840                 }
1841             }
1842             return null;
1843         }
1844
1845         internal string FindExtendedType(XmlSchemaType type, XmlSchemaObject context, CodeCompileUnit compileUnit, CodeNamespace mainNamespace, out SchemaImporterExtension extension) {
1846             extension = null;
1847             foreach (SchemaImporterExtension ex in Extensions) {
1848                 string typeName = ex.ImportSchemaType(type, context, Schemas, this, compileUnit, mainNamespace, Options, CodeProvider);
1849                 if (typeName != null && typeName.Length > 0) {
1850                     extension = ex;
1851                     return typeName; 
1852                 }
1853             }
1854             return null;
1855         }
1856
1857         XmlSchemaForm AttributeForm(string ns, XmlSchemaAttribute attribute) {
1858             if (attribute.Form == XmlSchemaForm.None) {
1859                 XmlSchemaObject parent = attribute;
1860                 while (parent.Parent != null) {
1861                     parent = parent.Parent;
1862                 }
1863                 XmlSchema schema = parent as XmlSchema;
1864                 if (schema != null) {
1865                     if (ns == null || ns.Length == 0) {
1866                         return schema.AttributeFormDefault == XmlSchemaForm.None ? XmlSchemaForm.Unqualified : schema.AttributeFormDefault;
1867                     }
1868                     else {
1869                         XmlSchemas.Preprocess(schema);
1870                         return attribute.QualifiedName.Namespace == null || attribute.QualifiedName.Namespace.Length == 0 ? XmlSchemaForm.Unqualified : XmlSchemaForm.Qualified;
1871                     }
1872                 }
1873                 return XmlSchemaForm.Unqualified;
1874             }
1875             return attribute.Form;
1876         }
1877     }
1878 }