/*
* $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.model;
import java.util.ArrayList;
import com.lowagie.text.pdf.IntHashtable;
import com.lowagie.text.pdf.PdfDictionary;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfNull;
import com.lowagie.text.pdf.PdfObject;
import com.lowagie.text.pdf.PdfReader;
/**
* A factory that can produce all the indirect objects in a PDF file.
*/
public class IndirectObjectFactory {
/** The reader object. */
protected PdfReader reader;
/** The current xref number. */
protected int current;
/** The highest xref number. */
protected int n;
/** A list of all the indirect objects in a PDF file. */
protected ArrayList<PdfObject> objects = new ArrayList<PdfObject>();
/** Mapping between the index in the objects list and the reference number in the xref table. */
protected IntHashtable idxToRef = new IntHashtable();
/** Mapping between the reference number in the xref table and the index in the objects list . */
protected IntHashtable refToIdx = new IntHashtable();
/**
* Creates a list that will contain all the indirect objects
* in a PDF document.
* @param reader the reader that will read the PDF document
*/
public IndirectObjectFactory(PdfReader reader) {
this.reader = reader;
current = -1;
n = reader.getXrefSize();
}
/**
* Gets the last object that has been registered.
* This method only makes sense while loading the factory.
* with loadNextObject().
* @return the number of the last object that was stored
*/
public int getCurrent() {
return current;
}
/**
* Gets the highest possible object number in the XRef table.
* @return an object number
*/
public int getXRefMaximum() {
return n;
}
/**
* Stores the next object of the XRef table.
* As soon as this method returns false, it makes no longer
* sense calling it as all the objects have been stored.
* @return false if there are no objects left to check.
*/
public boolean storeNextObject() {
while (current < n) {
current++;
PdfObject object = reader.getPdfObjectRelease(current);
if (object != null) {
int idx = size();
idxToRef.put(idx, current);
refToIdx.put(current, idx);
store(object);
return true;
}
}
return false;
}
/**
* If we store all the objects, we might run out of memory;
* that's why we'll only store the objects that are necessary
* to construct other objects (for instance the page table).
* @param object an object we might want to store
*/
private void store(PdfObject object) {
if (object.isDictionary()){
PdfDictionary dict = (PdfDictionary)object;
if (PdfName.PAGE.equals(dict.get(PdfName.TYPE))) {
objects.add(dict);
return;
}
}
objects.add(PdfNull.PDFNULL);
}
/**
* Gets the total number of indirect objects in the PDF file.
* This isn't necessarily the same number as returned by getXRefMaximum().
* The PDF specification allows gaps between object numbers.
* @return the total number of indirect objects in the PDF.
*/
public int size() {
return objects.size();
}
/**
* Gets the index of an object based on its number in the xref table.
* @param ref a number in the xref table
* @return the index in the list of indirect objects
*/
public int getIndexByRef(int ref) {
return refToIdx.get(ref);
}
/**
* Gets the reference number in the xref table based on the index in the
* indirect object list.
* @param i the index of an object in the indirect object list
* @return the corresponding reference number in the xref table
*/
public int getRefByIndex(int i) {
return idxToRef.get(i);
}
/**
* Gets an object based on its index in the indirect object list.
* @param i an index in the indirect object list
* @return a PDF object
*/
public PdfObject getObjectByIndex(int i) {
return getObjectByReference(getRefByIndex(i));
}
/**
* Gets an object based on its reference number in the xref table.
* @param ref a number in the xref table
* @return a PDF object
*/
public PdfObject getObjectByReference(int ref) {
return objects.get(getIndexByRef(ref));
}
/**
* Loads an object based on its reference number in the xref table.
* @param ref a reference number in the xref table.
* @return a PDF object
*/
public PdfObject loadObjectByReference(int ref) {
PdfObject object = getObjectByReference(ref);
if (object instanceof PdfNull) {
int idx = getIndexByRef(ref);
object = reader.getPdfObject(ref);
objects.set(idx, object);
}
return object;
}
}