-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First simple basic HTML output for features, inspired by GetFeatureIn…
…fo. Still needs consistent styling, paging links, alternate format links, eventually a link to a WMS preview
- Loading branch information
Showing
12 changed files
with
438 additions
and
45 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
74 changes: 74 additions & 0 deletions
74
src/community/wfs3/src/main/java/org/geoserver/wfs3/response/FreemarkerTemplateSupport.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 | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,74 @@ | |||
/* | |||
* (c) 2018 Open Source Geospatial Foundation - all rights reserved | |||
* * This code is licensed under the GPL 2.0 license, available at the root | |||
* * application directory. | |||
* | |||
*/ | |||
|
|||
/* | |||
* (c) 2018 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.wfs3.response; | |||
|
|||
import freemarker.template.Configuration; | |||
import freemarker.template.Template; | |||
import java.io.IOException; | |||
import org.geoserver.catalog.ResourceInfo; | |||
import org.geoserver.catalog.WorkspaceInfo; | |||
import org.geoserver.config.GeoServer; | |||
import org.geoserver.ows.LocalWorkspace; | |||
import org.geoserver.platform.GeoServerResourceLoader; | |||
import org.geoserver.template.DirectTemplateFeatureCollectionFactory; | |||
import org.geoserver.template.FeatureWrapper; | |||
import org.geoserver.template.GeoServerTemplateLoader; | |||
|
|||
public class FreemarkerTemplateSupport { | |||
|
|||
private static Configuration templateConfig = new Configuration(); | |||
|
|||
private final GeoServerResourceLoader resoureLoader; | |||
private final GeoServer geoServer; | |||
|
|||
static DirectTemplateFeatureCollectionFactory FC_FACTORY = | |||
new DirectTemplateFeatureCollectionFactory(); | |||
|
|||
static { | |||
// initialize the template engine, this is static to maintain a cache of templates being | |||
// loaded | |||
templateConfig = new Configuration(); | |||
templateConfig.setObjectWrapper(new FeatureWrapper(FC_FACTORY)); | |||
} | |||
|
|||
public FreemarkerTemplateSupport(GeoServerResourceLoader loader, GeoServer geoServer) { | |||
this.resoureLoader = loader; | |||
this.geoServer = geoServer; | |||
} | |||
|
|||
/** | |||
* Returns the template for the specified feature type. Looking up templates is pretty | |||
* expensive, so we cache templates by feture type and template. | |||
*/ | |||
Template getTemplate(ResourceInfo resource, String templateName) throws IOException { | |||
GeoServerTemplateLoader templateLoader = | |||
new GeoServerTemplateLoader(getClass(), resoureLoader); | |||
if (resource != null) { | |||
templateLoader.setResource(resource); | |||
} else { | |||
WorkspaceInfo ws = LocalWorkspace.get(); | |||
if (ws != null) { | |||
templateLoader.setWorkspace(ws); | |||
} | |||
} | |||
|
|||
// Configuration is not thread safe | |||
synchronized (templateConfig) { | |||
templateConfig.setTemplateLoader(templateLoader); | |||
Template t = templateConfig.getTemplate(templateName); | |||
t.setEncoding("UTF-8"); | |||
return t; | |||
} | |||
} | |||
} |
121 changes: 121 additions & 0 deletions
121
src/community/wfs3/src/main/java/org/geoserver/wfs3/response/GetFeatureHTMLOutputFormat.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 | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,121 @@ | |||
/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved | |||
* (c) 2001 - 2013 OpenPlans | |||
* This code is licensed under the GPL 2.0 license, available at the root | |||
* application directory. | |||
*/ | |||
package org.geoserver.wfs3.response; | |||
|
|||
import freemarker.template.Template; | |||
import freemarker.template.TemplateException; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.OutputStreamWriter; | |||
import java.util.List; | |||
import org.geoserver.catalog.FeatureTypeInfo; | |||
import org.geoserver.config.GeoServer; | |||
import org.geoserver.platform.GeoServerResourceLoader; | |||
import org.geoserver.platform.Operation; | |||
import org.geoserver.platform.ServiceException; | |||
import org.geoserver.wfs.TypeInfoCollectionWrapper; | |||
import org.geoserver.wfs.WFSGetFeatureOutputFormat; | |||
import org.geoserver.wfs.request.FeatureCollectionResponse; | |||
import org.geoserver.wfs3.BaseRequest; | |||
import org.geotools.feature.FeatureCollection; | |||
import org.opengis.feature.simple.SimpleFeatureType; | |||
|
|||
/** Produces a Feature response in HTML. */ | |||
public class GetFeatureHTMLOutputFormat extends WFSGetFeatureOutputFormat { | |||
|
|||
private static final String FORMAT = "text/html"; | |||
|
|||
private final GeoServer geoServer; | |||
private final FreemarkerTemplateSupport templateSupport; | |||
|
|||
public GetFeatureHTMLOutputFormat(GeoServerResourceLoader loader, GeoServer geoServer) { | |||
super(geoServer, BaseRequest.HTML_MIME); | |||
this.geoServer = geoServer; | |||
this.templateSupport = new FreemarkerTemplateSupport(loader, geoServer); | |||
} | |||
|
|||
@Override | |||
public String getMimeType(Object value, Operation operation) throws ServiceException { | |||
return FORMAT; | |||
} | |||
|
|||
@Override | |||
protected void write( | |||
FeatureCollectionResponse response, OutputStream output, Operation getFeature) | |||
throws IOException, ServiceException { | |||
// if there is only one feature type loaded, we allow for header/footer customization, | |||
// otherwise we stick with the generic ones | |||
FeatureTypeInfo referenceFeatureType = null; | |||
List<FeatureCollection> collections = response.getFeature(); | |||
if (collections.size() == 1) { | |||
referenceFeatureType = getResource(collections.get(0)); | |||
} | |||
|
|||
Template header = templateSupport.getTemplate(referenceFeatureType, "header.ftl"); | |||
Template footer = templateSupport.getTemplate(referenceFeatureType, "footer.ftl"); | |||
|
|||
try (OutputStreamWriter osw = new OutputStreamWriter(output)) { | |||
try { | |||
header.process(response, osw); | |||
} catch (TemplateException e) { | |||
String msg = "Error occured processing header template."; | |||
throw (IOException) new IOException(msg).initCause(e); | |||
} | |||
|
|||
// process content template for all feature collections found | |||
for (int i = 0; i < collections.size(); i++) { | |||
FeatureCollection fc = collections.get(i); | |||
if (fc != null && fc.size() > 0) { | |||
Template content = null; | |||
FeatureTypeInfo typeInfo = getResource(fc); | |||
if (!(fc.getSchema() instanceof SimpleFeatureType)) { | |||
// if there is a specific template for complex features, use that. | |||
content = templateSupport.getTemplate(typeInfo, "complex_content.ftl"); | |||
} | |||
if (content == null) { | |||
content = templateSupport.getTemplate(typeInfo, "content.ftl"); | |||
} | |||
try { | |||
content.process(fc, osw); | |||
} catch (TemplateException e) { | |||
String msg = | |||
"Error occurred processing content template " | |||
+ content.getName() | |||
+ " for " | |||
+ typeInfo.prefixedName(); | |||
throw (IOException) new IOException(msg).initCause(e); | |||
} | |||
} | |||
} | |||
|
|||
// if a template footer was loaded (ie, there were only one feature | |||
// collection), process it | |||
if (footer != null) { | |||
try { | |||
footer.process(response, osw); | |||
} catch (TemplateException e) { | |||
String msg = "Error occured processing footer template."; | |||
throw (IOException) new IOException(msg).initCause(e); | |||
} | |||
} | |||
osw.flush(); | |||
} finally { | |||
// close any open iterators | |||
FreemarkerTemplateSupport.FC_FACTORY.purge(); | |||
} | |||
} | |||
|
|||
private FeatureTypeInfo getResource(FeatureCollection collection) { | |||
FeatureTypeInfo info = null; | |||
if (collection instanceof TypeInfoCollectionWrapper) { | |||
info = ((TypeInfoCollectionWrapper) collection).getFeatureTypeInfo(); | |||
} | |||
if (info == null && collection.getSchema() != null) { | |||
info = geoServer.getCatalog().getFeatureTypeByName(collection.getSchema().getName()); | |||
} | |||
return info; | |||
} | |||
} |
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
67 changes: 67 additions & 0 deletions
67
src/community/wfs3/src/main/resources/org/geoserver/wfs3/response/complex_content.ftl
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 | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,67 @@ | |||
<#-- | |||
Macro's used for content | |||
--> | |||
|
|||
<#macro property node> | |||
<#if !node.isGeometry> | |||
<#if node.isComplex> | |||
<td> <@feature node=node.rawValue type=node.type /> </td> | |||
<#else> | |||
<td>${node.value?string}</td> | |||
</#if> | |||
</#if> | |||
</#macro> | |||
|
|||
<#macro header typenode> | |||
<caption class="featureInfo">${typenode.name}</caption> | |||
<tr> | |||
<th>fid</th> | |||
<#list typenode.attributes as attribute> | |||
<#if !attribute.isGeometry> | |||
<#if attribute.prefix == ""> | |||
<th >${attribute.name}</th> | |||
<#else> | |||
<th >${attribute.prefix}:${attribute.name}</th> | |||
</#if> | |||
</#if> | |||
</#list> | |||
</tr> | |||
</#macro> | |||
|
|||
<#macro feature node type> | |||
<table class="featureInfo"> | |||
<@header typenode=type /> | |||
<tr> | |||
<td>${node.fid}</td> | |||
<#list node.attributes as attribute> | |||
<@property node=attribute /> | |||
</#list> | |||
</tr> | |||
</table> | |||
</#macro> | |||
|
|||
<#-- | |||
Body section of the GetFeatureInfo template, it's provided with one feature collection, and | |||
will be called multiple times if there are various feature collections | |||
--> | |||
<table class="featureInfo"> | |||
<@header typenode=type /> | |||
|
|||
<#assign odd = false> | |||
<#list features as feature> | |||
<#if odd> | |||
<tr class="odd"> | |||
<#else> | |||
<tr> | |||
</#if> | |||
<#assign odd = !odd> | |||
|
|||
<td>${feature.fid}</td> | |||
<#list feature.attributes as attribute> | |||
<@property node=attribute /> | |||
</#list> | |||
</tr> | |||
</#list> | |||
</table> | |||
<br/> | |||
|
35 changes: 35 additions & 0 deletions
35
src/community/wfs3/src/main/resources/org/geoserver/wfs3/response/content.ftl
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 | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,35 @@ | |||
<#-- | |||
Body section of the GetFeatureInfo template, it's provided with one feature collection, and | |||
will be called multiple times if there are various feature collections | |||
--> | |||
<table class="featureInfo"> | |||
<caption class="featureInfo">${type.name}</caption> | |||
<tr> | |||
<th>fid</th> | |||
<#list type.attributes as attribute> | |||
<#if !attribute.isGeometry> | |||
<th >${attribute.name}</th> | |||
</#if> | |||
</#list> | |||
</tr> | |||
|
|||
<#assign odd = false> | |||
<#list features as feature> | |||
<#if odd> | |||
<tr class="odd"> | |||
<#else> | |||
<tr> | |||
</#if> | |||
<#assign odd = !odd> | |||
|
|||
<td>${feature.fid}</td> | |||
<#list feature.attributes as attribute> | |||
<#if !attribute.isGeometry> | |||
<td>${attribute.value?string}</td> | |||
</#if> | |||
</#list> | |||
</tr> | |||
</#list> | |||
</table> | |||
<br/> | |||
|
5 changes: 5 additions & 0 deletions
5
src/community/wfs3/src/main/resources/org/geoserver/wfs3/response/footer.ftl
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 | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,5 @@ | |||
<#-- | |||
Footer section of the GetFeatureInfo HTML output. Should close the body and the html tag. | |||
--> | |||
</body> | |||
</html> |
Oops, something went wrong.