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 org.apache.commons.javaflow.api.continuable;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 import net.sf.jasperreports.engine.JRException;
31 import net.sf.jasperreports.engine.JRExpression;
32 import net.sf.jasperreports.engine.JRGroup;
33 import net.sf.jasperreports.engine.JRRuntimeException;
34 import net.sf.jasperreports.engine.JasperReport;
35 import net.sf.jasperreports.engine.JasperReportsContext;
36 import net.sf.jasperreports.engine.type.FooterPositionEnum;
37 import net.sf.jasperreports.engine.type.IncrementTypeEnum;
38 import net.sf.jasperreports.engine.type.ResetTypeEnum;
39 import net.sf.jasperreports.engine.type.RunDirectionEnum;
40
41
42 /**
43  * @author Teodor Danciu (teodord@users.sourceforge.net)
44  */

45 public class JRVerticalFiller extends JRBaseFiller
46 {
47     
48     private static final Log log = LogFactory.getLog(JRVerticalFiller.class);
49     
50     protected boolean hasDetailOnPage;
51     
52
53     /**
54      *
55      */

56     protected JRVerticalFiller(
57         JasperReportsContext jasperReportsContext, 
58         JasperReport jasperReport
59         ) throws JRException
60     {
61         this(jasperReportsContext, jasperReport, null);
62     }
63
64     /**
65      *
66      */

67     public JRVerticalFiller(
68         JasperReportsContext jasperReportsContext,
69         JasperReport jasperReport, 
70         BandReportFillerParent parent 
71         ) throws JRException
72     {
73         this(jasperReportsContext, SimpleJasperReportSource.from(jasperReport), parent);
74     }
75
76     public JRVerticalFiller(
77         JasperReportsContext jasperReportsContext,
78         JasperReportSource reportSource, 
79         BandReportFillerParent parent 
80         ) throws JRException
81     {
82         super(jasperReportsContext, reportSource, parent);
83
84         setPageHeight(pageHeight);
85     }
86     
87     
88     public boolean hasDetailOnPage()
89     {
90         return hasDetailOnPage;
91     }
92
93
94     @Override
95     protected void setPageHeight(int pageHeight)
96     {
97         this.pageHeight = pageHeight;
98
99         columnFooterOffsetY = pageHeight - bottomMargin - pageFooter.getHeight() - columnFooter.getHeight();
100         lastPageColumnFooterOffsetY = pageHeight - bottomMargin - lastPageFooter.getHeight() - columnFooter.getHeight();
101         
102         if (log.isDebugEnabled())
103         {
104             log.debug("Filler " + fillerId + " - pageHeight: " + pageHeight
105                     + ", columnFooterOffsetY: " + columnFooterOffsetY
106                     + ", lastPageColumnFooterOffsetY: " + lastPageColumnFooterOffsetY);
107         }
108     }
109
110
111     @Override
112     @continuable
113     protected synchronized void fillReport() throws JRException
114     {
115         setLastPageFooter(false);
116
117         if (next())
118         {
119             fillReportStart();
120
121             while (next())
122             {
123                 fillReportContent();
124             }
125
126             fillReportEnd();
127         }
128         else
129         {
130             if (log.isDebugEnabled())
131             {
132                 log.debug("Fill " + fillerId + ": no data");
133             }
134
135             switch (getWhenNoDataType())
136             {
137                 case ALL_SECTIONS_NO_DETAIL :
138                 {
139                     if (log.isDebugEnabled())
140                     {
141                         log.debug("Fill " + fillerId + ": all sections");
142                     }
143
144                     scriptlet.callBeforeReportInit();
145                     calculator.initializeVariables(ResetTypeEnum.REPORT, IncrementTypeEnum.REPORT);
146                     scriptlet.callAfterReportInit();
147
148                     printPage = newPage();
149                     printPageContentsWidth = 0;
150                     addPage(printPage);
151                     setFirstColumn();
152                     offsetY = topMargin;
153                     isFirstPageBand = true;
154                     isFirstColumnBand = true;
155                     isCrtRecordOnPage = false;
156                     isCrtRecordOnColumn = false;
157
158                     fillBackground();
159
160                     fillTitle();
161
162                     fillPageHeader(JRExpression.EVALUATION_DEFAULT);
163
164                     fillColumnHeader(JRExpression.EVALUATION_DEFAULT);
165
166                     fillGroupHeaders(true);
167
168                     fillGroupFooters(true);
169
170                     fillSummary();
171
172                     break;
173                 }
174                 case BLANK_PAGE :
175                 {
176                     if (log.isDebugEnabled())
177                     {
178                         log.debug("Fill " + fillerId + ": blank page");
179                     }
180
181                     printPage = newPage();
182                     addPage(printPage);
183                     break;
184                 }
185                 case NO_DATA_SECTION:
186                 {
187                     if (log.isDebugEnabled())
188                     {
189                         log.debug("Fill " + fillerId + ": all sections");
190                     }
191
192                     scriptlet.callBeforeReportInit();
193                     calculator.initializeVariables(ResetTypeEnum.REPORT, IncrementTypeEnum.REPORT);
194                     scriptlet.callAfterReportInit();
195
196                     printPage = newPage();
197                     addPage(printPage);
198                     setFirstColumn();
199                     offsetY = topMargin;
200                     isFirstPageBand = true;
201                     isFirstColumnBand = true;
202                     isCrtRecordOnPage = false;
203                     isCrtRecordOnColumn = false;
204
205                     fillBackground();
206
207                     fillNoData();
208                     
209                     break;
210
211                 }
212                 case NO_PAGES :
213                 default :
214                 {
215                     if (log.isDebugEnabled())
216                     {
217                         log.debug("Fill " + fillerId + ": no pages");
218                     }
219                 }
220             }
221         }
222
223         recordUsedPageHeight(offsetY + bottomMargin);
224         if (ignorePagination)
225         {
226             jasperPrint.setPageHeight(usedPageHeight);
227         }
228
229         if (isSubreport())
230         {
231             addPageToParent(true);
232         }
233         else
234         {
235             addLastPageBookmarks();
236         }
237         
238         if (bookmarkHelper != null)
239         {
240             jasperPrint.setBookmarks(bookmarkHelper.getRootBookmarks());
241         }
242     }
243
244
245     /**
246      *
247      */

248     @continuable
249     private void fillReportStart() throws JRException
250     {
251         scriptlet.callBeforeReportInit();
252         calculator.initializeVariables(ResetTypeEnum.REPORT, IncrementTypeEnum.REPORT);
253         scriptlet.callAfterReportInit();
254
255         printPage = newPage();
256         printPageContentsWidth = 0;
257         addPage(printPage);
258         setFirstColumn();
259         offsetY = topMargin;
260         isFirstPageBand = true;
261         isFirstColumnBand = true;
262         isCrtRecordOnPage = false;
263         isCrtRecordOnColumn = false;
264
265         fillBackground();
266
267         fillTitle();
268
269         fillPageHeader(JRExpression.EVALUATION_DEFAULT);
270
271         fillColumnHeader(JRExpression.EVALUATION_DEFAULT);
272
273         fillGroupHeaders(true);
274
275         fillDetail();
276     }
277
278
279     /**
280      *
281      */

282     @continuable
283     private void fillReportContent() throws JRException
284     {
285         calculator.estimateGroupRuptures();
286
287         fillGroupFooters(false);
288
289         resolveGroupBoundElements(JRExpression.EVALUATION_OLD, false);
290         scriptlet.callBeforeGroupInit();
291         calculator.initializeVariables(ResetTypeEnum.GROUP, IncrementTypeEnum.GROUP);
292         scriptlet.callAfterGroupInit();
293
294         fillGroupHeaders(false);
295
296         fillDetail();
297     }
298
299
300     /**
301      *
302      */

303     @continuable
304     private void fillReportEnd() throws JRException
305     {
306         fillGroupFooters(true);
307
308         fillSummary();
309     }
310
311
312     /**
313      *
314      */

315     @continuable
316      private void fillTitle() throws JRException
317      {
318         if (log.isDebugEnabled() && !title.isEmpty())
319         {
320             log.debug("Fill " + fillerId + ": title at " + offsetY);
321         }
322
323         title.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
324
325         if (title.isToPrint())
326         {
327             while (
328                 title.getBreakHeight() > pageHeight - bottomMargin - offsetY
329                 )
330             {
331                 addPage(false);
332             }
333
334             title.evaluate(JRExpression.EVALUATION_DEFAULT);
335
336             JRPrintBand printBand = title.fill(pageHeight - bottomMargin - offsetY);
337
338             if (title.willOverflow() && title.isSplitPrevented() && !title.isSplitTypePreventInhibited())
339             {
340                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
341                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
342                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
343                 scriptlet.callBeforePageInit();
344                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
345                 scriptlet.callAfterPageInit();
346
347                 addPage(false);
348
349                 printBand = 
350                     title.refill(
351                         JRExpression.EVALUATION_DEFAULT, 
352                         pageHeight - bottomMargin - offsetY
353                         );
354             }
355
356             fillBand(printBand);
357             offsetY += printBand.getHeight();
358             isCrtRecordOnPage = true;
359             isCrtRecordOnColumn = true;
360
361             while (title.willOverflow())
362             {
363                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
364                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
365                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
366                 scriptlet.callBeforePageInit();
367                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
368                 scriptlet.callAfterPageInit();
369
370                 addPage(false);
371
372                 printBand = title.fill(pageHeight - bottomMargin - offsetY);
373
374                 fillBand(printBand);
375                 offsetY += printBand.getHeight();
376                 isCrtRecordOnPage = true;
377                 isCrtRecordOnColumn = true;
378             }
379
380             resolveBandBoundElements(title, JRExpression.EVALUATION_DEFAULT);
381
382             if (isTitleNewPage)
383             {
384                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
385                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
386                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
387                 scriptlet.callBeforePageInit();
388                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
389                 scriptlet.callAfterPageInit();
390
391                 addPage(false);
392             }
393         }
394     }
395
396
397     /**
398      *
399      */

400     @continuable
401     private void fillPageHeader(byte evaluation) throws JRException
402     {
403         if (log.isDebugEnabled() && !pageHeader.isEmpty())
404         {
405             log.debug("Fill " + fillerId + ": page header at " + offsetY);
406         }
407
408         setNewPageColumnInBands();
409
410         pageHeader.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
411
412         if (pageHeader.isToPrint())
413         {
414             int reattempts = getMasterColumnCount();
415             if (isCreatingNewPage)
416             {
417                 --reattempts;
418             }
419
420             boolean filled = fillBandNoOverflow(pageHeader, evaluation);
421
422             for (int i = 0; !filled && i < reattempts; ++i)
423             {
424                 resolveGroupBoundElements(evaluation, false);
425                 resolveColumnBoundElements(evaluation);
426                 resolvePageBoundElements(evaluation);
427                 scriptlet.callBeforePageInit();
428                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
429                 scriptlet.callAfterPageInit();
430
431                 addPage(false);
432
433                 filled = fillBandNoOverflow(pageHeader, evaluation);
434             }
435
436             if (!filled)
437             {
438                 throw 
439                     new JRRuntimeException(
440                         EXCEPTION_MESSAGE_KEY_PAGE_HEADER_OVERFLOW_INFINITE_LOOP,
441                         (Object[])null);
442             }
443         }
444
445         columnHeaderOffsetY = offsetY;
446
447         hasDetailOnPage = false;
448         
449         isNewPage = true;
450     }
451
452
453     private boolean fillBandNoOverflow(JRFillBand band, byte evaluation) throws JRException
454     {
455         int availableHeight = columnFooterOffsetY - offsetY;
456         boolean overflow = availableHeight < band.getHeight();
457
458         if (!overflow)
459         {
460             band.evaluate(evaluation);
461             JRPrintBand printBand = band.fill(availableHeight);
462
463             overflow = band.willOverflow();
464             if (overflow)
465             {
466                 band.rewind();
467             }
468             else
469             {
470                 fillBand(printBand);
471                 offsetY += printBand.getHeight();
472                 isCrtRecordOnPage = evaluation == JRExpression.EVALUATION_DEFAULT;
473                 isCrtRecordOnColumn = isCrtRecordOnPage;
474
475                 resolveBandBoundElements(band, evaluation);
476             }
477         }
478
479         return !overflow;
480     }
481
482
483     /**
484      *
485      */

486     @continuable
487     private void fillColumnHeader(byte evaluation) throws JRException
488     {
489         if (log.isDebugEnabled() && !columnHeader.isEmpty())
490         {
491             log.debug("Fill " + fillerId + ": column header at " + offsetY);
492         }
493
494         setNewPageColumnInBands();
495         isFirstColumnBand = true;
496
497         columnHeader.evaluatePrintWhenExpression(evaluation);
498
499         if (columnHeader.isToPrint())
500         {
501             int reattempts = getMasterColumnCount();
502             if (isCreatingNewPage)
503             {
504                 --reattempts;
505             }
506
507             setOffsetX();
508
509             boolean filled = fillBandNoOverflow(columnHeader, evaluation);
510
511             for (int i = 0; !filled && i < reattempts; ++i)
512             {
513                 while (columnIndex < columnCount - 1)
514                 {
515                     resolveGroupBoundElements(evaluation, false);
516                     resolveColumnBoundElements(evaluation);
517                     scriptlet.callBeforeColumnInit();
518                     calculator.initializeVariables(ResetTypeEnum.COLUMN, IncrementTypeEnum.COLUMN);
519                     scriptlet.callAfterColumnInit();
520
521                     columnIndex += 1;
522                     setOffsetX();
523                     offsetY = columnHeaderOffsetY;
524                     isCrtRecordOnColumn = false;
525
526                     setColumnNumberVar();
527                 }
528
529                 fillPageFooter(evaluation);
530
531                 resolveGroupBoundElements(evaluation, false);
532                 resolveColumnBoundElements(evaluation);
533                 resolvePageBoundElements(evaluation);
534                 scriptlet.callBeforePageInit();
535                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
536                 scriptlet.callAfterPageInit();
537
538                 addPage(false);
539
540                 fillPageHeader(evaluation);
541
542                 filled = fillBandNoOverflow(columnHeader, evaluation);
543             }
544
545             if (!filled)
546             {
547                 throw new JRRuntimeException(EXCEPTION_MESSAGE_KEY_COLUMN_HEADER_OVERFLOW_INFINITE_LOOP, (Object[]) null);
548             }
549         }
550
551         isNewColumn = true;
552     }
553
554
555     /**
556      *
557      */

558     @continuable
559     private void fillGroupHeaders(boolean isFillAll) throws JRException
560     {
561         if (groups != null && groups.length > 0)
562         {
563             for (int i = 0; i < groups.length; i++)
564             {
565                 JRFillGroup group = groups[i];
566
567                 if (isFillAll || group.hasChanged())
568                 {
569                     fillGroupHeader(group);
570                 }
571             }
572         }
573     }
574
575
576     /**
577      *
578      */

579     @continuable
580     private void fillGroupHeader(JRFillGroup group) throws JRException
581     {
582         JRFillSection groupHeaderSection = (JRFillSection)group.getGroupHeaderSection();
583
584         if (log.isDebugEnabled() && !groupHeaderSection.isEmpty())
585         {
586             log.debug("Fill " + fillerId + ": " + group.getName() + " header at " + offsetY);
587         }
588
589         //byte evalPrevPage = (group.isTopLevelChange()?JRExpression.EVALUATION_OLD:JRExpression.EVALUATION_DEFAULT);
590
591         if ( (group.isStartNewPage() || group.isResetPageNumber()) && !isNewPage )
592         {
593             fillPageBreak(
594                 group.isResetPageNumber(),
595                 isCrtRecordOnPage ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD, //evalPrevPage,
596                 JRExpression.EVALUATION_DEFAULT,
597                 true
598                 );
599         }
600         else if ( group.isStartNewColumn() && !isNewColumn )
601         {
602             fillColumnBreak(
603                 isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD, //evalPrevPage,
604                 JRExpression.EVALUATION_DEFAULT
605                 );
606         }
607
608         boolean isFirstHeaderBandToPrint = true;
609         boolean isGroupReset = false;
610         
611         JRFillBand[] groupHeaderBands = groupHeaderSection.getFillBands();
612         for (int i = 0; i < groupHeaderBands.length; i++)
613         {
614             JRFillBand groupHeaderBand = groupHeaderBands[i];
615
616             groupHeaderBand.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
617
618             if (groupHeaderBand.isToPrint())
619             {
620                 while (
621                     groupHeaderBand.getBreakHeight() > columnFooterOffsetY - offsetY ||
622                     (isFirstHeaderBandToPrint && group.getMinHeightToStartNewPage() > columnFooterOffsetY - offsetY) 
623                     )
624                 {
625                     fillColumnBreak(
626                         isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD, //evalPrevPage,
627                         JRExpression.EVALUATION_DEFAULT
628                         );
629                 }
630             }
631
632             if (!isGroupReset && (isFirstHeaderBandToPrint || i == groupHeaderBands.length - 1))
633             {
634                 // perform this group reset before the first header band prints, 
635                 // or before the last header band, regardless if it prints or not 
636                 setNewGroupInBands(group);
637
638                 group.setFooterPrinted(false);
639                 group.resetDetailsCount();
640                 
641                 isGroupReset = true;
642             }
643
644             ElementRange elementRange = null;
645             
646             if (
647                 (group.isKeepTogether() && !isNewColumn)
648                 || group.getMinDetailsToStartFromTop() > 0
649                 )
650             {
651                 elementRange = group.getKeepTogetherElementRange();
652                 
653                 if (elementRange == null)
654                 {
655                     // we need to set a keep together element range for the group
656                     // even if its header does not print,
657                     // but only if the column is not already new
658                     elementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
659                     
660                     group.setKeepTogetherElementRange(elementRange);
661                     // setting a non-null element range here would cause the group header band to be
662                     // refilled below and thus kept together, in case a split occurs in it;
663                     // the non-null element range will be also moved onto the new page/column in the process,
664                     // but it will contain no elements as the already mentioned non-splitting behavior of the group header band
665                     // would not add any element to it;
666                     // so the keep together element range set here is more like flag to signal the group header itself
667                     // should be prevented from splitting in the fillColumnBand call below
668                 }
669             }
670
671             if (groupHeaderBand.isToPrint())
672             {
673                 fillColumnBand(groupHeaderBand, JRExpression.EVALUATION_DEFAULT, false);
674                 
675                 ElementRange newElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
676                     
677                 // in case a column/page break occurred during the filling of the band above,
678                 // the provided element range is discarded/ignored,
679                 // but that should not be a problem because the discarded element range was already dealt with during the break
680                 // because it was a keep together element range
681                 ElementRangeUtil.expandOrIgnore(elementRange, newElementRange);
682
683                 isFirstPageBand = false;
684                 isFirstColumnBand = false;
685                 
686                 isFirstHeaderBandToPrint = false;
687             }
688         }
689
690         group.setHeaderPrinted(true);
691     }
692
693
694     /**
695      *
696      */

697     @continuable
698     private void fillGroupHeadersReprint(byte evaluation, boolean isPageBreak) throws JRException
699     {
700         if (groups != null && groups.length > 0)
701         {
702             for (int i = 0; i < groups.length; i++)
703             {
704                 JRFillGroup group = groups[i];
705                 
706                 if (
707                     group.getKeepTogetherElementRange() != null
708                     && (group.isKeepTogether() || !group.hasMinDetails())
709                     )
710                 {
711                     // we reprint headers only for groups that are "outer" to the one which 
712                     // triggered a potential "keep together" move 
713                     break;
714                 }
715
716                 if (
717                     (group.isReprintHeaderOnEachColumn() || (group.isReprintHeaderOnEachPage() && isPageBreak)) 
718                     && (!group.hasChanged() || (group.hasChanged() && group.isHeaderPrinted()))
719                     )
720                 {
721                     fillGroupHeaderReprint(groups[i], evaluation);
722                 }
723             }
724         }
725     }
726
727
728     /**
729      *
730      */

731     @continuable
732      private void fillGroupHeaderReprint(JRFillGroup group, byte evaluation) throws JRException
733      {
734         JRFillSection groupHeaderSection = (JRFillSection)group.getGroupHeaderSection();
735
736         JRFillBand[] groupHeaderBands = groupHeaderSection.getFillBands();
737         for (int i = 0; i < groupHeaderBands.length; i++)
738         {
739             JRFillBand groupHeaderBand = groupHeaderBands[i];
740
741             groupHeaderBand.evaluatePrintWhenExpression(evaluation);
742
743             if (groupHeaderBand.isToPrint())
744             {
745                 while (groupHeaderBand.getBreakHeight() > columnFooterOffsetY - offsetY)
746                 {
747                     fillColumnBreak(evaluation, evaluation); // using same evaluation for both side of the break is ok here
748                 }
749
750                 fillColumnBand(groupHeaderBand, evaluation, false);
751
752                 //isFirstPageBand = false;
753                 if (columnCount > 1)
754                 {
755                     isFirstColumnBand = false;
756                 }
757             }
758         }
759     }
760
761
762     /**
763      *
764      */

765     @continuable
766     private void fillDetail() throws JRException
767     {
768         if (log.isDebugEnabled() && !detailSection.isEmpty())
769         {
770             log.debug("Fill " + fillerId + ": detail at " + offsetY);
771         }
772
773         if (!detailSection.areAllPrintWhenExpressionsNull())
774         {
775             calculator.estimateVariables();
776         }
777
778         JRFillBand[] detailBands = detailSection.getFillBands();
779         for (int i = 0; i < detailBands.length; i++)
780         {
781             JRFillBand detailBand = detailBands[i];
782             
783             detailBand.evaluatePrintWhenExpression(JRExpression.EVALUATION_ESTIMATED);
784
785             if (detailBand.isToPrint())
786             {
787                 while (
788                     detailBand.getBreakHeight() > columnFooterOffsetY - offsetY
789                     )
790                 {
791                     fillColumnBreak(
792                         isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD,
793                         JRExpression.EVALUATION_DEFAULT
794                         );
795                 }
796                 
797                 break;
798             }
799         }
800
801         scriptlet.callBeforeDetailEval();
802         calculator.calculateVariables(true);
803         scriptlet.callAfterDetailEval();
804
805         detailElementRange = null;
806
807         boolean keepDetailElementRangeForOrphanFooter = true;
808         boolean atLeastOneDetailBandPrinted = false;
809         
810         for (int i = 0; i < detailBands.length; i++)
811         {
812             JRFillBand detailBand = detailBands[i];
813                     
814             detailBand.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
815
816             if (detailBand.isToPrint())
817             {
818                 while (
819                     detailBand.getBreakHeight() > columnFooterOffsetY - offsetY
820                     )
821                 {
822                     fillColumnBreak(
823                         isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD,
824                         JRExpression.EVALUATION_DEFAULT
825                         );
826                 }
827
828                 if (
829                     keepDetailElementRangeForOrphanFooter
830                     && detailElementRange == null
831                     )
832                 {
833                     detailElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
834                 }
835
836                 fillColumnBand(detailBand, JRExpression.EVALUATION_DEFAULT, !atLeastOneDetailBandPrinted); //recalculate variables on refill if this is the first detail band
837                 
838                 if (detailElementRange == null)
839                 {
840                     // page/column break occurred so we give up keeping the detail element range altogether;
841                     // even if the detail moved onto new page/column completely (did not start at the bottom as it was
842                     // non-splitting or did not fit within break height), we still need to give up on keeping
843                     // the current detail element range because only the next detail on the page/column would make
844                     // sense to move for orphan footers;
845                     // if there will be no second detail there, we simply can't move the only detail, so we still have to give up here
846                     keepDetailElementRangeForOrphanFooter = false;
847                 }
848                 else
849                 {
850                     // there was no overflow, otherwise this range would have been reset to null during page/column break
851                     
852                     ElementRange newElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
853
854                     ElementRangeUtil.expandOrIgnore(detailElementRange, newElementRange);
855                 }
856
857                 atLeastOneDetailBandPrinted = true;
858
859                 isFirstPageBand = false;
860                 isFirstColumnBand = false;
861             }
862         }
863         
864         if (atLeastOneDetailBandPrinted)
865         {
866             if (groups != null)
867             {
868                 for (JRFillGroup group : groups)
869                 {
870                     group.incrementDetailsCount();
871                 }
872             }
873         }
874         
875         hasDetailOnPage = atLeastOneDetailBandPrinted;
876
877         isNewPage = false;
878         isNewColumn = false;
879     }
880
881
882     /**
883      *
884      */

885     @continuable
886     private void fillGroupFooters(boolean isFillAll) throws JRException
887     {
888         if (groups != null && groups.length > 0)
889         {
890             byte evaluation = (isFillAll)?JRExpression.EVALUATION_DEFAULT:JRExpression.EVALUATION_OLD;
891
892             preventOrphanFootersMinLevel = null;
893             for (int i = groups.length - 1; i >= 0; i--)
894             {
895                 JRFillGroup group = groups[i];
896                 
897                 if (
898                     (isFillAll || group.hasChanged())
899                     && group.isPreventOrphanFooter()
900                     )
901                 {
902                     // we need to decide up-front if during the current group footers printing,
903                     // there are any potential orphans to take care of
904                     preventOrphanFootersMinLevel = i;
905                     break;
906                 }
907             }
908             
909             for (int i = groups.length - 1; i >= 0; i--)
910             {
911                 JRFillGroup group = groups[i];
912                 
913                 crtGroupFootersLevel = i;
914                 if (
915                     preventOrphanFootersMinLevel != null
916                     && crtGroupFootersLevel < preventOrphanFootersMinLevel
917                     )
918                 {
919                     // reset the element ranges when we get to the group footers
920                     // that are outer to the ones for which we need to prevent orphans;
921                     // these ranges act like flags to signal we need to deal with orphans
922                     orphanGroupFooterDetailElementRange = null;
923                     orphanGroupFooterElementRange = null;
924                     detailElementRange = null// put this line here just to have the same trio everywhere; could not find a case when this line really matters
925                 }
926                 
927                 if (isFillAll || group.hasChanged())
928                 {
929                     fillGroupFooter(group, evaluation);
930                     
931                     // regardless of whether the fillGroupFooter was printed or not, 
932                     // we just need to mark the end of the group 
933                     group.setKeepTogetherElementRange(null);
934                 }
935             }
936             
937             // resetting orphan footer element ranges because all group footers have been rendered
938             orphanGroupFooterDetailElementRange = null;
939             orphanGroupFooterElementRange = null;
940             detailElementRange = null// put this line here just to have the same trio everywhere; could not find a case when this line really matters
941             
942             // we need to take care of groupFooterPositionElementRange here because all groups footers have been 
943             // rendered and we need to consume remaining space before next groups start;
944             //
945             // but we don't process the last groupFooterPositionElementRange when the report ends (isFillAll true),
946             // because it will be dealt with during summary rendering, depending on whether a last page footer exists or not
947             if (
948                 !isFillAll
949                 && groupFooterPositionElementRange != null
950                 )
951             {
952                 ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
953                 groupFooterPositionElementRange = null;
954                 // update the offsetY to signal there is no more space left at the bottom after forcing the footer
955                 offsetY = columnFooterOffsetY;
956             }
957         }
958     }
959
960
961     /**
962      *
963      */

964     @continuable
965     private void fillGroupFooter(JRFillGroup group, byte evaluation) throws JRException
966     {
967         JRFillSection groupFooterSection = (JRFillSection)group.getGroupFooterSection();
968
969         if (log.isDebugEnabled() && !groupFooterSection.isEmpty())
970         {
971             log.debug("Fill " + fillerId + ": " + group.getName() + " footer at " + offsetY);
972         }
973
974         JRFillBand[] groupFooterBands = groupFooterSection.getFillBands();
975         for (int i = 0; i < groupFooterBands.length; i++)
976         {
977             JRFillBand groupFooterBand = groupFooterBands[i];
978             
979             groupFooterBand.evaluatePrintWhenExpression(evaluation);
980
981             if (groupFooterBand.isToPrint())
982             {
983                 if (
984                     preventOrphanFootersMinLevel != null
985                     && crtGroupFootersLevel >= preventOrphanFootersMinLevel 
986                     && orphanGroupFooterDetailElementRange == null
987                     )
988                 {
989                     // the detail element range can't be null here, unless there is no detail printing;
990                     // keeping the detail element range in this separate variable signals we are currently
991                     // dealing with orphan group footers
992                     orphanGroupFooterDetailElementRange = detailElementRange;
993                 }
994                 
995                 if (
996                     groupFooterBand.getBreakHeight() > columnFooterOffsetY - offsetY
997                     )
998                 {
999                     fillColumnBreak(evaluation, evaluation); // using same evaluation for both side of the break is ok here
1000                 }
1001
1002                 if (
1003                     groupFooterPositionElementRange == null 
1004                     && group.getFooterPositionValue() != FooterPositionEnum.NORMAL
1005                     )
1006                 {
1007                     groupFooterPositionElementRange = 
1008                         new SimpleGroupFooterElementRange(
1009                             new SimpleElementRange(getCurrentPage(), columnIndex, offsetY), 
1010                             group.getFooterPositionValue()
1011                             );
1012                 }
1013
1014                 if (groupFooterPositionElementRange != null)
1015                 {
1016                     // keep the current group footer position because it will be needed
1017                     // in case the band breaks and the group footer element range needs to
1018                     // be recreated on the new page
1019                     groupFooterPositionElementRange.setCurrentFooterPosition(group.getFooterPositionValue());
1020                 }
1021                 
1022                 if (orphanGroupFooterDetailElementRange != null)
1023                 {
1024                     ElementRange newElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
1025                     if (orphanGroupFooterElementRange == null)
1026                     {
1027                         orphanGroupFooterElementRange = newElementRange;
1028                     }
1029                     else
1030                     {
1031                         ElementRangeUtil.expandOrIgnore(orphanGroupFooterElementRange, newElementRange);
1032                     }
1033                 }
1034                 
1035                 fillColumnBand(groupFooterBand, evaluation, false);
1036                 
1037                 ElementRange newElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
1038                 
1039                 if (groupFooterPositionElementRange != null)
1040                 {
1041                     ElementRangeUtil.expandOrIgnore(groupFooterPositionElementRange.getElementRange(), newElementRange);
1042
1043                     switch (group.getFooterPositionValue())
1044                     {
1045                         case STACK_AT_BOTTOM :
1046                         {
1047                             groupFooterPositionElementRange.setMasterFooterPosition(FooterPositionEnum.STACK_AT_BOTTOM);
1048                             break;
1049                         }
1050                         case FORCE_AT_BOTTOM :
1051                         {
1052                             groupFooterPositionElementRange.setMasterFooterPosition(FooterPositionEnum.FORCE_AT_BOTTOM);
1053                             break;
1054                         }
1055                         case COLLATE_AT_BOTTOM :
1056                         {
1057                             break;
1058                         }
1059                         case NORMAL :
1060                         default :
1061                         {
1062                             // only StackAtBottom and CollateAtBottom can get here
1063                             if (groupFooterPositionElementRange.getMasterFooterPosition() == FooterPositionEnum.COLLATE_AT_BOTTOM)
1064                             {
1065                                 groupFooterPositionElementRange = null;
1066                             }
1067                             break;
1068                         }
1069                     }
1070                 }
1071                 
1072                 isFirstPageBand = false;
1073                 isFirstColumnBand = false;
1074             }
1075         }
1076
1077         // we need to perform ForceAtBottom here because only the group footer as a whole should be forced to bottom, 
1078         // not the individual bands in this footer section;
1079         // also, when forcing a group footer to bottom, we consider the normal/current columnFooterOffsetY, because it is impossible
1080         // to tell at this point if this would be the last page or not (last page footer)
1081         if (
1082             groupFooterPositionElementRange != null
1083             && groupFooterPositionElementRange.getMasterFooterPosition() == FooterPositionEnum.FORCE_AT_BOTTOM
1084             )
1085         {
1086             ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
1087             groupFooterPositionElementRange = null;
1088             // update the offsetY to signal there is no more space left at the bottom after forcing the footer
1089             offsetY = columnFooterOffsetY;
1090         }
1091
1092         isNewPage = false;
1093         isNewColumn = false;
1094
1095         group.setHeaderPrinted(false);
1096         group.setFooterPrinted(true);
1097     }
1098
1099
1100     /**
1101      *
1102      */

1103      private void fillColumnFooter(byte evaluation) throws JRException
1104      {
1105         if (log.isDebugEnabled() && !columnFooter.isEmpty())
1106         {
1107             log.debug("Fill " + fillerId + ": column footer at " + offsetY);
1108         }
1109
1110         setOffsetX();
1111         
1112         /*
1113         if (!isSubreport)
1114         {
1115             offsetY = columnFooterOffsetY;
1116         }
1117         */

1118
1119         if (isSubreport() && !isSubreportRunToBottom() && columnIndex == 0)
1120         {
1121             columnFooterOffsetY = offsetY;
1122         }
1123
1124         int oldOffsetY = offsetY;
1125         if (!isFloatColumnFooter && !ignorePagination)
1126         {
1127             offsetY = columnFooterOffsetY;
1128         }
1129
1130         // we first let the column footer Y offset calculations to occur normally above, 
1131         // before attempting to deal with existing groupFooterPositionElementRange
1132         if (groupFooterPositionElementRange != null)
1133         {
1134             // all types of footer position can get here (StackAtBottom, CollapseAtBottom and ForceAtBottom);
1135             // ForceAtBottom group footer element ranges could reach this point in case multi-band group footer gets
1136             // split across a column/page break; remaining bands in such group footer would be dealt at the end 
1137             // of the group footer filling method (see fillGroupFooter() method above)
1138             ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
1139             groupFooterPositionElementRange = null;
1140             // we do not need to set the offsetY because it has already been set properly earlier in this method;
1141         }
1142         
1143         columnFooter.evaluatePrintWhenExpression(evaluation);
1144
1145         if (columnFooter.isToPrint())
1146         {
1147             if (isFloatColumnFooter && !ignorePagination)
1148             {
1149                 floatColumnFooterElementRange = new SimpleElementRange(getCurrentPage(), columnIndex, offsetY);
1150             }
1151             
1152             fillFixedBand(columnFooter, evaluation);
1153             
1154             if (floatColumnFooterElementRange != null)
1155             {
1156                 floatColumnFooterElementRange.expand(offsetY);
1157             }
1158         }
1159
1160         if (isFloatColumnFooter && !ignorePagination)
1161         {
1162             offsetY += columnFooterOffsetY - oldOffsetY;
1163         }
1164     }
1165
1166
1167     /**
1168      *
1169      */

1170     private void fillPageFooter(byte evaluation) throws JRException
1171     {
1172         JRFillBand crtPageFooter = getCurrentPageFooter();
1173
1174         if (log.isDebugEnabled() && !crtPageFooter.isEmpty())
1175         {
1176             log.debug("Fill " + fillerId + ": " + (isLastPageFooter ? "last " : "") + "page footer at " + offsetY);
1177         }
1178
1179         offsetX = leftMargin;
1180
1181         if ((!isSubreport() || isSubreportRunToBottom()) && !ignorePagination)
1182         {
1183             offsetY = pageHeight - crtPageFooter.getHeight() - bottomMargin;
1184         }
1185
1186         crtPageFooter.evaluatePrintWhenExpression(evaluation);
1187
1188         if (crtPageFooter.isToPrint())
1189         {
1190             fillFixedBand(crtPageFooter, evaluation);
1191         }
1192     }
1193
1194
1195     /**
1196      *
1197      */

1198     @continuable
1199     private void fillSummary() throws JRException
1200     {
1201         if (log.isDebugEnabled() && !summary.isEmpty())
1202         {
1203             log.debug("Fill " + fillerId + ": summary at " + offsetY);
1204         }
1205
1206         offsetX = leftMargin;
1207         
1208         if (lastPageFooter == missingFillBand)
1209         {
1210             if (
1211                 !isSummaryNewPage
1212                 && columnIndex == 0
1213                 && summary.getBreakHeight() <= columnFooterOffsetY - offsetY
1214                 )
1215             {
1216                 fillSummaryNoLastFooterSamePage();
1217             }
1218             else
1219             {
1220                 fillSummaryNoLastFooterNewPage();
1221             }
1222         }
1223         else
1224         {
1225             if (isSummaryWithPageHeaderAndFooter)
1226             {
1227                 fillSummaryWithLastFooterAndPageBands();
1228             }
1229             else
1230             {
1231                 fillSummaryWithLastFooterNoPageBands();
1232             }
1233         }
1234
1235         resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1236         resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1237         resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1238         resolveReportBoundElements();
1239         if (isMasterReport())
1240         {
1241             resolveMasterBoundElements();
1242         }
1243     }
1244
1245
1246     /**
1247      *
1248      */

1249     @continuable
1250     private void fillSummaryNoLastFooterSamePage() throws JRException
1251     {
1252         summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
1253
1254         if (summary.isToPrint())
1255         {
1256             // deal with groupFooterPositionElementRange here because summary will attempt to use remaining space
1257             if (groupFooterPositionElementRange != null)
1258             {
1259                 ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
1260                 offsetY = columnFooterOffsetY;
1261                 // reset the element range here although it will not be checked anymore as the report ends
1262                 groupFooterPositionElementRange = null;
1263             }
1264             
1265             summary.evaluate(JRExpression.EVALUATION_DEFAULT);
1266
1267             JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
1268
1269             if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
1270             {
1271                 fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1272
1273                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1274
1275                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1276                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1277                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1278                 scriptlet.callBeforePageInit();
1279                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1280                 scriptlet.callAfterPageInit();
1281
1282                 addPage(false);
1283                 
1284                 if (isSummaryWithPageHeaderAndFooter)
1285                 {
1286                     fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1287                 }
1288
1289                 printBand = 
1290                     summary.refill(
1291                         JRExpression.EVALUATION_DEFAULT, 
1292                         pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0)
1293                         );
1294
1295                 fillBand(printBand);
1296                 offsetY += printBand.getHeight();
1297                 isCrtRecordOnPage = true;
1298                 isCrtRecordOnColumn = true;
1299
1300                 /*   */
1301                 fillSummaryOverflow();
1302                 
1303                 //DONE
1304             }
1305             else
1306             {
1307                 //SummaryReport.14 test
1308                 
1309                 fillBand(printBand);
1310                 offsetY += printBand.getHeight();
1311                 isCrtRecordOnPage = true;
1312                 isCrtRecordOnColumn = true;
1313
1314                 fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1315
1316                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1317                 
1318                 if (summary.willOverflow())
1319                 {
1320                     resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1321                     resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1322                     resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1323                     scriptlet.callBeforePageInit();
1324                     calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1325                     scriptlet.callAfterPageInit();
1326
1327                     addPage(false);
1328                     
1329                     if (isSummaryWithPageHeaderAndFooter)
1330                     {
1331                         fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1332                     }
1333
1334                     printBand = summary.fill(pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0));
1335
1336                     fillBand(printBand);
1337                     offsetY += printBand.getHeight();
1338                     isCrtRecordOnPage = true;
1339                     isCrtRecordOnColumn = true;
1340
1341                     /*   */
1342                     fillSummaryOverflow();
1343                     
1344                     //DONE
1345                 }
1346                 else
1347                 {
1348                     resolveBandBoundElements(summary, JRExpression.EVALUATION_DEFAULT);
1349
1350                     //DONE
1351                 }
1352             }
1353         }
1354         else
1355         {
1356             //SummaryReport.15 test
1357             
1358             // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
1359             
1360             fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1361
1362             fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1363             
1364             //DONE
1365         }
1366     }
1367
1368
1369     /**
1370      *
1371      */

