001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028: package net.sf.jasperreports.engine.fill;
029:
030: import java.io.File;
031: import java.io.IOException;
032: import java.io.InputStream;
033: import java.net.URL;
034: import java.sql.Connection;
035: import java.util.ArrayList;
036: import java.util.Collection;
037: import java.util.HashMap;
038: import java.util.HashSet;
039: import java.util.List;
040: import java.util.Map;
041: import java.util.Set;
042:
043: import net.sf.jasperreports.engine.JRAbstractObjectFactory;
044: import net.sf.jasperreports.engine.JRChild;
045: import net.sf.jasperreports.engine.JRDataSource;
046: import net.sf.jasperreports.engine.JRDatasetParameter;
047: import net.sf.jasperreports.engine.JRException;
048: import net.sf.jasperreports.engine.JRExpression;
049: import net.sf.jasperreports.engine.JRExpressionCollector;
050: import net.sf.jasperreports.engine.JRParameter;
051: import net.sf.jasperreports.engine.JRPrintElement;
052: import net.sf.jasperreports.engine.JRPrintPage;
053: import net.sf.jasperreports.engine.JRPrintRectangle;
054: import net.sf.jasperreports.engine.JRReport;
055: import net.sf.jasperreports.engine.JRRewindableDataSource;
056: import net.sf.jasperreports.engine.JRRuntimeException;
057: import net.sf.jasperreports.engine.JRStyle;
058: import net.sf.jasperreports.engine.JRSubreport;
059: import net.sf.jasperreports.engine.JRSubreportParameter;
060: import net.sf.jasperreports.engine.JRSubreportReturnValue;
061: import net.sf.jasperreports.engine.JRVariable;
062: import net.sf.jasperreports.engine.JasperCompileManager;
063: import net.sf.jasperreports.engine.JasperReport;
064: import net.sf.jasperreports.engine.design.JRDesignSubreportReturnValue;
065: import net.sf.jasperreports.engine.util.JRLoader;
066: import net.sf.jasperreports.engine.util.JRProperties;
067: import net.sf.jasperreports.engine.util.JRSingletonCache;
068: import net.sf.jasperreports.engine.util.JRStyleResolver;
069: import net.sf.jasperreports.engine.xml.JRXmlWriter;
070:
071: import org.apache.commons.logging.Log;
072: import org.apache.commons.logging.LogFactory;
073:
074: /**
075: * @author Teodor Danciu (teodord@users.sourceforge.net)
076: * @version $Id: JRFillSubreport.java 1828 2007-08-24 13:58:43Z teodord $
077: */
078: public class JRFillSubreport extends JRFillElement implements
079: JRSubreport {
080:
081: private static final Log log = LogFactory
082: .getLog(JRFillSubreport.class);
083:
084: private static final JRSingletonCache runnerFactoryCache = new JRSingletonCache(
085: JRSubreportRunnerFactory.class);
086:
087: /**
088: *
089: */
090: private Map parameterValues = null;
091: private JRSubreportParameter[] parameters = null;
092: private Connection connection = null;
093: private JRDataSource dataSource = null;
094: private JasperReport jasperReport = null;
095:
096: private Map loadedEvaluators = null;
097:
098: /**
099: * Values to be copied from the subreport.
100: */
101: private JRFillSubreportReturnValue[] returnValues = null;
102:
103: /**
104: *
105: */
106: protected JRBaseFiller subreportFiller = null;
107: private JRPrintPage printPage = null;
108:
109: private JRSubreportRunner runner;
110:
111: /**
112: * Set of checked reports.
113: */
114: private Set checkedReports;
115:
116: /**
117: *
118: */
119: protected JRFillSubreport(JRBaseFiller filler,
120: JRSubreport subreport, JRFillObjectFactory factory) {
121: super (filler, subreport, factory);
122:
123: parameters = subreport.getParameters();
124: JRSubreportReturnValue[] subrepReturnValues = subreport
125: .getReturnValues();
126: if (subrepReturnValues != null) {
127: List returnValuesList = new ArrayList(
128: subrepReturnValues.length * 2);
129:
130: returnValues = new JRFillSubreportReturnValue[subrepReturnValues.length];
131: for (int i = 0; i < subrepReturnValues.length; i++) {
132: addReturnValue(subrepReturnValues[i], returnValuesList,
133: factory);
134: }
135:
136: returnValues = new JRFillSubreportReturnValue[returnValuesList
137: .size()];
138: returnValuesList.toArray(returnValues);
139: }
140:
141: loadedEvaluators = new HashMap();
142: checkedReports = new HashSet();
143: }
144:
145: /**
146: *
147: */
148: public byte getMode() {
149: return JRStyleResolver.getMode(this , MODE_TRANSPARENT);
150: }
151:
152: /**
153: *
154: */
155: public boolean isUsingCache() {
156: return ((JRSubreport) parent).isUsingCache();
157: }
158:
159: /**
160: * @deprecated Replaced by {@link #setUsingCache(Boolean)}.
161: */
162: public void setUsingCache(boolean isUsingCache) {
163: }
164:
165: /**
166: *
167: */
168: public JRExpression getParametersMapExpression() {
169: return ((JRSubreport) parent).getParametersMapExpression();
170: }
171:
172: /**
173: *
174: */
175: public JRSubreportParameter[] getParameters() {
176: return parameters;
177: }
178:
179: /**
180: *
181: */
182: public JRExpression getConnectionExpression() {
183: return ((JRSubreport) parent).getConnectionExpression();
184: }
185:
186: /**
187: *
188: */
189: public JRExpression getDataSourceExpression() {
190: return ((JRSubreport) parent).getDataSourceExpression();
191: }
192:
193: /**
194: *
195: */
196: public JRExpression getExpression() {
197: return ((JRSubreport) parent).getExpression();
198: }
199:
200: /**
201: *
202: */
203: protected JRTemplateRectangle getJRTemplateRectangle() {
204: JRStyle style = getStyle();
205: JRTemplateRectangle template = (JRTemplateRectangle) getTemplate(style);
206: if (template == null) {
207: template = new JRTemplateRectangle(filler.getJasperPrint()
208: .getDefaultStyleProvider(), this );
209: registerTemplate(style, template);
210: }
211: return template;
212: }
213:
214: /**
215: *
216: */
217: protected Collection getPrintElements() {
218: Collection printElements = null;
219:
220: if (printPage != null) {
221: printElements = printPage.getElements();
222: }
223:
224: return printElements;
225: }
226:
227: /**
228: *
229: */
230: protected void evaluate(byte evaluation) throws JRException {
231: reset();
232:
233: evaluatePrintWhenExpression(evaluation);
234:
235: if ((isPrintWhenExpressionNull() || (!isPrintWhenExpressionNull() && isPrintWhenTrue()))) {
236: evaluateSubreport(evaluation);
237: }
238: }
239:
240: /**
241: *
242: */
243: protected void evaluateSubreport(byte evaluation)
244: throws JRException {
245: JRExpression expression = getExpression();
246: Object source = evaluateExpression(expression, evaluation);
247: if (source != null) // FIXME put some default broken image like in browsers
248: {
249: JREvaluator evaluator = null;
250:
251: if (isUsingCache()
252: && filler.fillContext.hasLoadedSubreport(source)) {
253: jasperReport = filler.fillContext
254: .getLoadedSubreport(source);
255: evaluator = (JREvaluator) loadedEvaluators
256: .get(jasperReport);
257:
258: if (evaluator == null) {
259: evaluator = JasperCompileManager
260: .loadEvaluator(jasperReport);
261: loadedEvaluators.put(jasperReport, evaluator);
262: }
263: } else {
264: Class expressionClass = expression.getValueClass();
265:
266: if (expressionClass
267: .equals(net.sf.jasperreports.engine.JasperReport.class)) {
268: jasperReport = (JasperReport) source;
269: } else if (expressionClass
270: .equals(java.io.InputStream.class)) {
271: jasperReport = (JasperReport) JRLoader
272: .loadObject((InputStream) source);
273: } else if (expressionClass.equals(java.net.URL.class)) {
274: jasperReport = (JasperReport) JRLoader
275: .loadObject((URL) source);
276: } else if (expressionClass.equals(java.io.File.class)) {
277: jasperReport = (JasperReport) JRLoader
278: .loadObject((File) source);
279: } else if (expressionClass
280: .equals(java.lang.String.class)) {
281: jasperReport = (JasperReport) JRLoader
282: .loadObjectFromLocation((String) source,
283: filler.reportClassLoader,
284: filler.urlHandlerFactory);
285: }
286:
287: if (jasperReport != null) {
288: evaluator = JasperCompileManager
289: .loadEvaluator(jasperReport);
290: }
291:
292: if (isUsingCache()) {
293: filler.fillContext.registerLoadedSubreport(source,
294: jasperReport);
295: loadedEvaluators.put(jasperReport, evaluator);
296: }
297: }
298:
299: if (jasperReport != null) {
300: /* */
301: expression = getConnectionExpression();
302: connection = (Connection) evaluateExpression(
303: expression, evaluation);
304:
305: /* */
306: expression = getDataSourceExpression();
307: dataSource = (JRDataSource) evaluateExpression(
308: expression, evaluation);
309:
310: parameterValues = getParameterValues(filler,
311: getParametersMapExpression(), getParameters(),
312: evaluation, false, jasperReport
313: .getResourceBundle() != null,//hasResourceBundle
314: jasperReport.getFormatFactoryClass() != null//hasFormatFactory
315: );
316:
317: if (subreportFiller != null) {
318: filler.unregisterSubfiller(subreportFiller);
319: }
320:
321: /* */
322: initSubreportFiller(evaluator);
323:
324: checkReturnValues();
325:
326: saveReturnVariables();
327: }
328: }
329: }
330:
331: protected void initSubreportFiller(JREvaluator evaluator)
332: throws JRException {
333: if (log.isDebugEnabled()) {
334: log.debug("Fill " + filler.fillerId
335: + ": creating subreport filler");
336: }
337:
338: switch (jasperReport.getPrintOrder()) {
339: case JRReport.PRINT_ORDER_HORIZONTAL: {
340: subreportFiller = new JRHorizontalFiller(jasperReport,
341: evaluator, filler);
342: break;
343: }
344: case JRReport.PRINT_ORDER_VERTICAL: {
345: subreportFiller = new JRVerticalFiller(jasperReport,
346: evaluator, filler);
347: break;
348: }
349: default: {
350: throw new JRRuntimeException("Unkown print order "
351: + jasperReport.getPrintOrder() + ".");
352: }
353: }
354:
355: runner = getRunnerFactory().createSubreportRunner(this ,
356: subreportFiller);
357: subreportFiller.setSubreportRunner(runner);
358: }
359:
360: protected void saveReturnVariables() {
361: if (returnValues != null) {
362: for (int i = 0; i < returnValues.length; i++) {
363: String varName = returnValues[i].getToVariable();
364: band.saveVariable(varName);
365: }
366: }
367: }
368:
369: /**
370: * Utility method used for constructing a parameter values map for subreports, sub datasets and crosstabs.
371: *
372: * @param filler report filler
373: * @param parametersMapExpression expression that yields bulk parameter values map
374: * @param subreportParameters list of individual parameter values
375: * @param evaluation evaluation type
376: * @param ignoreNullExpressions whether to ignore individual parameter value expressions
377: * @param removeResourceBundle whether to remove the {@link JRParameter#REPORT_RESOURCE_BUNDLE REPORT_RESOURCE_BUNDLE}
378: * value from the bulk values map
379: * @return the parameter values map
380: * @throws JRException
381: */
382: public static Map getParameterValues(JRBaseFiller filler,
383: JRExpression parametersMapExpression,
384: JRDatasetParameter[] subreportParameters, byte evaluation,
385: boolean ignoreNullExpressions,
386: boolean removeResourceBundle, boolean removeFormatFactory)
387: throws JRException {
388: Map parameterValues = null;
389: if (parametersMapExpression != null) {
390: parameterValues = (Map) filler.evaluateExpression(
391: parametersMapExpression, evaluation);
392: }
393:
394: if (parameterValues != null) {
395: //parameterValues.remove(JRParameter.REPORT_LOCALE);
396: if (removeResourceBundle) {
397: parameterValues
398: .remove(JRParameter.REPORT_RESOURCE_BUNDLE);
399: }
400: if (removeFormatFactory) {
401: parameterValues
402: .remove(JRParameter.REPORT_FORMAT_FACTORY);
403: }
404: //parameterValues.remove(JRParameter.REPORT_TIME_ZONE);
405: parameterValues.remove(JRParameter.REPORT_CONNECTION);
406: parameterValues.remove(JRParameter.REPORT_MAX_COUNT);
407: parameterValues.remove(JRParameter.REPORT_DATA_SOURCE);
408: parameterValues.remove(JRParameter.REPORT_SCRIPTLET);
409: parameterValues.remove(JRParameter.REPORT_VIRTUALIZER);
410: //parameterValues.remove(JRParameter.REPORT_CLASS_LOADER);
411: parameterValues.remove(JRParameter.IS_IGNORE_PAGINATION);
412: parameterValues.remove(JRParameter.REPORT_PARAMETERS_MAP);
413: }
414:
415: if (parameterValues == null) {
416: parameterValues = new HashMap();
417: }
418:
419: /* */
420: if (subreportParameters != null
421: && subreportParameters.length > 0) {
422: Object parameterValue = null;
423: for (int i = 0; i < subreportParameters.length; i++) {
424: JRExpression expression = subreportParameters[i]
425: .getExpression();
426: if (expression != null || !ignoreNullExpressions) {
427: parameterValue = filler.evaluateExpression(
428: expression, evaluation);
429: if (parameterValue == null) {
430: parameterValues.remove(subreportParameters[i]
431: .getName());
432: } else {
433: parameterValues.put(subreportParameters[i]
434: .getName(), parameterValue);
435: }
436: }
437: }
438: }
439:
440: if (!parameterValues.containsKey(JRParameter.REPORT_LOCALE)) {
441: parameterValues.put(JRParameter.REPORT_LOCALE, filler
442: .getLocale());
443: }
444:
445: if (!parameterValues.containsKey(JRParameter.REPORT_TIME_ZONE)) {
446: parameterValues.put(JRParameter.REPORT_TIME_ZONE, filler
447: .getTimeZone());
448: }
449:
450: if (!parameterValues
451: .containsKey(JRParameter.REPORT_FORMAT_FACTORY)
452: && !removeFormatFactory) {
453: parameterValues.put(JRParameter.REPORT_FORMAT_FACTORY,
454: filler.getFormatFactory());
455: }
456:
457: if (!parameterValues
458: .containsKey(JRParameter.REPORT_CLASS_LOADER)
459: && filler.reportClassLoader != null) {
460: parameterValues.put(JRParameter.REPORT_CLASS_LOADER,
461: filler.reportClassLoader);
462: }
463:
464: if (!parameterValues
465: .containsKey(JRParameter.REPORT_URL_HANDLER_FACTORY)
466: && filler.urlHandlerFactory != null) {
467: parameterValues.put(JRParameter.REPORT_URL_HANDLER_FACTORY,
468: filler.urlHandlerFactory);
469: }
470:
471: return parameterValues;
472: }
473:
474: protected void fillSubreport() throws JRException {
475: if (getConnectionExpression() != null) {
476: subreportFiller.fill(parameterValues, connection);
477: } else if (getDataSourceExpression() != null) {
478: subreportFiller.fill(parameterValues, dataSource);
479: } else {
480: subreportFiller.fill(parameterValues);
481: }
482: }
483:
484: /**
485: *
486: */
487: protected boolean prepare(int availableStretchHeight,
488: boolean isOverflow) throws JRException {
489: boolean willOverflow = false;
490:
491: super .prepare(availableStretchHeight, isOverflow);
492:
493: if (subreportFiller == null) {
494: setToPrint(false);
495: }
496:
497: if (!isToPrint()) {
498: return willOverflow;
499: }
500:
501: if (availableStretchHeight < getRelativeY() - getY()
502: - getBandBottomY()) {
503: setToPrint(false);
504: return true;//willOverflow;
505: }
506:
507: //willOverflow = prepareTextField((JRFillTextField)fillElement, availableStretchHeight);
508:
509: //subreportFiller.setPageHeight(getHeight() + availableStretchHeight);
510:
511: boolean filling = runner.isFilling();
512: boolean toPrint = !isOverflow || isPrintWhenDetailOverflows()
513: || !isAlreadyPrinted();
514: boolean reprinted = isOverflow && isPrintWhenDetailOverflows();
515:
516: if (!filling && toPrint && reprinted) {
517: rewind();
518: }
519:
520: int availableHeight = getHeight() + availableStretchHeight
521: - getRelativeY() + getY() + getBandBottomY();
522: subreportFiller.setPageHeight(availableHeight);
523:
524: synchronized (subreportFiller) {
525: JRSubreportRunResult result;
526: if (filling) {
527: if (log.isDebugEnabled()) {
528: log.debug("Fill " + filler.fillerId + ": resuming "
529: + subreportFiller.fillerId);
530: }
531:
532: result = runner.resume();
533: } else if (toPrint) {
534: setReprinted(reprinted);
535:
536: if (log.isDebugEnabled()) {
537: log.debug("Fill " + filler.fillerId + ": starting "
538: + subreportFiller.fillerId);
539: }
540:
541: result = runner.start();
542: } else {
543: printPage = null;
544: setStretchHeight(getHeight());
545: setToPrint(false);
546:
547: return willOverflow;
548: }
549:
550: if (result.getException() != null) {
551: Throwable error = result.getException();
552:
553: if (log.isErrorEnabled()) {
554: log.error(
555: "Fill " + filler.fillerId + ": exception",
556: error);
557: }
558:
559: if (error instanceof RuntimeException) {
560: throw (RuntimeException) error;
561: }
562:
563: throw new JRRuntimeException(error);
564: }
565:
566: if (result.hasFinished()) {
567: if (log.isDebugEnabled()) {
568: log.debug("Fill " + filler.fillerId
569: + ": subreport " + subreportFiller.fillerId
570: + " finished");
571: }
572:
573: copyValues();
574: } else {
575: if (log.isDebugEnabled()) {
576: log.debug("Fill " + filler.fillerId
577: + ": subreport " + subreportFiller.fillerId
578: + " to continue");
579: }
580: }
581:
582: printPage = subreportFiller.getCurrentPage();
583: setStretchHeight(result.hasFinished() ? subreportFiller
584: .getCurrentPageStretchHeight() : availableHeight);
585:
586: //if the subreport fill thread has not finished,
587: // it means that the subreport will overflow on the next page
588: willOverflow = !result.hasFinished();
589:
590: if (!willOverflow) {
591: //the subreport fill thread has finished and the next time we shall create a new one
592: runner.reset();
593: }
594: }// synchronized
595:
596: Collection printElements = getPrintElements();
597: if ((printElements == null || printElements.size() == 0)
598: && isRemoveLineWhenBlank() //FIXME if the line won't be removed, the background does not appear
599: ) {
600: setToPrint(false);
601: }
602:
603: return willOverflow;
604: }
605:
606: /**
607: *
608: */
609: public void rewind() throws JRException {
610: if (subreportFiller == null) {
611: return;
612: }
613:
614: if (log.isDebugEnabled()) {
615: log.debug("Fill " + filler.fillerId + ": cancelling "
616: + subreportFiller.fillerId);
617: }
618:
619: // marking the subreport filler for interruption
620: subreportFiller.setInterrupted(true);
621:
622: synchronized (subreportFiller) {
623: // forcing the creation of a new thread and a new subreport filler
624: runner.cancel();
625: runner.reset();
626: }
627:
628: filler.unregisterSubfiller(subreportFiller);
629:
630: initSubreportFiller(null);//FIXME used cached evaluator
631:
632: if (getConnectionExpression() == null && dataSource != null) {
633: if (dataSource instanceof JRRewindableDataSource) {
634: ((JRRewindableDataSource) dataSource).moveFirst();
635: } else {
636: if (log.isDebugEnabled())
637: log
638: .debug("The subreport is placed on a non-splitting band, but it does not have a rewindable data source.");
639: }
640: }
641: }
642:
643: /**
644: *
645: */
646: protected JRPrintElement fill() {
647: JRPrintRectangle printRectangle = new JRTemplatePrintRectangle(
648: getJRTemplateRectangle());
649:
650: printRectangle.setX(getX());
651: printRectangle.setY(getRelativeY());
652: printRectangle.setWidth(getWidth());
653: printRectangle.setHeight(getStretchHeight());
654:
655: return printRectangle;
656: }
657:
658: /**
659: *
660: */
661: public JRChild getCopy(JRAbstractObjectFactory factory) {
662: return factory.getSubreport(this );
663: }
664:
665: /**
666: *
667: */
668: public void collectExpressions(JRExpressionCollector collector) {
669: collector.collect(this );
670: }
671:
672: /**
673: *
674: */
675: public void writeXml(JRXmlWriter xmlWriter) throws IOException {
676: xmlWriter.writeSubreport(this );
677: }
678:
679: private JRFillSubreportReturnValue addReturnValue(
680: JRSubreportReturnValue parentReturnValue,
681: List returnValueList, JRFillObjectFactory factory) {
682: JRFillSubreportReturnValue returnValue = factory
683: .getSubreportReturnValue(parentReturnValue);
684:
685: byte calculation = returnValue.getCalculation();
686: switch (calculation) {
687: case JRVariable.CALCULATION_AVERAGE:
688: case JRVariable.CALCULATION_VARIANCE: {
689: JRSubreportReturnValue countVal = createHelperReturnValue(
690: parentReturnValue, "_COUNT",
691: JRVariable.CALCULATION_COUNT);
692: addReturnValue(countVal, returnValueList, factory);
693:
694: JRSubreportReturnValue sumVal = createHelperReturnValue(
695: parentReturnValue, "_SUM",
696: JRVariable.CALCULATION_SUM);
697: addReturnValue(sumVal, returnValueList, factory);
698:
699: filler.addVariableCalculationReq(returnValue
700: .getToVariable(), calculation);
701:
702: break;
703: }
704: case JRVariable.CALCULATION_STANDARD_DEVIATION: {
705: JRSubreportReturnValue varianceVal = createHelperReturnValue(
706: parentReturnValue, "_VARIANCE",
707: JRVariable.CALCULATION_VARIANCE);
708: addReturnValue(varianceVal, returnValueList, factory);
709:
710: filler.addVariableCalculationReq(returnValue
711: .getToVariable(), calculation);
712: break;
713: }
714: case JRVariable.CALCULATION_DISTINCT_COUNT: {
715: JRSubreportReturnValue countVal = createDistinctCountHelperReturnValue(parentReturnValue);
716: addReturnValue(countVal, returnValueList, factory);
717:
718: filler.addVariableCalculationReq(returnValue
719: .getToVariable(), calculation);
720: break;
721: }
722: }
723:
724: returnValueList.add(returnValue);
725: return returnValue;
726:
727: }
728:
729: protected JRSubreportReturnValue createHelperReturnValue(
730: JRSubreportReturnValue returnValue, String nameSuffix,
731: byte calculation) {
732: JRDesignSubreportReturnValue helper = new JRDesignSubreportReturnValue();
733: helper.setToVariable(returnValue.getToVariable() + nameSuffix);
734: helper.setSubreportVariable(returnValue.getSubreportVariable());
735: helper.setCalculation(calculation);
736: helper.setIncrementerFactoryClassName(helper
737: .getIncrementerFactoryClassName());//FIXME shouldn't it be returnValue?
738:
739: return helper;
740: }
741:
742: protected JRSubreportReturnValue createDistinctCountHelperReturnValue(
743: JRSubreportReturnValue returnValue) {
744: JRDesignSubreportReturnValue helper = new JRDesignSubreportReturnValue();
745: helper.setToVariable(returnValue.getToVariable()
746: + "_DISTINCT_COUNT");
747: helper.setSubreportVariable(returnValue.getSubreportVariable());
748: helper.setCalculation(JRVariable.CALCULATION_NOTHING);
749: helper.setIncrementerFactoryClassName(helper
750: .getIncrementerFactoryClassName());//FIXME shouldn't it be returnValue? tests required
751:
752: return helper;
753: }
754:
755: public JRSubreportReturnValue[] getReturnValues() {
756: return this .returnValues;
757: }
758:
759: public boolean usesForReturnValue(String variableName) {
760: boolean used = false;
761: if (returnValues != null) {
762: for (int j = 0; j < returnValues.length; j++) {
763: JRSubreportReturnValue returnValue = returnValues[j];
764: if (returnValue.getToVariable().equals(variableName)) {
765: used = true;
766: break;
767: }
768: }
769: }
770: return used;
771: }
772:
773: /**
774: * Copies the values from the subreport to the variables of the master report.
775: */
776: protected void copyValues() {
777: if (returnValues != null && returnValues.length > 0) {
778: for (int i = 0; i < returnValues.length; i++) {
779: copyValue(returnValues[i]);
780: }
781: }
782: }
783:
784: protected void copyValue(JRFillSubreportReturnValue returnValue) {
785: try {
786: JRFillVariable variable = filler.getVariable(returnValue
787: .getToVariable());
788: Object value = subreportFiller.getVariableValue(returnValue
789: .getSubreportVariable());
790:
791: Object newValue = returnValue.getIncrementer().increment(
792: variable, value,
793: AbstractValueProvider.getCurrentValueProvider());
794: variable.setOldValue(newValue);
795: variable.setValue(newValue);
796: variable.setIncrementedValue(newValue);
797: } catch (JRException e) {
798: throw new JRRuntimeException(e);
799: }
800: }
801:
802: /**
803: * Verifies the list of copied values against the subreport.
804: *
805: * @throws JRException
806: */
807: private void checkReturnValues() throws JRException {
808: if (returnValues != null && returnValues.length > 0
809: && !checkedReports.contains(jasperReport)) {
810: for (int i = 0; i < returnValues.length; i++) {
811: JRSubreportReturnValue returnValue = returnValues[i];
812: String subreportVariableName = returnValue
813: .getSubreportVariable();
814: JRVariable subrepVariable = subreportFiller
815: .getVariable(subreportVariableName);
816: if (subrepVariable == null) {
817: throw new JRException("Subreport variable "
818: + subreportVariableName + " not found.");
819: }
820:
821: JRVariable variable = filler.getVariable(returnValue
822: .getToVariable());
823: if (returnValue.getCalculation() == JRVariable.CALCULATION_COUNT
824: || returnValue.getCalculation() == JRVariable.CALCULATION_DISTINCT_COUNT) {
825: if (!Number.class.isAssignableFrom(variable
826: .getValueClass())) {
827: throw new JRException("Variable "
828: + returnValue.getToVariable()
829: + " must have a numeric type.");
830: }
831: } else if (!variable.getValueClass().isAssignableFrom(
832: subrepVariable.getValueClass())
833: && !(Number.class.isAssignableFrom(variable
834: .getValueClass()) && Number.class
835: .isAssignableFrom(subrepVariable
836: .getValueClass()))) {
837: throw new JRException(
838: "Variable "
839: + returnValue.getToVariable()
840: + " is not assignable from subreport variable "
841: + subreportVariableName);
842: }
843: }
844:
845: if (isUsingCache())
846: checkedReports.add(jasperReport);
847: }
848: }
849:
850: protected void resolveElement(JRPrintElement element,
851: byte evaluation) {
852: // nothing
853: }
854:
855: public Boolean isOwnUsingCache() {
856: return ((JRSubreport) parent).isOwnUsingCache();
857: }
858:
859: public void setUsingCache(Boolean isUsingCache) {
860: }
861:
862: public JRCloneable createClone(JRFillCloneFactory factory) {
863: //not needed
864: return null;
865: }
866:
867: protected static JRSubreportRunnerFactory getRunnerFactory()
868: throws JRException {
869: String factoryClassName = JRProperties
870: .getProperty(JRSubreportRunnerFactory.SUBREPORT_RUNNER_FACTORY);
871: if (factoryClassName == null) {
872: throw new JRException("Property \""
873: + JRSubreportRunnerFactory.SUBREPORT_RUNNER_FACTORY
874: + "\" must be set");
875: }
876: return (JRSubreportRunnerFactory) runnerFactoryCache
877: .getCachedInstance(factoryClassName);
878: }
879: }
|