KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jasperreports > engine > fill > JRFillElementContainer


1 /*
2  * ============================================================================
3  * GNU Lesser General Public License
4  * ============================================================================
5  *
6  * JasperReports - Free Java report-generating library.
7  * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * JasperSoft Corporation
24  * 303 Second Street, Suite 450 North
25  * San Francisco, CA 94107
26  * http://www.jaspersoft.com
27  */

28 package net.sf.jasperreports.engine.fill;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.Collections JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.HashSet JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.Set JavaDoc;
39
40 import net.sf.jasperreports.engine.JRConditionalStyle;
41 import net.sf.jasperreports.engine.JRElement;
42 import net.sf.jasperreports.engine.JRElementGroup;
43 import net.sf.jasperreports.engine.JRException;
44 import net.sf.jasperreports.engine.JRFrame;
45 import net.sf.jasperreports.engine.JRPrintElement;
46 import net.sf.jasperreports.engine.JRPrintElementContainer;
47 import net.sf.jasperreports.engine.JRReportFont;
48 import net.sf.jasperreports.engine.JRStyle;
49 import net.sf.jasperreports.engine.base.JRBaseStyle;
50 import net.sf.jasperreports.engine.util.JRStyleResolver;
51
52 /**
53  * Abstract implementation of an element container filler.
54  * <p>
55  * This is the base for band, frame and crosstab cell fillers.
56  *
57  * @author Lucian Chirita (lucianc@users.sourceforge.net)
58  * @version $Id: JRFillElementContainer.java 1502 2006-11-21 18:14:56 +0200 (Tue, 21 Nov 2006) teodord $
59  */

