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: * LayoutProcess.java
027: * ------------
028: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029: */package org.jfree.report.states;
030:
031: import javax.swing.table.TableModel;
032:
033: import org.jfree.report.DataRow;
034: import org.jfree.report.ResourceBundleFactory;
035: import org.jfree.report.event.PageEventListener;
036: import org.jfree.report.event.PrepareEventListener;
037: import org.jfree.report.event.ReportEvent;
038: import org.jfree.report.function.ExpressionRuntime;
039: import org.jfree.report.function.OutputFunction;
040: import org.jfree.report.function.ProcessingContext;
041: import org.jfree.report.function.StructureFunction;
042: import org.jfree.report.states.datarow.DefaultFlowController;
043: import org.jfree.report.states.datarow.GlobalMasterRow;
044: import org.jfree.report.states.datarow.ReportDataRow;
045: import org.jfree.util.Configuration;
046:
047: /**
048: * Creation-Date: Dec 14, 2006, 5:05:39 PM
049: *
050: * @author Thomas Morgner
051: */
052: public class LayoutProcess implements Cloneable {
053: private static class DataRowRuntime implements ExpressionRuntime {
054: private ReportState state;
055:
056: protected DataRowRuntime() {
057: }
058:
059: public ReportState getState() {
060: return state;
061: }
062:
063: public void setState(final ReportState state) {
064: this .state = state;
065: }
066:
067: public DataRow getDataRow() {
068: return state.getDataRow();
069: }
070:
071: public Configuration getConfiguration() {
072: return getProcessingContext().getConfiguration();
073: }
074:
075: public ResourceBundleFactory getResourceBundleFactory() {
076: return getProcessingContext().getResourceBundleFactory();
077: }
078:
079: /**
080: * Access to the tablemodel was granted using report properties, now direct.
081: */
082: public TableModel getData() {
083: final DefaultFlowController flowController = state
084: .getFlowController();
085: final GlobalMasterRow masterRow = flowController
086: .getMasterRow();
087: final ReportDataRow reportDataRow = masterRow
088: .getReportDataRow();
089: if (reportDataRow != null) {
090: return reportDataRow.getReportData();
091: }
092: return null;
093: }
094:
095: /**
096: * Where are we in the current processing.
097: */
098: public int getCurrentRow() {
099: return state.getCurrentDataItem();
100: }
101:
102: /**
103: * The output descriptor is a simple string collections consisting of the following components:
104: * exportclass/type/subtype
105: * <p/>
106: * For example, the PDF export would be: pageable/pdf The StreamHTML export would return table/html/stream
107: *
108: * @return the export descriptor.
109: */
110: public String getExportDescriptor() {
111: return getProcessingContext().getExportDescriptor();
112: }
113:
114: public ProcessingContext getProcessingContext() {
115: return state.getFlowController().getReportContext();
116: }
117: }
118:
119: public static final int LEVEL_PAGINATE = -2;
120: public static final int LEVEL_COLLECT = -1;
121:
122: private OutputFunction outputFunction;
123: private StructureFunction[] collectionFunctions;
124: private boolean outputFunctionIsPageListener;
125: private boolean outputFunctionIsPrepareListener;
126: private boolean[] collectionFunctionIsPageListener;
127: private boolean[] collectionFunctionIsPrepareListener;
128: private boolean hasPrepareListener;
129: private boolean hasPageListener;
130:
131: /** @noinspection InstanceofIncompatibleInterface*/
132: public LayoutProcess(final OutputFunction outputFunction,
133: final StructureFunction[] collectionFunctions) {
134: this .outputFunction = outputFunction;
135: this .collectionFunctions = collectionFunctions;
136:
137: this .outputFunctionIsPageListener = (outputFunction instanceof PageEventListener);
138: this .outputFunctionIsPrepareListener = (outputFunction instanceof PrepareEventListener);
139: this .collectionFunctionIsPageListener = new boolean[collectionFunctions.length];
140: this .collectionFunctionIsPrepareListener = new boolean[collectionFunctions.length];
141: this .hasPageListener = outputFunctionIsPageListener;
142: this .hasPrepareListener = outputFunctionIsPrepareListener;
143: for (int i = 0; i < collectionFunctions.length; i++) {
144: final StructureFunction fn = collectionFunctions[i];
145: if (fn instanceof PageEventListener) {
146: this .collectionFunctionIsPageListener[i] = true;
147: this .hasPageListener = true;
148: }
149: if (fn instanceof PrepareEventListener) {
150: this .collectionFunctionIsPrepareListener[i] = true;
151: this .hasPrepareListener = true;
152: }
153:
154: }
155: }
156:
157: public boolean isPrepareListener() {
158: return hasPrepareListener;
159: }
160:
161: public boolean isPageListener() {
162: return hasPageListener;
163: }
164:
165: public OutputFunction getOutputFunction() {
166: return outputFunction;
167: }
168:
169: public StructureFunction[] getCollectionFunctions() {
170: return (StructureFunction[]) collectionFunctions.clone();
171: }
172:
173: public LayoutProcess deriveForStorage() {
174: try {
175: final LayoutProcess lp = (LayoutProcess) clone();
176: lp.outputFunction = outputFunction.deriveForStorage();
177: lp.collectionFunctions = (StructureFunction[]) collectionFunctions
178: .clone();
179: for (int i = 0; i < collectionFunctions.length; i++) {
180: collectionFunctions[i] = (StructureFunction) collectionFunctions[i]
181: .clone();
182: }
183: return lp;
184: } catch (CloneNotSupportedException e) {
185: throw new IllegalStateException();
186: }
187: }
188:
189: public LayoutProcess deriveForPagebreak() {
190: try {
191: final LayoutProcess lp = (LayoutProcess) clone();
192: lp.outputFunction = outputFunction.deriveForPagebreak();
193: lp.collectionFunctions = (StructureFunction[]) collectionFunctions
194: .clone();
195: for (int i = 0; i < collectionFunctions.length; i++) {
196: collectionFunctions[i] = (StructureFunction) collectionFunctions[i]
197: .clone();
198: }
199: return lp;
200: } catch (CloneNotSupportedException e) {
201: throw new IllegalStateException();
202: }
203: }
204:
205: public Object clone() throws CloneNotSupportedException {
206: return super .clone();
207: }
208:
209: public void fireReportEvent(ReportEvent event) {
210: if (event.getState().isDeepTraversing()) {
211: // this is a deep traversing state. The meaning of deep-traversing is different for the layout-process.
212: event = new ReportEvent(event.getState(), event.getType()
213: | ReportEvent.DEEP_TRAVERSING_EVENT);
214: }
215:
216: final int level = event.getLevel();
217: if (level >= 0) {
218: return;
219: }
220:
221: final ExpressionRuntime oldRuntime = outputFunction
222: .getRuntime();
223: final DataRowRuntime runtime = new DataRowRuntime();
224: runtime.setState(event.getState());
225: outputFunction.setRuntime(runtime);
226: for (int i = 0; i < collectionFunctions.length; i++) {
227: final StructureFunction function = collectionFunctions[i];
228: function.setRuntime(runtime);
229: }
230:
231: try {
232: // first check the flagged events: Prepare, Page-Start, -end, cancel and rollback
233: // before heading for the unflagged events ..
234:
235: if (event.isPrepareEvent()) {
236: firePrepareEvent(event);
237: } else if ((event.getType() & ReportEvent.PAGE_STARTED) == ReportEvent.PAGE_STARTED) {
238: firePageStartedEvent(event);
239: } else if ((event.getType() & ReportEvent.PAGE_FINISHED) == ReportEvent.PAGE_FINISHED) {
240: firePageFinishedEvent(event);
241: } else if ((event.getType() & ReportEvent.ITEMS_ADVANCED) == ReportEvent.ITEMS_ADVANCED) {
242: fireItemsAdvancedEvent(event);
243: } else if ((event.getType() & ReportEvent.ITEMS_FINISHED) == ReportEvent.ITEMS_FINISHED) {
244: fireItemsFinishedEvent(event);
245: } else if ((event.getType() & ReportEvent.ITEMS_STARTED) == ReportEvent.ITEMS_STARTED) {
246: fireItemsStartedEvent(event);
247: } else if ((event.getType() & ReportEvent.GROUP_FINISHED) == ReportEvent.GROUP_FINISHED) {
248: fireGroupFinishedEvent(event);
249: } else if ((event.getType() & ReportEvent.GROUP_STARTED) == ReportEvent.GROUP_STARTED) {
250: fireGroupStartedEvent(event);
251: } else if ((event.getType() & ReportEvent.REPORT_INITIALIZED) == ReportEvent.REPORT_INITIALIZED) {
252: fireReportInitializedEvent(event);
253: } else if ((event.getType() & ReportEvent.REPORT_DONE) == ReportEvent.REPORT_DONE) {
254: fireReportDoneEvent(event);
255: } else if ((event.getType() & ReportEvent.REPORT_FINISHED) == ReportEvent.REPORT_FINISHED) {
256: fireReportFinishedEvent(event);
257: } else if ((event.getType() & ReportEvent.REPORT_STARTED) == ReportEvent.REPORT_STARTED) {
258: fireReportStartedEvent(event);
259: } else {
260: throw new IllegalArgumentException();
261: }
262: } finally {
263: outputFunction.setRuntime(oldRuntime);
264: for (int i = 0; i < collectionFunctions.length; i++) {
265: final StructureFunction function = collectionFunctions[i];
266: function.setRuntime(oldRuntime);
267: }
268: }
269: }
270:
271: private void fireItemsAdvancedEvent(final ReportEvent event) {
272: final int activeLevel = event.getState().getLevel();
273:
274: for (int i = 0; i < collectionFunctions.length; i++) {
275: final StructureFunction function = collectionFunctions[i];
276: function.itemsAdvanced(event);
277: }
278:
279: if (activeLevel == LEVEL_PAGINATE) {
280: outputFunction.itemsAdvanced(event);
281: }
282: }
283:
284: private void fireItemsStartedEvent(final ReportEvent event) {
285: final int activeLevel = event.getState().getLevel();
286:
287: for (int i = 0; i < collectionFunctions.length; i++) {
288: final StructureFunction function = collectionFunctions[i];
289: function.itemsStarted(event);
290: }
291:
292: if (activeLevel == LEVEL_PAGINATE) {
293: outputFunction.itemsStarted(event);
294: }
295:
296: }
297:
298: private void fireItemsFinishedEvent(final ReportEvent event) {
299: final int activeLevel = event.getState().getLevel();
300:
301: for (int i = 0; i < collectionFunctions.length; i++) {
302: final StructureFunction function = collectionFunctions[i];
303: function.itemsFinished(event);
304: }
305:
306: if (activeLevel == LEVEL_PAGINATE) {
307: outputFunction.itemsFinished(event);
308: }
309: }
310:
311: private void fireGroupStartedEvent(final ReportEvent event) {
312: final int activeLevel = event.getState().getLevel();
313:
314: for (int i = 0; i < collectionFunctions.length; i++) {
315: final StructureFunction function = collectionFunctions[i];
316: function.groupStarted(event);
317: }
318:
319: if (activeLevel == LEVEL_PAGINATE) {
320: outputFunction.groupStarted(event);
321: }
322: }
323:
324: private void fireGroupFinishedEvent(final ReportEvent event) {
325: final int activeLevel = event.getState().getLevel();
326:
327: for (int i = 0; i < collectionFunctions.length; i++) {
328: final StructureFunction function = collectionFunctions[i];
329: function.groupFinished(event);
330: }
331:
332: if (activeLevel == LEVEL_PAGINATE) {
333: outputFunction.groupFinished(event);
334: }
335:
336: }
337:
338: private void fireReportStartedEvent(final ReportEvent event) {
339: final int activeLevel = event.getState().getLevel();
340:
341: for (int i = 0; i < collectionFunctions.length; i++) {
342: final StructureFunction function = collectionFunctions[i];
343: function.reportStarted(event);
344: }
345:
346: if (activeLevel == LEVEL_PAGINATE) {
347: outputFunction.reportStarted(event);
348: }
349:
350: }
351:
352: private void fireReportDoneEvent(final ReportEvent event) {
353: final int activeLevel = event.getState().getLevel();
354:
355: for (int i = 0; i < collectionFunctions.length; i++) {
356: final StructureFunction function = collectionFunctions[i];
357: function.reportDone(event);
358: }
359:
360: if (activeLevel == LEVEL_PAGINATE) {
361: outputFunction.reportDone(event);
362: }
363:
364: }
365:
366: private void fireReportFinishedEvent(final ReportEvent event) {
367: final int activeLevel = event.getState().getLevel();
368:
369: for (int i = 0; i < collectionFunctions.length; i++) {
370: final StructureFunction function = collectionFunctions[i];
371: function.reportFinished(event);
372: }
373:
374: if (activeLevel == LEVEL_PAGINATE) {
375: outputFunction.reportFinished(event);
376: }
377:
378: }
379:
380: private void fireReportInitializedEvent(final ReportEvent event) {
381: final int activeLevel = event.getState().getLevel();
382:
383: for (int i = 0; i < collectionFunctions.length; i++) {
384: final StructureFunction function = collectionFunctions[i];
385: function.reportInitialized(event);
386: }
387:
388: if (activeLevel == LEVEL_PAGINATE) {
389: outputFunction.reportInitialized(event);
390: }
391:
392: }
393:
394: private void firePageStartedEvent(final ReportEvent event) {
395: final int activeLevel = event.getState().getLevel();
396:
397: for (int i = 0; i < collectionFunctions.length; i++) {
398: final StructureFunction function = collectionFunctions[i];
399: if (collectionFunctionIsPageListener[i]) {
400: final PageEventListener pel = (PageEventListener) function;
401: pel.pageStarted(event);
402: }
403: }
404:
405: if (activeLevel == LEVEL_PAGINATE
406: && outputFunctionIsPageListener) {
407: final PageEventListener pel = (PageEventListener) outputFunction;
408: pel.pageStarted(event);
409: }
410: }
411:
412: private void firePageFinishedEvent(final ReportEvent event) {
413: final int activeLevel = event.getState().getLevel();
414:
415: for (int i = 0; i < collectionFunctions.length; i++) {
416: final StructureFunction function = collectionFunctions[i];
417: if (collectionFunctionIsPageListener[i]) {
418: final PageEventListener pel = (PageEventListener) function;
419: pel.pageFinished(event);
420: }
421: }
422:
423: if (activeLevel == LEVEL_PAGINATE
424: && outputFunctionIsPageListener) {
425: final PageEventListener pel = (PageEventListener) outputFunction;
426: pel.pageFinished(event);
427: }
428:
429: }
430:
431: /** @noinspection CastToIncompatibleInterface*/
432: private void firePrepareEvent(final ReportEvent event) {
433: final int activeLevel = event.getState().getLevel();
434:
435: for (int i = 0; i < collectionFunctions.length; i++) {
436: final StructureFunction function = collectionFunctions[i];
437: if (collectionFunctionIsPrepareListener[i]) {
438: final PrepareEventListener pel = (PrepareEventListener) function;
439: pel.prepareEvent(event);
440: }
441: }
442:
443: if (activeLevel == LEVEL_PAGINATE
444: && outputFunctionIsPrepareListener) {
445: final PrepareEventListener pel = (PrepareEventListener) outputFunction;
446: pel.prepareEvent(event);
447: }
448:
449: }
450: }
|