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 */ 031 032 package org.jfree.report.modules.gui.swing.printing; 033 034 import java.awt.print.PageFormat; 035 import java.awt.print.Pageable; 036 import java.awt.print.Printable; 037 038 import org.jfree.layouting.StateException; 039 import org.jfree.layouting.modules.output.graphics.GraphicsOutputProcessor; 040 import org.jfree.layouting.modules.output.graphics.PageDrawable; 041 import org.jfree.layouting.modules.output.graphics.QueryPhysicalPageInterceptor; 042 import org.jfree.report.DataSourceException; 043 import org.jfree.report.ReportDataFactory; 044 import org.jfree.report.ReportDataFactoryException; 045 import org.jfree.report.ReportProcessingException; 046 import org.jfree.report.flow.LibLayoutReportTarget; 047 import org.jfree.report.flow.ReportJob; 048 import org.jfree.report.flow.ReportTargetState; 049 import org.jfree.report.flow.layoutprocessor.LayoutController; 050 import org.jfree.report.flow.paginating.PageState; 051 import org.jfree.report.flow.paginating.PaginatingReportProcessor; 052 import org.jfree.util.Log; 053 054 /** 055 * A paginating report processor that outputs to Pageables. 056 * 057 * @author Thomas Morgner 058 */ 059 public class PrintReportProcessor extends PaginatingReportProcessor 060 implements Pageable 061 { 062 private ReportJob job; 063 private Throwable error; 064 065 public PrintReportProcessor(final ReportJob job) 066 { 067 super(new GraphicsOutputProcessor(job.getConfiguration())); 068 this.job = job; 069 070 synchronized(job) 071 { 072 final ReportDataFactory dataFactory = job.getDataFactory(); 073 if (dataFactory != null) 074 { 075 dataFactory.open(); 076 } 077 } 078 } 079 080 protected GraphicsOutputProcessor getGraphicsProcessor() 081 { 082 return (GraphicsOutputProcessor) getOutputProcessor(); 083 } 084 085 public boolean isError() 086 { 087 return error != null; 088 } 089 090 protected ReportJob getJob() 091 { 092 return job; 093 } 094 095 public void close() 096 { 097 getJob().close(); 098 } 099 100 protected PageDrawable processPage(final int page) 101 throws ReportDataFactoryException, 102 DataSourceException, ReportProcessingException, StateException 103 { 104 final ReportJob job = getJob(); 105 synchronized (job) 106 { 107 // set up the scene 108 final PageState state = getPhysicalPageState(page); 109 110 final ReportTargetState targetState = state.getTargetState(); 111 final GraphicsOutputProcessor outputProcessor = getGraphicsProcessor(); 112 outputProcessor.setPageCursor(state.getPageCursor()); 113 final QueryPhysicalPageInterceptor interceptor = 114 new QueryPhysicalPageInterceptor(outputProcessor.getPhysicalPage(page)); 115 outputProcessor.setInterceptor(interceptor); 116 117 final LibLayoutReportTarget target = 118 (LibLayoutReportTarget) targetState.restore(outputProcessor); 119 120 LayoutController position = state.getLayoutController(); 121 122 // we have the data and we have our position inside the report. 123 // lets generate something ... 124 while (position.isAdvanceable()) 125 { 126 position = position.advance(target); 127 target.commit(); 128 129 while (position.isAdvanceable() == false && 130 position.getParent() != null) 131 { 132 final LayoutController parent = position.getParent(); 133 position = parent.join(position.getFlowController()); 134 } 135 136 if (interceptor.isMoreContentNeeded() == false) 137 { 138 outputProcessor.setInterceptor(null); 139 return interceptor.getDrawable(); 140 } 141 142 } 143 144 outputProcessor.setInterceptor(null); 145 return interceptor.getDrawable(); 146 } 147 } 148 149 /** 150 * Returns the number of pages in the set. To enable advanced printing 151 * features, it is recommended that <code>Pageable</code> implementations 152 * return the true number of pages rather than the UNKNOWN_NUMBER_OF_PAGES 153 * constant. 154 * 155 * @return the number of pages in this <code>Pageable</code>. 156 */ 157 public synchronized int getNumberOfPages() 158 { 159 if (isError()) 160 { 161 return 0; 162 } 163 164 if (isPaginated() == false) 165 { 166 try 167 { 168 prepareReportProcessing(getJob()); 169 } 170 catch (Exception e) 171 { 172 Log.debug("PrintReportProcessor: ", e); 173 error = e; 174 return 0; 175 } 176 } 177 Log.debug ("After pagination, we have " + 178 getGraphicsProcessor().getPhysicalPageCount() + " physical pages."); 179 return getGraphicsProcessor().getPhysicalPageCount(); 180 } 181 182 public boolean paginate() 183 { 184 if (isError()) 185 { 186 return false; 187 } 188 189 if (isPaginated() == false) 190 { 191 try 192 { 193 prepareReportProcessing(getJob()); 194 return true; 195 } 196 catch (Exception e) 197 { 198 error = e; 199 return false; 200 } 201 } 202 return true; 203 } 204 205 /** 206 * Returns the <code>PageFormat</code> of the page specified by 207 * <code>pageIndex</code>. 208 * 209 * @param pageIndex the zero based index of the page whose <code>PageFormat</code> 210 * is being requested 211 * @return the <code>PageFormat</code> describing the size and orientation. 212 * @throws IndexOutOfBoundsException if the <code>Pageable</code> does not 213 * contain the requested page. 214 */ 215 public synchronized PageFormat getPageFormat(final int pageIndex) 216 throws IndexOutOfBoundsException 217 { 218 if (isError()) 219 { 220 return null; 221 } 222 223 if (isPaginated() == false) 224 { 225 try 226 { 227 prepareReportProcessing(getJob()); 228 } 229 catch (Exception e) 230 { 231 error = e; 232 return null; 233 } 234 } 235 236 try 237 { 238 final PageDrawable pageDrawable = processPage(pageIndex); 239 return pageDrawable.getPageFormat(); 240 } 241 catch (Exception e) 242 { 243 throw new IllegalStateException("Unable to return a valid pageformat."); 244 } 245 } 246 247 /** 248 * Returns the <code>Printable</code> instance responsible for rendering the 249 * page specified by <code>pageIndex</code>. 250 * 251 * @param pageIndex the zero based index of the page whose <code>Printable</code> 252 * is being requested 253 * @return the <code>Printable</code> that renders the page. 254 * @throws IndexOutOfBoundsException if the <code>Pageable</code> does not 255 * contain the requested page. 256 */ 257 public synchronized Printable getPrintable(final int pageIndex) 258 throws IndexOutOfBoundsException 259 { 260 if (isError()) 261 { 262 return null; 263 } 264 265 if (isPaginated() == false) 266 { 267 try 268 { 269 prepareReportProcessing(getJob()); 270 } 271 catch (Exception e) 272 { 273 error = e; 274 return null; 275 } 276 } 277 278 try 279 { 280 final PageDrawable pageDrawable = processPage(pageIndex); 281 return new DrawablePrintable(pageDrawable); 282 } 283 catch (Exception e) 284 { 285 throw new IllegalStateException("Unable to return a valid pageformat."); 286 } 287 } 288 289 public PageDrawable getPageDrawable(final int pageIndex) 290 { 291 if (isError()) 292 { 293 return null; 294 } 295 296 if (isPaginated() == false) 297 { 298 try 299 { 300 prepareReportProcessing(getJob()); 301 } 302 catch (Exception e) 303 { 304 error = e; 305 return null; 306 } 307 } 308 309 try 310 { 311 return processPage(pageIndex); 312 } 313 catch (Exception e) 314 { 315 error = e; 316 Log.debug("Failed to process the page", e); 317 throw new IllegalStateException("Unable to return a valid pageformat."); 318 } 319 } 320 321 /** 322 * Throws an unsupported operation exception. Printing is controlled by a 323 * framework which calls this pageable class for each page. Therefore, 324 * printing has to be invoked from outside. 325 * 326 * @param job 327 * @throws UnsupportedOperationException 328 */ 329 public final void processReport(final ReportJob job) 330 { 331 throw new UnsupportedOperationException("Printing is a passive process."); 332 } 333 }