Skip to content

Commit

Permalink
started on layer preview format link
Browse files Browse the repository at this point in the history
tests part one

started on documentation

more documentation

cleanup and test fixes

clean

html output was missing feature and tiles and multi

more test fixes

PR responses

cleanup

added features tiles to alternate links

style and alternate style

started on grid management

Added bbox to gridloc

starting

featurebuilder handle multiple layers

feature support from with multiple

Got multi working

started on tile creation

started on matching tileset to tiles

tile creation organized and working

started on raster tile test

working on test

got best zoom function working

fixed PMD issue

started on wmts links

raster tile cache with test passing

added getfeatureinfo layergroup test
  • Loading branch information
turingtestfail committed Feb 24, 2025
1 parent d08472b commit 35bdbb3
Show file tree
Hide file tree
Showing 11 changed files with 779 additions and 231 deletions.
7 changes: 6 additions & 1 deletion doc/en/user/source/extensions/mapml/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Using tiles to access the layer can increase the performance of your web map. Th

**Use Tiles**
If you check the "Use Tiles" checkbox and select the MapML format on the Layer Preview page, the output will use tile-based references to the WMS server. For example, if your layer or layer group has a cached tile layer configured, GeoServer will generate tile references (e.g., <map-link rel="tile" tref="...request=GetTile...">) instead of WMS GetMap URLs (e.g., <map-link rel="image" tref="...request=GetMap...">).
If you check the "Use Tiles" checkbox and select the MapML format on the Layer Preview page, the output will use tile-based references to the WMS server. For example, if your layer or layer group has a cached tile layer configured, GeoServer will generate tile references (e.g., <map-link rel="tile" tref="...request=GetTile...">) instead of WMS GetMap URLs (e.g., <map-link rel="image" tref="...request=GetMap...">).

Client Requests
^^^^^^^^^^^^^^^
Expand All @@ -134,6 +135,7 @@ MapML supports the serving of vector feature representations of the data. This

**Use Features**
If the "Use Features" checkbox is checked, the output MapML on the Layer Preview page will define a feature-based reference to the WMS server. When making WMS request add `mapmlusefeatures:true` to the FORMAT_OPTIONS parameter. Otherwise, an image-based reference will be used. Note that this option is only available for vector source data. MapML <map-extent> element with a feature link:
If the "Use Features" checkbox is checked, the output MapML on the Layer Preview page will define a feature-based reference to the WMS server. When making WMS request add `mapmlusefeatures:true` to the FORMAT_OPTIONS parameter. Otherwise, an image-based reference will be used. Note that this option is only available for vector source data. MapML <map-extent> element with a feature link:

.. code-block:: html

Expand All @@ -148,6 +150,7 @@ MapML supports the serving of vector feature representations of the data. This
<map-link tref="http://localhost:8080/geoserver/tiger/wms?format_options=mapmlfeatures:true&amp;request=GetMap&amp;crs=MapML:WGS84&amp;bbox={xmin},{ymin},{xmax},{ymax}&amp;format=text/mapml&amp;language=en&amp;version=1.3.0&amp;transparent=true&amp;service=WMS&amp;layers=poi&amp;width={w}&amp;styles=&amp;height={h}" rel="features"/>
</map-extent>

When both "Use Tiles" and "Use Features" are set in the FORMAT_OPTIONS parameter (`mapmlusefeatures:true;mapmlusetiles:true`), the MapML extension will request tiled maps in ``text/mapml`` format.
When both "Use Tiles" and "Use Features" are set in the FORMAT_OPTIONS parameter (`mapmlusefeatures:true;mapmlusetiles:true`), the MapML extension will request tiled maps in ``text/mapml`` format.
The contents of the tiles will be clipped to the requested area, and feature attributes will be skiipped, as the MapML client cannot leverage them for the moment.

Expand Down Expand Up @@ -247,10 +250,12 @@ WMS GetMap considerations

By default, each layer/style pair that is requested via the GetMap parameters is composed into a single <map-extent>...<map-link tref="...">...</map-extent> structure as exemplified above.

If the FORMAT_OPTION parameter of the WMS request is configured with `mapmlusemultiextents:true`, a request for multiple layers or layer groups in MapML format on the Layer Preview page will result in the serialization of a MapML document containing multiple <map-extent> elements. Each layer/style pair is represented by a <map-extent> element in the response. The <map-extent> elements are represented in the client viewer layer control settings as sub-layers, which turn on and off independently of each other, but which are controlled by the parent <map-layer> element's state (checked / unchecked, opacity etc) (right-click or Shift+F10 to obtain context menus):
If the FORMAT_OPTION parameter of the WMS request is configured with `mapmlusemultiextents:true`, a request for multiple layers or layer groups in MapML format on the Layer Preview page will result in the serialization of a MapML document containing multiple <map-extent> elements. Each layer/style pair is represented by a <map-extent> element in the response. The <map-extent> elements are represented in the client viewer layer control settings as sub-layers, which turn on and off independently of each other, but which are controlled by the parent <map-layer> element's state (checked / unchecked, opacity etc) (right-click or Shift+F10 to obtain context menus):

.. figure:: images/mapml_wms_multi_extent.png

With the FORMAT_OPTION parameter of the WMS request is configured with `mapmlusemultiextents:true`, if two or more layers are requested in MapML format via the GetMap 'layers' parameter, the MapML extension serialize both layer's <map-extent> based on the mapmlusefeatures and mapmlusetiles settings in the FORMAT_OPTION parameter of the WMS request. If these are not set in FORMAT_OPTION they will default to false. Note that there is currently no "Use Features" support available for layer groups.
With the FORMAT_OPTION parameter of the WMS request is configured with `mapmlusemultiextents:true`, if two or more layers are requested in MapML format via the GetMap 'layers' parameter, the MapML extension serialize both layer's <map-extent> based on the mapmlusefeatures and mapmlusetiles settings in the FORMAT_OPTION parameter of the WMS request. If these are not set in FORMAT_OPTION they will default to false. Note that there is currently no "Use Features" support available for layer groups.

Tile Caching
Expand All @@ -271,7 +276,7 @@ In order to properly pass the proper multi-extent, tiling, and feature parameter

The Default Value entry should look like this::

mapmlusemultiextents:true;mapmlusefeatures:false;mapmlusetiles:true
mapmlusemultiextents:true; mapmlusefeatures:false;mapmlusetiles:true

