* SerializationCodeGenerator.cs: Several fixes: generate valid names for
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlReflectionImporter.cs
index ebda7356d0884325deb3fd3f0a1c0a2fab482167..59a62f8c575d0439ec0c2a04a7c2c6464d0f0817 100644 (file)
@@ -12,6 +12,7 @@
 
 using System.Reflection;
 using System.Collections;
+using System.Xml.Schema;
 
 namespace System.Xml.Serialization {
        public class XmlReflectionImporter {
@@ -19,10 +20,17 @@ namespace System.Xml.Serialization {
                string initialDefaultNamespace;
                XmlAttributeOverrides attributeOverrides;
                ArrayList includedTypes;
-               Hashtable clrTypes = new Hashtable ();
-               Hashtable schemaTypes = new Hashtable ();
                ReflectionHelper helper = new ReflectionHelper();
                int arrayChoiceCount = 1;
+               ArrayList relatedMaps = new ArrayList ();
+               bool allowPrivateTypes = false;
+
+               static readonly string errSimple = "Cannot serialize object of type '{0}'. Base " +
+                       "type '{1}' has simpleContent and can be only extended by adding XmlAttribute " +
+                       "elements. Please consider changing XmlText member of the base class to string array";
+
+               static readonly string errSimple2 = "Cannot serialize object of type '{0}'. " +
+                       "Consider changing type of XmlText member '{1}' from '{2}' to string or string array";
 
                #region Constructors
 
@@ -54,6 +62,18 @@ namespace System.Xml.Serialization {
                                this.attributeOverrides = attributeOverrides;
                }
 
+               void Reset ()
+               {
+                       helper = new ReflectionHelper();
+                       arrayChoiceCount = 1;
+               }
+               
+               internal bool AllowPrivateTypes
+               {
+                       get { return allowPrivateTypes; }
+                       set { allowPrivateTypes = value; }
+               }
+
                #endregion // Constructors
 
                #region Methods
@@ -63,14 +83,18 @@ namespace System.Xml.Serialization {
                        XmlReflectionMember [] members,
                        bool hasWrapperElement)
                {
+                       Reset ();
                        XmlMemberMapping[] mapping = new XmlMemberMapping[members.Length];
                        for (int n=0; n<members.Length; n++)
                        {
                                XmlTypeMapMember mapMem = CreateMapMember (members[n], ns);
-                               mapping[n] = new XmlMemberMapping (members[n], mapMem);
+                               mapping[n] = new XmlMemberMapping (members[n].MemberName, ns, mapMem, false);
                        }
-                       XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, mapping);
+                       XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, false, mapping);
+                       mps.RelatedMaps = relatedMaps;
                        mps.Format = SerializationFormat.Literal;
+                       mps.Source = new MembersSerializationSource (elementName, hasWrapperElement, members, false, true, ns, includedTypes);
+                       if (allowPrivateTypes) mps.Source.CanBeGenerated = false;
                        return mps;
                }
 
@@ -113,14 +137,20 @@ namespace System.Xml.Serialization {
                                default: throw new NotSupportedException ("Type " + type.FullName + " not supported for XML stialization");
                        }
 
+                       map.RelatedMaps = relatedMaps;
                        map.Format = SerializationFormat.Literal;
+                       map.Source = new XmlTypeSerializationSource (type, root, attributeOverrides, defaultNamespace, includedTypes);
+                       if (allowPrivateTypes) map.Source.CanBeGenerated = false;
                        return map;
                }
 
                XmlTypeMapping CreateTypeMapping (TypeData typeData, XmlRootAttribute root, string defaultXmlType, string defaultNamespace)
                {
-                       string membersNamespace = defaultNamespace;
+                       string rootNamespace = defaultNamespace;
+                       string typeNamespace = null;
+                       
                        string elementName;
+                       bool includeInSchema = true;
                        XmlAttributes atts = null;
                        if (defaultXmlType == null) defaultXmlType = typeData.XmlType;
 
@@ -141,11 +171,13 @@ namespace System.Xml.Serialization {
 
                        if (atts.XmlType != null)
                        {
-                               if (atts.XmlType.Namespace != null && atts.XmlType.Namespace != string.Empty)
-                                       membersNamespace = atts.XmlType.Namespace;
+                               if (atts.XmlType.Namespace != null && atts.XmlType.Namespace != string.Empty && typeData.SchemaType != SchemaTypes.Enum)
+                                       typeNamespace = atts.XmlType.Namespace;
 
                                if (atts.XmlType.TypeName != null && atts.XmlType.TypeName != string.Empty)
                                        defaultXmlType = atts.XmlType.TypeName;
+                                       
+                               includeInSchema = atts.XmlType.IncludeInSchema;
                        }
 
                        elementName = defaultXmlType;
@@ -155,52 +187,55 @@ namespace System.Xml.Serialization {
                                if (root.ElementName != null && root.ElementName != String.Empty)
                                        elementName = root.ElementName;
                                if (root.Namespace != null && root.Namespace != String.Empty)
-                                       membersNamespace = root.Namespace;
+                                       rootNamespace = root.Namespace;
                        }
 
-                       if (membersNamespace == null) membersNamespace = "";
-                       XmlTypeMapping map = new XmlTypeMapping (elementName, membersNamespace, typeData, defaultXmlType);
+                       if (rootNamespace == null) rootNamespace = "";
+                       if (typeNamespace == null || typeNamespace.Length == 0) typeNamespace = rootNamespace;
+                       
+                       XmlTypeMapping map = new XmlTypeMapping (elementName, rootNamespace, typeData, defaultXmlType, typeNamespace);
+                       map.IncludeInSchema = includeInSchema;
+                       relatedMaps.Add (map);
+                       
                        return map;
                }
 
                XmlTypeMapping ImportClassMapping (Type type, XmlRootAttribute root, string defaultNamespace)
                {
                        TypeData typeData = TypeTranslator.GetTypeData (type);
-                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
                        if (map != null) return map;
 
-                       map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+                       if (!allowPrivateTypes)
+                               ReflectionHelper.CheckSerializableType (type);
                        
-                       helper.RegisterClrType (map, type, defaultNamespace);
-                       helper.RegisterSchemaType (map, map.XmlType, defaultNamespace);
+                       map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+                       helper.RegisterClrType (map, type, map.XmlTypeNamespace);
+                       helper.RegisterSchemaType (map, map.XmlType, map.XmlTypeNamespace);
+
+                       // Import members
 
                        ClassMap classMap = new ClassMap ();
                        map.ObjectMap = classMap;
 
-                       // Import members
-
-                       try
-                       {
+//                     try
+//                     {
                                ICollection members = GetReflectionMembers (type);
                                foreach (XmlReflectionMember rmember in members)
                                {
                                        if (rmember.XmlAttributes.XmlIgnore) continue;
-                                       classMap.AddMember (CreateMapMember (rmember, map.Namespace));
+                                       XmlTypeMapMember mem = CreateMapMember (rmember, map.XmlTypeNamespace);
+                                       mem.CheckOptionalValueType (type);
+                                       classMap.AddMember (mem);
                                }
-                       }
-                       catch (Exception ex) {
-                               throw helper.CreateError (map, ex.Message);
-                       }
-
-                       // Import derived classes
+//                     }
+//                     catch (Exception ex) {
+//                             throw helper.CreateError (map, ex.Message);
+//                     }
 
-                       XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), false);
-                       for (int n=0; n<includes.Length; n++)
-                       {
-                               Type includedType = includes[n].Type;
-                               if (!includedType.IsSubclassOf(type)) throw helper.CreateError (map, "Type '" + includedType.FullName + "' is not a subclass of '" + type.FullName + "'");
-                               map.DerivedTypes.Add (ImportTypeMapping (includedType, root, defaultNamespace));
-                       }
+                       ImportIncludedTypes (type, defaultNamespace);
+                       
+                       // Import extra classes
 
                        if (type == typeof (object) && includedTypes != null)
                        {
@@ -208,20 +243,96 @@ namespace System.Xml.Serialization {
                                        map.DerivedTypes.Add (ImportTypeMapping (intype, defaultNamespace));
                        }
 
-                       // Register this map as a derived class of object
+                       // Register inheritance relations
 
-                       if (typeData.Type != typeof(object))
-                               ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
+                       if (type.BaseType != null)
+                       {
+                               XmlTypeMapping bmap = ImportClassMapping (type.BaseType, root, defaultNamespace);
+                               
+                               if (type.BaseType != typeof (object)) {
+                                       map.BaseMap = bmap;
+                                       classMap.SetCanBeSimpleType (false);
+                               }
+                               
+                               // At this point, derived classes of this map must be already registered
+                               
+                               RegisterDerivedMap (bmap, map);
+                               
+                               if (((ClassMap)bmap.ObjectMap).HasSimpleContent && classMap.ElementMembers != null && classMap.ElementMembers.Count != 1)
+                                       throw new InvalidOperationException (String.Format (errSimple, map.TypeData.TypeName, map.BaseMap.TypeData.TypeName));
+                       }
+                       
+                       if (classMap.XmlTextCollector != null && !classMap.HasSimpleContent)
+                       {
+                               XmlTypeMapMember mem = classMap.XmlTextCollector;
+                               if (mem.TypeData.Type != typeof(string) && 
+                                  mem.TypeData.Type != typeof(string[]) && 
+                                  mem.TypeData.Type != typeof(object[]) && 
+                                  mem.TypeData.Type != typeof(XmlNode[]))
+                                  
+                                       throw new InvalidOperationException (String.Format (errSimple2, map.TypeData.TypeName, mem.Name, mem.TypeData.TypeName));
+                       }
                        
                        return map;
                }
