* TypeTranslator.cs, XmlCustomFormatter.cs: Added support for base64. This
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlTypeMapping.cs
index 2f082fad66683ae68a1e2a98b5bf8a6cda6cd5f1..2d6bb038d09a354db7f52753f5ae97b9e248c5ce 100644 (file)
@@ -7,10 +7,32 @@
 //\r
 // (C) 2002 John Donagher\r
 //\r
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
 \r
 using System.Xml;\r
 using System;\r
 using System.Collections;\r
+using System.Globalization;\r
 \r
 namespace System.Xml.Serialization\r
 {\r
@@ -25,6 +47,8 @@ namespace System.Xml.Serialization
                bool multiReferenceType = false;\r
                bool isSimpleType;\r
                string documentation;\r
+               bool includeInSchema;\r
+               bool isNullable = true;\r
 \r
                ArrayList _derivedTypes = new ArrayList();\r
 \r
@@ -102,24 +126,48 @@ namespace System.Xml.Serialization
                        get { return documentation; }\r
                }\r
 \r
+               internal bool IncludeInSchema\r
+               {\r
+                       get { return includeInSchema; }\r
+                       set { includeInSchema = value; }\r
+               }\r
+               \r
+               internal bool IsNullable\r
+               {\r
+                       get { return isNullable; }\r
+                       set { isNullable = value; }\r
+               }\r
+\r
                internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName)\r
                {\r
                        // Returns the map for a subtype of this map's type\r
 \r
+                       objectFullTypeName = objectFullTypeName.Replace ('+','.');\r
                        if (TypeFullName == objectFullTypeName) return this;\r
-                       foreach (XmlTypeMapping map in _derivedTypes)\r
+                       for (int n=0; n<_derivedTypes.Count; n++) {\r
+                               XmlTypeMapping map = (XmlTypeMapping) _derivedTypes[n];\r
                                if (map.TypeFullName == objectFullTypeName) return map;\r
-\r
+                       }\r
+                       \r
                        return null;\r
                }\r
 \r
                internal XmlTypeMapping GetRealElementMap (string name, string ens)\r
                {\r
-                       if (xmlType == name && ns == ens) return this;\r
+                       if (xmlType == name && xmlTypeNamespace == ens) return this;\r
                        foreach (XmlTypeMapping map in _derivedTypes)\r
-                               if (map.xmlType == name && map.ns == ens) return map;\r
+                               if (map.xmlType == name && map.xmlTypeNamespace == ens) return map;\r
+                       \r
                        return null;\r
                }\r
+               \r
+               internal void UpdateRoot (XmlQualifiedName qname)\r
+               {\r
+                       if (qname != null) {\r
+                               this.elementName = qname.Name;\r
+                               this.ns = qname.Namespace;\r
+                       }\r
+               }\r
        }\r
 \r
        // Mapping info for classes and structs\r
@@ -129,23 +177,39 @@ namespace System.Xml.Serialization
                Hashtable _elements = new Hashtable ();\r
                ArrayList _elementMembers;\r
                Hashtable _attributeMembers;\r
+               XmlTypeMapMemberAttribute[] _attributeMembersArray;\r
+               XmlTypeMapElementInfo[] _elementsByIndex;\r
                ArrayList _flatLists;\r
                ArrayList _allMembers = new ArrayList ();\r
+               ArrayList _membersWithDefault;\r
                XmlTypeMapMemberAnyElement _defaultAnyElement;\r
                XmlTypeMapMemberAnyAttribute _defaultAnyAttribute;\r
                XmlTypeMapMemberNamespaces _namespaceDeclarations;\r
                XmlTypeMapMember _xmlTextCollector;\r