1372     @continuable
1373     private void fillSummaryNoLastFooterNewPage() throws JRException
1374     {
1375         //SummaryReport.13 test
1376
1377         // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
1378         
1379         fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1380
1381         fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1382
1383         summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
1384
1385         if (summary.isToPrint())
1386         {
1387             resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1388             resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1389             resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1390             scriptlet.callBeforePageInit();
1391             calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1392             scriptlet.callAfterPageInit();
1393
1394             addPage(false);
1395
1396             if (isSummaryWithPageHeaderAndFooter)
1397             {
1398                 fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1399             }
1400
1401             summary.evaluate(JRExpression.EVALUATION_DEFAULT);
1402
1403             JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0));
1404
1405             if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
1406             {
1407                 if (isSummaryWithPageHeaderAndFooter)
1408                 {
1409                     fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1410                 }
1411
1412                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1413                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1414                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1415                 scriptlet.callBeforePageInit();
1416                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1417                 scriptlet.callAfterPageInit();
1418
1419                 addPage(false);
1420
1421                 if (isSummaryWithPageHeaderAndFooter)
1422                 {
1423                     fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1424                 }
1425
1426                 printBand = 
1427                     summary.refill(
1428                         JRExpression.EVALUATION_DEFAULT, 
1429                         pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0)
1430                         );
1431             }
1432
1433             fillBand(printBand);
1434             offsetY += printBand.getHeight();
1435             isCrtRecordOnPage = true;
1436             isCrtRecordOnColumn = true;
1437
1438             /*   */
1439             fillSummaryOverflow();
1440         }
1441         
1442         //DONE
1443     }
1444
1445
1446     /**
1447      *
1448      */

