package com.sun.pdfview.action;
import java.io.IOException;
import java.util.ArrayList;
import com.sun.pdfview.PDFDestination;
import com.sun.pdfview.PDFObject;
import com.sun.pdfview.PDFParseException;
/*****************************************************************************
* Action directing to a location within an embedded PDF document
*
* @author Katja Sondermann
* @since 07.07.2009
****************************************************************************/
public class GoToEAction extends PDFAction {
/** the destination within the remote PDF file */
private PDFDestination destination;
/** the remote file this action refers to (optional)*/
private String file = null;
/** Should the remote file be opened in a new window? (optional)*/
private boolean newWindow = false;
/** The target dictionary*/
private GoToETarget target;
/**
* Creates a new instance of GoToEAction from an object
* @param obj the PDFObject with the action information
* @throws IOException - in case the action can not be parsed
*/
public GoToEAction(PDFObject obj, PDFObject root) throws IOException {
super("GoToE");
// find the destination and parse it
this.destination = PdfObjectParseUtil.parseDestination("D", obj, root, true);
// find the remote file and parse it
this.file = PdfObjectParseUtil.parseStringFromDict("F", obj, false);
// find the new window attribute and parse it if available
this.newWindow = PdfObjectParseUtil.parseBooleanFromDict("NewWindow", obj, false);
// parse the target dictionary
PDFObject targetObj = obj.getDictRef("T");
ArrayList<GoToETarget> list = new ArrayList<GoToETarget>();
this.target = parseTargetDistionary(targetObj, list);
}
/*************************************************************************
* Parse a target dictionary if available
* @param targetObj
* @param list - a list of all already parsed targets, for not getting in an endless loop
* (if a target is found which is already contained, the recursive calling
* of this method will stop).
* @throws IOException - in case a value can not be parsed
************************************************************************/
private GoToETarget parseTargetDistionary(PDFObject targetObj, ArrayList<GoToETarget> list) throws IOException {
GoToETarget target = null;
if (targetObj != null) {
target = new GoToETarget();
// find the relation and parse it
target.setRelation(PdfObjectParseUtil.parseStringFromDict("R", targetObj, true));
// find the name of the embedded file and parse it
target.setNameInTree(PdfObjectParseUtil.parseStringFromDict("N", targetObj, false));
// find the page number and parse it
String page = PdfObjectParseUtil.parseStringFromDict("P", targetObj, false);
if(page == null){
page = ""+PdfObjectParseUtil.parseIntegerFromDict("P", targetObj, false);
}
target.setPageNo(page);
// find the annotation index and parse it
String annot = PdfObjectParseUtil.parseStringFromDict("A", targetObj, false);
if(annot == null){
annot = ""+PdfObjectParseUtil.parseIntegerFromDict("A", targetObj, false);
}
target.setAnnotNo(annot);
//find target dictionary and parse it
PDFObject subTargetObj = targetObj.getDictRef("T");
if(subTargetObj != null){
// call this method recursive, in case the target was not already contained in the
// list (this is checked for not getting into an infinite loop)
if(list.contains(target) == false){
list.add(target);
GoToETarget subTargetDictionary = parseTargetDistionary(subTargetObj, list);
target.setTargetDictionary(subTargetDictionary);
}
}
} else {
if (this.file == null) {
throw new PDFParseException("No target dictionary in GoToE action " + targetObj);
}
}
return target;
}
/*************************************************************************
* Create a new GoToEAction from the given attributes
* @param dest
* @param file
* @param newWindow
************************************************************************/
public GoToEAction(PDFDestination dest, String file, boolean newWindow) {
super("GoToR");
this.file = file;
this.destination = dest;
this.newWindow = newWindow;
}
/*************************************************************************
* Get the destination this action refers to
* @return PDFDestination
************************************************************************/
public PDFDestination getDestination() {
return this.destination;
}
/*************************************************************************
* Get the file this action refers to
* @return PDFDestination
************************************************************************/
public String getFile() {
return this.file;
}
/*************************************************************************
* Should the remote file be opened in a new window?
* @return boolean
************************************************************************/
public boolean isNewWindow() {
return this.newWindow;
}
/*************************************************************************
* Get the target dictionary
* @return GoToETarget
************************************************************************/
public GoToETarget getTarget() {
return this.target;
}
/*****************************************************************************
* Inner class for holding the target dictionary's information
*
* @version $Id: GoToEAction.java,v 1.1 2009-07-10 12:47:31 xond Exp $
* @author xond
* @since 07.07.2009
****************************************************************************/
public static class GoToETarget {
private String relation;
private String nameInTree;
private String pageNo;
private String annotNo;
private GoToETarget targetDictionary;
/*************************************************************************
* Relation between current document and the target. Can either be "P" or "C"
* @return String
************************************************************************/
public String getRelation() {
return this.relation;
}
/*************************************************************************
* Relation between current document and the target. Can either be "P" or "C"
* @param relation
************************************************************************/
public void setRelation(String relation) {
this.relation = relation;
}
/*************************************************************************
* The file name in the embedded files tree
* @return String
************************************************************************/
public String getNameInTree() {
return this.nameInTree;
}
/*************************************************************************
* The file name in the embedded files tree
* @param nameInTree
************************************************************************/
public void setNameInTree(String nameInTree) {
this.nameInTree = nameInTree;
}
/*************************************************************************
* Page Number:
* If the value can be parsed as Integer, it specifies the page number in
* the current document containing the file attachment annotation. If the
* value is a string, it defines a named destination in the current document
* that provides the page number of the file attachment annotation.
*
* @return String
************************************************************************/
public String getPageNo() {
return this.pageNo;
}
/*************************************************************************
* Page Number:
* If the value can be parsed as Integer, it specifies the page number in
* the current document containing the file attachment annotation. If the
* value is a string, it defines a named destination in the current document
* that provides the page number of the file attachment annotation.
*
* @param pageNo
************************************************************************/
public void setPageNo(String pageNo) {
this.pageNo = pageNo;
}
/*************************************************************************
* The index of the according annotation in the annotations array
* @return String
************************************************************************/
public String getAnnotNo() {
return this.annotNo;
}
/*************************************************************************
* The index of the according annotation in the annotations array
* @param annotNo
************************************************************************/
public void setAnnotNo(String annotNo) {
this.annotNo = annotNo;
}
/*************************************************************************
* A target dictionary specifying additional target information. If missing,
* the current document is the target file containing the destination.
* @return GoToETarget
************************************************************************/
public GoToETarget getTargetDictionary() {
return this.targetDictionary;
}
/*************************************************************************
* A target dictionary specifying additional target information. If missing,
* the current document is the target file containing the destination.
* @param targetDictionary
************************************************************************/
public void setTargetDictionary(GoToETarget targetDictionary) {
this.targetDictionary = targetDictionary;
}
@Override
public boolean equals(Object obj) {
if((obj instanceof GoToETarget) == false){
return false;
}
if(super.equals(obj)){
return true;
}
GoToETarget that = (GoToETarget)obj;
// compare the strng values, as the attributes may also be null
return String.valueOf(this.annotNo).equals(String.valueOf(that.annotNo))
&& String.valueOf(this.nameInTree).equals(String.valueOf(that.nameInTree))
&& String.valueOf(this.pageNo).equals(String.valueOf(that.pageNo))
&& String.valueOf(this.relation).equals(String.valueOf(that.relation));
}
}
}