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: SectionLayoutController.java 3057 2007-07-30 14:27:28Z 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.layoutprocessor;
031:
032: import org.jfree.report.DataSourceException;
033: import org.jfree.report.ReportDataFactoryException;
034: import org.jfree.report.ReportProcessingException;
035: import org.jfree.report.expressions.Expression;
036: import org.jfree.report.flow.FlowController;
037: import org.jfree.report.flow.ReportContext;
038: import org.jfree.report.flow.ReportTarget;
039: import org.jfree.report.structure.Node;
040: import org.jfree.report.structure.Section;
041:
042: /**
043: * Creation-Date: 24.11.2006, 13:56:10
044: *
045: * @author Thomas Morgner
046: */
047: public class SectionLayoutController extends ElementLayoutController {
048: // we store the child instead of the index, as the report can be manipulated
049: // it is safer this way ..
050: private Node[] nodes;
051: private int index;
052:
053: public SectionLayoutController() {
054: }
055:
056: protected FlowController startData(final ReportTarget target,
057: final FlowController fc) throws DataSourceException,
058: ReportProcessingException, ReportDataFactoryException {
059: final Section s = (Section) getElement();
060: return LayoutControllerUtil.processFlowOperations(fc, s
061: .getOperationBefore());
062: }
063:
064: protected LayoutController processContent(final ReportTarget target)
065: throws DataSourceException, ReportProcessingException,
066: ReportDataFactoryException {
067:
068: final FlowController flowController = getFlowController();
069:
070: final Node[] nodes = getNodes();
071: final int currentIndex = getIndex();
072: if (currentIndex < nodes.length) {
073: final Node node = nodes[currentIndex];
074: final SectionLayoutController derived = (SectionLayoutController) clone();
075: return processChild(derived, node, flowController);
076: } else {
077: final SectionLayoutController derived = (SectionLayoutController) clone();
078: derived
079: .setProcessingState(ElementLayoutController.FINISHING);
080: return derived;
081: }
082: }
083:
084: protected LayoutController processChild(
085: final SectionLayoutController derived, final Node node,
086: final FlowController flowController)
087: throws DataSourceException, ReportProcessingException,
088: ReportDataFactoryException {
089: final ReportContext reportContext = flowController
090: .getReportContext();
091: final LayoutControllerFactory layoutControllerFactory = reportContext
092: .getLayoutControllerFactory();
093: if (isDisplayable(node)) {
094: derived
095: .setProcessingState(ElementLayoutController.WAITING_FOR_JOIN);
096: return layoutControllerFactory.create(flowController, node,
097: derived);
098: } else {
099: derived
100: .setProcessingState(ElementLayoutController.WAITING_FOR_JOIN);
101: final LayoutController childLc = layoutControllerFactory
102: .create(flowController, node, derived);
103: return LayoutControllerUtil.skipInvisibleElement(childLc);
104: // derived.setIndex(derived.getIndex() + 1);
105: // return LayoutControllerUtil.skipInvisibleElement(derived);
106: }
107: }
108:
109: protected boolean isDisplayable(final Node node)
110: throws DataSourceException {
111: if (node.isEnabled() == false) {
112: return false;
113: }
114:
115: final Expression expression = node.getDisplayCondition();
116: if (expression == null) {
117: return true;
118: }
119:
120: final Object result = LayoutControllerUtil.evaluateExpression(
121: getFlowController(), node, expression);
122: if (Boolean.TRUE.equals(result)) {
123: return true;
124: }
125: return false;
126: }
127:
128: /**
129: * Finishes the processing of this element. This method is called when the
130: * processing state is 'FINISHING'. The element should be closed now and all
131: * privatly owned resources should be freed. If the element has a parent, it
132: * would be time to join up with the parent now, else the processing state
133: * should be set to 'FINISHED'.
134: *
135: * @param target the report target that receives generated events.
136: * @return the new layout controller instance representing the new state.
137: *
138: * @throws DataSourceException if there was a problem reading data from
139: * the datasource.
140: * @throws ReportProcessingException if there was a general problem during
141: * the report processing.
142: * @throws ReportDataFactoryException if there was an error trying query
143: * data.
144: */
145: protected LayoutController finishElement(final ReportTarget target)
146: throws ReportProcessingException, DataSourceException,
147: ReportDataFactoryException {
148: FlowController fc = handleDefaultEndElement(target);
149:
150: // unwind the stack ..
151: final Section s = (Section) getElement();
152: fc = finishData(target, fc);
153:
154: if (s.isRepeat()) {
155: final FlowController cfc = tryRepeatingCommit(fc);
156: if (cfc != null) {
157: // Go back to the beginning ...
158: final SectionLayoutController derived = (SectionLayoutController) clone();
159: derived
160: .setProcessingState(ElementLayoutController.NOT_STARTED);
161: derived.setFlowController(cfc);
162: derived.resetSectionForRepeat();
163: return derived;
164: }
165: }
166:
167: // Go back to the beginning ...
168: final SectionLayoutController derived = (SectionLayoutController) clone();
169: derived.setProcessingState(ElementLayoutController.FINISHED);
170: derived.setFlowController(fc);
171: return derived;
172: }
173:
174: protected void resetSectionForRepeat() {
175: setIndex(0);
176: }
177:
178: protected FlowController finishData(final ReportTarget target,
179: final FlowController fc) throws DataSourceException,
180: ReportProcessingException {
181: final Section s = (Section) getElement();
182: return LayoutControllerUtil.processFlowOperations(fc, s
183: .getOperationAfter());
184: }
185:
186: /**
187: * Joins with a delegated process flow. This is generally called from a child
188: * flow and should *not* (I mean it!) be called from outside. If you do,
189: * you'll suffer.
190: *
191: * @param flowController the flow controller of the parent.
192: * @return the joined layout controller that incorperates all changes from the
193: * delegate.
194: */
195: public LayoutController join(final FlowController flowController) {
196: final Node[] nodes = getNodes();
197: int index = getIndex() + 1;
198: for (; index < nodes.length; index++) {
199: final Node node = nodes[index];
200: if (node.isEnabled()) {
201: break;
202: }
203: }
204:
205: if (index < nodes.length) {
206: final SectionLayoutController derived = (SectionLayoutController) clone();
207: derived.setProcessingState(ElementLayoutController.OPENED);
208: derived.setFlowController(flowController);
209: derived.setIndex(index);
210: return derived;
211: }
212:
213: final SectionLayoutController derived = (SectionLayoutController) clone();
214: derived.setProcessingState(ElementLayoutController.FINISHING);
215: derived.setFlowController(flowController);
216: return derived;
217: }
218:
219: public Node[] getNodes() {
220: if (nodes == null) {
221: final Section s = (Section) getElement();
222: nodes = s.getNodeArray();
223: }
224: return nodes;
225: }
226:
227: public int getIndex() {
228: return index;
229: }
230:
231: public void setIndex(final int index) {
232: this.index = index;
233: }
234: }
|