+               
+               void RegisterDerivedMap (XmlTypeMapping map, XmlTypeMapping derivedMap)
+               {
+                       map.DerivedTypes.Add (derivedMap);
+                       map.DerivedTypes.AddRange (derivedMap.DerivedTypes);
+                       
+                       if (map.BaseMap != null)
+                               RegisterDerivedMap (map.BaseMap, derivedMap);
+                       else {
+                               XmlTypeMapping obmap = ImportTypeMapping (typeof(object));
+                               if (obmap != map)
+                                       obmap.DerivedTypes.Add (derivedMap);
+                       }
+               }
 
+               string GetTypeNamespace (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
+               {
+                       string typeNamespace = null;
+                       
+                       XmlAttributes atts = null;
+                       if (!typeData.IsListType)
+                       {
+                               if (attributeOverrides != null)
+                                       atts = attributeOverrides[typeData.Type];
+                       }
+
+                       if (atts == null)
+                               atts = new XmlAttributes (typeData.Type);
+
+                       if (atts.XmlType != null)
+                       {
+                               if (atts.XmlType.Namespace != null && atts.XmlType.Namespace.Length != 0 && typeData.SchemaType != SchemaTypes.Enum)
+                                       typeNamespace = atts.XmlType.Namespace;
+                       }
+
+                       if (typeNamespace != null && typeNamespace.Length != 0) return typeNamespace;
+                       
+                       if (atts.XmlRoot != null && root == null)
+                               root = atts.XmlRoot;
+
+                       if (root != null)
+                       {
+                               if (root.Namespace != null && root.Namespace.Length != 0)
+                                       return root.Namespace;
+                       }
+
+                       if (defaultNamespace == null) return "";
+                       else return defaultNamespace;
+               }
 
                XmlTypeMapping ImportListMapping (Type type, XmlRootAttribute root, string defaultNamespace, XmlAttributes atts, int nestingLevel)
                {
                        TypeData typeData = TypeTranslator.GetTypeData (type);
                        ListMap obmap = new ListMap ();
 
+                       if (!allowPrivateTypes)
+                               ReflectionHelper.CheckSerializableType (type);
+                       
                        if (atts == null) atts = new XmlAttributes();
                        Type itemType = typeData.ListItemType;
 
@@ -234,11 +345,11 @@ namespace System.Xml.Serialization {
                        {
                                if (att.NestingLevel != nestingLevel) continue;
                                Type elemType = (att.Type != null) ? att.Type : itemType;
-                               XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (null, TypeTranslator.GetTypeData(elemType));
-                               elem.DataType = att.DataType;
-                               elem.Namespace = att.Namespace != null ? att.Namespace : "";
+                               XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (null, TypeTranslator.GetTypeData(elemType, att.DataType));
+                               elem.Namespace = att.Namespace != null ? att.Namespace : defaultNamespace;
+                               if (elem.Namespace == null) elem.Namespace = "";
                                elem.Form = att.Form;
-                               elem.IsNullable = att.IsNullable;
+                               elem.IsNullable = att.IsNullable && CanBeNull (elem.TypeData);
                                elem.NestingLevel = att.NestingLevel;
 
                                if (isMultiArray)
@@ -261,11 +372,11 @@ namespace System.Xml.Serialization {
                                else if (elem.TypeData.IsComplexType)
                                        elem.MappedType = ImportTypeMapping (itemType, null, defaultNamespace);
 
-                               if (elem.MappedType != null) elem.ElementName = elem.MappedType.ElementName;
+                               if (elem.MappedType != null) elem.ElementName = elem.MappedType.XmlType;
                                else elem.ElementName = TypeTranslator.GetTypeData(itemType).XmlType ;
 
                                elem.Namespace = (defaultNamespace != null) ? defaultNamespace : "";
-                               elem.IsNullable = true; // By default, items are nullable
+                               elem.IsNullable = CanBeNull (elem.TypeData);
                                list.Add (elem);
                        }
 
@@ -280,8 +391,8 @@ namespace System.Xml.Serialization {
                        else
                        {
                                XmlTypeMapElementInfo elem = ((XmlTypeMapElementInfo)list[0]);
-                               if (elem.MappedType != null) baseName = GetArrayName (elem.MappedType.ElementName);
-                               else baseName = GetArrayName (elem.ElementName);
+                               if (elem.MappedType != null) baseName = TypeTranslator.GetArrayName (elem.MappedType.XmlType);
+                               else baseName = TypeTranslator.GetArrayName (elem.ElementName);
                        }
 
                        // Avoid name colisions
@@ -292,14 +403,24 @@ namespace System.Xml.Serialization {
                        do {
                                XmlTypeMapping foundMap = helper.GetRegisteredSchemaType (name, defaultNamespace);
                                if (foundMap == null) nameCount = -1;
-                               else if (obmap.Equals (foundMap.ObjectMap)) return foundMap;
+                               else if (obmap.Equals (foundMap.ObjectMap) && typeData.Type == foundMap.TypeData.Type) return foundMap;
                                else name = baseName + (nameCount++);
                        }
                        while (nameCount != -1);
 
                        XmlTypeMapping map = CreateTypeMapping (typeData, root, name, defaultNamespace);
                        map.ObjectMap = obmap;
-
+                       
+                       // Register any of the including types as a derived class of object
+                       XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), false);
+                       
+                       XmlTypeMapping objectMapping = ImportTypeMapping (typeof(object));
+                       for (int i = 0; i < includes.Length; i++)
+                       {
+                               Type includedType = includes[i].Type;
+                               objectMapping.DerivedTypes.Add(ImportTypeMapping (includedType, null, defaultNamespace));
+                       }
+                       
                        // Register this map as a derived class of object
 
                        helper.RegisterSchemaType (map, name, defaultNamespace);
@@ -308,26 +429,21 @@ namespace System.Xml.Serialization {
                        return map;
                }
 
-               string GetArrayName (string elemName)
-               {
-                       return "ArrayOf" + Char.ToUpper (elemName [0]) + elemName.Substring (1);
-               }
-
                XmlTypeMapping ImportXmlNodeMapping (Type type, XmlRootAttribute root, string defaultNamespace)
                {
-                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (TypeTranslator.GetTypeData (type), root, defaultNamespace));
                        if (map != null) return map;
 
                        // Registers the maps for XmlNode and XmlElement
 
                        XmlTypeMapping nodeMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlNode)), root, null, defaultNamespace);
-                       helper.RegisterClrType (nodeMap, typeof(XmlNode), defaultNamespace);
+                       helper.RegisterClrType (nodeMap, typeof(XmlNode), nodeMap.XmlTypeNamespace);
 
                        XmlTypeMapping elemMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlElement)), root, null, defaultNamespace);