1449     @continuable
1450     private void fillSummaryWithLastFooterAndPageBands() throws JRException
1451     {
1452         if (
1453             !isSummaryNewPage
1454             && columnIndex == 0
1455             && summary.getBreakHeight() <= columnFooterOffsetY - offsetY
1456             )
1457         {
1458             summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
1459
1460             if (summary.isToPrint())
1461             {
1462                 // deal with groupFooterPositionElementRange here because summary will attempt to use remaining space
1463                 if (groupFooterPositionElementRange != null)
1464                 {
1465                     ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
1466                     offsetY = columnFooterOffsetY;
1467                     // reset the element range here although it will not be checked anymore as the report ends
1468                     groupFooterPositionElementRange = null;
1469                 }
1470                 
1471                 summary.evaluate(JRExpression.EVALUATION_DEFAULT);
1472
1473                 JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
1474
1475                 if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
1476                 {
1477                     fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1478
1479                     fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1480
1481                     resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1482                     resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1483                     resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1484                     scriptlet.callBeforePageInit();
1485                     calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1486                     scriptlet.callAfterPageInit();
1487
1488                     addPage(false);
1489                     
1490                     fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1491                     
1492                     printBand = 
1493                         summary.refill(
1494                             JRExpression.EVALUATION_DEFAULT,
1495                             pageHeight - bottomMargin - offsetY - pageFooter.getHeight()
1496                             );
1497
1498                     fillBand(printBand);
1499                     offsetY += printBand.getHeight();
1500                     isCrtRecordOnPage = true;
1501                     isCrtRecordOnColumn = true;
1502                 }
1503                 else
1504                 {
1505                     //SummaryReport.8 test
1506
1507                     fillBand(printBand);
1508                     offsetY += printBand.getHeight();
1509                     isCrtRecordOnPage = true;
1510                     isCrtRecordOnColumn = true;
1511
1512                     if (
1513                         !summary.willOverflow()
1514                         && offsetY <= lastPageColumnFooterOffsetY
1515                         )
1516                     {
1517                         setLastPageFooter(true);
1518                     }
1519                     
1520                     fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1521                 }
1522                 
1523                 /*   */
1524                 fillSummaryOverflow();
1525
1526                 //DONE
1527             }
1528             else
1529             {
1530                 //SummaryReport.9 test
1531                 
1532                 // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
1533                 
1534                 setLastPageFooter(true);
1535
1536                 fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1537
1538                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1539                 
1540                 //DONE
1541             }
1542         }
1543         else if (columnIndex == 0 && offsetY <= lastPageColumnFooterOffsetY)
1544         {
1545             summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
1546
1547             if (summary.isToPrint())
1548             {
1549                 //SummaryReport.10 test
1550
1551                 // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
1552                 
1553                 fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1554
1555                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1556
1557                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1558                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1559                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1560                 scriptlet.callBeforePageInit();
1561                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1562                 scriptlet.callAfterPageInit();
1563
1564                 addPage(false);
1565                 
1566                 fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1567
1568                 summary.evaluate(JRExpression.EVALUATION_DEFAULT);
1569
1570                 JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY - pageFooter.getHeight());
1571
1572                 if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
1573                 {
1574                     fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1575
1576                     resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1577                     resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1578                     resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1579                     scriptlet.callBeforePageInit();
1580                     calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1581                     scriptlet.callAfterPageInit();
1582
1583                     addPage(false);
1584                     
1585                     fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1586
1587                     printBand = 
1588                         summary.refill(
1589                             JRExpression.EVALUATION_DEFAULT,
1590                             pageHeight - bottomMargin - offsetY - pageFooter.getHeight()
1591                             );
1592                 }
1593
1594                 fillBand(printBand);
1595                 offsetY += printBand.getHeight();
1596                 isCrtRecordOnPage = true;
1597                 isCrtRecordOnColumn = true;
1598
1599                 /*   */
1600                 fillSummaryOverflow();
1601                 
1602                 //DONE
1603             }
1604             else
1605             {
1606                 //SummaryReport.11 test
1607
1608                 // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
1609                 
1610                 setLastPageFooter(true);
1611
1612                 fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1613
1614                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1615                 
1616                 //DONE
1617             }
1618         }
1619         else
1620         {
1621             // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
1622             
1623             fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1624
1625             fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1626
1627             resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
1628             resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1629             resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1630             scriptlet.callBeforePageInit();
1631             calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1632             scriptlet.callAfterPageInit();
1633
1634             addPage(false);
1635
1636             fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1637
1638             summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
1639
1640             if (summary.isToPrint())
1641             {
1642                 //SummaryReport.12 test
1643
1644                 summary.evaluate(JRExpression.EVALUATION_DEFAULT);
1645
1646                 JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY - pageFooter.getHeight());
1647
1648                 if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
1649                 {
1650                     fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1651
1652                     resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1653                     resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1654                     resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1655                     scriptlet.callBeforePageInit();
1656                     calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1657                     scriptlet.callAfterPageInit();
1658
1659                     addPage(false);
1660                     
1661                     fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1662
1663                     printBand = 
1664                         summary.refill(
1665                             JRExpression.EVALUATION_DEFAULT,
1666                             pageHeight - bottomMargin - offsetY - pageFooter.getHeight()
1667                             );
1668                 }
1669
1670                 fillBand(printBand);
1671                 offsetY += printBand.getHeight();
1672                 isCrtRecordOnPage = true;
1673                 isCrtRecordOnColumn = true;
1674             }
1675             else
1676             {
1677                 //SummaryReport.16 test
1678             }
1679
1680             /*   */
1681             fillSummaryOverflow();
1682             
1683             //DONE
1684         }
1685     }
1686
1687
1688     /**
1689      *
1690      */

