protected void fillSubreport() throws JRException {
   if (getConnectionExpression() != null) {
     subreportFiller.fill(parameterValues, connection);
   } else if (getDataSourceExpression() != null) {
     subreportFiller.fill(parameterValues, dataSource);
   } else {
     subreportFiller.fill(parameterValues);
   }
 }
  /**
   * Verifies the list of copied values against the subreport.
   *
   * @throws JRException
   */
  private void checkReturnValues() throws JRException {
    if (returnValues != null && returnValues.length > 0) {
      for (int i = 0; i < returnValues.length; i++) {
        JRSubreportReturnValue returnValue = returnValues[i];
        String subreportVariableName = returnValue.getSubreportVariable();
        JRVariable subrepVariable = subreportFiller.getVariable(subreportVariableName);
        if (subrepVariable == null) {
          throw new JRException("Subreport variable " + subreportVariableName + " not found.");
        }

        JRVariable variable = filler.getVariable(returnValue.getToVariable());
        if (returnValue.getCalculationValue() == CalculationEnum.COUNT
            || returnValue.getCalculationValue() == CalculationEnum.DISTINCT_COUNT) {
          if (!Number.class.isAssignableFrom(variable.getValueClass())) {
            throw new JRException(
                "Variable " + returnValue.getToVariable() + " must have a numeric type.");
          }
        } else if (!variable.getValueClass().isAssignableFrom(subrepVariable.getValueClass())
            && !(Number.class.isAssignableFrom(variable.getValueClass())
                && Number.class.isAssignableFrom(subrepVariable.getValueClass()))) {
          throw new JRException(
              "Variable "
                  + returnValue.getToVariable()
                  + " is not assignable from subreport variable "
                  + subreportVariableName);
        }
      }
    }
  }
  protected void initSubreportFiller(DatasetExpressionEvaluator evaluator) throws JRException {
    if (log.isDebugEnabled()) {
      log.debug("Fill " + filler.fillerId + ": creating subreport filler");
    }

    switch (jasperReport.getPrintOrderValue()) {
      case HORIZONTAL:
        {
          subreportFiller = new JRHorizontalFiller(jasperReport, evaluator, this);
          break;
        }
      case VERTICAL:
        {
          subreportFiller = new JRVerticalFiller(jasperReport, evaluator, this);
          break;
        }
      default:
        {
          throw new JRRuntimeException(
              "Unkown print order " + jasperReport.getPrintOrderValue().getValue() + ".");
        }
    }

    runner = getRunnerFactory().createSubreportRunner(this, subreportFiller);
    subreportFiller.setSubreportRunner(runner);
  }
  protected void copyValue(JRFillSubreportReturnValue returnValue) {
    try {
      JRFillVariable variable = filler.getVariable(returnValue.getToVariable());
      Object value = subreportFiller.getVariableValue(returnValue.getSubreportVariable());

      Object newValue =
          returnValue
              .getIncrementer()
              .increment(variable, value, AbstractValueProvider.getCurrentValueProvider());
      variable.setOldValue(newValue);
      variable.setValue(newValue);
      variable.setIncrementedValue(newValue);
    } catch (JRException e) {
      throw new JRRuntimeException(e);
    }
  }
  protected void cancelSubreportFill() throws JRException {
    if (log.isDebugEnabled()) {
      log.debug("Fill " + filler.fillerId + ": cancelling " + subreportFiller.fillerId);
    }

    // marking the subreport filler for interruption
    subreportFiller.setInterrupted(true);

    synchronized (subreportFiller) {
      // forcing the creation of a new thread and a new subreport filler
      runner.cancel();
      runner.reset();
    }

    filler.unregisterSubfiller(subreportFiller);
  }
 /**
  * Utility method used for constructing a parameter values map for subreports, sub datasets and
  * crosstabs.
  *
  * @param filler report filler
  * @param parametersMapExpression expression that yields bulk parameter values map
  * @param subreportParameters list of individual parameter values
  * @param evaluation evaluation type
  * @param ignoreNullExpressions whether to ignore individual parameter value expressions
  * @param removeResourceBundle whether to remove the {@link JRParameter#REPORT_RESOURCE_BUNDLE
  *     REPORT_RESOURCE_BUNDLE} value from the bulk values map
  * @return the parameter values map
  * @throws JRException
  */
 public static Map<String, Object> getParameterValues(
     JRBaseFiller filler,
     JRExpression parametersMapExpression,
     JRDatasetParameter[] subreportParameters,
     byte evaluation,
     boolean ignoreNullExpressions,
     boolean removeResourceBundle,
     boolean removeFormatFactory)
     throws JRException {
   return getParameterValues(
       filler,
       filler.getExpressionEvaluator(),
       parametersMapExpression,
       subreportParameters,
       evaluation,
       ignoreNullExpressions,
       removeResourceBundle,
       removeFormatFactory);
 }
 protected int getContentsStretchHeight() {
   return subreportFiller.getCurrentPageStretchHeight();
 }
  protected boolean prepare(int availableHeight, boolean isOverflow) throws JRException {
    boolean willOverflow = false;

    super.prepare(availableHeight, isOverflow);

    if (subreportFiller == null) {
      setToPrint(false);
    }

    if (!isToPrint()) {
      return willOverflow;
    }

    if (availableHeight < getRelativeY() + getHeight()) {
      setToPrint(false);
      return true; // willOverflow;
    }

    // willOverflow = prepareTextField((JRFillTextField)fillElement, availableStretchHeight);

    // subreportFiller.setPageHeight(getHeight() + availableStretchHeight);

    boolean filling = runner.isFilling();
    boolean toPrint = !isOverflow || isPrintWhenDetailOverflows() || !isAlreadyPrinted();
    boolean reprinted = isOverflow && isPrintWhenDetailOverflows();

    if (!filling && toPrint && reprinted) {
      rewind();
    }

    if (printPage instanceof JRVirtualPrintPage) {
      // if the previous page was virtualized, dispose it as soon as possible.
      // this normally already happened when we added the elements to the master page,
      // but there are cases (e.g. overflow) when a page is not added to the master.
      ((JRVirtualPrintPage) printPage).dispose();
    }

    subreportFiller.setPageHeight(availableHeight - getRelativeY());

    synchronized (subreportFiller) {
      JRSubreportRunResult result;
      if (filling) {
        if (log.isDebugEnabled()) {
          log.debug("Fill " + filler.fillerId + ": resuming " + subreportFiller.fillerId);
        }

        result = runner.resume();
      } else if (toPrint) {
        setReprinted(reprinted);

        if (log.isDebugEnabled()) {
          log.debug("Fill " + filler.fillerId + ": starting " + subreportFiller.fillerId);
        }

        result = runner.start();
      } else {
        printPage = null;
        setStretchHeight(getHeight());
        setToPrint(false);

        return willOverflow;
      }

      if (result.getException() != null) {
        Throwable error = result.getException();

        if (log.isErrorEnabled()) {
          log.error("Fill " + filler.fillerId + ": exception", error);
        }

        if (error instanceof RuntimeException) {
          throw (RuntimeException) error;
        }

        throw new JRRuntimeException(error);
      }

      if (result.hasFinished()) {
        if (log.isDebugEnabled()) {
          log.debug(
              "Fill " + filler.fillerId + ": subreport " + subreportFiller.fillerId + " finished");
        }

        copyValues();
      } else {
        if (log.isDebugEnabled()) {
          log.debug(
              "Fill "
                  + filler.fillerId
                  + ": subreport "
                  + subreportFiller.fillerId
                  + " to continue");
        }
      }

      printPage = subreportFiller.getCurrentPage();
      setStretchHeight(
          result.hasFinished()
              ? subreportFiller.getCurrentPageStretchHeight()
              : availableHeight - getRelativeY());

      // if the subreport fill thread has not finished,
      // it means that the subreport will overflow on the next page
      willOverflow = !result.hasFinished();

      if (!willOverflow) {
        // the subreport fill thread has finished and the next time we shall create a new one
        runner.reset();
      }
    } // synchronized

    Collection<JRPrintElement> printElements = getPrintElements();
    if ((printElements == null || printElements.size() == 0)
        && isRemoveLineWhenBlank() // FIXME if the line won't be removed, the background does not
    // appear
    ) {
      setToPrint(false);
    }

    return willOverflow;
  }
  /**
   * Utility method used for constructing a parameter values map for subreports, sub datasets and
   * crosstabs.
   *
   * @param filler report filler
   * @param expressionEvaluator expression evaluator
   * @param parametersMapExpression expression that yields bulk parameter values map
   * @param subreportParameters list of individual parameter values
   * @param evaluation evaluation type
   * @param ignoreNullExpressions whether to ignore individual parameter value expressions
   * @param removeResourceBundle whether to remove the {@link JRParameter#REPORT_RESOURCE_BUNDLE
   *     REPORT_RESOURCE_BUNDLE} value from the bulk values map
   * @return the parameter values map
   * @throws JRException
   */
  public static Map<String, Object> getParameterValues(
      // TODO using the filler or current dataset?
      JRBaseFiller filler,
      JRFillExpressionEvaluator expressionEvaluator,
      JRExpression parametersMapExpression,
      JRDatasetParameter[] subreportParameters,
      byte evaluation,
      boolean ignoreNullExpressions,
      boolean removeResourceBundle,
      boolean removeFormatFactory)
      throws JRException {
    Map<String, Object> parameterValues = null;
    if (parametersMapExpression != null) {
      parameterValues =
          (Map<String, Object>) expressionEvaluator.evaluate(parametersMapExpression, evaluation);
    }

    if (parameterValues != null) {
      // if the expression evaluates to the master parameters map
      if (parameterValues == filler.getParameterValuesMap()) {
        // create a clone of the map so that the master map is not altered
        parameterValues = new HashMap<String, Object>(parameterValues);
      }

      // parameterValues.remove(JRParameter.REPORT_LOCALE);
      if (removeResourceBundle) {
        parameterValues.remove(JRParameter.REPORT_RESOURCE_BUNDLE);
      }
      if (removeFormatFactory) {
        parameterValues.remove(JRParameter.REPORT_FORMAT_FACTORY);
      }
      // parameterValues.remove(JRParameter.REPORT_TIME_ZONE);
      parameterValues.remove(JRParameter.JASPER_REPORT);
      parameterValues.remove(JRParameter.REPORT_CONNECTION);
      parameterValues.remove(JRParameter.REPORT_MAX_COUNT);
      parameterValues.remove(JRParameter.REPORT_DATA_SOURCE);
      parameterValues.remove(JRParameter.REPORT_SCRIPTLET);
      // should we give access to scriplet extensions so that they can remove their parameters here?
      // yes, but then you should also give them access to create built-in parameters... too much
      // trouble.
      JRScriptlet[] scriptlets = filler.getJasperReport().getScriptlets();
      if (scriptlets != null) {
        for (int i = 0; i < scriptlets.length; i++) {
          parameterValues.remove(
              scriptlets[i].getName() + JRScriptlet.SCRIPTLET_PARAMETER_NAME_SUFFIX);
        }
      }
      parameterValues.remove(JRParameter.REPORT_VIRTUALIZER);
      // parameterValues.remove(JRParameter.REPORT_CLASS_LOADER);
      parameterValues.remove(JRParameter.IS_IGNORE_PAGINATION);
      parameterValues.remove(JRParameter.SORT_FIELDS);
      parameterValues.remove(JRParameter.FILTER);
      parameterValues.remove(JRParameter.REPORT_PARAMETERS_MAP);
    }

    if (parameterValues == null) {
      parameterValues = new HashMap<String, Object>();
    }

    /*   */
    if (subreportParameters != null && subreportParameters.length > 0) {
      Object parameterValue = null;
      for (int i = 0; i < subreportParameters.length; i++) {
        JRExpression expression = subreportParameters[i].getExpression();
        if (expression != null || !ignoreNullExpressions) {
          parameterValue = expressionEvaluator.evaluate(expression, evaluation);
          if (parameterValue == null) {
            parameterValues.remove(subreportParameters[i].getName());
          } else {
            parameterValues.put(subreportParameters[i].getName(), parameterValue);
          }
        }
      }
    }

    if (!parameterValues.containsKey(JRParameter.REPORT_LOCALE)) {
      parameterValues.put(JRParameter.REPORT_LOCALE, filler.getLocale());
    }

    if (!parameterValues.containsKey(JRParameter.REPORT_TIME_ZONE)) {
      parameterValues.put(JRParameter.REPORT_TIME_ZONE, filler.getTimeZone());
    }

    if (!parameterValues.containsKey(JRParameter.REPORT_FORMAT_FACTORY) && !removeFormatFactory) {
      parameterValues.put(JRParameter.REPORT_FORMAT_FACTORY, filler.getFormatFactory());
    }

    if (!parameterValues.containsKey(JRParameter.REPORT_CLASS_LOADER)
        && filler.reportClassLoader != null) {
      parameterValues.put(JRParameter.REPORT_CLASS_LOADER, filler.reportClassLoader);
    }

    if (!parameterValues.containsKey(JRParameter.REPORT_URL_HANDLER_FACTORY)
        && filler.urlHandlerFactory != null) {
      parameterValues.put(JRParameter.REPORT_URL_HANDLER_FACTORY, filler.urlHandlerFactory);
    }

    if (!parameterValues.containsKey(JRParameter.REPORT_FILE_RESOLVER)
        && filler.fileResolver != null) {
      parameterValues.put(JRParameter.REPORT_FILE_RESOLVER, filler.fileResolver);
    }

    if (!parameterValues.containsKey(JRParameter.REPORT_CONTEXT)) {
      ReportContext context =
          (ReportContext)
              filler.getMainDataset().getParameterValue(JRParameter.REPORT_CONTEXT, true);
      if (context != null) {
        parameterValues.put(JRParameter.REPORT_CONTEXT, context);
      }
    }

    return parameterValues;
  }