public LegendItemCollection getLegendItems(PlotInstance plotInstance) {
    PlotConfiguration plotConfiguration = plotInstance.getCurrentPlotConfigurationClone();
    LegendItemCollection legendItemCollection = new LegendItemCollection();

    // Get list of ValueSources which get an own legend entry.
    // These are those ValueSources, for which useSeriesFormatForDimension() returns true
    // for at least one dimension (not considering X and VALUE).

    // get all values sources
    List<ValueSource> allValueSources = plotConfiguration.getAllValueSources();

    // add the plots heading (if we have any value sources)
    if (!allValueSources.isEmpty()) {
      legendItemCollection.add(
          createTitleLegendItem(
              I18N.getGUILabel("plotter.legend.plots_heading.label") + ":", plotConfiguration));
    }

    // now find those value sources for which we need a legend entry,
    // and also remember which dimensions are shown in the legend entry (color, shape, ...)
    for (ValueSource valueSource : allValueSources) {
      CustomLegendItem legendItem = createValueSourceLegendItem(plotConfiguration, valueSource);
      if (legendItem != null) {
        legendItemCollection.add(legendItem);
      }
    }

    List<Set<PlotDimension>> dimensionsWithLegend =
        findCompatibleDimensions(plotConfiguration, allValueSources);

    // create legend items for DimensionConfigs
    for (Set<PlotDimension> dimensionSet : dimensionsWithLegend) {
      PlotDimension aDimension = dimensionSet.iterator().next();
      DimensionConfig dimensionConfig = plotConfiguration.getDimensionConfig(aDimension);

      createDimensionConfigLegendItem(
          plotInstance,
          (DefaultDimensionConfig) dimensionConfig,
          dimensionSet,
          legendItemCollection);
    }
    return legendItemCollection;
  }
  public PlotData(PlotInstance plotInstance, DataTable dataTable) {
    if (plotInstance == null) {
      throw new IllegalArgumentException("null not allowed for plotInstance");
    }
    this.plotInstance = plotInstance;
    plotInstance.setPlotData(this);
    PlotConfiguration plotConfiguration = plotInstance.getMasterPlotConfiguration();
    //		if (plotConfiguration.getPrioritizedListenerCount() > 0) {
    //			plotConfiguration.clearPrioritizedListeners();
    //		}
    plotConfiguration.addPlotConfigurationListener(this, true);

    this.originalDataTable = dataTable;
    originalDataTable.addDataTableListener(this, true);

    valueMappingDataTable = new ValueMappingDataTableView(originalDataTable);
    for (int i = 0; i < valueMappingDataTable.getColumnNumber(); ++i) {
      if (valueMappingDataTable.isNominal(i)) {
        valueMappingDataTable.setMappingProvider(
            i, new NominalSortingDataTableMapping(valueMappingDataTable, i, true));
      }
    }

    // add filtered data table view to view stack
    filteredDataTableView = new FilteredDataTable(valueMappingDataTable);

    // add sorted data table view on view stack (without sort provider for now)
    sortedDataTableView = new SortedDataTableView(filteredDataTableView, null);
    sortedDataTableView.addDataTableListener(this, true);

    // init valueSourceDataMap
    for (ValueSource valueSource : plotConfiguration.getAllValueSources()) {
      ValueSourceData valueSourceData = new ValueSourceData(valueSource, plotInstance);
      valueSourceDataMap.put(valueSource.getId(), valueSourceData);
    }

    // init dimensionConfigDataMap
    for (DefaultDimensionConfig dimensionConfig :
        plotConfiguration.getDefaultDimensionConfigs().values()) {
      DimensionConfigData dimensionConfigData =
          new DimensionConfigData(plotInstance, dimensionConfig);
      dimensionConfigDataMap.put(dimensionConfig.getId(), dimensionConfigData);
    }
    DefaultDimensionConfig domainConfig;
    domainConfig = plotConfiguration.getDomainConfigManager().getDomainConfig(true);
    dimensionConfigDataMap.put(
        domainConfig.getId(), new DimensionConfigData(plotInstance, domainConfig));
    domainConfig = plotConfiguration.getDomainConfigManager().getDomainConfig(false);
    dimensionConfigDataMap.put(
        domainConfig.getId(), new DimensionConfigData(plotInstance, domainConfig));

    // init DomainConfigManagerData
    domainConfigManagerData = new DomainConfigManagerData(plotInstance);

    // init RangeAxisDataMap
    for (RangeAxisConfig rangeAxisConfig : plotConfiguration.getRangeAxisConfigs()) {
      RangeAxisData rangeAxisData = new RangeAxisData(rangeAxisConfig, plotInstance);
      rangeAxisDataMap.put(rangeAxisConfig.getId(), rangeAxisData);
    }

    clearCache();
  }
  private void createDimensionConfigLegendItem(
      PlotInstance plotInstance,
      DefaultDimensionConfig dimensionConfig,
      Set<PlotDimension> dimensionSet,
      LegendItemCollection legendItemCollection) {
    PlotConfiguration plotConfiguration = plotInstance.getCurrentPlotConfigurationClone();
    DimensionConfigData dimensionConfigData =
        plotInstance.getPlotData().getDimensionConfigData(dimensionConfig);
    if (dimensionConfig.isGrouping()) {
      // create legend entry based on the grouping
      if (dimensionConfig.isNominal()) {
        // create categorical legend --> one item for each category
        createCategoricalLegendItems(
            plotInstance,
            dimensionSet,
            legendItemCollection,
            dimensionConfigData.getDistinctValues());
      } else if (dimensionConfig.isNumerical() || dimensionConfig.isDate()) {
        createDimensionTitleLegendItem(plotInstance, dimensionSet, legendItemCollection);

        // create one continuous legend item
        double minValue = dimensionConfigData.getMinValue();
        double maxValue = dimensionConfigData.getMaxValue();

        LegendItem legendItem =
            createContinuousLegendItem(
                plotInstance,
                dimensionSet,
                minValue,
                maxValue,
                dimensionConfig.isDate() ? dimensionConfig.getDateFormat() : null);
        if (legendItem != null) {
          legendItemCollection.add(legendItem);
        }
      } else {
        throw new RuntimeException(
            "unknown data type during legend creation - this should not happen");
      }
    } else {
      // dimension config not grouping --> create legend item only, if there exists
      // at least one non-aggregated value source (otherwise the dimension config is
      // not used at all in the plot and thus we also don't need a legend item for it).
      boolean createLegend = false;
      for (ValueSource valueSource : plotConfiguration.getAllValueSources()) {
        if (!valueSource.isUsingDomainGrouping()) {
          createLegend = true;
          break;
        }
      }
      if (createLegend) {
        // create legend based on the attribute values on the dimension config
        if (dimensionConfig.isNominal()) {
          // create one legend item for each nominal value
          List<Double> values = dimensionConfigData.getDistinctValues();
          createCategoricalLegendItems(plotInstance, dimensionSet, legendItemCollection, values);
        } else if (dimensionConfig.isNumerical() || dimensionConfig.isDate()) {
          createDimensionTitleLegendItem(plotInstance, dimensionSet, legendItemCollection);

          // create one continuous legend item for the value range
          double minValue = dimensionConfigData.getMinValue();
          double maxValue = dimensionConfigData.getMaxValue();

          LegendItem legendItem =
              createContinuousLegendItem(
                  plotInstance,
                  dimensionSet,
                  minValue,
                  maxValue,
                  dimensionConfig.isDate() ? dimensionConfig.getDateFormat() : null);
          if (legendItem != null) {
            legendItemCollection.add(legendItem);
          }
        } else {
          throw new RuntimeException(
              "unknown data type during legend creation - this should not happen");
        }
      }
    }
  }