1691     @continuable
1692     private void fillSummaryWithLastFooterNoPageBands() throws JRException
1693     {
1694         if (
1695             !isSummaryNewPage
1696             && columnIndex == 0
1697             && summary.getBreakHeight() <= lastPageColumnFooterOffsetY - offsetY
1698             )
1699         {
1700             setLastPageFooter(true);
1701
1702             summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
1703
1704             if (summary.isToPrint())
1705             {
1706                 // deal with groupFooterPositionElementRange here because summary will attempt to use remaining space
1707                 if (groupFooterPositionElementRange != null)
1708                 {
1709                     ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
1710                     offsetY = columnFooterOffsetY;
1711                     // reset the element range here although it will not be checked anymore as the report ends
1712                     groupFooterPositionElementRange = null;
1713                 }
1714                 
1715                 summary.evaluate(JRExpression.EVALUATION_DEFAULT);
1716
1717                 JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
1718
1719                 if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
1720                 {
1721                     fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1722
1723                     fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1724
1725                     resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1726                     resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1727                     resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1728                     scriptlet.callBeforePageInit();
1729                     calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1730                     scriptlet.callAfterPageInit();
1731
1732                     addPage(false);
1733
1734                     printBand = 
1735                         summary.refill(
1736                             JRExpression.EVALUATION_DEFAULT, 
1737                             pageHeight - bottomMargin - offsetY
1738                             );
1739
1740                     fillBand(printBand);
1741                     offsetY += printBand.getHeight();
1742                     isCrtRecordOnPage = true;
1743                     isCrtRecordOnColumn = true;
1744                 }
1745                 else
1746                 {
1747                     //SummaryReport.1 test
1748                     
1749                     fillBand(printBand);
1750                     offsetY += printBand.getHeight();
1751                     isCrtRecordOnPage = true;
1752                     isCrtRecordOnColumn = true;
1753
1754                     fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1755
1756                     fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1757                 }
1758
1759                 /*   */
1760                 fillSummaryOverflow();
1761                 
1762                 //DONE
1763             }
1764             else
1765             {
1766                 //SummaryReport.2 test
1767                 
1768                 // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do;
1769
1770                 fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1771
1772                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1773                 
1774                 //DONE
1775             }
1776         }
1777         else if (
1778             !isSummaryNewPage
1779             && columnIndex == 0
1780             && summary.getBreakHeight() <= columnFooterOffsetY - offsetY
1781             )
1782         {
1783             summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
1784
1785             if (summary.isToPrint())
1786             {
1787                 // deal with groupFooterPositionElementRange here because summary will attempt to use remaining space
1788                 if (groupFooterPositionElementRange != null)
1789                 {
1790                     ElementRangeUtil.moveContent(groupFooterPositionElementRange, columnFooterOffsetY);
1791                     offsetY = columnFooterOffsetY;
1792                     // reset the element range here although it will not be checked anymore as the report ends
1793                     groupFooterPositionElementRange = null;
1794                 }
1795                 
1796                 summary.evaluate(JRExpression.EVALUATION_DEFAULT);
1797
1798                 JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
1799
1800                 if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
1801                 {
1802                     if (offsetY <= lastPageColumnFooterOffsetY)
1803                     {
1804                         setLastPageFooter(true);
1805
1806                         fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1807
1808                         fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1809
1810                         resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1811                         resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1812                         resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1813                         scriptlet.callBeforePageInit();
1814                         calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1815                         scriptlet.callAfterPageInit();
1816
1817                         addPage(false);
1818
1819                         printBand = 
1820                             summary.refill(
1821                                 JRExpression.EVALUATION_DEFAULT,
1822                                 pageHeight - bottomMargin - offsetY
1823                                 );
1824
1825                         fillBand(printBand);
1826                         offsetY += printBand.getHeight();
1827                         isCrtRecordOnPage = true;
1828                         isCrtRecordOnColumn = true;
1829                     }
1830                     else
1831                     {
1832                         fillPageBreak(false, JRExpression.EVALUATION_DEFAULT, JRExpression.EVALUATION_DEFAULT, false);
1833
1834                         setLastPageFooter(true);
1835
1836                         printBand = 
1837                             summary.refill(
1838                                 JRExpression.EVALUATION_DEFAULT,
1839                                 lastPageColumnFooterOffsetY - offsetY
1840                                 );
1841
1842                         fillBand(printBand);
1843                         offsetY += printBand.getHeight();
1844                         isCrtRecordOnPage = true;
1845                         isCrtRecordOnColumn = true;
1846
1847                         fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1848
1849                         fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1850                     }
1851                 }
1852                 else
1853                 {
1854                     //SummaryReport.3 test
1855                     
1856                     fillBand(printBand);
1857                     offsetY += printBand.getHeight();
1858                     isCrtRecordOnPage = true;
1859                     isCrtRecordOnColumn = true;
1860
1861                     fillPageBreak(false, JRExpression.EVALUATION_DEFAULT, JRExpression.EVALUATION_DEFAULT, false);
1862
1863                     setLastPageFooter(true);
1864
1865                     if (summary.willOverflow())
1866                     {
1867                         printBand = summary.fill(lastPageColumnFooterOffsetY - offsetY);
1868
1869                         fillBand(printBand);
1870                         offsetY += printBand.getHeight();
1871                         isCrtRecordOnPage = true;
1872                         isCrtRecordOnColumn = true;
1873                     }
1874
1875                     fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1876
1877                     fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1878                 }
1879
1880                 /*   */
1881                 fillSummaryOverflow();
1882                 
1883                 //DONE
1884             }
1885             else
1886             {
1887                 // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do;
1888                 // it will be either the one in fillPageBreak or the following
1889                 
1890                 if (offsetY > lastPageColumnFooterOffsetY)
1891                 {
1892                     //SummaryReport.5 test
1893                     fillPageBreak(false, JRExpression.EVALUATION_DEFAULT, JRExpression.EVALUATION_DEFAULT, false);
1894                 }
1895                 else
1896                 {
1897                     //SummaryReport.4 test
1898                 }
1899                 
1900                 setLastPageFooter(true);
1901
1902                 fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1903
1904                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1905                 
1906                 //DONE
1907             }
1908         }
1909         else if (columnIndex == 0 && offsetY <= lastPageColumnFooterOffsetY)
1910         {
1911             //SummaryReport.6 test
1912             
1913             // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do
1914
1915             setLastPageFooter(true);
1916
1917             fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1918
1919             fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1920
1921             summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
1922
1923             if (summary.isToPrint())
1924             {
1925                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1926                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1927                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1928                 scriptlet.callBeforePageInit();
1929                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1930                 scriptlet.callAfterPageInit();
1931
1932                 addPage(false);
1933
1934                 summary.evaluate(JRExpression.EVALUATION_DEFAULT);
1935
1936                 JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY);
1937
1938                 if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
1939                 {
1940                     resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
1941                     resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1942                     resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1943                     scriptlet.callBeforePageInit();
1944                     calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1945                     scriptlet.callAfterPageInit();
1946
1947                     addPage(false);
1948
1949                     printBand = 
1950                         summary.refill(
1951                             JRExpression.EVALUATION_DEFAULT,
1952                             pageHeight - bottomMargin - offsetY
1953                             );
1954                 }
1955
1956                 fillBand(printBand);
1957                 offsetY += printBand.getHeight();
1958                 isCrtRecordOnPage = true;
1959                 isCrtRecordOnColumn = true;
1960
1961                 /*   */
1962                 fillSummaryOverflow();
1963             }
1964             
1965             //DONE
1966         }
1967         else
1968         {
1969             //SummaryReport.7 test
1970             
1971             // do nothing about groupFooterPositionElementRange because the following fillColumnFooter will do;
1972
1973             fillColumnFooter(JRExpression.EVALUATION_DEFAULT);
1974
1975             fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1976
1977             resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
1978             resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
1979             resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
1980             scriptlet.callBeforePageInit();
1981             calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
1982             scriptlet.callAfterPageInit();
1983
1984             addPage(false);
1985
1986             fillPageHeader(JRExpression.EVALUATION_DEFAULT);
1987
1988             //fillColumnHeader(JRExpression.EVALUATION_DEFAULT);
1989
1990             setLastPageFooter(true);
1991
1992             if (isSummaryNewPage)
1993             {
1994                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
1995
1996                 summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
1997
1998                 if (summary.isToPrint())
1999                 {
2000                     resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
2001                     resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
2002                     resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
2003                     scriptlet.callBeforePageInit();
2004                     calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
2005                     scriptlet.callAfterPageInit();
2006
2007                     addPage(false);
2008
2009                     summary.evaluate(JRExpression.EVALUATION_DEFAULT);
2010
2011                     JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY);
2012
2013                     if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
2014                     {
2015                         resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
2016                         resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
2017                         resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
2018                         scriptlet.callBeforePageInit();
2019                         calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
2020                         scriptlet.callAfterPageInit();
2021
2022                         addPage(false);
2023
2024                         printBand = 
2025                             summary.refill(
2026                                 JRExpression.EVALUATION_DEFAULT,
2027                                 pageHeight - bottomMargin - offsetY
2028                                 );
2029                     }
2030
2031                     fillBand(printBand);
2032                     offsetY += printBand.getHeight();
2033                     isCrtRecordOnPage = true;
2034                     isCrtRecordOnColumn = true;
2035
2036                     /*   */
2037                     fillSummaryOverflow();
2038                 }
2039                 
2040                 //DONE
2041             }
2042             else
2043             {
2044                 summary.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
2045
2046                 if (summary.isToPrint())
2047                 {
2048                     summary.evaluate(JRExpression.EVALUATION_DEFAULT);
2049
2050                     JRPrintBand printBand = summary.fill(columnFooterOffsetY - offsetY);
2051
2052                     if (summary.willOverflow() && summary.isSplitPrevented() && !summary.isSplitTypePreventInhibited())
2053                     {
2054                         fillPageFooter(JRExpression.EVALUATION_DEFAULT);
2055
2056                         resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
2057                         resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
2058                         resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
2059                         scriptlet.callBeforePageInit();
2060                         calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
2061                         scriptlet.callAfterPageInit();
2062
2063                         addPage(false);
2064
2065                         printBand = 
2066                             summary.refill(
2067                                 JRExpression.EVALUATION_DEFAULT,
2068                                 pageHeight - bottomMargin - offsetY
2069                                 );
2070
2071                         fillBand(printBand);
2072                         offsetY += printBand.getHeight();
2073                         isCrtRecordOnPage = true;
2074                         isCrtRecordOnColumn = true;
2075                     }
2076                     else
2077                     {
2078                         fillBand(printBand);
2079                         offsetY += printBand.getHeight();
2080                         isCrtRecordOnPage = true;
2081                         isCrtRecordOnColumn = true;
2082
2083                         fillPageFooter(JRExpression.EVALUATION_DEFAULT);
2084                     }
2085
2086                     /*   */
2087                     fillSummaryOverflow();
2088                 }
2089                 else
2090                 {
2091                     fillPageFooter(JRExpression.EVALUATION_DEFAULT);
2092                 }
2093                 
2094                 //DONE
2095             }
2096         }
2097     }
2098
2099
2100     /**
2101      *
2102      */

