Skip to content

Commit

Permalink
Adding extra resources and links to the vector tiles extension for WFS3
Browse files Browse the repository at this point in the history
  • Loading branch information
aaime committed Oct 12, 2018
1 parent 9994bf5 commit db632a9
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public LandingPageDocument landingPage(LandingPageRequest request) {

@Override
public CollectionsDocument collections(CollectionsRequest request) {
return new CollectionsDocument(request, geoServer);
return new CollectionsDocument(request, geoServer, extensions);
}

@Override
Expand All @@ -100,8 +100,10 @@ public CollectionDocument collection(CollectionRequest request) {
"typeName");
} else {
CollectionsDocument collections =
new CollectionsDocument(request, geoServer, featureType);
return collections.getCollections().next();
new CollectionsDocument(request, geoServer, featureType, extensions);
CollectionDocument collection = collections.getCollections().next();

return collection;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import java.io.InputStream;
import java.util.Collections;
import java.util.Map;
import org.geoserver.ows.URLMangler;
import org.geoserver.ows.util.ResponseUtils;
import org.geoserver.platform.ServiceException;
import org.geoserver.util.IOUtils;
import org.geoserver.wfs3.response.CollectionDocument;
import org.geoserver.wfs3.response.Link;
import org.geoserver.wms.mapbox.MapBoxTileBuilderFactory;

/** WFS3 extension adding support for the vector tiling OpenAPI paths */
public class VectorTilesExtension implements WFS3Extension {
Expand Down Expand Up @@ -57,6 +63,51 @@ public void extendAPI(OpenAPI api) {
apiComponents.getParameters().putAll(tileParameters);
}

@Override
public void extendCollection(CollectionDocument collection, BaseRequest request) {
String collectionId = collection.getName();

// links
String baseUrl = request.getBaseUrl();
String tilingSchemeURL =
ResponseUtils.buildURL(
baseUrl,
"wfs3/collections/" + collectionId + "/tiles/{tilingSchemeId}",
Collections.emptyMap(),
URLMangler.URLType.SERVICE);
collection
.getLinks()
.add(
new Link(
tilingSchemeURL,
"tilingScheme",
MapBoxTileBuilderFactory.MIME_TYPE,
collectionId
+ " associated tiling schemes. he link is a URI template \"\n"
+ " + \"where {tilingSchemeId} is one of the schemes listed in the 'tilingSchemes' resource",
"items"));

String tilesURL =
ResponseUtils.buildURL(
baseUrl,
"wfs3/collections/"
+ collectionId
+ "/tiles/{tilingSchemeId}/{level}/{row}/{col}",
Collections.emptyMap(),
URLMangler.URLType.SERVICE);
collection
.getLinks()
.add(
new Link(
tilesURL,
"tiles",
MapBoxTileBuilderFactory.MIME_TYPE,
collectionId
+ " as Mapbox vector tiles. The link is a URI template "
+ "where {tilingSchemeId} is one of the schemes listed in the 'tilingSchemes' resource, and {level}/{row}/{col} the tile based on the tiling scheme.",
"items"));
}

/**
* Reads the template to customize (each time, as the object tree is not thread safe nor
* cloneable not serializable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package org.geoserver.wfs3;

import io.swagger.v3.oas.models.OpenAPI;
import org.geoserver.wfs3.response.CollectionDocument;

/** Plugins can implement this interface to declare API extensions to */
public interface WFS3Extension {
Expand All @@ -16,5 +17,12 @@ public interface WFS3Extension {
*/
void extendAPI(OpenAPI api);

/**
* Extend the collection document
*
* @param collection
*/
void extendCollection(CollectionDocument collection, BaseRequest request);

/** Here we'll eventually have the method to actually run the extension calls */
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,14 @@ private RequestWrapper(HttpServletRequest wrapped) {
} else if (pathInfo.matches("/tilingSchemes/([^/]+)/?")) {
request = "describeTilingScheme";
Matcher matcher = Pattern.compile("/tilingSchemes/([^/]+)/?").matcher(pathInfo);
boolean matches = matcher.matches();
matcher.matches();
this.tilingScheme = matcher.group(1);
} else if (pathInfo.matches("/collections/([^/]+)/tiles/([^/]+)/?")) {
request = "describeTilingScheme";
Matcher matcher =
Pattern.compile("/collections/([^/]+)/tiles/([^/]+)/?").matcher(pathInfo);
matcher.matches();
this.tilingScheme = matcher.group(2);
} else if (pathInfo.startsWith("/collections")) {
List<Function<String, Boolean>> matchers = new ArrayList<>();
matchers.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.geoserver.wfs3.BaseRequest;
import org.geoserver.wfs3.DefaultWebFeatureService30;
import org.geoserver.wfs3.NCNameResourceCodec;
import org.geoserver.wfs3.WFS3Extension;
import org.opengis.filter.Filter;

/**
Expand All @@ -32,16 +33,22 @@ public class CollectionsDocument extends AbstractDocument {
private final BaseRequest request;
private final FeatureTypeInfo featureType;
private final GeoServer geoServer;
private final List<WFS3Extension> extensions;

public CollectionsDocument(BaseRequest request, GeoServer geoServer) {
this(request, geoServer, null);
public CollectionsDocument(
BaseRequest request, GeoServer geoServer, List<WFS3Extension> extensions) {
this(request, geoServer, null, extensions);
}

public CollectionsDocument(
BaseRequest request, GeoServer geoServer, FeatureTypeInfo featureType) {
BaseRequest request,
GeoServer geoServer,
FeatureTypeInfo featureType,
List<WFS3Extension> extensions) {
this.geoServer = geoServer;
this.request = request;
this.featureType = featureType;
this.extensions = extensions;

// build the links
List<String> formats =
Expand Down Expand Up @@ -104,6 +111,11 @@ public boolean hasNext() {
FeatureTypeInfo featureType = featureTypes.next();
CollectionDocument collection =
new CollectionDocument(geoServer, request, featureType);
if (extensions != null) {
for (WFS3Extension extension : extensions) {
extension.extendCollection(collection, request);
}
}

next = collection;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.io.IOException;
import java.io.OutputStream;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import no.ecc.vectortile.VectorTileEncoder;
import no.ecc.vectortile.VectorTileEncoderNoClip;
Expand Down Expand Up @@ -47,7 +48,14 @@ public class GetFeatureMapboxOutputFormat extends WFSGetFeatureOutputFormat {
private DefaultGridsets gridSets;

public GetFeatureMapboxOutputFormat(GeoServer gs) {
super(gs, MapBoxTileBuilderFactory.MIME_TYPE);
super(
gs,
new LinkedHashSet<String>() {
{
add(MapBoxTileBuilderFactory.MIME_TYPE);
add(MapBoxTileBuilderFactory.LEGACY_MIME_TYPE);
}
});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
format.wfs.application/geo+json=GeoJSON (RFC compliant)
format.wfs.text/html=HTML
format.wfs.application/gml+xml;version=3.2;profile=http://www.opengis.net/def/profile/ogc/2.0/gml-sf0=GML3.2
format.wfs.application/x-protobuf;type=mapbox-vector=MapBox vector tile
format.wfs.application/gml+xml;version\=3.2;profile\=http\://www.opengis.net/def/profile/ogc/2.0/gml-sf0=GML3.2 (WFS3)
format.wfs.application/x-protobuf;type\=mapbox-vector=MapBox vector tile
format.wfs.application/vnd.mapbox-vector-tile=mapbox-vector=MapBox vector tile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,28 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/exception"
"/collections/{collectionId}/tiles/{tilingSchemeId}":
get:
tags:
- Tiles
summary: retrieve a tiling scheme for the specified collection and id
operationId: getCollectionTilingScheme
parameters:
- $ref: "#/components/parameters/tilingSchemeId"
- $ref: "#/components/parameters/tilingSchemeFormat"
responses:
'200':
description: A tiling scheme.
content:
application/json:
schema:
$ref: "#/components/schemas/tilingScheme"
default:
description: An error occured.
content:
application/json:
schema:
$ref: "#/components/schemas/exception"
"/collections/{collectionId}/tiles/{tilingSchemeId}/{zoomLevel}/{row}/{column}":
get:
tags:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
*/
package org.geoserver.wfs3;

import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;

import com.jayway.jsonpath.DocumentContext;
import java.util.List;
Expand Down Expand Up @@ -43,8 +45,9 @@ public void testCollectionsJson() throws Exception {
// check we have the expected number of links and they all use the right "rel" relation
List<String> formats =
DefaultWebFeatureService30.getAvailableFormats(FeatureCollectionResponse.class);
assertEquals(
formats.size(), (int) json.read("collections[0].links.length()", Integer.class));
assertThat(
formats.size(),
lessThanOrEqualTo((int) json.read("collections[0].links.length()", Integer.class)));
for (String format : formats) {
// check title and rel.
List items = json.read("collections[0].links[?(@.type=='" + format + "')]", List.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import org.geoserver.data.test.MockData;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -46,40 +47,62 @@ public void testTilingSchemesResponse() throws Exception {
@Test
public void testTilingSchemeDescriptionGoogleMapsCompatible() throws Exception {
DocumentContext jsonDoc = getAsJSONPath("wfs3/tilingSchemes/GoogleMapsCompatible", 200);
assertEquals(
checkGoogleMapsCompatible(
jsonDoc,
"http://www.opengis.net/def/crs/EPSG/0/3857",
jsonDoc.read("boundingBox.crs", String.class));
assertEquals(
"-20037508.340000 -20037508.340000",
jsonDoc.read("boundingBox.lowerCorner", String.class));
assertEquals(
"http://www.opengis.net/def/wkss/OGC/1.0/GoogleMapsCompatible",
jsonDoc.read("wellKnownScaleSet", String.class));
assertEquals(
559082263.9508929d,
jsonDoc.read("tileMatrix[0].scaleDenominator", Double.class),
0.001d);
assertEquals(
new Integer(1073741824), jsonDoc.read("tileMatrix[30].matrixWidth", Integer.class));
0.001d,
1073741824,
"tileMatrix[30].matrixWidth");
}

@Test
public void testTilingSchemeDescriptionGoogleMapsCompatibleOnCollections() throws Exception {
String roadSegments = getEncodedName(MockData.ROAD_SEGMENTS);
DocumentContext jsonDoc =
getAsJSONPath(
"wfs3/collections/" + roadSegments + "/tiles/GoogleMapsCompatible", 200);
checkGoogleMapsCompatible(
jsonDoc,
"http://www.opengis.net/def/crs/EPSG/0/3857",
"-20037508.340000 -20037508.340000",
"http://www.opengis.net/def/wkss/OGC/1.0/GoogleMapsCompatible",
559082263.9508929d,
0.001d,
1073741824,
"tileMatrix[30].matrixWidth");
}

public void checkGoogleMapsCompatible(
DocumentContext jsonDoc,
String s,
String s2,
String s3,
double v,
double v2,
int i,
String s4) {
assertEquals(s, jsonDoc.read("boundingBox.crs", String.class));
assertEquals(s2, jsonDoc.read("boundingBox.lowerCorner", String.class));
assertEquals(s3, jsonDoc.read("wellKnownScaleSet", String.class));
assertEquals(v, jsonDoc.read("tileMatrix[0].scaleDenominator", Double.class), v2);
assertEquals(new Integer(i), jsonDoc.read(s4, Integer.class));
}

@Test
public void testTilingSchemeDescriptionGlobalCRS84Geometric() throws Exception {
DocumentContext jsonDoc = getAsJSONPath("wfs3/tilingSchemes/GlobalCRS84Geometric", 200);
assertEquals(
checkGoogleMapsCompatible(
jsonDoc,
"http://www.opengis.net/def/crs/EPSG/0/4326",
jsonDoc.read("boundingBox.crs", String.class));
assertEquals(
"-180.000000 -90.000000", jsonDoc.read("boundingBox.lowerCorner", String.class));
assertEquals(
"-180.000000 -90.000000",
"http://www.opengis.net/def/wkss/OGC/1.0/GlobalCRS84Geometric",
jsonDoc.read("wellKnownScaleSet", String.class));
assertEquals(
2.795411320143589E8d,
jsonDoc.read("tileMatrix[0].scaleDenominator", Double.class),
0.000000000000001E8d);
assertEquals(
new Integer(4194304), jsonDoc.read("tileMatrix[21].matrixWidth", Integer.class));
0.000000000000001E8d,
4194304,
"tileMatrix[21].matrixWidth");
assertEquals(
"90.000000 -180.000000",
jsonDoc.read("tileMatrix[21].topLeftCorner", String.class));
Expand Down

0 comments on commit db632a9

Please sign in to comment.