001package com.hfg.xml.msofficexml.docx; 002 003 004import java.awt.Font; 005import java.util.ArrayList; 006import java.util.HashMap; 007import java.util.List; 008import java.util.Map; 009 010import com.hfg.util.StringUtil; 011import com.hfg.xml.msofficexml.OfficeOpenXMLContentType; 012import com.hfg.xml.msofficexml.OfficeOpenXmlDocument; 013import com.hfg.xml.msofficexml.RelationshipType; 014import com.hfg.xml.msofficexml.docx.part.*; 015import com.hfg.xml.msofficexml.docx.part.VbaRelationshipPart; 016import com.hfg.xml.msofficexml.docx.wordprocessingml.WmlBookmark; 017import com.hfg.xml.msofficexml.docx.wordprocessingml.WmlFooter; 018import com.hfg.xml.msofficexml.docx.wordprocessingml.WmlHeader; 019import com.hfg.xml.msofficexml.docx.wordprocessingml.WmlXML; 020import com.hfg.xml.msofficexml.part.*; 021 022//------------------------------------------------------------------------------ 023/** 024 Office Open XML format Word document. 025 026 @author J. Alex Taylor, hairyfatguy.com 027 */ 028//------------------------------------------------------------------------------ 029// com.hfg XML/HTML Coding Library 030// 031// This library is free software; you can redistribute it and/or 032// modify it under the terms of the GNU Lesser General Public 033// License as published by the Free Software Foundation; either 034// version 2.1 of the License, or (at your option) any later version. 035// 036// This library is distributed in the hope that it will be useful, 037// but WITHOUT ANY WARRANTY; without even the implied warranty of 038// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 039// Lesser General Public License for more details. 040// 041// You should have received a copy of the GNU Lesser General Public 042// License along with this library; if not, write to the Free Software 043// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 044// 045// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 046// jataylor@hairyfatguy.com 047//------------------------------------------------------------------------------ 048/* 049 050 Testing notes: 051 052 - for zipping on the command-line: 'zip -r <foo.docx> *' 053 054 - docProps/app.xml is not required as long as there is no rel entry 055 - docProps/thumbnail.jpeg is not required as long as there is no rel entry 056 */ 057public class Docx extends OfficeOpenXmlDocument 058{ 059 private DocumentPart mDocumentPart; 060 private CommentsPart mCommentsPart; 061 private StylesPart mStylesPart; 062 private SettingsPart mSettingsPart; 063 private NumberingPart mNumberingPart; 064 private List<HeaderPart> mHeaderParts; 065 private List<FooterPart> mFooterParts; 066 private VbaDataPart mVBA_DataPart; 067 private VbaRelationshipPart mVBA_RelationshipPart; 068 069 // For convenience, keep a list of bookmarks in the document. 070 private Map<String, WmlBookmark> mBookmarkMap; 071 072 private static String sDefaultName = "Untitled.docx"; 073 074 //########################################################################## 075 // CONSTRUCTORS 076 //########################################################################## 077 078 //--------------------------------------------------------------------------- 079 public Docx() 080 { 081 super(); 082 083 init(); 084 } 085 086 //--------------------------------------------------------------------------- 087 private void init() 088 { 089 // Setup essential relationships 090 getPackageRelationshipPart().addRelationship(RelationshipType.OFFICE_DOCUMENT, WmlXML.DOCUMENT_FILE); 091 092 mDocumentPart = new DocumentPart(this); 093 094 getContentTypesPart().addDefault(WmlContentType.PRINTER_SETTINGS); 095 getContentTypesPart().addOverride(mDocumentPart, WmlContentType.MAIN_DOCUMENT); 096 /* 097 getContentTypesPart().addOverride(new OfficeXMLPart(this).setFile(new File("/docProps/app.xml")), OfficeOpenXMLContentType.EXTENDED_PROPERTIES); 098 getContentTypesPart().addOverride(new OfficeXMLPart(this).setFile(new File("/word/footnotes.xml")), WmlContentType.FOOTNOTES); 099 getContentTypesPart().addOverride(new OfficeXMLPart(this).setFile(new File("/word/fontTable.xml")), WmlContentType.FONT_TABLE); 100 getContentTypesPart().addOverride(new OfficeXMLPart(this).setFile(new File("/word/webSettings.xml")), WmlContentType.WEB_SETTINGS); 101*/ 102 } 103 104 //########################################################################## 105 // PUBLIC METHODS 106 //########################################################################## 107 108 //--------------------------------------------------------------------------- 109 public static String getDefaultName() 110 { 111 return sDefaultName; 112 } 113 114 //--------------------------------------------------------------------------- 115 @Override 116 public String name() 117 { 118 String name = super.name(); 119 if (! StringUtil.isSet(name)) 120 { 121 name = getDefaultName(); 122 setName(name); 123 } 124 125 return name; 126 } 127 128 //--------------------------------------------------------------------------- 129 /** 130 Convenience method for setting the default font for the document. 131 * @param inValue Font object to use as the default font-family, size, and style. 132 * @return the doument object to enable method chaining. 133 */ 134 public Docx setDefaultFont(Font inValue) 135 { 136 getStylesPart().getDocDefaults().getTextRunProperties().setFont(inValue); 137 return this; 138 } 139 140 //--------------------------------------------------------------------------- 141 public SettingsPart getSettingsPart() 142 { 143 if (null == mSettingsPart) 144 { 145 mSettingsPart = new SettingsPart(this); 146 addPart(mSettingsPart); 147 148 getContentTypesPart().addOverride(mSettingsPart, WmlContentType.SETTINGS); 149 } 150 151 return mSettingsPart; 152 } 153 154 //--------------------------------------------------------------------------- 155 public DocumentPart getDocumentPart() 156 { 157 return mDocumentPart; 158 } 159 160 //--------------------------------------------------------------------------- 161 public StylesPart getStylesPart() 162 { 163 if (null == mStylesPart) 164 { 165 mStylesPart = new StylesPart(this); 166 addPart(mStylesPart); 167 168 getDocumentPart().getRelationshipPart().addRelationship(RelationshipType.STYLES, WmlXML.STYLES_FILE); 169 getContentTypesPart().addOverride(mStylesPart, WmlContentType.STYLES); 170 } 171 172 return mStylesPart; 173 } 174 175 //--------------------------------------------------------------------------- 176 public NumberingPart getNumberingPart() 177 { 178 if (null == mNumberingPart) 179 { 180 mNumberingPart = new NumberingPart(this); 181 addPart(mNumberingPart); 182 183 getDocumentPart().getRelationshipPart().addRelationship(RelationshipType.NUMBERING, WmlXML.NUMBERING_FILE); 184 getContentTypesPart().addOverride(mNumberingPart, WmlContentType.NUMBERING); 185 } 186 187 return mNumberingPart; 188 } 189 190 //--------------------------------------------------------------------------- 191 // The comments part will only be instantiated if requested. 192 public CommentsPart getCommentsPart() 193 { 194 if (null == mCommentsPart) 195 { 196 mCommentsPart = new CommentsPart(this); 197 mCommentsPart.setParentDoc(this); 198 addPart(mCommentsPart); 199 getPackageRelationshipPart().addRelationship(RelationshipType.COMMENTS, WmlXML.COMMENTS_FILE); 200 getContentTypesPart().addOverride(mCommentsPart, OfficeOpenXMLContentType.COMMENTS); 201 } 202 203 return mCommentsPart; 204 } 205 206 //--------------------------------------------------------------------------- 207 public String addHeader(WmlHeader inValue) 208 { 209 HeaderPart headerPart = inValue.getPart(); 210 if (null == mHeaderParts) 211 { 212 mHeaderParts = new ArrayList<>(5); 213 } 214 215 mHeaderParts.add(headerPart); 216 addPart(headerPart); 217 getContentTypesPart().addOverride(headerPart, OfficeOpenXMLContentType.HEADER); 218 219 return getDocumentPart().getRelationshipPart().addRelationship(RelationshipType.HEADER, headerPart.getFile()); 220 } 221 222 //--------------------------------------------------------------------------- 223 public String addFooter(WmlFooter inValue) 224 { 225 FooterPart footerPart = inValue.getPart(); 226 if (null == mFooterParts) 227 { 228 mFooterParts = new ArrayList<>(5); 229 } 230 231 mFooterParts.add(footerPart); 232 addPart(footerPart); 233 getContentTypesPart().addOverride(footerPart, OfficeOpenXMLContentType.FOOTER); 234 235 return getDocumentPart().getRelationshipPart().addRelationship(RelationshipType.FOOTER, footerPart.getFile()); 236 } 237 238 //--------------------------------------------------------------------------- 239 /** 240 For convenience, bookmarks are automatically registered via this method so that 241 they can be retrieved via the getBookmark() method. 242 * @param inValue 243 */ 244 public void registerBookmark(WmlBookmark inValue) 245 { 246 if (null == mBookmarkMap) 247 { 248 mBookmarkMap = new HashMap<>(50); 249 } 250 251 mBookmarkMap.put(inValue.name(), inValue); 252 } 253 254 //--------------------------------------------------------------------------- 255 public WmlBookmark getBookmark(String inName) 256 { 257 WmlBookmark bookmark = null; 258 if (mBookmarkMap != null) 259 { 260 bookmark = mBookmarkMap.get(inName); 261 } 262 263 return bookmark; 264 } 265 266 267 //--------------------------------------------------------------------------- 268 public VbaDataPart getVBA_DataPart() 269 { 270 if (null == mVBA_DataPart) 271 { 272 mVBA_DataPart = new VbaDataPart(this); 273 274 getVBA_RelationshipPart().addRelationship(RelationshipType.WORD_VBA_DATA, WmlXML.VBA_DATA_FILE); 275 } 276 277 return mVBA_DataPart; 278 } 279 280 //--------------------------------------------------------------------------- 281 public VbaRelationshipPart getVBA_RelationshipPart() 282 { 283 if (null == mVBA_RelationshipPart) 284 { 285 mVBA_RelationshipPart = new VbaRelationshipPart(this); 286 } 287 288 return mVBA_RelationshipPart; 289 } 290 291}