context: // 
  // System.Xml.Serialization.SoapReflectionImporter 
  //
  // Author:
  //   Tim Coleman (tim@timcoleman.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.Collections;
  using System.Globalization;
  using System.Reflection;
  using System.Xml;
  using System.Xml.Schema;
  
  namespace System.Xml.Serialization {
  	public class SoapReflectionImporter {
  
  		SoapAttributeOverrides attributeOverrides;
  		string initialDefaultNamespace;
  		ArrayList includedTypes;
  		ArrayList relatedMaps = new ArrayList ();
  		ReflectionHelper helper = new ReflectionHelper();
  
  		#region Constructors
  
  		public SoapReflectionImporter (): this (null, null)
  		{ 
  		}
  
  		public SoapReflectionImporter (SoapAttributeOverrides attributeOverrides): this (attributeOverrides, null)
  		{ 
  		}
  
  		public SoapReflectionImporter (string defaultNamespace): this (null, defaultNamespace)
  		{
  		}
  
  		public SoapReflectionImporter (SoapAttributeOverrides attributeOverrides, string defaultNamespace)
  		{ 
  			if (defaultNamespace == null) initialDefaultNamespace = String.Empty;
  			else initialDefaultNamespace = defaultNamespace;
  
  			if (attributeOverrides == null) this.attributeOverrides = new SoapAttributeOverrides();
  			else this.attributeOverrides = attributeOverrides;
  		}
  
  		#endregion // Constructors
  
  		#region Methods
  
  		public XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members)
  		{
  			return ImportMembersMapping (elementName, ns, members, true, true, false);
  		}
  
  		public XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors)
  		{ 
  			return ImportMembersMapping (elementName, ns, members, hasWrapperElement, writeAccessors, false);
  		}
  
  		public XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors, bool validate)
  		{
  			return ImportMembersMapping (elementName, ns, members, hasWrapperElement, writeAccessors, validate, XmlMappingAccess.Read | XmlMappingAccess.Write);
  		}
  
  #if NET_2_0
  		[MonoTODO]
  		public
  #endif
  		XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors, bool validate, XmlMappingAccess access)
  		{
  			elementName = XmlConvert.EncodeLocalName (elementName);
  			XmlMemberMapping[] mapping = new XmlMemberMapping[members.Length];
  			for (int n=0; n<members.Length; n++)
  			{
  				XmlTypeMapMember mapMem = CreateMapMember (members[n], ns);
  				mapping[n] = new XmlMemberMapping (XmlConvert.EncodeLocalName (members[n].MemberName), ns, mapMem, true);
  			}
  			XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, writeAccessors, mapping);
  			mps.RelatedMaps = relatedMaps;
  			mps.Format = SerializationFormat.Encoded;
  			Type[] extraTypes = includedTypes != null ? (Type[])includedTypes.ToArray(typeof(Type)) : null;
  			mps.Source = new MembersSerializationSource (elementName, hasWrapperElement, members, writeAccessors, false, null, extraTypes);
  			return mps;
  		}
  
  		public XmlTypeMapping ImportTypeMapping (Type type)
  		{ 
  			return ImportTypeMapping (type, null);
  		}
  
  		public XmlTypeMapping ImportTypeMapping (Type type, string defaultNamespace)
  		{
  			if (type == null)
  				throw new ArgumentNullException ("type");
  
  			if (type == typeof (void))
  				throw new InvalidOperationException ("Type " + type.Name + " may not be serialized.");
  
  			return ImportTypeMapping (TypeTranslator.GetTypeData (type),
  				defaultNamespace);
  		}
  
  		internal XmlTypeMapping ImportTypeMapping (TypeData typeData, string defaultNamespace)
  		{
  			if (typeData == null)
  				throw new ArgumentNullException ("typeData");
  
  			if (typeData.Type == null)
  				throw new ArgumentException ("Specified TypeData instance does not have Type set.");
  
  			string oldNs = initialDefaultNamespace;
  			if (defaultNamespace == null) defaultNamespace = initialDefaultNamespace;
  			if (defaultNamespace == null) defaultNamespace = string.Empty;
  			initialDefaultNamespace = defaultNamespace; 
  
  			XmlTypeMapping map;
  			switch (typeData.SchemaType) {
  				case SchemaTypes.Class: map = ImportClassMapping (typeData, defaultNamespace); break;
  				case SchemaTypes.Array: map = ImportListMapping (typeData, defaultNamespace); break;
  				case SchemaTypes.XmlNode: throw CreateTypeException (typeData.Type);
  				case SchemaTypes.Primitive: map = ImportPrimitiveMapping (typeData, defaultNamespace); break;
  				case SchemaTypes.Enum: map = ImportEnumMapping (typeData, defaultNamespace); break;
  				case SchemaTypes.XmlSerializable:
  				default: throw new NotSupportedException ("Type " + typeData.Type.FullName + " not supported for XML serialization");
  			}
  			map.RelatedMaps = relatedMaps;
  			map.Format = SerializationFormat.Encoded;
  			Type[] extraTypes = includedTypes != null ? (Type[])includedTypes.ToArray(typeof(Type)) : null;
  			map.Source = new SoapTypeSerializationSource (typeData.Type, attributeOverrides, defaultNamespace, extraTypes);
  			
  			initialDefaultNamespace = oldNs;
  			return map;
  		}
  
  		XmlTypeMapping CreateTypeMapping (TypeData typeData, string defaultXmlType, string defaultNamespace)
  		{
  			string membersNamespace = defaultNamespace;
  			bool includeInSchema = true;
  
  			SoapAttributes atts = null;
  			if (defaultXmlType == null) defaultXmlType = typeData.XmlType;
  
  			if (!typeData.IsListType)
  			{
  				if (attributeOverrides != null) 
  					atts = attributeOverrides[typeData.Type];
  
  				if (atts != null && typeData.SchemaType == SchemaTypes.Primitive)
  					throw new InvalidOperationException ("SoapType attribute may not be specified for the type " + typeData.FullTypeName);
  			}
  
  			if (atts == null) 
  				atts = new SoapAttributes (typeData.Type);
  
  			if (atts.SoapType != null)
  			{
  				if (atts.SoapType.Namespace != null && atts.SoapType.Namespace != string.Empty)
  					membersNamespace = atts.SoapType.Namespace;
  
  				if (atts.SoapType.TypeName != null && atts.SoapType.TypeName != string.Empty)
  					defaultXmlType = XmlConvert.EncodeLocalName (atts.SoapType.TypeName);
  
  				includeInSchema = atts.SoapType.IncludeInSchema;
  			}
  
  			if (membersNamespace == null) membersNamespace = "";
  			XmlTypeMapping map = new XmlTypeMapping (defaultXmlType, membersNamespace, typeData, defaultXmlType, membersNamespace);
  			map.IncludeInSchema = includeInSchema;
  			relatedMaps.Add (map);
  
  			return map;
  		}
  
  		XmlTypeMapping ImportClassMapping (Type type, string defaultNamespace)
  		{
  			TypeData typeData = TypeTranslator.GetTypeData (type);
  			return ImportClassMapping (typeData, defaultNamespace);
  		}
  
  		XmlTypeMapping ImportClassMapping (TypeData typeData, string defaultNamespace)
  		{
  			Type type = typeData.Type;
  
  			if (type.IsValueType) throw CreateStructException (type);
  
  			if (type == typeof (object)) defaultNamespace = XmlSchema.Namespace;
  
  			ReflectionHelper.CheckSerializableType (type, false);
  			XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, defaultNamespace));
  			if (map != null) return map;
  
  			map = CreateTypeMapping (typeData, null, defaultNamespace);
  			helper.RegisterClrType (map, type, map.Namespace);
  			map.MultiReferenceType = true;
  
  			ClassMap classMap = new ClassMap ();
  			map.ObjectMap = classMap;
  
  			// Import members
  
  			ICollection members = GetReflectionMembers (type);
  			foreach (XmlReflectionMember rmember in members) {
  				if (rmember.SoapAttributes.SoapIgnore) continue;
  				classMap.AddMember (CreateMapMember (rmember, defaultNamespace));
  			}
  
  			// Import included classes
  
  			SoapIncludeAttribute[] includes = (SoapIncludeAttribute[])type.GetCustomAttributes (typeof (SoapIncludeAttribute), false);
  			for (int n=0; n<includes.Length; n++)
  			{
  				Type includedType = includes[n].Type;
  				ImportTypeMapping (includedType);
  			}
  
  			if (type == typeof (object) && includedTypes != null)
  			{
  				foreach (Type intype in includedTypes)
  
gt: 					map.DerivedTypes.Add (ImportTypeMapping (intype));