Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GeoJSON as new output format for WMS GetFeatureInfo (3.5) #1622

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
Expand All @@ -44,7 +43,7 @@ public class GeoJsonWriter extends JsonWriter implements GeoJsonFeatureWriter, G

private static final Logger LOG = LoggerFactory.getLogger(GeoJsonWriter.class);

private final GeoJsonGeometryWriter geoJsonGeometryWriter;
private GeoJsonGeometryWriter geoJsonGeometryWriter;

private final ICRS crs;

Expand All @@ -58,10 +57,25 @@ public class GeoJsonWriter extends JsonWriter implements GeoJsonFeatureWriter, G
* @throws UnknownCRSException if "crs:84" is not known as CRS (should never happen)
*/
public GeoJsonWriter(Writer writer, ICRS crs) throws UnknownCRSException {
this(writer, crs, false);
}

/**
* Instantiates a new {@link GeoJsonWriter}.
* @param writer the writer to write the GeoJSON into, never <code>null</code>
* @param crs the target crs of the geometries, may be <code>null</code>, then
* "EPSG:4326" will be used
* @param skipGeometries <code>true</code> if geometries should not be exported,
* <code>false</code> otherwise
* @throws UnknownCRSException if "crs:84" is not known as CRS (should never happen)
*/
public GeoJsonWriter(Writer writer, ICRS crs, boolean skipGeometries) throws UnknownCRSException {
super(writer);
setIndent(" ");
setHtmlSafe(true);
this.geoJsonGeometryWriter = new GeoJsonGeometryWriter(this, crs);
if (!skipGeometries) {
this.geoJsonGeometryWriter = new GeoJsonGeometryWriter(this, crs);
}
this.crs = crs;
}

Expand Down Expand Up @@ -119,6 +133,8 @@ public void writeSingleFeature(Feature feature) throws IOException, UnknownCRSEx
}

