File: Packaging\PartEditor.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\ReachFramework\ReachFramework.csproj (ReachFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
/*++
                                                                              
                                                       
    Module Name:                                                                
                                                                              
    Abstract:
        This file contains the definition  and implementation
        for PartEditor and XmlPartEditor classes.  These classes
        are used as wrappers around the Metro package API part
        classes.
                
                                     
                                                                             
--*/
using System;
using System.Diagnostics;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.IO.Packaging;
using System.Windows;
using System.Windows.Markup;
using System.Xml;
 
using MS.Internal.IO.Packaging.Extensions;
 
namespace System.Windows.Xps.Packaging
{
    /// <summary>
    /// Provides access to the stream of a Metro part
    /// </summary>
    internal class PartEditor : IDisposable
    {
        #region Constructors
 
        /// <summary>
        /// Attach an editor to a part
        /// </summary>
        /// <param name="metroPart"></param>
        internal
        PartEditor(
            PackagePart     metroPart
            )
        {
            ArgumentNullException.ThrowIfNull(metroPart);
 
            _metroPart = metroPart;
        }
 
        #endregion Constructors
 
        #region Protected properties
 
        protected PackagePart MetroPart
        {
            get
            {
                return _metroPart;
            }
        }
 
        #endregion Protected properties
 
        #region Internal properties
 
        /// <summary>
        /// Return a data stream for the part
        /// </summary>
        /// <value></value>
        internal Stream DataStream
        {
            get
            {
                if (null == _partDataStream)
                {
                    if (_metroPart.Package.FileOpenAccess == FileAccess.Write)
                    {
                        _partDataStream = _metroPart.GetStream(FileMode.Create);
                    }
                    else
                    {
                        _partDataStream = _metroPart.GetStream(FileMode.OpenOrCreate);
                    }
}
 
                return _partDataStream;
            }
        }
 
        #endregion Internal properties
 
        #region Internal methods
 
        /// <summary>
        /// Close the part data stream
        /// </summary>
        internal
        virtual
        void
        Close(
            )
        {
            if (null != _partDataStream)
            {
                if (_partDataStream.CanWrite)
                {
                    _partDataStream.Close();
                }
 
                GC.SuppressFinalize(this);
                _partDataStream = null;
            }
        }
 
        /// <summary>
        /// Forcibly flush the part data stream
        /// </summary>
        internal
        virtual
        void
        Flush(
            )
        {
            if (null != _partDataStream)
            {
                _partDataStream.Flush();
            }
        }
        
        #endregion Internal methods
 
        #region Private data
 
        private PackagePart _metroPart;
        private Stream _partDataStream;
 
        #endregion Private data
 
        #region IDisposable implementation
 
        void
        IDisposable.Dispose(
            )
        {
            Close();
        }
 
        #endregion IDisposable implementation
    }
 
    /// <summary>
    /// Part editor with XML content
    /// </summary>
    internal class XmlPartEditor : PartEditor
    {
        #region Constructors
 
        /// <summary>
        /// Attach an editor to an existing part
        /// </summary>
        /// <param name="metroPart"></param>
        internal
        XmlPartEditor(
            PackagePart     metroPart
            )
            : base(metroPart)
        {
            _doesWriteStartEndTags = true;
            _isStartElementWritten = false;
        }
 
        #endregion Constructors
 
        #region Internal properties
 
        internal bool DoesWriteStartEndTags
        {
            get
            {
                return _doesWriteStartEndTags;
            }
            set
            {
                _doesWriteStartEndTags = value;
            }
        }
 
        internal bool IsStartElementWritten
        {
            get
            {
                return _isStartElementWritten;
            }
        }
 
        internal XmlTextWriter XmlWriter
        {
            get
            {
                if (null == _xmlWriter)
                {
                    OpenDocumentForWrite();
                }
 
                return _xmlWriter;
            }
        }
        
        internal XmlTextReader XmlReader
        {
            get
            {
                if (null == _xmlReader)
                {
                    OpenDocumentForRead();
                }
 
                return _xmlReader;
            }
        }
 
        #endregion Internal properties
 
        #region Internal methods
 
        /// <summary>
        /// Setup for writing
        /// </summary>
        internal
        void
        OpenDocumentForRead(
            )
        {
            if (_xmlReader != null)
            {
                throw new XpsPackagingException(SR.ReachPackaging_OpenDocOrElementAlreadyCalled);
            }
 
            Stream stream = MetroPart.GetStream(FileMode.Open);
  
            _xmlReader = new XmlTextReader(stream);
        }
        
        /// <summary>
        /// Setup for writing
        /// </summary>
        internal
        void
        OpenDocumentForWrite(
            )
        {
            if (_xmlWriter != null)
            {
                throw new XpsPackagingException(SR.ReachPackaging_OpenDocOrElementAlreadyCalled);
            }
 
            Stream stream = MetroPart.GetStream(FileMode.Create);
 
            _xmlWriter = new XmlTextWriter(stream, System.Text.Encoding.UTF8);
        }
 
 
        internal
        void
        PrepareXmlWriter(
            string      startTag,
            string      namespaceUri
            )
        {
            if (null == _xmlWriter)
            {
                //
                // Stream not open yet, create it and write open tag
                //
                OpenDocumentForWrite();
 
                if (_doesWriteStartEndTags)
                {
                    _xmlWriter.WriteStartDocument();
                }
 
                _xmlWriter.WriteStartElement(startTag, namespaceUri);
                _isStartElementWritten = true;
            }
        }
 
 
 
        /// <summary>
        /// Flush any XML written so far for sequence (does not end Sequence tag)
        /// </summary>
        internal
        override
        void
        Flush(
            )
        {
            if (null != _xmlWriter)
            {
                _xmlWriter.Flush();
            }
        }
 
        /// <summary>
        /// Close XML written for sequence (adds end Sequence tag)
        /// </summary>
        internal
        override
        void
        Close(
            )
        {
            if (null != _xmlWriter)
            {
                _xmlWriter.Close();
                _xmlWriter = null;
            }
 
            if (null != _xmlReader)
            {
                _xmlReader.Close();
                _xmlReader = null;
            }
            base.Close();
        }
 
        #endregion Internal methods
 
        #region Private data
 
        private bool          _doesWriteStartEndTags;
        private XmlTextWriter _xmlWriter;
        private XmlTextReader _xmlReader;
        private bool          _isStartElementWritten;
 
        #endregion Private data
    }
}