[Schmitzm-commits] r751 - in trunk/src/schmitzm/jfree/feature: . style

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed Mar 3 15:26:40 CET 2010


Author: mojays
Date: 2010-03-03 15:26:40 +0100 (Wed, 03 Mar 2010)
New Revision: 751

Modified:
   trunk/src/schmitzm/jfree/feature/AggregationFunction.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
Log:
Normalization of aggregated (and weighted) attributes.

Modified: trunk/src/schmitzm/jfree/feature/AggregationFunction.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/AggregationFunction.java	2010-03-03 12:48:23 UTC (rev 750)
+++ trunk/src/schmitzm/jfree/feature/AggregationFunction.java	2010-03-03 14:26:40 UTC (rev 751)
@@ -84,7 +84,6 @@
 	public Double getResult(QuantileBin1D statistics) {
 		switch (this) {
 		case AVG:
-		case AVG_WEIGHTED:
 			return statistics.mean();
 		case MEDIAN:
 			return statistics.median();
@@ -95,6 +94,7 @@
 			// case SUM_ABS: // SK: Man müsste beim
 			// "packen der daten in die Statistik" schon abs() auf die werte
 			// anwenden und dann diese zeile einkommentieren
+		case AVG_WEIGHTED:
 		case SUM:
 			return statistics.sum();
 		case COUNT:

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2010-03-03 12:48:23 UTC (rev 750)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2010-03-03 14:26:40 UTC (rev 751)
@@ -59,6 +59,8 @@
 import org.opengis.feature.type.AttributeDescriptor;
 import org.opengis.feature.type.Name;
 
+import com.sun.org.apache.xml.internal.security.encryption.AgreementMethod;
+
 import schmitzm.geotools.feature.FeatureUtil;
 import schmitzm.geotools.feature.PipedFeatureIterator;
 import schmitzm.jfree.JFreeChartUtil;
@@ -77,767 +79,732 @@
 /**
  * This class contains static utility methods related to chart styles based on
  * {@link FeatureCollection}.
- * 
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
  * @version 1.0
  */
 public class FeatureChartUtil {
-	final static Logger LOGGER = Logger.getLogger(FeatureChartUtil.class);
+  final static Logger LOGGER = Logger.getLogger(FeatureChartUtil.class);
 
-	/** Instance of {@link ChartStyleXMLFactory}. */
-	public static final FeatureChartStyleXMLFactory FEATURE_CHART_STYLE_FACTORY = new FeatureChartStyleXMLFactory();
+  /** Instance of {@link ChartStyleXMLFactory}. */
+  public static final FeatureChartStyleXMLFactory FEATURE_CHART_STYLE_FACTORY = new FeatureChartStyleXMLFactory();
 
-	/**
-	 * Returns all {@link DatasetSelectionModel DatasetSelectionModels} that can
-	 * be reached via the renderers of a chart.
-	 * 
-	 * @param chart
-	 *            a chart
-	 */
-	public static List<FeatureDatasetSelectionModel<?, ?, ?>> getFeatureDatasetSelectionModelFor(
-			JFreeChart chart) {
-		ArrayList<FeatureDatasetSelectionModel<?, ?, ?>> renderers = new ArrayList<FeatureDatasetSelectionModel<?, ?, ?>>();
+  /**
+   * Returns all {@link DatasetSelectionModel DatasetSelectionModels} that can
+   * be reached via the renderers of a chart.
+   * @param chart a chart
+   */
+  public static List<FeatureDatasetSelectionModel<?, ?, ?>> getFeatureDatasetSelectionModelFor(
+      JFreeChart chart) {
+    ArrayList<FeatureDatasetSelectionModel<?, ?, ?>> renderers = new ArrayList<FeatureDatasetSelectionModel<?, ?, ?>>();
 
-		Plot plot = chart.getPlot();
+    Plot plot = chart.getPlot();
 
-		/** Collect renderers from XYPlot */
-		if (plot instanceof XYPlot) {
-			XYPlot xyplot = (XYPlot) plot;
+    /** Collect renderers from XYPlot */
+    if (plot instanceof XYPlot) {
+      XYPlot xyplot = (XYPlot) plot;
 
-			for (int i = 0; i < xyplot.getRendererCount(); i++) {
-				XYItemRenderer renderer = xyplot.getRenderer(i);
-				if (renderer instanceof DatasetSelectionModelProvider
-						&& ((DatasetSelectionModelProvider) renderer)
-								.getSelectionModel() instanceof FeatureDatasetSelectionModel) {
-					renderers
-							.add((FeatureDatasetSelectionModel) ((DatasetSelectionModelProvider) renderer)
-									.getSelectionModel());
-				}
-			}
-		}
-		/** Collect renderers from CategoryPlot */
-		if (plot instanceof CategoryPlot) {
-			CategoryPlot catPlot = (CategoryPlot) plot;
+      for (int i = 0; i < xyplot.getRendererCount(); i++) {
+        XYItemRenderer renderer = xyplot.getRenderer(i);
+        if (renderer instanceof DatasetSelectionModelProvider &&
+            ((DatasetSelectionModelProvider) renderer).getSelectionModel() instanceof FeatureDatasetSelectionModel) {
+          renderers.add((FeatureDatasetSelectionModel) ((DatasetSelectionModelProvider) renderer).getSelectionModel());
+        }
+      }
+    }
+    /** Collect renderers from CategoryPlot */
+    if (plot instanceof CategoryPlot) {
+      CategoryPlot catPlot = (CategoryPlot) plot;
 
-			for (int i = 0; i < catPlot.getRendererCount(); i++) {
-				CategoryItemRenderer renderer = catPlot.getRenderer(i);
-				if (renderer instanceof DatasetSelectionModelProvider
-						&& ((DatasetSelectionModelProvider) renderer)
-								.getSelectionModel() instanceof FeatureDatasetSelectionModel) {
-					renderers
-							.add((FeatureDatasetSelectionModel) ((DatasetSelectionModelProvider) renderer)
-									.getSelectionModel());
-				}
-			}
-		}
+      for (int i = 0; i < catPlot.getRendererCount(); i++) {
+        CategoryItemRenderer renderer = catPlot.getRenderer(i);
+        if (renderer instanceof DatasetSelectionModelProvider &&
+            ((DatasetSelectionModelProvider) renderer).getSelectionModel() instanceof FeatureDatasetSelectionModel) {
+          renderers.add((FeatureDatasetSelectionModel) ((DatasetSelectionModelProvider) renderer).getSelectionModel());
+        }
+      }
+    }
 
-		return renderers;
-	}
+    return renderers;
+  }
 
-	/**
-	 * Creates a {@link Dataset} for 1 or more attributes of a
-	 * {@link FeatureCollection}. According to the feature attribute type the
-	 * method decides whether a {@link XYDataset} or a {@link CategoryDataset}
-	 * is created:<br>
-	 * In case of an non-numeric X attribute a {@link CategoryDataset} is
-	 * created always. Otherwise the default is to create a {@link XYDataset}.
-	 * The flag {@code forceCat} can be used to create {@link CategoryDataset}
-	 * for numeric X attributes.
-	 * 
-	 * @param fc
-	 *            a {@link FeatureCollection}
-	 * @param forceCat
-	 *            forces a {@link CategoryDataset} also for numeric X attributes
-	 * @param sort
-	 *            sorts the features according to {@code xAttr} before creating
-	 *            the dataset
-	 * @param xAttr
-	 *            feature attribute used for the X-value
-	 * @param yAttr
-	 *            feature attribute(s) used for the Y-value (at least one; for
-	 *            each a series is created in the dataset)
-	 */
-	public static Dataset createDataset(
-			FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
-			FeatureChartStyle style) {
-		String xAttr = style.getAttributeName(0);
-		// Check the X attribute to differ between XY- and CategoryDataset
-		AttributeDescriptor xDesc = fc.getSchema().getDescriptor(xAttr);
-		if (xDesc == null)
-			throw new UnsupportedOperationException("Unknown attribute: "
-					+ xAttr);
+  /**
+   * Creates a {@link Dataset} for 1 or more attributes of a
+   * {@link FeatureCollection}. According to the feature attribute type the
+   * method decides whether a {@link XYDataset} or a {@link CategoryDataset} is
+   * created:<br>
+   * In case of an non-numeric X attribute a {@link CategoryDataset} is created
+   * always. Otherwise the default is to create a {@link XYDataset}. The flag
+   * {@code forceCat} can be used to create {@link CategoryDataset} for numeric
+   * X attributes.
+   * @param fc a {@link FeatureCollection}
+   * @param forceCat forces a {@link CategoryDataset} also for numeric X
+   *          attributes
+   * @param sort sorts the features according to {@code xAttr} before creating
+   *          the dataset
+   * @param xAttr feature attribute used for the X-value
+   * @param yAttr feature attribute(s) used for the Y-value (at least one; for
+   *          each a series is created in the dataset)
+   */
+  public static Dataset createDataset(
+      FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
+      FeatureChartStyle style) {
+    String xAttr = style.getAttributeName(0);
+    // Check the X attribute to differ between XY- and CategoryDataset
+    AttributeDescriptor xDesc = fc.getSchema().getDescriptor(xAttr);
+    if (xDesc == null)
+      throw new UnsupportedOperationException("Unknown attribute: " + xAttr);
 
-		// If domain attribute is numeric (and category not forced) create
-		// a XYDataset
-		if (!style.isForceCategories()
-				&& Number.class.isAssignableFrom(xDesc.getType().getBinding()))
-			return createXYDataset(fc, style);
-		else
-			return createCategoryDataset(fc, style);
-	}
+    // If domain attribute is numeric (and category not forced) create
+    // a XYDataset
+    if (!style.isForceCategories() &&
+        Number.class.isAssignableFrom(xDesc.getType().getBinding()))
+      return createXYDataset(fc, style);
+    else
+      return createCategoryDataset(fc, style);
+  }
 
-	/**
-	 * Checks whether an attribute exists and whether it is of a specific type.
-	 * Otherwise an {@link IllegalArgumentException} is thrown.
-	 * 
-	 * @param fType
-	 *            a feature type
-	 * @param aName
-	 *            the attribute name checked for numeric type
-	 * @param typeToCheck
-	 *            the type the attribute must support (if {@code null} only the
-	 *            attribute existing is checked!)
-	 */
-	private static void checkAttributeType(SimpleFeatureType fType,
-			String aName, Class<?> typeToCheck, String... errDesc) {
-		AttributeDescriptor aDesc = fType.getDescriptor(aName);
-		if (aDesc == null)
-			throw new UnsupportedOperationException("Unknown attribute: "
-					+ aName);
+  /**
+   * Checks whether an attribute exists and whether it is of a specific type.
+   * Otherwise an {@link IllegalArgumentException} is thrown.
+   * @param fType a feature type
+   * @param aName the attribute name checked for numeric type
+   * @param typeToCheck the type the attribute must support (if {@code null}
+   *          only the attribute existing is checked!)
+   */
+  private static void checkAttributeType(SimpleFeatureType fType, String aName,
+      Class<?> typeToCheck, String... errDesc) {
+    AttributeDescriptor aDesc = fType.getDescriptor(aName);
+    if (aDesc == null)
+      throw new UnsupportedOperationException("Unknown attribute: " + aName);
 
-		String attrDesc = errDesc.length > 0 ? errDesc[0] : "Attribute";
-		String datasetDesc = errDesc.length > 1 ? errDesc[1] : "Dataset";
+    String attrDesc = errDesc.length > 0 ? errDesc[0] : "Attribute";
+    String datasetDesc = errDesc.length > 1 ? errDesc[1] : "Dataset";
 
-		if (typeToCheck != null
-				&& !typeToCheck.isAssignableFrom(aDesc.getType().getBinding()))
-			throw new UnsupportedOperationException(attrDesc + " must be "
-					+ typeToCheck.getSimpleName() + " for " + datasetDesc
-					+ ": " + aName);
-	}
+    if (typeToCheck != null &&
+        !typeToCheck.isAssignableFrom(aDesc.getType().getBinding()))
+      throw new UnsupportedOperationException(attrDesc + " must be " +
+                                              typeToCheck.getSimpleName() +
+                                              " for " + datasetDesc + ": " +
+                                              aName);
+  }
 
-	/**
-	 * Creates a {@link XYDataset} for 2 (or more) attributes of a
-	 * {@link FeatureCollection}. XYDateset can only be created for
-	 * <b>numeric</b> attributes.
-	 * 
-	 * @param fc
-	 *            a {@link FeatureCollection}
-	 * @param style
-	 *            defines the attributes used to create the dataset from, as
-	 *            well as the sorting and normalization properties
-	 * @throws IllegalArgumentException
-	 *             if less then 2 attributes are specified
-	 * @throws UnsupportedOperationException
-	 *             if attributes are not numeric
-	 */
-	public static XYSeriesCollection createXYDataset(
-			FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
-			FeatureChartStyle chartStyle) {
-		int attrCount = chartStyle.getAttributeCount();
-		if (attrCount < 2)
-			throw new IllegalArgumentException(
-					"FeatureChartStyle must define at least 2 attributes to create XYDataset: "
-							+ attrCount);
-		String xAttrName = chartStyle.getAttributeName(ChartStyle.DOMAIN_AXIS);
-		// check data types of X attribute
-		checkAttributeType(fc.getSchema(), xAttrName, Number.class,
-				"Domain attribute", "XYDataset");
-		// check data types of Y attribute
-		for (int i = 1; i < attrCount; i++)
-			checkAttributeType(fc.getSchema(), chartStyle.getAttributeName(i),
-					Number.class, "Range attribute", "XYDataset");
+  /**
+   * Creates a {@link XYDataset} for 2 (or more) attributes of a
+   * {@link FeatureCollection}. XYDateset can only be created for <b>numeric</b>
+   * attributes.
+   * @param fc a {@link FeatureCollection}
+   * @param style defines the attributes used to create the dataset from, as
+   *          well as the sorting and normalization properties
+   * @throws IllegalArgumentException if less then 2 attributes are specified
+   * @throws UnsupportedOperationException if attributes are not numeric
+   */
+  public static XYSeriesCollection createXYDataset(
+      FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
+      FeatureChartStyle chartStyle) {
+    int attrCount = chartStyle.getAttributeCount();
+    if (attrCount < 2)
+      throw new IllegalArgumentException(
+          "FeatureChartStyle must define at least 2 attributes to create XYDataset: " +
+              attrCount);
+    String xAttrName = chartStyle.getAttributeName(ChartStyle.DOMAIN_AXIS);
+    // check data types of X attribute
+    checkAttributeType(fc.getSchema(), xAttrName, Number.class,
+                       "Domain attribute", "XYDataset");
+    // check data types of Y attribute
+    for (int i = 1; i < attrCount; i++)
+      checkAttributeType(fc.getSchema(), chartStyle.getAttributeName(i),
+                         Number.class, "Range attribute", "XYDataset");
 
-		// Create a series for each range attribute (note: the 0
-		// array element useless, but it is more comfortable to
-		// use an array of the same size as "attributes"
-		XYSeries[] xySeries = new XYSeries[attrCount];
-		for (int i = 1; i < xySeries.length; i++)
-			xySeries[i] = new XYSeries(chartStyle.getAttributeName(i), false,
-					true); // IMPORTANT: Do not use autosort!!
+    // Create a series for each range attribute (note: the 0
+    // array element useless, but it is more comfortable to
+    // use an array of the same size as "attributes"
+    XYSeries[] xySeries = new XYSeries[attrCount];
+    for (int i = 1; i < xySeries.length; i++)
+      xySeries[i] = new XYSeries(chartStyle.getAttributeName(i), false, true); // IMPORTANT
+    // :
+    // Do
+    // not
+    // use
+    // autosort
+    // !
+    // !
 
-		// Create a new dataset and insert the series
-		XYSeriesCollection dataset = new XYSeriesCollection();
-		Feature2SeriesDatasetMapping mapping = new Feature2SeriesDatasetMapping(
-				fc, dataset);
-		dataset.setGroup(new FeatureDatasetMetaData(mapping));
-		for (int i = 1; i < xySeries.length; i++)
-			dataset.addSeries(xySeries[i]);
+    // Create a new dataset and insert the series
+    XYSeriesCollection dataset = new XYSeriesCollection();
+    Feature2SeriesDatasetMapping mapping = new Feature2SeriesDatasetMapping(fc,
+        dataset);
+    dataset.setGroup(new FeatureDatasetMetaData(mapping));
+    for (int i = 1; i < xySeries.length; i++)
+      dataset.addSeries(xySeries[i]);
 
-		// Calculate any statistics needed for normalization.
-		HashMap<String, QuantileBin1D> statisticsForNormalization = calcStatisticsForNormalization(
-				fc, chartStyle);
-		// Prepare set for statistics to calculate aggregation
-		// functions (one statistic for each range attribute of
-		// each domain value)
-		HashMap<Number, QuantileBin1D>[] statisticsForAggregation = new HashMap[attrCount];
-		for (int i = 1; i < attrCount; i++)
-			statisticsForAggregation[i] = new HashMap<Number, QuantileBin1D>();
+    // Calculate any statistics needed for normalization.
+    HashMap<String, QuantileBin1D> statisticsForNormalization = calcStatisticsForNotAggregatedNormalization(
+                                                                                               fc,
+                                                                                               chartStyle);
+    // Prepare set for statistics to calculate aggregation
+    // functions (one statistic for each range attribute of
+    // each domain value)
+    HashMap<Number, QuantileBin1D>[] statisticsForAggregation = new HashMap[attrCount];
+    for (int i = 1; i < attrCount; i++)
+      statisticsForAggregation[i] = new HashMap<Number, QuantileBin1D>();
 
-		// If dataset should be sorted, the features must be sorted first
-		// according to the domain attribute. The "autoSort" functionality
-		// of XYSeries can NOT BE USED because of the following reason:
-		// To realize the synchronized feature/dataitem a mapping
-		// between the feature IDs and the data item index (in the series)
-		// must be created. Using the "autoSort" functionality, the
-		// indices inside the series change with every XYSeries.add(..)
-		// call, so that the mapping is destroyed!!
-		//
-		// Only solution: Pre-sort the features so that the XYSeries internal
-		// order does not change!
-		Iterator<SimpleFeature> fi = null;
-		if (chartStyle.isSortDomainAxis()) {
-			Vector<SimpleFeature> sortedFeatures = FeatureUtil.sortFeatures(fc,
-					xAttrName);
-			// Create an Iterator for the sorted Features
-			fi = sortedFeatures.iterator();
-		} else
-			fi = new PipedFeatureIterator(fc.features());
+    // If dataset should be sorted, the features must be sorted first
+    // according to the domain attribute. The "autoSort" functionality
+    // of XYSeries can NOT BE USED because of the following reason:
+    // To realize the synchronized feature/dataitem a mapping
+    // between the feature IDs and the data item index (in the series)
+    // must be created. Using the "autoSort" functionality, the
+    // indices inside the series change with every XYSeries.add(..)
+    // call, so that the mapping is destroyed!!
+    //
+    // Only solution: Pre-sort the features so that the XYSeries internal
+    // order does not change!
+    Iterator<SimpleFeature> fi = null;
+    if (chartStyle.isSortDomainAxis()) {
+      Vector<SimpleFeature> sortedFeatures = FeatureUtil.sortFeatures(fc,
+                                                                      xAttrName);
+      // Create an Iterator for the sorted Features
+      fi = sortedFeatures.iterator();
+    } else
+      fi = new PipedFeatureIterator(fc.features());
 
-		// Iterate the FeatureCollection and fill the series
-		int datasetIdx = 0;
-		for (; fi.hasNext();) {
-			SimpleFeature f = fi.next();
-			// Determine X value (NULL not permitted for XYDateset!)
-			Number xValue = (Number) f.getAttribute(xAttrName);
+    // Iterate the FeatureCollection and fill the series
+    int datasetIdx = 0;
+    for (; fi.hasNext();) {
+      SimpleFeature f = fi.next();
+      // Determine X value (NULL not permitted for XYDateset!)
+      Number xValue = (Number) f.getAttribute(xAttrName);
 
-			// Filter out NODATA values
-			xValue = chartStyle.filterNoDataValue(ChartStyle.DOMAIN_AXIS,
-					xValue);
-			if (xValue == null)
-				continue;
+      // Filter out NODATA values
+      xValue = chartStyle.filterNoDataValue(ChartStyle.DOMAIN_AXIS, xValue);
+      if (xValue == null)
+        continue;
 
-			/*
-			 * Normalization of the domain axis value (if they are not handled
-			 * as categories)
-			 */
-			if (chartStyle.isAttributeNormalized(ChartStyle.DOMAIN_AXIS))
-				xValue = normalize(xValue, xAttrName,
-						statisticsForNormalization);
+      /*
+       * Normalization of the domain axis value (if they are not handled as
+       * categories)
+       */
+      if (chartStyle.isAttributeNormalized(ChartStyle.DOMAIN_AXIS))
+        xValue = normalize(xValue, xAttrName, statisticsForNormalization);
 
-			// Determine the Y values and fill the series
-			for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
-				String yAttrName = chartStyle.getAttributeName(attrIdx);
-				Number yValue = (Number) f.getAttribute(yAttrName);
-				// AggregationFunction attributeAggregation = chartStyle
-				// .getAttributeAggregation(attrIdx);
+      // Determine the Y values and fill the series
+      for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
+        String yAttrName = chartStyle.getAttributeName(attrIdx);
+        Number yValue = (Number) f.getAttribute(yAttrName);
+        // AggregationFunction attributeAggregation = chartStyle
+        // .getAttributeAggregation(attrIdx);
 
-				// Filter out NoDataValues
-				yValue = chartStyle.filterNoDataValue(attrIdx, yValue);
-				if (yValue == null)
-					continue;
+        // Filter out NoDataValues
+        yValue = chartStyle.filterNoDataValue(attrIdx, yValue);
+        if (yValue == null)
+          continue;
 
-				/* Normalization of a range axis value */
-				if (chartStyle.isAttributeNormalized(attrIdx))
-					yValue = normalize(yValue, yAttrName,
-							statisticsForNormalization);
+        /* Normalization of a range axis value */
+        if (chartStyle.isAttributeNormalized(attrIdx))
+          yValue = normalize(yValue, yAttrName, statisticsForNormalization);
 
-				// Fill series, if no aggregation function is defined.
-				// Otherwise fill statistic (dataset is filled later!)
-				// if (attributeAggregation == null) {
-				// Fill series
-				xySeries[attrIdx].add(xValue, yValue);
-				// Mapping between FID and data index in series
-				mapping.setMapping(f.getID(), yAttrName, datasetIdx++);
-				// } else {
-				// // The values for this are aggregated
-				// StaticBin1D aggrStat = statisticsForAggregation[attrIdx]
-				// .get(xValue);
-				// if (aggrStat == null) {
-				// aggrStat = new DynamicBin1D();
-				// statisticsForAggregation[attrIdx].put(xValue, aggrStat);
-				// }
-				//
-				// // The default weight is 1
-				// // for (int i = 0; i < yWeightValue; i++)
-				// aggrStat.add(yValue.doubleValue());
-				//
-				// // TODO: Mapping vormerken (??)
-				// // Problem: siehe unten
-				// }
-			}
-		}
+        // Fill series, if no aggregation function is defined.
+        // Otherwise fill statistic (dataset is filled later!)
+        // if (attributeAggregation == null) {
+        // Fill series
+        xySeries[attrIdx].add(xValue, yValue);
+        // Mapping between FID and data index in series
+        mapping.setMapping(f.getID(), yAttrName, datasetIdx++);
+        // } else {
+        // // The values for this are aggregated
+        // StaticBin1D aggrStat = statisticsForAggregation[attrIdx]
+        // .get(xValue);
+        // if (aggrStat == null) {
+        // aggrStat = new DynamicBin1D();
+        // statisticsForAggregation[attrIdx].put(xValue, aggrStat);
+        // }
+        //
+        // // The default weight is 1
+        // // for (int i = 0; i < yWeightValue; i++)
+        // aggrStat.add(yValue.doubleValue());
+        //
+        // // TODO: Mapping vormerken (??)
+        // // Problem: siehe unten
+        // }
+      }
+    }
 
-		// // Fill series for aggregated range attributes
-		// for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
-		// // String yAttrName = chartStyle.getAttributeName(attrIdx);
-		// AggregationFunction aggrFunc = chartStyle
-		// .getAttributeAggregation(attrIdx);
-		// if (aggrFunc == null)
-		// continue;
-		// for (Number xValue : statisticsForAggregation[attrIdx].keySet()) {
-		// StaticBin1D aggrStat = statisticsForAggregation[attrIdx]
-		// .get(xValue);
-		// Number yValue = aggrFunc.getResult(aggrStat);
-		// // Fill series
-		// xySeries[attrIdx].add(xValue, yValue);
-		// // TODO: Mapping setzen
-		// // Problem: Pro dataset item kann nur EINE FeatureID gesetzt
-		// // werden (Feature2DatasetMapping, Zeile 124)
-		// // // Mapping between FID and data index in series
-		// // mapping.setMapping(f.getID() ??, yAttrName, datasetIdx++);
-		// }
-		// }
+    // // Fill series for aggregated range attributes
+    // for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
+    // // String yAttrName = chartStyle.getAttributeName(attrIdx);
+    // AggregationFunction aggrFunc = chartStyle
+    // .getAttributeAggregation(attrIdx);
+    // if (aggrFunc == null)
+    // continue;
+    // for (Number xValue : statisticsForAggregation[attrIdx].keySet()) {
+    // StaticBin1D aggrStat = statisticsForAggregation[attrIdx]
+    // .get(xValue);
+    // Number yValue = aggrFunc.getResult(aggrStat);
+    // // Fill series
+    // xySeries[attrIdx].add(xValue, yValue);
+    // // TODO: Mapping setzen
+    // // Problem: Pro dataset item kann nur EINE FeatureID gesetzt
+    // // werden (Feature2DatasetMapping, Zeile 124)
+    // // // Mapping between FID and data index in series
+    // // mapping.setMapping(f.getID() ??, yAttrName, datasetIdx++);
+    // }
+    // }
 
-		return dataset;
-	}
+    return dataset;
+  }
 
-	/**
-	 * Calculates statistics needed to normalize data. If normalization is not
-	 * used, this function returns an empty map.
-	 * 
-	 * @param fc
-	 *            {@link FeatureCollection} where the data comes from
-	 * @param chartStyle
-	 *            {@link ChartStyle} to determine which attributes shall be
-	 *            normalized.
-	 */
-	public static HashMap<String, QuantileBin1D> calcStatisticsForNormalization(
-			FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
-			FeatureChartStyle chartStyle) {
-		// NORMALIZATION:
-		// We have to create a descriptive statistic of all items before we can
-		// transform the first one. So we iterate over all items before we do
-		// optional sorting and insertion.
-		/**
-		 * Holds the statistics needed to normalize the attribute values. Key =
-		 * attributeName
-		 */
-		HashMap<String, QuantileBin1D> attribStats = new HashMap<String, QuantileBin1D>();
 
-		// First check if any attribute needs normalization. If not we can
-		// skip the whole iteration
-		boolean doNormalization = false;
-		for (int attrIdx = 0; attrIdx < chartStyle.getAttributeCount(); attrIdx++) {
-			if (chartStyle.isAttributeNormalized(attrIdx)) {
-				doNormalization = true;
-				break;
-			}
-		}
+  /**
+   * Calculates statistics needed to normalize data. If normalization is not
+   * used, this function returns an empty map.
+   * @param fc {@link FeatureCollection} where the data comes from
+   * @param chartStyle {@link ChartStyle} to determine which attributes shall be
+   *          normalized.
+   */
+  private static HashMap<String, QuantileBin1D> calcStatisticsForAggregatedNormalization(
+      HashMap<Comparable<?>,QuantileBin1D>[] aggrAttrValues, FeatureChartStyle chartStyle) {
+    
+    HashMap<String, QuantileBin1D> normStats = new HashMap<String, QuantileBin1D>();
 
-		if (doNormalization) {
-			final FeatureIterator<SimpleFeature> fIt = fc.features();
-			try {
+    for (int attrIdx = 0; attrIdx < chartStyle.getAttributeCount(); attrIdx++) {
+      if ( aggrAttrValues[attrIdx] == null )
+        continue;
+      if (!chartStyle.isAttributeNormalized(attrIdx))
+        continue;
+      String attrName = chartStyle.getAttributeName(attrIdx);
+      QuantileBin1D stat = normStats.get(attrName); 
+      if (stat == null) {
+        stat = new DynamicBin1D();
+        normStats.put(attrName, stat);
+      }
+      
+      for (Comparable<?> catValue : aggrAttrValues[attrIdx].keySet())
+        stat.add( chartStyle.getAttributeAggregation(attrIdx).getResult(aggrAttrValues[attrIdx].get(catValue)) );
+    }
 
-				// Loop over all features, and collect the attribute values we
-				// are interested in.
-				while (fIt.hasNext()) {
-					SimpleFeature f = fIt.next();
+    
+    return normStats;
+  }
+    
+  /**
+  }
+   * Calculates statistics needed to normalize data. If normalization is not
+   * used, this function returns an empty map.
+   * @param fc {@link FeatureCollection} where the data comes from
+   * @param chartStyle {@link ChartStyle} to determine which attributes shall be
+   *          normalized.
+   */
+  private static HashMap<String, QuantileBin1D> calcStatisticsForNotAggregatedNormalization(
+      FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
+      FeatureChartStyle chartStyle) {
+    // NORMALIZATION:
+    // We have to create a descriptive statistic of all items before we can
+    // transform the first one. So we iterate over all items before we do
+    // optional sorting and insertion.
+    /**
+     * Holds the statistics needed to normalize the attribute values. Key =
+     * attributeName
+     */
+    HashMap<String, QuantileBin1D> attribStats = new HashMap<String, QuantileBin1D>();
 
-					for (int attrIdx = 0; attrIdx < chartStyle
-							.getAttributeCount(); attrIdx++) {
+    // First check if any attribute needs normalization. If not we can
+    // skip the whole iteration
+    boolean doNormalization = false;
+    for (int attrIdx = 0; attrIdx < chartStyle.getAttributeCount(); attrIdx++) {
+      if (chartStyle.isAttributeNormalized(attrIdx) && chartStyle.getAttributeAggregation(attrIdx) == null) {
+        doNormalization = true;
+        break;
+      }
+    }
 
-						if (chartStyle.isAttributeNormalized(attrIdx)) {
+    if (doNormalization) {
+      final FeatureIterator<SimpleFeature> fIt = fc.features();
+      try {
 
-							String attrName = chartStyle
-									.getAttributeName(attrIdx);
+        // Loop over all features, and collect the attribute values we
+        // are interested in.
+        while (fIt.hasNext()) {
+          SimpleFeature f = fIt.next();
 
-							// SK: Since normalization is now usually set for
-							// all
-							// attributes (even when they are not numeric), we
-							// double check here, whether it is really a numeric
-							// attribute
-							if (!Number.class.isAssignableFrom(f
-									.getFeatureType().getDescriptor(attrName)
-									.getType().getBinding())) {
-								continue;
-							}
+          for (int attrIdx = 0; attrIdx < chartStyle.getAttributeCount(); attrIdx++) {
+            if (chartStyle.isAttributeNormalized(attrIdx) && chartStyle.getAttributeAggregation(attrIdx) == null) {
 
-							// Look for a cached version of the Statistics or
-							// create a new one
-							QuantileBin1D stat = attribStats.get(attrName);
-							if (stat == null) {
-								stat = new DynamicBin1D();
-								attribStats.put(attrName, stat);
-							}
+              String attrName = chartStyle.getAttributeName(attrIdx);
 
-							// Filter out NoDataValues
-							Object rawValue = chartStyle.filterNoDataValue(
-									attrIdx, f.getAttribute(attrName));
-							if (rawValue == null)
-								continue;
+              // SK: Since normalization is now usually set for
+              // all
+              // attributes (even when they are not numeric), we
+              // double check here, whether it is really a numeric
+              // attribute
+              if (!Number.class.isAssignableFrom(f.getFeatureType()
+                                                  .getDescriptor(attrName)
+                                                  .getType()
+                                                  .getBinding())) {
+                continue;
+              }
 
-							final Double doubleValue = new Double(
-									((Number) rawValue).doubleValue());
+              // Look for a cached version of the Statistics or
+              // create a new one
+              QuantileBin1D stat = attribStats.get(attrName);
+              if (stat == null) {
+                stat = new DynamicBin1D();
+                attribStats.put(attrName, stat);
+              }
 
-							stat.add(doubleValue);
-						}
-					}
-				}
-			} // Feature iterator
-			finally {
-				fc.close(fIt);
-			}
-		} // doNormlization
+              // Filter out NoDataValues
+              Object rawValue = chartStyle.filterNoDataValue(
+                                                             attrIdx,
+                                                             f.getAttribute(attrName));
+              if (rawValue == null)
+                continue;
 
-		return attribStats;
-	}
+              final Double doubleValue = new Double(
+                  ((Number) rawValue).doubleValue());
 
-	/**
-	 * Do a z-transformation on the data item.
-	 * 
-	 * @param statisticsForNormalization
-	 *            The statistics needed for normalization.
-	 * 
-	 * @see #calcStatisticsForNormalization(FeatureCollection,
-	 *      FeatureChartStyle, int)
-	 */
-	private static Number normalize(Number yValue, String attrName,
-			HashMap<String, QuantileBin1D> statisticsForNormalization) {
-		Number zValue;
+              stat.add(doubleValue);
+            }
+          }
+        }
+      } // Feature iterator
+      finally {
+        fc.close(fIt);
+      }
+    } // doNormlization
 
-		if (statisticsForNormalization.get(attrName) == null) {
-			throw new IllegalArgumentException(
-					"The statistics needed for the normlization need to be created before normalizing.");
-		}
+    return attribStats;
+  }
 
-		StaticBin1D stats = statisticsForNormalization.get(attrName);
+  /**
+   * Do a z-transformation on the data item.
+   * @param statisticsForNormalization The statistics needed for normalization.
+   * @see #calcStatisticsForNormalization(FeatureCollection, FeatureChartStyle,
+   *      int)
+   */
+  private static Number normalize(Number yValue, String attrName,
+      HashMap<String, QuantileBin1D> statisticsForNormalization) {
+    Number zValue;
 
-		zValue = (yValue.doubleValue() - stats.mean())
-				/ stats.standardDeviation();
+    if (statisticsForNormalization.get(attrName) == null) {
+      throw new IllegalArgumentException(
+          "The statistics needed for the normlization need to be created before normalizing.");
+    }
 
-		return zValue;
-	}
+    StaticBin1D stats = statisticsForNormalization.get(attrName);
 
-	/**
-	 * Creates a {@link XYDataset} for 2 (or more) attributes of a
-	 * {@link FeatureCollection}. XYDateset can only be created for
-	 * <b>numeric</b> attributes.
-	 * 
-	 * @param fc
-	 *            a {@link FeatureCollection}
-	 * @param style
-	 *            defines the attributes used to create the dataset from, as
-	 *            well as the sorting and normalization properties
-	 * @throws IllegalArgumentException
-	 *             if less then 2 attributes are specified
-	 * @throws UnsupportedOperationException
-	 *             if attributes are not numeric
-	 */
-	public static DefaultCategoryDataset createCategoryDataset(
-			FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
-			FeatureChartStyle chartStyle) {
-		int attrCount = chartStyle.getAttributeCount();
-		if (attrCount < 2)
-			throw new IllegalArgumentException(
-					"FeatureChartStyle must define at least 2 attributes to create CategoryDataset: "
-							+ attrCount);
-		String xAttrName = chartStyle.getAttributeName(ChartStyle.DOMAIN_AXIS);
-		// only check whether X attribute exists (numeric and not-numeric
-		// allowed)
-		checkAttributeType(fc.getSchema(), xAttrName, Comparable.class,
-				"Domain attribute", "CategoryDataset");
-		// check data types of Y attribute (only numeric allowed)
-		for (int i = 1; i < attrCount; i++)
-			checkAttributeType(fc.getSchema(), chartStyle.getAttributeName(i),
-					Number.class, "Range attribute", "CategoryDataset");
+    zValue = (yValue.doubleValue() - stats.mean()) / stats.standardDeviation();
 
-		// Calculate any statistics needed for normalization.
-		HashMap<String, QuantileBin1D> statisticsForNormalization = calcStatisticsForNormalization(
-				fc, chartStyle);
-		// Prepare set for statistics to calculate aggregation
-		// functions (one statistic for each range attribute of
-		// each domain value)
-		HashMap<Comparable<?>, QuantileBin1D>[] statisticsForAggregation = new HashMap[attrCount];
-		for (int i = 1; i < attrCount; i++)
-			statisticsForAggregation[i] = new HashMap<Comparable<?>, QuantileBin1D>();
+    return zValue;
+  }
 
-		// Create a new dataset and insert the series
-		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
-		Feature2CategoryDatasetMapping mapping = new Feature2CategoryDatasetMapping(
-				fc, dataset);
-		dataset.setGroup(new FeatureDatasetMetaData(mapping));
+  /**
+   * Creates a {@link XYDataset} for 2 (or more) attributes of a
+   * {@link FeatureCollection}. XYDateset can only be created for <b>numeric</b>
+   * attributes.
+   * @param fc a {@link FeatureCollection}
+   * @param style defines the attributes used to create the dataset from, as
+   *          well as the sorting and normalization properties
+   * @throws IllegalArgumentException if less then 2 attributes are specified
+   * @throws UnsupportedOperationException if attributes are not numeric
+   */
+  public static DefaultCategoryDataset createCategoryDataset(
+      FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
+      FeatureChartStyle chartStyle) {
+    int attrCount = chartStyle.getAttributeCount();
+    if (attrCount < 2)
+      throw new IllegalArgumentException(
+          "FeatureChartStyle must define at least 2 attributes to create CategoryDataset: " +
+              attrCount);
+    String xAttrName = chartStyle.getAttributeName(ChartStyle.DOMAIN_AXIS);
+    // only check whether X attribute exists (numeric and not-numeric
+    // allowed)
+    checkAttributeType(fc.getSchema(), xAttrName, Comparable.class,
+                       "Domain attribute", "CategoryDataset");
+    // check data types of Y attribute (only numeric allowed)
+    for (int i = 1; i < attrCount; i++)
+      checkAttributeType(fc.getSchema(), chartStyle.getAttributeName(i),
+                         Number.class, "Range attribute", "CategoryDataset");
 
-		// If dataset should be sorted, the features must be sorted first
-		// according to the domain attribute. CategoryDataset has no
-		// "autoSort", and this - at all - would not work (see
-		// createXYDataset(..))
-		Iterator<SimpleFeature> fi = null;
-		FeatureIterator<SimpleFeature> features = null;
+    // Calculate any statistics needed for normalization.
+    HashMap<String, QuantileBin1D> statisticsForNormalization = calcStatisticsForNotAggregatedNormalization(
+                                                                                               fc,
+                                                                                               chartStyle);
+    // Prepare set for statistics to calculate aggregation
+    // functions (one statistic for each range attribute of
+    // each domain value)
+    HashMap<Comparable<?>, QuantileBin1D>[] statisticsForAggregation = new HashMap[attrCount];
+    for (int i = 1; i < attrCount; i++)
+      statisticsForAggregation[i] = new HashMap<Comparable<?>, QuantileBin1D>();
 
-		// Für die Gewichtung muss zuerst Summe aller Gewichte ermittelt werden
-		Double[] sumWeights = new Double[attrCount];
-		for (int attrIdx = 1; attrIdx < attrCount; attrIdx++)
-			sumWeights[attrIdx - 1] = 0.;
-		long[] validFeaturesCount = new long[attrCount];
-		{
-			features = fc.features();
-			try {
-				while (features.hasNext()) {
+    // Create a new dataset and insert the series
+    DefaultCategoryDataset dataset = new DefaultCategoryDataset();
+    Feature2CategoryDatasetMapping mapping = new Feature2CategoryDatasetMapping(
+        fc, dataset);
+    dataset.setGroup(new FeatureDatasetMetaData(mapping));
 
-					SimpleFeature next = features.next();
-					// Determine the Y values and fill the dataset
-					for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
-						AggregationFunction attributeAggregation = chartStyle
-								.getAttributeAggregation(attrIdx);
+    FeatureIterator<SimpleFeature> features = null;
+    // Für die Gewichtung muss zuerst Summe aller Gewichte (pro Category!)
+    // ermittelt werden
+    HashMap<Comparable<?>, Double>[] weightSumsForAggregation = new HashMap[attrCount];
+    for (int i = 1; i < attrCount; i++)
+      weightSumsForAggregation[i] = new HashMap<Comparable<?>, Double>();
+    features = fc.features();
+    try {
+      while (features.hasNext()) {
+        SimpleFeature f = features.next();
+        // ignore features with NODATA in domain attribute
+        Comparable<?> catValue = (Comparable<?>) f.getAttribute(xAttrName);
+        catValue = chartStyle.filterNoDataValue(ChartStyle.DOMAIN_AXIS,
+                                                catValue);
+        if (catValue == null)
+          continue;
 
-						if (attributeAggregation == null)
-							continue;
-						if (!attributeAggregation.isWeighted())
-							continue;
-						if (chartStyle
-								.getAttributeAggregationWeightAttributeName(attrIdx) == null)
-							throw new RuntimeException(
-									JFreeChartUtil.R("Exception.noWeightAttributeDefinedforAWeightedAggregation")); 
-						
-						
-						
-						// NODATA Check yValue attribute
-						String yAttrName = chartStyle.getAttributeName(attrIdx);
-						Number yValue = (Number) next.getAttribute(yAttrName);
-						yValue = chartStyle.filterNoDataValue(attrIdx, yValue);
-						if (yValue == null)
-							continue;
+        // Iterate the feature attributes
+        for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
+          AggregationFunction attributeAggregation = chartStyle.getAttributeAggregation(attrIdx);
+          // Ignore
+          // - not aggregated attributes
+          // - not weighted aggregation attributes
+          if (attributeAggregation == null)
+            continue;
+          if (!attributeAggregation.isWeighted())
+            continue;
+          // weights must be defined for weighted aggregation
+          if (chartStyle.getAttributeAggregationWeightAttributeName(attrIdx) == null)
+            throw new RuntimeException(
+                JFreeChartUtil.R("Exception.noWeightAttributeDefinedforAWeightedAggregation"));
+          // ignore features with NODATA in range attribute
+          String yAttrName = chartStyle.getAttributeName(attrIdx);
+          Number yValue = (Number) chartStyle.filterNoDataValue(
+                                                                attrIdx,
+                                                                f.getAttribute(yAttrName));
+          if (yValue == null)
+            continue;
+          // ignore features with NODATA in weight attribute
+          String weightAttrName = chartStyle.getAttributeAggregationWeightAttributeName(attrIdx);
+          Number weight = (Number) chartStyle.filterWeightAttributeNoDataValue(
+                                                                               attrIdx,
+                                                                               f.getAttribute(weightAttrName));
+          if (weight == null)
+            continue;
 
-						// NODATA Check WEIGHT attribute
-						Number weight = (Number) next
-								.getAttribute(chartStyle
-										.getAttributeAggregationWeightAttributeName(attrIdx));
-						if (chartStyle.isWeightAttributeNoDataValue(attrIdx,
-								weight))
-							continue;
+          Double weightSum = weightSumsForAggregation[attrIdx].get(catValue);
+          if (weightSum == null)
+            weightSum = 0.0;
+          weightSum += weight.doubleValue();
+          weightSumsForAggregation[attrIdx].put(catValue, weightSum);
+        }
+      }
+    } finally {
+      if (features != null) {
+        // this is a hint
+        fc.close(features);
+      }
+    }
 
-						// NODATA Check Domain attribute
-						Comparable<?> catValue = (Comparable<?>) next
-								.getAttribute(xAttrName);
-						catValue = chartStyle.filterNoDataValue(
-								ChartStyle.DOMAIN_AXIS, catValue);
-						if (catValue == null)
-							continue;
+    // If dataset should be sorted, the features must be sorted first
+    // according to the domain attribute. CategoryDataset has no
+    // "autoSort", and this - at all - would not work (see
+    // createXYDataset(..))
+    Iterator<SimpleFeature> fi = null;
+    if (chartStyle.isSortDomainAxis()) {
+      Vector<SimpleFeature> sortedFeatures = FeatureUtil.sortFeatures(fc,
+                                                                      xAttrName);
+      // Create an Iterator for the sorted Features
+      fi = sortedFeatures.iterator();
+    } else {
+      features = fc.features();
+      fi = new PipedFeatureIterator(features);
+    }
 
-						// So, alle drei werte sind nicht NODATA
-						sumWeights[attrIdx - 1] += weight.doubleValue();
-						validFeaturesCount[attrIdx - 1]++;
-					}
-				}
-			} finally {
-				if (features != null) {
-					// this is a hint
-					fc.close(features);
-				}
-			}
-		} // Die Summe aller gewichte ist ermittelt
+    try {
+      // Iterate the FeatureCollection and fill the series
+      for (int fIdx = 0; fi.hasNext(); fIdx++) {
+        SimpleFeature f = fi.next();
+        // Determine the category (NULL not permitted!)
+        Comparable<?> catValue = (Comparable<?>) f.getAttribute(xAttrName);
+        // Filter out NODATA values
+        catValue = chartStyle.filterNoDataValue(ChartStyle.DOMAIN_AXIS,
+                                                catValue);
+        if (catValue == null)
+          continue;
 
-		if (chartStyle.isSortDomainAxis()) {
-			Vector<SimpleFeature> sortedFeatures = FeatureUtil.sortFeatures(fc,
-					xAttrName);
-			// Create an Iterator for the sorted Features
-			fi = sortedFeatures.iterator();
-		} else {
-			features = fc.features();
-			fi = new PipedFeatureIterator(features);
-		}
+        // Determine the Y values and fill the dataset
+        for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
+          AggregationFunction attributeAggregation = chartStyle.getAttributeAggregation(attrIdx);
 
-		try {
-			// Iterate the FeatureCollection and fill the series
-			for (int fIdx = 0; fi.hasNext(); fIdx++) {
-				SimpleFeature f = fi.next();
-				// Determine the category (NULL not permitted!)
-				Comparable<?> catValue = (Comparable<?>) f
-						.getAttribute(xAttrName);
+          String yAttrName = chartStyle.getAttributeName(attrIdx);
+          Number yValue = (Number) f.getAttribute(yAttrName);
 
-				// Filter out NODATA values
-				catValue = chartStyle.filterNoDataValue(ChartStyle.DOMAIN_AXIS,
-						catValue);
+          // By default the wight is 1 => no weighting. If the
+          // aggregation uses weighting, read the weight attribnute
+          // if (attributeAggregation != null &&
+          // attributeAggregation.isWeighted())
+          // yWeightValue = ((Number) f.getAttribute(WEIGHTATTRIB))
+          // .longValue();
 
-				if (catValue == null)
-					continue;
+          // Filter out NoDataValues
+          yValue = chartStyle.filterNoDataValue(attrIdx, yValue);
+          if (yValue == null)
+            continue;
 
-				// Determine the Y values and fill the dataset
-				for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
-					AggregationFunction attributeAggregation = chartStyle
-							.getAttributeAggregation(attrIdx);
+          // Fill series, if no aggregation function is defined.
+          // Otherwise fill statistic (dataset is filled later!)
+          if (attributeAggregation == null) {
+            /* Normalization of a range axis value */
+            if (chartStyle.isAttributeNormalized(attrIdx))
+              yValue = normalize(yValue, yAttrName, statisticsForNormalization);
+            // Add data to dataset
+            dataset.addValue(yValue, yAttrName, catValue);
+            // Mapping between FID and data index in series
+            mapping.setMapping(f.getID(), yAttrName, catValue);
+          } else {
+            QuantileBin1D aggrStat = statisticsForAggregation[attrIdx].get(catValue);
+            if (aggrStat == null) {
+              aggrStat = new DynamicBin1D();
+              statisticsForAggregation[attrIdx].put(catValue, aggrStat);
+            }
 
-					String yAttrName = chartStyle.getAttributeName(attrIdx);
-					Number yValue = (Number) f.getAttribute(yAttrName);
+            if (attributeAggregation.isWeighted()) {
+              // weight attribute must not be NULL
+              Object weightObj = f.getAttribute(chartStyle.getAttributeAggregationWeightAttributeName(attrIdx));
+              Number weight    = (Number)chartStyle.filterWeightAttributeNoDataValue(attrIdx, weightObj);
+              if ( weight == null )
+                continue;
+              aggrStat.add(yValue.doubleValue() * weight.doubleValue() / weightSumsForAggregation[attrIdx].get(catValue));
+            } else {
+              aggrStat.add(yValue.doubleValue());
+            }
+            // TODO: Mapping vormerken (??)
+            // Problem: siehe unten
+          }
+        }
 
-					// By default the wight is 1 => no weighting. If the
-					// aggregation uses weighting, read the weight attribnute
-					// if (attributeAggregation != null &&
-					// attributeAggregation.isWeighted())
-					// yWeightValue = ((Number) f.getAttribute(WEIGHTATTRIB))
-					// .longValue();
+      }
 
-					// Filter out NoDataValues
-					yValue = chartStyle.filterNoDataValue(attrIdx, yValue);
-					if (yValue == null)
-						continue;
+      // Fill series for aggregated range attributes
+      statisticsForNormalization = calcStatisticsForAggregatedNormalization(statisticsForAggregation,chartStyle);
+      for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
+        String yAttrName = chartStyle.getAttributeName(attrIdx);
+        AggregationFunction aggrFunc = chartStyle.getAttributeAggregation(attrIdx);
+        if (aggrFunc == null)
+          continue;
+        for (Comparable<?> catValue : statisticsForAggregation[attrIdx].keySet()) {
+          QuantileBin1D aggrStat = statisticsForAggregation[attrIdx].get(catValue);
+          Number yValue = aggrFunc.getResult(aggrStat);
+          
+          // Normalize the aggregated value
+          if ( chartStyle.isAttributeNormalized(attrIdx) )
+            yValue = normalize(yValue, yAttrName, statisticsForNormalization);
+          
+          // Fill series
+          dataset.addValue(yValue, yAttrName, catValue);
+          // TODO: Mapping setzen
+          // Problem: Pro dataset item kann nur EINE FeatureID gesetzt
+          // werden (Feature2DatasetMapping, Zeile 124)
+          // // Mapping between FID and data index in series
+          // mapping.setMapping(f.getID() ??, yAttrName,
+          // datasetIdx++);
+        }
+      }
+    } finally {
+      if (features != null) {
+        fc.close(features);
+      }
+    }
 
-					/* Normalization of a range axis value */
-					if (chartStyle.isAttributeNormalized(attrIdx))
-						yValue = normalize(yValue, yAttrName,
-								statisticsForNormalization);
+    return dataset;
+  }
 
