/**
  * Creates a new axis.
  *
  * @param label the axis label (<code>null</code> permitted).
  * @param first the first time period in the axis range (<code>null</code> not permitted).
  * @param last the last time period in the axis range (<code>null</code> not permitted).
  * @param timeZone the time zone (<code>null</code> not permitted).
  * @param locale the locale (<code>null</code> not permitted).
  * @since 1.0.13
  */
 public PeriodAxis(
     String label,
     RegularTimePeriod first,
     RegularTimePeriod last,
     TimeZone timeZone,
     Locale locale) {
   super(label, null);
   if (timeZone == null) {
     throw new IllegalArgumentException("Null 'timeZone' argument.");
   }
   if (locale == null) {
     throw new IllegalArgumentException("Null 'locale' argument.");
   }
   this.first = first;
   this.last = last;
   this.timeZone = timeZone;
   this.locale = locale;
   this.calendar = Calendar.getInstance(timeZone, locale);
   this.first.peg(this.calendar);
   this.last.peg(this.calendar);
   this.autoRangeTimePeriodClass = first.getClass();
   this.majorTickTimePeriodClass = first.getClass();
   this.minorTickMarksVisible = false;
   this.minorTickTimePeriodClass = RegularTimePeriod.downsize(this.majorTickTimePeriodClass);
   setAutoRange(true);
   this.labelInfo = new PeriodAxisLabelInfo[2];
   this.labelInfo[0] = new PeriodAxisLabelInfo(Month.class, new SimpleDateFormat("MMM", locale));
   this.labelInfo[1] = new PeriodAxisLabelInfo(Year.class, new SimpleDateFormat("yyyy", locale));
 }
  @SuppressWarnings("LeakingThisInConstructor")
  public SleepDataTimeSeries(
      final String name,
      final SleepData sleepData,
      final Class<?> timePeriodClass,
      final int maxMovements) {
    super(name);
    this.maxMovements = maxMovements;

    movementsX = new HashMap<>();
    movementsY = new HashMap<>();

    // set start and end time
    timeZone = TimeZone.getDefault();
    final RegularTimePeriod startTime =
        RegularTimePeriod.createInstance(timePeriodClass, sleepData.calculateStartTime(), timeZone);
    add(startTime, 0);

    final Date endTime = sleepData.calculateEndTime();
    final RegularTimePeriod endTimePeriod =
        RegularTimePeriod.createInstance(timePeriodClass, endTime, timeZone);
    addOrUpdate(endTimePeriod, 0);

    for (MovementData movement : sleepData.getMovements()) {
      addMovementData(movement);
    }
  }
 /** A test for bug report 1161329. */
 public void test1161329() {
   TimePeriodValues tpv = new TimePeriodValues("Test");
   RegularTimePeriod t = new Day();
   tpv.add(t, 1.0);
   t = t.next();
   tpv.add(t, 2.0);
   tpv.delete(0, 1);
   assertEquals(0, tpv.getItemCount());
   tpv.add(t, 2.0);
   assertEquals(1, tpv.getItemCount());
 }
  /**
   * Creates the demo chart.
   *
   * @return The chart.
   *     <p>private JFreeChart createChart() {
   *     <p>XYDataset dataset1 = createDataset("Series 1", 100.0, new Minute(), 200);
   *     <p>JFreeChart chart = ChartFactory.createTimeSeriesChart( "Multiple Axis Demo 1", "Time of
   *     Day", "Primary Range Axis", dataset1, true, true, false );
   *     <p>chart.addSubtitle(new TextTitle("Four datasets and four range axes.")); XYPlot plot =
   *     (XYPlot) chart.getPlot(); plot.setOrientation(PlotOrientation.VERTICAL);
   *     <p>plot.getRangeAxis().setFixedDimension(15.0);
   *     <p>// AXIS 2 NumberAxis axis2 = new NumberAxis("Range Axis 2");
   *     axis2.setFixedDimension(10.0); axis2.setAutoRangeIncludesZero(false); plot.setRangeAxis(1,
   *     axis2); plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_LEFT);
   *     <p>XYDataset dataset2 = createDataset("Series 2", 1000.0, new Minute(), 170);
   *     plot.setDataset(1, dataset2); plot.mapDatasetToRangeAxis(1, 1); XYItemRenderer renderer2 =
   *     new StandardXYItemRenderer(); plot.setRenderer(1, renderer2);
   *     <p>// AXIS 3 NumberAxis axis3 = new NumberAxis("Range Axis 3"); plot.setRangeAxis(2,
   *     axis3);
   *     <p>XYDataset dataset3 = createDataset("Series 3", 10000.0, new Minute(), 170);
   *     plot.setDataset(2, dataset3); plot.mapDatasetToRangeAxis(2, 2); XYItemRenderer renderer3 =
   *     new StandardXYItemRenderer(); plot.setRenderer(2, renderer3);
   *     <p>// AXIS 4 NumberAxis axis4 = new NumberAxis("Range Axis 4"); plot.setRangeAxis(3,
   *     axis4);
   *     <p>XYDataset dataset4 = createDataset("Series 4", 25.0, new Minute(), 200);
   *     plot.setDataset(3, dataset4); plot.mapDatasetToRangeAxis(3, 3);
   *     <p>XYItemRenderer renderer4 = new StandardXYItemRenderer(); plot.setRenderer(3, renderer4);
   *     <p>ChartUtilities.applyCurrentTheme(chart);
   *     <p>// change the series and axis colours after the theme has // been applied...
   *     plot.getRenderer().setSeriesPaint(0, Color.black); renderer2.setSeriesPaint(0, Color.red);
   *     axis2.setLabelPaint(Color.red); axis2.setTickLabelPaint(Color.red);
   *     renderer3.setSeriesPaint(0, Color.blue); axis3.setLabelPaint(Color.blue);
   *     axis3.setTickLabelPaint(Color.blue); renderer4.setSeriesPaint(0, Color.green);
   *     axis4.setLabelPaint(Color.green); axis4.setTickLabelPaint(Color.green);
   *     <p>return chart; }
   *     <p>/** Creates a sample dataset.
   * @param name the dataset name.
   * @param base the starting value.
   * @param start the starting period.
   * @param count the number of values to generate.
   * @return The dataset.
   */
  private static TimeSeries createDataset(
      String name, double base, RegularTimePeriod start, int count) {

    TimeSeries series = new TimeSeries(name, start.getClass());
    RegularTimePeriod period = start;
    double value = base;
    for (int i = 0; i < count; i++) {
      series.add(period, value);
      period = period.next();
      value = value * (1 + (Math.random() - 0.495) / 10.0);
    }
    return series;
  }
    private XYDataset createDataset(
        String s, double d, RegularTimePeriod regulartimeperiod, int i) {
      series = new TimeSeries(s);
      RegularTimePeriod regulartimeperiod1 = regulartimeperiod;
      double d1 = d;
      for (int j = 0; j < i; j++) {
        series.add(regulartimeperiod1, d1);
        regulartimeperiod1 = regulartimeperiod1.next();
        d1 *= 1.0D + (Math.random() - 0.495D) / 10D;
      }

      TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();
      timeseriescollection.addSeries(series);
      return timeseriescollection;
    }
  private void addMovementData(MovementData data) {
    // get time of movement
    final RegularTimePeriod timePeriod =
        RegularTimePeriod.createInstance(getTimePeriodClass(), data.getTimestamp(), timeZone);

    int x;
    Integer xOld;
    if ((x = data.getMovementsX()) > 0) {
      if ((xOld = movementsX.get(timePeriod)) != null) {
        x += xOld;
      }
      movementsX.put(timePeriod, x);
    }

    int y;
    Integer yOld;
    if ((y = data.getMovementsY()) > 0) {
      if ((yOld = movementsY.get(timePeriod)) != null) {
        y += yOld;
      }
      movementsY.put(timePeriod, y);
    }

    if (x + y > 0) {
      final int value = (x > y ? x : y);
      final int trimmedValue = value < maxMovements ? value : maxMovements;

      delete(timePeriod);
      add(new TimeSeriesDataItem(timePeriod, trimmedValue));
    }
  }
 public TimePeriod getValueFromLuceneField(String documentValue) {
   Date date = LuceneUtils.stringToDate(documentValue);
   if (date == null) {
     return null;
   }
   return RegularTimePeriod.createInstance(timePeriodClass, date, periodTimeZone);
 }
  private void setDataByRow(final IPentahoResultSet data) {
    // TODO Make this routine MDX friendly
    if (data == null) {
      noDataMessage =
          Messages.getInstance().getString("CHART.USER_NO_DATA_AVAILABLE"); // $NON-NLS-1$
      return; // No data so we've got nothing to set
      // TODO come up with some sort of error strategy here.
    }
    Class timePeriodClass =
        TimeSeriesCollectionChartDefinition.getTimePeriodClass(getDomainPeriodType());
    Object[] rowData = data.next();
    while (rowData != null) {
      String seriesName = (String) rowData[0];
      TimeSeries wrkSeries = new TimeSeries(seriesName, timePeriodClass);
      for (int column = 1; column < rowData.length - 1; column = column + 2) {
        Date keyDate = getValidDate(rowData[column]);
        TimeSeriesDataItem timeSeriesDataItem =
            new TimeSeriesDataItem(
                RegularTimePeriod.createInstance(
                    timePeriodClass, keyDate, RegularTimePeriod.DEFAULT_TIME_ZONE),
                ((Number) rowData[column + 1]).doubleValue());
        wrkSeries.add(timeSeriesDataItem);
      }
      addSeries(wrkSeries);
      rowData = data.next();
    }

    if ((data.getRowCount() > 0) && (this.getSeriesCount() <= 0)) {
      noDataMessage =
          Messages.getInstance().getString("CHART.USER_INCORRECT_DATA_FORMAT"); // $NON-NLS-1$
    }
  }
    /**
     * Creates a sample dataset.
     *
     * @param name the dataset name.
     * @param base the starting value.
     * @param start the starting period.
     * @param count the number of values to generate.
     * @return The dataset.
     */
    private XYDataset createDataset(String name, double base, RegularTimePeriod start, int count) {

      this.series = new TimeSeries(name, start.getClass());
      RegularTimePeriod period = start;
      double value = base;
      for (int i = 0; i < count; i++) {
        this.series.add(period, value);
        period = period.next();
        value = value * (1 + (Math.random() - 0.495) / 10.0);
      }

      TimeSeriesCollection dataset = new TimeSeriesCollection();
      dataset.addSeries(this.series);

      return dataset;
    }
  /** Tests the equals method. */
  public void testEquals() {
    TimePeriodValues s1 = new TimePeriodValues("Time Series 1");
    TimePeriodValues s2 = new TimePeriodValues("Time Series 2");
    boolean b1 = s1.equals(s2);
    assertFalse("b1", b1);

    s2.setKey("Time Series 1");
    boolean b2 = s1.equals(s2);
    assertTrue("b2", b2);

    // domain description
    s1.setDomainDescription("XYZ");
    assertFalse(s1.equals(s2));
    s2.setDomainDescription("XYZ");
    assertTrue(s1.equals(s2));

    // domain description - null
    s1.setDomainDescription(null);
    assertFalse(s1.equals(s2));
    s2.setDomainDescription(null);
    assertTrue(s1.equals(s2));

    // range description
    s1.setRangeDescription("XYZ");
    assertFalse(s1.equals(s2));
    s2.setRangeDescription("XYZ");
    assertTrue(s1.equals(s2));

    // range description - null
    s1.setRangeDescription(null);
    assertFalse(s1.equals(s2));
    s2.setRangeDescription(null);
    assertTrue(s1.equals(s2));

    RegularTimePeriod p1 = new Day();
    RegularTimePeriod p2 = p1.next();
    s1.add(p1, 100.0);
    s1.add(p2, 200.0);
    boolean b3 = s1.equals(s2);
    assertFalse("b3", b3);

    s2.add(p1, 100.0);
    s2.add(p2, 200.0);
    boolean b4 = s1.equals(s2);
    assertTrue("b4", b4);
  }
 /**
  * Adds a data item to the series.
  *
  * @param period the period.
  * @param stochasticOscillator the StochasticOscillator.
  */
 public void add(RegularTimePeriod period, BigDecimal stochasticOscillator) {
   if (!this.isEmpty()) {
     StochasticOscillatorItem item0 = (StochasticOscillatorItem) this.getDataItem(0);
     if (!period.getClass().equals(item0.getPeriod().getClass())) {
       throw new IllegalArgumentException("Can't mix RegularTimePeriod class types.");
     }
   }
   super.add(new StochasticOscillatorItem(period, stochasticOscillator), true);
 }
 /**
  * Adds a data item to the series.
  *
  * @param period the period.
  * @param open the open-value.
  * @param high the high-value.
  * @param low the low-value.
  * @param close the close-value.
  */
 public void add(RegularTimePeriod period, double open, double high, double low, double close) {
   if (getItemCount() > 0) {
     OHLCItem item0 = (OHLCItem) this.getDataItem(0);
     if (!period.getClass().equals(item0.getPeriod().getClass())) {
       throw new IllegalArgumentException("Can't mix RegularTimePeriod class types.");
     }
   }
   super.add(new OHLCItem(period, open, high, low, close), true);
 }
 /**
  * Adds a data item to the series.
  *
  * @param period the period.
  * @param MACD the MACD.
  */
 public void add(
     RegularTimePeriod period, BigDecimal MACD, BigDecimal signalLine, BigDecimal MACDHistogram) {
   if (!this.isEmpty()) {
     MACDItem item0 = (MACDItem) this.getDataItem(0);
     if (!period.getClass().equals(item0.getPeriod().getClass())) {
       throw new IllegalArgumentException("Can't mix RegularTimePeriod class types.");
     }
   }
   super.add(new MACDItem(period, MACD, signalLine, MACDHistogram), true);
 }
  /** Tests the equals method. */
  @Test
  public void testEquals() {
    TimeSeries s1 = new TimeSeries("Time Series 1");
    TimeSeries s2 = new TimeSeries("Time Series 2");
    boolean b1 = s1.equals(s2);
    assertFalse("b1", b1);

    s2.setKey("Time Series 1");
    boolean b2 = s1.equals(s2);
    assertTrue("b2", b2);

    RegularTimePeriod p1 = new Day();
    RegularTimePeriod p2 = p1.next();
    s1.add(p1, 100.0);
    s1.add(p2, 200.0);
    boolean b3 = s1.equals(s2);
    assertFalse("b3", b3);

    s2.add(p1, 100.0);
    s2.add(p2, 200.0);
    boolean b4 = s1.equals(s2);
    assertTrue("b4", b4);

    s1.setMaximumItemCount(100);
    boolean b5 = s1.equals(s2);
    assertFalse("b5", b5);

    s2.setMaximumItemCount(100);
    boolean b6 = s1.equals(s2);
    assertTrue("b6", b6);

    s1.setMaximumItemAge(100);
    boolean b7 = s1.equals(s2);
    assertFalse("b7", b7);

    s2.setMaximumItemAge(100);
    boolean b8 = s1.equals(s2);
    assertTrue("b8", b8);
  }
  protected void customIncrement() {
    if (timeSeries != null && timeSeries.length > 0) {
      if (seriesNames == null) {
        seriesNames = new ArrayList<Comparable<?>>();
        seriesMap = new HashMap<Comparable<?>, TimeSeries>();
        labelsMap = new HashMap<Comparable<?>, Map<RegularTimePeriod, String>>();
        itemHyperlinks = new HashMap<Comparable<?>, Map<RegularTimePeriod, JRPrintHyperlink>>();
      }

      for (int i = 0; i < timeSeries.length; i++) {
        JRFillTimeSeries crtTimeSeries = timeSeries[i];

        Comparable<?> seriesName = crtTimeSeries.getSeries();
        if (seriesName == null) {
          throw new JRRuntimeException("Time series name is null.");
        }

        TimeSeries series = seriesMap.get(seriesName);
        if (series == null) {
          series = new TimeSeries(seriesName.toString(), getTimePeriod());
          seriesNames.add(seriesName);
          seriesMap.put(seriesName, series);
        }

        RegularTimePeriod tp =
            RegularTimePeriod.createInstance(
                getTimePeriod(), crtTimeSeries.getTimePeriod(), getTimeZone());

        series.addOrUpdate(tp, crtTimeSeries.getValue());

        if (crtTimeSeries.getLabelExpression() != null) {
          Map<RegularTimePeriod, String> seriesLabels = labelsMap.get(seriesName);
          if (seriesLabels == null) {
            seriesLabels = new HashMap<RegularTimePeriod, String>();
            labelsMap.put(seriesName, seriesLabels);
          }

          seriesLabels.put(tp, crtTimeSeries.getLabel());
        }

        if (crtTimeSeries.hasItemHyperlink()) {
          Map<RegularTimePeriod, JRPrintHyperlink> seriesLinks = itemHyperlinks.get(seriesName);
          if (seriesLinks == null) {
            seriesLinks = new HashMap<RegularTimePeriod, JRPrintHyperlink>();
            itemHyperlinks.put(seriesName, seriesLinks);
          }
          seriesLinks.put(tp, crtTimeSeries.getPrintItemHyperlink());
        }
      }
    }
  }
 private void setDataByColumn(final IPentahoResultSet data) {
   // TODO Make this routine MDX friendly
   if (data == null) {
     noDataMessage =
         Messages.getInstance().getString("CHART.USER_NO_DATA_AVAILABLE"); // $NON-NLS-1$
     return; // No data so we've got nothing to set
     // TODO come up with some sort of error strategy here.
   }
   boolean firstPass = true;
   String lastSeries = ""; // $NON-NLS-1$
   String seriesName = ""; // $NON-NLS-1$
   Class timePeriodClass =
       TimeSeriesCollectionChartDefinition.getTimePeriodClass(getDomainPeriodType());
   Object[] rowData = data.next();
   TimeSeries wrkSeries = null;
   while (rowData != null) {
     seriesName = (String) rowData[0];
     if (firstPass || !seriesName.equalsIgnoreCase(lastSeries)) {
       if (!firstPass) {
         addSeries(wrkSeries);
       }
       wrkSeries = new TimeSeries(seriesName, timePeriodClass);
       lastSeries = seriesName;
       firstPass = false;
     }
     Date keyDate = getValidDate(rowData[1]);
     RegularTimePeriod regularTimePeriod =
         RegularTimePeriod.createInstance(
             timePeriodClass, keyDate, RegularTimePeriod.DEFAULT_TIME_ZONE);
     TimeSeriesDataItem timeSeriesDataItem =
         new TimeSeriesDataItem(regularTimePeriod, ((Number) rowData[2]).doubleValue());
     if (wrkSeries != null) {
       wrkSeries.add(timeSeriesDataItem);
     }
     rowData = data.next();
   }
   if (!firstPass) {
     addSeries(wrkSeries);
   }
   if ((data.getRowCount() > 0) && (this.getSeriesCount() <= 0)) {
     noDataMessage =
         Messages.getInstance().getString("CHART.USER_INCORRECT_DATA_FORMAT"); // $NON-NLS-1$
   }
 }
  @Override
  public Document getXmlContent() {

    // Create a document that describes the result
    Document result = DocumentHelper.createDocument();
    IPentahoRequestContext requestContext = PentahoRequestContextHolder.getRequestContext();
    setXslProperty(
        "baseUrl", requestContext.getContextPath()); // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    setXslProperty(
        "fullyQualifiedServerUrl",
        PentahoSystem.getApplicationContext()
            .getFullyQualifiedServerURL()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    String mapName = "chart" + AbstractChartComponent.chartCount++; // $NON-NLS-1$
    Document chartDefinition =
        jcrHelper.getSolutionDocument(definitionPath, RepositoryFilePermission.READ);

    if (chartDefinition == null) {
      Element errorElement = result.addElement("error"); // $NON-NLS-1$
      errorElement
          .addElement("title")
          .setText(
              Messages.getInstance()
                  .getString(
                      "ABSTRACTCHARTEXPRESSION.ERROR_0001_ERROR_GENERATING_CHART")); //$NON-NLS-1$
                                                                                     // //$NON-NLS-2$
      String message =
          Messages.getInstance()
              .getString(
                  "CHARTS.ERROR_0001_CHART_DEFINIION_MISSING", definitionPath); // $NON-NLS-1$
      errorElement.addElement("message").setText(message); // $NON-NLS-1$
      error(message);
      return result;
    }
    // create a pie definition from the XML definition
    dataDefinition = createChart(chartDefinition);

    if (dataDefinition == null) {
      Element errorElement = result.addElement("error"); // $NON-NLS-1$
      errorElement
          .addElement("title")
          .setText(
              Messages.getInstance()
                  .getString(
                      "ABSTRACTCHARTEXPRESSION.ERROR_0001_ERROR_GENERATING_CHART")); //$NON-NLS-1$
                                                                                     // //$NON-NLS-2$
      String message =
          Messages.getInstance()
              .getString(
                  "CHARTS.ERROR_0002_CHART_DATA_MISSING",
                  actionPath); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
      errorElement.addElement("message").setText(message); // $NON-NLS-1$
      // System .out.println( result.asXML() );
      return result;
    }

    // create an image for the dial using the JFreeChart engine
    PrintWriter printWriter = new PrintWriter(new StringWriter());
    // we'll dispay the title in HTML so that the dial image does not have
    // to
    // accommodate it
    String chartTitle = ""; // $NON-NLS-1$
    try {
      if (width == -1) {
        width =
            Integer.parseInt(
                chartDefinition.selectSingleNode("/chart/width").getText()); // $NON-NLS-1$
      }
      if (height == -1) {
        height =
            Integer.parseInt(
                chartDefinition.selectSingleNode("/chart/height").getText()); // $NON-NLS-1$
      }
    } catch (Exception e) {
      // go with the default
    }
    if (chartDefinition.selectSingleNode("/chart/" + AbstractChartComponent.URLTEMPLATE_NODE_NAME)
        != null) { //$NON-NLS-1$
      urlTemplate =
          chartDefinition
              .selectSingleNode("/chart/" + AbstractChartComponent.URLTEMPLATE_NODE_NAME)
              .getText(); //$NON-NLS-1$
    }

    if (chartDefinition.selectSingleNode("/chart/paramName") != null) { // $NON-NLS-1$
      paramName = chartDefinition.selectSingleNode("/chart/paramName").getText(); // $NON-NLS-1$
    }

    Element root = result.addElement("charts"); // $NON-NLS-1$
    TimeSeriesCollection chartDataDefinition = (TimeSeriesCollection) dataDefinition;
    if (chartDataDefinition.getSeriesCount() > 0) {
      // create temporary file names
      String[] tempFileInfo = createTempFile();
      String fileName = tempFileInfo[AbstractChartComponent.FILENAME_INDEX];
      String filePathWithoutExtension =
          tempFileInfo[AbstractChartComponent.FILENAME_WITHOUT_EXTENSION_INDEX];

      ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
      JFreeChartEngine.saveChart(
          chartDataDefinition,
          chartTitle,
          "",
          filePathWithoutExtension,
          width,
          height,
          JFreeChartEngine.OUTPUT_PNG,
          printWriter,
          info,
          this); //$NON-NLS-1$
      applyOuterURLTemplateParam();
      populateInfo(info);
      Element chartElement = root.addElement("chart"); // $NON-NLS-1$
      chartElement.addElement("mapName").setText(mapName); // $NON-NLS-1$
      chartElement.addElement("width").setText(Integer.toString(width)); // $NON-NLS-1$
      chartElement.addElement("height").setText(Integer.toString(height)); // $NON-NLS-1$
      for (int row = 0; row < chartDataDefinition.getSeriesCount(); row++) {
        for (int column = 0; column < chartDataDefinition.getItemCount(row); column++) {
          Number value = chartDataDefinition.getY(row, column);
          Comparable rowKey = chartDataDefinition.getSeriesKey(row);
          RegularTimePeriod columnKey = chartDataDefinition.getSeries(row).getTimePeriod(column);
          Element valueElement = chartElement.addElement("value2D"); // $NON-NLS-1$
          valueElement.addElement("value").setText(value.toString()); // $NON-NLS-1$
          valueElement.addElement("row-key").setText(rowKey.toString()); // $NON-NLS-1$
          valueElement.addElement("column-key").setText(columnKey.toString()); // $NON-NLS-1$
        }
      }
      String mapString = ImageMapUtilities.getImageMap(mapName, info);
      chartElement.addElement("imageMap").setText(mapString); // $NON-NLS-1$
      chartElement.addElement("image").setText(fileName); // $NON-NLS-1$
    }
    return result;
  }