60 public abstract class JRFillElementContainer extends JRFillElementGroup
61 {
62     protected JRBaseFiller filler;
63     
64     private JRFillElement[] ySortedElements = null;
65     private JRFillElement[] stretchElements = null;
66     private JRFillElement[] bandBottomElements = null;
67     private JRFillElement[] removableElements = null;
68     
69     private boolean willOverflow = false;
70     protected boolean isOverflow = false;
71     
72     private int stretchHeight = 0;
73     private int firstY = 0;
74     protected JRFillElement firstYElement = null;
75     
76     protected final JRFillExpressionEvaluator expressionEvaluator;
77     
78     protected JRFillElement[] deepElements;
79
80     /**
81      *
82      */

83     protected Set JavaDoc stylesToEvaluate = new HashSet JavaDoc();
84     protected Map JavaDoc evaluatedStyles = new HashMap JavaDoc();
85     
86     protected boolean hasPrintWhenOverflowElement;
87     
88     protected JRFillElementContainer(JRBaseFiller filler, JRElementGroup container, JRFillObjectFactory factory)
89     {
90         super(container, factory);
91         
92         expressionEvaluator = factory.getExpressionEvaluator();
93         initDeepElements();
94         
95         this.filler = filler;
96     }
97     
98     protected JRFillElementContainer(JRFillElementContainer container, JRFillCloneFactory factory)
99     {
100         super(container, factory);
101         
102         expressionEvaluator = container.expressionEvaluator;
103         initDeepElements();
104         
105         this.filler = container.filler;
106     }
107
108
109     private void initDeepElements()
110     {
111         if (elements == null)
112         {
113             deepElements = new JRFillElement[0];
114         }
115         else
116         {
117             List JavaDoc deepElementsList = new ArrayList JavaDoc(elements.length);
118             collectDeepElements(elements, deepElementsList);
119             deepElements = new JRFillElement[deepElementsList.size()];
120             deepElementsList.toArray(deepElements);
121         }
122     }
123
124     private static void collectDeepElements(JRElement[] elements, List JavaDoc deepElementsList)
125     {
126         for (int i = 0; i < elements.length; i++)
127         {
128             JRElement element = elements[i];
129             deepElementsList.add(element);
130             
131             if (element instanceof JRFillFrame)
132             {
133                 JRFrame frame = (JRFrame) element;
134                 collectDeepElements(frame.getElements(), deepElementsList);
135             }
136         }
137     }
138
139     protected final void initElements()
140     {
141         hasPrintWhenOverflowElement = false;
142         
143         if (elements != null && elements.length > 0)
144         {
145             List JavaDoc sortedElemsList = new ArrayList JavaDoc();
146             List JavaDoc stretchElemsList = new ArrayList JavaDoc();
147             List JavaDoc bandBottomElemsList = new ArrayList JavaDoc();
148             List JavaDoc removableElemsList = new ArrayList JavaDoc();
149             for(int i = 0; i < elements.length; i++)
150             {
151                 JRFillElement element = elements[i];
152                 sortedElemsList.add(element);
153                 
154                 if (element.getPositionType() == JRElement.POSITION_TYPE_FIX_RELATIVE_TO_BOTTOM)
155                 {
156                     bandBottomElemsList.add(element);
157                 }
158
159                 if (element.getStretchType() != JRElement.STRETCH_TYPE_NO_STRETCH)
160                 {
161                     stretchElemsList.add(element);
162                 }
163                 
164                 if (element.isRemoveLineWhenBlank())
165                 {
166                     removableElemsList.add(element);
167                 }
168                 
169                 if (element.isPrintWhenDetailOverflows())
170                 {
171                     hasPrintWhenOverflowElement = true;
172                 }
173             }
174
175             /* */
176             Collections.sort(sortedElemsList, new JRYComparator());
177             ySortedElements = new JRFillElement[elements.length];
178             sortedElemsList.toArray(ySortedElements);
179
180             /* */
181             stretchElements = new JRFillElement[stretchElemsList.size()];
182             stretchElemsList.toArray(stretchElements);
183
184             /* */
185             bandBottomElements = new JRFillElement[bandBottomElemsList.size()];
186             bandBottomElemsList.toArray(bandBottomElements);
187
188             /* */
189             removableElements = new JRFillElement[removableElemsList.size()];
190             removableElemsList.toArray(removableElements);
191         }
192         
193         /* */
194         setDependentElements();
195         
196         setElementsBandBottomY();
197     }
198
199     protected final void setElementsBandBottomY()
200     {
201         if (elements != null && elements.length > 0)
202         {
203             for(int i = 0; i < elements.length; i++)
204             {
205                 elements[i].setBandBottomY(
206                     getContainerHeight() - elements[i].getY() - elements[i].getHeight()
207                     );
208             }
209         }
210     }
211
212     /**
213      *
214      */

215     private void setDependentElements()
216     {
217         if (ySortedElements != null && ySortedElements.length > 0)
218         {
219             for(int i = 0; i < ySortedElements.length - 1; i++)
220             {
221                 JRFillElement iElem = ySortedElements[i];
222                 boolean isBreakElem = iElem instanceof JRFillBreak;
223
224                 for(int j = i + 1; j < ySortedElements.length; j++)
225                 {
226                     JRFillElement jElem = ySortedElements[j];
227                     
228                     int left = Math.min(iElem.getX(), jElem.getX());
229                     int right = Math.max(iElem.getX() + iElem.getWidth(), jElem.getX() + jElem.getWidth());
230                     
231                     if (
232                         ((isBreakElem && jElem.getPositionType() == JRElement.POSITION_TYPE_FIX_RELATIVE_TO_TOP) || jElem.getPositionType() == JRElement.POSITION_TYPE_FLOAT) &&
233                         iElem.getY() + iElem.getHeight() <= jElem.getY() &&
234                         iElem.getWidth() + jElem.getWidth() > right - left // FIXME band bottom elements should not have dependent elements
235
)
236                     {
237                         iElem.addDependantElement(jElem);
238                     }
239                 }
240
241                 /*
242                 if (iElem.getParent().getElementGroup() != null) //parent might be null
243                 {
244                     iElem.setGroupElements(
245                         iElem.getParent().getElementGroup().getElements()
246                         );
247                 }
248                 */

249             }
250         }
251     }
252
253     
254     /**
255      *
256      */

257     protected void evaluate(byte evaluation) throws JRException
258     {
259         //evaluatePrintWhenExpression(evaluation);
260

261         //if (
262
// (isPrintWhenExpressionNull() ||
263
// (!isPrintWhenExpressionNull() &&
264
// isPrintWhenTrue()))
265
// )
266
//{
267
JRElement[] allElements = getElements();
268             if (allElements != null && allElements.length > 0)
269             {
270                 for(int i = 0; i < allElements.length; i++)
271                 {
272                     JRFillElement element = (JRFillElement)allElements[i];
273                     element.setCurrentEvaluation(evaluation);
274                     element.evaluate(evaluation);
275                 }
276             }
277         //}
278
}
279
280
281     /**
282      *
283      */

284     protected void resetElements()
285     {
286         if (ySortedElements != null && ySortedElements.length > 0)
287         {
288             for(int i = 0; i < ySortedElements.length; i++)
289             {
290                 JRFillElement element = ySortedElements[i];
291
292                 element.reset();
293                 
294                 if (!isOverflow)
295                 {
296                     element.setAlreadyPrinted(false);
297                 }
298             }
299         }
300     }
301     
302     
303     /**
304      *
305      */

306     protected boolean willOverflow()
307     {
308         return willOverflow;
309     }
310
311
312     protected void initFill()
313     {
314         isOverflow = willOverflow;
315         firstY = 0;
316         firstYElement = null;
317     }
318
319
320     /**
321      *
322      */

323     protected void prepareElements(
324         int availableStretchHeight,
325         boolean isOverflowAllowed
326         ) throws JRException
327     {
328         boolean tmpWillOverflow = false;
329
330         int maxBandStretch = 0;
331         int bandStretch = 0;
332
333         firstY = isOverflow ? getContainerHeight() : 0;
334         firstYElement = null;
335         boolean isFirstYFound = false;
336
337         if (ySortedElements != null && ySortedElements.length > 0)
338         {
339             for(int i = 0; i < ySortedElements.length; i++)
340             {
341                 JRFillElement element = ySortedElements[i];
342
343                 tmpWillOverflow =
344                     element.prepare(
345                         availableStretchHeight + getElementFirstY(element),
346                         isOverflow
347                         )
348                     || tmpWillOverflow;
349
350                 element.moveDependantElements();
351
352                 if (element.isToPrint())
353                 {
354                     if (isOverflow)
355                     {
356                         if (element.isReprinted())
357                         {
358                             firstY = 0;
359                         }
360                         else if (!isFirstYFound)
361                         {
362                             firstY = element.getY();
363                         }
364                         isFirstYFound = true;
365                     }
366
367                     firstYElement = element;
368
369                     bandStretch = element.getRelativeY() + element.getStretchHeight() - getContainerHeight() + element.getBandBottomY();
370                     if (bandStretch > maxBandStretch)
371                     {
372                         maxBandStretch = bandStretch;
373                     }
374                 }
375             }
376         }
377
378         if (maxBandStretch > availableStretchHeight + firstY)
379         {
380             tmpWillOverflow = true;
381         }
382         
383         if (tmpWillOverflow)
384         {
385             stretchHeight = getContainerHeight() + availableStretchHeight;
386         }
387         else
388         {
389             stretchHeight = getContainerHeight() + maxBandStretch;
390         }
391
392         willOverflow = tmpWillOverflow && isOverflowAllowed;
393     }
394
395     private int getElementFirstY(JRFillElement element)
396     {
397         int elemFirstY;
398         if (!isOverflow || hasPrintWhenOverflowElement)
399         {
400             elemFirstY = 0;
401         }
402         else if (element.getY() >= firstY)
403         {
404             elemFirstY = firstY;
405         }
406         else
407         {
408             elemFirstY = element.getY();
409         }
410         return elemFirstY;
411     }
412
413     protected void setStretchHeight(int stretchHeight)
414     {
415         if (stretchHeight > this.stretchHeight)
416         {
417             this.stretchHeight = stretchHeight;
418         }
419     }
420
421     /**
422      *
423      */

424     protected void stretchElements()
425     {
426         if (stretchElements != null && stretchElements.length > 0)
427         {
428             for(int i = 0; i < stretchElements.length; i++)
429             {
430                 JRFillElement element = stretchElements[i];
431                 
432                 element.stretchElement(stretchHeight - getContainerHeight());
433                 
434                 element.moveDependantElements();
435             }
436         }
437         
438         if (ySortedElements != null && ySortedElements.length > 0)
439         {
440             for(int i = 0; i < ySortedElements.length; i++)
441             {
442                 JRFillElement element = ySortedElements[i];
443
444                 element.stretchHeightFinal();
445             }
446         }
447     }
448
449     
450     protected int getStretchHeight()
451     {
452         return stretchHeight;
453     }
454
455     
456     /**
457      *
458      */

459     protected void moveBandBottomElements()
460     {
461         //if (!willOverflow)
462
//{
463
if (bandBottomElements != null && bandBottomElements.length > 0)
464             {
465                 for(int i = 0; i < bandBottomElements.length; i++)
466                 {
467                     JRFillElement element = bandBottomElements[i];
468
469                     element.setRelativeY(
470                         element.getY() + stretchHeight - getContainerHeight()
471                         );
472
473                     // band bottom elements do not print if there will be an overflow
474
element.setToPrint(element.isToPrint() && !willOverflow);
475                 }
476             }
477         //}
478
}
479
480
481     /**
482      *
483      */

484     protected void removeBlankElements()
485     {
486         JRElement[] remElems = removableElements;
487         if (remElems != null && remElems.length > 0)
488         {
489             JRElement[] elems = ySortedElements;
490             
491             for(int i = 0; i < remElems.length; i++)
492             {
493                 JRFillElement iElem = (JRFillElement)remElems[i];
494
495                 int blankHeight;
496                 if (iElem.isToPrint())
497                 {
498                     blankHeight = iElem.getHeight() - iElem.getStretchHeight();
499                 }
500                 else
501                 {
502                     blankHeight = iElem.getHeight();//FIXME subreports that strech and then don't print, will not remove all space
503
}
504                 
505                 if (
506                     blankHeight > 0 &&
507                     iElem.getRelativeY() + iElem.getStretchHeight() <= stretchHeight &&
508                     iElem.getRelativeY() >= firstY
509                     )
510                 {
511                     int blankY = iElem.getRelativeY() + iElem.getHeight() - blankHeight;
512                     boolean isToRemove = true;
513                     
514                     for(int j = 0; j < elems.length; j++)
515                     {
516                         JRFillElement jElem = (JRFillElement)elems[j];
517                         
518                         if (iElem != jElem && jElem.isToPrint())
519                         {
520                             int top =
521                                 Math.min(blankY, jElem.getRelativeY());
522                             int bottom =
523                                 Math.max(
524                                     blankY + blankHeight,
525                                     jElem.getRelativeY() + jElem.getStretchHeight()
526                                     );
527                             
528                             if (blankHeight + jElem.getStretchHeight() > bottom - top)
529                             {
530                                 isToRemove = false;
531                                 break;
532                             }
533                         }
534                     }
535                     
536                     if (isToRemove)
537                     {
538                         for(int j = 0; j < elems.length; j++)
539                         {
540                             JRFillElement jElem = (JRFillElement)elems[j];
541                             
542                             if (jElem.getRelativeY() >= blankY + blankHeight)
543                             {
544                                 jElem.setRelativeY(jElem.getRelativeY() - blankHeight);
545                             }
546                         }
547                         
548                         stretchHeight = stretchHeight - blankHeight;
549                     }
550                 }
551             }
552         }
553     }
554
555
556     /**
557      *
558      */

559     protected void fillElements(JRPrintElementContainer printContainer) throws JRException
560     {
561         //int maxStretch = 0;
562
//int stretch = 0;
563
JRElement[] allElements = getElements();
564         if (allElements != null && allElements.length > 0)
565         {
566             for(int i = 0; i < allElements.length; i++)
567             {
568                 JRFillElement element = (JRFillElement)allElements[i];
569                 
570                 element.setRelativeY(element.getRelativeY() - firstY);
571
572                 if (element.getRelativeY() + element.getStretchHeight() > stretchHeight)
573                 {
574                     element.setToPrint(false);
575                 }
576                 
577                 element.setAlreadyPrinted(element.isToPrint() || element.isAlreadyPrinted());
578                 
579                 if (element.isToPrint())
580                 {
581                     JRPrintElement printElement = element.fill();
582                     //printElement.setY(printElement.getY() - firstY);
583

584                     if (printElement != null)
585                     {
586                         //FIXME not all elements affect height
587
//stretch = printElement.getY() + firstY + printElement.getHeight() - element.getY() - element.getHeight();
588
//if (stretch > maxStretch)
589
//{
590
// maxStretch = stretch;
591
//}
592
printContainer.addElement(printElement);
593                         
594                         if (element instanceof JRFillSubreport)
595                         {
596                             JRFillSubreport subreport = (JRFillSubreport)element;
597                             
598                             List JavaDoc fonts = subreport.subreportFiller.getJasperPrint().getFontsList();
599                             if (fonts != null)
600                             {
601                                 for(int j = 0; j < fonts.size(); j++)
602                                 {
603                                     filler.getJasperPrint().addFont((JRReportFont)fonts.get(j), true);
604                                 }
605                             }
606                             
607                             List JavaDoc styles = subreport.subreportFiller.getJasperPrint().getStylesList();
608                             if (styles != null)
609                             {
610                                 for(int j = 0; j < styles.size(); j++)
611                                 {
612                                     filler.getJasperPrint().addStyle((JRStyle)styles.get(j), true);
613                                 }
614                             }
615                             
616                             
617                             Collection JavaDoc printElements = subreport.getPrintElements();
618                             addSubElements(printContainer, element, printElements);
619                         }
620                         else if (element instanceof JRFillCrosstab)
621                         {
622                             List JavaDoc printElements = ((JRFillCrosstab) element).getPrintElements();
623                             addSubElements(printContainer, element, printElements);
624                         }
625                     }
626                 }
627             }
628         }
629         
630         //printBand.setHeight(getHeight() + maxStretch - firstY);
631
printContainer.setHeight(stretchHeight - firstY);
632     }
633
634
635     protected void addSubElements(JRPrintElementContainer printContainer, JRFillElement element, Collection JavaDoc printElements)
636     {
637         JRPrintElement printElement;
638         if (printElements != null && printElements.size() > 0)
639         {
640             for(Iterator JavaDoc it = printElements.iterator(); it.hasNext();)
641             {
642                 printElement = (JRPrintElement)it.next();
643                 printElement.setX(element.getX() + printElement.getX());
644                 printElement.setY(element.getRelativeY() + printElement.getY());
645                 printContainer.addElement(printElement);
646             }
647         }
648     }
649
650     
651     /**
652      *
653      */

654     protected void rewind() throws JRException
655     {
656         if (ySortedElements != null && ySortedElements.length > 0)
657         {
658             for(int i = 0; i < ySortedElements.length; i++)
659             {
660                 JRFillElement element = ySortedElements[i];
661
662                 element.rewind();
663
664                 element.setAlreadyPrinted(false);
665             }
666         }
667         
668         willOverflow = false;
669     }
670     
671     protected int getFirstY()
672     {
673         return firstY;
674     }
675
676     
677     /**
678      * Returns the height of the element container.
679      *
680      * @return the height of the element container
681      */

682     protected abstract int getContainerHeight();
683
684
685     /**
686      * Find all styles containing conditional styles which are referenced by elements in this band.
687      */

688     protected void initConditionalStyles()
689     {
690         collectConditionalStyle(filler.getDefaultStyle());
691         
692         for (int i = 0; i < deepElements.length; i++)
693         {
694             JRStyle style = deepElements[i].initStyle;
695             collectConditionalStyle(style);
696         }
697         
698         if (deepElements.length > 0)
699         {
700             for(int i = 0; i < deepElements.length; i++)
701             {
702                 deepElements[i].setConditionalStylesContainer(this);
703             }
704         }
705     }
706
707     protected void collectConditionalStyle(JRStyle style)
708     {
709         if (style != null)// && style.getConditionalStyles() != null)
710
{
711             stylesToEvaluate.add(style);
712         }
713     }
714
715
716     protected void evaluateConditionalStyles(byte evaluation) throws JRException
717     {
718         for (Iterator JavaDoc it = stylesToEvaluate.iterator(); it.hasNext();)
719         {
720             evaluateConditionalStyle((JRStyle) it.next(), evaluation);
721         }
722     }
723
724
725     protected JRStyle evaluateConditionalStyle(JRStyle initialStyle, byte evaluation) throws JRException
726     {
727         JRStyle consolidatedStyle = initialStyle;
728
729         StringBuffer JavaDoc code = new StringBuffer JavaDoc();
730         List JavaDoc condStylesToApply = new ArrayList JavaDoc();
731         
732         boolean anyTrue = buildConsolidatedStyle(initialStyle, evaluation, code, condStylesToApply);
733         
734         if (anyTrue)
735         {
736             String JavaDoc consolidatedStyleName = initialStyle.getName() + code.toString();
737             consolidatedStyle = (JRStyle)filler.getJasperPrint().getStylesMap().get(consolidatedStyleName);
738             if (consolidatedStyle == null)
739             {
740                 consolidatedStyle = new JRBaseStyle(consolidatedStyleName);
741                 for (int j = condStylesToApply.size() - 1; j >= 0; j--)
742                 {
743                     JRStyleResolver.appendStyle(consolidatedStyle, (JRStyle)condStylesToApply.get(j));
744                 }
745
746                 filler.getJasperPrint().addStyle(consolidatedStyle, true);
747             }
748         }
749
750         evaluatedStyles.put(initialStyle, consolidatedStyle);
751         
752         return consolidatedStyle;
753     }
754
755
756     protected boolean buildConsolidatedStyle(JRStyle style, byte evaluation, StringBuffer JavaDoc code, List JavaDoc condStylesToApply) throws JRException
757     {
758         boolean anyTrue = false;
759         
760         JRConditionalStyle[] conditionalStyles = style.getConditionalStyles();
761         if (conditionalStyles != null && conditionalStyles.length > 0)
762         {
763             for (int j = 0; j < conditionalStyles.length; j++)
764             {
765                 JRConditionalStyle conditionalStyle = conditionalStyles[j];
766                 Boolean JavaDoc expressionValue =
767                     (Boolean JavaDoc) expressionEvaluator.evaluate(
768                         conditionalStyle.getConditionExpression(),
769                         evaluation
770                         );
771                 
772                 boolean condition;
773                 if (expressionValue == null)
774                 {
775                     condition = false;
776                 }
777                 else
778                 {
779                     condition = expressionValue.booleanValue();
780                 }
781                 
782                 code.append(condition ? '1' : '0');
783                 anyTrue = anyTrue | condition;
784
785                 if (condition)
786                     condStylesToApply.add(conditionalStyle);
787             }
788         }
789
790         condStylesToApply.add(style);
791         
792         if (style.getStyle() != null)
793             anyTrue = anyTrue | buildConsolidatedStyle(style.getStyle(), evaluation, code, condStylesToApply);
794         
795         return anyTrue;
796     }
797
798
799     public JRStyle getEvaluatedConditionalStyle(JRStyle parentStyle)
800     {
801         return (JRStyle) evaluatedStyles.get(parentStyle);
802     }
803 }
804
Popular Tags