Skip to content

Commit

Permalink
[GEOS-10324] adding arbitrary number of columns to ogcLink tables (ge…
Browse files Browse the repository at this point in the history
…oserver#5432)

* [GEOS-10324] adding arbitrary number of columns to ogcLink tables

* [GEOS-10324] review of the feedback
  • Loading branch information
ydeliorman authored Dec 15, 2021
1 parent 239794a commit f131351
Show file tree
Hide file tree
Showing 15 changed files with 232 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ALTER TABLE public.collection_ogclink
add column "intTest" integer, add column "floatTest" float, add column "booleanTest" boolean, add column "dateTest" date, add column "varcharTest" varchar;
-- data
INSERT INTO collection
("id", "name", "title", "description", "primary", "footprint", "timeStart", "timeEnd", "productCqlFilter", "masked", "eoIdentifier", "eoProductType", "eoPlatform", "eoPlatformSerialIdentifier", "eoInstrument", "eoSensorType", "eoCompositeType", "eoProcessingLevel", "eoOrbitType", "eoSpectralRange", "eoWavelength", "eoSecurityConstraints", "eoDissemination", "eoAcquisitionStation", "license", "assets")
Expand All @@ -18,14 +20,14 @@ VALUES(34, 'DISABLED_COLLECTION', 'A disabled collections', 'Not meant to be sha
select setval('collection_id_seq'::regclass, 35);
-- collection ogc links
INSERT INTO public.collection_ogclink
("collection_id", "offering", "method", "code", "type", "href")
VALUES(17, 'http://www.opengis.net/spec/owc/1.0/req/atom/wms', 'GET', 'GetCapabilities', 'application/xml', '${BASE_URL}/sentinel2/ows?service=wms&version=1.3.0&request=GetCapabilities');
("collection_id", "offering", "method", "code", "type", "href", "intTest", "floatTest", "booleanTest", "dateTest", "varcharTest")
VALUES(17, 'http://www.opengis.net/spec/owc/1.0/req/atom/wms', 'GET', 'GetCapabilities', 'application/xml', '${BASE_URL}/sentinel2/ows?service=wms&version=1.3.0&request=GetCapabilities', 17, 17.1, true, '2017-01-01', 'text17');
INSERT INTO public.collection_ogclink
("collection_id", "offering", "method", "code", "type", "href")
VALUES(31, 'http://www.opengis.net/spec/owc/1.0/req/atom/wms', 'GET', 'GetCapabilities', 'application/xml', '${BASE_URL}/landsat8/ows?service=wms&version=1.3.0&request=GetCapabilities');
("collection_id", "offering", "method", "code", "type", "href", "intTest", "floatTest", "booleanTest", "dateTest", "varcharTest")
VALUES(31, 'http://www.opengis.net/spec/owc/1.0/req/atom/wms', 'GET', 'GetCapabilities', 'application/xml', '${BASE_URL}/landsat8/ows?service=wms&version=1.3.0&request=GetCapabilities', 31, 31.1, true, '2031-01-01', 'text31');
INSERT INTO public.collection_ogclink
("collection_id", "offering", "method", "code", "type", "href")
VALUES(32, 'http://www.opengis.net/spec/owc/1.0/req/atom/wms', 'GET', 'GetCapabilities', 'application/xml', '${BASE_URL}/sentinel1/ows?service=wms&version=1.3.0&request=GetCapabilities');
("collection_id", "offering", "method", "code", "type", "href", "intTest", "floatTest", "booleanTest", "dateTest", "varcharTest")
VALUES(32, 'http://www.opengis.net/spec/owc/1.0/req/atom/wms', 'GET', 'GetCapabilities', 'application/xml', '${BASE_URL}/sentinel1/ows?service=wms&version=1.3.0&request=GetCapabilities', 32, 32.1, true, '2032-01-01', 'text32');
-- collection publishing metadata
INSERT into public.collection_layer
("cid", "workspace", "layer", "separateBands", "bands", "browseBands", "heterogeneousCRS", "mosaicCRS", "defaultLayer")
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
import java.io.StringReader;
import java.lang.reflect.Array;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Logger;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -55,6 +59,7 @@
import org.geotools.feature.NameImpl;
import org.geotools.feature.collection.BaseSimpleFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureImpl;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.util.Converters;
import org.geotools.util.logging.Logging;
Expand All @@ -65,6 +70,7 @@
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.AttributeType;
import org.opengis.feature.type.FeatureType;
import org.opengis.feature.type.Name;
import org.opengis.feature.type.PropertyDescriptor;
Expand Down Expand Up @@ -97,6 +103,12 @@ interface ZipPart {

static final FilterFactory2 FF = CommonFactoryFinder.getFilterFactory2();

// taken from OgcLink properties. these properties are known(static) from OgcLink.
private static final Set<String> KNOWN_FIELDS =
new HashSet<>(
Arrays.asList(
"collection_id", "lid", "offering", "method", "code", "type", "href"));

protected OpenSearchAccessProvider accessProvider;

protected OseoJSONConverter jsonConverter;
Expand Down Expand Up @@ -217,7 +229,32 @@ protected OgcLinks buildOgcLinksFromFeature(Feature feature, boolean notFoundOnE
List<OgcLink> links = Collections.emptyList();
Collection<Property> linkProperties =
feature.getProperties(OpenSearchAccess.OGC_LINKS_PROPERTY_NAME);
if (linkProperties != null) {

Map<String, Object> unknownFields = new HashMap<>();

if (linkProperties != null && linkProperties.size() > 0) {
SimpleFeatureImpl simpleFeature =
(SimpleFeatureImpl) ((ArrayList) linkProperties).get(0);

// iterate over feature to get unknown properties from OgcLink
if (simpleFeature != null
&& simpleFeature.getType() != null
&& simpleFeature.getType().getTypes() != null) {
List<AttributeType> types = simpleFeature.getType().getTypes();
for (int i = 0; i < types.size(); i++) {
if (types.get(i) != null && simpleFeature.getAttributes().get(i) != null) {
String unknownColumnName = types.get(i).getName().getLocalPart();
if (!KNOWN_FIELDS.contains(unknownColumnName)
&& simpleFeature != null
&& simpleFeature.getAttributes() != null
&& simpleFeature.getAttributes().get(i) != null) {
unknownFields.put(
unknownColumnName, simpleFeature.getAttributes().get(i));
}
}
}
}

links =
linkProperties
.stream()
Expand All @@ -230,10 +267,12 @@ protected OgcLinks buildOgcLinksFromFeature(Feature feature, boolean notFoundOnE
String code = (String) sf.getAttribute("code");
String type = (String) sf.getAttribute("type");
String href = (String) sf.getAttribute("href");
return new OgcLink(offering, method, code, type, href);
return new OgcLink(
offering, method, code, type, href, unknownFields);
})
.collect(Collectors.toList());
}

if (links.isEmpty() && notFoundOnEmpty) {
throw new ResourceNotFoundException();
}
Expand Down Expand Up @@ -472,6 +511,11 @@ protected ListFeatureCollection beansToLinksCollection(OgcLinks links) throws IO
fb.set("code", link.code);
fb.set("type", link.type);
fb.set("href", link.href);
for (Map.Entry<String, Object> entry : link.unknownFields.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
fb.set(key, value);
}
SimpleFeature sf = fb.buildFeature(null);
linksCollection.add(sf);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
*/
package org.geoserver.opensearch.rest;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.util.HashMap;
import java.util.Map;

/**
* Bean representation of a OWS context OGC Link
*
Expand All @@ -20,16 +26,25 @@ class OgcLink {

String href;

Map<String, Object> unknownFields = new HashMap<>();

public OgcLink() {
// default constructor
}

public OgcLink(String offering, String method, String code, String type, String href) {
public OgcLink(
String offering,
String method,
String code,
String type,
String href,
Map<String, Object> unknownFields) {
this.offering = offering;
this.method = method;
this.code = code;
this.type = type;
this.href = href;
this.unknownFields = unknownFields;
}

public String getOffering() {
Expand Down Expand Up @@ -71,4 +86,16 @@ public String getHref() {
public void setHref(String href) {
this.href = href;
}

// Capture all other fields that Jackson do not match other members
@JsonAnyGetter
@JsonSerialize(using = UnknownFieldsSerializer.class)
public Map<String, Object> otherFields() {
return unknownFields;
}

@JsonAnySetter
public void setOtherField(String name, Object value) {
unknownFields.put(name, value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* (c) 2021 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.opensearch.rest;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import org.springframework.stereotype.Component;

/**
* This class is responsible for serializing date into ISO format and writing other fields to the
* JSON
*/
@Component
public class UnknownFieldsSerializer extends JsonSerializer {

private static final DateFormat DATE_FORMAT =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
if (value instanceof Map) {
for (Map.Entry<String, Object> entry : ((Map<String, Object>) value).entrySet()) {
String key = entry.getKey();
Object valuePair = entry.getValue();
if (valuePair instanceof Date) {
gen.writeObjectField(key, DATE_FORMAT.format(valuePair));
} else {
gen.writeObjectField(key, valuePair);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,11 @@ private void assertTest123Links() throws Exception {
assertEquals(
"${BASE_URL}/test123/ows?service=wms&version=1.3.0&request=GetCapabilities",
json.read("$.links[0].href"));
assertEquals("123", json.read("$.links[0].intTest").toString());
assertEquals("123.1", json.read("$.links[0].floatTest").toString());
assertEquals("false", json.read("$.links[0].booleanTest").toString());
assertEquals("2015-07-01T00:00:00.000Z", json.read("$.links[0].dateTest").toString());
assertEquals("text123", json.read("$.links[0].varcharTest").toString());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,11 @@ public void testGetProductLinks() throws Exception {
assertEquals(
"${BASE_URL}/sentinel2/ows?service=wms&version=1.3.0&request=GetCapabilities",
json.read("$.links[0].href"));
assertEquals("6881", json.read("$.links[0].intTest").toString());
assertEquals("6881.1", json.read("$.links[0].floatTest").toString());
assertEquals("true", json.read("$.links[0].booleanTest").toString());
assertEquals("2017-01-01T00:00:00.000Z", json.read("$.links[0].dateTest").toString());
assertEquals("6881text", json.read("$.links[0].varcharTest").toString());
}

@Test
Expand Down Expand Up @@ -540,6 +545,11 @@ private void assertProductLinks(String firstLinkType) throws Exception {
assertEquals(
"${BASE_URL}/SENTINEL2/S2A_OPER_MSI_L1C_TL_SGS__20180101T000000_A006640_T32TPP_N02.04/ows?service=wms&version=1.3.0&request=GetCapabilities",
json.read("$.links[0].href"));
assertEquals("1", json.read("$.links[0].intTest").toString());
assertEquals("1.1", json.read("$.links[0].floatTest").toString());
assertEquals("false", json.read("$.links[0].booleanTest").toString());
assertEquals("2015-07-01T00:00:00.000Z", json.read("$.links[0].dateTest").toString());
assertEquals("text1", json.read("$.links[0].varcharTest").toString());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,24 @@
"method": "GET",
"code": "GetCapabilities",
"type": "text/xml",
"href": "${BASE_URL}/SENTINEL2/S2A_OPER_MSI_L1C_TL_SGS__20180101T000000_A006640_T32TPP_N02.04/ows?service=wms&version=1.3.0&request=GetCapabilities"
"href": "${BASE_URL}/SENTINEL2/S2A_OPER_MSI_L1C_TL_SGS__20180101T000000_A006640_T32TPP_N02.04/ows?service=wms&version=1.3.0&request=GetCapabilities",
"intTest":1,
"floatTest":1.1,
"booleanTest":false,
"dateTest":"2015-07-01T07:20:21.000Z",
"varcharTest":"text1"
},
{
"offering": "http://www.opengis.net/spec/owc/1.0/req/atom/wms",
"method": "GET",
"code": "GetMap",
"type": "image/jpeg",
"href": "${BASE_URL}/SENTINEL2/S2A_OPER_MSI_L1C_TL_SGS__20180101T000000_A006640_T32TPP_N02.04/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&STYLES&LAYERS=landsat8%3ALS8_RGB&SRS=EPSG%3A4326&WIDTH=800&HEIGHT=600&BBOX=-180%2C-90%2C180%2C90"
"href": "${BASE_URL}/SENTINEL2/S2A_OPER_MSI_L1C_TL_SGS__20180101T000000_A006640_T32TPP_N02.04/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&STYLES&LAYERS=landsat8%3ALS8_RGB&SRS=EPSG%3A4326&WIDTH=800&HEIGHT=600&BBOX=-180%2C-90%2C180%2C90",
"intTest":2,
"floatTest":2.1,
"booleanTest":false,
"dateTest":"2015-07-01T07:20:21.000Z",
"varcharTest":"text2"
}
]
}
14 changes: 12 additions & 2 deletions src/community/oseo/oseo-rest/src/test/resources/product-links.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,24 @@
"method": "GET",
"code": "GetCapabilities",
"type": "application/xml",
"href": "${BASE_URL}/SENTINEL2/S2A_OPER_MSI_L1C_TL_SGS__20180101T000000_A006640_T32TPP_N02.04/ows?service=wms&version=1.3.0&request=GetCapabilities"
"href": "${BASE_URL}/SENTINEL2/S2A_OPER_MSI_L1C_TL_SGS__20180101T000000_A006640_T32TPP_N02.04/ows?service=wms&version=1.3.0&request=GetCapabilities",
"intTest":1,
"floatTest":1.1,
"booleanTest":false,
"dateTest":"2015-07-01T07:20:21.000Z",
"varcharTest":"text1"
},
{
"offering": "http://www.opengis.net/spec/owc/1.0/req/atom/wms",
"method": "GET",
"code": "GetMap",
"type": "image/jpeg",
"href": "${BASE_URL}/SENTINEL2/S2A_OPER_MSI_L1C_TL_SGS__20180101T000000_A006640_T32TPP_N02.04/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&STYLES&LAYERS=landsat8%3ALS8_RGB&SRS=EPSG%3A4326&WIDTH=800&HEIGHT=600&BBOX=-180%2C-90%2C180%2C90"
"href": "${BASE_URL}/SENTINEL2/S2A_OPER_MSI_L1C_TL_SGS__20180101T000000_A006640_T32TPP_N02.04/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&STYLES&LAYERS=landsat8%3ALS8_RGB&SRS=EPSG%3A4326&WIDTH=800&HEIGHT=600&BBOX=-180%2C-90%2C180%2C90",
"intTest":2,
"floatTest":2.1,
"booleanTest":false,
"dateTest":"2015-07-01T07:20:21.000Z",
"varcharTest":"text2"
}
]
}
14 changes: 12 additions & 2 deletions src/community/oseo/oseo-rest/src/test/resources/test123-links.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,24 @@
"method": "GET",
"code": "GetCapabilities",
"type": "application/xml",
"href": "${BASE_URL}/test123/ows?service=wms&version=1.3.0&request=GetCapabilities"
"href": "${BASE_URL}/test123/ows?service=wms&version=1.3.0&request=GetCapabilities",
"intTest":123,
"floatTest":123.1,
"booleanTest":false,
"dateTest":"2015-07-01T07:20:21.000Z",
"varcharTest":"text123"
},
{
"offering": "http://www.opengis.net/spec/owc/1.0/req/atom/wms",
"method": "GET",
"code": "GetMap",
"type": "image/jpeg",
"href": "${BASE_URL}/test123/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&STYLES&LAYERS=landsat8%3ALS8_RGB&SRS=EPSG%3A4326&WIDTH=800&HEIGHT=600&BBOX=-180%2C-90%2C180%2C90"
"href": "${BASE_URL}/test123/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fjpeg&STYLES&LAYERS=landsat8%3ALS8_RGB&SRS=EPSG%3A4326&WIDTH=800&HEIGHT=600&BBOX=-180%2C-90%2C180%2C90",
"intTest":123,
"floatTest":123,
"booleanTest":false,
"dateTest":"2015-07-01T07:20:21.000Z",
"varcharTest":"text123"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ private void checkLandsat8Collection(JSONArray features) {
JSONObject instrument = acquisition.getJSONObject("instrument");
assertEquals("OLI", instrument.get("instrumentShortName"));
assertEquals("OPTICAL", instrument.get("sensorType"));

JSONObject ogcLink = (JSONObject) sp.getJSONObject("links").getJSONArray("ogc").get(0);
assertEquals(ogcLink.get("intTest").toString(), "2");
assertEquals(ogcLink.get("floatTest").toString(), "2.1");
assertEquals(ogcLink.get("booleanTest").toString(), "false");
assertEquals(ogcLink.get("dateTest").toString(), "2015-07-01T07:20:21.000Z");
assertEquals(ogcLink.get("varcharTest").toString(), "text2");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,16 @@ public void testReadAndEvalJSON() throws Exception {
containsString("<h3>attribute3 => 3</h3>")));
}

@Test
public void testOgcLinkAttributeHTMLTemplate() throws Exception {
String uid = "LANDSAT8";
Document dom = getAsDOM("oseo/search?uid=" + uid);
assertThat(dom, hasXPath("/at:feed/at:entry[1]", containsString("31.1")));
assertThat(dom, hasXPath("/at:feed/at:entry[1]", containsString("true")));
assertThat(dom, hasXPath("/at:feed/at:entry[1]", containsString("text31")));
assertThat(dom, hasXPath("/at:feed/at:entry[1]", containsString("2031-01-01")));
}

private void summaryHasLink(Document dom, String link) {
assertThat(
dom,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<#assign a = model.attributes />
<#assign a = model.attributes />
<p>${a.ogcLinks}</p>
<tr valign="top">
<td>
<b>Title</b>
Expand Down
Loading

0 comments on commit f131351

Please sign in to comment.