package org.geoserver.wcs2_0.xml; import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertNotNull; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import javax.mail.BodyPart; import javax.mail.Multipart; import javax.xml.namespace.QName; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.custommonkey.xmlunit.XMLAssert; import org.geoserver.catalog.CoverageInfo; import org.geoserver.catalog.DimensionPresentation; import org.geoserver.catalog.ResourceInfo; import org.geoserver.config.GeoServerDataDirectory; import org.geoserver.data.test.MockData; import org.geoserver.data.test.SystemTestData; import org.geoserver.platform.GeoServerExtensions; import org.geoserver.platform.resource.Resource; import org.geoserver.wcs2_0.DefaultWebCoverageService20; import org.geoserver.wcs2_0.GetCoverage; import org.geoserver.wcs2_0.WCSTestSupport; import org.geoserver.wcs2_0.exception.WCS20Exception; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.grid.io.GridCoverage2DReader; import org.geotools.data.DataSourceException; import org.geotools.gce.geotiff.GeoTiffReader; import org.geotools.gce.imagemosaic.ImageMosaicFormat; import org.geotools.geometry.Envelope2D; import org.geotools.geometry.GeneralEnvelope; import org.geotools.referencing.CRS; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.junit.Before; import org.junit.Test; import org.opengis.coverage.grid.GridCoverage; import org.opengis.coverage.grid.GridEnvelope; import org.opengis.referencing.FactoryException; import org.opengis.referencing.NoSuchAuthorityCodeException; import org.w3c.dom.Document; import org.springframework.mock.web.MockHttpServletResponse; import net.opengis.wcs20.GetCoverageType; import net.opengis.wcs20.Wcs20Factory; /** * Testing WCS 2.0 Core {@link GetCoverage} * * @author Simone Giannecchini, GeoSolutions SAS * @author Emanuele Tajariol, GeoSolutions SAS * */ public class GetCoverageTest extends WCSTestSupport { protected static QName WATTEMP = new QName(MockData.SF_URI, "watertemp", MockData.SF_PREFIX); protected static QName TIMERANGES = new QName(MockData.SF_URI, "timeranges", MockData.SF_PREFIX); private static final QName RAIN = new QName(MockData.SF_URI, "rain", MockData.SF_PREFIX); private static final QName BORDERS = new QName(MockData.SF_URI, "borders", MockData.SF_PREFIX); private static final QName SPATIO_TEMPORAL = new QName(MockData.SF_URI, "spatio-temporal", MockData.SF_PREFIX); @Before public void clearDimensions() { clearDimensions(getLayerId(WATTEMP)); clearDimensions(getLayerId(TIMERANGES)); } @Override protected void onSetUp(SystemTestData testData) throws Exception { super.onSetUp(testData); testData.addRasterLayer(WATTEMP, "watertemp.zip", null, null, SystemTestData.class, getCatalog()); GeoServerDataDirectory dataDirectory = getDataDirectory(); Resource watertemp = dataDirectory.getResourceLoader().get("watertemp"); File data = watertemp.dir(); FilenameFilter groundElevationFilter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.matches(".*_000_.*tiff") || name.matches("watertemp\\..*"); } }; for(File file : data.listFiles(groundElevationFilter)) { file.delete(); } testData.addRasterLayer(RAIN, "rain.zip", "asc", getCatalog()); testData.addRasterLayer(BORDERS, "/borders.zip", null, getCatalog()); testData.addRasterLayer(TIMERANGES, "timeranges.zip", null, null, SystemTestData.class, getCatalog()); testData.addRasterLayer(SPATIO_TEMPORAL, "spatio-temporal.zip", null, null, SystemTestData.class, getCatalog()); sortByElevation(TIMERANGES); } // force sorting on elevation to get predictable results private void sortByElevation(QName layer) { CoverageInfo coverage = getCatalog().getCoverageByName(getLayerId(layer)); String sortByKey = ImageMosaicFormat.SORT_BY.getName().toString(); coverage.getParameters().put(sortByKey, "elevation"); getCatalog().save(coverage); } /** * Trimming only on Longitude * */ @Test public void testCoverageTrimmingLatitudeNativeCRSXML() throws Exception { final File xml= new File("./src/test/resources/trimming/requestGetCoverageTrimmingLatitudeNativeCRSXML.xml"); final String request= FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); checkCoverageTrimmingLatitudeNativeCRS(tiffContents); } /** * Trimming only on Longitude, plus multipart encoding * */ @Test public void testCoverageTrimmingLatitudeNativeCRSXMLMultipart() throws Exception { final File xml= new File("./src/test/resources/requestGetCoverageTrimmingLatitudeNativeCRSXMLMultipart.xml"); final String request= FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("multipart/related", response.getContentType()); // parse the multipart, check there are two parts Multipart multipart = getMultipart(response); assertEquals(2, multipart.getCount()); BodyPart xmlPart = multipart.getBodyPart(0); assertEquals("application/gml+xml", xmlPart.getHeader("Content-Type")[0]); assertEquals("wcs", xmlPart.getHeader("Content-ID")[0]); Document gml = dom(xmlPart.getInputStream()); // print(gml); // check the gml part refers to the file as its range XMLAssert.assertXpathEvaluatesTo("fileReference", "//gml:rangeSet/gml:File/gml:rangeParameters/@xlink:arcrole", gml); XMLAssert.assertXpathEvaluatesTo("cid:/coverages/wcs__BlueMarble.tif", "//gml:rangeSet/gml:File/gml:rangeParameters/@xlink:href", gml); XMLAssert.assertXpathEvaluatesTo( "http://www.opengis.net/spec/GMLCOV_geotiff-coverages/1.0/conf/geotiff-coverage", "//gml:rangeSet/gml:File/gml:rangeParameters/@xlink:role", gml); XMLAssert.assertXpathEvaluatesTo("cid:/coverages/wcs__BlueMarble.tif", "//gml:rangeSet/gml:File/gml:fileReference", gml); XMLAssert.assertXpathEvaluatesTo("image/tiff", "//gml:rangeSet/gml:File/gml:mimeType", gml); BodyPart coveragePart = multipart.getBodyPart(1); assertEquals("/coverages/wcs__BlueMarble.tif", coveragePart.getHeader("Content-ID")[0]); assertEquals("image/tiff", coveragePart.getContentType()); // make sure we can read the coverage back and perform checks on it byte[] tiffContents = IOUtils.toByteArray(coveragePart.getInputStream()); checkCoverageTrimmingLatitudeNativeCRS(tiffContents); } private void checkCoverageTrimmingLatitudeNativeCRS(byte[] tiffContents) throws IOException, DataSourceException, NoSuchAuthorityCodeException, FactoryException { File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // checks final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange(); final GeneralEnvelope expectedEnvelope= new GeneralEnvelope( new double[]{targetCoverage.getEnvelope().getMinimum(0),-43.5}, new double[]{targetCoverage.getEnvelope().getMaximum(0),-43.0}); expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true)); final double scale = getScale(targetCoverage); assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale); assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem())); assertEquals(gridRange.getSpan(0), 360); assertEquals(gridRange.getSpan(1), 120); } finally { try{ readerTarget.dispose(); } catch (Exception e) { // TODO: handle exception } try{ scheduleForCleaning(targetCoverage); } catch (Exception e) { // TODO: handle exception } } } @Test public void testCoverageTrimmingNativeCRSXML() throws Exception { final File xml= new File("./src/test/resources/trimming/requestGetCoverageTrimmingNativeCRSXML.xml"); final String request= FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // checks final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange(); final GeneralEnvelope expectedEnvelope= new GeneralEnvelope( new double[]{146.5,-43.5}, new double[]{147.0,-43.0}); expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true)); final double scale = getScale(targetCoverage); assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale); assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem())); assertEquals(gridRange.getSpan(0), 120); assertEquals(gridRange.getSpan(1), 120); } finally { try{ readerTarget.dispose(); } catch (Exception e) { // TODO: handle exception } try{ scheduleForCleaning(targetCoverage); } catch (Exception e) { // TODO: handle exception } } } @Test public void testCoverageTrimmingBorders() throws Exception { final File xml = new File( "./src/test/resources/trimming/requestGetCoverageTrimmingBorders.xml"); final String request = FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); // make sure we are not getting a service exception assertEquals("image/tiff", response.getContentType()); } @Test public void testCoverageTrimmingOutsideBorders() throws Exception { final File xml = new File( "./src/test/resources/trimming/requestGetCoverageTrimmingOutsideBorders.xml"); final String request = FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); // make sure we are not getting a service exception checkOws20Exception(response, 404, "InvalidSubsetting", null); } @Test public void testGetFullCoverageXML() throws Exception { final File xml= new File("./src/test/resources/requestGetFullCoverage.xml"); final String request= FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); // check the headers assertEquals("image/tiff", response.getContentType()); String contentDisposition = response.getHeader("Content-disposition"); assertEquals("inline; filename=wcs__BlueMarble.tif", contentDisposition); byte[] tiffContents = getBinary(response); File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); // check we can read it as a TIFF and it is similare to the origina one GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null, sourceCoverage=null; try { targetCoverage = readerTarget.read(null); sourceCoverage=(GridCoverage2D) this.getCatalog().getCoverageByName("BlueMarble").getGridCoverageReader(null, null).read(null); // checks assertEquals(sourceCoverage.getGridGeometry().getGridRange(), targetCoverage.getGridGeometry().getGridRange()); assertEquals(sourceCoverage.getCoordinateReferenceSystem(), targetCoverage.getCoordinateReferenceSystem()); assertEquals(sourceCoverage.getEnvelope(), targetCoverage.getEnvelope()); } finally { try{ readerTarget.dispose(); } catch (Exception e) { // TODO: handle exception } try{ scheduleForCleaning(targetCoverage); } catch (Exception e) { // TODO: handle exception } try{ scheduleForCleaning(sourceCoverage); } catch (Exception e) { // TODO: handle exception } } } @Test public void testInputLimits() throws Exception { final File xml= new File("./src/test/resources/requestGetFullCoverage.xml"); final String request= FileUtils.readFileToString(xml); // set limits setInputLimit(1); MockHttpServletResponse response = postAsServletResponse("wcs", request); System.out.println(new String(this.getBinary(response))); assertEquals("application/xml", response.getContentType()); // reset imits setInputLimit(-1); } @Test public void testOutputLimits() throws Exception { final File xml= new File("./src/test/resources/requestGetFullCoverage.xml"); final String request= FileUtils.readFileToString(xml); // set limits // set output limits setOutputLimit(1); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("application/xml", response.getContentType()); // reset imits setOutputLimit(-1); } /** * Trimming only on Longitude * */ @Test public void testCoverageTrimmingLongitudeNativeCRSXML() throws Exception { final File xml= new File("./src/test/resources/trimming/requestGetCoverageTrimmingLongNativeCRSXML.xml"); final String request= FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // checks final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange(); final GeneralEnvelope expectedEnvelope= new GeneralEnvelope( new double[]{146.5,targetCoverage.getEnvelope().getMinimum(1)}, new double[]{147.0,targetCoverage.getEnvelope().getMaximum(1)}); expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true)); final double scale = getScale(targetCoverage); assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale); assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem())); assertEquals(gridRange.getSpan(0), 120); assertEquals(gridRange.getSpan(1), 360); } finally { try{ readerTarget.dispose(); } catch (Exception e) { // TODO: handle exception } try{ scheduleForCleaning(targetCoverage); } catch (Exception e) { // TODO: handle exception } } } @Test public void testCoverageTrimmingSlicingNativeCRSXML() throws Exception { final File xml= new File("./src/test/resources/trimming/requestGetCoverageTrimmingSlicingNativeCRSXML.xml"); final String request= FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // checks final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange(); // 1 dimensional slice along latitude final GeneralEnvelope expectedEnvelope= new GeneralEnvelope( new double[]{146.49999999999477,-43.5}, new double[]{146.99999999999477,-43.49583333333119}); expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true)); final double scale = getScale(targetCoverage); assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale); assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem())); assertEquals(gridRange.getSpan(1), 1); assertEquals(gridRange.getSpan(0), 120); } finally { try{ readerTarget.dispose(); } catch (Exception e) { // TODO: handle exception } try{ scheduleForCleaning(targetCoverage); } catch (Exception e) { // TODO: handle exception } } } @Test public void testCoverageTrimmingDuplicatedNativeCRSXML() throws Exception { final File xml= new File("./src/test/resources/trimming/requestGetCoverageTrimmingDuplicatedNativeCRSXML.xml"); final String request= FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("application/xml", response.getContentType()); // checkOws20Exception(response, 404, "InvalidAxisLabel", "coverageId"); } @Test public void testCoverageSlicingLongitudeNativeCRSXML() throws Exception { final File xml= new File("./src/test/resources/trimming/requestGetCoverageSlicingLongitudeNativeCRSXML.xml"); final String request= FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // checks final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange(); // 1 dimensional slice along longitude final GeneralEnvelope expectedEnvelope= new GeneralEnvelope( new double[]{146.5,-44.49999999999784}, new double[]{146.50416666666143,-42.99999999999787}); expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true)); final double scale = getScale(targetCoverage); assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale); assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem())); assertEquals(gridRange.getSpan(0), 1); assertEquals(gridRange.getSpan(1), 360); } finally { try{ readerTarget.dispose(); } catch (Exception e) { // TODO: handle exception } try{ scheduleForCleaning(targetCoverage); } catch (Exception e) { // TODO: handle exception } } } @Test public void testCoverageSlicingLatitudeNativeCRSXML() throws Exception { final File xml= new File("./src/test/resources/trimming/requestGetCoverageSlicingLatitudeNativeCRSXML.xml"); final String request= FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // checks final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange(); // 1 dimensional slice along latitude final GeneralEnvelope expectedEnvelope= new GeneralEnvelope( new double[]{146.49999999999477,-43.499999999997854}, new double[]{147.99999999999474,-43.49583333333119}); expectedEnvelope.setCoordinateReferenceSystem(CRS.decode("EPSG:4326", true)); final double scale = getScale(targetCoverage); assertEnvelopeEquals(expectedEnvelope,scale,(GeneralEnvelope) targetCoverage.getEnvelope(),scale); assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem())); assertEquals(gridRange.getSpan(1), 1); assertEquals(gridRange.getSpan(0), 360); } finally { try{ readerTarget.dispose(); } catch (Exception e) { // TODO: handle exception } try{ scheduleForCleaning(targetCoverage); } catch (Exception e) { // TODO: handle exception } } } @Test public void testCoverageTimeSlicingNoTimeConfigured() throws Exception { final File xml= new File("./src/test/resources/trimming/requestGetCoverageTimeSlicingXML.xml"); String request = FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__watertemp"); request = request.replace("${slicePoint}", "2000-10-31T00:00:00.000Z"); MockHttpServletResponse response = postAsServletResponse("wcs", request); checkOws20Exception(response, 404, WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel.getExceptionCode(), null); } @Test public void testCoverageTimeSlicingTimeBefore() throws Exception { setupRasterDimension(getLayerId(WATTEMP), ResourceInfo.TIME, DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__watertemp"); request = request.replace("${slicePoint}", "2000-10-31T00:00:00.000Z"); // nearest neighbor match, lowest time returned checkWaterTempValue(request, 14.89799975766800344); } @Test public void testCoverageTimeSlicingTimeFirst() throws Exception { setupRasterDimension(getLayerId(WATTEMP), ResourceInfo.TIME, DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__watertemp"); request = request.replace("${slicePoint}", "2008-10-31T00:00:00.000Z"); checkWaterTempValue(request, 14.89799975766800344); } @Test public void testCoverageTimeSlicingTimeClosest() throws Exception { setupRasterDimension(getLayerId(WATTEMP), ResourceInfo.TIME, DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__watertemp"); request = request.replace("${slicePoint}", "2000-10-31T11:30:00.000Z"); // nearest neighbor match, lowest time returned checkWaterTempValue(request, 14.89799975766800344); } @Test public void testCoverageTimeSlicingTimeSecond() throws Exception { setupRasterDimension(getLayerId(WATTEMP), ResourceInfo.TIME, DimensionPresentation.LIST, null); System.out.println(getDataDirectory().root()); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__watertemp"); request = request.replace("${slicePoint}", "2008-11-01T00:00:00.000Z"); checkWaterTempValue(request, 14.52999974018894136); } @Test public void testCoverageTimeSlicingTimeAfter() throws Exception { setupRasterDimension(getLayerId(WATTEMP), ResourceInfo.TIME, DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__watertemp"); request = request.replace("${slicePoint}", "2011-11-01T00:00:00.000Z"); // nearest neighbor match, highest time returned checkWaterTempValue(request, 14.52999974018894136); } @Test public void testCoverageTimeSlicingAgainstFirstRange() throws Exception { setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.TIME, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.ELEVATION, DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__timeranges"); request = request.replace("${slicePoint}", "2008-10-31T00:00:00.000Z"); // timeranges is really just an expanded watertemp checkWaterTempValue(request, 18.478999927756377); } @Test public void testCoverageTimeSlicingAgainstRangeHole() throws Exception { setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.TIME, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.ELEVATION, DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__timeranges"); request = request.replace("${slicePoint}", "2008-11-04T11:00:00.000Z"); // timeranges is really just an expanded watertemp, and we expect NN checkWaterTempValue(request, 14.52999974018894136); } @Test public void testCoverageTimeSlicingAgainstSecondRange() throws Exception { setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.TIME, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.ELEVATION, DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__timeranges"); request = request.replace("${slicePoint}", "2008-11-06T00:00:00.000Z"); // timeranges is really just an expanded watertemp checkWaterTempValue(request, 14.52999974018894136); } @Test public void testCoverageTimeElevationSlicingAgainstLowestOldestGranule() throws Exception { setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.TIME, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.ELEVATION, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.CUSTOM_DIMENSION_PREFIX + "WAVELENGTH", DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeElevationCustomSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__timeranges"); request = request.replace("${slicePointElevation}", "20"); request = request.replace("${slicePointTime}", "2008-10-31T00:00:00.000Z"); request = request.replace("${Custom}", "WAVELENGTH"); request = request.replace("${slicePointCustom}", "20"); // timeranges is really just an expanded watertemp checkWaterTempValue(request, 18.478999927756377); } @Test public void testCoverageTimeElevationSlicingAgainstHighestNewestGranuleLatestWavelength() throws Exception { setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.TIME, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.ELEVATION, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.CUSTOM_DIMENSION_PREFIX + "WAVELENGTH", DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeElevationCustomSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__timeranges"); request = request.replace("${slicePointElevation}", "140"); request = request.replace("${slicePointTime}", "2008-11-07T00:00:00.000Z"); request = request.replace("${Custom}", "WAVELENGTH"); request = request.replace("${slicePointCustom}", "80"); // timeranges is really just an expanded watertemp checkWaterTempValue(request, 14.52999974018894136); } @Test public void testCoverageTimeElevationSlicingAgainstHighestNewestGranule() throws Exception { setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.TIME, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.ELEVATION, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.CUSTOM_DIMENSION_PREFIX + "WAVELENGTH", DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageTimeElevationSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__timeranges"); request = request.replace("${slicePointElevation}", "140"); request = request.replace("${slicePointTime}", "2008-11-07T00:00:00.000Z"); // timeranges is really just an expanded watertemp checkWaterTempValue(request, 14.52999974018894136); } @Test public void testCoverageElevationSlicingDefaultTime() throws Exception { setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.TIME, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.ELEVATION, DimensionPresentation.LIST, null); setupRasterDimension(getLayerId(TIMERANGES), ResourceInfo.CUSTOM_DIMENSION_PREFIX + "WAVELENGTH", DimensionPresentation.LIST, null); final File xml = new File("./src/test/resources/trimming/requestGetCoverageElevationSlicingXML.xml"); String request= FileUtils.readFileToString(xml); request = request.replace("${coverageId}", "sf__timeranges"); request = request.replace("${slicePoint}", "140"); // timeranges is really just an expanded watertemp checkWaterTempValue(request, 14.52999974018894136); } private void checkWaterTempValue(String request, double expectedValue) throws Exception, IOException, DataSourceException { MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); File file = File.createTempFile("bm_gtiff", "bm_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // checks spatial consistency GridCoverage2DReader sourceReader = (GridCoverage2DReader) getCatalog().getCoverageByName(getLayerId(WATTEMP)).getGridCoverageReader(null, null); GeneralEnvelope expectedEnvelope = sourceReader.getOriginalEnvelope(); assertEnvelopeEquals(expectedEnvelope, 1.0,(GeneralEnvelope) targetCoverage.getEnvelope(), 1.0); assertTrue(CRS.equalsIgnoreMetadata(targetCoverage.getCoordinateReferenceSystem(), expectedEnvelope.getCoordinateReferenceSystem())); // check raster space consistency final GridEnvelope gridRange = targetCoverage.getGridGeometry().getGridRange(); GridEnvelope expectedGridRange = sourceReader.getOriginalGridRange(); assertEquals(gridRange.getSpan(0), expectedGridRange.getSpan(0)); assertEquals(gridRange.getSpan(1), expectedGridRange.getSpan(1)); // check the reference pixel double[] pixel = new double[1]; targetCoverage.getRenderedImage().getData().getPixel(1, 24, pixel); assertEquals(expectedValue, pixel[0], 1e-6); } finally { readerTarget.dispose(); scheduleForCleaning(targetCoverage); } } @Test public void testDatelineCrossingMinGreaterThanMax() throws Exception { final File xml = new File("./src/test/resources/requestGetCoverageAcrossDateline.xml"); checkDatelineCrossing(xml); } @Test public void testDatelineCrossingPositiveCoordinates() throws Exception { final File xml = new File("./src/test/resources/requestGetCoverageAcrossDateline2.xml"); checkDatelineCrossing(xml); } private void checkDatelineCrossing(final File xml) throws IOException, Exception, DataSourceException { final String request = FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); File file = File.createTempFile("rain_gtiff", "rain_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // check we got the right envelope Envelope2D envelope = targetCoverage.getEnvelope2D(); assertEquals(160, envelope.getMinX(), 0d); assertEquals(0, envelope.getMinY(), 0d); assertEquals(200, envelope.getMaxX(), 0d); assertEquals(40, envelope.getMaxY(), 0d); assertTrue(CRS.equalsIgnoreMetadata(DefaultGeographicCRS.WGS84, targetCoverage.getCoordinateReferenceSystem2D())); // check we actually read the right stuff. For this case, we // just check we have the pixels in the range of values of that area Raster data = targetCoverage.getRenderedImage().getData(); double[] pixel = new double[1]; for (int i = data.getMinY(); i < data.getMinY() + data.getHeight(); i++) { for (int j = data.getMinX(); j < data.getMinX() + data.getWidth(); j++) { data.getPixel(i, j, pixel); double d = pixel[0]; assertTrue(String.valueOf(d), d > 500 && d < 5500); } } } finally { readerTarget.dispose(); scheduleForCleaning(targetCoverage); } } @Test public void testDatelineCrossingPolar() throws Exception { final File xml = new File("./src/test/resources/requestGetCoverageAcrossDatelinePolar.xml"); final String request = FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); File file = File.createTempFile("polar_gtiff", "polar_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // check we got the right envelope Envelope2D envelope = targetCoverage.getEnvelope2D(); // System.out.println(envelope); assertEquals(-1139998, envelope.getMinX(), 1d); assertEquals(-3333134, envelope.getMinY(), 1d); assertEquals(1139998, envelope.getMaxX(), 1d); assertEquals(-1023493, envelope.getMaxY(), 1d); assertTrue(CRS.equalsIgnoreMetadata(CRS.decode("EPSG:3031", true), targetCoverage.getCoordinateReferenceSystem2D())); // we don't check the values, as we don't have the smarts available in the // rendering subsystem to read a larger area also when the // reprojection makes the pixel shrink } finally { readerTarget.dispose(); scheduleForCleaning(targetCoverage); } } @Test public void testDatelineCrossingMercatorPDC() throws Exception { final File xml = new File( "./src/test/resources/requestGetCoverageAcrossDatelineMercatorPacific.xml"); final String request = FileUtils.readFileToString(xml); MockHttpServletResponse response = postAsServletResponse("wcs", request); assertEquals("image/tiff", response.getContentType()); byte[] tiffContents = getBinary(response); File file = File.createTempFile("polar_gtiff", "polar_gtiff.tiff", new File("./target")); FileUtils.writeByteArrayToFile(file, tiffContents); GeoTiffReader readerTarget = new GeoTiffReader(file); GridCoverage2D targetCoverage = null; try { targetCoverage = readerTarget.read(null); // check we got the right envelope Envelope2D envelope = targetCoverage.getEnvelope2D(); assertEquals(160, envelope.getMinX(), 0d); assertEquals(0, envelope.getMinY(), 0d); assertEquals(200, envelope.getMaxX(), 0d); assertEquals(40, envelope.getMaxY(), 0d); assertTrue(CRS.equalsIgnoreMetadata(DefaultGeographicCRS.WGS84, targetCoverage.getCoordinateReferenceSystem2D())); // check we actually read the right stuff. For this case, we // just check we have the pixels in the range of values of that area RenderedImage renderedImage = targetCoverage.getRenderedImage(); Raster data = renderedImage.getData(); double[] pixel = new double[1]; for (int i = data.getMinY(); i < data.getMinY() + data.getHeight(); i++) { for (int j = data.getMinX(); j < data.getMinX() + data.getWidth(); j++) { data.getPixel(i, j, pixel); double d = pixel[0]; assertTrue(String.valueOf(d), d > 500 && d < 5500); } } } finally { readerTarget.dispose(); scheduleForCleaning(targetCoverage); } } @Test public void testDeferredLoading() throws Exception { DefaultWebCoverageService20 wcs = GeoServerExtensions.bean(DefaultWebCoverageService20.class); GetCoverageType getCoverage = Wcs20Factory.eINSTANCE.createGetCoverageType(); getCoverage.setCoverageId(getLayerId(SPATIO_TEMPORAL)); getCoverage.setVersion("2.0.0"); getCoverage.setService("WCS"); GridCoverage coverage = null; try { coverage = wcs.getCoverage(getCoverage); assertNotNull(coverage); assertDeferredLoading(coverage.getRenderedImage()); } finally { scheduleForCleaning(coverage); } } }