-                       helper.RegisterClrType (elemMap, typeof(XmlElement), defaultNamespace);
+                       helper.RegisterClrType (elemMap, typeof(XmlElement), elemMap.XmlTypeNamespace);
 
                        XmlTypeMapping textMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlText)), root, null, defaultNamespace);
-                       helper.RegisterClrType (elemMap, typeof(XmlText), defaultNamespace);
+                       helper.RegisterClrType (elemMap, typeof(XmlText), textMap.XmlTypeNamespace);
 
                        XmlTypeMapping obmap = ImportTypeMapping (typeof(object));
                        obmap.DerivedTypes.Add (nodeMap);
@@ -336,74 +452,107 @@ namespace System.Xml.Serialization {
                        nodeMap.DerivedTypes.Add (elemMap);
                        nodeMap.DerivedTypes.Add (textMap);
 
-                       return helper.GetRegisteredClrType (type, defaultNamespace);
+                       return helper.GetRegisteredClrType (type, GetTypeNamespace (TypeTranslator.GetTypeData (type), root, defaultNamespace));
                }
 
                XmlTypeMapping ImportPrimitiveMapping (Type type, XmlRootAttribute root, string defaultNamespace)
                {
-                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+                       TypeData typeData = TypeTranslator.GetTypeData (type);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
                        if (map != null) return map;
-                       map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
-                       helper.RegisterClrType (map, type, defaultNamespace);
+                       map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+                       helper.RegisterClrType (map, type, map.XmlTypeNamespace);
                        return map;
                }
 
                XmlTypeMapping ImportEnumMapping (Type type, XmlRootAttribute root, string defaultNamespace)
                {
-                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+                       TypeData typeData = TypeTranslator.GetTypeData (type);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
                        if (map != null) return map;
-                       map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
-                       helper.RegisterClrType (map, type, defaultNamespace);
+                       map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+                       helper.RegisterClrType (map, type, map.XmlTypeNamespace);
 
                        string [] names = Enum.GetNames (type);
                        ArrayList members = new ArrayList();
                        foreach (string name in names)
                        {
                                MemberInfo[] mem = type.GetMember (name);
-                               string xmlName = name;
+                               string xmlName = null;
                                object[] atts = mem[0].GetCustomAttributes (typeof(XmlIgnoreAttribute), false);
                                if (atts.Length > 0) continue;
                                atts = mem[0].GetCustomAttributes (typeof(XmlEnumAttribute), false);
                                if (atts.Length > 0) xmlName = ((XmlEnumAttribute)atts[0]).Name;
+                               if (xmlName == null) xmlName = name;
                                members.Add (new EnumMap.EnumMapMember (xmlName, name));
                        }
 
-                       map.ObjectMap = new EnumMap ((EnumMap.EnumMapMember[])members.ToArray (typeof(EnumMap.EnumMapMember)));
+                       bool isFlags = type.GetCustomAttributes (typeof(FlagsAttribute),false).Length > 0;
+                       map.ObjectMap = new EnumMap ((EnumMap.EnumMapMember[])members.ToArray (typeof(EnumMap.EnumMapMember)), isFlags);
                        ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
                        return map;
                }
 
                XmlTypeMapping ImportXmlSerializableMapping (Type type, XmlRootAttribute root, string defaultNamespace)
                {
-                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+                       TypeData typeData = TypeTranslator.GetTypeData (type);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
                        if (map != null) return map;
-                       map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
-                       helper.RegisterClrType (map, type, defaultNamespace);
+                       map = CreateTypeMapping (typeData, root, null, defaultNamespace);
+                       helper.RegisterClrType (map, type, map.XmlTypeNamespace);
                        return map;
                }
 
