Skip to content

Commit 2237199

Browse files
dromagnoliaaime
authored andcommitted
TileJSON url: Supporting format parameter
1 parent 34b2016 commit 2237199

6 files changed

Lines changed: 119 additions & 41 deletions

File tree

geowebcache/wmts/src/main/java/org/geowebcache/service/wmts/WMTSGetCapabilities.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.geowebcache.layer.TileLayerDispatcher;
5151
import org.geowebcache.layer.meta.LayerMetaInformation;
5252
import org.geowebcache.layer.meta.MetadataURL;
53+
import org.geowebcache.mime.ApplicationMime;
5354
import org.geowebcache.stats.RuntimeStats;
5455
import org.geowebcache.util.ServletUtils;
5556
import org.geowebcache.util.URLMangler;
@@ -749,11 +750,19 @@ private void layerResourceUrls(
749750
layerResourceUrlsGen(xml, format, "FeatureInfo", template);
750751
}
751752
if (layer instanceof TileJSONProvider) {
753+
List<String> formatExtensions = WMTSUtils.getLayerFormatsExtensions(layer);
752754
TileJSONProvider provider = (TileJSONProvider) layer;
753-
String format = "json";
755+
String outputFormat = ApplicationMime.json.getFormat();
754756
if (provider.supportsTileJSON()) {
755-
String template = baseTemplate + "/{style}/tilejson?format=" + format;
756-
layerResourceUrlsGen(xml, format, "TileJSON", template);
757+
for (String tileJsonFormat : formatExtensions) {
758+
String template =
759+
baseTemplate
760+
+ "/{style}/tilejson/"
761+
+ tileJsonFormat
762+
+ "?format="
763+
+ outputFormat;
764+
layerResourceUrlsGen(xml, outputFormat, "TileJSON", template);
765+
}
757766
}
758767
}
759768
}

