/*
* Copyright 2006-2012 ICEsoft Technologies Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.icepdf.core.pobjects;
import org.icepdf.core.application.ProductInfo;
import org.icepdf.core.util.Library;
import java.util.Hashtable;
import java.util.logging.Logger;
import java.util.logging.Level;
/**
* <p>The <code>Catalog</code> object represents the root of a PDF document's
* object heirarchy. The <code>Catalog</code> is located by means of the
* <b>Root</b> entry in the trailer of the PDF file. The catalog contains
* references to other objects defining the document's contents, outline, names,
* destinations, and other attributes.</p>
* <p/>
* <p>The <code>Catalog</code> class can be accessed from the {@see Document}
* class for convenience, but can also be accessed via the {@see PTrailer} class.
* Useful information about the document can be extracted from the Catalog
* Dictionary, such as PDF version information and Viewer Preferences. All
* Catalog dictionary properties can be accesed via the getEntries method.
* See section 3.6.1 of the PDF Reference version 1.6 for more information on
* the properties available in the Catalog Object. </p>
*
* @since 1.0
*/
public class Catalog extends Dictionary {
private static final Logger logger =
Logger.getLogger(Catalog.class.toString());
private PageTree pageTree;
private Outlines outlines;
private NameTree nameTree;
private Dictionary dests;
private ViewerPreferences viewerPref;
private boolean outlinesInited = false;
private boolean namesTreeInited = false;
private boolean destsInited = false;
private boolean viewerPrefInited = false;
// Announce ICEpdf Core
static {
//if (logger.isLoggable(Level.INFO)) {
// logger.info("ICEsoft ICEpdf Core " + Document.getLibraryVersion());
//}
}
/**
* Creates a new instance of a Catalog.
*
* @param l document library.
* @param h Catalog dictionary entries.
*/
public Catalog(Library l, Hashtable h) {
super(l, h);
}
/**
* Initiate the PageTree.
*/
public synchronized void init() {
Object tmp = library.getObject(entries, "Pages");
pageTree = null;
if (tmp instanceof PageTree) {
pageTree = (PageTree) tmp;
}
// malformed core corner case, pages must not be references, but we
// have a couple cases that break the spec.
else if (tmp instanceof Hashtable) {
pageTree = new PageTree(library, (Hashtable) tmp);
}
try {
pageTree.init();
pageTree.initRootPageTree();
}
catch (NullPointerException e) {
logger.log(Level.FINE, "Error parsing page tree.", e);
}
}
/**
* Dispose the Catalog.
*
* @param cache if true, cached files are removed, otherwise objects are freed
* but object caches are left intact.
*/
public void dispose(boolean cache) {
// dispose the nameTree
if (nameTree != null) {
nameTree.dispose();
namesTreeInited = false;
if (!cache)
nameTree = null;
}
if (pageTree != null) {
pageTree.dispose(cache);
if (!cache)
pageTree = null;
}
if (outlines != null) {
if (!cache) {
outlines.dispose();
outlines = null;
}
}
}
/**
* Gets PageTree node that is the root of the document's page tree.
* The PageTree can be traversed to access child PageTree and Page objects.
*
* @return Catalogs PageTree.
* @see org.icepdf.core.pobjects.Page
*/
public PageTree getPageTree() {
return pageTree;
}
/**
* Gets the Outlines Dictionary that is the root of the document's outline
* hierarchy. The Outline can be traversed to access child OutlineItems.
*
* @return Outlines object if one exists; null, otherwise.
* @see org.icepdf.core.pobjects.OutlineItem
*/
public Outlines getOutlines() {
if (!outlinesInited) {
outlinesInited = true;
Object o = library.getObject(entries, "Outlines");
if (o != null)
outlines = new Outlines(library, (Hashtable) o);
}
return outlines;
}
/**
* Gets the document's Names dictionary. The Names dictionary contains
* a category of objects in a PDF file which can be referred to by name
* rather than by object reference.
*
* @return name dictionary for document. If no name dictionary exists null
* is returned.
*/
public NameTree getNameTree() {
if (!namesTreeInited) {
namesTreeInited = true;
Object o = library.getObject(entries, "Names");
if (o != null && o instanceof Hashtable) {
Hashtable dest = (Hashtable) o;
Object names = library.getObject(dest, "Dests");
if (names != null && names instanceof Hashtable) {
nameTree = new NameTree(library, (Hashtable) names);
nameTree.init();
}
}
}
return nameTree;
}
/**
* Gets a dictionary of names and corresponding destinations.
*
* @return A Dictionary of Destinations; if none, null is returned.
*/
public Dictionary getDestinations() {
if (!destsInited) {
destsInited = true;
Object o = library.getObject(entries, "Dests");
if (o != null) {
dests = new Dictionary(library, (Hashtable) o);
dests.init();
}
}
return dests;
}
/**
* Gets a dictionary of keys and corresponding viewer preferences
* This can be used to pull information based on the PDF specification,
* such as HideToolbar or FitWindow
*
* @return the constructed ViewerPreferences object
*/
public ViewerPreferences getViewerPreferences() {
if (!viewerPrefInited) {
viewerPrefInited = true;
Object o = library.getObject(entries, "ViewerPreferences");
if (o != null) {
viewerPref = new ViewerPreferences(library, (Hashtable) o);
viewerPref.init();
}
}
return viewerPref;
}
/**
* Returns a summary of the Catalog dictionary values.
*
* @return dictionary values.
*/
public String toString() {
return "CATALOG= " + entries.toString();
}
}