Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlTypeMapping.cs
index 0fd174ce84dcc326abf3fa8d5afa512967893aa1..2b0f8bd829d2768ed76993523618639fae3e1f0c 100644 (file)
-//\r
-// XmlTypeMapping.cs: \r
-//\r
-// Author:\r
-//   John Donagher (john@webmeta.com)\r
-//   Lluis Sanchez Gual (lluis@ximian.com)\r
-//\r
-// (C) 2002 John Donagher\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
-using System;\r
-using System.Collections;\r
-using System.Globalization;\r
-using System.Xml.Schema;\r
-\r
-namespace System.Xml.Serialization\r
-{\r
-       public class XmlTypeMapping : XmlMapping\r
-       {\r
-               private string xmlType;\r
-               private string xmlTypeNamespace;\r
-               TypeData type;\r
-               XmlTypeMapping baseMap;\r
-               bool multiReferenceType = false;\r
-               bool isSimpleType;\r
-               string documentation;\r
-               bool includeInSchema;\r
-               bool isNullable = true;\r
-\r
-               ArrayList _derivedTypes = new ArrayList();\r
-\r
-               internal XmlTypeMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)\r
-               : base (elementName, ns)\r
-               {\r
-                       this.type = typeData;\r
-                       this.xmlType = xmlType;\r
-                       this.xmlTypeNamespace = xmlTypeNamespace;\r
-               }\r
-\r
-#if !NET_2_0\r
-               public string ElementName\r
-               {\r
-                       get { return _elementName; }\r
-               }\r
-\r
-               public string Namespace\r
-               {\r
-                       get { return _namespace; }\r
-               }\r
-#endif\r
-\r
-               public string TypeFullName\r
-               {\r
-                       get { return type.FullTypeName; }\r
-               }\r
-\r
-               public string TypeName\r
-               {\r
-                       get { return type.TypeName; }\r
-               }\r
-\r
-               internal TypeData TypeData\r
-               {\r
-                       get { return type; }\r
-               }\r
-\r
-               internal string XmlType\r
-               {\r
-                       get { return xmlType; }\r
-               }\r
-\r
-               internal string XmlTypeNamespace\r
-               {\r
-                       get { return xmlTypeNamespace; }\r
-               }\r
-\r
-               internal ArrayList DerivedTypes\r
-               {\r
-                       get { return _derivedTypes; }\r
-                       set { _derivedTypes = value; }\r
-               }\r
-\r
-               internal bool MultiReferenceType\r
-               {\r
-                       get { return multiReferenceType; }\r
-                       set { multiReferenceType = value; }\r
-               }\r
-\r
-               internal XmlTypeMapping BaseMap\r
-               {\r
-                       get { return baseMap; }\r
-                       set { baseMap = value; }\r
-               }\r
-\r
-               internal bool IsSimpleType\r
-               {\r
-                       get { return isSimpleType; }\r
-                       set { isSimpleType = value; }\r
-               }\r
-\r
-               internal string Documentation\r
-               {\r
-                       set { documentation = value; }\r
-                       get { return documentation; }\r
-               }\r
-\r
-               internal bool IncludeInSchema\r
-               {\r
-                       get { return includeInSchema; }\r
-                       set { includeInSchema = value; }\r
-               }\r
-               \r
-               internal bool IsNullable\r
-               {\r
-                       get { return isNullable; }\r
-                       set { isNullable = value; }\r
-               }\r
-\r
-               internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName)\r
-               {\r
-                       if (TypeData.SchemaType == SchemaTypes.Enum)\r
-                               return this;\r
-\r
-                       // Returns the map for a subtype of this map's type\r
-                       objectFullTypeName = objectFullTypeName.Replace ('+','.');\r
-                       if (TypeFullName == objectFullTypeName) return this;\r
-                       for (int n=0; n<_derivedTypes.Count; n++) {\r
-                               XmlTypeMapping map = (XmlTypeMapping) _derivedTypes[n];\r
-                               if (map.TypeFullName == objectFullTypeName) return map;\r
-                       }\r
-                       \r
-                       return null;\r
-               }\r
-\r
-               internal XmlTypeMapping GetRealElementMap (string name, string ens)\r
-               {\r
-                       if (xmlType == name && xmlTypeNamespace == ens) return this;\r
-                       foreach (XmlTypeMapping map in _derivedTypes)\r
-                               if (map.xmlType == name && map.xmlTypeNamespace == ens) return map;\r
-                       \r
-                       return null;\r
-               }\r
-               \r
-               internal void UpdateRoot (XmlQualifiedName qname)\r
-               {\r
-                       if (qname != null) {\r
-                               this._elementName = qname.Name;\r
-                               this._namespace = qname.Namespace;\r
-                       }\r
-               }\r
-       }\r
-\r
\r
-       // Mapping info for XmlSerializable\r
-       internal class XmlSerializableMapping : XmlTypeMapping\r
-       {\r
-               XmlSchema _schema;\r
-\r
-               internal XmlSerializableMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)\r
-                       : base(elementName, ns, typeData, xmlType, xmlTypeNamespace)\r
-               {\r
-                       IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance(typeData.Type);\r
-                       _schema = serializable.GetSchema();\r
-                       if (_schema != null) \r
-                       {\r
-                               if (_schema.Id == null || _schema.Id.Length == 0) \r
-                                       throw new InvalidOperationException("Schema Id is missing. The schema returned from " + typeData.Type.FullName + ".GetSchema() must have an Id.");\r
-                       }\r
-               }\r
-\r
-               internal XmlSchema Schema\r
-               {\r
-                       get { return _schema; }\r
-               }\r
-       }\r
\r
-\r
-       // Mapping info for classes and structs\r
-\r
-       internal class ClassMap: ObjectMap\r
-       {\r
-               Hashtable _elements = new Hashtable ();\r
-               ArrayList _elementMembers;\r
-               Hashtable _attributeMembers;\r
-               XmlTypeMapMemberAttribute[] _attributeMembersArray;\r
-               XmlTypeMapElementInfo[] _elementsByIndex;\r
-               ArrayList _flatLists;\r
-               ArrayList _allMembers = new ArrayList ();\r
-               ArrayList _membersWithDefault;\r
-               ArrayList _listMembers;\r
-               XmlTypeMapMemberAnyElement _defaultAnyElement;\r
-               XmlTypeMapMemberAnyAttribute _defaultAnyAttribute;\r
-               XmlTypeMapMemberNamespaces _namespaceDeclarations;\r
-               XmlTypeMapMember _xmlTextCollector;\r
-               XmlTypeMapMember _returnMember;\r
-               bool _ignoreMemberNamespace;\r
-               bool _canBeSimpleType = true;\r
-\r
-               public void AddMember (XmlTypeMapMember member)\r
-               {\r
-                       member.GlobalIndex = _allMembers.Count;\r
-                       _allMembers.Add (member);\r
-                       \r
-                       if (!(member.DefaultValue is System.DBNull) && member.DefaultValue != null) {\r
-                               if (_membersWithDefault == null) _membersWithDefault = new ArrayList ();\r
-                               _membersWithDefault.Add (member);\r
-                       }\r
-                       \r
-                       if (member.IsReturnValue)\r
-                               _returnMember = member;\r
-                       \r
-                       if (member is XmlTypeMapMemberAttribute)\r
-                       {\r
-                               XmlTypeMapMemberAttribute atm = (XmlTypeMapMemberAttribute)member;\r
-                               if (_attributeMembers == null) _attributeMembers = new Hashtable();\r
-                               string key = BuildKey (atm.AttributeName, atm.Namespace);\r
-                               if (_attributeMembers.ContainsKey (key))\r
-                                       throw new InvalidOperationException ("The XML attribute named '" + atm.AttributeName + "' from namespace '" + atm.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the attribute.");\r
-                               member.Index = _attributeMembers.Count;\r
-                               _attributeMembers.Add (key, member);\r
-                               return;\r
-                       }\r
-                       else if (member is XmlTypeMapMemberFlatList)\r
-                       {\r
-                               RegisterFlatList ((XmlTypeMapMemberFlatList)member);\r
-                       }\r
-                       else if (member is XmlTypeMapMemberAnyElement)\r
-                       {\r
-                               XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement) member;\r
-                               if (mem.IsDefaultAny) _defaultAnyElement = mem;\r
-                               if (mem.TypeData.IsListType) RegisterFlatList (mem);\r
-                       }\r
-                       else if (member is XmlTypeMapMemberAnyAttribute)\r
-                       {\r
-                               _defaultAnyAttribute = (XmlTypeMapMemberAnyAttribute) member;\r
-                               return;\r
-                       }\r
-                       else if (member is XmlTypeMapMemberNamespaces)\r
-                       {\r
-                               _namespaceDeclarations = (XmlTypeMapMemberNamespaces) member;\r
-                               return;\r
-                       }\r
-\r
-                       if (member is XmlTypeMapMemberElement && ((XmlTypeMapMemberElement)member).IsXmlTextCollector)\r
-                       {\r
-                               if (_xmlTextCollector != null) throw new InvalidOperationException ("XmlTextAttribute can only be applied once in a class");\r
-                               _xmlTextCollector = member;\r
-                       }\r
-\r
-                       if (_elementMembers == null) {\r
-                               _elementMembers = new ArrayList();\r
-                               _elements = new Hashtable();\r
-                       }\r
-\r
-                       member.Index = _elementMembers.Count;\r
-                       _elementMembers.Add (member);\r
-\r
-                       ICollection elemsInfo = ((XmlTypeMapMemberElement)member).ElementInfo;\r
-                       foreach (XmlTypeMapElementInfo elem in elemsInfo)\r
-                       {\r
-                               string key = BuildKey (elem.ElementName, elem.Namespace);\r
-                               if (_elements.ContainsKey (key)) \r
-                                       throw new InvalidOperationException ("The XML element named '" + elem.ElementName + "' from namespace '" + elem.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.");\r
-                               _elements.Add (key, elem);\r
-                       }\r
-                       \r
-                       if (member.TypeData.IsListType && member.TypeData.Type != null && !member.TypeData.Type.IsArray) {\r
-                               if (_listMembers == null) _listMembers = new ArrayList ();\r
-                               _listMembers.Add (member);\r
-                       }\r
-               }\r
-\r
-               void RegisterFlatList (XmlTypeMapMemberExpandable member)\r
-               {\r
-                       if (_flatLists == null) _flatLists = new ArrayList ();\r
-                       member.FlatArrayIndex = _flatLists.Count;\r
-                       _flatLists.Add (member);\r
-               }\r
-\r
-               public XmlTypeMapMemberAttribute GetAttribute (string name, string ns)\r
-               {\r
-                       if (_attributeMembers == null) return null;\r
-                       return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey(name,ns)];\r
-               }\r
-\r
-               public XmlTypeMapElementInfo GetElement (string name, string ns)\r
-               {\r
-                       if (_elements == null) return null;\r
-                       return (XmlTypeMapElementInfo)_elements [BuildKey(name,ns)];\r
-               }\r
-               \r
-               public XmlTypeMapElementInfo GetElement (int index)\r
-               {\r
-                       if (_elements == null) return null;\r
-                       \r
-                       if (_elementsByIndex == null)\r
-                       {\r
-                               _elementsByIndex = new XmlTypeMapElementInfo [_elementMembers.Count];\r
-                               foreach (XmlTypeMapMemberElement mem in _elementMembers)\r
-                               {\r
-                                       if (mem.ElementInfo.Count != 1) \r
-                                               throw new InvalidOperationException ("Read by order only possible for encoded/bare format");\r
-                                               \r
-                                       _elementsByIndex [mem.Index] = (XmlTypeMapElementInfo) mem.ElementInfo [0];\r
-                               }\r
-                       }\r
-                       \r
-                       return _elementsByIndex [index];\r
-               }\r
-               \r
-               private string BuildKey (string name, string ns)\r
-               {\r
-                       if (_ignoreMemberNamespace) return name;\r
-                       else return name + " / " + ns;\r
-               }\r
-               \r
-               public ICollection AllElementInfos\r
-               {\r
-                       get { return _elements.Values; }\r
-               }\r
-               \r
-               \r
-               public bool IgnoreMemberNamespace\r
-               {\r
-                       get { return _ignoreMemberNamespace; }\r
-                       set { _ignoreMemberNamespace = value; }\r
-               }\r
-\r
-               public XmlTypeMapMember FindMember (string name)\r
-               {\r
-                       for (int n=0; n<_allMembers.Count; n++)\r
-                               if (((XmlTypeMapMember)_allMembers[n]).Name == name) return (XmlTypeMapMember)_allMembers[n];\r
-                       return null;\r
-               }\r
-\r
-               public XmlTypeMapMemberAnyElement DefaultAnyElementMember\r
-               {\r
-                       get { return _defaultAnyElement; }\r
-               }\r
-\r
-               public XmlTypeMapMemberAnyAttribute DefaultAnyAttributeMember\r
-               {\r
-                       get { return _defaultAnyAttribute; }\r
-               }\r
-\r
-               public XmlTypeMapMemberNamespaces NamespaceDeclarations\r
-               {\r
-                       get { return _namespaceDeclarations; }\r
-               }\r
-\r
-               public ICollection AttributeMembers\r
-               {\r
-                       get \r
-                       {\r
-                               if (_attributeMembers == null) return null;\r
-                               if (_attributeMembersArray != null) return _attributeMembersArray;\r
-                               \r
-                               _attributeMembersArray = new XmlTypeMapMemberAttribute[_attributeMembers.Count];\r
-                               foreach (XmlTypeMapMemberAttribute mem in _attributeMembers.Values)\r
-                                       _attributeMembersArray [mem.Index] = mem;\r
-                               return _attributeMembersArray;\r
-                       }\r
-               }\r
-\r
-               public ICollection ElementMembers\r
-               {\r
-                       get { return _elementMembers; }\r
-               }\r
-\r
-               public ArrayList AllMembers\r
-               {\r
-                       get { return _allMembers; }\r
-               }\r
-\r
-               public ArrayList FlatLists\r
-               {\r
-                       get { return _flatLists; }\r
-               }\r
-               \r
-               public ArrayList MembersWithDefault\r
-               {\r
-                       get { return _membersWithDefault; }\r
-               }\r
-               \r
-               public ArrayList ListMembers\r
-               {\r
-                       get { return _listMembers; }\r
-               }\r
-\r
-               public XmlTypeMapMember XmlTextCollector\r
-               {\r
-                       get { return _xmlTextCollector; }\r
-               }\r
-               \r
-               public XmlTypeMapMember ReturnMember\r
-               {\r
-                       get { return _returnMember; }\r
-               }\r
-\r
-               public XmlQualifiedName SimpleContentBaseType\r
-               {\r
-                       get\r
-                       {\r
-                               if (!_canBeSimpleType || _elementMembers == null || _elementMembers.Count != 1) return null;\r
-                               XmlTypeMapMemberElement member = (XmlTypeMapMemberElement) _elementMembers[0];\r
-                               if (member.ElementInfo.Count != 1) return null;\r
-                               XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo[0];\r
-                               if (!einfo.IsTextElement) return null;\r
-                               if (member.TypeData.SchemaType == SchemaTypes.Primitive || member.TypeData.SchemaType == SchemaTypes.Enum)\r
-                                       return new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace);\r
-                               return null;\r
-                       }\r
-               }\r
-               \r
-               public void SetCanBeSimpleType (bool can)\r
-               {\r
-                       _canBeSimpleType = can;\r
-               }\r
-\r
-               public bool HasSimpleContent\r
-               {\r
-                       get\r
-                       {\r
-                               return SimpleContentBaseType != null;\r
-                       }\r
-               }\r
-\r
-       }\r
-\r
-       // Mapping info for arrays and lists\r
-\r
-       internal class ListMap: ObjectMap\r
-       {\r
-               XmlTypeMapElementInfoList _itemInfo;\r
-               bool _gotNestedMapping;\r
-               XmlTypeMapping _nestedArrayMapping;\r
-               string _choiceMember;\r
-\r
-               public bool IsMultiArray\r
-               {\r
-                       get\r
-                       {\r
-                               return (NestedArrayMapping != null);\r
-                       }\r
-               }\r
-\r
-               public string ChoiceMember\r
-               {\r
-                       get { return _choiceMember; }\r
-                       set { _choiceMember = value; }\r
-               }\r
-\r
-               public XmlTypeMapping NestedArrayMapping\r
-               {\r
-                       get\r
-                       {\r
-                               if (_gotNestedMapping) return _nestedArrayMapping;\r
-                               _gotNestedMapping = true;\r
-\r
-                               _nestedArrayMapping = ((XmlTypeMapElementInfo)_itemInfo[0]).MappedType;\r
-\r
-                               if (_nestedArrayMapping == null) return null;\r
-                               \r
-                               if (_nestedArrayMapping.TypeData.SchemaType != SchemaTypes.Array) {\r
-                                       _nestedArrayMapping = null; return null;\r
-                               }\r
-\r
-                               foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
-                                       if (elem.MappedType != _nestedArrayMapping) {\r
-                                               _nestedArrayMapping = null;\r
-                                               return null;\r
-                                       }\r
-\r
-                               return _nestedArrayMapping;\r
-                       }\r
-               }\r
-\r
-               public XmlTypeMapElementInfoList ItemInfo\r
-               {\r
-\r
-                       get { return _itemInfo; }\r
-                       set { _itemInfo = value; }\r
-               }\r
-\r
-               public XmlTypeMapElementInfo FindElement (object ob, int index, object memberValue)\r
-               {\r
-                       if (_itemInfo.Count == 1) \r
-                               return (XmlTypeMapElementInfo) _itemInfo[0];\r
-                       else if (_choiceMember != null && index != -1)\r
-                       {\r
-                               Array values = (Array) XmlTypeMapMember.GetValue (ob, _choiceMember);\r
-                               if (values == null || index >= values.Length)\r
-                                       throw new InvalidOperationException ("Invalid or missing choice enum value in member '" + _choiceMember + "'.");\r
-                               object val = values.GetValue (index);\r
-                               foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
-                                       if (elem.ChoiceValue != null && elem.ChoiceValue.Equals (val))\r
-                                               return elem;\r
-                       }\r
-                       else\r
-                       {\r
-                               if (memberValue == null) return null;\r
-                               Type type = memberValue.GetType();\r
-                               foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
-                                       if (elem.TypeData.Type == type) return elem;\r
-                       }\r
-                       return null;\r
-               }       \r
-\r
-               public XmlTypeMapElementInfo FindElement (string elementName, string ns)\r
-               {\r
-                       foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
-                               if (elem.ElementName == elementName && elem.Namespace == ns) return elem;\r
-                       return null;\r
-               }\r
-               \r
-               public XmlTypeMapElementInfo FindTextElement ()\r
-               {\r
-                       foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
-                               if (elem.IsTextElement) return elem;\r
-                       return null;\r
-               }\r
-               \r
-               public string GetSchemaArrayName ()\r
-               {\r
-                       XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) _itemInfo[0];\r
-                       if (einfo.MappedType != null) return TypeTranslator.GetArrayName (einfo.MappedType.XmlType);\r
-                       else return TypeTranslator.GetArrayName (einfo.TypeData.XmlType);\r
-               }\r
-\r
-               public void GetArrayType (int itemCount, out string localName, out string ns)\r
-               {\r
-                       string arrayDim;\r
-                       if (itemCount != -1) arrayDim = "[" + itemCount + "]";\r
-                       else arrayDim = "[]";\r
-\r
-                       XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) _itemInfo[0];\r
-                       if (info.TypeData.SchemaType == SchemaTypes.Array)\r
-                       {\r
-                               string nm;\r
-                               ((ListMap)info.MappedType.ObjectMap).GetArrayType (-1, out nm, out ns);\r
-                               localName = nm + arrayDim;\r
-                       }\r
-                       else \r
-                       {\r
-                               if (info.MappedType != null)\r
-                               {\r
-                                       localName = info.MappedType.XmlType + arrayDim;\r
-                                       ns = info.MappedType.Namespace;\r
-                               }\r
-                               else \r
-                               {\r
-                                       localName = info.TypeData.XmlType + arrayDim;\r
-                                       ns = info.DataTypeNamespace;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               public override bool Equals (object other)\r
-               {\r
-                       ListMap lmap = other as ListMap;\r
-                       if (lmap == null) return false;\r
-\r
-                       if (_itemInfo.Count != lmap._itemInfo.Count) return false;\r
-                       for (int n=0; n<_itemInfo.Count; n++)\r
-                               if (!_itemInfo[n].Equals (lmap._itemInfo[n])) return false;\r
-                       return true;\r
-               }\r
-\r
-               public override int GetHashCode ()\r
-               {\r
-                       return base.GetHashCode ();\r
-               }\r
-       }\r
-\r
-       internal class EnumMap: ObjectMap\r
-       {\r
-               readonly EnumMapMember[] _members;\r
-               readonly bool _isFlags;\r
-               readonly string[] _enumNames = null;\r
-               readonly string[] _xmlNames = null;\r
-               readonly long[] _values = null;\r
-\r
-               public class EnumMapMember\r
-               {\r
-                       readonly string _xmlName;\r
-                       readonly string _enumName;\r
-                       readonly long _value;\r
-                       string _documentation;\r
-\r
-                       public EnumMapMember (string xmlName, string enumName)\r
-                               : this (xmlName, enumName, 0)\r
-                       {\r
-                       }\r
-\r
-                       public EnumMapMember (string xmlName, string enumName, long value)\r
-                       {\r
-                               _xmlName = xmlName;\r
-                               _enumName = enumName;\r
-                               _value = value;\r
-                       }\r
-\r
-                       public string XmlName\r
-                       {\r
-                               get { return _xmlName; }\r
-                       }\r
-\r
-                       public string EnumName\r
-                       {\r
-                               get { return _enumName; }\r
-                       }\r
-\r
-                       public long Value\r
-                       {\r
-                               get { return _value; }\r
-                       }\r
-\r
-                       public string Documentation\r
-                       {\r
-                               get { return _documentation; }\r
-                               set { _documentation = value; }\r
-                       }\r
-               }\r
-\r
-               public EnumMap (EnumMapMember[] members, bool isFlags)\r
-               {\r
-                       _members = members;\r
-                       _isFlags = isFlags;\r
-\r
-                       _enumNames = new string[_members.Length];\r
-                       _xmlNames = new string[_members.Length];\r
-                       _values = new long[_members.Length];\r
-\r
-                       for (int i = 0; i < _members.Length; i++) {\r
-                               EnumMapMember mem = _members[i];\r
-                               _enumNames[i] = mem.EnumName;\r
-                               _xmlNames[i] = mem.XmlName;\r
-                               _values[i] = mem.Value;\r
-                       }\r
-               }\r
-               \r
-               public bool IsFlags\r
-               {\r
-                       get { return _isFlags; }\r
-               }\r
-\r
-               public EnumMapMember[] Members\r
-               {\r
-                       get { return _members; }\r
-               }\r
-\r
-               public string[] EnumNames\r
-               {\r
-                       get {\r
-                               return _enumNames;\r
-                       }\r
-               }\r
-\r
-               public string[] XmlNames\r
-               {\r
-                       get {\r
-                               return _xmlNames;\r
-                       }\r
-               }\r
-\r
-               public long[] Values\r
-               {\r
-                       get {\r
-                               return _values;\r
-                       }\r
-               }\r
-\r
-               public string GetXmlName (string typeName, object enumValue)\r
-               {\r
-                       if (enumValue is string) {\r
-                               throw new InvalidCastException ();\r
-                       }\r
-\r
-                       long value = 0;\r
-\r
-                       try {\r
-                               value = ((IConvertible) enumValue).ToInt64 (CultureInfo.CurrentCulture);\r
-                       } catch (FormatException) {\r
-                               throw new InvalidCastException ();\r
-                       }\r
-\r
-                       for (int i = 0; i < Values.Length; i++) {\r
-                               if (Values[i] == value)\r
-                                       return XmlNames[i];\r
-                       }\r
-\r
-                       if (IsFlags && value == 0)\r
-                               return string.Empty;\r
-\r
-                       string xmlName = string.Empty;\r
-                       if (IsFlags) {\r
-#if NET_2_0\r
-                               xmlName = XmlCustomFormatter.FromEnum (value, XmlNames, Values, typeName);\r
-#else\r
-                               xmlName = XmlCustomFormatter.FromEnum (value, XmlNames, Values);\r
-#endif\r
-                       }\r
-\r
-                       if (xmlName.Length == 0) {\r
-#if NET_2_0\r
-                               throw new InvalidOperationException (string.Format(CultureInfo.CurrentCulture,\r
-                                       "'{0}' is not a valid value for {1}.", value, typeName));\r
-#else\r
-                               return value.ToString (CultureInfo.InvariantCulture);\r
-#endif\r
-                       }\r
-                       return xmlName;\r
-               }\r
-\r
-               public string GetEnumName (string typeName, string xmlName)\r
-               {\r
-                       if (_isFlags) {\r
-                               xmlName = xmlName.Trim ();\r
-                               if (xmlName.Length == 0)\r
-                                       return "0";\r
-\r
-                               System.Text.StringBuilder sb = new System.Text.StringBuilder ();\r
-                               string[] enumNames = xmlName.Split (null);\r
-                               foreach (string name in enumNames) {\r
-                                       if (name == string.Empty) continue;\r
-                                       string foundEnumValue = null;\r
-                                       for (int i = 0; i < XmlNames.Length; i++)\r
-                                               if (XmlNames[i] == name) {\r
-                                                       foundEnumValue = EnumNames[i];\r
-                                                       break;\r
-                                               }\r
-\r
-                                       if (foundEnumValue != null) {\r
-                                               if (sb.Length > 0)\r
-                                                       sb.Append (',');\r
-                                               sb.Append (foundEnumValue);\r
-                                       } else {\r
-                                               throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,\r
-                                                       "'{0}' is not a valid value for {1}.", name, typeName));\r
-                                       }\r
-                               }\r
-                               return sb.ToString ();\r
-                       }\r
-\r
-                       foreach (EnumMapMember mem in _members)\r
-                               if (mem.XmlName == xmlName) return mem.EnumName;\r
-                               \r
-                       return null;\r
-               }\r
-       }\r
-}\r
+//
+// XmlTypeMapping.cs: 
+//
+// Author:
+//   John Donagher (john@webmeta.com)
+//   Lluis Sanchez Gual (lluis@ximian.com)
+//
+// (C) 2002 John Donagher
+//
+
+//
+// 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;
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Xml.Schema;
+using System.Reflection;
+
+namespace System.Xml.Serialization
+{
+       public class XmlTypeMapping : XmlMapping
+       {
+               private string xmlType;
+               private string xmlTypeNamespace;
+               TypeData type;
+               XmlTypeMapping baseMap;
+               bool multiReferenceType = false;
+               bool isSimpleType;
+               string documentation;
+               bool includeInSchema;
+               bool isNullable = true;
+
+               ArrayList _derivedTypes = new ArrayList();
+
+               internal XmlTypeMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)
+               : base (elementName, ns)
+               {
+                       this.type = typeData;
+                       this.xmlType = xmlType;
+                       this.xmlTypeNamespace = xmlTypeNamespace;
+               }
+
+#if !NET_2_0
+               public string ElementName
+               {
+                       get { return _elementName; }
+               }
+
+               public string Namespace
+               {
+                       get { return _namespace; }
+               }
+#endif
+
+               public string TypeFullName
+               {
+                       get { return type.FullTypeName; }
+               }
+
+               public string TypeName
+               {
+                       get { return type.TypeName; }
+               }
+
+#if NET_2_0
+               public string XsdTypeName
+               {
+                       get { return XmlType; }
+               }
+
+               public string XsdTypeNamespace
+               {
+                       get { return XmlTypeNamespace; }
+               }
+#endif
+
+               internal TypeData TypeData
+               {
+                       get { return type; }
+               }
+
+               internal string XmlType
+               {
+                       get { return xmlType; }
+                       set { xmlType = value; }
+               }
+
+               internal string XmlTypeNamespace
+               {
+                       get { return xmlTypeNamespace ?? string.Empty; }
+                       set { xmlTypeNamespace = value; }
+               }
+
+               internal bool HasXmlTypeNamespace
+               {
+                       get { return xmlTypeNamespace != null; }
+               }
+
+               internal ArrayList DerivedTypes
+               {
+                       get { return _derivedTypes; }
+                       set { _derivedTypes = value; }
+               }
+
+               internal bool MultiReferenceType
+               {
+                       get { return multiReferenceType; }
+                       set { multiReferenceType = value; }
+               }
+
+               internal XmlTypeMapping BaseMap
+               {
+                       get { return baseMap; }
+                       set { baseMap = value; }
+               }
+
+               internal bool IsSimpleType
+               {
+                       get { return isSimpleType; }
+                       set { isSimpleType = value; }
+               }
+
+               internal string Documentation
+               {
+                       set { documentation = value; }
+                       get { return documentation; }
+               }
+
+               internal bool IncludeInSchema
+               {
+                       get { return includeInSchema; }
+                       set { includeInSchema = value; }
+               }
+               
+               internal bool IsNullable
+               {
+                       get { return isNullable; }
+                       set { isNullable = value; }
+               }
+
+               internal XmlTypeMapping GetRealTypeMap (Type objectType)
+               {
+                       if (TypeData.SchemaType == SchemaTypes.Enum)
+                               return this;
+
+                       // Returns the map for a subtype of this map's type
+                       if (TypeData.Type == objectType) return this;
+                       for (int n=0; n<_derivedTypes.Count; n++) {
+                               XmlTypeMapping map = (XmlTypeMapping) _derivedTypes[n];
+                               if (map.TypeData.Type == objectType) return map;
+                       }
+                       
+                       return null;
+               }
+
+               internal XmlTypeMapping GetRealElementMap (string name, string ens)
+               {
+                       if (xmlType == name && XmlTypeNamespace == ens) return this;
+                       foreach (XmlTypeMapping map in _derivedTypes)
+                               if (map.xmlType == name && map.XmlTypeNamespace == ens) return map;
+                       
+                       return null;
+               }
+               
+               internal void UpdateRoot (XmlQualifiedName qname)
+               {
+                       if (qname != null) {
+                               this._elementName = qname.Name;
+                               this._namespace = qname.Namespace;
+                       }
+               }
+       }
+
+       // Mapping info for XmlSerializable
+       internal class XmlSerializableMapping : XmlTypeMapping
+       {
+               XmlSchema _schema;
+#if NET_2_0 && !MOONLIGHT
+               XmlSchemaComplexType _schemaType;
+               XmlQualifiedName _schemaTypeName;
+#endif
+
+               internal XmlSerializableMapping(XmlRootAttribute root, string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)
+                       : base(elementName, ns, typeData, xmlType, xmlTypeNamespace)
+               {
+#if NET_2_0 && !MOONLIGHT
+                       XmlSchemaProviderAttribute schemaProvider = (XmlSchemaProviderAttribute) Attribute.GetCustomAttribute (typeData.Type, typeof (XmlSchemaProviderAttribute));
+
+                       if (schemaProvider != null) {
+                               string method = schemaProvider.MethodName;
+                               MethodInfo mi = typeData.Type.GetMethod (method, BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
+                               if (mi == null)
+                                       throw new InvalidOperationException (String.Format ("Type '{0}' must implement public static method '{1}'", typeData.Type, method));
+                               if (!typeof (XmlQualifiedName).IsAssignableFrom (mi.ReturnType) &&
+                                   // LAMESPEC: it is undocumented. (We don't have to tell users about it in the error message.)
+                                   // Also do not add such a silly compatibility test to assert that it does not raise an error.
+                                   !typeof (XmlSchemaComplexType).IsAssignableFrom (mi.ReturnType))
+                                       throw new InvalidOperationException (String.Format ("Method '{0}' indicated by XmlSchemaProviderAttribute must have its return type as XmlQualifiedName", method));
+                               XmlSchemaSet xs = new XmlSchemaSet ();
+                               object retVal = mi.Invoke (null, new object [] { xs });
+                               _schemaTypeName = XmlQualifiedName.Empty;
+                               if (retVal == null)
+                                       return;
+
+                               if (retVal is XmlSchemaComplexType) {
+                                       _schemaType = (XmlSchemaComplexType) retVal;
+                                       if (!_schemaType.QualifiedName.IsEmpty)
+                                               _schemaTypeName = _schemaType.QualifiedName;
+                                       else
+                                               _schemaTypeName = new XmlQualifiedName (xmlType, xmlTypeNamespace);
+                               }
+                               else if (retVal is XmlQualifiedName) {
+                                       _schemaTypeName = (XmlQualifiedName)retVal;
+                               }
+                               else
+                                       throw new InvalidOperationException (
+                                               String.Format ("Method {0}.{1}() specified by XmlSchemaProviderAttribute has invalid signature: return type must be compatible with System.Xml.XmlQualifiedName.", typeData.Type.Name, method));
+
+                               // defaultNamespace at XmlReflectionImporter takes precedence for Namespace, but not for XsdTypeNamespace.
+                               UpdateRoot (new XmlQualifiedName (root != null ? root.ElementName : _schemaTypeName.Name, root != null ? root.Namespace : Namespace ?? _schemaTypeName.Namespace));
+                               XmlTypeNamespace = _schemaTypeName.Namespace;
+                               XmlType = _schemaTypeName.Name;
+
+                               if (!_schemaTypeName.IsEmpty && xs.Count > 0) {
+                                       XmlSchema [] schemas = new XmlSchema [xs.Count];
+                                       xs.CopyTo (schemas, 0);
+                                       _schema = schemas [0];
+                               }
+
+                               return;
+                       }
+#endif
+#if NET_2_0 && !MOONLIGHT
+                       IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance (typeData.Type, true);
+                       try {
+                               _schema = serializable.GetSchema();
+                       } catch (Exception) {
+                               // LAMESPEC: .NET has a bad exception catch and swallows it silently.
+                       }
+#else
+                       IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance (typeData.Type);
+                       _schema = serializable.GetSchema();
+#endif
+#if !MOONLIGHT
+                       if (_schema != null) 
+                       {
+                               if (_schema.Id == null || _schema.Id.Length == 0) 
+                                       throw new InvalidOperationException("Schema Id is missing. The schema returned from " + typeData.Type.FullName + ".GetSchema() must have an Id.");
+                       }
+#endif
+               }
+
+               internal XmlSchema Schema
+               {
+                       get { return _schema; }
+               }
+
+#if NET_2_0 && !MOONLIGHT
+               internal XmlSchemaType SchemaType {
+                       get { return _schemaType; }
+               }
+
+               internal XmlQualifiedName SchemaTypeName {
+                       get { return _schemaTypeName; }
+               }
+#endif
+       }
+
+       // Mapping info for classes and structs
+
+       internal class ClassMap: ObjectMap
+       {
+               Hashtable _elements = new Hashtable ();
+               ArrayList _elementMembers;
+               Hashtable _attributeMembers;
+               XmlTypeMapMemberAttribute[] _attributeMembersArray;
+               XmlTypeMapElementInfo[] _elementsByIndex;
+               ArrayList _flatLists;
+               ArrayList _allMembers = new ArrayList ();
+               ArrayList _membersWithDefault;
+               ArrayList _listMembers;
+               XmlTypeMapMemberAnyElement _defaultAnyElement;
+               XmlTypeMapMemberAnyAttribute _defaultAnyAttribute;
+               XmlTypeMapMemberNamespaces _namespaceDeclarations;
+               XmlTypeMapMember _xmlTextCollector;
+               XmlTypeMapMember _returnMember;
+               bool _ignoreMemberNamespace;
+               bool _canBeSimpleType = true;
+               bool? _isOrderDependentMap;
+
+               public void AddMember (XmlTypeMapMember member)
+               {
+                       // If GlobalIndex has not been set, set it now
+                       if (member.GlobalIndex == -1)
+                               member.GlobalIndex = _allMembers.Count;
+                       
+                       _allMembers.Add (member);
+                       
+                       if (!(member.DefaultValue is System.DBNull) && member.DefaultValue != null) {
+                               if (_membersWithDefault == null) _membersWithDefault = new ArrayList ();
+                               _membersWithDefault.Add (member);
+                       }
+                       
+                       if (member.IsReturnValue)
+                               _returnMember = member;
+                       
+                       if (member is XmlTypeMapMemberAttribute)
+                       {
+                               XmlTypeMapMemberAttribute atm = (XmlTypeMapMemberAttribute)member;
+                               if (_attributeMembers == null) _attributeMembers = new Hashtable();
+                               string key = BuildKey (atm.AttributeName, atm.Namespace, -1);
+                               if (_attributeMembers.ContainsKey (key))
+                                       throw new InvalidOperationException ("The XML attribute named '" + atm.AttributeName + "' from namespace '" + atm.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the attribute.");
+                               member.Index = _attributeMembers.Count;
+                               _attributeMembers.Add (key, member);
+                               return;
+                       }
+                       else if (member is XmlTypeMapMemberFlatList)
+                       {
+                               RegisterFlatList ((XmlTypeMapMemberFlatList)member);
+                       }
+                       else if (member is XmlTypeMapMemberAnyElement)
+                       {
+                               XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement) member;
+                               if (mem.IsDefaultAny) _defaultAnyElement = mem;
+                               if (mem.TypeData.IsListType) RegisterFlatList (mem);
+                       }
+                       else if (member is XmlTypeMapMemberAnyAttribute)
+                       {
+                               _defaultAnyAttribute = (XmlTypeMapMemberAnyAttribute) member;
+                               return;
+                       }
+                       else if (member is XmlTypeMapMemberNamespaces)
+                       {
+                               _namespaceDeclarations = (XmlTypeMapMemberNamespaces) member;
+                               return;
+                       }
+
+                       if (member is XmlTypeMapMemberElement && ((XmlTypeMapMemberElement)member).IsXmlTextCollector)
+                       {
+                               if (_xmlTextCollector != null) throw new InvalidOperationException ("XmlTextAttribute can only be applied once in a class");
+                               _xmlTextCollector = member;
+                       }
+
+                       if (_elementMembers == null) {
+                               _elementMembers = new ArrayList();
+                               _elements = new Hashtable();
+                       }
+
+                       member.Index = _elementMembers.Count;
+                       _elementMembers.Add (member);
+
+                       ICollection elemsInfo = ((XmlTypeMapMemberElement)member).ElementInfo;
+                       foreach (XmlTypeMapElementInfo elem in elemsInfo)
+                       {
+                               string key = BuildKey (elem.ElementName, elem.Namespace, elem.ExplicitOrder);
+                               if (_elements.ContainsKey (key)) 
+                                       throw new InvalidOperationException ("The XML element named '" + elem.ElementName + "' from namespace '" + elem.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.");
+                               _elements.Add (key, elem);
+                       }
+                       
+                       if (member.TypeData.IsListType && member.TypeData.Type != null && !member.TypeData.Type.IsArray) {
+                               if (_listMembers == null) _listMembers = new ArrayList ();
+                               _listMembers.Add (member);
+                       }
+               }
+
+               void RegisterFlatList (XmlTypeMapMemberExpandable member)
+               {
+                       if (_flatLists == null) _flatLists = new ArrayList ();
+                       member.FlatArrayIndex = _flatLists.Count;
+                       _flatLists.Add (member);
+               }
+
+               public XmlTypeMapMemberAttribute GetAttribute (string name, string ns)
+               {
+                       if (_attributeMembers == null) return null;
+                       return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey (name,ns, -1)];
+               }
+
+               public XmlTypeMapElementInfo GetElement (string name, string ns, int order)
+               {
+                       if (_elements == null) return null;
+                       return (XmlTypeMapElementInfo)_elements [BuildKey (name,ns, order)];
+               }
+
+               public XmlTypeMapElementInfo GetElement(string name, string ns)
+               {
+                       if (_elements == null) return null;
+
+                       foreach (XmlTypeMapElementInfo info in _elements.Values)
+                               if (info.ElementName == name && info.Namespace == ns)
+                                       return info;
+
+                       return null;
+               }
+               
+               public XmlTypeMapElementInfo GetElement (int index)
+               {
+                       if (_elements == null) return null;
+                       
+                       if (_elementsByIndex == null)
+                       {
+                               _elementsByIndex = new XmlTypeMapElementInfo [_elementMembers.Count];
+                               foreach (XmlTypeMapMemberElement mem in _elementMembers)
+                               {
+                                       if (mem.ElementInfo.Count != 1) 
+                                               throw new InvalidOperationException ("Read by order only possible for encoded/bare format");
+                                               
+                                       _elementsByIndex [mem.Index] = (XmlTypeMapElementInfo) mem.ElementInfo [0];
+                               }
+                       }
+                       if (index >= _elementMembers.Count)
+                               return null;
+                       return _elementsByIndex [index];
+               }
+               
+               private string BuildKey (string name, string ns, int explicitOrder)
+               {
+                       if (_ignoreMemberNamespace) return name;
+                       else return name + " / " + ns + (explicitOrder < 0 ? "" : "/" + explicitOrder);
+               }
+               
+               public ICollection AllElementInfos
+               {
+                       get { return _elements.Values; }
+               }
+               
+               
+               public bool IgnoreMemberNamespace
+               {
+                       get { return _ignoreMemberNamespace; }
+                       set { _ignoreMemberNamespace = value; }
+               }
+
+               public bool IsOrderDependentMap {
+                       get {
+                               if (_isOrderDependentMap == null) {
+                                       _isOrderDependentMap = false;
+                                       foreach (XmlTypeMapElementInfo ei in _elements.Values)
+                                               if (ei.ExplicitOrder >= 0) {
+                                                       _isOrderDependentMap = true;
+                                                       break;
+                                               }
+                               }
+                               return (bool) _isOrderDependentMap;
+                       }
+               }
+
+               public XmlTypeMapMember FindMember (string name)
+               {
+                       for (int n=0; n<_allMembers.Count; n++)
+                               if (((XmlTypeMapMember)_allMembers[n]).Name == name) return (XmlTypeMapMember)_allMembers[n];
+                       return null;
+               }
+
+               public XmlTypeMapMemberAnyElement DefaultAnyElementMember
+               {
+                       get { return _defaultAnyElement; }
+               }
+
+               public XmlTypeMapMemberAnyAttribute DefaultAnyAttributeMember
+               {
+                       get { return _defaultAnyAttribute; }
+               }
+
+               public XmlTypeMapMemberNamespaces NamespaceDeclarations
+               {
+                       get { return _namespaceDeclarations; }
+               }
+
+               public ICollection AttributeMembers
+               {
+                       get 
+                       {
+                               if (_attributeMembers == null) return null;
+                               if (_attributeMembersArray != null) return _attributeMembersArray;
+                               
+                               _attributeMembersArray = new XmlTypeMapMemberAttribute[_attributeMembers.Count];
+                               foreach (XmlTypeMapMemberAttribute mem in _attributeMembers.Values)
+                                       _attributeMembersArray [mem.Index] = mem;
+                               return _attributeMembersArray;
+                       }
+               }
+
+               public ICollection ElementMembers
+               {
+                       get { return _elementMembers; }
+               }
+
+               public ArrayList AllMembers
+               {
+                       get { return _allMembers; }
+               }
+
+               public ArrayList FlatLists
+               {
+                       get { return _flatLists; }
+               }
+               
+               public ArrayList MembersWithDefault
+               {
+                       get { return _membersWithDefault; }
+               }
+               
+               public ArrayList ListMembers
+               {
+                       get { return _listMembers; }
+               }
+
+               public XmlTypeMapMember XmlTextCollector
+               {
+                       get { return _xmlTextCollector; }
+               }
+               
+               public XmlTypeMapMember ReturnMember
+               {
+                       get { return _returnMember; }
+               }
+
+               public XmlQualifiedName SimpleContentBaseType
+               {
+                       get
+                       {
+                               if (!_canBeSimpleType || _elementMembers == null || _elementMembers.Count != 1) return null;
+                               XmlTypeMapMemberElement member = (XmlTypeMapMemberElement) _elementMembers[0];
+                               if (member.ElementInfo.Count != 1) return null;
+                               XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo[0];
+                               if (!einfo.IsTextElement) return null;
+                               if (member.TypeData.SchemaType == SchemaTypes.Primitive || member.TypeData.SchemaType == SchemaTypes.Enum)
+                                       return new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace);
+                               return null;
+                       }
+               }
+               
+               public void SetCanBeSimpleType (bool can)
+               {
+                       _canBeSimpleType = can;
+               }
+
+               public bool HasSimpleContent
+               {
+                       get
+                       {
+                               return SimpleContentBaseType != null;
+                       }
+               }
+
+       }
+
+       // Mapping info for arrays and lists
+
+       internal class ListMap: ObjectMap
+       {
+               XmlTypeMapElementInfoList _itemInfo;
+               bool _gotNestedMapping;
+               XmlTypeMapping _nestedArrayMapping;
+               string _choiceMember;
+
+               public bool IsMultiArray
+               {
+                       get
+                       {
+                               return (NestedArrayMapping != null);
+                       }
+               }
+
+               public string ChoiceMember
+               {
+                       get { return _choiceMember; }
+                       set { _choiceMember = value; }
+               }
+
+               public XmlTypeMapping NestedArrayMapping
+               {
+                       get
+                       {
+                               if (_gotNestedMapping) return _nestedArrayMapping;
+                               _gotNestedMapping = true;
+
+                               _nestedArrayMapping = ((XmlTypeMapElementInfo)_itemInfo[0]).MappedType;
+
+                               if (_nestedArrayMapping == null) return null;
+                               
+                               if (_nestedArrayMapping.TypeData.SchemaType != SchemaTypes.Array) {
+                                       _nestedArrayMapping = null; return null;
+                               }
+
+                               foreach (XmlTypeMapElementInfo elem in _itemInfo)
+                                       if (elem.MappedType != _nestedArrayMapping) {
+                                               _nestedArrayMapping = null;
+                                               return null;
+                                       }
+
+                               return _nestedArrayMapping;
+                       }
+               }
+
+               public XmlTypeMapElementInfoList ItemInfo
+               {
+
+                       get { return _itemInfo; }
+                       set { _itemInfo = value; }
+               }
+
+               public XmlTypeMapElementInfo FindElement (object ob, int index, object memberValue)
+               {
+                       if (_itemInfo.Count == 1) 
+                               return (XmlTypeMapElementInfo) _itemInfo[0];
+                       else if (_choiceMember != null && index != -1)
+                       {
+                               Array values = (Array) XmlTypeMapMember.GetValue (ob, _choiceMember);
+                               if (values == null || index >= values.Length)
+                                       throw new InvalidOperationException ("Invalid or missing choice enum value in member '" + _choiceMember + "'.");
+                               object val = values.GetValue (index);
+                               foreach (XmlTypeMapElementInfo elem in _itemInfo)
+                                       if (elem.ChoiceValue != null && elem.ChoiceValue.Equals (val))
+                                               return elem;
+                       }
+                       else
+                       {
+                               if (memberValue == null) return null;
+                               Type type = memberValue.GetType();
+                               foreach (XmlTypeMapElementInfo elem in _itemInfo)
+                                       if (elem.TypeData.Type == type) return elem;
+                       }
+                       return null;
+               }       
+
+               public XmlTypeMapElementInfo FindElement (string elementName, string ns)
+               {
+                       foreach (XmlTypeMapElementInfo elem in _itemInfo)
+                               if (elem.ElementName == elementName && elem.Namespace == ns) return elem;
+                       return null;
+               }
+               
+               public XmlTypeMapElementInfo FindTextElement ()
+               {
+                       foreach (XmlTypeMapElementInfo elem in _itemInfo)
+                               if (elem.IsTextElement) return elem;
+                       return null;
+               }
+               
+               public string GetSchemaArrayName ()
+               {
+                       XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) _itemInfo[0];
+                       if (einfo.MappedType != null) return TypeTranslator.GetArrayName (einfo.MappedType.XmlType);
+                       else return TypeTranslator.GetArrayName (einfo.TypeData.XmlType);
+               }
+
+               public void GetArrayType (int itemCount, out string localName, out string ns)
+               {
+                       string arrayDim;
+                       if (itemCount != -1) arrayDim = "[" + itemCount + "]";
+                       else arrayDim = "[]";
+
+                       XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) _itemInfo[0];
+                       if (info.TypeData.SchemaType == SchemaTypes.Array)
+                       {
+                               string nm;
+                               ((ListMap)info.MappedType.ObjectMap).GetArrayType (-1, out nm, out ns);
+                               localName = nm + arrayDim;
+                       }
+                       else 
+                       {
+                               if (info.MappedType != null)
+                               {
+                                       localName = info.MappedType.XmlType + arrayDim;
+                                       ns = info.MappedType.Namespace;
+                               }
+                               else 
+                               {
+                                       localName = info.TypeData.XmlType + arrayDim;
+                                       ns = info.DataTypeNamespace;
+                               }
+                       }
+               }
+
+               public override bool Equals (object other)
+               {
+                       ListMap lmap = other as ListMap;
+                       if (lmap == null) return false;
+
+                       if (_itemInfo.Count != lmap._itemInfo.Count) return false;
+                       for (int n=0; n<_itemInfo.Count; n++)
+                               if (!_itemInfo[n].Equals (lmap._itemInfo[n])) return false;
+                       return true;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return base.GetHashCode ();
+               }
+       }
+
+       internal class EnumMap: ObjectMap
+       {
+               readonly EnumMapMember[] _members;
+               readonly bool _isFlags;
+               readonly string[] _enumNames = null;
+               readonly string[] _xmlNames = null;
+               readonly long[] _values = null;
+
+               public class EnumMapMember
+               {
+                       readonly string _xmlName;
+                       readonly string _enumName;
+                       readonly long _value;
+                       string _documentation;
+
+                       public EnumMapMember (string xmlName, string enumName)
+                               : this (xmlName, enumName, 0)
+                       {
+                       }
+
+                       public EnumMapMember (string xmlName, string enumName, long value)
+                       {
+                               _xmlName = xmlName;
+                               _enumName = enumName;
+                               _value = value;
+                       }
+
+                       public string XmlName
+                       {
+                               get { return _xmlName; }
+                       }
+
+                       public string EnumName
+                       {
+                               get { return _enumName; }
+                       }
+
+                       public long Value
+                       {
+                               get { return _value; }
+                       }
+
+                       public string Documentation
+                       {
+                               get { return _documentation; }
+                               set { _documentation = value; }
+                       }
+               }
+
+               public EnumMap (EnumMapMember[] members, bool isFlags)
+               {
+                       _members = members;
+                       _isFlags = isFlags;
+
+                       _enumNames = new string[_members.Length];
+                       _xmlNames = new string[_members.Length];
+                       _values = new long[_members.Length];
+
+                       for (int i = 0; i < _members.Length; i++) {
+                               EnumMapMember mem = _members[i];
+                               _enumNames[i] = mem.EnumName;
+                               _xmlNames[i] = mem.XmlName;
+                               _values[i] = mem.Value;
+                       }
+               }
+               
+               public bool IsFlags
+               {
+                       get { return _isFlags; }
+               }
+
+               public EnumMapMember[] Members
+               {
+                       get { return _members; }
+               }
+
+               public string[] EnumNames
+               {
+                       get {
+                               return _enumNames;
+                       }
+               }
+
+               public string[] XmlNames
+               {
+                       get {
+                               return _xmlNames;
+                       }
+               }
+
+               public long[] Values
+               {
+                       get {
+                               return _values;
+                       }
+               }
+
+               public string GetXmlName (string typeName, object enumValue)
+               {
+                       if (enumValue is string) {
+                               throw new InvalidCastException ();
+                       }
+
+                       long value = 0;
+
+                       try {
+                               value = ((IConvertible) enumValue).ToInt64 (CultureInfo.CurrentCulture);
+                       } catch (FormatException) {
+                               throw new InvalidCastException ();
+                       }
+
+                       for (int i = 0; i < Values.Length; i++) {
+                               if (Values[i] == value)
+                                       return XmlNames[i];
+                       }
+
+                       if (IsFlags && value == 0)
+                               return string.Empty;
+
+                       string xmlName = string.Empty;
+                       if (IsFlags) {
+#if NET_2_0
+                               xmlName = XmlCustomFormatter.FromEnum (value, XmlNames, Values, typeName);
+#else
+                               xmlName = XmlCustomFormatter.FromEnum (value, XmlNames, Values);
+#endif
+                       }
+
+                       if (xmlName.Length == 0) {
+#if NET_2_0
+                               throw new InvalidOperationException (string.Format(CultureInfo.CurrentCulture,
+                                       "'{0}' is not a valid value for {1}.", value, typeName));
+#else
+                               return value.ToString (CultureInfo.InvariantCulture);
+#endif
+                       }
+                       return xmlName;
+               }
+
+               public string GetEnumName (string typeName, string xmlName)
+               {
+                       if (_isFlags) {
+                               xmlName = xmlName.Trim ();
+                               if (xmlName.Length == 0)
+                                       return "0";
+
+                               System.Text.StringBuilder sb = new System.Text.StringBuilder ();
+                               string[] enumNames = xmlName.Split (null);
+                               foreach (string name in enumNames) {
+                                       if (name == string.Empty) continue;
+                                       string foundEnumValue = null;
+                                       for (int i = 0; i < XmlNames.Length; i++)
+                                               if (XmlNames[i] == name) {
+                                                       foundEnumValue = EnumNames[i];
+                                                       break;
+                                               }
+
+                                       if (foundEnumValue != null) {
+                                               if (sb.Length > 0)
+                                                       sb.Append (',');
+                                               sb.Append (foundEnumValue);
+                                       } else {
+                                               throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
+                                                       "'{0}' is not a valid value for {1}.", name, typeName));
+                                       }
+                               }
+                               return sb.ToString ();
+                       }
+
+                       foreach (EnumMapMember mem in _members)
+                               if (mem.XmlName == xmlName) return mem.EnumName;
+                               
+                       return null;
+               }
+       }
+}