/* (c) 2016 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.gwc.wmts; import org.geoserver.catalog.*; import org.geoserver.catalog.DimensionDefaultValueSetting.Strategy; import org.geoserver.catalog.impl.DimensionInfoImpl; import org.geoserver.gwc.wmts.dimensions.Dimension; import org.geoserver.gwc.wmts.dimensions.DimensionsUtils; import org.geoserver.gwc.wmts.dimensions.RasterTimeDimension; import org.geoserver.util.ISO8601Formatter; import org.geotools.feature.type.DateUtil; import org.junit.Test; import org.opengis.filter.Filter; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; /** * <p> * This class contains tests that check that time dimension values are correctly extracted from rasters. Some domain * values are dynamically created based on the current time, this matches what is done in WMS dimensions tests. * </p> * <p> * Note, there is some inconsistency between ISO formatter and GeoTools data serializer string output, this * is something that needs to be fixed (or maybe not) at GeoServer and GeoTools level. In the mean time * this tests will use the two formatter were needed. * </p> */ public class RasterTimeDimensionTest extends TestsSupport { // sorted time domain values as date objects protected static Date[] DATE_VALUES = new Date[]{ DateUtil.deserializeDateTime("2008-10-31T00:00:00Z"), DateUtil.deserializeDateTime("2008-11-01T00:00:00Z"), getGeneratedMinValue(), getGeneratedMiddleValue(), getGeneratedMaxValue() }; // sorted time domain values as strings formatted with ISO8601 formatter protected static String[] STRING_VALUES = new String[]{ formatDate(DATE_VALUES[0]), formatDate(DATE_VALUES[1]), formatDate(DATE_VALUES[2]), formatDate(DATE_VALUES[3]), formatDate(DATE_VALUES[4]) }; @Test public void testDisabledDimension() throws Exception { // enable a time dimension DimensionInfo dimensionInfo = new DimensionInfoImpl(); dimensionInfo.setEnabled(true); CoverageInfo rasterInfo = getCoverageInfo(); rasterInfo.getMetadata().put(ResourceInfo.TIME, dimensionInfo); getCatalog().save(rasterInfo); // check that we correctly retrieve the time dimension assertThat(DimensionsUtils.extractDimensions(wms, getLayerInfo()).size(), is(1)); // disable the time dimension dimensionInfo.setEnabled(false); rasterInfo.getMetadata().put(ResourceInfo.TIME, dimensionInfo); getCatalog().save(rasterInfo); // no dimensions should be available assertThat(DimensionsUtils.extractDimensions(wms, getLayerInfo()).size(), is(0)); } @Test public void testGetDefaultValue() { testDefaultValueStrategy(Strategy.MINIMUM, DateUtil.serializeDateTime(DATE_VALUES[0].getTime(), true)); testDefaultValueStrategy(Strategy.MAXIMUM, DateUtil.serializeDateTime(DATE_VALUES[4].getTime(), true)); } @Test public void testGetDomainsValues() throws Exception { testDomainsValuesRepresentation(DimensionPresentation.LIST, STRING_VALUES); testDomainsValuesRepresentation(DimensionPresentation.CONTINUOUS_INTERVAL, STRING_VALUES[0] + "--" + STRING_VALUES[4]); testDomainsValuesRepresentation(DimensionPresentation.DISCRETE_INTERVAL, STRING_VALUES[0] + "--" + STRING_VALUES[4]); } @Override protected Dimension buildDimension(DimensionInfo dimensionInfo) { return new RasterTimeDimension(wms, getLayerInfo(), dimensionInfo); } /** * Helper method that simply formats a date using the ISO8601 formatter. */ private static String formatDate(Date date) { ISO8601Formatter formatter = new ISO8601Formatter(); return formatter.format(date); } /** * Generates the current minimum date. */ private static Date getGeneratedMinValue() { TimeZone.setDefault(TimeZone.getTimeZone("UTC")); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, calendar.getActualMinimum(Calendar.HOUR_OF_DAY)); calendar.set(Calendar.MINUTE, calendar.getActualMinimum(Calendar.MINUTE)); calendar.set(Calendar.SECOND, calendar.getActualMinimum(Calendar.SECOND)); calendar.set(Calendar.MILLISECOND, calendar.getActualMinimum(Calendar.MILLISECOND)); return calendar.getTime(); } /** * Generates the current middle date, this date is one month later than the current minimum date. */ private static Date getGeneratedMiddleValue() { TimeZone.setDefault(TimeZone.getTimeZone("UTC")); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, calendar.getActualMinimum(Calendar.HOUR_OF_DAY)); calendar.set(Calendar.MINUTE, calendar.getActualMinimum(Calendar.MINUTE)); calendar.set(Calendar.SECOND, calendar.getActualMinimum(Calendar.SECOND)); calendar.set(Calendar.MILLISECOND, calendar.getActualMinimum(Calendar.MILLISECOND)); calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1); return calendar.getTime(); } /** * Generates the current maximum date, this date is one year later than the current minimum date. */ private static Date getGeneratedMaxValue() { TimeZone.setDefault(TimeZone.getTimeZone("UTC")); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, calendar.getActualMinimum(Calendar.HOUR_OF_DAY)); calendar.set(Calendar.MINUTE, calendar.getActualMinimum(Calendar.MINUTE)); calendar.set(Calendar.SECOND, calendar.getActualMinimum(Calendar.SECOND)); calendar.set(Calendar.MILLISECOND, calendar.getActualMinimum(Calendar.MILLISECOND)); // this is the way the original data month is setup, I don't understand this but without this the month may not correspond calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1); calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1); calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1); return calendar.getTime(); } @Test public void testGetHistogram() { DimensionInfo dimensionInfo = createDimension(true, DimensionPresentation.LIST, null); Dimension dimension = buildDimension(dimensionInfo); Tuple<String, List<Integer>> histogram = dimension.getHistogram(Filter.INCLUDE, "P1Y"); assertThat(histogram.first, is("2008-10-31T00:00:00.000Z/" + STRING_VALUES[4] + "/P1Y")); assertThat(histogram.second.stream().reduce(0, (total, value) -> total + value), is(6)); } /** * Helper method that just returns the current layer info. */ private LayerInfo getLayerInfo() { return catalog.getLayerByName(RASTER_TIME.getLocalPart()); } /** * Helper method that just returns the current coverage info. */ private CoverageInfo getCoverageInfo() { LayerInfo layerInfo = getLayerInfo(); assertThat(layerInfo.getResource(), instanceOf(CoverageInfo.class)); return (CoverageInfo) layerInfo.getResource(); } }