XpsFixedDocumentSequenceReaderWriter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Print / Reach / Packaging / XpsFixedDocumentSequenceReaderWriter.cs / 1 / XpsFixedDocumentSequenceReaderWriter.cs

                            /*++ 

    Copyright (C) 2004 - 2005 Microsoft Corporation
    All rights reserved.
 
    Module Name:
        XpsFixedDocumentSequenceReaderWriter.cs 
 
    Abstract:
        This file contains the definition for IXpsFixedDocumentSequenceReader 
        and IXpsFixedDocumentSequenceWriter interfaces as well as definition
        and implementation of XpsFixedDocumentSequenceReaderWriter.  These
        interfaces and class are used for writing document sequence
        parts to a Xps package. 

    Author: 
        [....] ([....]) 1-November-2004 

    Revision History: 
    05/5/2005:  [....]: Addition of Digital Signing support
    07/12/2005: [....]: Reach -> Xps
--*/
 
using System;
using System.IO; 
using System.Collections; 
using System.Collections.ObjectModel;
using System.Collections.Generic; 
using System.IO.Packaging;
using System.Xml;
using System.Security.Cryptography.X509Certificates;
using System.Printing; 

namespace System.Windows.Xps.Packaging 
{ 
    #region IXpsFixedDocumentSequenceReader interface definition
 
    /// 
    /// Interface for reading document sequence parts from a Xps package.
    /// 
    /// Class will be internal until reading/de-serialization is implemented. 
    public interface IXpsFixedDocumentSequenceReader
    { 
        #region Public methods 

        ///  
        /// This method retrieves a fixed document part from a Xps
        /// package using the given URI.
        /// 
        ///  
        /// The URI of the fixed document to retrieve.
        ///  
        ///  
        /// Returns an interface to an IXpsFixedDocumentReader to read
        /// the requested fixed document. 
        /// 
        IXpsFixedDocumentReader
        GetFixedDocument(
            Uri         documentSource 
            );
 
        #endregion Public methods 

        #region Public properties 

        /// 
        /// Gets the PrintTicket associated with this document sequence.
        ///  
        /// Value can be a PrintTicket or null.
        /// PrintTicket has already been committed. 
        /// Property is not a valid PrintTicket instance. 
        PrintTicket PrintTicket { get; }
 
        /// 
        /// Gets the URI assigned to this document sequence part.
        /// 
        /// Value is a URI for the Metro part. 
        Uri Uri { get; }
 
        ///  
        /// Gets a collection of all fixed documents that are contained within
        /// this document sequence. 
        /// 
        /// 
        /// Value is a Collection containing IXpsFixedDocumentReader interfaces.
        ///  
        ReadOnlyCollection  FixedDocuments { get; }
        ///  
        /// thumbnail image associated with this sequence 
        /// 
        XpsThumbnail 
        Thumbnail{ get; }

        #endregion Public properties
    } 

    #endregion IXpsFixedDocumentSequenceReader interface definition 
 
    #region IXpsFixedDocumentSequenceWriter interface definition
 
    /// 
    /// Interface for writing a document sequence to the Xps package.
    /// 
    public interface IXpsFixedDocumentSequenceWriter 
    {
        #region Public methods 
 
        /// 
        /// This method adds a fixed document part to the Xps package 
        /// and associates it with the current document sequence.
        /// 
        /// 
        /// Returns an interface to the newly created fixed document. 
        /// 
        /// Current DocumentSequence not completed. 
        IXpsFixedDocumentWriter 
        AddFixedDocument(
            ); 

        /// 
        /// This method adds a thumbnail to the current DocumentSequence.
        /// 
        /// There can only be one thumbnail attached to the DocumentSequence.
        ///  Calling this method when there 
        /// is already a starting part causes InvalidOperationException to be 
        /// thrown.
        ///  
        XpsThumbnail
        AddThumbnail(
            XpsImageType  imageType
            ); 

