1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 package com.sun.star.report.pentaho.layoutprocessor;
24 
25 import com.sun.star.report.pentaho.model.OfficeGroup;
26 import com.sun.star.report.pentaho.model.OfficeGroupSection;
27 
28 import org.jfree.layouting.util.AttributeMap;
29 import org.jfree.report.DataSourceException;
30 import org.jfree.report.JFreeReportInfo;
31 import org.jfree.report.ReportDataFactoryException;
32 import org.jfree.report.ReportProcessingException;
33 import org.jfree.report.flow.FlowController;
34 import org.jfree.report.flow.ReportTarget;
35 import org.jfree.report.flow.layoutprocessor.ElementLayoutController;
36 import org.jfree.report.flow.layoutprocessor.LayoutController;
37 import org.jfree.report.flow.layoutprocessor.SectionLayoutController;
38 import org.jfree.report.structure.Element;
39 
40 /**
41  * Todo: Document me!
42  *
43  * @author Thomas Morgner
44  * @since 15.03.2007
45  */
46 public class OfficeGroupLayoutController extends SectionLayoutController
47         implements OfficeRepeatingStructureLayoutController
48 {
49 
50     public static final int STATE_PROCESS_REPEATING_HEADER = 0;
51     public static final int STATE_PROCESS_REPEATING_FOOTER = 1;
52     public static final int STATE_PROCESS_NORMAL_FLOW = 3;
53     private boolean waitForJoin;
54     private int state;
55     private VariablesCollection variablesCollection;
56     private boolean repeatHeader;
57     private boolean repeatFooter;
58 
OfficeGroupLayoutController()59     public OfficeGroupLayoutController()
60     {
61     }
62 
63     /**
64      * Initializes the layout controller. This method is called exactly once. It
65      * is the creators responsibility to call this method.
66      * <p/>
67      * Calling initialize after the first advance must result in a
68      * IllegalStateException.
69      *
70      * @param node           the currently processed object or layout node.
71      * @param flowController the current flow controller.
72      * @param parent         the parent layout controller that was responsible for
73      *                       instantiating this controller.
74      * @throws org.jfree.report.DataSourceException
75      *          if there was a problem reading data from the datasource.
76      * @throws org.jfree.report.ReportProcessingException
77      *          if there was a general problem during the report processing.
78      * @throws org.jfree.report.ReportDataFactoryException
79      *          if a query failed.
80      */
initialize(final Object node, final FlowController flowController, final LayoutController parent)81     public void initialize(final Object node,
82             final FlowController flowController,
83             final LayoutController parent)
84             throws DataSourceException, ReportDataFactoryException,
85             ReportProcessingException
86     {
87         super.initialize(node, flowController, parent);
88         state = OfficeGroupLayoutController.STATE_PROCESS_REPEATING_HEADER;
89         variablesCollection = new VariablesCollection(computeVariablesPrefix());
90 
91 
92         final OfficeGroup group = (OfficeGroup) getElement();
93         final OfficeGroupSection header = group.getHeader();
94         repeatHeader = (header != null && header.isRepeatSection());
95 
96         final OfficeGroupSection footer = group.getFooter();
97         repeatFooter = (footer != null && footer.isRepeatSection());
98     }
99 
processContent(final ReportTarget target)100     protected LayoutController processContent(final ReportTarget target)
101             throws DataSourceException, ReportProcessingException,
102             ReportDataFactoryException
103     {
104         if (state == OfficeGroupLayoutController.STATE_PROCESS_REPEATING_HEADER)
105         {
106 
107             final OfficeGroupLayoutController controller =
108                     (OfficeGroupLayoutController) clone();
109             controller.state =
110                     OfficeGroupLayoutController.STATE_PROCESS_REPEATING_FOOTER;
111 
112             if (!repeatHeader)
113             {
114                 return controller;
115             }
116 
117             final OfficeGroup group = (OfficeGroup) getElement();
118             final OfficeGroupSection header = group.getHeader();
119             controller.waitForJoin = true;
120             return processChild(controller, header, getFlowController());
121         }
122 
123         if (state == OfficeGroupLayoutController.STATE_PROCESS_REPEATING_FOOTER)
124         {
125 
126             final OfficeGroupLayoutController controller =
127                     (OfficeGroupLayoutController) clone();
128             controller.state = OfficeGroupLayoutController.STATE_PROCESS_NORMAL_FLOW;
129 
130             if (!repeatFooter)
131             {
132                 return controller;
133             }
134 
135             final OfficeGroup group = (OfficeGroup) getElement();
136             final OfficeGroupSection footer = group.getFooter();
137             controller.waitForJoin = true;
138             return processChild(controller, footer, getFlowController());
139         }
140 
141         return super.processContent(target);
142     }
143 
144     /**
145      * Joins with a delegated process flow. This is generally called from a child
146      * flow and should *not* (I mean it!) be called from outside. If you do,
147      * you'll suffer.
148      *
149      * @param flowController the flow controller of the parent.
150      * @return the joined layout controller that incorperates all changes from the
151      *         delegate.
152      */
join(final FlowController flowController)153     public LayoutController join(final FlowController flowController)
154     {
155         if (waitForJoin)
156         {
157             final OfficeGroupLayoutController derived = (OfficeGroupLayoutController) clone();
158             derived.setProcessingState(ElementLayoutController.OPENED);
159             derived.setFlowController(flowController);
160             derived.waitForJoin = false;
161             return derived;
162         }
163         return super.join(flowController);
164     }
165 
isNormalFlowProcessing()166     public boolean isNormalFlowProcessing()
167     {
168         return state == OfficeGroupLayoutController.STATE_PROCESS_NORMAL_FLOW;
169     }
170 
computeVariablesPrefix()171     private String computeVariablesPrefix()
172     {
173         int count = 0;
174         LayoutController lc = this;
175         while (lc != null)
176         {
177             if (lc instanceof OfficeGroupLayoutController)
178             {
179                 count++;
180             }
181             lc = lc.getParent();
182         }
183         return "auto_group_" + count + "_";
184     }
185 
getVariablesCollection()186     public VariablesCollection getVariablesCollection()
187     {
188         return variablesCollection;
189     }
190 
computeAttributes(final FlowController fc, final Element element, final ReportTarget target)191     protected AttributeMap computeAttributes(final FlowController fc, final Element element, final ReportTarget target)
192             throws DataSourceException
193     {
194         final AttributeMap map = new AttributeMap(super.computeAttributes(fc, element, target));
195         final String value = String.valueOf(repeatHeader || repeatFooter);
196         map.setAttribute(JFreeReportInfo.REPORT_NAMESPACE, "repeating-header-or-footer", value);
197         map.makeReadOnly();
198         return map;
199     }
200 }
201