/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2003-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.data.collection;
import java.io.IOException;
import java.util.NoSuchElementException;
import org.geotools.data.DataTestCase;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultQuery;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.DiffFeatureReader;
import org.geotools.data.EmptyFeatureReader;
import org.geotools.data.FeatureReader;
import org.geotools.data.FeatureWriter;
import org.geotools.data.FilteringFeatureReader;
import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.data.TransactionStateDiff;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.IllegalAttributeException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
/**
* DOCUMENT ME!
*
* @author Jody Garnett, Refractions Research
*
* @source $URL$
*/
public class CollectionDataStoreTest extends DataTestCase {
CollectionDataStore data;
/**
* Constructor for MemoryDataStoreTest.
*
* @param arg0
*/
public CollectionDataStoreTest(String arg0) {
super(arg0);
}
/*
* @see TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
data = new CollectionDataStore(DataUtilities.collection(roadFeatures));
}
/*
* @see TestCase#tearDown()
*/
protected void tearDown() throws Exception {
data = null;
}
public void testGetFeatureTypes() {
String[] names = data.getTypeNames();
assertEquals(1, names.length);
assertTrue(contains(names, "road"));
}
boolean contains(Object[] array, Object expected) {
if ((array == null) || (array.length == 0)) {
return false;
}
for (int i = 0; i < array.length; i++) {
if (array[i].equals(expected)) {
return true;
}
}
return false;
}
/**
* Like contain but based on match rather than equals
*
* @param array DOCUMENT ME!
* @param expected DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
boolean containsLax(SimpleFeature[] array, SimpleFeature expected) {
if ((array == null) || (array.length == 0)) {
return false;
}
SimpleFeatureType type = expected.getFeatureType();
for (int i = 0; i < array.length; i++) {
if (match(array[i], expected)) {
return true;
}
}
return false;
}
/**
* Compare based on attributes not getID allows comparison of Diff contents
*
* @param expected DOCUMENT ME!
* @param actual DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
boolean match(SimpleFeature expected, SimpleFeature actual) {
SimpleFeatureType type = expected.getFeatureType();
for (int i = 0; i < type.getAttributeCount(); i++) {
Object av = actual.getAttribute(i);
Object ev = expected.getAttribute(i);
if ((av == null) && (ev != null)) {
return false;
} else if ((ev == null) && (av != null)) {
return false;
} else if (av instanceof Geometry && ev instanceof Geometry) {
Geometry ag = (Geometry) av;
Geometry eg = (Geometry) ev;
if (!ag.equals(eg)) {
return false;
}
} else if (!av.equals(ev)) {
return false;
}
}
return true;
}
public void testGetSchema() throws IOException {
assertSame(roadType, data.getSchema("road"));
}
void assertCovers(String msg, SimpleFeatureCollection c1, SimpleFeatureCollection c2) {
if (c1 == c2) {
return;
}
assertNotNull(msg, c1);
assertNotNull(msg, c2);
assertEquals(msg + " size", c1.size(), c2.size());
SimpleFeature f;
for (SimpleFeatureIterator i = c1.features(); i.hasNext();) {
f = i.next();
assertTrue(msg + " " + f.getID(), c2.contains(f));
}
}
public void testGetFeatureReader() throws IOException, IllegalAttributeException {
FeatureReader<SimpleFeatureType, SimpleFeature> reader = data.getFeatureReader("road");
assertCovered(roadFeatures, reader);
assertEquals(false, reader.hasNext());
}
// public void testGetFeatureReaderMutability() throws IOException, IllegalAttributeException {
// FeatureReader<SimpleFeatureType, SimpleFeature> reader = data.getFeatureReader("road");
// Feature feature;
//
// while (reader.hasNext()) {
// feature = (Feature) reader.next();
// feature.setAttribute("name", null);
// }
//
// reader.close();
//
// reader = data.getFeatureReader("road");
//
// while (reader.hasNext()) {
// feature = (Feature) reader.next();
// assertNotNull(feature.getAttribute("name"));
// }
//
// reader.close();
//
// try {
// reader.next();
// fail("next should fail with an IOException");
// } catch (IOException expected) {
// }
// }
public void testGetFeatureReaderConcurancy()
throws NoSuchElementException, IOException, IllegalAttributeException {
FeatureReader<SimpleFeatureType, SimpleFeature> reader1 = data.getFeatureReader("road");
FeatureReader<SimpleFeatureType, SimpleFeature> reader2 = data.getFeatureReader("road");
SimpleFeature feature1;
SimpleFeature feature2;
while (reader1.hasNext() || reader2.hasNext()) {
assertTrue(contains(roadFeatures, reader1.next()));
assertTrue(contains(roadFeatures, reader2.next()));
}
try {
reader1.next();
fail("next should fail with an IOException");
} catch (IOException expected) {
}
try {
reader2.next();
fail("next should fail with an IOException");
} catch (IOException expected) {
}
reader1.close();
reader2.close();
}
public void testGetFeatureReaderFilterAutoCommit()
throws NoSuchElementException, IOException, IllegalAttributeException {
SimpleFeatureType type = data.getSchema("road");
FeatureReader<SimpleFeatureType, SimpleFeature> reader;
reader = data.getFeatureReader(new DefaultQuery("road"), Transaction.AUTO_COMMIT);
assertFalse(reader instanceof FilteringFeatureReader);
assertEquals(type, reader.getFeatureType());
assertEquals(roadFeatures.length, count(reader));
reader = data.getFeatureReader(new DefaultQuery("road", Filter.EXCLUDE), Transaction.AUTO_COMMIT);
assertTrue(reader instanceof EmptyFeatureReader);
assertEquals(type, reader.getFeatureType());
assertEquals(0, count(reader));
reader = data.getFeatureReader(new DefaultQuery("road", rd1Filter), Transaction.AUTO_COMMIT);
assertTrue(reader instanceof FilteringFeatureReader);
assertEquals(type, reader.getFeatureType());
assertEquals(1, count(reader));
}
public void testGetFeatureReaderFilterTransaction()
throws NoSuchElementException, IOException, IllegalAttributeException {
Transaction t = new DefaultTransaction();
SimpleFeatureType type = data.getSchema("road");
FeatureReader<SimpleFeatureType, SimpleFeature> reader;
reader = data.getFeatureReader(new DefaultQuery("road", Filter.EXCLUDE), t);
assertTrue(reader instanceof EmptyFeatureReader);
assertEquals(type, reader.getFeatureType());
assertEquals(0, count(reader));
reader = data.getFeatureReader(new DefaultQuery("road"), t);
assertTrue(reader instanceof DiffFeatureReader);
assertEquals(type, reader.getFeatureType());
assertEquals(roadFeatures.length, count(reader));
reader = data.getFeatureReader(new DefaultQuery("road", rd1Filter), t);
//assertTrue(reader instanceof DiffFeatureReader); //currently it is being wraped by a FilteringFeatureReader
assertEquals(type, reader.getFeatureType());
assertEquals(1, count(reader));
TransactionStateDiff state = (TransactionStateDiff) t.getState(data);
FeatureWriter<SimpleFeatureType, SimpleFeature> writer = state.writer("road", Filter.INCLUDE);
SimpleFeature feature;
while (writer.hasNext()) {
feature = writer.next();
if (feature.getID().equals("road.rd1")) {
writer.remove();
}
}
reader = data.getFeatureReader(new DefaultQuery("road", Filter.EXCLUDE), t);
assertEquals(0, count(reader));
reader = data.getFeatureReader(new DefaultQuery("road"), t);
assertEquals(roadFeatures.length - 1, count(reader));
reader = data.getFeatureReader(new DefaultQuery("road", rd1Filter), t);
assertEquals(0, count(reader));
t.rollback();
reader = data.getFeatureReader(new DefaultQuery("road", Filter.EXCLUDE), t);
assertEquals(0, count(reader));
reader = data.getFeatureReader(new DefaultQuery("road"), t);
assertEquals(roadFeatures.length, count(reader));
reader = data.getFeatureReader(new DefaultQuery("road", rd1Filter), t);
assertEquals(1, count(reader));
}
void assertCovered(SimpleFeature[] features, FeatureReader<SimpleFeatureType, SimpleFeature> reader)
throws NoSuchElementException, IOException, IllegalAttributeException {
int count = 0;
try {
while (reader.hasNext()) {
assertTrue(contains(features, reader.next()));
count++;
}
} finally {
reader.close();
}
assertEquals(features.length, count);
}
/**
* Ensure that FeatureReader<SimpleFeatureType, SimpleFeature> reader contains extactly the contents of array.
*
* @param reader DOCUMENT ME!
* @param array DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws NoSuchElementException DOCUMENT ME!
* @throws IOException DOCUMENT ME!
* @throws IllegalAttributeException DOCUMENT ME!
*/
boolean covers(FeatureReader <SimpleFeatureType, SimpleFeature> reader, SimpleFeature[] array)
throws NoSuchElementException, IOException, IllegalAttributeException {
SimpleFeature feature;
int count = 0;
try {
while (reader.hasNext()) {
feature = reader.next();
if (!contains(array, feature)) {
return false;
}
count++;
}
} finally {
reader.close();
}
return count == array.length;
}
boolean coversLax(FeatureReader <SimpleFeatureType, SimpleFeature> reader, SimpleFeature[] array)
throws NoSuchElementException, IOException, IllegalAttributeException {
SimpleFeature feature;
int count = 0;
try {
while (reader.hasNext()) {
feature = reader.next();
if (!containsLax(array, feature)) {
return false;
}
count++;
}
} finally {
reader.close();
}
return count == array.length;
}
void dump(FeatureReader <SimpleFeatureType, SimpleFeature> reader)
throws NoSuchElementException, IOException, IllegalAttributeException {
SimpleFeature feature;
int count = 0;
try {
while (reader.hasNext()) {
feature = reader.next();
System.out.println(count + " feature:" + feature);
count++;
}
} finally {
reader.close();
}
}
void dump(Object[] array) {
for (int i = 0; i < array.length; i++) {
System.out.println(i + " feature:" + array[i]);
}
}
// SimpleFeature Source Testing
public void testGetFeatureSourceRoad() throws IOException {
SimpleFeatureSource road = data.getFeatureSource("road");
assertSame(roadType, road.getSchema());
assertSame(data, road.getDataStore());
assertEquals(3, road.getCount(Query.ALL));
assertEquals(new Envelope(1, 5, 0, 4), road.getBounds(Query.ALL));
SimpleFeatureCollection all = road.getFeatures();
assertEquals(3, all.size());
assertEquals(roadBounds, all.getBounds());
SimpleFeatureCollection expected = DataUtilities.collection(roadFeatures);
assertCovers("all", expected, all);
assertEquals(roadBounds, all.getBounds());
SimpleFeatureCollection some = road.getFeatures(rd12Filter);
assertEquals(2, some.size());
assertEquals(rd12Bounds, some.getBounds());
assertEquals(some.getSchema(), road.getSchema());
DefaultQuery query = new DefaultQuery( road.getSchema().getTypeName(), rd12Filter, new String[] { "name" });
SimpleFeatureCollection half = road.getFeatures(query);
assertEquals(2, half.size());
assertEquals(1, half.getSchema().getAttributeCount());
SimpleFeatureIterator reader = half.features();
SimpleFeatureType type = half.getSchema();
reader.close();
SimpleFeatureType actual = half.getSchema();
String name = type.getTypeName();
assertEquals(name, actual.getTypeName());
assertEquals(type.getName().getNamespaceURI(), actual.getName().getNamespaceURI());
assertEquals(type.getAttributeCount(), actual.getAttributeCount());
for (int i = 0; i < type.getAttributeCount(); i++) {
assertEquals(type.getDescriptor(i), actual.getDescriptor(i));
}
assertNull(type.getGeometryDescriptor());
assertEquals(type.getGeometryDescriptor(), actual.getGeometryDescriptor());
assertEquals(type, actual);
Envelope b = half.getBounds();
assertEquals(new Envelope(1,5,0,4), b);
}
}