[Schmitzm-commits] r875 - in trunk: src/schmitzm/geotools/styling src/schmitzm/jfree src/schmitzm/jfree/feature src/schmitzm/jfree/feature/style src/schmitzm/jfree/table src/schmitzm/jfree/table/style src_junit/schmitzm/jfree/feature/style

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri May 28 17:38:02 CEST 2010


Author: mojays
Date: 2010-05-28 17:37:56 +0200 (Fri, 28 May 2010)
New Revision: 875

Added:
   trunk/src/schmitzm/jfree/table/
   trunk/src/schmitzm/jfree/table/AggregationFunction.java
   trunk/src/schmitzm/jfree/table/AggregationFunctionJComboBox.java
   trunk/src/schmitzm/jfree/table/style/
   trunk/src/schmitzm/jfree/table/style/TableBasicChartStyle.java
   trunk/src/schmitzm/jfree/table/style/TableChartAxisStyle.java
   trunk/src/schmitzm/jfree/table/style/TableChartStyle.java
   trunk/src/schmitzm/jfree/table/style/TableChartStyleXMLFactory.java
   trunk/src/schmitzm/jfree/table/style/TableScatterChartStyle.java
Removed:
   trunk/src/schmitzm/jfree/feature/AggregationFunction.java
   trunk/src/schmitzm/jfree/feature/AggregationFunctionJComboBox.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartAxisStyle.java
Modified:
   trunk/src/schmitzm/geotools/styling/StylingUtil.java
   trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
   trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java
   trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java
Log:
Neue Zwischenebene TableChartStyle zwischen ChartStyle und FeatureChartStyle in neuem Package schmitzm.jfree.table:
- TableChartStyle
- TableBasicChartStyle
- TableScatterChartStyle
- TableChartStyleXMLFactory

AggregationFunction und AggregationFunctionJComboBox nach schmitzm.jfree.table verschoben.
FeatureChartAxisStyle umbenannt in TableChartAxisStyle und verschoben nach schmitzm.jfree.table.

Modified: trunk/src/schmitzm/geotools/styling/StylingUtil.java
===================================================================
--- trunk/src/schmitzm/geotools/styling/StylingUtil.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/geotools/styling/StylingUtil.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -122,13 +122,11 @@
 import org.opengis.filter.Filter;
 import org.opengis.filter.FilterFactory;
 import org.opengis.filter.FilterFactory2;
-import org.opengis.filter.Or;
 import org.opengis.filter.PropertyIsEqualTo;
 import org.opengis.filter.expression.Expression;
 import org.opengis.filter.expression.Function;
 import org.opengis.filter.expression.Literal;
 import org.opengis.filter.expression.PropertyName;
-import org.opengis.filter.spatial.Equals;
 
 import schmitzm.geotools.FilterUtil;
 import schmitzm.geotools.feature.FeatureUtil;

Deleted: trunk/src/schmitzm/jfree/feature/AggregationFunction.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/AggregationFunction.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/feature/AggregationFunction.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -1,134 +0,0 @@
-package schmitzm.jfree.feature;
-
-import schmitzm.jfree.JFreeChartUtil;
-import schmitzm.jfree.feature.style.FeatureChartStyle;
-import schmitzm.lang.ResourceProvider;
-
-/**
- * Defines possible aggregation function to calculate on attribute categories.
- * @see FeatureChartStyle#setAttributeAggregation(int, AggregationFunction)
- * @see FeatureChartStyle#getAttributeAggregation(int)
- * @see optionally FeatureChartStyle#setNoDataWeightValues(int, java.util.Set))
- * @see optionally
- *      FeatureChartStyle#getAttributeAggregationWeightAttributeName(int)
- */
-public enum AggregationFunction {
-
-  /** Count of the attribute values. */
-  COUNT(),
-  /** Sum of the attribute values. */
-  SUM(),
-  /** Sum of the absolute attribute values. */
-  SUM_ABS(true,false, false),
-  /** Weighted sum of the attribute values. Needs an attribute for weighting. */
-  SUM_WEIGHTED(false, true, false),
-  /** Average of the attribute values. */
-  AVG(),
-  /**
-   * Weighted average of the attribute values. Needs an attribute for weighting.
-   */
-  AVG_WEIGHTED(false, true, true),
-  /** Median of the attribute values. */
-  MEDIAN(),
-  /** Minimum attribute value. */
-  MIN(),
-  /** Maximum attribute value. */
-  MAX(),
-  /** Variance of the attribute values. */
-  VARIANCE(),
-  /** Standard deviation of the attribute values. */
-  STND_DEV();
-
-  // Indicates whether the attribute is must be transformed to positive
-  // values
-  private final boolean absoluted;
-  // Indicates whether the attribute is weighted with another attribute
-  private final boolean weighted;
-  // Indicates whether the attribute is weighted and averaged with the weight
-  // sum
-  private final boolean averaged;
-
-  /**
-   * Creates a default {@link Enum}, which is not absoluted, not weighted and
-   * not averaged.
-   */
-  private AggregationFunction() {
-    this(false,false,false);
-  }
-
-  /**
-   * Creates an {@link Enum} instance.
-   * @param absoluted Indicates whether the attribute is must be transformed to
-   *          positive values
-   * @param weighted Indicates whether the attribute is weighted with another
-   *          attribute
-   * @param averaged Indicates whether the attribute is weighted and averaged
-   *          with the weight sum (if averaged, weighted is automatically
-   *          implied!)
-   */
-  private AggregationFunction(boolean absoluted, boolean weighted,
-      boolean averaged) {
-    this.absoluted = absoluted;
-    this.weighted = weighted || averaged; // average implies weighted
-    this.averaged = averaged;
-  }
-
-  /**
-   * Returns <code>true</code>, if this aggregation method needs the
-   * absolute attribute value.
-   * @see Math#abs(double)
-   **/
-  public boolean isAbsoluted() {
-    return absoluted;
-  }
-
-  /**
-   * Returns <code>true</code>, if this aggregation method is used a second
-   * attribute for weighting.
-   **/
-  public boolean isWeighted() {
-    return weighted;
-  }
-
-  /**
-   * Returns <code>true</code>, if this aggregation method is used a second
-   * attribute for averaging.
-   **/
-  public boolean isAveraged() {
-    return averaged;
-  }
-
-  /**
-   * Prefix for the title (.TITLE) and description (.DESC) key in the resource
-   * bundle.
-   * @see #getTitle()
-   * @see #getDescription()
-   */
-  public final String RESOURCE_PREFIX = getClass().getSimpleName() + "." +
-                                        toString();
-
-  /**
-   * Returns a description of this kind of chart. Can be used for tool-tips. May
-   * return <code>null</code> if no localized String found.
-   */
-  public String getDescription() {
-    final String resource = JFreeChartUtil.R(RESOURCE_PREFIX + ".Desc");
-    if (resource == null ||
-        resource.equals(ResourceProvider.MISSING_RESOURCE_STRING))
-      return null;
-    return resource;
-  }
-
-  /**
-   * Returns a localized title of this kind of chart. If no localized string
-   * found, return the Enum.toString()
-   */
-  public String getTitle() {
-    final String resource = JFreeChartUtil.R(RESOURCE_PREFIX + ".Title");
-    if (resource == null ||
-        resource.equals(ResourceProvider.MISSING_RESOURCE_STRING))
-      return toString();
-    return resource;
-  }
-
-}

Deleted: trunk/src/schmitzm/jfree/feature/AggregationFunctionJComboBox.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/AggregationFunctionJComboBox.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/feature/AggregationFunctionJComboBox.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -1,89 +0,0 @@
-package schmitzm.jfree.feature;
-
-import java.awt.Component;
-import java.awt.event.ItemEvent;
-
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.JComboBox;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.ListCellRenderer;
-
-import schmitzm.jfree.JFreeChartUtil;
-import schmitzm.lang.LangUtil;
-import schmitzm.swing.SwingUtil;
-
-/**
- * A {@link JComboBox} to select one {@link AggregationFunction}s. Can be
- * initialized to also support a <code>null</code>.<br/>
- * Note: Different from {@link JComboBox}, this does not fire events for DESELCTED events. 
- * 
- * @author SK
- */
-public class AggregationFunctionJComboBox extends JComboBox {
-
-	/**
-	 * @param nullAlso
-	 *            if <code>true</code>, <code>null</code> will be the first item
-	 *            in the list.
-	 */
-	public AggregationFunctionJComboBox(boolean nullAlso) {
-		super(nullAlso ? LangUtil.extendArray(
-				new AggregationFunction[] { null }, AggregationFunction
-						.values()) : AggregationFunction.values());
-		setRenderer(listCellRenderer);
-		SwingUtil.addMouseWheelForCombobox(this, false);
-	}
-
-	/**
-	 * By default the <code>null</code> value is added.
-	 */
-	public AggregationFunctionJComboBox() {
-		this(true);
-	}
-	
-	/**
-	 * A static {@link DefaultListCellRenderer} that will render instances of
-	 * {@link AggregationFunction} with the title and description field as a
-	 * tooltip.<br/>
-	 * Any <code>null</code> value will also be rendered correctly.
-	 */
-	static ListCellRenderer listCellRenderer = new DefaultListCellRenderer() {
-
-		@Override
-		public Component getListCellRendererComponent(JList list, Object value,
-				int index, boolean isSelected, boolean cellHasFocus) {
-
-			Component proto = super.getListCellRendererComponent(list, value,
-					index, isSelected, cellHasFocus);
-
-			if (proto instanceof JLabel) {
-				JLabel jLabel = (JLabel) proto;
-
-				if (value instanceof AggregationFunction) {
-					jLabel.setText(((AggregationFunction) value).getTitle());
-					jLabel.setToolTipText(((AggregationFunction) value)
-							.getDescription());
-				} else if (value == null) {
-					jLabel.setText(JFreeChartUtil
-							.R("AggregationFunction.NONE.Title"));
-					jLabel.setToolTipText(JFreeChartUtil
-							.R("AggregationFunction.NONE.Desc"));
-				}
-			}
-
-			return proto;
-		}
-	};
-	
-	/**
-	 * The {@link JComboBox} does not fire events for DESELCTED event 
-	 */
-    @Override
-	protected void fireItemStateChanged(ItemEvent e) {
-    	if (e.getStateChange() == ItemEvent.DESELECTED) return;
-    	super.fireItemStateChanged(e);
-    }
-
-
-}

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -29,20 +29,16 @@
  ******************************************************************************/
 package schmitzm.jfree.feature.style;
 
-import java.util.Set;
-
 import org.geotools.feature.FeatureCollection;
 import org.jfree.chart.JFreeChart;
-import org.jfree.data.category.CategoryDataset;
 import org.jfree.data.general.Dataset;
-import org.jfree.data.xy.XYDataset;
 import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
 
 import schmitzm.jfree.chart.style.BasicChartStyle;
 import schmitzm.jfree.chart.style.ChartStyle;
 import schmitzm.jfree.chart.style.ChartType;
-import schmitzm.jfree.feature.AggregationFunction;
+import schmitzm.jfree.table.style.TableBasicChartStyle;
 
 /**
  * This class extends the {@link BasicChartStyle} with the properties
@@ -52,9 +48,9 @@
  * setting the attributes the style can not be applied to a feature collection!
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
  */
