0001: /*
0002: * GeoTools - OpenSource mapping toolkit
0003: * http://geotools.org
0004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
0005: *
0006: * This library is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU Lesser General Public
0008: * License as published by the Free Software Foundation;
0009: * version 2.1 of the License.
0010: *
0011: * This library is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * Lesser General Public License for more details.
0015: */
0016: package org.geotools.data.mysql;
0017:
0018: import java.io.IOException;
0019: import java.sql.Connection;
0020: import java.sql.DatabaseMetaData;
0021: import java.sql.ResultSet;
0022: import java.sql.ResultSetMetaData;
0023: import java.sql.SQLException;
0024: import java.sql.Statement;
0025: import java.util.NoSuchElementException;
0026: import java.util.PropertyResourceBundle;
0027: import java.util.logging.Logger;
0028:
0029: import junit.framework.Test;
0030: import junit.framework.TestCase;
0031: import junit.framework.TestSuite;
0032:
0033: import org.geotools.data.DataTestCase;
0034: import org.geotools.data.DataUtilities;
0035: import org.geotools.data.DefaultQuery;
0036: import org.geotools.data.DefaultTransaction;
0037: import org.geotools.data.EmptyFeatureReader;
0038: import org.geotools.data.FeatureLock;
0039: import org.geotools.data.FeatureLockFactory;
0040: import org.geotools.data.FeatureLocking;
0041: import org.geotools.data.FeatureReader;
0042: import org.geotools.data.FeatureSource;
0043: import org.geotools.data.FeatureStore;
0044: import org.geotools.data.FeatureWriter;
0045: import org.geotools.data.FilteringFeatureReader;
0046: import org.geotools.data.InProcessLockingManager;
0047: import org.geotools.data.Query;
0048: import org.geotools.data.Transaction;
0049: import org.geotools.data.jdbc.datasource.ManageableDataSource;
0050: import org.geotools.data.jdbc.fidmapper.BasicFIDMapper;
0051: import org.geotools.data.jdbc.fidmapper.TypedFIDMapper;
0052: import org.geotools.feature.AttributeType;
0053: import org.geotools.feature.Feature;
0054: import org.geotools.feature.FeatureCollection;
0055: import org.geotools.feature.FeatureIterator;
0056: import org.geotools.feature.FeatureType;
0057: import org.geotools.feature.IllegalAttributeException;
0058: import org.geotools.feature.SimpleFeature;
0059: import org.geotools.filter.AbstractFilter;
0060: import org.geotools.filter.CompareFilter;
0061: import org.geotools.filter.Expression;
0062: import org.opengis.filter.Filter;
0063: import org.geotools.filter.FilterFactory;
0064: import org.geotools.filter.FilterFactoryFinder;
0065:
0066: import com.vividsolutions.jts.geom.Envelope;
0067: import com.vividsolutions.jts.geom.Geometry;
0068:
0069: /**
0070: * This class tests the MySQLDataStore API against the same tests as
0071: * MemoryDataStore.
0072: *
0073: * <p>
0074: * The test fixture is available in the shared DataTestCase, really the common
0075: * elements should move to a shared DataStoreAPITestCase.
0076: * </p>
0077: *
0078: * <p>
0079: * This class does require your own DataStore, it will create a table populated
0080: * with the Features from the test fixture, and run a test, and then remove
0081: * the table.
0082: * </p>
0083: *
0084: * <p>
0085: * Because of the nature of this testing process you cannot run these tests in
0086: * conjunction with another user, so they cannot be implemented against the
0087: * public server.
0088: * </p>
0089: *
0090: * <p>
0091: * A simple properties file has been constructed,
0092: * <code>fixture.properties</code>, which you may direct to your own potgis
0093: * database installation.
0094: * </p>
0095: *
0096: * @author Jody Garnett, Refractions Research
0097: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/mysql/src/test/java/org/geotools/data/mysql/MySQLDataStoreAPITest.java $
0098: */
0099: public class MySQLDataStoreAPITest extends DataTestCase {
0100: private static final int LOCK_DURATION = 3600 * 1000; // one hour
0101: /** The logger for the filter module. */
0102: private static final Logger LOGGER = org.geotools.util.logging.Logging
0103: .getLogger("org.geotools.data.mysql");
0104: static boolean CHECK_TYPE = false;
0105: MySQLDataStore data;
0106: ManageableDataSource pool;
0107: String database;
0108: String victim = null; //"testGetFeatureWriterRemoveAll";
0109:
0110: /**
0111: * Constructor for MemoryDataStoreTest.
0112: *
0113: * @param test
0114: *
0115: * @throws AssertionError DOCUMENT ME!
0116: */
0117: public MySQLDataStoreAPITest(String test) {
0118: super (test);
0119:
0120: if ((victim != null) && !test.equals(victim)) {
0121: throw new AssertionError("test supressed " + test);
0122: }
0123: }
0124:
0125: public static void main(String[] args) {
0126: junit.textui.TestRunner.run(suite());
0127: }
0128:
0129: public static Test suite() {
0130: LOGGER.info("starting suite...");
0131:
0132: TestSuite suite = new TestSuite(MySQLDataStoreAPITest.class);
0133: LOGGER.info("made suite...");
0134:
0135: return suite;
0136: }
0137:
0138: /**
0139: * @see TestCase#setUp()
0140: */
0141: protected void setUp() throws Exception {
0142: super .setUp();
0143:
0144: PropertyResourceBundle resource;
0145: resource = new PropertyResourceBundle(this .getClass()
0146: .getResourceAsStream("fixture.properties"));
0147:
0148: String namespace = resource.getString("namespace");
0149: String host = resource.getString("host");
0150: int port = Integer.parseInt(resource.getString("port"));
0151: String database = resource.getString("database");
0152: this .database = database;
0153:
0154: String user = resource.getString("user");
0155: String password = resource.getString("passwd");
0156:
0157: if (namespace.equals("http://www.geotools.org/data/postgis")) {
0158: throw new IllegalStateException(
0159: "The fixture.properties file needs to be configured for your own database");
0160: }
0161:
0162: pool = MySQLDataStoreFactory.getDefaultDataSource(host, user,
0163: password, port, database, 10, 2, false);
0164:
0165: setUpRoadTable();
0166: setUpRiverTable();
0167:
0168: if (CHECK_TYPE) {
0169: checkTypesInDataBase();
0170: CHECK_TYPE = false; // just once
0171: }
0172:
0173: data = new MySQLDataStore(pool, null, getName());
0174: data.setFIDMapper("road", new TypedFIDMapper(
0175: new BasicFIDMapper("fid", 255, false), "road"));
0176: data.setFIDMapper("river", new TypedFIDMapper(
0177: new BasicFIDMapper("fid", 255, false), "river"));
0178: data.setFIDMapper("testset", new TypedFIDMapper(
0179: new BasicFIDMapper("gid", 255, true), "testset"));
0180:
0181: //
0182: // Update Fixture to reflect the actual data in the database
0183: // I am doing this because it
0184: updateRoadFeaturesFixture();
0185: updateRiverFeaturesFixture();
0186: }
0187:
0188: /**
0189: * This is a quick hack to have our fixture reflect the FIDs in the
0190: * database.
0191: *
0192: * <p>
0193: * When the dataStore learns how to preserve our FeatureIds this won't be
0194: * required.
0195: * </p>
0196: *
0197: * @throws Exception
0198: */
0199: protected void updateRoadFeaturesFixture() throws Exception {
0200: Connection conn = pool.getConnection();
0201: FeatureReader reader = data.getFeatureReader(new DefaultQuery(
0202: "road", Filter.INCLUDE), Transaction.AUTO_COMMIT);
0203:
0204: Envelope bounds = new Envelope();
0205:
0206: try {
0207: SimpleFeature f;
0208:
0209: while (reader.hasNext()) {
0210: f = (SimpleFeature) reader.next();
0211:
0212: int index = ((Integer) f.getAttribute("id")).intValue() - 1;
0213: roadFeatures[index] = f;
0214: bounds.expandToInclude(f.getBounds());
0215: }
0216: } finally {
0217: reader.close();
0218: conn.close();
0219: }
0220:
0221: if (!roadBounds.equals(bounds)) {
0222: System.out.println("warning! Database changed bounds()");
0223: System.out.println("was:" + roadBounds);
0224: System.out.println("now:" + bounds);
0225: roadBounds = bounds;
0226: }
0227:
0228: Envelope bounds12 = new Envelope();
0229: bounds12.expandToInclude(roadFeatures[0].getBounds());
0230: bounds12.expandToInclude(roadFeatures[1].getBounds());
0231:
0232: if (!rd12Bounds.equals(bounds12)) {
0233: System.out
0234: .println("warning! Database changed bounds of rd1 & rd2");
0235: System.out.println("was:" + rd12Bounds);
0236: System.out.println("now:" + bounds12);
0237: rd12Bounds = bounds12;
0238: }
0239:
0240: FeatureType schema = roadFeatures[0].getFeatureType();
0241: FilterFactory ff = FilterFactoryFinder.createFilterFactory();
0242: CompareFilter tFilter = ff
0243: .createCompareFilter(AbstractFilter.COMPARE_EQUALS);
0244: Expression rd1Literal = ff.createLiteralExpression("r1");
0245: tFilter.addLeftValue(rd1Literal);
0246:
0247: Expression rdNameAtt = ff.createAttributeExpression(schema,
0248: "name");
0249: tFilter.addRightValue(rdNameAtt);
0250: rd1Filter = tFilter;
0251:
0252: tFilter = ff.createCompareFilter(AbstractFilter.COMPARE_EQUALS);
0253:
0254: Expression rd2Literal = ff.createLiteralExpression("r2");
0255: tFilter.addLeftValue(rd2Literal);
0256: tFilter.addRightValue(rdNameAtt);
0257: rd2Filter = tFilter;
0258: rd12Filter = ff.or(rd2Filter, rd1Filter);
0259: }
0260:
0261: /**
0262: * This is a quick hack to have our fixture reflect the FIDs in the
0263: * database.
0264: *
0265: * <p>
0266: * When the dataStore learns how to preserve our FeatureIds this won't be
0267: * required.
0268: * </p>
0269: *
0270: * @throws Exception DOCUMENT ME!
0271: */
0272: protected void updateRiverFeaturesFixture() throws Exception {
0273: Connection conn = pool.getConnection();
0274: FeatureReader reader = data.getFeatureReader(new DefaultQuery(
0275: "river", Filter.INCLUDE), Transaction.AUTO_COMMIT);
0276:
0277: Envelope bounds = new Envelope();
0278:
0279: try {
0280: Feature f;
0281:
0282: while (reader.hasNext()) {
0283: f = reader.next();
0284:
0285: int index = ((Integer) f.getAttribute("id")).intValue() - 1;
0286: riverFeatures[index] = f;
0287: bounds.expandToInclude(f.getBounds());
0288: }
0289: } finally {
0290: reader.close();
0291: conn.close();
0292: }
0293:
0294: if (!riverBounds.equals(bounds)) {
0295: System.out
0296: .println("warning! Database changed bounds of river");
0297: System.out.println("was:" + riverBounds);
0298: System.out.println("now:" + bounds);
0299: riverBounds = bounds;
0300: }
0301:
0302: FilterFactory factory = FilterFactoryFinder
0303: .createFilterFactory();
0304: CompareFilter tFilter = factory
0305: .createCompareFilter(AbstractFilter.COMPARE_EQUALS);
0306: Expression rvLiteral = factory.createLiteralExpression("rv1");
0307: tFilter.addLeftValue(rvLiteral);
0308:
0309: FeatureType schema = riverFeatures[0].getFeatureType();
0310: Expression rvNameAtt = factory.createAttributeExpression(
0311: schema, "river");
0312: tFilter.addRightValue(rvNameAtt);
0313: rv1Filter = tFilter;
0314: }
0315:
0316: protected void checkTypesInDataBase() throws SQLException {
0317: Connection conn = pool.getConnection();
0318:
0319: try {
0320: DatabaseMetaData md = conn.getMetaData();
0321: ResultSet rs =
0322: //md.getTables( catalog, null, null, null );
0323: md
0324: .getTables(null, "public", "%",
0325: new String[] { "TABLE", });
0326: ResultSetMetaData rsmd = rs.getMetaData();
0327: int NUM = rsmd.getColumnCount();
0328: System.out.print(" ");
0329:
0330: for (int i = 1; i <= NUM; i++) {
0331: System.out.print(rsmd.getColumnName(i));
0332: System.out.flush();
0333: System.out.print(":");
0334: System.out.flush();
0335: System.out.print(rsmd.getColumnClassName(i));
0336: System.out.flush();
0337:
0338: if (i < NUM) {
0339: System.out.print(",");
0340: System.out.flush();
0341: }
0342: }
0343:
0344: System.out.println();
0345:
0346: while (rs.next()) {
0347: System.out.print(rs.getRow());
0348: System.out.print(":");
0349: System.out.flush();
0350:
0351: for (int i = 1; i <= NUM; i++) {
0352: System.out.print(rsmd.getColumnName(i));
0353: System.out.flush();
0354: System.out.print("=");
0355: System.out.flush();
0356: System.out.print(rs.getString(i));
0357: System.out.flush();
0358:
0359: if (i < NUM) {
0360: System.out.print(",");
0361: System.out.flush();
0362: }
0363: }
0364:
0365: System.out.println();
0366: }
0367: } finally {
0368: conn.close();
0369: }
0370: }
0371:
0372: protected void setUpRoadTable() throws Exception {
0373: Connection conn = pool.getConnection();
0374: conn.setAutoCommit(true);
0375:
0376: try {
0377: Statement s = conn.createStatement();
0378: s.execute("DROP TABLE road");
0379: } catch (Exception ignore) {
0380: }
0381:
0382: try {
0383: Statement s = conn.createStatement();
0384:
0385: s
0386: .execute("CREATE TABLE road (fid varchar(255) PRIMARY KEY, id int, geom LINESTRING not null, name varchar(255), spatial index(geom) ) engine = myisam");
0387:
0388: for (int i = 0; i < roadFeatures.length; i++) {
0389: Feature f = roadFeatures[i];
0390:
0391: //strip out the road.
0392: String fid = f.getID().substring("road.".length());
0393: String ql = "INSERT INTO road (fid,id,geom,name) VALUES ("
0394: + "'"
0395: + fid
0396: + "',"
0397: + f.getAttribute("id")
0398: + ","
0399: + "GeometryFromText('"
0400: + ((Geometry) f.getAttribute("geom")).toText()
0401: + "', 0 ),"
0402: + "'"
0403: + f.getAttribute("name")
0404: + "')";
0405:
0406: s.execute(ql);
0407: }
0408: } finally {
0409: conn.close();
0410: }
0411: }
0412:
0413: protected void killTestTables() throws Exception {
0414: Connection conn = pool.getConnection();
0415:
0416: try {
0417: Statement s = conn.createStatement();
0418: s.execute("SELECT dropgeometrycolumn( '" + database
0419: + "','road','geom')");
0420: s.execute("SELECT dropgeometrycolumn( '" + database
0421: + "','river','geom')");
0422: } catch (Exception ignore) {
0423: }
0424:
0425: try {
0426: Statement s = conn.createStatement();
0427: s.execute("DROP TABLE road");
0428: s.execute("DROP TABLE river");
0429: } catch (Exception ignore) {
0430: } finally {
0431: conn.close();
0432: }
0433: }
0434:
0435: protected void setUpRiverTable() throws Exception {
0436: Connection conn = pool.getConnection();
0437:
0438: try {
0439: Statement s = conn.createStatement();
0440: s.execute("DROP TABLE river");
0441: } catch (Exception ignore) {
0442: }
0443:
0444: try {
0445: Statement s = conn.createStatement();
0446:
0447: //postgis = new PostgisDataSource(connection, FEATURE_TABLE);
0448: s
0449: .execute("CREATE TABLE river(fid varchar(255) PRIMARY KEY, id int, geom MULTILINESTRING, river varchar(255), flow double)");
0450:
0451: for (int i = 0; i < riverFeatures.length; i++) {
0452: Feature f = riverFeatures[i];
0453: String fid = f.getID().substring("river.".length());
0454: s
0455: .execute("INSERT INTO river (fid, id, geom, river, flow) VALUES ("
0456: + "'"
0457: + fid
0458: + "',"
0459: + f.getAttribute("id")
0460: + ","
0461: + "GeometryFromText('"
0462: + f.getAttribute("geom").toString()
0463: + "', 0 ),"
0464: + "'"
0465: + f.getAttribute("river")
0466: + "',"
0467: + f.getAttribute("flow") + ")");
0468: }
0469: } finally {
0470: conn.close();
0471: }
0472: }
0473:
0474: /*
0475: * @see TestCase#tearDown()
0476: */
0477: protected void tearDown() throws Exception {
0478: data.dispose();
0479: data = null;
0480:
0481: super .tearDown();
0482: }
0483:
0484: public void testGetFeatureTypes() {
0485: try {
0486: String[] names = data.getTypeNames();
0487: assertTrue(contains(names, "road"));
0488: assertTrue(contains(names, "river"));
0489: } catch (IOException e) {
0490: e.printStackTrace();
0491: fail("An IOException has been thrown!");
0492: }
0493: }
0494:
0495: boolean contains(Object[] array, Object expected) {
0496: if ((array == null) || (array.length == 0)) {
0497: return false;
0498: }
0499:
0500: for (int i = 0; i < array.length; i++) {
0501: if (array[i].equals(expected)) {
0502: return true;
0503: }
0504: }
0505:
0506: return false;
0507: }
0508:
0509: void assertContains(Object[] array, Object expected) {
0510: assertFalse(array == null);
0511: assertFalse(array.length == 0);
0512: assertNotNull(expected);
0513:
0514: for (int i = 0; i < array.length; i++) {
0515: if (array[i].equals(expected)) {
0516: return;
0517: }
0518: }
0519:
0520: fail("Contains " + expected);
0521: }
0522:
0523: /**
0524: * Like contain but based on match rather than equals
0525: *
0526: * @param array DOCUMENT ME!
0527: * @param expected DOCUMENT ME!
0528: *
0529: * @return DOCUMENT ME!
0530: */
0531: boolean containsLax(Feature[] array, Feature expected) {
0532: if ((array == null) || (array.length == 0)) {
0533: return false;
0534: }
0535:
0536: FeatureType type = expected.getFeatureType();
0537:
0538: for (int i = 0; i < array.length; i++) {
0539: if (match(array[i], expected)) {
0540: return true;
0541: }
0542: }
0543:
0544: return false;
0545: }
0546:
0547: /**
0548: * Compare based on attributes not getID allows comparison of Diff contents
0549: *
0550: * @param expected DOCUMENT ME!
0551: * @param actual DOCUMENT ME!
0552: *
0553: * @return DOCUMENT ME!
0554: */
0555: boolean match(Feature expected, Feature actual) {
0556: FeatureType type = expected.getFeatureType();
0557:
0558: for (int i = 0; i < type.getAttributeCount(); i++) {
0559: Object av = actual.getAttribute(i);
0560: Object ev = expected.getAttribute(i);
0561:
0562: if ((av == null) && (ev != null)) {
0563: return false;
0564: } else if ((ev == null) && (av != null)) {
0565: return false;
0566: } else if (av instanceof Geometry && ev instanceof Geometry) {
0567: Geometry ag = (Geometry) av;
0568: Geometry eg = (Geometry) ev;
0569:
0570: if (!ag.equals(eg)) {
0571: return false;
0572: }
0573: } else if (!av.equals(ev)) {
0574: return false;
0575: }
0576: }
0577:
0578: return true;
0579: }
0580:
0581: public void testGetSchemaRoad() throws IOException {
0582: FeatureType expected = roadType;
0583: FeatureType actual = data.getSchema("road");
0584: assertEquals("namespace", expected.getNamespace(), actual
0585: .getNamespace());
0586: assertEquals("typeName", expected.getTypeName(), actual
0587: .getTypeName());
0588:
0589: //assertEquals( "compare", 0, DataUtilities.compare( expected, actual ));
0590: assertEquals("attributeCount", expected.getAttributeCount(),
0591: actual.getAttributeCount());
0592:
0593: for (int i = 0; i < expected.getAttributeCount(); i++) {
0594: AttributeType expectedAttribute = expected
0595: .getAttributeType(i);
0596: AttributeType actualAttribute = actual.getAttributeType(i);
0597: assertEquals("attribute " + expectedAttribute.getName(),
0598: expectedAttribute, actualAttribute);
0599: }
0600:
0601: assertEquals(expected, actual);
0602: }
0603:
0604: public void testGetSchemaRiver() throws IOException {
0605: FeatureType expected = riverType;
0606: FeatureType actual = data.getSchema("river");
0607: assertEquals("namespace", expected.getNamespace(), actual
0608: .getNamespace());
0609: assertEquals("typeName", expected.getTypeName(), actual
0610: .getTypeName());
0611:
0612: //assertEquals( "compare", 0, DataUtilities.compare( expected, actual ));
0613: assertEquals("attributeCount", expected.getAttributeCount(),
0614: actual.getAttributeCount());
0615:
0616: for (int i = 0; i < expected.getAttributeCount(); i++) {
0617: AttributeType expectedAttribute = expected
0618: .getAttributeType(i);
0619: AttributeType actualAttribute = actual.getAttributeType(i);
0620: assertEquals("attribute " + expectedAttribute.getName(),
0621: expectedAttribute, actualAttribute);
0622: }
0623:
0624: assertEquals(expected, actual);
0625: }
0626:
0627: static public void assertEquals(String message, String expected,
0628: String actual) {
0629: if (expected == actual) {
0630: return;
0631: }
0632:
0633: assertNotNull(message, expected);
0634: assertNotNull(message, actual);
0635:
0636: if (!expected.equals(actual)) {
0637: fail(message + " expected:<" + expected + "> but was <"
0638: + actual + ">");
0639: }
0640: }
0641:
0642: void assertCovers(String msg, FeatureCollection c1,
0643: FeatureCollection c2) {
0644: if (c1 == c2) {
0645: return;
0646: }
0647:
0648: assertNotNull(msg, c1);
0649: assertNotNull(msg, c2);
0650: assertEquals(msg + " size", c1.size(), c2.size());
0651:
0652: Feature f;
0653:
0654: for (FeatureIterator i = c1.features(); i.hasNext();) {
0655: f = i.next();
0656: assertTrue(msg + " " + f.getID(), c2.contains(f));
0657: }
0658: }
0659:
0660: public FeatureReader reader(String typeName) throws IOException {
0661: FeatureType type = data.getSchema(typeName);
0662:
0663: return data.getFeatureReader(type, Filter.INCLUDE,
0664: Transaction.AUTO_COMMIT);
0665: }
0666:
0667: public FeatureWriter writer(String typeName) throws IOException {
0668: return data.getFeatureWriter(typeName, Transaction.AUTO_COMMIT);
0669: }
0670:
0671: public void testGetFeatureReader() throws IOException,
0672: IllegalAttributeException {
0673: assertCovered(roadFeatures, reader("road"));
0674: assertEquals(3, count(reader("road")));
0675: }
0676:
0677: public void testGetFeatureReaderMutability() throws IOException,
0678: IllegalAttributeException {
0679: FeatureReader reader = reader("road");
0680: Feature feature;
0681:
0682: while (reader.hasNext()) {
0683: feature = (Feature) reader.next();
0684: feature.setAttribute("name", null);
0685: }
0686:
0687: reader.close();
0688:
0689: reader = reader("road");
0690:
0691: while (reader.hasNext()) {
0692: feature = (Feature) reader.next();
0693: assertNotNull(feature.getAttribute("name"));
0694: }
0695:
0696: reader.close();
0697:
0698: try {
0699: reader.next();
0700: fail("next should fail with an IOException");
0701: } catch (IOException expected) {
0702: }
0703: }
0704:
0705: public void testGetFeatureReaderConcurancy()
0706: throws NoSuchElementException, IOException,
0707: IllegalAttributeException {
0708: FeatureReader reader1 = reader("road");
0709: FeatureReader reader2 = reader("road");
0710: FeatureReader reader3 = reader("river");
0711:
0712: Feature feature1;
0713: Feature feature2;
0714: Feature feature3;
0715:
0716: while (reader1.hasNext() || reader2.hasNext()
0717: || reader3.hasNext()) {
0718: assertTrue(contains(roadFeatures, reader1.next()));
0719: assertTrue(contains(roadFeatures, reader2.next()));
0720:
0721: if (reader3.hasNext()) {
0722: assertTrue(contains(riverFeatures, reader3.next()));
0723: }
0724: }
0725:
0726: try {
0727: reader1.next();
0728: fail("next should fail with an NoSuchElementException");
0729: } catch (NoSuchElementException expectedNoElement) {
0730: // this is new to me, I had expected an IOException
0731: }
0732:
0733: try {
0734: reader2.next();
0735: fail("next should fail with an NoSuchElementException");
0736: } catch (NoSuchElementException expectedNoElement) {
0737: }
0738:
0739: try {
0740: reader3.next();
0741: fail("next should fail with an NoSuchElementException");
0742: } catch (NoSuchElementException expectedNoElement) {
0743: }
0744:
0745: reader1.close();
0746: reader2.close();
0747: reader3.close();
0748:
0749: try {
0750: reader1.next();
0751: fail("next should fail with an IOException");
0752: } catch (IOException expectedClosed) {
0753: }
0754:
0755: try {
0756: reader2.next();
0757: fail("next should fail with an IOException");
0758: } catch (IOException expectedClosed) {
0759: }
0760:
0761: try {
0762: reader3.next();
0763: fail("next should fail with an IOException");
0764: } catch (IOException expectedClosed) {
0765: }
0766: }
0767:
0768: public void testGetFeatureReaderFilterAutoCommit()
0769: throws NoSuchElementException, IOException,
0770: IllegalAttributeException {
0771: FeatureType type = data.getSchema("road");
0772: FeatureReader reader;
0773:
0774: reader = data.getFeatureReader(type, Filter.INCLUDE,
0775: Transaction.AUTO_COMMIT);
0776: assertFalse(reader instanceof FilteringFeatureReader);
0777: assertEquals(type, reader.getFeatureType());
0778: assertEquals(roadFeatures.length, count(reader));
0779:
0780: reader = data.getFeatureReader(type, Filter.EXCLUDE,
0781: Transaction.AUTO_COMMIT);
0782: assertTrue(reader instanceof EmptyFeatureReader);
0783:
0784: assertEquals(type, reader.getFeatureType());
0785: assertEquals(0, count(reader));
0786:
0787: reader = data.getFeatureReader(type, rd1Filter,
0788: Transaction.AUTO_COMMIT);
0789:
0790: //assertTrue(reader instanceof FilteringFeatureReader);
0791: assertEquals(type, reader.getFeatureType());
0792: assertEquals(1, count(reader));
0793: }
0794:
0795: // TODO: uncomment when and if MySQLDataStore gets transaction capabilities
0796: // public void testGetFeatureReaderFilterTransaction()
0797: // throws NoSuchElementException, IOException, IllegalAttributeException {
0798: // Transaction t = new DefaultTransaction();
0799: // FeatureType type = data.getSchema("road");
0800: // FeatureReader reader;
0801: //
0802: // reader = data.getFeatureReader(type, Filter.EXCLUDE, t);
0803: // assertTrue(reader instanceof EmptyFeatureReader);
0804: // assertEquals(type, reader.getFeatureType());
0805: // assertEquals(0, count(reader));
0806: //
0807: // reader = data.getFeatureReader(type, Filter.INCLUDE, t);
0808: // assertEquals(type, reader.getFeatureType());
0809: // assertEquals(roadFeatures.length, count(reader));
0810: //
0811: // reader = data.getFeatureReader(type, rd1Filter, t);
0812: // assertEquals(type, reader.getFeatureType());
0813: // assertEquals(1, count(reader));
0814: //
0815: // FeatureWriter writer = data.getFeatureWriter("road", Filter.INCLUDE, t);
0816: // Feature feature;
0817: //
0818: // while (writer.hasNext()) {
0819: // feature = writer.next();
0820: //
0821: // if (feature.getID().equals(roadFeatures[0].getID())) {
0822: // writer.remove();
0823: // }
0824: // }
0825: //
0826: // reader = data.getFeatureReader(type, Filter.EXCLUDE, t);
0827: // assertEquals(0, count(reader));
0828: //
0829: // reader = data.getFeatureReader(type, Filter.INCLUDE, t);
0830: // assertEquals(roadFeatures.length - 1, count(reader));
0831: //
0832: // reader = data.getFeatureReader(type, rd1Filter, t);
0833: // assertEquals(0, count(reader));
0834: //
0835: // t.rollback();
0836: // reader = data.getFeatureReader(type, Filter.EXCLUDE, t);
0837: // assertEquals(0, count(reader));
0838: //
0839: // reader = data.getFeatureReader(type, Filter.INCLUDE, t);
0840: // assertEquals(roadFeatures.length, count(reader));
0841: //
0842: // reader = data.getFeatureReader(type, rd1Filter, t);
0843: // assertEquals(1, count(reader));
0844: // }
0845:
0846: /**
0847: * Ensure readers contents equal those in the feature array
0848: *
0849: * @param features DOCUMENT ME!
0850: * @param reader DOCUMENT ME!
0851: *
0852: * @throws NoSuchElementException DOCUMENT ME!
0853: * @throws IOException DOCUMENT ME!
0854: * @throws IllegalAttributeException DOCUMENT ME!
0855: */
0856: void assertCovered(Feature[] features, FeatureReader reader)
0857: throws NoSuchElementException, IOException,
0858: IllegalAttributeException {
0859: int count = 0;
0860:
0861: try {
0862: while (reader.hasNext()) {
0863: assertContains(features, reader.next());
0864: count++;
0865: }
0866: } finally {
0867: reader.close();
0868: }
0869:
0870: assertEquals(features.length, count);
0871: }
0872:
0873: /**
0874: * Ensure readers contents match those in the feature array
0875: *
0876: * <p>
0877: * Implemented using match on attribute types, not feature id
0878: * </p>
0879: *
0880: * @param array DOCUMENT ME!
0881: * @param reader DOCUMENT ME!
0882: *
0883: * @throws Exception DOCUMENT ME!
0884: */
0885: void assertMatched(Feature[] array, FeatureReader reader)
0886: throws Exception {
0887: Feature feature;
0888: int count = 0;
0889:
0890: try {
0891: while (reader.hasNext()) {
0892: feature = reader.next();
0893: assertMatch(array, feature);
0894: count++;
0895: }
0896: } finally {
0897: reader.close();
0898: }
0899:
0900: assertEquals("array not matched by reader", array.length, count);
0901: }
0902:
0903: void assertMatch(Feature[] array, Feature feature) {
0904: assertTrue(array != null);
0905: assertTrue(array.length != 0);
0906:
0907: FeatureType schema = feature.getFeatureType();
0908:
0909: for (int i = 0; i < array.length; i++) {
0910: if (match(array[i], feature)) {
0911: return;
0912: }
0913: }
0914:
0915: System.out.println("not found:" + feature);
0916:
0917: for (int i = 0; i < array.length; i++) {
0918: System.out.println(i + ":" + array[i]);
0919: }
0920:
0921: fail("array has no match for " + feature);
0922: }
0923:
0924: /**
0925: * Ensure that FeatureReader reader contains extactly the contents of
0926: * array.
0927: *
0928: * @param reader DOCUMENT ME!
0929: * @param array DOCUMENT ME!
0930: *
0931: * @return DOCUMENT ME!
0932: *
0933: * @throws NoSuchElementException DOCUMENT ME!
0934: * @throws IOException DOCUMENT ME!
0935: * @throws IllegalAttributeException DOCUMENT ME!
0936: */
0937: boolean covers(FeatureReader reader, Feature[] array)
0938: throws NoSuchElementException, IOException,
0939: IllegalAttributeException {
0940: Feature feature;
0941: int count = 0;
0942:
0943: try {
0944: while (reader.hasNext()) {
0945: feature = reader.next();
0946:
0947: if (!contains(array, feature)) {
0948: return false;
0949: }
0950:
0951: count++;
0952: }
0953: } finally {
0954: reader.close();
0955: }
0956:
0957: return count == array.length;
0958: }
0959:
0960: boolean covers(FeatureIterator reader, Feature[] array)
0961: throws NoSuchElementException, IOException,
0962: IllegalAttributeException {
0963: Feature feature;
0964: int count = 0;
0965:
0966: try {
0967: while (reader.hasNext()) {
0968: feature = reader.next();
0969:
0970: if (!contains(array, feature)) {
0971: return false;
0972: }
0973:
0974: count++;
0975: }
0976: } finally {
0977: reader.close();
0978: }
0979:
0980: return count == array.length;
0981: }
0982:
0983: boolean coversLax(FeatureReader reader, Feature[] array)
0984: throws NoSuchElementException, IOException,
0985: IllegalAttributeException {
0986: Feature feature;
0987: int count = 0;
0988:
0989: try {
0990: while (reader.hasNext()) {
0991: feature = reader.next();
0992:
0993: if (!containsLax(array, feature)) {
0994: return false;
0995: }
0996:
0997: count++;
0998: }
0999: } finally {
1000: reader.close();
1001: }
1002:
1003: return count == array.length;
1004: }
1005:
1006: void dump(String message, FeatureReader reader)
1007: throws NoSuchElementException, IOException,
1008: IllegalAttributeException {
1009: Feature feature;
1010: int count = 0;
1011:
1012: try {
1013: while (reader.hasNext()) {
1014: feature = reader.next();
1015:
1016: String msg = message + ": feture " + count + "="
1017: + feature;
1018:
1019: //LOGGER.info( msg );
1020: System.out.println(msg);
1021: count++;
1022: }
1023: } finally {
1024: reader.close();
1025: }
1026: }
1027:
1028: void dump(String message, Object[] array) {
1029: for (int i = 0; i < array.length; i++) {
1030: String msg = message + ": " + i + "=" + array[i];
1031:
1032: //LOGGER.info( msg );
1033: System.out.println(msg);
1034: }
1035: }
1036:
1037: /*
1038: * Test for FeatureWriter getFeatureWriter(String, Filter, Transaction)
1039: */
1040: public void testGetFeatureWriter() throws Exception {
1041: FeatureWriter writer = data.getFeatureWriter("road",
1042: Filter.INCLUDE, Transaction.AUTO_COMMIT);
1043: assertEquals(roadFeatures.length, count(writer));
1044: }
1045:
1046: public void testGetFeatureWriterClose() throws Exception {
1047: FeatureWriter writer = data.getFeatureWriter("road",
1048: Filter.INCLUDE, Transaction.AUTO_COMMIT);
1049:
1050: writer.close();
1051:
1052: try {
1053: assertFalse(writer.hasNext());
1054: fail("Should not be able to use a closed writer");
1055: } catch (IOException expected) {
1056: }
1057:
1058: try {
1059: assertNull(writer.next());
1060: fail("Should not be able to use a closed writer");
1061: } catch (IOException expected) {
1062: }
1063:
1064: try {
1065: writer.close();
1066: } catch (IOException expected) {
1067: }
1068: }
1069:
1070: public void testGetFeatureWriterRemove() throws IOException,
1071: IllegalAttributeException {
1072: FeatureWriter writer = writer("road");
1073: Feature feature;
1074:
1075: while (writer.hasNext()) {
1076: feature = writer.next();
1077:
1078: if (feature.getID().equals(roadFeatures[0].getID())) {
1079: writer.remove();
1080: }
1081: }
1082:
1083: assertEquals(roadFeatures.length - 1, count("road"));
1084: }
1085:
1086: public void testGetFeatureWriterRemoveAll() throws IOException,
1087: IllegalAttributeException {
1088: FeatureWriter writer = writer("road");
1089: Feature feature;
1090:
1091: try {
1092: while (writer.hasNext()) {
1093: feature = writer.next();
1094: writer.remove();
1095: }
1096: } finally {
1097: writer.close();
1098: }
1099: assertEquals(0, count("road"));
1100: }
1101:
1102: public int count(String typeName) throws IOException {
1103: //return count(reader(typeName));
1104: // makes use of optimization if any
1105: return data.getFeatureSource(typeName).getFeatures().size();
1106: }
1107:
1108: public void testGetFeaturesWriterAdd() throws IOException,
1109: IllegalAttributeException {
1110: FeatureWriter writer = data.getFeatureWriter("road",
1111: Transaction.AUTO_COMMIT);
1112: SimpleFeature feature;
1113:
1114: LOGGER.info("about to call has next on writer " + writer);
1115:
1116: while (writer.hasNext()) {
1117: feature = (SimpleFeature) writer.next();
1118: }
1119:
1120: assertFalse(writer.hasNext());
1121:
1122: feature = (SimpleFeature) writer.next();
1123: feature.setAttributes(newRoad.getAttributes(null));
1124: writer.write();
1125:
1126: assertFalse(writer.hasNext());
1127: assertEquals(roadFeatures.length + 1, count("road"));
1128: }
1129:
1130: /**
1131: * Seach for feature based on AttributeType.
1132: *
1133: * <p>
1134: * If attributeName is null, we will search by feature.getID()
1135: * </p>
1136: *
1137: * <p>
1138: * The provided reader will be closed by this opperations.
1139: * </p>
1140: *
1141: * @param reader reader to search through
1142: * @param attributeName attributeName, or null for featureID
1143: * @param value value to match
1144: *
1145: * @return Feature
1146: *
1147: * @throws NoSuchElementException if a match could not be found
1148: * @throws IOException We could not use reader
1149: * @throws IllegalAttributeException if attributeName did not match schema
1150: */
1151: public Feature findFeature(FeatureReader reader,
1152: String attributeName, Object value)
1153: throws NoSuchElementException, IOException,
1154: IllegalAttributeException {
1155: Feature f;
1156:
1157: try {
1158: while (reader.hasNext()) {
1159: f = reader.next();
1160:
1161: if (attributeName == null) {
1162: if (value.equals(f.getID())) {
1163: return f;
1164: }
1165: } else {
1166: if (value.equals(f.getAttribute(attributeName))) {
1167: return f;
1168: }
1169: }
1170: }
1171: } finally {
1172: reader.close();
1173: }
1174:
1175: if (attributeName == null) {
1176: throw new NoSuchElementException("No match for FID="
1177: + value);
1178: } else {
1179: throw new NoSuchElementException("No match for "
1180: + attributeName + "=" + value);
1181: }
1182: }
1183:
1184: public Feature feature(String typeName, String fid)
1185: throws NoSuchElementException, IOException,
1186: IllegalAttributeException {
1187: FeatureReader reader = reader(typeName);
1188: Feature f;
1189:
1190: try {
1191: while (reader.hasNext()) {
1192: f = reader.next();
1193:
1194: if (fid.equals(f.getID())) {
1195: return f;
1196: }
1197: }
1198: } finally {
1199: reader.close();
1200: }
1201:
1202: return null;
1203: }
1204:
1205: public void testGetFeaturesWriterModify() throws IOException,
1206: IllegalAttributeException {
1207: FeatureWriter writer = writer("road");
1208: Feature feature;
1209:
1210: while (writer.hasNext()) {
1211: feature = writer.next();
1212:
1213: if (feature.getID().equals(roadFeatures[0].getID())) {
1214: feature.setAttribute("name", "changed");
1215: writer.write();
1216: }
1217: }
1218:
1219: feature = (Feature) feature("road", roadFeatures[0].getID());
1220: assertNotNull(feature);
1221: assertEquals("changed", feature.getAttribute("name"));
1222: }
1223:
1224: public void testGetFeatureWriterTypeNameTransaction()
1225: throws NoSuchElementException, IOException,
1226: IllegalAttributeException {
1227: FeatureWriter writer;
1228:
1229: writer = data.getFeatureWriter("road", Transaction.AUTO_COMMIT);
1230: assertEquals(roadFeatures.length, count(writer));
1231:
1232: //writer.close(); called by count.
1233: }
1234:
1235: public void testGetFeatureWriterAppendTypeNameTransaction()
1236: throws Exception {
1237: FeatureWriter writer;
1238:
1239: writer = data.getFeatureWriterAppend("road",
1240: Transaction.AUTO_COMMIT);
1241: assertEquals(0, count(writer));
1242:
1243: //writer.close(); called by count
1244: }
1245:
1246: /*
1247: * Test for FeatureWriter getFeatureWriter(String, boolean, Transaction)
1248: * @task REVISIT: JDBCDataStore currently does not return these proper
1249: * instanceof's. If we want to guarantee that people can't append to
1250: * a request with a FeatureWriter then we could add the functionality to
1251: * JDBCDataStore by having getFeatureWriter(.. Filter ...) check to see if
1252: * the FeatureWriter returned is instanceof FilteringFeatureWriter, and if
1253: * not then just wrap it in a FilteringFeatureWriter(writer, Filter.INCLUDE).
1254: * I think it'd be a bit of unnecessary overhead, but if we want it it's
1255: * easy to do. It will guarantee that calls with Filter won't ever append.
1256: * Doing with Filter.INCLUDE, however, would require a bit of reworking, as
1257: * the Filter getFeatureWriter is currently where we do the bulk of
1258: * the work.
1259: */
1260: public void testGetFeatureWriterFilter()
1261: throws NoSuchElementException, IOException,
1262: IllegalAttributeException {
1263: FeatureWriter writer;
1264:
1265: writer = data.getFeatureWriter("road", Filter.EXCLUDE,
1266: Transaction.AUTO_COMMIT);
1267:
1268: //see task above
1269: // assertTrue(writer instanceof EmptyFeatureWriter);
1270: assertEquals(0, count(writer));
1271:
1272: writer = data.getFeatureWriter("road", Filter.INCLUDE,
1273: Transaction.AUTO_COMMIT);
1274:
1275: //assertFalse(writer instanceof FilteringFeatureWriter);
1276: assertEquals(roadFeatures.length, count(writer));
1277:
1278: writer = data.getFeatureWriter("road", rd1Filter,
1279: Transaction.AUTO_COMMIT);
1280:
1281: //assertTrue(writer instanceof FilteringFeatureWriter);
1282: assertEquals(1, count(writer));
1283: }
1284:
1285: // Uncomment when and if MySQLDataStore will support transaction
1286: // /**
1287: // * Test two transactions one removing feature, and one adding a feature.
1288: // *
1289: // * @throws Exception DOCUMENT ME!
1290: // */
1291: // public void testGetFeatureWriterTransaction() throws Exception {
1292: // Transaction t1 = new DefaultTransaction();
1293: // Transaction t2 = new DefaultTransaction();
1294: // FeatureWriter writer1 = data.getFeatureWriter("road", rd1Filter, t1);
1295: // FeatureWriter writer2 = data.getFeatureWriterAppend("road", t2);
1296: //
1297: // FeatureType road = data.getSchema("road");
1298: // FeatureReader reader;
1299: // Feature feature;
1300: // Feature[] ORIGIONAL = roadFeatures;
1301: // Feature[] REMOVE = new Feature[ORIGIONAL.length - 1];
1302: // Feature[] ADD = new Feature[ORIGIONAL.length + 1];
1303: // Feature[] FINAL = new Feature[ORIGIONAL.length];
1304: // int i;
1305: // int index;
1306: // index = 0;
1307: //
1308: // for (i = 0; i < ORIGIONAL.length; i++) {
1309: // feature = ORIGIONAL[i];
1310: //
1311: // if (!feature.getID().equals(roadFeatures[0].getID())) {
1312: // REMOVE[index++] = feature;
1313: // }
1314: // }
1315: //
1316: // for (i = 0; i < ORIGIONAL.length; i++) {
1317: // ADD[i] = ORIGIONAL[i];
1318: // }
1319: //
1320: // ADD[i] = newRoad; // will need to update with Fid from database
1321: //
1322: // for (i = 0; i < REMOVE.length; i++) {
1323: // FINAL[i] = REMOVE[i];
1324: // }
1325: //
1326: // FINAL[i] = newRoad; // will need to update with Fid from database
1327: //
1328: // // start of with ORIGINAL
1329: // reader = data.getFeatureReader(road, Filter.INCLUDE, Transaction.AUTO_COMMIT);
1330: // assertTrue(covers(reader, ORIGIONAL));
1331: //
1332: // // writer 1 removes road.rd1 on t1
1333: // // -------------------------------
1334: // // - tests transaction independence from DataStore
1335: // while (writer1.hasNext()) {
1336: // feature = writer1.next();
1337: // assertEquals(roadFeatures[0].getID(), feature.getID());
1338: // writer1.remove();
1339: // }
1340: //
1341: // // still have ORIGIONAL and t1 has REMOVE
1342: // reader = data.getFeatureReader(road, Filter.INCLUDE, Transaction.AUTO_COMMIT);
1343: // assertTrue(covers(reader, ORIGIONAL));
1344: //
1345: // reader = data.getFeatureReader(road, Filter.INCLUDE, t1);
1346: // assertTrue(covers(reader, REMOVE));
1347: //
1348: // // close writer1
1349: // // --------------
1350: // // ensure that modification is left up to transaction commmit
1351: // writer1.close();
1352: //
1353: // // We still have ORIGIONAL and t1 has REMOVE
1354: // reader = data.getFeatureReader(road, Filter.INCLUDE, Transaction.AUTO_COMMIT);
1355: // assertTrue(covers(reader, ORIGIONAL));
1356: //
1357: // reader = data.getFeatureReader(road, Filter.INCLUDE, t1);
1358: // assertTrue(covers(reader, REMOVE));
1359: //
1360: // // writer 2 adds road.rd4 on t2
1361: // // ----------------------------
1362: // // - tests transaction independence from each other
1363: // feature = writer2.next();
1364: // feature.setAttributes(newRoad.getAttributes(null));
1365: // writer2.write();
1366: //
1367: // // HACK: ?!? update ADD and FINAL with new FID from database
1368: // //
1369: // reader = data.getFeatureReader(road, Filter.INCLUDE, t2);
1370: // newRoad = findFeature(reader, "id", new Integer(4));
1371: // System.out.println("newRoad:" + newRoad);
1372: // ADD[ADD.length - 1] = newRoad;
1373: // FINAL[FINAL.length - 1] = newRoad;
1374: //
1375: // // We still have ORIGIONAL and t2 has ADD
1376: // reader = data.getFeatureReader(road, Filter.INCLUDE, Transaction.AUTO_COMMIT);
1377: // assertTrue(covers(reader, ORIGIONAL));
1378: //
1379: // reader = data.getFeatureReader(road, Filter.INCLUDE, t2);
1380: // assertMatched(ADD, reader); // broken due to FID problem
1381: //
1382: // writer2.close();
1383: //
1384: // // Still have ORIGIONAL and t2 has ADD
1385: // reader = data.getFeatureReader(road, Filter.INCLUDE, Transaction.AUTO_COMMIT);
1386: // assertTrue(covers(reader, ORIGIONAL));
1387: // reader = data.getFeatureReader(road, Filter.INCLUDE, t2);
1388: // assertTrue(coversLax(reader, ADD));
1389: //
1390: // // commit t1
1391: // // ---------
1392: // // -ensure that delayed writing of transactions takes place
1393: // //
1394: // t1.commit();
1395: //
1396: // // We now have REMOVE, as does t1 (which has not additional diffs)
1397: // // t2 will have FINAL
1398: // reader = data.getFeatureReader(road, Filter.INCLUDE, Transaction.AUTO_COMMIT);
1399: // assertTrue(covers(reader, REMOVE));
1400: // reader = data.getFeatureReader(road, Filter.INCLUDE, t1);
1401: // assertTrue(covers(reader, REMOVE));
1402: // reader = data.getFeatureReader(road, Filter.INCLUDE, t2);
1403: // assertTrue(coversLax(reader, FINAL));
1404: //
1405: // // commit t2
1406: // // ---------
1407: // // -ensure that everyone is FINAL at the end of the day
1408: // t2.commit();
1409: //
1410: // // We now have Number( remove one and add one)
1411: // reader = data.getFeatureReader(road, Filter.INCLUDE, Transaction.AUTO_COMMIT);
1412: // reader = data.getFeatureReader(road, Filter.INCLUDE, Transaction.AUTO_COMMIT);
1413: // assertTrue(coversLax(reader, FINAL));
1414: //
1415: // reader = data.getFeatureReader(road, Filter.INCLUDE, t1);
1416: // assertTrue(coversLax(reader, FINAL));
1417: //
1418: // reader = data.getFeatureReader(road, Filter.INCLUDE, t2);
1419: // assertTrue(coversLax(reader, FINAL));
1420: // }
1421:
1422: // Feature Source Testing
1423: public void testGetFeatureSourceRoad() throws IOException {
1424: FeatureSource road = data.getFeatureSource("road");
1425:
1426: assertEquals(roadType, road.getSchema());
1427: assertSame(data, road.getDataStore());
1428:
1429: int count = road.getCount(Query.ALL);
1430: assertTrue((count == 3) || (count == -1));
1431:
1432: Envelope bounds = road.getBounds(Query.ALL);
1433: assertTrue((bounds == null) || bounds.equals(roadBounds));
1434:
1435: FeatureCollection all = road.getFeatures();
1436: assertEquals(3, all.size());
1437: assertEquals(roadBounds, all.getBounds());
1438:
1439: FeatureCollection expected = DataUtilities
1440: .collection(roadFeatures);
1441:
1442: assertCovers("all", expected, all);
1443: assertEquals(roadBounds, all.getBounds());
1444:
1445: FeatureCollection some = road.getFeatures(rd12Filter);
1446: assertEquals(2, some.size());
1447:
1448: Envelope e = new Envelope();
1449: e.expandToInclude(roadFeatures[0].getBounds());
1450: e.expandToInclude(roadFeatures[1].getBounds());
1451: assertEquals(e, some.getBounds());
1452: assertEquals(some.getSchema(), road.getSchema());
1453:
1454: DefaultQuery query = new DefaultQuery("road", rd12Filter,
1455: new String[] { "name" });
1456:
1457: FeatureCollection half = road.getFeatures(query);
1458: assertEquals(2, half.size());
1459: assertEquals(1, half.getSchema().getAttributeCount());
1460:
1461: FeatureIterator reader = half.features();
1462: FeatureType type = half.getSchema();
1463: reader.close();
1464:
1465: FeatureType actual = half.getSchema();
1466:
1467: assertEquals(type.getTypeName(), actual.getTypeName());
1468: assertEquals(type.getNamespace(), actual.getNamespace());
1469: assertEquals(type.getAttributeCount(), actual
1470: .getAttributeCount());
1471:
1472: for (int i = 0; i < type.getAttributeCount(); i++) {
1473: assertEquals(type.getAttributeType(i), actual
1474: .getAttributeType(i));
1475: }
1476:
1477: assertNull(type.getDefaultGeometry());
1478: assertEquals(type.getDefaultGeometry(), actual
1479: .getDefaultGeometry());
1480: assertEquals(type, actual);
1481:
1482: Envelope b = half.getBounds();
1483: assertEquals(roadBounds, b);
1484: }
1485:
1486: public void testGetFeatureSourceRiver()
1487: throws NoSuchElementException, IOException,
1488: IllegalAttributeException {
1489: FeatureSource river = data.getFeatureSource("river");
1490:
1491: assertEquals(riverType, river.getSchema());
1492: assertSame(data, river.getDataStore());
1493:
1494: FeatureCollection all = river.getFeatures();
1495: assertEquals(2, all.size());
1496: assertEquals(riverBounds, all.getBounds());
1497: assertTrue("rivers", covers(all.features(), riverFeatures));
1498:
1499: FeatureCollection expected = DataUtilities
1500: .collection(riverFeatures);
1501: assertCovers("all", expected, all);
1502: assertEquals(riverBounds, all.getBounds());
1503: }
1504:
1505: //
1506: // Feature Store Testing
1507: //
1508: public void testGetFeatureStoreModifyFeatures1() throws IOException {
1509: FeatureStore road = (FeatureStore) data
1510: .getFeatureSource("road");
1511:
1512: //FilterFactory factory = FilterFactoryFinder.createFilterFactory();
1513: //rd1Filter = factory.createFidFilter( roadFeatures[0].getID() );
1514: Object changed = new Integer(5);
1515: AttributeType name = roadType.getAttributeType("id");
1516: road.modifyFeatures(name, changed, rd1Filter);
1517:
1518: FeatureCollection results = road.getFeatures(rd1Filter);
1519: assertEquals(changed, results.features().next().getAttribute(
1520: "id"));
1521: }
1522:
1523: public void testGetFeatureStoreModifyFeatures2() throws IOException {
1524: FeatureStore road = (FeatureStore) data
1525: .getFeatureSource("road");
1526:
1527: FilterFactory factory = FilterFactoryFinder
1528: .createFilterFactory();
1529: rd1Filter = factory.createFidFilter(roadFeatures[0].getID());
1530:
1531: AttributeType name = roadType.getAttributeType("name");
1532: road.modifyFeatures(new AttributeType[] { name, },
1533: new Object[] { "changed", }, rd1Filter);
1534:
1535: FeatureCollection results = road.getFeatures(rd1Filter);
1536: assertEquals("changed", results.features().next().getAttribute(
1537: "name"));
1538: }
1539:
1540: public void testGetFeatureStoreRemoveFeatures() throws IOException {
1541: FeatureStore road = (FeatureStore) data
1542: .getFeatureSource("road");
1543:
1544: road.removeFeatures(rd1Filter);
1545: assertEquals(0, road.getFeatures(rd1Filter).size());
1546: assertEquals(roadFeatures.length - 1, road.getFeatures().size());
1547: }
1548:
1549: public void testGetFeatureStoreAddFeatures() throws IOException {
1550: FeatureStore road = (FeatureStore) data
1551: .getFeatureSource("road");
1552:
1553: road.addFeatures(DataUtilities.collection(newRoad));
1554: assertEquals(roadFeatures.length + 1, count("road"));
1555: }
1556:
1557: public void testGetFeatureStoreSetFeatures()
1558: throws NoSuchElementException, IOException,
1559: IllegalAttributeException {
1560: FeatureReader reader = DataUtilities
1561: .reader(new Feature[] { newRoad, });
1562:
1563: FeatureStore road = (FeatureStore) data
1564: .getFeatureSource("road");
1565:
1566: assertEquals(3, count("road"));
1567:
1568: road.setFeatures(reader);
1569:
1570: assertEquals(1, count("road"));
1571: }
1572:
1573: // Uncomment when and if MySQLDataStore will support transaction
1574: // public void testGetFeatureStoreTransactionSupport() throws Exception {
1575: // Transaction t1 = new DefaultTransaction();
1576: // Transaction t2 = new DefaultTransaction();
1577: //
1578: // FeatureStore road = (FeatureStore) data.getFeatureSource("road");
1579: // FeatureStore road1 = (FeatureStore) data.getFeatureSource("road");
1580: // FeatureStore road2 = (FeatureStore) data.getFeatureSource("road");
1581: //
1582: // road1.setTransaction(t1);
1583: // road2.setTransaction(t2);
1584: //
1585: // Feature feature;
1586: // Feature[] ORIGIONAL = roadFeatures;
1587: // Feature[] REMOVE = new Feature[ORIGIONAL.length - 1];
1588: // Feature[] ADD = new Feature[ORIGIONAL.length + 1];
1589: // Feature[] FINAL = new Feature[ORIGIONAL.length];
1590: // int i;
1591: // int index;
1592: // index = 0;
1593: //
1594: // for (i = 0; i < ORIGIONAL.length; i++) {
1595: // feature = ORIGIONAL[i];
1596: // LOGGER.info("id is " + feature.getID());
1597: //
1598: // if (!feature.getID().equals("road.rd1")) {
1599: // REMOVE[index++] = feature;
1600: // }
1601: // }
1602: //
1603: // for (i = 0; i < ORIGIONAL.length; i++) {
1604: // ADD[i] = ORIGIONAL[i];
1605: // }
1606: //
1607: // ADD[i] = newRoad;
1608: //
1609: // for (i = 0; i < REMOVE.length; i++) {
1610: // FINAL[i] = REMOVE[i];
1611: // }
1612: //
1613: // FINAL[i] = newRoad;
1614: //
1615: // // start of with ORIGINAL
1616: // assertTrue(covers(road.getFeatures().reader(), ORIGIONAL));
1617: //
1618: // // road1 removes road.rd1 on t1
1619: // // -------------------------------
1620: // // - tests transaction independence from DataStore
1621: // road1.removeFeatures(rd1Filter);
1622: //
1623: // // still have ORIGIONAL and t1 has REMOVE
1624: // assertTrue(covers(road.getFeatures().reader(), ORIGIONAL));
1625: // assertTrue(covers(road1.getFeatures().reader(), REMOVE));
1626: //
1627: // // road2 adds road.rd4 on t2
1628: // // ----------------------------
1629: // // - tests transaction independence from each other
1630: // FeatureReader reader = DataUtilities.reader(new Feature[] { newRoad, });
1631: // road2.addFeatures(reader);
1632: //
1633: // // We still have ORIGIONAL, t1 has REMOVE, and t2 has ADD
1634: // assertTrue(covers(road.getFeatures().reader(), ORIGIONAL));
1635: // assertTrue(covers(road1.getFeatures().reader(), REMOVE));
1636: // assertTrue(coversLax(road2.getFeatures().reader(), ADD));
1637: //
1638: // // commit t1
1639: // // ---------
1640: // // -ensure that delayed writing of transactions takes place
1641: // //
1642: // t1.commit();
1643: //
1644: // // We now have REMOVE, as does t1 (which has not additional diffs)
1645: // // t2 will have FINAL
1646: // assertTrue(covers(road.getFeatures().reader(), REMOVE));
1647: // assertTrue(covers(road1.getFeatures().reader(), REMOVE));
1648: // assertTrue(coversLax(road2.getFeatures().reader(), FINAL));
1649: //
1650: // // commit t2
1651: // // ---------
1652: // // -ensure that everyone is FINAL at the end of the day
1653: // t2.commit();
1654: //
1655: // // We now have Number( remove one and add one)
1656: // assertTrue(coversLax(road.getFeatures().reader(), FINAL));
1657: // assertTrue(coversLax(road1.getFeatures().reader(), FINAL));
1658: // assertTrue(coversLax(road2.getFeatures().reader(), FINAL));
1659: // }
1660:
1661: boolean isLocked(String typeName, String fid) {
1662: InProcessLockingManager lockingManager = (InProcessLockingManager) data
1663: .getLockingManager();
1664:
1665: return lockingManager.isLocked(typeName, fid);
1666: }
1667:
1668: //
1669: // FeatureLocking Testing
1670: //
1671:
1672: /*
1673: * Test for void lockFeatures()
1674: */
1675: public void testLockFeatures() throws IOException {
1676: FeatureLock lock = FeatureLockFactory.generate("test",
1677: LOCK_DURATION);
1678: FeatureLocking road = (FeatureLocking) data
1679: .getFeatureSource("road");
1680: road.setFeatureLock(lock);
1681:
1682: assertFalse(isLocked("road", "road.rd1"));
1683: road.lockFeatures();
1684: assertTrue(isLocked("road", "road.rd1"));
1685: }
1686:
1687: public void testUnLockFeatures() throws IOException {
1688: FeatureLock lock = FeatureLockFactory.generate("test",
1689: LOCK_DURATION);
1690: FeatureLocking road = (FeatureLocking) data
1691: .getFeatureSource("road");
1692: road.setFeatureLock(lock);
1693: road.lockFeatures();
1694:
1695: try {
1696: road.unLockFeatures();
1697: fail("unlock should fail due on AUTO_COMMIT");
1698: } catch (IOException expected) {
1699: }
1700:
1701: Transaction t = new DefaultTransaction();
1702: road.setTransaction(t);
1703:
1704: try {
1705: road.unLockFeatures();
1706: fail("unlock should fail due lack of authorization");
1707: } catch (IOException expected) {
1708: }
1709:
1710: t.addAuthorization(lock.getAuthorization());
1711: road.unLockFeatures();
1712: }
1713:
1714: public void testLockFeatureInteraction() throws IOException {
1715: FeatureLock lockA = FeatureLockFactory.generate("LockA",
1716: LOCK_DURATION);
1717: FeatureLock lockB = FeatureLockFactory.generate("LockB",
1718: LOCK_DURATION);
1719: Transaction t1 = new DefaultTransaction();
1720: Transaction t2 = new DefaultTransaction();
1721: FeatureLocking road1 = (FeatureLocking) data
1722: .getFeatureSource("road");
1723: FeatureLocking road2 = (FeatureLocking) data
1724: .getFeatureSource("road");
1725: road1.setTransaction(t1);
1726: road2.setTransaction(t2);
1727: road1.setFeatureLock(lockA);
1728: road2.setFeatureLock(lockB);
1729:
1730: assertFalse(isLocked("road", "road.rd1"));
1731: assertFalse(isLocked("road", "road.rd2"));
1732: assertFalse(isLocked("road", "road.rd3"));
1733:
1734: road1.lockFeatures(rd1Filter);
1735: assertTrue(isLocked("road", "road.rd1"));
1736: assertFalse(isLocked("road", "road.rd2"));
1737: assertFalse(isLocked("road", "road.rd3"));
1738:
1739: road2.lockFeatures(rd2Filter);
1740: assertTrue(isLocked("road", "road.rd1"));
1741: assertTrue(isLocked("road", "road.rd2"));
1742: assertFalse(isLocked("road", "road.rd3"));
1743:
1744: try {
1745: road1.unLockFeatures(rd1Filter);
1746: fail("need authorization");
1747: } catch (IOException expected) {
1748: }
1749:
1750: t1.addAuthorization(lockA.getAuthorization());
1751:
1752: try {
1753: road1.unLockFeatures(rd2Filter);
1754: fail("need correct authorization");
1755: } catch (IOException expected) {
1756: }
1757:
1758: road1.unLockFeatures(rd1Filter);
1759: assertFalse(isLocked("road", "road.rd1"));
1760: assertTrue(isLocked("road", "road.rd2"));
1761: assertFalse(isLocked("road", "road.rd3"));
1762:
1763: t2.addAuthorization(lockB.getAuthorization());
1764: road2.unLockFeatures(rd2Filter);
1765: assertFalse(isLocked("road", "road.rd1"));
1766: assertFalse(isLocked("road", "road.rd2"));
1767: assertFalse(isLocked("road", "road.rd3"));
1768: }
1769:
1770: public void testGetFeatureLockingExpire() throws Exception {
1771: FeatureLock lock = FeatureLockFactory.generate("Timed", 200);
1772:
1773: FeatureLocking road = (FeatureLocking) data
1774: .getFeatureSource("road");
1775: road.setFeatureLock(lock);
1776: assertFalse(isLocked("road", "road.rd1"));
1777:
1778: road.lockFeatures(rd1Filter);
1779: assertTrue(isLocked("road", "road.rd1"));
1780: long then = System.currentTimeMillis();
1781: do {
1782: Thread.sleep(200);
1783: } while (System.currentTimeMillis() - then < 200);
1784: assertFalse(isLocked("road", "road.rd1"));
1785: }
1786: }
|