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: DefaultFlowController.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.flow;
031:
032: import org.jfree.report.DataSourceException;
033: import org.jfree.report.ReportDataFactoryException;
034: import org.jfree.report.data.CachingReportDataFactory;
035: import org.jfree.report.data.ExpressionDataRow;
036: import org.jfree.report.data.ExpressionSlot;
037: import org.jfree.report.data.GlobalMasterRow;
038: import org.jfree.report.data.ImportedVariablesDataRow;
039: import org.jfree.report.data.ParameterDataRow;
040: import org.jfree.report.data.PrecomputedValueRegistry;
041: import org.jfree.report.data.PrecomputedValueRegistryBuilder;
042: import org.jfree.report.data.ReportDataRow;
043: import org.jfree.report.util.IntegerCache;
044: import org.jfree.util.FastStack;
045:
046: /**
047: * Creation-Date: 20.02.2006, 15:30:21
048: *
049: * @author Thomas Morgner
050: */
051: public class DefaultFlowController implements FlowController {
052: private static class ReportDataContext {
053: private FastStack markStack;
054: private boolean advanceRequested;
055:
056: private ReportDataContext(final FastStack markStack,
057: final boolean advanceRequested) {
058: this .advanceRequested = advanceRequested;
059: this .markStack = markStack;
060: }
061:
062: public boolean isAdvanceRequested() {
063: return advanceRequested;
064: }
065:
066: public FastStack getMarkStack() {
067: return markStack;
068: }
069: }
070:
071: private CachingReportDataFactory reportDataFactory;
072: private GlobalMasterRow dataRow;
073: private boolean advanceRequested;
074: private FastStack reportStack;
075: private FastStack markStack;
076: private FastStack expressionsStack;
077: private String exportDescriptor;
078: private ReportContext reportContext;
079: private ReportJob job;
080: private PrecomputedValueRegistry precomputedValueRegistry;
081:
082: public DefaultFlowController(final ReportContext reportContext,
083: final ReportJob job) throws DataSourceException {
084: if (job == null) {
085: throw new NullPointerException();
086: }
087: if (reportContext == null) {
088: throw new NullPointerException();
089: }
090:
091: this .reportContext = reportContext;
092: this .job = job;
093: this .exportDescriptor = reportContext.getExportDescriptor();
094: this .reportDataFactory = new CachingReportDataFactory(job
095: .getDataFactory());
096: this .reportStack = new FastStack();
097: this .markStack = new FastStack();
098: this .expressionsStack = new FastStack();
099: this .advanceRequested = false;
100: this .dataRow = GlobalMasterRow.createReportRow(reportContext);
101: this .dataRow.setParameterDataRow(new ParameterDataRow(job
102: .getParameters()));
103: this .precomputedValueRegistry = new PrecomputedValueRegistryBuilder();
104: }
105:
106: protected DefaultFlowController(final DefaultFlowController fc,
107: final GlobalMasterRow dataRow) {
108: this .reportContext = fc.reportContext;
109: this .job = fc.job;
110: this .exportDescriptor = fc.exportDescriptor;
111: this .reportDataFactory = fc.reportDataFactory;
112: this .reportStack = (FastStack) fc.reportStack.clone();
113: this .markStack = (FastStack) fc.markStack.clone();
114: this .expressionsStack = (FastStack) fc.expressionsStack.clone();
115: this .advanceRequested = fc.advanceRequested;
116: this .dataRow = dataRow;
117: this .precomputedValueRegistry = fc.precomputedValueRegistry;
118: }
119:
120: public FlowController performOperation(
121: final FlowControlOperation operation)
122: throws DataSourceException {
123: if (operation == FlowControlOperation.ADVANCE) {
124: if (dataRow.isAdvanceable() && advanceRequested == false) {
125: final DefaultFlowController fc = new DefaultFlowController(
126: this , dataRow);
127: fc.advanceRequested = true;
128: return fc;
129: }
130: } else if (operation == FlowControlOperation.MARK) {
131: final DefaultFlowController fc = new DefaultFlowController(
132: this , dataRow);
133: fc.markStack.push(dataRow);
134: return fc;
135: } else if (operation == FlowControlOperation.RECALL) {
136: if (markStack.isEmpty()) {
137: return this ;
138: }
139:
140: final DefaultFlowController fc = new DefaultFlowController(
141: this , dataRow);
142: fc.dataRow = (GlobalMasterRow) fc.markStack.pop();
143: fc.advanceRequested = false;
144: return fc;
145: } else if (operation == FlowControlOperation.DONE) {
146: // do not change the current data row..
147:
148: final DefaultFlowController fc = new DefaultFlowController(
149: this , dataRow);
150: fc.markStack.pop();
151: return fc;
152: } else if (operation == FlowControlOperation.COMMIT) {
153: if (isAdvanceRequested()) {
154: final DefaultFlowController fc = new DefaultFlowController(
155: this , dataRow);
156: fc.dataRow = dataRow.advance();
157: fc.advanceRequested = false;
158: return fc;
159: }
160: }
161: return this ;
162: }
163:
164: public GlobalMasterRow getMasterRow() {
165: return dataRow;
166: }
167:
168: public boolean isAdvanceRequested() {
169: return advanceRequested;
170: }
171:
172: /**
173: * This should be called only once per report processing. A JFreeReport object
174: * defines the global master report - all other reports are subreport
175: * instances.
176: * <p/>
177: * The global master report receives its parameter set from the
178: * Job-Definition, while subreports will read their parameters from the
179: * current datarow state.
180: *
181: * @param query
182: * @return
183: * @throws ReportDataFactoryException
184: * @throws DataSourceException
185: */
186: public FlowController performQuery(final String query)
187: throws ReportDataFactoryException, DataSourceException {
188:
189: final GlobalMasterRow masterRow = GlobalMasterRow
190: .createReportRow(dataRow, reportContext);
191: masterRow.setParameterDataRow(new ParameterDataRow(
192: getReportJob().getParameters()));
193:
194: masterRow.setReportDataRow(ReportDataRow.createDataRow(
195: reportDataFactory, query, dataRow.getGlobalView()));
196:
197: final DefaultFlowController fc = new DefaultFlowController(
198: this , masterRow);
199: fc.reportStack.push(new ReportDataContext(fc.markStack,
200: advanceRequested));
201: fc.markStack = new FastStack();
202: fc.dataRow = masterRow;
203: return fc;
204: }
205:
206: public FlowController performSubReportQuery(final String query,
207: final ParameterMapping[] inputParameters,
208: final ParameterMapping[] outputParameters)
209: throws ReportDataFactoryException, DataSourceException {
210: final GlobalMasterRow outerRow = dataRow.derive();
211:
212: // create a view for the parameters of the report ...
213: final GlobalMasterRow masterRow = GlobalMasterRow
214: .createReportRow(outerRow, reportContext);
215:
216: masterRow.setParameterDataRow(new ParameterDataRow(
217: inputParameters, outerRow.getGlobalView()));
218:
219: // perform the query ...
220: // add the resultset ...
221: masterRow.setReportDataRow(ReportDataRow.createDataRow(
222: reportDataFactory, query, masterRow.getGlobalView()));
223:
224: if (outputParameters == null) {
225: outerRow.setExportedDataRow(new ImportedVariablesDataRow(
226: masterRow));
227: } else {
228: // check and rebuild the parameter mapping from the inner to the outer
229: // context. Only deep-traversal expressions will be able to see these
230: // values (unless they have been defined as local variables).
231: outerRow.setExportedDataRow(new ImportedVariablesDataRow(
232: masterRow, outputParameters));
233: }
234:
235: final DefaultFlowController fc = new DefaultFlowController(
236: this , masterRow);
237: fc.reportStack.push(new ReportDataContext(fc.markStack,
238: advanceRequested));
239: fc.markStack = new FastStack();
240: fc.dataRow = masterRow;
241: return fc;
242: }
243:
244: public FlowController activateExpressions(
245: final ExpressionSlot[] expressions)
246: throws DataSourceException {
247: if (expressions.length == 0) {
248: final DefaultFlowController fc = new DefaultFlowController(
249: this , dataRow);
250: fc.expressionsStack.push(IntegerCache.getInteger(0));
251: return fc;
252: }
253:
254: final GlobalMasterRow dataRow = this .dataRow.derive();
255: final ExpressionDataRow edr = dataRow.getExpressionDataRow();
256: edr.pushExpressions(expressions);
257:
258: final DefaultFlowController fc = new DefaultFlowController(
259: this , dataRow);
260: final Integer exCount = IntegerCache
261: .getInteger(expressions.length);
262: fc.expressionsStack.push(exCount);
263: return fc;
264: }
265:
266: public FlowController deactivateExpressions()
267: throws DataSourceException {
268: final Integer counter = (Integer) this .expressionsStack.peek();
269: final int counterRaw = counter.intValue();
270: if (counterRaw == 0) {
271: final DefaultFlowController fc = new DefaultFlowController(
272: this , dataRow);
273: fc.expressionsStack.pop();
274: return fc;
275: }
276:
277: final GlobalMasterRow dataRow = this .dataRow.derive();
278: final ExpressionDataRow edr = dataRow.getExpressionDataRow();
279:
280: final DefaultFlowController fc = new DefaultFlowController(
281: this , dataRow);
282: fc.expressionsStack.pop();
283: edr.popExpressions(counterRaw);
284: return fc;
285: }
286:
287: public FlowController performReturnFromQuery()
288: throws DataSourceException {
289: final DefaultFlowController fc = new DefaultFlowController(
290: this , dataRow);
291: final ReportDataRow reportDataRow = dataRow.getReportDataRow();
292: if (reportDataRow == null) {
293: return this ;
294: }
295: // We dont close the report data, as some previously saved states may
296: // still reference it. (The caching report data factory takes care of
297: // that later.)
298:
299: final ReportDataContext context = (ReportDataContext) fc.reportStack
300: .pop();
301: fc.dataRow = dataRow.getParentDataRow();
302: fc.dataRow = fc.dataRow.derive();
303: fc.dataRow.setExportedDataRow(null);
304: fc.markStack = context.getMarkStack();
305: fc.advanceRequested = context.isAdvanceRequested();
306: return fc;
307: }
308:
309: public ReportJob getReportJob() {
310: return job;
311: }
312:
313: public String getExportDescriptor() {
314: return exportDescriptor;
315: }
316:
317: public ReportContext getReportContext() {
318: return reportContext;
319: }
320:
321: /**
322: * Returns the current expression slots of all currently active expressions.
323: *
324: * @return
325: * @throws org.jfree.report.DataSourceException
326: *
327: */
328: public ExpressionSlot[] getActiveExpressions()
329: throws DataSourceException {
330: return dataRow.getExpressionDataRow().getSlots();
331: }
332:
333: public FlowController createPrecomputeInstance()
334: throws DataSourceException {
335: final DefaultFlowController precompute = new DefaultFlowController(
336: this , dataRow.derive());
337: precompute.precomputedValueRegistry = new PrecomputedValueRegistryBuilder();
338: return precompute;
339: }
340:
341: public PrecomputedValueRegistry getPrecomputedValueRegistry() {
342: return precomputedValueRegistry;
343: }
344: }
|