001: /**
002: * ========================================
003: * JFreeReport : a free Java report library
004: * ========================================
005: *
006: * Project Info: http://reporting.pentaho.org/
007: *
008: * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
009: *
010: * This library is free software; you can redistribute it and/or modify it under the terms
011: * of the GNU Lesser General Public License as published by the Free Software Foundation;
012: * either version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015: * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: * See the GNU Lesser General Public License for more details.
017: *
018: * You should have received a copy of the GNU Lesser General Public License along with this
019: * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: *
022: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023: * in the United States and other countries.]
024: *
025: * ------------
026: * $Id: PrintReportProcessor.java 3525 2007-10-16 11:43:48Z tmorgner $
027: * ------------
028: * (C) Copyright 2000-2005, by Object Refinery Limited.
029: * (C) Copyright 2005-2007, by Pentaho Corporation.
030: */package org.jfree.report.modules.gui.swing.printing;
031:
032: import java.awt.print.PageFormat;
033: import java.awt.print.Pageable;
034: import java.awt.print.Printable;
035:
036: import org.jfree.layouting.StateException;
037: import org.jfree.layouting.modules.output.graphics.GraphicsOutputProcessor;
038: import org.jfree.layouting.modules.output.graphics.PageDrawable;
039: import org.jfree.layouting.modules.output.graphics.QueryPhysicalPageInterceptor;
040: import org.jfree.report.DataSourceException;
041: import org.jfree.report.ReportDataFactory;
042: import org.jfree.report.ReportDataFactoryException;
043: import org.jfree.report.ReportProcessingException;
044: import org.jfree.report.flow.LibLayoutReportTarget;
045: import org.jfree.report.flow.ReportJob;
046: import org.jfree.report.flow.ReportTargetState;
047: import org.jfree.report.flow.layoutprocessor.LayoutController;
048: import org.jfree.report.flow.paginating.PageState;
049: import org.jfree.report.flow.paginating.PaginatingReportProcessor;
050: import org.jfree.util.Log;
051:
052: /**
053: * A paginating report processor that outputs to Pageables.
054: *
055: * @author Thomas Morgner
056: */
057: public class PrintReportProcessor extends PaginatingReportProcessor
058: implements Pageable {
059: private ReportJob job;
060: private Throwable error;
061:
062: public PrintReportProcessor(final ReportJob job) {
063: super (new GraphicsOutputProcessor(job.getConfiguration()));
064: this .job = job;
065:
066: synchronized (job) {
067: final ReportDataFactory dataFactory = job.getDataFactory();
068: if (dataFactory != null) {
069: dataFactory.open();
070: }
071: }
072: }
073:
074: protected GraphicsOutputProcessor getGraphicsProcessor() {
075: return (GraphicsOutputProcessor) getOutputProcessor();
076: }
077:
078: public boolean isError() {
079: return error != null;
080: }
081:
082: protected ReportJob getJob() {
083: return job;
084: }
085:
086: public void close() {
087: getJob().close();
088: }
089:
090: protected PageDrawable processPage(final int page)
091: throws ReportDataFactoryException, DataSourceException,
092: ReportProcessingException, StateException {
093: final ReportJob job = getJob();
094: synchronized (job) {
095: // set up the scene
096: final PageState state = getPhysicalPageState(page);
097:
098: final ReportTargetState targetState = state
099: .getTargetState();
100: final GraphicsOutputProcessor outputProcessor = getGraphicsProcessor();
101: outputProcessor.setPageCursor(state.getPageCursor());
102: final QueryPhysicalPageInterceptor interceptor = new QueryPhysicalPageInterceptor(
103: outputProcessor.getPhysicalPage(page));
104: outputProcessor.setInterceptor(interceptor);
105:
106: final LibLayoutReportTarget target = (LibLayoutReportTarget) targetState
107: .restore(outputProcessor);
108:
109: LayoutController position = state.getLayoutController();
110:
111: // we have the data and we have our position inside the report.
112: // lets generate something ...
113: while (position.isAdvanceable()) {
114: position = position.advance(target);
115: target.commit();
116:
117: while (position.isAdvanceable() == false
118: && position.getParent() != null) {
119: final LayoutController parent = position
120: .getParent();
121: position = parent
122: .join(position.getFlowController());
123: }
124:
125: if (interceptor.isMoreContentNeeded() == false) {
126: outputProcessor.setInterceptor(null);
127: return interceptor.getDrawable();
128: }
129:
130: }
131:
132: outputProcessor.setInterceptor(null);
133: return interceptor.getDrawable();
134: }
135: }
136:
137: /**
138: * Returns the number of pages in the set. To enable advanced printing
139: * features, it is recommended that <code>Pageable</code> implementations
140: * return the true number of pages rather than the UNKNOWN_NUMBER_OF_PAGES
141: * constant.
142: *
143: * @return the number of pages in this <code>Pageable</code>.
144: */
145: public synchronized int getNumberOfPages() {
146: if (isError()) {
147: return 0;
148: }
149:
150: if (isPaginated() == false) {
151: try {
152: prepareReportProcessing(getJob());
153: } catch (Exception e) {
154: Log.debug("PrintReportProcessor: ", e);
155: error = e;
156: return 0;
157: }
158: }
159: Log.debug("After pagination, we have "
160: + getGraphicsProcessor().getPhysicalPageCount()
161: + " physical pages.");
162: return getGraphicsProcessor().getPhysicalPageCount();
163: }
164:
165: public boolean paginate() {
166: if (isError()) {
167: return false;
168: }
169:
170: if (isPaginated() == false) {
171: try {
172: prepareReportProcessing(getJob());
173: return true;
174: } catch (Exception e) {
175: error = e;
176: return false;
177: }
178: }
179: return true;
180: }
181:
182: /**
183: * Returns the <code>PageFormat</code> of the page specified by
184: * <code>pageIndex</code>.
185: *
186: * @param pageIndex the zero based index of the page whose <code>PageFormat</code>
187: * is being requested
188: * @return the <code>PageFormat</code> describing the size and orientation.
189: * @throws IndexOutOfBoundsException if the <code>Pageable</code> does not
190: * contain the requested page.
191: */
192: public synchronized PageFormat getPageFormat(final int pageIndex)
193: throws IndexOutOfBoundsException {
194: if (isError()) {
195: return null;
196: }
197:
198: if (isPaginated() == false) {
199: try {
200: prepareReportProcessing(getJob());
201: } catch (Exception e) {
202: error = e;
203: return null;
204: }
205: }
206:
207: try {
208: final PageDrawable pageDrawable = processPage(pageIndex);
209: return pageDrawable.getPageFormat();
210: } catch (Exception e) {
211: throw new IllegalStateException(
212: "Unable to return a valid pageformat.");
213: }
214: }
215:
216: /**
217: * Returns the <code>Printable</code> instance responsible for rendering the
218: * page specified by <code>pageIndex</code>.
219: *
220: * @param pageIndex the zero based index of the page whose <code>Printable</code>
221: * is being requested
222: * @return the <code>Printable</code> that renders the page.
223: * @throws IndexOutOfBoundsException if the <code>Pageable</code> does not
224: * contain the requested page.
225: */
226: public synchronized Printable getPrintable(final int pageIndex)
227: throws IndexOutOfBoundsException {
228: if (isError()) {
229: return null;
230: }
231:
232: if (isPaginated() == false) {
233: try {
234: prepareReportProcessing(getJob());
235: } catch (Exception e) {
236: error = e;
237: return null;
238: }
239: }
240:
241: try {
242: final PageDrawable pageDrawable = processPage(pageIndex);
243: return new DrawablePrintable(pageDrawable);
244: } catch (Exception e) {
245: throw new IllegalStateException(
246: "Unable to return a valid pageformat.");
247: }
248: }
249:
250: public PageDrawable getPageDrawable(final int pageIndex) {
251: if (isError()) {
252: return null;
253: }
254:
255: if (isPaginated() == false) {
256: try {
257: prepareReportProcessing(getJob());
258: } catch (Exception e) {
259: error = e;
260: return null;
261: }
262: }
263:
264: try {
265: return processPage(pageIndex);
266: } catch (Exception e) {
267: error = e;
268: Log.debug("Failed to process the page", e);
269: throw new IllegalStateException(
270: "Unable to return a valid pageformat.");
271: }
272: }
273:
274: /**
275: * Throws an unsupported operation exception. Printing is controlled by a
276: * framework which calls this pageable class for each page. Therefore,
277: * printing has to be invoked from outside.
278: *
279: * @param job
280: * @throws UnsupportedOperationException
281: */
282: public final void processReport(final ReportJob job) {
283: throw new UnsupportedOperationException(
284: "Printing is a passive process.");
285: }
286: }
|