-               public ICollection GetReflectionMembers (Type type)
+               void ImportIncludedTypes (Type type, string defaultNamespace)
                {
-                       ArrayList members = new ArrayList();
-                       PropertyInfo[] properties = type.GetProperties (BindingFlags.Instance | BindingFlags.Public);
-                       foreach (PropertyInfo prop in properties)
+                       XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), false);
+                       for (int n=0; n<includes.Length; n++)
                        {
-                               if (!prop.CanRead) continue;
-                               XmlAttributes atts = attributeOverrides[type, prop.Name];
-                               if (atts == null) atts = new XmlAttributes (prop);
-                               if (atts.XmlIgnore) continue;
-                               XmlReflectionMember member = new XmlReflectionMember(prop.Name, prop.PropertyType, atts);
-                               members.Add (member);
+                               Type includedType = includes[n].Type;
+                               ImportTypeMapping (includedType, null, defaultNamespace);
                        }
+               }
 
-                       FieldInfo[] fields = type.GetFields (BindingFlags.Instance | BindingFlags.Public);
-                       foreach (FieldInfo field in fields)
+               ICollection GetReflectionMembers (Type type)
+               {
+                       ArrayList members = new ArrayList();
+                       MemberInfo[] tmembers = type.GetMembers (BindingFlags.Instance | BindingFlags.Public);
+                       int currentTypePos = 0;
+                       Type currentType = null;
+                       
+                       foreach (MemberInfo tmember in tmembers)
                        {
-                               XmlAttributes atts = attributeOverrides[type, field.Name];
-                               if (atts == null) atts = new XmlAttributes (field);
-                               if (atts.XmlIgnore) continue;
-                               XmlReflectionMember member = new XmlReflectionMember(field.Name, field.FieldType, atts);
-                               members.Add (member);
+                               if (currentType != tmember.DeclaringType)
+                               {
+                                       currentType = tmember.DeclaringType;
+                                       currentTypePos = 0;
+                               }
+                               
+                               if (tmember is FieldInfo)
+                               {
+                                       FieldInfo field = tmember as FieldInfo;
+                                       XmlAttributes atts = attributeOverrides[type, field.Name];
+                                       if (atts == null) atts = new XmlAttributes (field);
+                                       if (atts.XmlIgnore) continue;
+                                       XmlReflectionMember member = new XmlReflectionMember(field.Name, field.FieldType, atts);
+                                       members.Insert (currentTypePos, member);
+                                       currentTypePos++;
+                               }
+                               else if (tmember is PropertyInfo)
+                               {
+                                       PropertyInfo prop  = tmember as PropertyInfo;
+                                       if (!prop.CanRead) continue;
+                                       if (!prop.CanWrite && TypeTranslator.GetTypeData (prop.PropertyType).SchemaType != SchemaTypes.Array)
+                                               continue;
+                                       if (prop.GetIndexParameters().Length > 0) continue;
+                                               
+                                       XmlAttributes atts = attributeOverrides[type, prop.Name];
+                                       if (atts == null) atts = new XmlAttributes (prop);
+                                       if (atts.XmlIgnore) continue;
+                                       XmlReflectionMember member = new XmlReflectionMember(prop.Name, prop.PropertyType, atts);
+                                       members.Insert (currentTypePos, member);
+                                       currentTypePos++;
+                               }
                        }
                        return members;
                }