        ///  
        /// This method commits any changes not already committed for this 
        /// document sequence.
        /// 
        /// 
        void
        Commit(
            ); 

        #endregion Public methods 
 
        #region Public properties
 
        /// 
        /// Sets the PrintTicket associated with this document sequence.
        /// 
        ///  
        /// The value must be a valid PrintTicket instance.
        /// 
        /// Note:  The PrintTicket can only be assigned to prior to if being 
        /// committed to the package.  The commit happens when a valid PrintTicket
        /// is set and a subsequent flush on the document occurs. 
        /// 
        /// PrintTicket has already been committed.
        /// Property is not a valid PrintTicket instance.
        PrintTicket PrintTicket { set; } 

        ///  
        /// Gets the URI assigned to this document sequence part. 
        /// 
        /// Value is a URI for the Metro part. 
        Uri Uri { get; }

        #endregion Public properties
    } 

    #endregion IXpsFixedDocumentSequenceWriter interface definition 
 
    /// 
    /// This class implements the reading and writing functionality for 
    /// a document sequence within a Xps package.
    /// 
    internal sealed class XpsFixedDocumentSequenceReaderWriter : XpsPartBase,
                        IXpsFixedDocumentSequenceReader, 
                        IXpsFixedDocumentSequenceWriter,
                        INode, 
                        IDisposable 
    {
        #region Constructors 

        /// 
        /// Internal constructor for the XpsFixedDocumentSequenceReaderWriter class.
        /// This class is created internally so we can keep the Xps hierarchy 
        /// completely under control when using these APIs.
        ///  
        ///  
        /// The XpsManager for the current Xps package.
        ///  
        /// 
        /// The parent node of this document.
        /// 
        ///  
        /// The internal Metro part that represents this document sequence.
        ///  
        /// part is null. 
        internal
        XpsFixedDocumentSequenceReaderWriter( 
            XpsManager    xpsManager,
            INode           parent,
            PackagePart     part
            ) 
            : base(xpsManager)
        { 
            if (null == part) 
            {
                throw new ArgumentNullException("part"); 
            }

            this.Uri = part.Uri;
            _metroPart = part; 
            _partEditor = new XmlPartEditor(_metroPart);
            _documentCache = new List(); 
            _parentNode = parent; 
            _hasParsedDocuments = false;
        } 

        #endregion Constructors

        #region Public properties 

        ///  
        /// Gets or sets the PrintTicket to be stored with this document 
        /// sequence.
        /// 
        /// NOTE:  The PrintTicket can only be assigned to prior to if being
        /// committed to the package.  The commit happens when a valid PrintTicket
        /// is set and a subsequent flush on the document occurs.
        ///  
        /// Value can be a PrintTicket or null.
        /// PrintTicket has already been committed. 
        /// Property is not a valid PrintTicket instance. 
        public PrintTicket PrintTicket
        { 
            get
            {
                if( _printTicket == null )
                { 
                    _printTicket = CurrentXpsManager.EnsurePrintTicket(Uri);
                } 
                return _printTicket; 
            }
            set 
            {
                if(value != null)
                {
                    if (_isPrintTicketCommitted) 
                    {
                        throw new XpsPackagingException(ReachSR.Get(ReachSRID.ReachPackaging_PrintTicketAlreadyCommitted)); 
                    } 
                    if (!value.GetType().Equals(typeof(PrintTicket)))
                    { 
                        throw new XpsPackagingException(ReachSR.Get(ReachSRID.ReachPackaging_NotAPrintTicket));
                    }
                    _printTicket = value.Clone();
                } 
                else
                { 
                    _printTicket = null; 
                }
            } 
        }

        /// 
        /// Gets a collection of all fixed documents that are contained within 
        /// this document sequence.
        ///  
        ///  
        /// Value is a Collection containing IXpsFixedDocumentReader interfaces.
        ///  
        /// 
        /// This is only internal until it is implemented.
        /// 
        public ReadOnlyCollection FixedDocuments 
        {
            get 
            { 
                UpdateDocumentCache();
                return new ReadOnlyCollection(_documentCache); 
            }
        }

        ///  
        /// thumbnail image associated with this sequence
        ///  
        public 
        XpsThumbnail
        Thumbnail 
        {
            get
            {
                EnsureThumbnail(); 
                return _thumbnail;
            } 
        } 
        #endregion Public properties
 
        #region Public methods

        /// 
        /// This method adds a fixed document part to the Xps package 
        /// and associates it with the current document sequence.
        ///  
        ///  
        /// Returns an interface to the newly created fixed document.
        ///  
        /// Current DocumentSequence not completed.
        public
        IXpsFixedDocumentWriter
        AddFixedDocument( 
            )
        { 
            // 
            // Create the part and coresponding writer
            // 
            PackagePart metroPart = CurrentXpsManager.GenerateUniquePart(XpsS0Markup.FixedDocumentContentType);
            XpsFixedDocumentReaderWriter fixedDocument = new XpsFixedDocumentReaderWriter(CurrentXpsManager, this, metroPart,_documentCache.Count+1);

            // 
            // Make sure the new fixed document makes it into the cached collection
            // 
            _documentCache.Add(fixedDocument); 

            // 
            // Write out FixedDocument markup
            //
            AddDocumentToSequence(fixedDocument.Uri);
 

            return fixedDocument; 
        } 

        ///  
        /// This method adds a thumbnail to the current DocumentSequence.
        ///
        /// There can only be one thumbnail attached to the DocumentSequence.
        ///  Calling this method when there 
        /// is already a starting part causes InvalidOperationException to be
        /// thrown. 
        ///  
        /// Returns a XpsThumbnail instance.
        public 
        XpsThumbnail
        AddThumbnail(
            XpsImageType  imageType
            ) 
        {
            _thumbnail = CurrentXpsManager.AddThumbnail( imageType, this, Thumbnail ); 
            _metroPart.CreateRelationship( _thumbnail.Uri, 
                                             TargetMode.Internal,
                                             XpsS0Markup.ThumbnailRelationshipName 
                                           );
            return _thumbnail;
        }
 
        /// 
        /// This method retrieves a fixed document part from a Xps 
        /// package using the given URI. 
        /// 
        ///  
        /// The URI of the fixed document to retrieve.
        /// 
        /// 
        /// Returns an interface to an IXpsFixedDocumentReader to read 
        /// the requested fixed document.
        ///  
        public 
        IXpsFixedDocumentReader
        GetFixedDocument( 
            Uri         documentUri
            )
        {
            UpdateDocumentCache(); 
            IXpsFixedDocumentReader fixedDocument  = null;
            // 
            // Check the cache for the requested document 
            //
            foreach (IXpsFixedDocumentReader reader in _documentCache) 
            {
                if( documentUri == reader.Uri )
                {
                    fixedDocument = reader;                } 
            }
 
            return fixedDocument; 
        }
 
        /// 
        /// This method commits any changes not already committed for this
        /// document sequence.
        /// 
        /// NOTE:  This commits changes on all child objects underneath this
        /// branch.  No further changes will be allowed. 
        ///  
        public
        void 
        Commit(
            )
        {
            CommitInternal(); 
        }
 
        ///  
        /// This method closes streams and frees memory for this
        /// document sequence. 
        /// 
        internal
        override
        void 
        CommitInternal(
            ) 
        { 
            CommitPrintTicket();
            if (null != _partEditor) 
            {
                ((INode)this).Flush();
                _partEditor.Close();
 

                _partEditor     = null; 
                _metroPart      = null; 

                _documentCache  = null; 

                _thumbnail      = null;

                _parentNode     = null; 
                _hasParsedDocuments = false;
           } 
        } 

 

        /// 
        /// Adds itself and and its reationship if it exists
        /// Adds dependent part Uris to the passed list following 
        /// the passed restrictions dependents
        /// include pages, annotaions, properties, and signatures 
        ///  
        internal
        void 
        CollectSelfAndDependents(
            Dictionary                     dependentList,
            List       selectorList,
            XpsDigSigPartAlteringRestrictions       restrictions 
            )
        { 
            // 
            // Add my self
            // 
            dependentList[Uri] = Uri;

            //
            // Add thumnail relationship 
            //
            selectorList.Add(new PackageRelationshipSelector( 
                                    Uri, 
                                    PackageRelationshipSelectorType.Type,
                                    XpsS0Markup.ThumbnailRelationshipName 
                                    )
                                 );

            // 
            //  Add my dependents
            // 
            CollectDependents( dependentList, selectorList,  restrictions); 

        } 

        internal
        void
        CollectXmlPartsAndDepenedents( 
            List                       xmlPartList
            ) 
        { 
            //
            // Add my self to be tested for V&E Markup 
            //
            xmlPartList.Add(_metroPart);
            UpdateDocumentCache();
            // Add all documents 
            foreach (IXpsFixedDocumentReader reader in _documentCache)
            { 
                (reader as XpsFixedDocumentReaderWriter).CollectXmlPartsAndDepenedents(xmlPartList); 
            }
        } 

        #endregion Public methods

        #region Private methods 

        private 
        void 
        AddDocumentToSequence(
            Uri         partUri 
            )
        {
            _partEditor.PrepareXmlWriter(XpsS0Markup.FixedDocumentSequence, XpsS0Markup.DocumentSequenceNamespace);
            XmlTextWriter xmlWriter = _partEditor.XmlWriter; 
            //
            // Write  
            // 
            String relativePath = XpsManager.MakeRelativePath(Uri, partUri);
 
            xmlWriter.WriteStartElement(XpsS0Markup.DocumentReference);
            xmlWriter.WriteAttributeString(XmlTags.Source, relativePath);
            xmlWriter.WriteEndElement();
        } 

        ///  
        /// This method writes the PrintTicket associated with 
        /// this document sequence to the Metro package.
        ///  
        private
        void
        CommitPrintTicket(
            ) 
        {
            // 
            // Flush the PrintTicket if needed 
            //
            if (!_isPrintTicketCommitted ) 
            {
                if(null != _printTicket)
                {
                    CurrentXpsManager.WritePrintTicket(this, _metroPart, _printTicket); 
                }
                else 
                { 
                    CurrentXpsManager.WriteEmptyPrintTicket(this, _metroPart);
                } 
                _isPrintTicketCommitted = true;
            }
        }
 
        /// 
        /// Test if the document cache has initialized and 
        /// Updates if necessary 
        /// 
        private 
        void
        UpdateDocumentCache()
        {
           if( !_hasParsedDocuments ) 
            {
                ParseDocuments(); 
                _hasParsedDocuments = true; 
            }
        } 

        /// 
        /// This method parses the part pulling out the Document Referneces
        /// and populates the _documentCache 
        /// 
        private 
        void 
        ParseDocuments()
        { 
            Stream stream = _metroPart.GetStream(FileMode.Open);
            //
            // If the stream is empty there are no documents to parse
            // 
            if( stream.Length > 0 )
            { 
                XmlTextReader reader = new XmlTextReader(stream); 

                while( reader.Read() ) 
                {
                    if( reader.NodeType == XmlNodeType.Element && reader.Name == XpsS0Markup.DocumentReference)
                    {
                        string attribute = reader.GetAttribute(XmlTags.Source); 
                        if( attribute != null )
                        { 
                          Uri relativeUri =  new Uri(attribute, UriKind.Relative); 
                          //This routine properly adds DocumentReaderWriter to the _documentCache
                          AddDocumentToCache(PackUriHelper.ResolvePartUri( Uri, relativeUri)); 
                        }
                    }
                }
            } 
        }
 
        ///  
        /// Adds dependent part Uris to the passed list
        ///  
        private
        void
        CollectDependents(
            Dictionary                     dependents, 
            List       selectorList,
            XpsDigSigPartAlteringRestrictions       restrictions 
            ) 
        {
            UpdateDocumentCache(); 
            // Add all documents
            foreach( IXpsFixedDocumentReader reader in _documentCache)
            {
                (reader as XpsFixedDocumentReaderWriter). 
                    CollectSelfAndDependents(
                        dependents, 
                        selectorList, 
                        restrictions);
            } 

            //
            // Add thumbnail
            // 
            EnsureThumbnail();
            if( _thumbnail != null ) 
            { 
                dependents[_thumbnail.Uri] = _thumbnail.Uri;
            } 
        }

        private
        void 
        EnsureThumbnail()
        { 
            if( _thumbnail == null ) 
            {
                _thumbnail = CurrentXpsManager.EnsureThumbnail( this, _metroPart ); 
            }
        }

        private 
        IXpsFixedDocumentReader
        AddDocumentToCache(Uri documentUri) 
        { 
            //
            // Retrieve the requested part from the package 
            //
            PackagePart documentPart = CurrentXpsManager.GetPart(documentUri);
            if (documentPart == null)
            { 
                 throw new XpsPackagingException(ReachSR.Get(ReachSRID.ReachPackaging_PartNotFound));
            } 
 
            //
            // If the part is not a fixed document then throw an exception 
            //
            if (!documentPart.ValidatedContentType.AreTypeAndSubTypeEqual(XpsS0Markup.FixedDocumentContentType))
            {
                throw new XpsPackagingException(ReachSR.Get(ReachSRID.ReachPackaging_NotAFixedDocument)); 
            }
 
            // 
            // Create the reader/writer for the part
            // 
            IXpsFixedDocumentReader  fixedDocument = new XpsFixedDocumentReaderWriter(CurrentXpsManager, null, documentPart, _documentCache.Count+1);

            //
            // Cache the new reader/writer for later 
            //
            _documentCache.Add( fixedDocument ); 
            return fixedDocument; 
        }
 

        #endregion Private methods

        #region Private data 

        private PackagePart _metroPart; 
        private PrintTicket _printTicket; 

        private XmlPartEditor _partEditor; 

        private List_documentCache;

        // 
        // This variable flags whether the PrintTicket property is
        // committed.  A writer can only commit this property once. 
        // 
        private bool _isPrintTicketCommitted;
 
        //
        // These variables are used to keep track of the parent
        // and current child of this node for walking up and
        // down the current tree.  This is used be the flushing 
        // policy to do interleave flushing of parts correctly.
        // 
        private INode _parentNode; 

        // 
        // This variable flags wehter the documentCashe
        // has been populated by parsing the part for dependent documents
        private bool _hasParsedDocuments;
 
        private XpsThumbnail _thumbnail;
 
        #endregion Private data 

        #region Internal properties 

        /// 
        /// Gets a reference to the XmlWriter for the internal Metro
        /// part that represents this document sequence. 
        /// 
        internal System.Xml.XmlWriter XmlWriter 
        { 
            get
            { 
                _partEditor.DoesWriteStartEndTags = false;
                return _partEditor.XmlWriter;
            }
        } 

        #endregion Internal properties 
 
        #region INode implementation
 
        void
        INode.Flush(
            )
        { 
            //
            // Commit the PrintTicket (if necessary) 
            // 
            CommitPrintTicket();
 
            if( CurrentXpsManager.Streaming )
            {
                _partEditor.FlushRelationships();
                _partEditor.Flush(); 
            }
 
            // 
            // Create the relationship between the package and the tumbnail
            // 
            if( _thumbnail != null )
            {
                _thumbnail = null;
            } 

        } 
 
        void
        INode.CommitInternal( 
            )
        {
            CommitInternal();
        } 

        PackagePart 
        INode.GetPart( 
            )
        { 
            return _metroPart;
        }

        #endregion INode implementation 

        #region IDisposable implementation 
 
        void
        IDisposable.Dispose( 
            )
        {
            CommitInternal();
        } 

        #endregion IDisposable implementation 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK