1 /*
2  * JasperReports - Free Java Reporting Library.
3  * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
4  * http://www.jaspersoft.com
5  *
6  * Unless you have purchased a commercial license agreement from Jaspersoft,
7  * the following license terms apply:
8  *
9  * This program is part of JasperReports.
10  *
11  * JasperReports is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * JasperReports is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with JasperReports. If not, see <http://www.gnu.org/licenses/>.
23  */

24 package net.sf.jasperreports.engine.fill;
25
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.ResourceBundle;
29 import java.util.TimeZone;
30
31 import net.sf.jasperreports.engine.JRComponentElement;
32 import net.sf.jasperreports.engine.JRException;
33 import net.sf.jasperreports.engine.JRExpression;
34 import net.sf.jasperreports.engine.JRExpressionCollector;
35 import net.sf.jasperreports.engine.JROrigin;
36 import net.sf.jasperreports.engine.JRPrintElement;
37 import net.sf.jasperreports.engine.JRStyle;
38 import net.sf.jasperreports.engine.JRVisitable;
39 import net.sf.jasperreports.engine.JRVisitor;
40 import net.sf.jasperreports.engine.component.Component;
41 import net.sf.jasperreports.engine.component.ComponentKey;
42 import net.sf.jasperreports.engine.component.ComponentManager;
43 import net.sf.jasperreports.engine.component.ComponentsEnvironment;
44 import net.sf.jasperreports.engine.component.ConditionalStyleAwareFillComponent;
45 import net.sf.jasperreports.engine.component.FillComponent;
46 import net.sf.jasperreports.engine.component.FillContext;
47 import net.sf.jasperreports.engine.component.FillPrepareResult;
48 import net.sf.jasperreports.engine.component.StretchableFillComponent;
49 import net.sf.jasperreports.engine.type.EvaluationTimeEnum;
50
51 /**
52  * A {@link JRComponentElement} which is used during report fill.
53  * 
54  * @author Lucian Chirita (lucianc@users.sourceforge.net)
55  */

56 public class JRFillComponentElement extends JRFillElement implements JRComponentElement, FillContext
57 {
58
59     private FillComponent fillComponent;
60     private boolean filling;
61     private List<JRFillDatasetRun> componentDatasetRuns;
62     
63     public JRFillComponentElement(JRBaseFiller filler, JRComponentElement element,
64             JRFillObjectFactory factory)
65     {
66         super(filler, element, factory);
67         
68         ComponentKey componentKey = element.getComponentKey();
69         ComponentManager manager = ComponentsEnvironment.getInstance(filler.getJasperReportsContext()).getManager(componentKey);
70         
71         factory.trackDatasetRuns();
72         fillComponent = manager.getComponentFillFactory(filler.getJasperReportsContext()).toFillComponent(element.getComponent(), factory);
73         fillComponent.initialize(this);
74         this.componentDatasetRuns = factory.getTrackedDatasetRuns();
75     }
76
77     public JRFillComponentElement(JRFillComponentElement element,
78             JRFillCloneFactory factory)
79     {
80         super(element, factory);
81         
82         ComponentKey componentKey = element.getComponentKey();
83         ComponentManager manager = ComponentsEnvironment.getInstance(filler.getJasperReportsContext()).getManager(componentKey);
84         fillComponent = manager.getComponentFillFactory(filler.getJasperReportsContext()).cloneFillComponent(element.fillComponent, factory);
85         fillComponent.initialize(this);
86     }
87
88     @Override
89     protected void setBand(JRFillBand band)
90     {
91         super.setBand(band);
92         
93         if (componentDatasetRuns != null && !componentDatasetRuns.isEmpty())
94         {
95             for (JRFillDatasetRun datasetRun : componentDatasetRuns)
96             {
97                 datasetRun.setBand(band);
98             }
99         }
100     }
101
102     @Override
103     protected void evaluate(byte evaluation) throws JRException
104     {
105         reset();
106         evaluatePrintWhenExpression(evaluation);
107
108         if (isPrintWhenExpressionNull() || isPrintWhenTrue())
109         {
110             fillComponent.evaluate(evaluation);
111         }
112         
113         filling = false;
114     }
115     
116     @Override
117     protected boolean prepare(int availableHeight, boolean isOverflow)
118             throws JRException
119     {
120         boolean willOverflow = false;
121
122         super.prepare(availableHeight, isOverflow);
123         
124         if (!isToPrint())
125         {
126             return willOverflow;
127         }
128         
129         boolean isToPrint = true;
130         boolean isReprinted = false;
131
132         if (!filling 
133                 && isOverflow && isAlreadyPrinted() && !isPrintWhenDetailOverflows())
134         {
135             isToPrint = false;
136         }
137
138         if (isToPrint && availableHeight <  getRelativeY() + getHeight())
139         {
140             isToPrint = false;
141             willOverflow = true;
142         }
143
144         if (!filling && isToPrint && isOverflow && isPrintWhenDetailOverflows()
145                 && (isAlreadyPrinted() || !isPrintRepeatedValues()))
146         {
147             isReprinted = true;
148         }
149
150         if (isToPrint)
151         {
152             FillPrepareResult result = fillComponent.prepare(availableHeight - getRelativeY());
153             
154             isToPrint = result.isToPrint();
155             willOverflow = result.willOverflow();
156             setPrepareHeight(result.getStretchHeight());
157             
158             // if the component will overflow, set the filling flag to true
159             // to know next time that the component is continuing
160             filling = willOverflow;
161         }
162         
163         setToPrint(isToPrint);
164         setReprinted(isReprinted);
165         
166         return willOverflow;
167     }
168
169     @Override
170     protected void setStretchHeight(int stretchHeight)
171     {
172         super.setStretchHeight(stretchHeight);
173         
174         StretchableFillComponent stretchableFillComponent = 
175             fillComponent instanceof StretchableFillComponent ? (StretchableFillComponent)fillComponent : null;
176         if (stretchableFillComponent != null)
177         {
178             stretchableFillComponent.setStretchHeight(stretchHeight);
179         }
180     }
181
182     @Override
183     public void setConditionalStylesContainer(JRFillElementContainer conditionalStylesContainer)
184     {
185         super.setConditionalStylesContainer(conditionalStylesContainer);
186         
187         ConditionalStyleAwareFillComponent conditionalStyleAwareFillComponent = 
188             fillComponent instanceof ConditionalStyleAwareFillComponent ? (ConditionalStyleAwareFillComponent)fillComponent : null;
189         if (conditionalStyleAwareFillComponent != null)
190         {
191             conditionalStyleAwareFillComponent.setConditionalStylesContainer(conditionalStylesContainer);
192         }
193     }
194
195     @Override
196     protected JRPrintElement fill() throws JRException
197     {
198         return fillComponent.fill();
199     }
200
201     @Override
202     protected JRTemplateElement createElementTemplate()
203     {
204         // not called
205         return null;
206     }
207
208     @Override
209     protected void resolveElement (JRPrintElement element, byte evaluation, 
210             JREvaluationTime evaluationTime) throws JRException
211     {
212         performDelayedEvaluation(element, evaluation);
213     }
214     
215     @Override
216     protected void resolveElement(JRPrintElement element, byte evaluation)
217             throws JRException
218     {
219         fillComponent.evaluateDelayedElement(element, evaluation);
220     }
221
222     @Override
223     protected void rewind() throws JRException
224     {
225         fillComponent.rewind();
226         filling = false;
227     }
228
229     @Override
230     public void collectExpressions(JRExpressionCollector collector)
231     {
232         collector.collect(this);
233     }
234
235     @Override
236     public void visit(JRVisitor visitor)
237     {
238         visitor.visitComponentElement(this);
239
240         // visiting the fill component, not the parent component
241         if (fillComponent instanceof JRVisitable)
242         {
243             ((JRVisitable) fillComponent).visit(visitor);
244         }
245     }
246
247     @Override
248     public JRFillCloneable createClone(JRFillCloneFactory factory)
249     {
250         return new JRFillComponentElement(this, factory);
251     }
252
253     @Override
254     public JRComponentElement getParent()
255     {
256         return (JRComponentElement) parent;
257     }
258
259     @Override
260     public Component getComponent()
261     {
262         return ((JRComponentElement) parent).getComponent();
263     }
264
265     @Override
266     public ComponentKey getComponentKey()
267     {
268         return ((JRComponentElement) parent).getComponentKey();
269     }
270     
271     @Override
272     public Object evaluate(JRExpression expression, byte evaluation)
273             throws JRException
274     {
275         return super.evaluateExpression(expression, evaluation);
276     }
277
278     @Override
279     public JRFillDataset getFillDataset()
280     {
281         return expressionEvaluator.getFillDataset();
282     }
283
284     @Override
285     public JRComponentElement getComponentElement()
286     {
287         return this;
288     }
289
290     @Override
291     public int getElementSourceId()
292     {
293         return printElementOriginator.getSourceElementId();
294     }
295     
296     @Override
297     public PrintElementOriginator getPrintElementOriginator()
298     {
299         return printElementOriginator;
300     }
301
302     @Override
303     public JROrigin getElementOrigin()
304     {
305         return super.getElementOrigin();
306     }
307
308     @Override
309     public int getElementPrintY()
310     {
311         return getRelativeY();
312     }
313
314     @Override
315     public JRStyle getElementStyle()
316     {
317         return getStyle();
318     }
319
320     @Override
321     public void registerDelayedEvaluation(JRPrintElement printElement, 
322             EvaluationTimeEnum evaluationTime, String evaluationGroup)
323     {
324         filler.addBoundElement(this, printElement, 
325                 evaluationTime, evaluationGroup, band);
326     }
327
328     @Override
329     public Locale getReportLocale()
330     {
331         return filler.getLocale();
332     }
333
334     @Override
335     public ResourceBundle getReportResourceBundle()
336     {
337         return filler.getResourceBundle();
338     }
339
340     @Override
341     public TimeZone getReportTimezone()
342     {
343         return filler.getTimeZone();
344     }
345
346     @Override
347     public JRBaseFiller getFiller()
348     {
349         return filler;
350     }
351
352     @Override
353     public FillContainerContext getFillContainerContext()
354     {
355         return fillContainerContext;
356     }
357
358 }
359