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: AutoTableLayoutController.java 3048 2007-07-28 18:02:42Z tmorgner $
027: * ------------
028: * (C) Copyright 2000-2005, by Object Refinery Limited.
029: * (C) Copyright 2005-2007, by Pentaho Corporation.
030: */package org.jfree.report.modules.misc.autotable.flow;
031:
032: import org.jfree.layouting.util.AttributeMap;
033: import org.jfree.report.DataSourceException;
034: import org.jfree.report.ReportDataFactoryException;
035: import org.jfree.report.ReportProcessingException;
036: import org.jfree.report.data.ReportDataRow;
037: import org.jfree.report.flow.FlowControlOperation;
038: import org.jfree.report.flow.FlowController;
039: import org.jfree.report.flow.ReportContext;
040: import org.jfree.report.flow.ReportTarget;
041: import org.jfree.report.flow.layoutprocessor.ElementLayoutController;
042: import org.jfree.report.flow.layoutprocessor.LayoutController;
043: import org.jfree.report.flow.layoutprocessor.LayoutControllerFactory;
044: import org.jfree.report.flow.layoutprocessor.LayoutControllerUtil;
045: import org.jfree.report.modules.misc.autotable.AutoTableElement;
046: import org.jfree.report.modules.misc.autotable.AutoTableModule;
047:
048: /**
049: * Creation-Date: Dec 9, 2006, 6:05:58 PM
050: *
051: * @author Thomas Morgner
052: */
053: public class AutoTableLayoutController extends ElementLayoutController {
054: public static final int HANDLING_HEADER = 0;
055: public static final int HANDLING_DATA = 1;
056: public static final int HANDLING_FOOTER = 2;
057:
058: private int currentColumn;
059: private int processingState;
060: private int columnCount;
061:
062: public AutoTableLayoutController() {
063: }
064:
065: public void initialize(final Object node,
066: final FlowController flowController,
067: final LayoutController parent) throws DataSourceException,
068: ReportDataFactoryException, ReportProcessingException {
069: super .initialize(node, flowController, parent);
070: final ReportDataRow reportDataRow = flowController
071: .getMasterRow().getReportDataRow();
072: this .columnCount = reportDataRow.getColumnCount();
073: }
074:
075: protected LayoutController processContent(final ReportTarget target)
076: throws DataSourceException, ReportProcessingException,
077: ReportDataFactoryException {
078: switch (processingState) {
079: case AutoTableLayoutController.HANDLING_HEADER:
080: return processHeader(target);
081: case AutoTableLayoutController.HANDLING_FOOTER:
082: return processFooter(target);
083: case AutoTableLayoutController.HANDLING_DATA:
084: return processData(target);
085: default:
086: throw new ReportProcessingException("No such state.");
087: }
088:
089: }
090:
091: private LayoutController processData(final ReportTarget target)
092: throws ReportProcessingException, DataSourceException,
093: ReportDataFactoryException {
094: // the auto-table is responsible for the iteration over the table.
095: final AutoTableElement node = (AutoTableElement) getElement();
096: if (node.getContentCount() == 0) {
097: throw new ReportProcessingException(
098: "An Auto-Table must have at least one defined column.");
099: }
100:
101: if (currentColumn == 0) {
102: // Start a new table-header section ..
103: final AttributeMap elementMap = LayoutControllerUtil
104: .createEmptyMap(
105: AutoTableModule.AUTOTABLE_NAMESPACE,
106: "data-row");
107: target.startElement(elementMap);
108: }
109:
110: if (currentColumn < columnCount) {
111: // now delegate the processing to the section handler for the header ..
112: final FlowController flowController = getFlowController();
113: final ReportContext reportContext = flowController
114: .getReportContext();
115: final LayoutControllerFactory layoutControllerFactory = reportContext
116: .getLayoutControllerFactory();
117:
118: final int idx = currentColumn % node.getContentCount();
119: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
120: return layoutControllerFactory.create(flowController, node
121: .getContentCell(idx), derived);
122: }
123:
124: // close the table-header section ..
125: final AttributeMap elementMap = LayoutControllerUtil
126: .createEmptyMap(AutoTableModule.AUTOTABLE_NAMESPACE,
127: "data-row");
128: target.endElement(elementMap);
129:
130: final FlowController flowController = getFlowController()
131: .performOperation(FlowControlOperation.ADVANCE);
132: final FlowController cfc = tryRepeatingCommit(flowController);
133: if (cfc != null) {
134: // Go back to the beginning. We have made a commit, so the cursor points
135: // to the next row of data ..
136: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
137: derived.setFlowController(cfc);
138: derived.currentColumn = 0;
139: return derived;
140: }
141:
142: // Advance is impossible, that means we reached the end of the group or
143: // the end of the table ..
144: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
145: derived.currentColumn = 0;
146: derived.processingState = AutoTableLayoutController.HANDLING_FOOTER;
147: return derived;
148: }
149:
150: private LayoutController processFooter(final ReportTarget target)
151: throws ReportProcessingException, DataSourceException,
152: ReportDataFactoryException {
153: final AutoTableElement node = (AutoTableElement) getElement();
154: if (node.getFooterCount() == 0) {
155: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
156: derived.currentColumn = 0;
157: derived.processingState = -1;
158: derived
159: .setProcessingState(ElementLayoutController.FINISHING);
160: return derived;
161: }
162:
163: if (currentColumn == 0) {
164: // Start a new table-header section ..
165: final AttributeMap elementMap = LayoutControllerUtil
166: .createEmptyMap(
167: AutoTableModule.AUTOTABLE_NAMESPACE,
168: "footer-row");
169: target.startElement(elementMap);
170: }
171:
172: if (currentColumn < columnCount) {
173: // now delegate the processing to the section handler for the header ..
174: final FlowController flowController = getFlowController();
175: final ReportContext reportContext = flowController
176: .getReportContext();
177: final LayoutControllerFactory layoutControllerFactory = reportContext
178: .getLayoutControllerFactory();
179:
180: final int idx = currentColumn % node.getFooterCount();
181: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
182: return layoutControllerFactory.create(flowController, node
183: .getFooterCell(idx), derived);
184: }
185:
186: // close the table-header section ..
187: final AttributeMap elementMap = LayoutControllerUtil
188: .createEmptyMap(AutoTableModule.AUTOTABLE_NAMESPACE,
189: "footer-row");
190: target.endElement(elementMap);
191:
192: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
193: derived.currentColumn = 0;
194: derived.processingState = -1;
195: derived.setProcessingState(ElementLayoutController.FINISHING);
196: return derived;
197: }
198:
199: private LayoutController processHeader(final ReportTarget target)
200: throws ReportProcessingException, DataSourceException,
201: ReportDataFactoryException {
202: final AutoTableElement node = (AutoTableElement) getElement();
203: if (node.getHeaderCount() == 0) {
204: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
205: derived.currentColumn = 0;
206: derived.processingState = AutoTableLayoutController.HANDLING_DATA;
207: return derived;
208: }
209:
210: if (currentColumn == 0) {
211: // Start a new table-header section ..
212: final AttributeMap elementMap = LayoutControllerUtil
213: .createEmptyMap(
214: AutoTableModule.AUTOTABLE_NAMESPACE,
215: "header-row");
216: target.startElement(elementMap);
217: }
218:
219: if (currentColumn < columnCount) {
220: // now delegate the processing to the section handler for the header ..
221: final FlowController flowController = getFlowController();
222: final ReportContext reportContext = flowController
223: .getReportContext();
224: final LayoutControllerFactory layoutControllerFactory = reportContext
225: .getLayoutControllerFactory();
226:
227: final int idx = currentColumn % node.getHeaderCount();
228: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
229: return layoutControllerFactory.create(flowController, node
230: .getHeaderCell(idx), derived);
231: }
232:
233: // close the table-header section ..
234: final AttributeMap elementMap = LayoutControllerUtil
235: .createEmptyMap(AutoTableModule.AUTOTABLE_NAMESPACE,
236: "header-row");
237: target.endElement(elementMap);
238:
239: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
240: derived.currentColumn = 0;
241: derived.processingState = AutoTableLayoutController.HANDLING_DATA;
242: return derived;
243: }
244:
245: /**
246: * Joins with a delegated process flow. This is generally called from a child flow and should *not* (I mean it!) be
247: * called from outside. If you do, you'll suffer.
248: *
249: * @param flowController the flow controller of the parent.
250: * @return the joined layout controller that incorperates all changes from the delegate.
251: */
252: public LayoutController join(final FlowController flowController) {
253: final AutoTableLayoutController derived = (AutoTableLayoutController) clone();
254: derived.setFlowController(flowController);
255: derived.currentColumn += 1;
256: return derived;
257: }
258:
259: public int getCurrentColumn() {
260: return currentColumn;
261: }
262: }
|