File: parent\Server\System\Data\Services\Epm\EpmCustomContentWriterNodeData.cs
Project: ndp\fx\src\DataWeb\Client\System.Data.Services.Client.csproj (System.Data.Services.Client)
//---------------------------------------------------------------------
// <copyright file="EpmCustomContentWriterNodeData.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <summary>
// Data held by each node in the EpmTargetTree containing information used 
// by the EpmCustomContentWriter visitor
// </summary>
//
// @owner  Microsoft
//---------------------------------------------------------------------
 
namespace System.Data.Services.Common
{
    using System;
    using System.IO;
    using System.Xml;
 
#if !ASTORIA_CLIENT
    using System.ServiceModel.Syndication;
    using System.Data.Services.Serializers;
    using System.Data.Services.Providers;
#else
    using System.Data.Services.Client;
#endif
 
    /// <summary>
    /// Data held by each node in the EpmTargetTree containing information used by the
    /// EpmCustomContentWriter visitor
    /// </summary>
    internal sealed class EpmCustomContentWriterNodeData : IDisposable
    {
        /// <summary>
        /// IDisposable helper state
        /// </summary>
        private bool disposed;
 
#if ASTORIA_CLIENT
        /// <summary>Initializes the per node data for custom serializer</summary>
        /// <param name="segment">Segment in target tree corresponding to this node</param>
        /// <param name="element">Object from which to read properties</param>
        internal EpmCustomContentWriterNodeData(EpmTargetPathSegment segment, object element)
#else
        /// <summary>Initializes the per node data for custom serializer</summary>
        /// <param name="segment">Segment in target tree corresponding to this node</param>
        /// <param name="element">Object from which to read properties</param>
        /// <param name="nullValuedProperties">Null valued properties found during serialization</param>
        /// <param name="provider">Data Service provider used for rights verification.</param>
        internal EpmCustomContentWriterNodeData(EpmTargetPathSegment segment, object element, EpmContentSerializer.EpmNullValuedPropertyTree nullValuedProperties, DataServiceProviderWrapper provider)
#endif
        {
            this.XmlContentStream = new MemoryStream();
            XmlWriterSettings customContentWriterSettings = new XmlWriterSettings();
            customContentWriterSettings.OmitXmlDeclaration = true;
            customContentWriterSettings.ConformanceLevel = ConformanceLevel.Fragment;
            this.XmlContentWriter = XmlWriter.Create(this.XmlContentStream, customContentWriterSettings);
#if ASTORIA_CLIENT
            this.PopulateData(segment, element);
#else
            this.PopulateData(segment, element, nullValuedProperties, provider);
#endif
        }
 
#if ASTORIA_CLIENT
        /// <summary>Initializes the per node data for custom serializer</summary>
        /// <param name="parentData">Parent node whose xml writer we are going to reuse</param>
        /// <param name="segment">Segment in target tree corresponding to this node</param>
        /// <param name="element">Object from which to read properties</param>
        internal EpmCustomContentWriterNodeData(EpmCustomContentWriterNodeData parentData, EpmTargetPathSegment segment, object element)
#else
        /// <summary>Initializes the per node data for custom serializer</summary>
        /// <param name="parentData">Parent node whose xml writer we are going to reuse</param>
        /// <param name="segment">Segment in target tree corresponding to this node</param>
        /// <param name="element">Object from which to read properties</param>
        /// <param name="nullValuedProperties">Null valued properties found during serialization</param>
        /// <param name="provider">Data Service provider used for rights verification.</param>
        internal EpmCustomContentWriterNodeData(EpmCustomContentWriterNodeData parentData, EpmTargetPathSegment segment, object element, EpmContentSerializer.EpmNullValuedPropertyTree nullValuedProperties, DataServiceProviderWrapper provider)
#endif
        {
            this.XmlContentStream = parentData.XmlContentStream;
            this.XmlContentWriter = parentData.XmlContentWriter;
#if ASTORIA_CLIENT
            this.PopulateData(segment, element);
#else
            this.PopulateData(segment, element, nullValuedProperties, provider);
#endif
        }
 
        /// <summary>
        /// Memory stream on top of which XmlWriter works
        /// </summary>
        internal MemoryStream XmlContentStream
        {
            get;
            private set;
        }
 
