Skip to content
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 @@ -217,11 +217,10 @@ protected List<LinkModel> getWfsLinks(String collectionId) {

StacCollectionModel model = result.getCollections().get(0);

// Filter WMS links where ai:group contains WMS_LINK_MARKER
// Filter WFS links by ai:group marker, falling back to rel="wfs"
return model.getLinks()
.stream()
.filter(link -> link.getAiGroup() != null)
.filter(link -> link.getAiGroup().contains(WFS_LINK_MARKER))
.filter(isWfsLink(WFS_LINK_MARKER))
.toList();
}

Expand Down Expand Up @@ -482,13 +481,9 @@ protected Optional<List<String>> getAllFeatureServerUrls(String collectionId) {
return Optional.of(
model.getLinks()
.stream()
.filter(link -> link.getAiGroup() != null)
.filter(link ->
// This is the pattern for wfs link
link.getAiGroup().contains(WFS_LINK_MARKER) ||
// The data itself can be unclean, ows is another option where it works with wfs
link.getHref().contains("/ows")
)
.filter(isWfsLink(WFS_LINK_MARKER)
// The data itself can be unclean, ows is another option where it works with wfs
.or(link -> link.getHref().contains("/ows")))
.map(LinkModel::getHref)
.toList()
);
Expand All @@ -512,8 +507,7 @@ public Optional<String> getFeatureServerUrlByTitleOrQueryParam(String collection
log.info("start to find wfs link for collectionId {} with layerName {}, total links to check {}", collectionId, layerName, model.getLinks().size());
return model.getLinks()
.stream()
.filter(link -> link.getAiGroup() != null)
.filter(link -> link.getAiGroup().contains(WFS_LINK_MARKER))
.filter(isWfsLink(WFS_LINK_MARKER))
.filter(link -> {
Optional<String> name = extractLayernameOrTypenameFromUrl(link.getHref());
return roughlyMatch(link.getTitle(), layerName) ||
Expand Down Expand Up @@ -611,11 +605,10 @@ public List<FeatureTypeInfo> filterFeatureTypesByWfsLinks(String collectionId, L

StacCollectionModel model = result.getCollections().get(0);

// Filter WFS links where ai:group contains "Data Access > wfs"
// Filter WFS links by ai:group marker, falling back to rel="wfs"
List<LinkModel> wfsLinks = model.getLinks()
.stream()
.filter(link -> link.getAiGroup() != null)
.filter(link -> link.getAiGroup().contains(WFS_LINK_MARKER))
.filter(isWfsLink(WFS_LINK_MARKER))
.toList();

// Filter feature types based on matching with WFS links
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,11 +449,10 @@ protected Optional<String> getMapServerUrl(String collectionId, FeatureRequest r
StacCollectionModel model = result.getCollections().get(0);

String layerName = request != null ? request.getLayerName() : null;
// Filter for WMS links
// Filter WMS links by ai:group marker, falling back to rel="wms"
List<LinkModel> wmsLinks = model.getLinks()
.stream()
.filter(link -> link.getAiGroup() != null)
.filter(link -> link.getAiGroup().contains(WMS_LINK_MARKER))
.filter(isWmsLink(WMS_LINK_MARKER))
.toList();

if (wmsLinks.isEmpty()) {
Expand Down Expand Up @@ -725,11 +724,10 @@ protected List<LinkModel> getWmsLinks(String collectionId) {

StacCollectionModel model = result.getCollections().get(0);

// Filter WMS links where ai:group contains WMS_LINK_MARKER
// Filter WMS links by ai:group marker, falling back to rel="wms"
return model.getLinks()
.stream()
.filter(link -> link.getAiGroup() != null)
.filter(link -> link.getAiGroup().contains(WMS_LINK_MARKER))
.filter(isWmsLink(WMS_LINK_MARKER))
.toList();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,36 @@
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;

@Slf4j
public class GeoserverUtils {
/**
* Predicate that matches a link as a WFS link.
* Primary: link has ai:group containing the WFS marker.
* Fallback: link has rel = "wfs" (for links without ai:group).
*
* @param wfsLinkMarker - The WFS marker string (e.g. "Data Access > wfs")
* @return Predicate matching WFS links
*/
public static Predicate<LinkModel> isWfsLink(String wfsLinkMarker) {
return link -> (link.getAiGroup() != null && link.getAiGroup().contains(wfsLinkMarker))
|| "wfs".equalsIgnoreCase(link.getRel());
}

/**
* Predicate that matches a link as a WMS link.
* Primary: link has ai:group containing the WMS marker.
* Fallback: link has rel = "wms" (for links without ai:group).
*
* @param wmsLinkMarker - The WMS marker string (e.g. "Data Access > wms")
* @return Predicate matching WMS links
*/
public static Predicate<LinkModel> isWmsLink(String wmsLinkMarker) {
return link -> (link.getAiGroup() != null && link.getAiGroup().contains(wmsLinkMarker))
|| "wms".equalsIgnoreCase(link.getRel());
}

/**
* Fuzzy match utility to compare layer names, ignoring namespace prefixes
* For example: "underway:nuyina_underway_202122020" matches "nuyina_underway_202122020"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static au.org.aodn.ogcapi.server.core.service.geoserver.wfs.WfsDefaultParam.WFS_LINK_MARKER;
import static org.junit.jupiter.api.Assertions.*;
Expand Down Expand Up @@ -393,6 +394,28 @@ void createWfsRequestUrl_stripsOldParamsFromServerUrl() {
assertEquals(1, requestCount, "REQUEST should appear exactly once");
}

@Test
void getFeatureServerUrl_withRelWfsFallback_returnsUrl() {
// Link has rel="wfs" but no aiGroup — should be found via fallback
String expectedUrl = "http://geoserver.example.com/geoserver/wfs";
LinkModel wfsLink = LinkModel.builder()
.rel("wfs")
.href(expectedUrl)
.title("test_layer")
.build();

StacCollectionModel model = StacCollectionModel.builder().links(List.of(wfsLink)).build();
ElasticSearchBase.SearchResult<StacCollectionModel> result = new ElasticSearchBase.SearchResult<>();
result.setCollections(List.of(model));
when(mockSearch.searchCollections(anyString())).thenReturn(result);

WfsServer server = new WfsServer(mockSearch, restTemplate, new RestTemplateUtils(restTemplate), entity, wfsDefaultParam);
Optional<String> url = server.getFeatureServerUrl("id", "test_layer");

assertTrue(url.isPresent(), "URL should be found via rel=wfs fallback when aiGroup is absent");
assertEquals(expectedUrl, url.get());
}

@Test
void createCapabilitiesQueryUrl_buildsCorrectUrl() {
// arrange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,48 @@ public void verifyHandleServiceExceptionReportCorrect() {
"DownloadableFieldsNotFoundException expected when layer is not found on server");
}

@Test
public void describeLayer_withRelWmsFallback_returnsResult() {
// Link has rel="wms" but no aiGroup — getMapServerUrl should find it via fallback
FeatureRequest request = FeatureRequest.builder().layerName("imos:test_layer").build();

ElasticSearchBase.SearchResult<StacCollectionModel> stac = new ElasticSearchBase.SearchResult<>();
stac.setCollections(new ArrayList<>());
stac.getCollections().add(
StacCollectionModel
.builder()
.links(List.of(
LinkModel.builder()
.rel("wms")
.href("http://geoserver-123.aodn.org.au/geoserver/wms")
.title(request.getLayerName())
.build()) // no aiGroup
)
.build()
);

String describeLayerXml = """
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE WMS_DescribeLayerResponse SYSTEM "https://geoserver-123.aodn.org.au/geoserver/schemas/wms/1.1.1/WMS_DescribeLayerResponse.dtd">
<WMS_DescribeLayerResponse version="1.1.1">
<LayerDescription name="imos:test_layer" wfs="https://geoserver-123.aodn.org.au/geoserver/wfs?" owsURL="https://geoserver-123.aodn.org.au/geoserver/wfs?" owsType="WFS">
<Query typeName="imos:test_layer"/>
</LayerDescription>
</WMS_DescribeLayerResponse>""";

when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(entity), eq(String.class)))
.thenReturn(ResponseEntity.ok(describeLayerXml));

String id = "id";
when(search.searchCollections(eq(id))).thenReturn(stac);

DescribeLayerResponse response = wmsServer.describeLayer(id, request);

assertNotNull(response, "describeLayer should succeed when link is found via rel=wms fallback");
assertNotNull(response.getLayerDescription());
assertEquals("imos:test_layer", response.getLayerDescription().getName());
}

@Test
public void verifyParseCorrect() throws JsonProcessingException {
DescribeLayerResponse value = wmsServer.xmlMapper.readValue(
Expand Down
Loading