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