Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GEOS-11394] OGC APIs cannot handle time extent when the source data type is java.sql.Date #7621

Merged
merged 1 commit into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -51,16 +53,29 @@ public class TemporalExtents {

public List<String[]> getInterval() {
if (temporal != null) {
java.util.Date minValue = temporal.getMinValue();
java.util.Date maxValue = temporal.getMaxValue();
if (minValue instanceof java.sql.Date) {
return Collections.singletonList(
new String[] {
ISO_INSTANT.format(sqlDateToInstant((java.sql.Date) minValue)),
ISO_INSTANT.format(sqlDateToInstant((java.sql.Date) maxValue))
});
}
return Collections.singletonList(
new String[] {
ISO_INSTANT.format(temporal.getMinValue().toInstant()),
ISO_INSTANT.format(temporal.getMaxValue().toInstant())
ISO_INSTANT.format(minValue.toInstant()),
ISO_INSTANT.format(maxValue.toInstant())
});
} else {
return null;
}
}

private Instant sqlDateToInstant(java.sql.Date minValue) {
return minValue.toLocalDate().atStartOfDay(ZoneOffset.UTC).toInstant();
}

public String getTrs() {
return "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import java.io.IOException;
import java.util.Date;
import java.util.Optional;
import java.util.logging.Logger;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.DimensionInfo;
Expand Down Expand Up @@ -62,14 +63,17 @@ private static DateRange getTimeExtent(FeatureTypeInfo ft, DimensionInfo time)
ft.getFeatureSource(null, null);
FeatureCollection<? extends FeatureType, ? extends Feature> collection = fs.getFeatures();

final MinVisitor min = new MinVisitor(time.getAttribute());
String timeAttribute = time.getAttribute();
final MinVisitor min = new MinVisitor(timeAttribute);
collection.accepts(min, null);
CalcResult minResult = min.getResult();
// check calcresult first to avoid potential IllegalStateException if no features are in
// collection
if (minResult != CalcResult.NULL_RESULT) {
Date minDate = (Date) min.getMin();
final MaxVisitor max = new MaxVisitor(time.getAttribute());
String endTimeAttribute =
Optional.ofNullable(time.getEndAttribute()).orElse(timeAttribute);
final MaxVisitor max = new MaxVisitor(endTimeAttribute);
collection.accepts(max, null);
Date maxDate = (Date) max.getMax();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<#setting locale="en_US">
<#setting time_zone="utc">
<#setting date_format="iso">
<#setting datetime_format="iso">
<!DOCTYPE html>
<html lang="en">
<head>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</li>
<#if collection.extent.temporal??>
<#assign temporal = collection.extent.temporal>
<li id="${collection.htmlId}_temporal"><b>Temporal extent</b>: ${temporal.minValue?datetime?iso_utc}/${temporal.maxValue?datetime?iso_utc}</li>
<li id="${collection.htmlId}_temporal"><b>Temporal extent</b>: ${temporal.minValue}/${temporal.maxValue}</li>
</#if>
</ul>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</li>
<#if collection.extent.temporal??>
<#assign temporal = collection.extent.temporal>
<li id="${collection.htmlId}_temporal"><b>Temporal extent</b>: ${temporal.minValue?datetime?iso_utc}/${temporal.maxValue?datetime?iso_utc}</li>
<li id="${collection.htmlId}_temporal"><b>Temporal extent</b>: ${temporal.minValue}/${temporal.maxValue}</li>
</#if>
<li> <a id="html_${collection.htmlId}_link" href="${collection.getLinkUrl('styles', 'text/html')!}">Map styles</a>.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,39 @@ public void testTemporalCollectionHTML() throws Exception {
document.select("#" + id + "_temporal").text());
}

/**
* Checks a temporal dimension defined over java.sql.date works in HTML
*
* @throws Exception
*/
@Test
public void testTemporalSqlDateHTML() throws Exception {
setupStartEndTimeDimension(TIME_WITH_START_END_DATE, "time", "startTime", "endTime");
org.jsoup.nodes.Document document =
getAsJSoup("ogc/maps/v1/collections/sf:TimeWithStartEndDate?f=html");

String id = getLayerId(TIME_WITH_START_END_DATE).replace(":", "__");

// check temporal extent
assertEquals(
"Temporal extent: 2012-02-11/2012-02-14",
document.select("#" + id + "_temporal").text());
}

/**
* Checks a temporal dimension defined over java.sql.date works in JSON
*
* @throws Exception
*/
@Test
public void testTemporalSqlDateJSON() throws Exception {
setupStartEndTimeDimension(TIME_WITH_START_END_DATE, "time", "startTime", "endTime");
DocumentContext json =
getAsJSONPath("ogc/maps/v1/collections/sf:TimeWithStartEndDate", 200);
assertEquals("2012-02-11T00:00:00Z", json.read("$.extent.temporal.interval[0][0]"));
assertEquals("2012-02-14T00:00:00Z", json.read("$.extent.temporal.interval[0][1]"));
}

@Test
public void testCollectionJson() throws Exception {
setupRasterDimension(TIMESERIES, TIME, DimensionPresentation.LIST, null, null, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
public class MapsTest extends MapsTestSupport {
@Test
public void testDatetimeJson() throws Exception {
setupStartEndTimeDimension(
TIME_WITH_START_END.getLocalPart(), "time", "startTime", "endTime");
setupStartEndTimeDimension(TIME_WITH_START_END, "time", "startTime", "endTime");
Integer[] values = {1, 1, 1, 1, 0, 1};
// work with different time resolutions
String[] dates = {
Expand All @@ -44,8 +43,7 @@ public void testDatetimeJson() throws Exception {

@Test
public void testDatetimeHTMLMapsFormat() throws Exception {
setupStartEndTimeDimension(
TIME_WITH_START_END.getLocalPart(), "time", "startTime", "endTime");
setupStartEndTimeDimension(TIME_WITH_START_END, "time", "startTime", "endTime");
Document document =
getAsJSoup(
"ogc/maps/v1/collections/sf:TimeWithStartEnd/styles/Default/map?f=html&datetime=2012-02-12T00:00:00Z");
Expand All @@ -55,8 +53,7 @@ public void testDatetimeHTMLMapsFormat() throws Exception {

@Test
public void testHTMLNoDatetime() throws Exception {
setupStartEndTimeDimension(
TIME_WITH_START_END.getLocalPart(), "time", "startTime", "endTime");
setupStartEndTimeDimension(TIME_WITH_START_END, "time", "startTime", "endTime");
// failed here when no datetime provided, FTL processing error, null on js_string
Document document =
getAsJSoup("ogc/maps/v1/collections/sf:TimeWithStartEnd/styles/Default/map?f=html");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package org.geoserver.ogcapi.v1.maps;

import java.util.Collections;
import java.util.TimeZone;
import javax.xml.namespace.QName;
import org.geoserver.catalog.DimensionInfo;
import org.geoserver.catalog.DimensionPresentation;
Expand All @@ -13,13 +14,22 @@
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.ogcapi.OGCApiTestSupport;
import org.junit.BeforeClass;

public class MapsTestSupport extends OGCApiTestSupport {
protected static final QName TIMESERIES =
new QName(MockData.SF_URI, "timeseries", MockData.SF_PREFIX);
static final QName TIME_WITH_START_END =
new QName(MockData.SF_URI, "TimeWithStartEnd", MockData.SF_PREFIX);

static final QName TIME_WITH_START_END_DATE =
new QName(MockData.SF_URI, "TimeWithStartEndDate", MockData.SF_PREFIX);

@BeforeClass
public static void setupTimeZone() throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}

@Override
protected void setUpTestData(SystemTestData testData) throws Exception {
testData.setUpDefault();
Expand All @@ -37,11 +47,17 @@ protected void onSetUp(SystemTestData testData) throws Exception {
"TimeElevationWithStartEnd.properties",
getClass(),
getCatalog());
testData.addVectorLayer(
TIME_WITH_START_END_DATE,
Collections.emptyMap(),
"TimeElevationWithStartEndDate.properties",
getClass(),
getCatalog());
}

protected void setupStartEndTimeDimension(
String featureTypeName, String dimension, String start, String end) {
FeatureTypeInfo info = getCatalog().getFeatureTypeByName(featureTypeName);
QName typeName, String dimension, String start, String end) {
FeatureTypeInfo info = getCatalog().getFeatureTypeByName(typeName.getLocalPart());
DimensionInfo di = new DimensionInfoImpl();
di.setEnabled(true);
di.setAttribute(start);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
_=id:java.lang.Integer,startTime:java.sql.Date,endTime:java.sql.Date,startElevation:double,endElevation:double,geom:Polygon:srid=4326
TimeElevationWithStartEnd.0=0|2012-02-11|2012-02-12|1.0|2.0|POLYGON((-180 90, 0 90, 0 0, -180 0, -180 90))
TimeElevationWithStartEnd.1=1|2012-02-12|2012-02-13|2.0|3.0|POLYGON((0 90, 180 90, 180 0, 0 0, 0 90))
TimeElevationWithStartEnd.2=2|2012-02-11|2012-02-14|1.0|3.0|POLYGON((-180 -90, 0 -90, 0 0, -180 0, -180 -90))
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.SimpleHash;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateSequenceModel;
Expand Down Expand Up @@ -227,6 +228,12 @@ public TemplateModel wrap(Object object) throws TemplateModelException {
return super.wrap(object);
}

@Override
public int getDefaultDateType() {
// allows to just serialize dates without specifying a formatting
return TemplateDateModel.DATETIME;
}

private SimpleHash buildType(ComplexType ft) {
// create a variable "attributes" which his a list of all the
// attributes, but at the same time, is a map keyed by name
Expand Down
Loading