private void writeGeometry(Feature feature) throws IOException, UnknownCRSException, TransformationException {
if (geoJsonGeometryWriter == null)
return;
List<Property> geometryProperties = feature.getGeometryProperties();
if (geometryProperties.isEmpty()) {
name("geometry").nullValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;

/**
Expand Down Expand Up @@ -56,6 +57,39 @@ public void testWrite() throws Exception {

}

@Test
public void testWrite_skipGeometries() throws Exception {
StringWriter featureAsJson = new StringWriter();
GeoJsonWriter geoJsonFeatureWriter = new GeoJsonWriter(featureAsJson, null, true);
Feature cadastralZoning = parseFeature("CadastralZoning.gml");

geoJsonFeatureWriter.startFeatureCollection();
geoJsonFeatureWriter.write(cadastralZoning);
geoJsonFeatureWriter.endFeatureCollection();

String featureCollection = featureAsJson.toString();

assertThat(featureCollection, JsonPathMatchers.isJson());
assertThat(featureCollection, hasJsonPath("$.type", is("FeatureCollection")));
assertThat(featureCollection, hasJsonPath("$.features.length()", is(1)));
assertThat(featureCollection, hasJsonPath("$.features[0].type", is("Feature")));
assertThat(featureCollection, hasNoJsonPath("$.features[0].srsName"));
assertThat(featureCollection, hasJsonPath("$.features[0].id", is("CP_CADASTRALZONING_Bundesland_02")));
assertThat(featureCollection, not(hasJsonPath("$.features[0].geometry")));
assertThat(featureCollection, hasJsonPath("$.features[0].properties.label", is("02")));
assertThat(featureCollection, hasJsonPath("$.features[0].properties.originalMapScaleDenominator", is(10)));
assertThat(featureCollection,
hasJsonPath("$.features[0].properties.beginLifespanVersion", is("2009-12-15T08:04:54Z")));
assertThat(featureCollection, hasJsonPath("$.features[0].properties.estimatedAccuracy.uom", is("m")));
assertThat(featureCollection, hasJsonPath("$.features[0].properties.inspireId.Identifier.localId",
is("urn:adv:oid:DEHHALKA10000005")));
assertThat(featureCollection, hasJsonPath(
"$.features[0].properties.name.GeographicalName.spelling.SpellingOfName.text", is("Hamburg")));
assertThat(featureCollection,
hasJsonPath("$.features[0].properties.levelName.LocalisedCharacterString.value", is("Bundesland")));

}

@Test
public void testWrite_SingleFeature() throws Exception {
StringWriter featureAsJson = new StringWriter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
Expand All @@ -52,6 +53,8 @@ public interface FeatureInfoContext {

XMLStreamWriter getXmlWriter() throws IOException, XMLStreamException;

Writer getWriter() throws IOException;

void sendRedirect(String location) throws IOException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,25 @@ Occam Labs UG (haftungsbeschränkt)
----------------------------------------------------------------------------*/
package org.deegree.featureinfo;

import static org.slf4j.LoggerFactory.getLogger;

import java.io.IOException;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import javax.xml.stream.XMLStreamException;

import org.deegree.featureinfo.serializing.FeatureInfoGmlWriter;
import org.deegree.featureinfo.serializing.FeatureInfoSerializer;
import org.deegree.featureinfo.serializing.GeoJsonFeatureInfoSerializer;
import org.deegree.featureinfo.serializing.PlainTextFeatureInfoSerializer;
import org.deegree.featureinfo.serializing.TemplateFeatureInfoSerializer;
import org.deegree.featureinfo.serializing.XsltFeatureInfoSerializer;
import org.deegree.gml.GMLVersion;
import org.deegree.workspace.Workspace;
import org.slf4j.Logger;

import javax.xml.stream.XMLStreamException;
import java.io.IOException;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import static org.slf4j.LoggerFactory.getLogger;

/**
* Responsible for managing feature info output formats and their serializers.
*
Expand Down Expand Up @@ -112,6 +112,14 @@ public void addOrReplaceXsltFormat(String format, URL xsltUrl, GMLVersion versio
featureInfoSerializers.put(format, xslt);
}

public void addOrReplaceGeoJsonFormat(String format, boolean allowOtherCrsThanWGS84,
boolean allowExportOfGeometries) {
LOG.debug("Adding GeoJson feature info format");
GeoJsonFeatureInfoSerializer geoJsonSerializer = new GeoJsonFeatureInfoSerializer(allowOtherCrsThanWGS84,
allowExportOfGeometries);
featureInfoSerializers.put(format, geoJsonSerializer);
}

public Set<String> getSupportedFormats() {
return featureInfoSerializers.keySet();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,18 @@ public class FeatureInfoParams {

private ICRS crs;

private final ICRS infoCrs;

public FeatureInfoParams(Map<String, String> nsBindings, FeatureCollection col, String format,
boolean withGeometries, String schemaLocation, FeatureType type, ICRS crs) {
boolean withGeometries, String schemaLocation, FeatureType type, ICRS crs, ICRS infoCrs) {
this.nsBindings = nsBindings;
this.featureCollection = col;
this.format = format;
this.withGeometries = withGeometries;
this.schemaLocation = schemaLocation;
this.featureType = type;
this.crs = crs;
this.infoCrs = infoCrs;
}

/**
Expand Down Expand Up @@ -128,4 +131,11 @@ public ICRS getCrs() {
return crs;
}

/**
* @return the CRS of the values to return
*/
public ICRS getInfoCrs() {
return infoCrs;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*----------------------------------------------------------------------------
This file is part of deegree
Copyright (C) 2001-2024 by:
- Department of Geography, University of Bonn -
and
- lat/lon GmbH -
and others

This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option)
any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Contact information:

e-mail: info@deegree.org
website: http://www.deegree.org/
----------------------------------------------------------------------------*/
package org.deegree.featureinfo.serializing;

import org.deegree.cs.coordinatesystems.ICRS;
import org.deegree.cs.exceptions.TransformationException;
import org.deegree.cs.exceptions.UnknownCRSException;
import org.deegree.feature.Feature;
import org.deegree.feature.FeatureCollection;
import org.deegree.featureinfo.FeatureInfoContext;
import org.deegree.featureinfo.FeatureInfoParams;
import org.deegree.geojson.GeoJsonFeatureWriter;
import org.deegree.geojson.GeoJsonWriter;
import org.slf4j.Logger;

import java.io.IOException;

import static org.slf4j.LoggerFactory.getLogger;

/**
* {@link FeatureInfoSerializer} to serialize feature info result as GeoJson.
*
* @author <a href="mailto:goltz@lat-lon.de">Lyn Goltz </a>
*/
public class GeoJsonFeatureInfoSerializer implements FeatureInfoSerializer {

private static final Logger LOG = getLogger(GeoJsonFeatureInfoSerializer.class);

private final boolean allowOtherCrsThanWGS84;

private final boolean allowExportOfGeometries;

public GeoJsonFeatureInfoSerializer(boolean allowOtherCrsThanWGS84, boolean allowExportOfGeometries) {
this.allowExportOfGeometries = allowExportOfGeometries;
this.allowOtherCrsThanWGS84 = allowOtherCrsThanWGS84;
}

@Override
public void serialize(FeatureInfoParams params, FeatureInfoContext context) {
ICRS crs = detectCrs(params);
boolean skipGeometries = detectSkipGeometries(params);
try (GeoJsonFeatureWriter geoJsonStreamWriter = new GeoJsonWriter(context.getWriter(), crs, skipGeometries)) {
geoJsonStreamWriter.startFeatureCollection();
FeatureCollection featureCollection = params.getFeatureCollection();
for (Feature feature : featureCollection) {
geoJsonStreamWriter.write(feature);
}
geoJsonStreamWriter.endFeatureCollection();
}
catch (IOException | TransformationException | UnknownCRSException e) {
LOG.error("GeoJson GFI response could not be written", e);
}
}

private boolean detectSkipGeometries(FeatureInfoParams params) {
if (allowExportOfGeometries && params.isWithGeometries())
return false;
return true;
}

private ICRS detectCrs(FeatureInfoParams params) {
if (allowOtherCrsThanWGS84 && params.getInfoCrs() != null) {
return params.getInfoCrs();
}
return null;
}

}
Loading