/* (c) 2014 - 2016 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.wps.gs;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.wps.WPSTestSupport;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.data.Query;
import org.geotools.data.crs.ForceCoordinateSystemFeatureResults;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.collection.DecoratingSimpleFeatureCollection;
import org.geotools.feature.collection.DecoratingSimpleFeatureIterator;
import org.geotools.process.ProcessException;
import org.geotools.referencing.CRS;
import org.geotools.util.DefaultProgressListener;
import org.geotools.util.SimpleInternationalString;
import org.junit.After;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.filter.FilterFactory;
public class ImportProcessTest extends WPSTestSupport {
@After
public void removeNewLayers() {
removeLayer(SystemTestData.CITE_PREFIX, "Buildings2");
removeLayer(SystemTestData.CITE_PREFIX, "Buildings4");
removeLayer(SystemTestData.CITE_PREFIX, "Buildings5");
removeLayer(SystemTestData.CITE_PREFIX, "Buildings6");
removeStore(SystemTestData.CITE_PREFIX, SystemTestData.CITE_PREFIX + "data");
removeStore(SystemTestData.CITE_PREFIX, SystemTestData.CITE_PREFIX + "raster");
}
/**
* Try to re-import buildings as another layer (different name, different projection)
*/
@Test
public void testImportBuildings() throws Exception {
FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(SystemTestData.BUILDINGS));
SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null,
null).getFeatures();
ForceCoordinateSystemFeatureResults forced = new ForceCoordinateSystemFeatureResults(
rawSource, CRS.decode("EPSG:4326"));
ImportProcess importer = new ImportProcess(getCatalog());
String result = importer.execute(forced, null, SystemTestData.CITE_PREFIX, SystemTestData.CITE_PREFIX,
"Buildings2", null, null, null, null);
checkBuildings(result,"Buildings2");
}
@Test
public void testImportBuildingsProgress() throws Exception {
FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(SystemTestData.BUILDINGS));
SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null,
null).getFeatures();
ForceCoordinateSystemFeatureResults forced = new ForceCoordinateSystemFeatureResults(
rawSource, CRS.decode("EPSG:4326"));
ImportProcess importer = new ImportProcess(getCatalog());
DefaultProgressListener testProgressListener = new DefaultProgressListener() {
float previousProgress = 0;
@Override
public void progress(float percent) {
super.progress(percent);
assertTrue(percent >= previousProgress);
previousProgress = percent;
}
};
String result = importer.execute(forced, null, SystemTestData.CITE_PREFIX, SystemTestData.CITE_PREFIX,
"Buildings6", null, null, null, testProgressListener);
assertEquals(100, testProgressListener.getProgress(), 0f);
checkBuildings(result,"Buildings6");
}
@Test
public void testImportBuildingsCancellation() throws Exception {
FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(SystemTestData.BUILDINGS));
SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null,
null).getFeatures();
// a feature collection whose scrolling will block until we relase it via the latch
final CountDownLatch latch = new CountDownLatch(1);
final SimpleFeatureCollection testFeatureCollection = new DecoratingSimpleFeatureCollection(rawSource) {
@Override
public SimpleFeatureIterator features() {
return new DecoratingSimpleFeatureIterator(super.features()) {
@Override
public SimpleFeature next() throws NoSuchElementException {
return super.next();
}
};
}
};
final ImportProcess importer = new ImportProcess(getCatalog());
final DefaultProgressListener listener = new DefaultProgressListener();
ExecutorService executor = Executors.newCachedThreadPool();
try {
Future<?> future = executor.submit(new Runnable() {
@Override
public void run() {
importer.execute(testFeatureCollection, null, SystemTestData.CITE_PREFIX, SystemTestData.CITE_PREFIX,
"Buildings2", null, null, null, listener);
}
});
// cancel the import
listener.setTask(new SimpleInternationalString("Test message"));
listener.setCanceled(true);
// release the importer
latch.countDown();
try {
future.get();
fail("Should have failed with an exception");
} catch(ExecutionException e) {
assertThat(e.getCause(), instanceOf(ProcessException.class));
assertEquals("Test message", e.getCause().getMessage());
}
} finally {
executor.shutdown();
}
}
/**
* Try to re-import buildings as another layer (different name, different projection)
*/
@Test
public void testImportBuildingsForceCRS() throws Exception {
FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(SystemTestData.BUILDINGS));
SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null,
null).getFeatures();
ImportProcess importer = new ImportProcess(getCatalog());
String result = importer.execute(rawSource, null, SystemTestData.CITE_PREFIX, SystemTestData.CITE_PREFIX,
"Buildings3", CRS.decode("EPSG:4326"), null, null, null);
checkBuildings(result,"Buildings3");
}
private void checkBuildings(String result,String expected) throws IOException {
assertEquals(SystemTestData.CITE_PREFIX + ":" + expected, result);
// check the layer
LayerInfo layer = getCatalog().getLayerByName(result);
assertNotNull(layer);
assertEquals("polygon", layer.getDefaultStyle().getName());
// check the feature type info
FeatureTypeInfo fti = (FeatureTypeInfo) layer.getResource();
assertEquals("EPSG:4326", fti.getSRS());
SimpleFeatureSource fs = (SimpleFeatureSource) fti.getFeatureSource(null, null);
assertEquals(2, fs.getCount(Query.ALL));
// _=the_geom:MultiPolygon,FID:String,ADDRESS:String
// Buildings.1107531701010=MULTIPOLYGON (((0.0008 0.0005, 0.0008 0.0007,
// 0.0012 0.0007, 0.0012 0.0005, 0.0008 0.0005)))|113|123 Main Street
// Buildings.1107531701011=MULTIPOLYGON (((0.002 0.0008, 0.002 0.001,
// 0.0024 0.001, 0.0024 0.0008, 0.002 0.0008)))|114|215 Main Street
FilterFactory ff = CommonFactoryFinder.getFilterFactory(null);
SimpleFeatureIterator fi = fs.getFeatures(ff.equals(ff.property("FID"), ff.literal("113")))
.features();
SimpleFeature f = fi.next();
fi.close();
assertEquals("113", f.getAttribute("FID"));
assertEquals("123 Main Street", f.getAttribute("ADDRESS"));
fi = fs.getFeatures(ff.equals(ff.property("FID"), ff.literal("114"))).features();
f = fi.next();
fi.close();
assertEquals("114", f.getAttribute("FID"));
assertEquals("215 Main Street", f.getAttribute("ADDRESS"));
}
/**
* Test creating a coverage store when a store name is specified but does not exist
*/
@Test
public void testCreateCoverageStore() throws Exception {
String storeName = SystemTestData.CITE_PREFIX + "raster";
// use Coverage2RenderedImageAdapterTest's method, just need any sample raster
GridCoverage2D sampleCoverage = Coverage2RenderedImageAdapterTest.createTestCoverage(500, 500, 0,0, 10,10);
CoverageStoreInfo storeInfo = catalog.getCoverageStoreByName(storeName);
assertNull("Store already exists " + storeInfo, storeInfo);
ImportProcess importer = new ImportProcess(getCatalog());
String result = importer.execute(null, sampleCoverage, SystemTestData.CITE_PREFIX, storeName,
"Buildings4", CRS.decode("EPSG:4326"), null, null, null);
// expect workspace:layername
assertEquals(result, SystemTestData.CITE_PREFIX + ":" + "Buildings4");
}
/**
* Test creating a vector store when a store name is specified but does not exist
*/
@Test
public void testCreateDataStore() throws Exception {
FeatureTypeInfo ti = getCatalog().getFeatureTypeByName(getLayerId(SystemTestData.BUILDINGS));
SimpleFeatureCollection rawSource = (SimpleFeatureCollection) ti.getFeatureSource(null,
null).getFeatures();
ForceCoordinateSystemFeatureResults sampleData = new ForceCoordinateSystemFeatureResults(
rawSource, CRS.decode("EPSG:4326"));
String storeName = SystemTestData.CITE_PREFIX + "data";
DataStoreInfo storeInfo = catalog.getDataStoreByName(storeName);
assertNull("Store already exists " + storeInfo, storeInfo);
ImportProcess importer = new ImportProcess(getCatalog());
String result = importer.execute(sampleData, null, SystemTestData.CITE_PREFIX, storeName,
"Buildings5", CRS.decode("EPSG:4326"), null, null, null);
// expect workspace:layername
assertEquals(result, SystemTestData.CITE_PREFIX + ":" + "Buildings5");
}
}