1
24 package net.sf.jasperreports.engine.fill;
25
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37 import net.sf.jasperreports.engine.CommonReturnValue;
38 import net.sf.jasperreports.engine.ExpressionReturnValue;
39 import net.sf.jasperreports.engine.JRBand;
40 import net.sf.jasperreports.engine.JRElement;
41 import net.sf.jasperreports.engine.JRException;
42 import net.sf.jasperreports.engine.JRExpression;
43 import net.sf.jasperreports.engine.JRGroup;
44 import net.sf.jasperreports.engine.JROrigin;
45 import net.sf.jasperreports.engine.JRPropertiesHolder;
46 import net.sf.jasperreports.engine.JRPropertiesMap;
47 import net.sf.jasperreports.engine.JRRuntimeException;
48 import net.sf.jasperreports.engine.type.BandTypeEnum;
49 import net.sf.jasperreports.engine.type.PrintOrderEnum;
50 import net.sf.jasperreports.engine.type.SplitTypeEnum;
51
52
53
56 public class JRFillBand extends JRFillElementContainer implements JRBand, JROriginProvider
57 {
58
59 private static final Log log = LogFactory.getLog(JRFillBand.class);
60
61
64 private JRBand parent;
65
66 private boolean isPrintWhenTrue = true;
67
68
71 private boolean isNewPageColumn;
72 private boolean isFirstWholeOnPageColumn;
73 private Map<JRGroup,Boolean> isNewGroupMap = new HashMap<JRGroup,Boolean>();
74
75 private Set<JREvaluationTime> nowEvaluationTimes;
76
77
78
79 private Map<String,Object> savedVariableValues = new HashMap<String,Object>();
80
81 protected JROrigin origin;
82
83 private SplitTypeEnum splitType;
84 private Integer breakHeight;
85
86 private FillReturnValues returnValues;
87 private FillReturnValues.SourceContext returnValuesContext = new FillReturnValues.SourceContext()
88 {
89 @Override
90 public Object getValue(CommonReturnValue returnValue)
91 {
92 ExpressionReturnValue expressionReturnValue = (ExpressionReturnValue)returnValue;
93 Object value = null;
94 try
95 {
96 value = filler.evaluateExpression(expressionReturnValue.getExpression(), JRExpression.EVALUATION_DEFAULT);
97 }
98 catch (JRException e)
99 {
100 throw new JRRuntimeException(e);
101 }
102 return value;
103 }
104
105 @Override
106 public void check(CommonReturnValue returnValue) throws JRException
107 {
108
109 }
110
111 @Override
112 public JRFillVariable getToVariable(String name)
113 {
114 return filler.getVariable(name);
115 }
116 };
117
118 private Set<FillReturnValues> returnValuesSet;
119
120
123 protected JRFillBand(
124 JRBaseFiller filler,
125 JRBand band,
126 JRFillObjectFactory factory
127 )
128 {
129 super(filler, band, factory);
130
131 parent = band;
132
133
134 returnValuesSet = new LinkedHashSet<FillReturnValues>();
135
136 if (deepElements.length > 0)
137 {
138 for(int i = 0; i < deepElements.length; i++)
139 {
140 deepElements[i].setBand(this);
141 }
142 }
143
144 List<ExpressionReturnValue> expRetValues = getReturnValues();
145 returnValues =
146 new FillReturnValues(
147 expRetValues == null ? null : (ExpressionReturnValue[]) expRetValues.toArray(new ExpressionReturnValue[expRetValues.size()]),
148 factory,
149 filler
150 );
151 registerReturnValues(returnValues);
152
153 initElements();
154
155 initConditionalStyles();
156
157 nowEvaluationTimes = new HashSet<JREvaluationTime>();
158 }
159
160
161 @Override
162 public JROrigin getOrigin()
163 {
164 return origin;
165 }
166
167
168
171 protected void setOrigin(JROrigin origin)
172 {
173 if (log.isDebugEnabled())
174 {
175 log.debug("Origin " + origin + " for band " + getId());
176 }
177
178 this.origin = origin;
179 this.filler.getJasperPrint().addOrigin(origin);
180 }
181
182
183
186 protected void setNewPageColumn(boolean isNew)
187 {
188 this.isNewPageColumn = isNew;
189 }
190
191
192
195 protected boolean isNewPageColumn()
196 {
197 return isNewPageColumn;
198 }
199
200
201
206 protected boolean isFirstWholeOnPageColumn()
207 {
208 return isFirstWholeOnPageColumn;
209 }
210
211
212
215 protected void setNewGroup(JRGroup group, boolean isNew)
216 {
217 isNewGroupMap.put(group, isNew);
218 }
219
220
221
224 protected boolean isNewGroup(JRGroup group)
225 {
226 Boolean value = isNewGroupMap.get(group);
227
228 if (value == null)
229 {
230 value = Boolean.FALSE;
231 }
232
233 return value;
234 }
235
236
237 @Override
238 public int getHeight()
239 {
240 return (parent == null ? 0 : parent.getHeight());
241 }
242
243
246 public int getBreakHeight()
247 {
248
249 if (breakHeight == null)
250 {
251 breakHeight = getHeight();
252 if (
253 SplitTypeEnum.IMMEDIATE == getSplitTypeValue()
254 && elements != null && elements.length > 0
255 )
256 {
257 for(int i = 0; i < elements.length; i++)
258 {
259 JRElement element = elements[i];
260 int bottom = element.getY() + element.getHeight();
261 breakHeight = bottom < breakHeight ? bottom : breakHeight;
262 }
263 }
264 }
265
266 return breakHeight;
267 }
268
269 @Override
270 public SplitTypeEnum getSplitTypeValue()
271 {
272
273
274 if (splitType == null)
275 {
276 splitType = (parent == null ? null : parent.getSplitTypeValue());
277 if (splitType == null)
278 {
279 splitType =
280 SplitTypeEnum.getByName(
281 filler.getPropertiesUtil().getProperty(filler.getMainDataset(), JRBand.PROPERTY_SPLIT_TYPE)
282 );
283 }
284 }
285
286 return splitType;
287 }
288
289 @Override
290 public void setSplitType(SplitTypeEnum splitType)
291 {
292 throw new UnsupportedOperationException();
293 }
294
295 @Override
296 public JRExpression getPrintWhenExpression()
297 {
298 return (parent == null ? null : parent.getPrintWhenExpression());
299 }
300
301
304 protected boolean isSplitPrevented()
305 {
306 return SplitTypeEnum.PREVENT == getSplitTypeValue();
307 }
308
309
312 protected boolean isPrintWhenExpressionNull()
313 {
314 return (getPrintWhenExpression() == null);
315 }
316
317
320 protected boolean isPrintWhenTrue()
321 {
322 return isPrintWhenTrue;
323 }
324
325
328 protected void setPrintWhenTrue(boolean isPrintWhenTrue)
329 {
330 this.isPrintWhenTrue = isPrintWhenTrue;
331 }
332
333
336 protected boolean isToPrint()
337 {
338 return
339 this != filler.missingFillBand
340 && (isPrintWhenExpressionNull()
341 || (!isPrintWhenExpressionNull() && isPrintWhenTrue()));
342 }
343
344
345
348 protected void evaluatePrintWhenExpression(
349 byte evaluation
350 ) throws JRException
351 {
352 boolean isPrintTrue = false;
353
354 JRExpression expression = getPrintWhenExpression();
355 if (expression != null)
356 {
357 Boolean printWhenExpressionValue = (Boolean)filler.evaluateExpression(expression, evaluation);
358 if (printWhenExpressionValue == null)
359 {
360 isPrintTrue = false;
361 }
362 else
363 {
364 isPrintTrue = printWhenExpressionValue;
365 }
366 }
367
368 setPrintWhenTrue(isPrintTrue);
369 }
370
371
372
373
376 protected JRPrintBand refill(
377 byte evaluation,
378 int availableHeight
379 ) throws JRException
380 {
381 rewind();
382 restoreSavedVariables();
383
384 JRPrintBand printBand = null;
385
386 @SuppressWarnings("deprecation")
387 boolean isLegacyBandEvaluationEnabled = filler.getFillContext().isLegacyBandEvaluationEnabled();
388 if (isLegacyBandEvaluationEnabled)
389 {
390 printBand = fill(availableHeight);
391 }
392 else
393 {
394 evaluatePrintWhenExpression(evaluation);
395
396 if (isToPrint())
397 {
398 evaluate(evaluation);
399
400 printBand = fill(availableHeight);
401 }
402 else
403 {
404 printBand = new JRPrintBand();
405 }
406 }
407
408 return printBand;
409 }
410
411
412
415 protected JRPrintBand fill() throws JRException
416 {
417 return fill(getHeight(), false);
418 }
419
420
421
424 protected JRPrintBand fill(
425 int availableHeight
426 ) throws JRException
427 {
428 return fill(availableHeight, true);
429 }
430
431
432
435 protected JRPrintBand fill(
436 int availableHeight,
437 boolean isOverflowAllowed
438 ) throws JRException
439 {
440 filler.checkInterrupted();
441
442 filler.setBandOverFlowAllowed(isOverflowAllowed);
443
444 initFill();
445
446 if (isNewPageColumn && !isOverflow)
447 {
448 isFirstWholeOnPageColumn = true;
449 }
450
451 resetElements();
452
453 prepareElements(availableHeight, isOverflowAllowed);
454
455 if (isLegacyElementStretchEnabled())
456 {
457 stretchElements();
458
459 moveBandBottomElements();
460
461 removeBlankElements();
462 }
463
464 isFirstWholeOnPageColumn = isNewPageColumn && isOverflow;
465 isNewPageColumn = false;
466 isNewGroupMap = new HashMap<JRGroup,Boolean>();
467
468 JRPrintBand printBand = new JRPrintBand();
469 fillElements(printBand);
470
471 if (!willOverflow())
472 {
473 returnValues.copyValues(returnValuesContext);
474 }
475
476 return printBand;
477 }
478
479
480 protected boolean willOverflowWithElements()
481 {
482 return willOverflowWithElements;
483 }
484
485
486 @Override
487 protected int getContainerHeight()
488 {
489 return getHeight();
490 }
491
492
493 @Override
494 protected int getActualContainerHeight()
495 {
496 return getContainerHeight();
497 }
498
499
500 protected boolean isVariableUsedInReturns(String variableName)
501 {
502 boolean used = false;
503 for (FillReturnValues returnValues : returnValuesSet)
504 {
505 if (returnValues.usesForReturnValue(variableName))
506 {
507 used = true;
508 break;
509 }
510 }
511 return used;
512 }
513
514
515 protected void addNowEvaluationTime(JREvaluationTime evaluationTime)
516 {
517 nowEvaluationTimes.add(evaluationTime);
518 }
519
520
521 protected void addNowEvaluationTimes(JREvaluationTime[] evaluationTimes)
522 {
523 for (int i = 0; i < evaluationTimes.length; i++)
524 {
525 nowEvaluationTimes.add(evaluationTimes[i]);
526 }
527 }
528
529
530 protected boolean isNowEvaluationTime(JREvaluationTime evaluationTime)
531 {
532 return nowEvaluationTimes.contains(evaluationTime);
533 }
534
535
536 protected int getId()
537 {
538
539 return System.identityHashCode(this);
540 }
541
542
543 @Override
544 protected void evaluate(byte evaluation) throws JRException
545 {
546 resetSavedVariables();
547 evaluateConditionalStyles(evaluation);
548 super.evaluate(evaluation);
549 }
550
551 protected void resetSavedVariables()
552 {
553 savedVariableValues.clear();
554 }
555
556 protected void saveVariable(String variableName)
557 {
558 if (!savedVariableValues.containsKey(variableName))
559 {
560 Object value = filler.getVariableValue(variableName);
561 savedVariableValues.put(variableName, value);
562 }
563 }
564
565 protected void restoreSavedVariables()
566 {
567 for (Iterator<Map.Entry<String,Object>> it = savedVariableValues.entrySet().iterator(); it.hasNext();)
568 {
569 Map.Entry<String,Object> entry = it.next();
570 String variableName = entry.getKey();
571 Object value = entry.getValue();
572 JRFillVariable variable = filler.getVariable(variableName);
573 variable.setOldValue(value);
574 variable.setValue(value);
575 variable.setIncrementedValue(value);
576 }
577 }
578
579
580 protected boolean isEmpty()
581 {
582 return this == filler.missingFillBand
583 || (getHeight() == 0
584 && (getElements() == null || getElements().length == 0)
585 && getPrintWhenExpression() == null);
586 }
587
588 protected boolean isColumnBand()
589 {
590 BandTypeEnum bandType = origin.getBandTypeValue();
591
592 return
593 bandType == BandTypeEnum.GROUP_HEADER
594 || bandType == BandTypeEnum.GROUP_FOOTER
595 || bandType == BandTypeEnum.DETAIL;
596 }
597
598 protected boolean isPageBreakInhibited()
599 {
600 boolean isPageBreakInhibited = filler.isFirstPageBand && !atLeastOneElementIsToPrint;
601
602 if (isPageBreakInhibited && filler.isSubreport())
603 {
604 isPageBreakInhibited = filler.getBandReportParent().isPageBreakInhibited();
605 }
606
607 return isPageBreakInhibited;
608 }
609
610 protected boolean isSplitTypePreventInhibited()
611 {
612 return isSplitTypePreventInhibited(true);
613 }
614
615 @Override
616 public boolean isSplitTypePreventInhibited(boolean isTopLevelCall)
617 {
618 boolean isSplitTypePreventInhibited = false;
619
620 if (
621 ((filler.printOrder == PrintOrderEnum.VERTICAL && filler.isFirstColumnBand)
622 || (filler.printOrder == PrintOrderEnum.HORIZONTAL && filler.isFirstPageBand))
623 && (isTopLevelCall || !atLeastOneElementIsToPrint)
624 )
625 {
626 if (isColumnBand() && filler.columnIndex < filler.columnCount - 1)
627 {
628 isSplitTypePreventInhibited = true;
629 }
630 else
631 {
632 if (filler.isSubreport())
633 {
634 isSplitTypePreventInhibited = filler.getBandReportParent().isSplitTypePreventInhibited(false);
635 }
636 else
637 {
638 isSplitTypePreventInhibited = true;
639 }
640 }
641 }
642
643 return isSplitTypePreventInhibited;
644 }
645
646 @Override
647 public boolean hasProperties()
648 {
649 return parent.hasProperties();
650 }
651
652
653 @Override
654 public JRPropertiesMap getPropertiesMap()
655 {
656 return parent.getPropertiesMap();
657 }
658
659 @Override
660 public JRPropertiesHolder getParentProperties()
661 {
662 return null;
663 }
664
665 @Override
666 public List<ExpressionReturnValue> getReturnValues()
667 {
668 return parent == null ? null : parent.getReturnValues();
669 }
670
671 public void registerReturnValues(FillReturnValues fillReturnValues)
672 {
673 returnValuesSet.add(fillReturnValues);
674 }
675
676 }
677