/**
   * Receives notification that the report has started.
   *
   * @param event the event.
   */
  public void reportStarted(final ReportEvent event) {
    if (event.isDeepTraversing()) {
      return;
    }

    pageFunction.reportStarted(event);
  }
 /**
  * Return a completly separated copy of this function. The copy does no longer share any
  * changeable objects with the original function.
  *
  * @return a copy of this function.
  */
 public Expression getInstance() {
   final IndexDataGeneratorFunction instance = (IndexDataGeneratorFunction) super.getInstance();
   instance.model = new TypedTableModel();
   instance.pageFunction = (PageFunction) pageFunction.getInstance();
   instance.dataFormula = (FormulaExpression) dataFormula.getInstance();
   instance.dataStorage = new TreeMap<String, IndexDataHolder>();
   instance.initialized = false;
   return instance;
 }
  /**
   * Receives notification that report generation initializes the current run.
   *
   * <p>The event carries a ReportState.Started state. Use this to initialize the report.
   *
   * @param event The event.
   */
  public void reportInitialized(final ReportEvent event) {
    if (event.isDeepTraversing()) {
      return;
    }

    if (initialized == false) {
      initialized = true;
      model.addColumn("item-data", Object.class);
      model.addColumn("item-pages", String.class);
      model.addColumn("item-pages-array", Integer[].class);
      model.addColumn("item-key", String.class);
    }

    pageFunction.reportInitialized(event);
  }
  /**
   * Receives notification that a row of data is being processed.
   *
   * @param event the event.
   */
  public void itemsAdvanced(final ReportEvent event) {
    if (event.isDeepTraversing()) {
      if ("index".equals(event.getOriginatingState().getReport().getMetaData().getName())) {
        return;
      }
    }

    final Object o = computeDataValue(event);
    if (o == null) {
      return;
    }

    if (FunctionUtilities.isDefinedPrepareRunLevel(this, event)) {
      dataStorage.put(String.valueOf(o), new IndexDataHolder(o));
    } else if (FunctionUtilities.isLayoutLevel(event)) {
      final IndexDataHolder o1 = dataStorage.get(String.valueOf(o));
      if (o1 == null) {
        throw new IllegalStateException(
            "Unable to compute index: Function values changed between prepare and layout run");
      }
      o1.addPage(pageFunction.getPage());
    }
  }
 /**
  * Clones the expression. The expression should be reinitialized after the cloning.
  *
  * <p>Expressions maintain no state, cloning is done at the beginning of the report processing to
  * disconnect the expression from any other object space.
  *
  * @return a clone of this expression.
  * @throws CloneNotSupportedException this should never happen.
  */
 public Object clone() throws CloneNotSupportedException {
   final IndexDataGeneratorFunction o = (IndexDataGeneratorFunction) super.clone();
   o.dataFormula = (FormulaExpression) dataFormula.clone();
   o.pageFunction = (PageFunction) pageFunction.clone();
   return o;
 }
 /**
  * Receives notification that a page is completed.
  *
  * @param event The event.
  */
 public void pageFinished(final ReportEvent event) {
   pageFunction.pageFinished(event);
 }
 /**
  * Receives notification that a new page is being started.
  *
  * @param event The event.
  */
 public void pageStarted(final ReportEvent event) {
   pageFunction.pageStarted(event);
 }