X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.XML%2FSystem.Xml.Serialization%2FXmlTypeMapping.cs;h=859042fd7e34d404f8bcc489a1cd91c5b3fc500a;hb=9f3ef8e4bac11601a2cf2670cbab337e6276103b;hp=d0e35adfc4875172fcc6e693d0b93ca41a546230;hpb=3d693eeb90339833968d66c3dc9fde2fa3ba2cef;p=mono.git diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs index d0e35adfc48..859042fd7e3 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs @@ -34,6 +34,7 @@ using System; using System.Collections; using System.Globalization; using System.Xml.Schema; +using System.Reflection; namespace System.Xml.Serialization { @@ -101,11 +102,18 @@ namespace System.Xml.Serialization internal string XmlType { get { return xmlType; } + set { xmlType = value; } } internal string XmlTypeNamespace { - get { return xmlTypeNamespace; } + get { return xmlTypeNamespace ?? string.Empty; } + set { xmlTypeNamespace = value; } + } + + internal bool HasXmlTypeNamespace + { + get { return xmlTypeNamespace != null; } } internal ArrayList DerivedTypes @@ -150,17 +158,16 @@ namespace System.Xml.Serialization set { isNullable = value; } } - internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName) + internal XmlTypeMapping GetRealTypeMap (Type objectType) { if (TypeData.SchemaType == SchemaTypes.Enum) return this; // Returns the map for a subtype of this map's type - objectFullTypeName = objectFullTypeName.Replace ('+','.'); - if (TypeFullName == objectFullTypeName) return this; + if (TypeData.Type == objectType) return this; for (int n=0; n<_derivedTypes.Count; n++) { XmlTypeMapping map = (XmlTypeMapping) _derivedTypes[n]; - if (map.TypeFullName == objectFullTypeName) return map; + if (map.TypeData.Type == objectType) return map; } return null; @@ -168,9 +175,9 @@ namespace System.Xml.Serialization internal XmlTypeMapping GetRealElementMap (string name, string ens) { - if (xmlType == name && xmlTypeNamespace == ens) return this; + if (xmlType == name && XmlTypeNamespace == ens) return this; foreach (XmlTypeMapping map in _derivedTypes) - if (map.xmlType == name && map.xmlTypeNamespace == ens) return map; + if (map.xmlType == name && map.XmlTypeNamespace == ens) return map; return null; } @@ -189,23 +196,95 @@ namespace System.Xml.Serialization internal class XmlSerializableMapping : XmlTypeMapping { XmlSchema _schema; +#if NET_2_0 && !MOONLIGHT + XmlSchemaComplexType _schemaType; + XmlQualifiedName _schemaTypeName; +#endif - internal XmlSerializableMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace) + internal XmlSerializableMapping(XmlRootAttribute root, string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace) : base(elementName, ns, typeData, xmlType, xmlTypeNamespace) { - IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance(typeData.Type); +#if NET_2_0 && !MOONLIGHT + XmlSchemaProviderAttribute schemaProvider = (XmlSchemaProviderAttribute) Attribute.GetCustomAttribute (typeData.Type, typeof (XmlSchemaProviderAttribute)); + + if (schemaProvider != null) { + string method = schemaProvider.MethodName; + MethodInfo mi = typeData.Type.GetMethod (method, BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy); + if (mi == null) + throw new InvalidOperationException (String.Format ("Type '{0}' must implement public static method '{1}'", typeData.Type, method)); + if (!typeof (XmlQualifiedName).IsAssignableFrom (mi.ReturnType) && + // LAMESPEC: it is undocumented. (We don't have to tell users about it in the error message.) + // Also do not add such a silly compatibility test to assert that it does not raise an error. + !typeof (XmlSchemaComplexType).IsAssignableFrom (mi.ReturnType)) + throw new InvalidOperationException (String.Format ("Method '{0}' indicated by XmlSchemaProviderAttribute must have its return type as XmlQualifiedName", method)); + XmlSchemaSet xs = new XmlSchemaSet (); + object retVal = mi.Invoke (null, new object [] { xs }); + _schemaTypeName = XmlQualifiedName.Empty; + if (retVal == null) + return; + + if (retVal is XmlSchemaComplexType) { + _schemaType = (XmlSchemaComplexType) retVal; + if (!_schemaType.QualifiedName.IsEmpty) + _schemaTypeName = _schemaType.QualifiedName; + else + _schemaTypeName = new XmlQualifiedName (xmlType, xmlTypeNamespace); + } + else if (retVal is XmlQualifiedName) { + _schemaTypeName = (XmlQualifiedName)retVal; + } + else + throw new InvalidOperationException ( + String.Format ("Method {0}.{1}() specified by XmlSchemaProviderAttribute has invalid signature: return type must be compatible with System.Xml.XmlQualifiedName.", typeData.Type.Name, method)); + + // defaultNamespace at XmlReflectionImporter takes precedence for Namespace, but not for XsdTypeNamespace. + UpdateRoot (new XmlQualifiedName (root != null ? root.ElementName : _schemaTypeName.Name, root != null ? root.Namespace : Namespace ?? _schemaTypeName.Namespace)); + XmlTypeNamespace = _schemaTypeName.Namespace; + XmlType = _schemaTypeName.Name; + + if (!_schemaTypeName.IsEmpty && xs.Count > 0) { + XmlSchema [] schemas = new XmlSchema [xs.Count]; + xs.CopyTo (schemas, 0); + _schema = schemas [0]; + } + + return; + } +#endif +#if NET_2_0 && !MOONLIGHT + IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance (typeData.Type, true); + try { + _schema = serializable.GetSchema(); + } catch (Exception) { + // LAMESPEC: .NET has a bad exception catch and swallows it silently. + } +#else + IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance (typeData.Type); _schema = serializable.GetSchema(); +#endif +#if !MOONLIGHT if (_schema != null) { if (_schema.Id == null || _schema.Id.Length == 0) throw new InvalidOperationException("Schema Id is missing. The schema returned from " + typeData.Type.FullName + ".GetSchema() must have an Id."); } +#endif } internal XmlSchema Schema { get { return _schema; } } + +#if NET_2_0 && !MOONLIGHT + internal XmlSchemaType SchemaType { + get { return _schemaType; } + } + + internal XmlQualifiedName SchemaTypeName { + get { return _schemaTypeName; } + } +#endif } @@ -229,10 +308,14 @@ namespace System.Xml.Serialization XmlTypeMapMember _returnMember; bool _ignoreMemberNamespace; bool _canBeSimpleType = true; + bool? _isOrderDependentMap; public void AddMember (XmlTypeMapMember member) { - member.GlobalIndex = _allMembers.Count; + // If GlobalIndex has not been set, set it now + if (member.GlobalIndex == -1) + member.GlobalIndex = _allMembers.Count; + _allMembers.Add (member); if (!(member.DefaultValue is System.DBNull) && member.DefaultValue != null) { @@ -247,7 +330,7 @@ namespace System.Xml.Serialization { XmlTypeMapMemberAttribute atm = (XmlTypeMapMemberAttribute)member; if (_attributeMembers == null) _attributeMembers = new Hashtable(); - string key = BuildKey (atm.AttributeName, atm.Namespace); + string key = BuildKey (atm.AttributeName, atm.Namespace, -1); if (_attributeMembers.ContainsKey (key)) throw new InvalidOperationException ("The XML attribute named '" + atm.AttributeName + "' from namespace '" + atm.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the attribute."); member.Index = _attributeMembers.Count; @@ -292,7 +375,7 @@ namespace System.Xml.Serialization ICollection elemsInfo = ((XmlTypeMapMemberElement)member).ElementInfo; foreach (XmlTypeMapElementInfo elem in elemsInfo) { - string key = BuildKey (elem.ElementName, elem.Namespace); + string key = BuildKey (elem.ElementName, elem.Namespace, elem.ExplicitOrder); if (_elements.ContainsKey (key)) throw new InvalidOperationException ("The XML element named '" + elem.ElementName + "' from namespace '" + elem.Namespace + "' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element."); _elements.Add (key, elem); @@ -314,13 +397,13 @@ namespace System.Xml.Serialization public XmlTypeMapMemberAttribute GetAttribute (string name, string ns) { if (_attributeMembers == null) return null; - return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey(name,ns)]; + return (XmlTypeMapMemberAttribute)_attributeMembers [BuildKey (name,ns, -1)]; } - public XmlTypeMapElementInfo GetElement (string name, string ns) + public XmlTypeMapElementInfo GetElement (string name, string ns, int order) { if (_elements == null) return null; - return (XmlTypeMapElementInfo)_elements [BuildKey(name,ns)]; + return (XmlTypeMapElementInfo)_elements [BuildKey (name,ns, order)]; } public XmlTypeMapElementInfo GetElement (int index) @@ -338,14 +421,15 @@ namespace System.Xml.Serialization _elementsByIndex [mem.Index] = (XmlTypeMapElementInfo) mem.ElementInfo [0]; } } - + if (index >= _elementMembers.Count) + return null; return _elementsByIndex [index]; } - private string BuildKey (string name, string ns) + private string BuildKey (string name, string ns, int explicitOrder) { if (_ignoreMemberNamespace) return name; - else return name + " / " + ns; + else return name + " / " + ns + (explicitOrder < 0 ? "" : "/" + explicitOrder); } public ICollection AllElementInfos @@ -360,6 +444,20 @@ namespace System.Xml.Serialization set { _ignoreMemberNamespace = value; } } + public bool IsOrderDependentMap { + get { + if (_isOrderDependentMap == null) { + _isOrderDependentMap = false; + foreach (XmlTypeMapElementInfo ei in _elements.Values) + if (ei.ExplicitOrder >= 0) { + _isOrderDependentMap = true; + break; + } + } + return (bool) _isOrderDependentMap; + } + } + public XmlTypeMapMember FindMember (string name) { for (int n=0; n<_allMembers.Count; n++)