001: /**
002: * Copyright (c) 2003-2006, www.pdfbox.org
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * 1. Redistributions of source code must retain the above copyright notice,
009: * this list of conditions and the following disclaimer.
010: * 2. Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: * 3. Neither the name of pdfbox; nor the names of its
014: * contributors may be used to endorse or promote products derived from this
015: * software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
021: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: *
028: * http://www.pdfbox.org
029: *
030: */package org.pdfbox.pdmodel;
031:
032: import java.io.IOException;
033: import java.util.ArrayList;
034: import java.util.List;
035:
036: import org.pdfbox.cos.COSArray;
037: import org.pdfbox.cos.COSBase;
038: import org.pdfbox.cos.COSDictionary;
039: import org.pdfbox.cos.COSName;
040: import org.pdfbox.cos.COSStream;
041: import org.pdfbox.cos.COSString;
042:
043: import org.pdfbox.pdmodel.common.COSArrayList;
044: import org.pdfbox.pdmodel.common.COSObjectable;
045: import org.pdfbox.pdmodel.common.PDDestinationOrAction;
046: import org.pdfbox.pdmodel.common.PDMetadata;
047: import org.pdfbox.pdmodel.documentinterchange.logicalstructure.PDMarkInfo;
048: import org.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureTreeRoot;
049: import org.pdfbox.pdmodel.interactive.action.type.PDActionURI;
050: import org.pdfbox.pdmodel.interactive.action.PDActionFactory;
051: import org.pdfbox.pdmodel.interactive.action.PDDocumentCatalogAdditionalActions;
052: import org.pdfbox.pdmodel.interactive.documentnavigation.destination.PDDestination;
053: import org.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
054: import org.pdfbox.pdmodel.interactive.form.PDAcroForm;
055:
056: import org.pdfbox.pdmodel.interactive.pagenavigation.PDThread;
057: import org.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences;
058:
059: /**
060: * This class represents the acroform of a PDF document.
061: *
062: * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
063: * @version $Revision: 1.21 $
064: */
065: public class PDDocumentCatalog implements COSObjectable {
066: private COSDictionary root;
067: private PDDocument document;
068:
069: private PDAcroForm acroForm = null;
070:
071: /**
072: * Page mode where neither the outline nor the thumbnails
073: * are displayed.
074: */
075: public static final String PAGE_MODE_USE_NONE = "UseNone";
076: /**
077: * Show bookmarks when pdf is opened.
078: */
079: public static final String PAGE_MODE_USE_OUTLINES = "UseOutlines";
080: /**
081: * Show thumbnails when pdf is opened.
082: */
083: public static final String PAGE_MODE_USE_THUMBS = "UseThumbs";
084: /**
085: * Full screen mode with no menu bar, window controls.
086: */
087: public static final String PAGE_MODE_FULL_SCREEN = "FullScreen";
088: /**
089: * Optional content group panel is visible when opened.
090: */
091: public static final String PAGE_MODE_USE_OPTIONAL_CONTENT = "UseOC";
092: /**
093: * Attachments panel is visible.
094: */
095: public static final String PAGE_MODE_USE_ATTACHMENTS = "UseAttachments";
096:
097: /**
098: * Display one page at a time.
099: */
100: public static final String PAGE_LAYOUT_SINGLE_PAGE = "SinglePage";
101: /**
102: * Display the pages in one column.
103: */
104: public static final String PAGE_LAYOUT_ONE_COLUMN = "OneColumn";
105: /**
106: * Display the pages in two columns, with odd numbered pagse on the left.
107: */
108: public static final String PAGE_LAYOUT_TWO_COLUMN_LEFT = "TwoColumnLeft";
109: /**
110: * Display the pages in two columns, with odd numbered pagse on the right.
111: */
112: public static final String PAGE_LAYOUT_TWO_COLUMN_RIGHT = "TwoColumnRight";
113: /**
114: * Display the pages two at a time, with odd-numbered pages on the left.
115: * @since PDF Version 1.5
116: */
117: public static final String PAGE_LAYOUT_TWO_PAGE_LEFT = "TwoPageLeft";
118: /**
119: * Display the pages two at a time, with odd-numbered pages on the right.
120: * @since PDF Version 1.5
121: */
122: public static final String PAGE_LAYOUT_TWO_PAGE_RIGHT = "TwoPageRight";
123:
124: /**
125: * Constructor.
126: *
127: * @param doc The document that this catalog is part of.
128: */
129: public PDDocumentCatalog(PDDocument doc) {
130: document = doc;
131: root = new COSDictionary();
132: root.setItem(COSName.TYPE, new COSString("Catalog"));
133: document.getDocument().getTrailer().setItem(COSName.ROOT, root);
134: }
135:
136: /**
137: * Constructor.
138: *
139: * @param doc The document that this catalog is part of.
140: * @param rootDictionary The root dictionary that this object wraps.
141: */
142: public PDDocumentCatalog(PDDocument doc,
143: COSDictionary rootDictionary) {
144: document = doc;
145: root = rootDictionary;
146: }
147:
148: /**
149: * Convert this standard java object to a COS object.
150: *
151: * @return The cos object that matches this Java object.
152: */
153: public COSBase getCOSObject() {
154: return root;
155: }
156:
157: /**
158: * Convert this standard java object to a COS object.
159: *
160: * @return The cos object that matches this Java object.
161: */
162: public COSDictionary getCOSDictionary() {
163: return root;
164: }
165:
166: /**
167: * This will get the documents acroform. This will return null if
168: * no acroform is part of the document.
169: *
170: * @return The documents acroform.
171: */
172: public PDAcroForm getAcroForm() {
173: if (acroForm == null) {
174: COSDictionary acroFormDic = (COSDictionary) root
175: .getDictionaryObject(COSName.ACRO_FORM);
176: if (acroFormDic != null) {
177: acroForm = new PDAcroForm(document, acroFormDic);
178: }
179: }
180: return acroForm;
181: }
182:
183: /**
184: * Set the acro form for this catalog.
185: *
186: * @param acro The new acro form.
187: */
188: public void setAcroForm(PDAcroForm acro) {
189: root.setItem(COSName.ACRO_FORM, acro);
190: }
191:
192: /**
193: * This will get the root node for the pages.
194: *
195: * @return The parent page node.
196: */
197: public PDPageNode getPages() {
198: return new PDPageNode((COSDictionary) root
199: .getDictionaryObject(COSName.PAGES));
200: }
201:
202: /**
203: * The PDF document contains a hierarchical structure of PDPageNode and PDPages, which
204: * is mostly just a way to store this information. This method will return a flat list
205: * of all PDPage objects in this document.
206: *
207: * @return A list of PDPage objects.
208: */
209: public List getAllPages() {
210: List retval = new ArrayList();
211: PDPageNode rootNode = getPages();
212: //old (slower):
213: //getPageObjects( rootNode, retval );
214: rootNode.getAllKids(retval);
215: return retval;
216: }
217:
218: /**
219: * Get the viewer preferences associated with this document or null if they
220: * do not exist.
221: *
222: * @return The document's viewer preferences.
223: */
224: public PDViewerPreferences getViewerPreferences() {
225: PDViewerPreferences retval = null;
226: COSDictionary dict = (COSDictionary) root
227: .getDictionaryObject("ViewerPreferences");
228: if (dict != null) {
229: retval = new PDViewerPreferences(dict);
230: }
231:
232: return retval;
233: }
234:
235: /**
236: * Set the viewer preferences.
237: *
238: * @param prefs The new viewer preferences.
239: */
240: public void setViewerPreferences(PDViewerPreferences prefs) {
241: root.setItem("ViewerPreferences", prefs);
242: }
243:
244: /**
245: * Get the outline associated with this document or null if it
246: * does not exist.
247: *
248: * @return The document's outline.
249: */
250: public PDDocumentOutline getDocumentOutline() {
251: PDDocumentOutline retval = null;
252: COSDictionary dict = (COSDictionary) root
253: .getDictionaryObject("Outlines");
254: if (dict != null) {
255: retval = new PDDocumentOutline(dict);
256: }
257:
258: return retval;
259: }
260:
261: /**
262: * Set the document outlines.
263: *
264: * @param outlines The new document outlines.
265: */
266: public void setDocumentOutline(PDDocumentOutline outlines) {
267: root.setItem("Outlines", outlines);
268: }
269:
270: /**
271: * Get the list threads for this pdf document.
272: *
273: * @return A list of PDThread objects.
274: */
275: public List getThreads() {
276: COSArray array = (COSArray) root.getDictionaryObject("Threads");
277: if (array == null) {
278: array = new COSArray();
279: root.setItem("Threads", array);
280: }
281: List pdObjects = new ArrayList();
282: for (int i = 0; i < array.size(); i++) {
283: pdObjects.add(new PDThread((COSDictionary) array
284: .getObject(i)));
285: }
286: return new COSArrayList(pdObjects, array);
287: }
288:
289: /**
290: * Set the list of threads for this pdf document.
291: *
292: * @param threads The list of threads, or null to clear it.
293: */
294: public void setThreads(List threads) {
295: root.setItem("Threads", COSArrayList
296: .converterToCOSArray(threads));
297: }
298:
299: /**
300: * Get the metadata that is part of the document catalog. This will
301: * return null if there is no meta data for this object.
302: *
303: * @return The metadata for this object.
304: */
305: public PDMetadata getMetadata() {
306: PDMetadata retval = null;
307: COSStream stream = (COSStream) root
308: .getDictionaryObject("Metadata");
309: if (stream != null) {
310: retval = new PDMetadata(stream);
311: }
312: return retval;
313: }
314:
315: /**
316: * Set the metadata for this object. This can be null.
317: *
318: * @param meta The meta data for this object.
319: */
320: public void setMetadata(PDMetadata meta) {
321: root.setItem("Metadata", meta);
322: }
323:
324: /**
325: * Set the Document Open Action for this object.
326: *
327: * @param action The action you want to perform.
328: */
329: public void setOpenAction(PDDestinationOrAction action) {
330: root.setItem(COSName.getPDFName("OpenAction"), action);
331: }
332:
333: /**
334: * Get the Document Open Action for this object.
335: *
336: * @return The action to perform when the document is opened.
337: *
338: * @throws IOException If there is an error creating the destination
339: * or action.
340: */
341: public PDDestinationOrAction getOpenAction() throws IOException {
342: PDDestinationOrAction action = null;
343: COSBase actionObj = root.getDictionaryObject("OpenAction");
344:
345: if (actionObj == null) {
346: //no op
347: } else if (actionObj instanceof COSDictionary) {
348: action = PDActionFactory
349: .createAction((COSDictionary) actionObj);
350: } else if (actionObj instanceof COSArray) {
351: action = PDDestination.create(actionObj);
352: } else {
353: throw new IOException("Unknown OpenAction " + actionObj);
354: }
355:
356: return action;
357: }
358:
359: /**
360: * @return The Additional Actions for this Document
361: */
362: public PDDocumentCatalogAdditionalActions getActions() {
363: COSDictionary addAct = (COSDictionary) root
364: .getDictionaryObject("AA");
365: if (addAct == null) {
366: addAct = new COSDictionary();
367: root.setItem("AA", addAct);
368: }
369: return new PDDocumentCatalogAdditionalActions(addAct);
370: }
371:
372: /**
373: * Set the additional actions for the document.
374: *
375: * @param actions The actions that are associated with this document.
376: */
377: public void setActions(PDDocumentCatalogAdditionalActions actions) {
378: root.setItem("AA", actions);
379: }
380:
381: /**
382: * @return The names dictionary for this document or null if none exist.
383: */
384: public PDDocumentNameDictionary getNames() {
385: PDDocumentNameDictionary nameDic = null;
386: COSDictionary names = (COSDictionary) root
387: .getDictionaryObject("Names");
388: if (names != null) {
389: nameDic = new PDDocumentNameDictionary(this , names);
390: }
391: return nameDic;
392: }
393:
394: /**
395: * Set the names dictionary for the document.
396: *
397: * @param names The names dictionary that is associated with this document.
398: */
399: public void setNames(PDDocumentNameDictionary names) {
400: root.setItem("Names", names);
401: }
402:
403: /**
404: * Get info about doc's usage of tagged features. This will return
405: * null if there is no information.
406: *
407: * @return The new mark info.
408: */
409: public PDMarkInfo getMarkInfo() {
410: PDMarkInfo retval = null;
411: COSDictionary dic = (COSDictionary) root
412: .getDictionaryObject("MarkInfo");
413: if (dic != null) {
414: retval = new PDMarkInfo(dic);
415: }
416: return retval;
417: }
418:
419: /**
420: * Set information about the doc's usage of tagged features.
421: *
422: * @param markInfo The new MarkInfo data.
423: */
424: public void setMarkInfo(PDMarkInfo markInfo) {
425: root.setItem("MarkInfo", markInfo);
426: }
427:
428: /**
429: * Set the page display mode, see the PAGE_MODE_XXX constants.
430: * @return A string representing the page mode.
431: */
432: public String getPageMode() {
433: return root.getNameAsString("PageMode", PAGE_MODE_USE_NONE);
434: }
435:
436: /**
437: * Set the page mode. See the PAGE_MODE_XXX constants for valid values.
438: * @param mode The new page mode.
439: */
440: public void setPageMode(String mode) {
441: root.setName("PageMode", mode);
442: }
443:
444: /**
445: * Set the page layout, see the PAGE_LAYOUT_XXX constants.
446: * @return A string representing the page layout.
447: */
448: public String getPageLayout() {
449: return root.getNameAsString("PageLayout",
450: PAGE_LAYOUT_SINGLE_PAGE);
451: }
452:
453: /**
454: * Set the page layout. See the PAGE_LAYOUT_XXX constants for valid values.
455: * @param layout The new page layout.
456: */
457: public void setPageLayout(String layout) {
458: root.setName("PageLayout", layout);
459: }
460:
461: /**
462: * Document level information in the URI.
463: * @return Document level URI.
464: */
465: public PDActionURI getURI() {
466: PDActionURI retval = null;
467: COSDictionary uri = (COSDictionary) root
468: .getDictionaryObject("URI");
469: if (uri != null) {
470: retval = new PDActionURI(uri);
471: }
472: return retval;
473: }
474:
475: /**
476: * Set the document level uri.
477: * @param uri The new document level uri.
478: */
479: public void setURI(PDActionURI uri) {
480: root.setItem("URI", uri);
481: }
482:
483: /**
484: * Get the document's structure tree root.
485: *
486: * @return The document's structure tree root or null if none exists.
487: */
488: public PDStructureTreeRoot getStructureTreeRoot() {
489: PDStructureTreeRoot treeRoot = null;
490: COSDictionary dic = (COSDictionary) root
491: .getDictionaryObject("StructTreeRoot");
492: if (dic != null) {
493: treeRoot = new PDStructureTreeRoot(dic);
494: }
495: return treeRoot;
496: }
497:
498: /**
499: * Set the document's structure tree root.
500: *
501: * @param treeRoot The new structure tree.
502: */
503: public void setStructureTreeRoot(PDStructureTreeRoot treeRoot) {
504: root.setItem("StructTreeRoot", treeRoot);
505: }
506:
507: /**
508: * The language for the document.
509: *
510: * @return The language for the document.
511: */
512: public String getLanguage() {
513: return root.getString("Lang");
514: }
515:
516: /**
517: * Set the Language for the document.
518: *
519: * @param language The new document language.
520: */
521: public void setLanguage(String language) {
522: root.setString("Lang", language);
523: }
524: }
|