001: /*
002: * Geotools2 - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */
017: package org.geotools.data.geometryless;
018:
019: import java.io.BufferedReader;
020: import java.io.IOException;
021: import java.io.InputStreamReader;
022: import java.sql.Connection;
023: import java.sql.PreparedStatement;
024: import java.sql.SQLException;
025: import java.sql.Statement;
026: import java.util.HashMap;
027: import java.util.NoSuchElementException;
028: import java.util.PropertyResourceBundle;
029: import java.util.logging.Level;
030: import java.util.logging.Logger;
031:
032: import javax.sql.DataSource;
033:
034: import junit.framework.Test;
035: import junit.framework.TestCase;
036: import junit.framework.TestSuite;
037:
038: import org.geotools.data.FeatureReader;
039: import org.geotools.data.FeatureWriter;
040: import org.geotools.data.SchemaNotFoundException;
041: import org.geotools.data.Transaction;
042: import org.geotools.data.jdbc.ConnectionPool;
043: import org.geotools.data.jdbc.ConnectionPoolManager;
044: import org.geotools.data.jdbc.datasource.DataSourceUtil;
045: import org.geotools.data.jdbc.fidmapper.BasicFIDMapper;
046: import org.geotools.data.jdbc.fidmapper.TypedFIDMapper;
047: import org.geotools.feature.Feature;
048: import org.geotools.feature.FeatureType;
049: import org.geotools.feature.IllegalAttributeException; //import org.opengis.filter.BinaryComparisonOperator;
050: import org.opengis.feature.GeometryAttribute;
051: import org.opengis.filter.PropertyIsEqualTo;
052:
053: import org.opengis.filter.expression.Expression;
054: import org.opengis.filter.Filter;
055:
056: import org.opengis.filter.FilterFactory;
057: import org.geotools.factory.CommonFactoryFinder;
058: import org.geotools.filter.IllegalFilterException;
059:
060: import com.vividsolutions.jts.geom.Coordinate;
061: import com.vividsolutions.jts.geom.Geometry;
062: import com.vividsolutions.jts.geom.GeometryFactory;
063: import com.vividsolutions.jts.geom.LinearRing;
064: import com.vividsolutions.jts.geom.MultiPolygon;
065: import com.vividsolutions.jts.geom.Point;
066: import com.vividsolutions.jts.geom.Polygon;
067:
068: //import com.vividsolutions.jts.geom.PrecisionModel;
069:
070: /**
071: * Test for Geometryless generic JDBC Data store. Must use a locally available instance of JDBC database.
072: *
073: * @author Rob Atkinson
074: * @author Chris Holmes, TOPP
075: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/geometryless/src/test/java/org/geotools/data/geometryless/LocationsXYDataStoreTest.java $
076: */
077: public class LocationsXYDataStoreTest extends TestCase {
078: /** The logger for the filter module. */
079: private static final Logger LOGGER = org.geotools.util.logging.Logging
080: .getLogger("org.geotools.data.geometryless");
081: private static String FEATURE_TABLE = "testset";
082: private static String TEST_NS = "http://www.geotools.org/data/postgis";
083: // private static GeometryFactory geomFac = new GeometryFactory();
084: private static String GEOM_NAME = "location";
085: private FilterFactory filterFac = CommonFactoryFinder
086: .getFilterFactory(null);
087:
088: //private FeatureCollection collection = FeatureCollections.newCollection();
089: private FeatureType schema;
090: //private int srid = -1;
091: private JDBCConnectionFactory connFactory;
092: private LocationsXYDataStore dstore;
093: private ConnectionPool connPool;
094: // private tFilter;
095: private int addId = 32;
096:
097: // private org.geotools.filter.GeometryFilter geomFilter;
098:
099: public LocationsXYDataStoreTest(String testName) {
100: super (testName);
101: }
102:
103: public static void main(String[] args) {
104: junit.textui.TestRunner.run(suite());
105: }
106:
107: public static Test suite() {
108: LOGGER.info("starting suite...");
109:
110: TestSuite suite = new TestSuite(LocationsXYDataStoreTest.class);
111: LOGGER.info("made suite...");
112:
113: return suite;
114: }
115:
116: protected void setUp() throws Exception {
117:
118: HashMap local = new HashMap();
119: local.put("dbtype", "jdbc");
120:
121: PropertyResourceBundle resource = new PropertyResourceBundle(
122: this .getClass().getResourceAsStream(
123: "fixture.properties"));
124:
125: String namespace = resource.getString("namespace");
126: String user = resource.getString("user");
127: local.put("user", user);
128: String password = resource.getString("password");
129: local.put("passwd", password);
130:
131: String dbschema = resource.getString("schema");
132: local.put("schema", dbschema);
133:
134: String driver = resource.getString("driver");
135: local.put("driver", driver);
136:
137: String urlprefix = resource.getString("urlprefix");
138: local.put("urlprefix", urlprefix);
139:
140: String xcolumn = resource.getString("xcolumn");
141: local.put("xcolumn", xcolumn);
142: String ycolumn = resource.getString("ycolumn");
143: local.put("ycolumn", ycolumn);
144: if (namespace.equals("http://www.geotools.org/data/postgis")) {
145: throw new IllegalStateException(
146: "The fixture.properties file needs to be configured for your own database");
147: }
148: /*
149: connFactory = new JDBCConnectionFactory( urlprefix, Driver);
150:
151: //connFactory = new PostgisConnectionFactory("localhost", "5432",
152: // "testdb");
153: //LOGGER.info("created new db connection");
154: connFactory.setLogin(user, password);
155: */
156: //LOGGER.info("set the login");
157: //LOGGER.info("created new datasource");
158: try {
159: DataSource dataSource = DataSourceUtil
160: .buildDefaultDataSource(urlprefix, driver, user,
161: password, null);
162:
163: /* connPool = connFactory.getConnectionPool();
164: */
165: setupTestTable(dataSource.getConnection());
166: dstore = new LocationsXYDataStore(dataSource, dbschema,
167: TEST_NS, xcolumn, ycolumn, GEOM_NAME);
168:
169: dstore.setFIDMapper("testset", new TypedFIDMapper(
170: new BasicFIDMapper("gid", 255, true), "testset"));
171:
172: //LOGGER.fine("about to create ds");
173: //postgis = new PostgisDataSource(connection, FEATURE_TABLE);
174: //LOGGER.fine("created de");
175: schema = dstore.getSchema(FEATURE_TABLE);
176: } catch (Exception e) {
177: LOGGER.log(Level.INFO, "exception while making schema", e);
178: }
179: }
180:
181: /**
182: * @param connection
183: */
184: private void setupTestTable(Connection conn) throws IOException,
185: SQLException {
186: // gid;int4;4;0;;YES;;
187: // area;float8;8;0;;YES;;
188: // perimeter;float8;8;0;;YES;;
189: // testb_;int4;4;0;;YES;;
190: // testb_id;int4;4;0;;YES;;
191: // name;varchar;0;0;;YES;;
192: // pcedflag;int4;4;0;;YES;;
193: // dbdflag;int4;4;0;;YES;;
194: // the_geom;geometry;-1;0;;YES;;
195:
196: Statement st = conn.createStatement();
197: try {
198: st.execute("DROP TABLE testset");
199: } catch (Exception e) {
200: }
201: st
202: .execute("CREATE TABLE testset ( gid integer, area real, perimeter real, testb_ integer, "
203: + " testb_id integer, name varchar(255), pcedflag integer, dbdflag integer, x real, y real)");
204: st.close();
205: PreparedStatement ps = conn
206: .prepareStatement("INSERT into testset values(?, ?, ?, ?, ?, ?, ?, ?, ?,?)");
207: BufferedReader reader = new BufferedReader(
208: new InputStreamReader(this .getClass()
209: .getResourceAsStream("testdata.txt")));
210:
211: try {
212:
213: String line = null;
214: while ((line = reader.readLine()) != null) {
215: String[] values = line.split(";");
216: ps.setInt(1, Integer.parseInt(values[0]));
217: ps.setDouble(2, Double.parseDouble(values[1]));
218: ps.setDouble(3, Double.parseDouble(values[2]));
219: ps.setInt(4, Integer.parseInt(values[3]));
220: ps.setInt(5, Integer.parseInt(values[4]));
221: ps.setString(6, values[5]);
222: ps.setInt(7, Integer.parseInt(values[6]));
223: ps.setInt(8, Integer.parseInt(values[7]));
224: ps.setDouble(9, Double.parseDouble(values[8]));
225: ps.setDouble(10, Double.parseDouble(values[9]));
226: ps.execute();
227: }
228: } finally {
229: reader.close();
230: ps.close();
231: }
232: }
233:
234: protected void tearDown() {
235: try {
236: // dropTestTable(connPool.getConnection());
237: } catch (Exception e) {
238: } finally {
239: ConnectionPoolManager.getInstance().closeAll();
240: }
241: }
242:
243: public void dropTestTable(Connection conn) throws SQLException {
244: Statement st = conn.createStatement();
245: st.execute("DROP TABLE testset");
246: }
247:
248: //todo assert on schema.
249: public void testFeatureTypes() throws Exception {
250: String[] types = dstore.getTypeNames();
251: FeatureType schema1 = dstore.getSchema(types[0]);
252:
253: //FeatureType schema2 = dstore.getSchema(types[1]);
254: //need to figure out spatial_ref_system and geometry_columns
255: LOGGER.fine("first schemas are: \n" + schema1); // + "\n" + schema2);
256:
257: try {
258: String badSchema = "bad-schema23";
259: dstore.getSchema(badSchema);
260: fail("should not have schema " + badSchema);
261: } catch (SchemaNotFoundException e) {
262: LOGGER.fine("succesfully caught exception: " + e);
263:
264: //catch the proper exception
265: }
266: }
267:
268: //tests todo: bad retyping. post filters.
269: public void testGetReader() throws Exception {
270: String testTable = FEATURE_TABLE;
271: LOGGER.fine("testTable " + testTable + " has schema "
272: + dstore.getSchema(testTable));
273:
274: FeatureReader reader = dstore.getFeatureReader(schema,
275: Filter.INCLUDE, Transaction.AUTO_COMMIT);
276: int numFeatures = count(reader);
277: assertEquals("Number of features off:", 6, numFeatures);
278: // reader.close(); //done in count()
279: }
280:
281: public void testFilter() throws Exception {
282: PropertyIsEqualTo test1 = null;
283:
284: try {
285: Integer testInt = new Integer(0);
286: Expression testLiteral = filterFac.literal(testInt);
287: Expression testProperty = filterFac.property("pcedflag");
288: test1 = filterFac.equals(testLiteral, testProperty);
289:
290: // test1.addLeftValue(testLiteral);
291: // test1.addRightValue(filterFac.createAttributeExpression(schema, "pcedflag"));
292: } catch (IllegalFilterException e) {
293: fail("Illegal Filter Exception " + e);
294: }
295:
296: // Query query = new DefaultQuery(FEATURE_TABLE, test1);
297: FeatureReader reader = dstore.getFeatureReader(schema, test1,
298: Transaction.AUTO_COMMIT);
299: assertEquals("Number of filtered features off:", 2,
300: count(reader));
301: // reader.close(); done in count()
302: }
303:
304: public void testGeometry() throws Exception {
305: String testTable = FEATURE_TABLE;
306: LOGGER.info("testTable " + testTable + " has schema "
307: + dstore.getSchema(testTable));
308:
309: FeatureReader reader = dstore.getFeatureReader(schema,
310: Filter.INCLUDE, Transaction.AUTO_COMMIT);
311: Feature feature = reader.next();
312: reader.close();
313:
314: LOGGER.info("feature is: " + feature);
315: /* Geometry geom = feature.getDefaultGeometry();
316: LOGGER.info("geometry is " + geom);
317: assertEquals(geom.getType().getBinding(), Point.class);
318: Point gPoint = (Point) geom.get();
319: assertTrue(151.0 == gPoint.getX());
320: */
321: }
322:
323: //This test currently fails, meaning that this datastore will not work
324: //if the geometry is requested in any position other than last. This
325: //is because the QueryData object is not yet equipped to deal with anything
326: //other than one result set column per attribute. It should be refactored
327: //to do so, as part of the refactoring for complex types in general. For
328: //the immediate a way forward may be to investigate sql concatting. Postgis
329: //supports this with the || operator, which I believe is ansi standard.
330: //It looks like you can run mysql in ansi mode and it will accept the ||
331: //operator, normally it uses a concat() function, and || is OR.
332: //If going this route then the XYLocationsSQLBuilder would use the concat
333: //statement for the x column, a delimiter, and the y column, probably
334: //do an AS (of the geom attribute name). Then the PointXYAttributeIO
335: //would read the column, split on the delimiter, and parse the string
336: //to a number. Not the fastest, but it may do the work with out having
337: //to re-architect geotools. -ch
338: /*public void testGeometryFirst() throws Exception {
339: String testTable = FEATURE_TABLE;
340: LOGGER.info("testTable " + testTable + " has schema " + dstore.getSchema(testTable));
341: String[] propNames = { GEOM_NAME, "gid", "name", "perimeter" };
342: Query geomQuery = new DefaultQuery(testTable, Filter.INCLUDE, 500,
343: propNames, "geomFirst");
344:
345: FeatureReader reader =
346: dstore.getFeatureReader(geomQuery, Transaction.AUTO_COMMIT);
347: Feature feature = reader.next();
348: LOGGER.info("feature is: " + feature);
349: }*/
350:
351: int count(FeatureReader reader) throws NoSuchElementException,
352: IOException, IllegalAttributeException {
353: int count = 0;
354:
355: try {
356: while (reader.hasNext()) {
357: reader.next();
358: count++;
359: }
360: } finally {
361: reader.close();
362: }
363:
364: return count;
365: }
366:
367: int count(FeatureWriter writer) throws NoSuchElementException,
368: IOException, IllegalAttributeException {
369: int count = 0;
370:
371: try {
372: while (writer.hasNext()) {
373: writer.next();
374: count++;
375: }
376: } finally {
377: writer.close();
378: }
379:
380: return count;
381: }
382:
383: /*
384: public void testGetFeatureWriter() throws Exception {
385: Transaction trans = new DefaultTransaction();
386: JDBCTransactionState state = new JDBCTransactionState(connPool);
387: trans.putState(connPool, state);
388:
389: FeatureWriter writer = dstore.getFeatureWriter("testset", Filter.INCLUDE, trans);
390:
391: //count(writer);
392: assertEquals(6, count(writer));
393:
394: try {
395: assertFalse(writer.hasNext());
396: } catch (IOException expected) {
397: }
398:
399: //TODO: test that writer.next is an empty feature.
400: //try {
401: // writer.next();
402: // fail("Should not be able to use a closed writer");
403: //} catch (IOException expected) {
404: //}
405: }
406: */
407: public void testBadTypeName() throws Exception {
408: try {
409: String badType = "badType43";
410: FeatureWriter writer = dstore.getFeatureWriter(badType,
411: Filter.INCLUDE, Transaction.AUTO_COMMIT);
412: fail("should not have type " + badType);
413: } catch (SchemaNotFoundException e) {
414: LOGGER.fine("succesfully caught exception: " + e);
415:
416: //catch the proper exception
417: }
418: }
419:
420: /*
421: public void testOptimizedBounds() throws Exception {
422: FeatureSource source = dstore.getFeatureSource(FEATURE_TABLE);
423: CompareFilter test1 = null;
424:
425: try {
426: test1 = filterFac.createCompareFilter(AbstractFilter.COMPARE_EQUALS);
427:
428: Integer testInt = new Integer(0);
429: Expression testLiteral = filterFac.createLiteralExpression(testInt);
430: test1.addLeftValue(testLiteral);
431: test1.addRightValue(filterFac.createAttributeExpression(schema, "pcedflag"));
432: } catch (IllegalFilterException e) {
433: fail("Illegal Filter Exception " + e);
434: }
435:
436: Query query = new DefaultQuery(FEATURE_TABLE, test1);
437: Envelope bounds = source.getBounds(query);
438: LOGGER.info("bounds on query " + query + " is " + bounds);
439:
440: Envelope fBounds = source.getBounds();
441: LOGGER.info("Bounds of source is " + fBounds);
442:
443: FeatureResults results = source.getFeatures(query);
444: LOGGER.info("bounds from feature results is " + results.getBounds());
445: }
446:
447: public void testGetFeaturesWriterModify() throws IOException, IllegalAttributeException {
448: Transaction trans = new DefaultTransaction();
449: JDBCTransactionState state = new JDBCTransactionState(connPool);
450: trans.putState(connPool, state);
451:
452: FeatureWriter writer = dstore.getFeatureWriter(FEATURE_TABLE, Filter.INCLUDE, trans);
453: int attKeyPos = 0;
454: Integer attKey = new Integer(10);
455: String attName = "name";
456: String newAttVal = "LS 503";
457: Feature feature;
458:
459: while (writer.hasNext()) {
460: feature = writer.next();
461:
462: if (feature.getAttribute(attKeyPos).equals(attKey)) {
463: LOGGER.info("changing name of feature " + feature);
464: ;
465: feature.setAttribute(attName, newAttVal);
466: writer.write();
467: }
468: }
469:
470: //writer.close();
471: FeatureReader reader = dstore.getFeatureReader(schema, Filter.INCLUDE, trans);
472:
473: while (reader.hasNext()) {
474: feature = reader.next();
475:
476: if (feature.getAttribute(attKeyPos).equals(attKey)) {
477: LOGGER.fine("checking feature " + feature);
478: ;
479:
480: Object modAtt = feature.getAttribute(attName);
481:
482: //LOGGER.fine("modified attribute is " + modAtt);
483: assertEquals("attribute was not changed", newAttVal, (String) modAtt);
484: }
485: }
486:
487: //feature = (Feature) data.features( "road" ).get( "road.rd1" );
488: //assertEquals( "changed", feature.getAttribute("name") );
489: state.rollback();
490: }
491:
492: public void testGetFeaturesWriterModifyGeometry()
493: throws IOException, IllegalAttributeException {
494: FeatureWriter writer =
495: dstore.getFeatureWriter("road", Filter.INCLUDE, Transaction.AUTO_COMMIT);
496: Feature feature;
497: Coordinate[] points =
498: {
499: new Coordinate(59, 59),
500: new Coordinate(17, 17),
501: new Coordinate(49, 39),
502: new Coordinate(57, 67),
503: new Coordinate(79, 79)};
504: LineString geom = geomFac.createLineString(points);
505:
506: while (writer.hasNext()) {
507: feature = writer.next();
508: LOGGER.info("looking at feature " + feature);
509:
510: if (feature.getAttribute(0).equals("asphalt")) {
511: LOGGER.info("changing name and geom");
512: feature.setAttribute("the_geom", geom);
513: writer.write();
514: }
515: }
516:
517: //feature = (Feature) data.features( "road" ).get( "road.rd1" );
518: //assertEquals( "changed", feature.getAttribute("name") );
519: writer.close();
520: }
521:
522: public void testGetFeaturesWriterModifyMultipleAtts()
523: throws IOException, IllegalAttributeException {
524: FeatureWriter writer =
525: dstore.getFeatureWriter("road", Filter.INCLUDE, Transaction.AUTO_COMMIT);
526: Feature feature;
527: Coordinate[] points =
528: {
529: new Coordinate(32, 44),
530: new Coordinate(62, 51),
531: new Coordinate(45, 35),
532: new Coordinate(55, 65),
533: new Coordinate(73, 75)};
534: LineString geom = geomFac.createLineString(points);
535:
536: while (writer.hasNext()) {
537: feature = writer.next();
538: LOGGER.info("looking at feature " + feature);
539:
540: if (feature.getAttribute(0).equals("asphalt")) {
541: LOGGER.info("changing name and geom");
542: feature.setAttribute("the_geom", geom);
543: feature.setAttribute("name", "trick");
544: writer.write();
545: }
546: }
547:
548: //feature = (Feature) data.features( "road" ).get( "road.rd1" );
549: //assertEquals( "changed", feature.getAttribute("name") );
550: writer.close();
551: }
552:
553: public void testGetFeaturesWriterAdd() throws IOException, IllegalAttributeException {
554: Transaction trans = new DefaultTransaction();
555: JDBCTransactionState state = new JDBCTransactionState(connPool);
556: trans.putState(connPool, state);
557:
558: FeatureWriter writer = dstore.getFeatureWriter(FEATURE_TABLE, Filter.INCLUDE, trans);
559: int count = 0;
560:
561: while (writer.hasNext()) {
562: Feature feature = writer.next();
563: count++;
564: }
565:
566: assertEquals("Checking num features before add", 6, count);
567: assertFalse(writer.hasNext());
568:
569: Feature feature = writer.next();
570: Object[] atts = getTestAtts("testAdd");
571: feature.setAttributes(atts);
572: writer.write();
573: assertFalse(writer.hasNext());
574:
575: //assertEquals( fixture.roadFeatures.length+1, data.features( "road" ).size() );
576: writer.close();
577:
578: FeatureReader reader = dstore.getFeatureReader(schema, Filter.INCLUDE, trans);
579: int numFeatures = count(reader);
580: assertEquals("Wrong number of features after add", 7, numFeatures);
581: state.rollback();
582: }
583: */
584: private Object[] getTestAtts(String name) {
585: Coordinate[] points = { new Coordinate(45, 45),
586: new Coordinate(45, 55), new Coordinate(55, 55),
587: new Coordinate(55, 45), new Coordinate(45, 45) };
588: GeometryFactory gf = new GeometryFactory();
589: LinearRing shell = gf.createLinearRing(points);
590: Polygon[] testPolys = { gf.createPolygon(shell, null) };
591: MultiPolygon the_geom = gf.createMultiPolygon(testPolys);
592: Integer gID = new Integer(addId);
593: Double area = new Double(100.0);
594: Double perimeter = new Double(40.0);
595: Integer testb_ = new Integer(22);
596: Integer testb_id = new Integer(4833);
597: Integer code = new Integer(0);
598:
599: Object[] attributes = { gID, area, perimeter, testb_, testb_id,
600: name, code, code, the_geom };
601:
602: return attributes;
603: }
604: /*
605: public void testGetFeatureWriterRemove() throws IOException, IllegalAttributeException {
606: Transaction trans = new DefaultTransaction();
607: JDBCTransactionState state = new JDBCTransactionState(connPool);
608: trans.putState(connPool, state);
609:
610: FeatureWriter writer = dstore.getFeatureWriter(FEATURE_TABLE, Filter.INCLUDE, trans);
611:
612: FeatureReader reader = dstore.getFeatureReader(schema, Filter.INCLUDE, trans);
613: int numFeatures = count(reader);
614:
615: //assertEquals("Wrong number of features before delete", 6, numFeatures);
616: Feature feature;
617:
618: while (writer.hasNext()) {
619: feature = writer.next();
620:
621: if (feature.getAttribute(0).equals(new Integer(4))) {
622: LOGGER.info("deleting feature " + feature);
623: writer.remove();
624: }
625: }
626:
627: writer.close();
628: reader = dstore.getFeatureReader(schema, Filter.INCLUDE, trans);
629: numFeatures = count(reader);
630: assertEquals("Wrong number of features after add", 5, numFeatures);
631: state.rollback();
632: }
633: */
634: //assertEquals( fixture.roadFeatures.length-1, data.features( "road" ).size() );
635: }
|