package org.geotools.data.csv; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.Serializable; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.geotools.data.DataStore; import org.geotools.data.Query; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.data.simple.SimpleFeatureStore; import org.geotools.factory.CommonFactoryFinder; import org.geotools.feature.DefaultFeatureCollection; import org.geotools.feature.simple.SimpleFeatureImpl; import org.geotools.filter.identity.FeatureIdImpl; import org.geotools.geometry.jts.JTSFactoryFinder; import org.geotools.geometry.jts.ReferencedEnvelope; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Point; /** * Test the CSVDataStore * * * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/unsupported/csv/src/test/java/org/geotools/data/csv/CSVDataStoreTest.java $ */ public class CSVDataStoreTest { private static final String TYPE_NAME = "locations"; private static final String TEST_FILE_NAME = TYPE_NAME + ".csv"; private static final String NUMBER_COL = "NUMBER"; private static final String CITY_COL = "CITY"; private File testFile; /** * Create a CSV file for the rest of the tests to use. * The features have 3 attributes, but "coordinate" is broken out into separate LAT/LON columns in the file. */ @Before public void createTestFile() throws IOException { File tempDir = new File(System.getProperty("java.io.tmpdir") + "/csvDataStoreTest"); if (!tempDir.exists()) { tempDir.mkdir(); } this.testFile = new File(tempDir, TEST_FILE_NAME); if (!this.testFile.exists()) { this.testFile.createNewFile(); } BufferedWriter writer = new BufferedWriter( new FileWriter( this.testFile ) ); writer.append("LAT, LON, CITY, NUMBER"); writer.newLine(); writer.append("46.066667, 11.116667, Trento, 140"); writer.newLine(); writer.append("44.9441, -93.0852, St Paul, 125"); writer.newLine(); writer.append("13.752222, 100.493889, Bangkok, 150"); writer.newLine(); writer.append("45.420833, -75.69, Ottawa, 200"); writer.newLine(); writer.append("44.9801, -93.251867, Minneapolis, 350"); writer.newLine(); writer.append("46.519833, 6.6335, Lausanne, 560"); writer.newLine(); writer.append("48.428611, -123.365556, Victoria, 721"); writer.newLine(); writer.append("-33.925278, 18.423889, Cape Town, 550"); writer.newLine(); writer.append("-33.859972, 151.211111, Sydney, 436"); writer.newLine(); writer.close(); } @After public void deleteTestFile() { testFile.delete(); } /** * Test basic loading/reading of CSV file. */ @Test public void testLoad() throws Exception { DataStore csv = this.getDataStore(); String[] names = csv.getTypeNames(); assertEquals( 1, names.length ); String typeName = names[0]; assertEquals( TYPE_NAME, typeName); SimpleFeatureType schema = csv.getSchema( typeName ); assertEquals( 3, schema.getAttributeCount() ); assertTrue( schema.getGeometryDescriptor().getType().getBinding().isAssignableFrom( Point.class )); SimpleFeatureSource rows = csv.getFeatureSource( typeName ); assertNotNull( rows ); int count = rows.getCount(Query.ALL); assertEquals( 9, count ); ReferencedEnvelope bounds = rows.getBounds(); assertFalse( bounds.isEmpty() || bounds.isNull() ); SimpleFeatureCollection features = rows.getFeatures(); SimpleFeatureIterator cursor = features.features(); Set<String> found = new HashSet<String>(); try { while( cursor.hasNext()){ SimpleFeature feature = cursor.next(); found.add( feature.getID() ); } String expected = TYPE_NAME + ".4"; System.out.println( found ); assertTrue( expected, found.contains( expected )); } finally { cursor.close(); } } private DataStore getDataStore() throws FileNotFoundException, IOException { assertTrue( this.testFile.exists() ); DataStore csv = new CSVDataStore( this.testFile ); return csv; } @Test public void testFactory() throws FileNotFoundException, IOException { Map<String, Serializable> params = new HashMap<String, Serializable>(); params.put("file", this.testFile); DataStore ds = new CSVDataStoreFactory().createDataStore(params); assertNotNull(ds); assertEquals("locations", ds.getNames().get(0).getLocalPart()); assertEquals("locations", ds.getTypeNames()[0]); } /** * Test basic filtering. */ @Test public void testFilter() throws FileNotFoundException, IOException { DataStore csv = this.getDataStore(); SimpleFeatureSource rows = csv.getFeatureSource( TYPE_NAME ); SimpleFeatureCollection matches = rows.getFeatures(this.newTestFilter()); List<String> filteredCities = this.filteredCities(); int count = 0; SimpleFeatureIterator iter = matches.features(); while(iter.hasNext()) { SimpleFeature f = iter.next(); filteredCities.contains(f.getAttribute(CITY_COL)); count++; } iter.close(); assertEquals(3, count); assertEquals(3, matches.size()); } /** * Test FeatureStore/Writer update */ @Test public void testUpdate() throws FileNotFoundException, IOException { DataStore csv = this.getDataStore(); SimpleFeatureStore rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); rows.modifyFeatures(NUMBER_COL, 333, this.newTestFilter()); // re-open csv = this.getDataStore(); rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); SimpleFeatureCollection features = rows.getFeatures(); assertEquals(9, features.size()); SimpleFeatureIterator cursor = features.features(); List<String> filteredCities = this.filteredCities(); while (cursor.hasNext()) { SimpleFeature feature = cursor.next(); if (filteredCities.contains(feature.getAttribute(CITY_COL))) { assertEquals("333", feature.getAttribute(NUMBER_COL)); } else { assertNotSame("333", feature.getAttribute(NUMBER_COL)); } } cursor.close(); } @Test public void testUpdateAll() throws FileNotFoundException, IOException { DataStore csv = this.getDataStore(); SimpleFeatureStore rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); rows.modifyFeatures(NUMBER_COL, 333, Filter.INCLUDE); // re-open csv = this.getDataStore(); rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); SimpleFeatureCollection features = rows.getFeatures(); assertEquals(9, features.size()); SimpleFeatureIterator cursor = features.features(); while (cursor.hasNext()) { SimpleFeature feature = cursor.next(); assertEquals("333", feature.getAttribute(NUMBER_COL)); } cursor.close(); } @Test public void testUpdateNone() throws FileNotFoundException, IOException { DataStore csv = this.getDataStore(); SimpleFeatureStore rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); rows.modifyFeatures(NUMBER_COL, 333, Filter.EXCLUDE); // re-open csv = this.getDataStore(); rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); SimpleFeatureCollection features = rows.getFeatures(); assertEquals(9, features.size()); SimpleFeatureIterator cursor = features.features(); while (cursor.hasNext()) { SimpleFeature feature = cursor.next(); assertNotSame("333", feature.getAttribute(NUMBER_COL)); } cursor.close(); } private Filter newTestFilter() { // Filter collects entries with number > 500 FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); return ff.greater(ff.property(NUMBER_COL), ff.literal(500)); } private List<String> filteredCities() { return Arrays.asList("Lausanne", "Victoria", "Cape Town"); } private Point newPoint(Coordinate coords) { return JTSFactoryFinder.getGeometryFactory(null).createPoint(coords); } /** * Test remove */ @Test public void testRemove() throws FileNotFoundException, IOException { DataStore csv = this.getDataStore(); SimpleFeatureStore rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); rows.removeFeatures(this.newTestFilter()); // re-open csv = this.getDataStore(); rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); SimpleFeatureCollection features = rows.getFeatures(); assertEquals(6, features.size()); } @Test public void testRemoveAll() throws FileNotFoundException, IOException { DataStore csv = this.getDataStore(); SimpleFeatureStore rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); rows.removeFeatures(Filter.INCLUDE); // re-open csv = this.getDataStore(); rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); SimpleFeatureCollection features = rows.getFeatures(); assertEquals(0, features.size()); } /** * Test add * @throws IOException * @throws FileNotFoundException */ @Test public void testAdd() throws FileNotFoundException, IOException { DataStore csv = this.getDataStore(); SimpleFeatureStore rows = (SimpleFeatureStore) csv.getFeatureSource(TYPE_NAME); SimpleFeatureType featureType = csv.getSchema(TYPE_NAME); DefaultFeatureCollection toAdd = new DefaultFeatureCollection("test", featureType); SimpleFeature newFeature = new SimpleFeatureImpl(new Object[] {this.newPoint(new Coordinate(12, 34)), "Manhattan Beach", 444}, featureType, new FeatureIdImpl("test"), false); toAdd.add(newFeature); rows.addFeatures(toAdd); // re-open csv = this.getDataStore(); rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); SimpleFeatureCollection features = rows.getFeatures(); assertEquals(10, features.size()); } /** * Test add more than one. * @throws IOException * @throws FileNotFoundException */ @Test public void testAddSeveral() throws FileNotFoundException, IOException { DataStore csv = this.getDataStore(); SimpleFeatureStore rows = (SimpleFeatureStore) csv.getFeatureSource(TYPE_NAME); SimpleFeatureType featureType = csv.getSchema(TYPE_NAME); DefaultFeatureCollection toAdd = new DefaultFeatureCollection("test", featureType); SimpleFeature newFeature = new SimpleFeatureImpl(new Object[] {this.newPoint(new Coordinate(12, 34)), "Manhattan Beach", 444}, featureType, new FeatureIdImpl("test1"), false); toAdd.add(newFeature); newFeature = new SimpleFeatureImpl(new Object[] {this.newPoint(new Coordinate(56, 78)), "Hermosa Beach", 555}, featureType, new FeatureIdImpl("test2"), false); toAdd.add(newFeature); newFeature = new SimpleFeatureImpl(new Object[] {this.newPoint(new Coordinate(90, 12)), "Redondo Beach", 666}, featureType, new FeatureIdImpl("test3"), false); toAdd.add(newFeature); rows.addFeatures(toAdd); // re-open csv = this.getDataStore(); rows = (SimpleFeatureStore) csv.getFeatureSource( TYPE_NAME ); SimpleFeatureCollection features = rows.getFeatures(); assertEquals(12, features.size()); } }