PageRenderTime 52ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs

https://bitbucket.org/foobar22/mono
C# | 911 lines | 764 code | 105 blank | 42 comment | 276 complexity | 26782a15b9f122c08794cf8ab745ff87 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Unlicense, Apache-2.0, LGPL-2.0
  1. //
  2. // XmlSerializationReaderInterpreter.cs:
  3. //
  4. // Author:
  5. // Lluis Sanchez Gual (lluis@ximian.com)
  6. //
  7. // (C) 2002, 2003 Ximian, Inc. http://www.ximian.com
  8. //
  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.
  28. //
  29. using System;
  30. using System.Reflection;
  31. using System.Collections;
  32. namespace System.Xml.Serialization
  33. {
  34. internal class XmlSerializationReaderInterpreter: XmlSerializationReader
  35. {
  36. XmlMapping _typeMap;
  37. SerializationFormat _format;
  38. static readonly XmlQualifiedName AnyType = new XmlQualifiedName("anyType", System.Xml.Schema.XmlSchema.Namespace);
  39. static readonly object [] empty_array = new object [0];
  40. public XmlSerializationReaderInterpreter(XmlMapping typeMap)
  41. {
  42. _typeMap = typeMap;
  43. _format = typeMap.Format;
  44. }
  45. protected override void InitCallbacks ()
  46. {
  47. ArrayList maps = _typeMap.RelatedMaps;
  48. if (maps != null)
  49. {
  50. foreach (XmlTypeMapping map in maps)
  51. {
  52. if (map.TypeData.SchemaType == SchemaTypes.Class || map.TypeData.SchemaType == SchemaTypes.Enum)
  53. {
  54. ReaderCallbackInfo info = new ReaderCallbackInfo (this, map);
  55. AddReadCallback (map.XmlType, map.Namespace, map.TypeData.Type, new XmlSerializationReadCallback (info.ReadObject));
  56. }
  57. }
  58. }
  59. }
  60. protected override void InitIDs ()
  61. {
  62. }
  63. protected XmlTypeMapping GetTypeMap (Type type)
  64. {
  65. ArrayList maps = _typeMap.RelatedMaps;
  66. if (maps != null)
  67. {
  68. foreach (XmlTypeMapping map in maps)
  69. if (map.TypeData.Type == type) return map;
  70. }
  71. throw new InvalidOperationException ("Type " + type + " not mapped");
  72. }
  73. public object ReadRoot ()
  74. {
  75. Reader.MoveToContent();
  76. if (_typeMap is XmlTypeMapping)
  77. {
  78. if (_format == SerializationFormat.Literal)
  79. return ReadRoot ((XmlTypeMapping)_typeMap);
  80. else
  81. return ReadEncodedObject ((XmlTypeMapping)_typeMap);
  82. }
  83. else
  84. return ReadMessage ((XmlMembersMapping)_typeMap);
  85. }
  86. object ReadEncodedObject (XmlTypeMapping typeMap)
  87. {
  88. #if MOONLIGHT
  89. throw new NotSupportedException ();
  90. #else
  91. object ob = null;
  92. Reader.MoveToContent();
  93. if (Reader.NodeType == System.Xml.XmlNodeType.Element)
  94. {
  95. if (Reader.LocalName == typeMap.ElementName && Reader.NamespaceURI == typeMap.Namespace)
  96. ob = ReadReferencedElement();
  97. else
  98. throw CreateUnknownNodeException();
  99. }
  100. else
  101. UnknownNode(null);
  102. ReadReferencedElements();
  103. return ob;
  104. #endif
  105. }
  106. protected virtual object ReadMessage (XmlMembersMapping typeMap)
  107. {
  108. #if MOONLIGHT
  109. throw new NotSupportedException ();
  110. #else
  111. object[] parameters = new object[typeMap.Count];
  112. if (typeMap.HasWrapperElement)
  113. {
  114. // bug #79988: out parameters need to be initialized if they
  115. // are value types
  116. ArrayList members = ((ClassMap) typeMap.ObjectMap).AllMembers;
  117. for (int n = 0; n < members.Count; n++) {
  118. XmlTypeMapMember mem = (XmlTypeMapMember) members [n];
  119. if (!mem.IsReturnValue && mem.TypeData.IsValueType)
  120. SetMemberValueFromAttr (mem, parameters, CreateInstance (
  121. mem.TypeData.Type), true);
  122. }
  123. if (_format == SerializationFormat.Encoded)
  124. {
  125. while (Reader.NodeType == System.Xml.XmlNodeType.Element)
  126. {
  127. string root = Reader.GetAttribute ("root", XmlSerializer.EncodingNamespace);
  128. if (root == null || System.Xml.XmlConvert.ToBoolean(root)) break;
  129. ReadReferencedElement ();
  130. Reader.MoveToContent ();
  131. }
  132. }
  133. while (Reader.NodeType != System.Xml.XmlNodeType.EndElement &&
  134. // it could be an empty root element
  135. Reader.ReadState == ReadState.Interactive)
  136. {
  137. if (Reader.IsStartElement(typeMap.ElementName, typeMap.Namespace)
  138. || _format == SerializationFormat.Encoded)
  139. {
  140. ReadAttributeMembers ((ClassMap)typeMap.ObjectMap, parameters, true);
  141. if (Reader.IsEmptyElement) {
  142. Reader.Skip();
  143. Reader.MoveToContent();
  144. continue;
  145. }
  146. Reader.ReadStartElement();
  147. ReadMembers ((ClassMap)typeMap.ObjectMap, parameters, true, false);
  148. ReadEndElement();
  149. break;
  150. }
  151. else
  152. UnknownNode(null);
  153. Reader.MoveToContent();
  154. }
  155. }
  156. else
  157. ReadMembers ((ClassMap)typeMap.ObjectMap, parameters, true, _format == SerializationFormat.Encoded);
  158. if (_format == SerializationFormat.Encoded)
  159. ReadReferencedElements();
  160. return parameters;
  161. #endif
  162. }
  163. object ReadRoot (XmlTypeMapping rootMap)
  164. {
  165. if (rootMap.TypeData.SchemaType == SchemaTypes.XmlNode)
  166. {
  167. return ReadXmlNodeElement (rootMap, true);
  168. }
  169. else
  170. {
  171. if (Reader.LocalName != rootMap.ElementName || Reader.NamespaceURI != rootMap.Namespace)
  172. throw CreateUnknownNodeException();
  173. return ReadObject (rootMap, rootMap.IsNullable, true);
  174. }
  175. }
  176. protected virtual object ReadObject (XmlTypeMapping typeMap, bool isNullable, bool checkType)
  177. {
  178. switch (typeMap.TypeData.SchemaType)
  179. {
  180. case SchemaTypes.Class: return ReadClassInstance (typeMap, isNullable, checkType);
  181. case SchemaTypes.Array: return ReadListElement (typeMap, isNullable, null, true);
  182. case SchemaTypes.XmlNode: return ReadXmlNodeElement (typeMap, isNullable);
  183. case SchemaTypes.Primitive: return ReadPrimitiveElement (typeMap, isNullable);
  184. case SchemaTypes.Enum: return ReadEnumElement (typeMap, isNullable);
  185. case SchemaTypes.XmlSerializable: return ReadXmlSerializableElement (typeMap, isNullable);
  186. default: throw new Exception ("Unsupported map type");
  187. }
  188. }
  189. protected virtual object ReadClassInstance (XmlTypeMapping typeMap, bool isNullable, bool checkType)
  190. {
  191. if (isNullable && ReadNull()) return null;
  192. if (checkType)
  193. {
  194. System.Xml.XmlQualifiedName t = GetXsiType();
  195. if (t != null)
  196. {
  197. XmlTypeMapping realMap = typeMap.GetRealElementMap (t.Name, t.Namespace);
  198. if (realMap == null) {
  199. if (typeMap.TypeData.Type == typeof(object))
  200. return ReadTypedPrimitive (t);
  201. else
  202. throw CreateUnknownTypeException((System.Xml.XmlQualifiedName)t);
  203. }
  204. if (realMap != typeMap)
  205. return ReadObject (realMap, false, false);
  206. }
  207. else if (typeMap.TypeData.Type == typeof(object))
  208. return ReadTypedPrimitive (AnyType);
  209. }
  210. object ob = CreateInstance (typeMap.TypeData.Type, true);
  211. Reader.MoveToElement();
  212. bool isEmpty = Reader.IsEmptyElement;
  213. ReadClassInstanceMembers (typeMap, ob);
  214. if (isEmpty) Reader.Skip();
  215. else ReadEndElement();
  216. return ob;
  217. }
  218. protected virtual void ReadClassInstanceMembers (XmlTypeMapping typeMap, object ob)
  219. {
  220. ReadMembers ((ClassMap) typeMap.ObjectMap, ob, false, false);
  221. }
  222. void ReadAttributeMembers (ClassMap map, object ob, bool isValueList)
  223. {
  224. XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
  225. int anyAttributeIndex = 0;
  226. object anyAttributeArray = null;
  227. while (Reader.MoveToNextAttribute())
  228. {
  229. XmlTypeMapMemberAttribute member = map.GetAttribute (Reader.LocalName, Reader.NamespaceURI);
  230. if (member != null)
  231. {
  232. SetMemberValue (member, ob, GetValueFromXmlString (Reader.Value, member.TypeData, member.MappedType), isValueList);
  233. }
  234. else if (IsXmlnsAttribute(Reader.Name))
  235. {
  236. // If the map has NamespaceDeclarations,
  237. // then store this xmlns to the given member.
  238. // If the instance doesn't exist, then create.
  239. if (map.NamespaceDeclarations != null) {
  240. XmlSerializerNamespaces nss = this.GetMemberValue (map.NamespaceDeclarations, ob, isValueList) as XmlSerializerNamespaces;
  241. if (nss == null) {
  242. nss = new XmlSerializerNamespaces ();
  243. SetMemberValue (map.NamespaceDeclarations, ob, nss, isValueList);
  244. }
  245. if (Reader.Prefix == "xmlns")
  246. nss.Add (Reader.LocalName, Reader.Value);
  247. else
  248. nss.Add ("", Reader.Value);
  249. }
  250. }
  251. #if !MOONLIGHT
  252. else if (anyAttrMember != null)
  253. {
  254. XmlAttribute attr = (XmlAttribute) Document.ReadNode(Reader);
  255. ParseWsdlArrayType (attr);
  256. AddListValue (anyAttrMember.TypeData, ref anyAttributeArray, anyAttributeIndex++, attr, true);
  257. }
  258. else
  259. ProcessUnknownAttribute(ob);
  260. #endif
  261. }
  262. #if !MOONLIGHT
  263. if (anyAttrMember != null)
  264. {
  265. anyAttributeArray = ShrinkArray ((Array)anyAttributeArray, anyAttributeIndex, anyAttrMember.TypeData.Type.GetElementType(), true);
  266. SetMemberValue (anyAttrMember, ob, anyAttributeArray, isValueList);
  267. }
  268. #endif
  269. Reader.MoveToElement ();
  270. }
  271. void ReadMembers (ClassMap map, object ob, bool isValueList, bool readBySoapOrder)
  272. {
  273. // Reads attributes
  274. ReadAttributeMembers (map, ob, isValueList);
  275. if (!isValueList)
  276. {
  277. Reader.MoveToElement();
  278. if (Reader.IsEmptyElement) {
  279. SetListMembersDefaults (map, ob, isValueList);
  280. return;
  281. }
  282. Reader.ReadStartElement();
  283. }
  284. // Reads elements
  285. bool[] readFlag = new bool[(map.ElementMembers != null) ? map.ElementMembers.Count : 0];
  286. bool hasAnyReturnMember = (isValueList && _format == SerializationFormat.Encoded && map.ReturnMember != null);
  287. Reader.MoveToContent();
  288. int[] indexes = null;
  289. object[] flatLists = null;
  290. object[] flatListsChoices = null;
  291. Fixup fixup = null;
  292. int ind = -1;
  293. int maxInd;
  294. if (readBySoapOrder) {
  295. if (map.ElementMembers != null) maxInd = map.ElementMembers.Count;
  296. else maxInd = -1;
  297. }
  298. else
  299. maxInd = int.MaxValue;
  300. if (map.FlatLists != null)
  301. {
  302. indexes = new int[map.FlatLists.Count];
  303. flatLists = new object[map.FlatLists.Count];
  304. foreach (XmlTypeMapMemberExpandable mem in map.FlatLists) {
  305. if (IsReadOnly (mem, mem.TypeData, ob, isValueList))
  306. flatLists [mem.FlatArrayIndex] = mem.GetValue (ob);
  307. else if (mem.TypeData.Type.IsArray) {
  308. flatLists [mem.FlatArrayIndex] = InitializeList (mem.TypeData);
  309. }
  310. else {
  311. object list = mem.GetValue (ob);
  312. if (list == null) {
  313. list = InitializeList (mem.TypeData);
  314. SetMemberValue (mem, ob, list, isValueList);
  315. }
  316. flatLists [mem.FlatArrayIndex] = list;
  317. }
  318. if (mem.ChoiceMember != null) {
  319. if (flatListsChoices == null)
  320. flatListsChoices = new object [map.FlatLists.Count];
  321. flatListsChoices [mem.FlatArrayIndex] = InitializeList (mem.ChoiceTypeData);
  322. }
  323. }
  324. }
  325. if (_format == SerializationFormat.Encoded && map.ElementMembers != null)
  326. {
  327. FixupCallbackInfo info = new FixupCallbackInfo (this, map, isValueList);
  328. fixup = new Fixup(ob, new XmlSerializationFixupCallback(info.FixupMembers), map.ElementMembers.Count);
  329. AddFixup (fixup);
  330. }
  331. XmlTypeMapMember previousMember = null;
  332. while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && (ind < maxInd - 1))
  333. {
  334. if (Reader.NodeType == System.Xml.XmlNodeType.Element)
  335. {
  336. XmlTypeMapElementInfo info;
  337. if (readBySoapOrder) {
  338. info = map.GetElement (Reader.LocalName, Reader.NamespaceURI, ind);
  339. }
  340. else if (hasAnyReturnMember) {
  341. info = (XmlTypeMapElementInfo) ((XmlTypeMapMemberElement)map.ReturnMember).ElementInfo[0];
  342. hasAnyReturnMember = false;
  343. }
  344. else {
  345. if (map.IsOrderDependentMap) {
  346. info = map.GetElement (Reader.LocalName, Reader.NamespaceURI, ind);
  347. }
  348. else
  349. info = map.GetElement (Reader.LocalName, Reader.NamespaceURI);
  350. }
  351. if (info != null && !readFlag[info.Member.Index] )
  352. {
  353. if (info.Member != previousMember)
  354. {
  355. ind = info.ExplicitOrder + 1;
  356. // If the member is a flat list don't increase the index, since the next element may
  357. // be another item of the list. This is a fix for Xamarin bug #9193.
  358. if (info.Member is XmlTypeMapMemberFlatList)
  359. ind--;
  360. previousMember = info.Member;
  361. }
  362. if (info.Member.GetType() == typeof (XmlTypeMapMemberList))
  363. {
  364. if (_format == SerializationFormat.Encoded && info.MultiReferenceType)
  365. {
  366. object list = ReadReferencingElement (out fixup.Ids[info.Member.Index]);
  367. if (fixup.Ids[info.Member.Index] == null) // Already read
  368. {
  369. if (IsReadOnly (info.Member, info.TypeData, ob, isValueList)) throw CreateReadOnlyCollectionException (info.TypeData.FullTypeName);
  370. else SetMemberValue (info.Member, ob, list, isValueList);
  371. }
  372. else if (!info.MappedType.TypeData.Type.IsArray)
  373. {
  374. if (IsReadOnly (info.Member, info.TypeData, ob, isValueList))
  375. list = GetMemberValue (info.Member, ob, isValueList);
  376. else {
  377. list = CreateList (info.MappedType.TypeData.Type);
  378. SetMemberValue (info.Member, ob, list, isValueList);
  379. }
  380. AddFixup (new CollectionFixup (list, new XmlSerializationCollectionFixupCallback (FillList), fixup.Ids[info.Member.Index]));
  381. fixup.Ids[info.Member.Index] = null; // The member already has the value, no further fix needed.
  382. }
  383. }
  384. else
  385. {
  386. if (IsReadOnly (info.Member, info.TypeData, ob, isValueList)) {
  387. ReadListElement (info.MappedType, info.IsNullable, GetMemberValue (info.Member, ob, isValueList), false);
  388. } else if (info.MappedType.TypeData.Type.IsArray) {
  389. object list = ReadListElement (info.MappedType, info.IsNullable, null, true);
  390. if (list != null || info.IsNullable)
  391. SetMemberValue (info.Member, ob, list, isValueList);
  392. } else {
  393. // If the member already has a list, reuse that list. No need to create a new one.
  394. object list = GetMemberValue (info.Member, ob, isValueList);
  395. if (list == null) {
  396. list = CreateList (info.MappedType.TypeData.Type);
  397. SetMemberValue (info.Member, ob, list, isValueList);
  398. }
  399. ReadListElement (info.MappedType, info.IsNullable, list, true);
  400. }
  401. }
  402. readFlag[info.Member.Index] = true;
  403. }
  404. else if (info.Member.GetType() == typeof (XmlTypeMapMemberFlatList))
  405. {
  406. XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
  407. AddListValue (mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, ReadObjectElement (info), !IsReadOnly (info.Member, info.TypeData, ob, isValueList));
  408. if (mem.ChoiceMember != null) {
  409. AddListValue (mem.ChoiceTypeData, ref flatListsChoices [mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]-1, info.ChoiceValue, true);
  410. }
  411. }
  412. else if (info.Member.GetType() == typeof (XmlTypeMapMemberAnyElement))
  413. {
  414. XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement)info.Member;
  415. if (mem.TypeData.IsListType) AddListValue (mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, ReadXmlNode (mem.TypeData.ListItemTypeData, false), true);
  416. else SetMemberValue (mem, ob, ReadXmlNode (mem.TypeData, false), isValueList);
  417. }
  418. else if (info.Member.GetType() == typeof(XmlTypeMapMemberElement))
  419. {
  420. object val;
  421. readFlag[info.Member.Index] = true;
  422. if (_format == SerializationFormat.Encoded)
  423. {
  424. if (info.Member.TypeData.SchemaType != SchemaTypes.Primitive)
  425. val = ReadReferencingElement (out fixup.Ids[info.Member.Index]);
  426. else
  427. val = ReadReferencingElement (info.Member.TypeData.XmlType, System.Xml.Schema.XmlSchema.Namespace, out fixup.Ids[info.Member.Index]);
  428. if (info.MultiReferenceType) {
  429. if (fixup.Ids[info.Member.Index] == null) // already read
  430. SetMemberValue (info.Member, ob, val, isValueList);
  431. }
  432. else if (val != null)
  433. SetMemberValue (info.Member, ob, val, isValueList);
  434. }
  435. else {
  436. SetMemberValue (info.Member, ob, ReadObjectElement (info), isValueList);
  437. if (info.ChoiceValue != null) {
  438. XmlTypeMapMemberElement imem = (XmlTypeMapMemberElement) info.Member;
  439. imem.SetChoice (ob, info.ChoiceValue);
  440. }
  441. }
  442. }
  443. else
  444. throw new InvalidOperationException ("Unknown member type");
  445. }
  446. else if (map.DefaultAnyElementMember != null)
  447. {
  448. XmlTypeMapMemberAnyElement mem = map.DefaultAnyElementMember;
  449. if (mem.TypeData.IsListType) AddListValue (mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, ReadXmlNode (mem.TypeData.ListItemTypeData, false), true);
  450. else SetMemberValue (mem, ob, ReadXmlNode (mem.TypeData, false), isValueList);
  451. }
  452. else
  453. ProcessUnknownElement(ob);
  454. }
  455. else if ((Reader.NodeType == System.Xml.XmlNodeType.Text || Reader.NodeType == System.Xml.XmlNodeType.CDATA) && map.XmlTextCollector != null)
  456. {
  457. if (map.XmlTextCollector is XmlTypeMapMemberExpandable)
  458. {
  459. XmlTypeMapMemberExpandable mem = (XmlTypeMapMemberExpandable)map.XmlTextCollector;
  460. XmlTypeMapMemberFlatList flatl = mem as XmlTypeMapMemberFlatList;
  461. TypeData itype = (flatl == null) ? mem.TypeData.ListItemTypeData : flatl.ListMap.FindTextElement().TypeData;
  462. object val = (itype.Type == typeof (string)) ? (object) Reader.ReadString() : (object) ReadXmlNode (itype, false);
  463. AddListValue (mem.TypeData, ref flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex]++, val, true);
  464. }
  465. else
  466. {
  467. XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement) map.XmlTextCollector;
  468. XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) mem.ElementInfo [0];
  469. if (info.TypeData.Type == typeof (string))
  470. SetMemberValue (mem, ob, ReadString ((string) GetMemberValue (mem, ob, isValueList)), isValueList);
  471. else
  472. SetMemberValue (mem, ob, GetValueFromXmlString (Reader.ReadString(), info.TypeData, info.MappedType), isValueList);
  473. }
  474. }
  475. #if !MOONLIGHT
  476. else
  477. UnknownNode(ob);
  478. #endif
  479. Reader.MoveToContent();
  480. }
  481. if (flatLists != null)
  482. {
  483. foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
  484. {
  485. Object list = flatLists[mem.FlatArrayIndex];
  486. if (mem.TypeData.Type.IsArray)
  487. list = ShrinkArray ((Array)list, indexes[mem.FlatArrayIndex], mem.TypeData.Type.GetElementType(), true);
  488. if (!IsReadOnly (mem, mem.TypeData, ob, isValueList) && mem.TypeData.Type.IsArray)
  489. SetMemberValue (mem, ob, list, isValueList);
  490. }
  491. }
  492. if (flatListsChoices != null)
  493. {
  494. foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
  495. {
  496. Object list = flatListsChoices[mem.FlatArrayIndex];
  497. if (list == null) continue;
  498. list = ShrinkArray ((Array)list, indexes[mem.FlatArrayIndex], mem.ChoiceTypeData.Type.GetElementType(), true);
  499. XmlTypeMapMember.SetValue (ob, mem.ChoiceMember, list);
  500. }
  501. }
  502. SetListMembersDefaults (map, ob, isValueList);
  503. }
  504. void SetListMembersDefaults (ClassMap map, object ob, bool isValueList)
  505. {
  506. if (map.ListMembers != null)
  507. {
  508. ArrayList members = map.ListMembers;
  509. for (int n=0; n<members.Count; n++) {
  510. XmlTypeMapMember mem = (XmlTypeMapMember) members[n];
  511. if (IsReadOnly (mem, mem.TypeData, ob, isValueList))
  512. continue;
  513. if (GetMemberValue (mem, ob, isValueList) == null)
  514. SetMemberValue (mem, ob, InitializeList (mem.TypeData), isValueList);
  515. }
  516. }
  517. }
  518. internal void FixupMembers (ClassMap map, object obfixup, bool isValueList)
  519. {
  520. Fixup fixup = (Fixup)obfixup;
  521. ICollection members = map.ElementMembers;
  522. string[] ids = fixup.Ids;
  523. foreach (XmlTypeMapMember member in members)
  524. {
  525. if (ids[member.Index] != null)
  526. SetMemberValue (member, fixup.Source, GetTarget(ids[member.Index]), isValueList);
  527. }
  528. }
  529. protected virtual void ProcessUnknownAttribute (object target)
  530. {
  531. UnknownNode (target);
  532. }
  533. protected virtual void ProcessUnknownElement (object target)
  534. {
  535. UnknownNode (target);
  536. }
  537. bool IsReadOnly (XmlTypeMapMember member, TypeData memType, object ob, bool isValueList)
  538. {
  539. if (isValueList) return !memType.HasPublicConstructor;
  540. else return member.IsReadOnly (ob.GetType()) || !memType.HasPublicConstructor;
  541. }
  542. void SetMemberValue (XmlTypeMapMember member, object ob, object value, bool isValueList)
  543. {
  544. if (isValueList)
  545. ((object[])ob)[member.GlobalIndex] = value;
  546. else
  547. member.SetValue (ob, value);
  548. if (member.IsOptionalValueType)
  549. member.SetValueSpecified (ob, true);
  550. }
  551. void SetMemberValueFromAttr (XmlTypeMapMember member, object ob, object value, bool isValueList)
  552. {
  553. // Enumeration values specified in custom attributes are stored as integer
  554. // values if the custom attribute property is of type object. So, it is
  555. // necessary to convert to the enum type before asigning the value to the field.
  556. if (member.TypeData.Type.IsEnum)
  557. value = Enum.ToObject (member.TypeData.Type, value);
  558. SetMemberValue (member, ob, value, isValueList);
  559. }
  560. object GetMemberValue (XmlTypeMapMember member, object ob, bool isValueList)
  561. {
  562. if (isValueList) return ((object[])ob)[member.GlobalIndex];
  563. else return member.GetValue (ob);
  564. }
  565. object ReadObjectElement (XmlTypeMapElementInfo elem)
  566. {
  567. switch (elem.TypeData.SchemaType)
  568. {
  569. case SchemaTypes.XmlNode:
  570. return ReadXmlNode (elem.TypeData, true);
  571. case SchemaTypes.Primitive:
  572. case SchemaTypes.Enum:
  573. return ReadPrimitiveValue (elem);
  574. case SchemaTypes.Array:
  575. return ReadListElement (elem.MappedType, elem.IsNullable, null, true);
  576. case SchemaTypes.Class:
  577. return ReadObject (elem.MappedType, elem.IsNullable, true);
  578. case SchemaTypes.XmlSerializable:
  579. object ob = CreateInstance (elem.TypeData.Type, true);
  580. return ReadSerializable ((IXmlSerializable)ob);
  581. default:
  582. throw new NotSupportedException ("Invalid value type");
  583. }
  584. }
  585. object ReadPrimitiveValue (XmlTypeMapElementInfo elem)
  586. {
  587. if (elem.TypeData.Type == typeof (XmlQualifiedName)) {
  588. if (elem.IsNullable) return ReadNullableQualifiedName ();
  589. else return ReadElementQualifiedName ();
  590. }
  591. else if (elem.IsNullable)
  592. return GetValueFromXmlString (ReadNullableString (), elem.TypeData, elem.MappedType);
  593. else
  594. return GetValueFromXmlString (Reader.ReadElementString (), elem.TypeData, elem.MappedType);
  595. }
  596. object GetValueFromXmlString (string value, TypeData typeData, XmlTypeMapping typeMap)
  597. {
  598. if (typeData.SchemaType == SchemaTypes.Array)
  599. return ReadListString (typeMap, value);
  600. else if (typeData.SchemaType == SchemaTypes.Enum)
  601. return GetEnumValue (typeMap, value);
  602. else if (typeData.Type == typeof (XmlQualifiedName))
  603. return ToXmlQualifiedName (value);
  604. else
  605. return XmlCustomFormatter.FromXmlString (typeData, value);
  606. }
  607. object ReadListElement (XmlTypeMapping typeMap, bool isNullable, object list, bool canCreateInstance)
  608. {
  609. Type listType = typeMap.TypeData.Type;
  610. ListMap listMap = (ListMap)typeMap.ObjectMap;
  611. if (listType.IsArray && ReadNull()) return null;
  612. if (list == null) {
  613. if (canCreateInstance && typeMap.TypeData.HasPublicConstructor) list = CreateList (listType);
  614. else throw CreateReadOnlyCollectionException (typeMap.TypeFullName);
  615. }
  616. if (Reader.IsEmptyElement) {
  617. Reader.Skip();
  618. if (listType.IsArray)
  619. list = ShrinkArray ((Array)list, 0, listType.GetElementType(), false);
  620. return list;
  621. }
  622. int index = 0;
  623. Reader.ReadStartElement();
  624. Reader.MoveToContent();
  625. while (Reader.NodeType != System.Xml.XmlNodeType.EndElement)
  626. {
  627. if (Reader.NodeType == System.Xml.XmlNodeType.Element)
  628. {
  629. XmlTypeMapElementInfo elemInfo = listMap.FindElement (Reader.LocalName, Reader.NamespaceURI);
  630. if (elemInfo != null)
  631. AddListValue (typeMap.TypeData, ref list, index++, ReadObjectElement (elemInfo), false);
  632. else
  633. UnknownNode(null);
  634. }
  635. else
  636. UnknownNode(null);
  637. Reader.MoveToContent();
  638. }
  639. ReadEndElement();
  640. if (listType.IsArray)
  641. list = ShrinkArray ((Array)list, index, listType.GetElementType(), false);
  642. return list;
  643. }
  644. object ReadListString (XmlTypeMapping typeMap, string values)
  645. {
  646. Type listType = typeMap.TypeData.Type;
  647. ListMap listMap = (ListMap)typeMap.ObjectMap;
  648. values = values.Trim ();
  649. if (values == string.Empty)
  650. {
  651. return Array.CreateInstance (listType.GetElementType(), 0);
  652. }
  653. string[] valueArray = values.Split (' ');
  654. Array list = Array.CreateInstance (listType.GetElementType(), valueArray.Length);
  655. XmlTypeMapElementInfo info = (XmlTypeMapElementInfo)listMap.ItemInfo[0];
  656. for (int index = 0; index < valueArray.Length; index++)
  657. list.SetValue (GetValueFromXmlString (valueArray[index], info.TypeData, info.MappedType), index);
  658. return list;
  659. }
  660. void AddListValue (TypeData listType, ref object list, int index, object value, bool canCreateInstance)
  661. {
  662. Type type = listType.Type;
  663. if (type.IsArray)
  664. {
  665. list = EnsureArrayIndex ((Array)list, index, type.GetElementType());
  666. ((Array)list).SetValue (value, index);
  667. }
  668. else // Must be IEnumerable
  669. {
  670. if (list == null) {
  671. if (canCreateInstance) list = CreateInstance (type, true);
  672. else throw CreateReadOnlyCollectionException (type.FullName);
  673. }
  674. MethodInfo mi = type.GetMethod ("Add", new Type[] {listType.ListItemType} );
  675. mi.Invoke (list, new object[] { value });
  676. }
  677. }
  678. static object CreateInstance (Type type, bool nonPublic)
  679. {
  680. #if MOONLIGHT
  681. return Activator.CreateInstance (type); // always false
  682. #else
  683. return Activator.CreateInstance (type, nonPublic);
  684. #endif
  685. }
  686. object CreateInstance (Type type)
  687. {
  688. return Activator.CreateInstance (type, empty_array);
  689. }
  690. object CreateList (Type listType)
  691. {
  692. if (listType.IsArray)
  693. return EnsureArrayIndex (null, 0, listType.GetElementType());
  694. else
  695. return CreateInstance (listType, true);
  696. }
  697. object InitializeList (TypeData listType)
  698. {
  699. if (listType.Type.IsArray)
  700. return null;
  701. else
  702. return CreateInstance (listType.Type, true);
  703. }
  704. void FillList (object list, object items)
  705. {
  706. CopyEnumerableList (items, list);
  707. }
  708. void CopyEnumerableList (object source, object dest)
  709. {
  710. if (dest == null) throw CreateReadOnlyCollectionException (source.GetType().FullName);
  711. object[] param = new object[1];
  712. MethodInfo mi = dest.GetType().GetMethod ("Add");
  713. foreach (object ob in (IEnumerable)source)
  714. {
  715. param[0] = ob;
  716. mi.Invoke (dest, param);
  717. }
  718. }
  719. object ReadXmlNodeElement (XmlTypeMapping typeMap, bool isNullable)
  720. {
  721. return ReadXmlNode (typeMap.TypeData, false);
  722. }
  723. object ReadXmlNode (TypeData type, bool wrapped)
  724. {
  725. #if MOONLIGHT
  726. throw new NotSupportedException ();
  727. #else
  728. if (type.Type == typeof (XmlDocument))
  729. return ReadXmlDocument (wrapped);
  730. else
  731. return ReadXmlNode (wrapped);
  732. #endif
  733. }
  734. object ReadPrimitiveElement (XmlTypeMapping typeMap, bool isNullable)
  735. {
  736. XmlQualifiedName t = GetXsiType();
  737. if (t == null) t = new XmlQualifiedName (typeMap.XmlType, typeMap.Namespace);
  738. return ReadTypedPrimitive (t);
  739. }
  740. object ReadEnumElement (XmlTypeMapping typeMap, bool isNullable)
  741. {
  742. Reader.ReadStartElement ();
  743. object o = GetEnumValue (typeMap, Reader.ReadString());
  744. ReadEndElement ();
  745. return o;
  746. }
  747. object GetEnumValue (XmlTypeMapping typeMap, string val)
  748. {
  749. if (val == null)
  750. return null;
  751. EnumMap map = (EnumMap) typeMap.ObjectMap;
  752. string ev = map.GetEnumName (typeMap.TypeFullName, val);
  753. if (ev == null) throw CreateUnknownConstantException (val, typeMap.TypeData.Type);
  754. return Enum.Parse (typeMap.TypeData.Type, ev, false);
  755. }
  756. object ReadXmlSerializableElement (XmlTypeMapping typeMap, bool isNullable)
  757. {
  758. Reader.MoveToContent ();
  759. if (Reader.NodeType == XmlNodeType.Element)
  760. {
  761. if (Reader.LocalName == typeMap.ElementName && Reader.NamespaceURI == typeMap.Namespace)
  762. {
  763. object ob = CreateInstance (typeMap.TypeData.Type, true);
  764. return ReadSerializable ((IXmlSerializable)ob);
  765. }
  766. else
  767. throw CreateUnknownNodeException ();
  768. }
  769. else
  770. {
  771. UnknownNode (null);
  772. return null;
  773. }
  774. }
  775. class FixupCallbackInfo
  776. {
  777. XmlSerializationReaderInterpreter _sri;
  778. ClassMap _map;
  779. bool _isValueList;
  780. public FixupCallbackInfo (XmlSerializationReaderInterpreter sri, ClassMap map, bool isValueList)
  781. {
  782. _sri = sri;
  783. _map = map;
  784. _isValueList = isValueList;
  785. }
  786. public void FixupMembers (object fixup)
  787. {
  788. _sri.FixupMembers (_map, fixup, _isValueList);
  789. }
  790. }
  791. class ReaderCallbackInfo
  792. {
  793. XmlSerializationReaderInterpreter _sri;
  794. XmlTypeMapping _typeMap;
  795. public ReaderCallbackInfo (XmlSerializationReaderInterpreter sri, XmlTypeMapping typeMap)
  796. {
  797. _sri = sri;
  798. _typeMap = typeMap;
  799. }
  800. internal object ReadObject ()
  801. {
  802. return _sri.ReadObject (_typeMap, true, true);
  803. }
  804. }
  805. }
  806. }