@@ -431,12 +580,17 @@ namespace System.Xml.Serialization {
                                         (rmember.MemberType.FullName == "System.Xml.XmlElement"))
                                {
                                        XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement();
-                                       member.ElementInfo = ImportAnyElementInfo (defaultNamespace, member, atts);
+                                       member.ElementInfo = ImportAnyElementInfo (defaultNamespace, rmember, member, atts);
                                        mapMember = member;
                                }
                                else
                                        throw new InvalidOperationException ("XmlAnyElementAttribute can only be applied to members of type XmlElement, XmlElement[] or XmlNode[]");
                        }
+                       else if (atts.Xmlns)
+                       {
+                               XmlTypeMapMemberNamespaces mapNamespaces = new XmlTypeMapMemberNamespaces ();
+                               mapMember = mapNamespaces;
+                       }
                        else if (atts.XmlAttribute != null)
                        {
                                // An attribute
@@ -450,12 +604,26 @@ namespace System.Xml.Serialization {
                                else 
                                        mapAttribute.AttributeName = atts.XmlAttribute.AttributeName;
 
-                               mapAttribute.DataType = atts.XmlAttribute.DataType;
-                               mapAttribute.Form = atts.XmlAttribute.Form;
-                               mapAttribute.Namespace = (atts.XmlAttribute.Namespace != null) ? atts.XmlAttribute.Namespace : "";
                                if (typeData.IsComplexType)
                                        mapAttribute.MappedType = ImportTypeMapping (typeData.Type, null, mapAttribute.Namespace);
-
+                               
+                               if (atts.XmlAttribute.Namespace != null && atts.XmlAttribute.Namespace != defaultNamespace)
+                               {
+                                       if (atts.XmlAttribute.Form == XmlSchemaForm.Unqualified)
+                                               throw new InvalidOperationException ("The Form property may not be 'Unqualified' when an explicit Namespace property is present");
+                                       mapAttribute.Form = XmlSchemaForm.Qualified;
+                                       mapAttribute.Namespace = atts.XmlAttribute.Namespace;
+                               }
+                               else
+                               {
+                                       mapAttribute.Form = atts.XmlAttribute.Form;
+                                       if (atts.XmlAttribute.Form == XmlSchemaForm.Qualified)
+                                               mapAttribute.Namespace = defaultNamespace;
+                                       else
+                                               mapAttribute.Namespace = "";
+                               }
+                               
+                               typeData = TypeTranslator.GetTypeData(rmember.MemberType, atts.XmlAttribute.DataType);
                                mapMember = mapAttribute;
                        }
                        else if (typeData.SchemaType == SchemaTypes.Array)
@@ -488,6 +656,9 @@ namespace System.Xml.Serialization {
                                        elem.ElementName = (atts.XmlArray != null && atts.XmlArray.ElementName != null) ? atts.XmlArray.ElementName : rmember.MemberName;
                                        elem.Namespace = (atts.XmlArray != null && atts.XmlArray.Namespace != null) ? atts.XmlArray.Namespace : defaultNamespace;
                                        elem.MappedType = ImportListMapping (rmember.MemberType, null, elem.Namespace, atts, 0);
+                                       elem.IsNullable = (atts.XmlArray != null) ? atts.XmlArray.IsNullable : false;
+                                       elem.Form = (atts.XmlArray != null) ? atts.XmlArray.Form : XmlSchemaForm.Qualified;
+
                                        member.ElementInfo.Add (elem);
                                        mapMember = member;
                                }
@@ -511,26 +682,9 @@ namespace System.Xml.Serialization {
                {
                        XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
 
-                       if (atts.XmlText != null)
-                       {
-                               member.IsXmlTextCollector = true;
-                               if (atts.XmlText.Type != null) defaultType = atts.XmlText.Type;
-                               if (defaultType == typeof(XmlNode)) defaultType = typeof(XmlText);      // Nodes must be text nodes
-                               
-                               XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType));
-                               if (atts.XmlText.DataType != null) elem.DataType = atts.XmlText.DataType;
-
-                               if (elem.TypeData.SchemaType != SchemaTypes.Primitive && elem.TypeData.SchemaType != SchemaTypes.Enum &&
-                                   elem.TypeData.SchemaType != SchemaTypes.XmlNode)
-                                       throw new InvalidOperationException ("XmlText cannot be used to encode complex types");
-
-                               elem.ElementName = "<text>";
-                               elem.Namespace = string.Empty;
-                               elem.WrappedElement = false;
-                               list.Add (elem);
-                       }
-
-                       if (atts.XmlElements.Count == 0)
+                       ImportTextElementInfo (list, defaultType, member, atts);
+                       
+                       if (atts.XmlElements.Count == 0 && list.Count == 0)
                        {
                                XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType));
                                elem.ElementName = defaultName;
