System.Drawing: added email to icon and test file headers
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlCustomFormatter.cs
1 //
2 // System.Xml.Serialization.XmlCustomFormatter.cs
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;
33 using System.Collections;
34 using System.Text;
35 using System.Xml;
36 using System.Globalization;
37
38 namespace System.Xml.Serialization {
39         internal class XmlCustomFormatter {
40
41                 #region Methods
42
43                 internal static string FromByteArrayBase64 (byte[] value)
44                 {
45                         return value == null ? String.Empty : Convert.ToBase64String(value);
46                 }
47
48                 internal static string FromByteArrayHex (byte[] value)
49                 {
50                         if (value == null) return null;
51                         StringBuilder output = new StringBuilder ();
52                         foreach (byte val in value)
53                                 output.Append (val.ToString ("X2", CultureInfo.InvariantCulture));
54                         return output.ToString ();
55                 }
56
57                 internal static string FromChar (char value)
58                 {
59                         return ((int) value).ToString (CultureInfo.InvariantCulture);
60                 }
61
62                 internal static string FromDate (DateTime value)
63                 {
64                         return XmlConvert.ToString (value, "yyyy-MM-dd");
65                 }
66
67                 internal static string FromDateTime (DateTime value)
68                 {
69 #if NET_2_0
70                         return XmlConvert.ToString (value, XmlDateTimeSerializationMode.RoundtripKind);
71 #else
72                         return XmlConvert.ToString (value, "yyyy-MM-ddTHH:mm:ss.fffffffzzz");
73 #endif
74                 }
75
76                 internal static string FromTime (DateTime value)
77                 {
78                         return XmlConvert.ToString (value, "HH:mm:ss.fffffffzzz");
79                 }
80
81                 internal static string FromEnum (long value, string[] values, long[] ids)
82                 {
83                         return FromEnum (value, values, ids, (string) null);
84                 }
85
86                 internal static string FromEnum (long value, string[] values, long[] ids, string typeName)
87                 {
88                         StringBuilder sb = new StringBuilder();
89                         int length = ids.Length;
90                         long valueToProcess = value;
91                         int zeroValue = -1;
92
93                         for (int i = 0; i < length; i ++) {
94                                 if (ids[i] == 0) {
95                                         zeroValue = i;
96                                 } else {
97                                         if (valueToProcess == 0) {
98                                                 break;
99                                         }
100
101                                         if ((ids[i] & value) == ids[i]) {
102                                                 if (sb.Length != 0)
103                                                         sb.Append (' ');
104                                                 sb.Append (values[i]);
105                                                 valueToProcess &= ~ids[i];
106                                         }
107                                 }
108                         }
109
110                         if (valueToProcess != 0) {
111 #if NET_2_0
112                                 if (typeName != null)
113                                         throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
114                                                 "'{0}' is not a valid value for {1}.", value, typeName));
115                                 else
116                                         throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
117                                                 "'{0}' is not a valid value.", value));
118 #else
119                                 return value.ToString ();
120 #endif
121                         }
122                         if (sb.Length == 0 && zeroValue != -1) {
123                                 sb.Append (values[zeroValue]);
124                         }
125                         return sb.ToString ();
126                 }
127
128                 internal static string FromXmlName (string name)
129                 {
130                         return XmlConvert.EncodeName (name);
131                 }
132
133                 internal static string FromXmlNCName (string ncName)
134                 {
135                         return XmlConvert.EncodeLocalName (ncName);
136                 }
137
138                 internal static string FromXmlNmToken (string nmToken)
139                 {
140                         return XmlConvert.EncodeNmToken (nmToken);
141                 }
142
143                 internal static string FromXmlNmTokens (string nmTokens)
144                 {
145                         string [] tokens = nmTokens.Split (' ');
146                         for (int i=0; i<tokens.Length; i++)
147                                 tokens [i] = FromXmlNmToken (tokens [i]);
148                         return String.Join (" ", tokens);
149                 }
150
151                 internal static byte[] ToByteArrayBase64 (string value)
152                 {
153                         return Convert.FromBase64String(value);
154                 }
155
156                 internal static char ToChar (string value)
157                 {
158                         return (char) XmlConvert.ToUInt16 (value);
159                 }
160
161                 internal static DateTime ToDate (string value)
162                 {
163                         return ToDateTime (value);
164                 }
165
166                 internal static DateTime ToDateTime (string value)
167                 {
168 #if NET_2_0
169                         return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
170 #else
171                         return XmlConvert.ToDateTime (value);
172 #endif
173                 }
174
175                 internal static DateTime ToTime (string value)
176                 {
177                         return ToDateTime (value);
178                 }
179
180                 internal static long ToEnum (string value, Hashtable values, string typeName, bool validate)
181                 {
182                         // Assuming that h contains map from value to Enumerated Name
183 /*
184                         You can try : 
185                                 return ToEnum ("One Two", h, "SomeType");
186                         where:
187                                 (1) no keys and values for h.
188                                 (2) string keys and long values.
189                         
190                         according to MSDN docs (for .NET 2.0) the hashtable "consists of the
191                         identifiers as keys and the constants as integral numbers"
192 */
193                         long enumValue = 0;
194                         string[] names = value.Split (' ');
195
196                         foreach (string name in names) {
197                                 object nameValue = values[name];
198                                 if (nameValue != null) {
199                                         enumValue |= (long) nameValue;
200                                 } else if (validate && name.Length != 0) {
201                                         throw new InvalidOperationException (String.Format ("'{0}' is not a valid member of type {1}.", name, typeName));
202                                 }
203                         }
204
205                         return enumValue;
206                 }
207
208                 internal static string ToXmlName (string value)
209                 {
210                         return XmlConvert.DecodeName (value);
211                 }
212
213                 internal static string ToXmlNCName (string value)
214                 {
215                         return ToXmlName (value);
216                 }
217
218                 internal static string ToXmlNmToken (string value)
219                 {
220                         return ToXmlName (value);
221                 }
222
223                 internal static string ToXmlNmTokens (string value)
224                 {
225                         return ToXmlName (value);
226                 }
227
228                 internal static string ToXmlString (TypeData type, object value)
229                 {
230                         if (value == null) return null;
231                         switch (type.XmlType)
232                         {
233                                 case "boolean": return XmlConvert.ToString ((bool)value);
234                                 case "unsignedByte": return XmlConvert.ToString ((byte)value);
235                                 case "char": return XmlConvert.ToString ((int)(char)value);
236 #if NET_2_0
237                                 case "dateTime": return XmlConvert.ToString ((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
238                                 case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
239                                 case "time": return ((DateTime)value).ToString("HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture);
240 #else
241                                 case "dateTime": return XmlConvert.ToString ((DateTime)value);
242                                 case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
243                                 case "time": return ((DateTime)value).ToString("HH:mm:ss.fffffffzzz", CultureInfo.InvariantCulture);
244 #endif
245                                 case "decimal": return XmlConvert.ToString ((decimal)value);
246                                 case "double": return XmlConvert.ToString ((double)value);
247                                 case "short": return XmlConvert.ToString ((Int16)value);
248                                 case "int": return XmlConvert.ToString ((Int32)value);
249                                 case "long": return XmlConvert.ToString ((Int64)value);
250                                 case "byte": return XmlConvert.ToString ((sbyte)value);
251                                 case "float": return XmlConvert.ToString ((Single)value);
252                                 case "unsignedShort": return XmlConvert.ToString ((UInt16)value);
253                                 case "unsignedInt": return XmlConvert.ToString ((UInt32)value);
254                                 case "unsignedLong": return XmlConvert.ToString ((UInt64)value);
255                                 case "guid": return XmlConvert.ToString ((Guid)value);
256                                 case "base64":
257                                 case "base64Binary": return value == null ? String.Empty : Convert.ToBase64String ((byte[])value);
258                                 case "hexBinary": return value == null ? String.Empty : XmlConvert.ToBinHexString ((byte[]) value);
259                                 case "duration": return (string) value;
260                         default: return value is IFormattable ? ((IFormattable) value).ToString (null, CultureInfo.InvariantCulture) : value.ToString ();
261                         }
262                 }
263
264                 internal static object FromXmlString (TypeData type, string value)
265                 {
266                         if (value == null) return null;
267
268                         switch (type.XmlType)
269                         {
270                                 case "boolean": return XmlConvert.ToBoolean (value);
271                                 case "unsignedByte": return XmlConvert.ToByte (value);
272                                 case "char": return (char)XmlConvert.ToInt32 (value);
273 #if NET_2_0
274                                 case "dateTime": return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.RoundtripKind);
275                                 case "date": return DateTime.ParseExact (value, "yyyy-MM-dd", null);
276                                 case "time": return DateTime.ParseExact (value, "HH:mm:ss.FFFFFFF", null);
277 #else
278                                 case "dateTime": return XmlConvert.ToDateTime (value);
279                                 case "date": return DateTime.ParseExact (value, "yyyy-MM-dd", null);
280                                 case "time": return DateTime.ParseExact (value, "HH:mm:ss.fffffffzzz", null);
281 #endif
282                                 case "decimal": return XmlConvert.ToDecimal (value);
283                                 case "double": return XmlConvert.ToDouble (value);
284                                 case "short": return XmlConvert.ToInt16 (value);
285                                 case "int": return XmlConvert.ToInt32 (value);
286                                 case "long": return XmlConvert.ToInt64 (value);
287                                 case "byte": return XmlConvert.ToSByte (value);
288                                 case "float": return XmlConvert.ToSingle (value);
289                                 case "unsignedShort": return XmlConvert.ToUInt16 (value);
290                                 case "unsignedInt": return XmlConvert.ToUInt32 (value);
291                                 case "unsignedLong": return XmlConvert.ToUInt64 (value);
292                                 case "guid": return XmlConvert.ToGuid (value);
293                                 case "base64":
294                                 case "base64Binary": return Convert.FromBase64String (value);
295                                 case "hexBinary": return XmlConvert.FromBinHexString (value);
296                                 case "duration": return value;
297                                 default: 
298                                         if (type.Type != null)
299                                                 return Convert.ChangeType (value, type.Type, null);
300                                         else
301                                                 return value;
302                         }
303                 }
304
305                 internal static string GenerateToXmlString (TypeData type, string value)
306                 {
307                         if (type.NullableOverride)
308                                 return "(" + value + " != null ? " + GenerateToXmlStringCore (type, value) + " : null)";
309                         else
310                                 return GenerateToXmlStringCore (type, value);
311                 }
312
313                 static string GenerateToXmlStringCore (TypeData type, string value)
314                 {
315                         if (type.NullableOverride)
316                                 value = value + ".Value";
317                         switch (type.XmlType)
318                         {
319                                 case "boolean": return "(" + value + "?\"true\":\"false\")";
320                                 case "unsignedByte": return value + ".ToString(CultureInfo.InvariantCulture)";
321                                 case "char": return "((int)(" + value + ")).ToString(CultureInfo.InvariantCulture)";
322 #if NET_2_0
323                                 case "dateTime": return "XmlConvert.ToString (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
324                                 case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
325                                 case "time": return value + ".ToString(\"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
326 #else
327                                 case "dateTime": return value + ".ToString(\"yyyy-MM-ddTHH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
328                                 case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
329                                 case "time": return value + ".ToString(\"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
330 #endif
331                                 case "decimal": return "XmlConvert.ToString (" + value + ")";
332                                 case "double": return "XmlConvert.ToString (" + value + ")";
333                                 case "short": return value + ".ToString(CultureInfo.InvariantCulture)";
334                                 case "int": return value + ".ToString(CultureInfo.InvariantCulture)";
335                                 case "long": return value + ".ToString(CultureInfo.InvariantCulture)";
336                                 case "byte": return value + ".ToString(CultureInfo.InvariantCulture)";
337                                 case "float": return "XmlConvert.ToString (" + value + ")";
338                                 case "unsignedShort": return value + ".ToString(CultureInfo.InvariantCulture)";
339                                 case "unsignedInt": return value + ".ToString(CultureInfo.InvariantCulture)";
340                                 case "unsignedLong": return value + ".ToString(CultureInfo.InvariantCulture)";
341                                 case "guid": return "XmlConvert.ToString (" + value + ")";
342                                 case "base64":
343                                 case "base64Binary": return value + " == null ? String.Empty : Convert.ToBase64String (" + value + ")";
344                                 case "hexBinary": return value + " == null ? String.Empty : ToBinHexString (" + value + ")";
345                                 case "duration": return value;
346                                 case "NMTOKEN":
347                                 case "Name":
348                                 case "NCName":
349                                 case "language":
350                                 case "ENTITY":
351                                 case "ID":
352                                 case "IDREF":
353                                 case "NOTATION":
354                                 case "token":
355                                 case "normalizedString":
356                                 case "string": return value;
357                                 default: return "((" + value + " != null) ? (" + value + ").ToString() : null)";
358                         }
359                 }
360
361                 internal static string GenerateFromXmlString (TypeData type, string value)
362                 {
363                         if (type.NullableOverride)
364                                 return String.Concat ("(", value, " != null ? (", type.CSharpName, "?)", GenerateFromXmlStringCore (type, value), " : null)");
365                         else
366                                 return GenerateFromXmlStringCore (type, value);
367                 }
368
369                 static string GenerateFromXmlStringCore (TypeData type, string value)
370                 {
371                         switch (type.XmlType)
372                         {
373                                 case "boolean": return "XmlConvert.ToBoolean (" + value + ")";
374                                 case "unsignedByte": return "byte.Parse (" + value + ", CultureInfo.InvariantCulture)";
375                                 case "char": return "(char)Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
376 #if NET_2_0
377                                 case "dateTime": return "XmlConvert.ToDateTime (" + value + ", XmlDateTimeSerializationMode.RoundtripKind)";
378                                 case "date": return "DateTime.ParseExact (" + value + ", \"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
379                                 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.FFFFFFF\", CultureInfo.InvariantCulture)";
380 #else
381                                 case "dateTime": return "XmlConvert.ToDateTime (" + value + ")";
382                                 case "date": return "DateTime.ParseExact (" + value + ", \"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
383                                 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
384 #endif
385                                 case "decimal": return "Decimal.Parse (" + value + ", CultureInfo.InvariantCulture)";
386                                 case "double": return "XmlConvert.ToDouble (" + value + ")";
387                                 case "short": return "Int16.Parse (" + value + ", CultureInfo.InvariantCulture)";
388                                 case "int": return "Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
389                                 case "long": return "Int64.Parse (" + value + ", CultureInfo.InvariantCulture)";
390                                 case "byte": return "SByte.Parse (" + value + ", CultureInfo.InvariantCulture)";
391                                 case "float": return "XmlConvert.ToSingle (" + value + ")";
392                                 case "unsignedShort": return "UInt16.Parse (" + value + ", CultureInfo.InvariantCulture)";
393                                 case "unsignedInt": return "UInt32.Parse (" + value + ", CultureInfo.InvariantCulture)";
394                                 case "unsignedLong": return "UInt64.Parse (" + value + ", CultureInfo.InvariantCulture)";
395                                 case "guid": return "XmlConvert.ToGuid (" + value + ")";
396                                 case "base64:":
397                                 case "base64Binary": return "Convert.FromBase64String (" + value + ")";
398                                 case "hexBinary": return "FromBinHexString (" + value + ")";
399                                 case "duration": return value;
400                                 default: return value;
401                         }
402                 }
403
404                 #endregion // Methods
405         }
406 }