-// \r
-// System.Xml.Serialization.XmlSchemaImporter\r
-//\r
-// Author:\r
-// Tim Coleman (tim@timcoleman.com)\r
-// Lluis Sanchez Gual (lluis@ximian.com)\r
-//\r
-// Copyright (C) Tim Coleman, 2002\r
-//\r
-\r
-//\r
-// Permission is hereby granted, free of charge, to any person obtaining\r
-// a copy of this software and associated documentation files (the\r
-// "Software"), to deal in the Software without restriction, including\r
-// without limitation the rights to use, copy, modify, merge, publish,\r
-// distribute, sublicense, and/or sell copies of the Software, and to\r
-// permit persons to whom the Software is furnished to do so, subject to\r
-// the following conditions:\r
-// \r
-// The above copyright notice and this permission notice shall be\r
-// included in all copies or substantial portions of the Software.\r
-// \r
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
-//\r
-\r
-using System.Xml;\r
-#if !TARGET_JVM\r
-using System.CodeDom.Compiler;\r
-#endif\r
-using System.Xml.Schema;\r
-using System.Collections;\r
-#if NET_2_0 && CONFIGURATION_DEP\r
-using System.Configuration;\r
-using System.Xml.Serialization.Configuration;\r
-#endif\r
-\r
-namespace System.Xml.Serialization \r
-{\r
- public class XmlSchemaImporter\r
-#if NET_2_0\r
- : SchemaImporter\r
-#endif\r
- {\r
- #region Fields\r
-\r
- XmlSchemas schemas;\r
- CodeIdentifiers typeIdentifiers;\r
- CodeIdentifiers elemIdentifiers = new CodeIdentifiers ();\r
- Hashtable mappedTypes = new Hashtable ();\r
- Hashtable dataMappedTypes = new Hashtable ();\r
- Queue pendingMaps = new Queue ();\r
- Hashtable sharedAnonymousTypes = new Hashtable ();\r
- bool encodedFormat = false;\r
- XmlReflectionImporter auxXmlRefImporter;\r
- SoapReflectionImporter auxSoapRefImporter;\r
- bool anyTypeImported;\r
-\r
-#if NET_2_0\r
- CodeGenerationOptions options;\r
-#endif\r
-\r
- static readonly XmlQualifiedName anyType = new XmlQualifiedName ("anyType",XmlSchema.Namespace);\r
- static readonly XmlQualifiedName arrayType = new XmlQualifiedName ("Array",XmlSerializer.EncodingNamespace);\r
- static readonly XmlQualifiedName arrayTypeRefName = new XmlQualifiedName ("arrayType",XmlSerializer.EncodingNamespace);\r
- \r
- const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";\r
- \r
- XmlSchemaElement anyElement = null;\r
-\r
- class MapFixup\r
- {\r
- public XmlTypeMapping Map;\r
- public XmlSchemaComplexType SchemaType;\r
- public XmlQualifiedName TypeName;\r
- }\r
-\r
- #endregion\r
-\r
- #region Constructors\r
-\r
- public XmlSchemaImporter (XmlSchemas schemas)\r
- {\r
- this.schemas = schemas;\r
- typeIdentifiers = new CodeIdentifiers ();\r
-\r
- InitializeExtensions ();\r
- }\r
-\r
- public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers)\r
- : this (schemas)\r
- {\r
- this.typeIdentifiers = typeIdentifiers;\r
- }\r
- \r
-#if NET_2_0\r
-#if !TARGET_JVM\r
- [MonoTODO]\r
- public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, CodeDomProvider codeProvider, ImportContext context)\r
- {\r
- this.schemas = schemas;\r
- this.options = options;\r
- if (context != null) {\r
- typeIdentifiers = context.TypeIdentifiers;\r
- InitSharedData (context);\r
- }\r
- else\r
- typeIdentifiers = new CodeIdentifiers ();\r
-\r
- InitializeExtensions ();\r
- }\r
-#endif\r
-\r
- public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, ImportContext context)\r
- {\r
- this.schemas = schemas;\r
- this.options = options;\r
- if (context != null) {\r
- typeIdentifiers = context.TypeIdentifiers;\r
- InitSharedData (context);\r
- }\r
- else\r
- typeIdentifiers = new CodeIdentifiers ();\r
-\r
- InitializeExtensions ();\r
- }\r
- \r
-\r
- public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers, CodeGenerationOptions options)\r
- {\r
- this.typeIdentifiers = typeIdentifiers;\r
- this.schemas = schemas;\r
- this.options = options;\r
-\r
- InitializeExtensions ();\r
- }\r
-\r
- void InitSharedData (ImportContext context)\r
- {\r
- if (context.ShareTypes) {\r
- mappedTypes = context.MappedTypes;\r
- dataMappedTypes = context.DataMappedTypes;\r
- sharedAnonymousTypes = context.SharedAnonymousTypes;\r
- }\r
- }\r
-#endif\r
- \r
- internal bool UseEncodedFormat\r
- {\r
- get { return encodedFormat; }\r
- set { encodedFormat = value; }\r
- }\r
-\r
- #endregion // Constructors\r
-\r
- #region Methods\r
-\r
- void InitializeExtensions ()\r
- {\r
-#if NET_2_0 && CONFIGURATION_DEP\r
- SerializationSectionGroup root = ConfigurationManager.GetSection ("system.xml.serialization") as SerializationSectionGroup;\r
- if (root == null)\r
- return;\r
-\r
- foreach (SchemaImporterExtensionElement element in\r
- root.SchemaImporterExtensions.SchemaImporterExtensions)\r
- Extensions.Add (element.Name, element.Type);\r
-#endif\r
- }\r
-\r
- public XmlMembersMapping ImportAnyType (XmlQualifiedName typeName, string elementName)\r
- {\r
- if (typeName == XmlQualifiedName.Empty)\r
- {\r
- XmlTypeMapMemberAnyElement mapMem = new XmlTypeMapMemberAnyElement ();\r
- mapMem.Name = typeName.Name;\r
- mapMem.TypeData = TypeTranslator.GetTypeData(typeof(XmlNode));\r
- mapMem.ElementInfo.Add (CreateElementInfo (typeName.Namespace, mapMem, typeName.Name, mapMem.TypeData, true, XmlSchemaForm.None));\r
- \r
- XmlMemberMapping[] mm = new XmlMemberMapping [1];\r
- mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);\r
- return new XmlMembersMapping (mm);\r
- }\r
- else\r
- {\r
- XmlSchemaComplexType stype = (XmlSchemaComplexType) schemas.Find (typeName, typeof (XmlSchemaComplexType));\r
- if (stype == null) \r
- throw new InvalidOperationException ("Referenced type '" + typeName + "' not found");\r
- \r
- if (!CanBeAnyElement (stype))\r
- throw new InvalidOperationException ("The type '" + typeName + "' is not valid for a collection of any elements");\r
- \r
- ClassMap cmap = new ClassMap ();\r
- CodeIdentifiers classIds = new CodeIdentifiers ();\r
- bool isMixed = stype.IsMixed;\r
- ImportSequenceContent (typeName, cmap, ((XmlSchemaSequence) stype.Particle).Items, classIds, false, ref isMixed);\r
- XmlTypeMapMemberAnyElement mapMem = (XmlTypeMapMemberAnyElement) cmap.AllMembers[0];\r
- mapMem.Name = typeName.Name;\r
- \r
- XmlMemberMapping[] mm = new XmlMemberMapping [1];\r
- mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);\r
- return new XmlMembersMapping (mm);\r
- }\r
- }\r
-\r
- public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType)\r
- {\r
- return ImportDerivedTypeMapping (name, baseType, true);\r
- }\r
- \r
- public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType, bool baseTypeCanBeIndirect)\r
- {\r
- XmlQualifiedName qname;\r
- XmlSchemaType stype;\r
- \r
- if (encodedFormat)\r
- {\r
- qname = name;\r
- stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;\r
- if (stype == null) throw new InvalidOperationException ("Schema type '" + name + "' not found or not valid");\r
- }\r
- else\r
- {\r
- if (!LocateElement (name, out qname, out stype))\r
- return null;\r
- }\r
-\r
- XmlTypeMapping map = GetRegisteredTypeMapping (qname);\r
- if (map != null)\r
- {\r
- // If the type has already been imported, make sure that the map \r
- // has the requested base type\r
- \r
- SetMapBaseType (map, baseType);\r
- map.UpdateRoot (name);\r
- return map;\r
- }\r
- \r
- map = CreateTypeMapping (qname, SchemaTypes.Class, name);\r
- if (stype != null) {\r
- map.Documentation = GetDocumentation (stype);\r
- RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);\r
- } else {\r
- ClassMap cmap = new ClassMap ();\r
- CodeIdentifiers classIds = new CodeIdentifiers ();\r
- map.ObjectMap = cmap;\r
- AddTextMember (qname, cmap, classIds);\r
- }\r
- \r
- BuildPendingMaps ();\r
- SetMapBaseType (map, baseType);\r
- \r
- return map;\r
- }\r
- \r
- void SetMapBaseType (XmlTypeMapping map, Type baseType)\r
- {\r
- // This method sets the base type for a given map.\r
- // If the map already inherits from this type, it does nothing.\r
- \r
- // Fiirst of all, check if the map already inherits from baseType\r
- \r
- XmlTypeMapping topMap = null;\r
- while (map != null)\r
- {\r
- if (map.TypeData.Type == baseType)\r
- return;\r
- topMap = map;\r
- map = map.BaseMap;\r
- }\r
- \r
- // Does not have the requested base type.\r
- // Then, get/create a map for that base type.\r
-\r
- XmlTypeMapping baseMap = ReflectType (baseType);\r
- \r
- // Add this map as a derived map of the base map\r
-\r
- topMap.BaseMap = baseMap;\r
- baseMap.DerivedTypes.Add (topMap);\r
- baseMap.DerivedTypes.AddRange (topMap.DerivedTypes);\r
- \r
- // Now add the base type fields to all derived maps\r
-\r
- ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;\r
- \r
- ClassMap cmap = (ClassMap)topMap.ObjectMap;\r
- foreach (XmlTypeMapMember member in baseClassMap.AllMembers)\r
- cmap.AddMember (member);\r
- \r
- foreach (XmlTypeMapping derivedMap in topMap.DerivedTypes)\r
- {\r
- cmap = (ClassMap)derivedMap.ObjectMap;\r
- foreach (XmlTypeMapMember member in baseClassMap.AllMembers)\r
- cmap.AddMember (member);\r
- }\r
- }\r
-\r
- public XmlMembersMapping ImportMembersMapping (XmlQualifiedName name)\r
- {\r
- XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));\r
- if (elem == null) throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");\r
-\r
- XmlSchemaComplexType stype;\r
- if (elem.SchemaType != null)\r
- {\r
- stype = elem.SchemaType as XmlSchemaComplexType;\r
- }\r
- else\r
- {\r
- if (elem.SchemaTypeName.IsEmpty) return null;\r
- object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));\r
- if (type == null) {\r
- if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) return null;\r
- throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");\r
- }\r
- stype = type as XmlSchemaComplexType;\r
- }\r
- \r
- if (stype == null) \r
- throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");\r
- \r
- XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, name); \r
- return new XmlMembersMapping (name.Name, name.Namespace, mapping);\r
- }\r
- \r
- public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names)\r
- {\r
- XmlMemberMapping[] mapping = new XmlMemberMapping [names.Length];\r
- for (int n=0; n<names.Length; n++)\r
- {\r
- XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (names[n], typeof (XmlSchemaElement));\r
- if (elem == null) throw new InvalidOperationException ("Schema element '" + names[n] + "' not found");\r
- \r
- XmlQualifiedName typeQName = new XmlQualifiedName ("Message", names[n].Namespace);\r
- XmlTypeMapping tmap;\r
- TypeData td = GetElementTypeData (typeQName, elem, names[n], out tmap);\r
- \r
- mapping[n] = ImportMemberMapping (elem.Name, typeQName.Namespace, elem.IsNillable, td, tmap);\r
- }\r
- BuildPendingMaps ();\r
- return new XmlMembersMapping (mapping);\r
- }\r
- \r
-#if NET_2_0\r
- [MonoTODO]\r
- public XmlMembersMapping ImportMembersMapping (string name, string ns, SoapSchemaMember[] members)\r
- {\r
- throw new NotImplementedException ();\r
- }\r
- \r
- [MonoTODO]\r
- public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName)\r
- {\r
- throw new NotImplementedException ();\r
- }\r
- \r
- [MonoTODO]\r
- public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType)\r
- {\r
- throw new NotImplementedException ();\r
- }\r
- \r
- [MonoTODO]\r
- public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType, bool baseTypeCanBeIndirect)\r
- {\r
- throw new NotImplementedException ();\r
- }\r
-#endif\r
- \r
- internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember[] members, bool hasWrapperElement)\r
- {\r
- XmlMemberMapping[] mapping = new XmlMemberMapping [members.Length];\r
- for (int n=0; n<members.Length; n++)\r
- {\r
- TypeData td = GetTypeData (members[n].MemberType, null);\r
- XmlTypeMapping tmap = GetTypeMapping (td);\r
- mapping[n] = ImportMemberMapping (members[n].MemberName, members[n].MemberType.Namespace, true, td, tmap);\r
- }\r
- BuildPendingMaps ();\r
- return new XmlMembersMapping (name, ns, hasWrapperElement, false, mapping);\r
- }\r
- \r
- internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember member)\r
- {\r
- XmlSchemaComplexType stype = schemas.Find (member.MemberType, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;\r
- if (stype == null) throw new InvalidOperationException ("Schema type '" + member.MemberType + "' not found or not valid");\r
-\r
- XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, member.MemberType); \r
- return new XmlMembersMapping (name, ns, mapping);\r
- }\r
- \r
- XmlMemberMapping[] ImportMembersMappingComposite (XmlSchemaComplexType stype, XmlQualifiedName refer)\r
- {\r
- if (stype.Particle == null) \r
- return new XmlMemberMapping [0];\r
-\r
- ClassMap cmap = new ClassMap ();\r
- \r
- XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;\r
- if (seq == null) throw new InvalidOperationException ("Schema element '" + refer + "' cannot be imported as XmlMembersMapping");\r
-\r
- CodeIdentifiers classIds = new CodeIdentifiers ();\r
- ImportParticleComplexContent (refer, cmap, seq, classIds, false);\r
- ImportAttributes (refer, cmap, stype.Attributes, stype.AnyAttribute, classIds);\r
-\r
- BuildPendingMaps ();\r
-\r
- int n = 0;\r
- XmlMemberMapping[] mapping = new XmlMemberMapping [cmap.AllMembers.Count];\r
- foreach (XmlTypeMapMember mapMem in cmap.AllMembers)\r
- mapping[n++] = new XmlMemberMapping (mapMem.Name, refer.Namespace, mapMem, encodedFormat);\r
- \r
- return mapping;\r
- }\r
- \r
- XmlMemberMapping ImportMemberMapping (string name, string ns, bool isNullable, TypeData type, XmlTypeMapping emap)\r
- {\r
- XmlTypeMapMemberElement mapMem;\r
- \r
- if (type.IsListType)\r
- mapMem = new XmlTypeMapMemberList ();\r
- else\r
- mapMem = new XmlTypeMapMemberElement ();\r
- \r
- mapMem.Name = name;\r
- mapMem.TypeData = type;\r
- mapMem.ElementInfo.Add (CreateElementInfo (ns, mapMem, name, type, isNullable, XmlSchemaForm.None, emap));\r
- return new XmlMemberMapping (name, ns, mapMem, encodedFormat);\r
- }\r
- \r
- [MonoTODO]\r
- public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names, Type baseType, bool baseTypeCanBeIndirect)\r
- {\r
- throw new NotImplementedException ();\r
- }\r
-\r
- public XmlTypeMapping ImportTypeMapping (XmlQualifiedName name)\r
- {\r
- XmlQualifiedName qname;\r
- XmlSchemaType stype;\r
-\r
- XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));\r
- if (!LocateElement (elem, out qname, out stype)) return null;\r
- \r
- if (stype == null) {\r
- // Importing a primitive type\r
- TypeData td = TypeTranslator.GetPrimitiveTypeData (qname.Name);\r
- return ReflectType (td, name.Namespace);\r
- }\r
- \r
- XmlTypeMapping map = GetRegisteredTypeMapping (qname);\r
- if (map != null) return map;\r
- \r
- map = CreateTypeMapping (qname, SchemaTypes.Class, name);\r
- map.Documentation = GetDocumentation (stype);\r
- map.IsNullable = elem.IsNillable;\r
- RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);\r
- \r
- BuildPendingMaps ();\r
- return map;\r
- }\r
-\r
- bool LocateElement (XmlQualifiedName name, out XmlQualifiedName qname, out XmlSchemaType stype)\r
- {\r
- XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));\r
- return LocateElement (elem, out qname, out stype);\r
- }\r
-\r
- bool LocateElement (XmlSchemaElement elem, out XmlQualifiedName qname, out XmlSchemaType stype)\r
- {\r
- qname = null;\r
- stype = null;\r
- \r
- if (elem == null) return false;\r
-\r
- // The root element must be an element with complex type\r
-\r
- if (elem.SchemaType != null)\r
- {\r
- stype = elem.SchemaType;\r
- qname = elem.QualifiedName;\r
- }\r
- else\r
- {\r
- if (elem.SchemaTypeName.IsEmpty) return false;\r
- \r
- object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));\r
- if (type == null) type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaSimpleType));\r
- if (type == null) {\r
- if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) {\r
- qname = elem.SchemaTypeName;\r
- return true;\r
- }\r
- throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");\r
- }\r
- stype = (XmlSchemaType) type;\r
- qname = stype.QualifiedName;\r
- \r
- XmlSchemaType btype = stype.BaseSchemaType as XmlSchemaType;\r
- if (btype != null && btype.QualifiedName == elem.SchemaTypeName)\r
- throw new InvalidOperationException ("Cannot import schema for type '" + elem.SchemaTypeName.Name + "' from namespace '" + elem.SchemaTypeName.Namespace + "'. Redefine not supported");\r
- }\r
-\r
- if (stype is XmlSchemaSimpleType) return false;\r
- return true;\r
- }\r
-\r
- XmlTypeMapping ImportType (XmlQualifiedName name, XmlQualifiedName root, bool throwOnError)\r
- {\r
- XmlTypeMapping map = GetRegisteredTypeMapping (name);\r
- if (map != null) {\r
- map.UpdateRoot (root);\r
- return map;\r
- }\r
-\r
- XmlSchemaType type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaComplexType));\r
- if (type == null) type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaSimpleType));\r
- \r
- if (type == null) \r
- {\r
- if (throwOnError) {\r
- if (name.Namespace == XmlSerializer.EncodingNamespace)\r
- throw new InvalidOperationException ("Referenced type '" + name + "' valid only for encoded SOAP.");\r
- else\r
- throw new InvalidOperationException ("Referenced type '" + name + "' not found.");\r
- } else\r
- return null;\r
- }\r
-\r
- return ImportType (name, type, root);\r
- }\r
-\r
- XmlTypeMapping ImportClass (XmlQualifiedName name)\r
- {\r
- XmlTypeMapping map = ImportType (name, null, true);\r
- if (map.TypeData.SchemaType == SchemaTypes.Class) return map;\r
- XmlSchemaComplexType stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;\r
- return CreateClassMap (name, stype, new XmlQualifiedName (map.ElementName, map.Namespace));\r
- }\r
- \r
- XmlTypeMapping ImportType (XmlQualifiedName name, XmlSchemaType stype, XmlQualifiedName root)\r
- {\r
- XmlTypeMapping map = GetRegisteredTypeMapping (name);\r
- if (map != null) {\r
- XmlSchemaComplexType ct = stype as XmlSchemaComplexType;\r
- if (map.TypeData.SchemaType != SchemaTypes.Class || ct == null || !CanBeArray (name, ct)) {\r
- map.UpdateRoot (root);\r
- return map;\r
- }\r
- \r
- // The map was initially imported as a class, but it turns out that it is an\r
- // array. It has to be imported now as array.\r
- }\r
- \r
- if (stype is XmlSchemaComplexType)\r
- return ImportClassComplexType (name, (XmlSchemaComplexType) stype, root);\r
- else if (stype is XmlSchemaSimpleType)\r
- return ImportClassSimpleType (name, (XmlSchemaSimpleType) stype, root);\r
-\r
- throw new NotSupportedException ("Schema type not supported: " + stype.GetType ());\r
- }\r
-\r
- XmlTypeMapping ImportClassComplexType (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)\r
- {\r
- // The need for fixups: If the complex type is an array, then to get the type of the\r
- // array we need first to get the type of the items of the array.\r
- // But if one of the item types or its children has a referece to this type array,\r
- // then we enter in an infinite loop. This does not happen with class types because\r
- // the class map is registered before parsing the children. We can't do the same\r
- // with the array type because to register the array map we need the type of the array.\r
-\r
- Type anyType = GetAnyElementType (stype);\r
- if (anyType != null)\r
- return GetTypeMapping (TypeTranslator.GetTypeData(anyType));\r
- \r
- if (CanBeArray (typeQName, stype))\r
- {\r
- TypeData typeData;\r
- ListMap listMap = BuildArrayMap (typeQName, stype, out typeData);\r
- if (listMap != null)\r
- {\r
- XmlTypeMapping map = CreateArrayTypeMapping (typeQName, typeData);\r
- map.ObjectMap = listMap;\r
- return map;\r
- }\r
-\r
- // After all, it is not an array. Create a class map then.\r
- }\r
- else if (CanBeIXmlSerializable (stype))\r
- {\r
- return ImportXmlSerializableMapping (typeQName.Namespace);\r
- }\r
-\r
- // Register the map right now but do not build it,\r
- // This will avoid loops.\r
-\r
- return CreateClassMap (typeQName, stype, root);\r
- }\r
- \r
- XmlTypeMapping CreateClassMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)\r
- {\r
- XmlTypeMapping map = CreateTypeMapping (typeQName, SchemaTypes.Class, root);\r
- map.Documentation = GetDocumentation (stype);\r
- RegisterMapFixup (map, typeQName, stype);\r
- return map;\r
- }\r
-\r
- void RegisterMapFixup (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)\r
- {\r
- MapFixup fixup = new MapFixup ();\r
- fixup.Map = map;\r
- fixup.SchemaType = stype;\r
- fixup.TypeName = typeQName;\r
- pendingMaps.Enqueue (fixup);\r
- }\r
-\r
- void BuildPendingMaps ()\r
- {\r
- while (pendingMaps.Count > 0) {\r
- MapFixup fixup = (MapFixup) pendingMaps.Dequeue ();\r
- if (fixup.Map.ObjectMap == null) {\r
- BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);\r
- if (fixup.Map.ObjectMap == null) pendingMaps.Enqueue (fixup);\r
- }\r
- }\r
- }\r
-\r
- void BuildPendingMap (XmlTypeMapping map)\r
- {\r
- if (map.ObjectMap != null) return;\r
-\r
- foreach (MapFixup fixup in pendingMaps)\r
- {\r
- if (fixup.Map == map) {\r
- BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);\r
- return;\r
- }\r
- }\r
- throw new InvalidOperationException ("Can't complete map of type " + map.XmlType + " : " + map.Namespace);\r
- }\r
-\r
- void BuildClassMap (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)\r
- {\r
- CodeIdentifiers classIds = new CodeIdentifiers();\r
- classIds.AddReserved (map.TypeData.TypeName);\r
-\r
- ClassMap cmap = new ClassMap ();\r
- map.ObjectMap = cmap;\r
- bool isMixed = stype.IsMixed;\r
-\r
- if (stype.Particle != null)\r
- ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, isMixed);\r
- else\r
- {\r
- if (stype.ContentModel is XmlSchemaSimpleContent) {\r
- ImportSimpleContent (typeQName, map, (XmlSchemaSimpleContent)stype.ContentModel, classIds, isMixed);\r
- }\r
- else if (stype.ContentModel is XmlSchemaComplexContent) {\r
- ImportComplexContent (typeQName, map, (XmlSchemaComplexContent)stype.ContentModel, classIds, isMixed);\r
- }\r
- }\r
-\r
- ImportAttributes (typeQName, cmap, stype.Attributes, stype.AnyAttribute, classIds);\r
- ImportExtensionTypes (typeQName);\r
-\r
- if (isMixed) AddTextMember (typeQName, cmap, classIds);\r
- \r
- AddObjectDerivedMap (map);\r
- }\r
- \r
- void ImportAttributes (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection atts, XmlSchemaAnyAttribute anyat, CodeIdentifiers classIds)\r
- {\r
- if (anyat != null)\r
- {\r
- XmlTypeMapMemberAnyAttribute member = new XmlTypeMapMemberAnyAttribute ();\r
- member.Name = classIds.AddUnique ("AnyAttribute", member);\r
- member.TypeData = TypeTranslator.GetTypeData (typeof(XmlAttribute[]));\r
- cmap.AddMember (member);\r
- }\r
- \r
- foreach (XmlSchemaObject at in atts)\r
- {\r
- if (at is XmlSchemaAttribute)\r
- {\r
- string ns;\r
- XmlSchemaAttribute attr = (XmlSchemaAttribute)at;\r
- XmlSchemaAttribute refAttr = GetRefAttribute (typeQName, attr, out ns);\r
- XmlTypeMapMemberAttribute member = new XmlTypeMapMemberAttribute ();\r
- member.Name = classIds.AddUnique (CodeIdentifier.MakeValid (refAttr.Name), member);\r
- member.Documentation = GetDocumentation (attr);\r
- member.AttributeName = refAttr.Name;\r
- member.Namespace = ns;\r
- member.Form = refAttr.Form;\r
- member.TypeData = GetAttributeTypeData (typeQName, attr);\r
- \r
- if (refAttr.DefaultValue != null) \r
- member.DefaultValue = ImportDefaultValue (member.TypeData, refAttr.DefaultValue);\r
- else if (member.TypeData.IsValueType)\r
- member.IsOptionalValueType = (refAttr.ValidatedUse != XmlSchemaUse.Required);\r
- \r
- if (member.TypeData.IsComplexType)\r
- member.MappedType = GetTypeMapping (member.TypeData);\r
- cmap.AddMember (member);\r
- }\r
- else if (at is XmlSchemaAttributeGroupRef)\r
- {\r
- XmlSchemaAttributeGroupRef gref = (XmlSchemaAttributeGroupRef)at;\r
- XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);\r
- ImportAttributes (typeQName, cmap, grp.Attributes, grp.AnyAttribute, classIds);\r
- }\r
- }\r
- }\r
-\r
- ListMap BuildArrayMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, out TypeData arrayTypeData)\r
- {\r
- if (encodedFormat)\r
- {\r
- XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;\r
- XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;\r
- XmlSchemaAttribute arrayTypeAt = FindArrayAttribute (rest.Attributes);\r
- \r
- if (arrayTypeAt != null)\r
- {\r
- XmlAttribute[] uatts = arrayTypeAt.UnhandledAttributes;\r
- if (uatts == null || uatts.Length == 0) throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);\r
- \r
- XmlAttribute xat = null;\r
- foreach (XmlAttribute at in uatts)\r
- if (at.LocalName == "arrayType" && at.NamespaceURI == XmlSerializer.WsdlNamespace)\r
- { xat = at; break; }\r
- \r
- if (xat == null) \r
- throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);\r
- \r
- string name, ns, dims;\r
- TypeTranslator.ParseArrayType (xat.Value, out name, out ns, out dims);\r
- return BuildEncodedArrayMap (name + dims, ns, out arrayTypeData);\r
- }\r
- else\r
- {\r
- XmlSchemaElement elem = null;\r
- XmlSchemaSequence seq = rest.Particle as XmlSchemaSequence;\r
- if (seq != null && seq.Items.Count == 1) \r
- elem = seq.Items[0] as XmlSchemaElement;\r
- else {\r
- XmlSchemaAll all = rest.Particle as XmlSchemaAll;\r
- if (all != null && all.Items.Count == 1)\r
- elem = all.Items[0] as XmlSchemaElement;\r
- }\r
- if (elem == null)\r
- throw new InvalidOperationException ("Unknown array format");\r
- \r
- return BuildEncodedArrayMap (elem.SchemaTypeName.Name + "[]", elem.SchemaTypeName.Namespace, out arrayTypeData);\r
- }\r
- }\r
- else\r
- {\r
- ClassMap cmap = new ClassMap ();\r
- CodeIdentifiers classIds = new CodeIdentifiers();\r
- ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, stype.IsMixed);\r
-\r
- XmlTypeMapMemberFlatList list = (cmap.AllMembers.Count == 1) ? cmap.AllMembers[0] as XmlTypeMapMemberFlatList : null;\r
- if (list != null && list.ChoiceMember == null)\r
- {\r
- arrayTypeData = list.TypeData;\r
- return list.ListMap;\r
- }\r
- else\r
- {\r
- arrayTypeData = null;\r
- return null;\r
- }\r
- }\r
- }\r
- \r
- ListMap BuildEncodedArrayMap (string type, string ns, out TypeData arrayTypeData)\r
- {\r
- ListMap map = new ListMap ();\r
- \r
- int i = type.LastIndexOf ("[");\r
- if (i == -1) throw new InvalidOperationException ("Invalid arrayType value: " + type);\r
- if (type.IndexOf (",",i) != -1) throw new InvalidOperationException ("Multidimensional arrays are not supported");\r
- \r
- string itemType = type.Substring (0,i);\r
- \r
- TypeData itemTypeData;\r
- if (itemType.IndexOf ("[") != -1) \r
- {\r
- ListMap innerListMap = BuildEncodedArrayMap (itemType, ns, out itemTypeData);\r
- \r
- int dims = itemType.Split ('[').Length - 1;\r
- string name = TypeTranslator.GetArrayName (type, dims);\r
- XmlQualifiedName qname = new XmlQualifiedName (name, ns);\r
- XmlTypeMapping tmap = CreateArrayTypeMapping (qname, itemTypeData);\r
- tmap.ObjectMap = innerListMap;\r
- }\r
- else\r
- {\r
- itemTypeData = GetTypeData (new XmlQualifiedName (itemType, ns), null);\r
- }\r
- \r
- arrayTypeData = itemTypeData.ListTypeData;\r
- \r
- map.ItemInfo = new XmlTypeMapElementInfoList();\r
- map.ItemInfo.Add (CreateElementInfo ("", null, "Item", itemTypeData, true, XmlSchemaForm.None));\r
- return map;\r
- }\r
- \r
- XmlSchemaAttribute FindArrayAttribute (XmlSchemaObjectCollection atts)\r
- {\r
- foreach (object ob in atts)\r
- {\r
- XmlSchemaAttribute att = ob as XmlSchemaAttribute;\r
- if (att != null && att.RefName == arrayTypeRefName) return att;\r
- \r
- XmlSchemaAttributeGroupRef gref = ob as XmlSchemaAttributeGroupRef;\r
- if (gref != null)\r
- {\r
- XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);\r
- att = FindArrayAttribute (grp.Attributes);\r
- if (att != null) return att;\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- void ImportParticleComplexContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool isMixed)\r
- {\r
- ImportParticleContent (typeQName, cmap, particle, classIds, false, ref isMixed);\r
- if (isMixed) AddTextMember (typeQName, cmap, classIds);\r
- }\r
- \r
- void AddTextMember (XmlQualifiedName typeQName, ClassMap cmap, CodeIdentifiers classIds)\r
- {\r
- if (cmap.XmlTextCollector == null)\r
- {\r
- XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();\r
- member.Name = classIds.AddUnique ("Text", member);\r
- member.TypeData = TypeTranslator.GetTypeData (typeof(string[]));\r
- member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData.ListItemTypeData));\r
- member.IsXmlTextCollector = true;\r
- member.ListMap = new ListMap ();\r
- member.ListMap.ItemInfo = member.ElementInfo;\r
- cmap.AddMember (member);\r
- }\r
- }\r
- \r
- void ImportParticleContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)\r
- {\r
- if (particle == null) return;\r
- \r
- if (particle is XmlSchemaGroupRef)\r
- particle = GetRefGroupParticle ((XmlSchemaGroupRef)particle);\r
-\r
- if (particle.MaxOccurs > 1) multiValue = true;\r
- \r
- if (particle is XmlSchemaSequence) {\r
- ImportSequenceContent (typeQName, cmap, ((XmlSchemaSequence)particle).Items, classIds, multiValue, ref isMixed);\r
- }\r
- else if (particle is XmlSchemaChoice) {\r
- if (((XmlSchemaChoice)particle).Items.Count == 1)\r
- ImportSequenceContent (typeQName, cmap, ((XmlSchemaChoice)particle).Items, classIds, multiValue, ref isMixed);\r
- else\r
- ImportChoiceContent (typeQName, cmap, (XmlSchemaChoice)particle, classIds, multiValue);\r
- }\r
- else if (particle is XmlSchemaAll) {\r
- ImportSequenceContent (typeQName, cmap, ((XmlSchemaAll)particle).Items, classIds, multiValue, ref isMixed);\r
- }\r
- }\r
-\r
- void ImportSequenceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection items, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)\r
- {\r
- foreach (XmlSchemaObject item in items)\r
- {\r
- if (item is XmlSchemaElement)\r
- {\r
- string ns;\r
- XmlSchemaElement elem = (XmlSchemaElement) item;\r
- XmlTypeMapping emap;\r
- TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);\r
- XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);\r
-\r
- if (elem.MaxOccurs == 1 && !multiValue)\r
- {\r
- XmlTypeMapMemberElement member = null;\r
- if (typeData.SchemaType != SchemaTypes.Array)\r
- {\r
- member = new XmlTypeMapMemberElement ();\r
- if (refElem.DefaultValue != null) member.DefaultValue = ImportDefaultValue (typeData, refElem.DefaultValue);\r
- }\r
- else if (GetTypeMapping (typeData).IsSimpleType)\r
- {\r
- // It is a simple list (space separated list).\r
- // Since this is not supported, map as a single item value\r
- member = new XmlTypeMapMemberElement ();\r
-#if NET_2_0\r
- // In MS.NET those types are mapped to a string\r
- typeData = TypeTranslator.GetTypeData(typeof(string));\r
-#else\r
- typeData = typeData.ListItemTypeData;\r
-#endif\r
- }\r
- else\r
- member = new XmlTypeMapMemberList ();\r
-\r
- if (elem.MinOccurs == 0 && typeData.IsValueType)\r
- member.IsOptionalValueType = true;\r
-\r
- member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);\r
- member.Documentation = GetDocumentation (elem);\r
- member.TypeData = typeData;\r
- member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));\r
- cmap.AddMember (member);\r
- }\r
- else\r
- {\r
- XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();\r
- member.ListMap = new ListMap ();\r
- member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);\r
- member.Documentation = GetDocumentation (elem);\r
- member.TypeData = typeData.ListTypeData;\r
- member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));\r
- member.ListMap.ItemInfo = member.ElementInfo;\r
- cmap.AddMember (member);\r
- }\r
- }\r
- else if (item is XmlSchemaAny)\r
- {\r
- XmlSchemaAny elem = (XmlSchemaAny) item;\r
- XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement ();\r
- member.Name = classIds.AddUnique ("Any", member);\r
- member.Documentation = GetDocumentation (elem);\r
- \r
- Type ctype;\r
- if (elem.MaxOccurs != 1 || multiValue)\r
- ctype = isMixed ? typeof(XmlNode[]) : typeof(XmlElement[]);\r
- else\r
- ctype = isMixed ? typeof(XmlNode) : typeof(XmlElement);\r
-\r
- member.TypeData = TypeTranslator.GetTypeData (ctype);\r
- XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, member.TypeData);\r
- einfo.IsUnnamedAnyElement = true;\r
- member.ElementInfo.Add (einfo);\r
-\r
- if (isMixed)\r
- {\r
- einfo = CreateTextElementInfo (typeQName.Namespace, member, member.TypeData);\r
- member.ElementInfo.Add (einfo);\r
- member.IsXmlTextCollector = true;\r
- isMixed = false; //Allow only one XmlTextAttribute\r
- }\r
- \r
- cmap.AddMember (member);\r
- }\r
- else if (item is XmlSchemaParticle) {\r
- ImportParticleContent (typeQName, cmap, (XmlSchemaParticle)item, classIds, multiValue, ref isMixed);\r
- }\r
- }\r
- }\r
- \r
- object ImportDefaultValue (TypeData typeData, string value)\r
- {\r
- if (typeData.SchemaType == SchemaTypes.Enum) {\r
- XmlTypeMapping map = GetTypeMapping (typeData);\r
- EnumMap emap = (EnumMap) map.ObjectMap;\r
- string res = emap.GetEnumName (map.TypeFullName, value);\r
- if (res == null) throw new InvalidOperationException ("'" + value + "' is not a valid enumeration value");\r
- return res;\r
- } else\r
- return XmlCustomFormatter.FromXmlString (typeData, value);\r
- }\r
- \r
- void ImportChoiceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaChoice choice, CodeIdentifiers classIds, bool multiValue)\r
- {\r
- XmlTypeMapElementInfoList choices = new XmlTypeMapElementInfoList ();\r
- multiValue = ImportChoices (typeQName, null, choices, choice.Items) || multiValue;\r
- if (choices.Count == 0) return;\r
-\r
- if (choice.MaxOccurs > 1) multiValue = true;\r
-\r
- XmlTypeMapMemberElement member;\r
- if (multiValue)\r
- {\r
- member = new XmlTypeMapMemberFlatList ();\r
- member.Name = classIds.AddUnique ("Items", member);\r
- ListMap listMap = new ListMap ();\r
- listMap.ItemInfo = choices;\r
- ((XmlTypeMapMemberFlatList)member).ListMap = listMap;\r
- }\r
- else\r
- {\r
- member = new XmlTypeMapMemberElement ();\r
- member.Name = classIds.AddUnique ("Item", member);\r
- }\r
- \r
- // If all choices have the same type, use that type for the member.\r
- // If not use System.Object.\r
- // If there are at least two choices with the same type, use a choice\r
- // identifier attribute\r
-\r
- TypeData typeData = null;\r
- bool twoEqual = false;\r
- bool allEqual = true;\r
- Hashtable types = new Hashtable ();\r
-\r
- for (int n = choices.Count - 1; n >= 0; n--)\r
- {\r
- XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) choices [n];\r
- \r
- // In some complex schemas, we may end up with several options\r
- // with the same name. It is better to ignore the extra options\r
- // than to crash. It's the best we can do, and btw it works\r
- // better than in MS.NET.\r
- \r
- if (cmap.GetElement (einfo.ElementName, einfo.Namespace) != null ||\r
- choices.IndexOfElement (einfo.ElementName, einfo.Namespace) != n)\r
- {\r
- choices.RemoveAt (n);\r
- continue;\r
- }\r
- \r
- if (types.ContainsKey (einfo.TypeData)) twoEqual = true;\r
- else types.Add (einfo.TypeData, einfo);\r
-\r
- TypeData choiceType = einfo.TypeData;\r
- if (choiceType.SchemaType == SchemaTypes.Class)\r
- {\r
- // When comparing class types, use the most generic class in the\r
- // inheritance hierarchy\r
-\r
- XmlTypeMapping choiceMap = GetTypeMapping (choiceType);\r
- BuildPendingMap (choiceMap);\r
- while (choiceMap.BaseMap != null) {\r
- choiceMap = choiceMap.BaseMap;\r
- BuildPendingMap (choiceMap);\r
- choiceType = choiceMap.TypeData;\r
- }\r
- }\r
- \r
- if (typeData == null) typeData = choiceType;\r
- else if (typeData != choiceType) allEqual = false;\r
- }\r
-\r
- if (!allEqual)\r
- typeData = TypeTranslator.GetTypeData (typeof(object));\r
-\r
- if (twoEqual)\r
- {\r
- // Create the choice member\r
- XmlTypeMapMemberElement choiceMember = new XmlTypeMapMemberElement ();\r
- choiceMember.Ignore = true;\r
- choiceMember.Name = classIds.AddUnique (member.Name + "ElementName", choiceMember);\r
- member.ChoiceMember = choiceMember.Name;\r
-\r
- // Create the choice enum\r
- XmlTypeMapping enumMap = CreateTypeMapping (new XmlQualifiedName (member.Name + "ChoiceType", typeQName.Namespace), SchemaTypes.Enum, null);\r
- enumMap.IncludeInSchema = false;\r
-\r
- CodeIdentifiers codeIdents = new CodeIdentifiers ();\r
- EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [choices.Count];\r
- for (int n=0; n<choices.Count; n++)\r
- {\r
- XmlTypeMapElementInfo it =(XmlTypeMapElementInfo) choices[n];\r
- bool extraNs = (it.Namespace != null && it.Namespace != "" && it.Namespace != typeQName.Namespace);\r
- string xmlName = extraNs ? it.Namespace + ":" + it.ElementName : it.ElementName;\r
- string enumName = codeIdents.AddUnique (CodeIdentifier.MakeValid (it.ElementName), it);\r
- members [n] = new EnumMap.EnumMapMember (xmlName, enumName);\r
- }\r
- enumMap.ObjectMap = new EnumMap (members, false);\r
-\r
- choiceMember.TypeData = multiValue ? enumMap.TypeData.ListTypeData : enumMap.TypeData;\r
- choiceMember.ElementInfo.Add (CreateElementInfo (typeQName.Namespace, choiceMember, choiceMember.Name, choiceMember.TypeData, false, XmlSchemaForm.None));\r
- cmap.AddMember (choiceMember);\r
- }\r
- \r
- if (typeData == null)\r
- return;\r
- \r
- if (multiValue)\r
- typeData = typeData.ListTypeData;\r
-\r
- member.ElementInfo = choices;\r
- member.Documentation = GetDocumentation (choice);\r
- member.TypeData = typeData;\r
- cmap.AddMember (member);\r
- }\r
-\r
- bool ImportChoices (XmlQualifiedName typeQName, XmlTypeMapMember member, XmlTypeMapElementInfoList choices, XmlSchemaObjectCollection items)\r
- {\r
- bool multiValue = false;\r
- foreach (XmlSchemaObject titem in items)\r
- {\r
- XmlSchemaObject item = titem;\r
- if (item is XmlSchemaGroupRef)\r
- item = GetRefGroupParticle ((XmlSchemaGroupRef)item);\r
-\r
- if (item is XmlSchemaElement)\r
- {\r
- string ns;\r
- XmlSchemaElement elem = (XmlSchemaElement) item;\r
- XmlTypeMapping emap;\r
- TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);\r
- XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);\r
- choices.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));\r
- if (elem.MaxOccurs > 1) multiValue = true;\r
- }\r
- else if (item is XmlSchemaAny)\r
- {\r
- XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));\r
- einfo.IsUnnamedAnyElement = true;\r
- choices.Add (einfo);\r
- }\r
- else if (item is XmlSchemaChoice) {\r
- multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaChoice)item).Items) || multiValue;\r
- }\r
- else if (item is XmlSchemaSequence) {\r
- multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaSequence)item).Items) || multiValue;\r
- }\r
- }\r
- return multiValue;\r
- }\r
-\r
- void ImportSimpleContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaSimpleContent content, CodeIdentifiers classIds, bool isMixed)\r
- {\r
- XmlSchemaSimpleContentExtension ext = content.Content as XmlSchemaSimpleContentExtension;\r
- ClassMap cmap = (ClassMap)map.ObjectMap;\r
- XmlQualifiedName qname = GetContentBaseType (content.Content);\r
- TypeData simpleType = null;\r
- \r
- if (!IsPrimitiveTypeNamespace (qname.Namespace))\r
- {\r
- // Add base map members to this map\r
- \r
- XmlTypeMapping baseMap = ImportType (qname, null, true);\r
- BuildPendingMap (baseMap);\r
- \r
- if (baseMap.IsSimpleType) {\r
- simpleType = baseMap.TypeData;\r
- } else {\r
- ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;\r
- \r
- foreach (XmlTypeMapMember member in baseClassMap.AllMembers)\r
- cmap.AddMember (member);\r
- \r
- map.BaseMap = baseMap;\r
- baseMap.DerivedTypes.Add (map);\r
- }\r
- }\r
- else\r
- simpleType = FindBuiltInType (qname);\r
- \r
- if (simpleType != null) {\r
- XmlTypeMapMemberElement member = new XmlTypeMapMemberElement ();\r
- member.Name = classIds.AddUnique("Value", member);\r
- member.TypeData = simpleType;\r
- member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData));\r
- member.IsXmlTextCollector = true;\r
- cmap.AddMember (member);\r
- }\r
- \r
- if (ext != null)\r
- ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);\r
- }\r
-\r
- TypeData FindBuiltInType (XmlQualifiedName qname)\r
- {\r
- XmlSchemaComplexType ct = (XmlSchemaComplexType) schemas.Find (qname, typeof(XmlSchemaComplexType));\r
- if (ct != null)\r
- {\r
- XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;\r
- if (sc == null) throw new InvalidOperationException ("Invalid schema");\r
- return FindBuiltInType (GetContentBaseType (sc.Content));\r
- }\r
- \r
- XmlSchemaSimpleType st = (XmlSchemaSimpleType) schemas.Find (qname, typeof(XmlSchemaSimpleType));\r
- if (st != null)\r
- return FindBuiltInType (qname, st);\r
-\r
- if (IsPrimitiveTypeNamespace (qname.Namespace))\r
- return TypeTranslator.GetPrimitiveTypeData (qname.Name);\r
-\r
- throw new InvalidOperationException ("Definition of type '" + qname + "' not found");\r
- }\r
-\r
- TypeData FindBuiltInType (XmlQualifiedName qname, XmlSchemaSimpleType st)\r
- {\r
- if (CanBeEnum (st) && qname != null)\r
- return ImportType (qname, null, true).TypeData;\r
-\r
- if (st.Content is XmlSchemaSimpleTypeRestriction) {\r
- XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction) st.Content;\r
- XmlQualifiedName bn = GetContentBaseType (rest);\r
- if (bn == XmlQualifiedName.Empty && rest.BaseType != null)\r
- return FindBuiltInType (qname, rest.BaseType);\r
- else\r
- return FindBuiltInType (bn);\r
- }\r
- else if (st.Content is XmlSchemaSimpleTypeList) {\r
- return FindBuiltInType (GetContentBaseType (st.Content)).ListTypeData;\r
- }\r
- else if (st.Content is XmlSchemaSimpleTypeUnion) {\r
- // MS.NET always import simple unions as string\r
- return FindBuiltInType (new XmlQualifiedName ("string", XmlSchema.Namespace));\r
- }\r
- else\r
- return null;\r
- }\r
-\r
- XmlQualifiedName GetContentBaseType (XmlSchemaObject ob)\r
- {\r
- if (ob is XmlSchemaSimpleContentExtension)\r
- return ((XmlSchemaSimpleContentExtension)ob).BaseTypeName;\r
- else if (ob is XmlSchemaSimpleContentRestriction)\r
- return ((XmlSchemaSimpleContentRestriction)ob).BaseTypeName;\r
- else if (ob is XmlSchemaSimpleTypeRestriction)\r
- return ((XmlSchemaSimpleTypeRestriction)ob).BaseTypeName;\r
- else if (ob is XmlSchemaSimpleTypeList)\r
- return ((XmlSchemaSimpleTypeList)ob).ItemTypeName;\r
- else\r
- return null;\r
- }\r
-\r
- void ImportComplexContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaComplexContent content, CodeIdentifiers classIds, bool isMixed)\r
- {\r
- ClassMap cmap = (ClassMap)map.ObjectMap;\r
- XmlQualifiedName qname;\r
-\r
- XmlSchemaComplexContentExtension ext = content.Content as XmlSchemaComplexContentExtension;\r
- if (ext != null) qname = ext.BaseTypeName;\r
- else qname = ((XmlSchemaComplexContentRestriction)content.Content).BaseTypeName;\r
- \r
- if (qname == typeQName)\r
- throw new InvalidOperationException ("Cannot import schema for type '" + typeQName.Name + "' from namespace '" + typeQName.Namespace + "'. Redefine not supported");\r
- \r
- // Add base map members to this map\r
-\r
- XmlTypeMapping baseMap = ImportClass (qname);\r
- BuildPendingMap (baseMap);\r
- ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;\r
-\r
- foreach (XmlTypeMapMember member in baseClassMap.AllMembers)\r
- cmap.AddMember (member);\r
-\r
- if (baseClassMap.XmlTextCollector != null) isMixed = false;\r
- else if (content.IsMixed) isMixed = true;\r
-\r
- map.BaseMap = baseMap;\r
- baseMap.DerivedTypes.Add (map);\r
-\r
- if (ext != null) {\r
- // Add the members of this map\r
- ImportParticleComplexContent (typeQName, cmap, ext.Particle, classIds, isMixed);\r
- ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);\r
- }\r
- else {\r
- if (isMixed) ImportParticleComplexContent (typeQName, cmap, null, classIds, true);\r
- }\r
- }\r
- \r
- void ImportExtensionTypes (XmlQualifiedName qname)\r
- {\r
- foreach (XmlSchema schema in schemas) {\r
- foreach (XmlSchemaObject sob in schema.Items) \r
- {\r
- XmlSchemaComplexType sct = sob as XmlSchemaComplexType;\r
- if (sct != null && sct.ContentModel is XmlSchemaComplexContent) {\r
- XmlQualifiedName exqname;\r
- XmlSchemaComplexContentExtension ext = sct.ContentModel.Content as XmlSchemaComplexContentExtension;\r
- if (ext != null) exqname = ext.BaseTypeName;\r
- else exqname = ((XmlSchemaComplexContentRestriction)sct.ContentModel.Content).BaseTypeName;\r
- if (exqname == qname)\r
- ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);\r
- }\r
- }\r
- } \r
- }\r
-\r
- XmlTypeMapping ImportClassSimpleType (XmlQualifiedName typeQName, XmlSchemaSimpleType stype, XmlQualifiedName root)\r
- {\r
- if (CanBeEnum (stype))\r
- {\r
- // Create an enum map\r
-\r
- CodeIdentifiers codeIdents = new CodeIdentifiers ();\r
- XmlTypeMapping enumMap = CreateTypeMapping (typeQName, SchemaTypes.Enum, null);\r
- enumMap.Documentation = GetDocumentation (stype);\r
- \r
- bool isFlags = false;\r
- if (stype.Content is XmlSchemaSimpleTypeList) {\r
- stype = ((XmlSchemaSimpleTypeList)stype.Content).ItemType;\r
- isFlags = true;\r
- }\r
- XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;\r
-\r
- codeIdents.AddReserved (enumMap.TypeData.TypeName);\r
-\r
- EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [rest.Facets.Count];\r
- for (int n=0; n<rest.Facets.Count; n++)\r
- {\r
- XmlSchemaEnumerationFacet enu = (XmlSchemaEnumerationFacet) rest.Facets[n];\r
- string enumName = codeIdents.AddUnique(CodeIdentifier.MakeValid (enu.Value), enu);\r
- members [n] = new EnumMap.EnumMapMember (enu.Value, enumName);\r
- members [n].Documentation = GetDocumentation (enu);\r
- }\r
- enumMap.ObjectMap = new EnumMap (members, isFlags);\r
- enumMap.IsSimpleType = true;\r
- return enumMap;\r
- }\r
-\r
- if (stype.Content is XmlSchemaSimpleTypeList)\r
- {\r
- XmlSchemaSimpleTypeList slist = (XmlSchemaSimpleTypeList)stype.Content;\r
- TypeData arrayTypeData = FindBuiltInType (slist.ItemTypeName, stype);\r
-\r
- ListMap listMap = new ListMap ();\r
-\r
- listMap.ItemInfo = new XmlTypeMapElementInfoList ();\r
- listMap.ItemInfo.Add (CreateElementInfo (typeQName.Namespace, null, "Item", arrayTypeData.ListItemTypeData, false, XmlSchemaForm.None));\r
-\r
- XmlTypeMapping map = CreateArrayTypeMapping (typeQName, arrayTypeData);\r
- map.ObjectMap = listMap;\r
- map.IsSimpleType = true;\r
- return map;\r
- }\r
-\r
- // It is an extension of a primitive or known type\r
- \r
- TypeData typeData = FindBuiltInType (typeQName, stype);\r
- XmlTypeMapping rmap = GetTypeMapping (typeData);\r
- \r
- // The resulting map must be a simple type. It needs to be explicitely set for arrays\r
- rmap.IsSimpleType = true;\r
- return rmap;\r
- }\r
-\r
- bool CanBeEnum (XmlSchemaSimpleType stype)\r
- {\r
- if (stype.Content is XmlSchemaSimpleTypeRestriction)\r
- {\r
- XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;\r
- if (rest.Facets.Count == 0) return false;\r
- foreach (object ob in rest.Facets)\r
- if (!(ob is XmlSchemaEnumerationFacet)) return false;\r
- return true;\r
- }\r
- else if (stype.Content is XmlSchemaSimpleTypeList)\r
- {\r
- XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList) stype.Content;\r
- return (list.ItemType != null && CanBeEnum (list.ItemType));\r
- }\r
- return false;\r
- }\r
-\r
- bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaComplexType stype)\r
- {\r
- if (encodedFormat)\r
- {\r
- XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;\r
- if (content == null) return false;\r
- XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;\r
- if (rest == null) return false;\r
- return rest.BaseTypeName == arrayType;\r
- }\r
- else\r
- {\r
- if (stype.Attributes.Count > 0 || stype.AnyAttribute != null) return false;\r
- else return !stype.IsMixed && CanBeArray (typeQName, stype.Particle, false);\r
- }\r
- }\r
-\r
- bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaParticle particle, bool multiValue)\r
- {\r
- // To be an array, there can't be a direct child of type typeQName\r
-\r
- if (particle == null) return false;\r
-\r
- multiValue = multiValue || particle.MaxOccurs > 1;\r
-\r
- if (particle is XmlSchemaGroupRef)\r
- return CanBeArray (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), multiValue);\r
-\r
- if (particle is XmlSchemaElement)\r
- {\r
- XmlSchemaElement elem = (XmlSchemaElement)particle;\r
- if (!elem.RefName.IsEmpty)\r
- return CanBeArray (typeQName, FindRefElement (elem), multiValue);\r
- else\r
- return multiValue && !typeQName.Equals (((XmlSchemaElement)particle).SchemaTypeName);\r
- }\r
-\r
- if (particle is XmlSchemaAny)\r
- return multiValue;\r
-\r
- if (particle is XmlSchemaSequence)\r
- {\r
- XmlSchemaSequence seq = particle as XmlSchemaSequence;\r
- if (seq.Items.Count != 1) return false;\r
- return CanBeArray (typeQName, (XmlSchemaParticle)seq.Items[0], multiValue);\r
- }\r
-\r
- if (particle is XmlSchemaChoice)\r
- {\r
- // Can be array if all choices have different types\r
- ArrayList types = new ArrayList ();\r
- if(!CheckChoiceType (typeQName, particle, types, ref multiValue)) return false;\r
- return multiValue;\r
- }\r
-\r
- return false;\r
- }\r
-\r
- bool CheckChoiceType (XmlQualifiedName typeQName, XmlSchemaParticle particle, ArrayList types, ref bool multiValue)\r
- {\r
- XmlQualifiedName type = null;\r
-\r
- multiValue = multiValue || particle.MaxOccurs > 1;\r
-\r
- if (particle is XmlSchemaGroupRef)\r
- return CheckChoiceType (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), types, ref multiValue);\r
-\r
- if (particle is XmlSchemaElement) {\r
- string ns;\r
- XmlSchemaElement elem = (XmlSchemaElement)particle;\r
- XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);\r
- if (refElem.SchemaType != null) return true;\r
- type = refElem.SchemaTypeName;\r
- }\r
- else if (particle is XmlSchemaAny) {\r
- type = anyType;\r
- }\r
- else if (particle is XmlSchemaSequence)\r
- {\r
- XmlSchemaSequence seq = particle as XmlSchemaSequence;\r
- foreach (XmlSchemaParticle par in seq.Items)\r
- if (!CheckChoiceType (typeQName, par, types, ref multiValue)) return false;\r
- return true;\r
- }\r
- else if (particle is XmlSchemaChoice)\r
- {\r
- foreach (XmlSchemaParticle choice in ((XmlSchemaChoice)particle).Items)\r
- if (!CheckChoiceType (typeQName, choice, types, ref multiValue)) return false;\r
- return true;\r
- }\r
-\r
- if (typeQName.Equals (type)) return false;\r
-\r
- // For primitive types, compare using CLR types, since several\r
- // xml types can be mapped to a single CLR type\r
-\r
- string t;\r
- if (IsPrimitiveTypeNamespace (type.Namespace))\r
- t = TypeTranslator.GetPrimitiveTypeData (type.Name).FullTypeName + ":" + type.Namespace;\r
-\r
- else\r
- t = type.Name + ":" + type.Namespace;\r
-\r
- if (types.Contains (t)) return false;\r
- types.Add (t);\r
- return true;\r
- }\r
- \r
- bool CanBeAnyElement (XmlSchemaComplexType stype)\r
- {\r
- XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;\r
- return (seq != null) && (seq.Items.Count == 1) && (seq.Items[0] is XmlSchemaAny);\r
- }\r
- \r
- Type GetAnyElementType (XmlSchemaComplexType stype)\r
- {\r
- XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;\r
- \r
- if ((seq == null) || (seq.Items.Count != 1) || !(seq.Items[0] is XmlSchemaAny))\r
- return null;\r
- \r
- if (encodedFormat) \r
- return typeof(object);\r
-\r
- XmlSchemaAny any = seq.Items[0] as XmlSchemaAny;\r
- if (any.MaxOccurs == 1)\r
- {\r
- if (stype.IsMixed)\r
- return typeof(XmlNode);\r
- else\r
- return typeof(XmlElement);\r
- }\r
- else\r
- {\r
- if (stype.IsMixed)\r
- return typeof(XmlNode[]);\r
- else\r
- return typeof(XmlElement[]);\r
- }\r
- }\r
-\r
- bool CanBeIXmlSerializable (XmlSchemaComplexType stype)\r
- {\r
- XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;\r
- if (seq == null) return false;\r
- if (seq.Items.Count != 2) return false;\r
- XmlSchemaElement elem = seq.Items[0] as XmlSchemaElement;\r
- if (elem == null) return false;\r
- if (elem.RefName != new XmlQualifiedName ("schema",XmlSchema.Namespace)) return false;\r
- return (seq.Items[1] is XmlSchemaAny);\r
- }\r
- \r
- XmlTypeMapping ImportXmlSerializableMapping (string ns)\r
- {\r
- XmlQualifiedName qname = new XmlQualifiedName ("System.Data.DataSet",ns);\r
- XmlTypeMapping map = mappedTypes [qname] as XmlTypeMapping;\r
- if (map != null) return map;\r
- \r
- TypeData typeData = new TypeData ("System.Data.DataSet", "System.Data.DataSet", "System.Data.DataSet", SchemaTypes.XmlSerializable, null);\r
- map = new XmlTypeMapping ("System.Data.DataSet", "", typeData, "System.Data.DataSet", ns);\r
- map.IncludeInSchema = true;\r
- mappedTypes [qname] = map;\r
- dataMappedTypes [typeData] = map;\r
- return map;\r
- }\r
- \r
- XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form)\r
- {\r
- if (typeData.IsComplexType)\r
- return CreateElementInfo (ns, member, name, typeData, isNillable, form, GetTypeMapping (typeData));\r
- else\r
- return CreateElementInfo (ns, member, name, typeData, isNillable, form, null);\r
- }\r
- \r
- XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form, XmlTypeMapping emap)\r
- {\r
- XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);\r
- einfo.ElementName = name;\r
- einfo.Namespace = ns;\r
- einfo.IsNullable = isNillable;\r
- einfo.Form = form;\r
- if (typeData.IsComplexType)\r
- einfo.MappedType = emap;\r
- return einfo;\r
- }\r
-\r
- XmlTypeMapElementInfo CreateTextElementInfo (string ns, XmlTypeMapMember member, TypeData typeData)\r
- {\r
- XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);\r
- einfo.IsTextElement = true;\r
- einfo.WrappedElement = false;\r
- if (typeData.IsComplexType)\r
- einfo.MappedType = GetTypeMapping (typeData);\r
- return einfo;\r
- }\r
-\r
- XmlTypeMapping CreateTypeMapping (XmlQualifiedName typeQName, SchemaTypes schemaType, XmlQualifiedName root)\r
- {\r
- string typeName = CodeIdentifier.MakeValid (typeQName.Name);\r
- typeName = typeIdentifiers.AddUnique (typeName, null);\r
-\r
- TypeData typeData = new TypeData (typeName, typeName, typeName, schemaType, null);\r
-\r
- string rootElem;\r
- string rootNs;\r
- if (root != null) {\r
- rootElem = root.Name;\r
- rootNs = root.Namespace;\r
- }\r
- else {\r
- rootElem = typeQName.Name;\r
- rootNs = "";\r
- }\r
- \r
- XmlTypeMapping map = new XmlTypeMapping (rootElem, rootNs, typeData, typeQName.Name, typeQName.Namespace);\r
- map.IncludeInSchema = true;\r
- mappedTypes [typeQName] = map;\r
- dataMappedTypes [typeData] = map;\r
-\r
- return map;\r
- }\r
-\r
- XmlTypeMapping CreateArrayTypeMapping (XmlQualifiedName typeQName, TypeData arrayTypeData)\r
- {\r
- XmlTypeMapping map;\r
- if (encodedFormat) map = new XmlTypeMapping ("Array", XmlSerializer.EncodingNamespace, arrayTypeData, "Array", XmlSerializer.EncodingNamespace);\r
- else map = new XmlTypeMapping (arrayTypeData.XmlType, typeQName.Namespace, arrayTypeData, arrayTypeData.XmlType, typeQName.Namespace);\r
- \r
- map.IncludeInSchema = true;\r
- mappedTypes [typeQName] = map;\r
- dataMappedTypes [arrayTypeData] = map;\r
-\r
- return map;\r
- }\r
-\r
- XmlSchemaElement GetRefElement (XmlQualifiedName typeQName, XmlSchemaElement elem, out string ns)\r
- {\r
-\r
- if (!elem.RefName.IsEmpty)\r
- {\r
- ns = elem.RefName.Namespace;\r
- return FindRefElement (elem);\r
- }\r
- else\r
- {\r
- ns = typeQName.Namespace;\r
- return elem;\r
- }\r
- }\r
-\r
- XmlSchemaAttribute GetRefAttribute (XmlQualifiedName typeQName, XmlSchemaAttribute attr, out string ns)\r
- {\r
- if (!attr.RefName.IsEmpty)\r
- {\r
- ns = attr.RefName.Namespace;\r
- XmlSchemaAttribute at = FindRefAttribute (attr.RefName);\r
- if (at == null) throw new InvalidOperationException ("The attribute " + attr.RefName + " is missing");\r
- return at;\r
- }\r
- else\r
- {\r
- ns = typeQName.Namespace;\r
- return attr;\r
- }\r
- }\r
-\r
- TypeData GetElementTypeData (XmlQualifiedName typeQName, XmlSchemaElement elem, XmlQualifiedName root, out XmlTypeMapping map)\r
- {\r
- bool sharedAnnType = false;\r
- map = null;\r
- \r
- if (!elem.RefName.IsEmpty) {\r
- XmlSchemaElement refElem = FindRefElement (elem);\r
- if (refElem == null) throw new InvalidOperationException ("Global element not found: " + elem.RefName);\r
- root = elem.RefName;\r
- elem = refElem;\r
- sharedAnnType = true;\r
- }\r
-\r
- TypeData td;\r
- if (!elem.SchemaTypeName.IsEmpty) {\r
- td = GetTypeData (elem.SchemaTypeName, root);\r
- map = GetRegisteredTypeMapping (elem.SchemaTypeName);\r
- }\r
- else if (elem.SchemaType == null) \r
- td = TypeTranslator.GetTypeData (typeof(object));\r
- else \r
- td = GetTypeData (elem.SchemaType, typeQName, elem.Name, sharedAnnType, root);\r
- \r
- if (map == null && td.IsComplexType)\r
- map = GetTypeMapping (td);\r
- \r
- return td;\r
- }\r
-\r
- TypeData GetAttributeTypeData (XmlQualifiedName typeQName, XmlSchemaAttribute attr)\r
- {\r
- bool sharedAnnType = false;\r
-\r
- if (!attr.RefName.IsEmpty) {\r
- XmlSchemaAttribute refAtt = FindRefAttribute (attr.RefName);\r
- if (refAtt == null) throw new InvalidOperationException ("Global attribute not found: " + attr.RefName);\r
- attr = refAtt;\r
- sharedAnnType = true;\r
- }\r
- \r
- if (!attr.SchemaTypeName.IsEmpty) return GetTypeData (attr.SchemaTypeName, null);\r
- if (attr.SchemaType == null) return TypeTranslator.GetTypeData (typeof(string));\r
- else return GetTypeData (attr.SchemaType, typeQName, attr.Name, sharedAnnType, null);\r
- }\r
-\r
- TypeData GetTypeData (XmlQualifiedName typeQName, XmlQualifiedName root)\r
- {\r
- if (IsPrimitiveTypeNamespace (typeQName.Namespace)) {\r
- XmlTypeMapping map = ImportType (typeQName, root, false);\r
- if (map != null) return map.TypeData;\r
- else return TypeTranslator.GetPrimitiveTypeData (typeQName.Name);\r
- }\r
- \r
- if (encodedFormat && typeQName.Namespace == "")\r
- return TypeTranslator.GetPrimitiveTypeData (typeQName.Name);\r
-\r
- return ImportType (typeQName, root, true).TypeData;\r
- }\r
-\r
- TypeData GetTypeData (XmlSchemaType stype, XmlQualifiedName typeQNname, string propertyName, bool sharedAnnType, XmlQualifiedName root)\r
- {\r
- string baseName;\r
-\r
- if (sharedAnnType)\r
- {\r
- // Anonymous types defined in root elements or attributes can be shared among all elements that\r
- // reference this root element or attribute\r
- TypeData std = sharedAnonymousTypes [stype] as TypeData;\r
- if (std != null) return std;\r
- baseName = propertyName;\r
- }\r
- else\r
- baseName = typeQNname.Name + typeIdentifiers.MakeRightCase (propertyName);\r
-\r
- baseName = elemIdentifiers.AddUnique (baseName, stype);\r
- \r
- XmlQualifiedName newName;\r
- newName = new XmlQualifiedName (baseName, typeQNname.Namespace);\r
-\r
- XmlTypeMapping map = ImportType (newName, stype, root);\r
- if (sharedAnnType) sharedAnonymousTypes [stype] = map.TypeData;\r
-\r
- return map.TypeData;\r
- }\r
-\r
- XmlTypeMapping GetTypeMapping (TypeData typeData)\r
- {\r
- if (typeData.Type == typeof(object) && !anyTypeImported)\r
- ImportAllObjectTypes ();\r
- \r
- XmlTypeMapping map = (XmlTypeMapping) dataMappedTypes [typeData];\r
- if (map != null) return map;\r
- \r
- if (typeData.IsListType)\r
- {\r
- // Create an array map for the type\r
-\r
- XmlTypeMapping itemMap = GetTypeMapping (typeData.ListItemTypeData);\r
- \r
- map = new XmlTypeMapping (typeData.XmlType, itemMap.Namespace, typeData, typeData.XmlType, itemMap.Namespace);\r
- map.IncludeInSchema = true;\r
-\r
- ListMap listMap = new ListMap ();\r
- listMap.ItemInfo = new XmlTypeMapElementInfoList();\r
- listMap.ItemInfo.Add (CreateElementInfo (itemMap.Namespace, null, typeData.ListItemTypeData.XmlType, typeData.ListItemTypeData, false, XmlSchemaForm.None));\r
- map.ObjectMap = listMap;\r
- \r
- mappedTypes [new XmlQualifiedName(map.ElementName, map.Namespace)] = map;\r
- dataMappedTypes [typeData] = map;\r
- return map;\r
- }\r
- else if (typeData.SchemaType == SchemaTypes.Primitive || typeData.Type == typeof(object) || typeof(XmlNode).IsAssignableFrom(typeData.Type))\r
- {\r
- return CreateSystemMap (typeData);\r
- }\r
- \r
- throw new InvalidOperationException ("Map for type " + typeData.TypeName + " not found");\r
- }\r
- \r
- void AddObjectDerivedMap (XmlTypeMapping map)\r
- {\r
- TypeData typeData = TypeTranslator.GetTypeData (typeof(object));\r
- XmlTypeMapping omap = (XmlTypeMapping) dataMappedTypes [typeData];\r
- if (omap == null)\r
- omap = CreateSystemMap (typeData);\r
- omap.DerivedTypes.Add (map);\r
- }\r
- \r
- XmlTypeMapping CreateSystemMap (TypeData typeData)\r
- {\r
- XmlTypeMapping map = new XmlTypeMapping (typeData.XmlType, XmlSchema.Namespace, typeData, typeData.XmlType, XmlSchema.Namespace);\r
- map.IncludeInSchema = false;\r
- map.ObjectMap = new ClassMap ();\r
- dataMappedTypes [typeData] = map;\r
- return map;\r
- }\r
- \r
- void ImportAllObjectTypes ()\r
- {\r
- // All complex types are subtypes of anyType, so all of them \r
- // must also be imported\r
- \r
- anyTypeImported = true;\r
- foreach (XmlSchema schema in schemas) {\r
- foreach (XmlSchemaObject sob in schema.Items) \r
- {\r
- XmlSchemaComplexType sct = sob as XmlSchemaComplexType;\r
- if (sct != null)\r
- ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);\r
- }\r
- } \r
- }\r
- \r
-\r
- XmlTypeMapping GetRegisteredTypeMapping (XmlQualifiedName typeQName)\r
- {\r
- return (XmlTypeMapping) mappedTypes [typeQName];\r
- }\r
-\r
- XmlSchemaParticle GetRefGroupParticle (XmlSchemaGroupRef refGroup)\r
- {\r
- XmlSchemaGroup grp = (XmlSchemaGroup) schemas.Find (refGroup.RefName, typeof (XmlSchemaGroup));\r
- return grp.Particle;\r
- }\r
-\r
- XmlSchemaElement FindRefElement (XmlSchemaElement elem)\r
- {\r
- XmlSchemaElement refelem = (XmlSchemaElement) schemas.Find (elem.RefName, typeof(XmlSchemaElement));\r
- if (refelem != null) return refelem;\r
- \r
- if (IsPrimitiveTypeNamespace (elem.RefName.Namespace))\r
- {\r
- if (anyElement != null) return anyElement;\r
- anyElement = new XmlSchemaElement ();\r
- anyElement.Name = "any";\r
- anyElement.SchemaTypeName = anyType;\r
- return anyElement;\r
- } else\r
- return null;\r
- }\r
- \r
- XmlSchemaAttribute FindRefAttribute (XmlQualifiedName refName)\r
- {\r
- if (refName.Namespace == XmlNamespace)\r
- {\r
- XmlSchemaAttribute at = new XmlSchemaAttribute ();\r
- at.Name = refName.Name;\r
- at.SchemaTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace);\r
- return at;\r
- }\r
- return (XmlSchemaAttribute) schemas.Find (refName, typeof(XmlSchemaAttribute));\r
- }\r
- \r
- XmlSchemaAttributeGroup FindRefAttributeGroup (XmlQualifiedName refName)\r
- {\r
- XmlSchemaAttributeGroup grp = (XmlSchemaAttributeGroup) schemas.Find (refName, typeof(XmlSchemaAttributeGroup));\r
- foreach (XmlSchemaObject at in grp.Attributes)\r
- {\r
- if (at is XmlSchemaAttributeGroupRef && ((XmlSchemaAttributeGroupRef)at).RefName == refName)\r
- throw new InvalidOperationException ("Cannot import attribute group '" + refName.Name + "' from namespace '" + refName.Namespace + "'. Redefine not supported");\r
- \r
- }\r
- return grp;\r
- }\r
-\r
- XmlTypeMapping ReflectType (Type type)\r
- {\r
- TypeData typeData = TypeTranslator.GetTypeData (type);\r
- return ReflectType (typeData, (string) null);\r
- }\r
-\r
- XmlTypeMapping ReflectType (TypeData typeData, string ns)\r
- {\r
- if (!encodedFormat)\r
- {\r
- if (auxXmlRefImporter == null) auxXmlRefImporter = new XmlReflectionImporter ();\r
- return auxXmlRefImporter.ImportTypeMapping (typeData, ns);\r
- }\r
- else\r
- {\r
- if (auxSoapRefImporter == null) auxSoapRefImporter = new SoapReflectionImporter ();\r
- return auxSoapRefImporter.ImportTypeMapping (typeData, ns);\r
- }\r
- }\r
-\r
-\r
- string GetDocumentation (XmlSchemaAnnotated elem)\r
- {\r
- string res = "";\r
- XmlSchemaAnnotation anot = elem.Annotation;\r
- if (anot == null || anot.Items == null) return null;\r
- \r
- foreach (object ob in anot.Items)\r
- {\r
- XmlSchemaDocumentation doc = ob as XmlSchemaDocumentation;\r
- if (doc != null && doc.Markup != null && doc.Markup.Length > 0) {\r
- if (res != string.Empty) res += "\n";\r
- foreach (XmlNode node in doc.Markup)\r
- res += node.Value;\r
- }\r
- }\r
- return res;\r
- }\r
- \r
- bool IsPrimitiveTypeNamespace (string ns)\r
- {\r
- return (ns == XmlSchema.Namespace) || (encodedFormat && ns == XmlSerializer.EncodingNamespace);\r
- }\r
-\r
- #endregion // Methods\r
- }\r
-}\r
+//
+// System.Xml.Serialization.XmlSchemaImporter
+//
+// Author:
+// Tim Coleman (tim@timcoleman.com)
+// Lluis Sanchez Gual (lluis@ximian.com)
+//
+// Copyright (C) Tim Coleman, 2002
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Xml;
+#if !TARGET_JVM
+using System.CodeDom.Compiler;
+#endif
+using System.Xml.Schema;
+using System.Collections;
+#if NET_2_0 && CONFIGURATION_DEP
+using System.Configuration;
+using System.Xml.Serialization.Configuration;
+#endif
+
+namespace System.Xml.Serialization
+{
+ public class XmlSchemaImporter
+#if NET_2_0
+ : SchemaImporter
+#endif
+ {
+ #region Fields
+
+ XmlSchemas schemas;
+ CodeIdentifiers typeIdentifiers;
+ CodeIdentifiers elemIdentifiers = new CodeIdentifiers ();
+ Hashtable mappedTypes = new Hashtable ();
+ Hashtable dataMappedTypes = new Hashtable ();
+ Queue pendingMaps = new Queue ();
+ Hashtable sharedAnonymousTypes = new Hashtable ();
+ bool encodedFormat = false;
+ XmlReflectionImporter auxXmlRefImporter;
+ SoapReflectionImporter auxSoapRefImporter;
+ bool anyTypeImported;
+
+#if NET_2_0
+ CodeGenerationOptions options;
+#endif
+
+ static readonly XmlQualifiedName anyType = new XmlQualifiedName ("anyType",XmlSchema.Namespace);
+ static readonly XmlQualifiedName arrayType = new XmlQualifiedName ("Array",XmlSerializer.EncodingNamespace);
+ static readonly XmlQualifiedName arrayTypeRefName = new XmlQualifiedName ("arrayType",XmlSerializer.EncodingNamespace);
+
+ const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
+
+ XmlSchemaElement anyElement = null;
+
+ class MapFixup
+ {
+ public XmlTypeMapping Map;
+ public XmlSchemaComplexType SchemaType;
+ public XmlQualifiedName TypeName;
+ }
+
+ #endregion
+
+ #region Constructors
+
+ public XmlSchemaImporter (XmlSchemas schemas)
+ {
+ this.schemas = schemas;
+ typeIdentifiers = new CodeIdentifiers ();
+
+ InitializeExtensions ();
+ }
+
+ public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers)
+ : this (schemas)
+ {
+ this.typeIdentifiers = typeIdentifiers;
+ }
+
+#if NET_2_0
+#if !TARGET_JVM
+ [MonoTODO]
+ public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, CodeDomProvider codeProvider, ImportContext context)
+ {
+ this.schemas = schemas;
+ this.options = options;
+ if (context != null) {
+ typeIdentifiers = context.TypeIdentifiers;
+ InitSharedData (context);
+ }
+ else
+ typeIdentifiers = new CodeIdentifiers ();
+
+ InitializeExtensions ();
+ }
+#endif
+
+ public XmlSchemaImporter (XmlSchemas schemas, CodeGenerationOptions options, ImportContext context)
+ {
+ this.schemas = schemas;
+ this.options = options;
+ if (context != null) {
+ typeIdentifiers = context.TypeIdentifiers;
+ InitSharedData (context);
+ }
+ else
+ typeIdentifiers = new CodeIdentifiers ();
+
+ InitializeExtensions ();
+ }
+
+
+ public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers, CodeGenerationOptions options)
+ {
+ this.typeIdentifiers = typeIdentifiers;
+ this.schemas = schemas;
+ this.options = options;
+
+ InitializeExtensions ();
+ }
+
+ void InitSharedData (ImportContext context)
+ {
+ if (context.ShareTypes) {
+ mappedTypes = context.MappedTypes;
+ dataMappedTypes = context.DataMappedTypes;
+ sharedAnonymousTypes = context.SharedAnonymousTypes;
+ }
+ }
+#endif
+
+ internal bool UseEncodedFormat
+ {
+ get { return encodedFormat; }
+ set { encodedFormat = value; }
+ }
+
+ #endregion // Constructors
+
+ #region Methods
+
+ void InitializeExtensions ()
+ {
+#if NET_2_0 && CONFIGURATION_DEP
+ SerializationSectionGroup root = ConfigurationManager.GetSection ("system.xml.serialization") as SerializationSectionGroup;
+ if (root == null)
+ return;
+
+ foreach (SchemaImporterExtensionElement element in
+ root.SchemaImporterExtensions.SchemaImporterExtensions)
+ Extensions.Add (element.Name, element.Type);
+#endif
+ }
+
+ public XmlMembersMapping ImportAnyType (XmlQualifiedName typeName, string elementName)
+ {
+ if (typeName == XmlQualifiedName.Empty)
+ {
+ XmlTypeMapMemberAnyElement mapMem = new XmlTypeMapMemberAnyElement ();
+ mapMem.Name = typeName.Name;
+ mapMem.TypeData = TypeTranslator.GetTypeData(typeof(XmlNode));
+ mapMem.ElementInfo.Add (CreateElementInfo (typeName.Namespace, mapMem, typeName.Name, mapMem.TypeData, true, XmlSchemaForm.None));
+
+ XmlMemberMapping[] mm = new XmlMemberMapping [1];
+ mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
+ return new XmlMembersMapping (mm);
+ }
+ else
+ {
+ XmlSchemaComplexType stype = (XmlSchemaComplexType) schemas.Find (typeName, typeof (XmlSchemaComplexType));
+ if (stype == null)
+ throw new InvalidOperationException ("Referenced type '" + typeName + "' not found");
+
+ if (!CanBeAnyElement (stype))
+ throw new InvalidOperationException ("The type '" + typeName + "' is not valid for a collection of any elements");
+
+ ClassMap cmap = new ClassMap ();
+ CodeIdentifiers classIds = new CodeIdentifiers ();
+ bool isMixed = stype.IsMixed;
+ ImportSequenceContent (typeName, cmap, ((XmlSchemaSequence) stype.Particle).Items, classIds, false, ref isMixed);
+ XmlTypeMapMemberAnyElement mapMem = (XmlTypeMapMemberAnyElement) cmap.AllMembers[0];
+ mapMem.Name = typeName.Name;
+
+ XmlMemberMapping[] mm = new XmlMemberMapping [1];
+ mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
+ return new XmlMembersMapping (mm);
+ }
+ }
+
+ public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType)
+ {
+ return ImportDerivedTypeMapping (name, baseType, true);
+ }
+
+ public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType, bool baseTypeCanBeIndirect)
+ {
+ XmlQualifiedName qname;
+ XmlSchemaType stype;
+
+ if (encodedFormat)
+ {
+ qname = name;
+ stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
+ if (stype == null) throw new InvalidOperationException ("Schema type '" + name + "' not found or not valid");
+ }
+ else
+ {
+ if (!LocateElement (name, out qname, out stype))
+ return null;
+ }
+
+ XmlTypeMapping map = GetRegisteredTypeMapping (qname);
+ if (map != null)
+ {
+ // If the type has already been imported, make sure that the map
+ // has the requested base type
+
+ SetMapBaseType (map, baseType);
+ map.UpdateRoot (name);
+ return map;
+ }
+
+ map = CreateTypeMapping (qname, SchemaTypes.Class, name);
+ if (stype != null) {
+ map.Documentation = GetDocumentation (stype);
+ RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
+ } else {
+ ClassMap cmap = new ClassMap ();
+ CodeIdentifiers classIds = new CodeIdentifiers ();
+ map.ObjectMap = cmap;
+ AddTextMember (qname, cmap, classIds);
+ }
+
+ BuildPendingMaps ();
+ SetMapBaseType (map, baseType);
+
+ return map;
+ }
+
+ void SetMapBaseType (XmlTypeMapping map, Type baseType)
+ {
+ // This method sets the base type for a given map.
+ // If the map already inherits from this type, it does nothing.
+
+ // Fiirst of all, check if the map already inherits from baseType
+
+ XmlTypeMapping topMap = null;
+ while (map != null)
+ {
+ if (map.TypeData.Type == baseType)
+ return;
+ topMap = map;
+ map = map.BaseMap;
+ }
+
+ // Does not have the requested base type.
+ // Then, get/create a map for that base type.
+
+ XmlTypeMapping baseMap = ReflectType (baseType);
+
+ // Add this map as a derived map of the base map
+
+ topMap.BaseMap = baseMap;
+ baseMap.DerivedTypes.Add (topMap);
+ baseMap.DerivedTypes.AddRange (topMap.DerivedTypes);
+
+ // Now add the base type fields to all derived maps
+
+ ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
+
+ ClassMap cmap = (ClassMap)topMap.ObjectMap;
+ foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
+ cmap.AddMember (member);
+
+ foreach (XmlTypeMapping derivedMap in topMap.DerivedTypes)
+ {
+ cmap = (ClassMap)derivedMap.ObjectMap;
+ foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
+ cmap.AddMember (member);
+ }
+ }
+
+ public XmlMembersMapping ImportMembersMapping (XmlQualifiedName name)
+ {
+ XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
+ if (elem == null) throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
+
+ XmlSchemaComplexType stype;
+ if (elem.SchemaType != null)
+ {
+ stype = elem.SchemaType as XmlSchemaComplexType;
+ }
+ else
+ {
+ if (elem.SchemaTypeName.IsEmpty) return null;
+ object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
+ if (type == null) {
+ if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) return null;
+ throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
+ }
+ stype = type as XmlSchemaComplexType;
+ }
+
+ if (stype == null)
+ throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
+
+ XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, name);
+ return new XmlMembersMapping (name.Name, name.Namespace, mapping);
+ }
+
+ public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names)
+ {
+ XmlMemberMapping[] mapping = new XmlMemberMapping [names.Length];
+ for (int n=0; n<names.Length; n++)
+ {
+ XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (names[n], typeof (XmlSchemaElement));
+ if (elem == null) throw new InvalidOperationException ("Schema element '" + names[n] + "' not found");
+
+ XmlQualifiedName typeQName = new XmlQualifiedName ("Message", names[n].Namespace);
+ XmlTypeMapping tmap;
+ TypeData td = GetElementTypeData (typeQName, elem, names[n], out tmap);
+
+ mapping[n] = ImportMemberMapping (elem.Name, typeQName.Namespace, elem.IsNillable, td, tmap);
+ }
+ BuildPendingMaps ();
+ return new XmlMembersMapping (mapping);
+ }
+
+#if NET_2_0
+ [MonoTODO]
+ public XmlMembersMapping ImportMembersMapping (string name, string ns, SoapSchemaMember[] members)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType)
+ {
+ throw new NotImplementedException ();
+ }
+
+ [MonoTODO]
+ public XmlTypeMapping ImportSchemaType (XmlQualifiedName typeName, Type baseType, bool baseTypeCanBeIndirect)
+ {
+ throw new NotImplementedException ();
+ }
+#endif
+
+ internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember[] members, bool hasWrapperElement)
+ {
+ XmlMemberMapping[] mapping = new XmlMemberMapping [members.Length];
+ for (int n=0; n<members.Length; n++)
+ {
+ TypeData td = GetTypeData (members[n].MemberType, null);
+ XmlTypeMapping tmap = GetTypeMapping (td);
+ mapping[n] = ImportMemberMapping (members[n].MemberName, members[n].MemberType.Namespace, true, td, tmap);
+ }
+ BuildPendingMaps ();
+ return new XmlMembersMapping (name, ns, hasWrapperElement, false, mapping);
+ }
+
+ internal XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember member)
+ {
+ XmlSchemaComplexType stype = schemas.Find (member.MemberType, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
+ if (stype == null) throw new InvalidOperationException ("Schema type '" + member.MemberType + "' not found or not valid");
+
+ XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, member.MemberType);
+ return new XmlMembersMapping (name, ns, mapping);
+ }
+
+ XmlMemberMapping[] ImportMembersMappingComposite (XmlSchemaComplexType stype, XmlQualifiedName refer)
+ {
+ if (stype.Particle == null)
+ return new XmlMemberMapping [0];
+
+ ClassMap cmap = new ClassMap ();
+
+ XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
+ if (seq == null) throw new InvalidOperationException ("Schema element '" + refer + "' cannot be imported as XmlMembersMapping");
+
+ CodeIdentifiers classIds = new CodeIdentifiers ();
+ ImportParticleComplexContent (refer, cmap, seq, classIds, false);
+ ImportAttributes (refer, cmap, stype.Attributes, stype.AnyAttribute, classIds);
+
+ BuildPendingMaps ();
+
+ int n = 0;
+ XmlMemberMapping[] mapping = new XmlMemberMapping [cmap.AllMembers.Count];
+ foreach (XmlTypeMapMember mapMem in cmap.AllMembers)
+ mapping[n++] = new XmlMemberMapping (mapMem.Name, refer.Namespace, mapMem, encodedFormat);
+
+ return mapping;
+ }
+
+ XmlMemberMapping ImportMemberMapping (string name, string ns, bool isNullable, TypeData type, XmlTypeMapping emap)
+ {
+ XmlTypeMapMemberElement mapMem;
+
+ if (type.IsListType)
+ mapMem = new XmlTypeMapMemberList ();
+ else
+ mapMem = new XmlTypeMapMemberElement ();
+
+ mapMem.Name = name;
+ mapMem.TypeData = type;
+ mapMem.ElementInfo.Add (CreateElementInfo (ns, mapMem, name, type, isNullable, XmlSchemaForm.None, emap));
+ return new XmlMemberMapping (name, ns, mapMem, encodedFormat);
+ }
+
+ [MonoTODO]
+ public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names, Type baseType, bool baseTypeCanBeIndirect)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public XmlTypeMapping ImportTypeMapping (XmlQualifiedName name)
+ {
+ XmlQualifiedName qname;
+ XmlSchemaType stype;
+
+ XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
+ if (!LocateElement (elem, out qname, out stype)) return null;
+
+ if (stype == null) {
+ // Importing a primitive type
+ TypeData td = TypeTranslator.GetPrimitiveTypeData (qname.Name);
+ return ReflectType (td, name.Namespace);
+ }
+
+ XmlTypeMapping map = GetRegisteredTypeMapping (qname);
+ if (map != null) return map;
+
+ map = CreateTypeMapping (qname, SchemaTypes.Class, name);
+ map.Documentation = GetDocumentation (stype);
+ map.IsNullable = elem.IsNillable;
+ RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
+
+ BuildPendingMaps ();
+ return map;
+ }
+
+ bool LocateElement (XmlQualifiedName name, out XmlQualifiedName qname, out XmlSchemaType stype)
+ {
+ XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
+ return LocateElement (elem, out qname, out stype);
+ }
+
+ bool LocateElement (XmlSchemaElement elem, out XmlQualifiedName qname, out XmlSchemaType stype)
+ {
+ qname = null;
+ stype = null;
+
+ if (elem == null) return false;
+
+ // The root element must be an element with complex type
+
+ if (elem.SchemaType != null)
+ {
+ stype = elem.SchemaType;
+ qname = elem.QualifiedName;
+ }
+ else
+ {
+ if (elem.SchemaTypeName.IsEmpty) return false;
+
+ object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
+ if (type == null) type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaSimpleType));
+ if (type == null) {
+ if (IsPrimitiveTypeNamespace (elem.SchemaTypeName.Namespace)) {
+ qname = elem.SchemaTypeName;
+ return true;
+ }
+ throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
+ }
+ stype = (XmlSchemaType) type;
+ qname = stype.QualifiedName;
+
+ XmlSchemaType btype = stype.BaseSchemaType as XmlSchemaType;
+ if (btype != null && btype.QualifiedName == elem.SchemaTypeName)
+ throw new InvalidOperationException ("Cannot import schema for type '" + elem.SchemaTypeName.Name + "' from namespace '" + elem.SchemaTypeName.Namespace + "'. Redefine not supported");
+ }
+
+ if (stype is XmlSchemaSimpleType) return false;
+ return true;
+ }
+
+ XmlTypeMapping ImportType (XmlQualifiedName name, XmlQualifiedName root, bool throwOnError)
+ {
+ XmlTypeMapping map = GetRegisteredTypeMapping (name);
+ if (map != null) {
+ map.UpdateRoot (root);
+ return map;
+ }
+
+ XmlSchemaType type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaComplexType));
+ if (type == null) type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaSimpleType));
+
+ if (type == null)
+ {
+ if (throwOnError) {
+ if (name.Namespace == XmlSerializer.EncodingNamespace)
+ throw new InvalidOperationException ("Referenced type '" + name + "' valid only for encoded SOAP.");
+ else
+ throw new InvalidOperationException ("Referenced type '" + name + "' not found.");
+ } else
+ return null;
+ }
+
+ return ImportType (name, type, root);
+ }
+
+ XmlTypeMapping ImportClass (XmlQualifiedName name)
+ {
+ XmlTypeMapping map = ImportType (name, null, true);
+ if (map.TypeData.SchemaType == SchemaTypes.Class) return map;
+ XmlSchemaComplexType stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
+ return CreateClassMap (name, stype, new XmlQualifiedName (map.ElementName, map.Namespace));
+ }
+
+ XmlTypeMapping ImportType (XmlQualifiedName name, XmlSchemaType stype, XmlQualifiedName root)
+ {
+ XmlTypeMapping map = GetRegisteredTypeMapping (name);
+ if (map != null) {
+ XmlSchemaComplexType ct = stype as XmlSchemaComplexType;
+ if (map.TypeData.SchemaType != SchemaTypes.Class || ct == null || !CanBeArray (name, ct)) {
+ map.UpdateRoot (root);
+ return map;
+ }
+
+ // The map was initially imported as a class, but it turns out that it is an
+ // array. It has to be imported now as array.
+ }
+
+ if (stype is XmlSchemaComplexType)
+ return ImportClassComplexType (name, (XmlSchemaComplexType) stype, root);
+ else if (stype is XmlSchemaSimpleType)
+ return ImportClassSimpleType (name, (XmlSchemaSimpleType) stype, root);
+
+ throw new NotSupportedException ("Schema type not supported: " + stype.GetType ());
+ }
+
+ XmlTypeMapping ImportClassComplexType (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
+ {
+ // The need for fixups: If the complex type is an array, then to get the type of the
+ // array we need first to get the type of the items of the array.
+ // But if one of the item types or its children has a referece to this type array,
+ // then we enter in an infinite loop. This does not happen with class types because
+ // the class map is registered before parsing the children. We can't do the same
+ // with the array type because to register the array map we need the type of the array.
+
+ Type anyType = GetAnyElementType (stype);
+ if (anyType != null)
+ return GetTypeMapping (TypeTranslator.GetTypeData(anyType));
+
+ if (CanBeArray (typeQName, stype))
+ {
+ TypeData typeData;
+ ListMap listMap = BuildArrayMap (typeQName, stype, out typeData);
+ if (listMap != null)
+ {
+ XmlTypeMapping map = CreateArrayTypeMapping (typeQName, typeData);
+ map.ObjectMap = listMap;
+ return map;
+ }
+
+ // After all, it is not an array. Create a class map then.
+ }
+ else if (CanBeIXmlSerializable (stype))
+ {
+ return ImportXmlSerializableMapping (typeQName.Namespace);
+ }
+
+ // Register the map right now but do not build it,
+ // This will avoid loops.
+
+ return CreateClassMap (typeQName, stype, root);
+ }
+
+ XmlTypeMapping CreateClassMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
+ {
+ XmlTypeMapping map = CreateTypeMapping (typeQName, SchemaTypes.Class, root);
+ map.Documentation = GetDocumentation (stype);
+ RegisterMapFixup (map, typeQName, stype);
+ return map;
+ }
+
+ void RegisterMapFixup (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
+ {
+ MapFixup fixup = new MapFixup ();
+ fixup.Map = map;
+ fixup.SchemaType = stype;
+ fixup.TypeName = typeQName;
+ pendingMaps.Enqueue (fixup);
+ }
+
+ void BuildPendingMaps ()
+ {
+ while (pendingMaps.Count > 0) {
+ MapFixup fixup = (MapFixup) pendingMaps.Dequeue ();
+ if (fixup.Map.ObjectMap == null) {
+ BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
+ if (fixup.Map.ObjectMap == null) pendingMaps.Enqueue (fixup);
+ }
+ }
+ }
+
+ void BuildPendingMap (XmlTypeMapping map)
+ {
+ if (map.ObjectMap != null) return;
+
+ foreach (MapFixup fixup in pendingMaps)
+ {
+ if (fixup.Map == map) {
+ BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
+ return;
+ }
+ }
+ throw new InvalidOperationException ("Can't complete map of type " + map.XmlType + " : " + map.Namespace);
+ }
+
+ void BuildClassMap (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
+ {
+ CodeIdentifiers classIds = new CodeIdentifiers();
+ classIds.AddReserved (map.TypeData.TypeName);
+
+ ClassMap cmap = new ClassMap ();
+ map.ObjectMap = cmap;
+ bool isMixed = stype.IsMixed;
+
+ if (stype.Particle != null)
+ ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, isMixed);
+ else
+ {
+ if (stype.ContentModel is XmlSchemaSimpleContent) {
+ ImportSimpleContent (typeQName, map, (XmlSchemaSimpleContent)stype.ContentModel, classIds, isMixed);
+ }
+ else if (stype.ContentModel is XmlSchemaComplexContent) {
+ ImportComplexContent (typeQName, map, (XmlSchemaComplexContent)stype.ContentModel, classIds, isMixed);
+ }
+ }
+
+ ImportAttributes (typeQName, cmap, stype.Attributes, stype.AnyAttribute, classIds);
+ ImportExtensionTypes (typeQName);
+
+ if (isMixed) AddTextMember (typeQName, cmap, classIds);
+
+ AddObjectDerivedMap (map);
+ }
+
+ void ImportAttributes (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection atts, XmlSchemaAnyAttribute anyat, CodeIdentifiers classIds)
+ {
+ if (anyat != null)
+ {
+ XmlTypeMapMemberAnyAttribute member = new XmlTypeMapMemberAnyAttribute ();
+ member.Name = classIds.AddUnique ("AnyAttribute", member);
+ member.TypeData = TypeTranslator.GetTypeData (typeof(XmlAttribute[]));
+ cmap.AddMember (member);
+ }
+
+ foreach (XmlSchemaObject at in atts)
+ {
+ if (at is XmlSchemaAttribute)
+ {
+ string ns;
+ XmlSchemaAttribute attr = (XmlSchemaAttribute)at;
+ XmlSchemaAttribute refAttr = GetRefAttribute (typeQName, attr, out ns);
+ XmlTypeMapMemberAttribute member = new XmlTypeMapMemberAttribute ();
+ member.Name = classIds.AddUnique (CodeIdentifier.MakeValid (refAttr.Name), member);
+ member.Documentation = GetDocumentation (attr);
+ member.AttributeName = refAttr.Name;
+ member.Namespace = ns;
+ member.Form = refAttr.Form;
+ member.TypeData = GetAttributeTypeData (typeQName, attr);
+
+ if (refAttr.DefaultValue != null)
+ member.DefaultValue = ImportDefaultValue (member.TypeData, refAttr.DefaultValue);
+ else if (member.TypeData.IsValueType)
+ member.IsOptionalValueType = (refAttr.ValidatedUse != XmlSchemaUse.Required);
+
+ if (member.TypeData.IsComplexType)
+ member.MappedType = GetTypeMapping (member.TypeData);
+ cmap.AddMember (member);
+ }
+ else if (at is XmlSchemaAttributeGroupRef)
+ {
+ XmlSchemaAttributeGroupRef gref = (XmlSchemaAttributeGroupRef)at;
+ XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
+ ImportAttributes (typeQName, cmap, grp.Attributes, grp.AnyAttribute, classIds);
+ }
+ }
+ }
+
+ ListMap BuildArrayMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, out TypeData arrayTypeData)
+ {
+ if (encodedFormat)
+ {
+ XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
+ XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
+ XmlSchemaAttribute arrayTypeAt = FindArrayAttribute (rest.Attributes);
+
+ if (arrayTypeAt != null)
+ {
+ XmlAttribute[] uatts = arrayTypeAt.UnhandledAttributes;
+ if (uatts == null || uatts.Length == 0) throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
+
+ XmlAttribute xat = null;
+ foreach (XmlAttribute at in uatts)
+ if (at.LocalName == "arrayType" && at.NamespaceURI == XmlSerializer.WsdlNamespace)
+ { xat = at; break; }
+
+ if (xat == null)
+ throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
+
+ string name, ns, dims;
+ TypeTranslator.ParseArrayType (xat.Value, out name, out ns, out dims);
+ return BuildEncodedArrayMap (name + dims, ns, out arrayTypeData);
+ }
+ else
+ {
+ XmlSchemaElement elem = null;
+ XmlSchemaSequence seq = rest.Particle as XmlSchemaSequence;
+ if (seq != null && seq.Items.Count == 1)
+ elem = seq.Items[0] as XmlSchemaElement;
+ else {
+ XmlSchemaAll all = rest.Particle as XmlSchemaAll;
+ if (all != null && all.Items.Count == 1)
+ elem = all.Items[0] as XmlSchemaElement;
+ }
+ if (elem == null)
+ throw new InvalidOperationException ("Unknown array format");
+
+ return BuildEncodedArrayMap (elem.SchemaTypeName.Name + "[]", elem.SchemaTypeName.Namespace, out arrayTypeData);
+ }
+ }
+ else
+ {
+ ClassMap cmap = new ClassMap ();
+ CodeIdentifiers classIds = new CodeIdentifiers();
+ ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, stype.IsMixed);
+
+ XmlTypeMapMemberFlatList list = (cmap.AllMembers.Count == 1) ? cmap.AllMembers[0] as XmlTypeMapMemberFlatList : null;
+ if (list != null && list.ChoiceMember == null)
+ {
+ arrayTypeData = list.TypeData;
+ return list.ListMap;
+ }
+ else
+ {
+ arrayTypeData = null;
+ return null;
+ }
+ }
+ }
+
+ ListMap BuildEncodedArrayMap (string type, string ns, out TypeData arrayTypeData)
+ {
+ ListMap map = new ListMap ();
+
+ int i = type.LastIndexOf ("[");
+ if (i == -1) throw new InvalidOperationException ("Invalid arrayType value: " + type);
+ if (type.IndexOf (",",i) != -1) throw new InvalidOperationException ("Multidimensional arrays are not supported");
+
+ string itemType = type.Substring (0,i);
+
+ TypeData itemTypeData;
+ if (itemType.IndexOf ("[") != -1)
+ {
+ ListMap innerListMap = BuildEncodedArrayMap (itemType, ns, out itemTypeData);
+
+ int dims = itemType.Split ('[').Length - 1;
+ string name = TypeTranslator.GetArrayName (type, dims);
+ XmlQualifiedName qname = new XmlQualifiedName (name, ns);
+ XmlTypeMapping tmap = CreateArrayTypeMapping (qname, itemTypeData);
+ tmap.ObjectMap = innerListMap;
+ }
+ else
+ {
+ itemTypeData = GetTypeData (new XmlQualifiedName (itemType, ns), null);
+ }
+
+ arrayTypeData = itemTypeData.ListTypeData;
+
+ map.ItemInfo = new XmlTypeMapElementInfoList();
+ map.ItemInfo.Add (CreateElementInfo ("", null, "Item", itemTypeData, true, XmlSchemaForm.None));
+ return map;
+ }
+
+ XmlSchemaAttribute FindArrayAttribute (XmlSchemaObjectCollection atts)
+ {
+ foreach (object ob in atts)
+ {
+ XmlSchemaAttribute att = ob as XmlSchemaAttribute;
+ if (att != null && att.RefName == arrayTypeRefName) return att;
+
+ XmlSchemaAttributeGroupRef gref = ob as XmlSchemaAttributeGroupRef;
+ if (gref != null)
+ {
+ XmlSchemaAttributeGroup grp = FindRefAttributeGroup (gref.RefName);
+ att = FindArrayAttribute (grp.Attributes);
+ if (att != null) return att;
+ }
+ }
+ return null;
+ }
+
+ void ImportParticleComplexContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool isMixed)
+ {
+ ImportParticleContent (typeQName, cmap, particle, classIds, false, ref isMixed);
+ if (isMixed) AddTextMember (typeQName, cmap, classIds);
+ }
+
+ void AddTextMember (XmlQualifiedName typeQName, ClassMap cmap, CodeIdentifiers classIds)
+ {
+ if (cmap.XmlTextCollector == null)
+ {
+ XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
+ member.Name = classIds.AddUnique ("Text", member);
+ member.TypeData = TypeTranslator.GetTypeData (typeof(string[]));
+ member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData.ListItemTypeData));
+ member.IsXmlTextCollector = true;
+ member.ListMap = new ListMap ();
+ member.ListMap.ItemInfo = member.ElementInfo;
+ cmap.AddMember (member);
+ }
+ }
+
+ void ImportParticleContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
+ {
+ if (particle == null) return;
+
+ if (particle is XmlSchemaGroupRef)
+ particle = GetRefGroupParticle ((XmlSchemaGroupRef)particle);
+
+ if (particle.MaxOccurs > 1) multiValue = true;
+
+ if (particle is XmlSchemaSequence) {
+ ImportSequenceContent (typeQName, cmap, ((XmlSchemaSequence)particle).Items, classIds, multiValue, ref isMixed);
+ }
+ else if (particle is XmlSchemaChoice) {
+ if (((XmlSchemaChoice)particle).Items.Count == 1)
+ ImportSequenceContent (typeQName, cmap, ((XmlSchemaChoice)particle).Items, classIds, multiValue, ref isMixed);
+ else
+ ImportChoiceContent (typeQName, cmap, (XmlSchemaChoice)particle, classIds, multiValue);
+ }
+ else if (particle is XmlSchemaAll) {
+ ImportSequenceContent (typeQName, cmap, ((XmlSchemaAll)particle).Items, classIds, multiValue, ref isMixed);
+ }
+ }
+
+ void ImportSequenceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection items, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
+ {
+ foreach (XmlSchemaObject item in items)
+ {
+ if (item is XmlSchemaElement)
+ {
+ string ns;
+ XmlSchemaElement elem = (XmlSchemaElement) item;
+ XmlTypeMapping emap;
+ TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
+ XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
+
+ if (elem.MaxOccurs == 1 && !multiValue)
+ {
+ XmlTypeMapMemberElement member = null;
+ if (typeData.SchemaType != SchemaTypes.Array)
+ {
+ member = new XmlTypeMapMemberElement ();
+ if (refElem.DefaultValue != null) member.DefaultValue = ImportDefaultValue (typeData, refElem.DefaultValue);
+ }
+ else if (GetTypeMapping (typeData).IsSimpleType)
+ {
+ // It is a simple list (space separated list).
+ // Since this is not supported, map as a single item value
+ member = new XmlTypeMapMemberElement ();
+#if NET_2_0
+ // In MS.NET those types are mapped to a string
+ typeData = TypeTranslator.GetTypeData(typeof(string));
+#else
+ typeData = typeData.ListItemTypeData;
+#endif
+ }
+ else
+ member = new XmlTypeMapMemberList ();
+
+ if (elem.MinOccurs == 0 && typeData.IsValueType)
+ member.IsOptionalValueType = true;
+
+ member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
+ member.Documentation = GetDocumentation (elem);
+ member.TypeData = typeData;
+ member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));
+ cmap.AddMember (member);
+ }
+ else
+ {
+ XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
+ member.ListMap = new ListMap ();
+ member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
+ member.Documentation = GetDocumentation (elem);
+ member.TypeData = typeData.ListTypeData;
+ member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));
+ member.ListMap.ItemInfo = member.ElementInfo;
+ cmap.AddMember (member);
+ }
+ }
+ else if (item is XmlSchemaAny)
+ {
+ XmlSchemaAny elem = (XmlSchemaAny) item;
+ XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement ();
+ member.Name = classIds.AddUnique ("Any", member);
+ member.Documentation = GetDocumentation (elem);
+
+ Type ctype;
+ if (elem.MaxOccurs != 1 || multiValue)
+ ctype = isMixed ? typeof(XmlNode[]) : typeof(XmlElement[]);
+ else
+ ctype = isMixed ? typeof(XmlNode) : typeof(XmlElement);
+
+ member.TypeData = TypeTranslator.GetTypeData (ctype);
+ XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, member.TypeData);
+ einfo.IsUnnamedAnyElement = true;
+ member.ElementInfo.Add (einfo);
+
+ if (isMixed)
+ {
+ einfo = CreateTextElementInfo (typeQName.Namespace, member, member.TypeData);
+ member.ElementInfo.Add (einfo);
+ member.IsXmlTextCollector = true;
+ isMixed = false; //Allow only one XmlTextAttribute
+ }
+
+ cmap.AddMember (member);
+ }
+ else if (item is XmlSchemaParticle) {
+ ImportParticleContent (typeQName, cmap, (XmlSchemaParticle)item, classIds, multiValue, ref isMixed);
+ }
+ }
+ }
+
+ object ImportDefaultValue (TypeData typeData, string value)
+ {
+ if (typeData.SchemaType == SchemaTypes.Enum) {
+ XmlTypeMapping map = GetTypeMapping (typeData);
+ EnumMap emap = (EnumMap) map.ObjectMap;
+ string res = emap.GetEnumName (map.TypeFullName, value);
+ if (res == null) throw new InvalidOperationException ("'" + value + "' is not a valid enumeration value");
+ return res;
+ } else
+ return XmlCustomFormatter.FromXmlString (typeData, value);
+ }
+
+ void ImportChoiceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaChoice choice, CodeIdentifiers classIds, bool multiValue)
+ {
+ XmlTypeMapElementInfoList choices = new XmlTypeMapElementInfoList ();
+ multiValue = ImportChoices (typeQName, null, choices, choice.Items) || multiValue;
+ if (choices.Count == 0) return;
+
+ if (choice.MaxOccurs > 1) multiValue = true;
+
+ XmlTypeMapMemberElement member;
+ if (multiValue)
+ {
+ member = new XmlTypeMapMemberFlatList ();
+ member.Name = classIds.AddUnique ("Items", member);
+ ListMap listMap = new ListMap ();
+ listMap.ItemInfo = choices;
+ ((XmlTypeMapMemberFlatList)member).ListMap = listMap;
+ }
+ else
+ {
+ member = new XmlTypeMapMemberElement ();
+ member.Name = classIds.AddUnique ("Item", member);
+ }
+
+ // If all choices have the same type, use that type for the member.
+ // If not use System.Object.
+ // If there are at least two choices with the same type, use a choice
+ // identifier attribute
+
+ TypeData typeData = null;
+ bool twoEqual = false;
+ bool allEqual = true;
+ Hashtable types = new Hashtable ();
+
+ for (int n = choices.Count - 1; n >= 0; n--)
+ {
+ XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) choices [n];
+
+ // In some complex schemas, we may end up with several options
+ // with the same name. It is better to ignore the extra options
+ // than to crash. It's the best we can do, and btw it works
+ // better than in MS.NET.
+
+ if (cmap.GetElement (einfo.ElementName, einfo.Namespace) != null ||
+ choices.IndexOfElement (einfo.ElementName, einfo.Namespace) != n)
+ {
+ choices.RemoveAt (n);
+ continue;
+ }
+
+ if (types.ContainsKey (einfo.TypeData)) twoEqual = true;
+ else types.Add (einfo.TypeData, einfo);
+
+ TypeData choiceType = einfo.TypeData;
+ if (choiceType.SchemaType == SchemaTypes.Class)
+ {
+ // When comparing class types, use the most generic class in the
+ // inheritance hierarchy
+
+ XmlTypeMapping choiceMap = GetTypeMapping (choiceType);
+ BuildPendingMap (choiceMap);
+ while (choiceMap.BaseMap != null) {
+ choiceMap = choiceMap.BaseMap;
+ BuildPendingMap (choiceMap);
+ choiceType = choiceMap.TypeData;
+ }
+ }
+
+ if (typeData == null) typeData = choiceType;
+ else if (typeData != choiceType) allEqual = false;
+ }
+
+ if (!allEqual)
+ typeData = TypeTranslator.GetTypeData (typeof(object));
+
+ if (twoEqual)
+ {
+ // Create the choice member
+ XmlTypeMapMemberElement choiceMember = new XmlTypeMapMemberElement ();
+ choiceMember.Ignore = true;
+ choiceMember.Name = classIds.AddUnique (member.Name + "ElementName", choiceMember);
+ member.ChoiceMember = choiceMember.Name;
+
+ // Create the choice enum
+ XmlTypeMapping enumMap = CreateTypeMapping (new XmlQualifiedName (member.Name + "ChoiceType", typeQName.Namespace), SchemaTypes.Enum, null);
+ enumMap.IncludeInSchema = false;
+
+ CodeIdentifiers codeIdents = new CodeIdentifiers ();
+ EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [choices.Count];
+ for (int n=0; n<choices.Count; n++)
+ {
+ XmlTypeMapElementInfo it =(XmlTypeMapElementInfo) choices[n];
+ bool extraNs = (it.Namespace != null && it.Namespace != "" && it.Namespace != typeQName.Namespace);
+ string xmlName = extraNs ? it.Namespace + ":" + it.ElementName : it.ElementName;
+ string enumName = codeIdents.AddUnique (CodeIdentifier.MakeValid (it.ElementName), it);
+ members [n] = new EnumMap.EnumMapMember (xmlName, enumName);
+ }
+ enumMap.ObjectMap = new EnumMap (members, false);
+
+ choiceMember.TypeData = multiValue ? enumMap.TypeData.ListTypeData : enumMap.TypeData;
+ choiceMember.ElementInfo.Add (CreateElementInfo (typeQName.Namespace, choiceMember, choiceMember.Name, choiceMember.TypeData, false, XmlSchemaForm.None));
+ cmap.AddMember (choiceMember);
+ }
+
+ if (typeData == null)
+ return;
+
+ if (multiValue)
+ typeData = typeData.ListTypeData;
+
+ member.ElementInfo = choices;
+ member.Documentation = GetDocumentation (choice);
+ member.TypeData = typeData;
+ cmap.AddMember (member);
+ }
+
+ bool ImportChoices (XmlQualifiedName typeQName, XmlTypeMapMember member, XmlTypeMapElementInfoList choices, XmlSchemaObjectCollection items)
+ {
+ bool multiValue = false;
+ foreach (XmlSchemaObject titem in items)
+ {
+ XmlSchemaObject item = titem;
+ if (item is XmlSchemaGroupRef)
+ item = GetRefGroupParticle ((XmlSchemaGroupRef)item);
+
+ if (item is XmlSchemaElement)
+ {
+ string ns;
+ XmlSchemaElement elem = (XmlSchemaElement) item;
+ XmlTypeMapping emap;
+ TypeData typeData = GetElementTypeData (typeQName, elem, null, out emap);
+ XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
+ choices.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable, refElem.Form, emap));
+ if (elem.MaxOccurs > 1) multiValue = true;
+ }
+ else if (item is XmlSchemaAny)
+ {
+ XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
+ einfo.IsUnnamedAnyElement = true;
+ choices.Add (einfo);
+ }
+ else if (item is XmlSchemaChoice) {
+ multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaChoice)item).Items) || multiValue;
+ }
+ else if (item is XmlSchemaSequence) {
+ multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaSequence)item).Items) || multiValue;
+ }
+ }
+ return multiValue;
+ }
+
+ void ImportSimpleContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaSimpleContent content, CodeIdentifiers classIds, bool isMixed)
+ {
+ XmlSchemaSimpleContentExtension ext = content.Content as XmlSchemaSimpleContentExtension;
+ ClassMap cmap = (ClassMap)map.ObjectMap;
+ XmlQualifiedName qname = GetContentBaseType (content.Content);
+ TypeData simpleType = null;
+
+ if (!IsPrimitiveTypeNamespace (qname.Namespace))
+ {
+ // Add base map members to this map
+
+ XmlTypeMapping baseMap = ImportType (qname, null, true);
+ BuildPendingMap (baseMap);
+
+ if (baseMap.IsSimpleType) {
+ simpleType = baseMap.TypeData;
+ } else {
+ ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
+
+ foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
+ cmap.AddMember (member);
+
+ map.BaseMap = baseMap;
+ baseMap.DerivedTypes.Add (map);
+ }
+ }
+ else
+ simpleType = FindBuiltInType (qname);
+
+ if (simpleType != null) {
+ XmlTypeMapMemberElement member = new XmlTypeMapMemberElement ();
+ member.Name = classIds.AddUnique("Value", member);
+ member.TypeData = simpleType;
+ member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData));
+ member.IsXmlTextCollector = true;
+ cmap.AddMember (member);
+ }
+
+ if (ext != null)
+ ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
+ }
+
+ TypeData FindBuiltInType (XmlQualifiedName qname)
+ {
+ XmlSchemaComplexType ct = (XmlSchemaComplexType) schemas.Find (qname, typeof(XmlSchemaComplexType));
+ if (ct != null)
+ {
+ XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;
+ if (sc == null) throw new InvalidOperationException ("Invalid schema");
+ return FindBuiltInType (GetContentBaseType (sc.Content));
+ }
+
+ XmlSchemaSimpleType st = (XmlSchemaSimpleType) schemas.Find (qname, typeof(XmlSchemaSimpleType));
+ if (st != null)
+ return FindBuiltInType (qname, st);
+
+ if (IsPrimitiveTypeNamespace (qname.Namespace))
+ return TypeTranslator.GetPrimitiveTypeData (qname.Name);
+
+ throw new InvalidOperationException ("Definition of type '" + qname + "' not found");
+ }
+
+ TypeData FindBuiltInType (XmlQualifiedName qname, XmlSchemaSimpleType st)
+ {
+ if (CanBeEnum (st) && qname != null)
+ return ImportType (qname, null, true).TypeData;
+
+ if (st.Content is XmlSchemaSimpleTypeRestriction) {
+ XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction) st.Content;
+ XmlQualifiedName bn = GetContentBaseType (rest);
+ if (bn == XmlQualifiedName.Empty && rest.BaseType != null)
+ return FindBuiltInType (qname, rest.BaseType);
+ else
+ return FindBuiltInType (bn);
+ }
+ else if (st.Content is XmlSchemaSimpleTypeList) {
+ return FindBuiltInType (GetContentBaseType (st.Content)).ListTypeData;
+ }
+ else if (st.Content is XmlSchemaSimpleTypeUnion) {
+ // MS.NET always import simple unions as string
+ return FindBuiltInType (new XmlQualifiedName ("string", XmlSchema.Namespace));
+ }
+ else
+ return null;
+ }
+
+ XmlQualifiedName GetContentBaseType (XmlSchemaObject ob)
+ {
+ if (ob is XmlSchemaSimpleContentExtension)
+ return ((XmlSchemaSimpleContentExtension)ob).BaseTypeName;
+ else if (ob is XmlSchemaSimpleContentRestriction)
+ return ((XmlSchemaSimpleContentRestriction)ob).BaseTypeName;
+ else if (ob is XmlSchemaSimpleTypeRestriction)
+ return ((XmlSchemaSimpleTypeRestriction)ob).BaseTypeName;
+ else if (ob is XmlSchemaSimpleTypeList)
+ return ((XmlSchemaSimpleTypeList)ob).ItemTypeName;
+ else
+ return null;
+ }
+
+ void ImportComplexContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaComplexContent content, CodeIdentifiers classIds, bool isMixed)
+ {
+ ClassMap cmap = (ClassMap)map.ObjectMap;
+ XmlQualifiedName qname;
+
+ XmlSchemaComplexContentExtension ext = content.Content as XmlSchemaComplexContentExtension;
+ if (ext != null) qname = ext.BaseTypeName;
+ else qname = ((XmlSchemaComplexContentRestriction)content.Content).BaseTypeName;
+
+ if (qname == typeQName)
+ throw new InvalidOperationException ("Cannot import schema for type '" + typeQName.Name + "' from namespace '" + typeQName.Namespace + "'. Redefine not supported");
+
+ // Add base map members to this map
+
+ XmlTypeMapping baseMap = ImportClass (qname);
+ BuildPendingMap (baseMap);
+ ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
+
+ foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
+ cmap.AddMember (member);
+
+ if (baseClassMap.XmlTextCollector != null) isMixed = false;
+ else if (content.IsMixed) isMixed = true;
+
+ map.BaseMap = baseMap;
+ baseMap.DerivedTypes.Add (map);
+
+ if (ext != null) {
+ // Add the members of this map
+ ImportParticleComplexContent (typeQName, cmap, ext.Particle, classIds, isMixed);
+ ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
+ }
+ else {
+ if (isMixed) ImportParticleComplexContent (typeQName, cmap, null, classIds, true);
+ }
+ }
+
+ void ImportExtensionTypes (XmlQualifiedName qname)
+ {
+ foreach (XmlSchema schema in schemas) {
+ foreach (XmlSchemaObject sob in schema.Items)
+ {
+ XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
+ if (sct != null && sct.ContentModel is XmlSchemaComplexContent) {
+ XmlQualifiedName exqname;
+ XmlSchemaComplexContentExtension ext = sct.ContentModel.Content as XmlSchemaComplexContentExtension;
+ if (ext != null) exqname = ext.BaseTypeName;
+ else exqname = ((XmlSchemaComplexContentRestriction)sct.ContentModel.Content).BaseTypeName;
+ if (exqname == qname)
+ ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
+ }
+ }
+ }
+ }
+
+ XmlTypeMapping ImportClassSimpleType (XmlQualifiedName typeQName, XmlSchemaSimpleType stype, XmlQualifiedName root)
+ {
+ if (CanBeEnum (stype))
+ {
+ // Create an enum map
+
+ CodeIdentifiers codeIdents = new CodeIdentifiers ();
+ XmlTypeMapping enumMap = CreateTypeMapping (typeQName, SchemaTypes.Enum, null);
+ enumMap.Documentation = GetDocumentation (stype);
+
+ bool isFlags = false;
+ if (stype.Content is XmlSchemaSimpleTypeList) {
+ stype = ((XmlSchemaSimpleTypeList)stype.Content).ItemType;
+ isFlags = true;
+ }
+ XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
+
+ codeIdents.AddReserved (enumMap.TypeData.TypeName);
+
+ EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [rest.Facets.Count];
+ for (int n=0; n<rest.Facets.Count; n++)
+ {
+ XmlSchemaEnumerationFacet enu = (XmlSchemaEnumerationFacet) rest.Facets[n];
+ string enumName = codeIdents.AddUnique(CodeIdentifier.MakeValid (enu.Value), enu);
+ members [n] = new EnumMap.EnumMapMember (enu.Value, enumName);
+ members [n].Documentation = GetDocumentation (enu);
+ }
+ enumMap.ObjectMap = new EnumMap (members, isFlags);
+ enumMap.IsSimpleType = true;
+ return enumMap;
+ }
+
+ if (stype.Content is XmlSchemaSimpleTypeList)
+ {
+ XmlSchemaSimpleTypeList slist = (XmlSchemaSimpleTypeList)stype.Content;
+ TypeData arrayTypeData = FindBuiltInType (slist.ItemTypeName, stype);
+
+ ListMap listMap = new ListMap ();
+
+ listMap.ItemInfo = new XmlTypeMapElementInfoList ();
+ listMap.ItemInfo.Add (CreateElementInfo (typeQName.Namespace, null, "Item", arrayTypeData.ListItemTypeData, false, XmlSchemaForm.None));
+
+ XmlTypeMapping map = CreateArrayTypeMapping (typeQName, arrayTypeData);
+ map.ObjectMap = listMap;
+ map.IsSimpleType = true;
+ return map;
+ }
+
+ // It is an extension of a primitive or known type
+
+ TypeData typeData = FindBuiltInType (typeQName, stype);
+ XmlTypeMapping rmap = GetTypeMapping (typeData);
+
+ // The resulting map must be a simple type. It needs to be explicitely set for arrays
+ rmap.IsSimpleType = true;
+ return rmap;
+ }
+
+ bool CanBeEnum (XmlSchemaSimpleType stype)
+ {
+ if (stype.Content is XmlSchemaSimpleTypeRestriction)
+ {
+ XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
+ if (rest.Facets.Count == 0) return false;
+ foreach (object ob in rest.Facets)
+ if (!(ob is XmlSchemaEnumerationFacet)) return false;
+ return true;
+ }
+ else if (stype.Content is XmlSchemaSimpleTypeList)
+ {
+ XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList) stype.Content;
+ return (list.ItemType != null && CanBeEnum (list.ItemType));
+ }
+ return false;
+ }
+
+ bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaComplexType stype)
+ {
+ if (encodedFormat)
+ {
+ XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
+ if (content == null) return false;
+ XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
+ if (rest == null) return false;
+ return rest.BaseTypeName == arrayType;
+ }
+ else
+ {
+ if (stype.Attributes.Count > 0 || stype.AnyAttribute != null) return false;
+ else return !stype.IsMixed && CanBeArray (typeQName, stype.Particle, false);
+ }
+ }
+
+ bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaParticle particle, bool multiValue)
+ {
+ // To be an array, there can't be a direct child of type typeQName
+
+ if (particle == null) return false;
+
+ multiValue = multiValue || particle.MaxOccurs > 1;
+
+ if (particle is XmlSchemaGroupRef)
+ return CanBeArray (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), multiValue);
+
+ if (particle is XmlSchemaElement)
+ {
+ XmlSchemaElement elem = (XmlSchemaElement)particle;
+ if (!elem.RefName.IsEmpty)
+ return CanBeArray (typeQName, FindRefElement (elem), multiValue);
+ else
+ return multiValue && !typeQName.Equals (((XmlSchemaElement)particle).SchemaTypeName);
+ }
+
+ if (particle is XmlSchemaAny)
+ return multiValue;
+
+ if (particle is XmlSchemaSequence)
+ {
+ XmlSchemaSequence seq = particle as XmlSchemaSequence;
+ if (seq.Items.Count != 1) return false;
+ return CanBeArray (typeQName, (XmlSchemaParticle)seq.Items[0], multiValue);
+ }
+
+ if (particle is XmlSchemaChoice)
+ {
+ // Can be array if all choices have different types
+ ArrayList types = new ArrayList ();
+ if(!CheckChoiceType (typeQName, particle, types, ref multiValue)) return false;
+ return multiValue;
+ }
+
+ return false;
+ }
+
+ bool CheckChoiceType (XmlQualifiedName typeQName, XmlSchemaParticle particle, ArrayList types, ref bool multiValue)
+ {
+ XmlQualifiedName type = null;
+
+ multiValue = multiValue || particle.MaxOccurs > 1;
+
+ if (particle is XmlSchemaGroupRef)
+ return CheckChoiceType (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), types, ref multiValue);
+
+ if (particle is XmlSchemaElement) {
+ string ns;
+ XmlSchemaElement elem = (XmlSchemaElement)particle;
+ XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
+ if (refElem.SchemaType != null) return true;
+ type = refElem.SchemaTypeName;
+ }
+ else if (particle is XmlSchemaAny) {
+ type = anyType;
+ }
+ else if (particle is XmlSchemaSequence)
+ {
+ XmlSchemaSequence seq = particle as XmlSchemaSequence;
+ foreach (XmlSchemaParticle par in seq.Items)
+ if (!CheckChoiceType (typeQName, par, types, ref multiValue)) return false;
+ return true;
+ }
+ else if (particle is XmlSchemaChoice)
+ {
+ foreach (XmlSchemaParticle choice in ((XmlSchemaChoice)particle).Items)
+ if (!CheckChoiceType (typeQName, choice, types, ref multiValue)) return false;
+ return true;
+ }
+
+ if (typeQName.Equals (type)) return false;
+
+ // For primitive types, compare using CLR types, since several
+ // xml types can be mapped to a single CLR type
+
+ string t;
+ if (IsPrimitiveTypeNamespace (type.Namespace))
+ t = TypeTranslator.GetPrimitiveTypeData (type.Name).FullTypeName + ":" + type.Namespace;
+
+ else
+ t = type.Name + ":" + type.Namespace;
+
+ if (types.Contains (t)) return false;
+ types.Add (t);
+ return true;
+ }
+
+ bool CanBeAnyElement (XmlSchemaComplexType stype)
+ {
+ XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
+ return (seq != null) && (seq.Items.Count == 1) && (seq.Items[0] is XmlSchemaAny);
+ }
+
+ Type GetAnyElementType (XmlSchemaComplexType stype)
+ {
+ XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
+
+ if ((seq == null) || (seq.Items.Count != 1) || !(seq.Items[0] is XmlSchemaAny))
+ return null;
+
+ if (encodedFormat)
+ return typeof(object);
+
+ XmlSchemaAny any = seq.Items[0] as XmlSchemaAny;
+ if (any.MaxOccurs == 1)
+ {
+ if (stype.IsMixed)
+ return typeof(XmlNode);
+ else
+ return typeof(XmlElement);
+ }
+ else
+ {
+ if (stype.IsMixed)
+ return typeof(XmlNode[]);
+ else
+ return typeof(XmlElement[]);
+ }
+ }
+
+ bool CanBeIXmlSerializable (XmlSchemaComplexType stype)
+ {
+ XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
+ if (seq == null) return false;
+ if (seq.Items.Count != 2) return false;
+ XmlSchemaElement elem = seq.Items[0] as XmlSchemaElement;
+ if (elem == null) return false;
+ if (elem.RefName != new XmlQualifiedName ("schema",XmlSchema.Namespace)) return false;
+ return (seq.Items[1] is XmlSchemaAny);
+ }
+
+ XmlTypeMapping ImportXmlSerializableMapping (string ns)
+ {
+ XmlQualifiedName qname = new XmlQualifiedName ("System.Data.DataSet",ns);
+ XmlTypeMapping map = mappedTypes [qname] as XmlTypeMapping;
+ if (map != null) return map;
+
+ TypeData typeData = new TypeData ("System.Data.DataSet", "System.Data.DataSet", "System.Data.DataSet", SchemaTypes.XmlSerializable, null);
+ map = new XmlTypeMapping ("System.Data.DataSet", "", typeData, "System.Data.DataSet", ns);
+ map.IncludeInSchema = true;
+ mappedTypes [qname] = map;
+ dataMappedTypes [typeData] = map;
+ return map;
+ }
+
+ XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form)
+ {
+ if (typeData.IsComplexType)
+ return CreateElementInfo (ns, member, name, typeData, isNillable, form, GetTypeMapping (typeData));
+ else
+ return CreateElementInfo (ns, member, name, typeData, isNillable, form, null);
+ }
+
+ XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable, XmlSchemaForm form, XmlTypeMapping emap)
+ {
+ XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
+ einfo.ElementName = name;
+ einfo.Namespace = ns;
+ einfo.IsNullable = isNillable;
+ einfo.Form = form;
+ if (typeData.IsComplexType)
+ einfo.MappedType = emap;
+ return einfo;
+ }
+
+ XmlTypeMapElementInfo CreateTextElementInfo (string ns, XmlTypeMapMember member, TypeData typeData)
+ {
+ XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
+ einfo.IsTextElement = true;
+ einfo.WrappedElement = false;
+ if (typeData.IsComplexType)
+ einfo.MappedType = GetTypeMapping (typeData);
+ return einfo;
+ }
+
+ XmlTypeMapping CreateTypeMapping (XmlQualifiedName typeQName, SchemaTypes schemaType, XmlQualifiedName root)
+ {
+ string typeName = CodeIdentifier.MakeValid (typeQName.Name);
+ typeName = typeIdentifiers.AddUnique (typeName, null);
+
+ TypeData typeData = new TypeData (typeName, typeName, typeName, schemaType, null);
+
+ string rootElem;
+ string rootNs;
+ if (root != null) {
+ rootElem = root.Name;
+ rootNs = root.Namespace;
+ }
+ else {
+ rootElem = typeQName.Name;
+ rootNs = "";
+ }
+
+ XmlTypeMapping map = new XmlTypeMapping (rootElem, rootNs, typeData, typeQName.Name, typeQName.Namespace);
+ map.IncludeInSchema = true;
+ mappedTypes [typeQName] = map;
+ dataMappedTypes [typeData] = map;
+
+ return map;
+ }
+
+ XmlTypeMapping CreateArrayTypeMapping (XmlQualifiedName typeQName, TypeData arrayTypeData)
+ {
+ XmlTypeMapping map;
+ if (encodedFormat) map = new XmlTypeMapping ("Array", XmlSerializer.EncodingNamespace, arrayTypeData, "Array", XmlSerializer.EncodingNamespace);
+ else map = new XmlTypeMapping (arrayTypeData.XmlType, typeQName.Namespace, arrayTypeData, arrayTypeData.XmlType, typeQName.Namespace);
+
+ map.IncludeInSchema = true;
+ mappedTypes [typeQName] = map;
+ dataMappedTypes [arrayTypeData] = map;
+
+ return map;
+ }
+
+ XmlSchemaElement GetRefElement (XmlQualifiedName typeQName, XmlSchemaElement elem, out string ns)
+ {
+
+ if (!elem.RefName.IsEmpty)
+ {
+ ns = elem.RefName.Namespace;
+ return FindRefElement (elem);
+ }
+ else
+ {
+ ns = typeQName.Namespace;
+ return elem;
+ }
+ }
+
+ XmlSchemaAttribute GetRefAttribute (XmlQualifiedName typeQName, XmlSchemaAttribute attr, out string ns)
+ {
+ if (!attr.RefName.IsEmpty)
+ {
+ ns = attr.RefName.Namespace;
+ XmlSchemaAttribute at = FindRefAttribute (attr.RefName);
+ if (at == null) throw new InvalidOperationException ("The attribute " + attr.RefName + " is missing");
+ return at;
+ }
+ else
+ {
+ ns = typeQName.Namespace;
+ return attr;
+ }
+ }
+
+ TypeData GetElementTypeData (XmlQualifiedName typeQName, XmlSchemaElement elem, XmlQualifiedName root, out XmlTypeMapping map)
+ {
+ bool sharedAnnType = false;
+ map = null;
+
+ if (!elem.RefName.IsEmpty) {
+ XmlSchemaElement refElem = FindRefElement (elem);
+ if (refElem == null) throw new InvalidOperationException ("Global element not found: " + elem.RefName);
+ root = elem.RefName;
+ elem = refElem;
+ sharedAnnType = true;
+ }
+
+ TypeData td;
+ if (!elem.SchemaTypeName.IsEmpty) {
+ td = GetTypeData (elem.SchemaTypeName, root);
+ map = GetRegisteredTypeMapping (elem.SchemaTypeName);
+ }
+ else if (elem.SchemaType == null)
+ td = TypeTranslator.GetTypeData (typeof(object));
+ else
+ td = GetTypeData (elem.SchemaType, typeQName, elem.Name, sharedAnnType, root);
+
+ if (map == null && td.IsComplexType)
+ map = GetTypeMapping (td);
+
+ return td;
+ }
+
+ TypeData GetAttributeTypeData (XmlQualifiedName typeQName, XmlSchemaAttribute attr)
+ {
+ bool sharedAnnType = false;
+
+ if (!attr.RefName.IsEmpty) {
+ XmlSchemaAttribute refAtt = FindRefAttribute (attr.RefName);
+ if (refAtt == null) throw new InvalidOperationException ("Global attribute not found: " + attr.RefName);
+ attr = refAtt;
+ sharedAnnType = true;
+ }
+
+ if (!attr.SchemaTypeName.IsEmpty) return GetTypeData (attr.SchemaTypeName, null);
+ if (attr.SchemaType == null) return TypeTranslator.GetTypeData (typeof(string));
+ else return GetTypeData (attr.SchemaType, typeQName, attr.Name, sharedAnnType, null);
+ }
+
+ TypeData GetTypeData (XmlQualifiedName typeQName, XmlQualifiedName root)
+ {
+ if (IsPrimitiveTypeNamespace (typeQName.Namespace)) {
+ XmlTypeMapping map = ImportType (typeQName, root, false);
+ if (map != null) return map.TypeData;
+ else return TypeTranslator.GetPrimitiveTypeData (typeQName.Name);
+ }
+
+ if (encodedFormat && typeQName.Namespace == "")
+ return TypeTranslator.GetPrimitiveTypeData (typeQName.Name);
+
+ return ImportType (typeQName, root, true).TypeData;
+ }
+
+ TypeData GetTypeData (XmlSchemaType stype, XmlQualifiedName typeQNname, string propertyName, bool sharedAnnType, XmlQualifiedName root)
+ {
+ string baseName;
+
+ if (sharedAnnType)
+ {
+ // Anonymous types defined in root elements or attributes can be shared among all elements that
+ // reference this root element or attribute
+ TypeData std = sharedAnonymousTypes [stype] as TypeData;
+ if (std != null) return std;
+ baseName = propertyName;
+ }
+ else
+ baseName = typeQNname.Name + typeIdentifiers.MakeRightCase (propertyName);
+
+ baseName = elemIdentifiers.AddUnique (baseName, stype);
+
+ XmlQualifiedName newName;
+ newName = new XmlQualifiedName (baseName, typeQNname.Namespace);
+
+ XmlTypeMapping map = ImportType (newName, stype, root);
+ if (sharedAnnType) sharedAnonymousTypes [stype] = map.TypeData;
+
+ return map.TypeData;
+ }
+
+ XmlTypeMapping GetTypeMapping (TypeData typeData)
+ {
+ if (typeData.Type == typeof(object) && !anyTypeImported)
+ ImportAllObjectTypes ();
+
+ XmlTypeMapping map = (XmlTypeMapping) dataMappedTypes [typeData];
+ if (map != null) return map;
+
+ if (typeData.IsListType)
+ {
+ // Create an array map for the type
+
+ XmlTypeMapping itemMap = GetTypeMapping (typeData.ListItemTypeData);
+
+ map = new XmlTypeMapping (typeData.XmlType, itemMap.Namespace, typeData, typeData.XmlType, itemMap.Namespace);
+ map.IncludeInSchema = true;
+
+ ListMap listMap = new ListMap ();
+ listMap.ItemInfo = new XmlTypeMapElementInfoList();
+ listMap.ItemInfo.Add (CreateElementInfo (itemMap.Namespace, null, typeData.ListItemTypeData.XmlType, typeData.ListItemTypeData, false, XmlSchemaForm.None));
+ map.ObjectMap = listMap;
+
+ mappedTypes [new XmlQualifiedName(map.ElementName, map.Namespace)] = map;
+ dataMappedTypes [typeData] = map;
+ return map;
+ }
+ else if (typeData.SchemaType == SchemaTypes.Primitive || typeData.Type == typeof(object) || typeof(XmlNode).IsAssignableFrom(typeData.Type))
+ {
+ return CreateSystemMap (typeData);
+ }
+
+ throw new InvalidOperationException ("Map for type " + typeData.TypeName + " not found");
+ }
+
+ void AddObjectDerivedMap (XmlTypeMapping map)
+ {
+ TypeData typeData = TypeTranslator.GetTypeData (typeof(object));
+ XmlTypeMapping omap = (XmlTypeMapping) dataMappedTypes [typeData];
+ if (omap == null)
+ omap = CreateSystemMap (typeData);
+ omap.DerivedTypes.Add (map);
+ }
+
+ XmlTypeMapping CreateSystemMap (TypeData typeData)
+ {
+ XmlTypeMapping map = new XmlTypeMapping (typeData.XmlType, XmlSchema.Namespace, typeData, typeData.XmlType, XmlSchema.Namespace);
+ map.IncludeInSchema = false;
+ map.ObjectMap = new ClassMap ();
+ dataMappedTypes [typeData] = map;
+ return map;
+ }
+
+ void ImportAllObjectTypes ()
+ {
+ // All complex types are subtypes of anyType, so all of them
+ // must also be imported
+
+ anyTypeImported = true;
+ foreach (XmlSchema schema in schemas) {
+ foreach (XmlSchemaObject sob in schema.Items)
+ {
+ XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
+ if (sct != null)
+ ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
+ }
+ }
+ }
+
+
+ XmlTypeMapping GetRegisteredTypeMapping (XmlQualifiedName typeQName)
+ {
+ return (XmlTypeMapping) mappedTypes [typeQName];
+ }
+
+ XmlSchemaParticle GetRefGroupParticle (XmlSchemaGroupRef refGroup)
+ {
+ XmlSchemaGroup grp = (XmlSchemaGroup) schemas.Find (refGroup.RefName, typeof (XmlSchemaGroup));
+ return grp.Particle;
+ }
+
+ XmlSchemaElement FindRefElement (XmlSchemaElement elem)
+ {
+ XmlSchemaElement refelem = (XmlSchemaElement) schemas.Find (elem.RefName, typeof(XmlSchemaElement));
+ if (refelem != null) return refelem;
+
+ if (IsPrimitiveTypeNamespace (elem.RefName.Namespace))
+ {
+ if (anyElement != null) return anyElement;
+ anyElement = new XmlSchemaElement ();
+ anyElement.Name = "any";
+ anyElement.SchemaTypeName = anyType;
+ return anyElement;
+ } else
+ return null;
+ }
+
+ XmlSchemaAttribute FindRefAttribute (XmlQualifiedName refName)
+ {
+ if (refName.Namespace == XmlNamespace)
+ {
+ XmlSchemaAttribute at = new XmlSchemaAttribute ();
+ at.Name = refName.Name;
+ at.SchemaTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace);
+ return at;
+ }
+ return (XmlSchemaAttribute) schemas.Find (refName, typeof(XmlSchemaAttribute));
+ }
+
+ XmlSchemaAttributeGroup FindRefAttributeGroup (XmlQualifiedName refName)
+ {
+ XmlSchemaAttributeGroup grp = (XmlSchemaAttributeGroup) schemas.Find (refName, typeof(XmlSchemaAttributeGroup));
+ foreach (XmlSchemaObject at in grp.Attributes)
+ {
+ if (at is XmlSchemaAttributeGroupRef && ((XmlSchemaAttributeGroupRef)at).RefName == refName)
+ throw new InvalidOperationException ("Cannot import attribute group '" + refName.Name + "' from namespace '" + refName.Namespace + "'. Redefine not supported");
+
+ }
+ return grp;
+ }
+
+ XmlTypeMapping ReflectType (Type type)
+ {
+ TypeData typeData = TypeTranslator.GetTypeData (type);
+ return ReflectType (typeData, (string) null);
+ }
+
+ XmlTypeMapping ReflectType (TypeData typeData, string ns)
+ {
+ if (!encodedFormat)
+ {
+ if (auxXmlRefImporter == null) auxXmlRefImporter = new XmlReflectionImporter ();
+ return auxXmlRefImporter.ImportTypeMapping (typeData, ns);
+ }
+ else
+ {
+ if (auxSoapRefImporter == null) auxSoapRefImporter = new SoapReflectionImporter ();
+ return auxSoapRefImporter.ImportTypeMapping (typeData, ns);
+ }
+ }
+
+
+ string GetDocumentation (XmlSchemaAnnotated elem)
+ {
+ string res = "";
+ XmlSchemaAnnotation anot = elem.Annotation;
+ if (anot == null || anot.Items == null) return null;
+
+ foreach (object ob in anot.Items)
+ {
+ XmlSchemaDocumentation doc = ob as XmlSchemaDocumentation;
+ if (doc != null && doc.Markup != null && doc.Markup.Length > 0) {
+ if (res != string.Empty) res += "\n";
+ foreach (XmlNode node in doc.Markup)
+ res += node.Value;
+ }
+ }
+ return res;
+ }
+
+ bool IsPrimitiveTypeNamespace (string ns)
+ {
+ return (ns == XmlSchema.Namespace) || (encodedFormat && ns == XmlSerializer.EncodingNamespace);
+ }
+
+ #endregion // Methods
+ }
+}