// Copyright 2001 freehep
package org.freehep.graphicsio.pdf;
import java.io.IOException;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Vector;
/**
* This class keeps track of all kinds of objects written to a pdf file and
* avoids to write them several times instead of referencing the same object
* several times. Right now only encoding tables are supported.
*
* An implementation for images and paint would be possible.
*
* @author Simon Fischer
* @version $Id: freehep-graphicsio-pdf/src/main/java/org/freehep/graphicsio/pdf/PDFRedundanceTracker.java f493ff6e61b2 2005/12/01 18:46:43 duns $
*/
public class PDFRedundanceTracker {
/**
* To be implemented by Writers which write objects that may already have
* been written.
*/
public interface Writer {
public void writeObject(Object o, PDFRef reference, PDFWriter pdf)
throws IOException;
}
private class Entry {
private static final String REF_PREFIX = "PDF_RTObj";
private Object object;
private Writer writer;
private boolean written;
private PDFRef reference;
private Object groupID;
private Entry(Object o, Object groupID, Writer w) {
this.object = o;
this.groupID = groupID;
this.writer = w;
this.written = false;
this.reference = pdf.ref(REF_PREFIX + (refCount++));
}
}
private static int refCount = 1;
private PDFWriter pdf;
private Map<Object, Entry> objects;
private Vector<Entry> orderedObjects; // to keep order
public PDFRedundanceTracker(PDFWriter pdf) {
this.pdf = pdf;
objects = new Hashtable<Object, Entry>();
orderedObjects = new Vector<Entry>();
}
/**
* Returns a reference that points to <tt>object</tt>. When this method
* is called several times for the same object (according to its hash code)
* the same reference is returned. When <tt>writeAll()</tt> is called the
* writer's <tt>writeObject()</tt> method will be called once with
* <tt>object</tt> as argument.<br>
* The groupID is only used for <tt>getGroup()</tt>
*/
public PDFRef getReference(Object object, Object groupID, Writer writer) {
Object o = objects.get(object);
if (o != null) {
return ((Entry) o).reference;
} else {
Entry entry = new Entry(object, groupID, writer);
objects.put(object, entry);
orderedObjects.add(entry);
return entry.reference;
}
}
public PDFRef getReference(Object object, Writer writer) {
return getReference(object, null, writer);
}
/**
* Writes all objects that are not yet written. If the method is called
* several times then each times only the new objects are written.
*/
public void writeAll() {
Iterator<Entry> i = orderedObjects.iterator();
while (i.hasNext()) {
Entry entry = i.next();
if (!entry.written) {
try {
// System.out.println("PDFRT: Writing: " + entry.object);
entry.writer
.writeObject(entry.object, entry.reference, pdf);
entry.written = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/** Returns all objects belonging to a particular group. */
public Collection<Object> getGroup(Object groupID) {
Collection<Object> result = new LinkedList<Object>();
Iterator<Entry> i = orderedObjects.iterator();
while (i.hasNext()) {
Entry entry = i.next();
if (groupID.equals(entry.groupID)) {
result.add(entry.object);
}
}
return result;
}
}