Wrap always_inline and noinline attributes in compiler checks and use MSVC equivalent.
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlReflectionImporter.cs
1 // 
2 // System.Xml.Serialization.XmlReflectionImporter 
3 //
4 // Author:
5 //   Tim Coleman (tim@timcoleman.com)
6 //   Erik LeBel (eriklebel@yahoo.ca)
7 //   Lluis Sanchez Gual (lluis@ximian.com)
8 //
9 // Copyright (C) Tim Coleman, 2002
10 // (C) 2003 Erik LeBel
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System.Collections;
35 using System.Collections.Generic;
36 using System.Globalization;
37 using System.Reflection;
38 using System.Xml.Schema;
39
40 namespace System.Xml.Serialization {
41         public class XmlReflectionImporter {
42
43                 string initialDefaultNamespace;
44                 XmlAttributeOverrides attributeOverrides;
45                 ArrayList includedTypes;
46                 ReflectionHelper helper = new ReflectionHelper();
47                 int arrayChoiceCount = 1;
48                 ArrayList relatedMaps = new ArrayList ();
49                 bool allowPrivateTypes = false;
50
51                 static readonly string errSimple = "Cannot serialize object of type '{0}'. Base " +
52                         "type '{1}' has simpleContent and can be only extended by adding XmlAttribute " +
53                         "elements. Please consider changing XmlText member of the base class to string array";
54
55                 static readonly string errSimple2 = "Cannot serialize object of type '{0}'. " +
56                         "Consider changing type of XmlText member '{1}' from '{2}' to string or string array";
57
58                 #region Constructors
59
60                 public XmlReflectionImporter ()
61                         : this (null, null)
62                 {
63                 }
64
65                 public XmlReflectionImporter (string defaultNamespace)
66                         : this (null, defaultNamespace)
67                 {
68                 }
69
70                 public XmlReflectionImporter (XmlAttributeOverrides attributeOverrides)
71                         : this (attributeOverrides, null)
72                 {
73                 }
74
75                 public XmlReflectionImporter (XmlAttributeOverrides attributeOverrides, string defaultNamespace)
76                 {
77                         if (defaultNamespace == null)
78                                 this.initialDefaultNamespace = String.Empty;
79                         else
80                                 this.initialDefaultNamespace = defaultNamespace;
81
82                         if (attributeOverrides == null)
83                                 this.attributeOverrides = new XmlAttributeOverrides();
84                         else
85                                 this.attributeOverrides = attributeOverrides;
86                 }
87
88 /*              void Reset ()
89                 {
90                         helper = new ReflectionHelper();
91                         arrayChoiceCount = 1;
92                 }
93 */
94                 
95                 internal bool AllowPrivateTypes
96                 {
97                         get { return allowPrivateTypes; }
98                         set { allowPrivateTypes = value; }
99                 }
100
101                 #endregion // Constructors
102
103                 #region Methods
104
105                 public XmlMembersMapping ImportMembersMapping (string elementName,
106                         string ns,
107                         XmlReflectionMember [] members,
108                         bool hasWrapperElement)
109                 {
110                         return ImportMembersMapping (elementName, ns, members, hasWrapperElement, true);
111                 }
112
113 #if NET_2_0
114                 [MonoTODO]
115                 public
116 #endif
117                 XmlMembersMapping ImportMembersMapping (string elementName, 
118                         string ns, 
119                         XmlReflectionMember[] members, 
120                         bool hasWrapperElement, 
121                         bool rpc)
122                 {
123                         return ImportMembersMapping (elementName, ns, members, hasWrapperElement, rpc, true);
124                 }
125
126 #if NET_2_0
127                 [MonoTODO]
128                 public
129 #endif
130                 XmlMembersMapping ImportMembersMapping (string elementName, 
131                         string ns, 
132                         XmlReflectionMember[] members, 
133                         bool hasWrapperElement, 
134                         bool rpc, 
135                         bool openModel)
136                 {
137                         return ImportMembersMapping (elementName, ns, members, hasWrapperElement, rpc, openModel, XmlMappingAccess.Read | XmlMappingAccess.Write);
138                 }
139
140 #if NET_2_0
141                 [MonoTODO] // FIXME: handle writeAccessors, validate, and mapping access
142                 public
143 #endif
144                 XmlMembersMapping ImportMembersMapping (string elementName, 
145                         string ns, 
146                         XmlReflectionMember[] members, 
147                         bool hasWrapperElement, 
148                         bool rpc, 
149                         bool openModel,
150                         XmlMappingAccess access)
151                 {
152 //                      Reset ();       Disabled. See ChangeLog
153
154                         ArrayList mapping = new ArrayList ();
155                         for (int n=0; n<members.Length; n++)
156                         {
157                                 XmlTypeMapMember mapMem = CreateMapMember (null, members[n], ns);
158                                 mapMem.GlobalIndex = n;
159                                 mapMem.CheckOptionalValueType (members);
160                                 mapping.Add (new XmlMemberMapping (members[n].MemberName, ns, mapMem, false));
161                         }
162                         elementName = XmlConvert.EncodeLocalName (elementName);
163                         XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, false, (XmlMemberMapping[])mapping.ToArray (typeof(XmlMemberMapping)));
164                         mps.RelatedMaps = relatedMaps;
165                         mps.Format = SerializationFormat.Literal;
166                         Type[] extraTypes = includedTypes != null ? (Type[])includedTypes.ToArray(typeof(Type)) : null;
167 #if !NET_2_1
168                         mps.Source = new MembersSerializationSource (elementName, hasWrapperElement, members, false, true, ns, extraTypes);
169                         if (allowPrivateTypes) mps.Source.CanBeGenerated = false;
170 #endif
171                         return mps;
172                 }
173
174                 public XmlTypeMapping ImportTypeMapping (Type type)
175                 {
176                         return ImportTypeMapping (type, null, null);
177                 }
178
179                 public XmlTypeMapping ImportTypeMapping (Type type, string defaultNamespace)
180                 {
181                         return ImportTypeMapping (type, null, defaultNamespace);
182                 }
183
184                 public XmlTypeMapping ImportTypeMapping (Type type, XmlRootAttribute root)
185                 {
186                         return ImportTypeMapping (type, root, null);
187                 }
188
189                 public XmlTypeMapping ImportTypeMapping (Type type, XmlRootAttribute root, string defaultNamespace)
190                 {
191                         if (type == null)
192                                 throw new ArgumentNullException ("type");
193
194                         if (type == typeof (void))
195                                 throw new NotSupportedException ("The type " + type.FullName + " may not be serialized.");
196
197                         return ImportTypeMapping (TypeTranslator.GetTypeData (type), root, 
198                                 defaultNamespace);
199                 }
200
201                 internal XmlTypeMapping ImportTypeMapping (TypeData typeData, string defaultNamespace)
202                 {
203                         return ImportTypeMapping (typeData, (XmlRootAttribute) null, 
204                                 defaultNamespace);
205                 }
206
207                 private XmlTypeMapping ImportTypeMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
208                 {
209                         if (typeData == null)
210                                 throw new ArgumentNullException ("typeData");
211
212                         if (typeData.Type == null)
213                                 throw new ArgumentException ("Specified TypeData instance does not have Type set.");
214
215                         if (defaultNamespace == null) defaultNamespace = initialDefaultNamespace;
216                         if (defaultNamespace == null) defaultNamespace = string.Empty;
217
218                         try {
219                                 XmlTypeMapping map;
220
221                                 switch (typeData.SchemaType) {
222                                         case SchemaTypes.Class: map = ImportClassMapping (typeData, root, defaultNamespace); break;
223                                         case SchemaTypes.Array: map = ImportListMapping (typeData, root, defaultNamespace, null, 0); break;
224                                         case SchemaTypes.XmlNode: map = ImportXmlNodeMapping (typeData, root, defaultNamespace); break;
225                                         case SchemaTypes.Primitive: map = ImportPrimitiveMapping (typeData, root, defaultNamespace); break;
226                                         case SchemaTypes.Enum: map = ImportEnumMapping (typeData, root, defaultNamespace); break;
227                                         case SchemaTypes.XmlSerializable: map = ImportXmlSerializableMapping (typeData, root, defaultNamespace); break;
228                                         default: throw new NotSupportedException ("Type " + typeData.Type.FullName + " not supported for XML stialization");
229                                 }
230
231 #if NET_2_0
232                                 // bug #372780
233                                 map.SetKey (typeData.Type.ToString ());
234 #endif
235                                 map.RelatedMaps = relatedMaps;
236                                 map.Format = SerializationFormat.Literal;
237                                 Type[] extraTypes = includedTypes != null ? (Type[]) includedTypes.ToArray (typeof (Type)) : null;
238 #if !NET_2_1
239                                 map.Source = new XmlTypeSerializationSource (typeData.Type, root, attributeOverrides, defaultNamespace, extraTypes);
240                                 if (allowPrivateTypes) map.Source.CanBeGenerated = false;
241 #endif
242                                 return map;
243                         } catch (InvalidOperationException ex) {
244                                 throw new InvalidOperationException (string.Format (CultureInfo.InvariantCulture,
245                                         "There was an error reflecting type '{0}'.", typeData.Type.FullName), ex);
246                         }
247                 }
248
249                 XmlTypeMapping CreateTypeMapping (TypeData typeData, XmlRootAttribute root, string defaultXmlType, string defaultNamespace)
250                 {
251                         string rootNamespace = defaultNamespace;
252                         string typeNamespace = null;
253                         string elementName;
254                         bool includeInSchema = true;
255                         XmlAttributes atts = null;
256                         bool nullable = CanBeNull (typeData);
257
258                         if (defaultXmlType == null) defaultXmlType = typeData.XmlType;
259
260                         if (!typeData.IsListType)
261                         {
262                                 if (attributeOverrides != null) 
263                                         atts = attributeOverrides[typeData.Type];
264
265                                 if (atts != null && typeData.SchemaType == SchemaTypes.Primitive)
266                                         throw new InvalidOperationException ("XmlRoot and XmlType attributes may not be specified for the type " + typeData.FullTypeName);
267                         }
268
269                         if (atts == null) 
270                                 atts = new XmlAttributes (typeData.Type);
271
272                         if (atts.XmlRoot != null && root == null)
273                                 root = atts.XmlRoot;
274
275                         if (atts.XmlType != null)
276                         {
277                                 if (atts.XmlType.Namespace != null)
278                                         typeNamespace = atts.XmlType.Namespace;
279
280                                 if (atts.XmlType.TypeName != null && atts.XmlType.TypeName != string.Empty)
281                                         defaultXmlType = XmlConvert.EncodeLocalName (atts.XmlType.TypeName);
282                                         
283                                 includeInSchema = atts.XmlType.IncludeInSchema;
284                         }
285
286                         elementName = defaultXmlType;
287
288                         if (root != null)
289                         {
290                                 if (root.ElementName.Length != 0)
291                                         elementName = XmlConvert.EncodeLocalName(root.ElementName);
292                                 if (root.Namespace != null)
293                                         rootNamespace = root.Namespace;
294                                 nullable = root.IsNullable;
295                         }
296
297                         if (rootNamespace == null) rootNamespace = "";
298                         if (typeNamespace == null) typeNamespace = rootNamespace;
299                         
300                         XmlTypeMapping map;
301                         switch (typeData.SchemaType) {
302                                 case SchemaTypes.XmlSerializable:
303                                         map = new XmlSerializableMapping (root, elementName, rootNamespace, typeData, defaultXmlType, typeNamespace);
304                                         break;
305                                 case SchemaTypes.Primitive:
306                                         if (!typeData.IsXsdType)
307                                                 map = new XmlTypeMapping (elementName, rootNamespace, 
308                                                         typeData, defaultXmlType, XmlSerializer.WsdlTypesNamespace);
309                                         else
310                                                 map = new XmlTypeMapping (elementName, rootNamespace, 
311                                                         typeData, defaultXmlType, typeNamespace);
312                                         break;
313                                 default:
314                                         map = new XmlTypeMapping (elementName, rootNamespace, typeData, defaultXmlType, typeNamespace);
315                                         break;
316                         }
317
318                         map.IncludeInSchema = includeInSchema;
319                         map.IsNullable = nullable;
320                         relatedMaps.Add (map);
321                         
322                         return map;
323                 }
324
325                 XmlTypeMapping ImportClassMapping (Type type, XmlRootAttribute root, string defaultNamespace)
326                 {
327                         TypeData typeData = TypeTranslator.GetTypeData (type);
328                         return ImportClassMapping (typeData, root, defaultNamespace);
329                 }
330
331                 XmlTypeMapping ImportClassMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
332                 {
333                         Type type = typeData.Type;
334
335                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
336                         if (map != null) return map;
337
338                         if (!allowPrivateTypes)
339                                 ReflectionHelper.CheckSerializableType (type, false);
340                         
341                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
342                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
343                         helper.RegisterSchemaType (map, map.XmlType, map.XmlTypeNamespace);
344
345                         // Import members
346
347                         ClassMap classMap = new ClassMap ();
348                         map.ObjectMap = classMap;
349
350                         var members = GetReflectionMembers (type);
351                         bool? isOrderExplicit = null;
352                         foreach (XmlReflectionMember rmember in members)
353                         {
354                                 int? order = rmember.XmlAttributes.Order;
355                                 if (isOrderExplicit == null)
356                                 {
357                                         if (order != null)
358                                                 isOrderExplicit = (int) order >= 0;
359                                 }
360                                 else if (order != null && isOrderExplicit != ((int) order >= 0))
361                                         throw new InvalidOperationException ("Inconsistent XML sequence was detected. If there are XmlElement/XmlArray/XmlAnyElement attributes with explicit Order, then every other member must have an explicit order too.");
362                         }
363                         if (isOrderExplicit == true)
364                                 members.Sort ((m1, m2) => (int) m1.XmlAttributes.SortableOrder - (int) m2.XmlAttributes.SortableOrder);
365
366                         foreach (XmlReflectionMember rmember in members)
367                         {
368                                 string ns = map.XmlTypeNamespace;
369                                 if (rmember.XmlAttributes.XmlIgnore) continue;
370                                 if (rmember.DeclaringType != null && rmember.DeclaringType != type) {
371                                         XmlTypeMapping bmap = ImportClassMapping (rmember.DeclaringType, root, defaultNamespace);
372                                         ns = bmap.XmlTypeNamespace;
373                                 }
374
375                                 try {
376                                         XmlTypeMapMember mem = CreateMapMember (type, rmember, ns);
377                                         mem.CheckOptionalValueType (type);
378                                         classMap.AddMember (mem);
379                                 } catch (Exception ex) {
380                                         throw new InvalidOperationException (string.Format (
381                                                 CultureInfo.InvariantCulture, "There was an error" +
382                                                 " reflecting field '{0}'.", rmember.MemberName), ex);
383                                 }
384                         }
385
386                         // Import extra classes
387
388                         if (type == typeof (object) && includedTypes != null)
389                         {
390                                 foreach (Type intype in includedTypes)
391                                         map.DerivedTypes.Add (ImportTypeMapping (intype, defaultNamespace));
392                         }
393
394                         // Register inheritance relations
395
396                         if (type.BaseType != null)
397                         {
398                                 XmlTypeMapping bmap = ImportClassMapping (type.BaseType, root, defaultNamespace);
399                                 ClassMap cbmap = bmap.ObjectMap as ClassMap;
400                                 
401                                 if (type.BaseType != typeof (object)) {
402                                         map.BaseMap = bmap;
403                                         if (!cbmap.HasSimpleContent)
404                                                 classMap.SetCanBeSimpleType (false);
405                                 }
406                                 
407                                 // At this point, derived classes of this map must be already registered
408                                 
409                                 RegisterDerivedMap (bmap, map);
410                                 
411                                 if (cbmap.HasSimpleContent && classMap.ElementMembers != null && classMap.ElementMembers.Count != 1)
412                                         throw new InvalidOperationException (String.Format (errSimple, map.TypeData.TypeName, map.BaseMap.TypeData.TypeName));
413                         }
414                         
415                         ImportIncludedTypes (type, defaultNamespace);
416                         
417                         if (classMap.XmlTextCollector != null && !classMap.HasSimpleContent)
418                         {
419                                 XmlTypeMapMember mem = classMap.XmlTextCollector;
420                                 if (mem.TypeData.Type != typeof(string) && 
421                                    mem.TypeData.Type != typeof(string[]) && 
422 #if !MOONLIGHT
423                                    mem.TypeData.Type != typeof(XmlNode[]) && 
424 #endif
425                                    mem.TypeData.Type != typeof(object[]))
426                                    
427                                         throw new InvalidOperationException (String.Format (errSimple2, map.TypeData.TypeName, mem.Name, mem.TypeData.TypeName));
428                         }
429                         
430                         return map;
431                 }
432                 
433                 void RegisterDerivedMap (XmlTypeMapping map, XmlTypeMapping derivedMap)
434                 {
435                         map.DerivedTypes.Add (derivedMap);
436                         map.DerivedTypes.AddRange (derivedMap.DerivedTypes);
437                         
438                         if (map.BaseMap != null)
439                                 RegisterDerivedMap (map.BaseMap, derivedMap);
440                         else {
441                                 XmlTypeMapping obmap = ImportTypeMapping (typeof(object));
442                                 if (obmap != map)
443                                         obmap.DerivedTypes.Add (derivedMap);
444                         }
445                 }
446
447                 string GetTypeNamespace (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
448                 {
449                         string typeNamespace = null;
450                         
451                         XmlAttributes atts = null;
452                         if (!typeData.IsListType)
453                         {
454                                 if (attributeOverrides != null)
455                                         atts = attributeOverrides[typeData.Type];
456                         }
457
458                         if (atts == null)
459                                 atts = new XmlAttributes (typeData.Type);
460
461                         if (atts.XmlType != null)
462                         {
463                                 if (atts.XmlType.Namespace != null && atts.XmlType.Namespace.Length != 0 && typeData.SchemaType != SchemaTypes.Enum)
464                                         typeNamespace = atts.XmlType.Namespace;
465                         }
466
467                         if (typeNamespace != null && typeNamespace.Length != 0) return typeNamespace;
468                         
469                         if (atts.XmlRoot != null && root == null)
470                                 root = atts.XmlRoot;
471
472                         if (root != null)
473                         {
474                                 if (root.Namespace != null && root.Namespace.Length != 0)
475                                         return root.Namespace;
476                         }
477
478                         if (defaultNamespace == null) return "";
479                         else return defaultNamespace;
480                 }
481
482                 XmlTypeMapping ImportListMapping (Type type, XmlRootAttribute root, string defaultNamespace, XmlAttributes atts, int nestingLevel)
483                 {
484                         TypeData typeData = TypeTranslator.GetTypeData (type);
485                         return ImportListMapping (typeData, root, defaultNamespace, atts, nestingLevel);
486                 }
487
488                 XmlTypeMapping ImportListMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace, XmlAttributes atts, int nestingLevel)
489                 {
490                         Type type = typeData.Type;
491                         ListMap obmap = new ListMap ();
492
493                         if (!allowPrivateTypes)
494                                 ReflectionHelper.CheckSerializableType (type, true);
495                         
496                         if (atts == null) atts = new XmlAttributes();
497                         Type itemType = typeData.ListItemType;
498
499                         // warning: byte[][] should not be considered multiarray
500                         bool isMultiArray = (type.IsArray && (TypeTranslator.GetTypeData(itemType).SchemaType == SchemaTypes.Array) && itemType.IsArray);
501
502                         XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
503
504                         foreach (XmlArrayItemAttribute att in atts.XmlArrayItems)
505                         {
506                                 if (att.Namespace != null && att.Form == XmlSchemaForm.Unqualified)
507                                         throw new InvalidOperationException ("XmlArrayItemAttribute.Form must not be Unqualified when it has an explicit Namespace value.");
508                                 if (att.NestingLevel != nestingLevel) continue;
509                                 Type elemType = (att.Type != null) ? att.Type : itemType;
510                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (null, TypeTranslator.GetTypeData(elemType, att.DataType));
511                                 elem.Namespace = att.Namespace != null ? att.Namespace : defaultNamespace;
512                                 if (elem.Namespace == null) elem.Namespace = "";
513                                 elem.Form = att.Form;
514                                 if (att.Form == XmlSchemaForm.Unqualified)
515                                         elem.Namespace = string.Empty;
516                                 elem.IsNullable = att.IsNullable && CanBeNull (elem.TypeData);
517                                 elem.NestingLevel = att.NestingLevel;
518
519                                 if (isMultiArray) {
520                                         elem.MappedType = ImportListMapping (elemType, null, elem.Namespace, atts, nestingLevel + 1);
521                                 } else if (elem.TypeData.IsComplexType) {
522                                         elem.MappedType = ImportTypeMapping (elemType, null, elem.Namespace);
523                                 }
524
525                                 if (att.ElementName.Length != 0) {
526                                         elem.ElementName = XmlConvert.EncodeLocalName (att.ElementName);
527                                 } else if (elem.MappedType != null) {
528                                         elem.ElementName = elem.MappedType.ElementName;
529                                 } else {
530                                         elem.ElementName = TypeTranslator.GetTypeData (elemType).XmlType;
531                                 }
532
533                                 list.Add (elem);
534                         }
535
536                         if (list.Count == 0)
537                         {
538                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (null, TypeTranslator.GetTypeData (itemType));
539                                 if (isMultiArray)
540                                         elem.MappedType = ImportListMapping (itemType, null, defaultNamespace, atts, nestingLevel + 1);
541                                 else if (elem.TypeData.IsComplexType)
542                                         elem.MappedType = ImportTypeMapping (itemType, null, defaultNamespace);
543
544                                 if (elem.MappedType != null) {
545                                         elem.ElementName = elem.MappedType.XmlType;
546                                 } else {
547                                         elem.ElementName = TypeTranslator.GetTypeData (itemType).XmlType;
548                                 }
549
550                                 elem.Namespace = (defaultNamespace != null) ? defaultNamespace : "";
551                                 elem.IsNullable = CanBeNull (elem.TypeData);
552                                 list.Add (elem);
553                         }
554
555                         obmap.ItemInfo = list;
556
557                         // If there can be different element names (types) in the array, then its name cannot
558                         // be "ArrayOfXXX" it must be something like ArrayOfChoiceNNN
559
560                         string baseName;
561                         if (list.Count > 1) {
562                                 baseName = "ArrayOfChoice" + (arrayChoiceCount++);
563                         } else {
564                                 XmlTypeMapElementInfo elem = ((XmlTypeMapElementInfo) list[0]);
565                                 if (elem.MappedType != null) {
566                                         baseName = TypeTranslator.GetArrayName (elem.MappedType.XmlType);
567                                 } else {
568                                         baseName = TypeTranslator.GetArrayName (elem.ElementName);
569                                 }
570                         }
571
572                         // Avoid name colisions
573
574                         int nameCount = 1;
575                         string name = baseName;
576
577                         do {
578                                 XmlTypeMapping foundMap = helper.GetRegisteredSchemaType (name, defaultNamespace);
579                                 if (foundMap == null) nameCount = -1;
580                                 else if (obmap.Equals (foundMap.ObjectMap) && typeData.Type == foundMap.TypeData.Type) return foundMap;
581                                 else name = baseName + (nameCount++);
582                         }
583                         while (nameCount != -1);
584
585                         XmlTypeMapping map = CreateTypeMapping (typeData, root, name, defaultNamespace);
586                         map.ObjectMap = obmap;
587                         
588                         // Register any of the including types as a derived class of object
589                         XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), false);
590                         
591                         XmlTypeMapping objectMapping = ImportTypeMapping (typeof(object));
592                         for (int i = 0; i < includes.Length; i++)
593                         {
594                                 Type includedType = includes[i].Type;
595                                 objectMapping.DerivedTypes.Add(ImportTypeMapping (includedType, null, defaultNamespace));
596                         }
597                         
598                         // Register this map as a derived class of object
599
600                         helper.RegisterSchemaType (map, name, defaultNamespace);
601                         ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
602
603                         return map;
604                 }
605
606                 XmlTypeMapping ImportXmlNodeMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
607                 {
608                         Type type = typeData.Type;
609                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
610                         if (map != null) return map;
611
612                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
613                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
614                         
615                         if (type.BaseType != null)
616                         {
617                                 XmlTypeMapping bmap = ImportTypeMapping (type.BaseType, root, defaultNamespace);
618                                 if (type.BaseType != typeof (object))
619                                         map.BaseMap = bmap;
620                                 
621                                 RegisterDerivedMap (bmap, map);
622                         }
623
624                         return map;
625                 }
626
627                 XmlTypeMapping ImportPrimitiveMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
628                 {
629                         Type type = typeData.Type;
630                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
631                         if (map != null) return map;
632                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
633                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
634                         return map;
635                 }
636 #if MOONLIGHT
637                 // Enum.GetNames is not available in SL API
638                 public static System.Collections.Generic.IEnumerable<string> GetEnumNames (Type type)
639                 {
640                         System.Collections.Generic.List<string> names = new System.Collections.Generic.List<string> ();
641                         foreach (FieldInfo fi in type.GetFields (BindingFlags.Static | BindingFlags.Public))
642                                 names.Add (fi.Name);
643                         return names;
644                 }
645 #endif
646                 XmlTypeMapping ImportEnumMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
647                 {
648                         Type type = typeData.Type;
649                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
650                         if (map != null) return map;
651                         
652                         if (!allowPrivateTypes)
653                                 ReflectionHelper.CheckSerializableType (type, false);
654                                 
655                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
656                         map.IsNullable = false;
657                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
658
659                         ArrayList members = new ArrayList();
660 #if MOONLIGHT
661                         foreach (string name in GetEnumNames (type)) {
662 #else
663                         string [] names = Enum.GetNames (type);
664                         foreach (string name in names) {
665 #endif
666                                 FieldInfo field = type.GetField (name);
667                                 string xmlName = null;
668                                 if (field.IsDefined(typeof(XmlIgnoreAttribute), false))
669                                         continue;
670                                 object[] atts = field.GetCustomAttributes (typeof(XmlEnumAttribute), false);
671                                 if (atts.Length > 0) xmlName = ((XmlEnumAttribute)atts[0]).Name;
672                                 if (xmlName == null) xmlName = name;
673                                 long value = ((IConvertible) field.GetValue (null)).ToInt64 (CultureInfo.InvariantCulture);
674                                 members.Add (new EnumMap.EnumMapMember (xmlName, name, value));
675                         }
676
677                         bool isFlags = type.IsDefined (typeof (FlagsAttribute), false);
678                         map.ObjectMap = new EnumMap ((EnumMap.EnumMapMember[])members.ToArray (typeof(EnumMap.EnumMapMember)), isFlags);
679                         ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
680                         return map;
681                 }
682
683                 XmlTypeMapping ImportXmlSerializableMapping (TypeData typeData, XmlRootAttribute root, string defaultNamespace)
684                 {
685                         Type type = typeData.Type;
686                         XmlTypeMapping map = helper.GetRegisteredClrType (type, GetTypeNamespace (typeData, root, defaultNamespace));
687                         if (map != null) return map;
688                         
689                         if (!allowPrivateTypes)
690                                 ReflectionHelper.CheckSerializableType (type, false);
691                                 
692                         map = CreateTypeMapping (typeData, root, null, defaultNamespace);
693                         helper.RegisterClrType (map, type, map.XmlTypeNamespace);
694                         return map;
695                 }
696
697                 void ImportIncludedTypes (Type type, string defaultNamespace)
698                 {
699                         XmlIncludeAttribute[] includes = (XmlIncludeAttribute[])type.GetCustomAttributes (typeof (XmlIncludeAttribute), false);
700                         for (int n=0; n<includes.Length; n++)
701                         {
702                                 Type includedType = includes[n].Type;
703                                 ImportTypeMapping (includedType, null, defaultNamespace);
704                         }
705                 }
706
707                 List<XmlReflectionMember> GetReflectionMembers (Type type)
708                 {
709                         // First we want to find the inheritance hierarchy in reverse order.
710                         Type currentType = type;
711                         ArrayList typeList = new ArrayList();
712                         typeList.Add(currentType);
713                         while (currentType != typeof(object))
714                         {
715                                 currentType = currentType.BaseType; // Read the base type.
716                                 typeList.Insert(0, currentType); // Insert at 0 to reverse the order.
717                         }
718
719                         // Read all Fields via reflection.
720                         ArrayList fieldList = new ArrayList();
721                         FieldInfo[] tfields = type.GetFields (BindingFlags.Instance | BindingFlags.Public);
722 #if TARGET_JVM
723                         // This statement ensures fields are ordered starting from the base type.
724                         for (int ti=0; ti<typeList.Count; ti++) {
725                                 for (int i=0; i<tfields.Length; i++) {
726                                         FieldInfo field = tfields[i];
727                                         if (field.DeclaringType == typeList[ti])
728                                                 fieldList.Add (field);
729                                 }
730                         }
731 #else
732                         currentType = null;
733                         int currentIndex = 0;
734                         foreach (FieldInfo field in tfields)
735                         {
736                                 // This statement ensures fields are ordered starting from the base type.
737                                 if (currentType != field.DeclaringType)
738                                 {
739                                         currentType = field.DeclaringType;
740                                         currentIndex=0;
741                                 }
742                                 fieldList.Insert(currentIndex++, field);
743                         }
744 #endif
745                         // Read all Properties via reflection.
746                         ArrayList propList = new ArrayList();
747                         PropertyInfo[] tprops = type.GetProperties (BindingFlags.Instance | BindingFlags.Public);
748 #if TARGET_JVM
749                         // This statement ensures properties are ordered starting from the base type.
750                         for (int ti=0; ti<typeList.Count; ti++) {
751                                 for (int i=0; i<tprops.Length; i++) {
752                                         PropertyInfo prop = tprops[i];
753                                         if (!prop.CanRead) continue;
754                                         if (prop.GetIndexParameters().Length > 0) continue;
755                                         if (prop.DeclaringType == typeList[ti])
756                                                 propList.Add (prop);
757                                 }
758                         }
759 #else
760                         currentType = null;
761                         currentIndex = 0;
762                         foreach (PropertyInfo prop in tprops)
763                         {
764                                 // This statement ensures properties are ordered starting from the base type.
765                                 if (currentType != prop.DeclaringType)
766                                 {
767                                         currentType = prop.DeclaringType;
768                                         currentIndex = 0;
769                                 }
770                                 if (!prop.CanRead) continue;
771                                 if (prop.GetIndexParameters().Length > 0) continue;
772                                 propList.Insert(currentIndex++, prop);
773                         }
774 #endif
775                         var members = new List<XmlReflectionMember>();
776                         int fieldIndex=0;
777                         int propIndex=0;
778                         // We now step through the type hierarchy from the base (object) through
779                         // to the supplied class, as each step outputting all Fields, and then
780                         // all Properties.  This is the exact same ordering as .NET 1.0/1.1.
781                         foreach (Type t in typeList)
782                         {
783                                 // Add any fields matching the current DeclaringType.
784                                 while (fieldIndex < fieldList.Count)
785                                 {
786                                         FieldInfo field = (FieldInfo)fieldList[fieldIndex];
787                                         if (field.DeclaringType==t)
788                                         {
789                                                 fieldIndex++;
790                                                 XmlAttributes atts = attributeOverrides[type, field.Name];
791                                                 if (atts == null) atts = new XmlAttributes (field);
792                                                 if (atts.XmlIgnore) continue;
793                                                 XmlReflectionMember member = new XmlReflectionMember(field.Name, field.FieldType, atts);
794                                                 member.DeclaringType = field.DeclaringType;
795                                                 members.Add(member);
796                                         }
797                                         else break;
798                                 }
799
800                                 // Add any properties matching the current DeclaringType.
801                                 while (propIndex < propList.Count)
802                                 {
803                                         PropertyInfo prop = (PropertyInfo)propList[propIndex];
804                                         if (prop.DeclaringType==t)
805                                         {
806                                                 propIndex++;
807                                                 XmlAttributes atts = attributeOverrides[type, prop.Name];
808                                                 if (atts == null) atts = new XmlAttributes (prop);
809                                                 if (atts.XmlIgnore) continue;
810                                                 if (!prop.CanWrite) {
811                                                         if (prop.PropertyType.IsGenericType && TypeData.GetGenericListItemType (prop.PropertyType) == null) continue; // check this before calling GetTypeData() which raises error for missing Add(). See bug #704813.
812                                                         if (TypeTranslator.GetTypeData (prop.PropertyType).SchemaType != SchemaTypes.Array || prop.PropertyType.IsArray) continue;
813                                                 }
814                                                 XmlReflectionMember member = new XmlReflectionMember(prop.Name, prop.PropertyType, atts);
815                                                 member.DeclaringType = prop.DeclaringType;
816                                                 members.Add(member);
817                                         }
818                                         else break;
819                                 }
820                         }
821                         
822                         return members;
823                 }
824                 
825                 private XmlTypeMapMember CreateMapMember (Type declaringType, XmlReflectionMember rmember, string defaultNamespace)
826                 {
827                         XmlTypeMapMember mapMember;
828                         XmlAttributes atts = rmember.XmlAttributes;
829                         TypeData typeData = TypeTranslator.GetTypeData (rmember.MemberType);
830
831                         if (atts.XmlArray != null) {
832                                 if (atts.XmlArray.Namespace != null && atts.XmlArray.Form == XmlSchemaForm.Unqualified)
833                                         throw new InvalidOperationException ("XmlArrayAttribute.Form must not be Unqualified when it has an explicit Namespace value.");
834                                 if (typeData.SchemaType != SchemaTypes.Array &&
835                                     !(typeData.SchemaType == SchemaTypes.Primitive && typeData.Type == typeof (byte [])))
836                                         throw new InvalidOperationException ("XmlArrayAttribute can be applied to members of array or collection type.");
837                         }
838
839 #if !MOONLIGHT
840                         if (atts.XmlAnyAttribute != null)
841                         {
842                                 if ( (rmember.MemberType.FullName == "System.Xml.XmlAttribute[]") ||
843                                          (rmember.MemberType.FullName == "System.Xml.XmlNode[]") )
844                                 {
845                                         mapMember = new XmlTypeMapMemberAnyAttribute();
846                                 }
847                                 else
848                                         throw new InvalidOperationException ("XmlAnyAttributeAttribute can only be applied to members of type XmlAttribute[] or XmlNode[]");
849                         }
850                         else
851 #endif
852                         if (atts.XmlAnyElements != null && atts.XmlAnyElements.Count > 0)
853                         {
854                                 // no XmlNode type check is done here (seealso: bug #553032).
855                                 XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement();
856                                 member.ElementInfo = ImportAnyElementInfo (defaultNamespace, rmember, member, atts);
857                                 mapMember = member;
858                         }
859                         else if (atts.Xmlns)
860                         {
861                                 XmlTypeMapMemberNamespaces mapNamespaces = new XmlTypeMapMemberNamespaces ();
862                                 mapMember = mapNamespaces;
863                         }
864                         else if (atts.XmlAttribute != null)
865                         {
866                                 // An attribute
867
868                                 if (atts.XmlElements != null && atts.XmlElements.Count > 0)
869                                         throw new Exception ("XmlAttributeAttribute and XmlElementAttribute cannot be applied to the same member");
870
871                                 XmlTypeMapMemberAttribute mapAttribute = new XmlTypeMapMemberAttribute ();
872                                 if (atts.XmlAttribute.AttributeName.Length == 0) 
873                                         mapAttribute.AttributeName = rmember.MemberName;
874                                 else 
875                                         mapAttribute.AttributeName = atts.XmlAttribute.AttributeName;
876
877                                 mapAttribute.AttributeName = XmlConvert.EncodeLocalName (mapAttribute.AttributeName);
878
879                                 if (typeData.IsComplexType)
880                                         mapAttribute.MappedType = ImportTypeMapping (typeData.Type, null, defaultNamespace);
881
882                                 if (atts.XmlAttribute.Namespace != null && atts.XmlAttribute.Namespace != defaultNamespace)
883                                 {
884                                         if (atts.XmlAttribute.Form == XmlSchemaForm.Unqualified)
885                                                 throw new InvalidOperationException ("The Form property may not be 'Unqualified' when an explicit Namespace property is present");
886                                         mapAttribute.Form = XmlSchemaForm.Qualified;
887                                         mapAttribute.Namespace = atts.XmlAttribute.Namespace;
888                                 }
889                                 else
890                                 {
891                                         mapAttribute.Form = atts.XmlAttribute.Form;
892                                         if (atts.XmlAttribute.Form == XmlSchemaForm.Qualified)
893                                                 mapAttribute.Namespace = defaultNamespace;
894                                         else
895                                                 mapAttribute.Namespace = "";
896                                 }
897                                 
898                                 typeData = TypeTranslator.GetTypeData(rmember.MemberType, atts.XmlAttribute.DataType);
899                                 mapMember = mapAttribute;
900                         }
901                         else if (typeData.SchemaType == SchemaTypes.Array)
902                         {
903                                 // If the member has a single XmlElementAttribute and the type is the type of the member,
904                                 // then it is not a flat list
905                                 
906                                 if (atts.XmlElements.Count > 1 ||
907                                    (atts.XmlElements.Count == 1 && atts.XmlElements[0].Type != typeData.Type) ||
908                                    (atts.XmlText != null))
909                                 {
910                                         // A flat list
911
912                                         // check that it does not have XmlArrayAttribute
913                                         if (atts.XmlArray != null)
914                                                 throw new InvalidOperationException ("XmlArrayAttribute cannot be used with members which also attributed with XmlElementAttribute or XmlTextAttribute.");
915
916                                         XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
917                                         member.ListMap = new ListMap ();
918                                         member.ListMap.ItemInfo = ImportElementInfo (declaringType, XmlConvert.EncodeLocalName (rmember.MemberName), defaultNamespace, typeData.ListItemType, member, atts);
919                                         member.ElementInfo = member.ListMap.ItemInfo;
920                                         member.ListMap.ChoiceMember = member.ChoiceMember;
921                                         mapMember = member;
922                                 }
923                                 else
924                                 {
925                                         // A list
926
927                                         XmlTypeMapMemberList member = new XmlTypeMapMemberList ();
928
929                                         // Creates an ElementInfo that identifies the array instance. 
930                                         member.ElementInfo = new XmlTypeMapElementInfoList();
931                                         XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, typeData);
932                                         elem.ElementName = XmlConvert.EncodeLocalName((atts.XmlArray != null && atts.XmlArray.ElementName.Length != 0) ? atts.XmlArray.ElementName : rmember.MemberName);
933                                         // note that it could be changed below (when Form is Unqualified)
934                                         elem.Namespace = (atts.XmlArray != null && atts.XmlArray.Namespace != null) ? atts.XmlArray.Namespace : defaultNamespace;
935                                         elem.MappedType = ImportListMapping (rmember.MemberType, null, elem.Namespace, atts, 0);
936                                         elem.IsNullable = (atts.XmlArray != null) ? atts.XmlArray.IsNullable : false;
937                                         elem.Form = (atts.XmlArray != null) ? atts.XmlArray.Form : XmlSchemaForm.Qualified;
938                                         elem.ExplicitOrder = (atts.XmlArray != null) ? atts.XmlArray.Order : -1;
939                                         // This is a bit tricky, but is done
940                                         // after filling descendant members, so
941                                         // that array items could be serialized
942                                         // with proper namespace.
943                                         if (atts.XmlArray != null && atts.XmlArray.Form == XmlSchemaForm.Unqualified)
944                                                 elem.Namespace = String.Empty;
945
946                                         member.ElementInfo.Add (elem);
947                                         mapMember = member;
948                                 }
949                         }
950                         else
951                         {
952                                 // An element
953
954                                 XmlTypeMapMemberElement member = new XmlTypeMapMemberElement ();
955                                 member.ElementInfo = ImportElementInfo (declaringType, XmlConvert.EncodeLocalName(rmember.MemberName), defaultNamespace, rmember.MemberType, member, atts);
956                                 mapMember = member;
957                         }
958
959                         mapMember.DefaultValue = GetDefaultValue (typeData, atts.XmlDefaultValue);
960                         mapMember.TypeData = typeData;
961                         mapMember.Name = rmember.MemberName;
962                         mapMember.IsReturnValue = rmember.IsReturnValue;
963                         return mapMember;
964                 }
965
966                 XmlTypeMapElementInfoList ImportElementInfo (Type cls, string defaultName, string defaultNamespace, Type defaultType, XmlTypeMapMemberElement member, XmlAttributes atts)
967                 {
968                         EnumMap choiceEnumMap = null;
969                         Type choiceEnumType = null;
970                         
971                         XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
972                         ImportTextElementInfo (list, defaultType, member, atts, defaultNamespace);
973                         
974                         if (atts.XmlChoiceIdentifier != null) {
975                                 if (cls == null)
976                                         throw new InvalidOperationException ("XmlChoiceIdentifierAttribute not supported in this context.");
977                                         
978                                 member.ChoiceMember = atts.XmlChoiceIdentifier.MemberName;
979                                 MemberInfo[] mems = cls.GetMember (member.ChoiceMember, BindingFlags.Instance|BindingFlags.Public);
980                                 
981                                 if (mems.Length == 0)
982                                         throw new InvalidOperationException ("Choice member '" + member.ChoiceMember + "' not found in class '" + cls);
983                                         
984                                 if (mems[0] is PropertyInfo) {
985                                         PropertyInfo pi = (PropertyInfo)mems[0];
986                                         if (!pi.CanWrite || !pi.CanRead)
987                                                 throw new InvalidOperationException ("Choice property '" + member.ChoiceMember + "' must be read/write.");
988                                         choiceEnumType = pi.PropertyType;
989                                 }
990                                 else choiceEnumType = ((FieldInfo)mems[0]).FieldType;
991                                 
992                                 member.ChoiceTypeData = TypeTranslator.GetTypeData (choiceEnumType);
993                                 
994                                 if (choiceEnumType.IsArray)
995                                         choiceEnumType = choiceEnumType.GetElementType ();
996                                 
997                                 choiceEnumMap = ImportTypeMapping (choiceEnumType).ObjectMap as EnumMap;
998                                 if (choiceEnumMap == null)
999                                         throw new InvalidOperationException ("The member '" + mems[0].Name + "' is not a valid target for XmlChoiceIdentifierAttribute.");
1000                         }
1001                         
1002                         if (atts.XmlElements.Count == 0 && list.Count == 0)
1003                         {
1004                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType));
1005                                 elem.ElementName = defaultName;
1006                                 elem.Namespace = defaultNamespace;
1007                                 if (elem.TypeData.IsComplexType)
1008                                         elem.MappedType = ImportTypeMapping (defaultType, null, defaultNamespace);
1009                                 list.Add (elem);
1010                         }
1011
1012                         bool multiType = (atts.XmlElements.Count > 1);
1013                         foreach (XmlElementAttribute att in atts.XmlElements)
1014                         {
1015                                 Type elemType = (att.Type != null) ? att.Type : defaultType;
1016                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(elemType, att.DataType));
1017                                 elem.Form = att.Form;
1018                                 if (elem.Form != XmlSchemaForm.Unqualified)
1019                                         elem.Namespace = (att.Namespace != null) ? att.Namespace : defaultNamespace;
1020                                 elem.IsNullable = att.IsNullable;
1021                                 elem.ExplicitOrder = att.Order;
1022
1023                                 if (elem.IsNullable && !elem.TypeData.IsNullable)
1024                                         throw new InvalidOperationException ("IsNullable may not be 'true' for value type " + elem.TypeData.FullTypeName + " in member '" + defaultName + "'");
1025                                         
1026                                 if (elem.TypeData.IsComplexType)
1027                                 {
1028                                         if (att.DataType.Length != 0) throw new InvalidOperationException (
1029                                                 string.Format(CultureInfo.InvariantCulture, "'{0}' is "
1030                                                         + "an invalid value for '{1}.{2}' of type '{3}'. "
1031                                                         + "The property may only be specified for primitive types.",
1032                                                         att.DataType, cls.FullName, defaultName, 
1033                                                         elem.TypeData.FullTypeName));
1034                                         elem.MappedType = ImportTypeMapping (elemType, null, elem.Namespace);
1035                                 }
1036
1037                                 if (att.ElementName.Length != 0)  {
1038                                         elem.ElementName = XmlConvert.EncodeLocalName(att.ElementName);
1039                                 } else if (multiType) {
1040                                         if (elem.MappedType != null) {
1041                                                 elem.ElementName = elem.MappedType.ElementName;
1042                                         } else {
1043                                                 elem.ElementName = TypeTranslator.GetTypeData (elemType).XmlType;
1044                                         }
1045                                 } else {
1046                                         elem.ElementName = defaultName;
1047                                 }
1048
1049                                 if (choiceEnumMap != null) {
1050                                         string cname = choiceEnumMap.GetEnumName (choiceEnumType.FullName, elem.ElementName);
1051                                         if (cname == null)
1052                                                 throw new InvalidOperationException (string.Format (
1053                                                         CultureInfo.InvariantCulture, "Type {0} is missing"
1054                                                         + " enumeration value '{1}' for element '{1} from"
1055                                                         + " namespace '{2}'.", choiceEnumType, elem.ElementName,
1056                                                         elem.Namespace));
1057                                         elem.ChoiceValue = Enum.Parse (choiceEnumType, cname, false);
1058                                 }
1059                                         
1060                                 list.Add (elem);
1061                         }
1062                         return list;
1063                 }
1064
1065                 XmlTypeMapElementInfoList ImportAnyElementInfo (string defaultNamespace, XmlReflectionMember rmember, XmlTypeMapMemberElement member, XmlAttributes atts)
1066                 {
1067                         XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
1068
1069                         ImportTextElementInfo (list, rmember.MemberType, member, atts, defaultNamespace);
1070
1071 #if !MOONLIGHT // no practical anyElement support
1072                         foreach (XmlAnyElementAttribute att in atts.XmlAnyElements)
1073                         {
1074                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
1075                                 if (att.Name.Length != 0) 
1076                                 {
1077                                         elem.ElementName = XmlConvert.EncodeLocalName(att.Name);
1078                                         elem.Namespace = (att.Namespace != null) ? att.Namespace : "";
1079                                 }
1080                                 else 
1081                                 {
1082                                         elem.IsUnnamedAnyElement = true;
1083                                         elem.Namespace = defaultNamespace;
1084                                         if (att.Namespace != null) 
1085                                                 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.");
1086                                 }
1087                                 elem.ExplicitOrder = att.Order;
1088                                 list.Add (elem);
1089                         }
1090 #endif
1091                         return list;
1092                 }
1093
1094                 void ImportTextElementInfo (XmlTypeMapElementInfoList list, Type defaultType, XmlTypeMapMemberElement member, XmlAttributes atts, string defaultNamespace)
1095                 {
1096                         if (atts.XmlText != null)
1097                         {
1098                                 member.IsXmlTextCollector = true;
1099                                 if (atts.XmlText.Type != null) {
1100                                         TypeData td = TypeTranslator.GetTypeData (defaultType);
1101                                         if ((td.SchemaType == SchemaTypes.Primitive || td.SchemaType == SchemaTypes.Enum) && atts.XmlText.Type != defaultType) {
1102                                                 throw new InvalidOperationException ("The type for XmlText may not be specified for primitive types.");
1103                                         }
1104                                         defaultType = atts.XmlText.Type;
1105                                 }
1106 #if !MOONLIGHT
1107                                 if (defaultType == typeof(XmlNode)) defaultType = typeof(XmlText);      // Nodes must be text nodes
1108 #endif
1109
1110                                 XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(defaultType, atts.XmlText.DataType));
1111
1112                                 if (elem.TypeData.SchemaType != SchemaTypes.Primitive &&
1113                                         elem.TypeData.SchemaType != SchemaTypes.Enum &&
1114                                     elem.TypeData.SchemaType != SchemaTypes.XmlNode &&
1115                                     !(elem.TypeData.SchemaType == SchemaTypes.Array && elem.TypeData.ListItemTypeData.SchemaType == SchemaTypes.XmlNode)
1116                                  )
1117                                         throw new InvalidOperationException ("XmlText cannot be used to encode complex types");
1118
1119                                 if (elem.TypeData.IsComplexType)
1120                                         elem.MappedType = ImportTypeMapping (defaultType, null, defaultNamespace);
1121                                 elem.IsTextElement = true;
1122                                 elem.WrappedElement = false;
1123                                 list.Add (elem);
1124                         }
1125                 }
1126                 
1127                 bool CanBeNull (TypeData type)
1128                 {
1129 #if !NET_2_0    // idiotic compatibility
1130                         if (type.Type == typeof (XmlQualifiedName))
1131                                 return false;
1132 #endif
1133                         return !type.Type.IsValueType || type.IsNullable;
1134                 }
1135                 
1136                 public void IncludeType (Type type)
1137                 {
1138                         if (type == null)
1139                                 throw new ArgumentNullException ("type");
1140
1141                         if (includedTypes == null) includedTypes = new ArrayList ();
1142                         if (!includedTypes.Contains (type))
1143                                 includedTypes.Add (type);
1144                         
1145                         if (relatedMaps.Count > 0) {
1146                                 foreach (XmlTypeMapping map in (ArrayList) relatedMaps.Clone ()) {
1147                                         if (map.TypeData.Type == typeof(object))
1148                                                 map.DerivedTypes.Add (ImportTypeMapping (type));
1149                                 }
1150                         }
1151                 }
1152
1153                 public void IncludeTypes (ICustomAttributeProvider provider)
1154                 { 
1155                         object[] ats = provider.GetCustomAttributes (typeof(XmlIncludeAttribute), true);
1156                         
1157                         foreach (XmlIncludeAttribute at in ats)
1158                                 IncludeType (at.Type);
1159                 }
1160
1161                 private object GetDefaultValue (TypeData typeData, object defaultValue)
1162                 {
1163                         if (defaultValue == DBNull.Value || typeData.SchemaType != SchemaTypes.Enum)
1164                                 return defaultValue;
1165
1166 #if MOONLIGHT
1167                         string namedValue = (defaultValue as Enum).ToString ("g");
1168                         string decimalValue = (defaultValue as Enum).ToString ("d");
1169 #else
1170                         // get string representation of enum value
1171                         string namedValue = Enum.Format (typeData.Type, defaultValue, "g");
1172                         // get decimal representation of enum value
1173                         string decimalValue = Enum.Format (typeData.Type, defaultValue, "d");
1174 #endif
1175                         // if decimal representation matches string representation, then
1176                         // the value is not defined in the enum type (as the "g" format
1177                         // will return the decimal equivalent of the value if the value
1178                         // is not equal to a combination of named enumerated constants
1179                         if (namedValue == decimalValue) {
1180                                 string msg = string.Format (CultureInfo.InvariantCulture,
1181                                         "Value '{0}' cannot be converted to {1}.", defaultValue,
1182                                         defaultValue.GetType ().FullName);
1183                                 throw new InvalidOperationException (msg);
1184                         }
1185
1186                         // XmlSerializer expects integral enum value
1187                         //return namedValue.Replace (',', ' ');
1188                         return defaultValue;
1189                 }
1190
1191                 #endregion // Methods
1192         }
1193 }