Skip to content

Commit

Permalink
Add extensibility of common preview formats via beans (#3521)
Browse files Browse the repository at this point in the history
  • Loading branch information
prushforth authored and aaime committed Jun 1, 2019
1 parent acfdccc commit 2c1d5c4
Show file tree
Hide file tree
Showing 11 changed files with 277 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ public void testAppSchemaGmlLinks() {
// collect GML links model objects
List<String> gmlLinks = new ArrayList<String>();
for (int i = 1; i <= EXPECTED_GML_LINKS.size(); i++) {
ExternalLink gmlLink = (ExternalLink) items.get(i + ":itemProperties:3:component:gml");
ExternalLink gmlLink =
(ExternalLink)
items.get(i + ":itemProperties:3:component:commonFormat:1")
.getDefaultModelObject();
assertNotNull(gmlLink);
gmlLinks.add(gmlLink.getDefaultModelObjectAsString());
}
Expand Down
20 changes: 19 additions & 1 deletion src/web/demo/src/main/java/applicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,25 @@
<property name="scope" value="org.geoserver.web.demo.MapPreviewPage"/>
<property name="javaScriptFilename" value="mappreview_keyshortcut.js"/>
</bean>


<bean id="openLayersPreview" class="org.geoserver.web.demo.OpenLayersFormatLink">
<property name="id" value="ol"/>
<property name="titleKey" value="ol.title"/>
<property name="order" value="10"/>
</bean>
<bean id="gMLPreview" class="org.geoserver.web.demo.GMLFormatLink">
<property name="id" value="gml"/>
<property name="titleKey" value="gml.title"/>
<property name="order" value="20"/>
<property name="geoserver">
<ref bean="geoServer"/>
</property>
</bean>
<bean id="kMLPreview" class="org.geoserver.web.demo.KMLFormatLink">
<property name="id" value="kml"/>
<property name="titleKey" value="kml.title"/>
<property name="order" value="30"/>
</bean>
<bean id="demoRequests" class="org.geoserver.web.DemoLinkInfo">
<property name="id" value="demoRequests"/>
<property name="titleKey" value="DemoRequestsPage.title"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* (c) 2019 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.web.demo;

import org.apache.wicket.markup.html.link.ExternalLink;
import org.geoserver.web.ToolLinkExternalInfo;

/**
* Extension point for MapPreviewPage. Subclasses will implement getFormatLink which returns an
* ExternalLink to a layer preview in the subclass format represented by the subclass e.g.
* GMLFormatLink.
*
* @author prushforth
*/
public abstract class CommonFormatLink extends ToolLinkExternalInfo
implements Comparable<CommonFormatLink> {

private final String componentId = "theLink";

private int order = 1000;

public CommonFormatLink() {
super();
}

/**
* Returns an ExternalLink object that is used to link to the layer preview.
*
* @param layer the PreviewLayer object for which the preview link is returned
* @return
*/
public abstract ExternalLink getFormatLink(PreviewLayer layer);

@Override
public void setComponentClass(Class<ExternalLink> componentClass) {}

public String getComponentId() {
return componentId;
}

/**
* @param order orders the list of common formats, by default new formats will be added at the
* of the list.
*/
public void setOrder(int order) {
this.order = order;
}

public int getOrder() {
return order;
}

@Override
public int compareTo(CommonFormatLink other) {
return getOrder() - other.getOrder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* (c) 2019 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.web.demo;

import java.util.HashMap;
import java.util.Map;
import org.apache.wicket.Component;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.model.StringResourceModel;
import org.geoserver.config.GeoServer;
import org.geoserver.web.demo.PreviewLayer.GMLOutputParams;
import org.geoserver.web.demo.PreviewLayer.PreviewLayerType;
import org.geoserver.wfs.WFSInfo;

public class GMLFormatLink extends CommonFormatLink {

private GeoServer geoserver;

/** GML output params computation may be expensive, results are cached in this map */
private final transient Map<String, GMLOutputParams> gmlParamsCache =
new HashMap<String, GMLOutputParams>();

@Override
public ExternalLink getFormatLink(PreviewLayer layer) {
ExternalLink gmlLink =
new ExternalLink(
this.getComponentId(),
layer.getGmlLink(gmlParamsCache) + this.getMaxFeatures(),
(new StringResourceModel(this.getTitleKey(), (Component) null, null))
.getString());
gmlLink.setVisible(
layer.getType() == PreviewLayerType.Vector && layer.hasServiceSupport("WFS"));
return gmlLink;
}

/**
* Generates the maxFeatures element of the WFS request using the value of
* maxNumberOfFeaturesForPreview. Values <= 0 give no limit.
*
* @return "&maxFeatures=${maxNumberOfFeaturesForPreview}" or "" if
* maxNumberOfFeaturesForPreview <= 0"
*/
private String getMaxFeatures() {
WFSInfo service = geoserver.getService(WFSInfo.class);
if (service.getMaxNumberOfFeaturesForPreview() > 0) {
return "&maxFeatures=" + service.getMaxNumberOfFeaturesForPreview();
}
return "";
}

public void setGeoserver(GeoServer geoserver) {
this.geoserver = geoserver;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* (c) 2019 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.web.demo;

import org.apache.wicket.Component;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.model.StringResourceModel;

public class KMLFormatLink extends CommonFormatLink {

@Override
public ExternalLink getFormatLink(PreviewLayer layer) {
ExternalLink kmlLink =
new ExternalLink(
this.getComponentId(),
layer.getWmsLink() + "/kml?layers=" + layer.getName(),
(new StringResourceModel(this.getTitleKey(), (Component) null, null))
.getString());
kmlLink.setVisible(layer.hasServiceSupport("WMS"));
return kmlLink;
}
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
<html xmlns:wicket="http://wicket.apache.org/">
<head>
<title><wicket:message key="page.title">Layer Preview</wicket:message></title>
</head>
<body>
<wicket:extend>
<!-- the table component -->
<div wicket:id="table"></div>

<!-- The fragment for the icon -->
<wicket:fragment wicket:id="iconFragment">
<img wicket:id="layerIcon"/>
</wicket:fragment>

<!-- The fragment for the common links -->
<wicket:fragment wicket:id="commonLinks">
<div style="white-space: nowrap;"><a target="_blank" wicket:id="ol"></a>&nbsp;<a target="_blank" wicket:id="kml"></a>&nbsp;<a target="_blank" wicket:id="gml"></a></div>
</wicket:fragment>

<!-- The custom drop down with optgroups -->
<wicket:fragment wicket:id="menuFragment">
<select wicket:id="menu">
<option><wicket:message key="selectOne">Select one</wicket:message></option>
<optgroup label="WMS" wicket:id="wms">
<option wicket:id="wmsFormats"></option>
</optgroup>
<optgroup label="WFS" wicket:id="wfs">
<option wicket:id="wfsFormats"></option>
</optgroup>
</select>
</wicket:fragment>
</wicket:extend>
</body>
</html>
<html xmlns:wicket="http://wicket.apache.org/">
<head>
<title><wicket:message key="page.title">Layer Preview</wicket:message></title>
</head>
<body>
<wicket:extend>
<!-- the table component -->
<div wicket:id="table"></div>

<!-- The fragment for the icon -->
<wicket:fragment wicket:id="iconFragment">
<img wicket:id="layerIcon"/>
</wicket:fragment>

<!-- The fragment for the common links -->
<wicket:fragment wicket:id="commonLinks">
<span style="white-space: nowrap;" wicket:id="commonFormat">
<a target="_blank" href="#" wicket:id="theLink">theTitle</a>&nbsp;
</span>
</wicket:fragment>

<!-- The custom drop down with optgroups -->
<wicket:fragment wicket:id="menuFragment">
<select wicket:id="menu">
<option><wicket:message key="selectOne">Select one</wicket:message></option>
<optgroup label="WMS" wicket:id="wms">
<option wicket:id="wmsFormats"></option>
</optgroup>
<optgroup label="WFS" wicket:id="wfs">
<option wicket:id="wfsFormats"></option>
</optgroup>
</select>
</wicket:fragment>
</wicket:extend>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.apache.commons.collections4.CollectionUtils;
Expand All @@ -29,19 +27,17 @@
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.PublishedType;
import org.geoserver.config.GeoServer;
import org.geoserver.ows.util.ResponseUtils;
import org.geoserver.security.DisabledServiceResourceFilter;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.web.GeoServerBasePage;
import org.geoserver.web.demo.PreviewLayer.GMLOutputParams;
import org.geoserver.web.demo.PreviewLayer.PreviewLayerType;
import org.geoserver.web.wicket.GeoServerDataProvider.Property;
import org.geoserver.web.wicket.GeoServerTablePanel;
import org.geoserver.wfs.WFSGetFeatureOutputFormat;
Expand All @@ -60,10 +56,6 @@ public class MapPreviewPage extends GeoServerBasePage {
private transient List<String> availableWMSFormats;
// private transient List<String> availableWFSFormats;

/** GML output params computation may be expensive, results are cached in this map */
private transient Map<String, GMLOutputParams> gmlParamsCache =
new HashMap<String, GMLOutputParams>();

public MapPreviewPage() {
// output formats for the drop downs
final List<String> wmsOutputFormats = getAvailableWMSFormats();
Expand All @@ -81,8 +73,8 @@ protected Component getComponentForProperty(
IModel<PreviewLayer> itemModel,
Property<PreviewLayer> property) {
PreviewLayer layer = itemModel.getObject();
boolean wmsVisible = hasServiceSupport(layer.getName(), "WMS");
boolean wfsVisible = hasServiceSupport(layer.getName(), "WFS");
boolean wmsVisible = layer.hasServiceSupport("WMS");
boolean wfsVisible = layer.hasServiceSupport("WFS");
if (property == TYPE) {
Fragment f = new Fragment(id, "iconFragment", MapPreviewPage.this);
f.add(new Image("layerIcon", layer.getIcon()));
Expand All @@ -93,27 +85,16 @@ protected Component getComponentForProperty(
return new Label(id, property.getModel(itemModel));
} else if (property == COMMON) {
Fragment f = new Fragment(id, "commonLinks", MapPreviewPage.this);
// openlayers preview
final String olUrl =
layer.getWmsLink() + "&format=application/openlayers";
ExternalLink olLink = new ExternalLink("ol", olUrl, "OpenLayers");
olLink.setVisible(wmsVisible);
f.add(olLink);
// kml preview
final String kmlUrl =
layer.getBaseURL("wms") + "/kml?layers=" + layer.getName();
ExternalLink kmlLink = new ExternalLink("kml", kmlUrl, "KML");
kmlLink.setVisible(wmsVisible);
f.add(kmlLink);
// gml preview (we actually want it only for vector layers)
final String gmlUrl =
layer.getGmlLink(gmlParamsCache) + getMaxFeatures();
Component gmlLink = new ExternalLink("gml", gmlUrl, "GML");
f.add(gmlLink);
gmlLink.setVisible(
layer.getType() == PreviewLayerType.Vector
&& hasServiceSupport(layer.getName(), "WFS"));

ListView lv =
new ListView("commonFormat", commonFormatLinks(layer)) {
@Override
public void populateItem(ListItem item) {
final ExternalLink link =
(ExternalLink) item.getModelObject();
item.add(link);
}
};
f.add(lv);
return f;
} else if (property == ALL) {
return buildJSWMSSelect(
Expand All @@ -130,6 +111,16 @@ protected Component getComponentForProperty(
add(table);
}

private List<ExternalLink> commonFormatLinks(PreviewLayer layer) {
List<ExternalLink> links = new ArrayList<>();
List<CommonFormatLink> formats =
getGeoServerApplication().getBeansOfType(CommonFormatLink.class);
Collections.sort(formats);
for (CommonFormatLink link : formats) {
links.add(link.getFormatLink(layer));
}
return links;
}
/**
* Generates the maxFeatures element of the WFS request using the value of
* maxNumberOfFeaturesForPreview. Values <= 0 give no limit.
Expand Down Expand Up @@ -292,18 +283,6 @@ private String translateFormat(String prefix, String format) {
}
}

/** Returns true if serviceName is available for resource, otherwise false */
protected boolean hasServiceSupport(String layerName, String serviceName) {
LayerInfo linfo = getGeoServer().getCatalog().getLayerByName(layerName);
if (linfo != null && linfo.getResource() != null && serviceName != null) {
List<String> disabledServices =
DisabledServiceResourceFilter.disabledServices(linfo.getResource());
return disabledServices.stream().noneMatch(d -> d.equalsIgnoreCase(serviceName));
}
// layer group and backward compatibility
return true;
}

/**
* Sorts the formats using the i18n translated name
*
Expand Down

0 comments on commit 2c1d5c4

Please sign in to comment.