merge -r 61110:61111
[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 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                         return XmlConvert.ToString (value, "yyyy-MM-ddTHH:mm:ss.fffffffzzz");
70                 }
71
72                 internal static string FromTime (DateTime value)
73                 {
74                         return XmlConvert.ToString (value, "HH:mm:ss.fffffffzzz");
75                 }
76
77                 internal static string FromEnum (long value, string[] values, long[] ids)
78                 {
79                         return FromEnum (value, values, ids, (string) null);
80                 }
81
82                 internal static string FromEnum (long value, string[] values, long[] ids, string typeName)
83                 {
84                         StringBuilder sb = new StringBuilder();
85                         int length = ids.Length;
86                         long valueToProcess = value;
87                         int zeroValue = -1;
88
89                         for (int i = 0; i < length; i ++) {
90                                 if (ids[i] == 0) {
91                                         zeroValue = i;
92                                 } else {
93                                         if (valueToProcess == 0) {
94                                                 break;
95                                         }
96
97                                         if ((ids[i] & value) == ids[i]) {
98                                                 if (sb.Length != 0)
99                                                         sb.Append (' ');
100                                                 sb.Append (values[i]);
101                                                 valueToProcess &= ~ids[i];
102                                         }
103                                 }
104                         }
105
106                         if (valueToProcess != 0) {
107 #if NET_2_0
108                                 if (typeName != null)
109                                         throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
110                                                 "'{0}' is not a valid value for {1}.", value, typeName));
111                                 else
112                                         throw new InvalidOperationException (string.Format (CultureInfo.CurrentCulture,
113                                                 "'{0}' is not a valid value.", value));
114 #else
115                                 return value.ToString ();
116 #endif
117                         }
118                         if (sb.Length == 0 && zeroValue != -1) {
119                                 sb.Append (values[zeroValue]);
120                         }
121                         return sb.ToString ();
122                 }
123
124                 internal static string FromXmlName (string name)
125                 {
126                         return XmlConvert.EncodeName (name);
127                 }
128
129                 internal static string FromXmlNCName (string ncName)
130                 {
131                         return XmlConvert.EncodeLocalName (ncName);
132                 }
133
134                 internal static string FromXmlNmToken (string nmToken)
135                 {
136                         return XmlConvert.EncodeNmToken (nmToken);
137                 }
138
139                 internal static string FromXmlNmTokens (string nmTokens)
140                 {
141                         string [] tokens = nmTokens.Split (' ');
142                         for (int i=0; i<tokens.Length; i++)
143                                 tokens [i] = FromXmlNmToken (tokens [i]);
144                         return String.Join (" ", tokens);
145                 }
146
147                 internal static byte[] ToByteArrayBase64 (string value)
148                 {
149                         return Convert.FromBase64String(value);
150                 }
151
152                 internal static char ToChar (string value)
153                 {
154                         return (char) XmlConvert.ToUInt16 (value);
155                 }
156
157                 internal static DateTime ToDate (string value)
158                 {
159                         return ToDateTime (value);
160                 }
161
162                 internal static DateTime ToDateTime (string value)
163                 {
164                         return XmlConvert.ToDateTime (value);
165                 }
166
167                 internal static DateTime ToTime (string value)
168                 {
169                         return ToDateTime (value);
170                 }
171
172                 internal static long ToEnum (string value, Hashtable values, string typeName, bool validate)
173                 {
174                         // Assuming that h contains map from value to Enumerated Name
175 /*
176                         You can try : 
177                                 return ToEnum ("One Two", h, "SomeType");
178                         where:
179                                 (1) no keys and values for h.
180                                 (2) string keys and long values.
181                         
182                         according to MSDN docs (for .NET 2.0) the hashtable "consists of the
183                         identifiers as keys and the constants as integral numbers"
184 */
185                         long enumValue = 0;
186                         string[] names = value.Split (' ');
187
188                         foreach (string name in names) {
189                                 object nameValue = values[name];
190                                 if (nameValue != null) {
191                                         enumValue |= (long) nameValue;
192                                 } else if (validate && name.Length != 0) {
193                                         throw new InvalidOperationException (String.Format ("'{0}' is not a valid member of type {1}.", name, typeName));
194                                 }
195                         }
196
197                         return enumValue;
198                 }
199
200                 internal static string ToXmlName (string value)
201                 {
202                         return XmlConvert.DecodeName (value);
203                 }
204
205                 internal static string ToXmlNCName (string value)
206                 {
207                         return ToXmlName (value);
208                 }
209
210                 internal static string ToXmlNmToken (string value)
211                 {
212                         return ToXmlName (value);
213                 }
214
215                 internal static string ToXmlNmTokens (string value)
216                 {
217                         return ToXmlName (value);
218                 }
219
220                 internal static string ToXmlString (TypeData type, object value)
221                 {
222                         if (value == null) return null;
223                         switch (type.XmlType)
224                         {
225                                 case "boolean": return XmlConvert.ToString ((bool)value);
226                                 case "unsignedByte": return XmlConvert.ToString ((byte)value);
227                                 case "char": return XmlConvert.ToString ((int)(char)value);
228                                 case "dateTime": return XmlConvert.ToString ((DateTime)value);
229                                 case "date": return ((DateTime)value).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
230                                 case "time": return ((DateTime)value).ToString("HH:mm:ss.fffffffzzz", CultureInfo.InvariantCulture);
231                                 case "decimal": return XmlConvert.ToString ((decimal)value);
232                                 case "double": return XmlConvert.ToString ((double)value);
233                                 case "short": return XmlConvert.ToString ((Int16)value);
234                                 case "int": return XmlConvert.ToString ((Int32)value);
235                                 case "long": return XmlConvert.ToString ((Int64)value);
236                                 case "byte": return XmlConvert.ToString ((sbyte)value);
237                                 case "float": return XmlConvert.ToString ((Single)value);
238                                 case "unsignedShort": return XmlConvert.ToString ((UInt16)value);
239                                 case "unsignedInt": return XmlConvert.ToString ((UInt32)value);
240                                 case "unsignedLong": return XmlConvert.ToString ((UInt64)value);
241                                 case "guid": return XmlConvert.ToString ((Guid)value);
242                                 case "base64":
243                                 case "base64Binary": return Convert.ToBase64String ((byte[])value);
244                                 case "duration": return XmlConvert.ToString ((TimeSpan) value);
245                         default: return value is IFormattable ? ((IFormattable) value).ToString (null, CultureInfo.InvariantCulture) : value.ToString ();
246                         }
247                 }
248
249                 internal static object FromXmlString (TypeData type, string value)
250                 {
251                         if (value == null) return null;
252
253                         switch (type.XmlType)
254                         {
255                                 case "boolean": return XmlConvert.ToBoolean (value);
256                                 case "unsignedByte": return XmlConvert.ToByte (value);
257                                 case "char": return (char)XmlConvert.ToInt32 (value);
258                                 case "dateTime": return XmlConvert.ToDateTime (value);
259                                 case "date": return DateTime.ParseExact (value, "yyyy-MM-dd", null);
260                                 case "time": return DateTime.ParseExact (value, "HH:mm:ss.fffffffzzz", null);
261                                 case "decimal": return XmlConvert.ToDecimal (value);
262                                 case "double": return XmlConvert.ToDouble (value);
263                                 case "short": return XmlConvert.ToInt16 (value);
264                                 case "int": return XmlConvert.ToInt32 (value);
265                                 case "long": return XmlConvert.ToInt64 (value);
266                                 case "byte": return XmlConvert.ToSByte (value);
267                                 case "float": return XmlConvert.ToSingle (value);
268                                 case "unsignedShort": return XmlConvert.ToUInt16 (value);
269                                 case "unsignedInt": return XmlConvert.ToUInt32 (value);
270                                 case "unsignedLong": return XmlConvert.ToUInt64 (value);
271                                 case "guid": return XmlConvert.ToGuid (value);
272                                 case "base64":
273                                 case "base64Binary": return Convert.FromBase64String (value);
274                                 case "duration": return XmlConvert.ToTimeSpan (value);
275                                 default: 
276                                         if (type.Type != null)
277                                                 return Convert.ChangeType (value, type.Type);
278                                         else
279                                                 return value;
280                         }
281                 }
282
283                 internal static string GenerateToXmlString (TypeData type, string value)
284                 {
285                         switch (type.XmlType)
286                         {
287                                 case "boolean": return "(" + value + "?\"true\":\"false\")";
288                                 case "unsignedByte": return value + ".ToString(CultureInfo.InvariantCulture)";
289                                 case "char": return "((int)(" + value + ")).ToString(CultureInfo.InvariantCulture)";
290                                 case "dateTime": return value + ".ToString(\"yyyy-MM-ddTHH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
291                                 case "date": return value + ".ToString(\"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
292                                 case "time": return value + ".ToString(\"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
293                                 case "decimal": return "XmlConvert.ToString (" + value + ")";
294                                 case "double": return "XmlConvert.ToString (" + value + ")";
295                                 case "short": return value + ".ToString(CultureInfo.InvariantCulture)";
296                                 case "int": return value + ".ToString(CultureInfo.InvariantCulture)";
297                                 case "long": return value + ".ToString(CultureInfo.InvariantCulture)";
298                                 case "byte": return value + ".ToString(CultureInfo.InvariantCulture)";
299                                 case "float": return "XmlConvert.ToString (" + value + ")";
300                                 case "unsignedShort": return value + ".ToString(CultureInfo.InvariantCulture)";
301                                 case "unsignedInt": return value + ".ToString(CultureInfo.InvariantCulture)";
302                                 case "unsignedLong": return value + ".ToString(CultureInfo.InvariantCulture)";
303                                 case "guid": return "XmlConvert.ToString (" + value + ")";
304                                 case "base64":
305                                 case "base64Binary": return "Convert.ToBase64String (" + value + ")";
306                                 case "duration": return "XmlConvert.ToString (" + value + ")";
307                                 case "NMTOKEN":
308                                 case "Name":
309                                 case "NCName":
310                                 case "language":
311                                 case "ENTITY":
312                                 case "ID":
313                                 case "IDREF":
314                                 case "NOTATION":
315                                 case "token":
316                                 case "normalizedString":
317                                 case "string": return value;
318                                 default: return "((" + value + " != null) ? (" + value + ").ToString() : null)";
319                         }
320                 }
321
322                 internal static string GenerateFromXmlString (TypeData type, string value)
323                 {
324                         switch (type.XmlType)
325                         {
326                                 case "boolean": return "XmlConvert.ToBoolean (" + value + ")";
327                                 case "unsignedByte": return "byte.Parse (" + value + ", CultureInfo.InvariantCulture)";
328                                 case "char": return "(char)Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
329                                 case "dateTime": return "XmlConvert.ToDateTime (" + value + ")";
330                                 case "date": return "DateTime.ParseExact (" + value + ", \"yyyy-MM-dd\", CultureInfo.InvariantCulture)";
331                                 case "time": return "DateTime.ParseExact (" + value + ", \"HH:mm:ss.fffffffzzz\", CultureInfo.InvariantCulture)";
332                                 case "decimal": return "Decimal.Parse (" + value + ", CultureInfo.InvariantCulture)";
333                                 case "double": return "XmlConvert.ToDouble (" + value + ")";
334                                 case "short": return "Int16.Parse (" + value + ", CultureInfo.InvariantCulture)";
335                                 case "int": return "Int32.Parse (" + value + ", CultureInfo.InvariantCulture)";
336                                 case "long": return "Int64.Parse (" + value + ", CultureInfo.InvariantCulture)";
337                                 case "byte": return "SByte.Parse (" + value + ", CultureInfo.InvariantCulture)";
338                                 case "float": return "XmlConvert.ToSingle (" + value + ")";
339                                 case "unsignedShort": return "UInt16.Parse (" + value + ", CultureInfo.InvariantCulture)";
340                                 case "unsignedInt": return "UInt32.Parse (" + value + ", CultureInfo.InvariantCulture)";
341                                 case "unsignedLong": return "UInt64.Parse (" + value + ", CultureInfo.InvariantCulture)";
342                                 case "guid": return "XmlConvert.ToGuid (" + value + ")";
343                                 case "base64:":
344                                 case "base64Binary": return "Convert.FromBase64String (" + value + ")";
345                                 case "duration": return "XmlConvert.ToTimeSpan (" + value + ")";
346                                 default: return value;
347                         }
348                 }
349
350                 #endregion // Methods
351         }
352 }