// // XmlSerializationReaderInterpreter.cs: // // Author: // Lluis Sanchez Gual (lluis@ximian.com) // // (C) 2002, 2003 Ximian, Inc. http://www.ximian.com // // // 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. // using System; using System.Reflection; using System.Collections; namespace System.Xml.Serialization { internal class XmlSerializationReaderInterpreter: XmlSerializationReader { XmlMapping _typeMap; SerializationFormat _format; static readonly XmlQualifiedName AnyType = new XmlQualifiedName("anyType", System.Xml.Schema.XmlSchema.Namespace); public XmlSerializationReaderInterpreter(XmlMapping typeMap) { _typeMap = typeMap; _format = typeMap.Format; } protected override void InitCallbacks () { ArrayList maps = _typeMap.RelatedMaps; if (maps != null) { foreach (XmlTypeMapping map in maps) { if (map.TypeData.SchemaType == SchemaTypes.Class || map.TypeData.SchemaType == SchemaTypes.Enum) { ReaderCallbackInfo info = new ReaderCallbackInfo (this, map); AddReadCallback (map.XmlType, map.Namespace, map.TypeData.Type, new XmlSerializationReadCallback (info.ReadObject)); } } } } protected override void InitIDs () { } protected XmlTypeMapping GetTypeMap (Type type) { ArrayList maps = _typeMap.RelatedMaps; if (maps != null) { foreach (XmlTypeMapping map in maps) if (map.TypeData.Type == type) return map; } throw new InvalidOperationException ("Type " + type + " not mapped"); } public object ReadRoot () { Reader.MoveToContent(); if (_typeMap is XmlTypeMapping) { if (_format == SerializationFormat.Literal) return ReadRoot ((XmlTypeMapping)_typeMap); else return ReadEncodedObject ((XmlTypeMapping)_typeMap); } else return ReadMessage ((XmlMembersMapping)_typeMap); } object ReadEncodedObject (XmlTypeMapping typeMap) { object ob = null; Reader.MoveToContent(); if (Reader.NodeType == System.Xml.XmlNodeType.Element) { if (Reader.LocalName == typeMap.ElementName && Reader.NamespaceURI == typeMap.Namespace) ob = ReadReferencedElement(); else throw CreateUnknownNodeException(); } else UnknownNode(null); ReadReferencedElements(); return ob; } protected virtual object ReadMessage (XmlMembersMapping typeMap) { object[] parameters = new object[typeMap.Count]; if (typeMap.HasWrapperElement) { if (_format == SerializationFormat.Encoded) { while (Reader.NodeType == System.Xml.XmlNodeType.Element) { string root = Reader.GetAttribute ("root", XmlSerializer.EncodingNamespace); if (root == null || System.Xml.XmlConvert.ToBoolean(root)) break; ReadReferencedElement (); Reader.MoveToContent (); } } while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) { if (Reader.IsStartElement(XmlConvert.EncodeLocalName(typeMap.ElementName), typeMap.Namespace) || _format == SerializationFormat.Encoded) { if (Reader.IsEmptyElement) { Reader.Skip(); Reader.MoveToContent(); continue; } Reader.ReadStartElement(); ReadMembers ((ClassMap)typeMap.ObjectMap, parameters, true, false); ReadEndElement(); break; } else UnknownNode(null); Reader.MoveToContent(); } } else ReadMembers ((ClassMap)typeMap.ObjectMap, parameters, true, _format == SerializationFormat.Encoded); if (_format == SerializationFormat.Encoded) ReadReferencedElements(); return parameters; } object ReadRoot (XmlTypeMapping rootMap) { if (rootMap.TypeData.SchemaType == SchemaTypes.XmlNode) { return ReadXmlNodeElement (rootMap, true); } else { if (Reader.LocalName != rootMap.ElementName || Reader.NamespaceURI != rootMap.Namespace) throw CreateUnknownNodeException(); return ReadObject (rootMap, true, true); } } protected virtual object ReadObject (XmlTypeMapping typeMap, bool isNullable, bool checkType) { switch (typeMap.TypeData.SchemaType) { case SchemaTypes.Class: return ReadClassInstance (typeMap, isNullable, checkType); case SchemaTypes.Array: return ReadListElement (typeMap, isNullable, null, true); case SchemaTypes.XmlNode: return ReadXmlNodeElement (typeMap, isNullable); case SchemaTypes.Primitive: return ReadPrimitiveElement (typeMap, isNullable); case SchemaTypes.Enum: return ReadEnumElement (typeMap, isNullable); case SchemaTypes.XmlSerializable: return ReadXmlSerializableElement (typeMap, isNullable); default: throw new Exception ("Unsupported map type"); } } protected virtual object ReadClassInstance (XmlTypeMapping typeMap, bool isNullable, bool checkType) { if (isNullable && ReadNull()) return null; if (checkType) { System.Xml.XmlQualifiedName t = GetXsiType(); if (t != null) { XmlTypeMapping realMap = typeMap.GetRealElementMap (t.Name, t.Namespace); if (realMap == null) { if (typeMap.TypeData.Type == typeof(object)) return ReadTypedPrimitive (t); else throw CreateUnknownTypeException((System.Xml.XmlQualifiedName)t); } if (realMap != typeMap) return ReadObject (realMap, false, false); } else if (typeMap.TypeData.Type == typeof(object)) return ReadTypedPrimitive (AnyType); } object ob = Activator.CreateInstance (typeMap.TypeData.Type); Reader.MoveToElement(); bool isEmpty = Reader.IsEmptyElement; ReadClassInstanceMembers (typeMap, ob); if (isEmpty) Reader.Skip(); else ReadEndElement(); return ob; } protected virtual void ReadClassInstanceMembers (XmlTypeMapping typeMap, object ob) { ReadMembers ((ClassMap) typeMap.ObjectMap, ob, false, false); } void ReadMembers (ClassMap map, object ob, bool isValueList, bool readByOrder) { // Set the default values of the members if (map.MembersWithDefault != null) { ArrayList members = map.MembersWithDefault; for (int n=0; n