001package com.hfg.xml.msofficexml;
002
003
004import java.io.ByteArrayOutputStream;
005import java.io.File;
006import java.io.FileOutputStream;
007import java.io.IOException;
008import java.io.OutputStream;
009import java.util.ArrayList;
010import java.util.List;
011import java.util.Set;
012import java.util.logging.Level;
013import java.util.logging.Logger;
014import java.util.zip.ZipEntry;
015import java.util.zip.ZipOutputStream;
016
017import com.hfg.util.StringUtil;
018import com.hfg.util.collection.CollectionUtil;
019import com.hfg.util.collection.OrderedSet;
020import com.hfg.util.io.FileBytes;
021import com.hfg.xml.msofficexml.part.*;
022
023//------------------------------------------------------------------------------
024/**
025 Abstract base class for Office Open XML format documents.
026
027 @author J. Alex Taylor, hairyfatguy.com
028 */
029//------------------------------------------------------------------------------
030// com.hfg XML/HTML Coding Library
031//
032// This library is free software; you can redistribute it and/or
033// modify it under the terms of the GNU Lesser General Public
034// License as published by the Free Software Foundation; either
035// version 2.1 of the License, or (at your option) any later version.
036//
037// This library is distributed in the hope that it will be useful,
038// but WITHOUT ANY WARRANTY; without even the implied warranty of
039// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
040// Lesser General Public License for more details.
041//
042// You should have received a copy of the GNU Lesser General Public
043// License along with this library; if not, write to the Free Software
044// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
045//
046// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
047// jataylor@hairyfatguy.com
048//------------------------------------------------------------------------------
049
050public abstract class OfficeOpenXmlDocument
051{
052   private Set<OfficeXMLPart>      mParts = new OrderedSet<>(20);
053   private List<MediaPart>         mMediaParts;
054   private List<ThemePart>         mThemeParts;
055   private List<VbaPart> mVbaParts;
056   private ContentTypesPart        mContentTypesPart;
057   private PackageRelationshipPart mPackageRelationshipPart;
058   private DocumentPropertiesPart  mDocumentPropertiesPart;
059
060   private String mName;
061
062   public static Level sSQLLoggingLevel = Level.FINE;
063
064   private final static Logger LOGGER = Logger.getLogger(OfficeOpenXmlDocument.class.getPackage().getName());
065
066   //---------------------------------------------------------------------------
067   protected OfficeOpenXmlDocument()
068   {
069      // Setup essential relationships
070      mPackageRelationshipPart = new PackageRelationshipPart(this);
071      mPackageRelationshipPart.addRelationship(RelationshipType.CORE_PROPERTIES, OfficeXML.CORE_PROPERTIES_FILE);
072
073      mContentTypesPart = new ContentTypesPart(this);
074
075      mDocumentPropertiesPart = new DocumentPropertiesPart(this);
076      mContentTypesPart.addOverride(mDocumentPropertiesPart,    OfficeOpenXMLContentType.CORE_PROPERTIES);
077   }
078
079   //---------------------------------------------------------------------------
080   public void addPart(OfficeXMLPart inPart)
081   {
082      if (inPart instanceof MediaPart)
083      {
084         addMediaPart((MediaPart) inPart);
085      }
086      else
087      {
088         mParts.add(inPart);
089
090         if (inPart instanceof ThemePart)
091         {
092            if (null == mThemeParts)
093            {
094               mThemeParts = new ArrayList<>(5);
095            }
096
097            mThemeParts.add((ThemePart) inPart);
098
099            ((ThemePart) inPart).setThemeIndex(mThemeParts.size());
100         }
101      }
102   }
103
104   //---------------------------------------------------------------------------
105   public void addMediaPart(MediaPart inValue)
106   {
107      if (null == mMediaParts)
108      {
109         mMediaParts = new ArrayList<>(10);
110      }
111
112      mMediaParts.add(inValue);
113   }
114
115   //---------------------------------------------------------------------------
116   public void addVBA_Part(VbaPart inValue)
117   {
118      if (null == mVbaParts)
119      {
120         mVbaParts = new ArrayList<>(2);
121      }
122
123      mVbaParts.add(inValue);
124   }
125
126   //---------------------------------------------------------------------------
127   public ContentTypesPart getContentTypesPart()
128   {
129      return mContentTypesPart;
130   }
131
132   //---------------------------------------------------------------------------
133   public PackageRelationshipPart getPackageRelationshipPart()
134   {
135      return mPackageRelationshipPart;
136   }
137
138   //---------------------------------------------------------------------------
139   public DocumentPropertiesPart getDocumentPropertiesPart()
140   {
141      return mDocumentPropertiesPart;
142   }
143
144
145   //---------------------------------------------------------------------------
146   public String name()
147   {
148      return mName;
149   }
150
151   //---------------------------------------------------------------------------
152   public OfficeOpenXmlDocument setName(String inValue)
153   {
154      mName = inValue;
155      return this;
156   }
157
158
159   //---------------------------------------------------------------------------
160   public FileBytes toFileBytes()
161         throws IOException
162   {
163      ByteArrayOutputStream stream = new ByteArrayOutputStream();
164      write(stream);
165
166      FileBytes fileBytes = new FileBytes(name());
167
168      fileBytes.setData(stream.toByteArray());
169
170      return fileBytes;
171   }
172
173   //---------------------------------------------------------------------------
174   public void write(File inFile)
175         throws IOException
176   {
177      FileOutputStream fileStream = null;
178      try
179      {
180         fileStream = new FileOutputStream(inFile);
181         write(fileStream);
182      }
183      finally
184      {
185         if (fileStream != null)
186         {
187            fileStream.close();
188         }
189      }
190   }
191
192   //---------------------------------------------------------------------------
193   public void write(OutputStream inStream)
194         throws IOException
195   {
196
197      if (LOGGER.isLoggable(sSQLLoggingLevel))
198      {
199         LOGGER.log(sSQLLoggingLevel, "Writing OfficeOpenXML document " + StringUtil.singleQuote(name()) + "\n" + OfficeOpenXmlXsd.getInstance().getConfigSummary());
200      }
201
202      ZipOutputStream zipStream = new ZipOutputStream(inStream);
203
204      for (OfficeXMLPart part : mParts)
205      {
206         // Be sure we don't have any lingering character entities.
207         part.replaceCharacterEntities();
208
209         ZipEntry zipEntry = new ZipEntry(part.getFile().getPath());
210         zipStream.putNextEntry(zipEntry);
211         part.toXML(zipStream);
212         zipStream.closeEntry();
213      }
214
215      if (CollectionUtil.hasValues(mMediaParts))
216      {
217         for (MediaPart mediaPart : mMediaParts)
218         {
219            ZipEntry zipEntry = new ZipEntry(mediaPart.getFile().getPath());
220            zipStream.putNextEntry(zipEntry);
221            mediaPart.write(zipStream);
222            zipStream.closeEntry();
223         }
224      }
225
226      if (CollectionUtil.hasValues(mVbaParts))
227      {
228         for (VbaPart vbaPart : mVbaParts)
229         {
230            ZipEntry zipEntry = new ZipEntry(vbaPart.getFile().getPath());
231            zipStream.putNextEntry(zipEntry);
232            vbaPart.write(zipStream);
233            zipStream.closeEntry();
234         }
235      }
236
237      zipStream.finish();
238   }
239
240}