/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2007-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2007-2012, Geomatys
*
* 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.geotoolkit.coverage.sql;
import java.util.Date;
import java.util.Set;
import java.util.SortedSet;
import java.io.IOException;
import java.sql.SQLException;
import java.net.URISyntaxException;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.operation.TransformException;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.apache.sis.test.DependsOn;
import org.apache.sis.geometry.GeneralEnvelope;
import org.geotoolkit.coverage.GridSampleDimension;
import org.geotoolkit.image.io.mosaic.TileManager;
import org.geotoolkit.internal.sql.table.CatalogTestBase;
import org.apache.sis.referencing.CommonCRS;
import org.junit.*;
import static org.junit.Assert.*;
import static org.apache.sis.referencing.CRS.getHorizontalComponent;
/**
* Tests {@link GridCoverageTable}.
*
* @author Martin Desruisseaux (Geomatys)
* @version 3.15
*
* @since 3.10 (derived from Seagis)
*/
@DependsOn(LayerTableTest.class)
public final strictfp class GridCoverageTableTest extends CatalogTestBase {
/**
* The name of the coverage to be tested.
*/
public static final String SAMPLE_NAME = "198602";
/**
* Small tolerance factor for comparison of floating point numbers.
*/
private static final double EPS = 1E-8;
/**
* Creates a new test suite.
*/
public GridCoverageTableTest() {
super(GridCoverageTable.class);
}
/**
* Tests the {@link GridCoverageTable#getAvailableTimes()} method.
*
* @throws SQLException If the test can't connect to the database.
*/
@Test
public void testAvailability() throws SQLException {
final GridCoverageTable table = getDatabase().getTable(GridCoverageTable.class);
table.envelope.clear();
table.setLayer(LayerTableTest.TEMPERATURE);
final SortedSet<Date> allTimes = table.getAvailableTimes();
assertEquals(7, allTimes.size());
assertTrue(allTimes.first().after (LayerTableTest.START_TIME));
assertTrue(allTimes.last ().before(LayerTableTest.END_TIME));
assertTrue(allTimes.contains(LayerTableTest.SAMPLE_TIME));
/*
* Reduce the time range and tests again available times.
*/
table.envelope.setTimeRange(LayerTableTest.SUB_START_TIME, LayerTableTest.SUB_END_TIME);
final Set<Date> availableTimes = table.getAvailableTimes();
assertEquals(3, availableTimes.size());
assertTrue(allTimes.containsAll(availableTimes));
assertFalse(availableTimes.containsAll(allTimes));
/*
* Reset the full range and test again.
*/
table.envelope.setTimeRange(LayerTableTest.START_TIME, LayerTableTest.END_TIME);
assertEquals(allTimes, table.getAvailableTimes());
table.release();
}
/**
* Tests the {@link GridCoverageTable#getEntry(Comparable)} method. This method is actually
* not used in typical {@link GridCoverageTable} usage, but we test it because it is the
* most direct way to test the creation of a particular {@link GridCoverageEntry}.
*
* @throws SQLException If the test can't connect to the database.
*/
@Test
public void testSelect() throws SQLException {
final GridCoverageTable table = getDatabase().getTable(GridCoverageTable.class);
table.envelope.clear();
table.setLayer(LayerTableTest.TEMPERATURE);
final GridCoverageReference entry = table.getEntry(SAMPLE_NAME);
assertEquals(Boolean.FALSE, table.getLayerEntry(true).isTiled);
assertEquals(SAMPLE_NAME + ":1", entry.getName());
assertSame(entry, table.getEntry(SAMPLE_NAME));
/*
* Test the sample dimension.
*/
final GridSampleDimension[] bands = entry.getSampleDimensions();
assertEquals(1, bands.length);
final GridSampleDimension band = bands[0];
assertSame("Should be geophysics.", band, band.geophysics(true));
SampleDimensionTableTest.checkTemperatureDimension(band.geophysics(false));
/*
* Test the envelope.
*/
final Envelope envelope = entry.getEnvelope();
assertTrue(getHorizontalComponent(envelope.getCoordinateReferenceSystem()) instanceof GeographicCRS);
assertEquals(-180, envelope.getMinimum(0), 0.0);
assertEquals(+180, envelope.getMaximum(0), 0.0);
assertEquals( -90, envelope.getMinimum(1), 0.0);
assertEquals( +90, envelope.getMaximum(1), 0.0);
assertEquals(6439, envelope.getMinimum(2), 0.0);
assertEquals(6447, envelope.getMaximum(2), 0.0);
table.release();
}
/**
* Tests the {@link GridCoverageTable#getEntries()} and {@link GridCoverageTable#getEntry()}
* methods.
*
* @throws SQLException If the test can't connect to the database.
*/
@Test
public void testList() throws SQLException {
final GridCoverageTable table = getDatabase().getTable(GridCoverageTable.class);
table.envelope.clear();
table.setLayer(LayerTableTest.TEMPERATURE);
/*
* Get the set of entries in the layer.
*/
table.envelope.setTimeRange(LayerTableTest.SUB_START_TIME, LayerTableTest.SUB_END_TIME);
final Set<GridCoverageEntry> entries = table.getEntries();
assertEquals(Boolean.FALSE, table.getLayerEntry(true).isTiled);
assertEquals(3, entries.size());
final GridCoverageReference entry = table.getEntry(SAMPLE_NAME);
assertTrue(entries.contains(entry));
/*
* Test the selection of an "appropriate" entry.
* Should select the one which is in the middle of the requested range.
*/
assertSame(entry, table.getEntry());
table.release();
}
/**
* Tests the table for NetCDF images. They use a Mercator projection.
*
* @throws SQLException If the test can't connect to the database.
*/
@Test
public void testNetCDF() throws SQLException {
final GridCoverageTable table = getDatabase().getTable(GridCoverageTable.class);
table.envelope.clear();
table.setLayer(LayerTableTest.NETCDF);
final Set<Date> availableTimes = table.getAvailableTimes();
assertEquals(3, availableTimes.size());
/*
* Tests a single entry.
*/
final GridCoverageReference entry = table.getEntry();
assertEquals(Boolean.FALSE, table.getLayerEntry(true).isTiled);
assertEquals(1, entry.getSampleDimensions().length);
/*
* Tests the envelope, which may be projected.
*/
final Envelope envelope = entry.getEnvelope();
assertTrue(getHorizontalComponent(envelope.getCoordinateReferenceSystem()) instanceof ProjectedCRS);
assertEquals(-2.00375E7, envelope.getMinimum(0), 100.0);
assertEquals( 2.00375E7, envelope.getMaximum(0), 100.0);
assertEquals(-1.38176E7, envelope.getMinimum(1), 100.0);
assertEquals( 1.38176E7, envelope.getMaximum(1), 100.0);
/*
* Tests the geographic envelope, which must be geographic.
*/
final GeographicBoundingBox bbox = entry.getGeographicBoundingBox();
assertEquals(-180, bbox.getWestBoundLongitude(), EPS);
assertEquals(+180, bbox.getEastBoundLongitude(), EPS);
assertEquals( -77, bbox.getSouthBoundLatitude(), 0.1);
assertEquals( +77, bbox.getNorthBoundLatitude(), 0.1);
table.release();
}
/**
* Tests the table for the NetCDF entry with different elevation range.
*
* @throws SQLException If the test can't connect to the database.
*/
@Test
public void testZRange() throws SQLException {
final GridCoverageTable table = getDatabase().getTable(GridCoverageTable.class);
table.envelope.clear();
table.setLayer(LayerTableTest.NETCDF);
GridCoverageEntry entry = table.getEntry();
assertEquals(Boolean.FALSE, table.getLayerEntry(true).isTiled);
assertEquals(1, entry.getIdentifier().imageIndex);
assertEquals("Should not have a z index when the requested z range is infinite.",
0, entry.getIdentifier().zIndex);
table.envelope.setVerticalRange(0, 0);
entry = table.getEntry();
assertEquals(1, entry.getIdentifier().imageIndex);
assertEquals(1, entry.getIdentifier().zIndex);
table.envelope.setVerticalRange(2.5, 7.5);
entry = table.getEntry();
assertEquals(1, entry.getIdentifier().imageIndex);
assertEquals(1, entry.getIdentifier().zIndex);
// Internally, match exactly one of the above elevations.
table.envelope.setVerticalRange(90, 110);
entry = table.getEntry();
assertEquals(1, entry.getIdentifier().imageIndex);
assertEquals(9, entry.getIdentifier().zIndex);
// Internally, slightly below one of the above elevations.
table.envelope.setVerticalRange(89, 110);
assertSame(entry, table.getEntry());
// Internally, slightly above one of the above elevations.
table.envelope.setVerticalRange(90, 111);
assertSame(entry, table.getEntry());
table.envelope.setVerticalRange(2000, 2000);
entry = table.getEntry();
assertEquals(1, entry.getIdentifier().imageIndex);
assertEquals(59, entry.getIdentifier().zIndex);
table.release();
}
/**
* Tests the table for the NetCDF entry with different tile value.
*
* @throws SQLException If the test can't connect to the database.
*
* @since 3.15
*/
@Test
public void testTRange() throws SQLException {
final GridCoverageTable table = getDatabase().getTable(GridCoverageTable.class);
table.envelope.clear();
table.setLayer(LayerTableTest.GEOSTROPHIC_CURRENT);
table.envelope.setTimeRange(date("2007-05-22 00:08:00"), date("2007-05-22 00:22:00"));
assertEquals("The time range should encompass only one entry.", 1, table.getEntries().size());
GridCoverageEntry entry = table.getEntry();
assertEquals(Boolean.FALSE, table.getLayerEntry(true).isTiled);
assertEquals(0, entry.getIdentifier().zIndex);
assertEquals(2, entry.getIdentifier().imageIndex);
table.envelope.setTimeRange(date("2007-05-22 00:24:00"), date("2007-05-22 00:36:00"));
assertEquals("The time range should encompass only one entry.", 1, table.getEntries().size());
entry = table.getEntry();
assertEquals(Boolean.FALSE, table.getLayerEntry(true).isTiled);
assertEquals(0, entry.getIdentifier().zIndex);
assertEquals(3, entry.getIdentifier().imageIndex);
table.release();
}
/**
* Tests the table for a NetCDF image with two bands.
*
* @throws SQLException If the test can't connect to the database.
*/
@Test
public void testTwoBands() throws SQLException {
final GridCoverageTable table = getDatabase().getTable(GridCoverageTable.class);
table.envelope.clear();
table.setLayer(LayerTableTest.GEOSTROPHIC_CURRENT);
final GridCoverageReference entry = table.getEntry();
assertEquals(2, entry.getSampleDimensions().length);
assertEquals(Boolean.FALSE, table.getLayerEntry(true).isTiled);
table.release();
}
/**
* Tests the request for a tiled image.
*
* @throws SQLException If the test can't connect to the database.
* @throws IOException Should not happen.
* @throws URISyntaxException Should never happen.
*/
@Test
public void testTiles() throws SQLException, IOException, URISyntaxException {
final GridCoverageTable table = getDatabase().getTable(GridCoverageTable.class);
table.envelope.clear();
table.setLayer(LayerTableTest.BLUEMARBLE);
final GridCoverageEntry entry = table.getEntry();
assertEquals(Boolean.TRUE, table.getLayerEntry(true).isTiled);
final TileManager[] tiles = (TileManager[]) entry.getInput();
assertEquals("We would had only 1 TileManager if we had tiles for every levels. " +
"But since L1 is missing, this is normal that L11 is considered to have " +
"no common dominator with L10, L12 and L13.", 2, tiles.length);
assertTrue(tiles[0].getTiles().size() > tiles[1].getTiles().size());
table.release();
}
/**
* Tests the request for the bounding box.
*
* @throws SQLException If the test can't connect to the database.
* @throws TransformException Should not happen.
*/
@Test
public void testBoundingBox() throws SQLException, TransformException {
final GridCoverageTable table = getDatabase().getTable(GridCoverageTable.class);
table.envelope.clear();
table.setLayer(LayerTableTest.TEMPERATURE);
GeneralEnvelope search = new GeneralEnvelope(table.envelope.getCoordinateReferenceSystem());
search.setToInfinite();
search.setRange(0, -200, 200);
search.setRange(1, -100, 100);
table.envelope.setEnvelope(search);
Envelope envelope = table.envelope;
assertEquals(-200, envelope.getMinimum(0), 0.0);
assertEquals(+200, envelope.getMaximum(0), 0.0);
assertEquals(-100, envelope.getMinimum(1), 0.0);
assertEquals(+100, envelope.getMaximum(1), 0.0);
table.trimEnvelope();
envelope = table.envelope;
assertEquals(-180, envelope.getMinimum(0), 0.0);
assertEquals(+180, envelope.getMaximum(0), 0.0);
assertEquals( -90, envelope.getMinimum(1), 0.0);
assertEquals( +90, envelope.getMaximum(1), 0.0);
assertEquals(6431, envelope.getMinimum(3), 0.0);
assertEquals(6487, envelope.getMaximum(3), 0.0);
/*
* Following test intentionally define an two-dimensional envelope instead than the
* expected three-dimensional spatio-temporal envelope. The time ordinates should be
* left unchanged.
*/
search = new GeneralEnvelope(CommonCRS.WGS84.normalizedGeographic());
search.setRange(0, -100, 120);
search.setRange(1, -80, 60);
table.envelope.setEnvelope(search);
table.trimEnvelope();
envelope = table.envelope;
assertEquals(-100, envelope.getMinimum(0), 0.0);
assertEquals(+120, envelope.getMaximum(0), 0.0);
assertEquals( -80, envelope.getMinimum(1), 0.0);
assertEquals( +60, envelope.getMaximum(1), 0.0);
assertEquals(6431, envelope.getMinimum(3), 0.0);
assertEquals(6487, envelope.getMaximum(3), 0.0);
table.release();
}
}