Moved chain building and validation from Mono.Security to System
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / TypeData.cs
index 53f929469c6f2260f3168b70604ddd71a639f587..00e9beb396e173de4f1360d3494bfc24d24d6189 100644 (file)
@@ -32,6 +32,9 @@
 
 using System;
 using System.Collections;
+#if NET_2_0
+using System.Collections.Generic;
+#endif
 using System.Globalization;
 using System.Reflection;
 using System.Text;
@@ -54,13 +57,17 @@ namespace System.Xml.Serialization
                TypeData mappedType;
                XmlSchemaPatternFacet facet;
                bool hasPublicConstructor = true;
-               bool genericNullable;
+               bool nullableOverride;
 
                public TypeData (Type type, string elementName, bool isPrimitive) :
                        this(type, elementName, isPrimitive, null, null) {}
 
                public TypeData (Type type, string elementName, bool isPrimitive, TypeData mappedType, XmlSchemaPatternFacet facet)
                {
+#if NET_2_0
+                       if (type.IsGenericTypeDefinition)
+                               throw new InvalidOperationException ("Generic type definition cannot be used in serialization. Only specific generic types can be used.");
+#endif
                        this.mappedType = mappedType;
                        this.facet = facet;
                        this.type = type;
@@ -180,7 +187,22 @@ namespace System.Xml.Serialization
                        string name = full ? type.FullName : type.Name;
                        name = name.Replace ('+', '.');
                        int idx = name.IndexOf ('`'); // generic definition has extra `n.
-                       return idx > 0 ? name.Substring (0, idx) : name;
+                       name = idx > 0 ? name.Substring (0, idx) : name;
+                       if (IsKeyword (name))
+                               return "@" + name;
+                       else
+                               return name;
+               }
+               
+               static bool IsKeyword (string name)
+               {
+                       if (keywordsTable == null) {
+                               Hashtable t = new Hashtable ();
+                               foreach (string s in keywords)
+                                       t [s] = s;
+                               keywordsTable = t;
+                       }
+                       return keywordsTable.Contains (name);
                }
 
                public SchemaTypes SchemaType
@@ -217,11 +239,16 @@ namespace System.Xml.Serialization
                        }
                }
 
+               public bool NullableOverride
+               {
+                       get { return nullableOverride; }
+               }
+
                public bool IsNullable
                {
                        get
                        {
-                               if (genericNullable)
+                               if (nullableOverride)
                                        return true;
 #if NET_2_0
                                return !IsValueType ||
@@ -232,13 +259,10 @@ namespace System.Xml.Serialization
                                return !IsValueType;
 #endif
                        }
-               }
 
-               public bool IsGenericNullable
-               {
                        set
                        {
-                               genericNullable = value;
+                               nullableOverride = value;
                        }
                }
 
@@ -261,22 +285,31 @@ namespace System.Xml.Serialization
 
                                if (listItemType != null) return listItemType;
 
+                               Type genericArgument = null;
+
                                if (SchemaType != SchemaTypes.Array)
                                        throw new InvalidOperationException (Type.FullName + " is not a collection");
                                else if (type.IsArray) 
                                        listItemType = type.GetElementType ();
-                               else if (typeof(ICollection).IsAssignableFrom (type))
+#if NET_2_0
+                               else if (typeof (ICollection).IsAssignableFrom (type) || (genericArgument = GetGenericListItemType (type)) != null)
+#else
+                               else if (typeof (ICollection).IsAssignableFrom (type))
+#endif
                                {
                                        if (typeof (IDictionary).IsAssignableFrom (type))
                                                throw new NotSupportedException (string.Format (CultureInfo.InvariantCulture,
                                                        "The type {0} is not supported because it implements" +
                                                        " IDictionary.", type.FullName));
 
-                                       PropertyInfo prop = GetIndexerProperty (type);
-                                       if (prop == null) 
-                                               throw new InvalidOperationException ("You must implement a default accessor on " + type.FullName + " because it inherits from ICollection");
-
-                                       listItemType = prop.PropertyType;
+                                       if (genericArgument != null)
+                                               listItemType = genericArgument;
+                                       else {
+                                               PropertyInfo prop = GetIndexerProperty (type);
+                                               if (prop == null) 
+                                                       throw new InvalidOperationException ("You must implement a default accessor on " + type.FullName + " because it inherits from ICollection");
+                                               listItemType = prop.PropertyType;
+                                       }
 
                                        MethodInfo addMethod = type.GetMethod ("Add", new Type[] { listItemType });
                                        if (addMethod == null)
@@ -365,5 +398,36 @@ namespace System.Xml.Serialization
                                "hierarchy. {2} does not implement Add({1}).", inheritFrom, 
                                argumentType.FullName, type.FullName));
                }
+
+               private static Hashtable keywordsTable;
+               private static string[] keywords = new string[] {
+                       "abstract","event","new","struct","as","explicit","null","switch","base","extern",
+                       "this","false","operator","throw","break","finally","out","true",
+                       "fixed","override","try","case","params","typeof","catch","for",
+                       "private","foreach","protected","checked","goto","public",
+                       "unchecked","class","if","readonly","unsafe","const","implicit","ref",
+                       "continue","in","return","using","virtual","default",
+                       "interface","sealed","volatile","delegate","internal","do","is",
+                       "sizeof","while","lock","stackalloc","else","static","enum",
+                       "namespace",
+                       "object","bool","byte","float","uint","char","ulong","ushort",
+                       "decimal","int","sbyte","short","double","long","string","void",
+#if NET_2_0
+                       "partial", "yield", "where"
+#endif
+               };
+
+#if NET_2_0
+               private Type GetGenericListItemType (Type type)
+               {
+                       if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (ICollection<>))
+                               return type.GetGenericArguments () [0];
+                       Type t = null;
+                       foreach (Type i in type.GetInterfaces ())
+                               if ((t = GetGenericListItemType (i)) != null)
+                                       return t;
+                       return null;
+               }
+#endif
        }
 }