New test.
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlCodeExporter.cs
1 // \r
2 // System.Xml.Serialization.XmlCodeExporter \r
3 //\r
4 // Author:\r
5 //   Tim Coleman (tim@timcoleman.com)\r
6 //   Lluis Sanchez Gual (lluis@ximian.com)\r
7 //\r
8 // Copyright (C) Tim Coleman, 2002\r
9 //\r
10 \r
11 //\r
12 // Permission is hereby granted, free of charge, to any person obtaining\r
13 // a copy of this software and associated documentation files (the\r
14 // "Software"), to deal in the Software without restriction, including\r
15 // without limitation the rights to use, copy, modify, merge, publish,\r
16 // distribute, sublicense, and/or sell copies of the Software, and to\r
17 // permit persons to whom the Software is furnished to do so, subject to\r
18 // the following conditions:\r
19 // \r
20 // The above copyright notice and this permission notice shall be\r
21 // included in all copies or substantial portions of the Software.\r
22 // \r
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
30 //\r
31 \r
32 using System.CodeDom;\r
33 using System.Collections;\r
34 using System.Xml.Schema;\r
35 using System.CodeDom.Compiler;\r
36 \r
37 namespace System.Xml.Serialization \r
38 {\r
39 \r
40         public class XmlCodeExporter \r
41 #if NET_2_0\r
42                 : CodeExporter\r
43 #endif\r
44         {\r
45                 #region Fields\r
46 \r
47 #if NET_2_0\r
48                 CodeGenerationOptions options;\r
49 #else\r
50                 XmlMapCodeGenerator codeGenerator;\r
51 #endif\r
52 \r
53                 #endregion\r
54 \r
55                 #region Constructors\r
56 \r
57                 public XmlCodeExporter (CodeNamespace codeNamespace): this (codeNamespace, null)\r
58                 {\r
59                 }\r
60 \r
61                 public XmlCodeExporter (CodeNamespace codeNamespace, CodeCompileUnit codeCompileUnit)\r
62                 {\r
63 #if NET_2_0\r
64                         codeGenerator = new XmlMapCodeGenerator (codeNamespace, codeCompileUnit, CodeGenerationOptions.GenerateProperties);\r
65 #else\r
66                         codeGenerator = new XmlMapCodeGenerator (codeNamespace, codeCompileUnit, CodeGenerationOptions.None);\r
67 #endif\r
68                 }\r
69 \r
70 #if NET_2_0\r
71                 public XmlCodeExporter (CodeNamespace codeNamespace, \r
72                                                                 CodeCompileUnit codeCompileUnit, \r
73                                                                 CodeGenerationOptions options)\r
74                 : this (codeNamespace, codeCompileUnit, null, options, null)\r
75                 {\r
76                 }\r
77                 \r
78                 public XmlCodeExporter (CodeNamespace codeNamespace, \r
79                                                                 CodeCompileUnit codeCompileUnit, \r
80                                                                 CodeGenerationOptions options, \r
81                                                                 Hashtable mappings)\r
82                 : this (codeNamespace, codeCompileUnit, null, options, mappings)\r
83                 {\r
84                         \r
85                 }\r
86                 \r
87                 [MonoTODO ("mappings?")]\r
88                 public XmlCodeExporter (CodeNamespace codeNamespace, \r
89                                                                 CodeCompileUnit codeCompileUnit, \r
90                                                                 CodeDomProvider codeProvider, \r
91                                                                 CodeGenerationOptions options, \r
92                                                                 Hashtable mappings)\r
93                 {\r
94                         codeGenerator = new XmlMapCodeGenerator (codeNamespace, codeCompileUnit, codeProvider, options, mappings);\r
95                 }\r
96 #endif\r
97 \r
98                 #endregion // Constructors\r
99 \r
100                 #region Properties\r
101 \r
102 #if !NET_2_0\r
103                 public CodeAttributeDeclarationCollection IncludeMetadata {\r
104                         get { return codeGenerator.IncludeMetadata; }\r
105                 }\r
106 #endif\r
107 \r
108                 #endregion Properties\r
109 \r
110                 #region Methods\r
111 \r
112                 public void AddMappingMetadata (CodeAttributeDeclarationCollection metadata, XmlMemberMapping member, string ns)\r
113                 {\r
114                         AddMappingMetadata (metadata, member, ns, false);\r
115                 }\r
116 \r
117                 public void AddMappingMetadata (CodeAttributeDeclarationCollection metadata, XmlTypeMapping member, string ns)\r
118                 {\r
119                         if ( (member.TypeData.SchemaType == SchemaTypes.Primitive ||\r
120                               member.TypeData.SchemaType == SchemaTypes.Array) \r
121                                 && member.Namespace != XmlSchema.Namespace)\r
122                         {\r
123                                 CodeAttributeDeclaration ratt = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlRoot");\r
124                                 ratt.Arguments.Add (MapCodeGenerator.GetArg (member.ElementName));\r
125                                 ratt.Arguments.Add (MapCodeGenerator.GetArg ("Namespace", member.Namespace));\r
126                                 ratt.Arguments.Add (MapCodeGenerator.GetArg ("IsNullable", member.IsNullable));\r
127                                 metadata.Add (ratt);\r
128                         }\r
129                 }\r
130 \r
131                 public void AddMappingMetadata (CodeAttributeDeclarationCollection metadata, XmlMemberMapping member, string ns, bool forceUseMemberName)\r
132                 {\r
133                         CodeAttributeDeclaration att;\r
134                         TypeData memType = member.TypeMapMember.TypeData;\r
135                         \r
136                         if (member.Any)\r
137                         {\r
138                                 XmlTypeMapElementInfoList list = (XmlTypeMapElementInfoList)((XmlTypeMapMemberElement)member.TypeMapMember).ElementInfo;\r
139                                 foreach (XmlTypeMapElementInfo info in list)\r
140                                 {\r
141                                         if (info.IsTextElement)\r
142                                                 metadata.Add (new CodeAttributeDeclaration ("System.Xml.Serialization.XmlText"));\r
143                                         else {\r
144                                                 att = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlAnyElement");\r
145                                                 if (!info.IsUnnamedAnyElement) {\r
146                                                         att.Arguments.Add (MapCodeGenerator.GetArg ("Name", info.ElementName));\r
147                                                         if (info.Namespace != ns) att.Arguments.Add (MapCodeGenerator.GetArg ("Namespace", member.Namespace));\r
148                                                 }\r
149                                                 metadata.Add (att);\r
150                                         }\r
151                                 }\r
152                         }\r
153                         else if (member.TypeMapMember is XmlTypeMapMemberList)\r
154                         {\r
155                                 // Array parameter\r
156                                 XmlTypeMapMemberList list = member.TypeMapMember as XmlTypeMapMemberList;\r
157                                 ListMap listMap = (ListMap) list.ListTypeMapping.ObjectMap;\r
158                                 \r
159                                 codeGenerator.AddArrayAttributes (metadata, list, ns, forceUseMemberName);\r
160                                 codeGenerator.AddArrayItemAttributes (metadata, listMap, memType.ListItemTypeData, list.Namespace, 0);\r
161                         }\r
162                         else if (member.TypeMapMember is XmlTypeMapMemberElement) {\r
163                                 codeGenerator.AddElementMemberAttributes ((XmlTypeMapMemberElement) member.TypeMapMember, ns, metadata, forceUseMemberName);\r
164                         }\r
165                         else if (member.TypeMapMember is XmlTypeMapMemberAttribute) {\r
166                                 codeGenerator.AddAttributeMemberAttributes ((XmlTypeMapMemberAttribute) member.TypeMapMember, ns, metadata, forceUseMemberName);\r
167                         }\r
168                         else\r
169                                 throw new NotSupportedException ("Schema type not supported");\r
170                 }\r
171 \r
172                 public void ExportMembersMapping (XmlMembersMapping xmlMembersMapping)\r
173                 {\r
174                         codeGenerator.ExportMembersMapping (xmlMembersMapping);\r
175                 }\r
176 \r
177                 public void ExportTypeMapping (XmlTypeMapping xmlTypeMapping)\r
178                 {\r
179                         codeGenerator.ExportTypeMapping (xmlTypeMapping, true);\r
180                 }\r
181 \r
182                 #endregion // Methods\r
183         }\r
184         \r
185         class XmlMapCodeGenerator : MapCodeGenerator\r
186         {\r
187                 public XmlMapCodeGenerator (CodeNamespace codeNamespace, CodeCompileUnit codeCompileUnit, CodeGenerationOptions options)\r
188                 : base (codeNamespace, codeCompileUnit, options)\r
189                 {\r
190                 }\r
191 \r
192                 public XmlMapCodeGenerator (CodeNamespace codeNamespace, CodeCompileUnit codeCompileUnit, CodeDomProvider codeProvider, CodeGenerationOptions options, Hashtable mappings)\r
193                 : base (codeNamespace, codeCompileUnit, codeProvider, options, mappings)\r
194                 {\r
195                 }\r
196                 \r
197                 protected override void GenerateClass (XmlTypeMapping map, CodeTypeDeclaration codeClass, bool isTopLevel)\r
198                 {\r
199                         CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlTypeAttribute");\r
200                         if (map.XmlType != map.TypeData.TypeName) att.Arguments.Add (GetArg (map.XmlType));\r
201                         if (map.XmlTypeNamespace != "") att.Arguments.Add (GetArg ("Namespace", map.XmlTypeNamespace));\r
202                         if (!map.IncludeInSchema) att.Arguments.Add (GetArg ("IncludeInSchema", false));\r
203                         AddCustomAttribute (codeClass, att, false);\r
204 \r
205                         CodeAttributeDeclaration ratt = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlRootAttribute");\r
206                         if (map.ElementName != map.XmlType) ratt.Arguments.Add (GetArg (map.ElementName));\r
207                         if (isTopLevel) {\r
208                                 ratt.Arguments.Add (GetArg ("Namespace", map.Namespace));\r
209                                 ratt.Arguments.Add (GetArg ("IsNullable", map.IsNullable));\r
210                         } else {\r
211                                 if (map.Namespace != "") \r
212                                         ratt.Arguments.Add (GetArg ("Namespace", map.Namespace));\r
213                         }\r
214                         AddCustomAttribute (codeClass, ratt, isTopLevel);\r
215                 }\r
216                 \r
217                 protected override void GenerateClassInclude (CodeAttributeDeclarationCollection attributes, XmlTypeMapping map)\r
218                 {\r
219                         CodeAttributeDeclaration iatt = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlIncludeAttribute");\r
220                         iatt.Arguments.Add (new CodeAttributeArgument (new CodeTypeOfExpression(map.TypeData.FullTypeName)));\r
221                         attributes.Add (iatt);\r
222                 }\r
223                 \r
224                 protected override void GenerateAnyAttribute (CodeTypeMember codeField)\r
225                 {\r
226                         AddCustomAttribute (codeField, "System.Xml.Serialization.XmlAnyAttribute");\r
227                 }\r
228                 \r
229                 protected override void GenerateAttributeMember (CodeAttributeDeclarationCollection attributes, XmlTypeMapMemberAttribute attinfo, string defaultNamespace, bool forceUseMemberName)\r
230                 {\r
231                         CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlAttributeAttribute");\r
232                         if (forceUseMemberName || attinfo.Name != attinfo.AttributeName) att.Arguments.Add (GetArg (attinfo.AttributeName));\r
233                         if (attinfo.Namespace != defaultNamespace) att.Arguments.Add (GetArg ("Namespace", attinfo.Namespace));\r
234                         if (attinfo.Form == XmlSchemaForm.Qualified) att.Arguments.Add (GetEnumArg ("Form","System.Xml.Schema.XmlSchemaForm",attinfo.Form.ToString()));\r
235                         if (!TypeTranslator.IsDefaultPrimitiveTpeData(attinfo.TypeData)) att.Arguments.Add (GetArg ("DataType",attinfo.TypeData.XmlType));\r
236                         attributes.Add (att);\r
237                         \r
238                         if (attinfo.Ignore)\r
239                                 attributes.Add (new CodeAttributeDeclaration ("System.Xml.Serialization.XmlIgnoreAttribute"));\r
240                 }\r
241                 \r
242                 protected override void GenerateElementInfoMember (CodeAttributeDeclarationCollection attributes, XmlTypeMapMemberElement member, XmlTypeMapElementInfo einfo, TypeData defaultType, string defaultNamespace, bool addAlwaysAttr, bool forceUseMemberName)\r
243                 {\r
244                         CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlElementAttribute");\r
245                         if (forceUseMemberName || einfo.ElementName != member.Name) att.Arguments.Add (GetArg (einfo.ElementName));\r
246                         if (einfo.TypeData.FullTypeName != defaultType.FullTypeName) att.Arguments.Add (GetTypeArg ("Type", einfo.TypeData.FullTypeName));\r
247                         if (einfo.Namespace != defaultNamespace) att.Arguments.Add (GetArg ("Namespace", einfo.Namespace));\r
248                         if (einfo.Form == XmlSchemaForm.Unqualified) att.Arguments.Add (GetEnumArg ("Form", "System.Xml.Schema.XmlSchemaForm", einfo.Form.ToString()));\r
249                         if (einfo.IsNullable) att.Arguments.Add (GetArg ("IsNullable", true));\r
250                         if (!TypeTranslator.IsDefaultPrimitiveTpeData(einfo.TypeData)) att.Arguments.Add (GetArg ("DataType",einfo.TypeData.XmlType));\r
251                         if (addAlwaysAttr || att.Arguments.Count > 0) attributes.Add (att);\r
252                 }\r
253                 \r
254                 protected override void GenerateElementMember (CodeAttributeDeclarationCollection attributes, XmlTypeMapMemberElement member)\r
255                 {\r
256                         if (member.ChoiceMember != null) {\r
257                                 CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlChoiceIdentifier");\r
258                                 att.Arguments.Add (GetArg(member.ChoiceMember));\r
259                                 attributes.Add (att);\r
260                         }\r
261 \r
262                         if (member.Ignore)\r
263                                 attributes.Add (new CodeAttributeDeclaration ("System.Xml.Serialization.XmlIgnoreAttribute"));\r
264                 }\r
265                 \r
266                 protected override void GenerateArrayElement (CodeAttributeDeclarationCollection attributes, XmlTypeMapMemberElement member, string defaultNamespace, bool forceUseMemberName)\r
267                 {\r
268                         XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo[0];\r
269                         CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlArray");\r
270                         if (forceUseMemberName || (einfo.ElementName != member.Name)) att.Arguments.Add (GetArg ("ElementName", einfo.ElementName));\r
271                         if (einfo.Namespace != defaultNamespace) att.Arguments.Add (GetArg ("Namespace", einfo.Namespace));\r
272                         if (einfo.Form == XmlSchemaForm.Unqualified) att.Arguments.Add (MapCodeGenerator.GetEnumArg ("Form", "System.Xml.Schema.XmlSchemaForm", einfo.Form.ToString()));\r
273                         if (einfo.IsNullable) att.Arguments.Add (GetArg ("IsNullable", true));\r
274                         if (att.Arguments.Count > 0) attributes.Add (att);\r
275                 }\r
276                 \r
277                 protected override void GenerateArrayItemAttributes (CodeAttributeDeclarationCollection attributes, ListMap listMap, TypeData type, XmlTypeMapElementInfo ainfo, string defaultName, string defaultNamespace, int nestingLevel)\r
278                 {\r
279                         bool needsType = (listMap.ItemInfo.Count > 1) ||\r
280                                                          (ainfo.TypeData.FullTypeName != type.FullTypeName && !listMap.IsMultiArray);\r
281 \r
282                         CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlArrayItem");\r
283                         if (ainfo.ElementName != defaultName) att.Arguments.Add (GetArg ("ElementName", ainfo.ElementName));\r
284                         if (ainfo.Namespace != defaultNamespace && ainfo.Namespace != XmlSchema.Namespace) att.Arguments.Add (GetArg ("Namespace", ainfo.Namespace));\r
285                         if (needsType) att.Arguments.Add (GetTypeArg ("Type", ainfo.TypeData.FullTypeName));\r
286                         if (!ainfo.IsNullable) att.Arguments.Add (GetArg ("IsNullable", false));\r
287                         if (ainfo.Form == XmlSchemaForm.Unqualified) att.Arguments.Add (MapCodeGenerator.GetEnumArg ("Form", "System.Xml.Schema.XmlSchemaForm", ainfo.Form.ToString()));\r
288                         if (att.Arguments.Count > 0 && nestingLevel > 0) att.Arguments.Add (GetArg ("NestingLevel", nestingLevel));\r
289                         \r
290                         if (att.Arguments.Count > 0) attributes.Add (att);\r
291                 }\r
292 \r
293                 protected override void GenerateTextElementAttribute (CodeAttributeDeclarationCollection attributes, XmlTypeMapElementInfo einfo, TypeData defaultType)\r
294                 {\r
295                         CodeAttributeDeclaration uatt = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlTextAttribute");\r
296                         if (einfo.TypeData.FullTypeName != defaultType.FullTypeName) uatt.Arguments.Add (GetTypeArg ("Type", einfo.TypeData.FullTypeName));\r
297                         attributes.Add (uatt);\r
298                 }\r
299                 \r
300                 protected override void GenerateUnnamedAnyElementAttribute (CodeAttributeDeclarationCollection attributes, XmlTypeMapElementInfo einfo, string defaultNamespace)\r
301                 {\r
302                         CodeAttributeDeclaration uatt = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlAnyElement");\r
303                         if (!einfo.IsUnnamedAnyElement) uatt.Arguments.Add (GetArg ("Name", einfo.ElementName));\r
304                         if (einfo.Namespace != defaultNamespace) uatt.Arguments.Add (GetArg ("Namespace", einfo.Namespace));\r
305                         attributes.Add (uatt);\r
306                 }\r
307 \r
308                 protected override void GenerateEnum (XmlTypeMapping map, CodeTypeDeclaration codeEnum, bool isTopLevel)\r
309                 {\r
310                         GenerateClass (map, codeEnum, isTopLevel);\r
311                 }\r
312                 \r
313                 protected override void GenerateEnumItem (CodeMemberField codeField, EnumMap.EnumMapMember emem)\r
314                 {\r
315                         if (emem.EnumName != emem.XmlName)\r
316                         {\r
317                                 CodeAttributeDeclaration xatt = new CodeAttributeDeclaration ("System.Xml.Serialization.XmlEnumAttribute");\r
318                                 xatt.Arguments.Add (GetArg (emem.XmlName));\r
319 \r
320                                 AddCustomAttribute (codeField, xatt, true);\r
321                         }\r
322                 }\r
323                 \r
324                 protected override void GenerateSpecifierMember (CodeTypeMember codeField)\r
325                 {\r
326                         AddCustomAttribute (codeField, "System.Xml.Serialization.XmlIgnore");\r
327                 }\r
328 \r
329         }\r
330 }\r