+               XmlTypeMapMember _returnMember;\r
+               bool _ignoreMemberNamespace;\r
+               bool _canBeSimpleType = true;\r
 \r
                public void AddMember (XmlTypeMapMember member)\r
                {\r
                        _allMembers.Add (member);\r
+                       \r
+                       if (!(member.DefaultValue is System.DBNull)) {\r
+                               if (_membersWithDefault == null) _membersWithDefault = new ArrayList ();\r
+                               _membersWithDefault.Add (member);\r
+                       }\r
+                       \r
+                       if (member.IsReturnValue)\r
+                               _returnMember = member;\r
+                       \r
                        if (member is XmlTypeMapMemberAttribute)\r
                        {\r
                                XmlTypeMapMemberAttribute atm = (XmlTypeMapMemberAttribute)member;\r
                                if (_attributeMembers == null) _attributeMembers = new Hashtable();\r
-                               string key = atm.AttributeName + "/" + atm.Namespace;\r
+                               string key = BuildKey (atm.AttributeName, atm.Namespace);\r
                                if (_attributeMembers.ContainsKey (key))\r
                                        throw new InvalidOperationException ("The XML attribute named '" + atm.AttributeName + "' from namespace '" + atm.Namespace + "' already present in the current scope. Use XML attributes to specify another XML name or namespace for the attribute.");\r
+                               member.Index = _attributeMembers.Count;\r
                                _attributeMembers.Add (key, member);\r
                                return;\r
                        }\r
@@ -187,7 +251,7 @@ namespace System.Xml.Serialization
                        ICollection elemsInfo = ((XmlTypeMapMemberElement)member).ElementInfo;\r
                        foreach (XmlTypeMapElementInfo elem in elemsInfo)\r
                        {\r
-                               string key = elem.ElementName+"/"+elem.Namespace;\r
+                               string key = BuildKey (elem.ElementName, elem.Namespace);\r
                                if (_elements.ContainsKey (key)) \r
                                        throw new InvalidOperationException ("The XML element named '" + elem.ElementName + "' from namespace '" + elem.Namespace + "' already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.");\r
                                _elements.Add (key, elem);\r
@@ -204,13 +268,38 @@ namespace System.Xml.Serialization
                public XmlTypeMapMemberAttribute GetAttribute (string name, string ns)\r
                {\r
                        if (_attributeMembers == null) return null;\r
-                       return (XmlTypeMapMemberAttribute)_attributeMembers[name + "/" + ns];\r
+                       return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey(name,ns)];\r
                }\r
 \r
                public XmlTypeMapElementInfo GetElement (string name, string ns)\r
                {\r
                        if (_elements == null) return null;\r
-                       return (XmlTypeMapElementInfo)_elements[name + "/" + ns];\r
+                       return (XmlTypeMapElementInfo)_elements [BuildKey(name,ns)];\r
+               }\r
+               \r
+               public XmlTypeMapElementInfo GetElement (int index)\r
+               {\r
+                       if (_elements == null) return null;\r
+                       \r
+                       if (_elementsByIndex == null)\r
+                       {\r
+                               _elementsByIndex = new XmlTypeMapElementInfo [_elementMembers.Count];\r
+                               foreach (XmlTypeMapMemberElement mem in _elementMembers)\r
+                               {\r
+                                       if (mem.ElementInfo.Count != 1) \r
+                                               throw new InvalidOperationException ("Read by order only possible for encoded/bare format");\r
+                                               \r
+                                       _elementsByIndex [mem.Index] = (XmlTypeMapElementInfo) mem.ElementInfo [0];\r
+                               }\r
+                       }\r
+                       \r
+                       return _elementsByIndex [index];\r
+               }\r
+               \r
+               private string BuildKey (string name, string ns)\r
+               {\r
+                       if (_ignoreMemberNamespace) return name;\r
+                       else return name + " / " + ns;\r
                }\r
                \r
                public ICollection AllElementInfos\r
@@ -218,6 +307,12 @@ namespace System.Xml.Serialization
                        get { return _elements.Values; }\r
                }\r
                \r
+               \r
+               public bool IgnoreMemberNamespace\r
+               {\r
+                       get { return _ignoreMemberNamespace; }\r
+                       set { _ignoreMemberNamespace = value; }\r
+               }\r
 \r
                public XmlTypeMapMember FindMember (string name)\r
                {\r
@@ -243,7 +338,16 @@ namespace System.Xml.Serialization
 \r
                public ICollection AttributeMembers\r
                {\r
-                       get { return (_attributeMembers != null) ? _attributeMembers.Values : null; }\r
+                       get \r
+                       {\r
+                               if (_attributeMembers == null) return null;\r
+                               if (_attributeMembersArray != null) return _attributeMembersArray;\r
+                               \r
+                               _attributeMembersArray = new XmlTypeMapMemberAttribute[_attributeMembers.Count];\r
+                               foreach (XmlTypeMapMemberAttribute mem in _attributeMembers.Values)\r
+                                       _attributeMembersArray [mem.Index] = mem;\r
+                               return _attributeMembersArray;\r
+                       }\r
                }\r
 \r
                public ICollection ElementMembers\r
@@ -260,26 +364,41 @@ namespace System.Xml.Serialization
                {\r
                        get { return _flatLists; }\r
                }\r
+               \r
+               public ArrayList MembersWithDefault\r
+               {\r
+                       get { return _membersWithDefault; }\r
+               }\r
 \r
                public XmlTypeMapMember XmlTextCollector\r
                {\r
                        get { return _xmlTextCollector; }\r
                }\r
+               \r
+               public XmlTypeMapMember ReturnMember\r
+               {\r
+                       get { return _returnMember; }\r
+               }\r
 \r
                public XmlQualifiedName SimpleContentBaseType\r
                {\r
                        get\r
                        {\r
-                               if (_elementMembers == null || _elementMembers.Count != 1) return null;\r
+                               if (!_canBeSimpleType || _elementMembers == null || _elementMembers.Count != 1) return null;\r
                                XmlTypeMapMemberElement member = (XmlTypeMapMemberElement) _elementMembers[0];\r
                                if (member.ElementInfo.Count != 1) return null;\r
                                XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo[0];\r
                                if (!einfo.IsTextElement) return null;\r
-                               if (einfo.TypeData.SchemaType == SchemaTypes.Primitive || einfo.TypeData.SchemaType == SchemaTypes.Enum)\r
+                               if (member.TypeData.SchemaType == SchemaTypes.Primitive || member.TypeData.SchemaType == SchemaTypes.Enum)\r
                                        return new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace);\r
                                return null;\r
                        }\r
                }\r