@@ -544,14 +698,20 @@ namespace System.Xml.Serialization {
                        foreach (XmlElementAttribute att in atts.XmlElements)
                        {
                                Type elemType = (att.Type != null) ? att.Type : defaultType;
-                               XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(elemType));
+                               XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(elemType, att.DataType));
                                elem.ElementName = (att.ElementName != null) ? att.ElementName : defaultName;
-                               elem.DataType = att.DataType;
                                elem.Namespace = (att.Namespace != null) ? att.Namespace : defaultNamespace;
                                elem.Form = att.Form;
                                elem.IsNullable = att.IsNullable;
+                               
+                               if (elem.IsNullable && elem.TypeData.IsValueType)
+                                       throw new InvalidOperationException ("IsNullable may not be 'true' for value type " + elem.TypeData.FullTypeName + " in member '" + defaultName + "'");
+                                       
                                if (elem.TypeData.IsComplexType)
+                               {
+                                       if (att.DataType != null) throw new InvalidOperationException ("'" + att.DataType + "' is an invalid value for the XmlElementAttribute.DateTime property. The property may only be specified for primitive types.");
                                        elem.MappedType = ImportTypeMapping (elemType, null, elem.Namespace);
+                               }
 
                                if (att.ElementName != null) 
                                        elem.ElementName = att.ElementName;
