Source for org.jfree.report.flow.layoutprocessor.SectionLayoutController

   1: /**
   2:  * ========================================
   3:  * JFreeReport : a free Java report library
   4:  * ========================================
   5:  *
   6:  * Project Info:  http://reporting.pentaho.org/
   7:  *
   8:  * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
   9:  *
  10:  * This library is free software; you can redistribute it and/or modify it under the terms
  11:  * of the GNU Lesser General Public License as published by the Free Software Foundation;
  12:  * either version 2.1 of the License, or (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  15:  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16:  * See the GNU Lesser General Public License for more details.
  17:  *
  18:  * You should have received a copy of the GNU Lesser General Public License along with this
  19:  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20:  * Boston, MA 02111-1307, USA.
  21:  *
  22:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  23:  * in the United States and other countries.]
  24:  *
  25:  * ------------
  26:  * $Id: SectionLayoutController.java 3057 2007-07-30 14:27:28Z tmorgner $
  27:  * ------------
  28:  * (C) Copyright 2000-2005, by Object Refinery Limited.
  29:  * (C) Copyright 2005-2007, by Pentaho Corporation.
  30:  */
  31: 
  32: package org.jfree.report.flow.layoutprocessor;
  33: 
  34: import org.jfree.report.DataSourceException;
  35: import org.jfree.report.ReportDataFactoryException;
  36: import org.jfree.report.ReportProcessingException;
  37: import org.jfree.report.expressions.Expression;
  38: import org.jfree.report.flow.FlowController;
  39: import org.jfree.report.flow.ReportContext;
  40: import org.jfree.report.flow.ReportTarget;
  41: import org.jfree.report.structure.Node;
  42: import org.jfree.report.structure.Section;
  43: 
  44: /**
  45:  * Creation-Date: 24.11.2006, 13:56:10
  46:  *
  47:  * @author Thomas Morgner
  48:  */
  49: public class SectionLayoutController extends ElementLayoutController
  50: {
  51:   // we store the child instead of the index, as the report can be manipulated
  52:   // it is safer this way ..
  53:   private Node[] nodes;
  54:   private int index;
  55: 
  56:   public SectionLayoutController()
  57:   {
  58:   }
  59: 
  60:   protected FlowController startData(final ReportTarget target,
  61:                                      final FlowController fc)
  62:       throws DataSourceException, ReportProcessingException,
  63:       ReportDataFactoryException
  64:   {
  65:     final Section s = (Section) getElement();
  66:     return LayoutControllerUtil.processFlowOperations
  67:         (fc, s.getOperationBefore());
  68:   }
  69: 
  70:   protected LayoutController processContent(final ReportTarget target)
  71:       throws DataSourceException, ReportProcessingException,
  72:       ReportDataFactoryException
  73:   {
  74: 
  75:     final FlowController flowController = getFlowController();
  76: 
  77:     final Node[] nodes = getNodes();
  78:     final int currentIndex = getIndex();
  79:     if (currentIndex < nodes.length)
  80:     {
  81:       final Node node = nodes[currentIndex];
  82:       final SectionLayoutController derived = (SectionLayoutController) clone();
  83:       return processChild(derived, node, flowController);
  84:     }
  85:     else
  86:     {
  87:       final SectionLayoutController derived = (SectionLayoutController) clone();
  88:       derived.setProcessingState(ElementLayoutController.FINISHING);
  89:       return derived;
  90:     }
  91:   }
  92: 
  93:   protected LayoutController processChild(final SectionLayoutController derived,
  94:                                           final Node node,
  95:                                           final FlowController flowController)
  96:       throws DataSourceException, ReportProcessingException,
  97:       ReportDataFactoryException
  98:   {
  99:     final ReportContext reportContext = flowController.getReportContext();
 100:     final LayoutControllerFactory layoutControllerFactory = reportContext.getLayoutControllerFactory();
 101:     if (isDisplayable(node))
 102:     {
 103:       derived.setProcessingState(ElementLayoutController.WAITING_FOR_JOIN);
 104:       return layoutControllerFactory.create(flowController, node, derived);
 105:     }
 106:     else
 107:     {
 108:       derived.setProcessingState(ElementLayoutController.WAITING_FOR_JOIN);
 109:       final LayoutController childLc = layoutControllerFactory.create(flowController, node, derived);
 110:       return LayoutControllerUtil.skipInvisibleElement(childLc);
 111: //      derived.setIndex(derived.getIndex() + 1);
 112: //      return LayoutControllerUtil.skipInvisibleElement(derived);
 113:     }
 114:   }
 115: 
 116:   protected boolean isDisplayable(final Node node)
 117:       throws DataSourceException
 118:   {
 119:     if (node.isEnabled() == false)
 120:     {
 121:       return false;
 122:     }
 123: 
 124:     final Expression expression = node.getDisplayCondition();
 125:     if (expression == null)
 126:     {
 127:       return true;
 128:     }
 129: 
 130:     final Object result = LayoutControllerUtil.evaluateExpression(getFlowController(), node, expression);
 131:     if (Boolean.TRUE.equals(result))
 132:     {
 133:       return true;
 134:     }
 135:     return false;
 136:   }
 137: 
 138:   /**
 139:    * Finishes the processing of this element. This method is called when the
 140:    * processing state is 'FINISHING'. The element should be closed now and all
 141:    * privatly owned resources should be freed. If the element has a parent, it
 142:    * would be time to join up with the parent now, else the processing state
 143:    * should be set to 'FINISHED'.
 144:    *
 145:    * @param target the report target that receives generated events.
 146:    * @return the new layout controller instance representing the new state.
 147:    *
 148:    * @throws DataSourceException        if there was a problem reading data from
 149:    *                                    the datasource.
 150:    * @throws ReportProcessingException  if there was a general problem during
 151:    *                                    the report processing.
 152:    * @throws ReportDataFactoryException if there was an error trying query
 153:    *                                    data.
 154:    */
 155:   protected LayoutController finishElement(final ReportTarget target)
 156:       throws ReportProcessingException, DataSourceException,
 157:       ReportDataFactoryException
 158:   {
 159:     FlowController fc = handleDefaultEndElement(target);
 160: 
 161:     // unwind the stack ..
 162:     final Section s = (Section) getElement();
 163:     fc = finishData(target, fc);
 164: 
 165:     if (s.isRepeat())
 166:     {
 167:       final FlowController cfc = tryRepeatingCommit(fc);
 168:       if (cfc != null)
 169:       {
 170:         // Go back to the beginning ...
 171:         final SectionLayoutController derived = (SectionLayoutController) clone();
 172:         derived.setProcessingState(ElementLayoutController.NOT_STARTED);
 173:         derived.setFlowController(cfc);
 174:         derived.resetSectionForRepeat();
 175:         return derived;
 176:       }
 177:     }
 178: 
 179:     // Go back to the beginning ...
 180:     final SectionLayoutController derived = (SectionLayoutController) clone();
 181:     derived.setProcessingState(ElementLayoutController.FINISHED);
 182:     derived.setFlowController(fc);
 183:     return derived;
 184:   }
 185: 
 186:   protected void resetSectionForRepeat()
 187:   {
 188:     setIndex(0);
 189:   }
 190: 
 191:   protected FlowController finishData(final ReportTarget target,
 192:                                       final FlowController fc)
 193:       throws DataSourceException, ReportProcessingException
 194:   {
 195:     final Section s = (Section) getElement();
 196:     return LayoutControllerUtil.processFlowOperations
 197:         (fc, s.getOperationAfter());
 198:   }
 199: 
 200:   /**
 201:    * Joins with a delegated process flow. This is generally called from a child
 202:    * flow and should *not* (I mean it!) be called from outside. If you do,
 203:    * you'll suffer.
 204:    *
 205:    * @param flowController the flow controller of the parent.
 206:    * @return the joined layout controller that incorperates all changes from the
 207:    *         delegate.
 208:    */
 209:   public LayoutController join(final FlowController flowController)
 210:   {
 211:     final Node[] nodes = getNodes();
 212:     int index = getIndex() + 1;
 213:     for (; index < nodes.length; index++)
 214:     {
 215:       final Node node = nodes[index];
 216:       if (node.isEnabled())
 217:       {
 218:         break;
 219:       }
 220:     }
 221: 
 222:     if (index < nodes.length)
 223:     {
 224:       final SectionLayoutController derived = (SectionLayoutController) clone();
 225:       derived.setProcessingState(ElementLayoutController.OPENED);
 226:       derived.setFlowController(flowController);
 227:       derived.setIndex(index);
 228:       return derived;
 229:     }
 230: 
 231:     final SectionLayoutController derived = (SectionLayoutController) clone();
 232:     derived.setProcessingState(ElementLayoutController.FINISHING);
 233:     derived.setFlowController(flowController);
 234:     return derived;
 235:   }
 236: 
 237:   public Node[] getNodes()
 238:   {
 239:     if (nodes == null)
 240:     {
 241:       final Section s = (Section) getElement();
 242:       nodes = s.getNodeArray();
 243:     }
 244:     return nodes;
 245:   }
 246: 
 247:   public int getIndex()
 248:   {
 249:     return index;
 250:   }
 251: 
 252:   public void setIndex(final int index)
 253:   {
 254:     this.index = index;
 255:   }
 256: }