001: package com.etymon.pjx.util;
002:
003: import java.io.*;
004: import java.util.*;
005: import com.etymon.pjx.*;
006:
007: /**
008: Examines a specified object and returns the set of all objects it
009: references. This class implements the {@link PdfObjectFilter
010: PdfObjectFilter} interface. The {@link #preFilter(PdfObject)
011: preFilter(PdfObject)} method can be overridden in a subclass to
012: pre-process the object and its contents. This class is
013: synchronized.
014: @author Nassib Nassar
015: */
016: public class PdfReferencedObjects implements PdfObjectFilter {
017:
018: /**
019: The total set of referenced objects (stored as indirect
020: references).
021: */
022: protected Set _ref_master;
023:
024: /**
025: The current set of referenced objects (stored as indirect
026: references).
027: */
028: protected Set _ref;
029:
030: /**
031: The manager to use for resolving references.
032: */
033: protected PdfManager _m;
034:
035: /**
036: Constructs a <code>PdfReferencedObjects</code> instance.
037: @param manager the manager associated with the document.
038: */
039: public PdfReferencedObjects(PdfManager manager) {
040:
041: _m = manager;
042:
043: }
044:
045: /**
046: Returns the set of all objects referenced by the specified
047: PDF object. This method calls {@link
048: PdfObject#filter(PdfObjectFilter)
049: PdfObject.filter(PdfObjectFilter)} to process objects
050: recursively.
051: @param obj the object to examine.
052: @throws PdfFormatException
053: */
054: public Set getReferenced(PdfObject obj) throws IOException,
055: PdfFormatException {
056: synchronized (this ) {
057: synchronized (_m) {
058:
059: // get initial set of objects
060: _ref_master = new HashSet();
061: _ref = new HashSet();
062: PdfObject newObj = _m.getObjectIndirect(obj);
063: newObj.filter(this );
064:
065: _ref_master = _ref;
066: _ref = new HashSet();
067:
068: // now loop until all references have
069: // been resolved
070: Set left = new HashSet(_ref_master);
071: while (left.isEmpty() == false) {
072:
073: // take one element
074: PdfReference t = (PdfReference) left.iterator()
075: .next();
076: left.remove(t);
077:
078: newObj = _m.getObjectIndirect(t);
079: newObj.filter(this );
080:
081: left.addAll(_ref);
082: _ref_master.addAll(_ref);
083: _ref.clear();
084:
085: }
086:
087: _ref = null;
088: Set r = _ref_master;
089: _ref_master = null;
090: return r;
091:
092: }
093: }
094: }
095:
096: /**
097: This method is used by {@link #getReferenced(PdfObject)
098: getReferenced(PdfObject)} and <b>should not be called
099: externally</b>; however, it may be overridden in subclasses
100: in order to pre-process the objects. (It is not
101: synchronized.)
102: @param obj the object to filter.
103: @return the filtered object.
104: @throws PdfFormatException
105: */
106: public PdfObject preFilter(PdfObject obj) throws PdfFormatException {
107: return obj;
108: }
109:
110: /**
111: This method is used by {@link #getReferenced(PdfObject)
112: getReferenced(PdfObject)} and <b>should not be called
113: externally</b>. (It is not synchronized.)
114: @param obj the object to filter.
115: @return the filtered object.
116: @throws PdfFormatException
117: */
118: public PdfObject postFilter(PdfObject obj)
119: throws PdfFormatException {
120: if (obj instanceof PdfReference) {
121: if (_ref_master.contains(obj) == false) {
122: _ref.add(obj);
123: }
124: }
125: return obj;
126: }
127:
128: }
|