+               \r
+               public void SetCanBeSimpleType (bool can)\r
+               {\r
+                       _canBeSimpleType = can;\r
+               }\r
 \r
                public bool HasSimpleContent\r
                {\r
@@ -359,6 +478,20 @@ namespace System.Xml.Serialization
                                if (elem.ElementName == elementName && elem.Namespace == ns) return elem;\r
                        return null;\r
                }\r
+               \r
+               public XmlTypeMapElementInfo FindTextElement ()\r
+               {\r
+                       foreach (XmlTypeMapElementInfo elem in _itemInfo)\r
+                               if (elem.IsTextElement) return elem;\r
+                       return null;\r
+               }\r
+               \r
+               public string GetSchemaArrayName ()\r
+               {\r
+                       XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) _itemInfo[0];\r
+                       if (einfo.MappedType != null) return TypeTranslator.GetArrayName (einfo.MappedType.XmlType);\r
+                       else return TypeTranslator.GetArrayName (einfo.TypeData.XmlType);\r
+               }\r
 \r
                public void GetArrayType (int itemCount, out string localName, out string ns)\r
                {\r
@@ -465,8 +598,9 @@ namespace System.Xml.Serialization
                                string[] enumNames = enumValue.ToString().Split (',');\r
                                foreach (string name in enumNames)\r
                                {\r
+                                       string tname = name.Trim();\r
                                        foreach (EnumMapMember mem in _members)\r
-                                               if (mem.EnumName == name.Trim()) {\r
+                                               if (mem.EnumName == tname) {\r
                                                        sb.Append (mem.XmlName).Append (' ');\r
                                                        break;\r
                                                }\r
@@ -478,11 +612,14 @@ namespace System.Xml.Serialization
                        foreach (EnumMapMember mem in _members)\r
                                if (mem.EnumName == enumName) return mem.XmlName;\r
                        \r
-                       return Convert.ToInt64(enumValue).ToString();\r
+                       return Convert.ToInt64(enumValue).ToString(CultureInfo.InvariantCulture);\r
                }\r
 \r
                public string GetEnumName (string xmlName)\r
                {\r
+                       if (_isFlags && xmlName.Length == 0) \r
+                               return "0";\r
+                       \r
                        if (_isFlags && xmlName.Trim().IndexOf (' ') != -1)\r
                        {\r
                                System.Text.StringBuilder sb = new System.Text.StringBuilder ();\r
@@ -495,7 +632,7 @@ namespace System.Xml.Serialization
                                                if (mem.XmlName == name) { foundEnumValue = mem.EnumName; break; }\r
 \r
                                        if (foundEnumValue != null) sb.Append (foundEnumValue).Append (','); \r
-                                       else throw new InvalidOperationException ("Invalid enum value '" + name + "'");\r
+                                       else return null;\r
                                }\r
                                sb.Remove (sb.Length-1, 1);\r
                                return sb.ToString ();\r
@@ -504,13 +641,7 @@ namespace System.Xml.Serialization
                        foreach (EnumMapMember mem in _members)\r
                                if (mem.XmlName == xmlName) return mem.EnumName;\r
                                \r
-                       try {\r
-                               Int64.Parse (xmlName);\r
-                               return xmlName;\r
-                       }\r
-                       catch {\r
-                               throw new InvalidOperationException ("Invalid enumeration value: " + xmlName);\r
-                       }\r
+                       return null;\r
                }\r
        }\r
-}
+}\r