2009-05-21 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.Runtime.Serialization / System.Runtime.Serialization / XmlFormatterSerializer.cs
1 //
2 // XmlFormatterSerializer.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2005 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 #if NET_2_0
29 using System;
30 using System.Collections;
31 using System.IO;
32 using System.Reflection;
33 using System.Runtime.Serialization.Formatters.Binary;
34 using System.Xml;
35 using System.Xml.Schema;
36
37 using QName = System.Xml.XmlQualifiedName;
38
39 namespace System.Runtime.Serialization
40 {
41         internal class XmlFormatterSerializer
42         {
43                 XmlDictionaryWriter writer;
44                 object graph;
45                 KnownTypeCollection types;
46                 
47                 bool save_id;
48                 bool ignore_unknown;
49                 IDataContractSurrogate surrogate;
50                 int max_items;
51
52                 ArrayList objects = new ArrayList ();
53                 Hashtable references = new Hashtable (); // preserve possibly referenced objects to ids. (new in 3.5 SP1)
54
55                 public static void Serialize (XmlDictionaryWriter writer, object graph,
56                         KnownTypeCollection types,
57                         bool ignoreUnknown, int maxItems, string root_ns)
58                 {
59                         new XmlFormatterSerializer (writer, types, ignoreUnknown, maxItems, root_ns)
60                                 .Serialize (graph != null ? graph.GetType () : null, graph);
61                 }
62
63                 public XmlFormatterSerializer (XmlDictionaryWriter writer,
64                         KnownTypeCollection types,
65                         bool ignoreUnknown, int maxItems, string root_ns)
66                 {
67                         this.writer = writer;
68                         this.types = types;
69                         ignore_unknown = ignoreUnknown;
70                         max_items = maxItems;
71                 }
72
73                 public ArrayList SerializingObjects {
74                         get { return objects; }
75                 }
76
77                 public IDictionary References {
78                         get { return references; }
79                 }
80
81                 public XmlDictionaryWriter Writer {
82                         get { return writer; }
83                 }
84
85                 public void Serialize (Type type, object graph)
86                 {
87                         if (graph == null)
88                                 writer.WriteAttributeString ("nil", XmlSchema.InstanceNamespace, "true");
89                         else {
90                                 Type actualType = graph.GetType ();
91                                 if (actualType != type) {
92                                         QName qname = types.GetXmlName (actualType);
93                                         string name = qname.Name;
94                                         string ns = qname.Namespace;
95                                         if (qname == QName.Empty) {
96                                                 name = XmlConvert.EncodeLocalName (actualType.Name);
97                                                 ns = KnownTypeCollection.DefaultClrNamespaceBase + actualType.Namespace;
98                                         } else if (qname.Namespace == KnownTypeCollection.MSSimpleNamespace)
99                                                 ns = XmlSchema.Namespace;
100                                         if (writer.LookupPrefix (ns) == null) // it goes first (extraneous, but it makes att order compatible)
101                                                 writer.WriteXmlnsAttribute (null, ns);
102                                         writer.WriteStartAttribute ("type", XmlSchema.InstanceNamespace);
103                                         writer.WriteQualifiedName (name, ns);
104                                         writer.WriteEndAttribute ();
105                                 }
106                                 QName predef = KnownTypeCollection.GetPredefinedTypeName (actualType);
107                                 if (predef != QName.Empty)
108                                         SerializePrimitive (type, graph, predef);
109                                 else
110                                         SerializeNonPrimitive (type, graph);
111                         }
112                 }
113
114                 public void SerializePrimitive (Type type, object graph, QName qname)
115                 {
116 //                      writer.WriteStartAttribute ("type", XmlSchema.InstanceNamespace);
117 //                      writer.WriteQualifiedName (qname.Name, qname.Namespace);
118 //                      writer.WriteEndAttribute ();
119                         writer.WriteString (KnownTypeCollection.PredefinedTypeObjectToString (graph));
120                 }
121
122                 public void WriteStartElement (string rootName, string rootNamespace, string currentNamespace)
123                 {
124                         writer.WriteStartElement (rootName, rootNamespace);
125                         if (!string.IsNullOrEmpty (currentNamespace) && currentNamespace != rootNamespace)
126                                 writer.WriteXmlnsAttribute (null, currentNamespace);
127                 }
128
129                 public void WriteEndElement ()
130                 {
131                         writer.WriteEndElement ();
132                 }
133
134                 public void SerializeNonPrimitive (Type type, object graph)
135                 {
136                         Type actualType = graph.GetType ();
137
138                         SerializationMap map = types.FindUserMap (actualType);
139                         if (map == null) {
140                                 /* Unknown actual type */
141                                 types.Add (actualType);
142                                 map = types.FindUserMap (actualType);
143                         }
144
145                         map.Serialize (graph, this);
146                 }
147         }
148 }
149 #endif