/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.feature.retype;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import junit.framework.TestCase;
import org.geoserver.data.test.MockData;
import org.geoserver.util.IOUtils;
import org.geotools.data.DataStore;
import org.geotools.data.DataUtilities;
import org.geotools.data.Query;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureLock;
import org.geotools.data.FeatureLockFactory;
import org.geotools.data.FeatureReader;
import org.geotools.data.FeatureStore;
import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.data.property.PropertyDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureLocking;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.filter.identity.FeatureIdImpl;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.Id;
import org.opengis.filter.identity.FeatureId;
import com.vividsolutions.jts.io.WKTReader;
public class RetypingDataStoreTest {
static final String RENAMED = "houses";
RetypingDataStore rts;
private File data;
private Id fidFilter;
private String fid;
@Before
public void setUp() throws Exception {
data = File.createTempFile("retype", "data", new File("./target"));
data.delete();
data.mkdir();
final String fileName = MockData.BUILDINGS.getLocalPart() + ".properties";
URL properties = MockData.class.getResource(fileName);
IOUtils.copy(properties.openStream(), new File(data, fileName));
PropertyDataStore pds = new PropertyDataStore(data);
rts = new RetypingDataStore(pds) {
@Override
protected String transformFeatureTypeName(String originalName) {
if (originalName.equals(MockData.BUILDINGS.getLocalPart()))
return RENAMED;
else
return super.transformFeatureTypeName(originalName);
}
};
// build a filter that will retrieve one feature only
FilterFactory ff = CommonFactoryFinder.getFilterFactory(null);
fid = RENAMED + ".1107531701011";
fidFilter = ff.id(Collections.singleton(ff.featureId(fid)));
}
@After
public void tearDown() throws Exception {
IOUtils.delete(data);
}
@Test
public void testLookupFeatureType() throws Exception {
try {
rts.getSchema(MockData.BUILDINGS.getLocalPart());
fail("The original type name should not be visible");
} catch (IOException e) {
// cool, as expected
}
final SimpleFeatureType schema = rts.getSchema(RENAMED);
assertNotNull(schema);
assertEquals(RENAMED, schema.getName().getLocalPart());
}
@Test
public void testGetFeaturesFeatureSource() throws Exception {
// check the schemas in feature source and feature collection
SimpleFeatureSource fs = rts.getFeatureSource(RENAMED);
assertEquals(RENAMED, fs.getSchema().getName().getLocalPart());
SimpleFeatureCollection fc = fs.getFeatures();
assertEquals(RENAMED, fc.getSchema().getName().getLocalPart());
assertTrue(fc.size() > 0);
// make sure the feature schema is good as well
FeatureIterator <SimpleFeature> it = fc.features();
SimpleFeature sf = it.next();
it.close();
assertEquals(RENAMED, sf.getFeatureType().getName().getLocalPart());
// check the feature ids have been renamed as well
assertTrue("Feature id has not been renamed, it's still " + sf.getID(), sf.getID()
.startsWith(RENAMED));
}
@Test
public void testGetFeaturesReader() throws Exception {
FeatureReader<SimpleFeatureType, SimpleFeature> fr;
fr = rts.getFeatureReader(new Query(RENAMED), Transaction.AUTO_COMMIT);
SimpleFeature sf = fr.next();
fr.close();
assertEquals(RENAMED, sf.getFeatureType().getName().getLocalPart());
// check the feature ids have been renamed as well
assertTrue("Feature id has not been renamed, it's still " + sf.getID(), sf.getID()
.startsWith(RENAMED));
}
@Test
public void testFeautureSourceFidFilter() throws Exception {
// grab the last feature in the collection (there are more than one)
SimpleFeatureSource fs = rts.getFeatureSource(RENAMED);
// build a filter that will retrieve that feature only
FilterFactory ff = CommonFactoryFinder.getFilterFactory(null);
final String fid = RENAMED + ".1107531701011";
Filter fidFilter = ff.id(Collections.singleton(ff.featureId(fid)));
SimpleFeatureCollection fc = fs.getFeatures(new Query(RENAMED, fidFilter));
assertEquals(RENAMED, fc.getSchema().getName().getLocalPart());
assertEquals(1, fc.size());
FeatureIterator <SimpleFeature> it = fc.features();
assertTrue(it.hasNext());
SimpleFeature sf = it.next();
assertFalse(it.hasNext());
it.close();
assertEquals(fid, sf.getID());
}
@Test
public void testFeautureReaderFidFilter() throws Exception {
FeatureReader<SimpleFeatureType, SimpleFeature> fr;
fr = rts.getFeatureReader(new Query(RENAMED, fidFilter), Transaction.AUTO_COMMIT);
assertEquals(RENAMED, fr.getFeatureType().getName().getLocalPart());
assertTrue(fr.hasNext());
SimpleFeature sf = fr.next();
assertFalse(fr.hasNext());
fr.close();
assertEquals(fid, sf.getID());
}
@Test
public void testDelete() throws Exception {
final Query queryAll = new Query(RENAMED);
SimpleFeatureStore store;
store = (SimpleFeatureStore) rts.getFeatureSource(RENAMED);
int count = store.getCount(queryAll);
store.removeFeatures(fidFilter);
assertEquals(count - 1, store.getCount(queryAll));
}
@Test
public void testModify() throws Exception {
final Query queryAll = new Query(RENAMED);
SimpleFeatureStore store;
store = (SimpleFeatureStore) rts.getFeatureSource(RENAMED);
SimpleFeature original = store.getFeatures(fidFilter).features().next();
String newAddress = ((String) original.getAttribute("ADDRESS")) + " xxx";
store.modifyFeatures(original.getFeatureType().getDescriptor("ADDRESS"), newAddress,
fidFilter);
SimpleFeature modified = store.getFeatures(fidFilter).features().next();
assertEquals(newAddress, modified.getAttribute("ADDRESS"));
}
/**
* This test is made with mock objects because the property data store does
* not generate fids in the <type>.<id> form
*
*/
@SuppressWarnings("unchecked")
@Test
public void testAppend() throws Exception {
SimpleFeatureType type = DataUtilities.createType("trees",
"the_geom:Point,FID:String,NAME:String");
SimpleFeatureStore fs = createMock(SimpleFeatureStore.class);
expect(fs.addFeatures(isA(FeatureCollection.class))).andReturn(
Collections.singletonList((FeatureId)(new FeatureIdImpl("trees.105"))));
replay(fs);
DataStore ds = createMock(DataStore.class);
expect(ds.getTypeNames()).andReturn(new String[] { "trees" }).anyTimes();
expect(ds.getSchema("trees")).andReturn(type).anyTimes();
expect(ds.getFeatureSource("trees")).andReturn(fs);
replay(ds);
RetypingDataStore rts = new RetypingDataStore(ds) {
@Override
protected String transformFeatureTypeName(String originalName) {
return "oaks";
}
};
SimpleFeatureBuilder sfb = new SimpleFeatureBuilder(type);
WKTReader reader = new WKTReader();
sfb.set("the_geom", reader.read("POINT (0.002 0.0008)"));
sfb.set("FID", "023");
sfb.set("NAME", "Old oak");
SimpleFeature feature = sfb.buildFeature(null);
SimpleFeatureCollection fc = DataUtilities.collection(feature);
SimpleFeatureStore store = (SimpleFeatureStore) rts.getFeatureSource("oaks");
List<FeatureId> ids = store.addFeatures(fc);
assertEquals(1, ids.size());
String id = ((FeatureId) ids.iterator().next()).getID();
assertTrue("Id does not start with " + "oaks" + " it's " + id, id.startsWith("oaks"));
}
@Test
public void testLockUnlockFilter() throws Exception {
SimpleFeatureLocking fl;
fl = (SimpleFeatureLocking) rts.getFeatureSource(RENAMED);
final FeatureLock lock = FeatureLockFactory.generate(10 * 60 * 1000);
Transaction t = new DefaultTransaction();
t.addAuthorization(lock.getAuthorization());
fl.setTransaction(t);
fl.setFeatureLock(lock);
SimpleFeatureLocking fl2;
fl2 = (SimpleFeatureLocking) rts.getFeatureSource(RENAMED);
fl.setFeatureLock(lock);
fl2.setTransaction(new DefaultTransaction());
assertEquals(1, fl.lockFeatures(fidFilter));
assertEquals(0, fl2.lockFeatures(fidFilter));
fl.unLockFeatures(fidFilter);
assertEquals(1, fl2.lockFeatures(fidFilter));
}
@Test
public void testLockUnlockQuery() throws Exception {
SimpleFeatureLocking fl;
fl = (SimpleFeatureLocking) rts.getFeatureSource(RENAMED);
final FeatureLock lock = FeatureLockFactory.generate(10 * 60 * 1000);
Transaction t = new DefaultTransaction();
t.addAuthorization(lock.getAuthorization());
fl.setTransaction(t);
fl.setFeatureLock(lock);
SimpleFeatureLocking fl2;
fl2 = (SimpleFeatureLocking) rts.getFeatureSource(RENAMED);
fl.setFeatureLock(lock);
fl2.setTransaction(new DefaultTransaction());
Query q = new Query(RENAMED, fidFilter);
assertEquals(1, fl.lockFeatures(q));
assertEquals(0, fl2.lockFeatures(q));
fl.unLockFeatures(q);
assertEquals(1, fl2.lockFeatures(q));
}
@Test
public void testQueryWithPropertyNames() throws Exception {
// check the schemas in feature source and feature collection
SimpleFeatureSource fs = rts.getFeatureSource(RENAMED);
Query q = new Query(RENAMED, Filter.INCLUDE, new String[] { "ADDRESS"} );
FeatureCollection<SimpleFeatureType,SimpleFeature> fc = fs.getFeatures( q );
assertEquals( 1, fc.getSchema().getAttributeCount() );
// make sure the feature schema is good as well
FeatureIterator <SimpleFeature> it = fc.features();
SimpleFeature sf = it.next();
it.close();
assertEquals( 1, sf.getAttributeCount() );
assertNull( sf.getAttribute( "FID" ) );
assertNotNull( sf.getAttribute( "ADDRESS"));
}
}