@@ -567,27 +727,75 @@ namespace System.Xml.Serialization {
                        return list;
                }
 
-               XmlTypeMapElementInfoList ImportAnyElementInfo (string defaultNamespace, XmlTypeMapMemberElement member, XmlAttributes atts)
+               XmlTypeMapElementInfoList ImportAnyElementInfo (string defaultNamespace, XmlReflectionMember rmember, XmlTypeMapMemberElement member, XmlAttributes atts)
                {
                        XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
 
+                       ImportTextElementInfo (list, rmember.MemberType, member, atts);
+
                        foreach (XmlAnyElementAttribute att in atts.XmlAnyElements)
                        {
                                XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
-                               elem.ElementName = (att.Name != null) ? att.Name : "";
-                               elem.Namespace = (att.Namespace != null) ? att.Namespace : "";
+                               if (att.Name != null && att.Name != string.Empty) 
+                               {
+                                       elem.ElementName = att.Name;
+                                       elem.Namespace = (att.Namespace != null) ? att.Namespace : "";
+                               }
+                               else 
+                               {
+                                       elem.IsUnnamedAnyElement = true;
+                                       elem.Namespace = defaultNamespace;
+                                       if (att.Namespace != null) 
+                                               throw new InvalidOperationException ("The element " + rmember.MemberName + " has been attributed with an XmlAnyElementAttribute and a namespace '" + att.Namespace + "', but no name. When a namespace is supplied, a name is also required. Supply a name or remove the namespace.");
+                               }
                                list.Add (elem);
                        }
                        return list;
                }
 