geowebcache/wmts/src/main/java/org/geowebcache/service/wmts/WMTSService.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ enum RestRequest {
9090
FEATUREINFO(buildRestPattern(7, false), RequestType.FEATUREINFO, false),
9191
// "/{layer}/{style}/{tileMatrixSet}/{tileMatrix}/{tileRow}/{tileCol}/{j}/{i}",
9292
FEATUREINFO_STYLE(buildRestPattern(8, true), RequestType.FEATUREINFO, true),
93-
// "/{layer}/tilejson"
94-
TILEJSON(buildRestPattern(2, false), RequestType.TILEJSON, false),
95-
// "/{layer}/{style}/tilejson"
96-
TILEJSON_STYLE(buildRestPattern(3, true), RequestType.TILEJSON, true);
93+
// "/{layer}/tilejson/{tileformat}"
94+
TILEJSON(buildRestPattern(3, false), RequestType.TILEJSON, false),
95+
// "/{layer}/{style}/tilejson/{tileformat}"
96+
TILEJSON_STYLE(buildRestPattern(4, true), RequestType.TILEJSON, true);
9797

9898
Pattern pattern;
9999
RequestType type;
@@ -143,6 +143,8 @@ public Map<String, String> toKVP(HttpServletRequest request) {
143143
values.put("j", matcher.group(i++));
144144
values.put("i", matcher.group(i++));
145145
}
146+
} else {
147+
values.put("tileformat", matcher.group(++i));
146148
}
147149
if (request.getParameter("format") instanceof String) {
148150
if (isFeatureInfo) {
@@ -238,6 +240,7 @@ public Conveyor getConveyor(HttpServletRequest request, HttpServletResponse resp
238240
"tilematrix",
239241
"tilerow",
240242
"tilecol",
243+
"tileformat",
241244
"i",
242245
"j"
243246
};
@@ -347,6 +350,8 @@ public Conveyor getKvpConveyor(
347350
return tile;
348351
} else if (req.equals(GET_TILEJSON)) {
349352
ConveyorTile tile = new ConveyorTile(sb, values.get("layer"), request, response);
353+
String format = values.get("tileformat");
354+
tile.setMimeType(MimeType.createFromExtension(format));
350355
String hint = req;
351356
// I Will need the style when setting up the TileJSON tiles url
352357
String style = values.get("style");

geowebcache/wmts/src/main/java/org/geowebcache/service/wmts/WMTSTileJSON.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.geowebcache.layer.TileJSONProvider;
3232
import org.geowebcache.layer.TileLayer;
3333
import org.geowebcache.layer.meta.TileJSON;
34+
import org.geowebcache.layer.meta.VectorLayerMetadata;
3435
import org.geowebcache.mime.ApplicationMime;
3536
import org.geowebcache.mime.MimeType;
3637
import org.geowebcache.util.URLMangler;
@@ -60,11 +61,15 @@ public void writeResponse(TileLayer layer) {
6061
TileJSON json = provider.getTileJSON();
6162

6263
List<String> urls = new ArrayList<>();
63-
for (MimeType mimeType : layer.getMimeTypes()) {
64-
Set<String> gridSubSets = layer.getGridSubsets();
65-
for (String gridSubSet : gridSubSets) {
66-
addTileUrl(layer, gridSubSet, mimeType, urls);
67-
}
64+
MimeType mimeType = convTile.getMimeType();
65+
Set<String> gridSubSets = layer.getGridSubsets();
66+
for (String gridSubSet : gridSubSets) {
67+
addTileUrl(layer, gridSubSet, mimeType, urls);
68+
}
69+
List<VectorLayerMetadata> vectorLayers = json.getLayers();
70+
if (vectorLayers != null && !vectorLayers.isEmpty() && !mimeType.isVector()) {
71+
// Removing vectorLayers info when requesting a raster format
72+
json.setLayers(null);
6873
}
6974

7075
String[] tileUrls = urls.toArray(new String[urls.size()]);

geowebcache/wmts/src/main/java/org/geowebcache/service/wmts/WMTSUtils.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ protected static List<String> getLayerFormats(TileLayer layer) throws IOExceptio
3030
return layer.getMimeTypes().stream().map(MimeType::getFormat).collect(Collectors.toList());
3131
}
3232

33+
protected static List<String> getLayerFormatsExtensions(TileLayer layer) throws IOException {
34+
return layer.getMimeTypes()
35+
.stream()
36+
.map(MimeType::getFileExtension)
37+
.collect(Collectors.toList());
38+
}
39+
3340
public static List<String> getInfoFormats(TileLayer layer) {
3441
return layer.getInfoMimeTypes()
3542
.stream()

geowebcache/wmts/src/test/java/org/geowebcache/service/wmts/WMTSRestTest.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists;
1919
import static org.junit.Assert.assertArrayEquals;
2020
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertFalse;
2122
import static org.junit.Assert.assertTrue;
2223
import static org.mockito.ArgumentMatchers.any;
2324
import static org.mockito.ArgumentMatchers.anyInt;
@@ -61,6 +62,8 @@
6162
import org.geowebcache.layer.TileLayer;
6263
import org.geowebcache.layer.TileLayerDispatcher;
6364
import org.geowebcache.layer.meta.TileJSON;
65+
import org.geowebcache.layer.meta.VectorLayerMetadata;
66+
import org.geowebcache.mime.ApplicationMime;
6467
import org.geowebcache.mime.MimeType;
6568
import org.geowebcache.service.OWSException;
6669
import org.geowebcache.stats.RuntimeStats;
@@ -161,11 +164,11 @@ public void testGetTileWithStyle() throws Exception {
161164

162165
@Test
163166
public void testGetTileJSONWithStyle() throws Exception {
164-
addTileLayerJsonMock();
167+
addTileLayerJsonMock("image/png");
165168

166169
MockHttpServletRequest req = new MockHttpServletRequest();
167-
req.setPathInfo("geowebcache/service/wmts/rest/mockLayerTileJSON/style-a/tilejson");
168-
req.addParameter("format", "json");
170+
req.setPathInfo("geowebcache/service/wmts/rest/mockLayerTileJSON/style-a/tilejson/png");
171+
req.addParameter("format", "application/json");
169172
MockHttpServletResponse resp = dispatch(req);
170173

171174
assertEquals(200, resp.getStatus());
@@ -175,15 +178,17 @@ public void testGetTileJSONWithStyle() throws Exception {
175178
assertTrue(
176179
content.contains(
177180
"\"tiles\":[\"http://localhost/service/wmts/rest/mockLayerTileJSON/style-a/EPSG:900913/EPSG:900913:{z}/{y}/{x}?format=image/png\"]"));
181+
assertFalse(content.contains("vector_layers"));
178182
}
179183

180184
@Test
181185
public void testGetTileJSONWithoutStyle() throws Exception {
182-
addTileLayerJsonMock();
186+
String mvt = ApplicationMime.mapboxVector.getFormat();
187+
addTileLayerJsonMock(mvt);
183188

184189
MockHttpServletRequest req = new MockHttpServletRequest();
185-
req.setPathInfo("geowebcache/service/wmts/rest/mockLayerTileJSON/tilejson");
186-
req.addParameter("format", "json");
190+
req.setPathInfo("geowebcache/service/wmts/rest/mockLayerTileJSON/tilejson/pbf");
191+
req.addParameter("format", ApplicationMime.json.getFormat());
187192
MockHttpServletResponse resp = dispatch(req);
188193

189194
assertEquals(200, resp.getStatus());
@@ -192,13 +197,15 @@ public void testGetTileJSONWithoutStyle() throws Exception {
192197
// Checking the response contains a tileUrl without the style
193198
assertTrue(
194199
content.contains(
195-
"\"tiles\":[\"http://localhost/service/wmts/rest/mockLayerTileJSON/EPSG:900913/EPSG:900913:{z}/{y}/{x}?format=image/png\"]"));
200+
"\"tiles\":[\"http://localhost/service/wmts/rest/mockLayerTileJSON/EPSG:900913/EPSG:900913:{z}/{y}/{x}?format="
201+
+ mvt
202+
+ "\"]"));
203+
assertTrue(content.contains("vector_layers"));
196204
}
197205

198-
private void addTileLayerJsonMock() throws GeoWebCacheException {
199-
200-
final MimeType mimeType1 = MimeType.createFromFormat("image/png");
206+
private void addTileLayerJsonMock(String mimeType) throws GeoWebCacheException {
201207

208+
final MimeType mimeType1 = MimeType.createFromFormat(mimeType);
202209
String layerNameJson = "mockLayerTileJSON";
203210
TileLayer tileLayerJson =
204211
mock(TileLayer.class, withSettings().extraInterfaces(TileJSONProvider.class));
@@ -209,7 +216,11 @@ private void addTileLayerJsonMock() throws GeoWebCacheException {
209216
when(tileLayerJson.getMimeTypes()).thenReturn(Arrays.asList(mimeType1));
210217
TileJSONProvider tileJSONProvider = (TileJSONProvider) tileLayerJson;
211218
when(tileJSONProvider.supportsTileJSON()).thenReturn(true);
212-
when(tileJSONProvider.getTileJSON()).thenReturn(new TileJSON());
219+
TileJSON json = new TileJSON();
220+
VectorLayerMetadata metadata = new VectorLayerMetadata();
221+
metadata.setFields(Collections.singletonMap("FIELD", "TYPE"));
222+
json.setLayers(Collections.singletonList(metadata));
223+
when(tileJSONProvider.getTileJSON()).thenReturn(json);
213224

214225
String googleMercator = "EPSG:900913";
215226
when(tileLayerJson.getGridSubsets()).thenReturn(Collections.singleton(googleMercator));

geowebcache/wmts/src/test/java/org/geowebcache/service/wmts/WMTSServiceTest.java

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.io.File;
2828
import java.io.IOException;
2929
import java.io.OutputStream;
30+
import java.io.UnsupportedEncodingException;
3031
import java.net.URL;
3132
import java.util.ArrayList;
3233
import java.util.Arrays;
@@ -73,6 +74,10 @@
7374
import org.geowebcache.layer.TileLayer;
7475
import org.geowebcache.layer.TileLayerDispatcher;
7576
import org.geowebcache.layer.meta.MetadataURL;
77+
import org.geowebcache.layer.meta.TileJSON;
78+
import org.geowebcache.layer.meta.VectorLayerMetadata;
79+
import org.geowebcache.mime.ApplicationMime;
80+
import org.geowebcache.mime.ImageMime;
7681
import org.geowebcache.mime.MimeType;
7782
import org.geowebcache.mime.XMLMime;
7883
import org.geowebcache.service.OWSException;
@@ -236,15 +241,11 @@ private TileLayer mockTileLayerWithJSONSupport(String layerName, List<String> gr
236241
when(tileLayer.isEnabled()).thenReturn(true);
237242
when(tileLayer.isAdvertised()).thenReturn(true);
238243

239-
final MimeType mimeType1 = MimeType.createFromFormat("image/png");
240-
final MimeType mimeType2 = MimeType.createFromFormat("image/jpeg");
241-
when(tileLayer.getMimeTypes()).thenReturn(Arrays.asList(mimeType1, mimeType2));
244+
final MimeType mimeType1 = ImageMime.png;
245+
final MimeType mimeType2 = ApplicationMime.mapboxVector;
242246

243-
final MimeType infoMimeType1 = MimeType.createFromFormat("text/plain");
244-
final MimeType infoMimeType2 = MimeType.createFromFormat("text/html");
245-
final MimeType infoMimeType3 = MimeType.createFromFormat("application/vnd.ogc.gml");
246-
when(tileLayer.getInfoMimeTypes())
247-
.thenReturn(Arrays.asList(infoMimeType1, infoMimeType2, infoMimeType3));
247+
// Mocking a tile layer supporting both png (raster) and mvt (vector)
248+
when(tileLayer.getMimeTypes()).thenReturn(Arrays.asList(mimeType1, mimeType2));
248249

249250
Map<String, GridSubset> subsets = new HashMap<>();
250251
Map<SRS, List<GridSubset>> bySrs = new HashMap<>();
@@ -276,6 +277,11 @@ private TileLayer mockTileLayerWithJSONSupport(String layerName, List<String> gr
276277
when(tileLayer.getGridSubsets()).thenReturn(subsets.keySet());
277278
TileJSONProvider tileJSONProvider = (TileJSONProvider) tileLayer;
278279
when(tileJSONProvider.supportsTileJSON()).thenReturn(true);
280+
TileJSON json = new TileJSON();
281+
VectorLayerMetadata metadata = new VectorLayerMetadata();
282+
metadata.setFields(Collections.singletonMap("FIELD", "TYPE"));
283+
json.setLayers(Collections.singletonList(metadata));
284+
when(tileJSONProvider.getTileJSON()).thenReturn(json);
279285

280286
// sanity check
281287
for (String gsetName : gridSetNames) {
@@ -1489,7 +1495,7 @@ public void testGetFeatureSecure() throws Exception {
14891495
}
14901496

14911497
@Test
1492-
public void testGetCapWithTileJSON() throws Exception {
1498+
public void testGetCapWithTileJSONDifferentUrls() throws Exception {
14931499

14941500
GeoWebCacheDispatcher gwcd = mock(GeoWebCacheDispatcher.class);
14951501
when(gwcd.getServletPrefix()).thenReturn(null);
@@ -1507,12 +1513,9 @@ public void testGetCapWithTileJSON() throws Exception {
15071513
when(req.getCharacterEncoding()).thenReturn("UTF-8");
15081514
when(req.getParameterMap()).thenReturn(kvp);
15091515

1510-
{
1511-
List<String> gridSetNames = Arrays.asList("EPSG:900913");
1512-
1513-
TileLayer tileLayer = mockTileLayerWithJSONSupport("mockLayer", gridSetNames);
1514-
when(tld.getLayerList()).thenReturn(Collections.singletonList(tileLayer));
1515-
}
1516+
List<String> gridSetNames = Arrays.asList("EPSG:900913");
1517+
TileLayer tileLayer = mockTileLayerWithJSONSupport("mockLayer", gridSetNames);
1518+
when(tld.getLayerList()).thenReturn(Collections.singletonList(tileLayer));
15161519

15171520
Conveyor conv = service.getConveyor(req, resp);
15181521
assertNotNull(conv);
@@ -1535,7 +1538,6 @@ public void testGetCapWithTileJSON() throws Exception {
15351538
"inline;filename=wmts-getcapabilities.xml", resp.getHeader("content-disposition"));
15361539
String result = resp.getContentAsString();
15371540

1538-
// Ensure the advertised Layer is contained and the unadvertised not
15391541
assertTrue(result.contains("mockLayer"));
15401542

15411543
Document doc = XMLUnit.buildTestDocument(result);
@@ -1557,10 +1559,49 @@ public void testGetCapWithTileJSON() throws Exception {
15571559
"1",
15581560
xpath.evaluate(
15591561
"count(//wmts:Contents/wmts:Layer/wmts:ResourceURL[@resourceType='TileJSON']"
1560-
+ "[@format='json']"
1562+
+ "[@format='application/json']"
15611563
+ "[@template='http://localhost:8080/geowebcache"
15621564
+ WMTSService.REST_PATH
1563-
+ "/mockLayer/{style}/tilejson?format=json'])",
1565+
+ "/mockLayer/{style}/tilejson/png?format=application/json'])",
15641566
doc));
1567+
1568+
assertEquals(
1569+
"1",
1570+
xpath.evaluate(
1571+
"count(//wmts:Contents/wmts:Layer/wmts:ResourceURL[@resourceType='TileJSON']"
1572+
+ "[@format='application/json']"
1573+
+ "[@template='http://localhost:8080/geowebcache"
1574+
+ WMTSService.REST_PATH
1575+
+ "/mockLayer/{style}/tilejson/pbf?format=application/json'])",
1576+
doc));
1577+
1578+
// Sending the above 2 getTileJson urls
1579+
// Vector tilejson
1580+
kvp.put("request", new String[] {"GetTileJSON"});
1581+
kvp.put("tileformat", new String[] {"pbf"});
1582+
when(req.getParameterMap()).thenReturn(kvp);
1583+
conv = service.getConveyor(req, resp);
1584+
result = writeTileJsonResponse((ConveyorTile) conv, tileLayer, resp);
1585+
assertTrue(
1586+
result.contains(
1587+
"\"tiles\":[\"http://localhost/service/wmts/rest/mockLayer/EPSG:900913/EPSG:900913:{z}/{y}/{x}?format=application/vnd.mapbox-vector-tile\"]"));
1588+
1589+
// Raster tilejson
1590+
kvp.put("tileformat", new String[] {"png"});
1591+
when(req.getParameterMap()).thenReturn(kvp);
1592+
conv = service.getConveyor(req, resp);
1593+
result = writeTileJsonResponse((ConveyorTile) conv, tileLayer, resp);
1594+
assertTrue(
1595+
result.contains(
1596+
"\"tiles\":[\"http://localhost/service/wmts/rest/mockLayer/EPSG:900913/EPSG:900913:{z}/{y}/{x}?format=image/png\"]"));
1597+
}
1598+
1599+
private String writeTileJsonResponse(
1600+
ConveyorTile conv, TileLayer tileLayer, MockHttpServletResponse resp)
1601+
throws UnsupportedEncodingException {
1602+
WMTSTileJSON tileJSON =
1603+
new WMTSTileJSON(conv, "http://localhost", "", null, new NullURLMangler());
1604+
tileJSON.writeResponse(tileLayer);
1605+
return resp.getContentAsString();
15651606
}
15661607
}

0 commit comments

Comments
 (0)