/**
   * Receives notification that report generation has completed, the report footer was printed, no
   * more output is done. This is a helper event to shut down the output service.
   *
   * @param event The event.
   */
  public void reportDone(final ReportEvent event) {
    if (event.isDeepTraversing()) {
      return;
    }

    if (FunctionUtilities.isDefinedPrepareRunLevel(this, event)) {
      final Iterator iterator = dataStorage.entrySet().iterator();
      while (iterator.hasNext()) {
        final Map.Entry entry = (Map.Entry) iterator.next();
        final String key = (String) entry.getKey();
        final IndexDataHolder data = (IndexDataHolder) entry.getValue();
        model.addRow(
            new Object[] {
              data.getData(),
              data.getPagesText(indexSeparator, condensedStyle),
              data.getPages(),
              key
            });
      }
    } else if (FunctionUtilities.isLayoutLevel(event)) {
      final int rowCount = model.getRowCount();
      for (int i = 0; i < rowCount; i++) {
        final String key = (String) model.getValueAt(i, 3);
        final IndexDataHolder dataHolder = dataStorage.get(key);
        model.setValueAt(dataHolder.getPagesText(indexSeparator, condensedStyle), i, 1);
        model.setValueAt(dataHolder.getPages(), i, 2);
      }
    }
  }
  public TableModel produce(final DataRow parameters, final DataFactoryContext dataFactoryContext)
      throws ReportDataFactoryException {
    final int limit = getTypedParameter("limit", Integer.class, 100);
    final long seed = getTypedParameter("seed", Long.class, System.currentTimeMillis());

    final TypedTableModel model = new TypedTableModel();
    model.addColumn("rowcount", Integer.class);
    model.addColumn("integer", Integer.class);
    model.addColumn("double", Double.class);
    model.addColumn("text", String.class);
    model.addColumn("text2", String.class);
    model.addColumn("date", Date.class);

    final Random random = new Random();
    random.setSeed(seed);

    final Calendar baseDate = new GregorianCalendar(2000, 1, 1);
    baseDate.setTimeZone(TimeZone.getTimeZone("UTC"));
    final long millis = baseDate.getTimeInMillis();
    for (int i = 0; i < limit; i++) {
      model.addRow(
          i,
          (int) (random.nextDouble() * Integer.MAX_VALUE) - (Integer.MAX_VALUE / 2),
          random.nextDouble() * Integer.MAX_VALUE,
          "Some Text with breaks " + i,
          "SomeTextWithoutBreaks" + i,
          new Date(millis + (long) (200 * random.nextDouble() * Integer.MAX_VALUE)));
    }

    return model;
  }
  /**
   * 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);
  }
  public TableModel produce(final DataRow parameters, final DataFactoryContext dataFactoryContext)
      throws ReportDataFactoryException {
    final String col = getTypedParameter("column", String.class);
    if (col == null) {
      throw new ReportDataFactoryException("Column parameter is not defined.");
    }

    final String displayName = getTypedParameter("display-name", String.class, col);
    final Object o = parameters.get(col);
    if (o == null || o.getClass().isArray() == false) {
      return new TypedTableModel(new String[] {displayName});
    }

    final TypedTableModel model =
        new TypedTableModel(
            new String[] {displayName}, new Class[] {o.getClass().getComponentType()});
    final int length = Array.getLength(o);
    for (int i = 0; i < length; i += 1) {
      model.addRow(Array.get(o, i));
    }

    return model;
  }