View Javadoc

1   // Copyright 2001 freehep
2   package org.freehep.graphicsio.pdf;
3   
4   import java.io.IOException;
5   import java.util.Collection;
6   import java.util.Hashtable;
7   import java.util.Iterator;
8   import java.util.LinkedList;
9   import java.util.Map;
10  import java.util.Vector;
11  
12  /**
13   * This class keeps track of all kinds of objects written to a pdf file and
14   * avoids to write them several times instead of referencing the same object
15   * several times. Right now only encoding tables are supported.
16   * 
17   * An implementation for images and paint would be possible.
18   * 
19   * @author Simon Fischer
20   * @version $Id: PDFRedundanceTracker.java 8584 2006-08-10 23:06:37Z duns $
21   */
22  public class PDFRedundanceTracker {
23  
24      /**
25       * To be implemented by Writers which write objects that may already have
26       * been written.
27       */
28      public interface Writer {
29          public void writeObject(Object o, PDFRef reference, PDFWriter pdf)
30                  throws IOException;
31      }
32  
33      private class Entry {
34          private static final String REF_PREFIX = "PDF_RTObj";
35  
36          private Object object;
37  
38          private Writer writer;
39  
40          private boolean written;
41  
42          private PDFRef reference;
43  
44          private Object groupID;
45  
46          private Entry(Object o, Object groupID, Writer w) {
47              this.object = o;
48              this.groupID = groupID;
49              this.writer = w;
50              this.written = false;
51              this.reference = pdf.ref(REF_PREFIX + (refCount++));
52          }
53      }
54  
55      private static int refCount = 1;
56  
57      private PDFWriter pdf;
58  
59      private Map objects;
60  
61      private Vector orderedObjects; // to keep order
62  
63      public PDFRedundanceTracker(PDFWriter pdf) {
64          this.pdf = pdf;
65          objects = new Hashtable();
66          orderedObjects = new Vector();
67      }
68  
69      /**
70       * Returns a reference that points to <tt>object</tt>. When this method
71       * is called several times for the same object (according to its hash code)
72       * the same reference is returned. When <tt>writeAll()</tt> is called the
73       * writer's <tt>writeObject()</tt> method will be called once with
74       * <tt>object</tt> as argument.<br>
75       * The groupID is only used for <tt>getGroup()</tt>
76       */
77      public PDFRef getReference(Object object, Object groupID, Writer writer) {
78          Object o = objects.get(object);
79          if (o != null) {
80              return ((Entry) o).reference;
81          } else {
82              Entry entry = new Entry(object, groupID, writer);
83              objects.put(object, entry);
84              orderedObjects.add(entry);
85              return entry.reference;
86          }
87      }
88  
89      public PDFRef getReference(Object object, Writer writer) {
90          return getReference(object, null, writer);
91      }
92  
93      /**
94       * Writes all objects that are not yet written. If the method is called
95       * several times then each times only the new objects are written.
96       */
97      public void writeAll() {
98          Iterator i = orderedObjects.iterator();
99          while (i.hasNext()) {
100             Entry entry = (Entry) i.next();
101             if (!entry.written) {
102                 try {
103                     // System.out.println("PDFRT: Writing: " + entry.object);
104                     entry.writer
105                             .writeObject(entry.object, entry.reference, pdf);
106                     entry.written = true;
107                 } catch (IOException e) {
108                     e.printStackTrace();
109                 }
110             }
111         }
112     }
113 
114     /** Returns all objects belonging to a particular group. */
115     public Collection getGroup(Object groupID) {
116         Collection result = new LinkedList();
117         Iterator i = orderedObjects.iterator();
118         while (i.hasNext()) {
119             Entry entry = (Entry) i.next();
120             if (groupID.equals(entry.groupID)) {
121                 result.add(entry.object);
122             }
123         }
124         return result;
125     }
126 }