-public class FeatureBasicChartStyle extends BasicChartStyle implements FeatureChartStyle {
+public class FeatureBasicChartStyle extends TableBasicChartStyle<FeatureCollection<SimpleFeatureType, SimpleFeature>> implements FeatureChartStyle {
 	/** Used to maintain the {@link FeatureChartStyle} properties. */
-	protected Dummy dummyFeatureChartStyle = null;
+	protected FeatureChartStyle.Dummy dummyFeatureChartStyle = null;
 
 	/**
 	 * Creates a normal line style with default values.
@@ -71,7 +67,7 @@
 	 */
 	public FeatureBasicChartStyle(String id, ChartType type) {
 		super(id, type);
-		dummyFeatureChartStyle = new Dummy(id,-1);
+		dummyFeatureChartStyle = new FeatureChartStyle.Dummy(id,-1);
 	}
 	
     /**
@@ -100,421 +96,16 @@
     }
 
     /**
-     * Removes all style informations about an attribute and
-     * reorganizes the attribute indexes so there is an continuous 
-     * order. 
-     * @param idx an attribute
+     * Creates an appropriate {@link Dataset} for the attributes defined
+     * by this style.
+     * @see #applyToFeatureCollection(FeatureCollection)
      */
     @Override
-    public void removeAttribute(int idx) {
-      dummyFeatureChartStyle.removeAttribute(idx);
+    public JFreeChart applyToTable(FeatureCollection<SimpleFeatureType, SimpleFeature> fc) {
+      return applyToFeatureCollection(fc);
     }
 
     /**
-	 * Returns the maximum number of feature attributes that can be
-	 * specified by this style.
-	 * @return always -1 which indicates no limit
-	 */
-	@Override
-	public int getMaxAttributeCount() {
-	  return dummyFeatureChartStyle.getMaxAttributeCount();
-	}
-
-    /**
-     * Returns the number of feature attributes defined in this style.
-     */
-	@Override
-	public int getAttributeCount() {
-		return dummyFeatureChartStyle.getAttributeCount();
-	}
-
-	/**
-	 * Returns the name of a feature attribute needed to create a
-	 * chart for this style.
-     * @param idx attribute index (0=domain; 1=1st range series;
-     *            2=2nd range series; ...)
-	 */
-    @Override
-	public String getAttributeName(int idx) {
-		return dummyFeatureChartStyle.getAttributeName(idx);
-	}
-
-	/**
-	 * Sets the name of a feature attribute needed to create a
-	 * chart for this style.
-     * @param idx attribute index (0=domain; 1=1st range series;
-     *            2=2nd range series; ...)
-	 * @param attrName feature attribute name 
-	 */
-	@Override
-	public void setAttributeName(int idx, String attrName) {
-		dummyFeatureChartStyle.setAttributeName(idx,attrName);
-	}
-
-
-	/**
-	 * Sets whether the features are sorted according to the
-	 * domain attribute (before creating a {@link Dataset}).
-	 */
-    @Override
-	public void setSortDomainAxis(boolean sortDomainAxis){
-	  dummyFeatureChartStyle.setSortDomainAxis(sortDomainAxis);
-	}
-
-	/**
-	 * Returns whether the features are sorted according to the
-	 * domain attribute (before creating a {@link Dataset}).
-     * @return {@code false} as default
-	 */
-    @Override
-	public boolean isSortDomainAxis() {
-	  return dummyFeatureChartStyle.isSortDomainAxis();
-	}
-
-	/** 
-	 * Sets whether a {@link CategoryDataset} is forced for
-	 * a numeric domain attribute. The default is to create {@link XYDataset}
-	 * for a numeric and {@link CategoryDataset} for a non-numeric domain
-	 * attribute.
-	 */
-    @Override
-	public void setForceCategories(boolean forceCategories){
-      dummyFeatureChartStyle.setForceCategories(forceCategories);
-	}
-
-	/** 
-	 * Returns whether a {@link CategoryDataset} is forced for
-	 * a numeric domain attribute. The default is to create {@link XYDataset}
-	 * for a numeric and {@link CategoryDataset} for a non-numeric domain
-	 * attribute.
-     * @return {@code false} as default
-	 */
-    @Override
-	public boolean isForceCategories(){
-      return dummyFeatureChartStyle.isForceCategories();
-	}
-
-    /** 
-     * Sets whether the attribute data is normalized for an
-     * attribute(before creating a {@link Dataset}).
-     * @param idx attribute index (0=domain; 1=1st range series;
-     *            2=2nd range series; ...)
-     * @param normalize indicates the normalize property
-     */  
-    @Override
-	public void setAttributeNormalized(int idx, Boolean normalize){
-	  dummyFeatureChartStyle.setAttributeNormalized(idx, normalize);
-	}
-
-    /** 
-     * Returns whether the attribute data is normalized for an
-     * attribute(before creating a {@link Dataset}).
-     * @param idx attribute index (0=domain; 1=1st range series;
-     *            2=2nd range series; ...)
-     * @return {@code false} as default
-     */  
-	@Override
-	public boolean isAttributeNormalized(int idx) {
-		return dummyFeatureChartStyle.isAttributeNormalized(idx);
-	}
-
-    /** 
-     * Sets an arithmetical function which is calculated on
-     * the attribute values (when creating a {@link Dataset}
-     * from Features).
-     * The function is calculated on all values with the same
-     * domain value (X/category). If no function is set, duplicate
-     * domain values are ignored (only the "last" value is shown, because
-     * of replacement behavior).
-     * @param idx attribute index (1=1st range series;
-     *            2=2nd range series; ...)
-     * @param func defines the calculated function
-     * @exception IllegalArgumentException if function is set on
-     *            domain attribute (0)
-     */  
-	@Override
-    public void setAttributeAggregation(int idx, AggregationFunction func) {
-      dummyFeatureChartStyle.setAttributeAggregation(idx, func);
-    }
-      
-    /** 
-     * Returns an arithmetical function which is calculated on
-     * the attribute values (when creating a {@link Dataset}
-     * from Features).
-     * The function is calculated on all values with the same
-     * domain value (X/category). If no function is set, duplicate
-     * domain values are ignored (only the "last" value is shown, because
-     * of replacement behavior).
-     * @param idx attribute index (1=1st range series;
-     *            2=2nd range series; ...)
-     * @return {@code null} for index 0 (domain axis)
-     */  
-    @Override
-    public AggregationFunction getAttributeAggregation(int idx) {
-     return dummyFeatureChartStyle.getAttributeAggregation(idx); 
-    }
-
-    /**
-     * Sets the values, which are interpreted as "No Data". 
-     * @param idx attribute index the "No Data" values are set for
-     * @param noDataValues the "No Data" values
-     */
-    public void setNoDataValues(int idx, Set<Object> noDataValues) {
-      dummyFeatureChartStyle.setNoDataValues(idx, noDataValues);
-    }
-    
-    /**
-     * Returns the values, which are interpreted as "No Data". 
-     * @param idx attribute index the "No Data" values are returned for
-     */
-    public Set<Object> getNoDataValues(int idx) {
-      return dummyFeatureChartStyle.getNoDataValues(idx);
-    }
-    
-    /**
-     * Sets a value, which is interpreted as "No Data". 
-     * @param idx attribute index the "No Data" value is set for
-     * @param noDataValue the "No Data" value
-     */
-    public void addNoDataValue(int idx, Object noDataValue) {
-      dummyFeatureChartStyle.addNoDataValue(idx, noDataValue);
-    }
-
-    /**
-     * Removes a "No Data" value for an attribute. 
-     * @param idx attribute index the "No Data" value is removed for
-     * @param noDataValue the "No Data" value to remove
-     * @return {@code false} if the value was not an "No Data" value 
-     */
-    public boolean removeNoDataValue(int idx, Object noDataValue) {
-      return dummyFeatureChartStyle.removeNoDataValue(idx, noDataValue);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for
-     * the attribute.
-     * @param idx attribute index the "No Data" value is checked for
-     * @param value an attribute value
-     */
-    public boolean isNoDataValue(int idx, Object value) {
-      return dummyFeatureChartStyle.isNoDataValue(idx, value);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for
-     * the attribute. In this case this method returns {@code null}, otherwise
-     * the value itself.
-     * @param idx attribute index the "No Data" value is checked for
-     * @param value an attribute value
-     * @return {@code null} if the given value is one of the "No data" values 
-     */
-    public <T> T filterNoDataValue(int idx, T value) {
-      return dummyFeatureChartStyle.filterNoDataValue(idx, value);
-    }
-
-    /**
-     * Sets the feature attribute the i-th chart attribute is weighted with.<br>
-     * <b>Note:</b>
-     * <ul>
-     * <li>The weight attribute can not be set for the domain attribute 0.</li>
-     * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
-     * </ul>
-     * @param idx the feature attribute
-     * @param weightAttrName name of the weight attribute
-     * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
-     *      attribute.<br/>
-     * @exception IllegalArgumentException if weight attribute is set for
-     *              attribute 0
-     **/
-    @Override
-    public void setAttributeAggregationWeightAttributeName(int idx,
-        String weightAttrName) {
-      dummyFeatureChartStyle.setAttributeAggregationWeightAttributeName(idx, weightAttrName);
-    }
-
-    /**
-     * Returns the feature attribute the i-th chart attribute is weighted with.
-     * <b>Note:</b><br>
-     * This method returns {@code null} unless a
-     * {@linkplain AggregationFunction#isWeighted() weighted} aggregation
-     * function is set for the i-th attribute.
-     * @param idx the feature attribute
-     * @see #setAttributeAggregationWeightAttributeName(int, String)
-     **/
-    @Override
-    public String getAttributeAggregationWeightAttributeName(int idx) {
-      return dummyFeatureChartStyle.getAttributeAggregationWeightAttributeName(idx);
-    }
-
-    /**
-     * Sets the values, which are interpreted as "No Data" for the optional weight
-     * attribute.
-     * @param idx weight attribute index the "No Data" values are set for
-     * @param noDataValues the "No Data" values
-     */
-    @Override
-    public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues) {
-      dummyFeatureChartStyle.setWeightAttributeNoDataValues(idx, noDataValues);
-    }
-
-    /**
-     * Returns the values, which are interpreted as "No Data" for the
-     * weight attribute.
-     * @param idx weight attribute index the "No Data" values are returned for
-     */
-    @Override
-    public Set<Object> getWeightAttributeNoDataValues(int idx) {
-      return dummyFeatureChartStyle.getWeightAttributeNoDataValues(idx);
-    }
-
-    /**
-     * Sets a value, which is interpreted as "No Data" for the weight
-     * attribute.
-     * @param idx attribute index the "No Data" value is set for
-     * @param noDataValue the "No Data" value
-     */
-    @Override
-    public void addWeightAttributeNoDataValue(int idx, Object noDataValue) {
-      dummyFeatureChartStyle.addWeightAttributeNoDataValue(idx, noDataValue);
-    }
-
-    /**
-     * Removes a "No Data" value for a weight attribute.
-     * @param idx attribute index the "No Data" value is removed for
-     * @param noDataValue the "No Data" value to remove
-     * @return {@code false} if the value was not an "No Data" value
-     */
-    @Override
-    public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue) {
-      return dummyFeatureChartStyle.removeWeightAttributeNoDataValue(idx, noDataValue);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * weight attribute.
-     * @param idx weight attribute index the "No Data" value is checked for
-     * @param value an attribute value
-     * @return {@code false} is not weight attribute is set for attribute i
-     * @see #setAttributeAggregationWeightAttributeName(int, String)
-     */
-    @Override
-    public boolean isWeightAttributeNoDataValue(int idx, Object value) {
-      return dummyFeatureChartStyle.isWeightAttributeNoDataValue(idx, value);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * attribute. In this case this method returns {@code null}, otherwise the
-     * value itself.
-     * @param idx attribute index the "No Data" value is checked for
-     * @param value an attribute value
-     * @return {@code null} if the given value is one of the "No data" values
-     */
-    @Override
-    public <T> T filterWeightAttributeNoDataValue(int idx, T value) {
-      return dummyFeatureChartStyle.filterWeightAttributeNoDataValue(idx, value);
-    }
-
-    /**
-     * Defines the attribute whose values are used to define
-     * groups. For each group value a series is created in the chart
-     * dataset.
-     * @param attrName feature attribute name
-     */
-    @Override
-    public void setSeriesAttributeName(String attrName) {
-      dummyFeatureChartStyle.setSeriesAttributeName(attrName);
-    }
-    
-    /**
-     * Returns the attribute whose values are used to define
-     * groups. For each group value a series is created in the chart
-     * dataset.
-     */
-    @Override
-    public String getSeriesAttributeName() {
-      return dummyFeatureChartStyle.getSeriesAttributeName();
-    }
-
-    /**
-     * Sets the values, which are interpreted as "No Data" for the
-     * series attribute.
-     * @param noDataValues the "No Data" values
-     */
-    @Override
-    public void setSeriesAttributeNoDataValues(Set<Object> noDataValues) {
-      dummyFeatureChartStyle.setSeriesAttributeNoDataValues(noDataValues);
-    }
-
-    /**
-     * Returns the values, which are interpreted as "No Data" for the
-     * series attribute.
-     */
-    @Override
-    public Set<Object> getSeriesAttributeNoDataValues() {
-      return dummyFeatureChartStyle.getSeriesAttributeNoDataValues();
-    }
-
-    /**
-     * Sets a value, which is interpreted as "No Data" for the
-     * series attribute.
-     * @param noDataValue the "No Data" value
-     */
-    @Override
-    public void addSeriesAttributeNoDataValue(Object noDataValue) {
-      dummyFeatureChartStyle.addSeriesAttributeNoDataValue(noDataValue);
-    }
-
-    /**
-     * Removes a "No Data" value for the series attribute.
-     * @param noDataValue the "No Data" value to remove
-     * @return {@code false} if the value was not an "No Data" value
-     */
-    @Override
-   public boolean removeSeriesAttributeNoDataValue(Object noDataValue) {
-      return dummyFeatureChartStyle.removeSeriesAttributeNoDataValue(noDataValue);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * series attribute.
-     * @param value an attribute value
-     */
-    @Override
-    public boolean isSeriesAttributeNoDataValue(Object value) {
-      return dummyFeatureChartStyle.isSeriesAttributeNoDataValue(value);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * series attribute. In this case this method returns {@code null}, otherwise the
-     * value itself.
-     * @param value an attribute value
-     * @return {@code null} if the given value is one of the "No data" values
-     */
-    @Override
-    public <T> T filterSeriesAttributeNoDataValue(T value) {
-      return dummyFeatureChartStyle.filterSeriesAttributeNoDataValue(value);
-    }
-
-    /**
-     * Defines the attribute whose values are used to define the legend
-     * title for the series defined by {@link #setSeriesAttributeName(String)}.
-     * @param attrName feature attribute name
-     */
-    public void setSeriesLegendTitleAttributeName(String attrName) {
-      dummyFeatureChartStyle.setSeriesLegendTitleAttributeName(attrName);
-    }
-    
-    /**
-     * Returns the attribute whose values are used to define the legend
-     * title for the series defined by {@link #setSeriesAttributeName(String)}.
-     */
-    public String getSeriesLegendTitleAttributeName() {
-      return dummyFeatureChartStyle.getSeriesLegendTitleAttributeName();
-    }
-
-    /**
      * Creates an appropriate {@link Dataset} for the attributes defined
      * by this style (according to the attributes types in the given
      * {@link FeatureCollection}) and calls {@link #applyToDataset(Dataset)}.

Deleted: trunk/src/schmitzm/jfree/feature/style/FeatureChartAxisStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartAxisStyle.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartAxisStyle.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -1,142 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 Martin O. J. Schmitz.
- * 
- * This file is part of the SCHMITZM library - a collection of utility 
- * classes based on Java 1.6, focusing (not only) on Java Swing 
- * and the Geotools library.
- * 
- * The SCHMITZM project is hosted at:
- * http://wald.intevation.org/projects/schmitzm/
- * 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public License (license.txt)
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- * or try this link: http://www.gnu.org/licenses/lgpl.html
- * 
- * Contributors:
- *     Martin O. J. Schmitz - initial API and implementation
- *     Stefan A. Tzeggai - additional utility classes
- ******************************************************************************/
-
-package schmitzm.jfree.feature.style;
-
-import java.awt.Color;
-
-import org.jfree.chart.axis.Axis;
-
-import schmitzm.jfree.JFreeChartUtil;
-import schmitzm.jfree.chart.style.ChartAxisStyle;
-import schmitzm.lang.LangUtil;
-import skrueger.i8n.Translation;
-
-/**
- * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
- *
- */
-public class FeatureChartAxisStyle extends ChartAxisStyle {
-  /** Holds the {@link FeatureChartStyle} the axis is connected to. */
-  protected FeatureChartStyle chartStyle = null;
-  
-  /**
-   * Creates a new style with default values (empty label, color black, angle 0).
-   * @param chartStyle the chart style the axis is connected to
-   */
-  public FeatureChartAxisStyle(FeatureChartStyle chartStyle) {
-    this(chartStyle,"",Color.black,0.0,0.0);
-  }
-
-  /**
-   * Creates a new style.
-   * @param chartStyle the chart style the axis is connected to
-   * @param title axis title
-   * @param color text color for the axis title
-   * @param labelAngle angel (in degrees) the axis label is rotated by
-   * @param valuesAngle angel (in degrees) the axis values are rotated by
-   */
-  public FeatureChartAxisStyle(FeatureChartStyle chartStyle, String title, Color color, Double labelAngle, Double valuesAngle) {
-    super(title, color, labelAngle, valuesAngle);
-    this.chartStyle = chartStyle; 
-  }
-
-  /**
-   * Creates a new style.
-   * @param chartStyle the chart style the axis is connected to
-   * @param title axis title as an internationalized {@link Translation} 
-   * @param color text color for the axis title
-   * @param labelAngle angel (in degrees) the axis label is rotated by
-   * @param valuesAngle angel (in degrees) the axis values are rotated by
-   */
-  public FeatureChartAxisStyle(FeatureChartStyle chartStyle, Translation title, Color color, Double labelAngle, Double valuesAngle) {
-    super(title, color, labelAngle, valuesAngle);
-    this.chartStyle = chartStyle; 
-  }
-  
-  /**
-   * Creates a (deep) clone of this style.
-   */
-  @Override
-  public FeatureChartAxisStyle copy() {
-    return (FeatureChartAxisStyle)copyTo( new FeatureChartAxisStyle(null) );
-  }
-
-  /**
-   * Returns the chart style, the axis is connected to.
-   */
-  public FeatureChartStyle getChartStyle() {
-    return chartStyle;
-  }
-
-  /**
-   * Sets the chart style, the axis is connected to.
-   */
-  public void setChartStyle(FeatureChartStyle style) {
-    chartStyle = style;
-  }
-  
-  /**
-   * Applies the style to a specific axis.<br>
-   * Note: Some style properties can only be applied to specific axis types.
-   * @param axis an axis
-   */
-  @Override
-  public void applyToAxis(Axis axis) {
-    super.applyToAxis(axis);
-    if (axis == null) {
-      return;
-    }
-
-    // Determine the unit, aggregation function title and normalization
-    // to display with the axis title
-    String unitStr = isUnitVisible() ? getUnitString() : null;
-    String funcStr = null;
-    String normStr = null; 
-    for (int i=0; i<chartStyle.getAxisCount(); i++)
-      if ( chartStyle.getAxisStyle(i) == this ) {
-        // ToDo: ??? von welchem Attribut die Aggr.Function und
-        //       Normalisierung verwenden. Ist 'i' richtig?
-        if ( chartStyle.getAttributeAggregation(i) != null )
-          funcStr = chartStyle.getAttributeAggregation(i).getTitle();
-        if ( chartStyle.isAttributeNormalized(i) )
-          normStr = JFreeChartUtil.R("FeatureChartAxisStyle.normalized");
-        break;
-      }
-    
-    // If unit, function or normalization is set, add it to axis title
-    String axisLabel = getLabel();
-    String unitLabel = LangUtil.listString(", ",unitStr,funcStr,normStr);
-    if ( unitLabel != null && !"".equals(unitLabel) )
-      axisLabel += " ["+unitLabel.trim()+"]";
-    axis.setLabel( axisLabel );
-  }
-
-}

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -29,23 +29,14 @@
  ******************************************************************************/
 package schmitzm.jfree.feature.style;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
 import org.geotools.feature.FeatureCollection;
 import org.jfree.chart.JFreeChart;
-import org.jfree.data.category.CategoryDataset;
 import org.jfree.data.general.Dataset;
-import org.jfree.data.xy.XYDataset;
 import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
 
-import schmitzm.jfree.chart.style.AbstractChartStyle;
 import schmitzm.jfree.chart.style.ChartStyle;
-import schmitzm.jfree.feature.AggregationFunction;
-import schmitzm.lang.LangUtil;
+import schmitzm.jfree.table.style.TableChartStyle;
 
 /**
  * This interface extends the chart style with several functionalities used to
@@ -53,313 +44,313 @@
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
  * @version 1.0
  */
-public interface FeatureChartStyle extends ChartStyle {
+public interface FeatureChartStyle extends TableChartStyle<FeatureCollection<SimpleFeatureType, SimpleFeature>> {
+//
+//  /**
+//   * Returns the maximum number of feature attributes that can be specified by
+//   * this style.
+//   * @return -1 if there is no limit for range attributes
+//   */
+//  public int getMaxAttributeCount();
+//
+//  /**
+//   * Returns the number of feature attributes defined in this style.
+//   */
+//  public int getAttributeCount();
+//
+//  /**
+//   * Removes all style informations about an attribute and reorganizes the
+//   * attribute indexes so there is an continuous order.
+//   * @param idx an attribute index
+//   */
+//  public void removeAttribute(int idx);
+//
+//  /**
+//   * Returns the name of a feature attribute needed to create a chart for this
+//   * style.
+//   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+//   *          series; ...)
+//   */
+//  public String getAttributeName(int idx);
+//
+//  /**
+//   * Sets the name of a feature attribute needed to create a chart for this
+//   * style.
+//   * @see #setNoDataValues(idx, Set) to set NoDataValues for this attribute.
+//   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+//   *          series; ...)
+//   * @param attrName feature attribute name
+//   */
+//  public void setAttributeName(int idx, String attrName);
+//
+//  /**
+//   * Sets whether the features are sorted according to the domain attribute
+//   * (before creating a {@link Dataset}).
+//   */
+//  public void setSortDomainAxis(boolean sort);
+//
+//  /**
+//   * Returns whether the features are sorted according to the domain attribute
+//   * (before creating a {@link Dataset}).
+//   * @return {@code false} as default
+//   */
+//  public boolean isSortDomainAxis();
+//
+//  /**
+//   * Sets whether a {@link CategoryDataset} is forced for a numeric domain
+//   * attribute. The default is to create {@link XYDataset} for a numeric and
+//   * {@link CategoryDataset} for a non-numeric domain attribute.
+//   */
+//  public void setForceCategories(boolean forceCategories);
+//
+//  /**
+//   * Returns whether a {@link CategoryDataset} is forced for a numeric domain
+//   * attribute. The default is to create {@link XYDataset} for a numeric and
+//   * {@link CategoryDataset} for a non-numeric domain attribute.
+//   * @return {@code false} as default
+//   */
+//  public boolean isForceCategories();
+//
+//  /**
+//   * Sets whether the attribute data is normalized for an attribute (before
+//   * creating a {@link Dataset}).
+//   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+//   *          series; ...)
+//   * @param normalize indicates the normalize property
+//   */
+//  public void setAttributeNormalized(int idx, Boolean normalize);
+//
+//  /**
+//   * Returns whether the attribute data is normalized for an attribute (before
+//   * creating a {@link Dataset}).
+//   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+//   *          series; ...)
+//   * @return {@code false} as default
+//   */
+//  public boolean isAttributeNormalized(int idx);
+//
+//  /**
+//   * Sets an arithmetical function which is calculated on the attribute values
+//   * (when creating a {@link Dataset} from Features). The function is calculated
+//   * on all values with the same domain value (X/category). If no function is
+//   * set, duplicate domain values are ignored (only the "last" value is shown,
+//   * because of replacement behavior).
+//   * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
+//   * @param func defines the calculated function
+//   * @exception IllegalArgumentException if function is set on domain attribute
+//   *              (0)
+//   */
+//  public void setAttributeAggregation(int idx, AggregationFunction func);
+//
+//  /**
+//   * Returns an arithmetical function which is calculated on the attribute
+//   * values (when creating a {@link Dataset} from Features). The function is
+//   * calculated on all values with the same domain value (X/category). If no
+//   * function is set, duplicate domain values are ignored (only the "last" value
+//   * is shown, because of replacement behavior).
+//   * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
+//   * @return {@code null} for index 0 (domain axis)
+//   */
+//  public AggregationFunction getAttributeAggregation(int idx);
+//
+//  /**
+//   * Sets the values, which are interpreted as "No Data".
+//   * @param idx attribute index the "No Data" values are set for
+//   * @param noDataValues the "No Data" values
+//   */
+//  public void setNoDataValues(int idx, Set<Object> noDataValues);
+//
+//  /**
+//   * Returns the values, which are interpreted as "No Data".
+//   * @param idx attribute index the "No Data" values are returned for
+//   */
+//  public Set<Object> getNoDataValues(int idx);
+//
+//  /**
+//   * Sets a value, which is interpreted as "No Data".
+//   * @param idx attribute index the "No Data" value is set for
+//   * @param noDataValue the "No Data" value
+//   */
+//  public void addNoDataValue(int idx, Object noDataValue);
+//
+//  /**
+//   * Removes a "No Data" value for an attribute.
+//   * @param idx attribute index the "No Data" value is removed for
+//   * @param noDataValue the "No Data" value to remove
+//   * @return {@code false} if the value was not an "No Data" value
+//   */
+//  public boolean removeNoDataValue(int idx, Object noDataValue);
+//
+//  /**
+//   * Checks whether the given value is one of the "No data" values for the
+//   * attribute.
+//   * @param idx attribute index the "No Data" value is checked for
+//   * @param value an attribute value
+//   */
+//  public boolean isNoDataValue(int idx, Object value);
+//
+//  /**
+//   * Checks whether the given value is one of the "No data" values for the
+//   * attribute. In this case this method returns {@code null}, otherwise the
+//   * value itself.
+//   * @param idx attribute index the "No Data" value is checked for
+//   * @param value an attribute value
+//   * @return {@code null} if the given value is one of the "No data" values
+//   */
+//  public <T> T filterNoDataValue(int idx, T value);
+//
+//  /**
+//   * Sets the feature attribute the i-th chart attribute is weighted with.<br>
+//   * <b>Note:</b>
+//   * <ul>
+//   * <li>The weight attribute can not be set for the domain attribute 0.</li>
+//   * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
+//   * </ul>
+//   * @param idx the feature attribute
+//   * @param weightAttribName name of the weight attribute
+//   * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
+//   *      attribute.<br/>
+//   * @exception IllegalArgumentException if weight attribute is set for
+//   *              attribute 0
+//   **/
+//  public void setAttributeAggregationWeightAttributeName(int idx,
+//      String weightAttribName);
+//
+//  /**
+//   * Returns the feature attribute the i-th chart attribute is weighted with.
+//   * <b>Note:</b><br>
+//   * This method returns {@code null} unless a
+//   * {@linkplain AggregationFunction#isWeighted() weighted} aggregation function
+//   * is set for the i-th attribute.
+//   * @param idx the feature attribute
+//   * @see #setAttributeAggregationWeightAttributeName(int, String)
+//   **/
+//  public String getAttributeAggregationWeightAttributeName(int idx);
+//
+//  /**
+//   * Sets the values, which are interpreted as "No Data" for the optional weight
+//   * attribute.
+//   * @param idx weight attribute index the "No Data" values are set for
+//   * @param noDataValues the "No Data" values
+//   */
+//  public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues);
+//
+//  /**
+//   * Returns the values, which are interpreted as "No Data" for the
+//   * weight attribute.
+//   * @param idx weight attribute index the "No Data" values are returned for
+//   */
+//  public Set<Object> getWeightAttributeNoDataValues(int idx);
+//
+//  /**
+//   * Sets a value, which is interpreted as "No Data" for the weight
+//   * attribute.
+//   * @param idx attribute index the "No Data" value is set for
+//   * @param noDataValue the "No Data" value
+//   */
+//  public void addWeightAttributeNoDataValue(int idx, Object noDataValue);
+//
+//  /**
+//   * Removes a "No Data" value for a weight attribute.
+//   * @param idx attribute index the "No Data" value is removed for
+//   * @param noDataValue the "No Data" value to remove
+//   * @return {@code false} if the value was not an "No Data" value
+//   */
+//  public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue);
+//
+//  /**
+//   * Checks whether the given value is one of the "No data" values for the
+//   * weight attribute.
+//   * @param idx weight attribute index the "No Data" value is checked for
+//   * @param value an attribute value
+//   * @return {@code false} is not weight attribute is set for attribute i
+//   * @see #setAttributeAggregationWeightAttributeName(int, String)
+//   */
+//  public boolean isWeightAttributeNoDataValue(int idx, Object value);
+//
+//  /**
+//   * Checks whether the given value is one of the "No data" values for the
+//   * attribute. In this case this method returns {@code null}, otherwise the
+//   * value itself.
+//   * @param idx attribute index the "No Data" value is checked for
+//   * @param value an attribute value
+//   * @return {@code null} if the given value is one of the "No data" values
+//   */
+//  public <T> T filterWeightAttributeNoDataValue(int idx, T value);
+//
+//  /**
+//   * Defines the attribute whose values are used to define
+//   * groups. For each group value a series is created in the chart
+//   * dataset.
+//   * @param attrName feature attribute name
+//   */
+//  public void setSeriesAttributeName(String attrName);
+//  
+//  /**
+//   * Returns the attribute whose values are used to define
+//   * groups. For each group value a series is created in the chart
+//   * dataset.
+//   */
+//  public String getSeriesAttributeName();
+//
+//  /**
+//   * Sets the values, which are interpreted as "No Data" for the
+//   * series attribute.
+//   * @param noDataValues the "No Data" values
+//   */
+//  public void setSeriesAttributeNoDataValues(Set<Object> noDataValues);
+//
+//  /**
+//   * Returns the values, which are interpreted as "No Data" for the
+//   * series attribute.
+//   */
+//  public Set<Object> getSeriesAttributeNoDataValues();
+//
+//  /**
+//   * Sets a value, which is interpreted as "No Data" for the
+//   * series attribute.
+//   * @param noDataValue the "No Data" value
+//   */
+//  public void addSeriesAttributeNoDataValue(Object noDataValue);
+//
+//  /**
+//   * Removes a "No Data" value for the series attribute.
+//   * @param noDataValue the "No Data" value to remove
+//   * @return {@code false} if the value was not an "No Data" value
+//   */
+//  public boolean removeSeriesAttributeNoDataValue(Object noDataValue);
+//
+//  /**
+//   * Checks whether the given value is one of the "No data" values for the
+//   * series attribute.
+//   * @param value an attribute value
+//   */
+//  public boolean isSeriesAttributeNoDataValue(Object value);
+//
+//  /**
+//   * Checks whether the given value is one of the "No data" values for the
+//   * series attribute. In this case this method returns {@code null}, otherwise the
+//   * value itself.
+//   * @param value an attribute value
+//   * @return {@code null} if the given value is one of the "No data" values
+//   */
+//  public <T> T filterSeriesAttributeNoDataValue(T value);
+//
+//  /**
+//   * Defines the attribute whose values are used to define the legend
+//   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+//   * @param attrName feature attribute name
+//   */
+//  public void setSeriesLegendTitleAttributeName(String attrName);
+//  
+//  /**
+//   * Returns the attribute whose values are used to define the legend
+//   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+//   */
+//  public String getSeriesLegendTitleAttributeName();
 
   /**
-   * Returns the maximum number of feature attributes that can be specified by
-   * this style.
-   * @return -1 if there is no limit for range attributes
-   */
-  public int getMaxAttributeCount();
-
-  /**
-   * Returns the number of feature attributes defined in this style.
-   */
-  public int getAttributeCount();
-
-  /**
-   * Removes all style informations about an attribute and reorganizes the
-   * attribute indexes so there is an continuous order.
-   * @param idx an attribute index
-   */
-  public void removeAttribute(int idx);
-
-  /**
-   * Returns the name of a feature attribute needed to create a chart for this
-   * style.
-   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
-   *          series; ...)
-   */
-  public String getAttributeName(int idx);
-
-  /**
-   * Sets the name of a feature attribute needed to create a chart for this
-   * style.
-   * @see #setNoDataValues(idx, Set) to set NoDataValues for this attribute.
-   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
-   *          series; ...)
-   * @param attrName feature attribute name
-   */
-  public void setAttributeName(int idx, String attrName);
-
-  /**
-   * Sets whether the features are sorted according to the domain attribute
-   * (before creating a {@link Dataset}).
-   */
-  public void setSortDomainAxis(boolean sort);
-
-  /**
-   * Returns whether the features are sorted according to the domain attribute
-   * (before creating a {@link Dataset}).
-   * @return {@code false} as default
-   */
-  public boolean isSortDomainAxis();
-
-  /**
-   * Sets whether a {@link CategoryDataset} is forced for a numeric domain
-   * attribute. The default is to create {@link XYDataset} for a numeric and
-   * {@link CategoryDataset} for a non-numeric domain attribute.
-   */
-  public void setForceCategories(boolean forceCategories);
-
-  /**
-   * Returns whether a {@link CategoryDataset} is forced for a numeric domain
-   * attribute. The default is to create {@link XYDataset} for a numeric and
-   * {@link CategoryDataset} for a non-numeric domain attribute.
-   * @return {@code false} as default
-   */
-  public boolean isForceCategories();
-
-  /**
-   * Sets whether the attribute data is normalized for an attribute (before
-   * creating a {@link Dataset}).
-   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
-   *          series; ...)
-   * @param normalize indicates the normalize property
-   */
-  public void setAttributeNormalized(int idx, Boolean normalize);
-
-  /**
-   * Returns whether the attribute data is normalized for an attribute (before
-   * creating a {@link Dataset}).
-   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
-   *          series; ...)
-   * @return {@code false} as default
-   */
-  public boolean isAttributeNormalized(int idx);
-
-  /**
-   * Sets an arithmetical function which is calculated on the attribute values
-   * (when creating a {@link Dataset} from Features). The function is calculated
-   * on all values with the same domain value (X/category). If no function is
-   * set, duplicate domain values are ignored (only the "last" value is shown,
-   * because of replacement behavior).
-   * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
-   * @param func defines the calculated function
-   * @exception IllegalArgumentException if function is set on domain attribute
-   *              (0)
-   */
-  public void setAttributeAggregation(int idx, AggregationFunction func);
-
-  /**
-   * Returns an arithmetical function which is calculated on the attribute
-   * values (when creating a {@link Dataset} from Features). The function is
-   * calculated on all values with the same domain value (X/category). If no
-   * function is set, duplicate domain values are ignored (only the "last" value
-   * is shown, because of replacement behavior).
-   * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
-   * @return {@code null} for index 0 (domain axis)
-   */
-  public AggregationFunction getAttributeAggregation(int idx);
-
-  /**
-   * Sets the values, which are interpreted as "No Data".
-   * @param idx attribute index the "No Data" values are set for
-   * @param noDataValues the "No Data" values
-   */
-  public void setNoDataValues(int idx, Set<Object> noDataValues);
-
-  /**
-   * Returns the values, which are interpreted as "No Data".
-   * @param idx attribute index the "No Data" values are returned for
-   */
-  public Set<Object> getNoDataValues(int idx);
-
-  /**
-   * Sets a value, which is interpreted as "No Data".
-   * @param idx attribute index the "No Data" value is set for
-   * @param noDataValue the "No Data" value
-   */
-  public void addNoDataValue(int idx, Object noDataValue);
-
-  /**
-   * Removes a "No Data" value for an attribute.
-   * @param idx attribute index the "No Data" value is removed for
-   * @param noDataValue the "No Data" value to remove
-   * @return {@code false} if the value was not an "No Data" value
-   */
-  public boolean removeNoDataValue(int idx, Object noDataValue);
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * attribute.
-   * @param idx attribute index the "No Data" value is checked for
-   * @param value an attribute value
-   */
-  public boolean isNoDataValue(int idx, Object value);
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * attribute. In this case this method returns {@code null}, otherwise the
-   * value itself.
-   * @param idx attribute index the "No Data" value is checked for
-   * @param value an attribute value
-   * @return {@code null} if the given value is one of the "No data" values
-   */
-  public <T> T filterNoDataValue(int idx, T value);
-
-  /**
-   * Sets the feature attribute the i-th chart attribute is weighted with.<br>
-   * <b>Note:</b>
-   * <ul>
-   * <li>The weight attribute can not be set for the domain attribute 0.</li>
-   * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
-   * </ul>
-   * @param idx the feature attribute
-   * @param weightAttribName name of the weight attribute
-   * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
-   *      attribute.<br/>
-   * @exception IllegalArgumentException if weight attribute is set for
-   *              attribute 0
-   **/
-  public void setAttributeAggregationWeightAttributeName(int idx,
-      String weightAttribName);
-
-  /**
-   * Returns the feature attribute the i-th chart attribute is weighted with.
-   * <b>Note:</b><br>
-   * This method returns {@code null} unless a
-   * {@linkplain AggregationFunction#isWeighted() weighted} aggregation function
-   * is set for the i-th attribute.
-   * @param idx the feature attribute
-   * @see #setAttributeAggregationWeightAttributeName(int, String)
-   **/
-  public String getAttributeAggregationWeightAttributeName(int idx);
-
-  /**
-   * Sets the values, which are interpreted as "No Data" for the optional weight
-   * attribute.
-   * @param idx weight attribute index the "No Data" values are set for
-   * @param noDataValues the "No Data" values
-   */
-  public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues);
-
-  /**
-   * Returns the values, which are interpreted as "No Data" for the
-   * weight attribute.
-   * @param idx weight attribute index the "No Data" values are returned for
-   */
-  public Set<Object> getWeightAttributeNoDataValues(int idx);
-
-  /**
-   * Sets a value, which is interpreted as "No Data" for the weight
-   * attribute.
-   * @param idx attribute index the "No Data" value is set for
-   * @param noDataValue the "No Data" value
-   */
-  public void addWeightAttributeNoDataValue(int idx, Object noDataValue);
-
-  /**
-   * Removes a "No Data" value for a weight attribute.
-   * @param idx attribute index the "No Data" value is removed for
-   * @param noDataValue the "No Data" value to remove
-   * @return {@code false} if the value was not an "No Data" value
-   */
-  public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue);
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * weight attribute.
-   * @param idx weight attribute index the "No Data" value is checked for
-   * @param value an attribute value
-   * @return {@code false} is not weight attribute is set for attribute i
-   * @see #setAttributeAggregationWeightAttributeName(int, String)
-   */
-  public boolean isWeightAttributeNoDataValue(int idx, Object value);
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * attribute. In this case this method returns {@code null}, otherwise the
-   * value itself.
-   * @param idx attribute index the "No Data" value is checked for
-   * @param value an attribute value
-   * @return {@code null} if the given value is one of the "No data" values
-   */
-  public <T> T filterWeightAttributeNoDataValue(int idx, T value);
-
-  /**
-   * Defines the attribute whose values are used to define
-   * groups. For each group value a series is created in the chart
-   * dataset.
-   * @param attrName feature attribute name
-   */
-  public void setSeriesAttributeName(String attrName);
-  
-  /**
-   * Returns the attribute whose values are used to define
-   * groups. For each group value a series is created in the chart
-   * dataset.
-   */
-  public String getSeriesAttributeName();
-
-  /**
-   * Sets the values, which are interpreted as "No Data" for the
-   * series attribute.
-   * @param noDataValues the "No Data" values
-   */
-  public void setSeriesAttributeNoDataValues(Set<Object> noDataValues);
-
-  /**
-   * Returns the values, which are interpreted as "No Data" for the
-   * series attribute.
-   */
-  public Set<Object> getSeriesAttributeNoDataValues();
-
-  /**
-   * Sets a value, which is interpreted as "No Data" for the
-   * series attribute.
-   * @param noDataValue the "No Data" value
-   */
-  public void addSeriesAttributeNoDataValue(Object noDataValue);
-
-  /**
-   * Removes a "No Data" value for the series attribute.
-   * @param noDataValue the "No Data" value to remove
-   * @return {@code false} if the value was not an "No Data" value
-   */
-  public boolean removeSeriesAttributeNoDataValue(Object noDataValue);
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * series attribute.
-   * @param value an attribute value
-   */
-  public boolean isSeriesAttributeNoDataValue(Object value);
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * series attribute. In this case this method returns {@code null}, otherwise the
-   * value itself.
-   * @param value an attribute value
-   * @return {@code null} if the given value is one of the "No data" values
-   */
-  public <T> T filterSeriesAttributeNoDataValue(T value);
-
-  /**
-   * Defines the attribute whose values are used to define the legend
-   * title for the series defined by {@link #setSeriesAttributeName(String)}.
-   * @param attrName feature attribute name
-   */
-  public void setSeriesLegendTitleAttributeName(String attrName);
-  
-  /**
-   * Returns the attribute whose values are used to define the legend
-   * title for the series defined by {@link #setSeriesAttributeName(String)}.
-   */
-  public String getSeriesLegendTitleAttributeName();
-
-  /**
-   * Creates a chart according to the given
+   * Creates a chart according to the given feature collection.
    * @param fc a feature collection
    * @exception UnsupportedOperationException if the style can not be applied to
    *              the {@link FeatureCollection} (e.g. the
@@ -382,76 +373,75 @@
    * but throw an exception instead!!
    * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
    */
-  public static class Dummy extends AbstractChartStyle implements
-      FeatureChartStyle {
+  public static class Dummy extends TableChartStyle.Dummy<FeatureCollection<SimpleFeatureType, SimpleFeature>> implements FeatureChartStyle {
+//    /**
+//     * Indicates whether the features are sorted according to the domain
+//     * attribute (before creating a {@link Dataset}).
+//     */
+//    protected boolean sortDomainAxis;
+//    /**
+//     * Indicates whether a {@link CategoryDataset} is forced for a numeric
+//     * domain attribute. The default is to create {@link XYDataset} for a
+//     * numeric and {@link CategoryDataset} for a non-numeric domain attribute.
+//     */
+//    protected boolean forceCategories;
+//
+//    /**
+//     * Holds the attributes needed to specify the chart data from feature
+//     * collection (0 = attribute for domain axis; others assigned to the range
+//     * axis as series).
+//     */
+//    protected Map<Integer, String> attrNames = new HashMap<Integer, String>();
+//
+//    /**
+//     * Indicates for each attribute whether the attribute data is normalized
+//     * (before creating a {@link Dataset}).
+//     */
+//    protected Map<Integer, Boolean> normalizeAttr = new HashMap<Integer, Boolean>();
+//
+//    /**
+//     * Holds the maximum number of attributes the style can be defined defined
+//     * for (-1 = no limit).
+//     */
+//    protected int maxAttrCount = -1;
+//
+//    /** Holds the number of attributes the style is defined for. */
+//    protected int maxAttrIdx = 0;
+//
+//    /** Holds the "No Data" values for each attribute. */
+//    protected Map<Integer, Set<Object>> noDataValues = new HashMap<Integer, Set<Object>>();
+//
+//    /** Holds the aggregation function for each attribute. */
+//    protected Map<Integer, AggregationFunction> aggrFuncs = new HashMap<Integer, AggregationFunction>();
+//
+//    /**
+//     * Holds the weight attributes needed to weight the attribute values of
+//     * {@link #attrNames} if a {@linkplain AggregationFunction#isWeighted()
+//     * weighted} aggregation function is set.
+//     */
+//    protected Map<Integer, String> weightAttrNames = new HashMap<Integer, String>();
+//
+//    /** Holds the "No Data" values for each weight attribute. */
+//    protected Map<Integer, Set<Object>> weightAttrNoDataValues = new HashMap<Integer, Set<Object>>();
+//
+//    
+//    /**
+//     * Holds the attribute name of the series attribute, whose values are
+//     * used to define groups. For each group a series is created in the
+//     * dataset.
+//     */
+//    protected String seriesAttrName = null;
+//
+//    /** Holds the "No Data" values for the series attribute. */
+//    protected Set<Object> seriesAttrNoDataValues = new HashSet<Object>();
+//
+//    /**
+//     * Holds the name of the attribute, whose values define the legend
+//     * title for the series defined by {@link #seriesAttrName}.
+//     */
+//    protected String seriesLegendTitleAttrName = null;
+//
     /**
-     * Indicates whether the features are sorted according to the domain
-     * attribute (before creating a {@link Dataset}).
-     */
-    protected boolean sortDomainAxis;
-    /**
-     * Indicates whether a {@link CategoryDataset} is forced for a numeric
-     * domain attribute. The default is to create {@link XYDataset} for a
-     * numeric and {@link CategoryDataset} for a non-numeric domain attribute.
-     */
-    protected boolean forceCategories;
-
-    /**
-     * Holds the attributes needed to specify the chart data from feature
-     * collection (0 = attribute for domain axis; others assigned to the range
-     * axis as series).
-     */
-    protected Map<Integer, String> attrNames = new HashMap<Integer, String>();
-
-    /**
-     * Indicates for each attribute whether the attribute data is normalized
-     * (before creating a {@link Dataset}).
-     */
-    protected Map<Integer, Boolean> normalizeAttr = new HashMap<Integer, Boolean>();
-
-    /**
-     * Holds the maximum number of attributes the style can be defined defined
-     * for (-1 = no limit).
-     */
-    protected int maxAttrCount = -1;
-
-    /** Holds the number of attributes the style is defined for. */
-    protected int maxAttrIdx = 0;
-
-    /** Holds the "No Data" values for each attribute. */
-    protected Map<Integer, Set<Object>> noDataValues = new HashMap<Integer, Set<Object>>();
-
-    /** Holds the aggregation function for each attribute. */
-    protected Map<Integer, AggregationFunction> aggrFuncs = new HashMap<Integer, AggregationFunction>();
-
-    /**
-     * Holds the weight attributes needed to weight the attribute values of
-     * {@link #attrNames} if a {@linkplain AggregationFunction#isWeighted()
-     * weighted} aggregation function is set.
-     */
-    protected Map<Integer, String> weightAttrNames = new HashMap<Integer, String>();
-
-    /** Holds the "No Data" values for each weight attribute. */
-    protected Map<Integer, Set<Object>> weightAttrNoDataValues = new HashMap<Integer, Set<Object>>();
-
-    
-    /**
-     * Holds the attribute name of the series attribute, whose values are
-     * used to define groups. For each group a series is created in the
-     * dataset.
-     */
-    protected String seriesAttrName = null;
-
-    /** Holds the "No Data" values for the series attribute. */
-    protected Set<Object> seriesAttrNoDataValues = new HashSet<Object>();
-
-    /**
-     * Holds the name of the attribute, whose values define the legend
-     * title for the series defined by {@link #seriesAttrName}.
-     */
-    protected String seriesLegendTitleAttrName = null;
-
-    /**
      * Creates a new dummy. This constructor is protected so that only derived
      * classes can instantiate a dummy! There is no limit for the number of
      * attributes which can be defined by the style.
@@ -469,595 +459,594 @@
      *          feature collection
      */
     protected Dummy(String id, int maxAttrCount) {
-      super(id);
-      this.maxAttrCount = maxAttrCount;
+      super(id, maxAttrCount);
     }
 
-    /**
-     * Updates the local variable for the number of attributes the maximum index
-     * (key) of the several hash maps.
-     */
-    private void updateAttributeCount() {
-      maxAttrIdx = LangUtil.max(attrNames.keySet(),
-                                normalizeAttr.keySet(),
-                                noDataValues.keySet(),
-                                aggrFuncs.keySet(),
-                                weightAttrNames.keySet(),
-                                weightAttrNoDataValues.keySet()
-      );
+//    /**
+//     * Updates the local variable for the number of attributes the maximum index
+//     * (key) of the several hash maps.
+//     */
+//    private void updateAttributeCount() {
+//      maxAttrIdx = LangUtil.max(attrNames.keySet(),
+//                                normalizeAttr.keySet(),
+//                                noDataValues.keySet(),
+//                                aggrFuncs.keySet(),
+//                                weightAttrNames.keySet(),
+//                                weightAttrNoDataValues.keySet()
+//      );
+//
+//      if (maxAttrCount > 0 && maxAttrIdx >= maxAttrCount)
+//        throw new IllegalArgumentException("Only " + maxAttrCount +
+//                                           " attributes can be specified for " +
+//                                           LangUtil.getSimpleClassName(this));
+//    }
+//
+//    /**
+//     * Removes all style informations about an attribute and reorganizes the
+//     * attribute indexes so there is an continuous order.
+//     * @param idx an attribute
+//     */
+//    @Override
+//    public void removeAttribute(int idx) {
+//      // clear sets and maps of the removed attribute
+//      Set<Object> noDataValues = getNoDataValues(idx);
+//      if (noDataValues != null)
+//        noDataValues.clear();
+//
+//      // remove the attribute by move the "greater" attributes
+//      // one position "forward"
+//      int maxIdx = getAttributeCount() - 1;
+//      for (int i = idx; i < maxIdx; i++) {
+//        this.attrNames.put(i, this.attrNames.get(i + 1));
+//        this.normalizeAttr.put(i, this.normalizeAttr.get(i + 1));
+//        this.noDataValues.put(i, this.noDataValues.get(i + 1));
+//      }
+//
+//      // delete the last attribute, because now is is stored
+//      // one position forward
+//      this.attrNames.remove(maxIdx);
+//      this.normalizeAttr.remove(maxIdx);
+//      this.noDataValues.remove(maxIdx);
+//
+//      updateAttributeCount();
+//    }
+//
+//    /**
+//     * Creates a (deep) clone of this style. The properties of the super class (
+//     * {@link AbstractChartStyle}) are <b>ignored</b> because they are unused
+//     * for the dummy.
+//     */
+//    @Override
+//    public AbstractChartStyle copy() {
+//      return (AbstractChartStyle) copyTo((FeatureChartStyle) new Dummy(""));
+//    }
+//
+//    /**
+//     * Copies all properties of this style to another one. The properties of the
+//     * super class ({@link AbstractChartStyle}) are <b>ignored</b> because they
+//     * are unused for the dummy.
+//     * @param dest destination object (if {@code null} the copy is created by
+//     *          {@link #copy()})
+//     * @return {@code dest} or the new instance
+//     */
+//    @Override
+//    public ChartStyle copyTo(ChartStyle dest) {
+//      // !! do NOT copy the super class properties !!
+//      // !! copy only this classes properties !!
+//      // !! Reason: the dummy does not maintain the !!
+//      // !! super class properties and we !!
+//      // !! do not want to overwrite them !!
+//      if (dest instanceof FeatureChartStyle) {
+//        FeatureChartStyle destFCS = (FeatureChartStyle) dest;
+//        destFCS.setSortDomainAxis(isSortDomainAxis());
+//        destFCS.setForceCategories(isForceCategories());
+//
+//        // Clear the attribute names, normalization, aggregation,
+//        // etc.
+//        // NOTE: The no data value set must NOT be cleared deep,
+//        //       because these sets may originate from somewhere else!
+//        //       So only the hash entry is set to NULL.
+//        int max = destFCS.getMaxAttributeCount();
+//        for (int i = 0; i < max; i++) {
+//          destFCS.setAttributeName(i, null);
+//          destFCS.setAttributeNormalized(i, null);
+//          destFCS.setAttributeAggregation(i, null);
+//          destFCS.setAttributeAggregationWeightAttributeName(i, null);
+//          destFCS.setNoDataValues(i, null);
+//          destFCS.setWeightAttributeNoDataValues(i, null);
+//        }
+//        
+//        // Copy attribute names, normalization, aggregation, etc.
+//        for (Integer idx : attrNames.keySet())
+//          if (getAttributeName(idx) != null)
+//            destFCS.setAttributeName(idx, getAttributeName(idx));
+//        for (Integer idx : normalizeAttr.keySet())
+//          if (isAttributeNormalized(idx))
+//            destFCS.setAttributeNormalized(idx, isAttributeNormalized(idx));
+//        for (Integer idx : aggrFuncs.keySet())
+//          destFCS.setAttributeAggregation(idx, getAttributeAggregation(idx));
+//        for (Integer idx : weightAttrNames.keySet())
+//          destFCS.setAttributeAggregationWeightAttributeName(idx, getAttributeAggregationWeightAttributeName(idx));
+//        
+//        // The nodata value set are not copies deep, because these
+//        // sets may originate from somewhere else, so the only
+//        // are "redirected".
+//        for (Integer idx : noDataValues.keySet())
+//          destFCS.setNoDataValues(idx, getNoDataValues(idx));
+//        for (Integer idx : weightAttrNoDataValues.keySet())
+//          destFCS.setNoDataValues(idx, getWeightAttributeNoDataValues(idx));
+//      }
+//
+//      return dest;
+//    }
+//
+//    /**
+//     * Returns the maximum number of feature attributes that can be specified by
+//     * this style.
+//     * @return -1 if there is no limit for range attributes
+//     */
+//    @Override
+//    public int getMaxAttributeCount() {
+//      return maxAttrCount;
+//    }
+//
+//    /**
+//     * Returns the number of feature attributes defined in this style.
+//     */
+//    @Override
+//    public int getAttributeCount() {
+//      return maxAttrIdx + 1;
+//    }
+//
+//    /**
+//     * Returns the name of a feature attribute needed to create a chart for this
+//     * style.
+//     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+//     *          series; ...)
+//     */
+//    @Override
+//    public String getAttributeName(int idx) {
+//      return attrNames.get(idx);
+//    }
+//
+//    /**
+//     * Sets the name of a feature attribute needed to create a chart for this
+//     * style.
+//     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+//     *          series; ...)
+//     * @param attrName feature attribute name
+//     */
+//    @Override
+//    public void setAttributeName(int idx, String attrName) {
+//      attrNames.put(idx, attrName);
+//      updateAttributeCount();
+//    }
+//
+//    /**
+//     * Sets whether the features are sorted according to the domain attribute
+//     * (before creating a {@link Dataset}).
+//     */
+//    @Override
+//    public void setSortDomainAxis(boolean sortDomainAxis) {
+//      this.sortDomainAxis = sortDomainAxis;
+//    }
+//
+//    /**
+//     * Returns whether the features are sorted according to the domain attribute
+//     * (before creating a {@link Dataset}).
+//     * @return {@code false} as default
+//     */
+//    @Override
+//    public boolean isSortDomainAxis() {
+//      return sortDomainAxis;
+//    }
+//
+//    /**
+//     * Sets whether a {@link CategoryDataset} is forced for a numeric domain
+//     * attribute. The default is to create {@link XYDataset} for a numeric and
+//     * {@link CategoryDataset} for a non-numeric domain attribute.
+//     */
+//    @Override
+//    public void setForceCategories(boolean forceCategories) {
+//      this.forceCategories = forceCategories;
+//    }
+//
+//    /**
+//     * Returns whether a {@link CategoryDataset} is forced for a numeric domain
+//     * attribute. The default is to create {@link XYDataset} for a numeric and
+//     * {@link CategoryDataset} for a non-numeric domain attribute.
+//     * @return {@code false} as default
+//     */
+//    @Override
+//    public boolean isForceCategories() {
+//      return forceCategories;
+//    }
+//
+//    /**
+//     * Sets whether the attribute data is normalized for an attribute (before
+//     * creating a {@link Dataset}).
+//     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+//     *          series; ...)
+//     * @param normalize indicates the normalize property
+//     */
+//    @Override
+//    public void setAttributeNormalized(int idx, Boolean normalize) {
+//      normalizeAttr.put(idx, normalize);
+//      updateAttributeCount();
+//    }
+//
+//    /**
+//     * Returns whether the attribute data is normalized for an attribute (before
+//     * creating a {@link Dataset}).
+//     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+//     *          series; ...)
+//     * @return {@code false} as default
+//     */
+//    @Override
+//    public boolean isAttributeNormalized(int idx) {
+//      Boolean normalize = normalizeAttr.get(idx);
+//      return normalize != null && normalize;
+//    }
+//
+//    /**
+//     * Sets an arithmetical function which is calculated on the attribute values
+//     * (when creating a {@link Dataset} from Features). The function is
+//     * calculated on all values with the same domain value (X/category). If no
+//     * function is set, duplicate domain values are ignored (only the "last"
+//     * value is shown, because of replacement behavior).
+//     * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
+//     * @param func defines the calculated function
+//     * @exception IllegalArgumentException if function is set on domain
+//     *              attribute (0)
+//     */
+//    @Override
+//    public void setAttributeAggregation(int idx, AggregationFunction func) {
+//      if (idx == 0 && func != null)
+//        throw new IllegalArgumentException(
+//            "Aggregation function not allowed for attribute 0 (domain attribute)!");
+//      aggrFuncs.put(idx, func);
+//    }
+//
+//    /**
+//     * Returns an arithmetical function which is calculated on the attribute
+//     * values (when creating a {@link Dataset} from Features). The function is
+//     * calculated on all values with the same domain value (X/category). If no
+//     * function is set, duplicate domain values are ignored (only the "last"
+//     * value is shown, because of replacement behavior).
+//     * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
+//     * @return {@code null} for index 0 (domain axis)
+//     */
+//    @Override
+//    public AggregationFunction getAttributeAggregation(int idx) {
+//      if (idx == 0)
+//        return null;
+//      return aggrFuncs.get(idx);
+//    }
+//
+//    /**
+//     * Sets the values, which are interpreted as "No Data".
+//     * @param idx attribute index the "No Data" values are set for
+//     * @param noDataValues the "No Data" values
+//     */
+//    public void setNoDataValues(int idx, Set<Object> noDataValues) {
+//      this.noDataValues.put(idx, noDataValues);
+//      updateAttributeCount();
+//    }
+//
+//    /**
+//     * Returns the values, which are interpreted as "No Data".
+//     * @param idx attribute index the "No Data" values are returned for
+//     */
+//    public Set<Object> getNoDataValues(int idx) {
+//      return this.noDataValues.get(idx);
+//    }
+//
+//    /**
+//     * Sets a value, which is interpreted as "No Data".
+//     * @param idx attribute index the "No Data" value is set for
+//     * @param noDataValue the "No Data" value
+//     */
+//    public void addNoDataValue(int idx, Object noDataValue) {
+//      Set<Object> noDataValues = getNoDataValues(idx);
+//      if (noDataValues == null) {
+//        noDataValues = new HashSet<Object>();
+//        setNoDataValues(idx, noDataValues);
+//      }
+//      noDataValues.add(noDataValue);
+//    }
+//
+//    /**
+//     * Removes a "No Data" value for an attribute.
+//     * @param idx attribute index the "No Data" value is removed for
+//     * @param noDataValue the "No Data" value to remove
+//     * @return {@code false} if the value was not an "No Data" value
+//     */
+//    public boolean removeNoDataValue(int idx, Object noDataValue) {
+//      Set<Object> noDataValues = getNoDataValues(idx);
+//      if (noDataValues == null)
+//        return false;
+//      return noDataValues.remove(noDataValue);
+//    }
+//
+//    /**
+//     * Checks whether the given value is one of the "No data" values for the
+//     * attribute.
+//     * @param idx attribute index the "No Data" value is checked for
+//     * @param value an attribute value
+//     */
+//    public boolean isNoDataValue(int idx, Object value) {
+//      Set<Object> noDataValues = getNoDataValues(idx);
+//      if (noDataValues == null)
+//        return false;
+//      return noDataValues.contains(value);
+//    }
+//
+//    /**
+//     * Checks whether the given value is one of the "No data" values for the
+//     * attribute. In this case this method returns {@code null}, otherwise the
+//     * value itself.
+//     * @param idx attribute index the "No Data" value is checked for
+//     * @param value an attribute value
+//     * @return {@code null} if the given value is one of the "No data" values
+//     */
+//    public <T> T filterNoDataValue(int idx, T value) {
+//      if (isNoDataValue(idx, value))
+//        return null;
+//      return value;
+//    }
+//
+//    /**
+//     * Sets the feature attribute the i-th chart attribute is weighted with.<br>
+//     * <b>Note:</b>
+//     * <ul>
+//     * <li>The weight attribute can not be set for the domain attribute 0.</li>
+//     * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
+//     * </ul>
+//     * @param idx the feature attribute
+//     * @param weightAttrName name of the weight attribute
+//     * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
+//     *      attribute.<br/>
+//     * @exception IllegalArgumentException if weight attribute is set for
+//     *              attribute 0
+//     **/
+//    @Override
+//    public void setAttributeAggregationWeightAttributeName(int idx,
+//        String weightAttrName) {
+//      if (idx == 0 && weightAttrName != null)
+//        throw new IllegalArgumentException(
+//            "Weight attribute not allowed for attribute 0 because aggregation function not allowed for domain attribute!");
+//      weightAttrNames.put(idx, weightAttrName);
+//    }
+//
+//    /**
+//     * Returns the feature attribute the i-th chart attribute is weighted with.
+//     * <b>Note:</b><br>
+//     * This method returns {@code null} unless a
+//     * {@linkplain AggregationFunction#isWeighted() weighted} aggregation
+//     * function is set for the i-th attribute.
+//     * @param idx the feature attribute
+//     * @see #setAttributeAggregationWeightAttributeName(int, String)
+//     **/
+//    @Override
+//    public String getAttributeAggregationWeightAttributeName(int idx) {
+//      AggregationFunction af = getAttributeAggregation(idx);
+//      if (af == null || !af.isWeighted() || idx == 0)
+//        return null;
+//      return weightAttrNames.get(idx);
+//    }
+//
+//    /**
+//     * Sets the values, which are interpreted as "No Data" for the optional weight
+//     * attribute.
+//     * @param idx weight attribute index the "No Data" values are set for
+//     * @param noDataValues the "No Data" values
+//     */
+//    @Override
+//    public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues) {
+//      if (idx == 0 && noDataValues != null)
+//        throw new IllegalArgumentException(
+//            "Weight attribute not allowed for attribute 0 because aggregation function not allowed for domain attribute!");
+//      weightAttrNoDataValues.put(idx, noDataValues);
+//    }
+//
+//    /**
+//     * Returns the values, which are interpreted as "No Data" for the
+//     * weight attribute.
+//     * @param idx weight attribute index the "No Data" values are returned for
+//     */
+//    @Override
+//    public Set<Object> getWeightAttributeNoDataValues(int idx) {
+//      return weightAttrNoDataValues.get(idx);
+//    }
+//
+//    /**
+//     * Sets a value, which is interpreted as "No Data" for the weight
+//     * attribute.
+//     * @param idx attribute index the "No Data" value is set for
+//     * @param noDataValue the "No Data" value
+//     */
+//    @Override
+//    public void addWeightAttributeNoDataValue(int idx, Object noDataValue) {
+//      Set<Object> noDataValues = getWeightAttributeNoDataValues(idx);
+//      if (noDataValues == null) {
+//        noDataValues = new HashSet<Object>();
+//        setWeightAttributeNoDataValues(idx, noDataValues);
+//      }
+//      noDataValues.add(noDataValue);
+//    }
+//
+//    /**
+//     * Removes a "No Data" value for a weight attribute.
+//     * @param idx attribute index the "No Data" value is removed for
+//     * @param noDataValue the "No Data" value to remove
+//     * @return {@code false} if the value was not an "No Data" value
+//     */
+//    @Override
+//    public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue) {
+//      Set<Object> noDataValues = getWeightAttributeNoDataValues(idx);
+//      if (noDataValues == null)
+//        return false;
+//      return noDataValues.remove(noDataValue);
+//    }
+//
+//    /**
+//     * Checks whether the given value is one of the "No data" values for the
+//     * weight attribute.
+//     * @param idx weight attribute index the "No Data" value is checked for
+//     * @param value an attribute value
+//     * @return {@code false} is not weight attribute is set for attribute i
+//     * @see #setAttributeAggregationWeightAttributeName(int, String)
+//     */
+//    @Override
+//    public boolean isWeightAttributeNoDataValue(int idx, Object value) {
+//      Set<Object> noDataValues = getWeightAttributeNoDataValues(idx);
+//      if (noDataValues == null)
+//        return false;
+//      return noDataValues.contains(value);
+//    }
+//
+//    /**
+//     * Checks whether the given value is one of the "No data" values for the
+//     * attribute. In this case this method returns {@code null}, otherwise the
+//     * value itself.
+//     * @param idx attribute index the "No Data" value is checked for
+//     * @param value an attribute value
+//     * @return {@code null} if the given value is one of the "No data" values
+//     */
+//    @Override
+//    public <T> T filterWeightAttributeNoDataValue(int idx, T value) {
+//      if (isWeightAttributeNoDataValue(idx, value))
+//        return null;
+//      return value;
+//    }
+//
+//    /**
+//     * Defines the attribute whose values are used to define
+//     * groups. For each group value a series is created in the chart
+//     * dataset.
+//     * @param attrName feature attribute name
+//     */
+//    @Override
+//    public void setSeriesAttributeName(String attrName) {
+//      this.seriesAttrName = attrName;
+//    }
+//    
+//    /**
+//     * Returns the attribute whose values are used to define
+//     * groups. For each group value a series is created in the chart
+//     * dataset.
+//     */
+//    @Override
+//    public String getSeriesAttributeName() {
+//      return seriesAttrName;
+//    }
+//
+//    /**
+//     * Sets the values, which are interpreted as "No Data" for the
+//     * series attribute.
+//     * @param noDataValues the "No Data" values
+//     */
+//    @Override
+//    public void setSeriesAttributeNoDataValues(Set<Object> noDataValues) {
+//      seriesAttrNoDataValues = noDataValues;
+//    }
+//
+//    /**
+//     * Returns the values, which are interpreted as "No Data" for the
+//     * series attribute.
+//     */
+//    @Override
+//    public Set<Object> getSeriesAttributeNoDataValues() {
+//      return this.seriesAttrNoDataValues;
+//    }
+//
+//    /**
+//     * Sets a value, which is interpreted as "No Data" for the
+//     * series attribute.
+//     * @param noDataValue the "No Data" value
+//     */
+//    @Override
+//    public void addSeriesAttributeNoDataValue(Object noDataValue) {
+//      Set<Object> noDataValues = getSeriesAttributeNoDataValues();
+//      if (noDataValues == null) {
+//        noDataValues = new HashSet<Object>();
+//        setSeriesAttributeNoDataValues(noDataValues);
+//      }
+//      noDataValues.add(noDataValue);
+//    }
+//
+//    /**
+//     * Removes a "No Data" value for the series attribute.
+//     * @param noDataValue the "No Data" value to remove
+//     * @return {@code false} if the value was not an "No Data" value
+//     */
+//    @Override
+//   public boolean removeSeriesAttributeNoDataValue(Object noDataValue) {
+//      Set<Object> noDataValues = getSeriesAttributeNoDataValues();
+//      if (noDataValues == null)
+//        return false;
+//      return noDataValues.remove(noDataValue);
+//    }
+//
+//    /**
+//     * Checks whether the given value is one of the "No data" values for the
+//     * series attribute.
+//     * @param value an attribute value
+//     */
+//    @Override
+//    public boolean isSeriesAttributeNoDataValue(Object value) {
+//      Set<Object> noDataValues = getSeriesAttributeNoDataValues();
+//      if (noDataValues == null)
+//        return false;
+//      return noDataValues.contains(value);
+//    }
+//
+//    /**
+//     * Checks whether the given value is one of the "No data" values for the
+//     * series attribute. In this case this method returns {@code null}, otherwise the
+//     * value itself.
+//     * @param value an attribute value
+//     * @return {@code null} if the given value is one of the "No data" values
+//     */
+//    @Override
+//    public <T> T filterSeriesAttributeNoDataValue(T value) {
+//      if (isSeriesAttributeNoDataValue(value))
+//        return null;
+//      return value;
+//    }
+//
+//    /**
+//     * Defines the attribute whose values are used to define the legend
+//     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+//     * @param attrName feature attribute name
+//     */
+//    public void setSeriesLegendTitleAttributeName(String attrName) {
+//      seriesLegendTitleAttrName = attrName;
+//    }
+//    
+//    /**
+//     * Returns the attribute whose values are used to define the legend
+//     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+//     */
+//    public String getSeriesLegendTitleAttributeName() {
+//      return seriesLegendTitleAttrName;
+//    }
+//
+//    /**
+//     * Does nothing, but always throws a {@link UnsupportedOperationException},
+//     * because the dummy can not provide this functionality.
+//     */
+//    @Override
+//    public JFreeChart applyToDataset(Dataset dataset) {
+//      throw new UnsupportedOperationException(
+//          "FeatureChartStyle.Dummy does not implement applyToDataset(..)");
+//    }
 
-      if (maxAttrCount > 0 && maxAttrIdx >= maxAttrCount)
-        throw new IllegalArgumentException("Only " + maxAttrCount +
-                                           " attributes can be specified for " +
-                                           LangUtil.getSimpleClassName(this));
-    }
-
     /**
-     * Removes all style informations about an attribute and reorganizes the
-     * attribute indexes so there is an continuous order.
-     * @param idx an attribute
-     */
-    @Override
-    public void removeAttribute(int idx) {
-      // clear sets and maps of the removed attribute
-      Set<Object> noDataValues = getNoDataValues(idx);
-      if (noDataValues != null)
-        noDataValues.clear();
-
-      // remove the attribute by move the "greater" attributes
-      // one position "forward"
-      int maxIdx = getAttributeCount() - 1;
-      for (int i = idx; i < maxIdx; i++) {
-        this.attrNames.put(i, this.attrNames.get(i + 1));
-        this.normalizeAttr.put(i, this.normalizeAttr.get(i + 1));
-        this.noDataValues.put(i, this.noDataValues.get(i + 1));
-      }
-
-      // delete the last attribute, because now is is stored
-      // one position forward
-      this.attrNames.remove(maxIdx);
-      this.normalizeAttr.remove(maxIdx);
-      this.noDataValues.remove(maxIdx);
-
-      updateAttributeCount();
-    }
-
-    /**
-     * Creates a (deep) clone of this style. The properties of the super class (
-     * {@link AbstractChartStyle}) are <b>ignored</b> because they are unused
-     * for the dummy.
-     */
-    @Override
-    public AbstractChartStyle copy() {
-      return (AbstractChartStyle) copyTo((FeatureChartStyle) new Dummy(""));
-    }
-
-    /**
-     * Copies all properties of this style to another one. The properties of the
-     * super class ({@link AbstractChartStyle}) are <b>ignored</b> because they
-     * are unused for the dummy.
-     * @param dest destination object (if {@code null} the copy is created by
-     *          {@link #copy()})
-     * @return {@code dest} or the new instance
-     */
-    @Override
-    public ChartStyle copyTo(ChartStyle dest) {
-      // !! do NOT copy the super class properties !!
-      // !! copy only this classes properties !!
-      // !! Reason: the dummy does not maintain the !!
-      // !! super class properties and we !!
-      // !! do not want to overwrite them !!
-      if (dest instanceof FeatureChartStyle) {
-        FeatureChartStyle destFCS = (FeatureChartStyle) dest;
-        destFCS.setSortDomainAxis(isSortDomainAxis());
-        destFCS.setForceCategories(isForceCategories());
-
-        // Clear the attribute names, normalization, aggregation,
-        // etc.
-        // NOTE: The no data value set must NOT be cleared deep,
-        //       because these sets may originate from somewhere else!
-        //       So only the hash entry is set to NULL.
-        int max = destFCS.getMaxAttributeCount();
-        for (int i = 0; i < max; i++) {
-          destFCS.setAttributeName(i, null);
-          destFCS.setAttributeNormalized(i, null);
-          destFCS.setAttributeAggregation(i, null);
-          destFCS.setAttributeAggregationWeightAttributeName(i, null);
-          destFCS.setNoDataValues(i, null);
-          destFCS.setWeightAttributeNoDataValues(i, null);
-        }
-        
-        // Copy attribute names, normalization, aggregation, etc.
-        for (Integer idx : attrNames.keySet())
-          if (getAttributeName(idx) != null)
-            destFCS.setAttributeName(idx, getAttributeName(idx));
-        for (Integer idx : normalizeAttr.keySet())
-          if (isAttributeNormalized(idx))
-            destFCS.setAttributeNormalized(idx, isAttributeNormalized(idx));
-        for (Integer idx : aggrFuncs.keySet())
-          destFCS.setAttributeAggregation(idx, getAttributeAggregation(idx));
-        for (Integer idx : weightAttrNames.keySet())
-          destFCS.setAttributeAggregationWeightAttributeName(idx, getAttributeAggregationWeightAttributeName(idx));
-        
-        // The nodata value set are not copies deep, because these
-        // sets may originate from somewhere else, so the only
-        // are "redirected".
-        for (Integer idx : noDataValues.keySet())
-          destFCS.setNoDataValues(idx, getNoDataValues(idx));
-        for (Integer idx : weightAttrNoDataValues.keySet())
-          destFCS.setNoDataValues(idx, getWeightAttributeNoDataValues(idx));
-      }
-
-      return dest;
-    }
-
-    /**
-     * Returns the maximum number of feature attributes that can be specified by
-     * this style.
-     * @return -1 if there is no limit for range attributes
-     */
-    @Override
-    public int getMaxAttributeCount() {
-      return maxAttrCount;
-    }
-
-    /**
-     * Returns the number of feature attributes defined in this style.
-     */
-    @Override
-    public int getAttributeCount() {
-      return maxAttrIdx + 1;
-    }
-
-    /**
-     * Returns the name of a feature attribute needed to create a chart for this
-     * style.
-     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
-     *          series; ...)
-     */
-    @Override
-    public String getAttributeName(int idx) {
-      return attrNames.get(idx);
-    }
-
-    /**
-     * Sets the name of a feature attribute needed to create a chart for this
-     * style.
-     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
-     *          series; ...)
-     * @param attrName feature attribute name
-     */
-    @Override
-    public void setAttributeName(int idx, String attrName) {
-      attrNames.put(idx, attrName);
-      updateAttributeCount();
-    }
-
-    /**
-     * Sets whether the features are sorted according to the domain attribute
-     * (before creating a {@link Dataset}).
-     */
-    @Override
-    public void setSortDomainAxis(boolean sortDomainAxis) {
-      this.sortDomainAxis = sortDomainAxis;
-    }
-
-    /**
-     * Returns whether the features are sorted according to the domain attribute
-     * (before creating a {@link Dataset}).
-     * @return {@code false} as default
-     */
-    @Override
-    public boolean isSortDomainAxis() {
-      return sortDomainAxis;
-    }
-
-    /**
-     * Sets whether a {@link CategoryDataset} is forced for a numeric domain
-     * attribute. The default is to create {@link XYDataset} for a numeric and
-     * {@link CategoryDataset} for a non-numeric domain attribute.
-     */
-    @Override
-    public void setForceCategories(boolean forceCategories) {
-      this.forceCategories = forceCategories;
-    }
-
-    /**
-     * Returns whether a {@link CategoryDataset} is forced for a numeric domain
-     * attribute. The default is to create {@link XYDataset} for a numeric and
-     * {@link CategoryDataset} for a non-numeric domain attribute.
-     * @return {@code false} as default
-     */
-    @Override
-    public boolean isForceCategories() {
-      return forceCategories;
-    }
-
-    /**
-     * Sets whether the attribute data is normalized for an attribute (before
-     * creating a {@link Dataset}).
-     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
-     *          series; ...)
-     * @param normalize indicates the normalize property
-     */
-    @Override
-    public void setAttributeNormalized(int idx, Boolean normalize) {
-      normalizeAttr.put(idx, normalize);
-      updateAttributeCount();
-    }
-
-    /**
-     * Returns whether the attribute data is normalized for an attribute (before
-     * creating a {@link Dataset}).
-     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
-     *          series; ...)
-     * @return {@code false} as default
-     */
-    @Override
-    public boolean isAttributeNormalized(int idx) {
-      Boolean normalize = normalizeAttr.get(idx);
-      return normalize != null && normalize;
-    }
-
-    /**
-     * Sets an arithmetical function which is calculated on the attribute values
-     * (when creating a {@link Dataset} from Features). The function is
-     * calculated on all values with the same domain value (X/category). If no
-     * function is set, duplicate domain values are ignored (only the "last"
-     * value is shown, because of replacement behavior).
-     * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
-     * @param func defines the calculated function
-     * @exception IllegalArgumentException if function is set on domain
-     *              attribute (0)
-     */
-    @Override
-    public void setAttributeAggregation(int idx, AggregationFunction func) {
-      if (idx == 0 && func != null)
-        throw new IllegalArgumentException(
-            "Aggregation function not allowed for attribute 0 (domain attribute)!");
-      aggrFuncs.put(idx, func);
-    }
-
-    /**
-     * Returns an arithmetical function which is calculated on the attribute
-     * values (when creating a {@link Dataset} from Features). The function is
-     * calculated on all values with the same domain value (X/category). If no
-     * function is set, duplicate domain values are ignored (only the "last"
-     * value is shown, because of replacement behavior).
-     * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
-     * @return {@code null} for index 0 (domain axis)
-     */
-    @Override
-    public AggregationFunction getAttributeAggregation(int idx) {
-      if (idx == 0)
-        return null;
-      return aggrFuncs.get(idx);
-    }
-
-    /**
-     * Sets the values, which are interpreted as "No Data".
-     * @param idx attribute index the "No Data" values are set for
-     * @param noDataValues the "No Data" values
-     */
-    public void setNoDataValues(int idx, Set<Object> noDataValues) {
-      this.noDataValues.put(idx, noDataValues);
-      updateAttributeCount();
-    }
-
-    /**
-     * Returns the values, which are interpreted as "No Data".
-     * @param idx attribute index the "No Data" values are returned for
-     */
-    public Set<Object> getNoDataValues(int idx) {
-      return this.noDataValues.get(idx);
-    }
-
-    /**
-     * Sets a value, which is interpreted as "No Data".
-     * @param idx attribute index the "No Data" value is set for
-     * @param noDataValue the "No Data" value
-     */
-    public void addNoDataValue(int idx, Object noDataValue) {
-      Set<Object> noDataValues = getNoDataValues(idx);
-      if (noDataValues == null) {
-        noDataValues = new HashSet<Object>();
-        setNoDataValues(idx, noDataValues);
-      }
-      noDataValues.add(noDataValue);
-    }
-
-    /**
-     * Removes a "No Data" value for an attribute.
-     * @param idx attribute index the "No Data" value is removed for
-     * @param noDataValue the "No Data" value to remove
-     * @return {@code false} if the value was not an "No Data" value
-     */
-    public boolean removeNoDataValue(int idx, Object noDataValue) {
-      Set<Object> noDataValues = getNoDataValues(idx);
-      if (noDataValues == null)
-        return false;
-      return noDataValues.remove(noDataValue);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * attribute.
-     * @param idx attribute index the "No Data" value is checked for
-     * @param value an attribute value
-     */
-    public boolean isNoDataValue(int idx, Object value) {
-      Set<Object> noDataValues = getNoDataValues(idx);
-      if (noDataValues == null)
-        return false;
-      return noDataValues.contains(value);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * attribute. In this case this method returns {@code null}, otherwise the
-     * value itself.
-     * @param idx attribute index the "No Data" value is checked for
-     * @param value an attribute value
-     * @return {@code null} if the given value is one of the "No data" values
-     */
-    public <T> T filterNoDataValue(int idx, T value) {
-      if (isNoDataValue(idx, value))
-        return null;
-      return value;
-    }
-
-    /**
-     * Sets the feature attribute the i-th chart attribute is weighted with.<br>
-     * <b>Note:</b>
-     * <ul>
-     * <li>The weight attribute can not be set for the domain attribute 0.</li>
-     * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
-     * </ul>
-     * @param idx the feature attribute
-     * @param weightAttrName name of the weight attribute
-     * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
-     *      attribute.<br/>
-     * @exception IllegalArgumentException if weight attribute is set for
-     *              attribute 0
-     **/
-    @Override
-    public void setAttributeAggregationWeightAttributeName(int idx,
-        String weightAttrName) {
-      if (idx == 0 && weightAttrName != null)
-        throw new IllegalArgumentException(
-            "Weight attribute not allowed for attribute 0 because aggregation function not allowed for domain attribute!");
-      weightAttrNames.put(idx, weightAttrName);
-    }
-
-    /**
-     * Returns the feature attribute the i-th chart attribute is weighted with.
-     * <b>Note:</b><br>
-     * This method returns {@code null} unless a
-     * {@linkplain AggregationFunction#isWeighted() weighted} aggregation
-     * function is set for the i-th attribute.
-     * @param idx the feature attribute
-     * @see #setAttributeAggregationWeightAttributeName(int, String)
-     **/
-    @Override
-    public String getAttributeAggregationWeightAttributeName(int idx) {
-      AggregationFunction af = getAttributeAggregation(idx);
-      if (af == null || !af.isWeighted() || idx == 0)
-        return null;
-      return weightAttrNames.get(idx);
-    }
-
-    /**
-     * Sets the values, which are interpreted as "No Data" for the optional weight
-     * attribute.
-     * @param idx weight attribute index the "No Data" values are set for
-     * @param noDataValues the "No Data" values
-     */
-    @Override
-    public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues) {
-      if (idx == 0 && noDataValues != null)
-        throw new IllegalArgumentException(
-            "Weight attribute not allowed for attribute 0 because aggregation function not allowed for domain attribute!");
-      weightAttrNoDataValues.put(idx, noDataValues);
-    }
-
-    /**
-     * Returns the values, which are interpreted as "No Data" for the
-     * weight attribute.
-     * @param idx weight attribute index the "No Data" values are returned for
-     */
-    @Override
-    public Set<Object> getWeightAttributeNoDataValues(int idx) {
-      return weightAttrNoDataValues.get(idx);
-    }
-
-    /**
-     * Sets a value, which is interpreted as "No Data" for the weight
-     * attribute.
-     * @param idx attribute index the "No Data" value is set for
-     * @param noDataValue the "No Data" value
-     */
-    @Override
-    public void addWeightAttributeNoDataValue(int idx, Object noDataValue) {
-      Set<Object> noDataValues = getWeightAttributeNoDataValues(idx);
-      if (noDataValues == null) {
-        noDataValues = new HashSet<Object>();
-        setWeightAttributeNoDataValues(idx, noDataValues);
-      }
-      noDataValues.add(noDataValue);
-    }
-
-    /**
-     * Removes a "No Data" value for a weight attribute.
-     * @param idx attribute index the "No Data" value is removed for
-     * @param noDataValue the "No Data" value to remove
-     * @return {@code false} if the value was not an "No Data" value
-     */
-    @Override
-    public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue) {
-      Set<Object> noDataValues = getWeightAttributeNoDataValues(idx);
-      if (noDataValues == null)
-        return false;
-      return noDataValues.remove(noDataValue);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * weight attribute.
-     * @param idx weight attribute index the "No Data" value is checked for
-     * @param value an attribute value
-     * @return {@code false} is not weight attribute is set for attribute i
-     * @see #setAttributeAggregationWeightAttributeName(int, String)
-     */
-    @Override
-    public boolean isWeightAttributeNoDataValue(int idx, Object value) {
-      Set<Object> noDataValues = getWeightAttributeNoDataValues(idx);
-      if (noDataValues == null)
-        return false;
-      return noDataValues.contains(value);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * attribute. In this case this method returns {@code null}, otherwise the
-     * value itself.
-     * @param idx attribute index the "No Data" value is checked for
-     * @param value an attribute value
-     * @return {@code null} if the given value is one of the "No data" values
-     */
-    @Override
-    public <T> T filterWeightAttributeNoDataValue(int idx, T value) {
-      if (isWeightAttributeNoDataValue(idx, value))
-        return null;
-      return value;
-    }
-
-    /**
-     * Defines the attribute whose values are used to define
-     * groups. For each group value a series is created in the chart
-     * dataset.
-     * @param attrName feature attribute name
-     */
-    @Override
-    public void setSeriesAttributeName(String attrName) {
-      this.seriesAttrName = attrName;
-    }
-    
-    /**
-     * Returns the attribute whose values are used to define
-     * groups. For each group value a series is created in the chart
-     * dataset.
-     */
-    @Override
-    public String getSeriesAttributeName() {
-      return seriesAttrName;
-    }
-
-    /**
-     * Sets the values, which are interpreted as "No Data" for the
-     * series attribute.
-     * @param noDataValues the "No Data" values
-     */
-    @Override
-    public void setSeriesAttributeNoDataValues(Set<Object> noDataValues) {
-      seriesAttrNoDataValues = noDataValues;
-    }
-
-    /**
-     * Returns the values, which are interpreted as "No Data" for the
-     * series attribute.
-     */
-    @Override
-    public Set<Object> getSeriesAttributeNoDataValues() {
-      return this.seriesAttrNoDataValues;
-    }
-
-    /**
-     * Sets a value, which is interpreted as "No Data" for the
-     * series attribute.
-     * @param noDataValue the "No Data" value
-     */
-    @Override
-    public void addSeriesAttributeNoDataValue(Object noDataValue) {
-      Set<Object> noDataValues = getSeriesAttributeNoDataValues();
-      if (noDataValues == null) {
-        noDataValues = new HashSet<Object>();
-        setSeriesAttributeNoDataValues(noDataValues);
-      }
-      noDataValues.add(noDataValue);
-    }
-
-    /**
-     * Removes a "No Data" value for the series attribute.
-     * @param noDataValue the "No Data" value to remove
-     * @return {@code false} if the value was not an "No Data" value
-     */
-    @Override
-   public boolean removeSeriesAttributeNoDataValue(Object noDataValue) {
-      Set<Object> noDataValues = getSeriesAttributeNoDataValues();
-      if (noDataValues == null)
-        return false;
-      return noDataValues.remove(noDataValue);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * series attribute.
-     * @param value an attribute value
-     */
-    @Override
-    public boolean isSeriesAttributeNoDataValue(Object value) {
-      Set<Object> noDataValues = getSeriesAttributeNoDataValues();
-      if (noDataValues == null)
-        return false;
-      return noDataValues.contains(value);
-    }
-
-    /**
-     * Checks whether the given value is one of the "No data" values for the
-     * series attribute. In this case this method returns {@code null}, otherwise the
-     * value itself.
-     * @param value an attribute value
-     * @return {@code null} if the given value is one of the "No data" values
-     */
-    @Override
-    public <T> T filterSeriesAttributeNoDataValue(T value) {
-      if (isSeriesAttributeNoDataValue(value))
-        return null;
-      return value;
-    }
-
-    /**
-     * Defines the attribute whose values are used to define the legend
-     * title for the series defined by {@link #setSeriesAttributeName(String)}.
-     * @param attrName feature attribute name
-     */
-    public void setSeriesLegendTitleAttributeName(String attrName) {
-      seriesLegendTitleAttrName = attrName;
-    }
-    
-    /**
-     * Returns the attribute whose values are used to define the legend
-     * title for the series defined by {@link #setSeriesAttributeName(String)}.
-     */
-    public String getSeriesLegendTitleAttributeName() {
-      return seriesLegendTitleAttrName;
-    }
-
-    /**
      * Does nothing, but always throws a {@link UnsupportedOperationException},
      * because the dummy can not provide this functionality.
      */
     @Override
-    public JFreeChart applyToDataset(Dataset dataset) {
-      throw new UnsupportedOperationException(
-          "FeatureChartStyle.Dummy does not implement applyToDataset(..)");
-    }
-
-    /**
-     * Does nothing, but always throws a {@link UnsupportedOperationException},
-     * because the dummy can not provide this functionality.
-     */
-    @Override
     public JFreeChart applyToFeatureCollection(
         FeatureCollection<SimpleFeatureType, SimpleFeature> fc) {
       throw new UnsupportedOperationException(

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -29,111 +29,20 @@
  ******************************************************************************/
 package schmitzm.jfree.feature.style;
 
-import java.util.List;
-import java.util.Set;
-
-import org.geotools.feature.FeatureCollection;
-import org.jdom.Element;
-
-import schmitzm.jfree.chart.style.ChartAxisStyle;
-import schmitzm.jfree.chart.style.ChartStyle;
-import schmitzm.jfree.chart.style.ChartStyleXMLFactory;
 import schmitzm.jfree.chart.style.ChartType;
-import schmitzm.jfree.feature.AggregationFunction;
-import schmitzm.xml.XMLUtil;
+import schmitzm.jfree.table.style.TableChartStyle;
+import schmitzm.jfree.table.style.TableChartStyleXMLFactory;
 	
 /**
  * This class defines a factory to create a chart style from XML
- * specialized for {@link FeatureCollection}.
+ * specialized for feature data.
+ * @see TableChartStyle
  * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
  * @version 1.0
  */
-public class FeatureChartStyleXMLFactory extends ChartStyleXMLFactory<FeatureChartStyle> {
+public class FeatureChartStyleXMLFactory extends TableChartStyleXMLFactory<FeatureChartStyle> {
 
   /**
-   * Applies the chart style definition from XML (<b>except the type and id!!</b>)
-   * to an existing {@link ChartStyle} object.
-   * @param chartStyle an existing chart style ({@code null} not permitted!)
-   * @param element    element to read the properties from
-   */
-  @Override
-  public void applyStyleFromXML(FeatureChartStyle chartStyle, Element element) {
-    // Apply the normal style properties
-    super.applyStyleFromXML(chartStyle, element);
-    
-    // Convert ChartAxisStyle to FeatureChartAxisStyle
-    for (int i=0; i<chartStyle.getAxisCount(); i++) {
-      ChartAxisStyle axisStyle = chartStyle.getAxisStyle(i);
-      if ( axisStyle != null ) {
-        FeatureChartAxisStyle featureAxisStyle = (FeatureChartAxisStyle)axisStyle.copyTo( new FeatureChartAxisStyle(chartStyle) );
-        chartStyle.setAxisStyle(i, featureAxisStyle);
-      }
-    }
-    
-    // Attribute definitions in <attributes> element
-    Element featureElement = element.getChild("featureAttributes");
-    if ( featureElement == null )
-      throw new UnsupportedOperationException("<featureAttributes> element necessary for FeatureChartStyle!");
-
-    // Read domain attribute
-    Element domainAttrElem = featureElement.getChild("domainAttr");
-    if ( domainAttrElem == null )
-      throw new UnsupportedOperationException("Attribute <domainAttr> required for FeatureChartType");
-    String domainAttrName = XMLUtil.getAttribute(domainAttrElem, "name");
-    if ( domainAttrName == null )
-      throw new UnsupportedOperationException("Attribute 'name' necessary for <domainAttr> element of FeatureChartStyle!");
-    chartStyle.setAttributeName(0, domainAttrName);
-    chartStyle.setAttributeNormalized(0, XMLUtil.getBooleanAttribute(domainAttrElem, "normalize", false));
-    chartStyle.setSortDomainAxis(XMLUtil.getBooleanAttribute(domainAttrElem, "sort", false));
-    chartStyle.setForceCategories(XMLUtil.getBooleanAttribute(domainAttrElem, "forceCategories", false));
-    Set<Object> nullAliases = XMLUtil.getSetAttribute(domainAttrElem, "nullAliases");
-    if (nullAliases != null)
-      chartStyle.setNoDataValues(0, nullAliases);
-    
-    // Read all range attribute definitions
-    int rangeAttrNo = 0;
-    for (Element rangeAttrElem : (List<Element>)featureElement.getChildren("rangeAttr") ) {
-      String featureAttrName = XMLUtil.getAttribute(rangeAttrElem, "name");
-      if ( featureAttrName == null )
-        throw new UnsupportedOperationException("Attribute 'name' necessary for <rangeAttr> element of FeatureChartStyle!");
-      // Apply attributes to style
-      rangeAttrNo++;
-      chartStyle.setAttributeName(rangeAttrNo, featureAttrName);
-      chartStyle.setAttributeNormalized(rangeAttrNo, XMLUtil.getBooleanAttribute(rangeAttrElem, "normalize", false));
-      nullAliases = XMLUtil.getSetAttribute(rangeAttrElem, "nullAliases");
-      if (nullAliases != null)
-    	  chartStyle.setNoDataValues(rangeAttrNo, nullAliases);
-      
-      String aggrFuncStr = XMLUtil.getAttribute(rangeAttrElem, "function", (String)null);
-      if ( aggrFuncStr != null ) 
-        chartStyle.setAttributeAggregation(rangeAttrNo, AggregationFunction.valueOf(aggrFuncStr) );
-
-      String aggrFuncWeightAtt = XMLUtil.getAttribute(rangeAttrElem, "weightAttrName", (String)null);
-      if ( aggrFuncWeightAtt != null )
-        chartStyle.setAttributeAggregationWeightAttributeName(rangeAttrNo, aggrFuncWeightAtt );
-      
-      nullAliases = XMLUtil.getSetAttribute(rangeAttrElem, "weightAttrNullAliases");
-      if (nullAliases != null)
-    	  chartStyle.setWeightAttributeNoDataValues(rangeAttrNo, nullAliases);
-    }
-
-    // Read (optional) series attribute (its values defines the series groups)
-    Element seriesAttrElem = featureElement.getChild("seriesAttr");
-    if ( seriesAttrElem != null ) {
-      String seriesAttrName = XMLUtil.getAttribute(seriesAttrElem, "name");
-      if ( seriesAttrName == null )
-        throw new UnsupportedOperationException("Attribute 'name' necessary for <seriesAttr> element of FeatureChartStyle!");
-      chartStyle.setSeriesAttributeName(seriesAttrName);
-      nullAliases = XMLUtil.getSetAttribute(seriesAttrElem, "nullAliases");
-      if (nullAliases != null)
-        chartStyle.setSeriesAttributeNoDataValues(nullAliases);
-      String seriesLegendLableAttrName = XMLUtil.getAttribute(seriesAttrElem, "titleAttrName");
-      if (seriesLegendLableAttrName != null)
-        chartStyle.setSeriesLegendTitleAttributeName(seriesLegendLableAttrName);
-    }
-}
-
-  /**
    * Creates a default style for a chart type.
    * @param id   a (unique) ID for the style
    * @param type a chart type
@@ -151,49 +60,4 @@
     throw new UnsupportedOperationException("Style for this chart type not yet supported for features: "+type);
   }
 
-
-  /**
-   * Creates a XML {@link Element} representing the {@link FeatureChartStylee}.
-   * @param style           style to create an element for
-   * @param rootElementName name for the root element (if {@code null} "ChartType" is 
-   *                        used)
-   */
-  @Override
-  public Element createElementFromStyle(FeatureChartStyle style, String rootElementName) {
-    Element root = super.createElementFromStyle(style, rootElementName);
-    
-    // Create and add element <featureAttributes>
-    Element attrElem = addChildToElement(root, "featureAttributes");
-    
-    // Domain attribute definition
-    if ( style.getAttributeCount() > 0 )
-      addChildToElement(attrElem, "domainAttr", false,
-          "name", style.getAttributeName(0),
-          "normalize", style.isAttributeNormalized(0),
-          "nullAliases", XMLUtil.convertSetToSeparatedString(style.getNoDataValues(0)), 
-          "sort", style.isSortDomainAxis(),
-          "forceCategories", style.isForceCategories()
-      );
-    
-    // Range attributes definition
-    for (int i=1; i<style.getAttributeCount(); i++)
-      addChildToElement(attrElem, "rangeAttr", false,
-          "name", style.getAttributeName(i),
-          "normalize", style.isAttributeNormalized(i),
-          "nullAliases", XMLUtil.convertSetToSeparatedString(style.getNoDataValues(i)), 
-          "function", style.getAttributeAggregation(i),
-          "weightAttrName", style.getAttributeAggregationWeightAttributeName(i),
-          "weightAttrNullAliases", XMLUtil.convertSetToSeparatedString(style.getWeightAttributeNoDataValues(i))
-      );
-
-    // Series attribute definition
-    if ( style.getSeriesAttributeName() != null )
-      addChildToElement(attrElem, "seriesAttr", false,
-          "name", style.getSeriesAttributeName(),
-          "nullAliases", XMLUtil.convertSetToSeparatedString(style.getSeriesAttributeNoDataValues()),
-          "titleAttrName", style.getSeriesLegendTitleAttributeName()
-      );
-
-    return root;
-  }
 }

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -48,7 +48,6 @@
 import org.jfree.chart.plot.XYPlot;
 import org.jfree.chart.renderer.category.CategoryItemRenderer;
 import org.jfree.chart.renderer.xy.XYItemRenderer;
-import org.jfree.data.UnknownKeyException;
 import org.jfree.data.category.CategoryDataset;
 import org.jfree.data.category.DefaultCategoryDataset;
 import org.jfree.data.general.Dataset;
@@ -71,12 +70,12 @@
 import schmitzm.jfree.chart.style.ChartRendererStyle;
 import schmitzm.jfree.chart.style.ChartStyle;
 import schmitzm.jfree.chart.style.ChartStyleXMLFactory;
-import schmitzm.jfree.feature.AggregationFunction;
 import schmitzm.jfree.feature.Feature2CategoryDatasetMapping;
 import schmitzm.jfree.feature.Feature2PieDatasetMapping;
 import schmitzm.jfree.feature.Feature2SeriesDatasetMapping;
 import schmitzm.jfree.feature.FeatureDatasetMetaData;
 import schmitzm.jfree.feature.FeatureDatasetSelectionModel;
+import schmitzm.jfree.table.AggregationFunction;
 import schmitzm.lang.LangUtil;
 import skrueger.AttributeMetadataInterface;
 import skrueger.geotools.AttributeMetadataMap;

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -29,19 +29,15 @@
  ******************************************************************************/
 package schmitzm.jfree.feature.style;
 
-import java.util.Set;
-
 import org.geotools.feature.FeatureCollection;
 import org.jfree.chart.JFreeChart;
-import org.jfree.data.category.CategoryDataset;
 import org.jfree.data.general.Dataset;
-import org.jfree.data.xy.XYDataset;
 import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
 
 import schmitzm.jfree.chart.style.ChartStyle;
 import schmitzm.jfree.chart.style.ScatterChartStyle;
-import schmitzm.jfree.feature.AggregationFunction;
+import schmitzm.jfree.table.style.TableScatterChartStyle;
 
 /**
  * This class extends the {@link ScatterChartStyle} with the properties
@@ -51,9 +47,9 @@
  * setting the attributes the style can not be applied to a feature collection!
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
  */
-public class FeatureScatterChartStyle extends ScatterChartStyle implements FeatureChartStyle {
+public class FeatureScatterChartStyle extends TableScatterChartStyle<FeatureCollection<SimpleFeatureType, SimpleFeature>> implements FeatureChartStyle {
   /** Used to maintain the {@link FeatureChartStyle} properties. */
-  protected Dummy dummyFeatureChartStyle = null;
+  protected FeatureChartStyle.Dummy dummyFeatureChartStyle = null;
   
   /**
    * Creates a scatter chart style a regression line shown.
@@ -61,18 +57,9 @@
    */
   public FeatureScatterChartStyle(String id) {
     super(id);
-    dummyFeatureChartStyle = new Dummy(id,2);
+    dummyFeatureChartStyle = new FeatureChartStyle.Dummy(id,2);
   }
   
-  @Override
-  /**
-   * Nicer debugging
-   */
-	public String toString() {
-	  
-	  String titel = getTitleStyle() != null ? getTitleStyle().getLabel() : " - null title!!! - ";
-		return "ID="+getID()+"   "+titel+"" + super.toString();
-	}
 
   /**
    * Creates a scatter chart style a regression line shown.
@@ -114,421 +101,17 @@
   }
 
   /**
-   * Removes all style informations about an attribute and
-   * reorganizes the attribute indexes so there is an continuous 
-   * order. 
-   * @param idx an attribute
+   * Creates an appropriate {@link Dataset} for the attributes defined
+   * by this style.
+   * @see #applyToFeatureCollection(FeatureCollection)
    */
   @Override
-  public void removeAttribute(int idx) {
-    dummyFeatureChartStyle.removeAttribute(idx);
+  public JFreeChart applyToTable(FeatureCollection<SimpleFeatureType, SimpleFeature> fc) {
+    return applyToFeatureCollection(fc);
   }
 
-  /**
-   * Returns the maximum number of feature attributes that can be
-   * specified by this style.
-   * @return always 2
-   */
-  @Override
-  public int getMaxAttributeCount() {
-    return dummyFeatureChartStyle.getMaxAttributeCount();
-  }
 
   /**
-   * Returns the number of feature attributes defined in this style.
-   */
-  @Override
-  public int getAttributeCount() {
-    return dummyFeatureChartStyle.getAttributeCount();
-  }
-
-  /**
-   * Returns the name of a feature attribute needed to create a
-   * chart for this style.
-   * @param idx attribute index (0=domain; 1=1st range series;
-   *            2=2nd range series; ...)
-   */
-  @Override
-  public String getAttributeName(int idx) {
-    return dummyFeatureChartStyle.getAttributeName(idx);
-  }
-
-  /**
-   * Sets the name of a feature attribute needed to create a
-   * chart for this style.
-   * @param idx attribute index (0=domain; 1=1st range series;
-   *            2=2nd range series; ...)
-   * @param attrName feature attribute name 
-   */
-  @Override
-  public void setAttributeName(int idx, String attrName) {
-    dummyFeatureChartStyle.setAttributeName(idx,attrName);
-  }
-
-  /**
-   * Sets whether the features are sorted according to the
-   * domain attribute (before creating a {@link Dataset}).
-   */
-  @Override
-  public void setSortDomainAxis(boolean sortDomainAxis){
-    dummyFeatureChartStyle.setSortDomainAxis(sortDomainAxis);
-  }
-
-  /**
-   * Returns whether the features are sorted according to the
-   * domain attribute (before creating a {@link Dataset}).
-   * @return {@code false} as default
-   */
-  @Override
-  public boolean isSortDomainAxis() {
-    return dummyFeatureChartStyle.isSortDomainAxis();
-  }
-
-  /** 
-   * Sets whether a {@link CategoryDataset} is forced for
-   * a numeric domain attribute. The default is to create {@link XYDataset}
-   * for a numeric and {@link CategoryDataset} for a non-numeric domain
-   * attribute.
-   */
-  @Override
-  public void setForceCategories(boolean forceCategories){
-    dummyFeatureChartStyle.setForceCategories(forceCategories);
-  }
-
-  /** 
-   * Returns whether a {@link CategoryDataset} is forced for
-   * a numeric domain attribute. The default is to create {@link XYDataset}
-   * for a numeric and {@link CategoryDataset} for a non-numeric domain
-   * attribute.
-   * @return {@code false} as default
-   */
-  @Override
-  public boolean isForceCategories(){
-    return dummyFeatureChartStyle.isForceCategories();
-  }
-
-  /** 
-   * Sets whether the attribute data is normalized for an
-   * attribute(before creating a {@link Dataset}).
-   * @param idx attribute index (0=domain; 1=1st range series;
-   *            2=2nd range series; ...)
-   * @param normalize indicates the normalize property
-   */  
-  @Override
-  public void setAttributeNormalized(int idx, Boolean normalize){
-    dummyFeatureChartStyle.setAttributeNormalized(idx, normalize);
-  }
-
-  /** 
-   * Returns whether the attribute data is normalized for an
-   * attribute(before creating a {@link Dataset}).
-   * @param idx attribute index (0=domain; 1=1st range series;
-   *            2=2nd range series; ...)
-   * @return {@code false} as default
-   */  
-  @Override
-  public boolean isAttributeNormalized(int idx) {
-       return dummyFeatureChartStyle.isAttributeNormalized(idx);
-  }
-
-  /** 
-   * Sets an arithmetical function which is calculated on
-   * the attribute values (when creating a {@link Dataset}
-   * from Features).
-   * The function is calculated on all values with the same
-   * domain value (X/category). If no function is set, duplicate
-   * domain values are ignored (only the "last" value is shown, because
-   * of replacement behavior).
-   * @param idx attribute index (1=1st range series;
-   *            2=2nd range series; ...)
-   * @param func defines the calculated function
-   * @exception IllegalArgumentException if function is set on
-   *            domain attribute (0)
-   */  
-  @Override
-  public void setAttributeAggregation(int idx, AggregationFunction func) {
-    dummyFeatureChartStyle.setAttributeAggregation(idx, func);
-  }
-    
-  /** 
-   * Returns an arithmetical function which is calculated on
-   * the attribute values (when creating a {@link Dataset}
-   * from Features).
-   * The function is calculated on all values with the same
-   * domain value (X/category). If no function is set, duplicate
-   * domain values are ignored (only the "last" value is shown, because
-   * of replacement behavior).
-   * @param idx attribute index (1=1st range series;
-   *            2=2nd range series; ...)
-   * @return {@code null} for index 0 (domain axis)
-   */
-  @Override
-  public AggregationFunction getAttributeAggregation(int idx) {
-   return dummyFeatureChartStyle.getAttributeAggregation(idx); 
-  }
-
-  /**
-   * Sets the values, which are interpreted as "No Data". 
-   * @param idx attribute index the "No Data" values are set for
-   * @param noDataValues the "No Data" values
-   */
-  public void setNoDataValues(int idx, Set<Object> noDataValues) {
-    dummyFeatureChartStyle.setNoDataValues(idx, noDataValues);
-  }
-  
-  /**
-   * Returns the values, which are interpreted as "No Data". 
-   * @param idx attribute index the "No Data" values are returned for
-   */
-  public Set<Object> getNoDataValues(int idx) {
-    return dummyFeatureChartStyle.getNoDataValues(idx);
-  }
-  
-  /**
-   * Sets a value, which is interpreted as "No Data". 
-   * @param idx attribute index the "No Data" value is set for
-   * @param noDataValue the "No Data" value
-   */
-  public void addNoDataValue(int idx, Object noDataValue) {
-    dummyFeatureChartStyle.addNoDataValue(idx, noDataValue);
-  }
-
-  /**
-   * Removes a "No Data" value for an attribute. 
-   * @param idx attribute index the "No Data" value is removed for
-   * @param noDataValue the "No Data" value to remove
-   * @return {@code false} if the value was not an "No Data" value 
-   */
-  public boolean removeNoDataValue(int idx, Object noDataValue) {
-    return dummyFeatureChartStyle.removeNoDataValue(idx, noDataValue);
-  }
-
-  /**
-   * Checks whether the given value is one of the "No data" values for
-   * the attribute.
-   * @param idx attribute index the "No Data" value is checked for
-   * @param value an attribute value
-   */
-  public boolean isNoDataValue(int idx, Object value) {
-    return dummyFeatureChartStyle.isNoDataValue(idx, value);
-  }
-
-  /**
-   * Checks whether the given value is one of the "No data" values for
-   * the attribute. In this case this method returns {@code null}, otherwise
-   * the value itself.
-   * @param idx attribute index the "No Data" value is checked for
-   * @param value an attribute value
-   * @return {@code null} if the given value is one of the "No data" values 
-   */
-  public <T> T filterNoDataValue(int idx, T value) {
-    return dummyFeatureChartStyle.filterNoDataValue(idx, value);
-  }
-
-  /**
-   * Sets the feature attribute the i-th chart attribute is weighted with.<br>
-   * <b>Note:</b>
-   * <ul>
-   * <li>The weight attribute can not be set for the domain attribute 0.</li>
-   * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
-   * </ul>
-   * @param idx the feature attribute
-   * @param weightAttrName name of the weight attribute
-   * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
-   *      attribute.<br/>
-   * @exception IllegalArgumentException if weight attribute is set for
-   *              attribute 0
-   **/
-  @Override
-  public void setAttributeAggregationWeightAttributeName(int idx,
-      String weightAttrName) {
-    dummyFeatureChartStyle.setAttributeAggregationWeightAttributeName(idx, weightAttrName);
-  }
-
-  /**
-   * Returns the feature attribute the i-th chart attribute is weighted with.
-   * <b>Note:</b><br>
-   * This method returns {@code null} unless a
-   * {@linkplain AggregationFunction#isWeighted() weighted} aggregation
-   * function is set for the i-th attribute.
-   * @param idx the feature attribute
-   * @see #setAttributeAggregationWeightAttributeName(int, String)
-   **/
-  @Override
-  public String getAttributeAggregationWeightAttributeName(int idx) {
-    return dummyFeatureChartStyle.getAttributeAggregationWeightAttributeName(idx);
-  }
-
-  /**
-   * Sets the values, which are interpreted as "No Data" for the optional weight
-   * attribute.
-   * @param idx weight attribute index the "No Data" values are set for
-   * @param noDataValues the "No Data" values
-   */
-  @Override
-  public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues) {
-    dummyFeatureChartStyle.setWeightAttributeNoDataValues(idx, noDataValues);
-  }
-
-  /**
-   * Returns the values, which are interpreted as "No Data" for the
-   * weight attribute.
-   * @param idx weight attribute index the "No Data" values are returned for
-   */
-  @Override
-  public Set<Object> getWeightAttributeNoDataValues(int idx) {
-    return dummyFeatureChartStyle.getWeightAttributeNoDataValues(idx);
-  }
-
-  /**
-   * Sets a value, which is interpreted as "No Data" for the weight
-   * attribute.
-   * @param idx attribute index the "No Data" value is set for
-   * @param noDataValue the "No Data" value
-   */
-  @Override
-  public void addWeightAttributeNoDataValue(int idx, Object noDataValue) {
-    dummyFeatureChartStyle.addWeightAttributeNoDataValue(idx, noDataValue);
-  }
-
-  /**
-   * Removes a "No Data" value for a weight attribute.
-   * @param idx attribute index the "No Data" value is removed for
-   * @param noDataValue the "No Data" value to remove
-   * @return {@code false} if the value was not an "No Data" value
-   */
-  @Override
-  public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue) {
-    return dummyFeatureChartStyle.removeWeightAttributeNoDataValue(idx, noDataValue);
-  }
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * weight attribute.
-   * @param idx weight attribute index the "No Data" value is checked for
-   * @param value an attribute value
-   * @return {@code false} is not weight attribute is set for attribute i
-   * @see #setAttributeAggregationWeightAttributeName(int, String)
-   */
-  @Override
-  public boolean isWeightAttributeNoDataValue(int idx, Object value) {
-    return dummyFeatureChartStyle.isWeightAttributeNoDataValue(idx, value);
-  }
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * attribute. In this case this method returns {@code null}, otherwise the
-   * value itself.
-   * @param idx attribute index the "No Data" value is checked for
-   * @param value an attribute value
-   * @return {@code null} if the given value is one of the "No data" values
-   */
-  @Override
-  public <T> T filterWeightAttributeNoDataValue(int idx, T value) {
-    return dummyFeatureChartStyle.filterWeightAttributeNoDataValue(idx, value);
-  }
-
-  /**
-   * Defines the attribute whose values are used to define
-   * groups. For each group value a series is created in the chart
-   * dataset.
-   * @param attrName feature attribute name
-   */
-  @Override
-  public void setSeriesAttributeName(String attrName) {
-    dummyFeatureChartStyle.setSeriesAttributeName(attrName);
-  }
-  
-  /**
-   * Returns the attribute whose values are used to define
-   * groups. For each group value a series is created in the chart
-   * dataset.
-   */
-  @Override
-  public String getSeriesAttributeName() {
-    return dummyFeatureChartStyle.getSeriesAttributeName();
-  }
-
-  /**
-   * Sets the values, which are interpreted as "No Data" for the
-   * series attribute.
-   * @param noDataValues the "No Data" values
-   */
-  @Override
-  public void setSeriesAttributeNoDataValues(Set<Object> noDataValues) {
-    dummyFeatureChartStyle.setSeriesAttributeNoDataValues(noDataValues);
-  }
-
-  /**
-   * Returns the values, which are interpreted as "No Data" for the
-   * series attribute.
-   */
-  @Override
-  public Set<Object> getSeriesAttributeNoDataValues() {
-    return dummyFeatureChartStyle.getSeriesAttributeNoDataValues();
-  }
-
-  /**
-   * Sets a value, which is interpreted as "No Data" for the
-   * series attribute.
-   * @param noDataValue the "No Data" value
-   */
-  @Override
-  public void addSeriesAttributeNoDataValue(Object noDataValue) {
-    dummyFeatureChartStyle.addSeriesAttributeNoDataValue(noDataValue);
-  }
-
-  /**
-   * Removes a "No Data" value for the series attribute.
-   * @param noDataValue the "No Data" value to remove
-   * @return {@code false} if the value was not an "No Data" value
-   */
-  @Override
- public boolean removeSeriesAttributeNoDataValue(Object noDataValue) {
-    return dummyFeatureChartStyle.removeSeriesAttributeNoDataValue(noDataValue);
-  }
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * series attribute.
-   * @param value an attribute value
-   */
-  @Override
-  public boolean isSeriesAttributeNoDataValue(Object value) {
-    return dummyFeatureChartStyle.isSeriesAttributeNoDataValue(value);
-  }
-
-  /**
-   * Checks whether the given value is one of the "No data" values for the
-   * series attribute. In this case this method returns {@code null}, otherwise the
-   * value itself.
-   * @param value an attribute value
-   * @return {@code null} if the given value is one of the "No data" values
-   */
-  @Override
-  public <T> T filterSeriesAttributeNoDataValue(T value) {
-    return dummyFeatureChartStyle.filterSeriesAttributeNoDataValue(value);
-  }
-
-  /**
-   * Defines the attribute whose values are used to define the legend
-   * title for the series defined by {@link #setSeriesAttributeName(String)}.
-   * @param attrName feature attribute name
-   */
-  public void setSeriesLegendTitleAttributeName(String attrName) {
-    dummyFeatureChartStyle.setSeriesLegendTitleAttributeName(attrName);
-  }
-  
-  /**
-   * Returns the attribute whose values are used to define the legend
-   * title for the series defined by {@link #setSeriesAttributeName(String)}.
-   */
-  public String getSeriesLegendTitleAttributeName() {
-    return dummyFeatureChartStyle.getSeriesLegendTitleAttributeName();
-  }
-
-
-  /**
    * Creates an appropriate {@link Dataset} for the attributes defined
    * by this style (according to the attributes types in the given
    * {@link FeatureCollection}) and calls {@link #applyToDataset(Dataset)}.

Added: trunk/src/schmitzm/jfree/table/AggregationFunction.java
===================================================================
--- trunk/src/schmitzm/jfree/table/AggregationFunction.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/table/AggregationFunction.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -0,0 +1,134 @@
+package schmitzm.jfree.table;
+
+import schmitzm.jfree.JFreeChartUtil;
+import schmitzm.jfree.table.style.TableChartStyle;
+import schmitzm.lang.ResourceProvider;
+
+/**
+ * Defines possible aggregation function to calculate on attribute categories.
+ * @see TableChartStyle#setAttributeAggregation(int, AggregationFunction)
+ * @see TableChartStyle#getAttributeAggregation(int)
+ * @see optionally TableChartStyle#setNoDataWeightValues(int, java.util.Set))
+ * @see optionally
+ *      TableChartStyle#getAttributeAggregationWeightAttributeName(int)
+ */
+public enum AggregationFunction {
+
+  /** Count of the attribute values. */
+  COUNT(),
+  /** Sum of the attribute values. */
+  SUM(),
+  /** Sum of the absolute attribute values. */
+  SUM_ABS(true,false, false),
+  /** Weighted sum of the attribute values. Needs an attribute for weighting. */
+  SUM_WEIGHTED(false, true, false),
+  /** Average of the attribute values. */
+  AVG(),
+  /**
+   * Weighted average of the attribute values. Needs an attribute for weighting.
+   */
+  AVG_WEIGHTED(false, true, true),
+  /** Median of the attribute values. */
+  MEDIAN(),
+  /** Minimum attribute value. */
+  MIN(),
+  /** Maximum attribute value. */
+  MAX(),
+  /** Variance of the attribute values. */
+  VARIANCE(),
+  /** Standard deviation of the attribute values. */
+  STND_DEV();
+
+  // Indicates whether the attribute is must be transformed to positive
+  // values
+  private final boolean absoluted;
+  // Indicates whether the attribute is weighted with another attribute
+  private final boolean weighted;
+  // Indicates whether the attribute is weighted and averaged with the weight
+  // sum
+  private final boolean averaged;
+
+  /**
+   * Creates a default {@link Enum}, which is not absoluted, not weighted and
+   * not averaged.
+   */
+  private AggregationFunction() {
+    this(false,false,false);
+  }
+
+  /**
+   * Creates an {@link Enum} instance.
+   * @param absoluted Indicates whether the attribute is must be transformed to
+   *          positive values
+   * @param weighted Indicates whether the attribute is weighted with another
+   *          attribute
+   * @param averaged Indicates whether the attribute is weighted and averaged
+   *          with the weight sum (if averaged, weighted is automatically
+   *          implied!)
+   */
+  private AggregationFunction(boolean absoluted, boolean weighted,
+      boolean averaged) {
+    this.absoluted = absoluted;
+    this.weighted = weighted || averaged; // average implies weighted
+    this.averaged = averaged;
+  }
+
+  /**
+   * Returns <code>true</code>, if this aggregation method needs the
+   * absolute attribute value.
+   * @see Math#abs(double)
+   **/
+  public boolean isAbsoluted() {
+    return absoluted;
+  }
+
+  /**
+   * Returns <code>true</code>, if this aggregation method is used a second
+   * attribute for weighting.
+   **/
+  public boolean isWeighted() {
+    return weighted;
+  }
+
+  /**
+   * Returns <code>true</code>, if this aggregation method is used a second
+   * attribute for averaging.
+   **/
+  public boolean isAveraged() {
+    return averaged;
+  }
+
+  /**
+   * Prefix for the title (.TITLE) and description (.DESC) key in the resource
+   * bundle.
+   * @see #getTitle()
+   * @see #getDescription()
+   */
+  public final String RESOURCE_PREFIX = getClass().getSimpleName() + "." +
+                                        toString();
+
+  /**
+   * Returns a description of this kind of chart. Can be used for tool-tips. May
+   * return <code>null</code> if no localized String found.
+   */
+  public String getDescription() {
+    final String resource = JFreeChartUtil.R(RESOURCE_PREFIX + ".Desc");
+    if (resource == null ||
+        resource.equals(ResourceProvider.MISSING_RESOURCE_STRING))
+      return null;
+    return resource;
+  }
+
+  /**
+   * Returns a localized title of this kind of chart. If no localized string
+   * found, return the Enum.toString()
+   */
+  public String getTitle() {
+    final String resource = JFreeChartUtil.R(RESOURCE_PREFIX + ".Title");
+    if (resource == null ||
+        resource.equals(ResourceProvider.MISSING_RESOURCE_STRING))
+      return toString();
+    return resource;
+  }
+
+}

Added: trunk/src/schmitzm/jfree/table/AggregationFunctionJComboBox.java
===================================================================
--- trunk/src/schmitzm/jfree/table/AggregationFunctionJComboBox.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/table/AggregationFunctionJComboBox.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -0,0 +1,89 @@
+package schmitzm.jfree.table;
+
+import java.awt.Component;
+import java.awt.event.ItemEvent;
+
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+
+import schmitzm.jfree.JFreeChartUtil;
+import schmitzm.lang.LangUtil;
+import schmitzm.swing.SwingUtil;
+
+/**
+ * A {@link JComboBox} to select one {@link AggregationFunction}s. Can be
+ * initialized to also support a <code>null</code>.<br/>
+ * Note: Different from {@link JComboBox}, this does not fire events for DESELCTED events. 
+ * 
+ * @author SK
+ */
+public class AggregationFunctionJComboBox extends JComboBox {
+
+	/**
+	 * @param nullAlso
+	 *            if <code>true</code>, <code>null</code> will be the first item
+	 *            in the list.
+	 */
+	public AggregationFunctionJComboBox(boolean nullAlso) {
+		super(nullAlso ? LangUtil.extendArray(
+				new AggregationFunction[] { null }, AggregationFunction
+						.values()) : AggregationFunction.values());
+		setRenderer(listCellRenderer);
+		SwingUtil.addMouseWheelForCombobox(this, false);
+	}
+
+	/**
+	 * By default the <code>null</code> value is added.
+	 */
+	public AggregationFunctionJComboBox() {
+		this(true);
+	}
+	
+	/**
+	 * A static {@link DefaultListCellRenderer} that will render instances of
+	 * {@link AggregationFunction} with the title and description field as a
+	 * tooltip.<br/>
+	 * Any <code>null</code> value will also be rendered correctly.
+	 */
+	static ListCellRenderer listCellRenderer = new DefaultListCellRenderer() {
+
+		@Override
+		public Component getListCellRendererComponent(JList list, Object value,
+				int index, boolean isSelected, boolean cellHasFocus) {
+
+			Component proto = super.getListCellRendererComponent(list, value,
+					index, isSelected, cellHasFocus);
+
+			if (proto instanceof JLabel) {
+				JLabel jLabel = (JLabel) proto;
+
+				if (value instanceof AggregationFunction) {
+					jLabel.setText(((AggregationFunction) value).getTitle());
+					jLabel.setToolTipText(((AggregationFunction) value)
+							.getDescription());
+				} else if (value == null) {
+					jLabel.setText(JFreeChartUtil
+							.R("AggregationFunction.NONE.Title"));
+					jLabel.setToolTipText(JFreeChartUtil
+							.R("AggregationFunction.NONE.Desc"));
+				}
+			}
+
+			return proto;
+		}
+	};
+	
+	/**
+	 * The {@link JComboBox} does not fire events for DESELCTED event 
+	 */
+    @Override
+	protected void fireItemStateChanged(ItemEvent e) {
+    	if (e.getStateChange() == ItemEvent.DESELECTED) return;
+    	super.fireItemStateChanged(e);
+    }
+
+
+}

Added: trunk/src/schmitzm/jfree/table/style/TableBasicChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/table/style/TableBasicChartStyle.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/table/style/TableBasicChartStyle.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -0,0 +1,511 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Tzeggai - additional utility classes
+ ******************************************************************************/
+package schmitzm.jfree.table.style;
+
+import java.util.Set;
+
+import org.jfree.chart.JFreeChart;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.xy.XYDataset;
+
+import schmitzm.jfree.chart.style.BasicChartStyle;
+import schmitzm.jfree.chart.style.ChartStyle;
+import schmitzm.jfree.chart.style.ChartType;
+import schmitzm.jfree.table.AggregationFunction;
+
+/**
+ * This class extends the {@link BasicChartStyle} with the properties
+ * of the {@link TableChartStyle}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public abstract class TableBasicChartStyle<E> extends BasicChartStyle implements TableChartStyle<E> {
+	/** Used to maintain the {@link TableChartStyle} properties. */
+	protected Dummy<E> dummyTableChartStyle = null;
+
+	/**
+	 * Creates a normal line style with default values.
+	 * @param id a (unique) ID for the style
+	 */
+	public TableBasicChartStyle(String id) {
+		this(id, ChartType.LINE);
+	}
+
+	/**
+	 * Creates a normal, vertical line, bar or area style.
+	 * @param id   a (unique) ID for the style
+	 * @param type type of the chart layout
+	 */
+	public TableBasicChartStyle(String id, ChartType type) {
+		super(id, type);
+		dummyTableChartStyle = new Dummy<E>(id,-1);
+	}
+	
+    /**
+     * Copies all properties of this style to another one.
+     * @param dest destination object (if {@code null} the copy
+     *             is created by {@link #copy()})
+     * @return {@code dest} or the new instance
+     */
+    @Override
+    public ChartStyle copyTo(ChartStyle dest) {
+      // copy the super class properties
+      dest = super.copyTo(dest);
+      // copy this classes properties
+      if ( dest instanceof TableChartStyle )
+        dummyTableChartStyle.copyTo(dest);
+
+      return dest;
+    }
+
+    /**
+     * Removes all style informations about an attribute and
+     * reorganizes the attribute indexes so there is an continuous 
+     * order. 
+     * @param idx an attribute
+     */
+    @Override
+    public void removeAttribute(int idx) {
+      dummyTableChartStyle.removeAttribute(idx);
+    }
+
+    /**
+	 * Returns the maximum number of table attributes that can be
+	 * specified by this style.
+	 * @return always -1 which indicates no limit
+	 */
+	@Override
+	public int getMaxAttributeCount() {
+	  return dummyTableChartStyle.getMaxAttributeCount();
+	}
+
+    /**
+     * Returns the number of table attributes defined in this style.
+     */
+	@Override
+	public int getAttributeCount() {
+		return dummyTableChartStyle.getAttributeCount();
+	}
+
+	/**
+	 * Returns the name of a table attribute needed to create a
+	 * chart for this style.
+     * @param idx attribute index (0=domain; 1=1st range series;
+     *            2=2nd range series; ...)
+	 */
+    @Override
+	public String getAttributeName(int idx) {
+		return dummyTableChartStyle.getAttributeName(idx);
+	}
+
+	/**
+	 * Sets the name of a table attribute needed to create a
+	 * chart for this style.
+     * @param idx attribute index (0=domain; 1=1st range series;
+     *            2=2nd range series; ...)
+	 * @param attrName table attribute name 
+	 */
+	@Override
+	public void setAttributeName(int idx, String attrName) {
+		dummyTableChartStyle.setAttributeName(idx,attrName);
+	}
+
+
+	/**
+	 * Sets whether the table rows are sorted according to the
+	 * domain attribute (before creating a {@link Dataset}).
+	 */
+    @Override
+	public void setSortDomainAxis(boolean sortDomainAxis){
+	  dummyTableChartStyle.setSortDomainAxis(sortDomainAxis);
+	}
+
+	/**
+	 * Returns whether the table rows are sorted according to the
+	 * domain attribute (before creating a {@link Dataset}).
+     * @return {@code false} as default
+	 */
+    @Override
+	public boolean isSortDomainAxis() {
+	  return dummyTableChartStyle.isSortDomainAxis();
+	}
+
+	/** 
+	 * Sets whether a {@link CategoryDataset} is forced for
+	 * a numeric domain attribute. The default is to create {@link XYDataset}
+	 * for a numeric and {@link CategoryDataset} for a non-numeric domain
+	 * attribute.
+	 */
+    @Override
+	public void setForceCategories(boolean forceCategories){
+      dummyTableChartStyle.setForceCategories(forceCategories);
+	}
+
+	/** 
+	 * Returns whether a {@link CategoryDataset} is forced for
+	 * a numeric domain attribute. The default is to create {@link XYDataset}
+	 * for a numeric and {@link CategoryDataset} for a non-numeric domain
+	 * attribute.
+     * @return {@code false} as default
+	 */
+    @Override
+	public boolean isForceCategories(){
+      return dummyTableChartStyle.isForceCategories();
+	}
+
+    /** 
+     * Sets whether the attribute data is normalized for an
+     * attribute(before creating a {@link Dataset}).
+     * @param idx attribute index (0=domain; 1=1st range series;
+     *            2=2nd range series; ...)
+     * @param normalize indicates the normalize property
+     */  
+    @Override
+	public void setAttributeNormalized(int idx, Boolean normalize){
+	  dummyTableChartStyle.setAttributeNormalized(idx, normalize);
+	}
+
+    /** 
+     * Returns whether the attribute data is normalized for an
+     * attribute(before creating a {@link Dataset}).
+     * @param idx attribute index (0=domain; 1=1st range series;
+     *            2=2nd range series; ...)
+     * @return {@code false} as default
+     */  
+	@Override
+	public boolean isAttributeNormalized(int idx) {
+		return dummyTableChartStyle.isAttributeNormalized(idx);
+	}
+
+    /** 
+     * Sets an arithmetical function which is calculated on
+     * the attribute values (when creating a {@link Dataset}
+     * e.g. from Features).
+     * The function is calculated on all values with the same
+     * domain value (X/category). If no function is set, duplicate
+     * domain values are ignored (only the "last" value is shown, because
+     * of replacement behavior).
+     * @param idx attribute index (1=1st range series;
+     *            2=2nd range series; ...)
+     * @param func defines the calculated function
+     * @exception IllegalArgumentException if function is set on
+     *            domain attribute (0)
+     */  
+	@Override
+    public void setAttributeAggregation(int idx, AggregationFunction func) {
+      dummyTableChartStyle.setAttributeAggregation(idx, func);
+    }
+      
+    /** 
+     * Returns an arithmetical function which is calculated on
+     * the attribute values (when creating a {@link Dataset}
+     * e.g. from Features).
+     * The function is calculated on all values with the same
+     * domain value (X/category). If no function is set, duplicate
+     * domain values are ignored (only the "last" value is shown, because
+     * of replacement behavior).
+     * @param idx attribute index (1=1st range series;
+     *            2=2nd range series; ...)
+     * @return {@code null} for index 0 (domain axis)
+     */  
+    @Override
+    public AggregationFunction getAttributeAggregation(int idx) {
+     return dummyTableChartStyle.getAttributeAggregation(idx); 
+    }
+
+    /**
+     * Sets the values, which are interpreted as "No Data". 
+     * @param idx attribute index the "No Data" values are set for
+     * @param noDataValues the "No Data" values
+     */
+    public void setNoDataValues(int idx, Set<Object> noDataValues) {
+      dummyTableChartStyle.setNoDataValues(idx, noDataValues);
+    }
+    
+    /**
+     * Returns the values, which are interpreted as "No Data". 
+     * @param idx attribute index the "No Data" values are returned for
+     */
+    public Set<Object> getNoDataValues(int idx) {
+      return dummyTableChartStyle.getNoDataValues(idx);
+    }
+    
+    /**
+     * Sets a value, which is interpreted as "No Data". 
+     * @param idx attribute index the "No Data" value is set for
+     * @param noDataValue the "No Data" value
+     */
+    public void addNoDataValue(int idx, Object noDataValue) {
+      dummyTableChartStyle.addNoDataValue(idx, noDataValue);
+    }
+
+    /**
+     * Removes a "No Data" value for an attribute. 
+     * @param idx attribute index the "No Data" value is removed for
+     * @param noDataValue the "No Data" value to remove
+     * @return {@code false} if the value was not an "No Data" value 
+     */
+    public boolean removeNoDataValue(int idx, Object noDataValue) {
+      return dummyTableChartStyle.removeNoDataValue(idx, noDataValue);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for
+     * the attribute.
+     * @param idx attribute index the "No Data" value is checked for
+     * @param value an attribute value
+     */
+    public boolean isNoDataValue(int idx, Object value) {
+      return dummyTableChartStyle.isNoDataValue(idx, value);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for
+     * the attribute. In this case this method returns {@code null}, otherwise
+     * the value itself.
+     * @param idx attribute index the "No Data" value is checked for
+     * @param value an attribute value
+     * @return {@code null} if the given value is one of the "No data" values 
+     */
+    public <T> T filterNoDataValue(int idx, T value) {
+      return dummyTableChartStyle.filterNoDataValue(idx, value);
+    }
+
+    /**
+     * Sets the table attribute the i-th chart attribute is weighted with.<br>
+     * <b>Note:</b>
+     * <ul>
+     * <li>The weight attribute can not be set for the domain attribute 0.</li>
+     * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
+     * </ul>
+     * @param idx the table attribute
+     * @param weightAttrName name of the weight attribute
+     * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
+     *      attribute.<br/>
+     * @exception IllegalArgumentException if weight attribute is set for
+     *              attribute 0
+     **/
+    @Override
+    public void setAttributeAggregationWeightAttributeName(int idx,
+        String weightAttrName) {
+      dummyTableChartStyle.setAttributeAggregationWeightAttributeName(idx, weightAttrName);
+    }
+
+    /**
+     * Returns the table attribute the i-th chart attribute is weighted with.
+     * <b>Note:</b><br>
+     * This method returns {@code null} unless a
+     * {@linkplain AggregationFunction#isWeighted() weighted} aggregation
+     * function is set for the i-th attribute.
+     * @param idx the table attribute
+     * @see #setAttributeAggregationWeightAttributeName(int, String)
+     **/
+    @Override
+    public String getAttributeAggregationWeightAttributeName(int idx) {
+      return dummyTableChartStyle.getAttributeAggregationWeightAttributeName(idx);
+    }
+
+    /**
+     * Sets the values, which are interpreted as "No Data" for the optional weight
+     * attribute.
+     * @param idx weight attribute index the "No Data" values are set for
+     * @param noDataValues the "No Data" values
+     */
+    @Override
+    public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues) {
+      dummyTableChartStyle.setWeightAttributeNoDataValues(idx, noDataValues);
+    }
+
+    /**
+     * Returns the values, which are interpreted as "No Data" for the
+     * weight attribute.
+     * @param idx weight attribute index the "No Data" values are returned for
+     */
+    @Override
+    public Set<Object> getWeightAttributeNoDataValues(int idx) {
+      return dummyTableChartStyle.getWeightAttributeNoDataValues(idx);
+    }
+
+    /**
+     * Sets a value, which is interpreted as "No Data" for the weight
+     * attribute.
+     * @param idx attribute index the "No Data" value is set for
+     * @param noDataValue the "No Data" value
+     */
+    @Override
+    public void addWeightAttributeNoDataValue(int idx, Object noDataValue) {
+      dummyTableChartStyle.addWeightAttributeNoDataValue(idx, noDataValue);
+    }
+
+    /**
+     * Removes a "No Data" value for a weight attribute.
+     * @param idx attribute index the "No Data" value is removed for
+     * @param noDataValue the "No Data" value to remove
+     * @return {@code false} if the value was not an "No Data" value
+     */
+    @Override
+    public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue) {
+      return dummyTableChartStyle.removeWeightAttributeNoDataValue(idx, noDataValue);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * weight attribute.
+     * @param idx weight attribute index the "No Data" value is checked for
+     * @param value an attribute value
+     * @return {@code false} is not weight attribute is set for attribute i
+     * @see #setAttributeAggregationWeightAttributeName(int, String)
+     */
+    @Override
+    public boolean isWeightAttributeNoDataValue(int idx, Object value) {
+      return dummyTableChartStyle.isWeightAttributeNoDataValue(idx, value);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * attribute. In this case this method returns {@code null}, otherwise the
+     * value itself.
+     * @param idx attribute index the "No Data" value is checked for
+     * @param value an attribute value
+     * @return {@code null} if the given value is one of the "No data" values
+     */
+    @Override
+    public <T> T filterWeightAttributeNoDataValue(int idx, T value) {
+      return dummyTableChartStyle.filterWeightAttributeNoDataValue(idx, value);
+    }
+
+    /**
+     * Defines the attribute whose values are used to define
+     * groups. For each group value a series is created in the chart
+     * dataset.
+     * @param attrName table attribute name
+     */
+    @Override
+    public void setSeriesAttributeName(String attrName) {
+      dummyTableChartStyle.setSeriesAttributeName(attrName);
+    }
+    
+    /**
+     * Returns the attribute whose values are used to define
+     * groups. For each group value a series is created in the chart
+     * dataset.
+     */
+    @Override
+    public String getSeriesAttributeName() {
+      return dummyTableChartStyle.getSeriesAttributeName();
+    }
+
+    /**
+     * Sets the values, which are interpreted as "No Data" for the
+     * series attribute.
+     * @param noDataValues the "No Data" values
+     */
+    @Override
+    public void setSeriesAttributeNoDataValues(Set<Object> noDataValues) {
+      dummyTableChartStyle.setSeriesAttributeNoDataValues(noDataValues);
+    }
+
+    /**
+     * Returns the values, which are interpreted as "No Data" for the
+     * series attribute.
+     */
+    @Override
+    public Set<Object> getSeriesAttributeNoDataValues() {
+      return dummyTableChartStyle.getSeriesAttributeNoDataValues();
+    }
+
+    /**
+     * Sets a value, which is interpreted as "No Data" for the
+     * series attribute.
+     * @param noDataValue the "No Data" value
+     */
+    @Override
+    public void addSeriesAttributeNoDataValue(Object noDataValue) {
+      dummyTableChartStyle.addSeriesAttributeNoDataValue(noDataValue);
+    }
+
+    /**
+     * Removes a "No Data" value for the series attribute.
+     * @param noDataValue the "No Data" value to remove
+     * @return {@code false} if the value was not an "No Data" value
+     */
+    @Override
+   public boolean removeSeriesAttributeNoDataValue(Object noDataValue) {
+      return dummyTableChartStyle.removeSeriesAttributeNoDataValue(noDataValue);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * series attribute.
+     * @param value an attribute value
+     */
+    @Override
+    public boolean isSeriesAttributeNoDataValue(Object value) {
+      return dummyTableChartStyle.isSeriesAttributeNoDataValue(value);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * series attribute. In this case this method returns {@code null}, otherwise the
+     * value itself.
+     * @param value an attribute value
+     * @return {@code null} if the given value is one of the "No data" values
+     */
+    @Override
+    public <T> T filterSeriesAttributeNoDataValue(T value) {
+      return dummyTableChartStyle.filterSeriesAttributeNoDataValue(value);
+    }
+
+    /**
+     * Defines the attribute whose values are used to define the legend
+     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+     * @param attrName table attribute name
+     */
+    public void setSeriesLegendTitleAttributeName(String attrName) {
+      dummyTableChartStyle.setSeriesLegendTitleAttributeName(attrName);
+    }
+    
+    /**
+     * Returns the attribute whose values are used to define the legend
+     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+     */
+    public String getSeriesLegendTitleAttributeName() {
+      return dummyTableChartStyle.getSeriesLegendTitleAttributeName();
+    }
+
+    /**
+     * Creates a chart according to the given table data.
+     * @param table the table
+     * @exception UnsupportedOperationException if the style can not be applied to
+     *            the table
+     */
+    @Override
+    public abstract JFreeChart applyToTable(E table);
+}

Added: trunk/src/schmitzm/jfree/table/style/TableChartAxisStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/table/style/TableChartAxisStyle.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/table/style/TableChartAxisStyle.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Tzeggai - additional utility classes
+ ******************************************************************************/
+
+package schmitzm.jfree.table.style;
+
+import java.awt.Color;
+
+import org.jfree.chart.axis.Axis;
+
+import schmitzm.jfree.JFreeChartUtil;
+import schmitzm.jfree.chart.style.ChartAxisStyle;
+import schmitzm.lang.LangUtil;
+import skrueger.i8n.Translation;
+
+/**
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ *
+ */
+public class TableChartAxisStyle extends ChartAxisStyle {
+  /** Holds the {@link TableChartStyle} the axis is connected to. */
+  protected TableChartStyle<?> chartStyle = null;
+  
+  /**
+   * Creates a new style with default values (empty label, color black, angle 0).
+   * @param chartStyle the chart style the axis is connected to
+   */
+  public TableChartAxisStyle(TableChartStyle<?> chartStyle) {
+    this(chartStyle,"",Color.black,0.0,0.0);
+  }
+
+  /**
+   * Creates a new style.
+   * @param chartStyle the chart style the axis is connected to
+   * @param title axis title
+   * @param color text color for the axis title
+   * @param labelAngle angel (in degrees) the axis label is rotated by
+   * @param valuesAngle angel (in degrees) the axis values are rotated by
+   */
+  public TableChartAxisStyle(TableChartStyle<?> chartStyle, String title, Color color, Double labelAngle, Double valuesAngle) {
+    super(title, color, labelAngle, valuesAngle);
+    this.chartStyle = chartStyle; 
+  }
+
+  /**
+   * Creates a new style.
+   * @param chartStyle the chart style the axis is connected to
+   * @param title axis title as an internationalized {@link Translation} 
+   * @param color text color for the axis title
+   * @param labelAngle angel (in degrees) the axis label is rotated by
+   * @param valuesAngle angel (in degrees) the axis values are rotated by
+   */
+  public TableChartAxisStyle(TableChartStyle<?> chartStyle, Translation title, Color color, Double labelAngle, Double valuesAngle) {
+    super(title, color, labelAngle, valuesAngle);
+    this.chartStyle = chartStyle; 
+  }
+  
+  /**
+   * Creates a (deep) clone of this style.
+   */
+  @Override
+  public TableChartAxisStyle copy() {
+    return (TableChartAxisStyle)copyTo( new TableChartAxisStyle(null) );
+  }
+
+  /**
+   * Returns the chart style, the axis is connected to.
+   */
+  public TableChartStyle<?> getChartStyle() {
+    return chartStyle;
+  }
+
+  /**
+   * Sets the chart style, the axis is connected to.
+   */
+  public void setChartStyle(TableChartStyle<?> style) {
+    chartStyle = style;
+  }
+  
+  /**
+   * Applies the style to a specific axis.<br>
+   * Note: Some style properties can only be applied to specific axis types.
+   * @param axis an axis
+   */
+  @Override
+  public void applyToAxis(Axis axis) {
+    super.applyToAxis(axis);
+    if (axis == null) {
+      return;
+    }
+
+    // Determine the unit, aggregation function title and normalization
+    // to display with the axis title
+    String unitStr = isUnitVisible() ? getUnitString() : null;
+    String funcStr = null;
+    String normStr = null; 
+    for (int i=0; i<chartStyle.getAxisCount(); i++)
+      if ( chartStyle.getAxisStyle(i) == this ) {
+        // ToDo: ??? von welchem Attribut die Aggr.Function und
+        //       Normalisierung verwenden. Ist 'i' richtig?
+        if ( chartStyle.getAttributeAggregation(i) != null )
+          funcStr = chartStyle.getAttributeAggregation(i).getTitle();
+        if ( chartStyle.isAttributeNormalized(i) )
+          normStr = JFreeChartUtil.R("FeatureChartAxisStyle.normalized");
+        break;
+      }
+    
+    // If unit, function or normalization is set, add it to axis title
+    String axisLabel = getLabel();
+    String unitLabel = LangUtil.listString(", ",unitStr,funcStr,normStr);
+    if ( unitLabel != null && !"".equals(unitLabel) )
+      axisLabel += " ["+unitLabel.trim()+"]";
+    axis.setLabel( axisLabel );
+  }
+
+}

Added: trunk/src/schmitzm/jfree/table/style/TableChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/table/style/TableChartStyle.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/table/style/TableChartStyle.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -0,0 +1,1063 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Tzeggai - additional utility classes
+ ******************************************************************************/
+package schmitzm.jfree.table.style;
+
+import java.sql.ResultSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.geotools.feature.FeatureCollection;
+import org.jfree.chart.JFreeChart;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.xy.XYDataset;
+
+import schmitzm.jfree.chart.style.AbstractChartStyle;
+import schmitzm.jfree.chart.style.ChartStyle;
+import schmitzm.jfree.table.AggregationFunction;
+import schmitzm.lang.LangUtil;
+
+/**
+ * This interface extends the chart style with several functionalities used to
+ * define a chart on "some abstract kind table", whose columns are defined by
+ * attributes. The kind of table ({@link FeatureCollection}, {@link ResultSet}, ...)
+ * is specified by the several sub classes.
+ * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
+ * @version 1.0
+ */
+public interface TableChartStyle<E> extends ChartStyle {
+
+  /**
+   * Returns the maximum number of attributes that can be specified by
+   * this style.
+   * @return -1 if there is no limit for range attributes
+   */
+  public int getMaxAttributeCount();
+
+  /**
+   * Returns the number of attributes defined in this style.
+   */
+  public int getAttributeCount();
+
+  /**
+   * Removes all style informations about an attribute and reorganizes the
+   * attribute indexes so there is an continuous order.
+   * @param idx an attribute index
+   */
+  public void removeAttribute(int idx);
+
+  /**
+   * Returns the name of a attribute needed to create a chart for this
+   * style.
+   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+   *          series; ...)
+   */
+  public String getAttributeName(int idx);
+
+  /**
+   * Sets the name of a attribute needed to create a chart for this
+   * style.
+   * @see #setNoDataValues(idx, Set) to set NoDataValues for this attribute.
+   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+   *          series; ...)
+   * @param attrName attribute name
+   */
+  public void setAttributeName(int idx, String attrName);
+
+  /**
+   * Sets whether the table rows are sorted according to the domain attribute
+   * (before creating a {@link Dataset}).
+   */
+  public void setSortDomainAxis(boolean sort);
+
+  /**
+   * Returns whether the table rows are sorted according to the domain attribute
+   * (before creating a {@link Dataset}).
+   * @return {@code false} as default
+   */
+  public boolean isSortDomainAxis();
+
+  /**
+   * Sets whether a {@link CategoryDataset} is forced for a numeric domain
+   * attribute. The default is to create {@link XYDataset} for a numeric and
+   * {@link CategoryDataset} for a non-numeric domain attribute.
+   */
+  public void setForceCategories(boolean forceCategories);
+
+  /**
+   * Returns whether a {@link CategoryDataset} is forced for a numeric domain
+   * attribute. The default is to create {@link XYDataset} for a numeric and
+   * {@link CategoryDataset} for a non-numeric domain attribute.
+   * @return {@code false} as default
+   */
+  public boolean isForceCategories();
+
+  /**
+   * Sets whether the attribute data is normalized for an attribute (before
+   * creating a {@link Dataset}).
+   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+   *          series; ...)
+   * @param normalize indicates the normalize property
+   */
+  public void setAttributeNormalized(int idx, Boolean normalize);
+
+  /**
+   * Returns whether the attribute data is normalized for an attribute (before
+   * creating a {@link Dataset}).
+   * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+   *          series; ...)
+   * @return {@code false} as default
+   */
+  public boolean isAttributeNormalized(int idx);
+
+  /**
+   * Sets an arithmetical function which is calculated on the attribute values
+   * (when creating a {@link Dataset} e.g. from Features). The function is calculated
+   * on all values with the same domain value (X/category). If no function is
+   * set, duplicate domain values are ignored (only the "last" value is shown,
+   * because of replacement behavior).
+   * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
+   * @param func defines the calculated function
+   * @exception IllegalArgumentException if function is set on domain attribute
+   *              (0)
+   */
+  public void setAttributeAggregation(int idx, AggregationFunction func);
+
+  /**
+   * Returns an arithmetical function which is calculated on the attribute
+   * values (when creating a {@link Dataset} e.g. from Features). The function is
+   * calculated on all values with the same domain value (X/category). If no
+   * function is set, duplicate domain values are ignored (only the "last" value
+   * is shown, because of replacement behavior).
+   * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
+   * @return {@code null} for index 0 (domain axis)
+   */
+  public AggregationFunction getAttributeAggregation(int idx);
+
+  /**
+   * Sets the values, which are interpreted as "No Data".
+   * @param idx attribute index the "No Data" values are set for
+   * @param noDataValues the "No Data" values
+   */
+  public void setNoDataValues(int idx, Set<Object> noDataValues);
+
+  /**
+   * Returns the values, which are interpreted as "No Data".
+   * @param idx attribute index the "No Data" values are returned for
+   */
+  public Set<Object> getNoDataValues(int idx);
+
+  /**
+   * Sets a value, which is interpreted as "No Data".
+   * @param idx attribute index the "No Data" value is set for
+   * @param noDataValue the "No Data" value
+   */
+  public void addNoDataValue(int idx, Object noDataValue);
+
+  /**
+   * Removes a "No Data" value for an attribute.
+   * @param idx attribute index the "No Data" value is removed for
+   * @param noDataValue the "No Data" value to remove
+   * @return {@code false} if the value was not an "No Data" value
+   */
+  public boolean removeNoDataValue(int idx, Object noDataValue);
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * attribute.
+   * @param idx attribute index the "No Data" value is checked for
+   * @param value an attribute value
+   */
+  public boolean isNoDataValue(int idx, Object value);
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * attribute. In this case this method returns {@code null}, otherwise the
+   * value itself.
+   * @param idx attribute index the "No Data" value is checked for
+   * @param value an attribute value
+   * @return {@code null} if the given value is one of the "No data" values
+   */
+  public <T> T filterNoDataValue(int idx, T value);
+
+  /**
+   * Sets the table attribute the i-th chart attribute is weighted with.<br>
+   * <b>Note:</b>
+   * <ul>
+   * <li>The weight attribute can not be set for the domain attribute 0.</li>
+   * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
+   * </ul>
+   * @param idx the table attribute
+   * @param weightAttribName name of the weight attribute
+   * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
+   *      attribute.<br/>
+   * @exception IllegalArgumentException if weight attribute is set for
+   *              attribute 0
+   **/
+  public void setAttributeAggregationWeightAttributeName(int idx,
+      String weightAttribName);
+
+  /**
+   * Returns the table attribute the i-th chart attribute is weighted with.
+   * <b>Note:</b><br>
+   * This method returns {@code null} unless a
+   * {@linkplain AggregationFunction#isWeighted() weighted} aggregation function
+   * is set for the i-th attribute.
+   * @param idx the table attribute
+   * @see #setAttributeAggregationWeightAttributeName(int, String)
+   **/
+  public String getAttributeAggregationWeightAttributeName(int idx);
+
+  /**
+   * Sets the values, which are interpreted as "No Data" for the optional weight
+   * attribute.
+   * @param idx weight attribute index the "No Data" values are set for
+   * @param noDataValues the "No Data" values
+   */
+  public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues);
+
+  /**
+   * Returns the values, which are interpreted as "No Data" for the
+   * weight attribute.
+   * @param idx weight attribute index the "No Data" values are returned for
+   */
+  public Set<Object> getWeightAttributeNoDataValues(int idx);
+
+  /**
+   * Sets a value, which is interpreted as "No Data" for the weight
+   * attribute.
+   * @param idx attribute index the "No Data" value is set for
+   * @param noDataValue the "No Data" value
+   */
+  public void addWeightAttributeNoDataValue(int idx, Object noDataValue);
+
+  /**
+   * Removes a "No Data" value for a weight attribute.
+   * @param idx attribute index the "No Data" value is removed for
+   * @param noDataValue the "No Data" value to remove
+   * @return {@code false} if the value was not an "No Data" value
+   */
+  public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue);
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * weight attribute.
+   * @param idx weight attribute index the "No Data" value is checked for
+   * @param value an attribute value
+   * @return {@code false} is not weight attribute is set for attribute i
+   * @see #setAttributeAggregationWeightAttributeName(int, String)
+   */
+  public boolean isWeightAttributeNoDataValue(int idx, Object value);
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * attribute. In this case this method returns {@code null}, otherwise the
+   * value itself.
+   * @param idx attribute index the "No Data" value is checked for
+   * @param value an attribute value
+   * @return {@code null} if the given value is one of the "No data" values
+   */
+  public <T> T filterWeightAttributeNoDataValue(int idx, T value);
+
+  /**
+   * Defines the attribute whose values are used to define
+   * groups. For each group value a series is created in the chart
+   * dataset.
+   * @param attrName attribute name
+   */
+  public void setSeriesAttributeName(String attrName);
+  
+  /**
+   * Returns the attribute whose values are used to define
+   * groups. For each group value a series is created in the chart
+   * dataset.
+   */
+  public String getSeriesAttributeName();
+
+  /**
+   * Sets the values, which are interpreted as "No Data" for the
+   * series attribute.
+   * @param noDataValues the "No Data" values
+   */
+  public void setSeriesAttributeNoDataValues(Set<Object> noDataValues);
+
+  /**
+   * Returns the values, which are interpreted as "No Data" for the
+   * series attribute.
+   */
+  public Set<Object> getSeriesAttributeNoDataValues();
+
+  /**
+   * Sets a value, which is interpreted as "No Data" for the
+   * series attribute.
+   * @param noDataValue the "No Data" value
+   */
+  public void addSeriesAttributeNoDataValue(Object noDataValue);
+
+  /**
+   * Removes a "No Data" value for the series attribute.
+   * @param noDataValue the "No Data" value to remove
+   * @return {@code false} if the value was not an "No Data" value
+   */
+  public boolean removeSeriesAttributeNoDataValue(Object noDataValue);
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * series attribute.
+   * @param value an attribute value
+   */
+  public boolean isSeriesAttributeNoDataValue(Object value);
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * series attribute. In this case this method returns {@code null}, otherwise the
+   * value itself.
+   * @param value an attribute value
+   * @return {@code null} if the given value is one of the "No data" values
+   */
+  public <T> T filterSeriesAttributeNoDataValue(T value);
+
+  /**
+   * Defines the attribute whose values are used to define the legend
+   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+   * @param attrName attribute name
+   */
+  public void setSeriesLegendTitleAttributeName(String attrName);
+  
+  /**
+   * Returns the attribute whose values are used to define the legend
+   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+   */
+  public String getSeriesLegendTitleAttributeName();
+
+  /**
+   * Creates a chart according to the given table data.
+   * @param table the table
+   * @exception UnsupportedOperationException if the style can not be applied to
+   *              the table
+   */
+  public JFreeChart applyToTable(E table);
+
+  /**
+   * This class defines a dummy implementation of {@link TableChartStyle} just
+   * to maintain the properties of the interface {@link TableChartStyle}, so
+   * sub classes of {@link TableChartStyle} which usually are derived from a
+   * normal {@link ChartStyle} implementation must not implement the
+   * {@link TableChartStyle} maintenance each. Instead they can create an
+   * instance of this dummy an pipe their method implementations to the dummy!<br>
+   * <br>
+   * The {@link #applyToTable(E)} and {@link #applyToDataset(Dataset)}
+   * methods are not implemented by the dummy, but throw an exception instead!!
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+   */
+  public static class Dummy<E> extends AbstractChartStyle implements TableChartStyle<E> {
+    /**
+     * Indicates whether the table rows are sorted according to the domain
+     * attribute (before creating a {@link Dataset}).
+     */
+    protected boolean sortDomainAxis;
+    /**
+     * Indicates whether a {@link CategoryDataset} is forced for a numeric
+     * domain attribute. The default is to create {@link XYDataset} for a
+     * numeric and {@link CategoryDataset} for a non-numeric domain attribute.
+     */
+    protected boolean forceCategories;
+
+    /**
+     * Holds the attributes needed to specify the chart data from table data
+     * (0 = attribute for domain axis; others assigned to the range
+     * axis as series).
+     */
+    protected Map<Integer, String> attrNames = new HashMap<Integer, String>();
+
+    /**
+     * Indicates for each attribute whether the attribute data is normalized
+     * (before creating a {@link Dataset}).
+     */
+    protected Map<Integer, Boolean> normalizeAttr = new HashMap<Integer, Boolean>();
+
+    /**
+     * Holds the maximum number of attributes the style can be defined defined
+     * for (-1 = no limit).
+     */
+    protected int maxAttrCount = -1;
+
+    /** Holds the number of attributes the style is defined for. */
+    protected int maxAttrIdx = 0;
+
+    /** Holds the "No Data" values for each attribute. */
+    protected Map<Integer, Set<Object>> noDataValues = new HashMap<Integer, Set<Object>>();
+
+    /** Holds the aggregation function for each attribute. */
+    protected Map<Integer, AggregationFunction> aggrFuncs = new HashMap<Integer, AggregationFunction>();
+
+    /**
+     * Holds the weight attributes needed to weight the attribute values of
+     * {@link #attrNames} if a {@linkplain AggregationFunction#isWeighted()
+     * weighted} aggregation function is set.
+     */
+    protected Map<Integer, String> weightAttrNames = new HashMap<Integer, String>();
+
+    /** Holds the "No Data" values for each weight attribute. */
+    protected Map<Integer, Set<Object>> weightAttrNoDataValues = new HashMap<Integer, Set<Object>>();
+
+    
+    /**
+     * Holds the attribute name of the series attribute, whose values are
+     * used to define groups. For each group a series is created in the
+     * dataset.
+     */
+    protected String seriesAttrName = null;
+
+    /** Holds the "No Data" values for the series attribute. */
+    protected Set<Object> seriesAttrNoDataValues = new HashSet<Object>();
+
+    /**
+     * Holds the name of the attribute, whose values define the legend
+     * title for the series defined by {@link #seriesAttrName}.
+     */
+    protected String seriesLegendTitleAttrName = null;
+
+    /**
+     * Creates a new dummy. This constructor is protected so that only derived
+     * classes can instantiate a dummy! There is no limit for the number of
+     * attributes which can be defined by the style.
+     * @param id a (unique) ID for the style
+     */
+    protected Dummy(String id) {
+      this(id, -1);
+    }
+
+    /**
+     * Creates a new dummy. This constructor is protected so that only derived
+     * classes can instantiate a dummy!
+     * @param id a (unique) ID for the style
+     * @param maxAttrCount attribute count needed to specify the chart data from
+     *          table data
+     */
+    protected Dummy(String id, int maxAttrCount) {
+      super(id);
+      this.maxAttrCount = maxAttrCount;
+    }
+
+    /**
+     * Updates the local variable for the number of attributes the maximum index
+     * (key) of the several hash maps.
+     */
+    private void updateAttributeCount() {
+      maxAttrIdx = LangUtil.max(attrNames.keySet(),
+                                normalizeAttr.keySet(),
+                                noDataValues.keySet(),
+                                aggrFuncs.keySet(),
+                                weightAttrNames.keySet(),
+                                weightAttrNoDataValues.keySet()
+      );
+
+      if (maxAttrCount > 0 && maxAttrIdx >= maxAttrCount)
+        throw new IllegalArgumentException("Only " + maxAttrCount +
+                                           " attributes can be specified for " +
+                                           LangUtil.getSimpleClassName(this));
+    }
+
+    /**
+     * Removes all style informations about an attribute and reorganizes the
+     * attribute indexes so there is an continuous order.
+     * @param idx an attribute
+     */
+    @Override
+    public void removeAttribute(int idx) {
+      // clear sets and maps of the removed attribute
+      Set<Object> noDataValues = getNoDataValues(idx);
+      if (noDataValues != null)
+        noDataValues.clear();
+
+      // remove the attribute by move the "greater" attributes
+      // one position "forward"
+      int maxIdx = getAttributeCount() - 1;
+      for (int i = idx; i < maxIdx; i++) {
+        this.attrNames.put(i, this.attrNames.get(i + 1));
+        this.normalizeAttr.put(i, this.normalizeAttr.get(i + 1));
+        this.noDataValues.put(i, this.noDataValues.get(i + 1));
+      }
+
+      // delete the last attribute, because now is is stored
+      // one position forward
+      this.attrNames.remove(maxIdx);
+      this.normalizeAttr.remove(maxIdx);
+      this.noDataValues.remove(maxIdx);
+
+      updateAttributeCount();
+    }
+
+    /**
+     * Creates a (deep) clone of this style. The properties of the super class (
+     * {@link AbstractChartStyle}) are <b>ignored</b> because they are unused
+     * for the dummy.
+     */
+    @Override
+    public AbstractChartStyle copy() {
+      return (AbstractChartStyle) copyTo((TableChartStyle) new Dummy(""));
+    }
+
+    /**
+     * Copies all properties of this style to another one. The properties of the
+     * super class ({@link AbstractChartStyle}) are <b>ignored</b> because they
+     * are unused for the dummy.
+     * @param dest destination object (if {@code null} the copy is created by
+     *          {@link #copy()})
+     * @return {@code dest} or the new instance
+     */
+    @Override
+    public ChartStyle copyTo(ChartStyle dest) {
+      // !! do NOT copy the super class properties !!
+      // !! copy only this classes properties !!
+      // !! Reason: the dummy does not maintain the !!
+      // !! super class properties and we !!
+      // !! do not want to overwrite them !!
+      if (dest instanceof TableChartStyle) {
+        TableChartStyle destFCS = (TableChartStyle) dest;
+        destFCS.setSortDomainAxis(isSortDomainAxis());
+        destFCS.setForceCategories(isForceCategories());
+
+        // Clear the attribute names, normalization, aggregation,
+        // etc.
+        // NOTE: The no data value set must NOT be cleared deep,
+        //       because these sets may originate from somewhere else!
+        //       So only the hash entry is set to NULL.
+        int max = destFCS.getMaxAttributeCount();
+        for (int i = 0; i < max; i++) {
+          destFCS.setAttributeName(i, null);
+          destFCS.setAttributeNormalized(i, null);
+          destFCS.setAttributeAggregation(i, null);
+          destFCS.setAttributeAggregationWeightAttributeName(i, null);
+          destFCS.setNoDataValues(i, null);
+          destFCS.setWeightAttributeNoDataValues(i, null);
+        }
+        
+        // Copy attribute names, normalization, aggregation, etc.
+        for (Integer idx : attrNames.keySet())
+          if (getAttributeName(idx) != null)
+            destFCS.setAttributeName(idx, getAttributeName(idx));
+        for (Integer idx : normalizeAttr.keySet())
+          if (isAttributeNormalized(idx))
+            destFCS.setAttributeNormalized(idx, isAttributeNormalized(idx));
+        for (Integer idx : aggrFuncs.keySet())
+          destFCS.setAttributeAggregation(idx, getAttributeAggregation(idx));
+        for (Integer idx : weightAttrNames.keySet())
+          destFCS.setAttributeAggregationWeightAttributeName(idx, getAttributeAggregationWeightAttributeName(idx));
+        
+        // The nodata value set are not copies deep, because these
+        // sets may originate from somewhere else, so the only
+        // are "redirected".
+        for (Integer idx : noDataValues.keySet())
+          destFCS.setNoDataValues(idx, getNoDataValues(idx));
+        for (Integer idx : weightAttrNoDataValues.keySet())
+          destFCS.setNoDataValues(idx, getWeightAttributeNoDataValues(idx));
+      }
+
+      return dest;
+    }
+
+    /**
+     * Returns the maximum number of attributes that can be specified by
+     * this style.
+     * @return -1 if there is no limit for range attributes
+     */
+    @Override
+    public int getMaxAttributeCount() {
+      return maxAttrCount;
+    }
+
+    /**
+     * Returns the number of attributes defined in this style.
+     */
+    @Override
+    public int getAttributeCount() {
+      return maxAttrIdx + 1;
+    }
+
+    /**
+     * Returns the name of a table attribute needed to create a chart for this
+     * style.
+     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+     *          series; ...)
+     */
+    @Override
+    public String getAttributeName(int idx) {
+      return attrNames.get(idx);
+    }
+
+    /**
+     * Sets the name of a table attribute needed to create a chart for this
+     * style.
+     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+     *          series; ...)
+     * @param attrName table attribute name
+     */
+    @Override
+    public void setAttributeName(int idx, String attrName) {
+      attrNames.put(idx, attrName);
+      updateAttributeCount();
+    }
+
+    /**
+     * Sets whether the table rows are sorted according to the domain attribute
+     * (before creating a {@link Dataset}).
+     */
+    @Override
+    public void setSortDomainAxis(boolean sortDomainAxis) {
+      this.sortDomainAxis = sortDomainAxis;
+    }
+
+    /**
+     * Returns whether the table rows are sorted according to the domain attribute
+     * (before creating a {@link Dataset}).
+     * @return {@code false} as default
+     */
+    @Override
+    public boolean isSortDomainAxis() {
+      return sortDomainAxis;
+    }
+
+    /**
+     * Sets whether a {@link CategoryDataset} is forced for a numeric domain
+     * attribute. The default is to create {@link XYDataset} for a numeric and
+     * {@link CategoryDataset} for a non-numeric domain attribute.
+     */
+    @Override
+    public void setForceCategories(boolean forceCategories) {
+      this.forceCategories = forceCategories;
+    }
+
+    /**
+     * Returns whether a {@link CategoryDataset} is forced for a numeric domain
+     * attribute. The default is to create {@link XYDataset} for a numeric and
+     * {@link CategoryDataset} for a non-numeric domain attribute.
+     * @return {@code false} as default
+     */
+    @Override
+    public boolean isForceCategories() {
+      return forceCategories;
+    }
+
+    /**
+     * Sets whether the attribute data is normalized for an attribute (before
+     * creating a {@link Dataset}).
+     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+     *          series; ...)
+     * @param normalize indicates the normalize property
+     */
+    @Override
+    public void setAttributeNormalized(int idx, Boolean normalize) {
+      normalizeAttr.put(idx, normalize);
+      updateAttributeCount();
+    }
+
+    /**
+     * Returns whether the attribute data is normalized for an attribute (before
+     * creating a {@link Dataset}).
+     * @param idx attribute index (0=domain; 1=1st range series; 2=2nd range
+     *          series; ...)
+     * @return {@code false} as default
+     */
+    @Override
+    public boolean isAttributeNormalized(int idx) {
+      Boolean normalize = normalizeAttr.get(idx);
+      return normalize != null && normalize;
+    }
+
+    /**
+     * Sets an arithmetical function which is calculated on the attribute values
+     * (when creating a {@link Dataset} e.g. from Features). The function is
+     * calculated on all values with the same domain value (X/category). If no
+     * function is set, duplicate domain values are ignored (only the "last"
+     * value is shown, because of replacement behavior).
+     * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
+     * @param func defines the calculated function
+     * @exception IllegalArgumentException if function is set on domain
+     *              attribute (0)
+     */
+    @Override
+    public void setAttributeAggregation(int idx, AggregationFunction func) {
+      if (idx == 0 && func != null)
+        throw new IllegalArgumentException(
+            "Aggregation function not allowed for attribute 0 (domain attribute)!");
+      aggrFuncs.put(idx, func);
+    }
+
+    /**
+     * Returns an arithmetical function which is calculated on the attribute
+     * values (when creating a {@link Dataset} e.g. from Features). The function is
+     * calculated on all values with the same domain value (X/category). If no
+     * function is set, duplicate domain values are ignored (only the "last"
+     * value is shown, because of replacement behavior).
+     * @param idx attribute index (1=1st range series; 2=2nd range series; ...)
+     * @return {@code null} for index 0 (domain axis)
+     */
+    @Override
+    public AggregationFunction getAttributeAggregation(int idx) {
+      if (idx == 0)
+        return null;
+      return aggrFuncs.get(idx);
+    }
+
+    /**
+     * Sets the values, which are interpreted as "No Data".
+     * @param idx attribute index the "No Data" values are set for
+     * @param noDataValues the "No Data" values
+     */
+    public void setNoDataValues(int idx, Set<Object> noDataValues) {
+      this.noDataValues.put(idx, noDataValues);
+      updateAttributeCount();
+    }
+
+    /**
+     * Returns the values, which are interpreted as "No Data".
+     * @param idx attribute index the "No Data" values are returned for
+     */
+    public Set<Object> getNoDataValues(int idx) {
+      return this.noDataValues.get(idx);
+    }
+
+    /**
+     * Sets a value, which is interpreted as "No Data".
+     * @param idx attribute index the "No Data" value is set for
+     * @param noDataValue the "No Data" value
+     */
+    public void addNoDataValue(int idx, Object noDataValue) {
+      Set<Object> noDataValues = getNoDataValues(idx);
+      if (noDataValues == null) {
+        noDataValues = new HashSet<Object>();
+        setNoDataValues(idx, noDataValues);
+      }
+      noDataValues.add(noDataValue);
+    }
+
+    /**
+     * Removes a "No Data" value for an attribute.
+     * @param idx attribute index the "No Data" value is removed for
+     * @param noDataValue the "No Data" value to remove
+     * @return {@code false} if the value was not an "No Data" value
+     */
+    public boolean removeNoDataValue(int idx, Object noDataValue) {
+      Set<Object> noDataValues = getNoDataValues(idx);
+      if (noDataValues == null)
+        return false;
+      return noDataValues.remove(noDataValue);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * attribute.
+     * @param idx attribute index the "No Data" value is checked for
+     * @param value an attribute value
+     */
+    public boolean isNoDataValue(int idx, Object value) {
+      Set<Object> noDataValues = getNoDataValues(idx);
+      if (noDataValues == null)
+        return false;
+      return noDataValues.contains(value);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * attribute. In this case this method returns {@code null}, otherwise the
+     * value itself.
+     * @param idx attribute index the "No Data" value is checked for
+     * @param value an attribute value
+     * @return {@code null} if the given value is one of the "No data" values
+     */
+    public <T> T filterNoDataValue(int idx, T value) {
+      if (isNoDataValue(idx, value))
+        return null;
+      return value;
+    }
+
+    /**
+     * Sets the table attribute the i-th chart attribute is weighted with.<br>
+     * <b>Note:</b>
+     * <ul>
+     * <li>The weight attribute can not be set for the domain attribute 0.</li>
+     * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
+     * </ul>
+     * @param idx the table attribute
+     * @param weightAttrName name of the weight attribute
+     * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
+     *      attribute.<br/>
+     * @exception IllegalArgumentException if weight attribute is set for
+     *              attribute 0
+     **/
+    @Override
+    public void setAttributeAggregationWeightAttributeName(int idx,
+        String weightAttrName) {
+      if (idx == 0 && weightAttrName != null)
+        throw new IllegalArgumentException(
+            "Weight attribute not allowed for attribute 0 because aggregation function not allowed for domain attribute!");
+      weightAttrNames.put(idx, weightAttrName);
+    }
+
+    /**
+     * Returns the table attribute the i-th chart attribute is weighted with.
+     * <b>Note:</b><br>
+     * This method returns {@code null} unless a
+     * {@linkplain AggregationFunction#isWeighted() weighted} aggregation
+     * function is set for the i-th attribute.
+     * @param idx the table attribute
+     * @see #setAttributeAggregationWeightAttributeName(int, String)
+     **/
+    @Override
+    public String getAttributeAggregationWeightAttributeName(int idx) {
+      AggregationFunction af = getAttributeAggregation(idx);
+      if (af == null || !af.isWeighted() || idx == 0)
+        return null;
+      return weightAttrNames.get(idx);
+    }
+
+    /**
+     * Sets the values, which are interpreted as "No Data" for the optional weight
+     * attribute.
+     * @param idx weight attribute index the "No Data" values are set for
+     * @param noDataValues the "No Data" values
+     */
+    @Override
+    public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues) {
+      if (idx == 0 && noDataValues != null)
+        throw new IllegalArgumentException(
+            "Weight attribute not allowed for attribute 0 because aggregation function not allowed for domain attribute!");
+      weightAttrNoDataValues.put(idx, noDataValues);
+    }
+
+    /**
+     * Returns the values, which are interpreted as "No Data" for the
+     * weight attribute.
+     * @param idx weight attribute index the "No Data" values are returned for
+     */
+    @Override
+    public Set<Object> getWeightAttributeNoDataValues(int idx) {
+      return weightAttrNoDataValues.get(idx);
+    }
+
+    /**
+     * Sets a value, which is interpreted as "No Data" for the weight
+     * attribute.
+     * @param idx attribute index the "No Data" value is set for
+     * @param noDataValue the "No Data" value
+     */
+    @Override
+    public void addWeightAttributeNoDataValue(int idx, Object noDataValue) {
+      Set<Object> noDataValues = getWeightAttributeNoDataValues(idx);
+      if (noDataValues == null) {
+        noDataValues = new HashSet<Object>();
+        setWeightAttributeNoDataValues(idx, noDataValues);
+      }
+      noDataValues.add(noDataValue);
+    }
+
+    /**
+     * Removes a "No Data" value for a weight attribute.
+     * @param idx attribute index the "No Data" value is removed for
+     * @param noDataValue the "No Data" value to remove
+     * @return {@code false} if the value was not an "No Data" value
+     */
+    @Override
+    public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue) {
+      Set<Object> noDataValues = getWeightAttributeNoDataValues(idx);
+      if (noDataValues == null)
+        return false;
+      return noDataValues.remove(noDataValue);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * weight attribute.
+     * @param idx weight attribute index the "No Data" value is checked for
+     * @param value an attribute value
+     * @return {@code false} is not weight attribute is set for attribute i
+     * @see #setAttributeAggregationWeightAttributeName(int, String)
+     */
+    @Override
+    public boolean isWeightAttributeNoDataValue(int idx, Object value) {
+      Set<Object> noDataValues = getWeightAttributeNoDataValues(idx);
+      if (noDataValues == null)
+        return false;
+      return noDataValues.contains(value);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * attribute. In this case this method returns {@code null}, otherwise the
+     * value itself.
+     * @param idx attribute index the "No Data" value is checked for
+     * @param value an attribute value
+     * @return {@code null} if the given value is one of the "No data" values
+     */
+    @Override
+    public <T> T filterWeightAttributeNoDataValue(int idx, T value) {
+      if (isWeightAttributeNoDataValue(idx, value))
+        return null;
+      return value;
+    }
+
+    /**
+     * Defines the attribute whose values are used to define
+     * groups. For each group value a series is created in the chart
+     * dataset.
+     * @param attrName table attribute name
+     */
+    @Override
+    public void setSeriesAttributeName(String attrName) {
+      this.seriesAttrName = attrName;
+    }
+    
+    /**
+     * Returns the attribute whose values are used to define
+     * groups. For each group value a series is created in the chart
+     * dataset.
+     */
+    @Override
+    public String getSeriesAttributeName() {
+      return seriesAttrName;
+    }
+
+    /**
+     * Sets the values, which are interpreted as "No Data" for the
+     * series attribute.
+     * @param noDataValues the "No Data" values
+     */
+    @Override
+    public void setSeriesAttributeNoDataValues(Set<Object> noDataValues) {
+      seriesAttrNoDataValues = noDataValues;
+    }
+
+    /**
+     * Returns the values, which are interpreted as "No Data" for the
+     * series attribute.
+     */
+    @Override
+    public Set<Object> getSeriesAttributeNoDataValues() {
+      return this.seriesAttrNoDataValues;
+    }
+
+    /**
+     * Sets a value, which is interpreted as "No Data" for the
+     * series attribute.
+     * @param noDataValue the "No Data" value
+     */
+    @Override
+    public void addSeriesAttributeNoDataValue(Object noDataValue) {
+      Set<Object> noDataValues = getSeriesAttributeNoDataValues();
+      if (noDataValues == null) {
+        noDataValues = new HashSet<Object>();
+        setSeriesAttributeNoDataValues(noDataValues);
+      }
+      noDataValues.add(noDataValue);
+    }
+
+    /**
+     * Removes a "No Data" value for the series attribute.
+     * @param noDataValue the "No Data" value to remove
+     * @return {@code false} if the value was not an "No Data" value
+     */
+    @Override
+   public boolean removeSeriesAttributeNoDataValue(Object noDataValue) {
+      Set<Object> noDataValues = getSeriesAttributeNoDataValues();
+      if (noDataValues == null)
+        return false;
+      return noDataValues.remove(noDataValue);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * series attribute.
+     * @param value an attribute value
+     */
+    @Override
+    public boolean isSeriesAttributeNoDataValue(Object value) {
+      Set<Object> noDataValues = getSeriesAttributeNoDataValues();
+      if (noDataValues == null)
+        return false;
+      return noDataValues.contains(value);
+    }
+
+    /**
+     * Checks whether the given value is one of the "No data" values for the
+     * series attribute. In this case this method returns {@code null}, otherwise the
+     * value itself.
+     * @param value an attribute value
+     * @return {@code null} if the given value is one of the "No data" values
+     */
+    @Override
+    public <T> T filterSeriesAttributeNoDataValue(T value) {
+      if (isSeriesAttributeNoDataValue(value))
+        return null;
+      return value;
+    }
+
+    /**
+     * Defines the attribute whose values are used to define the legend
+     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+     * @param attrName table attribute name
+     */
+    public void setSeriesLegendTitleAttributeName(String attrName) {
+      seriesLegendTitleAttrName = attrName;
+    }
+    
+    /**
+     * Returns the attribute whose values are used to define the legend
+     * title for the series defined by {@link #setSeriesAttributeName(String)}.
+     */
+    public String getSeriesLegendTitleAttributeName() {
+      return seriesLegendTitleAttrName;
+    }
+
+    /**
+     * Does nothing, but always throws a {@link UnsupportedOperationException},
+     * because the dummy can not provide this functionality.
+     */
+    @Override
+    public JFreeChart applyToDataset(Dataset dataset) {
+      throw new UnsupportedOperationException(
+          "TableChartStyle.Dummy does not implement applyToDataset(..)");
+    }
+
+    /**
+     * Does nothing, but always throws a {@link UnsupportedOperationException},
+     * because the dummy can not provide this functionality.
+     */
+    @Override
+    public JFreeChart applyToTable(E table) {
+      throw new UnsupportedOperationException(
+          "TableChartStyle.Dummy does not implement applyToTable(..)");
+    }
+
+  }
+}

Added: trunk/src/schmitzm/jfree/table/style/TableChartStyleXMLFactory.java
===================================================================
--- trunk/src/schmitzm/jfree/table/style/TableChartStyleXMLFactory.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/table/style/TableChartStyleXMLFactory.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Tzeggai - additional utility classes
+ ******************************************************************************/
+package schmitzm.jfree.table.style;
+
+import java.util.List;
+import java.util.Set;
+
+import org.jdom.Element;
+
+import schmitzm.jfree.chart.style.ChartAxisStyle;
+import schmitzm.jfree.chart.style.ChartStyle;
+import schmitzm.jfree.chart.style.ChartStyleXMLFactory;
+import schmitzm.jfree.chart.style.ChartType;
+import schmitzm.jfree.table.AggregationFunction;
+import schmitzm.xml.XMLUtil;
+	
+/**
+ * This class defines a factory to create a chart style from XML
+ * specialized for table data.
+ * @see TableChartStyle
+ * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
+ * @version 1.0
+ */
+public abstract class TableChartStyleXMLFactory<E extends TableChartStyle<?>> extends ChartStyleXMLFactory<E> {
+
+  /**
+   * Applies the chart style definition from XML (<b>except the type and id!!</b>)
+   * to an existing {@link ChartStyle} object.
+   * @param chartStyle an existing chart style ({@code null} not permitted!)
+   * @param element    element to read the properties from
+   */
+  @Override
+  public void applyStyleFromXML(E chartStyle, Element element) {
+    // Apply the normal style properties
+    super.applyStyleFromXML(chartStyle, element);
+    
+    // Convert ChartAxisStyle to ChartAxisStyle
+    for (int i=0; i<chartStyle.getAxisCount(); i++) {
+      ChartAxisStyle axisStyle = chartStyle.getAxisStyle(i);
+      if ( axisStyle != null ) {
+        TableChartAxisStyle tableAxisStyle = (TableChartAxisStyle)axisStyle.copyTo( new TableChartAxisStyle(chartStyle) );
+        chartStyle.setAxisStyle(i, tableAxisStyle);
+      }
+    }
+    
+    // Attribute definitions in <attributes> element
+    Element featureElement = element.getChild("featureAttributes");
+    if ( featureElement == null )
+      throw new UnsupportedOperationException("<featureAttributes> element necessary for FeatureChartStyle!");
+
+    // Read domain attribute
+    Element domainAttrElem = featureElement.getChild("domainAttr");
+    if ( domainAttrElem == null )
+      throw new UnsupportedOperationException("Attribute <domainAttr> required for FeatureChartType");
+    String domainAttrName = XMLUtil.getAttribute(domainAttrElem, "name");
+    if ( domainAttrName == null )
+      throw new UnsupportedOperationException("Attribute 'name' necessary for <domainAttr> element of FeatureChartStyle!");
+    chartStyle.setAttributeName(0, domainAttrName);
+    chartStyle.setAttributeNormalized(0, XMLUtil.getBooleanAttribute(domainAttrElem, "normalize", false));
+    chartStyle.setSortDomainAxis(XMLUtil.getBooleanAttribute(domainAttrElem, "sort", false));
+    chartStyle.setForceCategories(XMLUtil.getBooleanAttribute(domainAttrElem, "forceCategories", false));
+    Set<Object> nullAliases = XMLUtil.getSetAttribute(domainAttrElem, "nullAliases");
+    if (nullAliases != null)
+      chartStyle.setNoDataValues(0, nullAliases);
+    
+    // Read all range attribute definitions
+    int rangeAttrNo = 0;
+    for (Element rangeAttrElem : (List<Element>)featureElement.getChildren("rangeAttr") ) {
+      String featureAttrName = XMLUtil.getAttribute(rangeAttrElem, "name");
+      if ( featureAttrName == null )
+        throw new UnsupportedOperationException("Attribute 'name' necessary for <rangeAttr> element of FeatureChartStyle!");
+      // Apply attributes to style
+      rangeAttrNo++;
+      chartStyle.setAttributeName(rangeAttrNo, featureAttrName);
+      chartStyle.setAttributeNormalized(rangeAttrNo, XMLUtil.getBooleanAttribute(rangeAttrElem, "normalize", false));
+      nullAliases = XMLUtil.getSetAttribute(rangeAttrElem, "nullAliases");
+      if (nullAliases != null)
+    	  chartStyle.setNoDataValues(rangeAttrNo, nullAliases);
+      
+      String aggrFuncStr = XMLUtil.getAttribute(rangeAttrElem, "function", (String)null);
+      if ( aggrFuncStr != null ) 
+        chartStyle.setAttributeAggregation(rangeAttrNo, AggregationFunction.valueOf(aggrFuncStr) );
+
+      String aggrFuncWeightAtt = XMLUtil.getAttribute(rangeAttrElem, "weightAttrName", (String)null);
+      if ( aggrFuncWeightAtt != null )
+        chartStyle.setAttributeAggregationWeightAttributeName(rangeAttrNo, aggrFuncWeightAtt );
+      
+      nullAliases = XMLUtil.getSetAttribute(rangeAttrElem, "weightAttrNullAliases");
+      if (nullAliases != null)
+    	  chartStyle.setWeightAttributeNoDataValues(rangeAttrNo, nullAliases);
+    }
+
+    // Read (optional) series attribute (its values defines the series groups)
+    Element seriesAttrElem = featureElement.getChild("seriesAttr");
+    if ( seriesAttrElem != null ) {
+      String seriesAttrName = XMLUtil.getAttribute(seriesAttrElem, "name");
+      if ( seriesAttrName == null )
+        throw new UnsupportedOperationException("Attribute 'name' necessary for <seriesAttr> element of FeatureChartStyle!");
+      chartStyle.setSeriesAttributeName(seriesAttrName);
+      nullAliases = XMLUtil.getSetAttribute(seriesAttrElem, "nullAliases");
+      if (nullAliases != null)
+        chartStyle.setSeriesAttributeNoDataValues(nullAliases);
+      String seriesLegendLableAttrName = XMLUtil.getAttribute(seriesAttrElem, "titleAttrName");
+      if (seriesLegendLableAttrName != null)
+        chartStyle.setSeriesLegendTitleAttributeName(seriesLegendLableAttrName);
+    }
+  }
+
+
+  /**
+   * Creates a default style for a chart type.
+   * @param id   a (unique) ID for the style
+   * @param type a chart type
+   */
+  @Override
+  public E createDefaultChartStyle(String id, ChartType type) {
+    throw new UnsupportedOperationException("TableChartStyleXMLFactory can not create default styles, because the TableChartStyle implentation ist abstract for type "+type);
+  }
+
+  /**
+   * Creates a XML {@link Element} representing the {@link TableChartStylee}.
+   * @param style           style to create an element for
+   * @param rootElementName name for the root element (if {@code null} "ChartType" is 
+   *                        used)
+   */
+  @Override
+  public Element createElementFromStyle(E style, String rootElementName) {
+    Element root = super.createElementFromStyle(style, rootElementName);
+    
+    // Create and add element <featureAttributes>
+    Element attrElem = addChildToElement(root, "featureAttributes");
+    
+    // Domain attribute definition
+    if ( style.getAttributeCount() > 0 )
+      addChildToElement(attrElem, "domainAttr", false,
+          "name", style.getAttributeName(0),
+          "normalize", style.isAttributeNormalized(0),
+          "nullAliases", XMLUtil.convertSetToSeparatedString(style.getNoDataValues(0)), 
+          "sort", style.isSortDomainAxis(),
+          "forceCategories", style.isForceCategories()
+      );
+    
+    // Range attributes definition
+    for (int i=1; i<style.getAttributeCount(); i++)
+      addChildToElement(attrElem, "rangeAttr", false,
+          "name", style.getAttributeName(i),
+          "normalize", style.isAttributeNormalized(i),
+          "nullAliases", XMLUtil.convertSetToSeparatedString(style.getNoDataValues(i)), 
+          "function", style.getAttributeAggregation(i),
+          "weightAttrName", style.getAttributeAggregationWeightAttributeName(i),
+          "weightAttrNullAliases", XMLUtil.convertSetToSeparatedString(style.getWeightAttributeNoDataValues(i))
+      );
+
+    // Series attribute definition
+    if ( style.getSeriesAttributeName() != null )
+      addChildToElement(attrElem, "seriesAttr", false,
+          "name", style.getSeriesAttributeName(),
+          "nullAliases", XMLUtil.convertSetToSeparatedString(style.getSeriesAttributeNoDataValues()),
+          "titleAttrName", style.getSeriesLegendTitleAttributeName()
+      );
+
+    return root;
+  }
+}

Added: trunk/src/schmitzm/jfree/table/style/TableScatterChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/table/style/TableScatterChartStyle.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src/schmitzm/jfree/table/style/TableScatterChartStyle.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -0,0 +1,524 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Tzeggai - additional utility classes
+ ******************************************************************************/
+package schmitzm.jfree.table.style;
+
+import java.util.Set;
+
+import org.jfree.chart.JFreeChart;
+import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.general.Dataset;
+import org.jfree.data.xy.XYDataset;
+
+import schmitzm.jfree.chart.style.ChartStyle;
+import schmitzm.jfree.chart.style.ScatterChartStyle;
+import schmitzm.jfree.table.AggregationFunction;
+
+/**
+ * This class extends the {@link ScatterChartStyle} with the properties
+ * of the {@link TableChartStyle}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public abstract class TableScatterChartStyle<E> extends ScatterChartStyle implements TableChartStyle<E> {
+  /** Used to maintain the {@link TableChartStyle} properties. */
+  protected Dummy<E> dummyTableChartStyle = null;
+  
+  /**
+   * Creates a scatter chart style a regression line shown.
+   * @param id   a (unique) ID for the style
+   */
+  public TableScatterChartStyle(String id) {
+    super(id);
+    dummyTableChartStyle = new Dummy(id,2);
+  }
+  
+  @Override
+  /**
+   * Nicer debugging
+   */
+	public String toString() {
+	  
+	  String titel = getTitleStyle() != null ? getTitleStyle().getLabel() : " - null title!!! - ";
+		return "ID="+getID()+"   "+titel+"" + super.toString();
+	}
+
+  /**
+   * Creates a scatter chart style a regression line shown.
+   * @param id         a (unique) ID for the style
+   * @param title      title for the chart
+   * @param xAttrName  table attribute used for domain axis
+   * @param yAttrName  table attribute used for range axis
+   */
+  public TableScatterChartStyle(String id, String title, String xAttrName, String yAttrName) {
+    this(id);
+    setAttributeName(0, xAttrName);
+    setAttributeName(1, yAttrName);
+    getTitleStyle().setLabel(title);
+  }
+
+  /**
+   * Copies all properties of this style to another one.
+   * @param dest destination object (if {@code null} the copy
+   *             is created by {@link #copy()})
+   * @return {@code dest} or the new instance
+   */
+  @Override
+  public ChartStyle copyTo(ChartStyle dest) {
+    // copy the super class properties
+    dest = super.copyTo(dest);
+    // copy this classes properties
+    if ( dest instanceof TableChartStyle )
+      dummyTableChartStyle.copyTo(dest);
+
+    return dest;
+  }
+
+  /**
+   * Removes all style informations about an attribute and
+   * reorganizes the attribute indexes so there is an continuous 
+   * order. 
+   * @param idx an attribute
+   */
+  @Override
+  public void removeAttribute(int idx) {
+    dummyTableChartStyle.removeAttribute(idx);
+  }
+
+  /**
+   * Returns the maximum number of table attributes that can be
+   * specified by this style.
+   * @return always 2
+   */
+  @Override
+  public int getMaxAttributeCount() {
+    return dummyTableChartStyle.getMaxAttributeCount();
+  }
+
+  /**
+   * Returns the number of table attributes defined in this style.
+   */
+  @Override
+  public int getAttributeCount() {
+    return dummyTableChartStyle.getAttributeCount();
+  }
+
+  /**
+   * Returns the name of a table attribute needed to create a
+   * chart for this style.
+   * @param idx attribute index (0=domain; 1=1st range series;
+   *            2=2nd range series; ...)
+   */
+  @Override
+  public String getAttributeName(int idx) {
+    return dummyTableChartStyle.getAttributeName(idx);
+  }
+
+  /**
+   * Sets the name of a table attribute needed to create a
+   * chart for this style.
+   * @param idx attribute index (0=domain; 1=1st range series;
+   *            2=2nd range series; ...)
+   * @param attrName table attribute name 
+   */
+  @Override
+  public void setAttributeName(int idx, String attrName) {
+    dummyTableChartStyle.setAttributeName(idx,attrName);
+  }
+
+  /**
+   * Sets whether the table rows are sorted according to the
+   * domain attribute (before creating a {@link Dataset}).
+   */
+  @Override
+  public void setSortDomainAxis(boolean sortDomainAxis){
+    dummyTableChartStyle.setSortDomainAxis(sortDomainAxis);
+  }
+
+  /**
+   * Returns whether the table rows are sorted according to the
+   * domain attribute (before creating a {@link Dataset}).
+   * @return {@code false} as default
+   */
+  @Override
+  public boolean isSortDomainAxis() {
+    return dummyTableChartStyle.isSortDomainAxis();
+  }
+
+  /** 
+   * Sets whether a {@link CategoryDataset} is forced for
+   * a numeric domain attribute. The default is to create {@link XYDataset}
+   * for a numeric and {@link CategoryDataset} for a non-numeric domain
+   * attribute.
+   */
+  @Override
+  public void setForceCategories(boolean forceCategories){
+    dummyTableChartStyle.setForceCategories(forceCategories);
+  }
+
+  /** 
+   * Returns whether a {@link CategoryDataset} is forced for
+   * a numeric domain attribute. The default is to create {@link XYDataset}
+   * for a numeric and {@link CategoryDataset} for a non-numeric domain
+   * attribute.
+   * @return {@code false} as default
+   */
+  @Override
+  public boolean isForceCategories(){
+    return dummyTableChartStyle.isForceCategories();
+  }
+
+  /** 
+   * Sets whether the attribute data is normalized for an
+   * attribute(before creating a {@link Dataset}).
+   * @param idx attribute index (0=domain; 1=1st range series;
+   *            2=2nd range series; ...)
+   * @param normalize indicates the normalize property
+   */  
+  @Override
+  public void setAttributeNormalized(int idx, Boolean normalize){
+    dummyTableChartStyle.setAttributeNormalized(idx, normalize);
+  }
+
+  /** 
+   * Returns whether the attribute data is normalized for an
+   * attribute(before creating a {@link Dataset}).
+   * @param idx attribute index (0=domain; 1=1st range series;
+   *            2=2nd range series; ...)
+   * @return {@code false} as default
+   */  
+  @Override
+  public boolean isAttributeNormalized(int idx) {
+       return dummyTableChartStyle.isAttributeNormalized(idx);
+  }
+
+  /** 
+   * Sets an arithmetical function which is calculated on
+   * the attribute values (when creating a {@link Dataset}
+   * e.g. from Features).
+   * The function is calculated on all values with the same
+   * domain value (X/category). If no function is set, duplicate
+   * domain values are ignored (only the "last" value is shown, because
+   * of replacement behavior).
+   * @param idx attribute index (1=1st range series;
+   *            2=2nd range series; ...)
+   * @param func defines the calculated function
+   * @exception IllegalArgumentException if function is set on
+   *            domain attribute (0)
+   */  
+  @Override
+  public void setAttributeAggregation(int idx, AggregationFunction func) {
+    dummyTableChartStyle.setAttributeAggregation(idx, func);
+  }
+    
+  /** 
+   * Returns an arithmetical function which is calculated on
+   * the attribute values (when creating a {@link Dataset}
+   * e.g. from Features).
+   * The function is calculated on all values with the same
+   * domain value (X/category). If no function is set, duplicate
+   * domain values are ignored (only the "last" value is shown, because
+   * of replacement behavior).
+   * @param idx attribute index (1=1st range series;
+   *            2=2nd range series; ...)
+   * @return {@code null} for index 0 (domain axis)
+   */
+  @Override
+  public AggregationFunction getAttributeAggregation(int idx) {
+   return dummyTableChartStyle.getAttributeAggregation(idx); 
+  }
+
+  /**
+   * Sets the values, which are interpreted as "No Data". 
+   * @param idx attribute index the "No Data" values are set for
+   * @param noDataValues the "No Data" values
+   */
+  public void setNoDataValues(int idx, Set<Object> noDataValues) {
+    dummyTableChartStyle.setNoDataValues(idx, noDataValues);
+  }
+  
+  /**
+   * Returns the values, which are interpreted as "No Data". 
+   * @param idx attribute index the "No Data" values are returned for
+   */
+  public Set<Object> getNoDataValues(int idx) {
+    return dummyTableChartStyle.getNoDataValues(idx);
+  }
+  
+  /**
+   * Sets a value, which is interpreted as "No Data". 
+   * @param idx attribute index the "No Data" value is set for
+   * @param noDataValue the "No Data" value
+   */
+  public void addNoDataValue(int idx, Object noDataValue) {
+    dummyTableChartStyle.addNoDataValue(idx, noDataValue);
+  }
+
+  /**
+   * Removes a "No Data" value for an attribute. 
+   * @param idx attribute index the "No Data" value is removed for
+   * @param noDataValue the "No Data" value to remove
+   * @return {@code false} if the value was not an "No Data" value 
+   */
+  public boolean removeNoDataValue(int idx, Object noDataValue) {
+    return dummyTableChartStyle.removeNoDataValue(idx, noDataValue);
+  }
+
+  /**
+   * Checks whether the given value is one of the "No data" values for
+   * the attribute.
+   * @param idx attribute index the "No Data" value is checked for
+   * @param value an attribute value
+   */
+  public boolean isNoDataValue(int idx, Object value) {
+    return dummyTableChartStyle.isNoDataValue(idx, value);
+  }
+
+  /**
+   * Checks whether the given value is one of the "No data" values for
+   * the attribute. In this case this method returns {@code null}, otherwise
+   * the value itself.
+   * @param idx attribute index the "No Data" value is checked for
+   * @param value an attribute value
+   * @return {@code null} if the given value is one of the "No data" values 
+   */
+  public <T> T filterNoDataValue(int idx, T value) {
+    return dummyTableChartStyle.filterNoDataValue(idx, value);
+  }
+
+  /**
+   * Sets the table attribute the i-th chart attribute is weighted with.<br>
+   * <b>Note:</b>
+   * <ul>
+   * <li>The weight attribute can not be set for the domain attribute 0.</li>
+   * <li>Do not forget to set the NULL values for the weight attributes, too!</li>
+   * </ul>
+   * @param idx the table attribute
+   * @param weightAttrName name of the weight attribute
+   * @see #setWeightAttributeNoDataValues(idx, Set) to set NoDataValues for this
+   *      attribute.<br/>
+   * @exception IllegalArgumentException if weight attribute is set for
+   *              attribute 0
+   **/
+  @Override
+  public void setAttributeAggregationWeightAttributeName(int idx,
+      String weightAttrName) {
+    dummyTableChartStyle.setAttributeAggregationWeightAttributeName(idx, weightAttrName);
+  }
+
+  /**
+   * Returns the table attribute the i-th chart attribute is weighted with.
+   * <b>Note:</b><br>
+   * This method returns {@code null} unless a
+   * {@linkplain AggregationFunction#isWeighted() weighted} aggregation
+   * function is set for the i-th attribute.
+   * @param idx the table attribute
+   * @see #setAttributeAggregationWeightAttributeName(int, String)
+   **/
+  @Override
+  public String getAttributeAggregationWeightAttributeName(int idx) {
+    return dummyTableChartStyle.getAttributeAggregationWeightAttributeName(idx);
+  }
+
+  /**
+   * Sets the values, which are interpreted as "No Data" for the optional weight
+   * attribute.
+   * @param idx weight attribute index the "No Data" values are set for
+   * @param noDataValues the "No Data" values
+   */
+  @Override
+  public void setWeightAttributeNoDataValues(int idx, Set<Object> noDataValues) {
+    dummyTableChartStyle.setWeightAttributeNoDataValues(idx, noDataValues);
+  }
+
+  /**
+   * Returns the values, which are interpreted as "No Data" for the
+   * weight attribute.
+   * @param idx weight attribute index the "No Data" values are returned for
+   */
+  @Override
+  public Set<Object> getWeightAttributeNoDataValues(int idx) {
+    return dummyTableChartStyle.getWeightAttributeNoDataValues(idx);
+  }
+
+  /**
+   * Sets a value, which is interpreted as "No Data" for the weight
+   * attribute.
+   * @param idx attribute index the "No Data" value is set for
+   * @param noDataValue the "No Data" value
+   */
+  @Override
+  public void addWeightAttributeNoDataValue(int idx, Object noDataValue) {
+    dummyTableChartStyle.addWeightAttributeNoDataValue(idx, noDataValue);
+  }
+
+  /**
+   * Removes a "No Data" value for a weight attribute.
+   * @param idx attribute index the "No Data" value is removed for
+   * @param noDataValue the "No Data" value to remove
+   * @return {@code false} if the value was not an "No Data" value
+   */
+  @Override
+  public boolean removeWeightAttributeNoDataValue(int idx, Object noDataValue) {
+    return dummyTableChartStyle.removeWeightAttributeNoDataValue(idx, noDataValue);
+  }
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * weight attribute.
+   * @param idx weight attribute index the "No Data" value is checked for
+   * @param value an attribute value
+   * @return {@code false} is not weight attribute is set for attribute i
+   * @see #setAttributeAggregationWeightAttributeName(int, String)
+   */
+  @Override
+  public boolean isWeightAttributeNoDataValue(int idx, Object value) {
+    return dummyTableChartStyle.isWeightAttributeNoDataValue(idx, value);
+  }
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * attribute. In this case this method returns {@code null}, otherwise the
+   * value itself.
+   * @param idx attribute index the "No Data" value is checked for
+   * @param value an attribute value
+   * @return {@code null} if the given value is one of the "No data" values
+   */
+  @Override
+  public <T> T filterWeightAttributeNoDataValue(int idx, T value) {
+    return dummyTableChartStyle.filterWeightAttributeNoDataValue(idx, value);
+  }
+
+  /**
+   * Defines the attribute whose values are used to define
+   * groups. For each group value a series is created in the chart
+   * dataset.
+   * @param attrName table attribute name
+   */
+  @Override
+  public void setSeriesAttributeName(String attrName) {
+    dummyTableChartStyle.setSeriesAttributeName(attrName);
+  }
+  
+  /**
+   * Returns the attribute whose values are used to define
+   * groups. For each group value a series is created in the chart
+   * dataset.
+   */
+  @Override
+  public String getSeriesAttributeName() {
+    return dummyTableChartStyle.getSeriesAttributeName();
+  }
+
+  /**
+   * Sets the values, which are interpreted as "No Data" for the
+   * series attribute.
+   * @param noDataValues the "No Data" values
+   */
+  @Override
+  public void setSeriesAttributeNoDataValues(Set<Object> noDataValues) {
+    dummyTableChartStyle.setSeriesAttributeNoDataValues(noDataValues);
+  }
+
+  /**
+   * Returns the values, which are interpreted as "No Data" for the
+   * series attribute.
+   */
+  @Override
+  public Set<Object> getSeriesAttributeNoDataValues() {
+    return dummyTableChartStyle.getSeriesAttributeNoDataValues();
+  }
+
+  /**
+   * Sets a value, which is interpreted as "No Data" for the
+   * series attribute.
+   * @param noDataValue the "No Data" value
+   */
+  @Override
+  public void addSeriesAttributeNoDataValue(Object noDataValue) {
+    dummyTableChartStyle.addSeriesAttributeNoDataValue(noDataValue);
+  }
+
+  /**
+   * Removes a "No Data" value for the series attribute.
+   * @param noDataValue the "No Data" value to remove
+   * @return {@code false} if the value was not an "No Data" value
+   */
+  @Override
+ public boolean removeSeriesAttributeNoDataValue(Object noDataValue) {
+    return dummyTableChartStyle.removeSeriesAttributeNoDataValue(noDataValue);
+  }
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * series attribute.
+   * @param value an attribute value
+   */
+  @Override
+  public boolean isSeriesAttributeNoDataValue(Object value) {
+    return dummyTableChartStyle.isSeriesAttributeNoDataValue(value);
+  }
+
+  /**
+   * Checks whether the given value is one of the "No data" values for the
+   * series attribute. In this case this method returns {@code null}, otherwise the
+   * value itself.
+   * @param value an attribute value
+   * @return {@code null} if the given value is one of the "No data" values
+   */
+  @Override
+  public <T> T filterSeriesAttributeNoDataValue(T value) {
+    return dummyTableChartStyle.filterSeriesAttributeNoDataValue(value);
+  }
+
+  /**
+   * Defines the attribute whose values are used to define the legend
+   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+   * @param attrName table attribute name
+   */
+  public void setSeriesLegendTitleAttributeName(String attrName) {
+    dummyTableChartStyle.setSeriesLegendTitleAttributeName(attrName);
+  }
+  
+  /**
+   * Returns the attribute whose values are used to define the legend
+   * title for the series defined by {@link #setSeriesAttributeName(String)}.
+   */
+  public String getSeriesLegendTitleAttributeName() {
+    return dummyTableChartStyle.getSeriesLegendTitleAttributeName();
+  }
+  
+  /**
+   * Creates a chart according to the given table data.
+   * @param table the table
+   * @exception UnsupportedOperationException if the style can not be applied to
+   *            the table
+   */
+  @Override
+  public abstract JFreeChart applyToTable(E table);
+}

Modified: trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java
===================================================================
--- trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java	2010-05-28 15:13:05 UTC (rev 874)
+++ trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java	2010-05-28 15:37:56 UTC (rev 875)
@@ -40,7 +40,8 @@
 import schmitzm.jfree.chart.style.ChartLabelStyle;
 import schmitzm.jfree.chart.style.ChartRendererStyle;
 import schmitzm.jfree.chart.style.ChartType;
-import schmitzm.jfree.feature.AggregationFunction;
+import schmitzm.jfree.table.AggregationFunction;
+import schmitzm.jfree.table.style.TableChartStyleXMLFactory;
 
 public class FeatureChartStyleTest {
 	private static Logger log = Logger.getLogger(FeatureChartStyleTest.class);



More information about the Schmitzm-commits mailing list