The Labs \ Source Viewer \ SSCLI \ System.Xml.Serialization \ SoapSchemaImporter

  1. //------------------------------------------------------------------------------
  2. // <copyright file="SoapSchemaImporter.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. // <owner current="true" primary="true">ElenaK</owner>
  15. //------------------------------------------------------------------------------
  16. namespace System.Xml.Serialization
  17. {
  18.    
  19.     using System;
  20.     using System.Xml.Schema;
  21.     using System.Xml;
  22.     using System.Collections;
  23.     using System.ComponentModel;
  24.     using System.Reflection;
  25.     using System.Diagnostics;
  26.     using System.CodeDom.Compiler;
  27.     using System.Security.Permissions;
  28.    
  29.     /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter"]/*' />
  30.     ///<internalonly/>
  31.     /// <devdoc>
  32.     /// <para>[To be supplied.]</para>
  33.     /// </devdoc>
  34.     public class SoapSchemaImporter : SchemaImporter
  35.     {
  36.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.SoapSchemaImporter"]/*' />
  37.         /// <devdoc>
  38.         /// <para>[To be supplied.]</para>
  39.         /// </devdoc>
  40.         public SoapSchemaImporter(XmlSchemas schemas) : base(schemas, CodeGenerationOptions.GenerateProperties, null, new ImportContext())
  41.         {
  42.         }
  43.        
  44.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.SoapSchemaImporter1"]/*' />
  45.         /// <devdoc>
  46.         /// <para>[To be supplied.]</para>
  47.         /// </devdoc>
  48.         public SoapSchemaImporter(XmlSchemas schemas, CodeIdentifiers typeIdentifiers) : base(schemas, CodeGenerationOptions.GenerateProperties, null, new ImportContext(typeIdentifiers, false))
  49.         {
  50.         }
  51.        
  52.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.SoapSchemaImporter2"]/*' />
  53.         /// <devdoc>
  54.         /// <para>[To be supplied.]</para>
  55.         /// </devdoc>
  56.         public SoapSchemaImporter(XmlSchemas schemas, CodeIdentifiers typeIdentifiers, CodeGenerationOptions options) : base(schemas, options, null, new ImportContext(typeIdentifiers, false))
  57.         {
  58.         }
  59.        
  60.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.SoapSchemaImporter3"]/*' />
  61.         /// <devdoc>
  62.         /// <para>[To be supplied.]</para>
  63.         /// </devdoc>
  64.         public SoapSchemaImporter(XmlSchemas schemas, CodeGenerationOptions options, ImportContext context) : base(schemas, options, null, context)
  65.         {
  66.         }
  67.        
  68.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.SoapSchemaImporter4"]/*' />
  69.         /// <devdoc>
  70.         /// <para>[To be supplied.]</para>
  71.         /// </devdoc>
  72.         public SoapSchemaImporter(XmlSchemas schemas, CodeGenerationOptions options, CodeDomProvider codeProvider, ImportContext context) : base(schemas, options, codeProvider, context)
  73.         {
  74.         }
  75.        
  76.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.ImportDerivedTypeMapping"]/*' />
  77.         /// <devdoc>
  78.         /// <para>[To be supplied.]</para>
  79.         /// </devdoc>
  80.         public XmlTypeMapping ImportDerivedTypeMapping(XmlQualifiedName name, Type baseType, bool baseTypeCanBeIndirect)
  81.         {
  82.             TypeMapping mapping = ImportType(name, false);
  83.             if (mapping is StructMapping) {
  84.                 MakeDerived((StructMapping)mapping, baseType, baseTypeCanBeIndirect);
  85.             }
  86.             else if (baseType != null)
  87.                 throw new InvalidOperationException(Res.GetString(Res.XmlPrimitiveBaseType, name.Name, name.Namespace, baseType.FullName));
  88.             ElementAccessor accessor = new ElementAccessor();
  89.             accessor.IsSoap = true;
  90.             accessor.Name = name.Name;
  91.             accessor.Namespace = name.Namespace;
  92.             accessor.Mapping = mapping;
  93.             accessor.IsNullable = true;
  94.             accessor.Form = XmlSchemaForm.Qualified;
  95.            
  96.             return new XmlTypeMapping(Scope, accessor);
  97.         }
  98.        
  99.        
  100.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.ImportMembersMapping"]/*' />
  101.         /// <devdoc>
  102.         /// <para>[To be supplied.]</para>
  103.         /// </devdoc>
  104.         public XmlMembersMapping ImportMembersMapping(string name, string ns, SoapSchemaMember member)
  105.         {
  106.             TypeMapping typeMapping = ImportType(member.MemberType, true);
  107.             if (!(typeMapping is StructMapping))
  108.                 return ImportMembersMapping(name, ns, new SoapSchemaMember[] {member});
  109.            
  110.             MembersMapping mapping = new MembersMapping();
  111.             mapping.TypeDesc = Scope.GetTypeDesc(typeof(object[]));
  112.             mapping.Members = ((StructMapping)typeMapping).Members;
  113.             mapping.HasWrapperElement = true;
  114.            
  115.             ElementAccessor accessor = new ElementAccessor();
  116.             accessor.IsSoap = true;
  117.             accessor.Name = name;
  118.             accessor.Namespace = typeMapping.Namespace != null ? typeMapping.Namespace : ns;
  119.             accessor.Mapping = mapping;
  120.             accessor.IsNullable = false;
  121.             accessor.Form = XmlSchemaForm.Qualified;
  122.            
  123.             return new XmlMembersMapping(Scope, accessor, XmlMappingAccess.Read | XmlMappingAccess.Write);
  124.         }
  125.        
  126.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.ImportMembersMapping1"]/*' />
  127.         /// <devdoc>
  128.         /// <para>[To be supplied.]</para>
  129.         /// </devdoc>
  130.         public XmlMembersMapping ImportMembersMapping(string name, string ns, SoapSchemaMember[] members)
  131.         {
  132.             return ImportMembersMapping(name, ns, members, true);
  133.         }
  134.        
  135.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.ImportMembersMapping2"]/*' />
  136.         /// <devdoc>
  137.         /// <para>[To be supplied.]</para>
  138.         /// </devdoc>
  139.         public XmlMembersMapping ImportMembersMapping(string name, string ns, SoapSchemaMember[] members, bool hasWrapperElement)
  140.         {
  141.             return ImportMembersMapping(name, ns, members, hasWrapperElement, null, false);
  142.         }
  143.        
  144.         /// <include file='doc\SoapSchemaImporter.uex' path='docs/doc[@for="SoapSchemaImporter.ImportMembersMapping3"]/*' />
  145.         /// <devdoc>
  146.         /// <para>[To be supplied.]</para>
  147.         /// </devdoc>
  148.         public XmlMembersMapping ImportMembersMapping(string name, string ns, SoapSchemaMember[] members, bool hasWrapperElement, Type baseType, bool baseTypeCanBeIndirect)
  149.         {
  150.             XmlSchemaComplexType type = new XmlSchemaComplexType();
  151.             XmlSchemaSequence seq = new XmlSchemaSequence();
  152.             type.Particle = seq;
  153.             foreach (SoapSchemaMember member in members) {
  154.                 XmlSchemaElement element = new XmlSchemaElement();
  155.                 element.Name = member.MemberName;
  156.                 element.SchemaTypeName = member.MemberType;
  157.                 seq.Items.Add(element);
  158.             }
  159.            
  160.             CodeIdentifiers identifiers = new CodeIdentifiers();
  161.             identifiers.UseCamelCasing = true;
  162.             MembersMapping mapping = new MembersMapping();
  163.             mapping.TypeDesc = Scope.GetTypeDesc(typeof(object[]));
  164.             mapping.Members = ImportTypeMembers(type, ns, identifiers);
  165.             mapping.HasWrapperElement = hasWrapperElement;
  166.            
  167.             if (baseType != null) {
  168.                 for (int i = 0; i < mapping.Members.Length; i++) {
  169.                     MemberMapping member = mapping.Members[i];
  170.                     if (member.Accessor.Mapping is StructMapping)
  171.                         MakeDerived((StructMapping)member.Accessor.Mapping, baseType, baseTypeCanBeIndirect);
  172.                 }
  173.             }
  174.             ElementAccessor accessor = new ElementAccessor();
  175.             accessor.IsSoap = true;
  176.             accessor.Name = name;
  177.             accessor.Namespace = ns;
  178.             accessor.Mapping = mapping;
  179.             accessor.IsNullable = false;
  180.             accessor.Form = XmlSchemaForm.Qualified;
  181.            
  182.             return new XmlMembersMapping(Scope, accessor, XmlMappingAccess.Read | XmlMappingAccess.Write);
  183.         }
  184.        
  185.         ElementAccessor ImportElement(XmlSchemaElement element, string ns)
  186.         {
  187.             if (!element.RefName.IsEmpty) {
  188.                 throw new InvalidOperationException(Res.GetString(Res.RefSyntaxNotSupportedForElements0, element.RefName.Name, element.RefName.Namespace));
  189.             }
  190.            
  191.             if (element.Name.Length == 0) {
  192.                 XmlQualifiedName parentType = XmlSchemas.GetParentName(element);
  193.                 throw new InvalidOperationException(Res.GetString(Res.XmlElementHasNoName, parentType.Name, parentType.Namespace));
  194.             }
  195.             TypeMapping mapping = ImportElementType(element, ns);
  196.             ElementAccessor accessor = new ElementAccessor();
  197.             accessor.IsSoap = true;
  198.             accessor.Name = element.Name;
  199.             accessor.Namespace = ns;
  200.             accessor.Mapping = mapping;
  201.             accessor.IsNullable = element.IsNillable;
  202.             accessor.Form = XmlSchemaForm.None;
  203.            
  204.             return accessor;
  205.         }
  206.        
  207.         TypeMapping ImportElementType(XmlSchemaElement element, string ns)
  208.         {
  209.             TypeMapping mapping;
  210.             if (!element.SchemaTypeName.IsEmpty)
  211.                 mapping = ImportType(element.SchemaTypeName, false);
  212.             else if (element.SchemaType != null) {
  213.                 XmlQualifiedName parentType = XmlSchemas.GetParentName(element);
  214.                 if (element.SchemaType is XmlSchemaComplexType) {
  215.                     mapping = ImportType((XmlSchemaComplexType)element.SchemaType, ns, false);
  216.                     if (!(mapping is ArrayMapping)) {
  217.                         throw new InvalidOperationException(Res.GetString(Res.XmlInvalidSchemaElementType, parentType.Name, parentType.Namespace, element.Name));
  218.                     }
  219.                 }
  220.                 else {
  221.                     throw new InvalidOperationException(Res.GetString(Res.XmlInvalidSchemaElementType, parentType.Name, parentType.Namespace, element.Name));
  222.                 }
  223.             }
  224.             else if (!element.SubstitutionGroup.IsEmpty) {
  225.                 XmlQualifiedName parentType = XmlSchemas.GetParentName(element);
  226.                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidSubstitutionGroupUse, parentType.Name, parentType.Namespace));
  227.             }
  228.             else {
  229.                 XmlQualifiedName parentType = XmlSchemas.GetParentName(element);
  230.                 throw new InvalidOperationException(Res.GetString(Res.XmlElementMissingType, parentType.Name, parentType.Namespace, element.Name));
  231.             }
  232.            
  233.             mapping.ReferencedByElement = true;
  234.            
  235.             return mapping;
  236.         }
  237.        
  238.         [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
  239.         internal override void ImportDerivedTypes(XmlQualifiedName baseName)
  240.         {
  241.             foreach (XmlSchema schema in Schemas) {
  242.                 if (Schemas.IsReference(schema))
  243.                     continue;
  244.                 if (XmlSchemas.IsDataSet(schema))
  245.                     continue;
  246.                 XmlSchemas.Preprocess(schema);
  247.                 foreach (object item in schema.SchemaTypes.Values) {
  248.                     if (item is XmlSchemaType) {
  249.                         XmlSchemaType type = (XmlSchemaType)item;
  250.                         if (type.DerivedFrom == baseName) {
  251.                             ImportType(type.QualifiedName, false);
  252.                         }
  253.                     }
  254.                 }
  255.             }
  256.         }
  257.        
  258.         TypeMapping ImportType(XmlQualifiedName name, bool excludeFromImport)
  259.         {
  260.             if (name.Name == Soap.UrType && name.Namespace == XmlSchema.Namespace)
  261.                 return ImportRootMapping();
  262.             object type = FindType(name);
  263.             TypeMapping mapping = (TypeMapping)ImportedMappings[type];
  264.             if (mapping == null) {
  265.                 if (type is XmlSchemaComplexType)
  266.                     mapping = ImportType((XmlSchemaComplexType)type, name.Namespace, excludeFromImport);
  267.                 else if (type is XmlSchemaSimpleType)
  268.                     mapping = ImportDataType((XmlSchemaSimpleType)type, name.Namespace, name.Name, false);
  269.                 else
  270.                     throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
  271.             }
  272.             if (excludeFromImport)
  273.                 mapping.IncludeInSchema = false;
  274.             return mapping;
  275.         }
  276.        
  277.         TypeMapping ImportType(XmlSchemaComplexType type, string typeNs, bool excludeFromImport)
  278.         {
  279.             if (type.Redefined != null) {
  280.                 // we do not support redefine in the current version
  281.                 throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedRedefine, type.Name, typeNs));
  282.             }
  283.             TypeMapping mapping = ImportAnyType(type, typeNs);
  284.             if (mapping == null)
  285.                 mapping = ImportArrayMapping(type, typeNs);
  286.             if (mapping == null)
  287.                 mapping = ImportStructType(type, typeNs, excludeFromImport);
  288.             return mapping;
  289.         }
  290.         TypeMapping ImportAnyType(XmlSchemaComplexType type, string typeNs)
  291.         {
  292.             if (type.Particle == null)
  293.                 return null;
  294.             if (!(type.Particle is XmlSchemaAll || type.Particle is XmlSchemaSequence))
  295.                 return null;
  296.             XmlSchemaGroupBase group = (XmlSchemaGroupBase)type.Particle;
  297.            
  298.             if (group.Items.Count != 1 || !(group.Items[0] is XmlSchemaAny))
  299.                 return null;
  300.             return ImportRootMapping();
  301.         }
  302.        
  303.         StructMapping ImportStructType(XmlSchemaComplexType type, string typeNs, bool excludeFromImport)
  304.         {
  305.             if (type.Name == null) {
  306.                 XmlSchemaElement element = (XmlSchemaElement)type.Parent;
  307.                 XmlQualifiedName parentType = XmlSchemas.GetParentName(element);
  308.                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidSchemaElementType, parentType.Name, parentType.Namespace, element.Name));
  309.             }
  310.            
  311.             TypeDesc baseTypeDesc = null;
  312.            
  313.             Mapping baseMapping = null;
  314.             if (!type.DerivedFrom.IsEmpty) {
  315.                 baseMapping = ImportType(type.DerivedFrom, excludeFromImport);
  316.                
  317.                 if (baseMapping is StructMapping)
  318.                     baseTypeDesc = ((StructMapping)baseMapping).TypeDesc;
  319.                 else
  320.                     baseMapping = null;
  321.             }
  322.             if (baseMapping == null)
  323.                 baseMapping = GetRootMapping();
  324.             Mapping previousMapping = (Mapping)ImportedMappings[type];
  325.             if (previousMapping != null) {
  326.                 return (StructMapping)previousMapping;
  327.             }
  328.             string typeName = GenerateUniqueTypeName(Accessor.UnescapeName(type.Name));
  329.             StructMapping structMapping = new StructMapping();
  330.             structMapping.IsReference = Schemas.IsReference(type);
  331.             TypeFlags flags = TypeFlags.Reference;
  332.             if (type.IsAbstract)
  333.                 flags |= TypeFlags.Abstract;
  334.             structMapping.TypeDesc = new TypeDesc(typeName, typeName, TypeKind.Struct, baseTypeDesc, flags);
  335.             structMapping.Namespace = typeNs;
  336.             structMapping.TypeName = type.Name;
  337.             structMapping.BaseMapping = (StructMapping)baseMapping;
  338.             ImportedMappings.Add(type, structMapping);
  339.             if (excludeFromImport)
  340.                 structMapping.IncludeInSchema = false;
  341.             CodeIdentifiers members = new CodeIdentifiers();
  342.             members.AddReserved(typeName);
  343.             AddReservedIdentifiersForDataBinding(members);
  344.             structMapping.Members = ImportTypeMembers(type, typeNs, members);
  345.             Scope.AddTypeMapping(structMapping);
  346.             ImportDerivedTypes(new XmlQualifiedName(type.Name, typeNs));
  347.             return structMapping;
  348.         }
  349.        
  350.         MemberMapping[] ImportTypeMembers(XmlSchemaComplexType type, string typeNs, CodeIdentifiers members)
  351.         {
  352.             if (type.AnyAttribute != null) {
  353.                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidAnyAttributeUse, type.Name, type.QualifiedName.Namespace));
  354.             }
  355.            
  356.             XmlSchemaObjectCollection items = type.Attributes;
  357.             for (int i = 0; i < items.Count; i++) {
  358.                 object item = items[i];
  359.                 if (item is XmlSchemaAttributeGroup) {
  360.                     throw new InvalidOperationException(Res.GetString(Res.XmlSoapInvalidAttributeUse, type.Name, type.QualifiedName.Namespace));
  361.                 }
  362.                 if (item is XmlSchemaAttribute) {
  363.                     XmlSchemaAttribute attr = (XmlSchemaAttribute)item;
  364.                     if (attr.Use != XmlSchemaUse.Prohibited)
  365.                         throw new InvalidOperationException(Res.GetString(Res.XmlSoapInvalidAttributeUse, type.Name, type.QualifiedName.Namespace));
  366.                 }
  367.             }
  368.             if (type.Particle != null) {
  369.                 ImportGroup(type.Particle, members, typeNs);
  370.             }
  371.             else if (type.ContentModel != null && type.ContentModel is XmlSchemaComplexContent) {
  372.                 XmlSchemaComplexContent model = (XmlSchemaComplexContent)type.ContentModel;
  373.                
  374.                 if (model.Content is XmlSchemaComplexContentExtension) {
  375.                     if (((XmlSchemaComplexContentExtension)model.Content).Particle != null) {
  376.                         ImportGroup(((XmlSchemaComplexContentExtension)model.Content).Particle, members, typeNs);
  377.                     }
  378.                 }
  379.                 else if (model.Content is XmlSchemaComplexContentRestriction) {
  380.                     if (((XmlSchemaComplexContentRestriction)model.Content).Particle != null) {
  381.                         ImportGroup(((XmlSchemaComplexContentRestriction)model.Content).Particle, members, typeNs);
  382.                     }
  383.                 }
  384.             }
  385.             return (MemberMapping[])members.ToArray(typeof(MemberMapping));
  386.         }
  387.        
  388.         void ImportGroup(XmlSchemaParticle group, CodeIdentifiers members, string ns)
  389.         {
  390.             if (group is XmlSchemaChoice) {
  391.                 XmlQualifiedName parentType = XmlSchemas.GetParentName(group);
  392.                 throw new InvalidOperationException(Res.GetString(Res.XmlSoapInvalidChoice, parentType.Name, parentType.Namespace));
  393.             }
  394.             else
  395.                 ImportGroupMembers(group, members, ns);
  396.         }
  397.        
  398.         void ImportGroupMembers(XmlSchemaParticle particle, CodeIdentifiers members, string ns)
  399.         {
  400.             XmlQualifiedName parentType = XmlSchemas.GetParentName(particle);
  401.             if (particle is XmlSchemaGroupRef) {
  402.                 throw new InvalidOperationException(Res.GetString(Res.XmlSoapUnsupportedGroupRef, parentType.Name, parentType.Namespace));
  403.             }
  404.             else if (particle is XmlSchemaGroupBase) {
  405.                 XmlSchemaGroupBase group = (XmlSchemaGroupBase)particle;
  406.                 if (group.IsMultipleOccurrence)
  407.                     throw new InvalidOperationException(Res.GetString(Res.XmlSoapUnsupportedGroupRepeat, parentType.Name, parentType.Namespace));
  408.                 for (int i = 0; i < group.Items.Count; i++) {
  409.                     object item = group.Items[i];
  410.                     if (item is XmlSchemaGroupBase || item is XmlSchemaGroupRef)
  411.                         throw new InvalidOperationException(Res.GetString(Res.XmlSoapUnsupportedGroupNested, parentType.Name, parentType.Namespace));
  412.                     else if (item is XmlSchemaElement)
  413.                         ImportElementMember((XmlSchemaElement)item, members, ns);
  414.                     else if (item is XmlSchemaAny)
  415.                         throw new InvalidOperationException(Res.GetString(Res.XmlSoapUnsupportedGroupAny, parentType.Name, parentType.Namespace));
  416.                 }
  417.             }
  418.         }
  419.        
  420.        
  421.         ElementAccessor ImportArray(XmlSchemaElement element, string ns)
  422.         {
  423.             if (element.SchemaType == null)
  424.                 return null;
  425.             if (!element.IsMultipleOccurrence)
  426.                 return null;
  427.             XmlSchemaType type = element.SchemaType;
  428.             ArrayMapping arrayMapping = ImportArrayMapping(type, ns);
  429.             if (arrayMapping == null)
  430.                 return null;
  431.             ElementAccessor arrayAccessor = new ElementAccessor();
  432.             arrayAccessor.IsSoap = true;
  433.             arrayAccessor.Name = element.Name;
  434.             arrayAccessor.Namespace = ns;
  435.             arrayAccessor.Mapping = arrayMapping;
  436.             arrayAccessor.IsNullable = false;
  437.             arrayAccessor.Form = XmlSchemaForm.None;
  438.            
  439.             return arrayAccessor;
  440.         }
  441.        
  442.         ArrayMapping ImportArrayMapping(XmlSchemaType type, string ns)
  443.         {
  444.             ArrayMapping arrayMapping;
  445.             if (type.Name == Soap.Array && ns == Soap.Encoding) {
  446.                 arrayMapping = new ArrayMapping();
  447.                 TypeMapping mapping = GetRootMapping();
  448.                 ElementAccessor itemAccessor = new ElementAccessor();
  449.                 itemAccessor.IsSoap = true;
  450.                 itemAccessor.Name = Soap.UrType;
  451.                 itemAccessor.Namespace = ns;
  452.                 itemAccessor.Mapping = mapping;
  453.                 itemAccessor.IsNullable = true;
  454.                 itemAccessor.Form = XmlSchemaForm.None;
  455.                
  456.                 arrayMapping.Elements = new ElementAccessor[] {itemAccessor};
  457.                 arrayMapping.TypeDesc = itemAccessor.Mapping.TypeDesc.CreateArrayTypeDesc();
  458.                 arrayMapping.TypeName = "ArrayOf" + CodeIdentifier.MakePascal(itemAccessor.Mapping.TypeName);
  459.                 return arrayMapping;
  460.             }
  461.             if (!(type.DerivedFrom.Name == Soap.Array && type.DerivedFrom.Namespace == Soap.Encoding))
  462.                 return null;
  463.            
  464.             // the type should be a XmlSchemaComplexType
  465.             XmlSchemaContentModel model = ((XmlSchemaComplexType)type).ContentModel;
  466.            
  467.             // the Content should be an restriction
  468.             if (!(model.Content is XmlSchemaComplexContentRestriction))
  469.                 return null;
  470.            
  471.             arrayMapping = new ArrayMapping();
  472.            
  473.             XmlSchemaComplexContentRestriction restriction = (XmlSchemaComplexContentRestriction)model.Content;
  474.            
  475.             for (int i = 0; i < restriction.Attributes.Count; i++) {
  476.                 XmlSchemaAttribute attribute = restriction.Attributes[i] as XmlSchemaAttribute;
  477.                 if (attribute != null && attribute.RefName.Name == Soap.ArrayType && attribute.RefName.Namespace == Soap.Encoding) {
  478.                     // read the value of the wsdl:arrayType attribute
  479.                     string arrayType = null;
  480.                    
  481.                     if (attribute.UnhandledAttributes != null) {
  482.                         foreach (XmlAttribute a in attribute.UnhandledAttributes) {
  483.                             if (a.LocalName == Wsdl.ArrayType && a.NamespaceURI == Wsdl.Namespace) {
  484.                                 arrayType = a.Value;
  485.                                 break;
  486.                             }
  487.                         }
  488.                     }
  489.                     if (arrayType != null) {
  490.                         string dims;
  491.                         XmlQualifiedName typeName = TypeScope.ParseWsdlArrayType(arrayType, out dims, attribute);
  492.                        
  493.                         TypeMapping mapping;
  494.                         TypeDesc td = Scope.GetTypeDesc(typeName.Name, typeName.Namespace);
  495.                         if (td != null && td.IsPrimitive) {
  496.                             mapping = new PrimitiveMapping();
  497.                             mapping.TypeDesc = td;
  498.                             mapping.TypeName = td.DataType.Name;
  499.                         }
  500.                         else {
  501.                             mapping = ImportType(typeName, false);
  502.                         }
  503.                         ElementAccessor itemAccessor = new ElementAccessor();
  504.                         itemAccessor.IsSoap = true;
  505.                         itemAccessor.Name = typeName.Name;
  506.                         itemAccessor.Namespace = ns;
  507.                         itemAccessor.Mapping = mapping;
  508.                         itemAccessor.IsNullable = true;
  509.                         itemAccessor.Form = XmlSchemaForm.None;
  510.                        
  511.                         arrayMapping.Elements = new ElementAccessor[] {itemAccessor};
  512.                         arrayMapping.TypeDesc = itemAccessor.Mapping.TypeDesc.CreateArrayTypeDesc();
  513.                         arrayMapping.TypeName = "ArrayOf" + CodeIdentifier.MakePascal(itemAccessor.Mapping.TypeName);
  514.                        
  515.                         return arrayMapping;
  516.                     }
  517.                 }
  518.             }
  519.            
  520.             XmlSchemaParticle particle = restriction.Particle;
  521.             if (particle is XmlSchemaAll || particle is XmlSchemaSequence) {
  522.                 XmlSchemaGroupBase group = (XmlSchemaGroupBase)particle;
  523.                 if (group.Items.Count != 1 || !(group.Items[0] is XmlSchemaElement))
  524.                     return null;
  525.                 XmlSchemaElement itemElement = (XmlSchemaElement)group.Items[0];
  526.                 if (!itemElement.IsMultipleOccurrence)
  527.                     return null;
  528.                 ElementAccessor itemAccessor = ImportElement(itemElement, ns);
  529.                 arrayMapping.Elements = new ElementAccessor[] {itemAccessor};
  530.                 arrayMapping.TypeDesc = ((TypeMapping)itemAccessor.Mapping).TypeDesc.CreateArrayTypeDesc();
  531.             }
  532.             else {
  533.                 return null;
  534.             }
  535.             return arrayMapping;
  536.         }
  537.        
  538.         void ImportElementMember(XmlSchemaElement element, CodeIdentifiers members, string ns)
  539.         {
  540.             ElementAccessor accessor;
  541.             if ((accessor = ImportArray(element, ns)) == null) {
  542.                 accessor = ImportElement(element, ns);
  543.             }
  544.            
  545.             MemberMapping member = new MemberMapping();
  546.             member.Name = CodeIdentifier.MakeValid(Accessor.UnescapeName(accessor.Name));
  547.             member.Name = members.AddUnique(member.Name, member);
  548.             if (member.Name.EndsWith("Specified", StringComparison.Ordinal)) {
  549.                 string name = member.Name;
  550.                 member.Name = members.AddUnique(member.Name, member);
  551.                 members.Remove(name);
  552.             }
  553.             member.TypeDesc = ((TypeMapping)accessor.Mapping).TypeDesc;
  554.             member.Elements = new ElementAccessor[] {accessor};
  555.             if (element.IsMultipleOccurrence)
  556.                 member.TypeDesc = member.TypeDesc.CreateArrayTypeDesc();
  557.            
  558.             if (element.MinOccurs == 0 && member.TypeDesc.IsValueType && !member.TypeDesc.HasIsEmpty) {
  559.                 member.CheckSpecified = true;
  560.             }
  561.         }
  562.        
  563.         TypeMapping ImportDataType(XmlSchemaSimpleType dataType, string typeNs, string identifier, bool isList)
  564.         {
  565.             TypeMapping mapping = ImportNonXsdPrimitiveDataType(dataType, typeNs);
  566.             if (mapping != null)
  567.                 return mapping;
  568.            
  569.             if (dataType.Content is XmlSchemaSimpleTypeRestriction) {
  570.                 XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)dataType.Content;
  571.                 foreach (object o in restriction.Facets) {
  572.                     if (o is XmlSchemaEnumerationFacet) {
  573.                         return ImportEnumeratedDataType(dataType, typeNs, identifier, isList);
  574.                     }
  575.                 }
  576.             }
  577.             else if (dataType.Content is XmlSchemaSimpleTypeList || dataType.Content is XmlSchemaSimpleTypeUnion) {
  578.                 if (dataType.Content is XmlSchemaSimpleTypeList) {
  579.                     // check if we have enumeration list
  580.                     XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)dataType.Content;
  581.                     if (list.ItemType != null) {
  582.                         mapping = ImportDataType(list.ItemType, typeNs, identifier, true);
  583.                         if (mapping != null) {
  584.                             return mapping;
  585.                         }
  586.                     }
  587.                 }
  588.                 mapping = new PrimitiveMapping();
  589.                 mapping.TypeDesc = Scope.GetTypeDesc(typeof(string));
  590.                 mapping.TypeName = mapping.TypeDesc.DataType.Name;
  591.                 return mapping;
  592.             }
  593.             return ImportPrimitiveDataType(dataType);
  594.         }
  595.        
  596.         TypeMapping ImportEnumeratedDataType(XmlSchemaSimpleType dataType, string typeNs, string identifier, bool isList)
  597.         {
  598.             TypeMapping mapping = (TypeMapping)ImportedMappings[dataType];
  599.             if (mapping != null)
  600.                 return mapping;
  601.            
  602.             XmlSchemaSimpleType sourceDataType = FindDataType(dataType.DerivedFrom);
  603.             TypeDesc sourceTypeDesc = Scope.GetTypeDesc(sourceDataType);
  604.             if (sourceTypeDesc != null && sourceTypeDesc != Scope.GetTypeDesc(typeof(string)))
  605.                 return ImportPrimitiveDataType(dataType);
  606.             identifier = Accessor.UnescapeName(identifier);
  607.             string typeName = GenerateUniqueTypeName(identifier);
  608.             EnumMapping enumMapping = new EnumMapping();
  609.             enumMapping.IsReference = Schemas.IsReference(dataType);
  610.             enumMapping.TypeDesc = new TypeDesc(typeName, typeName, TypeKind.Enum, null, 0);
  611.             enumMapping.TypeName = identifier;
  612.             enumMapping.Namespace = typeNs;
  613.             enumMapping.IsFlags = isList;
  614.             CodeIdentifiers constants = new CodeIdentifiers();
  615.            
  616.             if (!(dataType.Content is XmlSchemaSimpleTypeRestriction))
  617.                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidEnumContent, dataType.Content.GetType().Name, identifier));
  618.            
  619.             XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)dataType.Content;
  620.            
  621.             for (int i = 0; i < restriction.Facets.Count; i++) {
  622.                 object facet = restriction.Facets[i];
  623.                 if (!(facet is XmlSchemaEnumerationFacet))
  624.                     continue;
  625.                 XmlSchemaEnumerationFacet enumeration = (XmlSchemaEnumerationFacet)facet;
  626.                 ConstantMapping constant = new ConstantMapping();
  627.                 string constantName = CodeIdentifier.MakeValid(enumeration.Value);
  628.                 constant.Name = constants.AddUnique(constantName, constant);
  629.                 constant.XmlName = enumeration.Value;
  630.                 constant.Value = i;
  631.             }
  632.             enumMapping.Constants = (ConstantMapping[])constants.ToArray(typeof(ConstantMapping));
  633.             if (isList && enumMapping.Constants.Length > 63) {
  634.                 // if we have 64+ flag constants we cannot map the type to long enum, we will use string mapping instead.
  635.                 mapping = new PrimitiveMapping();
  636.                 mapping.TypeDesc = Scope.GetTypeDesc(typeof(string));
  637.                 mapping.TypeName = mapping.TypeDesc.DataType.Name;
  638.                 ImportedMappings.Add(dataType, mapping);
  639.                 return mapping;
  640.             }
  641.             ImportedMappings.Add(dataType, enumMapping);
  642.             Scope.AddTypeMapping(enumMapping);
  643.             return enumMapping;
  644.         }
  645.        
  646.         PrimitiveMapping ImportPrimitiveDataType(XmlSchemaSimpleType dataType)
  647.         {
  648.             TypeDesc sourceTypeDesc = GetDataTypeSource(dataType);
  649.             PrimitiveMapping mapping = new PrimitiveMapping();
  650.             mapping.TypeDesc = sourceTypeDesc;
  651.             mapping.TypeName = sourceTypeDesc.DataType.Name;
  652.             return mapping;
  653.         }
  654.        
  655.         PrimitiveMapping ImportNonXsdPrimitiveDataType(XmlSchemaSimpleType dataType, string ns)
  656.         {
  657.             PrimitiveMapping mapping = null;
  658.             TypeDesc typeDesc = null;
  659.             if (dataType.Name != null && dataType.Name.Length != 0) {
  660.                 typeDesc = Scope.GetTypeDesc(dataType.Name, ns);
  661.                 if (typeDesc != null) {
  662.                     mapping = new PrimitiveMapping();
  663.                     mapping.TypeDesc = typeDesc;
  664.                     mapping.TypeName = typeDesc.DataType.Name;
  665.                 }
  666.             }
  667.             return mapping;
  668.         }
  669.        
  670.         TypeDesc GetDataTypeSource(XmlSchemaSimpleType dataType)
  671.         {
  672.             if (dataType.Name != null && dataType.Name.Length != 0) {
  673.                 TypeDesc typeDesc = Scope.GetTypeDesc(dataType);
  674.                 if (typeDesc != null)
  675.                     return typeDesc;
  676.             }
  677.             if (!dataType.DerivedFrom.IsEmpty) {
  678.                 return GetDataTypeSource(FindDataType(dataType.DerivedFrom));
  679.             }
  680.             return Scope.GetTypeDesc(typeof(string));
  681.         }
  682.        
  683.         XmlSchemaSimpleType FindDataType(XmlQualifiedName name)
  684.         {
  685.             TypeDesc typeDesc = Scope.GetTypeDesc(name.Name, name.Namespace);
  686.             if (typeDesc != null && typeDesc.DataType is XmlSchemaSimpleType)
  687.                 return (XmlSchemaSimpleType)typeDesc.DataType;
  688.             XmlSchemaSimpleType dataType = (XmlSchemaSimpleType)Schemas.Find(name, typeof(XmlSchemaSimpleType));
  689.             if (dataType != null) {
  690.                 return dataType;
  691.             }
  692.             if (name.Namespace == XmlSchema.Namespace)
  693.                 return (XmlSchemaSimpleType)Scope.GetTypeDesc(typeof(string)).DataType;
  694.             else
  695.                 throw new InvalidOperationException(Res.GetString(Res.XmlMissingDataType, name.ToString()));
  696.         }
  697.        
  698.         object FindType(XmlQualifiedName name)
  699.         {
  700.             if (name != null && name.Namespace == Soap.Encoding) {
  701.                 // we have a build-in support fo the encoded types, we need to make sure that we generate the same
  702.                 // object model whether http://www.w3.org/2003/05/soap-encoding schema was specified or not.
  703.                 object type = Schemas.Find(name, typeof(XmlSchemaComplexType));
  704.                 if (type != null) {
  705.                     XmlSchemaType encType = (XmlSchemaType)type;
  706.                     XmlQualifiedName baseType = encType.DerivedFrom;
  707.                     if (!baseType.IsEmpty) {
  708.                         return FindType(baseType);
  709.                     }
  710.                     return encType;
  711.                 }
  712.                 return FindDataType(name);
  713.             }
  714.             else {
  715.                 object type = Schemas.Find(name, typeof(XmlSchemaComplexType));
  716.                 if (type != null) {
  717.                     return type;
  718.                 }
  719.                 return FindDataType(name);
  720.             }
  721.         }
  722.     }
  723. }

Developer Fusion