+               void ImportTextElementInfo (XmlTypeMapElementInfoList list, Type defaultType, XmlTypeMapMemberElement member, XmlAttributes atts)
+               {
+                       if (atts.XmlText != null)
+                       {
+                               member.IsXmlTextCollector = true;
+                               if (atts.XmlText.Type != null) defaultType = atts.XmlText.Type;
+                               if (defaultType == typeof(XmlNode)) defaultType = typeof(XmlText);      // Nodes must be text nodes
+
+                               XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType, atts.XmlText.DataType));
+
+                               if (elem.TypeData.SchemaType != SchemaTypes.Primitive &&
+                                       elem.TypeData.SchemaType != SchemaTypes.Enum &&
+                                   elem.TypeData.SchemaType != SchemaTypes.XmlNode &&
+                                   !(elem.TypeData.SchemaType == SchemaTypes.Array && elem.TypeData.ListItemTypeData.SchemaType == SchemaTypes.XmlNode)
+                                )
+                                       throw new InvalidOperationException ("XmlText cannot be used to encode complex types");
+
+                               elem.IsTextElement = true;
+                               elem.WrappedElement = false;
+                               list.Add (elem);
+                       }
+               }
+               
+               bool CanBeNull (TypeData type)
+               {
+                       return (type.SchemaType != SchemaTypes.Primitive || type.Type == typeof (string));
+               }
+               
                public void IncludeType (Type type)
                {
                        if (type == null)
                                throw new ArgumentNullException ("type");
 
                        if (includedTypes == null) includedTypes = new ArrayList ();
-                       includedTypes.Add (type);
+                       if (!includedTypes.Contains (type))
+                               includedTypes.Add (type);
+               }
+
+               public void IncludeTypes (ICustomAttributeProvider provider)
+               { 
+                       object[] ats = provider.GetCustomAttributes (typeof(XmlIncludeAttribute), true);
+                       foreach (XmlIncludeAttribute at in ats)
+                               IncludeType (at.Type);
                }
 
                #endregion // Methods