1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.ServiceModel.Syndication
6 {
7     using System.Collections.ObjectModel;
8     using System.Runtime.Serialization;
9     using System.Xml.Serialization;
10     using System.Collections.Generic;
11     using System.Xml;
12     using System.Xml.Schema;
13     using System.ServiceModel.Channels;
14     using System.ServiceModel.Diagnostics;
15     using System.Diagnostics;
16     using System.Diagnostics.CodeAnalysis;
17     using System.Runtime.CompilerServices;
18 
19     [TypeForwardedFrom("System.ServiceModel.Web, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
20     [XmlRoot(ElementName = App10Constants.Categories, Namespace = App10Constants.Namespace)]
21     public class AtomPub10CategoriesDocumentFormatter : CategoriesDocumentFormatter, IXmlSerializable
22     {
23         Type inlineDocumentType;
24         int maxExtensionSize;
25         bool preserveAttributeExtensions;
26         bool preserveElementExtensions;
27         Type referencedDocumentType;
28 
AtomPub10CategoriesDocumentFormatter()29         public AtomPub10CategoriesDocumentFormatter()
30             : this(typeof(InlineCategoriesDocument), typeof(ReferencedCategoriesDocument))
31         {
32         }
33 
AtomPub10CategoriesDocumentFormatter(Type inlineDocumentType, Type referencedDocumentType)34         public AtomPub10CategoriesDocumentFormatter(Type inlineDocumentType, Type referencedDocumentType)
35             : base()
36         {
37             if (inlineDocumentType == null)
38             {
39                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("inlineDocumentType");
40             }
41             if (!typeof(InlineCategoriesDocument).IsAssignableFrom(inlineDocumentType))
42             {
43                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("inlineDocumentType",
44                     SR.GetString(SR.InvalidObjectTypePassed, "inlineDocumentType", "InlineCategoriesDocument"));
45             }
46             if (referencedDocumentType == null)
47             {
48                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("referencedDocumentType");
49             }
50             if (!typeof(ReferencedCategoriesDocument).IsAssignableFrom(referencedDocumentType))
51             {
52                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("referencedDocumentType",
53                     SR.GetString(SR.InvalidObjectTypePassed, "referencedDocumentType", "ReferencedCategoriesDocument"));
54             }
55             this.maxExtensionSize = int.MaxValue;
56             this.preserveAttributeExtensions = true;
57             this.preserveElementExtensions = true;
58             this.inlineDocumentType = inlineDocumentType;
59             this.referencedDocumentType = referencedDocumentType;
60         }
61 
AtomPub10CategoriesDocumentFormatter(CategoriesDocument documentToWrite)62         public AtomPub10CategoriesDocumentFormatter(CategoriesDocument documentToWrite)
63             : base(documentToWrite)
64         {
65             // No need to check that the parameter passed is valid - it is checked by the c'tor of the base class
66             this.maxExtensionSize = int.MaxValue;
67             preserveAttributeExtensions = true;
68             preserveElementExtensions = true;
69             if (documentToWrite.IsInline)
70             {
71                 this.inlineDocumentType = documentToWrite.GetType();
72                 this.referencedDocumentType = typeof(ReferencedCategoriesDocument);
73             }
74             else
75             {
76                 this.referencedDocumentType = documentToWrite.GetType();
77                 this.inlineDocumentType = typeof(InlineCategoriesDocument);
78             }
79         }
80 
81         public override string Version
82         {
83             get { return App10Constants.Namespace; }
84         }
85 
CanRead(XmlReader reader)86         public override bool CanRead(XmlReader reader)
87         {
88             if (reader == null)
89             {
90                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
91             }
92             return reader.IsStartElement(App10Constants.Categories, App10Constants.Namespace);
93         }
94 
95         [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "The IXmlSerializable implementation is only for exposing under WCF DataContractSerializer. The funcionality is exposed to derived class through the ReadFrom\\WriteTo methods")]
IXmlSerializable.GetSchema()96         XmlSchema IXmlSerializable.GetSchema()
97         {
98             return null;
99         }
100 
101         [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "The IXmlSerializable implementation is only for exposing under WCF DataContractSerializer. The funcionality is exposed to derived class through the ReadFrom\\WriteTo methods")]
IXmlSerializable.ReadXml(XmlReader reader)102         void IXmlSerializable.ReadXml(XmlReader reader)
103         {
104             if (reader == null)
105             {
106                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
107             }
108             TraceCategoriesDocumentReadBegin();
109             ReadDocument(reader);
110             TraceCategoriesDocumentReadEnd();
111         }
112 
113         [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "The IXmlSerializable implementation is only for exposing under WCF DataContractSerializer. The funcionality is exposed to derived class through the ReadFrom\\WriteTo methods")]
IXmlSerializable.WriteXml(XmlWriter writer)114         void IXmlSerializable.WriteXml(XmlWriter writer)
115         {
116             if (writer == null)
117             {
118                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
119             }
120             if (this.Document == null)
121             {
122                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.DocumentFormatterDoesNotHaveDocument)));
123             }
124             TraceCategoriesDocumentWriteBegin();
125             WriteDocument(writer);
126             TraceCategoriesDocumentWriteEnd();
127         }
128 
ReadFrom(XmlReader reader)129         public override void ReadFrom(XmlReader reader)
130         {
131             if (reader == null)
132             {
133                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
134             }
135             if (!CanRead(reader))
136             {
137                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.UnknownDocumentXml, reader.LocalName, reader.NamespaceURI)));
138             }
139             TraceCategoriesDocumentReadBegin();
140             ReadDocument(reader);
141             TraceCategoriesDocumentReadEnd();
142         }
143 
WriteTo(XmlWriter writer)144         public override void WriteTo(XmlWriter writer)
145         {
146             if (writer == null)
147             {
148                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
149             }
150             if (this.Document == null)
151             {
152                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.DocumentFormatterDoesNotHaveDocument)));
153             }
154             TraceCategoriesDocumentWriteBegin();
155             writer.WriteStartElement(App10Constants.Prefix, App10Constants.Categories, App10Constants.Namespace);
156             WriteDocument(writer);
157             writer.WriteEndElement();
158             TraceCategoriesDocumentWriteEnd();
159         }
160 
TraceCategoriesDocumentReadBegin()161         internal static void TraceCategoriesDocumentReadBegin()
162         {
163             if (DiagnosticUtility.ShouldTraceInformation)
164             {
165                 TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.SyndicationReadCategoriesDocumentBegin, SR.GetString(SR.TraceCodeSyndicationReadCategoriesDocumentBegin));
166             }
167         }
168 
TraceCategoriesDocumentReadEnd()169         internal static void TraceCategoriesDocumentReadEnd()
170         {
171             if (DiagnosticUtility.ShouldTraceInformation)
172             {
173                 TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.SyndicationReadCategoriesDocumentEnd, SR.GetString(SR.TraceCodeSyndicationReadCategoriesDocumentEnd));
174             }
175         }
176 
TraceCategoriesDocumentWriteBegin()177         internal static void TraceCategoriesDocumentWriteBegin()
178         {
179             if (DiagnosticUtility.ShouldTraceInformation)
180             {
181                 TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.SyndicationWriteCategoriesDocumentBegin, SR.GetString(SR.TraceCodeSyndicationWriteCategoriesDocumentBegin));
182             }
183         }
184 
TraceCategoriesDocumentWriteEnd()185         internal static void TraceCategoriesDocumentWriteEnd()
186         {
187             if (DiagnosticUtility.ShouldTraceInformation)
188             {
189                 TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.SyndicationWriteCategoriesDocumentEnd, SR.GetString(SR.TraceCodeSyndicationWriteCategoriesDocumentEnd));
190             }
191         }
192 
CreateInlineCategoriesDocument()193         protected override InlineCategoriesDocument CreateInlineCategoriesDocument()
194         {
195             if (inlineDocumentType == typeof(InlineCategoriesDocument))
196             {
197                 return new InlineCategoriesDocument();
198             }
199             else
200             {
201                 return (InlineCategoriesDocument)Activator.CreateInstance(this.inlineDocumentType);
202             }
203         }
204 
CreateReferencedCategoriesDocument()205         protected override ReferencedCategoriesDocument CreateReferencedCategoriesDocument()
206         {
207             if (referencedDocumentType == typeof(ReferencedCategoriesDocument))
208             {
209                 return new ReferencedCategoriesDocument();
210             }
211             else
212             {
213                 return (ReferencedCategoriesDocument)Activator.CreateInstance(this.referencedDocumentType);
214             }
215         }
216 
ReadDocument(XmlReader reader)217         void ReadDocument(XmlReader reader)
218         {
219             try
220             {
221                 SyndicationFeedFormatter.MoveToStartElement(reader);
222                 SetDocument(AtomPub10ServiceDocumentFormatter.ReadCategories(reader, null,
223                     delegate()
224                     {
225                         return this.CreateInlineCategoriesDocument();
226                     },
227 
228                     delegate()
229                     {
230                         return this.CreateReferencedCategoriesDocument();
231                     },
232                     this.Version,
233                     this.preserveElementExtensions,
234                     this.preserveAttributeExtensions,
235                     this.maxExtensionSize));
236             }
237             catch (FormatException e)
238             {
239                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(FeedUtils.AddLineInfo(reader, SR.ErrorParsingDocument), e));
240             }
241             catch (ArgumentException e)
242             {
243                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(FeedUtils.AddLineInfo(reader, SR.ErrorParsingDocument), e));
244             }
245         }
246 
WriteDocument(XmlWriter writer)247         void WriteDocument(XmlWriter writer)
248         {
249             // declare the atom10 namespace upfront for compactness
250             writer.WriteAttributeString(Atom10Constants.Atom10Prefix, Atom10FeedFormatter.XmlNsNs, Atom10Constants.Atom10Namespace);
251             AtomPub10ServiceDocumentFormatter.WriteCategoriesInnerXml(writer, this.Document, null, this.Version);
252         }
253     }
254 }
255