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,v 1.3 2007/04/01 18:49:25 taqua Exp $
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 }