001: /**
002: * ===========================================
003: * JFreeReport : a free Java reporting library
004: * ===========================================
005: *
006: * Project Info: http://reporting.pentaho.org/
007: *
008: * (C) Copyright 2001-2007, by Object Refinery Ltd, 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: * DefaultFlowController.java
027: * ------------
028: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029: */package org.jfree.report.states.datarow;
030:
031: import org.jfree.report.DataFactory;
032: import org.jfree.report.ParameterDataRow;
033: import org.jfree.report.ParameterMapping;
034: import org.jfree.report.ReportDataFactoryException;
035: import org.jfree.report.ReportProcessingException;
036: import org.jfree.report.event.ReportEvent;
037: import org.jfree.report.function.Expression;
038: import org.jfree.report.function.ProcessingContext;
039: import org.jfree.report.states.CachingDataFactory;
040: import org.jfree.report.util.IntegerCache;
041: import org.jfree.report.util.ReportProperties;
042: import org.jfree.util.FastStack;
043:
044: /**
045: * Creation-Date: 20.02.2006, 15:30:21
046: *
047: * @author Thomas Morgner
048: */
049: public final class DefaultFlowController {
050: private static class ReportDataContext {
051: private boolean advanceRequested;
052:
053: protected ReportDataContext(final boolean advanceRequested) {
054: this .advanceRequested = advanceRequested;
055: }
056:
057: public boolean isAdvanceRequested() {
058: return advanceRequested;
059: }
060: }
061:
062: private CachingDataFactory reportDataFactory;
063: private GlobalMasterRow dataRow;
064: private boolean advanceRequested;
065: private ReportDataContext dataContext;
066: private FastStack expressionsStack;
067: private String exportDescriptor;
068: private ProcessingContext reportContext;
069: private ReportProperties parameters;
070:
071: public DefaultFlowController(final ProcessingContext reportContext,
072: final DataFactory dataFactory,
073: final ReportProperties parameters)
074: throws ReportDataFactoryException {
075: if (reportContext == null) {
076: throw new NullPointerException();
077: }
078: if (dataFactory == null) {
079: throw new NullPointerException();
080: }
081: if (parameters == null) {
082: throw new NullPointerException();
083: }
084:
085: this .reportContext = reportContext;
086: this .exportDescriptor = reportContext.getExportDescriptor();
087: this .reportDataFactory = new CachingDataFactory(dataFactory
088: .derive());
089: this .expressionsStack = new FastStack();
090: this .advanceRequested = false;
091: this .parameters = parameters;
092:
093: this .dataRow = GlobalMasterRow.createReportRow(reportContext);
094: this .dataRow.setParameterDataRow(new ParameterDataRow(
095: parameters));
096: }
097:
098: private DefaultFlowController(final DefaultFlowController fc,
099: final GlobalMasterRow dataRow) {
100: this .reportContext = fc.reportContext;
101: this .exportDescriptor = fc.exportDescriptor;
102: this .reportDataFactory = fc.reportDataFactory;
103: this .dataContext = fc.dataContext;
104: this .expressionsStack = (FastStack) fc.expressionsStack.clone();
105: this .advanceRequested = fc.advanceRequested;
106: this .dataRow = dataRow;
107: this .parameters = fc.parameters;
108: }
109:
110: public DefaultFlowController derive() {
111: return new DefaultFlowController(this , dataRow.derive());
112: }
113:
114: public DefaultFlowController performAdvance() {
115: if (dataRow.isAdvanceable() && advanceRequested == false) {
116: final DefaultFlowController fc = new DefaultFlowController(
117: this , dataRow);
118: fc.advanceRequested = true;
119: return fc;
120: }
121: return this ;
122: }
123:
124: public DefaultFlowController performCommit() {
125: if (isAdvanceRequested()) {
126: final DefaultFlowController fc = new DefaultFlowController(
127: this , dataRow);
128: fc.dataRow = dataRow.advance();
129: fc.advanceRequested = false;
130: return fc;
131: }
132: return this ;
133: }
134:
135: public GlobalMasterRow getMasterRow() {
136: return dataRow;
137: }
138:
139: public boolean isAdvanceRequested() {
140: return advanceRequested;
141: }
142:
143: /**
144: * This should be called only once per report processing. A JFreeReport object
145: * defines the global master report - all other reports are subreport
146: * instances.
147: * <p/>
148: * The global master report receives its parameter set from the
149: * Job-Definition, while subreports will read their parameters from the
150: * current datarow state.
151: *
152: * @param query
153: * @return
154: * @throws ReportDataFactoryException
155: */
156: public DefaultFlowController performQuery(final String query)
157: throws ReportDataFactoryException {
158: final GlobalMasterRow outerRow = dataRow.derive();
159:
160: final GlobalMasterRow masterRow = GlobalMasterRow
161: .createReportRow(outerRow, reportContext);
162: masterRow.setParameterDataRow(new ParameterDataRow(parameters));
163: masterRow.setReportDataRow(ReportDataRow.createDataRow(
164: reportDataFactory, query, masterRow.getGlobalView()));
165:
166: final DefaultFlowController fc = new DefaultFlowController(
167: this , masterRow);
168: fc.dataContext = new ReportDataContext(advanceRequested);
169: fc.dataRow = masterRow;
170: return fc;
171: }
172:
173: public DefaultFlowController performSubReportQuery(
174: final String query,
175: final ParameterMapping[] inputParameters,
176: final ParameterMapping[] outputParameters)
177: throws ReportDataFactoryException {
178: final GlobalMasterRow parentDataRow = dataRow.derive();
179:
180: // create a view for the parameters of the report ...
181: final GlobalMasterRow subReportDataRow = GlobalMasterRow
182: .createReportRow(parentDataRow, reportContext);
183: if (isGlobalImportOrExport(inputParameters)) {
184: subReportDataRow.setParameterDataRow(new ParameterDataRow(
185: parentDataRow.getGlobalView()));
186: } else {
187: subReportDataRow.setParameterDataRow(new ParameterDataRow(
188: inputParameters, parentDataRow.getGlobalView()));
189: }
190:
191: // perform the query ...
192: // add the resultset ...
193:
194: subReportDataRow.setReportDataRow(ReportDataRow.createDataRow(
195: reportDataFactory, query, subReportDataRow
196: .getGlobalView()));
197:
198: if (isGlobalImportOrExport(outputParameters)) {
199: parentDataRow
200: .setExportedDataRow(new ImportedVariablesDataRow(
201: subReportDataRow));
202: } else {
203: // check and rebuild the parameter mapping from the inner to the outer
204: // context. Only deep-traversal expressions will be able to see these
205: // values (unless they have been defined as local variables).
206: parentDataRow
207: .setExportedDataRow(new ImportedVariablesDataRow(
208: subReportDataRow, outputParameters));
209: }
210:
211: final DefaultFlowController fc = new DefaultFlowController(
212: this , subReportDataRow);
213: fc.dataContext = new ReportDataContext(advanceRequested);
214: fc.dataRow = subReportDataRow;
215: return fc;
216: }
217:
218: /**
219: * Checks, whether a global import is defined. A global import effectly
220: * overrides all other imports.
221: *
222: * @return true, if there is a global import defined, false otherwise.
223: */
224: private boolean isGlobalImportOrExport(
225: final ParameterMapping[] inputParameters) {
226: for (int i = 0; i < inputParameters.length; i++) {
227: final ParameterMapping inputParameter = inputParameters[i];
228: if ("*".equals(inputParameter.getName())
229: && "*".equals(inputParameter.getAlias())) {
230: return true;
231: }
232: }
233: return false;
234: }
235:
236: public DefaultFlowController activateExpressions(
237: final Expression[] expressions, final boolean preserveState)
238: throws ReportProcessingException {
239: final GlobalMasterRow dataRow = this .dataRow.derive();
240: final ExpressionDataRow edr = dataRow.getExpressionDataRow();
241: edr.pushExpressions(expressions, preserveState);
242:
243: final DefaultFlowController fc = new DefaultFlowController(
244: this , dataRow);
245: final Integer exCount = IntegerCache
246: .getInteger(expressions.length);
247: fc.expressionsStack.push(exCount);
248: return fc;
249: }
250:
251: public DefaultFlowController deactivateExpressions() {
252: final Integer counter = (Integer) this .expressionsStack.peek();
253: final int counterRaw = counter.intValue();
254: if (counterRaw == 0) {
255: final DefaultFlowController fc = new DefaultFlowController(
256: this , dataRow);
257: fc.expressionsStack.pop();
258: return fc;
259: }
260:
261: final GlobalMasterRow dataRow = this .dataRow.derive();
262: final ExpressionDataRow edr = dataRow.getExpressionDataRow();
263:
264: final DefaultFlowController fc = new DefaultFlowController(
265: this , dataRow);
266: fc.expressionsStack.pop();
267: edr.popExpressions(counterRaw);
268: return fc;
269: }
270:
271: public DefaultFlowController performReturnFromQuery() {
272: final ReportDataRow reportDataRow = dataRow.getReportDataRow();
273: if (reportDataRow == null) {
274: return this ;
275: }
276: // We dont close the report data, as some previously saved states may
277: // still reference it. (The caching report data factory takes care of
278: // that later.)
279:
280: final GlobalMasterRow innerDr = dataRow.derive();
281: innerDr.setReportDataRow(null);
282: innerDr.setParameterDataRow(null);
283:
284: final DefaultFlowController fc = new DefaultFlowController(
285: this , innerDr);
286: final ReportDataContext context = fc.dataContext;
287: fc.dataRow = dataRow.getParentDataRow();
288: fc.dataRow = fc.dataRow.derive();
289: fc.advanceRequested = context.isAdvanceRequested();
290: return fc;
291: }
292:
293: public DefaultFlowController performClearExportedParameters() {
294: final ImportedVariablesDataRow exportedDataRow = dataRow
295: .getExportedDataRow();
296: if (exportedDataRow == null) {
297: return this ;
298: }
299:
300: final DefaultFlowController derived = derive();
301: derived.dataRow.setExportedDataRow(null);
302: return derived;
303: }
304:
305: public String getExportDescriptor() {
306: return exportDescriptor;
307: }
308:
309: public ProcessingContext getReportContext() {
310: return reportContext;
311: }
312:
313: public DefaultFlowController fireReportEvent(final ReportEvent event) {
314: dataRow.fireReportEvent(event);
315: return this ;
316: }
317:
318: public int getCursor() {
319: if (dataRow.getReportDataRow() != null) {
320: return dataRow.getReportDataRow().getCursor();
321: }
322: return 0;
323: }
324:
325: public CachingDataFactory getDataFactory() {
326: return reportDataFactory;
327: }
328: }
|