**** Merged from MCS ****
[mono-project.git] / mcs / class / System.Runtime.Serialization.Formatters.Soap / System.Runtime.Serialization.Formatters.Soap / SoapTypeMapper.cs
blob0df2dae2348566f733c61991ca5c1eb854d319c0
1 // created on 09/04/2003 at 18:58
2 //
3 // System.Runtime.Serialization.Formatters.Soap.SoapTypeMapper
4 //
5 // Authors:
6 // Jean-Marc Andre (jean-marc.andre@polymtl.ca)
7 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System;
31 using System.Reflection;
32 using System.Collections;
33 using System.Runtime.Remoting;
34 using System.Xml;
35 using System.Xml.Serialization;
36 using System.Runtime.Serialization.Formatters;
37 using System.Xml.Schema;
38 using System.Runtime.Remoting.Metadata.W3cXsd2001;
39 using System.Globalization;
41 namespace System.Runtime.Serialization.Formatters.Soap {
43 internal class Element
45 private string _prefix;
46 private string _localName;
47 private string _namespaceURI;
49 public Element(string prefix, string localName, string namespaceURI)
51 _prefix = prefix;
52 _localName = localName;
53 _namespaceURI = namespaceURI;
56 public Element(string localName, string namespaceURI): this(null, localName, namespaceURI)
60 public string Prefix
62 get
64 return _prefix;
68 public string LocalName
70 get
72 return _localName;
76 public string NamespaceURI
78 get
80 return _namespaceURI;
84 public override bool Equals(object obj)
86 Element element = obj as Element;
87 return (_localName == XmlConvert.DecodeName(element._localName) &&
88 _namespaceURI == XmlConvert.DecodeName(element._namespaceURI))?true:false;
91 public override int GetHashCode()
93 return (String.Format("{0} {1}",
94 XmlConvert.DecodeName(_localName),
95 XmlConvert.DecodeName(_namespaceURI))).GetHashCode();
98 public override string ToString()
100 return string.Format("Element.Prefix = {0}, Element.LocalName = {1}, Element.NamespaceURI = {2}", this.Prefix, this.LocalName, this.NamespaceURI);
104 internal class SoapTypeMapper {
105 private static Hashtable xmlNodeToTypeTable = new Hashtable();
106 private static Hashtable typeToXmlNodeTable = new Hashtable();
107 public static readonly string SoapEncodingNamespace = "http://schemas.xmlsoap.org/soap/encoding/";
108 public static readonly string SoapEncodingPrefix = "SOAP-ENC";
109 public static readonly string SoapEnvelopeNamespace = "http://schemas.xmlsoap.org/soap/envelope/";
110 public static readonly string SoapEnvelopePrefix = "SOAP-ENV";
111 //internal static readonly string SoapEnvelope;
112 private XmlTextWriter _xmlWriter;
113 private long _prefixNumber;
114 private Hashtable namespaceToPrefixTable = new Hashtable();
115 private SerializationBinder _binder;
116 private static ArrayList _canBeValueTypeList;
117 private FormatterAssemblyStyle _assemblyFormat = FormatterAssemblyStyle.Full;
118 private Element elementString;
121 // Constructor used by SoapReader
122 public SoapTypeMapper(SerializationBinder binder)
124 _binder = binder;
127 // Constructor used by SoapWriter
128 public SoapTypeMapper(
129 XmlTextWriter xmlWriter,
130 FormatterAssemblyStyle assemblyFormat,
131 FormatterTypeStyle typeFormat)
133 _xmlWriter = xmlWriter;
134 _assemblyFormat = assemblyFormat;
135 _prefixNumber = 1;
136 Type elementType;
137 elementType = typeof(string);
138 if(typeFormat == FormatterTypeStyle.XsdString)
140 elementString = new Element("xsd", "string", XmlSchema.Namespace);
142 else
144 elementString = new Element(SoapEncodingPrefix, "string", SoapEncodingNamespace);
146 // typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
149 static SoapTypeMapper() {
150 // SoapEnvelope = String.Format(
151 // "<{0}:Envelope xmlns:{0}='{1}' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='{2}' xmlns:{3}='{4}' xmlns:clr='{5}' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>",
152 // SoapEnvelopePrefix,
153 // SoapEnvelopeNamespace,
154 // XmlSchema.Namespace,
155 // SoapEncodingPrefix,
156 // SoapEncodingNamespace,
157 // SoapServices.XmlNsForClrType);
158 _canBeValueTypeList = new ArrayList();
159 _canBeValueTypeList.Add(typeof(DateTime).ToString());
160 _canBeValueTypeList.Add(typeof(TimeSpan).ToString());
161 _canBeValueTypeList.Add(typeof(string).ToString());
162 _canBeValueTypeList.Add(typeof(decimal).ToString());
163 _canBeValueTypeList.Sort();
164 InitMappingTables();
168 public Type this[Element element]
170 get
172 Type type = null;
174 string localName = XmlConvert.DecodeName(element.LocalName);
175 string namespaceURI = XmlConvert.DecodeName(element.NamespaceURI);
176 string typeNamespace, assemblyName;
177 SoapServices.DecodeXmlNamespaceForClrTypeNamespace(
178 element.NamespaceURI,
179 out typeNamespace,
180 out assemblyName);
181 string typeName = typeNamespace + Type.Delimiter + localName;
183 if(assemblyName != null && assemblyName != string.Empty && _binder != null)
185 type = _binder.BindToType(assemblyName, typeName);
187 if(type == null)
189 string assemblyQualifiedName = (string)xmlNodeToTypeTable[element];
190 if(assemblyQualifiedName != null)
191 type = Type.GetType(assemblyQualifiedName);
192 else
195 type = Type.GetType(element.LocalName);
196 if(type == null)
199 type = Type.GetType(typeName);
200 if(type == null)
203 if(assemblyName == null || assemblyName == String.Empty)
204 throw new SerializationException(
205 String.Format("Parse Error, no assembly associated with XML key {0} {1}",
206 localName,
207 namespaceURI));
208 type = FormatterServices.GetTypeFromAssembly(
209 Assembly.Load(assemblyName),
210 typeName);
214 if(type == null)
215 throw new SerializationException();
217 return type;
222 public Element this[string typeFullName, string assemblyName]
224 get
226 Element element;
227 string typeNamespace = string.Empty;
228 string typeName = typeFullName;
229 if(_assemblyFormat == FormatterAssemblyStyle.Simple)
231 string[] items = assemblyName.Split(',');
232 assemblyName = items[0];
234 string assemblyQualifiedName = typeFullName + ", " + assemblyName;
235 element = (Element) typeToXmlNodeTable[assemblyQualifiedName];
236 if(element == null)
238 int typeNameIndex = typeFullName.LastIndexOf('.');
239 if(typeNameIndex != -1)
241 typeNamespace = typeFullName.Substring(0, typeNameIndex);
242 typeName = typeFullName.Substring(typeNamespace.Length + 1);
244 string namespaceURI =
245 SoapServices.CodeXmlNamespaceForClrTypeNamespace(
246 typeNamespace,
247 (!assemblyName.StartsWith("mscorlib"))?assemblyName:String.Empty);
248 string prefix = (string) namespaceToPrefixTable[namespaceURI];
249 if(prefix == null || prefix == string.Empty)
251 prefix = "a" + (_prefixNumber++).ToString();
252 namespaceToPrefixTable[namespaceURI] = prefix;
255 element = new Element(
256 prefix,
257 XmlConvert.EncodeName(typeName),
258 namespaceURI);
260 return element;
264 public Element this[Type type]
266 get
268 if(type == typeof(string)) return elementString;
269 Element element = (Element) typeToXmlNodeTable[type.AssemblyQualifiedName];
270 if(element == null)
272 element = this[type.FullName, type.Assembly.FullName];
273 // if(_assemblyFormat == FormatterAssemblyStyle.Full)
274 // element = this[type.FullName, type.Assembly.FullName];
275 // else
276 // element = this[type.FullName, type.Assembly.GetName().Name];
279 else
281 element = new Element((element.Prefix == null)?_xmlWriter.LookupPrefix(element.NamespaceURI):element.Prefix, element.LocalName, element.NamespaceURI);
283 if(element == null)
284 throw new SerializationException("Oooops");
285 return element;
289 public static bool CanBeValue(Type type)
291 if(type.IsPrimitive) return true;
292 if(type.IsEnum) return true;
293 if(_canBeValueTypeList.BinarySearch(type.ToString()) >= 0)
295 return true;
297 return false;
300 private static void InitMappingTables()
302 Element element;
303 Type elementType;
304 element = new Element("Array", SoapEncodingNamespace);
305 elementType = typeof(System.Array);
306 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
307 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
309 element = new Element("string", XmlSchema.Namespace);
310 elementType = typeof(string);
311 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
312 // typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
314 element = new Element("string", SoapEncodingNamespace);
315 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
317 element = new Element("long", XmlSchema.Namespace);
318 elementType = typeof(long);
319 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
320 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
322 element = new Element("int", XmlSchema.Namespace);
323 elementType = typeof(int);
324 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
325 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
327 element = new Element("float", XmlSchema.Namespace);
328 elementType = typeof(float);
329 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
330 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
332 element = new Element("decimal", XmlSchema.Namespace);
333 elementType = typeof(decimal);
334 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
335 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
337 element = new Element("short", XmlSchema.Namespace);
338 elementType = typeof(short);
339 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
340 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
342 element = new Element("anyType", XmlSchema.Namespace);
343 elementType = typeof(object);
344 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
345 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
347 element = new Element("dateTime", XmlSchema.Namespace);
348 elementType = typeof(DateTime);
349 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
350 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
352 element = new Element("duration", XmlSchema.Namespace);
353 elementType = typeof(TimeSpan);
354 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
355 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
357 element = new Element("Fault", SoapEnvelopeNamespace);
358 elementType = typeof(System.Runtime.Serialization.Formatters.SoapFault);
359 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
360 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
362 element = new Element("base64", SoapEncodingNamespace);
363 elementType = typeof(byte[]);
364 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
365 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
368 public static string GetXsdValue (object value)
370 if (value is DateTime) {
371 return SoapDateTime.ToString ((DateTime)value);
373 else if (value is decimal) {
374 return ((decimal) value).ToString (CultureInfo.InvariantCulture);
376 else if (value is double) {
377 return ((double) value).ToString (CultureInfo.InvariantCulture);
379 else if (value is float) {
380 return ((float) value).ToString (CultureInfo.InvariantCulture);
382 else if (value is TimeSpan) {
383 return SoapDuration.ToString ((TimeSpan)value);
385 else {
386 return value.ToString ();
390 public static object ParseXsdValue (string value, Type type)
392 if (type == typeof(DateTime)) {
393 return SoapDateTime.Parse (value);
395 else if (type == typeof(decimal)) {
396 return decimal.Parse (value, CultureInfo.InvariantCulture);
398 else if (type == typeof(double)) {
399 return double.Parse (value, CultureInfo.InvariantCulture);
401 else if (type == typeof(float)) {
402 return float.Parse (value, CultureInfo.InvariantCulture);
404 else if (type == typeof (TimeSpan)) {
405 return SoapDuration.Parse (value);
407 else if(type.IsEnum) {
408 return Enum.Parse(type, value);
410 else {
411 return Convert.ChangeType (value, type, CultureInfo.InvariantCulture);