/*
* $Id$
*
* Copyright 2007 Bruno Lowagie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.lowagie.rups.view.itext.treenodes;
import com.lowagie.rups.view.icons.IconFetcher;
import com.lowagie.rups.view.icons.IconTreeNode;
import com.lowagie.text.pdf.PdfDictionary;
import com.lowagie.text.pdf.PdfIndirectReference;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfObject;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfString;
/**
* Every node in our tree corresponds with a PDF object.
* This class is the superclass of all tree nodes used.
*/
public class PdfObjectTreeNode extends IconTreeNode {
/** the PDF object corresponding with this node. */
protected PdfObject object;
/** the key if the parent of this node is a dictionary. */
protected PdfName key = null;
/** if the object is indirect, the number of the PDF object. */
protected int number = -1;
/** indicates if the object is indirect and recursive. */
protected boolean recursive = false;
/**
* Creates a tree node for a PDF object.
* @param object the PDF object represented by this tree node.
*/
protected PdfObjectTreeNode(PdfObject object) {
super(null, getCaption(object));
this.object = object;
switch(object.type()) {
case PdfObject.INDIRECT:
if (isRecursive())
icon = IconFetcher.getIcon("ref_recursive.png");
else
icon = IconFetcher.getIcon("ref.png");
return;
case PdfObject.ARRAY:
icon = IconFetcher.getIcon("array.png");
return;
case PdfObject.DICTIONARY:
icon = IconFetcher.getIcon("dictionary.png");
return;
case PdfObject.STREAM:
icon = IconFetcher.getIcon("stream.png");
return;
case PdfObject.BOOLEAN:
icon = IconFetcher.getIcon("boolean.png");
return;
case PdfObject.NAME:
icon = IconFetcher.getIcon("name.png");
return;
case PdfObject.NULL:
icon = IconFetcher.getIcon("null.png");
return;
case PdfObject.NUMBER:
icon = IconFetcher.getIcon("number.png");
return;
case PdfObject.STRING:
icon = IconFetcher.getIcon("string.png");
return;
}
}
/**
* Creates a tree node for a PDF object.
* @param icon the file with the icon
* @param object the PDF object represented by this tree node.
*/
protected PdfObjectTreeNode(String icon, PdfObject object) {
super(icon, getCaption(object));
this.object = object;
}
/**
* Creates an instance of a tree node for a PDF object.
* @param object the PDF object represented by this tree node.
* @return a PdfObjectTreeNode
*/
public static PdfObjectTreeNode getInstance(PdfObject object) {
if (object.isDictionary()) {
if (PdfName.PAGE.equals(((PdfDictionary)object).get(PdfName.TYPE))) {
return new PdfPageTreeNode((PdfDictionary)object);
}
else if (PdfName.PAGES.equals(((PdfDictionary)object).get(PdfName.TYPE))) {
return new PdfPagesTreeNode((PdfDictionary)object);
}
}
return new PdfObjectTreeNode(object);
}
/**
* Creates an instance of a tree node for an indirect object.
* @param object the PDF object represented by this tree node.
* @param number the xref number of the indirect object
* @return a PdfObjectTreeNode
*/
public static PdfObjectTreeNode getInstance(PdfObject object, int number) {
PdfObjectTreeNode node = getInstance(object);
node.number = number;
return node;
}
/**
* Creates an instance of a tree node for the object corresponding with a key in a dictionary.
* @param dict the dictionary that is the parent of this tree node.
* @param key the dictionary key corresponding with the PDF object in this tree node.
* @return a PdfObjectTreeNode
*/
public static PdfObjectTreeNode getInstance(PdfDictionary dict, PdfName key) {
PdfObjectTreeNode node = getInstance(dict.get(key));
node.setUserObject(getDictionaryEntryCaption(dict, key));
node.key = key;
return node;
}
/**
* Getter for the PDF Object.
* @return the PDF object represented by this tree node.
*/
public PdfObject getPdfObject() {
return object;
}
/**
* Getter for the object number in case the object is indirect.
* @return -1 for direct objects; the object number for indirect objects
*/
public int getNumber() {
if (isIndirectReference()) {
return ((PdfIndirectReference)object).getNumber();
}
return number;
}
/**
* Tells you if the node contains an indirect reference.
* @return true if the object is an indirect reference
*/
public boolean isIndirectReference() {
return object.type() == PdfObject.INDIRECT;
}
/**
* Tells you if the object is indirect.
* @return true for indirect objects; false for direct objects.
*/
public boolean isIndirect() {
return isIndirectReference() || number > -1;
}
/**
* Tells you if the node contains an array.
* @return true if the object is a PdfArray
*/
public boolean isArray() {
return object.isArray();
}
/**
* Checks if this node is a dictionary item with a specific key.
* @param key the key of the node we're looking for
*/
public boolean isDictionaryNode(PdfName key) {
if (key == null) return false;
return key.equals(this.key);
}
/**
* Tells you if the node contains a dictionary.
* @return true if the object is a PdfDictionary
*/
public boolean isDictionary() {
return object.isDictionary();
}
/**
* Tells you if the node contains a stream.
* @return true if the object is a PRStream
*/
public boolean isStream() {
return object.isStream();
}
/**
* Set this to true if the object is a reference to a node higher up in the tree.
* @param recursive true if the object is indirect and recursive
*/
public void setRecursive(boolean recursive) {
this.recursive = recursive;
}
/**
* Tells you if the object is a reference to a node higher up in the tree.
* @return true if the node is used recursively.
*/
public boolean isRecursive() {
return recursive;
}
/**
* Creates the caption for a PDF object.
* @param object the object for which a caption has to be created.
* @return a caption for a PDF object
*/
public static String getCaption(PdfObject object) {
if (object == null)
return "null";
switch (object.type()) {
case PdfObject.INDIRECT:
{
String reffedCaption = getCaption( PdfReader.getPdfObject( object ) );
return object.toString() + " -> " + reffedCaption;
}
case PdfObject.ARRAY:
return "Array";
case PdfObject.STREAM:
return "Stream";
case PdfObject.STRING:
return ((PdfString)object).toUnicodeString();
}
return object.toString();
}
/**
* Creates the caption for an object that is a dictionary entry.
* @param dict a dictionary
* @param key a key in the dictionary
* @return a caption for the object corresponding with the key in the dictionary.
*/
public static String getDictionaryEntryCaption(PdfDictionary dict, PdfName key) {
StringBuffer buf = new StringBuffer(key.toString());
buf.append(": ");
PdfObject valObj = dict.get(key);
if (valObj.isIndirect()) {
buf.append( getCaption( valObj ) );
} else {
buf.append(dict.get(key).toString());
}
return buf.toString();
}
/**
* Gets the tree path of an ancestor.
* This only works with recursive references
* @return the treepath to an ancestor
*/
public PdfObjectTreeNode getAncestor() {
if (isRecursive()) {
PdfObjectTreeNode node = this;
while(true) {
node = (PdfObjectTreeNode)node.getParent();
if (node.isIndirectReference() && node.getNumber() == getNumber()) {
return node;
}
}
}
return null;
}
/** a serial version UID. */
private static final long serialVersionUID = -5617844659397445879L;
}