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