📄 pageablereportprocessor.java
字号:
/**
* ========================================
* JFreeReport : a free Java report library
* ========================================
*
* Project Info: http://www.jfree.org/jfreereport/index.html
* Project Lead: Thomas Morgner;
*
* (C) Copyright 2000-2003, by Simba Management Limited and Contributors.
*
* 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., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* ----------------------------
* PageableReportProcessor.java
* ----------------------------
* (C)opyright 2002, 2003, by Thomas Morgner and Contributors.
*
* Original Author: Thomas Morgner;
* Contributor(s): David Gilbert (for Simba Management Limited);
*
* $Id: PageableReportProcessor.java,v 1.10.2.1 2003/12/21 23:28:45 taqua Exp $
*
* Changes
* -------
* 03-Dec-2002 : Added Javadocs (DG);
* 02-Feb-2003 : added Interrupt handling and removed log messages.
* 04-Feb-2003 : Code-Optimizations
* 12-Feb-2003 : BugFix: Page is ended when isPageEndedIsTrue(), dont wait for the next page.
* This caused lost rows.
*/
package org.jfree.report.modules.output.pageable.base;
import java.awt.print.PageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import org.jfree.report.EmptyReportException;
import org.jfree.report.JFreeReport;
import org.jfree.report.ReportEventException;
import org.jfree.report.ReportInterruptedException;
import org.jfree.report.ReportProcessingException;
import org.jfree.report.event.RepaginationListener;
import org.jfree.report.event.RepaginationState;
import org.jfree.report.function.FunctionInitializeException;
import org.jfree.report.modules.output.pageable.base.pagelayout.PageLayouter;
import org.jfree.report.modules.output.pageable.base.pagelayout.SimplePageLayouter;
import org.jfree.report.states.FinishState;
import org.jfree.report.states.ReportState;
import org.jfree.report.states.ReportStateProgress;
import org.jfree.report.states.StartState;
import org.jfree.report.util.Log;
/**
* A report processor for Pageable OutputTargets. The processor coordinates
* and initializes the output process for all page- and print-oriented output
* formats.
*
* @author Thomas Morgner
*/
public class PageableReportProcessor
{
/**
* A compile time constant that defines how many events should be generated
* during the report processing.
*/
private static final int MAX_EVENTS_PER_RUN = 400;
/** The level where the page function is executed. */
private static final int PRINT_FUNCTION_LEVEL = -1;
/** The page layout manager name. */
public static final String LAYOUTMANAGER_NAME = "pageable.layoutManager";
/** The report being processed. */
private JFreeReport report;
/** The output target. */
private OutputTarget outputTarget;
/** A flag defining whether to check for Thread-Interrupts. */
private boolean handleInterruptedState;
/** Storage for listener references. */
private ArrayList listeners;
/** The listeners as object array for faster access. */
private Object[] listenersCache;
/**
* Creates a new ReportProcessor.
*
* @param report the report.
*
* @throws ReportProcessingException if the report cannot be cloned.
*/
public PageableReportProcessor(final JFreeReport report)
throws ReportProcessingException, FunctionInitializeException
{
try
{
// first cloning ... protect the page layouter function ...
// and any changes we may do to the report instance.
// a second cloning is done in the start state, to protect the
// processed data.
this.report = (JFreeReport) report.clone();
}
catch (CloneNotSupportedException cne)
{
throw new ReportProcessingException("Initial Clone of Report failed");
}
final String layouter = (String) this.report.getProperty(LAYOUTMANAGER_NAME);
final PageLayouter lm = getLayoutManager(layouter);
this.report.addFunction(lm);
}
/**
* Adds a repagination listener. This listener will be informed of
* pagination events.
*
* @param l the listener.
*/
public void addRepaginationListener(final RepaginationListener l)
{
if (l == null)
{
throw new NullPointerException("Listener == null");
}
if (listeners == null)
{
listeners = new ArrayList(5);
}
listenersCache = null;
listeners.add(l);
}
/**
* Removes a repagination listener.
*
* @param l the listener.
*/
public void removeRepaginationListener(final RepaginationListener l)
{
if (l == null)
{
throw new NullPointerException("Listener == null");
}
if (listeners == null)
{
return;
}
listenersCache = null;
listeners.remove(l);
}
/**
* Sends a repagination update to all registered listeners.
*
* @param state the state.
*/
protected void fireStateUpdate(final RepaginationState state)
{
if (listeners == null)
{
return;
}
if (listenersCache == null)
{
listenersCache = listeners.toArray();
}
for (int i = 0; i < listenersCache.length; i++)
{
final RepaginationListener l = (RepaginationListener) listenersCache[i];
l.repaginationUpdate(state);
}
}
/**
* Returns whether the processor should check the threads interrupted state.
* If this is set to true and the thread was interrupted, then the report processing
* is aborted.
*
* @return true, if the processor should check the current thread state, false otherwise.
*/
public boolean isHandleInterruptedState()
{
return handleInterruptedState;
}
/**
* Defines, whether the processor should check the threads interrupted state.
* If this is set to true and the thread was interrupted, then the report processing
* is aborted.
*
* @param handleInterruptedState true, if the processor should check the current thread state,
* false otherwise.
*/
public void setHandleInterruptedState(final boolean handleInterruptedState)
{
this.handleInterruptedState = handleInterruptedState;
}
/**
* Returns the output target.
*
* @return the output target.
*/
public OutputTarget getOutputTarget()
{
return outputTarget;
}
/**
* Sets the output target.
*
* @param outputTarget the output target.
*/
public void setOutputTarget(final OutputTarget outputTarget)
{
this.outputTarget = outputTarget;
}
/**
* Returns the report.
*
* @return the report.
*/
public JFreeReport getReport()
{
return report;
}
/**
* Returns the layout manager. If the key is <code>null</code>, an instance of the
* <code>SimplePageLayouter</code> class is returned.
*
* @param key the key (null permitted).
*
* @return the page layouter.
*
* @throws org.jfree.report.ReportProcessingException if there is a processing error.
*/
private PageLayouter getLayoutManager(String key) throws ReportProcessingException
{
if (key == null)
{
key = SimplePageLayouter.class.getName();
}
try
{
final Class c = getClass().getClassLoader().loadClass(key);
final PageLayouter lm = (PageLayouter) c.newInstance();
lm.setName(LAYOUTMANAGER_NAME);
return lm;
}
catch (Exception e)
{
throw new ReportProcessingException("Unable to create the layoutmanager", e);
}
}
/**
* Processes the report in two passes, the first pass calculates page boundaries and function
* values, the second pass sends each page to the output target.
* <p>
* It is possible for the report processing to fail. A base cause is that the report is
* designed for a certain page size, but ends up being sent to an output target with a much
* smaller page size. If the headers and footers don't leave enough room on the page for at
* least one row of data to be printed, then no progress is made. An exception will be thrown
* if this happens.
*
* @throws org.jfree.report.ReportProcessingException if the report did not proceed and got stuck.
* @throws org.jfree.report.EmptyReportException if the repagination returned no pages.
*/
public void processReport()
throws ReportProcessingException, EmptyReportException
{
// do a repagination
final ReportStateList list = repaginate();
if (list.size() == 0)
{
throw new EmptyReportException("Repaginating returned no pages");
}
final boolean failOnError = getReport().getReportConfiguration().isStrictErrorHandling();
final RepaginationState repaginationState = new RepaginationState(this, 0, 0, 0, 0, false);
for (int i = 0; i < list.size(); i++)
{
final ReportState rs = list.get(i);
// fire an event for every generated page. It does not really matter
// if that policy is not very informative, it is sufficient ...
repaginationState.reuse(PRINT_FUNCTION_LEVEL,
rs.getCurrentPage(), rs.getCurrentDataItem(), rs.getNumberOfRows(), false);
fireStateUpdate(repaginationState);
processPage(rs, getOutputTarget(), failOnError);
}
}
/**
* Processes the entire report and records the state at the end of every page.
*
* @return a list of report states (one for the beginning of each page in the report).
*
* @throws ReportProcessingException if there was a problem processing the report.
*/
public ReportStateList repaginate() throws ReportProcessingException
{
try
{
// every report processing starts with an StartState.
final StartState startState = new StartState(getReport());
ReportState state = startState;
final int maxRows = getReport().getData().getRowCount();
ReportStateList pageStates = null;
// make sure the output target is configured
getOutputTarget().configure(getReport().getReportConfiguration());
// the report processing can be splitted into 2 separate processes.
// The first is the ReportPreparation; all function values are resolved and
// a dummy run is done to calculate the final layout. This dummy run is
// also necessary to resolve functions which use or depend on the PageCount.
// the second process is the printing of the report, this is done in the
// processReport() method.
// during a prepare run the REPORT_PREPARERUN_PROPERTY is set to true.
state.setProperty(JFreeReport.REPORT_PREPARERUN_PROPERTY, Boolean.TRUE);
// the pageformat is added to the report properties, PageFormat is not serializable,
// so a repaginated report is no longer serializable.
//
// The pageformat will cause trouble in later versions, when printing over
// multiple pages gets implemented. This property will be replaced by a more
// suitable alternative.
final PageFormat p = getOutputTarget().getLogicalPage().getPhysicalPageFormat();
state.setProperty(JFreeReport.REPORT_PAGEFORMAT_PROPERTY, p.clone());
// now change the writer function to be a dummy writer. We don't want any
// output in the prepare runs.
final OutputTarget dummyOutput = getOutputTarget().createDummyWriter();
dummyOutput.configure(report.getReportConfiguration());
dummyOutput.open();
// now process all function levels.
// there is at least one level defined, as we added the PageLayouter
// to the report.
// the levels are defined from +inf to 0
// we don't draw and we do not collect states in a StateList yet
final Iterator it = startState.getLevels();
if (it.hasNext() == false)
{
throw new IllegalStateException("No functions defined, invalid implementation.");
}
boolean hasNext;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -