[Schmitzm-commits] r920 - in trunk: src/schmitzm/geotools/feature src/schmitzm/jfree/feature/style src_junit/schmitzm/geotools/feature src_junit/schmitzm/jfree/feature/style
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Jul 1 17:45:24 CEST 2010
Author: mojays
Date: 2010-07-01 17:45:20 +0200 (Thu, 01 Jul 2010)
New Revision: 920
Added:
trunk/src/schmitzm/geotools/feature/FeatureComparator.java
trunk/src_junit/schmitzm/geotools/feature/FeatureComparatorTest.java
Modified:
trunk/src/schmitzm/geotools/feature/FeatureUtil.java
trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java
Log:
new FeatureComparator to compare features by multiple attributes
new FeatureComparatorTest
FeatureUtil.sortFeatures(.): support of multiple ordering attributes
FeatureChartUtil: Sorting features also by series attribute (on grouping) during dataset creation with sorted domain axis
Added: trunk/src/schmitzm/geotools/feature/FeatureComparator.java
===================================================================
--- trunk/src/schmitzm/geotools/feature/FeatureComparator.java 2010-07-01 13:34:07 UTC (rev 919)
+++ trunk/src/schmitzm/geotools/feature/FeatureComparator.java 2010-07-01 15:45:20 UTC (rev 920)
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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. Krüger - additional utility classes
+ ******************************************************************************/
+
+package schmitzm.geotools.feature;
+
+import java.util.Comparator;
+
+import org.geotools.feature.FeatureComparators;
+import org.opengis.feature.simple.SimpleFeature;
+
+/**
+ * This class is an extension of {@link FeatureComparators.Name}.
+ * In contrast to {@link FeatureComparators.Name}, respectively
+ * {@link FeatureComparators.Index}, this class allows to specify MULTIPLE
+ * attributes (names or indices) which are compared sequently.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public class FeatureComparator implements Comparator<SimpleFeature> {
+
+ /** Holds the comparators for each attribute which is included in
+ * the comparison. */
+ protected Comparator<SimpleFeature>[] attrComp = null;
+
+ /**
+ * Creates a new comparator.
+ * @param attrName compare attributes in the order of comparison.
+ */
+ public FeatureComparator(String... attrName) {
+ if ( attrName == null || attrName.length < 1 )
+ throw new IllegalArgumentException("At least one attribute must be specified for FeatureComparator.");
+ // Create comparators for each attribute
+ this.attrComp = new Comparator[attrName.length];
+ for (int i=0; i<attrComp.length; i++) {
+ if ( attrName[i] == null )
+ throw new IllegalArgumentException("NULL not allowed as comparation attribute: "+i);
+ this.attrComp[i] = FeatureComparators.byAttributeName(attrName[i]);
+ }
+ }
+
+ /**
+ * Creates a new comparator.
+ * @param attrIdx compare attributes (by index) in the order of comparison.
+ */
+ public FeatureComparator(int... attrIdx) {
+ if ( attrIdx == null || attrIdx.length < 1 )
+ throw new IllegalArgumentException("At least one attribute must be specified for FeatureComparator.");
+ // Create comparators for each attribute
+ this.attrComp = new Comparator[attrIdx.length];
+ for (int i=0; i<attrComp.length; i++) {
+ if ( attrIdx[i] < 0 )
+ throw new IllegalArgumentException("Negative indices are not allowed as comparation attribute: "+i+" ("+attrIdx[i]+")");
+ this.attrComp[i] = FeatureComparators.byAttributeIndex(attrIdx[i]);
+ }
+ }
+
+ /**
+ * Compares all comparison attributes of two features.
+ * @return a negative value if {@code f1 < f2}, a positive value if {@code f1 > f2} or
+ * zero if {@code f1} and {@code f2} equal in all comparison attributes.
+ */
+ @Override
+ public int compare(SimpleFeature f1, SimpleFeature f2) {
+ for (int i=0; i<attrComp.length; i++) {
+ int comp = attrComp[i].compare(f1, f2);
+ if ( comp != 0 )
+ return comp;
+ }
+ // no difference in all attributes
+ // -> Features are equal
+ return 0;
+ }
+
+}
Modified: trunk/src/schmitzm/geotools/feature/FeatureUtil.java
===================================================================
--- trunk/src/schmitzm/geotools/feature/FeatureUtil.java 2010-07-01 13:34:07 UTC (rev 919)
+++ trunk/src/schmitzm/geotools/feature/FeatureUtil.java 2010-07-01 15:45:20 UTC (rev 920)
@@ -780,12 +780,12 @@
* @param fi
* the features to order
* @param attrName
- * the attribute to order by
+ * the attribute(s) to order by
* @return a list of ordered features
*/
public static Vector<SimpleFeature> sortFeatures(
FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
- String attrName) {
+ String... attrName) {
final FeatureCollection<SimpleFeatureType, SimpleFeature> source = fc;
FeatureIterator<SimpleFeature> iterator = source.features();
try {
@@ -806,35 +806,52 @@
* @param fi
* an iterator for the features
* @param attrName
- * the attribute to order by
+ * the attribute(s) to order by
* @return a list of ordered features
*/
protected static Vector<SimpleFeature> sortFeatures(
- FeatureIterator<SimpleFeature> fi, String attrName) {
+ FeatureIterator<SimpleFeature> fi, String... attrName) {
+
+ // Create a comparator for sorting in order to
+ // the sort attributes
+ FeatureComparator fComp = new FeatureComparator(attrName);
+
+
// First create a SortedMap with CollisionList
- SortedMap<Comparable<?>, Vector<SimpleFeature>> sortedFeatureLists = new TreeMap<Comparable<?>, Vector<SimpleFeature>>();
+ SortedMap<SimpleFeature, Vector<SimpleFeature>> sortedFeatureLists = new TreeMap<SimpleFeature, Vector<SimpleFeature>>(fComp);
+
for (; fi.hasNext();) {
SimpleFeature f = fi.next();
- // Check whether attribute value is Comparable
- Object attrValue = f.getAttribute(attrName);
- if (attrValue != null && !(attrValue instanceof Comparable))
- throw new UnsupportedOperationException(
- "SimpleFeature sort only supported for Comparable attributes: "
- + LangUtil.getSimpleClassName(attrValue));
- // Determine X value as sort attribute (NULL not permitted for
- // XYDateset!)
- Comparable<?> xValue = (Comparable<?>) attrValue;
- if (xValue == null)
- continue;
+// // Check whether attribute value is Comparable
+// Object attrValue = f.getAttribute(attrName);
+// if (attrValue != null && !(attrValue instanceof Comparable))
+// throw new UnsupportedOperationException(
+// "SimpleFeature sort only supported for Comparable attributes: "
+// + LangUtil.getSimpleClassName(attrValue));
+// // Determine X value as sort attribute (NULL not permitted for
+// // XYDateset!)
+// Comparable<?> xValue = (Comparable<?>) attrValue;
+// if (xValue == null)
+// continue;
+//
+// // Check whether collision list exists
+// Vector<SimpleFeature> collList = sortedFeatureLists.get(xValue);
+// if (collList == null) {
+// collList = new Vector<SimpleFeature>();
+// sortedFeatureLists.put(xValue, collList);
+// }
+// // Add feature to collision list
+// collList.add(f);
- // Check whether collision list exists
- Vector<SimpleFeature> collList = sortedFeatureLists.get(xValue);
- if (collList == null) {
- collList = new Vector<SimpleFeature>();
- sortedFeatureLists.put(xValue, collList);
- }
- // Add feature to collision list
- collList.add(f);
+ // Check whether collision list exists
+ Vector<SimpleFeature> collList = sortedFeatureLists.get(f);
+ if (collList == null) {
+ collList = new Vector<SimpleFeature>();
+ sortedFeatureLists.put(f, collList);
+ }
+ // Add feature to collision list
+ collList.add(f);
+
}
// Put the (now ordered) features from the collision lists
Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java 2010-07-01 13:34:07 UTC (rev 919)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java 2010-07-01 15:45:20 UTC (rev 920)
@@ -253,8 +253,14 @@
FeatureIterator<SimpleFeature> features = null;
Iterator<SimpleFeature> fi = null;
if (chartStyle.isSortDomainAxis()) {
- Vector<SimpleFeature> sortedFeatures = FeatureUtil.sortFeatures(fc,
- xAttrName);
+ // Sorting attribute(s) -> Category attribute
+ String[] sortAttr = new String[] {xAttrName};
+ // If grouping is used so create series, also sort by
+ // this attribute, so that the series are also sorted
+ // "inside" every category
+ if ( chartStyle.getSeriesAttributeName() != null )
+ sortAttr = LangUtil.extendArray(sortAttr, chartStyle.getSeriesAttributeName());
+ Vector<SimpleFeature> sortedFeatures = FeatureUtil.sortFeatures(fc,sortAttr);
// Create an Iterator for the sorted Features
fi = sortedFeatures.iterator();
} else {
@@ -660,8 +666,14 @@
FeatureIterator<SimpleFeature> features = null;
Iterator<SimpleFeature> fi = null;
if (chartStyle.isSortDomainAxis()) {
- Vector<SimpleFeature> sortedFeatures = FeatureUtil.sortFeatures(fc,
- xAttrName);
+ // Sorting attribute(s) -> Category attribute
+ String[] sortAttr = new String[] {xAttrName};
+ // If grouping is used so create series, also sort by
+ // this attribute, so that the series are also sorted
+ // "inside" every category
+ if ( chartStyle.getSeriesAttributeName() != null )
+ sortAttr = LangUtil.extendArray(sortAttr, chartStyle.getSeriesAttributeName());
+ Vector<SimpleFeature> sortedFeatures = FeatureUtil.sortFeatures(fc,sortAttr);
// Create an Iterator for the sorted Features
fi = sortedFeatures.iterator();
} else {
Added: trunk/src_junit/schmitzm/geotools/feature/FeatureComparatorTest.java
===================================================================
--- trunk/src_junit/schmitzm/geotools/feature/FeatureComparatorTest.java 2010-07-01 13:34:07 UTC (rev 919)
+++ trunk/src_junit/schmitzm/geotools/feature/FeatureComparatorTest.java 2010-07-01 15:45:20 UTC (rev 920)
@@ -0,0 +1,109 @@
+package schmitzm.geotools.feature;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.GraphicsEnvironment;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.geotools.feature.FeatureCollection;
+import org.geotools.feature.FeatureIterator;
+import org.junit.Test;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
+import org.opengis.feature.type.GeometryDescriptor;
+
+import schmitzm.geotools.feature.FeatureUtil.GeometryForm;
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.jfree.feature.style.FeatureChartStyleTest;
+
+import com.vividsolutions.jts.geom.Point;
+import com.vividsolutions.jts.geom.Polygon;
+
+
+public class FeatureComparatorTest {
+ /** If tests are run on a system with head, we may theoretically open dialgs, frames etc. **/
+
+ boolean INTERACTIVE = !GraphicsEnvironment.isHeadless();
+
+ String resLocation = "/schmitzm/jfree/feature/style/testLineChartShape/testKreiseLineChart.shp";
+
+ @Test
+ public void testFeatureComparator() throws Exception {
+ // Testdatenshape einlesen
+ URL resourceUrl = FeatureChartStyleTest.class.getResource(
+ resLocation);
+ assertNotNull(resLocation+" wurde nicht gefunden!",
+ resourceUrl);
+ FeatureCollection<SimpleFeatureType, SimpleFeature> testFeatures = GeoImportUtil
+ .readFeaturesFromShapeURL(resourceUrl);
+ assertNotNull("Testfeatures konnten nicht aus " + resourceUrl
+ + " gelesen werden", testFeatures);
+
+ String[] sortAttr = new String[] {"dm_u3","jahr" };
+
+ // Show features unsorted
+ System.out.println("**** FEATURES UNSORTED ****");
+ showFeatures(new PipedFeatureIterator(testFeatures.features()),false,sortAttr);
+ // Sort features
+ Vector<SimpleFeature> testFeaturesSorted = FeatureUtil.sortFeatures(testFeatures, sortAttr);
+ // Show features unsorted
+ System.out.println("**** FEATURES SORTED ****");
+ showFeatures(testFeaturesSorted.iterator(),true,sortAttr);
+
+
+
+ }
+
+ /**
+ * Shows features.
+ * @param fi an iterator for the features
+ * @param checkSorting indicates whether the ordering is checked during showing
+ * @param attrName the attributes which are shown (and checked for ordering)
+ */
+ private void showFeatures(Iterator<SimpleFeature> fi, boolean checkSorting, String... attrName) {
+ // Show features unsorted
+ SimpleFeature lastFeature = null;
+ for (;fi.hasNext();) {
+ SimpleFeature f = fi.next();
+ // Show ID and the specified attributes
+ if ( INTERACTIVE ) {
+ System.out.print(f.getID() + "\t");
+ for (String name : attrName)
+ System.out.print( f.getAttribute(name) + "\t");
+ System.out.println();
+ }
+ // Check sorting if at least 2 Features are present (optional)
+ if ( checkSorting && lastFeature != null )
+ checkAscendingSort(lastFeature,f,attrName);
+
+ lastFeature = f;
+ }
+ }
+
+ /**
+ * Checks whether f1 <= f2 by fundamental methods :-)
+ * If not an assertion is thrown.
+ * @param lastFeature a feature
+ * @param f another feature
+ */
+ private void checkAscendingSort(SimpleFeature f1, SimpleFeature f2, String... attrName) {
+ for (String name : attrName) {
+ Object a1 = f1.getAttribute(name);
+ Object a2 = f2.getAttribute(name);
+ // Attribute values must be Comparable
+ assertTrue("a1 must be Comparable", a1 instanceof Comparable);
+ assertTrue("a2 must be Comparable", a2 instanceof Comparable);
+
+ // f1 must be <= f2
+ int comp = ((Comparable)a1).compareTo(a2);
+ assertTrue("a1."+name+" must be <= a2."+name+"("+a1+" <= "+a2+")", comp <= 0);
+ // if f1 < f2, the other attributes must be ignored
+ if ( comp < 0 )
+ break;
+ }
+ }
+}
Modified: trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java
===================================================================
--- trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java 2010-07-01 13:34:07 UTC (rev 919)
+++ trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java 2010-07-01 15:45:20 UTC (rev 920)
@@ -106,6 +106,8 @@
barChartStyle.setTooltips(true);
barChartStyle.setSeriesAttributeName(groupAttribName);
+
+ barChartStyle.setSortDomainAxis(true);
assertNull("Wenn nicht explizit gesetzt wird null geliefert",
barChartStyle.getRendererStyle(0));
More information about the Schmitzm-commits
mailing list