1
24 package net.sf.jasperreports.engine.fill;
25
26 import java.awt.Color;
27 import java.io.Serializable;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Set;
37 import java.util.TimeZone;
38 import java.util.UUID;
39
40 import net.sf.jasperreports.engine.JRConditionalStyle;
41 import net.sf.jasperreports.engine.JRConstants;
42 import net.sf.jasperreports.engine.JRDefaultStyleProvider;
43 import net.sf.jasperreports.engine.JRElement;
44 import net.sf.jasperreports.engine.JRElementGroup;
45 import net.sf.jasperreports.engine.JRException;
46 import net.sf.jasperreports.engine.JRExpression;
47 import net.sf.jasperreports.engine.JRExpressionChunk;
48 import net.sf.jasperreports.engine.JRGroup;
49 import net.sf.jasperreports.engine.JROrigin;
50 import net.sf.jasperreports.engine.JRPrintElement;
51 import net.sf.jasperreports.engine.JRPropertiesHolder;
52 import net.sf.jasperreports.engine.JRPropertiesMap;
53 import net.sf.jasperreports.engine.JRPropertyExpression;
54 import net.sf.jasperreports.engine.JRStyle;
55 import net.sf.jasperreports.engine.JRStyleSetter;
56 import net.sf.jasperreports.engine.JasperPrint;
57 import net.sf.jasperreports.engine.base.JRBaseStyle;
58 import net.sf.jasperreports.engine.design.JRDesignPropertyExpression;
59 import net.sf.jasperreports.engine.style.StyleProvider;
60 import net.sf.jasperreports.engine.style.StyleProviderFactory;
61 import net.sf.jasperreports.engine.type.CalculationEnum;
62 import net.sf.jasperreports.engine.type.EvaluationTimeEnum;
63 import net.sf.jasperreports.engine.type.ModeEnum;
64 import net.sf.jasperreports.engine.type.PositionTypeEnum;
65 import net.sf.jasperreports.engine.type.StretchTypeEnum;
66 import net.sf.jasperreports.engine.util.StyleResolver;
67 import net.sf.jasperreports.engine.util.StyleUtil;
68
69
70
73 public abstract class JRFillElement implements JRElement, JRFillCloneable, JRStyleSetter, DynamicPropertiesHolder
74 {
75
78 public static final String EXCEPTION_MESSAGE_KEY_INVALID_BOOKMARK_LEVEL = "fill.anchor.bookmark.level.invalid";
79
80
81
84 protected JRElement parent;
85 protected List<JRPropertyExpression> propertyExpressions;
86 protected List<String> dynamicTransferProperties;
87 protected JRStyle providerStyle;
88 protected Map<JRStyle,JRTemplateElement> templates = new HashMap<JRStyle,JRTemplateElement>();
89 protected List<StyleProvider> styleProviders;
90
91
94 protected JRBaseFiller filler;
95 protected JRFillExpressionEvaluator expressionEvaluator;
96
97 protected JRDefaultStyleProvider defaultStyleProvider;
98
99
102 protected JRGroup printWhenGroupChanges;
103 protected JRFillElementGroup elementGroup;
104
105
108 protected JRFillBand band;
109
110 protected JROriginProvider originProvider;
111
112 protected PrintElementOriginator printElementOriginator;
113
114
117 private boolean isPrintWhenExpressionNull = true;
118 private boolean isPrintWhenTrue = true;
119 private boolean isToPrint = true;
120 private boolean isReprinted;
121 private boolean isAlreadyPrinted;
122 private Collection<JRFillElement> dependantElements = new ArrayList<JRFillElement>();
123 private int relativeY;
124 private int collapsedHeightAbove;
125 private int collapsedHeightBelow;
126
129 private int stretchHeight;
130
133 private int prepareHeight;
134
135 private int x;
136 private int y;
137 private int width;
138 private int height;
139
140 private boolean isValueRepeating;
141
142 protected byte currentEvaluation;
143
144
145 protected Map<JREvaluationTime,DelayedEvaluations> delayedEvaluationsMap;
146
147 protected JRFillElementContainer conditionalStylesContainer;
148 protected FillContainerContext fillContainerContext;
149
150 protected JRStyle initStyle;
151
152 protected JRStyle currentStyle;
153
154
158 private boolean shrinkable;
159
160 protected JRPropertiesMap staticProperties;
161 protected JRPropertiesMap dynamicProperties;
162 protected JRPropertiesMap mergedProperties;
163
164
174 protected JRFillElement(
175 JRBaseFiller filler,
176 JRElement element,
177 JRFillObjectFactory factory
178 )
179 {
180 factory.put(element, this);
181
182 this.parent = element;
183 this.filler = filler;
184 this.expressionEvaluator = factory.getExpressionEvaluator();
185 this.defaultStyleProvider = factory.getDefaultStyleProvider();
186
187 printElementOriginator = filler.assignElementId(this);
188
189
190 printWhenGroupChanges = factory.getGroup(element.getPrintWhenGroupChanges());
191 elementGroup = (JRFillElementGroup)factory.getVisitResult(element.getElementGroup());
192
193 x = element.getX();
194 y = element.getY();
195 width = element.getWidth();
196 height = element.getHeight();
197
198 staticProperties = element.hasProperties() ? element.getPropertiesMap().cloneProperties() : null;
199 mergedProperties = staticProperties;
200
201 JRPropertyExpression[] elementPropertyExpressions = element.getPropertyExpressions();
202 propertyExpressions = elementPropertyExpressions == null ? new ArrayList<JRPropertyExpression>(0)
203 : new ArrayList<JRPropertyExpression>(Arrays.asList(elementPropertyExpressions));
204
205 dynamicTransferProperties = findDynamicTransferProperties();
206
207 factory.registerDelayedStyleSetter(this, parent);
208
209 initStyleProviders();
210 }
211
212
213 protected JRFillElement(JRFillElement element, JRFillCloneFactory factory)
214 {
215 factory.put(element, this);
216
217 this.parent = element.parent;
218 this.filler = element.filler;
219 this.expressionEvaluator = element.expressionEvaluator;
220 this.defaultStyleProvider = element.defaultStyleProvider;
221 this.originProvider = element.originProvider;
222
223 printElementOriginator = element.printElementOriginator;
224
225
226 printWhenGroupChanges = element.printWhenGroupChanges;
227 elementGroup = (JRFillElementGroup) factory.getClone((JRFillElementGroup) element.getElementGroup());
228
229 x = element.getX();
230 y = element.getY();
231 width = element.getWidth();
232 height = element.getHeight();
233
234 templates = element.templates;
235
236 initStyle = element.initStyle;
237
238 shrinkable = element.shrinkable;
239
240 staticProperties = element.staticProperties == null ? null : element.staticProperties.cloneProperties();
241 mergedProperties = staticProperties;
242 this.propertyExpressions = new ArrayList<JRPropertyExpression>(element.propertyExpressions);
243 this.dynamicTransferProperties = element.dynamicTransferProperties;
244
245
246 initStyleProviders();
247 }
248
249 private List<String> findDynamicTransferProperties()
250 {
251 if (propertyExpressions.isEmpty())
252 {
253 return null;
254 }
255
256 List<String> prefixes = filler.getPrintTransferPropertyPrefixes();
257 List<String> transferProperties = new ArrayList<String>(propertyExpressions.size());
258 for (JRPropertyExpression propertyExpression : propertyExpressions)
259 {
260 String propertyName = propertyExpression.getName();
261 for (String prefix : prefixes)
262 {
263 if (propertyName.startsWith(prefix))
264 {
265 transferProperties.add(propertyName);
266 break;
267 }
268 }
269 }
270 return transferProperties;
271 }
272
273
274 @Override
275 public JRDefaultStyleProvider getDefaultStyleProvider()
276 {
277 return defaultStyleProvider;
278 }
279
280
283 protected StyleResolver getStyleResolver()
284 {
285 return getDefaultStyleProvider().getStyleResolver();
286 }
287
288 @Override
289 public UUID getUUID()
290 {
291 return parent.getUUID();
292 }
293
294 @Override
295 public String getKey()
296 {
297 return parent.getKey();
298 }
299
300 @Override
301 public PositionTypeEnum getPositionTypeValue()
302 {
303 return parent.getPositionTypeValue();
304 }
305
306 @Override
307 public void setPositionType(PositionTypeEnum positionType)
308 {
309 throw new UnsupportedOperationException();
310 }
311
312 @Override
313 public StretchTypeEnum getStretchTypeValue()
314 {
315 return parent.getStretchTypeValue();
316 }
317
318 @Override
319 public void setStretchType(StretchTypeEnum stretchType)
320 {
321 throw new UnsupportedOperationException();
322 }
323
324 @Override
325 public boolean isPrintRepeatedValues()
326 {
327 return parent.isPrintRepeatedValues();
328 }
329
330 @Override
331 public void setPrintRepeatedValues(boolean isPrintRepeatedValues)
332 {
333 }
334
335 @Override
336 public ModeEnum getModeValue()
337 {
338 return getStyleResolver().getMode(this, ModeEnum.OPAQUE);
339 }
340
341 @Override
342 public ModeEnum getOwnModeValue()
343 {
344 return providerStyle == null || providerStyle.getOwnModeValue() == null ? parent.getOwnModeValue() : providerStyle.getOwnModeValue();
345 }
346
347 @Override
348 public void setMode(ModeEnum modeValue)
349 {
350 }
351
352 @Override
353 public int getX()
354 {
355 return x;
356 }
357
358 @Override
359 public void setX(int x)
360 {
361 this.x = x;
362 }
363
364
367 public void setY(int y)
368 {
369 this.y = y;
370 }
371
372 @Override
373 public int getY()
374 {
375 return y;
376 }
377
378 @Override
379 public int getWidth()
380 {
381 return width;
382 }
383
384 @Override
385 public void setWidth(int width)
386 {
387 this.width = width;
388 }
389
390
393 public void setHeight(int height)
394 {
395 this.height = height;
396 }
397
398 @Override
399 public int getHeight()
400 {
401 return height;
402 }
403
404 @Override
405 public boolean isRemoveLineWhenBlank()
406 {
407 return parent.isRemoveLineWhenBlank();
408 }
409
410 @Override
411 public void setRemoveLineWhenBlank(boolean isRemoveLine)
412 {
413 }
414
415 @Override
416 public boolean isPrintInFirstWholeBand()
417 {
418 return parent.isPrintInFirstWholeBand();
419 }
420
421 @Override
422 public void setPrintInFirstWholeBand(boolean isPrint)
423 {
424 }
425
426 @Override
427 public boolean isPrintWhenDetailOverflows()
428 {
429 return parent.isPrintWhenDetailOverflows();
430 }
431
432 @Override
433 public void setPrintWhenDetailOverflows(boolean isPrint)
434 {
435 }
436
437 @Override
438 public Color getForecolor()
439 {
440 return getStyleResolver().getForecolor(this);
441 }
442
443 @Override
444 public Color getOwnForecolor()
445 {
446 return providerStyle == null || providerStyle.getOwnForecolor() == null ? parent.getOwnForecolor() : providerStyle.getOwnForecolor();
447 }
448
449 @Override
450 public void setForecolor(Color forecolor)
451 {
452 }
453
454 @Override
455 public Color getBackcolor()
456 {
457 return getStyleResolver().getBackcolor(this);
458 }
459
460 @Override
461 public Color getOwnBackcolor()
462 {
463 return providerStyle == null || providerStyle.getOwnBackcolor() == null ? parent.getOwnBackcolor() : providerStyle.getOwnBackcolor();
464 }
465
466 @Override
467 public void setBackcolor(Color backcolor)
468 {
469 }
470
471 @Override
472 public JRExpression getPrintWhenExpression()
473 {
474 return parent.getPrintWhenExpression();
475 }
476
477 @Override
478 public JRGroup getPrintWhenGroupChanges()
479 {
480 return printWhenGroupChanges;
481 }
482
483 @Override
484 public JRElementGroup getElementGroup()
485 {
486 return elementGroup;
487 }
488
489
492 protected boolean isPrintWhenExpressionNull()
493 {
494 return isPrintWhenExpressionNull;
495 }
496
497
500 protected void setPrintWhenExpressionNull(boolean isPrintWhenExpressionNull)
501 {
502 this.isPrintWhenExpressionNull = isPrintWhenExpressionNull;
503 }
504
505
508 protected boolean isPrintWhenTrue()
509 {
510 return isPrintWhenTrue;
511 }
512
513
516 protected void setPrintWhenTrue(boolean isPrintWhenTrue)
517 {
518 this.isPrintWhenTrue = isPrintWhenTrue;
519 }
520
521
524 public boolean isToPrint()
525 {
526 return isToPrint;
527 }
528
529
532 protected void setToPrint(boolean isToPrint)
533 {
534 this.isToPrint = isToPrint;
535 }
536
537
540 protected boolean isReprinted()
541 {
542 return isReprinted;
543 }
544
545
548 protected void setReprinted(boolean isReprinted)
549 {
550 this.isReprinted = isReprinted;
551 }
552
553
556 public boolean isAlreadyPrinted()
557 {
558 return isAlreadyPrinted;
559 }
560
561
564 public void setAlreadyPrinted(boolean isAlreadyPrinted)
565 {
566 this.isAlreadyPrinted = isAlreadyPrinted;
567 }
568
569
572 protected JRElement[] getGroupElements()
573 {
574 JRElement[] groupElements = null;
575
576 if (elementGroup != null)
577 {
578 groupElements = elementGroup.getElements();
579 }
580
581 return groupElements;
582 }
583
584
587 protected Collection<JRFillElement> getDependantElements()
588 {
589 return dependantElements;
590 }
591
592
595 protected void addDependantElement(JRFillElement element)
596 {
597 dependantElements.add(element);
598 }
599
600
603 protected int getRelativeY()
604 {
605 return relativeY;
606 }
607
608
611 protected void setRelativeY(int relativeY)
612 {
613 this.relativeY = relativeY;
614 }
615
616
619 protected int getCollapsedHeightAbove()
620 {
621 return collapsedHeightAbove;
622 }
623
624
627 protected void setCollapsedHeightAbove(int collapsedHeightAbove)
628 {
629 this.collapsedHeightAbove = collapsedHeightAbove;
630 }
631
632
635 protected int getCollapsedHeightBelow()
636 {
637 return collapsedHeightBelow;
638 }
639
640
643 protected void setCollapsedHeightBelow(int collapsedHeightBelow)
644 {
645 this.collapsedHeightBelow = collapsedHeightBelow;
646 }
647
648
651 public int getStretchHeight()
652 {
653 return stretchHeight;
654 }
655
656
659 protected void setStretchHeight(int stretchHeight)
660 {
661 if (stretchHeight > getHeight() || (shrinkable && isRemoveLineWhenBlank()))
662 {
663 this.stretchHeight = stretchHeight;
664 }
665 else
666 {
667 this.stretchHeight = getHeight();
668 }
669 }
670
671
674 public int getPrepareHeight()
675 {
676 return prepareHeight;
677 }
678
679
686 protected void setPrepareHeight(int prepareHeight)
687 {
688 this.prepareHeight = prepareHeight;
689
690 setStretchHeight(prepareHeight);
691 }
692
693
696 protected JRFillBand getBand()
697 {
698 return band;
699 }
700
701
704 protected void setBand(JRFillBand band)
705 {
706 this.band = band;
707
708 if (this.originProvider == null)
709 {
710 setOriginProvider(band);
711 }
712 }
713
714
715
718 protected void initStyleProviders()
719 {
720 List<StyleProviderFactory> styleProviderFactories = filler.getJasperReportsContext().getExtensions(StyleProviderFactory.class);
721 if (styleProviderFactories != null && styleProviderFactories.size() > 0)
722 {
723 FillStyleProviderContext styleProviderContext = new FillStyleProviderContext(this);
724 for (StyleProviderFactory styleProviderFactory : styleProviderFactories)
725 {
726 StyleProvider styleProvider = styleProviderFactory.getStyleProvider(styleProviderContext, filler.getJasperReportsContext());
727 if (styleProvider != null)
728 {
729 if (styleProviders == null)
730 {
731 styleProviders = new ArrayList<StyleProvider>();
732 }
733 styleProviders.add(styleProvider);
734 }
735 }
736 }
737 }
738
739
740
743 protected void reset()
744 {
745 relativeY = y;
746 collapsedHeightAbove = 0;
747 collapsedHeightBelow = 0;
748 stretchHeight = height;
749 prepareHeight = height;
750
751 if (elementGroup != null)
752 {
753 elementGroup.reset();
754 }
755 }
756
757 protected void setCurrentEvaluation(byte evaluation)
758 {
759 currentEvaluation = evaluation;
760 }
761
762
765 protected abstract void evaluate(
766 byte evaluation
767 ) throws JRException;
768
769
770
773 protected void evaluateStyle(
774 byte evaluation
775 ) throws JRException
776 {
777 providerStyle = null;
778
779 if (styleProviders != null && styleProviders.size() > 0)
780 {
781 for (StyleProvider styleProvider : styleProviders)
782 {
783 JRStyle style = styleProvider.getStyle(evaluation);
784 if (style != null)
785 {
786 if (providerStyle == null)
787 {
788 providerStyle = new JRBaseStyle();
789 }
790 StyleUtil.appendStyle(providerStyle, style);
791 }
792 }
793 }
794 }
795
796 protected TimeZone getTimeZone()
797 {
798 return filler.getTimeZone();
799 }
800
801
804 protected void evaluatePrintWhenExpression(
805 byte evaluation
806 ) throws JRException
807 {
808 boolean isExprNull = true;
809 boolean isExprTrue = false;
810
811 JRExpression expression = getPrintWhenExpression();
812 if (expression != null)
813 {
814 isExprNull = false;
815 Boolean printWhenExpressionValue = (Boolean) evaluateExpression(expression, evaluation);
816 if (printWhenExpressionValue == null)
817 {
818 isExprTrue = false;
819 }
820 else
821 {
822 isExprTrue = printWhenExpressionValue;
823 }
824 }
825
826 setPrintWhenExpressionNull(isExprNull);
827 setPrintWhenTrue(isExprTrue);
828 }
829
830
831
834 protected abstract void rewind() throws JRException;
835
836
837
840 protected abstract JRPrintElement fill() throws JRException;
841
842 protected JRTemplateElement getElementTemplate()
843 {
844 JRTemplateElement template = null;
845 JRStyle style = null;
846
847 if (providerStyle == null)
848 {
849
850 style = getStyle();
851 template = getTemplate(style);
852 }
853
854 if (template == null)
855 {
856 template = createElementTemplate();
857 transferProperties(template);
858
859
860 template = filler.fillContext.deduplicate(template);
861
862 if (providerStyle == null)
863 {
864 registerTemplate(style, template);
865 }
866 }
867 return template;
868 }
869
870 protected abstract JRTemplateElement createElementTemplate();
871
872
875 protected boolean prepare(
876 int availableHeight,
877 boolean isOverflow
878 ) throws JRException
879 {
880 if (
881 isPrintWhenExpressionNull() ||
882 ( !isPrintWhenExpressionNull() &&
883 isPrintWhenTrue() )
884 )
885 {
886 setToPrint(true);
887 }
888 else
889 {
890 setToPrint(false);
891 }
892
893 setReprinted(false);
894
895 return false;
896 }
897
898
899
902 protected void _stretchElement(int bandStretch)
903 {
904 switch (getStretchTypeValue())
905 {
906 case RELATIVE_TO_BAND_HEIGHT :
907 case CONTAINER_HEIGHT :
908 case CONTAINER_BOTTOM :
909 {
910 _stretchElementToHeight(getHeight() + bandStretch);
911 break;
912 }
913 case RELATIVE_TO_TALLEST_OBJECT :
914 case ELEMENT_GROUP_HEIGHT :
915 case ELEMENT_GROUP_BOTTOM :
916 {
917 if (elementGroup != null)
918 {
919
920 _stretchElementToHeight(getHeight() + elementGroup.getStretchHeightDiff());
921 }
922
923 break;
924 }
925 case NO_STRETCH :
926 default :
927 {
928 break;
929 }
930 }
931 }
932
933
936 protected void _stretchElementToHeight(int stretchHeight)
937 {
938 if (stretchHeight > getStretchHeight())
939 {
940 setStretchHeight(stretchHeight);
941 }
942 }
943
944
945
948 @SuppressWarnings("deprecation")
949 protected boolean stretchElement(int containerStretch)
950 {
951 boolean applied = false;
952 switch (getStretchTypeValue())
953 {
954 case RELATIVE_TO_BAND_HEIGHT :
955 case CONTAINER_HEIGHT :
956 case CONTAINER_BOTTOM :
957 {
958 applied = stretchElementToContainer(containerStretch);
959 break;
960 }
961 case RELATIVE_TO_TALLEST_OBJECT :
962 case ELEMENT_GROUP_HEIGHT :
963 case ELEMENT_GROUP_BOTTOM :
964 {
965 applied = stretchElementToElementGroup();
966 break;
967 }
968 case NO_STRETCH :
969 default :
970 {
971 break;
972 }
973 }
974 return applied;
975 }
976
977
978
981 @SuppressWarnings("deprecation")
982 protected boolean stretchElementToContainer(int containerStretch)
983 {
984 boolean applied = false;
985 switch (getStretchTypeValue())
986 {
987 case RELATIVE_TO_BAND_HEIGHT :
988 case CONTAINER_HEIGHT :
989 {
990 applied = stretchElementToHeight(getHeight() + containerStretch);
991 break;
992 }
993 case CONTAINER_BOTTOM :
994 {
995 applied = stretchElementToHeight(getY() - getRelativeY() + getHeight() + containerStretch);
996 break;
997 }
998 }
999 return applied;
1000 }
1001
1002
1003
1006 @SuppressWarnings("deprecation")
1007 protected boolean stretchElementToElementGroup()
1008 {
1009 boolean applied = false;
1010 if (elementGroup != null)
1011 {
1012 switch (getStretchTypeValue())
1013 {
1014 case RELATIVE_TO_TALLEST_OBJECT :
1015 case ELEMENT_GROUP_HEIGHT :
1016 {
1017 applied = stretchElementToHeight(getHeight() + elementGroup.getStretchHeightDiff());
1018 break;
1019 }
1020 case ELEMENT_GROUP_BOTTOM :
1021 {
1022 applied = stretchElementToHeight(getY() - getRelativeY() + getHeight() + elementGroup.getStretchHeightDiff());
1023 break;
1024 }
1025 }
1026 }
1027 return applied;
1028 }
1029
1030
1031
1036 protected boolean stretchElementToHeight(int stretchHeight)
1037 {
1038
1039
1040 boolean applied = false;
1041 if (stretchHeight > getPrepareHeight())
1042 {
1043
1044 setStretchHeight(stretchHeight);
1045 applied = true;
1046 }
1047 return applied;
1048 }
1049
1050
1051
1054 protected void _moveDependantElements()
1055 {
1056 Collection<JRFillElement> elements = getDependantElements();
1057 if (elements != null && elements.size() > 0)
1058 {
1059 for (JRFillElement element : elements)
1060 {
1061 int newRelativeY =
1062 getRelativeY() + getStretchHeight()
1063 + (element.getY() - (getY() + getHeight()));
1064
1065 if (newRelativeY > element.getRelativeY())
1066 {
1067 element.setRelativeY(newRelativeY);
1068 }
1069 }
1070 }
1071 }
1072
1073
1074
1077 protected void moveDependantElements()
1078 {
1079 Collection<JRFillElement> elements = getDependantElements();
1080 if (elements != null && elements.size() > 0)
1081 {
1082 for (JRFillElement element : elements)
1083 {
1084 int newRelativeY =
1085 getRelativeY() + getStretchHeight()
1086 + (element.getY() - (getY() + getHeight()))
1087 - (element.getCollapsedHeightAbove() - getCollapsedHeightAbove());
1088
1089 if (newRelativeY > element.getRelativeY())
1090 {
1091 element.setRelativeY(newRelativeY);
1092
1093 element.moveDependantElements();
1094 }
1095 }
1096 }
1097 }
1098
1099
1100
1106 protected abstract void resolveElement (JRPrintElement element, byte evaluation) throws JRException;
1107
1108 protected void performDelayedEvaluation(JRPrintElement element, byte evaluation)
1109 throws JRException
1110 {
1111 boolean updateTemplate = false;
1112
1113 JRStyle printStyle = element.getStyle();
1114 if (isDelayedStyleEvaluation())
1115 {
1116 JRStyle elementStyle = initStyle;
1117 if (elementStyle == null)
1118 {
1119 elementStyle = filler.getDefaultStyle();
1120 }
1121
1122 if (elementStyle != null)
1123 {
1124 JRStyle evaluatedStyle = conditionalStylesContainer.evaluateConditionalStyle(
1125 elementStyle, evaluation);
1126
1127 if (evaluatedStyle != printStyle)
1128 {
1129
1130 printStyle = evaluatedStyle;
1131
1132 updateTemplate = true;
1133 }
1134 }
1135 }
1136
1137
1138 this.currentStyle = printStyle;
1139
1140 resolveElement(element, evaluation);
1141
1142 if (updateTemplate || providerStyle != null
1143 || delayedEvaluationUpdatesTemplate())
1144 {
1145
1146
1147 JRTemplateElement newTemplate = getElementTemplate();
1148 ((JRTemplatePrintElement) element).updateElementTemplate(
1149 newTemplate);
1150 }
1151
1152
1153 this.currentStyle = null;
1154
1155 }
1156
1157 protected boolean delayedEvaluationUpdatesTemplate()
1158 {
1159 return false;
1160 }
1161
1162
1163
1171 public final Object evaluateExpression(JRExpression expression, byte evaluation) throws JRException
1172 {
1173 return expressionEvaluator.evaluate(expression, evaluation);
1174 }
1175
1176
1177
1187 protected boolean isValueRepeating()
1188 {
1189 return isValueRepeating;
1190 }
1191
1192
1193
1201 protected void setValueRepeating(boolean isValueRepeating)
1202 {
1203 this.isValueRepeating = isValueRepeating;
1204 }
1205
1206
1207 protected JRFillVariable getVariable(String variableName)
1208 {
1209 return filler.getVariable(variableName);
1210 }
1211
1212
1213 protected JRFillField getField(String fieldName)
1214 {
1215 return filler.getField(fieldName);
1216 }
1217
1218
1219 protected EvaluationTimeEnum getEvaluationTimeValue()
1220 {
1221 return EvaluationTimeEnum.NOW;
1222 }
1223
1224
1231 protected void resolveElement (JRPrintElement element, byte evaluation, JREvaluationTime evaluationTime) throws JRException
1232 {
1233 EvaluationTimeEnum evaluationTimeType = getEvaluationTimeValue();
1234 switch (evaluationTimeType)
1235 {
1236 case NOW:
1237 break;
1238 case AUTO:
1239 delayedEvaluate((JRRecordedValuesPrintElement) element, evaluationTime, evaluation);
1240 break;
1241 default:
1242 performDelayedEvaluation(element, evaluation);
1243 break;
1244 }
1245 }
1246
1247 private static class DelayedEvaluations implements Serializable
1248 {
1249 private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID;
1250
1251 final Set<String> fields;
1252 final Set<String> variables;
1253
1254 DelayedEvaluations()
1255 {
1256 fields = new HashSet<String>();
1257 variables = new HashSet<String>();
1258 }
1259 }
1260
1261 protected void initDelayedEvaluations()
1262 {
1263 if (getEvaluationTimeValue() == EvaluationTimeEnum.AUTO && delayedEvaluationsMap == null)
1264 {
1265 delayedEvaluationsMap = new HashMap<JREvaluationTime,DelayedEvaluations>();
1266 collectDelayedEvaluations();
1267 }
1268 }
1269
1270 protected void collectDelayedEvaluations()
1271 {
1272 if (isDelayedStyleEvaluation())
1273 {
1274 collectStyleDelayedEvaluations();
1275 collectStyleProviderDelayedEvaluations();
1276 }
1277 }
1278
1279 protected void collectStyleDelayedEvaluations()
1280 {
1281 JRStyle elementStyle = initStyle;
1282 if (elementStyle == null)
1283 {
1284 elementStyle = filler.getDefaultStyle();
1285 }
1286
1287 if (elementStyle != null)
1288 {
1289 JRStyle style = elementStyle;
1290 while (style != null)
1291 {
1292 collectDelayedEvaluations(style);
1293
1294
1295 style = style.getStyle();
1296 }
1297 }
1298 }
1299
1300 protected void collectDelayedEvaluations(JRStyle style)
1301 {
1302 JRConditionalStyle[] conditionalStyles = style.getConditionalStyles();
1303
1304 if (conditionalStyles != null && conditionalStyles.length > 0)
1305 {
1306 for (int i = 0; i < conditionalStyles.length; i++)
1307 {
1308 collectDelayedEvaluations(
1309 conditionalStyles[i].getConditionExpression());
1310 }
1311 }
1312 }
1313
1314
1315 protected void collectDelayedEvaluations(JRExpression expression)
1316 {
1317 if (expression != null)
1318 {
1319 JRExpressionChunk[] chunks = expression.getChunks();
1320 if (chunks != null)
1321 {
1322 for (int i = 0; i < chunks.length; i++)
1323 {
1324 JRExpressionChunk chunk = chunks[i];
1325 switch (chunk.getType())
1326 {
1327 case JRExpressionChunk.TYPE_FIELD:
1328 {
1329 DelayedEvaluations delayedEvaluations = getDelayedEvaluations(JREvaluationTime.EVALUATION_TIME_NOW);
1330 delayedEvaluations.fields.add(chunk.getText());
1331 break;
1332 }
1333 case JRExpressionChunk.TYPE_VARIABLE:
1334 {
1335 JREvaluationTime time = autogetVariableEvaluationTime(chunk.getText());
1336 DelayedEvaluations delayedEvaluations = getDelayedEvaluations(time);
1337 delayedEvaluations.variables.add(chunk.getText());
1338 break;
1339 }
1340 }
1341 }
1342 }
1343 }
1344 }
1345
1346
1347 protected void collectStyleProviderDelayedEvaluations()
1348 {
1349 if (styleProviders != null && styleProviders.size() > 0)
1350 {
1351 for (StyleProvider styleProvider : styleProviders)
1352 {
1353 String[] fields = styleProvider.getFields();
1354 if (fields != null && fields.length > 0)
1355 {
1356 DelayedEvaluations delayedEvaluations = getDelayedEvaluations(JREvaluationTime.EVALUATION_TIME_NOW);
1357 for (String field : fields)
1358 {
1359 delayedEvaluations.fields.add(field);
1360 }
1361 }
1362 String[] variables = styleProvider.getVariables();
1363 if (variables != null && variables.length > 0)
1364 {
1365 for (String variable : variables)
1366 {
1367 JREvaluationTime time = autogetVariableEvaluationTime(variable);
1368 DelayedEvaluations delayedEvaluations = getDelayedEvaluations(time);
1369 delayedEvaluations.variables.add(variable);
1370 }
1371 }
1372 }
1373 }
1374 }
1375
1376
1377 private DelayedEvaluations getDelayedEvaluations(JREvaluationTime time)
1378 {
1379 DelayedEvaluations delayedEvaluations = delayedEvaluationsMap.get(time);
1380 if (delayedEvaluations == null)
1381 {
1382 delayedEvaluations = new DelayedEvaluations();
1383 delayedEvaluationsMap.put(time, delayedEvaluations);
1384 }
1385 return delayedEvaluations;
1386 }
1387
1388
1389 private JREvaluationTime autogetVariableEvaluationTime(String variableName)
1390 {
1391 JRFillVariable variable = getVariable(variableName);
1392 JREvaluationTime evaluationTime;
1393 switch (variable.getResetTypeValue())
1394 {
1395 case REPORT:
1396 evaluationTime = JREvaluationTime.EVALUATION_TIME_REPORT;
1397 break;
1398 case MASTER:
1399 evaluationTime = JREvaluationTime.EVALUATION_TIME_MASTER;
1400 break;
1401 case PAGE:
1402 evaluationTime = JREvaluationTime.EVALUATION_TIME_PAGE;
1403 break;
1404 case COLUMN:
1405 evaluationTime = JREvaluationTime.EVALUATION_TIME_COLUMN;
1406 break;
1407 case GROUP:
1408 evaluationTime = JREvaluationTime.getGroupEvaluationTime(variable.getResetGroup().getName());
1409 break;
1410 default:
1411 evaluationTime = JREvaluationTime.EVALUATION_TIME_NOW;
1412 break;
1413 }
1414
1415 if (!evaluationTime.equals(JREvaluationTime.EVALUATION_TIME_NOW) &&
1416 band.isNowEvaluationTime(evaluationTime))
1417 {
1418 evaluationTime = JREvaluationTime.EVALUATION_TIME_NOW;
1419 }
1420
1421 if (variable.getCalculationValue() == CalculationEnum.SYSTEM &&
1422 evaluationTime.equals(JREvaluationTime.EVALUATION_TIME_NOW) &&
1423 band.isVariableUsedInReturns(variableName))
1424 {
1425 evaluationTime = JREvaluationTime.getBandEvaluationTime(band);
1426 }
1427
1428 return evaluationTime;
1429 }
1430
1431
1432 protected void initDelayedEvaluationPrint(JRRecordedValuesPrintElement printElement) throws JRException
1433 {
1434 for (Iterator<JREvaluationTime> it = delayedEvaluationsMap.keySet().iterator(); it.hasNext();)
1435 {
1436 JREvaluationTime evaluationTime = it.next();
1437 if (!evaluationTime.equals(JREvaluationTime.EVALUATION_TIME_NOW))
1438 {
1439 filler.addBoundElement(this, printElement, evaluationTime);
1440 }
1441 }
1442
1443 printElement.initRecordedValues(delayedEvaluationsMap.keySet());
1444
1445 if (delayedEvaluationsMap.containsKey(JREvaluationTime.EVALUATION_TIME_NOW))
1446 {
1447 delayedEvaluate(printElement, JREvaluationTime.EVALUATION_TIME_NOW, currentEvaluation);
1448 }
1449 }
1450
1451
1452 protected void delayedEvaluate(JRRecordedValuesPrintElement printElement, JREvaluationTime evaluationTime, byte evaluation) throws JRException
1453 {
1454 JRRecordedValues recordedValues = printElement.getRecordedValues();
1455 if (!recordedValues.lastEvaluationTime())
1456 {
1457 DelayedEvaluations delayedEvaluations = delayedEvaluationsMap.get(evaluationTime);
1458
1459 for (Iterator<String> it = delayedEvaluations.fields.iterator(); it.hasNext();)
1460 {
1461 String fieldName = it.next();
1462 JRFillField field = getField(fieldName);
1463 recordedValues.recordFieldValue(fieldName, field.getValue(evaluation));
1464 }
1465
1466 for (Iterator<String> it = delayedEvaluations.variables.iterator(); it.hasNext();)
1467 {
1468 String variableName = it.next();
1469 JRFillVariable variable = getVariable(variableName);
1470 recordedValues.recordVariableValue(variableName, variable.getValue(evaluation));
1471 }
1472 }
1473
1474 recordedValues.doneEvaluation(evaluationTime);
1475
1476 if (recordedValues.finishedEvaluations())
1477 {
1478 overwriteWithRecordedValues(recordedValues, evaluation);
1479 performDelayedEvaluation(printElement, evaluation);
1480 restoreValues(recordedValues, evaluation);
1481 printElement.deleteRecordedValues();
1482 }
1483 }
1484
1485
1486 private void overwriteWithRecordedValues(JRRecordedValues recordedValues, byte evaluation)
1487 {
1488 Map<String,Object> fieldValues = recordedValues.getRecordedFieldValues();
1489 if (fieldValues != null)
1490 {
1491 for (Iterator<Map.Entry<String,Object>> it = fieldValues.entrySet().iterator(); it.hasNext();)
1492 {
1493 Map.Entry<String,Object> entry = it.next();
1494 String fieldName = entry.getKey();
1495 Object fieldValue = entry.getValue();
1496 JRFillField field = getField(fieldName);
1497 field.overwriteValue(fieldValue, evaluation);
1498 }
1499 }
1500
1501 Map<String,Object> variableValues = recordedValues.getRecordedVariableValues();
1502 if (variableValues != null)
1503 {
1504 for (Iterator<Map.Entry<String,Object>> it = variableValues.entrySet().iterator(); it.hasNext();)
1505 {
1506 Map.Entry<String,Object> entry = it.next();
1507 String variableName = entry.getKey();
1508 Object variableValue = entry.getValue();
1509 JRFillVariable variable = getVariable(variableName);
1510 variable.overwriteValue(variableValue, evaluation);
1511 }
1512 }
1513 }
1514
1515 private void restoreValues(JRRecordedValues recordedValues, byte evaluation)
1516 {
1517 Map<String,Object> fieldValues = recordedValues.getRecordedFieldValues();
1518 if (fieldValues != null)
1519 {
1520 for (Iterator<String> it = fieldValues.keySet().iterator(); it.hasNext();)
1521 {
1522 String fieldName = it.next();
1523 JRFillField field = getField(fieldName);
1524 field.restoreValue(evaluation);
1525 }
1526 }
1527
1528 Map<String,Object> variableValues = recordedValues.getRecordedVariableValues();
1529 if (variableValues != null)
1530 {
1531 for (Iterator<String> it = variableValues.keySet().iterator(); it.hasNext();)
1532 {
1533 String variableName = it.next();
1534 JRFillVariable variable = getVariable(variableName);
1535 variable.restoreValue(evaluation);
1536 }
1537 }
1538 }
1539
1540
1543 public void setConditionalStylesContainer(JRFillElementContainer conditionalStylesContainer)
1544 {
1545 this.conditionalStylesContainer = conditionalStylesContainer;
1546 if (fillContainerContext == null)
1547 {
1548 fillContainerContext = conditionalStylesContainer;
1549 }
1550 }
1551
1552
1555 public JRFillElementContainer getConditionalStylesContainer()
1556 {
1557 return conditionalStylesContainer;
1558 }
1559
1560 @Override
1561 public JRStyle getStyle()
1562 {
1563
1564 if (currentStyle != null)
1565 {
1566 return currentStyle;
1567 }
1568
1569 JRStyle crtStyle = initStyle;
1570
1571 boolean isUsingDefaultStyle = false;
1572
1573 if (crtStyle == null)
1574 {
1575 crtStyle = filler.getDefaultStyle();
1576 isUsingDefaultStyle = true;
1577 }
1578
1579 JRStyle evalStyle = crtStyle;
1580
1581 if (conditionalStylesContainer != null)
1582 {
1583 evalStyle = conditionalStylesContainer.getEvaluatedConditionalStyle(crtStyle);
1584 }
1585 if (isUsingDefaultStyle && evalStyle == crtStyle)
1586 {
1587 evalStyle = null;
1588 }
1589
1590 return evalStyle;
1591 }
1592
1593
1596 protected JRTemplateElement getTemplate(JRStyle style)
1597 {
1598 return templates.get(style);
1599 }
1600
1601
1604 protected void registerTemplate(JRStyle style, JRTemplateElement template)
1605 {
1606 templates.put(style, template);
1607 }
1608
1609
1610
1617 protected final void setShrinkable(boolean shrinkable)
1618 {
1619 this.shrinkable = shrinkable;
1620 }
1621
1622
1623
1628 protected void stretchHeightFinal()
1629 {
1630
1631 }
1632
1633
1634 protected boolean isEvaluateNow()
1635 {
1636 boolean evaluateNow;
1637 switch (getEvaluationTimeValue())
1638 {
1639 case NOW:
1640 evaluateNow = true;
1641 break;
1642
1643 case AUTO:
1644 evaluateNow = isAutoEvaluateNow();
1645 break;
1646
1647 default:
1648 evaluateNow = false;
1649 break;
1650 }
1651 return evaluateNow;
1652 }
1653
1654
1655 protected boolean isAutoEvaluateNow()
1656 {
1657 return delayedEvaluationsMap == null || delayedEvaluationsMap.isEmpty()
1658 || (delayedEvaluationsMap.size() == 1
1659 && delayedEvaluationsMap.containsKey(JREvaluationTime.EVALUATION_TIME_NOW));
1660 }
1661
1662
1663 protected boolean isEvaluateAuto()
1664 {
1665 return getEvaluationTimeValue() == EvaluationTimeEnum.AUTO && !isAutoEvaluateNow();
1666 }
1667
1668 @Override
1669 public String getStyleNameReference()
1670 {
1671 return null;
1672 }
1673
1674 @Override
1675 public void setStyle(JRStyle style)
1676 {
1677 initStyle = style;
1678 if (conditionalStylesContainer != null)
1679 {
1680 conditionalStylesContainer.collectConditionalStyle(style);
1681 }
1682 }
1683
1684 @Override
1685 public void setStyleNameReference(String name)
1686 {
1687 throw new UnsupportedOperationException("Style name references not allowed at fill time");
1688 }
1689
1690 @Override
1691 public Object clone()
1692 {
1693 throw new UnsupportedOperationException();
1694 }
1695
1696 @Override
1697 public Object clone(JRElementGroup parentGroup)
1698 {
1699 throw new UnsupportedOperationException();
1700 }
1701
1702 @Override
1703 public JRElement clone(JRElementGroup parentGroup, int y)
1704 {
1705 throw new UnsupportedOperationException();
1706 }
1707
1708 @Override
1709 public boolean hasProperties()
1710 {
1711 return mergedProperties != null && mergedProperties.hasProperties();
1712 }
1713
1714 @Override
1715 public JRPropertiesMap getPropertiesMap()
1716 {
1717 return mergedProperties;
1718 }
1719
1720 @Override
1721 public JRPropertiesHolder getParentProperties()
1722 {
1723
1724 return filler.getMainDataset();
1725 }
1726
1727
1728 @Override
1729 public JRPropertyExpression[] getPropertyExpressions()
1730 {
1731 return propertyExpressions.toArray(new JRPropertyExpression[propertyExpressions.size()]);
1732 }
1733
1734 protected void transferProperties(JRTemplateElement template)
1735 {
1736 filler.getPropertiesUtil().transferProperties(parent, template,
1737 JasperPrint.PROPERTIES_PRINT_TRANSFER_PREFIX);
1738 }
1739
1740 protected void transferProperties(JRPrintElement element)
1741 {
1742 filler.getPropertiesUtil().transferProperties(dynamicProperties, element,
1743 dynamicTransferProperties);
1744 }
1745
1746 protected JRPropertiesMap getEvaluatedProperties()
1747 {
1748 return mergedProperties;
1749 }
1750
1751 protected void evaluateProperties(byte evaluation) throws JRException
1752 {
1753 if (propertyExpressions.isEmpty())
1754 {
1755 dynamicProperties = null;
1756 mergedProperties = staticProperties;
1757 }
1758 else
1759 {
1760 dynamicProperties = new JRPropertiesMap();
1761
1762 for (JRPropertyExpression prop : propertyExpressions)
1763 {
1764 String value = (String) evaluateExpression(prop.getValueExpression(), evaluation);
1765
1766 {
1767 dynamicProperties.setProperty(prop.getName(), value);
1768 }
1769 }
1770
1771 mergedProperties = dynamicProperties.cloneProperties();
1772 mergedProperties.setBaseProperties(staticProperties);
1773 }
1774 }
1775
1776 protected void setOriginProvider(JROriginProvider originProvider)
1777 {
1778 this.originProvider = originProvider;
1779 }
1780
1781 protected JROrigin getElementOrigin()
1782 {
1783 JROrigin elementOrigin = null;
1784 if (originProvider != null)
1785 {
1786 elementOrigin = originProvider.getOrigin();
1787 }
1788 return elementOrigin;
1789 }
1790
1791 protected boolean isDelayedStyleEvaluation()
1792 {
1793 return filler.getPropertiesUtil().getBooleanProperty(this,
1794 JRStyle.PROPERTY_EVALUATION_TIME_ENABLED, false);
1795 }
1796
1797 public JRBaseFiller getFiller()
1798 {
1799 return filler;
1800 }
1801
1802
1803 @Override
1804 public boolean hasDynamicProperties()
1805 {
1806 return !propertyExpressions.isEmpty();
1807 }
1808
1809 @Override
1810 public boolean hasDynamicProperty(String name)
1811 {
1812
1813 for (JRPropertyExpression prop : propertyExpressions)
1814 {
1815 if (prop.getName().equals(name))
1816 {
1817 return true;
1818 }
1819 }
1820 return false;
1821 }
1822
1823 @Override
1824 public JRPropertiesMap getDynamicProperties()
1825 {
1826 return dynamicProperties;
1827 }
1828
1829 protected JRStyle getInitStyle()
1830 {
1831 return initStyle;
1832 }
1833
1834 protected JRElement getParent()
1835 {
1836 return parent;
1837 }
1838
1839 protected void addDynamicProperty(String name, JRExpression expression)
1840 {
1841 JRDesignPropertyExpression prop = new JRDesignPropertyExpression();
1842 prop.setName(name);
1843 prop.setValueExpression(expression);
1844
1845 propertyExpressions.add(prop);
1846
1847 dynamicTransferProperties = findDynamicTransferProperties();
1848 }
1849
1850 protected void setExpressionEvaluator(JRFillExpressionEvaluator expressionEvaluator)
1851 {
1852 this.expressionEvaluator = expressionEvaluator;
1853 }
1854
1855
1856
1859 public static Integer getBookmarkLevel(Object value) throws JRException
1860 {
1861 Integer level = null;
1862
1863 if (value != null)
1864 {
1865 if (value instanceof Number)
1866 {
1867 level = ((Number)value).intValue();
1868 }
1869 else
1870 {
1871 try
1872 {
1873 level = Integer.parseInt(value.toString());
1874 }
1875 catch (NumberFormatException e)
1876 {
1877
1878 }
1879 }
1880
1881 if (level == null || level < 0)
1882 {
1883 throw
1884 new JRException(
1885 EXCEPTION_MESSAGE_KEY_INVALID_BOOKMARK_LEVEL,
1886 new Object[] {value}
1887 );
1888 }
1889 }
1890
1891 return level;
1892 }
1893 }
1894