-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GEOS-10892] Allow configuring custom links for OGC API collections a…
…nd single collection resources
- Loading branch information
Showing
40 changed files
with
1,302 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
Configuring the GeoServer OGC API module | ||
======================================== | ||
|
||
The OGC API module is mostly using the same configurations as the equivalent OWS services. | ||
So, for example, setting the WFS limited SRS list will also limit the SRS list for OGC API - Features. | ||
|
||
The OGC API module is also using the same security configuration as the equivalent OWS services. | ||
|
||
In addition, the OGC API module has some unique configuration options, explained below. | ||
|
||
Custom links for the "collections" resource | ||
------------------------------------------- | ||
|
||
By specification, the ``collections`` resource can have a number of additional links, beyond | ||
the basic ones that the service code already includes. | ||
|
||
The administrator can add links for this resource either in the Global pages, or in the | ||
workspace specific settings: | ||
|
||
.. figure:: img/links.png | ||
|
||
Links editor | ||
|
||
Link editor column description: | ||
|
||
* **rel**: the link relation type, as per the OGC API - Features specification | ||
* **Mime type**: the mime type for the resource found following the link | ||
* **URL**: the link URL | ||
* **Title**: the link title (optional) | ||
* **Service**: the service for which the link is valid (optional, defaults to all) | ||
|
||
|
||
Common links relationships that could be added for the ``collections`` resource are: | ||
|
||
* ``enclosure``, in case there is a package delivering all the collections (e.g. a GeoPackage, a ZIP full of shapefiles). | ||
* ``describedBy``, in case there is a document describing all the collections (e.g. a JSON or XML schema). | ||
* ``license``, if all collection data is under the same license. | ||
|
||
Custom links for single collections | ||
----------------------------------- | ||
|
||
By specification, the ``collection`` resource can have a number of additional links, beyond | ||
the basics ones that the service code already includes. | ||
|
||
The editor is the same, but is found in the "Publishing" tab of the layer in question. | ||
The relationships are the same as for the ``collections`` resource, but used in case | ||
there is anything that is specific to the collection (e.g., the schema for the single collection). | ||
In addition, other relations can be specified, like the ``tag`` relation, to link to the eventual | ||
INSPIRE feature concept dictionary entry. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
src/community/ogcapi/ogcapi-core/src/main/java/org/geoserver/ogcapi/LinkInfo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* (c) 2023 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.ogcapi; | ||
|
||
/** | ||
* Configurable links for OGC API services, they can be provided at the {@link | ||
* org.geoserver.catalog.ResourceInfo} and {@link org.geoserver.config.GeoServerInfo} level. More | ||
* places to be added in the future (e.g., {@link org.geoserver.catalog.LayerGroupInfo}, {@link | ||
* org.geoserver.config.ServiceInfo} | ||
*/ | ||
import java.io.Serializable; | ||
import org.geoserver.catalog.MetadataMap; | ||
|
||
public interface LinkInfo extends Serializable { | ||
|
||
String LINKS_METADATA_KEY = "ogcApiLinks"; | ||
|
||
/** Returns the relation type, e.g., "self", "alternate", "service-desc", ... */ | ||
String getRel(); | ||
|
||
/** | ||
* Sets the relation type for this link (mandatory). e.g., "self", "alternate", "service-desc", | ||
*/ | ||
void setRel(String rel); | ||
|
||
/** Returns the MIME type, e.g., "application/json", "text/html", "application/atom+xml", ... */ | ||
String getType(); | ||
|
||
/** Sets the MIME type for this link (mandatory) */ | ||
void setType(String type); | ||
|
||
/** Returns the title, if any */ | ||
String getTitle(); | ||
|
||
/** Sets the title for this link (optional) */ | ||
void setTitle(String title); | ||
|
||
/** Returns the href for this link */ | ||
String getHref(); | ||
|
||
/** Returns the href */ | ||
void setHref(String href); | ||
|
||
/** Returns the service type, if any, e.g.,"Features", "Maps", ... */ | ||
String getService(); | ||
|
||
/** Sets the service type for this link (optional) */ | ||
void setService(String service); | ||
|
||
/** | ||
* Returns the metadata map, which can be used to store additional information about the link | ||
*/ | ||
MetadataMap getMetadata(); | ||
|
||
/** Returns a clone of this link info */ | ||
LinkInfo clone(); | ||
} |
64 changes: 64 additions & 0 deletions
64
src/community/ogcapi/ogcapi-core/src/main/java/org/geoserver/ogcapi/LinkInfoCallback.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* (c) 2023 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.ogcapi; | ||
|
||
import org.geoserver.catalog.PublishedInfo; | ||
import org.geoserver.catalog.ResourceInfo; | ||
import org.geoserver.config.GeoServer; | ||
import org.geoserver.config.SettingsInfo; | ||
import org.geoserver.ows.Request; | ||
import org.geoserver.platform.Service; | ||
import org.springframework.stereotype.Component; | ||
|
||
/** | ||
* Adds links to the OGC API documents, based on the {@link LinkInfo} objects attached to either the | ||
* {@link ResourceInfo}, the {@link PublishedInfo} object, or the {@link SettingsInfo} object. | ||
* Filters out links that are not applicable to the current service. | ||
*/ | ||
@Component | ||
public class LinkInfoCallback implements DocumentCallback { | ||
|
||
GeoServer geoServer; | ||
|
||
public LinkInfoCallback(GeoServer geoServer) { | ||
this.geoServer = geoServer; | ||
} | ||
|
||
@Override | ||
public void apply(Request dr, AbstractDocument document) { | ||
if (document instanceof AbstractCollectionDocument) { | ||
decorateCollection(dr, (AbstractCollectionDocument) document); | ||
} else if (isCollectionsDocument(dr)) { | ||
decorateCollections(dr, document); | ||
} | ||
} | ||
|
||
private void decorateCollections(Request dr, AbstractDocument document) { | ||
Class<?> serviceClass = getServiceClass(dr); | ||
SettingsInfo settings = geoServer.getSettings(); | ||
LinkInfoConverter.addLinksToDocument(document, settings, serviceClass); | ||
} | ||
|
||
private boolean isCollectionsDocument(Request dr) { | ||
return dr.getPath().equals("collections"); | ||
} | ||
|
||
private void decorateCollection(Request dr, AbstractCollectionDocument document) { | ||
Object subject = document.getSubject(); | ||
Class<?> serviceClass = getServiceClass(dr); | ||
if (subject instanceof ResourceInfo) { | ||
ResourceInfo resource = (ResourceInfo) subject; | ||
LinkInfoConverter.addLinksToDocument(document, resource, serviceClass); | ||
} else if (subject instanceof PublishedInfo) { | ||
PublishedInfo layer = (PublishedInfo) subject; | ||
LinkInfoConverter.addLinksToDocument(document, layer, serviceClass); | ||
} | ||
} | ||
|
||
private static Class<?> getServiceClass(Request dr) { | ||
Service service = dr.getOperation().getService(); | ||
return service != null ? service.getService().getClass() : null; | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
src/community/ogcapi/ogcapi-core/src/main/java/org/geoserver/ogcapi/LinkInfoConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* (c) 2023 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.ogcapi; | ||
|
||
import static org.geoserver.ogcapi.LinkInfo.LINKS_METADATA_KEY; | ||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
import org.geoserver.catalog.LayerGroupInfo; | ||
import org.geoserver.catalog.LayerInfo; | ||
import org.geoserver.catalog.PublishedInfo; | ||
import org.geoserver.catalog.ResourceInfo; | ||
import org.geoserver.config.SettingsInfo; | ||
|
||
/** Helper class to convert {@link LinkInfo} to {@link Link} and add them to a document */ | ||
public class LinkInfoConverter { | ||
|
||
/** | ||
* Adds links found under the {@link LinkInfo#LINKS_METADATA_KEY} metadata key to the document, | ||
* eventually filtering them by service class | ||
*/ | ||
public static void addLinksToDocument( | ||
AbstractDocument document, PublishedInfo publishedInfo, Class serviceClass) { | ||
if (publishedInfo instanceof LayerInfo) { | ||
addLinksToDocument(document, ((LayerInfo) publishedInfo).getResource(), serviceClass); | ||
} | ||
} | ||
|
||
/** | ||
* Adds links found under the {@link LinkInfo#LINKS_METADATA_KEY} metadata key to the document, | ||
* eventually filtering them by service class | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
public static void addLinksToDocument( | ||
AbstractDocument document, LayerGroupInfo group, Class serviceClass) { | ||
List<LinkInfo> links = group.getMetadata().get(LINKS_METADATA_KEY, List.class); | ||
addLinksToDocument(document, serviceClass, links); | ||
} | ||
|
||
/** | ||
* Adds links found under the {@link LinkInfo#LINKS_METADATA_KEY} metadata key to the document, | ||
* eventually filtering them by service class | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
public static void addLinksToDocument( | ||
AbstractDocument document, ResourceInfo resource, Class serviceClass) { | ||
List<LinkInfo> links = resource.getMetadata().get(LINKS_METADATA_KEY, List.class); | ||
addLinksToDocument(document, serviceClass, links); | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
public static void addLinksToDocument( | ||
AbstractDocument document, SettingsInfo settings, Class<?> serviceClass) { | ||
List<LinkInfo> links = settings.getMetadata().get(LINKS_METADATA_KEY, List.class); | ||
addLinksToDocument(document, serviceClass, links); | ||
} | ||
|
||
private static void addLinksToDocument( | ||
AbstractDocument document, Class serviceClass, List<LinkInfo> links) { | ||
if (links != null) { | ||
APIService annotation = APIDispatcher.getApiServiceAnnotation(serviceClass); | ||
String service = Optional.ofNullable(annotation).map(s -> s.service()).orElse(null); | ||
links.stream() | ||
.filter(l -> serviceMatch(l, service)) | ||
.forEach(l -> addLinkToDocument(l, document)); | ||
} | ||
} | ||
|
||
private static void addLinkToDocument(LinkInfo l, AbstractDocument document) { | ||
document.addLink(toLink(l)); | ||
} | ||
|
||
/** Converts a LinkInfo to a Link */ | ||
public static Link toLink(LinkInfo l) { | ||
return new Link(l.getHref(), l.getRel(), l.getType(), l.getTitle()); | ||
} | ||
|
||
private static boolean serviceMatch(LinkInfo l, String service) { | ||
return l.getService() == null || Objects.equals(l.getService(), service); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
...api/ogcapi-core/src/main/java/org/geoserver/ogcapi/OGCAPIXStreamPersisterInitializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* (c) 2023 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.ogcapi; | ||
|
||
import com.thoughtworks.xstream.XStream; | ||
import java.util.List; | ||
import org.geoserver.config.util.XStreamPersister; | ||
import org.geoserver.config.util.XStreamPersisterInitializer; | ||
import org.geoserver.ogcapi.impl.LinkInfoImpl; | ||
import org.springframework.stereotype.Component; | ||
|
||
/** Configures XStream for OGC API configuration objects that will end up in the metadata maps. */ | ||
@Component | ||
public class OGCAPIXStreamPersisterInitializer implements XStreamPersisterInitializer { | ||
@Override | ||
public void init(XStreamPersister persister) { | ||
XStream xs = persister.getXStream(); | ||
xs.alias("link", LinkInfo.class); | ||
xs.addDefaultImplementation(LinkInfoImpl.class, LinkInfo.class); | ||
persister.registerBreifMapComplexType("list", List.class); | ||
xs.allowTypes(new Class[] {LinkInfo.class}); | ||
} | ||
} |
Oops, something went wrong.