2103     @continuable
2104     private void fillSummaryOverflow() throws JRException
2105     {
2106         while (summary.willOverflow())
2107         {
2108             if (isSummaryWithPageHeaderAndFooter)
2109             {
2110                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
2111             }
2112             
2113             resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
2114             resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
2115             resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
2116             scriptlet.callBeforePageInit();
2117             calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
2118             scriptlet.callAfterPageInit();
2119
2120             addPage(false);
2121
2122             if (isSummaryWithPageHeaderAndFooter)
2123             {
2124                 fillPageHeader(JRExpression.EVALUATION_DEFAULT);
2125             }
2126             
2127             JRPrintBand printBand = summary.fill(pageHeight - bottomMargin - offsetY - (isSummaryWithPageHeaderAndFooter?pageFooter.getHeight():0));
2128
2129             fillBand(printBand);
2130             offsetY += printBand.getHeight();
2131             isCrtRecordOnPage = true;
2132             isCrtRecordOnColumn = true;
2133         }
2134
2135         resolveBandBoundElements(summary, JRExpression.EVALUATION_DEFAULT);
2136
2137         if (isSummaryWithPageHeaderAndFooter)
2138         {
2139             if (offsetY > pageHeight - bottomMargin - lastPageFooter.getHeight())
2140             {
2141                 fillPageFooter(JRExpression.EVALUATION_DEFAULT);
2142                 
2143                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, true);
2144                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
2145                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
2146                 scriptlet.callBeforePageInit();
2147                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
2148                 scriptlet.callAfterPageInit();
2149
2150                 addPage(false);
2151
2152                 fillPageHeader(JRExpression.EVALUATION_DEFAULT);
2153             }
2154             
2155             if (lastPageFooter != missingFillBand)
2156             {
2157                 setLastPageFooter(true);
2158             }
2159             
2160             fillPageFooter(JRExpression.EVALUATION_DEFAULT);
2161         }
2162     }
2163
2164
2165     /**
2166      *
2167      */

