[Schmitzm-commits] r721 - trunk/src/schmitzm/jfree/feature/style
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Feb 25 16:25:56 CET 2010
Author: alfonx
Date: 2010-02-25 16:25:55 +0100 (Thu, 25 Feb 2010)
New Revision: 721
Modified:
trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
Log:
For BAR charts the design GUI now supports aggregation.
Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java 2010-02-25 14:26:02 UTC (rev 720)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java 2010-02-25 15:25:55 UTC (rev 721)
@@ -31,11 +31,17 @@
import hep.aida.bin.StaticBin1D;
+import java.awt.Component;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+
import org.geotools.feature.FeatureCollection;
import org.jfree.chart.JFreeChart;
import org.jfree.data.category.CategoryDataset;
@@ -51,673 +57,350 @@
import schmitzm.lang.ResourceProvider;
/**
- * This interface extends the chart style with several functionalities
- * used to define a chart on a {@link FeatureCollection}.
+ * This interface extends the chart style with several functionalities used to
+ * define a chart on a {@link FeatureCollection}.
+ *
* @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
* @version 1.0
*/
public interface FeatureChartStyle extends ChartStyle {
- /**
- * Defines possible aggregation function to calculate
- * on attribute categories.
- * @see FeatureChartStyle#setAttributeAggregation(int, AggregationFunction)
- * @see FeatureChartStyle#getAttributeAggregation(int)
- */
- public static enum AggregationFunction {
- /** Count of the attribute values. */
- COUNT,
- /** Sum of the attribute values. */
- SUM,
- /** Sum of the absolute attribute values. */
- SUM_ABS,
- /** Average of the attribute values. */
- AVG,
- /** 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;
-
- /**
- * 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 the result of the function from a statistic.
- * @param statistics Statistic to take the result from.
- */
- public Double getResult(StaticBin1D statistics) {
- switch ( this ) {
- case AVG: return statistics.mean();
- case MAX: return statistics.max();
- case MIN: return statistics.min();
-// case SUM_ABS: // SK: Man müsste beim "packen der daten in die Statistik" schon abs() auf die werte anwenden und dann diese zeile einkommentieren
- case SUM: return statistics.sum();
- case COUNT: return ((Integer)statistics.size()).doubleValue();
- case STND_DEV: return statistics.standardDeviation();
- case VARIANCE: return Math.pow(statistics.standardDeviation(),2);
- case MEDIAN: return statistics.mean();
- }
- throw new UnsupportedOperationException("Aggregation function not yet supported: "+this);
- }
-
- /**
- * 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;
- }
+ /**
+ * Defines possible aggregation function to calculate on attribute
+ * categories.
+ *
+ * @see FeatureChartStyle#setAttributeAggregation(int, AggregationFunction)
+ * @see FeatureChartStyle#getAttributeAggregation(int)
+ */
+ public static enum AggregationFunction {
+ /** Count of the attribute values. */
+ COUNT,
+ /** Sum of the attribute values. */
+ SUM,
+// /** Sum of the absolute attribute values. */
+// SUM_ABS,
+ /** Average of the attribute values. */
+ AVG,
+// /** 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;
- /**
- * 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;
- }
- }
+ /**
+ * 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 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 result of the function from a statistic.
+ *
+ * @param statistics
+ * Statistic to take the result from.
+ */
+ public Double getResult(StaticBin1D statistics) {
+ switch (this) {
+ case AVG:
+ return statistics.mean();
+ case MAX:
+ return statistics.max();
+ case MIN:
+ return statistics.min();
+ // case SUM_ABS: // SK: Man müsste beim
+ // "packen der daten in die Statistik" schon abs() auf die werte
+ // anwenden und dann diese zeile einkommentieren
+ case SUM:
+ return statistics.sum();
+ case COUNT:
+ return ((Integer) statistics.size()).doubleValue();
+ case STND_DEV:
+ return statistics.standardDeviation();
+ case VARIANCE:
+ return Math.pow(statistics.standardDeviation(), 2);
+// case MEDIAN:
+// case SUM_ABS:
+ }
+ throw new UnsupportedOperationException(
+ "Aggregation function not yet supported: " + this);
+ }
- /**
- * Returns the number of feature attributes defined in this style.
- */
- public int getAttributeCount();
+ /**
+ * 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;
+ }
- /**
- * 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 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;
+ }
- /**
- * 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.
- * @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);
-
- /**
- * Creates a chart according to the given
- * @param fc a feature collection
- * @exception UnsupportedOperationException if the style can not be applied
- * to the {@link FeatureCollection} (e.g. the {@link FeatureCollection}
- * does not provide the required attributes)
- */
- public JFreeChart applyToFeatureCollection(FeatureCollection<SimpleFeatureType, SimpleFeature> fc);
-
- /**
- * Sets whether the features are sorted according to the
- * domain attribute (before creating a {@link Dataset}).
- */
- public void setSortDomainAxis(boolean sort);
+ /**
+ * A static {@link DefaultListCellRenderer} that will render instances
+ * of {@link AggregationFunction} with the title and description field
+ * as a tooltip.
+ */
+ static ListCellRenderer listCellRenderer = new DefaultListCellRenderer() {
- /**
- * Returns whether the features are sorted according to the
- * domain attribute (before creating a {@link Dataset}).
- * @return {@code false} as default
- */
- public boolean isSortDomainAxis();
+ @Override
+ public Component getListCellRendererComponent(JList list,
+ Object value, int index, boolean isSelected,
+ boolean cellHasFocus) {
- /**
- * 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);
+ Component proto = super.getListCellRendererComponent(list,
+ value, index, isSelected, cellHasFocus);
- /**
- * 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);
+ if (proto instanceof JLabel
+ && value instanceof AggregationFunction) {
+ ((JLabel) proto).setText(((AggregationFunction) value)
+ .getTitle());
+ ((JLabel) proto)
+ .setToolTipText(((AggregationFunction) value)
+ .getDescription());
+ }
- /**
- * 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);
+ return proto;
+ }
+ };
- /**
- * 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);
+ /**
+ * Returns a {@link ListCellRenderer} that will render elemnts of type
+ * {@link AggregationFunction} with their title and description as
+ * tooltip
+ **/
+ public static ListCellRenderer getListCellRenderer() {
+ return listCellRenderer;
+ }
+ }
- /**
- * 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);
-
- /**
- * Updates the unitVisible parameter for all axes at once.
- * @param visible
- * <code>true</code> if unit string shall be displayed in the
- * chart.
- */
- public void setUnitVisible(boolean visible);
+ /**
+ * 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();
- /**
- * This class defines a dummy implementation of {@link FeatureChartStyle} just
- * to maintain the properties of the interface {@link FeatureChartStyle}, so
- * sub classes of {@link FeatureChartStyle} which usually are derived from
- * a normal {@link ChartStyle} implementation must not implement the
- * {@link FeatureChartStyle} maintenance each. Instead they can create an
- * instance of this dummy an pipe their method implementations to the
- * dummy!<br>
- * <br>
- * The {@link #applyToFeatureCollection(FeatureCollection)} 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 extends AbstractChartStyle 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;
+ /**
+ * Returns the number of feature attributes defined in this style.
+ */
+ public int getAttributeCount();
- /** 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;
+ /**
+ * 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);
- /** 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>>();
+ /**
+ * 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);
- /** Holds the aggregation function for each attribute. */
- protected Map<Integer,AggregationFunction> aggrFuncs = new HashMap<Integer, AggregationFunction>();
+ /**
+ * 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
+ */
+ public void setAttributeName(int idx, String attrName);
- /**
- * 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 chart according to the given
+ *
+ * @param fc
+ * a feature collection
+ * @exception UnsupportedOperationException
+ * if the style can not be applied to the
+ * {@link FeatureCollection} (e.g. the
+ * {@link FeatureCollection} does not provide the required
+ * attributes)
+ */
+ public JFreeChart applyToFeatureCollection(
+ FeatureCollection<SimpleFeatureType, SimpleFeature> fc);
- /**
- * 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 feature collection
- */
- protected Dummy(String id, int maxAttrCount) {
- super(id);
- this.maxAttrCount = maxAttrCount;
- }
+ /**
+ * Sets whether the features are sorted according to the domain attribute
+ * (before creating a {@link Dataset}).
+ */
+ public void setSortDomainAxis(boolean sort);
- /**
- * Updates the local variable for the number of attributes
- * the maximum index (key) of the several hash maps.
- */
- private void updateAttributeCount() {
- // attribute names define the number of attributes, also
- // if there are "more" normalize constraints specified
- maxAttrIdx = LangUtil.max( attrNames.keySet(),
- normalizeAttr.keySet(),
- noDataValues.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() );
+ /**
+ * Returns whether the features are sorted according to the domain attribute
+ * (before creating a {@link Dataset}).
+ *
+ * @return {@code false} as default
+ */
+ public boolean isSortDomainAxis();
- // Clear the attribute names and attribute normalization
- int max = destFCS.getMaxAttributeCount();
- for (int i=0; i<max; i++) {
- destFCS.setAttributeName(i, null);
- destFCS.setAttributeNormalized(i, null);
-
- // Added by SK. In this special case we don't
- destFCS.setNoDataValues(i, getNoDataValues(i));
- }
- // Copy attribute names and normalization
- 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));
-
- }
-
- return dest;
- }
+ /**
+ * 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 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 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();
- /**
- * Returns the number of feature attributes defined in this style.
- */
- @Override
- public int getAttributeCount() {
- return maxAttrIdx+1;
- }
+ /**
+ * 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 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);
- }
+ /**
+ * 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 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 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 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 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);
- /**
- * 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 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);
- /**
- * 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 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);
- /**
- * 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 )
- 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);
- }
+ /**
+ * 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);
- /**
- * 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);
- }
+ /**
+ * 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);
- /**
- * 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. 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);
- /**
- * 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;
- }
-
- /**
- * 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("FeatureChartStyle.Dummy does not implement applyToFeatureCollection(..)");
- }
-
/**
* Updates the unitVisible parameter for all axes at once.
*
@@ -725,15 +408,489 @@
* <code>true</code> if unit string shall be displayed in the
* chart.
*/
- @Override
- public void setUnitVisible(boolean visible) {
- // TODO MArtin! Funktioniert so leider nicht. Warum ist hier getAxisCount() immer 0 ????
- for (int axisIndex = 0; axisIndex < getAxisCount(); axisIndex++) {
- getAxisStyle(axisIndex).setUnitVisible(visible);
+ public void setUnitVisible(boolean visible);
+
+ /**
+ * This class defines a dummy implementation of {@link FeatureChartStyle}
+ * just to maintain the properties of the interface
+ * {@link FeatureChartStyle}, so sub classes of {@link FeatureChartStyle}
+ * which usually are derived from a normal {@link ChartStyle} implementation
+ * must not implement the {@link FeatureChartStyle} maintenance each.
+ * Instead they can create an instance of this dummy an pipe their method
+ * implementations to the dummy!<br>
+ * <br>
+ * The {@link #applyToFeatureCollection(FeatureCollection)} 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 extends AbstractChartStyle 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>();
+
+ /**
+ * 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
+ * feature collection
+ */
+ 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() {
+ // attribute names define the number of attributes, also
+ // if there are "more" normalize constraints specified
+ maxAttrIdx = LangUtil.max(attrNames.keySet(), normalizeAttr
+ .keySet(), noDataValues.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 and attribute normalization
+ int max = destFCS.getMaxAttributeCount();
+ for (int i = 0; i < max; i++) {
+ destFCS.setAttributeName(i, null);
+ destFCS.setAttributeNormalized(i, null);
+
+ // Added by SK. In this special case we don't
+ destFCS.setNoDataValues(i, getNoDataValues(i));
+ }
+ // Copy attribute names and normalization
+ 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));
+
+ }
+
+ 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)
+ 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;
+ }
+
+ /**
+ * 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(
+ "FeatureChartStyle.Dummy does not implement applyToFeatureCollection(..)");
+ }
+
+ /**
+ * Updates the unitVisible parameter for all axes at once.
+ *
+ * @param visible
+ * <code>true</code> if unit string shall be displayed in the
+ * chart.
+ */
+ @Override
+ public void setUnitVisible(boolean visible) {
+ // TODO MArtin! Funktioniert so leider nicht. Warum ist hier
+ // getAxisCount() immer 0 ????
+ for (int axisIndex = 0; axisIndex < getAxisCount(); axisIndex++) {
+ getAxisStyle(axisIndex).setUnitVisible(visible);
+ }
+ }
+
}
- }
-
}
-
More information about the Schmitzm-commits
mailing list