/* (c) 2015 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps.gdal;
import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.ogr.core.Format;
import org.geoserver.wcs.response.GdalConfigurator;
import org.geoserver.wcs.response.GdalCoverageResponseDelegate;
import org.geoserver.wcs.response.GdalTestUtil;
import org.geoserver.wps.WPSTestSupport;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.gce.arcgrid.ArcGridFormat;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.springframework.mock.web.MockHttpServletResponse;
import com.vividsolutions.jts.geom.Envelope;
public class GdalWpsTest extends WPSTestSupport {
@Override
protected void onSetUp(SystemTestData testData) throws Exception {
super.onSetUp(testData);
addWcs11Coverages(testData);
}
@Before
public void setUp() throws Exception {
Assume.assumeTrue(GdalTestUtil.isGdalAvailable());
GdalConfigurator.DEFAULT.setExecutable(GdalTestUtil.getGdalTranslate());
GdalConfigurator.DEFAULT.setEnvironment(GdalTestUtil.getGdalData());
// force reload of the config, some tests may alter it
GdalConfigurator configurator = applicationContext.getBean(GdalConfigurator.class);
configurator.loadConfiguration();
}
@Test
public void testDescribeProcess() throws Exception {
GdalCoverageResponseDelegate delegate = applicationContext.getBean(GdalCoverageResponseDelegate.class);
Document d = getAsDOM(root()
+ "service=wps&request=describeprocess&identifier=gs:CropCoverage");
String base = "/wps:ProcessDescriptions/ProcessDescription/ProcessOutputs";
for (Format f : delegate.getFormats()) {
assertXpathExists(base + "/Output[1]/ComplexOutput/Supported/Format[MimeType='"
+ delegate.getMimeType(f.getGeoserverFormat()) + "; subtype=" + f.getGeoserverFormat() + "']", d);
}
}
@Test
public void testCrop() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n"
+ " <ows:Identifier>gs:CropCoverage</ows:Identifier>\n"
+ " <wps:DataInputs>\n"
+ " <wps:Input>\n"
+ " <ows:Identifier>coverage</ows:Identifier>\n"
+ " <wps:Reference mimeType=\"image/tiff\" xlink:href=\"http://geoserver/wcs\" method=\"POST\">\n"
+ " <wps:Body>\n"
+ " <wcs:GetCoverage service=\"WCS\" version=\"1.1.1\">\n"
+ " <ows:Identifier>" + getLayerId(MockData.TASMANIA_DEM) + "</ows:Identifier>\n"
+ " <wcs:DomainSubset>\n"
+ " <gml:BoundingBox crs=\"http://www.opengis.net/gml/srs/epsg.xml#4326\">\n"
+ " <ows:LowerCorner>-180.0 -90.0</ows:LowerCorner>\n"
+ " <ows:UpperCorner>180.0 90.0</ows:UpperCorner>\n"
+ " </gml:BoundingBox>\n"
+ " </wcs:DomainSubset>\n"
+ " <wcs:Output format=\"image/tiff\"/>\n"
+ " </wcs:GetCoverage>\n"
+ " </wps:Body>\n"
+ " </wps:Reference>\n"
+ " </wps:Input>\n"
+ " <wps:Input>\n"
+ " <ows:Identifier>cropShape</ows:Identifier>\n"
+ " <wps:Data>\n"
+ " <wps:ComplexData mimeType=\"application/wkt\"><![CDATA[POLYGON((145.5 -41.9, 145.5 -42.1, 145.6 -42, 145.5 -41.9))]]></wps:ComplexData>\n"
+ " </wps:Data>\n" + " </wps:Input>\n" + " </wps:DataInputs>\n"
+ " <wps:ResponseForm>\n"
+ " <wps:RawDataOutput mimeType=\"application/zip; subtype=GDAL-ArcInfoGrid\">\n"
+ " <ows:Identifier>result</ows:Identifier>\n" + " </wps:RawDataOutput>\n"
+ " </wps:ResponseForm>\n" + "</wps:Execute>\n" + "\n" + "";
MockHttpServletResponse response = postAsServletResponse(root(), xml);
ZipInputStream is = new ZipInputStream(getBinaryInputStream(response));
ZipEntry entry = null;
boolean arcGridFound = false;
while ((entry = is.getNextEntry()) != null && !arcGridFound) {
if (entry.getName().endsWith(".asc")) {
ArcGridFormat format = new ArcGridFormat();
GridCoverage2D gc = format.getReader(is).read(null);
assertTrue(new Envelope(-145.4, 145.6, -41.8, -42.1).contains(new ReferencedEnvelope(gc.getEnvelope())));
double[] valueInside = (double[]) gc.evaluate(new DirectPosition2D(145.55, -42));
assertEquals(615.0, valueInside[0], 1E-12);
double[] valueOutside = (double[]) gc.evaluate(new DirectPosition2D(145.57, -41.9));
// this should really be NoData... (-9999 & 0xFFFF)
assertEquals(55537.0, valueOutside[0], 1E-12);
gc.dispose(true);
arcGridFound = true;
}
}
assertTrue(arcGridFound);
}
@Test
public void testCropText() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n"
+ " <ows:Identifier>gs:CropCoverage</ows:Identifier>\n"
+ " <wps:DataInputs>\n"
+ " <wps:Input>\n"
+ " <ows:Identifier>coverage</ows:Identifier>\n"
+ " <wps:Reference mimeType=\"image/tiff\" xlink:href=\"http://geoserver/wcs\" method=\"POST\">\n"
+ " <wps:Body>\n"
+ " <wcs:GetCoverage service=\"WCS\" version=\"1.1.1\">\n"
+ " <ows:Identifier>" + getLayerId(MockData.TASMANIA_DEM) + "</ows:Identifier>\n"
+ " <wcs:DomainSubset>\n"
+ " <gml:BoundingBox crs=\"http://www.opengis.net/gml/srs/epsg.xml#4326\">\n"
+ " <ows:LowerCorner>-180.0 -90.0</ows:LowerCorner>\n"
+ " <ows:UpperCorner>180.0 90.0</ows:UpperCorner>\n"
+ " </gml:BoundingBox>\n"
+ " </wcs:DomainSubset>\n"
+ " <wcs:Output format=\"image/tiff\"/>\n"
+ " </wcs:GetCoverage>\n"
+ " </wps:Body>\n"
+ " </wps:Reference>\n"
+ " </wps:Input>\n"
+ " <wps:Input>\n"
+ " <ows:Identifier>cropShape</ows:Identifier>\n"
+ " <wps:Data>\n"
+ " <wps:ComplexData mimeType=\"application/wkt\"><![CDATA[POLYGON((145.5 -41.9, 145.5 -42.1, 145.6 -42, 145.5 -41.9))]]></wps:ComplexData>\n"
+ " </wps:Data>\n" + " </wps:Input>\n" + " </wps:DataInputs>\n"
+ " <wps:ResponseForm>\n"
+ " <wps:RawDataOutput mimeType=\"text/plain; subtype=GDAL-XYZ\">\n"
+ " <ows:Identifier>result</ows:Identifier>\n" + " </wps:RawDataOutput>\n"
+ " </wps:ResponseForm>\n" + "</wps:Execute>\n" + "\n" + "";
MockHttpServletResponse response = postAsServletResponse(root(), xml);
BufferedReader reader = new BufferedReader(new InputStreamReader(getBinaryInputStream(response)));
String line = null;
boolean valueInsideFound = false, valueOutsideFound = false;
double x1 = -145.4, x2 = 145.6, y1 = -42.1, y2 = -41.8;
while ((line = reader.readLine()) != null) {
String[] cols = line.split(" ");
assertTrue(cols.length == 3);
double x = round(Double.valueOf(cols[0]));
double y = round(Double.valueOf(cols[1]));
double value = Double.valueOf(cols[2]);
assertTrue(x >= x1 && x <= x2);
assertTrue(y >= y1 && y <= y2);
if (x == 145.55 && y == -42 && !valueInsideFound) {
assertEquals(550.0, value, 1E-12);
valueInsideFound = true;
}
if (x == 145.57 && y == -41.9 && !valueOutsideFound) {
assertEquals(55537.0, value, 1E-12);
valueOutsideFound = true;
}
}
assertTrue(valueInsideFound);
assertTrue(valueOutsideFound);
}
private double round(double value) {
return Math.round(value * 100) / 100.0;
}
}