Exemple #18
0
  private ArrayList<DefaultXYZDataset> getXYBlockChartDatasetList(
      HashMap<String, TaskSeries> tsMap) {

    ArrayList<DefaultXYZDataset> datasetList = new ArrayList<DefaultXYZDataset>();
    DefaultXYZDataset datasetOverall = new DefaultXYZDataset();
    datasetList.add(datasetOverall);
    maxArray = new double[tsMap.keySet().size() + 1];
    maxArray[0] = Double.MIN_VALUE;
    int k = 0;

    if (performanceUI.isConsiderHoliday()) {
      holidays = performanceUI.getHolidayArray();
    }
    int startTime = 0;
    int endTime = 23;
    if (performanceUI.isConsiderWorkingHour()) {
      startTime = performanceUI.getStartHour();
      endTime = performanceUI.getEndHour();
    }

    for (String key : tsMap.keySet()) {
      // for the individual dataset
      Date startDate = null;
      Date endDate = null;
      maxArray[k + 1] = Double.MIN_VALUE;

      TaskSeries ts = tsMap.get(key);
      for (int i = 0; i < ts.getTasks().size(); i++) {
        Task task = ts.get(i);
        SimpleTimePeriod stp = (SimpleTimePeriod) task.getDuration();
        if (startDate == null || startDate.after(stp.getStart())) {
          startDate = stp.getStart();
        }
        if (endDate == null || endDate.before(stp.getEnd())) {
          endDate = stp.getEnd();
        }
      }

      int duration;
      if (endDate != null && startDate != null) {
        duration = (int) ((endDate.getTime() / 86400000L - startDate.getTime() / 86400000L)) + 1;
      } else {
        duration = -1;
      }

      if (duration == -1) continue;

      double[] xvalues = new double[duration * 24];
      double[] yvalues = new double[duration * 24];
      double[] zvalues = new double[duration * 24];

      RegularTimePeriod t = new Day(startDate);
      for (int days = 0; days < duration; days++) {
        for (int hour = 0; hour < 24; hour++) {
          xvalues[days * 24 + hour] = t.getFirstMillisecond();
          yvalues[days * 24 + hour] = hour;
          zvalues[days * 24 + hour] = 0.0;
        }
        t = t.next();
      }

      for (int i = 0; i < ts.getTasks().size(); i++) {
        Task task = ts.get(i);
        SimpleTimePeriod stp = (SimpleTimePeriod) task.getDuration();

        int day1 =
            (int) ((stp.getStart().getTime() / 86400000L) - (startDate.getTime() / 86400000L));
        int hour1 =
            (int)
                ((stp.getStart().getTime() - (stp.getStart().getTime() / 86400000L) * 86400000L)
                    / 3600000L);
        double time1 =
            (double) (stp.getStart().getTime() - (stp.getStart().getTime() / 3600000L) * 3600000L)
                / ((double) getTimeUnit());
        time1 = ((double) (3600000L - time1)) / (double) getTimeUnit();
        int day2 = (int) ((stp.getEnd().getTime() / 86400000L) - (startDate.getTime() / 86400000L));
        int hour2 =
            (int)
                ((stp.getEnd().getTime() - (stp.getEnd().getTime() / 86400000L) * 86400000L)
                    / 3600000L);
        double time2 =
            ((double) (stp.getEnd().getTime() - (stp.getEnd().getTime() / 3600000L) * 3600000L))
                / ((double) getTimeUnit());

        zvalues[day1 * 24 + hour1] = zvalues[day1 * 24 + hour1] + time1;
        maxArray[k + 1] = Math.max(zvalues[day1 * 24 + hour1], maxArray[k + 1]);
        if ((day1 * 24 + hour1) != (day2 * 24 + hour2)) {
          zvalues[day2 * 24 + hour2] = zvalues[day2 * 24 + hour2] + time2;
          maxArray[k + 1] = Math.max(zvalues[day2 * 24 + hour2], maxArray[k + 1]);
        }
        for (int j = (day1 * 24 + hour1) + 1; j < (day2 * 24 + hour2); j++) {
          if (!performanceUI.isConsiderHoliday() || holidays[j / 24]) {
            if ((j % 24) >= startTime && (j % 24) <= endTime) {
              zvalues[j] = zvalues[j] + (3600000.0 / getTimeUnit());
              maxArray[k + 1] = Math.max(zvalues[j], maxArray[k + 1]);
            }
          }
        }
      }
      DefaultXYZDataset dataset = new DefaultXYZDataset();
      dataset.addSeries(key, new double[][] {xvalues, yvalues, zvalues});
      datasetList.add(dataset);
      k++;

      if (startDateOverall == null || startDateOverall.after(startDate)) {
        startDateOverall = startDate;
      }
      if (endDateOverall == null || endDateOverall.before(endDate)) {
        endDateOverall = endDate;
      }
    }

    int duration;
    if (endDateOverall != null && startDateOverall != null) {
      duration =
          (int) ((endDateOverall.getTime() / 86400000L - startDateOverall.getTime() / 86400000L))
              + 1;
    } else {
      duration = -1;
    }
    if (duration == -1) return datasetList;
    double[] xvalues = new double[duration * 24];
    double[] yvalues = new double[duration * 24];
    double[] zvalues = new double[duration * 24];

    RegularTimePeriod t = new Day(startDateOverall);
    for (int days = 0; days < duration; days++) {
      for (int hour = 0; hour < 24; hour++) {
        xvalues[days * 24 + hour] = t.getFirstMillisecond();
        yvalues[days * 24 + hour] = hour;
        zvalues[days * 24 + hour] = 0.0;
      }
      t = t.next();
    }

    for (TaskSeries ts : tsMap.values()) {
      for (int i = 0; i < ts.getTasks().size(); i++) {
        Task task = ts.get(i);
        SimpleTimePeriod stp = (SimpleTimePeriod) task.getDuration();

        int day1 =
            (int)
                ((stp.getStart().getTime() / 86400000L) - (startDateOverall.getTime() / 86400000L));
        int hour1 =
            (int)
                ((stp.getStart().getTime() - (stp.getStart().getTime() / 86400000L) * 86400000L)
                    / 3600000L);
        double time1 =
            (double) (stp.getStart().getTime() - (stp.getStart().getTime() / 3600000L) * 3600000L)
                / ((double) getTimeUnit());
        time1 = ((double) (3600000L - time1)) / (double) getTimeUnit();
        int day2 =
            (int) ((stp.getEnd().getTime() / 86400000L) - (startDateOverall.getTime() / 86400000L));
        int hour2 =
            (int)
                ((stp.getEnd().getTime() - (stp.getEnd().getTime() / 86400000L) * 86400000L)
                    / 3600000L);
        double time2 =
            ((double) (stp.getEnd().getTime() - (stp.getEnd().getTime() / 3600000L) * 3600000L))
                / ((double) getTimeUnit());

        zvalues[day1 * 24 + hour1] = zvalues[day1 * 24 + hour1] + time1;
        maxArray[0] = Math.max(zvalues[day1 * 24 + hour1], maxArray[0]);
        if ((day1 * 24 + hour1) != (day2 * 24 + hour2)) {
          zvalues[day2 * 24 + hour2] = zvalues[day2 * 24 + hour2] + time2;
          maxArray[0] = Math.max(zvalues[day2 * 24 + hour2], maxArray[0]);
        }
        for (int j = (day1 * 24 + hour1) + 1; j < (day2 * 24 + hour2); j++) {
          if (!performanceUI.isConsiderHoliday() || holidays[j / 24]) {
            if ((j % 24) >= startTime && (j % 24) <= endTime) {
              zvalues[j] = zvalues[j] + (3600000.0 / getTimeUnit());
              maxArray[0] = Math.max(zvalues[j], maxArray[0]);
            }
          }
        }
      }
    }

    datasetOverall.addSeries("Overall", new double[][] {xvalues, yvalues, zvalues});

    return datasetList;
  }
 /**
  * Draws the major and minor tick marks for an axis that lies at the top or bottom of the plot.
  *
  * @param g2 the graphics device.
  * @param state the axis state.
  * @param dataArea the data area.
  * @param edge the edge.
  */
 protected void drawTickMarksHorizontal(
     Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) {
   List<ValueTick> ticks = new ArrayList<ValueTick>();
   double x0;
   double y0 = state.getCursor();
   double insideLength = getTickMarkInsideLength();
   double outsideLength = getTickMarkOutsideLength();
   RegularTimePeriod t =
       createInstance(
           this.majorTickTimePeriodClass, this.first.getStart(), getTimeZone(), this.locale);
   long t0 = t.getFirstMillisecond();
   Line2D inside = null;
   Line2D outside = null;
   long firstOnAxis = getFirst().getFirstMillisecond();
   long lastOnAxis = getLast().getLastMillisecond() + 1;
   while (t0 <= lastOnAxis) {
     ticks.add(new NumberTick((double) t0, "", TextAnchor.CENTER, TextAnchor.CENTER, 0.0));
     x0 = valueToJava2D(t0, dataArea, edge);
     if (edge == RectangleEdge.TOP) {
       inside = new Line2D.Double(x0, y0, x0, y0 + insideLength);
       outside = new Line2D.Double(x0, y0, x0, y0 - outsideLength);
     } else if (edge == RectangleEdge.BOTTOM) {
       inside = new Line2D.Double(x0, y0, x0, y0 - insideLength);
       outside = new Line2D.Double(x0, y0, x0, y0 + outsideLength);
     }
     if (t0 >= firstOnAxis) {
       g2.setPaint(getTickMarkPaint());
       g2.setStroke(getTickMarkStroke());
       g2.draw(inside);
       g2.draw(outside);
     }
     // draw minor tick marks
     if (this.minorTickMarksVisible) {
       RegularTimePeriod tminor =
           createInstance(this.minorTickTimePeriodClass, new Date(t0), getTimeZone(), this.locale);
       long tt0 = tminor.getFirstMillisecond();
       while (tt0 < t.getLastMillisecond() && tt0 < lastOnAxis) {
         double xx0 = valueToJava2D(tt0, dataArea, edge);
         if (edge == RectangleEdge.TOP) {
           inside = new Line2D.Double(xx0, y0, xx0, y0 + this.minorTickMarkInsideLength);
           outside = new Line2D.Double(xx0, y0, xx0, y0 - this.minorTickMarkOutsideLength);
         } else if (edge == RectangleEdge.BOTTOM) {
           inside = new Line2D.Double(xx0, y0, xx0, y0 - this.minorTickMarkInsideLength);
           outside = new Line2D.Double(xx0, y0, xx0, y0 + this.minorTickMarkOutsideLength);
         }
         if (tt0 >= firstOnAxis) {
           g2.setPaint(this.minorTickMarkPaint);
           g2.setStroke(this.minorTickMarkStroke);
           g2.draw(inside);
           g2.draw(outside);
         }
         tminor = tminor.next();
         tminor.peg(this.calendar);
         tt0 = tminor.getFirstMillisecond();
       }
     }
     t = t.next();
     t.peg(this.calendar);
     t0 = t.getFirstMillisecond();
   }
   if (edge == RectangleEdge.TOP) {
     state.cursorUp(Math.max(outsideLength, this.minorTickMarkOutsideLength));
   } else if (edge == RectangleEdge.BOTTOM) {
     state.cursorDown(Math.max(outsideLength, this.minorTickMarkOutsideLength));
   }
   state.setTicks(ticks);
 }
  /**
   * Draws the tick labels for one "band" of time periods.
   *
   * @param band the band index (zero-based).
   * @param g2 the graphics device.
   * @param state the axis state.
   * @param dataArea the data area.
   * @param edge the edge where the axis is located.
   * @return The updated axis state.
   */
  protected AxisState drawTickLabels(
      int band, Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) {

    // work out the initial gap
    double delta1 = 0.0;
    FontMetrics fm = g2.getFontMetrics(this.labelInfo[band].getLabelFont());
    if (edge == RectangleEdge.BOTTOM) {
      delta1 = this.labelInfo[band].getPadding().calculateTopOutset(fm.getHeight());
    } else if (edge == RectangleEdge.TOP) {
      delta1 = this.labelInfo[band].getPadding().calculateBottomOutset(fm.getHeight());
    }
    state.moveCursor(delta1, edge);
    long axisMin = this.first.getFirstMillisecond();
    long axisMax = this.last.getLastMillisecond();
    g2.setFont(this.labelInfo[band].getLabelFont());
    g2.setPaint(this.labelInfo[band].getLabelPaint());

    // work out the number of periods to skip for labelling
    RegularTimePeriod p1 =
        this.labelInfo[band].createInstance(new Date(axisMin), this.timeZone, this.locale);
    RegularTimePeriod p2 =
        this.labelInfo[band].createInstance(new Date(axisMax), this.timeZone, this.locale);
    String label1 =
        this.labelInfo[band].getDateFormat().format(new Date(p1.getMiddleMillisecond()));
    String label2 =
        this.labelInfo[band].getDateFormat().format(new Date(p2.getMiddleMillisecond()));
    Rectangle2D b1 = TextUtilities.getTextBounds(label1, g2, g2.getFontMetrics());
    Rectangle2D b2 = TextUtilities.getTextBounds(label2, g2, g2.getFontMetrics());
    double w = Math.max(b1.getWidth(), b2.getWidth());
    long ww = Math.round(java2DToValue(dataArea.getX() + w + 5.0, dataArea, edge));
    if (isInverted()) {
      ww = axisMax - ww;
    } else {
      ww = ww - axisMin;
    }
    long length = p1.getLastMillisecond() - p1.getFirstMillisecond();
    int periods = (int) (ww / length) + 1;

    RegularTimePeriod p =
        this.labelInfo[band].createInstance(new Date(axisMin), this.timeZone, this.locale);
    Rectangle2D b = null;
    long lastXX = 0L;
    float y = (float) (state.getCursor());
    TextAnchor anchor = TextAnchor.TOP_CENTER;
    float yDelta = (float) b1.getHeight();
    if (edge == RectangleEdge.TOP) {
      anchor = TextAnchor.BOTTOM_CENTER;
      yDelta = -yDelta;
    }
    while (p.getFirstMillisecond() <= axisMax) {
      float x = (float) valueToJava2D(p.getMiddleMillisecond(), dataArea, edge);
      DateFormat df = this.labelInfo[band].getDateFormat();
      String label = df.format(new Date(p.getMiddleMillisecond()));
      long first = p.getFirstMillisecond();
      long last = p.getLastMillisecond();
      if (last > axisMax) {
        // this is the last period, but it is only partially visible
        // so check that the label will fit before displaying it...
        Rectangle2D bb = TextUtilities.getTextBounds(label, g2, g2.getFontMetrics());
        if ((x + bb.getWidth() / 2) > dataArea.getMaxX()) {
          float xstart = (float) valueToJava2D(Math.max(first, axisMin), dataArea, edge);
          if (bb.getWidth() < (dataArea.getMaxX() - xstart)) {
            x = ((float) dataArea.getMaxX() + xstart) / 2.0f;
          } else {
            label = null;
          }
        }
      }
      if (first < axisMin) {
        // this is the first period, but it is only partially visible
        // so check that the label will fit before displaying it...
        Rectangle2D bb = TextUtilities.getTextBounds(label, g2, g2.getFontMetrics());
        if ((x - bb.getWidth() / 2) < dataArea.getX()) {
          float xlast = (float) valueToJava2D(Math.min(last, axisMax), dataArea, edge);
          if (bb.getWidth() < (xlast - dataArea.getX())) {
            x = (xlast + (float) dataArea.getX()) / 2.0f;
          } else {
            label = null;
          }
        }
      }
      if (label != null) {
        g2.setPaint(this.labelInfo[band].getLabelPaint());
        b = TextUtilities.drawAlignedString(label, g2, x, y, anchor);
      }
      if (lastXX > 0L) {
        if (this.labelInfo[band].getDrawDividers()) {
          long nextXX = p.getFirstMillisecond();
          long mid = (lastXX + nextXX) / 2;
          float mid2d = (float) valueToJava2D(mid, dataArea, edge);
          g2.setStroke(this.labelInfo[band].getDividerStroke());
          g2.setPaint(this.labelInfo[band].getDividerPaint());
          g2.draw(new Line2D.Float(mid2d, y, mid2d, y + yDelta));
        }
      }
      lastXX = last;
      for (int i = 0; i < periods; i++) {
        p = p.next();
      }
      p.peg(this.calendar);
    }
    double used = 0.0;
    if (b != null) {
      used = b.getHeight();
      // work out the trailing gap
      if (edge == RectangleEdge.BOTTOM) {
        used += this.labelInfo[band].getPadding().calculateBottomOutset(fm.getHeight());
      } else if (edge == RectangleEdge.TOP) {
        used += this.labelInfo[band].getPadding().calculateTopOutset(fm.getHeight());
      }
    }
    state.moveCursor(used, edge);
    return state;
  }
  private void addData(
      JFreeChart chart,
      DSLAMSource source,
      Timeinterval time,
      Serializable filter,
      Properties properties,
      Map<String, Object> colorScheme,
      Properties outputProperties)
      throws IOException {
    if (chart != null) {
      PerformanceCounterDataCollection cData = null;

      long dataSize = 0;

      try {
        cData =
            getPerformanceCounterDataCollection(source, time, filter, properties, outputProperties);
        Collection<PerformanceCounterData> data = null;

        Date d0 = null; // first timestamp for data
        Date d1 = null; // last timestamp for data
        RegularTimePeriod time0 = null;

        if (cData != null) {
          data = cData.getData();

          {
            int l = data.size();
            outputProperties.setProperty("data.count", Integer.toString(l));
          }

          if (data != null && data.size() > 0) {
            dataSize = data.size();

            // Set 'd0':
            {
              // TODO: Avoid assumption "data is sorted"!
              PerformanceCounterData e = data.iterator().next();
              d0 = e.getTimestamp();
            }

            // Set 'd1':
            {
              // TODO: Avoid assumption "data is sorted"!
              for (PerformanceCounterData e : data) {
                d1 = e.getTimestamp();
              }
            }

            time0 = createRegularTimePeriod(d0);
          }
        }

        XYPlot plot = chart.getXYPlot();

        // Set the first dataset:
        {
          TimeSeriesCollection dataset = new TimeSeriesCollection();

          List<Paint> seriesPaint = new ArrayList<Paint>();
          List<Stroke> seriesStroke = new ArrayList<Stroke>();

          // Add series 'ES':
          {
            if (data != null && data.size() > 0) {
              TimeSeries series = new TimeSeries("ES", time0.getClass());

              for (PerformanceCounterData e : data) {
                Date d = e.getTimestamp();
                RegularTimePeriod timePeriod = createRegularTimePeriod(d);

                // Add point:
                {
                  int value = getES(e);

                  addOrUpdate(series, timePeriod, (double) value);
                }
              }

              seriesPaint.add((Paint) colorScheme.get("color.counter.es"));
              seriesStroke.add(STROKE_COUNTER_ES);

              dataset.addSeries(series);
            }
          }

          // Add series 'SES':
          {
            if (data != null && data.size() > 0) {
              TimeSeries series = new TimeSeries("SES", time0.getClass());

              for (PerformanceCounterData e : data) {
                Date d = e.getTimestamp();
                RegularTimePeriod timePeriod = createRegularTimePeriod(d);

                // Add point:
                {
                  int value = getSES(e);

                  addOrUpdate(series, timePeriod, (double) value);
                }
              }

              seriesPaint.add((Paint) colorScheme.get("color.counter.ses"));
              seriesStroke.add(STROKE_COUNTER_SES);

              dataset.addSeries(series);
            }
          }

          // Add series 'US':
          {
            if (data != null && data.size() > 0) {
              TimeSeries series = new TimeSeries("US", time0.getClass());

              for (PerformanceCounterData e : data) {
                Date d = e.getTimestamp();
                RegularTimePeriod timePeriod = createRegularTimePeriod(d);

                // Add point:
                {
                  int value = getUS(e);

                  addOrUpdate(series, timePeriod, (double) value);
                }
              }

              seriesPaint.add((Paint) colorScheme.get("color.counter.us"));
              seriesStroke.add(STROKE_COUNTER_US);

              dataset.addSeries(series);
            }
          }

          // superspeed
          {
            if (data != null && data.size() > 0) {
              TimeSeries series = new TimeSeries("LEFTRS", time0.getClass());
              for (PerformanceCounterData e : data) {
                Date d = e.getTimestamp();
                RegularTimePeriod timePeriod = createRegularTimePeriod(d);
                {
                  int value = getPreviousLEFTRS(e);
                  addOrUpdate(series, timePeriod, (double) value);
                }
              }
              seriesPaint.add((Paint) colorScheme.get("color.counter.previousleftrs"));
              seriesStroke.add(STROKE_COUNTER_US);
              dataset.addSeries(series);
            }
          }
          // ends
          {
            if (data != null && data.size() > 0) {
              boolean showLinearCurve = getShowLinearCurve();

              if (showLinearCurve) {
                // Add series for a linear curve:
                {
                  TimeSeries series = new TimeSeries("Linear", time0.getClass());

                  long t0 = d0.getTime();
                  long t1 = d1.getTime();

                  if (t0 < t1) {
                    long timeX = 15 * 60 * 1000; // 15 minutes intervals
                    // TODO: Read length of intervals from obtained data!

                    double value0 = 0;
                    double value1 = 900;
                    // TODO: Read '900' from obtained data!

                    long timeDelta = t1 - t0;
                    double valueDelta = value1 - value0;

                    long t = t0;
                    int i = 0;

                    while (t <= t1) {
                      Date d = new Date(t);

                      RegularTimePeriod timePeriod = createRegularTimePeriod(d);
                      double value = value0 + ((t - t0) * valueDelta) / timeDelta;

                      // Add point:
                      {
                        addOrUpdate(series, timePeriod, (double) value);
                      }

                      t += timeX;
                      i += 1;
                    }
                  }

                  seriesPaint.add(Color.red);
                  seriesStroke.add(STROKE_COUNTER_DEFAULT);

                  dataset.addSeries(series);
                }
              }
            }
          }

          setDefaultRenderer(chart, colorScheme, 0, seriesPaint, seriesStroke);
          plot.setDataset(0, dataset);
          plot.mapDatasetToRangeAxis(0, 0);
        }
      } finally {
        if (cData != null) {
          cData.dispose();
          cData = null;
        }
      }

      if (outputProperties != null) {
        outputProperties.setProperty("data.count", Long.toString(dataSize));
      }
    }
  }
  /**
   * Tests the correct output of a DataSet to a TimeSeries by outputting it, then iterating through
   * TimeSeries object checking the correct values were stored/output.
   */
  public void testOutput()
      throws ClassNotFoundException, NoSuchMethodException, InstantiationException,
          IllegalAccessException, InvocationTargetException, InstantiationException {
    // Constants used to determine size of test
    int NUMBER_OF_TIME_PERIODS = 10;
    String TIME_VARIABLE = "t";

    // Set up array for expected results
    double expectedValue[] = new double[NUMBER_OF_TIME_PERIODS];

    // We'll set up periods starting from today
    RegularTimePeriod period = new Day();

    // Create a test DataSet for output
    //  - note that only one independent variable (the time variable)
    //    will be output. This is expected.
    DataSet dataSet = new DataSet();
    dataSet.setTimeVariable(TIME_VARIABLE);
    for (int d = 0; d < NUMBER_OF_TIME_PERIODS; d++) {
      double value = (double) d;
      DataPoint obs = new Observation(value);
      obs.setIndependentValue(TIME_VARIABLE, period.getMiddleMillisecond());
      dataSet.add(obs);

      period = period.next();
      expectedValue[d] = value;
    }

    assertEquals(
        "Checking only one independent variable exists in dataSet",
        1,
        dataSet.getIndependentVariables().length);

    assertEquals(
        "Checking dataSet has correct number of entries", NUMBER_OF_TIME_PERIODS, dataSet.size());

    // Create TimeSeriesOutputter and use it to output dataSet
    TimeSeries timeSeries = new TimeSeries("test");
    TimeSeriesOutputter outputter = new TimeSeriesOutputter(timeSeries, period.getClass());
    outputter.output(dataSet);

    assertEquals(
        "Checking number of items in time series",
        NUMBER_OF_TIME_PERIODS,
        timeSeries.getItemCount());

    // Reset period to start checking from today onwards
    period = new Day();
    for (int d = 0; d < NUMBER_OF_TIME_PERIODS; d++) {
      TimeSeriesDataItem dataItem = timeSeries.getDataItem(d);

      period = dataItem.getPeriod();
      assertNotNull("Checking time period", period);

      long timeValue = period.getMiddleMillisecond();
      assertTrue(
          "Checking time periods match",
          (double) timeValue >= period.getFirstMillisecond()
              && (double) timeValue <= period.getLastMillisecond());

      assertEquals(
          "Checking values for period " + dataItem.getPeriod() + " match",
          expectedValue[d],
          dataItem.getValue().doubleValue(),
          TOLERANCE);

      period = period.next();
    }
  }