-					// Fill series, if no aggregation function is defined.
-					// Otherwise fill statistic (dataset is filled later!)
-					if (attributeAggregation == null) {
-						// Add data to dataset
-						dataset.addValue(yValue, yAttrName, catValue);
-						// Mapping between FID and data index in series
-						mapping.setMapping(f.getID(), yAttrName, catValue);
-					} else {
-						QuantileBin1D aggrStat = statisticsForAggregation[attrIdx]
-								.get(catValue);
-						if (aggrStat == null) {
-							aggrStat = new DynamicBin1D();
-							statisticsForAggregation[attrIdx].put(catValue,
-									aggrStat);
-						}
+  /**
+   * After loading from XML, a {@link FeatureChartStyle} contains whatever is
+   * written in the XML. But the DBF Schema can change quickly by accident! This
+   * method checks an {@link FeatureChartStyle} against a schema and corrects
+   * upperCase/lowerCase problems where possible. Returns <code>false</code> if
+   * attributes had to be removed from the {@link FeatureChartStyle}.
+   * @author SK
+   */
+  public static boolean correctAttributeNames(
+      FeatureChartStyle featureChartStyle, SimpleFeatureType schema) {
 
-						if (attributeAggregation.isWeighted()) {
-// fliegt schon vorher raus..
-//							if (chartStyle
-//									.getAttributeAggregationWeightAttributeName(attrIdx) == null)
-//								throw new RuntimeException(
-//										JFreeChartUtil.R("Exception.noWeightAttributeDefinedforAWeightedAggregation")); 
+    ArrayList<Integer> willRemove = new ArrayList<Integer>();
 
-							Object weightObj = f
-									.getAttribute(chartStyle
-											.getAttributeAggregationWeightAttributeName(attrIdx));
+    // 1. Check.. all attributes in the atm should be in the schema as well.
+    // maybe correct some upperCase/loweCase stuff
+    for (int idx = 0; idx < featureChartStyle.getAttributeCount(); idx++) {
 
-							if (!chartStyle.isWeightAttributeNoDataValue(
-									attrIdx, weightObj)) {
-								Number weight = (Number) weightObj;
-								aggrStat.add(yValue.doubleValue()
-										* weight.doubleValue()
-										/ sumWeights[attrIdx - 1]
-										* validFeaturesCount[attrIdx - 1]);
-							} else {
-								// NIchts added, denn das weight ist hier NODATA
-							}
+      // Check the main attribute
+      String attributeName = featureChartStyle.getAttributeName(idx);
 
-						} else {
-							aggrStat.add(yValue.doubleValue());
-						}
+      AttributeDescriptor foundDescr = schema.getDescriptor(attributeName);
+      if (foundDescr == null) {
+        Name bestMatch = FeatureUtil.findBestMatchingAttribute(schema,
+                                                               attributeName);
+        if (bestMatch == null) {
+          willRemove.add(idx);
+          continue;
+        } else
+          featureChartStyle.setAttributeName(idx, bestMatch.getLocalPart());
+      }
 
-						// TODO: Mapping vormerken (??)
-						// Problem: siehe unten
-					}
-				}
+      // Check the optional weight attribute value
+      if (idx > 0) {
+        String weightAtt = featureChartStyle.getAttributeAggregationWeightAttributeName(idx);
+        if (weightAtt != null) {
+          AttributeDescriptor foundWeightDescr = schema.getDescriptor(attributeName);
+          if (foundWeightDescr == null) {
+            Name bestMatch = FeatureUtil.findBestMatchingAttribute(schema,
+                                                                   weightAtt);
+            if (bestMatch == null) {
+              featureChartStyle.setAttributeAggregationWeightAttributeName(idx,
+                                                                           null);
+            } else
+              featureChartStyle.setAttributeAggregationWeightAttributeName(
+                                                                           idx,
+                                                                           bestMatch.getLocalPart());
+          }
+        }
+      }
+    }
 
