2004-04-15 Jean-Marc Andre <jeanmarc.andre@cpe.fr>
[mono.git] / mcs / class / System.Runtime.Serialization.Formatters.Soap / System.Runtime.Serialization.Formatters.Soap / SoapTypeMapper.cs
index 5ff113839d2fec496800efa3eef8f7ab0cac7ab5..fe1d7bf684b140ea059453aef48d88f8a8c36fef 100644 (file)
-// created on 09/04/2003 at 18:58\r
-//\r
-//     System.Runtime.Serialization.Formatters.Soap.SoapTypeMapper\r
-//\r
-//     Authors:\r
-//             Jean-Marc Andre (jean-marc.andre@polymtl.ca)\r
-//\r
-\r
-using System;\r
-using System.Reflection;\r
-using System.Collections;\r
-using System.Runtime.Remoting;\r
-using System.Xml.Serialization;\r
-using System.Xml.Schema;\r
-\r
-namespace System.Runtime.Serialization.Formatters.Soap {\r
-       \r
-       internal class SoapTypeMapper {\r
-               private static Hashtable _mappingTable = new Hashtable();\r
-               private static Hashtable _invertMappingTable = new Hashtable();\r
-               \r
-               static SoapTypeMapper() {\r
-                       InitMappingTable();\r
-                       \r
-               }\r
-               \r
-               // returns the SoapTypeMapping corresponding to the System.Type\r
-               public static SoapTypeMapping GetSoapType(Type type) {\r
-                       object rtnMapping;\r
-\r
-                       if (type.IsByRef) type = type.GetElementType ();\r
-\r
-                       \r
-                       if(type.IsArray){\r
-                                       rtnMapping = _mappingTable[typeof(System.Array)];\r
-                       }\r
-                       else {\r
-                               rtnMapping = (object) _mappingTable[type];\r
-                               \r
-                               if(rtnMapping == null){\r
-                                       string sTypeNamespace;\r
-                                       AssemblyName assName = type.Assembly.GetName();\r
-                                       if(assName.Name.StartsWith("mscorlib")) sTypeNamespace = "http://schemas.microsoft.com/clr/ns/"+type.Namespace;\r
-                                       else sTypeNamespace = SoapServices.CodeXmlNamespaceForClrTypeNamespace(type.Namespace, type.Assembly.FullName);\r
-                                       string sType = type.FullName;\r
-                                       string sTypeName = type.FullName;\r
-                                       if(type.Namespace != null && type.Namespace.Length > 0) sTypeName = sTypeName.Remove(0, type.Namespace.Length+1);\r
-                                       SoapTypeMapping newType =  new SoapTypeMapping(type, sTypeName, sTypeNamespace, false, type.IsPrimitive, type.IsValueType, true);\r
-                                       \r
-                                       _mappingTable.Add(type, newType);\r
-                                       _invertMappingTable.Add(newType, type);\r
-                                       \r
-                                       return newType;\r
-                               }\r
-                                       \r
-                       }\r
-                       \r
-                       return (SoapTypeMapping)rtnMapping;\r
-               }\r
-               \r
-               // returns the Type corresponding to the SoapTypeMapping\r
-               public static Type GetType(SoapTypeMapping mapping) {\r
-                       object rtnObject;\r
-                       rtnObject = _invertMappingTable[mapping];\r
-                       \r
-                       if(rtnObject == null && mapping.TypeNamespace.Length != 0) {\r
-                               string typeNamespace;\r
-                               string assemblyName;\r
-                               SoapServices.DecodeXmlNamespaceForClrTypeNamespace(mapping.TypeNamespace, out typeNamespace, out assemblyName);\r
-                               rtnObject = Type.GetType(typeNamespace+"."+mapping.TypeName);\r
-                               \r
-                               if(rtnObject == null) {\r
-                                       Assembly ass =Assembly.Load(assemblyName);\r
-                                       if(ass != null) {\r
-                                               rtnObject = ass.GetType(typeNamespace+"."+mapping.TypeName, true);\r
-                                       }\r
-                               }\r
-                       }\r
-                       \r
-                       return (Type)rtnObject;\r
-               }\r
-\r
-               private static void RegisterSchemaType (Type type, string typeName, bool canBeValue, bool isPrimitive,bool isValueType,bool needId)\r
-               {\r
-                       SoapTypeMapping mapping =  new SoapTypeMapping (type, typeName, canBeValue, isPrimitive, isValueType, needId);\r
-                       _mappingTable.Add(type, mapping);\r
-                       _invertMappingTable.Add(mapping, type);\r
-               }\r
-               \r
-               // initialize the mapping tables\r
-               private static void InitMappingTable() {\r
-                       SoapTypeMapping mapping;\r
-                       \r
-                       // the primitive type "System.String"\r
-                       mapping =  new SoapTypeMapping(typeof(string), "string", true, false, false, true);\r
-                       _mappingTable.Add(typeof(string),mapping);\r
-                       _invertMappingTable.Add(mapping, typeof(string));\r
-                       mapping =  new SoapTypeMapping(typeof(string), "string", XmlSchema.Namespace, true, false, false, true);\r
-                       _invertMappingTable.Add(mapping, typeof(string));\r
-\r
-                       RegisterSchemaType (typeof(short), "short", true, true, true, false);\r
-                       RegisterSchemaType (typeof(ushort), "unsignedShort", true, true, true, false);\r
-                       RegisterSchemaType (typeof(int), "int", true, true, true, false);\r
-                       RegisterSchemaType (typeof(uint), "unsignedInt", true, true, true, false);\r
-                       RegisterSchemaType (typeof(long), "long", true, true, true, false);\r
-                       RegisterSchemaType (typeof(ulong), "unsignedLong", true, true, true, false);\r
-                       RegisterSchemaType (typeof(decimal), "decimal", true, true, true, false);\r
-                       RegisterSchemaType (typeof(sbyte), "byte", true, true, true, false);\r
-                       RegisterSchemaType (typeof(byte), "unsignedByte", true, true, true, false);\r
-                       RegisterSchemaType (typeof(DateTime), "dateTime", true, true, true, false);\r
-                       RegisterSchemaType (typeof(TimeSpan), "duration", true, true, true, false);\r
-                       RegisterSchemaType (typeof(double), "double", true, true, true, false);\r
-                       RegisterSchemaType (typeof(Char), "char", true, true, true, false);\r
-                       RegisterSchemaType (typeof(bool), "boolean", true, true, true, false);\r
-                       RegisterSchemaType (typeof(System.Single), "float", true, true, true, false);\r
-                       RegisterSchemaType (typeof(System.Array), "Array", false, false, false, true);\r
-                       \r
-                       mapping = new SoapTypeMapping(typeof(object), "anyType", "http://www.w3.org/2001/XMLSchema", false, false, false, true);\r
-                       _mappingTable.Add(typeof(object), mapping);\r
-                       _invertMappingTable.Add(mapping, typeof(object));\r
-                       \r
-                       mapping = new SoapTypeMapping(typeof(System.Runtime.Serialization.Formatters.SoapFault), "Fault", "http://schemas.xmlsoap.org/soap/envelope/", false, false, false, true);\r
-                       _mappingTable.Add(typeof(System.Runtime.Serialization.Formatters.SoapFault), mapping);\r
-                       _invertMappingTable.Add(mapping, typeof(System.Runtime.Serialization.Formatters.SoapFault));\r
-                       \r
-                       \r
-               }\r
-       }\r
-}\r
+// created on 09/04/2003 at 18:58
+//
+//     System.Runtime.Serialization.Formatters.Soap.SoapTypeMapper
+//
+//     Authors:
+//             Jean-Marc Andre (jean-marc.andre@polymtl.ca)
+//
+
+using System;
+using System.Reflection;
+using System.Collections;
+using System.Runtime.Remoting;
+using System.Xml;
+using System.Xml.Serialization;
+using System.Runtime.Serialization.Formatters;
+using System.Xml.Schema;
+
+namespace System.Runtime.Serialization.Formatters.Soap {
+
+       internal class Element
+       {
+               private string _prefix;
+               private string _localName;
+               private string _namespaceURI;
+
+               public Element(string prefix, string localName, string namespaceURI) 
+               {
+                       _prefix = prefix;
+                       _localName = localName;
+                       _namespaceURI = namespaceURI;
+               }
+
+               public Element(string localName, string namespaceURI): this(null, localName, namespaceURI)
+               {
+               }
+
+               public string Prefix
+               {
+                       get
+                       {
+                               return _prefix;
+                       }
+               }
+
+               public string LocalName
+               {
+                       get
+                       {
+                               return _localName;
+                       }
+               }
+
+               public string NamespaceURI 
+               {
+                       get 
+                       {
+                               return _namespaceURI;
+                       }
+               }
+
+               public override bool Equals(object obj) 
+               {
+                       Element element = obj as Element;
+                       return (_localName == XmlConvert.DecodeName(element._localName) &&
+                               _namespaceURI == XmlConvert.DecodeName(element._namespaceURI))?true:false;
+               }
+
+               public override int GetHashCode()
+               {
+                       return (String.Format("{0} {1}", 
+                               XmlConvert.DecodeName(_localName),
+                               XmlConvert.DecodeName(_namespaceURI))).GetHashCode();
+               }
+
+               public override string ToString() 
+               {
+                       return string.Format("Element.Prefix = {0}, Element.LocalName = {1}, Element.NamespaceURI = {2}", this.Prefix, this.LocalName, this.NamespaceURI);
+               }
+       }
+
+       internal class SoapTypeMapper {
+               private static Hashtable xmlNodeToTypeTable = new Hashtable();
+               private static Hashtable typeToXmlNodeTable = new Hashtable();
+               public static readonly string SoapEncodingNamespace = "http://schemas.xmlsoap.org/soap/encoding/";
+               public static readonly string SoapEncodingPrefix = "SOAP-ENC";
+               public static readonly string SoapEnvelopeNamespace = "http://schemas.xmlsoap.org/soap/envelope/";
+               public static readonly string SoapEnvelopePrefix = "SOAP-ENV";
+               internal static readonly string SoapEnvelope;
+               private XmlTextWriter _xmlWriter;
+               private long _prefixNumber;
+               private Hashtable namespaceToPrefixTable = new Hashtable();
+               private SerializationBinder _binder;
+               private static ArrayList _canBeValueTypeList;
+               private FormatterAssemblyStyle _assemblyFormat = FormatterAssemblyStyle.Full;
+               private Element elementString;
+
+
+               // Constructor used by SoapReader
+               public SoapTypeMapper(SerializationBinder binder) 
+               {
+                       _binder = binder;
+               }
+
+               // Constructor used by SoapWriter
+               public SoapTypeMapper(
+                       XmlTextWriter xmlWriter, 
+                       FormatterAssemblyStyle assemblyFormat,
+                       FormatterTypeStyle typeFormat) 
+               {
+                       _xmlWriter = xmlWriter;
+                       _assemblyFormat = assemblyFormat;
+                       _prefixNumber = 1;
+                       Element element;
+                       Type elementType;
+                       elementType = typeof(string);
+                       if(typeFormat == FormatterTypeStyle.XsdString)\r
+                       {
+                               elementString = new Element("string", XmlSchema.Namespace);
+                       }
+                       else
+                       {
+                               elementString = new Element("string", SoapEncodingNamespace);
+                       }
+//                     typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+               }
+               
+               static SoapTypeMapper() {
+//                     SoapEnvelope = String.Format(
+//                             "<{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/'/>",
+//                             SoapEnvelopePrefix,
+//                             SoapEnvelopeNamespace,
+//                             XmlSchema.Namespace,
+//                             SoapEncodingPrefix,
+//                             SoapEncodingNamespace,
+//                             SoapServices.XmlNsForClrType);
+                       _canBeValueTypeList = new ArrayList();
+                       _canBeValueTypeList.Add(typeof(DateTime).ToString());
+                       _canBeValueTypeList.Add(typeof(TimeSpan).ToString());
+                       _canBeValueTypeList.Add(typeof(string).ToString());
+                       _canBeValueTypeList.Add(typeof(decimal).ToString());
+                       _canBeValueTypeList.Sort();
+                       InitMappingTables();
+                       
+               }
+
+               public Type this[Element element]
+               {
+                       get 
+                       {
+                               Type type = null;
+
+                               string localName = XmlConvert.DecodeName(element.LocalName);
+                               string namespaceURI = XmlConvert.DecodeName(element.NamespaceURI);
+                               string typeNamespace, assemblyName;
+                               SoapServices.DecodeXmlNamespaceForClrTypeNamespace(
+                                       element.NamespaceURI, 
+                                       out typeNamespace, 
+                                       out assemblyName);
+                               string typeName = typeNamespace + Type.Delimiter + localName;
+
+                               if(assemblyName != null && assemblyName != string.Empty && _binder != null) 
+                               {
+                                       type = _binder.BindToType(assemblyName, typeName);
+                               }
+                               if(type == null) 
+                               {
+                                       string assemblyQualifiedName = (string)xmlNodeToTypeTable[element];
+                                       if(assemblyQualifiedName != null)
+                                               type = Type.GetType(assemblyQualifiedName);
+                                       else
+                                       { 
+
+                                               type = Type.GetType(element.LocalName);
+                                               if(type == null) 
+                                               { 
+
+                                                       type = Type.GetType(typeName);
+                                                       if(type == null) 
+                                                       {
+
+                                                               if(assemblyName == null || assemblyName == String.Empty)
+                                                                       throw new SerializationException(
+                                                                               String.Format("Parse Error, no assembly associated with XML key {1} {2}", 
+                                                                               localName, 
+                                                                               namespaceURI));
+                                                               type = FormatterServices.GetTypeFromAssembly(
+                                                                       Assembly.Load(assemblyName), 
+                                                                       typeName);
+                                                       }
+                                               }
+                                       }
+                                       if(type == null)
+                                               throw new SerializationException();
+                               }
+                               return type;
+                       }
+               }
+
+
+               public Element this[string typeFullName, string assemblyName]
+               {
+                       get 
+                       {
+                               Element element;
+                               string typeNamespace = string.Empty;
+                               string typeName = typeFullName;
+                               if(_assemblyFormat == FormatterAssemblyStyle.Simple)\r
+                               {
+                                       string[] items = assemblyName.Split(',');
+                                       assemblyName = items[0];
+                               }
+                               string assemblyQualifiedName = typeFullName + ", " + assemblyName;
+                               element = (Element) typeToXmlNodeTable[assemblyQualifiedName];
+                               if(element == null)
+                               {
+                                       int typeNameIndex = typeFullName.LastIndexOf('.');
+                                       if(typeNameIndex != -1) 
+                                       {
+                                               typeNamespace = typeFullName.Substring(0, typeNameIndex);
+                                               typeName = typeFullName.Substring(typeNamespace.Length + 1);
+                                       }
+                                       string namespaceURI = 
+                                               SoapServices.CodeXmlNamespaceForClrTypeNamespace(
+                                               typeNamespace, 
+                                               (!assemblyName.StartsWith("mscorlib"))?assemblyName:String.Empty);
+                                       string prefix = (string) namespaceToPrefixTable[namespaceURI];
+                                       if(prefix == null || prefix == string.Empty)
+                                       {
+                                               prefix = "a" + (_prefixNumber++).ToString();
+                                               namespaceToPrefixTable[namespaceURI] = prefix;
+
+                                       }
+                                       element = new Element(
+                                               prefix, 
+                                               XmlConvert.EncodeName(typeName), 
+                                               namespaceURI);
+                               }
+                               return element;
+                       }
+               }
+
+               public Element this[Type type]
+               {
+                       get 
+                       {
+                               Element element = (Element) typeToXmlNodeTable[type.AssemblyQualifiedName];
+                               if(element == null)
+                               {
+                                       element = this[type.FullName, type.Assembly.FullName];
+//                                     if(_assemblyFormat == FormatterAssemblyStyle.Full)
+//                                             element = this[type.FullName, type.Assembly.FullName];
+//                                     else
+//                                             element = this[type.FullName, type.Assembly.GetName().Name];
+
+                               }
+                               else
+                               {
+                                       element = new Element((element.Prefix == null)?_xmlWriter.LookupPrefix(element.NamespaceURI):element.Prefix, element.LocalName, element.NamespaceURI);
+                               }
+                               if(element == null)
+                                       throw new SerializationException("Oooops");
+                               return element;
+                       }
+               }
+
+               public static bool CanBeValue(Type type)
+               {
+                       if(type.IsPrimitive) return true;
+                       if(type.IsEnum) return true;
+                       if(_canBeValueTypeList.BinarySearch(type.ToString()) >= 0) 
+                       {
+                               return true;
+                       }
+                       return false;
+               }
+
+               private static void InitMappingTables() 
+               {
+                       Element element;
+                       Type elementType;
+                       element = new Element("Array", SoapEncodingNamespace);
+                       elementType = typeof(System.Array);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("string", XmlSchema.Namespace);
+                       elementType = typeof(string);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+//                     typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("string", SoapEncodingNamespace);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+
+                       element = new Element("long", XmlSchema.Namespace);
+                       elementType = typeof(long);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("int", XmlSchema.Namespace);
+                       elementType = typeof(int);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("float", XmlSchema.Namespace);
+                       elementType = typeof(float);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("decimal", XmlSchema.Namespace);
+                       elementType = typeof(decimal);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("short", XmlSchema.Namespace);
+                       elementType = typeof(short);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("anyType", XmlSchema.Namespace);
+                       elementType = typeof(object);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("dateTime", XmlSchema.Namespace);
+                       elementType = typeof(DateTime);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("duration", XmlSchema.Namespace);
+                       elementType = typeof(TimeSpan);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+                       element = new Element("Fault", SoapEnvelopeNamespace);
+                       elementType = typeof(System.Runtime.Serialization.Formatters.SoapFault);
+                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
+                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+
+
+               }
+
+
+       }
+}