1
24
25
29 package net.sf.jasperreports.engine.fill;
30
31 import java.util.Map;
32
33 import net.sf.jasperreports.annotations.properties.Property;
34 import net.sf.jasperreports.annotations.properties.PropertyScope;
35 import net.sf.jasperreports.engine.JRException;
36 import net.sf.jasperreports.engine.JRExpression;
37 import net.sf.jasperreports.engine.JRPropertiesUtil;
38 import net.sf.jasperreports.engine.JRVariable;
39 import net.sf.jasperreports.engine.type.DatasetResetTypeEnum;
40 import net.sf.jasperreports.engine.type.IncrementTypeEnum;
41 import net.sf.jasperreports.engine.type.ResetTypeEnum;
42 import net.sf.jasperreports.engine.type.WhenResourceMissingTypeEnum;
43 import net.sf.jasperreports.properties.PropertyConstants;
44
45
46
69 public class JRCalculator implements JRFillExpressionEvaluator
70 {
71
72
75 @Property(
76 category = PropertyConstants.CATEGORY_FILL,
77 defaultValue = PropertyConstants.BOOLEAN_FALSE,
78 scopes = {PropertyScope.CONTEXT},
79 sinceVersion = PropertyConstants.VERSION_6_5_0,
80 valueType = Boolean.class
81 )
82 public static final String PROPERTY_LEGACY_BAND_EVALUATION_ENABLED =
83 JRPropertiesUtil.PROPERTY_PREFIX + "legacy.band.evaluation.enabled";
84
85
88 protected JRFillDataset dataset;
89 protected Map<String, JRFillParameter> parsm;
90 protected Map<String, JRFillField> fldsm;
91 protected Map<String, JRFillVariable> varsm;
92 protected JRFillVariable[] variables;
93 protected JRFillGroup[] groups;
94 protected JRFillElementDataset[] datasets;
95
96 private JRFillVariable pageNumber;
97 private JRFillVariable columnNumber;
98
99
102 private boolean legacyBandEvaluationEnabled;
103
104
107 private final DatasetExpressionEvaluator evaluator;
108
109
110
115 protected JRCalculator(DatasetExpressionEvaluator evaluator)
116 {
117 this.evaluator = evaluator;
118 }
119
120
121
126 protected JRCalculator(JREvaluator evaluator)
127 {
128 this((DatasetExpressionEvaluator) evaluator);
129 }
130
131
132
138 protected void init(JRFillDataset dataset) throws JRException
139 {
140 this.dataset = dataset;
141 parsm = dataset.parametersMap;
142 fldsm = dataset.fieldsMap;
143 varsm = dataset.variablesMap;
144 variables = dataset.variables;
145 groups = dataset.groups;
146 datasets = dataset.elementDatasets;
147
148 pageNumber = varsm.get(JRVariable.PAGE_NUMBER);
149 columnNumber = varsm.get(JRVariable.COLUMN_NUMBER);
150
151 WhenResourceMissingTypeEnum whenResourceMissingType = dataset.getWhenResourceMissingTypeValue();
152 boolean ignoreNPE =
153 JRPropertiesUtil.getInstance(getFillDataset().getJasperReportsContext())
154 .getBooleanProperty(
155 getFillDataset(),
156 JREvaluator.PROPERTY_IGNORE_NPE,
157 true
158 );
159 evaluator.init(parsm, fldsm,varsm, whenResourceMissingType, ignoreNPE);
160
161 legacyBandEvaluationEnabled =
162 JRPropertiesUtil.getInstance(getFillDataset().getJasperReportsContext())
163 .getBooleanProperty(
164 PROPERTY_LEGACY_BAND_EVALUATION_ENABLED
165 );
166 }
167
168
169
172 public JRFillVariable getPageNumber()
173 {
174 return pageNumber;
175 }
176
177
178
181 public JRFillVariable getColumnNumber()
182 {
183 return columnNumber;
184 }
185
186
187
190 public void calculateVariables(boolean incrementDatasets) throws JRException
191 {
192 if (variables != null && variables.length > 0)
193 {
194 for (int i = 0; i < variables.length; i++)
195 {
196 JRFillVariable variable = variables[i];
197 Object expressionValue = evaluate(variable.getExpression());
198 Object newValue = variable.getIncrementer().increment(variable, expressionValue, AbstractValueProvider.getCurrentValueProvider());
199 variable.setValue(newValue);
200 variable.setInitialized(false);
201 variable.setPreviousIncrementedValue(variable.getIncrementedValue());
202
203 if (variable.getIncrementTypeValue() == IncrementTypeEnum.NONE)
204 {
205 variable.setIncrementedValue(variable.getValue());
206 }
207 }
208 }
209
210 if (incrementDatasets && datasets != null && datasets.length > 0)
211 {
212 for (int i = 0; i < datasets.length; i++)
213 {
214 JRFillElementDataset elementDataset = datasets[i];
215 elementDataset.evaluate(this);
216
217 if (elementDataset.getIncrementTypeValue() == IncrementTypeEnum.NONE)
218 {
219 elementDataset.increment();
220 }
221 }
222 }
223 }
224
225
226 protected void recalculateVariables() throws JRException
227 {
228 if (variables != null)
229 {
230 for (JRFillVariable variable : variables)
231 {
232 variable.setIncrementedValue(variable.getPreviousIncrementedValue());
233 }
234 }
235
236 calculateVariables(false);
237 }
238
239
240
243 public void estimateVariables() throws JRException
244 {
245 if (variables != null && variables.length > 0)
246 {
247 for(int i = 0; i < variables.length; i++)
248 {
249 JRFillVariable variable = variables[i];
250 Object expressionValue = evaluateEstimated(variable.getExpression());
251 Object newValue = variable.getIncrementer().increment(variable, expressionValue, AbstractValueProvider.getEstimatedValueProvider());
252 variable.setEstimatedValue(newValue);
253
254 }
255 }
256 }
257
258
259
267 public void estimateGroupRuptures() throws JRException
268 {
269 if (groups != null && groups.length > 0)
270 {
271
272
273
274 for(int i = groups.length - 1; i >= 0; i--)
275 {
276 JRFillGroup group = groups[i];
277
278 Object oldValue = evaluateOld(group.getExpression());
279 Object estimatedValue = evaluateEstimated(group.getExpression());
280
281 if (
282 (oldValue == null && estimatedValue != null) ||
283 (oldValue != null && !oldValue.equals(estimatedValue))
284 )
285 {
286 group.setHasChanged(true);
287 }
288 else
289 {
290 group.setHasChanged(false);
291 }
292 }
293
294
295
296 if (variables != null && variables.length > 0)
297 {
298 for(int i = 0; i < variables.length; i++)
299 {
300 JRFillVariable variable = variables[i];
301 if (variable.getIncrementTypeValue() == IncrementTypeEnum.GROUP)
302 {
303 JRFillGroup group = (JRFillGroup)variable.getIncrementGroup();
304 if (group.hasChanged())
305 {
306 variable.setIncrementedValue(variable.getValue());
307 }
308 }
309 }
310 }
311
312
313
314 estimateVariables();
315
316 boolean groupHasChanged = false;
317 for(int i = 0; i < groups.length; i++)
318 {
319 JRFillGroup group = groups[i];
320
321 boolean isTopLevelChange = false;
322
323 if (!groupHasChanged)
324 {
325 Object oldValue = evaluateOld(group.getExpression());
326 Object estimatedValue = evaluateEstimated(group.getExpression());
327
328 if (
329 (oldValue == null && estimatedValue != null) ||
330 (oldValue != null && !oldValue.equals(estimatedValue))
331 )
332 {
333 groupHasChanged = true;
334 isTopLevelChange = true;
335 }
336 }
337
338 group.setHasChanged(groupHasChanged);
339 group.setTopLevelChange(isTopLevelChange);
340 }
341 }
342 }
343
344
345
348 public void initializeVariables(ResetTypeEnum resetType, IncrementTypeEnum incrementType) throws JRException
349 {
350 if (variables != null && variables.length > 0)
351 {
352 for(int i = 0; i < variables.length; i++)
353 {
354 incrementVariable(variables[i], incrementType);
355 initializeVariable(variables[i], resetType);
356 }
357 }
358
359 if (datasets != null && datasets.length > 0)
360 {
361 for(int i = 0; i < datasets.length; i++)
362 {
363 incrementDataset(datasets[i], incrementType);
364 initializeDataset(datasets[i], resetType);
365 }
366 }
367 }
368
369
370
373 private void incrementVariable(JRFillVariable variable, IncrementTypeEnum incrementType)
374 {
375 if (variable.getIncrementTypeValue() != IncrementTypeEnum.NONE)
376 {
377 boolean toIncrement = false;
378 boolean toSetPreviousValue = false;
379 switch (incrementType)
380 {
381 case REPORT :
382 {
383 toIncrement = true;
384 break;
385 }
386 case PAGE :
387 {
388 toIncrement =
389 (
390 variable.getIncrementTypeValue() == IncrementTypeEnum.PAGE ||
391 variable.getIncrementTypeValue() == IncrementTypeEnum.COLUMN
392 );
393 toSetPreviousValue = toIncrement;
394 break;
395 }
396 case COLUMN :
397 {
398 toIncrement = (variable.getIncrementTypeValue() == IncrementTypeEnum.COLUMN);
399 toSetPreviousValue = toIncrement;
400 break;
401 }
402 case GROUP :
403 {
404 if (variable.getIncrementTypeValue() == IncrementTypeEnum.GROUP)
405 {
406 JRFillGroup group = (JRFillGroup)variable.getIncrementGroup();
407 toIncrement = group.hasChanged();
408 }
409 break;
410 }
411 case NONE :
412 default :
413 {
414 }
415 }
416
417 if (toIncrement)
418 {
419 variable.setIncrementedValue(variable.getValue());
420 if (toSetPreviousValue && !legacyBandEvaluationEnabled)
421 {
422 variable.setPreviousIncrementedValue(variable.getValue());
423 }
424
425
426
427
428 }
429 }
430 else
431 {
432 variable.setIncrementedValue(variable.getValue());
433
434
435
436 }
437 }
438
439
440
443 private void incrementDataset(JRFillElementDataset elementDataset, IncrementTypeEnum incrementType)
444 {
445 if (elementDataset.getIncrementTypeValue() != IncrementTypeEnum.NONE)
446 {
447 boolean toIncrement = false;
448 switch (incrementType)
449 {
450 case REPORT :
451 {
452 toIncrement = true;
453 break;
454 }
455 case PAGE :
456 {
457 toIncrement =
458 (
459 elementDataset.getIncrementTypeValue() == IncrementTypeEnum.PAGE ||
460 elementDataset.getIncrementTypeValue() == IncrementTypeEnum.COLUMN
461 );
462 break;
463 }
464 case COLUMN :
465 {
466 toIncrement = (elementDataset.getIncrementTypeValue() == IncrementTypeEnum.COLUMN);
467 break;
468 }
469 case GROUP :
470 {
471 if (elementDataset.getIncrementTypeValue() == IncrementTypeEnum.GROUP)
472 {
473 JRFillGroup group = (JRFillGroup)elementDataset.getIncrementGroup();
474 toIncrement = group.hasChanged();
475 }
476 break;
477 }
478 case NONE :
479 default :
480 {
481 }
482 }
483
484 if (toIncrement)
485 {
486 elementDataset.increment();
487 }
488 }
489 }
490
491
492
495 private void initializeVariable(JRFillVariable variable, ResetTypeEnum resetType) throws JRException
496 {
497
498 if (variable.getResetTypeValue() != ResetTypeEnum.NONE)
499 {
500 boolean toInitialize = false;
501 boolean toSetOldValue = false;
502 switch (resetType)
503 {
504 case REPORT :
505 {
506 toInitialize = true;
507 break;
508 }
509 case PAGE :
510 {
511 toInitialize =
512 (
513 variable.getResetTypeValue() == ResetTypeEnum.PAGE ||
514 variable.getResetTypeValue() == ResetTypeEnum.COLUMN
515 );
516 toSetOldValue = toInitialize;
517 break;
518 }
519 case COLUMN :
520 {
521 toInitialize = (variable.getResetTypeValue() == ResetTypeEnum.COLUMN);
522 toSetOldValue = toInitialize;
523 break;
524 }
525 case GROUP :
526 {
527 if (variable.getResetTypeValue() == ResetTypeEnum.GROUP)
528 {
529 JRFillGroup group = (JRFillGroup)variable.getResetGroup();
530 toInitialize = group.hasChanged();
531 }
532 break;
533 }
534 case NONE :
535 default :
536 {
537 }
538 }
539
540 if (toInitialize)
541 {
542 variable.setValue(
543 evaluate(variable.getInitialValueExpression())
544 );
545 variable.setInitialized(true);
546 variable.setIncrementedValue(null);
547 if (toSetOldValue && !legacyBandEvaluationEnabled)
548 {
549 variable.setOldValue(variable.getValue());
550 variable.setPreviousIncrementedValue(null);
551 }
552 }
553 }
554 else
555 {
556 variable.setValue(
557 evaluate(variable.getExpression())
558 );
559 variable.setIncrementedValue(variable.getValue());
560 }
561 }
562
563
564
567 private void initializeDataset(JRFillElementDataset elementDataset, ResetTypeEnum resetType)
568 {
569 boolean toInitialize = false;
570 switch (resetType)
571 {
572 case REPORT :
573 {
574 toInitialize = true;
575 break;
576 }
577 case PAGE :
578 {
579 toInitialize =
580 (
581 elementDataset.getDatasetResetType() == DatasetResetTypeEnum.PAGE ||
582 elementDataset.getDatasetResetType() == DatasetResetTypeEnum.COLUMN
583 );
584 break;
585 }
586 case COLUMN :
587 {
588 toInitialize = (elementDataset.getDatasetResetType() == DatasetResetTypeEnum.COLUMN);
589 break;
590 }
591 case GROUP :
592 {
593 if (elementDataset.getDatasetResetType() == DatasetResetTypeEnum.GROUP)
594 {
595 JRFillGroup group = (JRFillGroup)elementDataset.getResetGroup();
596 toInitialize = group.hasChanged();
597 }
598 else if (elementDataset.getDatasetResetType() == DatasetResetTypeEnum.NONE)
599 {
600
601 toInitialize = true;
602 }
603 break;
604 }
605 case NONE :
606 default :
607 {
608 }
609 }
610
611 if (toInitialize)
612 {
613 elementDataset.initialize();
614 }
615 }
616
617
618 @Override
619 public Object evaluate(
620 JRExpression expression,
621 byte evaluationType
622 ) throws JRException
623 {
624 Object value = null;
625
626 switch (evaluationType)
627 {
628 case JRExpression.EVALUATION_OLD :
629 {
630 value = evaluateOld(expression);
631 break;
632 }
633 case JRExpression.EVALUATION_ESTIMATED :
634 {
635 value = evaluateEstimated(expression);
636 break;
637 }
638 case JRExpression.EVALUATION_DEFAULT :
639 default :
640 {
641 value = evaluate(expression);
642 break;
643 }
644 }
645
646 return value;
647 }
648
649
650
653 public Object evaluateOld(JRExpression expression) throws JRExpressionEvalException
654 {
655 return evaluator.evaluateOld(expression);
656 }
657
658
659
662 public Object evaluateEstimated(JRExpression expression) throws JRExpressionEvalException
663 {
664 return evaluator.evaluateEstimated(expression);
665 }
666
667
668
671 public Object evaluate(JRExpression expression) throws JRExpressionEvalException
672 {
673 return evaluator.evaluate(expression);
674 }
675
676
677 @Override
678 public JRFillDataset getFillDataset()
679 {
680 return dataset;
681 }
682 }
683