        /// <summary>
        /// Xml writer used for holding custom content fragment
        /// </summary>
        internal XmlWriter XmlContentWriter
        {
            get;
            private set;
        }
 
        /// <summary>Data for current node</summary>
        internal String Data
        {
            get;
            private set;
        }
 
        /// <summary>
        /// Closes XmlWriter and disposes the MemoryStream
        /// </summary>
        public void Dispose()
        {
            if (!this.disposed)
            {
                if (this.XmlContentWriter != null)
                {
                    this.XmlContentWriter.Close();
                    this.XmlContentWriter = null;
                }
 
                if (this.XmlContentStream != null)
                {
                    this.XmlContentStream.Dispose();
                    this.XmlContentStream = null;
                }
 
                this.disposed = true;
            }
        }
 
        /// <summary>
        /// Adds the content generated through custom serialization to the SyndicationItem or XmlWriter
        /// </summary>
        /// <param name="target">SyndicationItem or XmlWriter being serialized</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "XmlReader on MemoryStream does not require disposal")]
#if ASTORIA_CLIENT
        internal void AddContentToTarget(XmlWriter target)
#else
        internal void AddContentToTarget(SyndicationItem target)
#endif
        {
#if ASTORIA_CLIENT
            Util.CheckArgumentNull(target, "target");
#else
            WebUtil.CheckArgumentNull(target, "target");
#endif
            this.XmlContentWriter.Close();
            this.XmlContentWriter = null;
            this.XmlContentStream.Seek(0, SeekOrigin.Begin);
            XmlReaderSettings customContentReaderSettings = new XmlReaderSettings();
            customContentReaderSettings.ConformanceLevel = ConformanceLevel.Fragment;
            XmlReader reader = XmlReader.Create(this.XmlContentStream, customContentReaderSettings);
            this.XmlContentStream = null;
#if ASTORIA_CLIENT
            target.WriteNode(reader, false);
#else
            target.ElementExtensions.Add(reader);
#endif
        }
 
#if ASTORIA_CLIENT
        /// <summary>
        /// Populates the data value corresponding to this node, also updates the list of null attributes
        /// in the parent null attribute list if current node is attribute with null value
        /// </summary>
        /// <param name="segment">Segment being populated</param>
        /// <param name="element">Object whose property will be read</param>
        private void PopulateData(EpmTargetPathSegment segment, object element)
#else
        /// <summary>
        /// Populates the data value corresponding to this node, also updates the list of null attributes
        /// in the parent null attribute list if current node is attribute with null value
        /// </summary>
        /// <param name="segment">Segment being populated</param>
        /// <param name="element">Object whose property will be read</param>
        /// <param name="nullValuedProperties">Null valued properties found during serialization</param>
        /// <param name="provider">Data Service provider used for rights verification.</param>
        private void PopulateData(EpmTargetPathSegment segment, object element, EpmContentSerializer.EpmNullValuedPropertyTree nullValuedProperties, DataServiceProviderWrapper provider)
#endif
        {
            if (segment.EpmInfo != null)
            {
                Object propertyValue;
 
                try
                {
#if ASTORIA_CLIENT
                    propertyValue = segment.EpmInfo.ReadPropertyValue(element);
#else
                    propertyValue = segment.EpmInfo.ReadPropertyValue(element, provider);
#endif
                }
                catch 
#if ASTORIA_CLIENT
                (System.Reflection.TargetInvocationException)
#else
                (System.Reflection.TargetInvocationException e)
#endif
                {
#if !ASTORIA_CLIENT
                    ErrorHandler.HandleTargetInvocationException(e);
#endif
                    throw;
                }
 
#if ASTORIA_CLIENT
                this.Data = propertyValue == null ? String.Empty : ClientConvert.ToString(propertyValue, false /* atomDateConstruct */);
#else
                if (propertyValue == null || propertyValue == DBNull.Value)
                {
                    this.Data = String.Empty;
                    nullValuedProperties.Add(segment.EpmInfo);
                }
                else
                {
                    this.Data = PlainXmlSerializer.PrimitiveToString(propertyValue);
                }
#endif
            }
        }
    }
}