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}