2168     private void fillBackground() throws JRException
2169     {
2170         if (log.isDebugEnabled() && !background.isEmpty())
2171         {
2172             log.debug("Fill " + fillerId + ": background at " + offsetY);
2173         }
2174
2175         //offsetX = leftMargin;
2176
2177         //if (!isSubreport)
2178         //{
2179         //    offsetY = pageHeight - pageFooter.getHeight() - bottomMargin;
2180         //}
2181
2182         if (background.getHeight() <= pageHeight - bottomMargin - offsetY)
2183         {
2184             background.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
2185
2186             if (background.isToPrint())
2187             {
2188                 background.evaluate(JRExpression.EVALUATION_DEFAULT);
2189
2190                 JRPrintBand printBand = background.fill(pageHeight - bottomMargin - offsetY);
2191
2192                 fillBand(printBand);
2193                 //offsetY += printBand.getHeight();
2194                 isCrtRecordOnPage = true;
2195                 isCrtRecordOnColumn = true;
2196                 
2197                 //FIXMENOW does not have resolveBandBoundElements
2198             }
2199         }
2200     }
2201
2202
2203     /**
2204      *
2205      */

2206     @continuable
2207     private void addPage(boolean isResetPageNumber) throws JRException
2208     {
2209         if (isSubreport())
2210         {
2211             addPageToParent(false);
2212         }
2213         
2214         if (printPage != null)
2215         {
2216             recordUsedPageHeight(offsetY + bottomMargin);
2217         }
2218
2219         printPage = newPage();
2220         printPageContentsWidth = 0;
2221
2222         JRFillVariable pageNumberVar = calculator.getPageNumber();
2223         if (isResetPageNumber)
2224         {
2225             pageNumberVar.setValue(1);
2226         }
2227         else
2228         {
2229             pageNumberVar.setValue(
2230                 ((Number)pageNumberVar.getValue()).intValue() + 1
2231                 );
2232         }
2233         pageNumberVar.setOldValue(pageNumberVar.getValue());
2234
2235         addPage(printPage);
2236
2237         setFirstColumn();
2238         offsetY = topMargin;
2239         isFirstPageBand = true;
2240         isFirstColumnBand = true;
2241         isCrtRecordOnPage = false;
2242         isCrtRecordOnColumn = false;
2243
2244         fillBackground();
2245     }
2246
2247     private void setFirstColumn()
2248     {
2249         columnIndex = 0;
2250         offsetX = leftMargin;
2251         setColumnNumberVar();
2252     }
2253
2254     private void setColumnNumberVar()
2255     {
2256         JRFillVariable columnNumber = calculator.getColumnNumber();
2257         columnNumber.setValue(columnIndex + 1);
2258         columnNumber.setOldValue(columnNumber.getValue());
2259     }
2260
2261     /**
2262      *
2263      */

