diff --git a/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/OafResource.java b/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/OafResource.java index a53f3a81..e456012d 100644 --- a/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/OafResource.java +++ b/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/OafResource.java @@ -276,7 +276,7 @@ private FeatureTypeMetadata createFeatureTypeMetadata( FeatureStore featureStore List metadataUrls = datasetMetadata != null && !datasetMetadata.getMetadataUrls().isEmpty() ? datasetMetadata.getMetadataUrls() : Collections.emptyList(); - String storageCrs = featureStore.getStorageCrs() != null ? featureStore.getStorageCrs().getName() : null; + String[] storageCrsCodes = featureStore.getStorageCrs() != null ? featureStore.getStorageCrs().getOrignalCodeStrings() : null; return new FeatureTypeMetadata( name ) .dateTimeProperty( dateTimeProperty ) .extent( extent ) @@ -285,7 +285,7 @@ private FeatureTypeMetadata createFeatureTypeMetadata( FeatureStore featureStore .metadataUrls( metadataUrls ) .filterProperties( filterProperties ) .featureType( featureType ) - .storageCrs( storageCrs ); + .storageCrsCodes( storageCrsCodes != null ? Arrays.asList( storageCrsCodes ) : null ); } private List parseFilterProperties( FeatureType featureType ) { diff --git a/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/workspace/DeegreeDataAccess.java b/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/workspace/DeegreeDataAccess.java index 9fae1df6..fa7712fc 100644 --- a/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/workspace/DeegreeDataAccess.java +++ b/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/workspace/DeegreeDataAccess.java @@ -231,11 +231,45 @@ private Collection createCollection( OafDatasetConfiguration oafConfiguration, S String title = featureType.getTitle(); String description = featureType.getDescription(); List suppportedCrs = oafConfiguration.getSuppportedCrs(); + + /* + * From the codes known for the storage CRS we try to use one that is part of the + * supported CRS. + * + * For reference from "OGC API Features Part 2: Coordinate Reference Systems": + * + * Requirement 4: + * The value of the storageCrs property SHALL be one of the CRS identifiers from the list + * of supported CRS identifiers found in the collection object using the crs property. + */ + String selectedCode = selectCrsCode( featureType.getStorageCrsCodes(), suppportedCrs ); + return new Collection( featureTypeId, title, description, links, featureType.getExtent(), suppportedCrs, - featureType.getStorageCrs() ); + selectedCode ); } - private Map getFeatureTypeNsPrefixes( FeatureStore featureStore ) { + /** + * Select a CRS code from the given codes, preferring codes from the given list of supported codes. + * If there is no match the first code is used as fall-back. + * + * @param crsCodes codes to select from + * @param suppportedCodes the supported/preferred codes + * @return the selected code + */ + public static String selectCrsCode(List crsCodes, List suppportedCodes) { + if (crsCodes == null || crsCodes.isEmpty()) { + return null; + } + + for (String candidate : crsCodes) { + if (suppportedCodes.contains(candidate)) { + return candidate; + } + } + return crsCodes.get(0); + } + + private Map getFeatureTypeNsPrefixes( FeatureStore featureStore ) { Map prefixToNs = new HashMap(); FeatureType[] featureTypes = featureStore.getSchema().getFeatureTypes(); for ( FeatureType ft : featureTypes ) { diff --git a/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/workspace/configuration/FeatureTypeMetadata.java b/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/workspace/configuration/FeatureTypeMetadata.java index 7e62109a..dd140e4d 100644 --- a/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/workspace/configuration/FeatureTypeMetadata.java +++ b/deegree-ogcapi-features/src/main/java/org/deegree/services/oaf/workspace/configuration/FeatureTypeMetadata.java @@ -49,7 +49,7 @@ public class FeatureTypeMetadata { private FeatureType featureType; - private String storageCrs; + private List storageCrsCodes; public FeatureTypeMetadata( QName featureTypeName ) { this.name = featureTypeName; @@ -91,8 +91,8 @@ public FeatureTypeMetadata featureType( FeatureType featureType ) { return this; } - public FeatureTypeMetadata storageCrs( String storageCrs ) { - this.storageCrs = storageCrs; + public FeatureTypeMetadata storageCrsCodes( List storageCrsCodes ) { + this.storageCrsCodes = storageCrsCodes; return this; } @@ -128,7 +128,7 @@ public FeatureType getFeatureType() { return featureType; } - public String getStorageCrs() { - return storageCrs; + public List getStorageCrsCodes() { + return storageCrsCodes; } } diff --git a/deegree-ogcapi-features/src/test/java/org/deegree/services/oaf/workspace/DeegreeDataAccessTest.java b/deegree-ogcapi-features/src/test/java/org/deegree/services/oaf/workspace/DeegreeDataAccessTest.java new file mode 100644 index 00000000..f0b0d89f --- /dev/null +++ b/deegree-ogcapi-features/src/test/java/org/deegree/services/oaf/workspace/DeegreeDataAccessTest.java @@ -0,0 +1,72 @@ +/*- + * #%L + * deegree-ogcapi-features - OGC API Features (OAF) implementation - Querying and modifying of geospatial data objects + * %% + * Copyright (C) 2019 - 2020 lat/lon GmbH, info@lat-lon.de, www.lat-lon.de + * %% + * This program 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, either version 2.1 of the + * License, or (at your option) any later version. + * + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ +package org.deegree.services.oaf.workspace; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.Arrays; +import java.util.List; + +import org.deegree.cs.coordinatesystems.ICRS; +import org.deegree.cs.exceptions.UnknownCRSException; +import org.deegree.cs.persistence.CRSManager; +import org.junit.Test; + +public class DeegreeDataAccessTest { + + @Test + public void test_selectCrsCode_ETRS89() throws UnknownCRSException { + String lookupCode = "http://www.opengis.net/def/crs/EPSG/0/4258"; + String code = selectCode( lookupCode, Arrays.asList( lookupCode ) ); + assertThat( code, is( lookupCode )); + } + + @Test + public void test_selectCrsCode_WGS84() throws UnknownCRSException { + String lookupCode = "http://www.opengis.net/def/crs/EPSG/0/4326"; + String code = selectCode( lookupCode, Arrays.asList( lookupCode ) ); + assertThat( code, is( lookupCode ) ); + } + + @Test + public void test_selectCrsCode_ETRS89_AlternateCode() throws UnknownCRSException { + String lookupCode = "urn:ogc:def:crs:EPSG::4258"; + String allowedCode = "http://www.opengis.net/def/crs/EPSG/0/4258"; + String code = selectCode( lookupCode, Arrays.asList( allowedCode ) ); + assertThat( code, is( allowedCode ) ); + } + + @Test + public void test_selectCrsCode_NoMatch() throws UnknownCRSException { + String lookupCode = "http://www.opengis.net/def/crs/EPSG/0/4326"; + ICRS crs = CRSManager.lookup( lookupCode ); + String code = selectCode( lookupCode, Arrays.asList( "EPSG:12345" ) ); + assertThat( code, is( crs.getCode().getOriginal() )); + } + + private String selectCode( String crsCode, List supportedCodes ) throws UnknownCRSException { + ICRS crs = CRSManager.lookup( crsCode ); + return DeegreeDataAccess.selectCrsCode( Arrays.asList( crs.getOrignalCodeStrings() ), supportedCodes ); + } + +}