Moved TestConfiguration.cs to Npgsql.
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / MapCodeGenerator.cs
1 // 
2 // System.Xml.Serialization.MapCodeGenerator 
3 //
4 // Author:
5 //   Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // Copyright (C) Ximian, Inc., 2003
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.CodeDom;
32 using System.CodeDom.Compiler;
33 using System.Collections;
34 #if NET_2_0
35 using System.ComponentModel;
36 using System.Diagnostics;
37 #endif
38 using System.Globalization;
39 using System.Xml.Schema;
40
41 using Microsoft.CSharp;
42
43 namespace System.Xml.Serialization {
44         internal class MapCodeGenerator {
45
46                 CodeNamespace codeNamespace;
47                 CodeCompileUnit codeCompileUnit;
48                 CodeAttributeDeclarationCollection includeMetadata;
49                 XmlTypeMapping exportedAnyType = null;
50                 protected bool includeArrayTypes;
51                 CodeDomProvider codeProvider;
52                 CodeGenerationOptions options;
53
54                 Hashtable exportedMaps = new Hashtable ();
55                 Hashtable includeMaps = new Hashtable ();
56
57                 public MapCodeGenerator (CodeNamespace codeNamespace, CodeCompileUnit codeCompileUnit, CodeGenerationOptions options)
58                 {
59                         this.codeCompileUnit = codeCompileUnit;
60                         this.codeNamespace = codeNamespace;
61                         this.options = options;
62                 }
63
64                 public MapCodeGenerator (CodeNamespace codeNamespace, CodeCompileUnit codeCompileUnit, CodeDomProvider codeProvider, CodeGenerationOptions options, Hashtable mappings)
65                 {
66                         this.codeCompileUnit = codeCompileUnit;
67                         this.codeNamespace = codeNamespace;
68                         this.codeProvider = codeProvider;
69                         this.options = options;
70 //                      this.mappings = mappings;
71                 }
72
73                 public CodeAttributeDeclarationCollection IncludeMetadata 
74                 {
75                         get 
76                         { 
77                                 if (includeMetadata != null) return includeMetadata;
78                                 includeMetadata = new CodeAttributeDeclarationCollection ();
79                                 
80                                 foreach (XmlTypeMapping map in includeMaps.Values)
81                                         GenerateClassInclude (includeMetadata, map);
82                                 
83                                 return includeMetadata; 
84                         }
85                 }
86                 
87                 #region Code generation methods
88
89                 public void ExportMembersMapping (XmlMembersMapping xmlMembersMapping)
90                 {
91                         CodeTypeDeclaration dummyClass = new CodeTypeDeclaration ();
92                         ExportMembersMapCode (dummyClass, (ClassMap)xmlMembersMapping.ObjectMap, xmlMembersMapping.Namespace, null);
93                 }
94
95                 public void ExportTypeMapping (XmlTypeMapping xmlTypeMapping, bool isTopLevel)
96                 {
97                         ExportMapCode (xmlTypeMapping, isTopLevel);
98                         RemoveInclude (xmlTypeMapping);
99                 }
100
101                 void ExportMapCode (XmlTypeMapping map, bool isTopLevel)
102                 {
103                         switch (map.TypeData.SchemaType)
104                         {
105                                 case SchemaTypes.Enum:
106                                         ExportEnumCode (map, isTopLevel);
107                                         break;
108
109                                 case SchemaTypes.Array:
110                                         ExportArrayCode (map);
111                                         break;
112
113                                 case SchemaTypes.Class:
114                                         ExportClassCode (map, isTopLevel);
115                                         break;
116
117                                 case SchemaTypes.XmlSerializable:
118                                 case SchemaTypes.XmlNode:
119                                 case SchemaTypes.Primitive:
120                                         // Ignore
121                                         break;
122                         }
123                 }
124
125                 void ExportClassCode (XmlTypeMapping map, bool isTopLevel)
126                 {
127                         CodeTypeDeclaration codeClass;
128                         if (IsMapExported (map)) {
129                                 codeClass = GetMapDeclaration (map);
130                                 if (codeClass != null) {
131                                         // Regenerate attributes, since things may have changed
132                                         codeClass.CustomAttributes.Clear ();
133 #if NET_2_0
134                                         AddClassAttributes (codeClass);
135 #endif
136                                         GenerateClass (map, codeClass, isTopLevel);
137                                         ExportDerivedTypeAttributes (map, codeClass);
138                                 }
139                                 return;
140                         }
141
142                         if (map.TypeData.Type == typeof(object))
143                         {
144                                 exportedAnyType = map;
145                                 SetMapExported (map, null);
146                                 foreach (XmlTypeMapping dmap in exportedAnyType.DerivedTypes) {
147                                         if (IsMapExported (dmap) || !dmap.IncludeInSchema) continue;
148                                         ExportTypeMapping (dmap, false);
149                                         AddInclude (dmap);
150                                 }
151                                 return;
152                         }
153                         
154                         codeClass = new CodeTypeDeclaration (map.TypeData.TypeName);
155                         SetMapExported (map, codeClass);
156
157                         AddCodeType (codeClass, map.Documentation);
158                         codeClass.Attributes = MemberAttributes.Public;
159
160 #if NET_2_0
161                         codeClass.IsPartial = CodeProvider.Supports(GeneratorSupport.PartialTypes);
162                         AddClassAttributes (codeClass);
163 #endif
164
165                         GenerateClass (map, codeClass, isTopLevel);
166                         ExportDerivedTypeAttributes (map, codeClass);
167                         
168                         ExportMembersMapCode (codeClass, (ClassMap)map.ObjectMap, map.XmlTypeNamespace, map.BaseMap);
169
170                         if (map.BaseMap != null && map.BaseMap.TypeData.SchemaType != SchemaTypes.XmlNode)
171                         {
172                                 CodeTypeReference ctr = new CodeTypeReference (map.BaseMap.TypeData.FullTypeName);
173                                 codeClass.BaseTypes.Add (ctr);
174                                 if (map.BaseMap.IncludeInSchema) {
175                                         ExportMapCode (map.BaseMap, false);
176                                         AddInclude (map.BaseMap);
177                                 }
178                         }
179                         ExportDerivedTypes (map, codeClass);
180                 }
181                 
182                 void ExportDerivedTypeAttributes (XmlTypeMapping map, CodeTypeDeclaration codeClass)
183                 {
184                         foreach (XmlTypeMapping tm in map.DerivedTypes)
185                         {
186                                 GenerateClassInclude (codeClass.CustomAttributes, tm);
187                                 ExportDerivedTypeAttributes (tm, codeClass);
188                         }
189                 }
190
191                 void ExportDerivedTypes (XmlTypeMapping map, CodeTypeDeclaration codeClass)
192                 {
193                         foreach (XmlTypeMapping tm in map.DerivedTypes)
194                         {
195                                 if (codeClass.CustomAttributes == null) 
196                                         codeClass.CustomAttributes = new CodeAttributeDeclarationCollection ();
197
198                                 ExportMapCode (tm, false);
199                                 ExportDerivedTypes (tm, codeClass);
200                         }
201                 }
202
203                 void ExportMembersMapCode (CodeTypeDeclaration codeClass, ClassMap map, string defaultNamespace, XmlTypeMapping baseMap)
204                 {
205                         // Write attributes
206
207                         ICollection attributes = map.AttributeMembers;
208                         if (attributes != null) {
209                                 foreach (XmlTypeMapMemberAttribute attr in attributes) {
210                                         if (baseMap != null && DefinedInBaseMap (baseMap, attr)) continue;
211                                         AddAttributeFieldMember (codeClass, attr, defaultNamespace);
212                                 }
213                         }
214
215                         ICollection members = map.ElementMembers;
216                                 
217                         if (members != null)
218                         {
219                                 foreach (XmlTypeMapMemberElement member in members)
220                                 {
221                                         if (baseMap != null && DefinedInBaseMap (baseMap, member)) continue;
222
223                                         Type memType = member.GetType();
224                                         if (memType == typeof(XmlTypeMapMemberList))
225                                         {
226                                                 AddArrayElementFieldMember (codeClass, (XmlTypeMapMemberList) member, defaultNamespace);
227                                         }
228                                         else if (memType == typeof(XmlTypeMapMemberFlatList))
229                                         {
230                                                 AddElementFieldMember (codeClass, member, defaultNamespace);
231                                         }
232                                         else if (memType == typeof(XmlTypeMapMemberAnyElement))
233                                         {
234                                                 AddAnyElementFieldMember (codeClass, member, defaultNamespace);
235                                         }
236                                         else if (memType == typeof(XmlTypeMapMemberElement))
237                                         {
238                                                 AddElementFieldMember (codeClass, member, defaultNamespace);
239                                         }
240                                         else
241                                         {
242                                                 throw new InvalidOperationException ("Member type " + memType + " not supported");
243                                         }
244                                 }
245                         }
246
247                         XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
248                         if (anyAttrMember != null)
249                         {
250                                 CodeTypeMember codeField = CreateFieldMember (codeClass, anyAttrMember.TypeData, anyAttrMember.Name);
251                                 AddComments (codeField, anyAttrMember.Documentation);
252                                 codeField.Attributes = MemberAttributes.Public;
253                                 GenerateAnyAttribute (codeField);
254                         }
255                 }
256                 
257                 CodeTypeMember CreateFieldMember (CodeTypeDeclaration codeClass, Type type, string name)
258                 {
259                         return CreateFieldMember (codeClass, new CodeTypeReference(type), name, System.DBNull.Value, null, null);
260                 }
261
262                 CodeTypeMember CreateFieldMember (CodeTypeDeclaration codeClass, TypeData type, string name)
263                 {
264                         return CreateFieldMember (codeClass, GetDomType (type), name, System.DBNull.Value, null, null);
265                 }
266
267                 CodeTypeMember CreateFieldMember (CodeTypeDeclaration codeClass, XmlTypeMapMember member)
268                 {
269                         return CreateFieldMember (codeClass, GetDomType (member.TypeData), member.Name, member.DefaultValue, member.TypeData, member.Documentation);
270                 }
271                 
272                 CodeTypeMember CreateFieldMember (CodeTypeDeclaration codeClass, CodeTypeReference type, string name, object defaultValue, TypeData defaultType, string documentation)
273                 {
274                         CodeMemberField codeField = null;
275                         CodeTypeMember codeProp = null;
276
277                         if ((options & CodeGenerationOptions.GenerateProperties) > 0) {
278                                 string field = CodeIdentifier.MakeCamel (name + "Field");
279                                 codeField = new CodeMemberField (type, field);
280                                 codeField.Attributes = MemberAttributes.Private;
281                                 codeClass.Members.Add (codeField);
282                                 
283                                 CodeMemberProperty prop = new CodeMemberProperty ();
284                                 prop.Name = name;
285                                 prop.Type = type;
286                                 prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
287                                 codeProp = prop;
288                                 prop.HasGet = prop.HasSet = true;
289                                 
290                                 CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), field);
291                                 prop.SetStatements.Add (new CodeAssignStatement (ce, new CodePropertySetValueReferenceExpression()));
292                                 prop.GetStatements.Add (new CodeMethodReturnStatement (ce));
293                         }
294                         else {
295                                 codeField = new CodeMemberField (type, name);
296                                 codeField.Attributes = MemberAttributes.Public;
297                                 codeProp = codeField;
298                         }
299                         
300                         if (defaultValue != System.DBNull.Value)
301                                 GenerateDefaultAttribute (codeField, codeProp, defaultType, defaultValue);
302
303                         AddComments (codeProp, documentation);
304                         codeClass.Members.Add (codeProp);
305                         return codeProp;
306                 }
307
308                 void AddAttributeFieldMember (CodeTypeDeclaration codeClass, XmlTypeMapMemberAttribute attinfo, string defaultNamespace)
309                 {
310                         CodeTypeMember codeField = CreateFieldMember (codeClass, attinfo);
311
312                         CodeAttributeDeclarationCollection attributes = codeField.CustomAttributes;
313                         if (attributes == null) attributes = new CodeAttributeDeclarationCollection ();
314                         
315                         GenerateAttributeMember (attributes, attinfo, defaultNamespace, false);
316                         if (attributes.Count > 0) codeField.CustomAttributes = attributes;
317
318                         if (attinfo.MappedType != null) {
319                                 ExportMapCode (attinfo.MappedType, false);
320                                 RemoveInclude (attinfo.MappedType);
321                         }
322
323                         if (attinfo.TypeData.IsValueType && attinfo.IsOptionalValueType)
324                         {
325                                 codeField = CreateFieldMember (codeClass, typeof(bool), attinfo.Name + "Specified");
326                                 codeField.Attributes = MemberAttributes.Public;
327                                 GenerateSpecifierMember (codeField);
328                         }
329                 }
330                 
331                 public void AddAttributeMemberAttributes (XmlTypeMapMemberAttribute attinfo, string defaultNamespace, CodeAttributeDeclarationCollection attributes, bool forceUseMemberName)
332                 {
333                         GenerateAttributeMember (attributes, attinfo, defaultNamespace, forceUseMemberName);
334                 }
335
336                 void AddElementFieldMember (CodeTypeDeclaration codeClass, XmlTypeMapMemberElement member, string defaultNamespace)
337                 {
338                         CodeTypeMember codeField = CreateFieldMember (codeClass, member);
339                         
340                         CodeAttributeDeclarationCollection attributes = codeField.CustomAttributes;
341                         if (attributes == null) attributes = new CodeAttributeDeclarationCollection ();
342                         
343                         AddElementMemberAttributes (member, defaultNamespace, attributes, false);
344                         if (attributes.Count > 0) codeField.CustomAttributes = attributes;
345                         
346                         if (member.TypeData.IsValueType && member.IsOptionalValueType)
347                         {
348                                 codeField = CreateFieldMember (codeClass, typeof(bool), member.Name + "Specified");
349                                 codeField.Attributes = MemberAttributes.Public;
350                                 GenerateSpecifierMember (codeField);
351                         }
352                 }
353
354                 public void AddElementMemberAttributes (XmlTypeMapMemberElement member, string defaultNamespace, CodeAttributeDeclarationCollection attributes, bool forceUseMemberName)
355                 {
356                         TypeData defaultType = member.TypeData;
357                         bool addAlwaysAttr = false;
358                         
359                         if (member is XmlTypeMapMemberFlatList)
360                         {
361                                 defaultType = defaultType.ListItemTypeData;
362                                 addAlwaysAttr = true;
363                         }
364                         
365                         foreach (XmlTypeMapElementInfo einfo in member.ElementInfo)
366                         {
367                                 if (ExportExtraElementAttributes (attributes, einfo, defaultNamespace, defaultType))
368                                         continue;
369
370                                 GenerateElementInfoMember (attributes, member, einfo, defaultType, defaultNamespace, addAlwaysAttr, forceUseMemberName);
371                                 if (einfo.MappedType != null) {
372                                         ExportMapCode (einfo.MappedType, false);
373                                         RemoveInclude (einfo.MappedType);
374                                 }
375                         }
376
377                         GenerateElementMember (attributes, member);
378                 }
379
380                 void AddAnyElementFieldMember (CodeTypeDeclaration codeClass, XmlTypeMapMemberElement member, string defaultNamespace)
381                 {
382                         CodeTypeMember codeField = CreateFieldMember (codeClass, member);
383
384                         CodeAttributeDeclarationCollection attributes = new CodeAttributeDeclarationCollection ();
385                         foreach (XmlTypeMapElementInfo einfo in member.ElementInfo)
386                                 ExportExtraElementAttributes (attributes, einfo, defaultNamespace, einfo.TypeData);
387                                 
388                         if (attributes.Count > 0) codeField.CustomAttributes = attributes;
389                 }
390
391                 bool DefinedInBaseMap (XmlTypeMapping map, XmlTypeMapMember member)
392                 {
393                         if (((ClassMap)map.ObjectMap).FindMember (member.Name) != null)
394                                 return true;
395                         else if (map.BaseMap != null)
396                                 return DefinedInBaseMap (map.BaseMap, member);
397                         else
398                                 return false;
399                 }
400
401                 void AddArrayElementFieldMember (CodeTypeDeclaration codeClass, XmlTypeMapMemberList member, string defaultNamespace)
402                 {
403                         CodeTypeMember codeField = CreateFieldMember (codeClass, member.TypeData, member.Name);
404
405                         CodeAttributeDeclarationCollection attributes = new CodeAttributeDeclarationCollection ();
406                         AddArrayAttributes (attributes, member, defaultNamespace, false);
407
408                         ListMap listMap = (ListMap) member.ListTypeMapping.ObjectMap;
409                         AddArrayItemAttributes (attributes, listMap, member.TypeData.ListItemTypeData, defaultNamespace, 0);
410                         
411                         if (attributes.Count > 0) codeField.CustomAttributes = attributes;
412                 }
413
414                 public void AddArrayAttributes (CodeAttributeDeclarationCollection attributes, XmlTypeMapMemberElement member, string defaultNamespace, bool forceUseMemberName)
415                 {
416                         GenerateArrayElement (attributes, member, defaultNamespace, forceUseMemberName);
417                 }
418
419                 public void AddArrayItemAttributes (CodeAttributeDeclarationCollection attributes, ListMap listMap, TypeData type, string defaultNamespace, int nestingLevel)
420                 {
421                         foreach (XmlTypeMapElementInfo ainfo in listMap.ItemInfo)
422                         {
423                                 string defaultName;
424                                 if (ainfo.MappedType != null) defaultName = ainfo.MappedType.ElementName;
425                                 else defaultName = ainfo.TypeData.XmlType;
426
427                                 GenerateArrayItemAttributes (attributes, listMap, type, ainfo, defaultName, defaultNamespace, nestingLevel);
428                                 if (ainfo.MappedType != null) {
429                                         if (!IsMapExported (ainfo.MappedType) && includeArrayTypes)
430                                                 AddInclude (ainfo.MappedType);
431                                         ExportMapCode (ainfo.MappedType, false);
432                                 }
433                         }
434
435                         if (listMap.IsMultiArray)
436                         {
437                                 XmlTypeMapping nmap = listMap.NestedArrayMapping;
438                                 AddArrayItemAttributes (attributes, (ListMap) nmap.ObjectMap, nmap.TypeData.ListItemTypeData, defaultNamespace, nestingLevel + 1);
439                         }
440                 }
441                 
442                 void ExportArrayCode (XmlTypeMapping map)
443                 {
444                         ListMap listMap = (ListMap) map.ObjectMap;
445                         foreach (XmlTypeMapElementInfo ainfo in listMap.ItemInfo)
446                         {
447                                 if (ainfo.MappedType != null) {
448                                         if (!IsMapExported (ainfo.MappedType) && includeArrayTypes)
449                                                 AddInclude (ainfo.MappedType);
450                                         ExportMapCode (ainfo.MappedType, false);
451                                 }
452                         }
453                 }
454
455                 bool ExportExtraElementAttributes (CodeAttributeDeclarationCollection attributes, XmlTypeMapElementInfo einfo, string defaultNamespace, TypeData defaultType)
456                 {
457                         if (einfo.IsTextElement) {
458                                 GenerateTextElementAttribute (attributes, einfo, defaultType);
459                                 return true;
460                         }
461                         else if (einfo.IsUnnamedAnyElement) {
462                                 GenerateUnnamedAnyElementAttribute (attributes, einfo, defaultNamespace);
463                                 return true;
464                         }
465                         return false;
466                 }
467
468                 void ExportEnumCode (XmlTypeMapping map, bool isTopLevel)
469                 {
470                         if (IsMapExported (map)) return;
471
472                         CodeTypeDeclaration codeEnum = new CodeTypeDeclaration (map.TypeData.TypeName);
473                         SetMapExported (map, codeEnum);
474                         
475                         codeEnum.Attributes = MemberAttributes.Public;
476                         codeEnum.IsEnum = true;
477                         AddCodeType (codeEnum, map.Documentation);
478
479                         EnumMap emap = (EnumMap) map.ObjectMap;
480                         if (emap.IsFlags)
481                                 codeEnum.CustomAttributes.Add (new CodeAttributeDeclaration ("System.FlagsAttribute"));
482
483 #if NET_2_0
484                         CodeAttributeDeclaration generatedCodeAttribute = new CodeAttributeDeclaration (
485                                 new CodeTypeReference (typeof(GeneratedCodeAttribute)));
486                         generatedCodeAttribute.Arguments.Add (new CodeAttributeArgument (
487                                 new CodePrimitiveExpression ("System.Xml")));
488                         generatedCodeAttribute.Arguments.Add (new CodeAttributeArgument (
489                                 new CodePrimitiveExpression (Consts.FxFileVersion)));
490                         codeEnum.CustomAttributes.Add (generatedCodeAttribute);
491
492                         codeEnum.CustomAttributes.Add (new CodeAttributeDeclaration (
493                                 new CodeTypeReference (typeof (SerializableAttribute))));
494 #endif
495
496                         GenerateEnum (map, codeEnum, isTopLevel);
497                         
498                         int flag = 1;
499                         foreach (EnumMap.EnumMapMember emem in emap.Members)
500                         {
501                                 CodeMemberField codeField = new CodeMemberField ("", emem.EnumName);
502                                 if (emap.IsFlags) {
503                                         codeField.InitExpression = new CodePrimitiveExpression (flag);
504                                         flag *= 2;
505                                 }
506                                 
507                                 AddComments (codeField, emem.Documentation);
508
509                                 GenerateEnumItem (codeField, emem);
510                                 codeEnum.Members.Add (codeField);
511                         }
512                 }
513                 
514                 void AddInclude (XmlTypeMapping map)
515                 {
516                         if (!includeMaps.ContainsKey (map.TypeData.FullTypeName))
517                                 includeMaps [map.TypeData.FullTypeName] = map;
518                 }
519
520                 void RemoveInclude (XmlTypeMapping map)
521                 {
522                         includeMaps.Remove (map.TypeData.FullTypeName);
523                 }
524
525                 #endregion
526                 
527                 #region Helper methods
528                 
529                 bool IsMapExported (XmlTypeMapping map)
530                 {
531                         if (exportedMaps.Contains (map.TypeData.FullTypeName)) return true;
532                         return false;
533                 }
534
535                 void SetMapExported (XmlTypeMapping map, CodeTypeDeclaration declaration)
536                 {
537                         exportedMaps.Add (map.TypeData.FullTypeName, declaration);
538                 }
539
540                 CodeTypeDeclaration GetMapDeclaration (XmlTypeMapping map)
541                 {
542                         return exportedMaps [map.TypeData.FullTypeName] as CodeTypeDeclaration;
543                 }
544
545                 public static void AddCustomAttribute (CodeTypeMember ctm, CodeAttributeDeclaration att, bool addIfNoParams)
546                 {
547                         if (att.Arguments.Count == 0 && !addIfNoParams) return;
548                         
549                         if (ctm.CustomAttributes == null) ctm.CustomAttributes = new CodeAttributeDeclarationCollection ();
550                         ctm.CustomAttributes.Add (att);
551                 }
552
553                 public static void AddCustomAttribute (CodeTypeMember ctm, string name, params CodeAttributeArgument[] args)
554                 {
555                         if (ctm.CustomAttributes == null) ctm.CustomAttributes = new CodeAttributeDeclarationCollection ();
556                         ctm.CustomAttributes.Add (new CodeAttributeDeclaration (name, args));
557                 }
558
559                 public static CodeAttributeArgument GetArg (string name, object value)
560                 {
561                         return new CodeAttributeArgument (name, new CodePrimitiveExpression(value));
562                 }
563
564                 public static CodeAttributeArgument GetArg (object value)
565                 {
566                         return new CodeAttributeArgument (new CodePrimitiveExpression(value));
567                 }
568
569                 public static CodeAttributeArgument GetTypeArg (string name, string typeName)
570                 {
571                         return new CodeAttributeArgument (name, new CodeTypeOfExpression(typeName));
572                 }
573
574                 public static CodeAttributeArgument GetEnumArg (string name, string enumType, string enumValue)
575                 {
576                         return new CodeAttributeArgument (name, new CodeFieldReferenceExpression (new CodeTypeReferenceExpression(enumType), enumValue));
577                 }
578                 
579                 public static void AddComments (CodeTypeMember member, string comments)
580                 {
581                         if (comments == null || comments == "") member.Comments.Add (new CodeCommentStatement ("<remarks/>", true));
582                         else member.Comments.Add (new CodeCommentStatement ("<remarks>\n" + comments + "\n</remarks>", true));
583                 }
584
585                 void AddCodeType (CodeTypeDeclaration type, string comments)
586                 {
587                         AddComments (type, comments);
588                         codeNamespace.Types.Add (type);
589                 }
590
591 #if NET_2_0
592                 void AddClassAttributes (CodeTypeDeclaration codeClass)
593                 {
594                         CodeAttributeDeclaration generatedCodeAttribute = new CodeAttributeDeclaration (
595                                 new CodeTypeReference (typeof (GeneratedCodeAttribute)));
596                         generatedCodeAttribute.Arguments.Add (new CodeAttributeArgument (
597                                 new CodePrimitiveExpression ("System.Xml")));
598                         generatedCodeAttribute.Arguments.Add (new CodeAttributeArgument (
599                                 new CodePrimitiveExpression (Consts.FxFileVersion)));
600                         codeClass.CustomAttributes.Add (generatedCodeAttribute);
601
602                         codeClass.CustomAttributes.Add (new CodeAttributeDeclaration (
603                                 new CodeTypeReference (typeof (SerializableAttribute))));
604                         codeClass.CustomAttributes.Add (new CodeAttributeDeclaration (
605                                 new CodeTypeReference (typeof (DebuggerStepThroughAttribute))));
606
607                         CodeAttributeDeclaration designerCategoryAttribute = new CodeAttributeDeclaration (
608                                 new CodeTypeReference (typeof (DesignerCategoryAttribute)));
609                         designerCategoryAttribute.Arguments.Add (new CodeAttributeArgument (
610                                 new CodePrimitiveExpression ("code")));
611                         codeClass.CustomAttributes.Add (designerCategoryAttribute);
612                 }
613 #endif
614                 
615                 CodeTypeReference GetDomType (TypeData data)
616                 {
617                         if (data.SchemaType == SchemaTypes.Array)
618                                 return new CodeTypeReference (GetDomType (data.ListItemTypeData),1);
619                         else
620                                 return new CodeTypeReference (data.FullTypeName);
621                 }
622                 
623                 #endregion
624
625                 #region Private Properties
626
627 #if NET_2_0
628                 private CodeDomProvider CodeProvider {
629                         get {
630                                 if (codeProvider == null) {
631                                         codeProvider = new CSharpCodeProvider ();
632                                 }
633                                 return codeProvider;
634                         }
635                 }
636 #endif
637
638                 #endregion
639
640                 #region Overridable methods
641
642                 protected virtual void GenerateClass (XmlTypeMapping map, CodeTypeDeclaration codeClass, bool isTopLevel)
643                 {
644                 }
645                 
646                 protected virtual void GenerateClassInclude (CodeAttributeDeclarationCollection attributes, XmlTypeMapping map)
647                 {
648                 }
649                 
650                 protected virtual void GenerateAnyAttribute (CodeTypeMember codeField)
651                 {
652                 }
653                 
654                 protected virtual void GenerateDefaultAttribute (CodeMemberField internalField, CodeTypeMember externalField, TypeData typeData, object defaultValue)
655                 {
656                         if (typeData.Type == null)
657                         {
658                                 // It must be an enumeration defined in the schema.
659                                 if (typeData.SchemaType != SchemaTypes.Enum) 
660                                         throw new InvalidOperationException ("Type " + typeData.TypeName + " not supported");
661
662                                 IFormattable defaultValueFormattable = defaultValue as IFormattable;
663                                 CodeFieldReferenceExpression fref = new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typeData.FullTypeName), defaultValueFormattable != null ? defaultValueFormattable.ToString(null, CultureInfo.InvariantCulture) : defaultValue.ToString ());
664                                 CodeAttributeArgument arg = new CodeAttributeArgument (fref);
665                                 AddCustomAttribute (externalField, "System.ComponentModel.DefaultValue", arg);
666                                 internalField.InitExpression = fref;
667                         }
668                         else
669                         {
670                                 AddCustomAttribute (externalField, "System.ComponentModel.DefaultValue", GetArg (defaultValue));
671                                 internalField.InitExpression = new CodePrimitiveExpression (defaultValue);
672                         }
673                 }
674                 
675                 protected virtual void GenerateAttributeMember (CodeAttributeDeclarationCollection attributes, XmlTypeMapMemberAttribute attinfo, string defaultNamespace, bool forceUseMemberName)
676                 {
677                 }
678                 
679                 protected virtual void GenerateElementInfoMember (CodeAttributeDeclarationCollection attributes, XmlTypeMapMemberElement member, XmlTypeMapElementInfo einfo, TypeData defaultType, string defaultNamespace, bool addAlwaysAttr, bool forceUseMemberName)
680                 {
681                 }
682                 
683                 protected virtual void GenerateElementMember (CodeAttributeDeclarationCollection attributes, XmlTypeMapMemberElement member)
684                 {
685                 }
686                 
687                 protected virtual void GenerateArrayElement (CodeAttributeDeclarationCollection attributes, XmlTypeMapMemberElement member, string defaultNamespace, bool forceUseMemberName)
688                 {
689                 }
690                 
691                 protected virtual void GenerateArrayItemAttributes (CodeAttributeDeclarationCollection attributes, ListMap listMap, TypeData type, XmlTypeMapElementInfo ainfo, string defaultName, string defaultNamespace, int nestingLevel)
692                 {
693                 }
694
695                 protected virtual void GenerateTextElementAttribute (CodeAttributeDeclarationCollection attributes, XmlTypeMapElementInfo einfo, TypeData defaultType)
696                 {
697                 }
698                 
699                 protected virtual void GenerateUnnamedAnyElementAttribute (CodeAttributeDeclarationCollection attributes, XmlTypeMapElementInfo einfo, string defaultNamespace)
700                 {
701                 }
702
703                 protected virtual void GenerateEnum (XmlTypeMapping map, CodeTypeDeclaration codeEnum, bool isTopLevel)
704                 {
705                 }
706                 
707                 protected virtual void GenerateEnumItem (CodeMemberField codeField, EnumMap.EnumMapMember emem)
708                 {
709                 }
710
711                 protected virtual void GenerateSpecifierMember (CodeTypeMember codeField)
712                 {
713                 }
714
715                 #endregion
716         }
717 }