2264     @continuable
2265     private void fillPageBreak(
2266         boolean isResetPageNumber,
2267         byte evalPrevPage,
2268         byte evalNextPage,
2269         boolean isReprintGroupHeaders
2270         ) throws JRException
2271     {
2272         if (isCreatingNewPage)
2273         {
2274             throw 
2275                 new JRException(
2276                     EXCEPTION_MESSAGE_KEY_INFINITE_LOOP_CREATING_NEW_PAGE,  
2277                     (Object[])null 
2278                     );
2279         }
2280
2281         if (groups != null)
2282         {
2283             for (JRFillGroup group : groups)
2284             {
2285                 if (group.getKeepTogetherElementRange() != null)
2286                 {
2287                     group.getKeepTogetherElementRange().expand(offsetY);
2288                 }
2289             }
2290         }
2291         
2292         FooterPositionEnum groupFooterPositionForOverflow = null;
2293         if (groupFooterPositionElementRange != null)
2294         {
2295             groupFooterPositionForOverflow = groupFooterPositionElementRange.getCurrentFooterPosition();
2296             // we are during group footers filling, otherwise this element range would have been null;
2297             // adding the content of the group footer band that is currently breaking
2298             groupFooterPositionElementRange.getElementRange().expand(offsetY);
2299         }
2300
2301         if (orphanGroupFooterElementRange != null)
2302         {
2303             // we are during a group footer filling and footers already started to print,
2304             // so the current expansion applies to the group footer element range, not the detail element range
2305             orphanGroupFooterElementRange.expand(offsetY);
2306         }
2307         else if (orphanGroupFooterDetailElementRange != null)
2308         {
2309             // we are during a group footer filling, but footers did not yet start to print,
2310             // so the current expansion applies to the detail element range
2311             orphanGroupFooterDetailElementRange.expand(offsetY);
2312         }
2313         
2314         isCreatingNewPage = true;
2315
2316         fillColumnFooter(evalPrevPage);
2317
2318         fillPageFooter(evalPrevPage);
2319
2320         resolveGroupBoundElements(evalPrevPage, false);
2321         resolveColumnBoundElements(evalPrevPage);
2322         resolvePageBoundElements(evalPrevPage);
2323         scriptlet.callBeforePageInit();
2324         calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
2325         scriptlet.callAfterPageInit();
2326         
2327         JRFillGroup keepTogetherGroup = getKeepTogetherGroup();
2328         
2329         ElementRange elementRangeToMove = null;
2330         ElementRange elementRangeToMove2 = null// we don't have more than two possible element ranges to move; at least for now
2331         if (keepTogetherGroup != null)
2332         {
2333             elementRangeToMove = keepTogetherGroup.getKeepTogetherElementRange();
2334         }
2335         else if (orphanGroupFooterDetailElementRange != null)
2336         {
2337             elementRangeToMove = orphanGroupFooterDetailElementRange;
2338             elementRangeToMove2 = orphanGroupFooterElementRange;
2339         }
2340
2341         if (floatColumnFooterElementRange != null && elementRangeToMove != null)
2342         {
2343             ElementRangeUtil.moveContent(floatColumnFooterElementRange, elementRangeToMove.getTopY());
2344         }
2345
2346         // remove second range first, otherwise element indexes would become out of range
2347         ElementRangeContents elementsToMove2 = null;
2348         if (elementRangeToMove2 != null)
2349         {
2350             elementsToMove2 = ElementRangeUtil.removeContent(elementRangeToMove2, delayedActions);
2351         }
2352         ElementRangeContents elementsToMove = null;
2353         if (elementRangeToMove != null)
2354         {
2355             elementsToMove = ElementRangeUtil.removeContent(elementRangeToMove, delayedActions);
2356         }
2357
2358         addPage(isResetPageNumber);
2359
2360         fillPageHeader(evalNextPage);
2361
2362         fillColumnHeader(evalNextPage);
2363
2364         if (isReprintGroupHeaders)
2365         {
2366             fillGroupHeadersReprint(evalNextPage, true);
2367
2368             ElementRange keepTogetherElementRange = keepTogetherGroup == null ? null : keepTogetherGroup.getKeepTogetherElementRange();
2369             
2370             if (
2371                 keepTogetherElementRange != null
2372                 && offsetY > keepTogetherElementRange.getTopY()
2373                 )
2374             {
2375                 throw new JRException(EXCEPTION_MESSAGE_KEY_KEEP_TOGETHER_CONTENT_DOES_NOT_FIT, (Object[]) null);
2376             }
2377         }
2378
2379         // reseting all movable element ranges
2380         orphanGroupFooterDetailElementRange = null;
2381         orphanGroupFooterElementRange = null;
2382         detailElementRange = null;
2383         if (keepTogetherGroup != null)
2384         {
2385             keepTogetherGroup.setKeepTogetherElementRange(null);
2386         }
2387
2388         if (elementRangeToMove != null)
2389         {
2390             ElementRangeUtil.addContent(
2391                 printPage, 
2392                 currentPageIndex(),
2393                 elementsToMove,
2394                 //regardless whether there was page break or column  break, the X offset needs to account for columnIndex difference
2395                 (columnIndex - elementRangeToMove.getColumnIndex()) * (columnSpacing + columnWidth),
2396                 offsetY - elementRangeToMove.getTopY(),
2397                 delayedActions
2398                 );
2399
2400             offsetY = offsetY + elementRangeToMove.getBottomY() - elementRangeToMove.getTopY();
2401             
2402             if (elementRangeToMove2 != null)
2403             {
2404                 ElementRangeUtil.addContent( 
2405                     printPage, 
2406                     currentPageIndex(),
2407                     elementsToMove2,
2408                     //regardless whether there was page break or column  break, the X offset needs to account for columnIndex difference
2409                     (columnIndex - elementRangeToMove2.getColumnIndex()) * (columnSpacing + columnWidth),
2410                     offsetY - elementRangeToMove2.getTopY(),
2411                     delayedActions
2412                     );
2413
2414                 offsetY = offsetY + elementRangeToMove2.getBottomY() - elementRangeToMove2.getTopY();
2415             }
2416             
2417             isFirstPageBand = false;
2418             isFirstColumnBand = false;
2419         } 
2420         else if (
2421             groupFooterPositionForOverflow != null
2422             && groupFooterPositionForOverflow != FooterPositionEnum.NORMAL
2423             )
2424         {
2425             // here we are during a group footer filling that broke over onto a new page;
2426             // recreating the group footer element range for the overflow content of the band
2427             groupFooterPositionElementRange = 
2428                 new SimpleGroupFooterElementRange(
2429                     new SimpleElementRange(getCurrentPage(), columnIndex, offsetY), 
2430                     groupFooterPositionForOverflow
2431                     );
2432         }
2433
2434         isCreatingNewPage = false;
2435     }
2436
2437
2438     /**
2439      *
2440      */

2441     @continuable
2442     private void fillColumnBreak(
2443         byte evalPrevPage,
2444         byte evalNextPage
2445         ) throws JRException
2446     {
2447         if (columnIndex == columnCount - 1)
2448         {
2449             fillPageBreak(false, evalPrevPage, evalNextPage, true);
2450         }
2451         else
2452         {
2453             if (groups != null)
2454             {
2455                 for (JRFillGroup group : groups)
2456                 {
2457                     if (group.getKeepTogetherElementRange() != null)
2458                     {
2459                         group.getKeepTogetherElementRange().expand(offsetY);
2460                     }
2461                 }
2462             }
2463             
2464             FooterPositionEnum groupFooterPositionForOverflow = null;
2465             if (groupFooterPositionElementRange != null)
2466             {
2467                 groupFooterPositionForOverflow = groupFooterPositionElementRange.getCurrentFooterPosition();
2468                 // we are during group footers filling, otherwise this element range would have been null;
2469                 // adding the content of the group footer band that is currently breaking
2470                 groupFooterPositionElementRange.getElementRange().expand(offsetY);
2471             }
2472             
2473             if (orphanGroupFooterElementRange != null)
2474             {
2475                 // we are during a group footer filling and footers already started to print,
2476                 // so the current expansion applies to the group footer element range, not the detail element range
2477                 orphanGroupFooterElementRange.expand(offsetY);
2478             }
2479             else if (orphanGroupFooterDetailElementRange != null)
2480             {
2481                 // we are during a group footer filling, but footers did not yet start to print,
2482                 // so the current expansion applies to the detail element range
2483                 orphanGroupFooterDetailElementRange.expand(offsetY);
2484             }
2485             
2486             fillColumnFooter(evalPrevPage);
2487
2488             resolveGroupBoundElements(evalPrevPage, false);
2489             resolveColumnBoundElements(evalPrevPage);
2490             scriptlet.callBeforeColumnInit();
2491             calculator.initializeVariables(ResetTypeEnum.COLUMN, IncrementTypeEnum.COLUMN);
2492             scriptlet.callAfterColumnInit();
2493
2494             JRFillGroup keepTogetherGroup = getKeepTogetherGroup();
2495
2496             ElementRange elementRangeToMove = null;
2497             ElementRange elementRangeToMove2 = null// we don't have more than two possible element ranges to move; at least for now
2498             if (keepTogetherGroup != null)
2499             {
2500                 elementRangeToMove = keepTogetherGroup.getKeepTogetherElementRange();
2501             }
2502             else if (orphanGroupFooterDetailElementRange != null)
2503             {
2504                 elementRangeToMove = orphanGroupFooterDetailElementRange;
2505                 elementRangeToMove2 = orphanGroupFooterElementRange;
2506             }
2507             
2508             if (floatColumnFooterElementRange != null && elementRangeToMove != null)
2509             {
2510                 ElementRangeUtil.moveContent(floatColumnFooterElementRange, elementRangeToMove.getTopY());
2511             }
2512             
2513             // remove second range first, otherwise element indexes would become out of range
2514             ElementRangeContents elementsToMove2 = null;
2515             if (elementRangeToMove2 != null)
2516             {
2517                 elementsToMove2 = ElementRangeUtil.removeContent(elementRangeToMove2, delayedActions);
2518             }
2519             ElementRangeContents elementsToMove = null;
2520             if (elementRangeToMove != null)
2521             {
2522                 elementsToMove = ElementRangeUtil.removeContent(elementRangeToMove, null);
2523             }
2524
2525             columnIndex += 1;
2526             setOffsetX();
2527             offsetY = columnHeaderOffsetY;
2528             isCrtRecordOnColumn = false;
2529
2530             setColumnNumberVar();
2531
2532             fillColumnHeader(evalNextPage);
2533
2534             //if (isReprintGroupHeaders)
2535             {
2536                 fillGroupHeadersReprint(evalNextPage, false);
2537
2538                 ElementRange keepTogetherElementRange = keepTogetherGroup == null ? null : keepTogetherGroup.getKeepTogetherElementRange();
2539                 
2540                 if (
2541                     keepTogetherElementRange != null
2542                     && offsetY > keepTogetherElementRange.getTopY()
2543                     )
2544                 {
2545                     throw new JRException(EXCEPTION_MESSAGE_KEY_KEEP_TOGETHER_CONTENT_DOES_NOT_FIT, (Object[]) null);
2546                 }
2547             }
2548
2549             // reseting all movable element ranges
2550             orphanGroupFooterDetailElementRange = null;
2551             orphanGroupFooterElementRange = null;
2552             detailElementRange = null;
2553             if (keepTogetherGroup != null)
2554             {
2555                 keepTogetherGroup.setKeepTogetherElementRange(null);
2556             }
2557
2558             if (elementRangeToMove != null)
2559             {
2560                 ElementRangeUtil.addContent(
2561                     printPage, 
2562                     currentPageIndex(),
2563                     elementsToMove,
2564                     //regardless whether there was page break or column  break, the X offset needs to account for columnIndex difference
2565                     (columnIndex - elementRangeToMove.getColumnIndex()) * (columnSpacing + columnWidth),
2566                     offsetY - elementRangeToMove.getTopY(),
2567                     delayedActions
2568                     );
2569
2570                 offsetY = offsetY + elementRangeToMove.getBottomY() - elementRangeToMove.getTopY();
2571                 
2572                 if (elementRangeToMove2 != null)
2573                 {
2574                     ElementRangeUtil.addContent( 
2575                         printPage, 
2576                         currentPageIndex(),
2577                         elementsToMove2,
2578                         //regardless whether there was page break or column  break, the X offset needs to account for columnIndex difference
2579                         (columnIndex - elementRangeToMove2.getColumnIndex()) * (columnSpacing + columnWidth),
2580                         offsetY - elementRangeToMove2.getTopY(),
2581                         delayedActions
2582                         );
2583
2584                     offsetY = offsetY + elementRangeToMove2.getBottomY() - elementRangeToMove2.getTopY();
2585                 }
2586                 
2587                 isFirstPageBand = false;
2588                 isFirstColumnBand = false;
2589             }
2590             else if (
2591                 groupFooterPositionForOverflow != null
2592                 && groupFooterPositionForOverflow != FooterPositionEnum.NORMAL
2593                 )
2594             {
2595                 // here we are during a group footer filling that broke over onto a new column;
2596                 // recreating the group footer element range for the overflow content of the band
2597                 groupFooterPositionElementRange = 
2598                     new SimpleGroupFooterElementRange(
2599                         new SimpleElementRange(getCurrentPage(), columnIndex, offsetY), 
2600                         groupFooterPositionForOverflow
2601                         );
2602             }
2603         }
2604     }
2605
2606
2607     /**
2608      *
2609      */

