/* Copyright 2013 The jeo project. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.jeo.postgis; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.sql.Connection; import java.sql.Statement; import java.util.Locale; import java.util.NoSuchElementException; import java.util.Set; import io.jeo.data.Cursor; import io.jeo.data.Dataset; import io.jeo.data.Handle; import io.jeo.vector.FeatureCursor; import io.jeo.vector.FeatureWriteCursor; import io.jeo.vector.VectorQuery; import io.jeo.vector.VectorDataset; import io.jeo.vector.Feature; import io.jeo.vector.Schema; import io.jeo.vector.SchemaBuilder; import io.jeo.geom.GeomBuilder; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.postgresql.ds.PGPoolingDataSource; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; public class PostGISTest { PostGISWorkspace pg; //uncomment to view debug logs during test // @BeforeClass // public static void logging() { // PostGISTests.logging(); // } @BeforeClass public static void connect() { PostGISTests.connect(); } @BeforeClass public static void setUpData() throws Exception { PostGISTests.setupStatesData(); } @Before public void rollback() throws Exception { PGPoolingDataSource ds = PostGISWorkspace.createDataSource(PostGISTests.OPTS); try (Connection cx = ds.getConnection()) { try (Statement st = cx.createStatement()) { st.executeUpdate( "DELETE FROM states WHERE \"STATE_NAME\" = 'JEOLAND' OR \"STATE_NAME\" is null"); st.executeUpdate("UPDATE states set \"STATE_ABBR\" = upper(\"STATE_ABBR\")"); st.executeUpdate("DROP TABLE IF EXISTS widgets"); } } ds.close(); } @Before public void setUp() throws Exception { pg = new PostGISWorkspace(PostGISTests.OPTS); } @After public void tearDown() throws Exception { pg.close(); } @Test public void testLayers() throws Exception { Iterables.find(pg.list(), refFor("states")); try { Iterables.find(pg.list(), refFor("geometry_columns")); fail(); } catch(NoSuchElementException e) {} try { Iterables.find(pg.list(), refFor("geography_columns")); fail(); } catch(NoSuchElementException e) {} try { Iterables.find(pg.list(), refFor("raster_columns")); fail(); } catch(NoSuchElementException e) {} try { Iterables.find(pg.list(), refFor("raster_overviews")); fail(); } catch(NoSuchElementException e) {} try { Iterables.find(pg.list(), refFor("topology")); fail(); } catch(NoSuchElementException e) {} } Predicate<Handle<Dataset>> refFor(final String name) { return new Predicate<Handle<Dataset>>() { @Override public boolean apply(Handle<Dataset> input) { return name.equals(input.name()); } }; } @Test public void testSchema() throws Exception { VectorDataset states = pg.get("states"); assertNotNull(states); Schema schema = states.schema(); assertNotNull(schema.field("STATE_NAME")); assertNotNull(schema.geometry()); assertEquals(MultiPolygon.class, schema.geometry().type()); assertNotNull(schema.crs()); assertEquals("EPSG:4326", schema.crs().getName()); } @Test public void testBounds() throws Exception { VectorDataset states = pg.get("states"); Envelope bounds = states.bounds(); assertNotNull(bounds); assertEquals(-124.7, bounds.getMinX(), 0.1); assertEquals(25.0, bounds.getMinY(), 0.1); assertEquals(-67.0, bounds.getMaxX(), 0.1); assertEquals(49.3, bounds.getMaxY(), 0.1); } @Test public void testCount() throws Exception { VectorDataset states = pg.get("states"); assertEquals(49, states.count(new VectorQuery())); } @Test public void testCountWithBounds() throws Exception { VectorDataset states = pg.get("states"); Set<String> abbrs = Sets.newHashSet("MO", "OK", "TX", "NM", "AR", "LA"); Envelope bbox = new Envelope(-106.649513, -93.507217, 25.845198, 36.493877); assertEquals(abbrs.size(), states.count(new VectorQuery().bounds(bbox))); } @Test public void testCursorRead() throws Exception { VectorDataset states = pg.get("states"); Cursor<Feature> c = states.read(new VectorQuery()); assertNotNull(c); for (int i = 0; i < 49; i++) { assertTrue(c.hasNext()); Feature f = c.next(); //assertEquals(new Integer(i+1), Integer.valueOf(f.getId())); assertNotNull(f); assertTrue(f.geometry() instanceof MultiPolygon); assertNotNull(f.get("STATE_NAME")); } assertFalse(c.hasNext()); assertNull(c.next()); c.close(); } @Test public void testCursorFilter() throws Exception { VectorDataset states = pg.get("states"); assertEquals(1, states.read(new VectorQuery().filter("STATE_NAME = 'Texas'")).count()); } @Test public void testCursorUpdate() throws Exception { VectorDataset states = pg.get("states"); FeatureWriteCursor c = states.update(new VectorQuery()); while(c.hasNext()) { Feature f = c.next(); String abbr = f.get("STATE_ABBR").toString(); assertEquals(abbr, abbr.toUpperCase(Locale.ROOT)); f.put("STATE_ABBR", f.get("STATE_ABBR").toString().toLowerCase(Locale.ROOT)); c.write(); } c.close(); for (Feature f : states.read(new VectorQuery())) { String abbr = f.get("STATE_ABBR").toString(); assertEquals(abbr, abbr.toLowerCase(Locale.ROOT)); } c.close(); } @Test public void testCursorInsert() throws Exception { VectorDataset states = pg.get("states"); Schema schema = states.schema(); FeatureWriteCursor c = states.append(new VectorQuery()); Feature f = c.next(); GeomBuilder gb = new GeomBuilder(); Geometry g = gb.point(0,0).point().buffer(1).toMultiPolygon(); f.put(schema.geometry().name(), g); f.put("STATE_NAME", "JEOLAND"); c.write(); c.close(); assertEquals(50, states.count(new VectorQuery())); FeatureCursor d = states.read(new VectorQuery().bounds(g.getEnvelopeInternal())); assertTrue(d.hasNext()); assertEquals("JEOLAND", d.next().get("STATE_NAME")); d.close(); } @Test public void testCreate() throws Exception { Schema widgets = new SchemaBuilder("widgets").field("shape", Polygon.class) .field("name", String.class).field("cost", Double.class).schema(); PostGISDataset data = pg.create(widgets); assertEquals(0, data.count(new VectorQuery())); GeomBuilder gb = new GeomBuilder(); FeatureWriteCursor c = data.append(new VectorQuery()); Feature f = c.next(); f.put("shape", gb.point(0,0).point().buffer(10).get()); f.put("name", "bomb"); f.put("cost", 1.99); c.write(); f = c.next(); f.put("shape", gb.points(0,0,1,1).lineString().buffer(1).get()); f.put("name", "dynamite"); f.put("cost", 2.99); c.write(); f = c.next(); f.put("shape", gb.points(-5,5, 5,5, 2,-2, 3,-5, -3,-5, -2,-2, -5,5).ring().toPolygon()); f.put("name", "anvil"); f.put("cost", 3.99); c.write(); c.close(); data = pg.get("widgets"); assertEquals(3, data.count(new VectorQuery())); FeatureCursor d = data.read(new VectorQuery().filter("name = 'bomb'")); assertTrue(d.hasNext()); assertEquals(1.99, d.next().get("cost")); d.close(); } }