-			}
+    // Remove the ones that were not findable in the schema
+    for (Integer removeIdx : willRemove) {
+      featureChartStyle.removeAttribute(removeIdx);
+    }
 
-			// Fill series for aggregated range attributes
-			for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
-				String yAttrName = chartStyle.getAttributeName(attrIdx);
-				AggregationFunction aggrFunc = chartStyle
-						.getAttributeAggregation(attrIdx);
-				if (aggrFunc == null)
-					continue;
-				for (Comparable<?> catValue : statisticsForAggregation[attrIdx]
-						.keySet()) {
-					QuantileBin1D aggrStat = statisticsForAggregation[attrIdx]
-							.get(catValue);
-					Number yValue = aggrFunc.getResult(aggrStat);
-					// Fill series
-					dataset.addValue(yValue, yAttrName, catValue);
-					// TODO: Mapping setzen
-					// Problem: Pro dataset item kann nur EINE FeatureID gesetzt
-					// werden (Feature2DatasetMapping, Zeile 124)
-					// // Mapping between FID and data index in series
-					// mapping.setMapping(f.getID() ??, yAttrName,
-					// datasetIdx++);
-				}
-			}
-		} finally {
-			if (features != null) {
-				fc.close(features);
-			}
-		}
+    // * Returns false if attributes had to be removed from the {@link
+    // FeatureChartStyle}.
+    return willRemove.isEmpty();
+  }
 
