1
24 package net.sf.jasperreports.engine.fill;
25
26 import java.sql.Connection;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Locale;
32 import java.util.Map;
33 import java.util.TimeZone;
34
35 import org.apache.commons.javaflow.api.continuable;
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38
39 import net.sf.jasperreports.engine.BookmarkHelper;
40 import net.sf.jasperreports.engine.JRAbstractScriptlet;
41 import net.sf.jasperreports.engine.JRDataSource;
42 import net.sf.jasperreports.engine.JRDataset;
43 import net.sf.jasperreports.engine.JRException;
44 import net.sf.jasperreports.engine.JRExpression;
45 import net.sf.jasperreports.engine.JRParameter;
46 import net.sf.jasperreports.engine.JRPrintElement;
47 import net.sf.jasperreports.engine.JRPrintPage;
48 import net.sf.jasperreports.engine.JRPropertiesUtil;
49 import net.sf.jasperreports.engine.JRRuntimeException;
50 import net.sf.jasperreports.engine.JRVirtualizer;
51 import net.sf.jasperreports.engine.JasperPrint;
52 import net.sf.jasperreports.engine.JasperReport;
53 import net.sf.jasperreports.engine.JasperReportsContext;
54 import net.sf.jasperreports.engine.ReportContext;
55 import net.sf.jasperreports.engine.base.JRVirtualPrintPage;
56 import net.sf.jasperreports.engine.type.CalculationEnum;
57 import net.sf.jasperreports.engine.util.DefaultFormatFactory;
58 import net.sf.jasperreports.engine.util.FormatFactory;
59 import net.sf.jasperreports.engine.util.JRGraphEnvInitializer;
60 import net.sf.jasperreports.repo.RepositoryContext;
61 import net.sf.jasperreports.repo.SimpleRepositoryContext;
62
63
66 public abstract class BaseReportFiller implements ReportFiller
67 {
68 private static final Log log = LogFactory.getLog(BaseReportFiller.class);
69
70 protected JasperReportsContext jasperReportsContext;
71 protected JRPropertiesUtil propertiesUtil;
72
73 protected JRFillContext fillContext;
74
75 protected FillerParent parent;
76
77 protected final int fillerId;
78
79 protected List<String> printTransferPropertyPrefixes;
80
81 protected JasperReportSource reportSource;
82
83
86 protected JasperReport jasperReport;
87
88 protected RepositoryContext repositoryContext;
89
90 protected JRCalculator calculator;
91
92 protected final JRFillObjectFactory factory;
93
94
97 protected JRFillDataset mainDataset;
98
99
102 protected Map<String,JRFillDataset> datasetMap;
103
104 protected DelayedFillActions delayedActions;
105
106 protected JRAbstractScriptlet scriptlet;
107
108 protected FormatFactory formatFactory;
109
110 protected boolean ignorePagination;
111
112 protected BookmarkHelper bookmarkHelper;
113
114 protected JRVirtualizationContext virtualizationContext;
115
116 protected JasperPrint jasperPrint;
117
118 protected Thread fillingThread;
119
120 private boolean isInterrupted;
121 private boolean threadInterrupted;
122
123 protected FillListener fillListener;
124
125 protected int usedPageWidth = 0;
126
127 public BaseReportFiller(JasperReportsContext jasperReportsContext, JasperReport jasperReport,
128 FillerParent parent) throws JRException
129 {
130 this(jasperReportsContext, SimpleJasperReportSource.from(jasperReport), parent);
131 }
132
133 public BaseReportFiller(JasperReportsContext jasperReportsContext, JasperReportSource reportSource,
134 FillerParent parent) throws JRException
135 {
136 JRGraphEnvInitializer.initializeGraphEnv();
137
138 setJasperReportsContext(jasperReportsContext);
139
140 this.reportSource = reportSource;
141 this.jasperReport = reportSource.getReport();
142 this.repositoryContext = SimpleRepositoryContext.of(jasperReportsContext, reportSource.getRepositoryReportContext());
143 jasperReportSet();
144
145 this.parent = parent;
146
147 DatasetExpressionEvaluator initEvaluator = null;
148 if (parent == null)
149 {
150 fillContext = new JRFillContext(this);
151 printTransferPropertyPrefixes = readPrintTransferPropertyPrefixes();
152 }
153 else
154 {
155 fillContext = parent.getFiller().fillContext;
156 printTransferPropertyPrefixes = parent.getFiller().printTransferPropertyPrefixes;
157 initEvaluator = parent.getCachedEvaluator();
158 }
159
160 this.fillerId = fillContext.generatedFillerId();
161 if (log.isDebugEnabled())
162 {
163 log.debug("Fill " + fillerId + ": created for " + jasperReport.getName());
164 }
165
166 if (initEvaluator == null)
167 {
168 calculator = JRFillDataset.createCalculator(jasperReportsContext, jasperReport, jasperReport.getMainDataset());
169 }
170 else
171 {
172 calculator = new JRCalculator(initEvaluator);
173 }
174
175 jasperPrint = new JasperPrint();
176
177 factory = initFillFactory();
178
179 createDatasets();
180 mainDataset = factory.getDataset(jasperReport.getMainDataset());
181
182 if (parent == null)
183 {
184 FillDatasetPosition masterFillPosition = new FillDatasetPosition(null);
185 mainDataset.setFillPosition(masterFillPosition);
186 }
187
188 delayedActions = new DelayedFillActions(this);
189 if (log.isDebugEnabled())
190 {
191 log.debug("created delayed actions " + delayedActions.getId() + " for filler " + fillerId);
192 }
193 }
194
195 protected abstract void jasperReportSet();
196
197 private List<String> readPrintTransferPropertyPrefixes()
198 {
199 List<JRPropertiesUtil.PropertySuffix> transferProperties = propertiesUtil.getProperties(
200 JasperPrint.PROPERTIES_PRINT_TRANSFER_PREFIX);
201 List<String> prefixes = new ArrayList<String>(transferProperties.size());
202 for (JRPropertiesUtil.PropertySuffix property : transferProperties)
203 {
204 String transferPrefix = property.getValue();
205 if (transferPrefix != null && transferPrefix.length() > 0)
206 {
207 prefixes.add(transferPrefix);
208 }
209 }
210 return prefixes;
211 }
212
213 protected abstract JRFillObjectFactory initFillFactory();
214
215 private void createDatasets() throws JRException
216 {
217 datasetMap = new HashMap<String,JRFillDataset>();
218
219 JRDataset[] datasets = jasperReport.getDatasets();
220 if (datasets != null && datasets.length > 0)
221 {
222 for (int i = 0; i < datasets.length; i++)
223 {
224 JRFillDataset fillDataset = factory.getDataset(datasets[i]);
225 fillDataset.createCalculator(jasperReport);
226
227 datasetMap.put(datasets[i].getName(), fillDataset);
228 }
229 }
230 }
231
232 protected final void initDatasets() throws JRException
233 {
234 mainDataset.initElementDatasets(factory);
235 initDatasets(factory);
236
237 mainDataset.checkVariableCalculationReqs(factory);
238
239 mainDataset.setCalculator(calculator);
240 mainDataset.initCalculator();
241 }
242
243 private void initDatasets(JRFillObjectFactory factory)
244 {
245 for (Iterator<JRFillDataset> it = datasetMap.values().iterator(); it.hasNext();)
246 {
247 JRFillDataset dataset = it.next();
248 dataset.inheritFromMain();
249 dataset.initElementDatasets(factory);
250 }
251 }
252
253 protected final void createBoundElementMaps(JREvaluationTime evaluationTime)
254 {
255 delayedActions.createDelayedEvaluationTime(evaluationTime);
256 }
257
258
263 @Override
264 public void addFillListener(FillListener fillListener)
265 {
266 this.fillListener = CompositeFillListener.addListener(this.fillListener, fillListener);
267 }
268
269 public JasperReportsContext getJasperReportsContext()
270 {
271 return jasperReportsContext;
272 }
273
274 public RepositoryContext getRepositoryContext()
275 {
276 return repositoryContext;
277 }
278
279 public JRPropertiesUtil getPropertiesUtil()
280 {
281 return propertiesUtil;
282 }
283
284 public JasperReportSource getReportSource()
285 {
286 return reportSource;
287 }
288
289
294 public JasperReport getJasperReport()
295 {
296 return jasperReport;
297 }
298
299 public JasperPrint getJasperPrint()
300 {
301 return jasperPrint;
302 }
303
304 protected void setJasperReportsContext(JasperReportsContext jasperReportsContext)
305 {
306 this.jasperReportsContext = jasperReportsContext;
307 this.propertiesUtil = JRPropertiesUtil.getInstance(jasperReportsContext);
308 }
309
310 protected final void setParametersToContext(Map<String,Object> parameterValues)
311 {
312 @SuppressWarnings("deprecation")
313 JasperReportsContext localContext =
314 net.sf.jasperreports.engine.util.LocalJasperReportsContext.getLocalContext(jasperReportsContext, parameterValues);
315 if (localContext != jasperReportsContext)
316 {
317 setJasperReportsContext(localContext);
318 }
319 }
320
321 protected void initVirtualizationContext(Map<String, Object> parameterValues)
322 {
323 if (isSubreport())
324 {
325 if (fillContext.isUsingVirtualizer())
326 {
327 if (parent.isParentPagination())
328 {
329
330
331
332 virtualizationContext = new JRVirtualizationContext(fillContext.getVirtualizationContext());
333
334
335 setVirtualPageSize(parameterValues);
336 }
337 else
338 {
339
340
341 virtualizationContext = fillContext.getVirtualizationContext();
342 }
343 }
344 }
345 else
346 {
347
348 JRVirtualizer virtualizer = (JRVirtualizer) parameterValues.get(JRParameter.REPORT_VIRTUALIZER);
349 if (virtualizer == null)
350 {
351 return;
352 }
353
354 if (log.isDebugEnabled())
355 {
356 log.debug("Fill " + fillerId + ": using virtualizer " + virtualizer);
357 }
358
359 fillContext.setUsingVirtualizer(true);
360
361 virtualizationContext = fillContext.getVirtualizationContext();
362 virtualizationContext.setVirtualizer(virtualizer);
363
364 setVirtualPageSize(parameterValues);
365
366 JRVirtualizationContext.register(virtualizationContext, jasperPrint);
367 }
368
369 if (virtualizationContext != null && log.isDebugEnabled())
370 {
371 log.debug("filler " + fillerId + " created virtualization context " + virtualizationContext);
372 }
373 }
374
375 protected void setVirtualPageSize(Map<String, Object> parameterValues)
376 {
377
378 Integer virtualPageSize = (Integer) parameterValues.get(
379 JRVirtualPrintPage.PROPERTY_VIRTUAL_PAGE_ELEMENT_SIZE);
380 if (virtualPageSize == null)
381 {
382
383 String pageSizeProp = jasperReport.getPropertiesMap().getProperty(
384 JRVirtualPrintPage.PROPERTY_VIRTUAL_PAGE_ELEMENT_SIZE);
385 if (pageSizeProp != null)
386 {
387 virtualPageSize = JRPropertiesUtil.asInteger(pageSizeProp);
388 }
389 }
390
391 if (virtualPageSize != null)
392 {
393 if (log.isDebugEnabled())
394 {
395 log.debug("virtual page size " + virtualPageSize);
396 }
397
398
399 virtualizationContext.setPageElementSize(virtualPageSize);
400 }
401 }
402
403 @Override
404 @continuable
405 public JasperPrint fill(Map<String,Object> parameterValues, Connection conn) throws JRException
406 {
407 if (parameterValues == null)
408 {
409 parameterValues = new HashMap<String,Object>();
410 }
411
412 setConnectionParameterValue(parameterValues, conn);
413
414 return fill(parameterValues);
415 }
416
417 protected void setConnectionParameterValue(Map<String,Object> parameterValues, Connection conn)
418 {
419 mainDataset.setConnectionParameterValue(parameterValues, conn);
420 }
421
422 @Override
423 @continuable
424 public JasperPrint fill(Map<String,Object> parameterValues, JRDataSource ds) throws JRException
425 {
426 if (parameterValues == null)
427 {
428 parameterValues = new HashMap<String,Object>();
429 }
430
431 setDatasourceParameterValue(parameterValues, ds);
432
433 return fill(parameterValues);
434 }
435
436 protected void setDatasourceParameterValue(Map<String,Object> parameterValues, JRDataSource ds)
437 {
438 mainDataset.setDatasourceParameterValue(parameterValues, ds);
439 }
440
441 protected void setParameters(Map<String,Object> parameterValues) throws JRException
442 {
443 initVirtualizationContext(parameterValues);
444
445 setFormatFactory(parameterValues);
446
447 setIgnorePagination(parameterValues);
448
449 if (parent == null)
450 {
451 ReportContext reportContext = (ReportContext) parameterValues.get(JRParameter.REPORT_CONTEXT);
452 fillContext.setReportContext(reportContext);
453 }
454
455 mainDataset.setParameterValues(parameterValues);
456 mainDataset.evaluateFieldProperties();
457 mainDataset.initDatasource();
458
459 this.scriptlet = mainDataset.delegateScriptlet;
460
461 if (!isSubreport())
462 {
463 fillContext.setMasterFormatFactory(getFormatFactory());
464 fillContext.setMasterLocale(getLocale());
465 fillContext.setMasterTimeZone(getTimeZone());
466 }
467 }
468
469 protected void setBookmarkHelper()
470 {
471 boolean isCreateBookmarks = propertiesUtil.getBooleanProperty(mainDataset,
472 JasperPrint.PROPERTY_CREATE_BOOKMARKS, false);
473 if (isCreateBookmarks)
474 {
475 boolean collapseMissingLevels = propertiesUtil.getBooleanProperty(mainDataset,
476 JasperPrint.PROPERTY_COLLAPSE_MISSING_BOOKMARK_LEVELS, false);
477 bookmarkHelper = new BookmarkHelper(collapseMissingLevels);
478 }
479 }
480
481 protected void setIgnorePagination(Map<String,Object> parameterValues)
482 {
483 boolean ignore;
484 if (parent == null)
485 {
486 ignore = getOwnIgnorePagination(parameterValues, false);
487 }
488 else
489 {
490 if (parent.isParentPagination())
491 {
492
493 ignore = parent.getFiller().ignorePagination;
494 }
495 else
496 {
497
498
499 Boolean ownIgnorePagination = getOwnIgnorePagination(parameterValues, true);
500 if (ownIgnorePagination != null)
501 {
502 ignore = ownIgnorePagination;
503 }
504 else
505 {
506
507 ignore = parent.getFiller().ignorePagination;
508 }
509 }
510 }
511
512 ignorePagination = ignore;
513 parameterValues.put(JRParameter.IS_IGNORE_PAGINATION, ignorePagination);
514 ignorePaginationSet(parameterValues);
515 }
516
517 protected Boolean getOwnIgnorePagination(Map<String,Object> parameterValues, boolean onlySetAttribute)
518 {
519 Boolean isIgnorePaginationParam = (Boolean) parameterValues.get(JRParameter.IS_IGNORE_PAGINATION);
520 if (isIgnorePaginationParam != null)
521 {
522 return isIgnorePaginationParam;
523 }
524
525 boolean ignorePaginationAttribute = jasperReport.isIgnorePagination();
526 if (ignorePaginationAttribute)
527 {
528 return ignorePaginationAttribute;
529 }
530
531 return onlySetAttribute ? null : false;
532 }
533
534 protected abstract void ignorePaginationSet(Map<String, Object> parameterValues);
535
536 public boolean isIgnorePagination()
537 {
538 return ignorePagination;
539 }
540
541 protected boolean isInterrupted()
542 {
543 return (isInterrupted || threadInterrupted || (parent != null && parent.getFiller().isInterrupted()));
544 }
545
546 protected boolean isDeliberatelyInterrupted()
547 {
548 return (isInterrupted || (parent != null && parent.getFiller().isDeliberatelyInterrupted()));
549 }
550
551 protected void setInterrupted(boolean isInterrupted)
552 {
553 this.isInterrupted = isInterrupted;
554 }
555
556 protected void checkInterrupted()
557 {
558 if (Thread.interrupted())
559 {
560 threadInterrupted = true;
561 }
562
563 if (isInterrupted())
564 {
565 if (log.isDebugEnabled())
566 {
567 log.debug("Fill " + fillerId + ": interrupting");
568 }
569
570 throw new JRFillInterruptedException();
571 }
572 }
573
574 @Override
575 public JRFillContext getFillContext()
576 {
577 return fillContext;
578 }
579
580 public JRVirtualizationContext getVirtualizationContext()
581 {
582 return virtualizationContext;
583 }
584
585 public JRFillDataset getMainDataset()
586 {
587 return mainDataset;
588 }
589
590
595 public Map<String,Object> getParameterValuesMap()
596 {
597 return mainDataset.getParameterValuesMap();
598 }
599
600
605 protected Map<String,JRFillParameter> getParametersMap()
606 {
607 return mainDataset.parametersMap;
608 }
609
610
616 public Object getParameterValue(String parameterName)
617 {
618 return mainDataset.getParameterValue(parameterName);
619 }
620
621
626 protected Locale getLocale()
627 {
628 return mainDataset.getLocale();
629 }
630
631
636 protected TimeZone getTimeZone()
637 {
638 return mainDataset.timeZone;
639 }
640
641
649 protected void addVariableCalculationReq(String variableName, CalculationEnum calculation)
650 {
651 mainDataset.addVariableCalculationReq(variableName, calculation);
652 }
653
654
660 public JRFillVariable getVariable(String variableName)
661 {
662 return mainDataset.getVariable(variableName);
663 }
664
665
675 public Object getVariableValue(String variableName)
676 {
677 return mainDataset.getVariableValue(variableName);
678 }
679
680 protected JRFillExpressionEvaluator getExpressionEvaluator()
681 {
682 return calculator;
683 }
684
685 protected boolean isSubreport()
686 {
687 return parent != null;
688 }
689
690 protected boolean isMasterReport()
691 {
692 return parent == null;
693 }
694
695
702 public Object evaluateExpression(JRExpression expression, byte evaluation) throws JRException
703 {
704 return mainDataset.evaluateExpression(expression, evaluation);
705 }
706
707 protected final void setFormatFactory(Map<String,Object> parameterValues)
708 {
709 formatFactory = (FormatFactory)parameterValues.get(JRParameter.REPORT_FORMAT_FACTORY);
710 if (formatFactory == null)
711 {
712 formatFactory = DefaultFormatFactory.createFormatFactory(jasperReport.getFormatFactoryClass());
713 parameterValues.put(JRParameter.REPORT_FORMAT_FACTORY, formatFactory);
714 }
715 }
716
717
722 protected FormatFactory getFormatFactory()
723 {
724 return formatFactory;
725 }
726
727 protected void addLastPageBookmarks()
728 {
729 if (bookmarkHelper != null)
730 {
731 int pageIndex = jasperPrint.getPages() == null ? -1 : (jasperPrint.getPages().size() - 1);
732 if (pageIndex >= 0)
733 {
734 JRPrintPage page = jasperPrint.getPages().get(pageIndex);
735 bookmarkHelper.addBookmarks(page, pageIndex);
736 }
737 }
738 }
739
740 public void updateBookmark(JRPrintElement element)
741 {
742 if (isMasterReport())
743 {
744 if (bookmarkHelper != null)
745 {
746 bookmarkHelper.updateBookmark(element);
747 }
748 }
749 else
750 {
751 parent.updateBookmark(element);
752 }
753 }
754
755
756
761 @Override
762 public void cancelFill() throws JRException
763 {
764 if (log.isDebugEnabled())
765 {
766 log.debug("Fill " + fillerId + ": cancelling");
767 }
768
769 fillContext.markCanceled();
770
771 if (fillContext.cancelRunningQuery())
772 {
773 if (log.isDebugEnabled())
774 {
775 log.debug("Fill " + fillerId + ": query cancelled");
776 }
777 }
778 else
779 {
780 Thread t = fillingThread;
781 if (t != null)
782 {
783 if (log.isDebugEnabled())
784 {
785 log.debug("Fill " + fillerId + ": Interrupting thread " + t);
786 }
787
788 t.interrupt();
789 }
790 }
791 }
792
793 protected void addBoundElement(JRFillElement element, JRPrintElement printElement, JREvaluationTime evaluationTime,
794 FillPageKey pageKey)
795 {
796 if (log.isDebugEnabled())
797 {
798 log.debug("Adding evaluation of " + printElement + " by " + element
799 + " for evaluation " + evaluationTime);
800 }
801
802 delayedActions.addDelayedAction(element, printElement, evaluationTime, pageKey);
803 }
804
805 protected void resolveBoundElements(JREvaluationTime evaluationTime, byte evaluation) throws JRException
806 {
807 delayedActions.runActions(evaluationTime, evaluation);
808 }
809
810 protected void resolveMasterBoundElements() throws JRException
811 {
812 resolveBoundElements(JREvaluationTime.EVALUATION_TIME_MASTER, JRExpression.EVALUATION_DEFAULT);
813 }
814
815 public void recordUsedPageWidth(int width)
816 {
817 if (width > usedPageWidth)
818 {
819 usedPageWidth = width;
820 }
821 }
822
823 public int getUsedPageWidth()
824 {
825 return usedPageWidth;
826 }
827
828 }