Here is an example regular expression that matches the MapML FORMAT_OPTIONS parameters in any order::

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.MetadataMap;
import org.geoserver.catalog.PublishedInfo;
import org.geoserver.catalog.PublishedType;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StoreInfo;
import org.geoserver.catalog.StyleInfo;
Expand Down Expand Up @@ -193,6 +192,8 @@ public MapMLDocumentBuilder(WMSMapContent mapContent, WMS wms, HttpServletReques
this.request = request;
this.mapContent = mapContent;
GetMapRequest getMapRequest = mapContent.getRequest();
this.useFeatures = useFeatures(getMapRequest);
this.useTiles = useTiles(getMapRequest);
String rawLayersCommaDL = getMapRequest.getRawKvp().get("layers");
this.layers = toRawLayers(rawLayersCommaDL);
this.stylesCommaDelimited = getMapRequest.getRawKvp().get("styles") != null
Expand All @@ -219,7 +220,7 @@ public MapMLDocumentBuilder(WMSMapContent mapContent, WMS wms, HttpServletReques
this.layerTitlesCommaDelimited = layers.stream().map(RawLayer::getTitle).collect(Collectors.joining(","));
}

private String extractCRS(Map<String, String> rawKvp) {
public static String extractCRS(Map<String, String> rawKvp) {
String srs = null;
String version = rawKvp.get("VERSION");
if ("1.3.0".equalsIgnoreCase(version)) {
Expand All @@ -238,7 +239,7 @@ private String extractCRS(Map<String, String> rawKvp) {
* @param bbox Envelope object
* @return comma delimited string
*/
private String toCommaDelimitedBbox(Envelope bbox) {
public static String toCommaDelimitedBbox(Envelope bbox) {
return bbox.getMinX() + "," + bbox.getMinY() + "," + bbox.getMaxX() + "," + bbox.getMaxY();
}

Expand All @@ -256,24 +257,37 @@ private List<RawLayer> toRawLayers(String rawLayersCommaDL) {
String[] rawLayersArray = rawLayersCommaDL.split(",");
for (String rawLayerTitle : rawLayersArray) {
LayerInfo layerInfo = wms.getLayerByName(rawLayerTitle);
RawLayer rawLayer = new RawLayer();

if (layerInfo == null) {
LayerGroupInfo layerGroupInfo = wms.getLayerGroupByName(rawLayerTitle);
rawLayer.setTitle(getTitle(layerGroupInfo, rawLayerTitle));
rawLayer.setName(layerGroupInfo.getName());
rawLayer.setLayerGroup(true);
rawLayer.setPublishedInfo(layerGroupInfo);
if (!useFeatures) {
RawLayer rawLayer = new RawLayer();
rawLayer.setTitle(getTitle(layerGroupInfo, rawLayerTitle));
rawLayer.setName(layerGroupInfo.getName());
rawLayer.setLayerGroup(true);
rawLayer.setPublishedInfo(layerGroupInfo);
rawLayers.add(rawLayer);
} else {
for (PublishedInfo publishedInfo : layerGroupInfo.getLayers()) {
addToRawLayers(rawLayers, publishedInfo.getTitle(), (LayerInfo) publishedInfo);
}
}
} else {
rawLayer.setTitle(getTitle(layerInfo, rawLayerTitle));
rawLayer.setLayerGroup(false);
rawLayer.setName(layerInfo.getName());
rawLayer.setPublishedInfo(layerInfo);
addToRawLayers(rawLayers, rawLayerTitle, layerInfo);
}
rawLayers.add(rawLayer);
}
return rawLayers;
}

private void addToRawLayers(List<RawLayer> rawLayers, String rawLayerTitle, LayerInfo layerInfo) {
RawLayer rawLayer = new RawLayer();
rawLayer.setTitle(getTitle(layerInfo, rawLayerTitle));
rawLayer.setLayerGroup(false);
rawLayer.setName(layerInfo.getName());
rawLayer.setPublishedInfo(layerInfo);
rawLayers.add(rawLayer);
}

/**
* Get the format from the GetMapRequest object
*
Expand Down Expand Up @@ -407,9 +421,6 @@ private MapMLLayerMetadata layersToOneMapMLLayerMetadata(List<RawLayer> layers)
MapMLLayerMetadata mapMLLayerMetadata = new MapMLLayerMetadata();
mapMLLayerMetadata.setLayerMeta(new MetadataMap());
mapMLLayerMetadata.setUseTiles(false);
if (layers.size() == 1) {
useFeatures = useFeatures(layers.get(0), mapContent.getRequest());
}
mapMLLayerMetadata.setUseFeatures(useFeatures);
mapMLLayerMetadata.setLayerName(layersCommaDelimited);
mapMLLayerMetadata.setStyleName(stylesCommaDelimited);
Expand Down Expand Up @@ -590,9 +601,7 @@ private MapMLLayerMetadata layerToMapMLLayerMetadata(RawLayer layer, String styl
cqlFilter = cql != null ? cql : "";
tileLayerExists = gwc.hasTileLayer(isLayerGroup ? layerGroupInfo : layerInfo)
&& gwc.getTileLayer(isLayerGroup ? layerGroupInfo : layerInfo).getGridSubset(projType.value()) != null;
useTiles = useTiles(layer, mapContent.getRequest());
boolean useRemote = Boolean.TRUE.equals(layerMeta.get(MAPML_USE_REMOTE, Boolean.class));
useFeatures = useFeatures(layer, mapContent.getRequest());

return new MapMLLayerMetadata(
layerInfo,
Expand All @@ -618,31 +627,28 @@ private MapMLLayerMetadata layerToMapMLLayerMetadata(RawLayer layer, String styl
/**
* Check if layer should be represented as a feature
*
* @param layer RawLayer
* @param getMapRequest GetMapRequest
* @return boolean true if layer should be represented as a feature
*/
@SuppressWarnings("unchecked")
private static boolean useFeatures(RawLayer layer, GetMapRequest getMapRequest) {
private static boolean useFeatures(GetMapRequest getMapRequest) {
Optional useFeaturesOptional = Optional.ofNullable(getMapRequest
.getFormatOptions()
.getOrDefault(
MAPML_CREATE_FEATURE_LINKS.toUpperCase(),
getMapRequest.getFormatOptions().get(MAPML_CREATE_FEATURE_LINKS.toLowerCase())));
return (Boolean.parseBoolean(
(String) useFeaturesOptional.orElse(MAPML_CREATE_FEATURE_LINKS_DEFAULT.toString())))
&& (PublishedType.VECTOR == layer.getPublishedInfo().getType());
(String) useFeaturesOptional.orElse(MAPML_CREATE_FEATURE_LINKS_DEFAULT.toString())));
}

/**
* Check if layer should be represented with tiles
*
* @param layer RawLayer
* @param getMapRequest GetMapRequest
* @return boolean useTiles
*/
@SuppressWarnings("unchecked")
private static boolean useTiles(RawLayer layer, GetMapRequest getMapRequest) {
public static boolean useTiles(GetMapRequest getMapRequest) {
Optional useTilesOptional = Optional.ofNullable(getMapRequest
.getFormatOptions()
.getOrDefault(
Expand Down Expand Up @@ -733,7 +739,10 @@ private HeadContent prepareHead() throws IOException {
Base base = new Base();
Map<String, String> wmsParams = new HashMap<>();
wmsParams.put("format", MapMLConstants.MAPML_MIME_TYPE);
String formatOptions = getFormatOptions(format, useTiles, useFeatures);
String formatOptions =
MapMLConstants.MAPML_WMS_MIME_TYPE_OPTION + ":" + escapeHtml4((String) format.orElse(imageFormat)) + ";"
+ MapMLConstants.MAPML_MULTILAYER_AS_MULTIEXTENT + ":" + isMultiExtent + ";"
+ MAPML_USE_TILES_REP + ":" + useTiles + ";" + MAPML_CREATE_FEATURE_LINKS + ":" + useFeatures;
wmsParams.put("format_options", formatOptions);
wmsParams.put("layers", layersCommaDelimited);
wmsParams.put("crs", projType.getCRSCode());
Expand Down Expand Up @@ -881,14 +890,6 @@ private HeadContent prepareHead() throws IOException {
return head;
}

private String getFormatOptions(Optional<Object> format, Boolean useTiles, Boolean useFeatures) {
String formatOptions =
MapMLConstants.MAPML_WMS_MIME_TYPE_OPTION + ":" + escapeHtml4((String) format.orElse(imageFormat)) + ";"
+ MapMLConstants.MAPML_MULTILAYER_AS_MULTIEXTENT + ":" + isMultiExtent + ";"
+ MAPML_USE_TILES_REP + ":" + useTiles + ";" + MAPML_CREATE_FEATURE_LINKS + ":" + useFeatures;
return formatOptions;
}

/**
* Get Links generated from the head template
*
Expand Down Expand Up @@ -1950,7 +1951,10 @@ private String buildGetMap(
kvp.put("CQL_FILTER", cqlFilter);
}
kvp.put("FORMAT", MAPML_MIME_TYPE);
String formatOptions = getFormatOptions(format, useTiles, useFeatures);
String formatOptions =
MapMLConstants.MAPML_WMS_MIME_TYPE_OPTION + ":" + escapeHtml4((String) format.orElse(imageFormat)) + ";"
+ MapMLConstants.MAPML_MULTILAYER_AS_MULTIEXTENT + ":" + isMultiExtent + ";"
+ MAPML_USE_TILES_REP + ":" + useTiles + ";" + MAPML_CREATE_FEATURE_LINKS + ":" + useFeatures;
kvp.put("format_options", formatOptions);
kvp.put("SERVICE", "WMS");
kvp.put("REQUEST", "GetMap");
Expand Down
Loading

0 comments on commit 35bdbb3

Please sign in to comment.