-		return dataset;
-	}
+  /**
+   * Passes the NODATA Values stored in the {@link AttributeMetadataMap} to the
+   * attributes (and optional weighting attributes) of the {@link ChartStyle}.
+   */
+  public static void passNoDataValues(
+      AttributeMetadataMap attributeMetaDataMap,
+      FeatureChartStyle featureChartStyle) {
 
-	/**
-	 * After loading from XML, a {@link FeatureChartStyle} contains whatever is
-	 * written in the XML. But the DBF Schema can change quickly by accident!
-	 * This method checks an {@link FeatureChartStyle} against a schema and
-	 * corrects upperCase/lowerCase problems where possible.
-	 * 
-	 * Returns <code>false</code> if attributes had to be removed from the
-	 * {@link FeatureChartStyle}.
-	 * 
-	 * @author SK
-	 */
-	public static boolean correctAttributeNames(
-			FeatureChartStyle featureChartStyle, SimpleFeatureType schema) {
+    // Pass the NODATA values for the attributes to the ChartStyle
+    for (int idx = 0; idx < featureChartStyle.getAttributeCount(); idx++) {
 
-		ArrayList<Integer> willRemove = new ArrayList<Integer>();
+      String attributeName = featureChartStyle.getAttributeName(idx);
+      AttributeMetadata attributeMetadata = attributeMetaDataMap.get(attributeName);
 
-		// 1. Check.. all attributes in the atm should be in the schema as well.
-		// maybe correct some upperCase/loweCase stuff
-		for (int idx = 0; idx < featureChartStyle.getAttributeCount(); idx++) {
+      if (attributeMetadata != null) {
+        featureChartStyle.setNoDataValues(idx,
+                                          attributeMetadata.getNodataValues());
+      }
 
-			// Check the main attribute
-			String attributeName = featureChartStyle.getAttributeName(idx);
-
-			AttributeDescriptor foundDescr = schema
-					.getDescriptor(attributeName);
-			if (foundDescr == null) {
-				Name bestMatch = FeatureUtil.findBestMatchingAttribute(schema,
-						attributeName);
-				if (bestMatch == null) {
-					willRemove.add(idx);
-					continue;
-				} else
-					featureChartStyle.setAttributeName(idx, bestMatch
-							.getLocalPart());
-			}
-
-			// Check the optional weight attribute value
-			if (idx > 0) {
-				String weightAtt = featureChartStyle
-						.getAttributeAggregationWeightAttributeName(idx);
-				if (weightAtt != null) {
-					AttributeDescriptor foundWeightDescr = schema
-							.getDescriptor(attributeName);
-					if (foundWeightDescr == null) {
-						Name bestMatch = FeatureUtil.findBestMatchingAttribute(
-								schema, weightAtt);
-						if (bestMatch == null) {
-							featureChartStyle
-									.setAttributeAggregationWeightAttributeName(
-											idx, null);
-						} else
-							featureChartStyle
-									.setAttributeAggregationWeightAttributeName(
-											idx, bestMatch.getLocalPart());
-					}
-				}
-			}
-		}
-
-		// Remove the ones that were not findable in the schema
-		for (Integer removeIdx : willRemove) {
-			featureChartStyle.removeAttribute(removeIdx);
-		}
-
-		// * Returns false if attributes had to be removed from the {@link
-		// FeatureChartStyle}.
-		return willRemove.isEmpty();
-	}
-
-	/**
-	 * Passes the NODATA Values stored in the {@link AttributeMetadataMap} to
-	 * the attributes (and optional weighting attributes) of the
-	 * {@link ChartStyle}.
-	 */
-	public static void passNoDataValues(
-			AttributeMetadataMap attributeMetaDataMap,
-			FeatureChartStyle featureChartStyle) {
-
-		// Pass the NODATA values for the attributes to the ChartStyle
-		for (int idx = 0; idx < featureChartStyle.getAttributeCount(); idx++) {
-
-			String attributeName = featureChartStyle.getAttributeName(idx);
-			AttributeMetadata attributeMetadata = attributeMetaDataMap
-					.get(attributeName);
-
-			if (attributeMetadata != null) {
-				featureChartStyle.setNoDataValues(idx, attributeMetadata
-						.getNodataValues());
-			}
-
-			// Set NODATA-Values for the weight attributes
-			String weightAtt = featureChartStyle
-					.getAttributeAggregationWeightAttributeName(idx);
-			if (weightAtt != null) {
-				AttributeMetadata weightAttributeMetadata = attributeMetaDataMap
-						.get(attributeName);
-				if (weightAttributeMetadata != null) {
-					featureChartStyle.setWeightAttributeNoDataValues(idx,
-							weightAttributeMetadata.getNodataValues());
-				}
-			}
-		}
-	}
+      // Set NODATA-Values for the weight attributes
+      String weightAtt = featureChartStyle.getAttributeAggregationWeightAttributeName(idx);
+      if (weightAtt != null) {
+        AttributeMetadata weightAttributeMetadata = attributeMetaDataMap.get(attributeName);
+        if (weightAttributeMetadata != null) {
+          featureChartStyle.setWeightAttributeNoDataValues(
+                                                           idx,
+                                                           weightAttributeMetadata.getNodataValues());
+        }
+      }
+    }
+  }
 }



More information about the Schmitzm-commits mailing list