2610     @continuable
2611     protected void fillColumnBand(JRFillBand band, byte evaluation, boolean recalculateVariables) throws JRException
2612     {
2613         band.evaluate(evaluation);
2614
2615         JRPrintBand printBand = band.fill(columnFooterOffsetY - offsetY);
2616
2617         if (band.willOverflow())
2618         {
2619             boolean toRefill = band.isSplitPrevented() && !band.isSplitTypePreventInhibited();
2620             
2621             if (!toRefill)
2622             {
2623                 if (groups != null)
2624                 {
2625                     // this works even for group headers and footers, not only detail,
2626                     // because outer groups keep together is honored, while for the
2627                     // inner keep together groups, the element range would be null 
2628                     // in-between parent group breaks
2629                     for (JRFillGroup group : groups)
2630                     {
2631                         if (
2632                             group.getKeepTogetherElementRange() != null
2633                             && (group.isKeepTogether() || !group.hasMinDetails())
2634                             )
2635                         {
2636                             toRefill = true;
2637                             break;
2638                         }
2639                     }
2640                 }
2641             }
2642             
2643             if (!toRefill)
2644             {
2645                 if (orphanGroupFooterDetailElementRange != null)
2646                 {
2647                     toRefill = true;
2648                 }
2649             }
2650             
2651             if (toRefill)
2652             {
2653                 fillColumnBreak(
2654                     evaluation == JRExpression.EVALUATION_DEFAULT 
2655                         ? (isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD) 
2656                         : evaluation, 
2657                     evaluation
2658                     );
2659
2660                 if (recalculateVariables)
2661                 {
2662                     @SuppressWarnings("deprecation")
2663                     boolean isLegacyBandEvaluationEnabled = getFillContext().isLegacyBandEvaluationEnabled(); 
2664                     if (!isLegacyBandEvaluationEnabled)
2665                     {
2666                         mainDataset.revertVariablesToOldValues();
2667                         
2668                         calculator.recalculateVariables();
2669                     }
2670                 }
2671                 
2672                 printBand = band.refill(evaluation, columnFooterOffsetY - offsetY);
2673             }
2674         }
2675
2676         fillBand(printBand);
2677         offsetY += printBand.getHeight();
2678         isCrtRecordOnPage = evaluation == JRExpression.EVALUATION_DEFAULT;
2679         isCrtRecordOnColumn = isCrtRecordOnPage;
2680         
2681         while (band.willOverflow())
2682         {
2683             // this overflow here is special in the sense that it is the overflow of a detail band or group header or footer,
2684             // which are the only bands that are involved with movable element ranges such as keep together, footer position or orphan footer;
2685             // it is also special in the sense that it is an overflow after the band actually generated some content on the current page/column
2686             // and is not an early overflow like the one occurring when the band does not fit with its declared height or is non-splitting band;
2687             // having said that, it is OK to be more specific about the type of overflow here and only deal with non-white-space overflows of the band,
2688             // as they are the only ones which actually need to introduce a page/column break and continue rendering their remaining elements;
2689             // white space band overflows do not render anything on the next page/column and don't even preserve their remaining white space (historical behavior);
2690             // avoiding a page/column break here in case of white space overflows helps with preserving the detail element range, which would
2691             // thus be moved onto the new page/column as a non-breaking detail, if orphan footers follow; 
2692             // a page/column break here would cause the existing detail element range to be discarded (lost on subsequent element range expand),
2693             // and thus it would not be moved in case orphan footer follows, 
2694             // even if nothing gets rendered by this detail on the next page/column 
2695             if (band.willOverflowWithElements())
2696             {
2697                 fillColumnBreak(
2698                     evaluation == JRExpression.EVALUATION_DEFAULT 
2699                         ? (isCrtRecordOnColumn ? JRExpression.EVALUATION_DEFAULT : JRExpression.EVALUATION_OLD) 
2700                         : evaluation, 
2701                     evaluation
2702                     );
2703             }
2704
2705             // we continue filling band overflow normally, because even in case of white space band overflow, nothing gets actually rendered
2706             // and the offsetY remains unchanged;
2707             // but we need to do this because the isOverflow flag would eventually be set to false and thus the current band rendering would end,
2708             // bringing the band into a state ready for the next filling
2709             printBand = band.fill(columnFooterOffsetY - offsetY);
2710
2711             fillBand(printBand);
2712             offsetY += printBand.getHeight();
2713             isCrtRecordOnPage = evaluation == JRExpression.EVALUATION_DEFAULT;
2714             isCrtRecordOnColumn = isCrtRecordOnPage;
2715         }
2716
2717         resolveBandBoundElements(band, evaluation);
2718     }
2719
2720
2721     /**
2722      *
2723      */

2724     protected void fillFixedBand(JRFillBand band, byte evaluation) throws JRException
2725     {
2726         band.evaluate(evaluation);
2727
2728         JRPrintBand printBand = band.fill();
2729
2730         fillBand(printBand);
2731         offsetY += printBand.getHeight();
2732         isCrtRecordOnPage = evaluation == JRExpression.EVALUATION_DEFAULT;
2733         isCrtRecordOnColumn = isCrtRecordOnPage;
2734
2735         resolveBandBoundElements(band, evaluation);
2736     }
2737
2738
2739     /**
2740      *
2741      */

2742     private void setNewPageColumnInBands()
2743     {
2744         title.setNewPageColumn(true);
2745         pageHeader.setNewPageColumn(true);
2746         columnHeader.setNewPageColumn(true);
2747         detailSection.setNewPageColumn(true);
2748         columnFooter.setNewPageColumn(true);
2749         pageFooter.setNewPageColumn(true);
2750         lastPageFooter.setNewPageColumn(true);
2751         summary.setNewPageColumn(true);
2752         noData.setNewPageColumn(true);
2753
2754         if (groups != null && groups.length > 0)
2755         {
2756             for(int i = 0; i < groups.length; i++)
2757             {
2758                 ((JRFillSection)groups[i].getGroupHeaderSection()).setNewPageColumn(true);
2759                 ((JRFillSection)groups[i].getGroupFooterSection()).setNewPageColumn(true);
2760             }
2761         }
2762     }
2763
2764
2765     /**
2766      *
2767      */

2768     private void setNewGroupInBands(JRGroup group)
2769     {
2770         title.setNewGroup(group, true);
2771         pageHeader.setNewGroup(group, true);
2772         columnHeader.setNewGroup(group, true);
2773         detailSection.setNewGroup(group, true);
2774         columnFooter.setNewGroup(group, true);
2775         pageFooter.setNewGroup(group, true);
2776         lastPageFooter.setNewGroup(group, true);
2777         summary.setNewGroup(group, true);
2778         noData.setNewGroup(group, true);
2779
2780         if (groups != null && groups.length > 0)
2781         {
2782             for(int i = 0; i < groups.length; i++)
2783             {
2784                 ((JRFillSection)groups[i].getGroupHeaderSection()).setNewGroup(group, true);
2785                 ((JRFillSection)groups[i].getGroupFooterSection()).setNewGroup(group, true);
2786             }
2787         }
2788     }
2789
2790
2791     /**
2792      *
2793      */

2794     private JRFillBand getCurrentPageFooter()
2795     {
2796         return isLastPageFooter ? lastPageFooter : pageFooter;
2797     }
2798
2799
2800     /**
2801      *
2802      */

2803     private void setLastPageFooter(boolean isLastPageFooter)
2804     {
2805         this.isLastPageFooter = isLastPageFooter;
2806
2807         if (isLastPageFooter)
2808         {
2809             columnFooterOffsetY = lastPageColumnFooterOffsetY;
2810         }
2811     }
2812
2813     
2814     /**
2815      *
2816      */

2817     @continuable
2818     private void fillNoData() throws JRException
2819     {
2820         if (log.isDebugEnabled() && !noData.isEmpty())
2821         {
2822             log.debug("Fill " + fillerId + ": noData at " + offsetY);
2823         }
2824
2825         noData.evaluatePrintWhenExpression(JRExpression.EVALUATION_DEFAULT);
2826
2827         if (noData.isToPrint())
2828         {
2829             while (noData.getBreakHeight() > pageHeight - bottomMargin - offsetY)
2830             {
2831                 addPage(false);
2832             }
2833
2834             noData.evaluate(JRExpression.EVALUATION_DEFAULT);
2835
2836             JRPrintBand printBand = noData.fill(pageHeight - bottomMargin - offsetY);
2837
2838             if (noData.willOverflow() && noData.isSplitPrevented() && !noData.isSplitTypePreventInhibited())
2839             {
2840                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
2841                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
2842                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
2843                 scriptlet.callBeforePageInit();
2844                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
2845                 scriptlet.callAfterPageInit();
2846                 
2847                 addPage(false);
2848                 
2849                 printBand = 
2850                     noData.refill(
2851                         JRExpression.EVALUATION_DEFAULT,
2852                         pageHeight - bottomMargin - offsetY
2853                         );
2854             }
2855
2856             fillBand(printBand);
2857             offsetY += printBand.getHeight();
2858             isCrtRecordOnPage = true;
2859             isCrtRecordOnColumn = true;
2860
2861             while (noData.willOverflow())
2862             {
2863                 resolveGroupBoundElements(JRExpression.EVALUATION_DEFAULT, false);
2864                 resolveColumnBoundElements(JRExpression.EVALUATION_DEFAULT);
2865                 resolvePageBoundElements(JRExpression.EVALUATION_DEFAULT);
2866                 scriptlet.callBeforePageInit();
2867                 calculator.initializeVariables(ResetTypeEnum.PAGE, IncrementTypeEnum.PAGE);
2868                 scriptlet.callAfterPageInit();
2869                 
2870                 addPage(false);
2871                 
2872                 printBand = noData.fill(pageHeight - bottomMargin - offsetY);
2873                 
2874                 fillBand(printBand);
2875                 offsetY += printBand.getHeight();
2876                 isCrtRecordOnPage = true;
2877                 isCrtRecordOnColumn = true;
2878             }
2879
2880             resolveBandBoundElements(noData, JRExpression.EVALUATION_DEFAULT);
2881         }
2882     }
2883
2884     
2885     /**
2886      *
2887      */

2888     private void setOffsetX()
2889     {
2890         if (columnDirection == RunDirectionEnum.RTL)
2891         {
2892             offsetX = pageWidth - rightMargin - columnWidth - columnIndex * (columnSpacing + columnWidth);
2893         }
2894         else
2895         {
2896             offsetX = leftMargin + columnIndex * (columnSpacing + columnWidth);
2897         }
2898     }
2899
2900     
2901 }
2902