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}