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: BufferingLayoutController.java 2725 2007-04-01 18:49:29Z taqua $ 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.flow.layoutprocessor; 033 034 import org.jfree.report.DataSourceException; 035 import org.jfree.report.ReportDataFactoryException; 036 import org.jfree.report.ReportProcessingException; 037 import org.jfree.report.flow.FlowController; 038 import org.jfree.report.flow.ReportTarget; 039 040 /** 041 * Todo: Document me! 042 * 043 * @author Thomas Morgner 044 * @since 05.03.2007 045 */ 046 public abstract class BufferingLayoutController 047 extends AbstractLayoutController 048 { 049 private BufferedReportTarget reportTarget; 050 private LayoutController delegate; 051 private boolean finished; 052 053 protected BufferingLayoutController() 054 { 055 reportTarget = new BufferedReportTarget(); 056 } 057 058 /** 059 * Advances the processing position. 060 * 061 * @param target the report target that receives generated events. 062 * @return the new layout controller instance representing the new state. 063 * 064 * @throws DataSourceException if there was a problem reading data from 065 * the datasource. 066 * @throws ReportProcessingException if there was a general problem during 067 * the report processing. 068 * @throws ReportDataFactoryException if a query failed. 069 */ 070 public LayoutController advance(final ReportTarget target) 071 throws DataSourceException, ReportDataFactoryException, 072 ReportProcessingException 073 { 074 reportTarget.setTarget(target); 075 if (delegate != null) 076 { 077 try 078 { 079 final BufferingLayoutController bc = (BufferingLayoutController) clone(); 080 bc.delegate = delegate.advance(reportTarget); 081 return bc; 082 } 083 finally 084 { 085 reportTarget.setTarget(null); 086 } 087 } 088 089 // write all buffered changes to the real report target. 090 reportTarget.close(target); 091 if (getParent() == null) 092 { 093 final BufferingLayoutController bc = (BufferingLayoutController) clone(); 094 bc.finished = true; 095 return bc; 096 } 097 098 return joinWithParent(); 099 } 100 101 /** 102 * Joins the layout controller with the parent. This simply calls 103 * {@link #join(org.jfree.report.flow.FlowController)} on the parent. A join 104 * operation is necessary to propagate changes in the flow-controller to the 105 * parent for further processing. 106 * 107 * @return the joined parent. 108 * @throws IllegalStateException if this layout controller has no parent. 109 * @throws org.jfree.report.ReportProcessingException 110 * @throws org.jfree.report.ReportDataFactoryException 111 * @throws org.jfree.report.DataSourceException 112 */ 113 protected LayoutController joinWithParent() 114 throws ReportProcessingException, ReportDataFactoryException, 115 DataSourceException 116 { 117 final LayoutController parent = getParent(); 118 if (parent == null) 119 { 120 // skip to the next step .. 121 throw new IllegalStateException("There is no parent to join with. " + 122 "This should not happen in a sane environment!"); 123 } 124 125 return parent.join(getFlowController()); 126 } 127 128 129 /** 130 * Initializes the layout controller. This method is called exactly once. It 131 * is the creators responsibility to call this method. 132 * <p/> 133 * Calling initialize after the first advance must result in a 134 * IllegalStateException. 135 * 136 * @param node the currently processed object or layout node. 137 * @param flowController the current flow controller. 138 * @param parent the parent layout controller that was responsible for 139 * instantiating this controller. 140 * @throws DataSourceException if there was a problem reading data from 141 * the datasource. 142 * @throws ReportProcessingException if there was a general problem during 143 * the report processing. 144 * @throws ReportDataFactoryException if a query failed. 145 */ 146 public void initialize(final Object node, final FlowController flowController, 147 final LayoutController parent) 148 throws DataSourceException, ReportDataFactoryException, 149 ReportProcessingException 150 { 151 super.initialize(node, flowController, parent); 152 delegate = getInitialDelegate(); 153 } 154 155 protected abstract LayoutController getInitialDelegate(); 156 157 public boolean isAdvanceable() 158 { 159 if (delegate == null) 160 { 161 return finished == false; 162 } 163 return delegate.isAdvanceable(); 164 } 165 166 /** 167 * Joins with a delegated process flow. This is generally called from a child 168 * flow and should *not* (I mean it!) be called from outside. If you do, 169 * you'll suffer. 170 * 171 * @param flowController the flow controller of the parent. 172 * @return the joined layout controller that incorperates all changes from 173 * the delegate. 174 */ 175 public LayoutController join(final FlowController flowController) 176 throws ReportProcessingException, DataSourceException 177 { 178 // the delegation is finished, the element has returned. 179 final BufferingLayoutController bc = (BufferingLayoutController) clone(); 180 bc.delegate = null; 181 return bc; 182 } 183 184 public Object clone() 185 { 186 final BufferingLayoutController o = (BufferingLayoutController) super.clone(); 187 o.reportTarget = (BufferedReportTarget) reportTarget.clone(); 188 return o; 189 } 190 }