Skip to content

Commit

Permalink
[GEOS-11294] MapML Add Support to WMS for Vector Representation
Browse files Browse the repository at this point in the history
useFeatures UI test

added usefeatures to builder

Return features links

started on conversion

First pass at building features

clarify multi error

cleanup

PR comments part 1

Configuration Panel Constants

check for raster and more constants

fixed metadata tests

added getAsMapML to tests

removed alternative projection links and added feature reprojection

test issue

more test cleanup

fixed default num decimals

reprojectingfeaturecollection needs fallback CRS

if feature links, no query links

PR changes and documentation

documentation
  • Loading branch information
turingtestfail authored and aaime committed Mar 1, 2024
1 parent 5cef739 commit 8587072
Show file tree
Hide file tree
Showing 17 changed files with 1,475 additions and 690 deletions.
Binary file modified doc/en/user/source/extensions/mapml/images/mapml_config_ui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions doc/en/user/source/extensions/mapml/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ Using tiles to access the layer can increase the performance of your web map. Th
**Use Tiles**
If the "Use Tiles" checkbox is checked, by default the output MapML will define a tile-based reference to the WMS server. Otherwise, an image-based reference will be used. If one or more of the MapML-defined GridSets is referenced by the layer or layer group in its "Tile Caching" profile, GeoServer will generate tile references instead of generating WMS GetMap URLs in the MapML document body.

Vector Settings
^^^^^^^^^^^^^^^

MapML supports the serving of vector feature representations of the data. This results in a smoother user navigation experience, smaller bandwidth requirements, and more options for dynamic styling on the client-side.

**Use Features**
If the "Use Features" checkbox is checked, by default the output MapML will define a feature-based reference to the WMS server. Otherwise, an image-based reference will be used. Note that this option is only available for vector source data. For multi-layer requests, all of the layers must have the feature option enabled or image-based links will be returned instead.

Tile Caching
^^^^^^^^^^^^

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,69 @@ public final class MapMLConstants {
/** format name */
public static final String FORMAT_NAME = "MAPML";

/** MapML format options */
public static final String MAPML_FEATURE_FORMAT_OPTIONS = "mapmlfeatures:true";

/** MapML layer metadata use features */
public static final String MAPML_USE_FEATURES = "mapml.useFeatures";

/** MapML layer metadata use tiles */
public static final String MAPML_USE_TILES = "mapml.useTiles";

/** MapML layer resource metadata */
public static final String RESOURCE_METADATA = "resource.metadata";

/** LIST FAILED */
public static final String LIST_FAILED = "Grabbing the attribute list failed";

/** ATTRIBUTE_LIST_FAILED */
public static final String ATTRIBUTE_LIST_FAILED = "attributeListingFailed";

/** FEATURE_CAPTION_TEMPLATE */
public static final String FEATURE_CAPTION_TEMPLATE = "featureCaptionTemplate";

/** FEATURE_CAPTION */
public static final String FEATURE_CAPTION = "mapml.featureCaption";

/** FEATURE_CAPTION_ATTRIBUTES */
public static final String FEATURE_CAPTION_ATTRIBUTES = "featurecaptionattributes";

/** MAPML_PREFIX */
public static final String MAPML_PREFIX = "mapml.";

/** DIMENSION */
public static final String DIMENSION = "dimension";

/** MAPML_DIMENSION */
public static final String MAPML_DIMENSION = MAPML_PREFIX + DIMENSION;

/** SHARD_LIST */
public static final String SHARD_LIST = "shardList";

/** ENABLE_SHARDING */
public static final String ENABLE_SHARDING = "enableSharding";

/** USE_TILES */
public static final String USE_TILES = "useTiles";

/** LICENSE_LINK */
public static final String LICENSE = "licenseLink";

/** LICENSE_TITLE2 */
public static final String LICENSE_TITLE2 = "licenseTitle";

/** USE_FEATURES */
public static final String USE_FEATURES = "useFeatures";

/** SHARD_SERVER_PATTERN */
public static final String SHARD_SERVER_PATTERN = "shardServerPattern";

/** LICENSE_TITLE */
public static final String LICENSE_TITLE = "license.title";

/** LICENSE_LINK */
public static final String LICENSE_LINK = "license.link";

public static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

public static final String REL_ZOOMIN = "zoomin";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

import static org.apache.commons.text.StringEscapeUtils.escapeHtml4;
import static org.geoserver.mapml.MapMLConstants.DATE_FORMAT;
import static org.geoserver.mapml.MapMLConstants.MAPML_FEATURE_FORMAT_OPTIONS;
import static org.geoserver.mapml.MapMLConstants.MAPML_MIME_TYPE;
import static org.geoserver.mapml.MapMLConstants.MAPML_USE_FEATURES;
import static org.geoserver.mapml.MapMLConstants.MAPML_USE_TILES;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
Expand All @@ -32,6 +35,7 @@
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.StyleInfo;
import org.geoserver.catalog.impl.LayerGroupStyle;
Expand Down Expand Up @@ -109,8 +113,9 @@ public class MapMLDocumentBuilder {
private final GWC gwc = GWC.get();
private final String layersCommaDelimited;
private final String layerTitlesCommaDelimited;
private final String stylesCommaDelimited;
private final GetMapRequest getMapRequest;
private final String stylesCommaDelimited;

private String defaultStyle;
private String layerTitle;
private String imageFormat;
Expand All @@ -129,6 +134,7 @@ public class MapMLDocumentBuilder {

private Input zoomInput;

private boolean useFeaturesAllLayers = true;
private List<MapMLLayerMetadata> mapMLLayerMetadataList = new ArrayList<>();

private Mapml mapml;
Expand Down Expand Up @@ -279,6 +285,7 @@ public void initialize() throws ServiceException {
MapMLLayerMetadata mapMLLayerMetadata = layersToOneMapMLLayerMetadata(layers);
mapMLLayerMetadataList.add(mapMLLayerMetadata);
}
useFeaturesAllLayers = allLayersUsingFeatures(layers);
// populate Map-wide variables using the first layer
if (!mapMLLayerMetadataList.isEmpty()) {
defaultStyle =
Expand Down Expand Up @@ -362,6 +369,24 @@ private MapMLLayerMetadata layersToOneMapMLLayerMetadata(List<RawLayer> layers)
return mapMLLayerMetadata;
}

/**
* Check if all layers in the request use features
*
* @param layers List of RawLayer objects
* @return boolean
*/
private boolean allLayersUsingFeatures(List<RawLayer> layers) {
for (RawLayer layer : layers) {
Boolean useFeatures =
layer.getPublishedInfo().getMetadata().get(MAPML_USE_FEATURES, Boolean.class);
Boolean isVector = (PublishedType.VECTOR == layer.getPublishedInfo().getType());
if (useFeatures == null || isVector == null || !useFeatures || !isVector) {
return false;
}
}
return true;
}

/**
* Parses the projection into a ProjType, or throws a proper service exception indicating the
* unsupported CRS
Expand Down Expand Up @@ -498,7 +523,6 @@ private MapMLLayerMetadata layerToMapMLLayerMetadata(RawLayer layer, String styl
String styleName = null;
boolean tileLayerExists = false;
if (isLayerGroup) {
// layerGroupInfo = geoServer.getCatalog().getLayerGroupByName(layer.getTitle());
layerGroupInfo = (LayerGroupInfo) layer.getPublishedInfo();
if (layerGroupInfo == null) {
throw new ServiceException("Invalid layer or layer group name");
Expand Down Expand Up @@ -536,7 +560,8 @@ private MapMLLayerMetadata layerToMapMLLayerMetadata(RawLayer layer, String styl
&& gwc.getTileLayer(isLayerGroup ? layerGroupInfo : layerInfo)
.getGridSubset(projType.value())
!= null;
boolean useTiles = Boolean.TRUE.equals(layerMeta.get("mapml.useTiles", Boolean.class));
boolean useTiles = Boolean.TRUE.equals(layerMeta.get(MAPML_USE_TILES, Boolean.class));
boolean useFeatures = Boolean.TRUE.equals(layerMeta.get(MAPML_USE_FEATURES, Boolean.class));

return new MapMLLayerMetadata(
layerInfo,
Expand All @@ -552,7 +577,8 @@ private MapMLLayerMetadata layerToMapMLLayerMetadata(RawLayer layer, String styl
projType,
styleName,
tileLayerExists,
useTiles);
useTiles,
useFeatures);
}

/**
Expand Down Expand Up @@ -999,7 +1025,8 @@ private void generateTemplatedLinks(MapMLLayerMetadata mapMLLayerMetadata) {
}

// query inputs
if (mapMLLayerMetadata.isQueryable()) {
if (mapMLLayerMetadata.isQueryable()
&& !useFeaturesAllLayers) { // No query links for feature representations
if (mapMLLayerMetadata.isUseTiles() && mapMLLayerMetadata.isTileLayerExists()) {
generateWMTSQueryClientLinks(mapMLLayerMetadata);
} else {
Expand Down Expand Up @@ -1322,7 +1349,11 @@ public void generateWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) {

// image link
Link imageLink = new Link();
imageLink.setRel(RelType.IMAGE);
if (useFeaturesAllLayers) {
imageLink.setRel(RelType.FEATURES);
} else {
imageLink.setRel(RelType.IMAGE);
}
String path = "wms";
HashMap<String, String> params = new HashMap<>();
params.put("version", "1.3.0");
Expand All @@ -1338,7 +1369,12 @@ public void generateWMSClientLinks(MapMLLayerMetadata mapMLLayerMetadata) {
params.put("elevation", "{elevation}");
}
params.put("bbox", "{xmin},{ymin},{xmax},{ymax}");
params.put("format", imageFormat);
if (useFeaturesAllLayers) {
params.put("format", MAPML_MIME_TYPE);
params.put("format_options", MAPML_FEATURE_FORMAT_OPTIONS);
} else {
params.put("format", imageFormat);
}
params.put("transparent", Boolean.toString(mapMLLayerMetadata.isTransparent()));
params.put("language", this.request.getLocale().getLanguage());
params.put("width", "{w}");
Expand Down Expand Up @@ -1746,6 +1782,7 @@ public void setTitle(String title) {

/** MapML layer metadata */
static class MapMLLayerMetadata {
private boolean useFeatures;
private LayerInfo layerInfo;
private ReferencedEnvelope bbox;
private boolean isLayerGroup;
Expand All @@ -1769,6 +1806,24 @@ static class MapMLLayerMetadata {

private String layerLabel;

/**
* get if the layer uses features
*
* @return
*/
public boolean isUseFeatures() {
return useFeatures;
}

/**
* set if the layer uses features
*
* @param useFeatures boolean
*/
public void setUseFeatures(boolean useFeatures) {
this.useFeatures = useFeatures;
}

/**
* Constructor
*
Expand Down Expand Up @@ -1801,7 +1856,8 @@ public MapMLLayerMetadata(
ProjType projType,
String styleName,
boolean tileLayerExists,
boolean useTiles) {
boolean useTiles,
boolean useFeatures) {
this.layerInfo = layerInfo;
this.bbox = bbox;
this.isLayerGroup = isLayerGroup;
Expand All @@ -1816,6 +1872,7 @@ public MapMLLayerMetadata(
this.isTransparent = isTransparent;
this.tileLayerExists = tileLayerExists;
this.useTiles = useTiles;
this.useFeatures = useFeatures;
}

/** Constructor */
Expand Down
Loading

0 comments on commit 8587072

Please sign in to comment.