-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Backport 2.25.x] [GEOS-11340][Community] WFS Freemarker HTML Outputf…
…ormat (#7557) * [GEOS-11340] Extracted `HTMLTemplateManager`. * [GEOS-11340] Added wfs-freemarker community module. * [GEOS-11340] Added wfs-freemarker community module tests. * - Minor fix on formatting and headers - Improved module documentation * Update doc/en/user/source/community/wfs-freemarker/configuration.rst Co-authored-by: Andrea Aime <andrea.aime@gmail.com> * Update src/community/wfs-freemarker/src/main/java/org/geoserver/wfsfreemarker/html/HtmlGetFeatureOutputFormat.java Co-authored-by: Andrea Aime <andrea.aime@gmail.com> * Update doc/en/user/source/community/wfs-freemarker/index.rst Co-authored-by: Andrea Aime <andrea.aime@gmail.com> * - Updates according to the review request changes * - Fix documentation references * - Suppress unchecked warning * - Formatting issues * - Fix version number --------- Co-authored-by: Alessandro Ricchiuti <alessandro.ricchiuti@geosolutionsgroup.com> Co-authored-by: afabiani <alessio.fabiani@geosolutionsgroup.com>
- Loading branch information
1 parent
76c6f8b
commit ed78065
Showing
19 changed files
with
434 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
doc/en/user/source/community/wfs-freemarker/configuration.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
.. _community_wfsfreemarker_config: | ||
|
||
WFS FreeMarker Extension configuration | ||
====================================== | ||
|
||
Template Lookup | ||
``````````````` | ||
|
||
Reference: :ref:`tutorials_getfeatureinfo` | ||
|
||
Example Configuration on a Vector Layer | ||
`````````````````````````````````````````` | ||
|
||
The WFS GetFeature can generate output in various formats: GML, GeoJSON, ... and, through this extension, also HTML. | ||
|
||
WFS Templating is concerned with the HTML one. | ||
|
||
Assume we have a Vectorial layer named :guilabel:`geosolutions:bplandmarks` | ||
|
||
#. Go to the Layer preview to show :guilabel:`geosolutions:bplandmarks` layer. | ||
|
||
#. Search for the HTML format from the :guilabel:`All Formats` select-box, under the WFS ones. | ||
|
||
.. figure:: images/info1.png | ||
|
||
#. In order to configure a custom template of the GetFeature results create three files ``.ftl`` in ``$geoserver_data/workspaces/geosolutions`` directory named: | ||
|
||
.. code:: | ||
- header.ftl | ||
- content.ftl | ||
- footer.ftl | ||
.. note:: | ||
|
||
The Template is managed using Freemarker. This is a simple yet powerful template engine that GeoServer uses whenever developers allowed user customization of textual outputs. In particular, at the time of writing, it’s used to allow customization of GetFeatureInfo, GeoRSS and KML outputs. | ||
|
||
.. note:: | ||
|
||
Splitting the template in three files allows the administrator to keep a consistent styling for the GetFeatureInfo result, but use different templates for different workspaces or different layers. This is done by providing a master header.ftl and footer.ftl file, but specify a different content.ftl for each layer. | ||
|
||
#. In header.ftl file enter the following HTML: | ||
|
||
.. code:: | ||
<#-- | ||
Header section of the GetFeatureInfo HTML output. Should have the <head> section, and | ||
a starter of the <body>. It is advised that eventual CSS uses a special class for featureInfo, | ||
since the generated HTML may blend with another page changing its aspect when using generic classes | ||
like td, tr, and so on. | ||
--> | ||
<html> | ||
<head> | ||
<title>Geoserver GetFeatureInfo output</title> | ||
</head> | ||
<style type="text/css"> | ||
table.featureInfo, table.featureInfo td, table.featureInfo th { | ||
border:1px solid #ddd; | ||
border-collapse:collapse; | ||
margin:0; | ||
padding:0; | ||
font-size: 90%; | ||
padding:.2em .1em; | ||
} | ||
table.featureInfo th{ | ||
padding:.2em .2em; | ||
text-transform:uppercase; | ||
font-weight:bold; | ||
background:#eee; | ||
} | ||
table.featureInfo td{ | ||
background:#fff; | ||
} | ||
table.featureInfo tr.odd td{ | ||
background:#eee; | ||
} | ||
table.featureInfo caption{ | ||
text-align:left; | ||
font-size:100%; | ||
font-weight:bold; | ||
text-transform:uppercase; | ||
padding:.2em .2em; | ||
} | ||
</style> | ||
<body> | ||
#. In content.ftl file enter the following HTML: | ||
|
||
.. code:: | ||
<ul> | ||
<#list features as feature> | ||
<li><b>Type: ${type.name}</b> (id: <em>${feature.fid}</em>): | ||
<ul> | ||
<#list feature.attributes as attribute> | ||
<#if !attribute.isGeometry> | ||
<li>${attribute.name}: ${attribute.value}</li> | ||
</#if> | ||
</#list> | ||
</ul> | ||
</li> | ||
</#list> | ||
</ul> | ||
#. In footer.ftl file enter the following HTML: | ||
|
||
.. code:: | ||
<#-- | ||
Footer section of the GetFeatureInfo HTML output. Should close the body and the html tag. | ||
--> | ||
</body> | ||
</html> | ||
#. Refresh the WFS GetFeature HTML output | ||
|
||
.. figure:: images/info2.png |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
.. _community_wfsfreemarker: | ||
|
||
WFS FreeMarker Extension | ||
======================== | ||
|
||
The WFS FreeMarker plugin enables the application of a FreeMarker template to a WFS GetFeature response, allowing for the generation of HTML output, akin to the functionality already present for WMS GetFeatureInfo requests. | ||
|
||
It leverages the same logic and machinery utilized in templating WMS responses, utilizing the same Freemarker templates already in use for the GetFeatureInfo HTML output. | ||
|
||
This feature is also accessible on the :guilabel:`Layer Preview` page in GeoServer, where a new `HTML` output format is provided for the WFS preview. | ||
|
||
.. toctree:: | ||
:maxdepth: 2 | ||
|
||
installing | ||
configuration |
11 changes: 11 additions & 0 deletions
11
doc/en/user/source/community/wfs-freemarker/installing.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.. _community_wfsfreemarker_installing: | ||
|
||
Installing the WFS FreeMarker Extension | ||
======================================= | ||
|
||
#. Download the Features Templating community module from :download_community:`wfs-freemarker`. | ||
|
||
|
||
.. warning:: Make sure to match the version of the extension to the version of the GeoServer instance! | ||
|
||
#. Extract the contents of the archive into the ``WEB-INF/lib`` directory of the GeoServer installation. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<assembly> | ||
<id>wfs-freemarker-plugin</id> | ||
<formats> | ||
<format>zip</format> | ||
</formats> | ||
<includeBaseDirectory>false</includeBaseDirectory> | ||
<fileSets> | ||
<fileSet> | ||
<directory>release/target/dependency</directory> | ||
<outputDirectory></outputDirectory> | ||
<includes> | ||
<include>gs-wfs-freemarker*.jar</include> | ||
</includes> | ||
</fileSet> | ||
</fileSets> | ||
</assembly> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.geoserver</groupId> | ||
<artifactId>community</artifactId> | ||
<version>2.25-SNAPSHOT</version> | ||
</parent> | ||
|
||
<groupId>org.geoserver.community</groupId> | ||
<artifactId>gs-wfs-freemarker</artifactId> | ||
<packaging>jar</packaging> | ||
<name>WFS Freemarker module</name> | ||
<description>WFS Freemarker plugin: allows HTML output format for WFS layers.</description> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.geoserver</groupId> | ||
<artifactId>gs-main</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.geoserver</groupId> | ||
<artifactId>gs-wfs</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.geoserver</groupId> | ||
<artifactId>gs-wms</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.geoserver</groupId> | ||
<artifactId>gs-main</artifactId> | ||
<version>${project.version}</version> | ||
<classifier>tests</classifier> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.geoserver</groupId> | ||
<artifactId>gs-wfs</artifactId> | ||
<version>${project.version}</version> | ||
<classifier>tests</classifier> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
70 changes: 70 additions & 0 deletions
70
...freemarker/src/main/java/org/geoserver/wfsfreemarker/html/HTMLGetFeatureOutputFormat.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* (c) 2024 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.wfsfreemarker.html; | ||
|
||
import static org.geoserver.wms.featureinfo.FreeMarkerTemplateManager.OutputFormat.HTML; | ||
|
||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.util.List; | ||
import org.geoserver.config.GeoServer; | ||
import org.geoserver.platform.GeoServerResourceLoader; | ||
import org.geoserver.platform.Operation; | ||
import org.geoserver.platform.ServiceException; | ||
import org.geoserver.wfs.WFSGetFeatureOutputFormat; | ||
import org.geoserver.wfs.request.FeatureCollectionResponse; | ||
import org.geoserver.wfs.response.ComplexFeatureAwareFormat; | ||
import org.geoserver.wms.WMS; | ||
import org.geoserver.wms.featureinfo.FreeMarkerTemplateManager; | ||
import org.geoserver.wms.featureinfo.HTMLTemplateManager; | ||
import org.geotools.feature.FeatureCollection; | ||
|
||
/** | ||
* A GetFeature response handler specialized in producing HTML data for a GetFeature request through | ||
* the {@link FreeMarkerTemplateManager}. | ||
*/ | ||
public class HTMLGetFeatureOutputFormat extends WFSGetFeatureOutputFormat | ||
implements ComplexFeatureAwareFormat { | ||
|
||
private final HTMLTemplateManager templateManager; | ||
|
||
public HTMLGetFeatureOutputFormat( | ||
GeoServer gs, final WMS wms, GeoServerResourceLoader resourceLoader) { | ||
super(gs, HTML.getFormat()); | ||
this.templateManager = new HTMLTemplateManager(HTML, wms, resourceLoader); | ||
} | ||
|
||
/** capabilities output format string. */ | ||
@Override | ||
public String getCapabilitiesElementName() { | ||
return "HTML"; | ||
} | ||
|
||
/** Returns the mime type */ | ||
@Override | ||
public String getMimeType(Object value, Operation operation) throws ServiceException { | ||
return HTML.getFormat(); | ||
} | ||
|
||
@Override | ||
@SuppressWarnings( | ||
"PMD.CloseResource") // the output stream is managed outside, only wrappers here | ||
protected void write( | ||
FeatureCollectionResponse featureCollection, OutputStream output, Operation operation) | ||
throws IOException { | ||
List<FeatureCollection> resultsList = featureCollection.getFeature(); | ||
templateManager.write(resultsList, output); | ||
} | ||
|
||
@Override | ||
public String getCharset(Operation operation) { | ||
return gs.getGlobal().getSettings().getCharset(); | ||
} | ||
|
||
@Override | ||
protected String getExtension(FeatureCollectionResponse response) { | ||
return "html"; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/community/wfs-freemarker/src/main/resources/applicationContext.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> | ||
<beans> | ||
|
||
<!-- GetFeature HTML --> | ||
<bean id="HtmlGetFeatureOutputFormat" class="org.geoserver.wfsfreemarker.html.HTMLGetFeatureOutputFormat"> | ||
<constructor-arg ref="geoServer"/> | ||
</bean> | ||
|
||
</beans> |
40 changes: 40 additions & 0 deletions
40
...freemarker/src/test/java/org/geoserver/wfsfreemarker/html/GetFeatureOutputFormatTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* (c) 2024 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.wfsfreemarker.html; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
import org.custommonkey.xmlunit.XMLAssert; | ||
import org.geoserver.wfs.WFSTestSupport; | ||
import org.junit.Test; | ||
import org.springframework.mock.web.MockHttpServletResponse; | ||
import org.w3c.dom.Document; | ||
|
||
/** Test for checking WFS GetFeature HTML templating */ | ||
public class GetFeatureOutputFormatTest extends WFSTestSupport { | ||
|
||
@Test | ||
public void testGetFeatureResponseMimeType() throws Exception { | ||
String request = | ||
"wfs?version=1.1.0&request=GetFeature&typeName=cite:Forests&outputFormat=text/html"; | ||
|
||
MockHttpServletResponse response = getAsServletResponse(request); | ||
|
||
assertEquals("text/html", getBaseMimeType(response.getContentType())); | ||
} | ||
|
||
@Test | ||
public void testGetFeatureHtmlDefaultTemplate() throws Exception { | ||
String request = | ||
"wfs?version=1.1.0&request=GetFeature&typeName=cite:Forests&outputFormat=text/html"; | ||
|
||
Document dom = getAsDOM(request); | ||
|
||
XMLAssert.assertXpathExists("/html/body/table", dom); | ||
XMLAssert.assertXpathEvaluatesTo("Forests", "/html/body/table/caption", dom); | ||
XMLAssert.assertXpathEvaluatesTo("2", "count(/html/body/table/tr)", dom); | ||
XMLAssert.assertXpathEvaluatesTo("Green Forest", "/html/body/table/tr[2]/td[3]", dom); | ||
} | ||
} |
Oops, something went wrong.