be64183c576b932667c613b6107740b88876c10d
[mono.git] / mcs / class / System.ServiceModel.Web / System.ServiceModel.Syndication / SyndicationElementExtension.cs
1 //
2 // SyndicationElementExtension.cs
3 //
4 // Author:
5 //      Atsushi Enomoto  <atsushi@ximian.com>
6 //
7 // Copyright (C) 2007 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 using System;
29 using System.Collections.Generic;
30 using System.Collections.ObjectModel;
31 using System.IO;
32 using System.Runtime.Serialization;
33 using System.Text;
34 using System.Xml;
35 using System.Xml.Serialization;
36
37 namespace System.ServiceModel.Syndication
38 {
39         public class SyndicationElementExtension
40         {
41                 ReadWriteHandler handler;
42
43                 public SyndicationElementExtension (object dataContractExtension)
44                         : this (dataContractExtension, (XmlObjectSerializer) null)
45                 {
46                 }
47
48                 public SyndicationElementExtension (object dataContractExtension, XmlObjectSerializer dataContractSerializer)
49                         : this (null, null, dataContractExtension, dataContractSerializer)
50                 {
51                 }
52
53                 public SyndicationElementExtension (string outerName, string outerNamespace, object dataContractExtension)
54                         : this (outerName, outerNamespace, dataContractExtension, null)
55                 {
56                 }
57
58                 public SyndicationElementExtension (string outerName, string outerNamespace, object dataContractExtension, XmlObjectSerializer dataContractSerializer)
59                 {
60                         if (dataContractExtension == null)
61                                 throw new ArgumentNullException ("dataContractExtension");
62                         handler = new DataContractReadWriteHandler (outerName, outerNamespace, dataContractExtension, dataContractSerializer);
63                 }
64
65                 public SyndicationElementExtension (object xmlSerializerExtension, XmlSerializer serializer)
66                 {
67                         if (xmlSerializerExtension == null)
68                                 throw new ArgumentNullException ("xmlSerializerExtension");
69                         handler = new XmlSerializationReadWriteHandler (xmlSerializerExtension, serializer);
70                 }
71
72                 public SyndicationElementExtension (XmlReader xmlReader)
73                 {
74                         if (xmlReader == null)
75                                 throw new ArgumentNullException ("xmlReader");
76                         xmlReader.MoveToContent ();
77                         if (xmlReader.NodeType != XmlNodeType.Element)
78                                 throw new XmlException ("Element node is expected on the argument xmlReader");
79
80                         handler = new XmlReaderReadWriteHandler (xmlReader);
81                 }
82
83                 public string OuterName {
84                         get { return handler != null ? handler.Name : null; }
85                 }
86
87                 public string OuterNamespace {
88                         get { return handler != null ? handler.Namespace : null; }
89                 }
90
91                 public TExtension GetObject<TExtension> ()
92                 {
93                         return GetObject<TExtension> (new DataContractSerializer (typeof (TExtension)));
94                 }
95
96                 public TExtension GetObject<TExtension> (XmlObjectSerializer serializer)
97                 {
98                         if (serializer == null)
99                                 throw new ArgumentNullException ("serializer");
100                         return (TExtension) serializer.ReadObject (GetReader (), false);
101                 }
102
103                 public TExtension GetObject<TExtension> (XmlSerializer serializer)
104                 {
105                         if (serializer == null)
106                                 throw new ArgumentNullException ("serializer");
107                         return (TExtension) serializer.Deserialize (GetReader ());
108                 }
109
110                 public XmlReader GetReader ()
111                 {
112                         var r = handler.GetReader ();
113                         r.MoveToContent ();
114                         return r;
115                 }
116
117                 public void WriteTo (XmlWriter writer)
118                 {
119                         if (writer == null)
120                                 throw new ArgumentNullException ("writer");
121
122                         handler.WriteTo (writer);
123                 }
124
125                 abstract class ReadWriteHandler
126                 {
127                         public string Name { get; protected set; }
128
129                         public string Namespace { get; protected set; }
130
131                         public virtual XmlReader GetReader ()
132                         {
133                                 StringWriter sw = new StringWriter ();
134                                 using (XmlWriter w = XmlWriter.Create (sw))
135                                         WriteTo (w);
136                                 return XmlReader.Create (new StringReader (sw.ToString ()));
137                         }
138
139                         public abstract void WriteTo (XmlWriter writer);
140                 }
141
142                 class DataContractReadWriteHandler : ReadWriteHandler
143                 {
144                         object extension;
145                         XmlObjectSerializer serializer;
146                         
147                         public DataContractReadWriteHandler (string name, string ns, object extension, XmlObjectSerializer serializer)
148                         {
149                                 if (serializer == null)
150                                         serializer = new DataContractSerializer (extension.GetType ());
151 #if NET_4_0
152                                 // FIXME: this is a nasty workaround that mcs somehow fails to resolve InternalVisibleTo(System.ServiceModel) in System.Runtime.Serialization.dll and thus rejects the use of KnownTypeCollection unlike NET_2_0 case (where System.ServiceModel.Web.dll is referenced).
153                                 XmlQualifiedName qname = null;
154                                 if (name == null || ns == null) {
155                                         var ms = new MemoryStream ();
156                                         using (var xw = XmlWriter.Create (ms))
157                                                 serializer.WriteStartObject (xw, extension);
158                                         ms.Position = 0;
159                                         var xr = XmlReader.Create (ms);
160                                         xr.MoveToContent ();
161                                         qname = new XmlQualifiedName (xr.LocalName, xr.NamespaceURI);
162                                 }
163 #else
164                                 var qname = name == null || ns == null ? KnownTypeCollection.GetStaticQName (extension.GetType ()) : null;
165 #endif
166                                 this.Name = name ?? qname.Name;
167                                 this.Namespace = ns ?? qname.Namespace;
168                                 this.extension = extension;
169                                 this.serializer = serializer;
170                         }
171
172                         public override void WriteTo (XmlWriter writer)
173                         {
174                                 if (Name != null) {
175                                         writer.WriteStartElement (Name, Namespace);
176                                         serializer.WriteObjectContent (writer, extension);
177                                         writer.WriteFullEndElement ();
178                                 }
179                                 else
180                                         serializer.WriteObject (writer, extension);
181                         }
182                 }
183
184                 class XmlSerializationReadWriteHandler : ReadWriteHandler
185                 {
186                         object extension;
187                         XmlSerializer serializer;
188
189                         public XmlSerializationReadWriteHandler (object extension, XmlSerializer serializer)
190                         {
191                                 this.extension = extension;
192                                 this.serializer = serializer;
193
194                                 if (serializer == null)
195                                         serializer = new XmlSerializer (extension.GetType ());
196                         }
197
198                         public override void WriteTo (XmlWriter writer)
199                         {
200                                 serializer.Serialize (writer, extension);
201                         }
202                 }
203
204                 class XmlReaderReadWriteHandler : ReadWriteHandler
205                 {
206                         string xml;
207
208                         public XmlReaderReadWriteHandler (XmlReader reader)
209                         {
210                                 reader.MoveToContent ();
211                                 Name = reader.LocalName;
212                                 Namespace = reader.NamespaceURI;
213                                 xml = reader.ReadOuterXml ();
214                         }
215
216                         public override XmlReader GetReader ()
217                         {
218                                 var r = XmlReader.Create (new StringReader (xml));
219                                 r.MoveToContent ();
220                                 return r;
221                         }
222
223                         public override void WriteTo (XmlWriter writer)
224                         {
225                                 writer.WriteNode (GetReader (), false);
226                         }
227                 }
228         }
229 }