* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlSerializationReader.cs
1 //
2 // System.Xml.Serialization.XmlSerializationReader.cs
3 //
4 // Authors:
5 //      Tim Coleman (tim@timcoleman.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //  Lluis Sanchez Gual (lluis@ximian.com)
8 //
9 // Copyright (C) Tim Coleman, 2002
10 // (c) 2002 Ximian, Inc. (http://www.ximian.com)
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System;
35 using System.Collections;
36 using System.Globalization;
37 using System.Xml;
38 using System.Xml.Schema;
39 using System.Reflection;
40
41 namespace System.Xml.Serialization 
42 {
43         public abstract class XmlSerializationReader 
44 #if NET_2_0
45                 : XmlSerializationGeneratedCode
46 #endif
47         {
48
49                 #region Fields
50
51                 XmlDocument document;
52                 XmlReader reader;
53                 ArrayList fixups;
54                 Hashtable collFixups;
55                 ArrayList collItemFixups;
56                 Hashtable typesCallbacks;
57                 ArrayList noIDTargets;
58                 Hashtable targets;
59                 Hashtable delayedListFixups;
60                 XmlSerializer eventSource;
61                 int delayedFixupId = 0;
62                 Hashtable referencedObjects;
63
64                 string w3SchemaNS;
65                 string w3InstanceNS;
66                 string w3InstanceNS2000;
67                 string w3InstanceNS1999;
68                 string soapNS;
69                 string wsdlNS;
70                 string nullX;
71                 string nil;
72                 string typeX;
73                 string arrayType;
74                 XmlQualifiedName arrayQName;
75                 #endregion
76
77                 internal void Initialize (XmlReader reader, XmlSerializer eventSource)
78                 {
79                         w3SchemaNS = reader.NameTable.Add (XmlSchema.Namespace);
80                         w3InstanceNS = reader.NameTable.Add (XmlSchema.InstanceNamespace);
81                         w3InstanceNS2000 = reader.NameTable.Add ("http://www.w3.org/2000/10/XMLSchema-instance");
82                         w3InstanceNS1999 = reader.NameTable.Add ("http://www.w3.org/1999/XMLSchema-instance");
83                         soapNS = reader.NameTable.Add (XmlSerializer.EncodingNamespace);
84                         wsdlNS = reader.NameTable.Add (XmlSerializer.WsdlNamespace);
85                         nullX = reader.NameTable.Add ("null");
86                         nil = reader.NameTable.Add ("nil");
87                         typeX = reader.NameTable.Add ("type");
88                         arrayType = reader.NameTable.Add ("arrayType");
89                         this.reader = reader;
90                         this.eventSource = eventSource;
91                         arrayQName = new XmlQualifiedName ("Array", soapNS);
92                         InitIDs ();
93                 }
94                         
95                 private ArrayList EnsureArrayList (ArrayList list)
96                 {
97                         if (list == null)
98                                 list = new ArrayList ();
99                         return list;
100                 }
101                 
102                 private Hashtable EnsureHashtable (Hashtable hash)
103                 {
104                         if (hash == null)
105                                 hash = new Hashtable ();
106                         return hash;
107                 }
108                 
109                 protected XmlSerializationReader ()
110                 {
111                 }
112
113                 protected XmlDocument Document
114                 {
115                         get {
116                                 if (document == null)
117                                         document = new XmlDocument (reader.NameTable);
118
119                                 return document;
120                         }
121                 }
122
123                 protected XmlReader Reader {
124                         get { return reader; }
125                 }
126
127                 [MonoTODO]
128                 protected bool IsReturnValue
129                 {
130                         get {
131                                 throw new NotImplementedException ();
132                         }
133                         set {
134                                 throw new NotImplementedException ();
135                         }
136
137                 }
138
139
140                 #region Methods
141
142                 protected void AddFixup (CollectionFixup fixup)
143                 {
144                         collFixups = EnsureHashtable (collFixups);
145                         collFixups [fixup.Id] = fixup;
146
147                         if (delayedListFixups != null && delayedListFixups.ContainsKey (fixup.Id)) {
148                                 fixup.CollectionItems = delayedListFixups [fixup.Id];
149                                 delayedListFixups.Remove (fixup.Id);
150                         }
151                 }
152
153                 protected void AddFixup (Fixup fixup)
154                 {
155                         fixups = EnsureArrayList (fixups);
156                         fixups.Add (fixup);
157                 }
158
159                 void AddFixup (CollectionItemFixup fixup)
160                 {
161                         collItemFixups = EnsureArrayList (collItemFixups);
162                         collItemFixups.Add(fixup);
163                 }
164
165                 protected void AddReadCallback (string name, string ns, Type type, XmlSerializationReadCallback read)
166                 {
167                         WriteCallbackInfo info = new WriteCallbackInfo ();
168                         info.Type = type;
169                         info.TypeName = name;
170                         info.TypeNs = ns;
171                         info.Callback = read;
172                         typesCallbacks = EnsureHashtable (typesCallbacks);
173                         typesCallbacks.Add (new XmlQualifiedName (name, ns), info);
174                 }
175
176                 protected void AddTarget (string id, object o)
177                 {
178                         if (id != null) {
179                                 targets = EnsureHashtable (targets);
180                                 if (targets [id] == null)
181                                         targets.Add (id, o);
182                         } else {
183                                 if (o != null)
184                                         return;
185                                 noIDTargets = EnsureArrayList (noIDTargets);
186                                 noIDTargets.Add (o);
187                         }
188                 }
189
190                 private string CurrentTag ()
191                 {
192                         switch (reader.NodeType) {
193                         case XmlNodeType.Element:
194                                 return String.Format ("<{0} xmlns='{1}'>", reader.LocalName,
195                                                                            reader.NamespaceURI);
196                         case XmlNodeType.Attribute:
197                                 return reader.Value;
198                         case XmlNodeType.Text:
199                                 return "CDATA";
200                         case XmlNodeType.ProcessingInstruction:
201                                 return "<--";
202                         case XmlNodeType.Entity:
203                                 return "<?";
204                         case XmlNodeType.EndElement:
205                                 return ">";
206                         default:
207                                 return "(unknown)";
208                         }
209                 }
210
211                 protected Exception CreateCtorHasSecurityException (string typeName)
212                 {
213                         string message = string.Format ("The type '{0}' cannot"
214                                 + " be serialized because its parameterless"
215                                 + " constructor is decorated with declarative"
216                                 + " security permission attributes."
217                                 + " Consider using imperative asserts or demands"
218                                 + " in the constructor.", typeName);
219                         return new InvalidOperationException (message);
220                 }
221
222                 protected Exception CreateInaccessibleConstructorException (string typeName)
223                 {
224                         string message = string.Format ("{0} cannot be serialized"
225                                 + " because it does not have a default public"
226                                 + " constructor.", typeName);
227                         return new InvalidOperationException (message);
228                 }
229
230                 protected Exception CreateAbstractTypeException (string name, string ns)
231                 {
232                         string message = "The specified type is abstrace: name='" + name + "' namespace='" + ns + "', at " + CurrentTag ();
233                         return new InvalidOperationException (message);
234                 }
235
236                 protected Exception CreateInvalidCastException (Type type, object value)
237                 {
238                         string message = String.Format (CultureInfo.InvariantCulture, "Cannot assign object of type {0} to an object of " +
239                                                         "type {1}.", value.GetType (), type);
240                         return new InvalidCastException (message);
241                 }
242
243                 protected Exception CreateReadOnlyCollectionException (string name)
244                 {
245                         string message = String.Format ("Could not serialize {0}. Default constructors are " +
246                                                         "required for collections and enumerators.", name);
247                         return new InvalidOperationException (message);
248                 }
249
250                 protected Exception CreateUnknownConstantException (string value, Type enumType)
251                 {
252                         string message = String.Format ("'{0}' is not a valid value for {1}.", value, enumType);
253                         return new InvalidOperationException (message);
254                 }
255
256                 protected Exception CreateUnknownNodeException ()
257                 {
258                         string message = CurrentTag () + " was not expected";
259                         return new InvalidOperationException (message);
260                 }
261
262                 protected Exception CreateUnknownTypeException (XmlQualifiedName type)
263                 {
264                         string message = "The specified type was not recognized: name='" + type.Name + "' namespace='" + type.Namespace + "', at " + CurrentTag ();
265                         return new InvalidOperationException (message);
266                 }
267
268                 protected Array EnsureArrayIndex (Array a, int index, Type elementType)
269                 {
270                         if (a != null && index < a.Length)
271                                 return a;
272
273                         int size;
274                         if (a == null) {
275                                 size = 32;
276                         } else {
277                                 size = a.Length * 2;
278                         }
279
280                         Array result = Array.CreateInstance (elementType, size);
281                         if (a != null)
282                                 Array.Copy (a, result, index);
283
284                         return result;
285                 }
286
287                 [MonoTODO ("Implement")]
288                 protected void FixupArrayRefs (object fixup)
289                 {
290                         throw new NotImplementedException ();
291                 }
292
293                 [MonoTODO ("Implement")]
294                 protected int GetArrayLength (string name, string ns)
295                 {
296                         throw new NotImplementedException ();
297                 }
298
299                 protected bool GetNullAttr ()
300                 {
301                         string na = reader.GetAttribute (nullX, w3InstanceNS);
302                         if (na == null) {
303                                 na = reader.GetAttribute (nil, w3InstanceNS);
304                                 if (na == null) {
305                                         na = reader.GetAttribute (nullX, w3InstanceNS2000);
306                                         if (na == null)
307                                                 na = reader.GetAttribute (nullX, w3InstanceNS1999);
308                                 }
309                         }
310                         return (na != null);
311                 }
312
313                 protected object GetTarget (string id)
314                 {
315                         if (targets == null) return null;
316                         object ob = targets [id];
317                         if (ob != null) {
318                                 if (referencedObjects == null) referencedObjects = new Hashtable ();
319                                 referencedObjects [ob] = ob;
320                         }
321                         return ob;
322                 }
323
324                 bool TargetReady (string id)
325                 {
326                         if (targets == null) return false;
327                         return targets.ContainsKey (id);
328                 }
329
330                 protected XmlQualifiedName GetXsiType ()
331                 {
332                         string typeName = Reader.GetAttribute (typeX, XmlSchema.InstanceNamespace);
333                         
334                         if (typeName == string.Empty || typeName == null) {
335                                 typeName = Reader.GetAttribute (typeX, w3InstanceNS1999);
336                                 if (typeName == string.Empty || typeName == null) {
337                                         typeName = Reader.GetAttribute (typeX, w3InstanceNS2000);
338                                         if (typeName == string.Empty || typeName == null)
339                                                 return null;
340                                 }
341                         }
342                         
343                         int i = typeName.IndexOf (":");
344                         if (i == -1) return new XmlQualifiedName (typeName, Reader.NamespaceURI);
345                         else 
346                         {
347                                 string prefix = typeName.Substring(0,i);
348                                 string name = typeName.Substring (i+1);
349                                 return new XmlQualifiedName (name, Reader.LookupNamespace (prefix));
350                         }
351                 }
352
353                 protected abstract void InitCallbacks ();
354                 protected abstract void InitIDs ();
355
356                 protected bool IsXmlnsAttribute (string name)
357                 {
358                         int length = name.Length;
359                         if (length < 5)
360                                 return false;
361
362                         if (length == 5)
363                                 return (name == "xmlns");
364
365                         return name.StartsWith ("xmlns:");
366                 }
367
368                 protected void ParseWsdlArrayType (XmlAttribute attr)
369                 {
370                         if (attr.NamespaceURI == wsdlNS && attr.LocalName == arrayType)
371                         {
372                                 string ns = "", type, dimensions;
373                                 TypeTranslator.ParseArrayType (attr.Value, out type, out ns, out dimensions);
374                                 if (ns != "") ns = Reader.LookupNamespace (ns) + ":";
375                                 attr.Value = ns + type + dimensions;
376                         }
377                 }
378
379                 protected XmlQualifiedName ReadElementQualifiedName ()
380                 {
381                         if (reader.IsEmptyElement) {
382                                 reader.Skip();
383                                 return ToXmlQualifiedName (String.Empty);
384                         }
385
386                         reader.ReadStartElement ();
387                         XmlQualifiedName xqn = ToXmlQualifiedName(reader.ReadString ());
388                         reader.ReadEndElement ();
389                         return xqn;
390                 }
391
392                 protected void ReadEndElement ()
393                 {
394                         while (reader.NodeType == XmlNodeType.Whitespace)
395                                 reader.Skip ();
396
397                         if (reader.NodeType != XmlNodeType.None) {
398                                 reader.ReadEndElement ();
399                         } else {
400                                 reader.Skip ();
401                         }
402                 }
403
404                 protected bool ReadNull ()
405                 {
406                         if (!GetNullAttr ())
407                                 return false;
408
409                         if (reader.IsEmptyElement) {
410                                 reader.Skip();
411                                 return true;
412                         }
413
414                         reader.ReadStartElement();
415                         while (reader.NodeType != XmlNodeType.EndElement)
416                                 UnknownNode (null);
417
418                         ReadEndElement ();
419                         return true;
420                 }
421
422                 protected XmlQualifiedName ReadNullableQualifiedName ()
423                 {
424                         if (ReadNull ())
425                                 return null;
426
427                         return ReadElementQualifiedName ();
428                 }
429
430                 protected string ReadNullableString ()
431                 {
432                         if (ReadNull ())
433                                 return null;
434
435                         return reader.ReadElementString ();
436                 }
437
438                 protected bool ReadReference (out string fixupReference)
439                 {
440                         string href = reader.GetAttribute ("href");
441                         if (href == null) {
442                                 fixupReference = null;
443                                 return false;
444                         }
445
446                         if (href [0] != '#')
447                                 throw new InvalidOperationException("href not found: " + href);
448
449                         fixupReference = href.Substring (1);
450                         if (!reader.IsEmptyElement) {
451                                 reader.ReadStartElement ();
452                                 ReadEndElement ();
453                         } else {
454                                 reader.Skip ();
455                         }
456                         return true;
457                 }
458
459                 protected object ReadReferencedElement ()
460                 {
461                         return ReadReferencedElement (Reader.LocalName, Reader.NamespaceURI);
462                 }
463
464                 WriteCallbackInfo GetCallbackInfo (XmlQualifiedName qname)
465                 {
466                         if (typesCallbacks == null) 
467                         {
468                                 typesCallbacks = new Hashtable ();
469                                 InitCallbacks ();
470                         }
471                         return (WriteCallbackInfo) typesCallbacks[qname];
472                 }
473
474                 protected object ReadReferencedElement (string name, string ns)
475                 {
476                         XmlQualifiedName qname = GetXsiType ();
477                         if (qname == null) qname = new XmlQualifiedName (name, ns);
478
479                         string id = Reader.GetAttribute ("id");
480                         object ob;
481
482                         if (qname == arrayQName)
483                         {
484                                 CollectionFixup fixup = (collFixups != null) ? (CollectionFixup) collFixups[id] : null;
485                                 if (ReadList (out ob))
486                                 {
487                                         // List complete (does not contain references)
488                                         if (fixup != null)
489                                         {
490                                                 fixup.Callback (fixup.Collection, ob);
491                                                 collFixups.Remove (id);
492                                                 ob = fixup.Collection;
493                                         }
494                                 }
495                                 else if (fixup != null) 
496                                 {
497                                         fixup.CollectionItems = (object[])ob;
498                                         ob = fixup.Collection;
499                                 }
500                         }
501                         else
502                         {
503                                 WriteCallbackInfo info = GetCallbackInfo (qname);
504                                 if (info == null)
505                                         ob = ReadTypedPrimitive (qname, id != null);
506                                 else
507                                         ob = info.Callback();
508                         }
509                         AddTarget (id, ob);
510                         return ob;
511                 }
512                 
513                 bool ReadList (out object resultList)
514                 {
515                         string arrayTypeAttr = Reader.GetAttribute (arrayType, soapNS);
516                         if (arrayTypeAttr == null) arrayTypeAttr = Reader.GetAttribute (arrayType, wsdlNS);
517                         
518                         XmlQualifiedName qn = ToXmlQualifiedName (arrayTypeAttr);
519                         int i = qn.Name.LastIndexOf ('[');
520                         string dim = qn.Name.Substring (i);
521                         string itemType = qn.Name.Substring (0,i);
522                         int count = Int32.Parse (dim.Substring (1, dim.Length - 2), CultureInfo.InvariantCulture);
523
524                         Array list;
525
526                         i = itemType.IndexOf ('['); if (i == -1) i = itemType.Length;
527                         string baseType = itemType.Substring (0,i);
528                         string arrayTypeName;
529
530                         if (qn.Namespace == w3SchemaNS)
531                                 arrayTypeName = TypeTranslator.GetPrimitiveTypeData (baseType).Type.FullName + itemType.Substring (i);
532                         else
533                         {
534                                 WriteCallbackInfo info = GetCallbackInfo (new XmlQualifiedName (baseType,qn.Namespace));
535                                 arrayTypeName = info.Type.FullName + itemType.Substring (i) + ", " + info.Type.Assembly.FullName;
536                         }
537
538                         list = Array.CreateInstance (Type.GetType (arrayTypeName), count);
539
540                         bool listComplete = true;
541
542                         if (Reader.IsEmptyElement)
543                                 Reader.Skip ();
544                         else {
545                                 Reader.ReadStartElement ();
546                                 for (int n=0; n<count; n++)
547                                 {
548                                         Reader.MoveToContent ();
549                                         string id;
550                                         object item = ReadReferencingElement (itemType, qn.Namespace, out id);
551                                         if (id == null) 
552                                                 list.SetValue (item,n);
553                                         else
554                                         {
555                                                 AddFixup (new CollectionItemFixup (list, n, id));
556                                                 listComplete = false;
557                                         }
558                                 }
559                                 Reader.ReadEndElement ();
560                         }
561
562                         resultList = list;
563                         return listComplete;
564                 }
565                 
566                 protected void ReadReferencedElements ()
567                 {
568                         reader.MoveToContent();
569                         XmlNodeType nt = reader.NodeType;
570                         while (nt != XmlNodeType.EndElement && nt != XmlNodeType.None) {
571                                 ReadReferencedElement ();
572                                 reader.MoveToContent ();
573                                 nt = reader.NodeType;
574                         }
575
576                         // Registers delayed list
577                         
578                         if (delayedListFixups != null)
579                         {
580                                 foreach (DictionaryEntry entry in delayedListFixups)
581                                         AddTarget ((string)entry.Key, entry.Value);
582                         }
583                         // Fix arrays
584
585                         if (collItemFixups != null)
586                         {
587                                 foreach (CollectionItemFixup itemFixup in collItemFixups)
588                                         itemFixup.Collection.SetValue (GetTarget (itemFixup.Id), itemFixup.Index);
589                         }
590
591                         // Fills collections
592
593                         if (collFixups != null)
594                         {
595                                 ICollection cfixups = collFixups.Values;
596                                 foreach (CollectionFixup fixup in cfixups)
597                                         fixup.Callback (fixup.Collection, fixup.CollectionItems);
598                         }
599
600                         // Fills class instances
601
602                         if (fixups != null)
603                         {
604                                 foreach (Fixup fixup in fixups)
605                                         fixup.Callback (fixup);
606                         }
607                         
608                         if (targets != null) {
609                                 foreach (DictionaryEntry e in targets) {
610                                         if (e.Value != null && (referencedObjects == null || !referencedObjects.Contains (e.Value)))
611                                                 UnreferencedObject ((string)e.Key, e.Value);
612                                 }
613                         }
614                 }
615
616                 protected object ReadReferencingElement (out string fixupReference)
617                 {
618                         return ReadReferencingElement (Reader.LocalName, Reader.NamespaceURI, false, out fixupReference);
619                 }
620
621                 protected object ReadReferencingElement (string name, string ns, out string fixupReference)
622                 {
623                         return ReadReferencingElement (name, ns, false, out fixupReference);
624                 }
625
626                 protected object ReadReferencingElement (string name,
627                                                          string ns,
628                                                          bool elementCanBeType,
629                                                          out string fixupReference)
630                 {
631                         if (ReadNull ())
632                         {
633                                 fixupReference = null;
634                                 return null;
635                         }
636
637                         string refid = Reader.GetAttribute ("href");
638
639                         if (refid == string.Empty || refid == null)
640                         {
641                                 fixupReference = null;
642
643                                 XmlQualifiedName qname = GetXsiType ();
644                                 if (qname == null) qname = new XmlQualifiedName (name, ns);
645                                 string arrayTypeAttr = Reader.GetAttribute (arrayType, soapNS);
646
647                                 if (qname == arrayQName || arrayTypeAttr != null)
648                                 {
649                                         delayedListFixups = EnsureHashtable (delayedListFixups);
650                                         fixupReference = "__<" + (delayedFixupId++) + ">";
651                                         object items;
652                                         ReadList (out items);
653                                         delayedListFixups [fixupReference] = items;
654                                         return null;
655                                 }
656                                 else
657                                 {
658                                         WriteCallbackInfo info = GetCallbackInfo (qname);
659                                         if (info == null)
660                                                 return ReadTypedPrimitive (qname, true);
661                                         else
662                                                 return info.Callback();
663                                 }
664                         }
665                         else
666                         {
667                                 if (refid.StartsWith ("#")) refid = refid.Substring (1);
668
669                                 Reader.Skip ();
670                                 if (TargetReady (refid))
671                                 {
672                                         fixupReference = null;
673                                         return GetTarget (refid);
674                                 }
675                                 else
676                                 {
677                                         fixupReference = refid;
678                                         return null;
679                                 }
680                         }
681                 }
682
683                 protected IXmlSerializable ReadSerializable (IXmlSerializable serializable)
684                 {
685                         if (ReadNull ()) return null;
686                         int depth = reader.Depth;
687                         serializable.ReadXml (reader);
688                         Reader.MoveToContent ();
689                         while (reader.Depth > depth)
690                                 reader.Skip ();
691                         if (reader.Depth == depth && reader.NodeType == XmlNodeType.EndElement)
692                                 reader.ReadEndElement ();
693                         return serializable;
694                 }
695
696                 protected string ReadString (string value)
697                 {
698                         if (value == null || value == String.Empty)
699                                 return reader.ReadString ();
700
701                         return (value + reader.ReadString ());
702                 }
703
704                 protected object ReadTypedPrimitive (XmlQualifiedName qname)
705                 {
706                         return ReadTypedPrimitive (qname, false);
707                 }
708                 
709                 object ReadTypedPrimitive (XmlQualifiedName qname, bool reportUnknown)
710                 {
711                         if (qname == null) qname = GetXsiType ();
712                         
713                         TypeData typeData = TypeTranslator.FindPrimitiveTypeData (qname.Name);
714                         if (typeData == null || typeData.SchemaType != SchemaTypes.Primitive)
715                         {
716                                 // Put everything into a node array
717                                 XmlNode node = Document.ReadNode (reader);
718                                 
719                                 if (reportUnknown)
720                                         OnUnknownNode (node, null);
721
722                                 if (node.ChildNodes.Count == 0 && node.Attributes.Count == 0)
723                                         return new Object ();
724
725                                 XmlElement elem = node as XmlElement;
726                                 
727                                 if (elem == null)
728                                         return new XmlNode[] {node};
729                                 else {
730                                         XmlNode[] nodes = new XmlNode[elem.Attributes.Count + elem.ChildNodes.Count];
731                                         int n = 0;
732                                         foreach (XmlNode no in elem.Attributes)
733                                                 nodes[n++] = no;
734                                         foreach (XmlNode no in elem.ChildNodes)
735                                                 nodes[n++] = no;
736                                         return nodes;
737                                 }
738                         }
739
740                         if (typeData.Type == typeof (XmlQualifiedName)) return ReadNullableQualifiedName ();
741                         return XmlCustomFormatter.FromXmlString (typeData, Reader.ReadElementString ());
742                 }
743
744                 protected XmlNode ReadXmlNode (bool wrapped)
745                 {
746                         XmlNode node = Document.ReadNode (reader);
747                         if (wrapped)
748                                 return node.FirstChild;
749                         else
750                                 return node;
751                 }
752
753                 protected XmlDocument ReadXmlDocument (bool wrapped)
754                 {
755                         if (wrapped)
756                                 reader.ReadStartElement ();
757                                 
758                         XmlDocument doc = new XmlDocument ();
759                         XmlNode node = doc.ReadNode (reader);
760                         doc.AppendChild (node);
761                         
762                         if (wrapped)
763                                 reader.ReadEndElement ();
764                                 
765                         return doc;
766                 }
767
768                 protected void Referenced (object o)
769                 {
770                         if (o != null) {
771                                 if (referencedObjects == null) referencedObjects = new Hashtable ();
772                                 referencedObjects [o] = o;
773                         }
774                 }
775
776                 protected Array ShrinkArray (Array a, int length, Type elementType, bool isNullable)
777                 {
778                         if (length == 0 && isNullable) return null;
779                         if (a == null) return Array.CreateInstance (elementType, length);
780                         if (a.Length == length) return a;
781
782                         Array result = Array.CreateInstance (elementType, length);
783                         Array.Copy (a, result, length);
784                         return result;
785                 }
786
787                 protected byte[] ToByteArrayBase64 (bool isNull)
788                 {
789                         return Convert.FromBase64String (Reader.ReadString());
790                 }
791
792                 [MonoTODO ("Implement")]
793                 protected static byte[] ToByteArrayBase64 (string value)
794                 {
795                         throw new NotImplementedException ();
796                 }
797
798                 [MonoTODO ("Implement")]
799                 protected byte[] ToByteArrayHex (bool isNull)
800                 {
801                         throw new NotImplementedException ();
802                 }
803
804                 [MonoTODO ("Implement")]
805                 protected static byte[] ToByteArrayHex (string value)
806                 {
807                         throw new NotImplementedException ();
808                 }
809
810                 protected static char ToChar (string value)
811                 {
812                         return XmlCustomFormatter.ToChar (value);
813                 }
814
815                 protected static DateTime ToDate (string value)
816                 {
817                         return XmlCustomFormatter.ToDate (value);
818                 }
819
820                 protected static DateTime ToDateTime (string value)
821                 {
822                         return XmlCustomFormatter.ToDateTime (value);
823                 }
824
825                 protected static long ToEnum (string value, Hashtable h, string typeName)
826                 {
827                         return XmlCustomFormatter.ToEnum (value, h, typeName, true);
828                 }
829
830                 protected static DateTime ToTime (string value)
831                 {
832                         return XmlCustomFormatter.ToTime (value);
833                 }
834
835                 protected static string ToXmlName (string value)
836                 {
837                         return XmlCustomFormatter.ToXmlName (value);
838                 }
839
840                 protected static string ToXmlNCName (string value)
841                 {
842                         return XmlCustomFormatter.ToXmlNCName (value);
843                 }
844
845                 protected static string ToXmlNmToken (string value)
846                 {
847                         return XmlCustomFormatter.ToXmlNmToken (value);
848                 }
849
850                 protected static string ToXmlNmTokens (string value)
851                 {
852                         return XmlCustomFormatter.ToXmlNmTokens (value);
853                 }
854
855                 protected XmlQualifiedName ToXmlQualifiedName (string value)
856                 {
857                         string name;
858                         string ns;
859                         int lastColon = value.LastIndexOf (':');
860                         string decodedValue = XmlConvert.DecodeName (value);
861                         if (lastColon < 0) {
862                                 name = reader.NameTable.Add (decodedValue);
863                                 ns = reader.LookupNamespace (String.Empty);
864                         } else {
865                                 string prefix = value.Substring (0, lastColon);
866                                 ns = reader.LookupNamespace (prefix);
867                                 if (ns == null)
868                                         throw new InvalidOperationException ("namespace " + prefix + " not defined");
869
870                                 name = reader.NameTable.Add (value.Substring (lastColon + 1));
871                         }
872
873                         return new XmlQualifiedName (name, ns);
874                 }
875
876                 protected void UnknownAttribute (object o, XmlAttribute attr)
877                 {
878                         int line_number, line_position;
879                         
880                         if (Reader is XmlTextReader){
881                                 line_number = ((XmlTextReader)Reader).LineNumber;
882                                 line_position = ((XmlTextReader)Reader).LinePosition;
883                         } else {
884                                 line_number = 0;
885                                 line_position = 0;
886                         }
887
888                         if (eventSource != null)
889                                 eventSource.OnUnknownAttribute (new XmlAttributeEventArgs (attr, line_number, line_position, o));
890                 }
891
892                 protected void UnknownElement (object o, XmlElement elem)
893                 {
894                         int line_number, line_position;
895                         
896                         if (Reader is XmlTextReader){
897                                 line_number = ((XmlTextReader)Reader).LineNumber;
898                                 line_position = ((XmlTextReader)Reader).LinePosition;
899                         } else {
900                                 line_number = 0;
901                                 line_position = 0;
902                         }
903         
904                         if (eventSource != null)
905                                 eventSource.OnUnknownElement (new XmlElementEventArgs (elem, line_number, line_position,o));
906                 }
907
908                 protected void UnknownNode (object o)
909                 {
910                         OnUnknownNode (ReadXmlNode (false), o);
911                 }
912                 
913                 void OnUnknownNode (XmlNode node, object o)
914                 {
915                         int line_number, line_position;
916                         
917                         if (Reader is XmlTextReader){
918                                 line_number = ((XmlTextReader)Reader).LineNumber;
919                                 line_position = ((XmlTextReader)Reader).LinePosition;
920                         } else {
921                                 line_number = 0;
922                                 line_position = 0;
923                         }
924         
925                         if (node is XmlAttribute)
926                         {
927                                 UnknownAttribute (o, (XmlAttribute)node);
928                                 return;
929                         }
930                         else if (node is XmlElement)
931                         {
932                                 UnknownElement (o, (XmlElement) node);
933                                 return;
934                         }
935                         else
936                         {
937                                 if (eventSource != null)
938                                         eventSource.OnUnknownNode (new XmlNodeEventArgs(line_number, line_position, node.LocalName, node.Name, node.NamespaceURI, node.NodeType, o, node.Value));
939         
940                                 if (Reader.ReadState == ReadState.EndOfFile) 
941                                         throw new InvalidOperationException ("End of document found");
942                         }
943                 }
944
945                 protected void UnreferencedObject (string id, object o)
946                 {
947                         if (eventSource != null)
948                                 eventSource.OnUnreferencedObject (new UnreferencedObjectEventArgs (o,id));
949                 }
950
951                 #endregion // Methods
952
953                 class WriteCallbackInfo
954                 {
955                         public Type Type;
956                         public string TypeName;
957                         public string TypeNs;
958                         public XmlSerializationReadCallback Callback;
959                 }
960
961                 protected class CollectionFixup {
962                         
963                         XmlSerializationCollectionFixupCallback callback;
964                         object collection;
965                         object collectionItems;
966                         string id;
967
968                         public CollectionFixup (object collection, XmlSerializationCollectionFixupCallback callback, string id)
969                         {
970                                 this.callback = callback;
971                                 this.collection = collection;
972                                 this.id = id;
973                         }
974
975                         public XmlSerializationCollectionFixupCallback Callback { 
976                                 get { return callback; }
977                         }
978
979                         public object Collection {
980                                 get { return collection; }
981                         }
982
983                         public object Id {
984                                 get { return id; }
985                         }
986
987                         internal object CollectionItems
988                         {
989                                 get { return collectionItems; }
990                                 set { collectionItems = value; }
991                         }
992                 }
993
994                 protected class Fixup {
995
996                         object source;
997                         string[] ids;
998                         XmlSerializationFixupCallback callback;
999
1000                         public Fixup (object o, XmlSerializationFixupCallback callback, int count) 
1001                         {
1002                                 this.source = o;
1003                                 this.callback = callback;
1004                                 this.ids = new string[count];
1005                         }
1006
1007                         public Fixup (object o, XmlSerializationFixupCallback callback, string[] ids)
1008                         {
1009                                 this.source = o;
1010                                 this.ids = ids;
1011                                 this.callback = callback;
1012                         }
1013
1014                         public XmlSerializationFixupCallback Callback {
1015                                 get { return callback; }
1016                         }
1017
1018                         public string[] Ids {
1019                                 get { return ids; }
1020                         }
1021
1022                         public object Source {
1023                                 get { return source; }
1024                                 set { source = value; }
1025                         }
1026                 }
1027
1028                 protected class CollectionItemFixup 
1029                 {
1030                         Array list;
1031                         int index;
1032                         string id;
1033
1034                         public CollectionItemFixup (Array list, int index, string id)
1035                         {
1036                                 this.list = list;
1037                                 this.index = index;
1038                                 this.id = id;
1039                         }
1040
1041                         public Array Collection
1042                         {
1043                                 get { return list; }
1044                         }
1045
1046                         public int Index
1047                         {
1048                                 get { return index; }
1049                         }
1050
1051                         public string Id
1052                         {
1053                                 get { return id; }
1054                         }
1055                 }
1056                 
1057 #if NET_2_0
1058                 [MonoTODO]
1059                 protected bool DecodeName
1060                 {
1061                         get { throw new NotImplementedException(); }
1062                         set { throw new NotImplementedException(); }
1063                 }
1064
1065                 [MonoTODO]
1066                 protected string CollapseWhitespace (string value)
1067                 {
1068                         throw new NotImplementedException ();
1069                 }
1070                                 
1071                 [MonoTODO]
1072                 protected Exception CreateBadDerivationException (
1073                         string xsdDerived, 
1074                         string nsDerived, 
1075                         string xsdBase, 
1076                         string nsBase, 
1077                         string clrDerived, 
1078                         string clrBase)
1079                 {
1080                         throw new NotImplementedException ();
1081                 }
1082                 
1083                 [MonoTODO]
1084                 protected Exception CreateInvalidCastException (Type type, object value, string id)
1085                 {
1086                         throw new NotImplementedException ();
1087                 }
1088                 
1089                 [MonoTODO]
1090                 protected Exception CreateMissingIXmlSerializableType (string name, string ns, string clrType)
1091                 {
1092                         throw new NotImplementedException ();
1093                 }
1094
1095                 [MonoTODO]
1096                 protected IXmlSerializable ReadSerializable (IXmlSerializable serializable, bool wrapped)
1097                 {
1098                         throw new NotImplementedException ();
1099                 }
1100                 
1101                 [MonoTODO]
1102                 protected string ReadString (string value, bool trim)
1103                 {
1104                         throw new NotImplementedException ();
1105                 }
1106                 
1107                 [MonoTODO]
1108                 protected object ReadTypedNull (XmlQualifiedName type)
1109                 {
1110                         throw new NotImplementedException ();
1111                 }
1112                 
1113                 [MonoTODO]
1114                 protected static Assembly ResolveDynamicAssembly (string assemblyFullName)
1115                 {
1116                         throw new NotImplementedException ();
1117                 }
1118
1119 #endif
1120
1121         }
1122 }