[Schmitzm-commits] r277 - in trunk/src/schmitzm: geotools/feature jfree/chart/style jfree/feature/style

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Sat Aug 1 21:55:42 CEST 2009


Author: mojays
Date: 2009-08-01 21:55:40 +0200 (Sat, 01 Aug 2009)
New Revision: 277

Modified:
   trunk/src/schmitzm/geotools/feature/FeatureUtil.java
   trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
   trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java
Log:
support of category datasets

Modified: trunk/src/schmitzm/geotools/feature/FeatureUtil.java
===================================================================
--- trunk/src/schmitzm/geotools/feature/FeatureUtil.java	2009-08-01 18:26:53 UTC (rev 276)
+++ trunk/src/schmitzm/geotools/feature/FeatureUtil.java	2009-08-01 19:55:40 UTC (rev 277)
@@ -538,11 +538,15 @@
    */
   public static Vector<Feature> sortFeatures(FeatureIterator fi, String attrName) {
     // First create a SortedMap with CollisionList
-    SortedMap<Number, Vector<Feature>> sortedFeatureLists = new TreeMap<Number, Vector<Feature>>();
+    SortedMap<Comparable, Vector<Feature>> sortedFeatureLists = new TreeMap<Comparable, Vector<Feature>>();
     for (;fi.hasNext();) {
       Feature f = fi.next();
+      // Check whether attribute value is Comparable
+      Object attrValue  = f.getAttribute(attrName);
+      if ( attrValue != null && !(attrValue instanceof Comparable) )
+        throw new UnsupportedOperationException("Feature sort only supported for Comparable attributes: "+LangUtil.getSimpleClassName(attrValue));
       // Determine X value as sort attribute (NULL not permitted for XYDateset!)
-      Number xValue = (Number)f.getAttribute(attrName);
+      Comparable xValue = (Comparable)attrValue;
       if ( xValue == null )
         continue;
       

Modified: trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java	2009-08-01 18:26:53 UTC (rev 276)
+++ trunk/src/schmitzm/jfree/chart/style/AbstractChartStyle.java	2009-08-01 19:55:40 UTC (rev 277)
@@ -383,6 +383,7 @@
       plot.getRenderer().setURLGenerator( hasURLs() ? URLGEN_XY : null );
       if ( getOrientation() != null )
         plot.setOrientation( getOrientation() );
+      
       // style renderer
       for (int i=0; i<plot.getRendererCount(); i++) {
         XYItemRenderer     renderer      = plot.getRenderer(i);
@@ -396,6 +397,10 @@
       plot.getRenderer().setBaseItemURLGenerator( hasURLs() ? URLGEN_CAT : null );
       if ( getOrientation() != null )
         plot.setOrientation( getOrientation() );
+
+// DEBUG!! ///
+//      plot.setOrientation(PlotOrientation.VERTICAL);
+/////////////
       // style renderer
       for (int i=0; i<plot.getRendererCount(); i++) {
         CategoryItemRenderer renderer      = plot.getRenderer(i);
@@ -405,41 +410,6 @@
       }
     }
     
-//    // style the legend (by the series properties of ChartRendererStyle!!)
-//    LegendTitle legend = chart.getLegend();
-//    if ( legend != null && legend.getSources().length > 0 ) {
-//      final LegendItemSource[]   legendSource = legend.getSources();      
-//      final LegendItemCollection oldLegend    = legendSource[0].getLegendItems();      
-//      // redefine the primary legend
-//      legendSource[0] = new LegendItemSource() {
-//        public LegendItemCollection getLegendItems() {
-//          LegendItemCollection lic = new LegendItemCollection();
-//          for (int i=0 ; i<oldLegend.getItemCount(); i++ ) {
-//            // create a changeable copy of the legend item
-//            LegendItem          legendItem     = oldLegend.get(i);
-//            ChangableLegendItem changeableItem = null;
-//            if ( legendItem instanceof ChangableLegendItem )
-//              changeableItem = (ChangableLegendItem)legendItem;
-//            else
-//              changeableItem = new ChangableLegendItem( legendItem );
-//            
-//            // restyle the legend item according to the renderer style
-//            int rendererIdx              = newItem.getDatasetIndex();
-//            int seriesIdx                = newItem.getSeriesIndex();
-//            ChartRendererStyle rendStyle = getRendererStyle(rendererIdx);
-//            if ( rendStyle != null ) {
-//              if ( rendStyle.getSeriesLegendLabel(seriesIdx) != null )
-//                newItem.setLabel(rendStyle.getSeriesLegendLabel(seriesIdx).getLabel());
-//              if ( rendStyle.getSeriesLegendTooltip(seriesIdx) != null )
-//                newItem.setToolTipText(rendStyle.getSeriesLegendTooltip(seriesIdx).getLabel());
-//            }
-//            lic.add(newItem);
-//          } 
-//          return lic;
-//        }
-//      }
-//    }
-
     // style plot
     if ( getPlotStyle() != null )
       getPlotStyle().applyToPlot(chart.getPlot());

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2009-08-01 18:26:53 UTC (rev 276)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2009-08-01 19:55:40 UTC (rev 277)
@@ -181,16 +181,10 @@
      * 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)}.
-     * @see schmitzm.jfree.feature.style.FeatureChartStyle#applyToFeatureCollection(org.geotools.feature.FeatureCollection)
      */
     @Override
     public JFreeChart applyToFeatureCollection(FeatureCollection fc) {
-      final XYSeriesCollection dataset = FeatureChartUtil.createXYDataset(
-          fc,
-          this
-      );
-      JFreeChart chart = applyToDataset(dataset);
-
-      return chart;
+      Dataset    dataset = FeatureChartUtil.createDataset(fc,this);
+      return applyToDataset(dataset);
     }
 }

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2009-08-01 18:26:53 UTC (rev 276)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2009-08-01 19:55:40 UTC (rev 277)
@@ -45,6 +45,7 @@
 import org.jfree.chart.renderer.category.CategoryItemRenderer;
 import org.jfree.chart.renderer.xy.XYItemRenderer;
 import org.jfree.data.category.CategoryDataset;
+import org.jfree.data.category.DefaultCategoryDataset;
 import org.jfree.data.general.Dataset;
 import org.jfree.data.xy.XYDataset;
 import org.jfree.data.xy.XYSeries;
@@ -123,7 +124,8 @@
    * @param yAttr feature attribute(s) used for the Y-value (at least one; for each a
    *              series is created in the dataset)
    */
-  public static Dataset createDataset(FeatureCollection fc, boolean forceCat, boolean sort, String xAttr, String... yAttr) {
+  public static Dataset createDataset(FeatureCollection fc, FeatureChartStyle style) {
+    String xAttr = style.getAttributeName(0);
     // Check the X attribute to differ between XY- and CategoryDataset
     AttributeType xType = fc.getSchema().getAttributeType(xAttr);
     if ( xType == null )
@@ -131,29 +133,31 @@
 
     // If domain attribute is numeric (and category not forced) create
     // a XYDataset
-    if ( !forceCat && Number.class.isAssignableFrom(xType.getBinding()) )
-      ;//sdsd
+    if ( !style.isForceCategories() && Number.class.isAssignableFrom(xType.getBinding()) )
+      return createXYDataset(fc, style);
     else
-      ;//
-    
-    return null;
+      return createCategoryDataset(fc, style);
   }
   
   /**
-   * Checks whether an attribute exists and whether it is numeric.
+   * Checks whether an attribute exists and whether it is of
+   * a specific type.
    * Otherwise an {@link IllegalArgumentException} is thrown.
-   * @param fType a feature type
-   * @param aName the attribute name checked for numeric type
+   * @param fType       a feature type
+   * @param aName       the attribute name checked for numeric type
+   * @param typeToCheck the type the attribute must support (if {@code null}
+   *                    only the attribute existing is checked!)
    */
-  private static void checkAttributeNumeric(FeatureType fType, String aName, String... errDesc) {
+  private static void checkAttributeType(FeatureType fType, String aName, Class typeToCheck, String... errDesc) {
+    AttributeType aType = fType.getAttributeType(aName);
+    if ( aType == null )
+      throw new UnsupportedOperationException("Unknown attribute: "+aName);
+
     String attrDesc = errDesc.length > 0 ? errDesc[0] : "Attribute";
     String datasetDesc = errDesc.length > 1 ? errDesc[1] : "Dataset";
     
-    AttributeType aType = fType.getAttributeType(aName);
-    if ( aType == null )
-      throw new UnsupportedOperationException("Unknown attribute: "+aName);
-    if ( !Number.class.isAssignableFrom(aType.getBinding()) )
-      throw new UnsupportedOperationException(attrDesc+" must be numeric for "+datasetDesc+": "+aName);
+    if ( typeToCheck != null && !typeToCheck.isAssignableFrom(aType.getBinding()) )
+      throw new UnsupportedOperationException(attrDesc+" must be "+typeToCheck.getSimpleName()+" for "+datasetDesc+": "+aName);
   }
   
   /**
@@ -171,10 +175,10 @@
       throw new IllegalArgumentException("FeatureChartStyle must define at least 2 attributes to create XYDataset: "+attrCount);
     String xAttrName = chartStyle.getAttributeName(0);
     // check data types of X attribute
-    checkAttributeNumeric(fc.getSchema(), xAttrName, "Domain attribute", "XYDataset");
+    checkAttributeType(fc.getSchema(), xAttrName, Number.class, "Domain attribute", "XYDataset");
     // check data types of Y attribute
     for (int i=1; i<attrCount; i++)
-      checkAttributeNumeric(fc.getSchema(), chartStyle.getAttributeName(i), "Range attribute", "XYDataset");
+      checkAttributeType(fc.getSchema(), chartStyle.getAttributeName(i), Number.class, "Range attribute", "XYDataset");
     
     // Create a series for each range attribute (note: the 0
     // array element useless, but it is more comfortable to
@@ -237,4 +241,71 @@
     }
     return dataset;
   }
+
+  /**
+   * Creates a {@link XYDataset} for 2 (or more) attributes of a {@link FeatureCollection}.
+   * XYDateset can only be created for <b>numeric</b> attributes.
+   * @param fc    a {@link FeatureCollection}
+   * @param style defines the attributes used to create the dataset from, as well
+   *              as the sorting and normalization properties
+   * @throws IllegalArgumentException if less then 2 attributes are specified
+   * @throws UnsupportedOperationException if attributes are not numeric
+   */
+  public static DefaultCategoryDataset createCategoryDataset(FeatureCollection fc, FeatureChartStyle chartStyle) {
+    int attrCount = chartStyle.getAttributeCount();
+    if ( attrCount < 2 )
+      throw new IllegalArgumentException("FeatureChartStyle must define at least 2 attributes to create CategoryDataset: "+attrCount);
+    String xAttrName = chartStyle.getAttributeName(0);
+    // only check whether X attribute exists (numeric and not-numeric allowed)
+    checkAttributeType(fc.getSchema(), xAttrName, Comparable.class, "Domain attribute", "CategoryDataset");
+    // check data types of Y attribute (only numeric allowed)
+    for (int i=1; i<attrCount; i++)
+      checkAttributeType(fc.getSchema(), chartStyle.getAttributeName(i), Number.class, "Range attribute", "CategoryDataset");
+    
+    // Create a new dataset and insert the series
+    DefaultCategoryDataset       dataset   = new DefaultCategoryDataset();
+// TODO: Mapping for CategoryDataset!! (CategoryDataset is no SeriesDataset!)
+//    Feature2SeriesDatasetMapping mapping   = new Feature2SeriesDatasetMapping(fc,dataset);
+//    dataset.setGroup( new FeatureDatasetMetaData(mapping) );
+
+    // If dataset should be sorted, the features must be sorted first
+    // according to the domain attribute. CategoryDataset has no
+    // "autoSort", and this - at all - would not work (see createXYDataset(..))
+    Iterator<Feature> fi = null; 
+    if ( chartStyle.isSortDomainAxis() ) {
+      Vector<Feature> sortedFeatures = FeatureUtil.sortFeatures(fc.features(), xAttrName);
+      // Create an Iterator for the sorted Features
+      fi = sortedFeatures.iterator();
+    } else
+      fi = new PipedFeatureIterator( fc.features() );
+    
+    // Iterate the FeatureCollection and fill the series 
+    for (int fIdx=0; fi.hasNext(); fIdx++) {
+      Feature f = fi.next();
+      // Determine the category (NULL not permitted!)
+      Comparable catValue = (Comparable)f.getAttribute(xAttrName);
+      if ( catValue == null )
+        continue;
+      // Determine the Y values and fill the dataset
+      for (int attrIdx=1; attrIdx<attrCount; attrIdx++) {
+        String yAttrName = chartStyle.getAttributeName(attrIdx);
+        Number yValue    = (Number)f.getAttribute(yAttrName);
+//      // TODO: here maybe filtering the several NULL aliases
+//      if ( yValue is a NULL alias )
+//        yValue = null;
+//      // TODO: her maybe ignore NULL values completely        
+//      if ( yValue == null )
+//        continue;
+        
+        // Add data to dataset 
+        dataset.addValue(yValue, xAttrName, yAttrName);
+        
+//TODO: Implement the Mapping for CategoryDataset
+//        // Mapping between FID and data index in series
+//        mapping.setMapping(f.getID(), yAttrName, fIdx);
+      }
+      
+    }
+    return dataset;
+  }
 }

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java	2009-08-01 18:26:53 UTC (rev 276)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java	2009-08-01 19:55:40 UTC (rev 277)
@@ -183,16 +183,10 @@
    * 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)}.
-   * @see schmitzm.jfree.feature.style.FeatureChartStyle#applyToFeatureCollection(org.geotools.feature.FeatureCollection)
    */
   @Override
   public JFreeChart applyToFeatureCollection(FeatureCollection fc) {
-    // TODO: Check the attribute data and create a CategoryDataset if
-    //       a non-numeric column is specified
-    Dataset dataset = FeatureChartUtil.createXYDataset(
-        fc,
-        this
-    );
+    Dataset dataset = FeatureChartUtil.createDataset(fc,this);
     return applyToDataset(dataset);
   }
 }



More information about the Schmitzm-commits mailing list