📄 reportstate.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.
*
* ----------------
* ReportState.java
* ----------------
* (C)opyright 2000-2003, by Simba Management Limited and Contributors.
*
* Original Author: David Gilbert (for Simba Management Limited);
* Contributor(s): Thomas Morgner;
*
* $Id: ReportState.java,v 1.7 2003/11/15 20:51:15 taqua Exp $
*
* Changes (from 8-Feb-2002)
* -------------------------
* 08-Feb-2002 : Updated code to work with latest version of the JCommon class library (DG);
* 19-Feb-2002 : Moved constants into the ReportStateConstants interface (DG);
* 18-Apr-2002 : Added detection whether a report did proceed.
* 10-May-2002 : ReportState is now smarter. All state transitions formerly handled by
* JFreeReport.advanceState has moved into the corresponding ReportState-class.
* ReportEvents are used to inform listeners, a ReportProcessor encapsulates the
* knowledge how to display the elements.
* 17-May-2002 : Fixed the ReportPropertyBug by adding a new state (PreReportHeaderState).
* ReportState.StartState.advance has to be executed before the first page is printed.
* 26-May-2002 : Moved ReportProperties into the state so that different runs do not affect
* each other. Added Property isPrepareRun() to signal whether the report is
* currently repaginated.
* 11-May-2002 : A bug in the ReportPropertyHandling is fixed.
* 24-Jun-2002 : Populate Elements must not be called before Function values are calculated.
* 28-Jul-2002 : Added datarow support, the report is now cloned on start
* 21-Aug-2002 : isProceeding() was buggy, did not test the reportstate correctly (returned always
* true)
* 28-Aug-2002 : Downport to JDK1.2.2, added many this-references for innerclasses ...
*/
package org.jfree.report.states;
import java.util.Iterator;
import java.util.List;
import org.jfree.report.Band;
import org.jfree.report.DataRow;
import org.jfree.report.Group;
import org.jfree.report.JFreeReport;
import org.jfree.report.ReportDefinition;
import org.jfree.report.ReportProcessingException;
import org.jfree.report.event.LayoutEvent;
import org.jfree.report.event.ReportEvent;
import org.jfree.report.function.LevelledExpressionList;
import org.jfree.report.util.ReportProperties;
import org.jfree.report.util.ReportPropertiesList;
import org.jfree.util.ObjectUtils;
/**
* Captures state information for a report while it is in the process of being displayed or
* printed. JFreeReport uses a state transition diagram to track progress through the report
* generation.
* <p>
* The report processing will usually pass through many states for each page generated. We
* record the report state at the end of each page, so that we can jump directly to the start of
* any page without having to regenerate all the preceding pages.
*
* @author David Gilbert
* @author Thomas Morgner
*/
public abstract class ReportState implements Cloneable
{
/** The report that the state belongs to. */
private ReportDefinitionImpl report;
/** The number of rows in the tablemodel. */
private final int numberOfRows;
/** The current item (row in the TableModel). */
private int currentItem;
/** The page that this state applies to. */
private int currentPage;
/** The current group. */
private int currentGroupIndex;
/** The report properties. */
private final ReportProperties reportProperties;
/** The data row. */
private DataRowBackend dataRow;
/** The data row preview. */
private DataRowPreview dataRowPreview;
/** A row number that is 'before' the first row. */
public static final int BEFORE_FIRST_ROW = -1;
/** A group number that is 'before' the first group. */
public static final int BEFORE_FIRST_GROUP = -1;
/** The first page. */
public static final int BEFORE_FIRST_PAGE = 0;
/** The ancestor hash code. */
private int ancestorHashcode;
/**
* Constructs a new state for the specified report. The report (which encapsulates a reference
* to the data, plus definitions for the required layout) is cloned to isolate the reporting
* engine from changes to the report that occur after report processing begins.
* <p>
* This constructor is protected, it is intended to be used by subclasses only.
*
* @param reportPar the report.
* @throws CloneNotSupportedException if the initial cloning of the report definition fails.
*/
protected ReportState(final JFreeReport reportPar) throws CloneNotSupportedException
{
setReportDefinition(new ReportDefinitionImpl(reportPar));
numberOfRows = reportPar.getData().getRowCount();
reportProperties = getReport().getProperties();
final LevelledExpressionList functions = new LevelledExpressionList(reportPar.getExpressions(),
reportPar.getFunctions());
final DataRowBackend dr = new DataRowBackend();
dr.setTablemodel(reportPar.getData());
dr.setFunctions(functions);
dr.setReportProperties(new ReportPropertiesList(reportProperties));
getReportDefinition().getDataRowConnector().setDataRowBackend(dr);
this.dataRow = dr;
// we have no clone-ancestor, so forget everyting
setAncestorHashcode(this.hashCode());
// reset the current data row ...
resetState();
}
/**
* Resets the state, so that the datarow points to the first row.
*/
protected void resetState()
{
setCurrentItem(BEFORE_FIRST_ROW);
setCurrentPage(BEFORE_FIRST_PAGE);
setCurrentGroupIndex(BEFORE_FIRST_GROUP);
getDataRowBackend().setCurrentRow(getCurrentDisplayItem());
}
/**
* Constructs a ReportState from an existing ReportState and optionally resets
* the state.
*
* @param clone the base report state from which to initialize.
* @param reset true, if the state should be reseted, false otherwise.
*/
protected ReportState(final ReportState clone, final boolean reset)
{
setReportDefinition(clone.getReportDefinition());
reportProperties = clone.reportProperties;
numberOfRows = clone.getNumberOfRows();
dataRowPreview = clone.dataRowPreview;
this.dataRow = clone.getDataRowBackend();
if (reset)
{
resetState();
}
else
{
setCurrentItem(clone.getCurrentDataItem());
setCurrentPage(clone.getCurrentPage());
setCurrentGroupIndex(clone.getCurrentGroupIndex());
getDataRowBackend().setCurrentRow(getCurrentDisplayItem());
}
// we have no clone-ancestor, so forget everything
setAncestorHashcode(this.hashCode());
}
/**
* Constructs a ReportState from an existing ReportState.
*
* @param clone the existing state.
*/
protected ReportState(final ReportState clone)
{
this(clone, false);
}
/**
* Implements a singleton datarow preview.
*
* @return the preview instance of the datarow.
*/
protected DataRowPreview getDataRowPreview()
{
if (dataRowPreview == null)
{
dataRowPreview = new DataRowPreview(getDataRowBackend());
}
dataRowPreview.update(getDataRowBackend());
return dataRowPreview;
}
/**
* Returns the number of rows.
*
* @return The number of row.
*/
public int getNumberOfRows()
{
return numberOfRows;
}
/**
* Returns the current data row.
*
* @return the current data row.
*/
public DataRow getDataRow()
{
return dataRow.getDataRow();
}
/**
* Returns the data row backend.
*
* @return the data row backend.
*/
protected DataRowBackend getDataRowBackend()
{
return dataRow;
}
/**
* Returns the report this state is assigned to.
*
* @return the report.
*/
public ReportDefinition getReport()
{
return report;
}
/**
* The advance method performs a transition from the current report state to the next report
* state. Each transition will usually involve some processing of the report.
*
* @return the next report state.
* @throws ReportProcessingException if there is a problem processing the report.
*/
public abstract ReportState advance() throws ReportProcessingException;
/**
* Sets the report for this state.
*
* @param report the report (null not permitted).
*
* @throws NullPointerException if the given report is null
*/
private void setReportDefinition(final ReportDefinitionImpl report)
{
if (report == null)
{
throw new NullPointerException("A ReportState without a report is not allowed");
}
this.report = report;
}
/**
* Returns the report definition implementation used as backend when generating
* the report. Don't play with it!
*
* @return the internal report definition.
*/
protected ReportDefinitionImpl getReportDefinition()
{
return this.report;
}
/**
* Returns the current item (that is, the current row of the data in the TableModel).
*
* @return The current row index.
*/
public int getCurrentDataItem()
{
return this.currentItem;
}
/**
* Returns the current item that should be displayed for this state. Before any item
* has advanced, dataItem is -1. This function automatically corrects the currentRow according
* to the current state of the report (if the header is processed, add +1).
*
* @return the row to use for obtaining data from the TableModel.
*/
public final int getCurrentDisplayItem()
{
if (isPrefetchState())
{
return this.currentItem + 1;
}
else
{
return this.currentItem;
}
}
/**
* Returns the 'prefetch' state for this report state (defaults to false).
* <p>
* Some states will override this method and return true...in this case, any access to the
* report's TableModel will look to the current row + 1.
*
* @return always false (subclasses may override).
*/
public boolean isPrefetchState()
{
return false;
}
/**
* Sets the current item index (corresponds to a row in the TableModel).
* This element is -1 before a row is read.
*
* @param itemIndex The new item index.
*/
public void setCurrentItem(final int itemIndex)
{
this.currentItem = itemIndex;
}
/**
* Returns the page number.
*
* @return the page number.
*/
public int getCurrentPage()
{
return this.currentPage;
}
/**
* Sets the current page number.
*
* @param page The new page number.
*/
public void setCurrentPage(final int page)
{
if (page < 0)
{
throw new IllegalArgumentException("Page must be >= 0");
}
this.currentPage = page;
}
/**
* Returns the current group index.
* <p>
* This starts at zero for the item group, and increases for each higher level group.
*
* @return The current group index.
*/
public int getCurrentGroupIndex()
{
return currentGroupIndex;
}
/**
* Sets the current group index (zero is the item group).
*
* @param index The new group index.
*/
public void setCurrentGroupIndex(final int index)
{
if (index < -1)
{
throw new IllegalArgumentException("GroupIndex must be >= 0 or BEFORE_FIRST_GROUP");
}
this.currentGroupIndex = index;
}
/**
* Returns the function collection.
*
* @return the functions.
*/
protected final LevelledExpressionList getFunctions()
{
if (dataRow.getFunctions().getDataRow() != dataRow.getDataRow())
{
throw new IllegalStateException("Paranoia: Unconnected or invalid function datarow");
}
return dataRow.getFunctions();
}
/**
* Returns the value of a property with the specified name.
*
* @param key the property name.
*
* @return the property value.
*/
public Object getProperty(final String key)
{
return reportProperties.get(key);
}
/**
* Returns a property with the specified name. If no property with the specified name is found,
* returns def.
*
* @param key the property name.
* @param def the default value.
*
* @return the property value.
*/
public Object getProperty(final String key, final Object def)
{
return reportProperties.get(key, def);
}
/**
* Sets a property.
*
* @param key the property name.
* @param o the property value.
*/
public void setProperty(final String key, final Object o)
{
reportProperties.put(key, o);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -