2009-05-26 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
92                                 SerializationMap map = types.FindUserMap (actualType);
93                                 if (map == null) {
94                                         /* Unknown actual type */
95                                         types.Add (actualType);
96                                         map = types.FindUserMap (actualType);
97                                 }
98
99                                 if (actualType != type && (map == null || map.OutputXsiType)) {
100                                         QName qname = types.GetXmlName (actualType);
101                                         string name = qname.Name;
102                                         string ns = qname.Namespace;
103                                         if (qname == QName.Empty) {
104                                                 name = XmlConvert.EncodeLocalName (actualType.Name);
105                                                 ns = KnownTypeCollection.DefaultClrNamespaceBase + actualType.Namespace;
106                                         } else if (qname.Namespace == KnownTypeCollection.MSSimpleNamespace)
107                                                 ns = XmlSchema.Namespace;
108                                         if (writer.LookupPrefix (ns) == null) // it goes first (extraneous, but it makes att order compatible)
109                                                 writer.WriteXmlnsAttribute (null, ns);
110                                         writer.WriteStartAttribute ("type", XmlSchema.InstanceNamespace);
111                                         writer.WriteQualifiedName (name, ns);
112                                         writer.WriteEndAttribute ();
113                                 }
114                                 QName predef = KnownTypeCollection.GetPredefinedTypeName (actualType);
115                                 if (predef != QName.Empty)
116                                         SerializePrimitive (type, graph, predef);
117                                 else
118                                         map.Serialize (graph, this);
119                         }
120                 }
121
122                 public void SerializePrimitive (Type type, object graph, QName qname)
123                 {
124 //                      writer.WriteStartAttribute ("type", XmlSchema.InstanceNamespace);
125 //                      writer.WriteQualifiedName (qname.Name, qname.Namespace);
126 //                      writer.WriteEndAttribute ();
127                         writer.WriteString (KnownTypeCollection.PredefinedTypeObjectToString (graph));
128                 }
129
130                 public void WriteStartElement (string rootName, string rootNamespace, string currentNamespace)
131                 {
132                         writer.WriteStartElement (rootName, rootNamespace);
133                         if (!string.IsNullOrEmpty (currentNamespace) && currentNamespace != rootNamespace)
134                                 writer.WriteXmlnsAttribute (null, currentNamespace);
135                 }
136
137                 public void WriteEndElement ()
138                 {
139                         writer.WriteEndElement ();
140                 }
141         }
142 }
143 #endif