]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Move out all statistics/debug related code into an inner Statistics class.
authorVincent Hennebert <vhennebert@apache.org>
Fri, 20 Apr 2007 08:04:55 +0000 (08:04 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Fri, 20 Apr 2007 08:04:55 +0000 (08:04 +0000)
Patch submitted by Adrian Cumiskey (fop-dev AT cumiskey DOT com)

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@530682 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/area/AreaTreeHandler.java

index e7f6effe034457a24cf3d03cb2daea47e186036a..d818a0d83fa34ac73d6c9e075d7133df7e25828a 100644 (file)
@@ -53,36 +53,23 @@ import org.apache.fop.fo.extensions.destination.Destination;
 
 /**
  * Area tree handler for formatting objects.
- *
- * Concepts:
- * The area tree is to be as small as possible. With minimal classes
- * and data to fully represent an area tree for formatting objects.
- * The area tree needs to be simple to render and follow the spec
- * closely.
- * This area tree has the concept of page sequences.
- * Wherever possible information is discarded or optimized to
- * keep memory use low. The data is also organized to make it
- * possible for renderers to minimize their output.
- * A page can be saved if not fully resolved and once rendered
- * a page contains only size and id reference information.
- * The area tree pages are organized in a model that depends on the
+ * 
+ * Concepts: The area tree is to be as small as possible. With minimal classes
+ * and data to fully represent an area tree for formatting objects. The area
+ * tree needs to be simple to render and follow the spec closely. This area tree
+ * has the concept of page sequences. Wherever possible information is discarded
+ * or optimized to keep memory use low. The data is also organized to make it
+ * possible for renderers to minimize their output. A page can be saved if not
+ * fully resolved and once rendered a page contains only size and id reference
+ * information. The area tree pages are organized in a model that depends on the
  * type of renderer.
  */
 public class AreaTreeHandler extends FOEventHandler {
 
-    private static Log log = LogFactory.getLog(AreaTreeHandler.class);
-
-    // show statistics after document complete?
-    private boolean outputStatistics;
-
-    // for statistics gathering
-    private Runtime runtime;
-
-    // heap memory allocated (for statistics)
-    private long initialMemory;
+    /** debug statistics */
+    private Statistics statistics = null;
 
-    // time used in rendering (for statistics)
-    private long startTime;
+    private static Log log = LogFactory.getLog(AreaTreeHandler.class);
 
     // the LayoutManager maker
     private LayoutManagerMaker lmMaker;
@@ -93,66 +80,68 @@ public class AreaTreeHandler extends FOEventHandler {
     // The fo:root node of the document
     private Root rootFObj;
 
-    // HashMap of ID's whose area is located on one or more consecutive 
-    // PageViewports.  Each ID has an arraylist of PageViewports that
+    // HashMap of ID's whose area is located on one or more consecutive
+    // PageViewports. Each ID has an arraylist of PageViewports that
     // form the defined area of this ID
     private Map idLocations = new HashMap();
 
     // idref's whose target PageViewports have yet to be identified
     // Each idref has a HashSet of Resolvable objects containing that idref
     private Map unresolvedIDRefs = new HashMap();
-    
+
     private Set unfinishedIDs = new HashSet();
+
     private Set alreadyResolvedIDs = new HashSet();
 
-     // The formatting results to be handed back to the caller.
+    // The formatting results to be handed back to the caller.
     private FormattingResults results = new FormattingResults();
 
     private PageSequenceLayoutManager prevPageSeqLM;
 
     private int idGen = 0;
-    
+
     /**
      * Constructor.
+     * 
      * @param userAgent FOUserAgent object for process
-     * @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
+     * @param outputFormat the MIME type of the output format to use (ex.
+     * "application/pdf").
      * @param stream OutputStream
      * @throws FOPException if the RenderPagesModel cannot be created
      */
-    public AreaTreeHandler (FOUserAgent userAgent, String outputFormat, 
-                OutputStream stream) throws FOPException {
+    public AreaTreeHandler(FOUserAgent userAgent, String outputFormat,
+            OutputStream stream) throws FOPException {
         super(userAgent);
 
         setupModel(userAgent, outputFormat, stream);
-            
+
         lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride();
         if (lmMaker == null) {
             lmMaker = new LayoutManagerMapping();
         }
 
-        outputStatistics = log.isDebugEnabled();
-
-        if (outputStatistics) {
-            runtime = Runtime.getRuntime();
+        if (log.isDebugEnabled()) {
+            statistics = new Statistics();
         }
     }
 
     /**
      * Sets up the AreaTreeModel instance for use by the AreaTreeHandler.
+     * 
      * @param userAgent FOUserAgent object for process
-     * @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
+     * @param outputFormat the MIME type of the output format to use (ex.
+     * "application/pdf").
      * @param stream OutputStream
      * @throws FOPException if the RenderPagesModel cannot be created
      */
-    protected void setupModel(FOUserAgent userAgent, String outputFormat, 
+    protected void setupModel(FOUserAgent userAgent, String outputFormat,
             OutputStream stream) throws FOPException {
-        model = new RenderPagesModel(userAgent, outputFormat, fontInfo,
-                stream);
+        model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream);
     }
-    
+
     /**
      * Get the area tree model for this area tree.
-     *
+     * 
      * @return AreaTreeModel the model being used for this area tree
      */
     public AreaTreeModel getAreaTreeModel() {
@@ -161,17 +150,19 @@ public class AreaTreeHandler extends FOEventHandler {
 
     /**
      * Get the LayoutManager maker for this area tree.
-     *
-     * @return LayoutManagerMaker the LayoutManager maker being used for this area tree
+     * 
+     * @return LayoutManagerMaker the LayoutManager maker being used for this
+     *         area tree
      */
     public LayoutManagerMaker getLayoutManagerMaker() {
         return lmMaker;
     }
 
     /**
-     * Tie a PageViewport with an ID found on a child area of the PV.
-     * Note that an area with a given ID may be on more than one PV, hence
-     * an ID may have more than one PV associated with it.
+     * Tie a PageViewport with an ID found on a child area of the PV. Note that
+     * an area with a given ID may be on more than one PV, hence an ID may have
+     * more than one PV associated with it.
+     * 
      * @param id the property ID of the area
      * @param pv a page viewport that contains the area with this ID
      */
@@ -185,22 +176,23 @@ public class AreaTreeHandler extends FOEventHandler {
             idLocations.put(id, pvList);
             pvList.add(pv);
 
-            /* 
-             * See if this ID is in the unresolved idref list, if so
-             * resolve Resolvable objects tied to it.
+            /*
+             * See if this ID is in the unresolved idref list, if so resolve
+             * Resolvable objects tied to it.
              */
             if (!unfinishedIDs.contains(id)) {
-              tryIDResolution(id, pv, pvList);
+                tryIDResolution(id, pv, pvList);
             }
         } else {
             pvList.add(pv);
         }
     }
-    
+
     /**
-     * This method tie an ID to the areaTreeHandler until this one is
-     * ready to be processed. This is used in page-number-citation-last processing so we know
-     * when an id can be resolved.
+     * This method tie an ID to the areaTreeHandler until this one is ready to
+     * be processed. This is used in page-number-citation-last processing so we
+     * know when an id can be resolved.
+     * 
      * @param id the id of the object being processed
      */
     public void signalPendingID(String id) {
@@ -209,23 +201,25 @@ public class AreaTreeHandler extends FOEventHandler {
         }
         unfinishedIDs.add(id);
     }
-    
+
     /**
-     * Signals that all areas for the formatting object with the given ID have been generated.
-     * This is used to determine when page-number-citation-last ref-ids can be resolved.
+     * Signals that all areas for the formatting object with the given ID have
+     * been generated. This is used to determine when page-number-citation-last
+     * ref-ids can be resolved.
+     * 
      * @param id the id of the formatting object which was just finished
      */
     public void signalIDProcessed(String id) {
         if (log.isDebugEnabled()) {
             log.debug("signalIDProcessed(" + id + ")");
         }
-        
+
         alreadyResolvedIDs.add(id);
         if (!unfinishedIDs.contains(id)) {
             return;
         }
         unfinishedIDs.remove(id);
-        
+
         List pvList = (List) idLocations.get(id);
         Set todo = (Set) unresolvedIDRefs.get(id);
         if (todo != null) {
@@ -236,9 +230,10 @@ public class AreaTreeHandler extends FOEventHandler {
             unresolvedIDRefs.remove(id);
         }
     }
-    
+
     /**
      * Check if an ID has already been resolved
+     * 
      * @param id the id to check
      * @return true if the ID has been resolved
      */
@@ -248,6 +243,7 @@ public class AreaTreeHandler extends FOEventHandler {
 
     /**
      * Tries to resolve all unresolved ID references on the given page.
+     * 
      * @param id ID to resolve
      * @param pv page viewport whose ID refs to resolve
      * @param List of PageViewports
@@ -270,6 +266,7 @@ public class AreaTreeHandler extends FOEventHandler {
 
     /**
      * Tries to resolve all unresolved ID references on the given page.
+     * 
      * @param pv page viewport whose ID refs to resolve
      */
     public void tryIDResolution(PageViewport pv) {
@@ -283,9 +280,10 @@ public class AreaTreeHandler extends FOEventHandler {
             }
         }
     }
-    
+
     /**
      * Get the list of page viewports that have an area with a given id.
+     * 
      * @param id the id to lookup
      * @return the list of PageViewports
      */
@@ -294,8 +292,8 @@ public class AreaTreeHandler extends FOEventHandler {
     }
 
     /**
-     * Get information about the rendered output, like
-     * number of pages created.
+     * Get information about the rendered output, like number of pages created.
+     * 
      * @return the results structure
      */
     public FormattingResults getResults() {
@@ -304,6 +302,7 @@ public class AreaTreeHandler extends FOEventHandler {
 
     /**
      * Add an Resolvable object with an unresolved idref
+     * 
      * @param idref the idref whose target id has not yet been located
      * @param res the Resolvable object needing the idref to be resolved
      */
@@ -318,16 +317,16 @@ public class AreaTreeHandler extends FOEventHandler {
     }
 
     /**
-     * Prepare AreaTreeHandler for document processing
-     * This is called from FOTreeBuilder.startDocument()
-     *
-     * @throws SAXException if there is an error
+     * Prepare AreaTreeHandler for document processing This is called from
+     * FOTreeBuilder.startDocument()
+     * 
+     * @throws SAXException
+     *             if there is an error
      */
     public void startDocument() throws SAXException {
-        //Initialize statistics
-        if (outputStatistics) {
-            initialMemory = runtime.totalMemory() - runtime.freeMemory();
-            startTime = System.currentTimeMillis();
+        // Initialize statistics
+        if (statistics != null) {
+            statistics.start();
         }
     }
 
@@ -344,40 +343,39 @@ public class AreaTreeHandler extends FOEventHandler {
 
     /**
      * @see org.apache.fop.fo.FOEventHandler
-     * @param pageSequence is the pageSequence being started 
-     * */
+     * @param pageSequence
+     *            is the pageSequence being started
+     */
     public void startPageSequence(PageSequence pageSequence) {
         rootFObj = pageSequence.getRoot();
         finishPrevPageSequence(pageSequence.getInitialPageNumber());
         pageSequence.initPageNumber();
-        //extension attachments from fo:root
+        // extension attachments from fo:root
         wrapAndAddExtensionAttachments(rootFObj.getExtensionAttachments());
-        //extension attachments from fo:declarations
+        // extension attachments from fo:declarations
         if (rootFObj.getDeclarations() != null) {
             wrapAndAddExtensionAttachments(rootFObj.getDeclarations().getExtensionAttachments());
         }
     }
-    
+
     private void wrapAndAddExtensionAttachments(List list) {
         Iterator i = list.iterator();
         while (i.hasNext()) {
-            ExtensionAttachment attachment = (ExtensionAttachment)i.next();
+            ExtensionAttachment attachment = (ExtensionAttachment) i.next();
             addOffDocumentItem(new OffDocumentExtensionAttachment(attachment));
         }
     }
-    
+
     /**
-     * End the PageSequence.
-     * The PageSequence formats Pages and adds them to the AreaTree.
-     * The area tree then handles what happens with the pages.
-     *
+     * End the PageSequence. The PageSequence formats Pages and adds them to the
+     * AreaTree. The area tree then handles what happens with the pages.
+     * 
      * @param pageSequence the page sequence ending
      */
     public void endPageSequence(PageSequence pageSequence) {
 
-        if (outputStatistics) {
-            long memoryNow = runtime.totalMemory() - runtime.freeMemory();
-            log.debug("Current heap size: " + (memoryNow / 1024L) + "Kb");
+        if (statistics != null) {
+            statistics.end();
         }
 
         // If no main flow, nothing to layout!
@@ -388,28 +386,28 @@ public class AreaTreeHandler extends FOEventHandler {
             pageSLM.activateLayout();
             // preserve the current PageSequenceLayoutManger for the
             // force-page-count check at the beginning of the next PageSequence
-            prevPageSeqLM = pageSLM; 
+            prevPageSeqLM = pageSLM;
         }
     }
 
     /**
-     * Called by the PageSequenceLayoutManager when it is finished with a page-sequence.
+     * Called by the PageSequenceLayoutManager when it is finished with a
+     * page-sequence.
+     * 
      * @param pageSequence the page-sequence just finished
      * @param pageCount The number of pages generated for the page-sequence
      */
     public void notifyPageSequenceFinished(PageSequence pageSequence,
-                                           int pageCount) {
-        this.results.haveFormattedPageSequence(pageSequence, 
-                                               pageCount);
+            int pageCount) {
+        this.results.haveFormattedPageSequence(pageSequence, pageCount);
         if (log.isDebugEnabled()) {
-            log.debug("Last page-sequence produced " 
-                    + pageCount + " pages.");
+            log.debug("Last page-sequence produced " + pageCount + " pages.");
         }
     }
 
     /**
      * End the document.
-     *
+     * 
      * @throws SAXException if there is some error
      */
     public void endDocument() throws SAXException {
@@ -418,8 +416,8 @@ public class AreaTreeHandler extends FOEventHandler {
         // process fox:destination elements
         ArrayList destinationList = rootFObj.getDestinationList();
         if (destinationList != null) {
-            while(destinationList.size() > 0) {
-                Destination destination = (Destination)destinationList.remove(0);
+            while (destinationList.size() > 0) {
+                Destination destination = (Destination) destinationList.remove(0);
                 DestinationData destinationData = new DestinationData(destination);
                 addOffDocumentItem(destinationData);
             }
@@ -430,35 +428,23 @@ public class AreaTreeHandler extends FOEventHandler {
             BookmarkData data = new BookmarkData(bookmarkTree);
             addOffDocumentItem(data);
             if (!data.isResolved()) {
-                //bookmarks did not fully resolve, add anyway. (hacky? yeah)
+                // bookmarks did not fully resolve, add anyway. (hacky? yeah)
                 model.handleOffDocumentItem(data);
             }
         }
 
         model.endDocument();
 
-        if (outputStatistics) {
-            long memoryNow = runtime.totalMemory() - runtime.freeMemory();
-            long memoryUsed = (memoryNow - initialMemory) / 1024L;
-            long timeUsed = System.currentTimeMillis() - startTime;
-            int pageCount = rootFObj.getTotalPagesGenerated();
-            log.debug("Initial heap size: " + (initialMemory / 1024L) + "Kb");
-            log.debug("Current heap size: " + (memoryNow / 1024L) + "Kb");
-            log.debug("Total memory used: " + memoryUsed + "Kb");
-            log.debug("Total time used: " + timeUsed + "ms");
-            log.debug("Pages rendered: " + pageCount);
-            if (pageCount > 0) {
-                long perPage = (timeUsed / pageCount);
-                long ppm = (timeUsed != 0 ? Math.round(60000 * pageCount / (double)timeUsed) : -1);
-                log.debug("Avg render time: " + perPage + "ms/page (" + ppm + "pages/min)");
-            }
+        if (statistics != null) {
+            statistics.logResults();
         }
     }
 
     /**
-     * Add a OffDocumentItem to the area tree model
-     * This checks if the OffDocumentItem is resolvable and attempts
-     * to resolve or add the resolvable ids for later resolution.
+     * Add a OffDocumentItem to the area tree model. This checks if the
+     * OffDocumentItem is resolvable and attempts to resolve or add the
+     * resolvable ids for later resolution.
+     * 
      * @param odi the OffDocumentItem to add.
      */
     private void addOffDocumentItem(OffDocumentItem odi) {
@@ -469,8 +455,8 @@ public class AreaTreeHandler extends FOEventHandler {
                 if (idLocations.containsKey(ids[count])) {
                     res.resolveIDRef(ids[count], (List) idLocations.get(ids[count]));
                 } else {
-                    log.warn(odi.getName() + ": Unresolved id reference \"" 
-                        + ids[count] + "\" found.");
+                    log.warn(odi.getName() + ": Unresolved id reference \""
+                            + ids[count] + "\" found.");
                     addUnresolvedIDRef(ids[count], res);
                 }
             }
@@ -482,15 +468,60 @@ public class AreaTreeHandler extends FOEventHandler {
             model.handleOffDocumentItem(odi);
         }
     }
-    
+
     /**
      * Generates and returns a unique key for a page viewport.
+     * 
      * @return the generated key.
      */
     public String generatePageViewportKey() {
         this.idGen++;
         return "P" + this.idGen;
     }
-    
-}
 
+    /**
+     * Gather statistics when log is debug
+     */
+    private final class Statistics {
+        // for statistics gathering
+        private Runtime runtime;
+
+        // heap memory allocated (for statistics)
+        private long initialMemory;
+
+        // time used in rendering (for statistics)
+        private long startTime;
+
+        private Statistics() {
+            runtime = Runtime.getRuntime();
+        }
+
+        public void start() {
+            initialMemory = runtime.totalMemory() - runtime.freeMemory();
+            startTime = System.currentTimeMillis();
+        }
+
+        public void end() {
+            long memoryNow = runtime.totalMemory() - runtime.freeMemory();
+            log.debug("Current heap size: " + (memoryNow / 1024L) + "KB");
+        }
+
+        public void logResults() {
+            long memoryNow = runtime.totalMemory() - runtime.freeMemory();
+            long memoryUsed = (memoryNow - initialMemory) / 1024L;
+            long timeUsed = System.currentTimeMillis() - startTime;
+            int pageCount = rootFObj.getTotalPagesGenerated();
+            log.debug("Initial heap size: " + (initialMemory / 1024L) + "KB");
+            log.debug("Current heap size: " + (memoryNow / 1024L) + "KB");
+            log.debug("Total memory used: " + memoryUsed + "KB");
+            log.debug("Total time used: " + timeUsed + "ms");
+            log.debug("Pages rendered: " + pageCount);
+            if (pageCount > 0) {
+                long perPage = (timeUsed / pageCount);
+                long ppm = (timeUsed != 0 ? Math.round(60000 * pageCount
+                        / (double) timeUsed) : -1);
+                log.debug("Avg render time: " + perPage + "ms/page (" + ppm + "pages/min)");
+            }
+        }
+    }
+}