From 839673a30c7ff5fa99ef5849a05922643fe5124c Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sat, 2 Sep 2023 14:34:02 +0200 Subject: [PATCH] Introduce WFS HTTP handler --- .../OSGI-INF/geoJsonHttpHandler.xml | 2 +- .../src/org/argeo/app/geo/CqlUtils.java | 3 +- .../http/WfsHttpHandler.java} | 62 +++++++++++-------- .../app/internal/geo/http/GmlHttpHandler.java | 31 ---------- 4 files changed, 38 insertions(+), 60 deletions(-) rename org.argeo.app.geo/src/org/argeo/app/{internal/geo/http/GeoJsonHttpHandler.java => geo/http/WfsHttpHandler.java} (76%) delete mode 100644 org.argeo.app.geo/src/org/argeo/app/internal/geo/http/GmlHttpHandler.java diff --git a/org.argeo.app.geo/OSGI-INF/geoJsonHttpHandler.xml b/org.argeo.app.geo/OSGI-INF/geoJsonHttpHandler.xml index 4fbec8f..352595b 100644 --- a/org.argeo.app.geo/OSGI-INF/geoJsonHttpHandler.xml +++ b/org.argeo.app.geo/OSGI-INF/geoJsonHttpHandler.xml @@ -1,6 +1,6 @@ - + diff --git a/org.argeo.app.geo/src/org/argeo/app/geo/CqlUtils.java b/org.argeo.app.geo/src/org/argeo/app/geo/CqlUtils.java index 8d6c138..f4413ad 100644 --- a/org.argeo.app.geo/src/org/argeo/app/geo/CqlUtils.java +++ b/org.argeo.app.geo/src/org/argeo/app/geo/CqlUtils.java @@ -12,10 +12,9 @@ import org.opengis.filter.PropertyIsEqualTo; import org.opengis.filter.expression.Literal; import org.opengis.filter.expression.PropertyName; +/** Utilities around the CQL query format. */ public class CqlUtils { - public final static String CQL_FILTER = "cql_filter"; - public static void filter(BasicSearch search, String cql) { try { filter(search, CQL.toFilter(cql)); diff --git a/org.argeo.app.geo/src/org/argeo/app/internal/geo/http/GeoJsonHttpHandler.java b/org.argeo.app.geo/src/org/argeo/app/geo/http/WfsHttpHandler.java similarity index 76% rename from org.argeo.app.geo/src/org/argeo/app/internal/geo/http/GeoJsonHttpHandler.java rename to org.argeo.app.geo/src/org/argeo/app/geo/http/WfsHttpHandler.java index ca81258..6408b40 100644 --- a/org.argeo.app.geo/src/org/argeo/app/internal/geo/http/GeoJsonHttpHandler.java +++ b/org.argeo.app.geo/src/org/argeo/app/geo/http/WfsHttpHandler.java @@ -1,6 +1,4 @@ -package org.argeo.app.internal.geo.http; - -import static org.argeo.app.geo.CqlUtils.CQL_FILTER; +package org.argeo.app.geo.http; import java.io.IOException; import java.io.InputStream; @@ -27,36 +25,65 @@ import org.geotools.data.DataUtilities; import org.geotools.data.geojson.GeoJSONWriter; import org.geotools.feature.SchemaException; import org.geotools.feature.simple.SimpleFeatureBuilder; -import org.geotools.filter.text.cql2.CQL; import org.geotools.geometry.jts.JTSFactoryFinder; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; -import org.opengis.filter.Filter; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; -public class GeoJsonHttpHandler implements HttpHandler { +/** A partially implemented WFS 2.0 server. */ +public class WfsHttpHandler implements HttpHandler { private ProvidedRepository contentRepository; + // HTTP parameters + final static String OUTPUT_FORMAT = "outputFormat"; + final static String TYPE_NAMES = "typeNames"; + final static String CQL_FILTER = "cql_filter"; + @Override public void handle(HttpExchange exchange) throws IOException { String path = HttpServerUtils.subPath(exchange); ContentSession session = HttpServerUtils.getContentSession(contentRepository, exchange); // Content content = session.get(path); - exchange.getResponseHeaders().set(HttpHeader.CONTENT_TYPE.getHeaderName(), "application/json"); - Map> parameters = HttpServerUtils.parseParameters(exchange); String cql = parameters.containsKey(CQL_FILTER) ? parameters.get(CQL_FILTER).get(0) : null; + String typeNamesStr = parameters.containsKey(TYPE_NAMES) ? parameters.get(TYPE_NAMES).get(0) : null; + String outputFormat = parameters.containsKey(OUTPUT_FORMAT) ? parameters.get(OUTPUT_FORMAT).get(0) : null; + if (outputFormat == null) { + outputFormat = "application/json"; + } + + switch (outputFormat) { + case "application/json" -> { + exchange.getResponseHeaders().set(HttpHeader.CONTENT_TYPE.getHeaderName(), "application/json"); + } + + default -> throw new IllegalArgumentException("Unexpected value: " + outputFormat); + } + + QName[] typeNames; + if (typeNamesStr != null) { + String[] arr = typeNamesStr.split(","); + typeNames = new QName[arr.length]; + for (int i = 0; i < arr.length; i++) { + typeNames[i] = NamespaceUtils.parsePrefixedName(arr[i]); + } + } else { + typeNames = new QName[] { EntityType.local.qName() }; + } if (cql != null) { Stream res = session.search((search) -> { CqlUtils.filter(search.from(path), cql); - search.getWhere().isContentClass(EntityType.local); + search.getWhere().any((f) -> { + for (QName typeName : typeNames) + f.isContentClass(typeName); + }); }); exchange.sendResponseHeaders(200, 0); @@ -65,13 +92,6 @@ public class GeoJsonHttpHandler implements HttpHandler { GeoJSONWriter geoJSONWriter = new GeoJSONWriter(exchange.getResponseBody()); geoJSONWriter.setPrettyPrinting(true); -// Writer writer = new OutputStreamWriter(exchange.getResponseBody()); -// writer.write(""" -// { -// "type": "FeatureCollection", -// "features": [ -// """); - boolean gpx = false; SimpleFeatureType TYPE; try { @@ -125,17 +145,12 @@ public class GeoJsonHttpHandler implements HttpHandler { String uuid = c.attr(LdapAttr.entryUUID); SimpleFeature feature = featureBuilder.buildFeature(uuid); -// String json = GeoJSONWriter.toGeoJSON(feature); try { geoJSONWriter.write(feature); } catch (IOException e) { throw new UncheckedIOException(e); } }); -// writer.write(""" -// ] -// } -// """); geoJSONWriter.close(); } @@ -144,9 +159,4 @@ public class GeoJsonHttpHandler implements HttpHandler { public void setContentRepository(ProvidedRepository contentRepository) { this.contentRepository = contentRepository; } - - public static void main(String[] args) throws Exception { - Filter filter = CQL.toFilter("entity:type='apafField' AND jcr:isCheckedOut=false"); - System.out.println(CQL.toCQL(filter)); - } } diff --git a/org.argeo.app.geo/src/org/argeo/app/internal/geo/http/GmlHttpHandler.java b/org.argeo.app.geo/src/org/argeo/app/internal/geo/http/GmlHttpHandler.java deleted file mode 100644 index 7213cd2..0000000 --- a/org.argeo.app.geo/src/org/argeo/app/internal/geo/http/GmlHttpHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.argeo.app.internal.geo.http; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -import org.argeo.api.acr.Content; -import org.argeo.api.acr.ContentSession; -import org.argeo.api.acr.spi.ProvidedRepository; -import org.argeo.app.geo.CqlUtils; -import org.argeo.cms.http.server.HttpServerUtils; - -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; - -public class GmlHttpHandler implements HttpHandler { - private ProvidedRepository contentRepository; - - @Override - public void handle(HttpExchange exchange) throws IOException { - String path = HttpServerUtils.subPath(exchange); - ContentSession session = HttpServerUtils.getContentSession(contentRepository, exchange); -// Content content = session.get(path); - } - - public void setContentRepository(ProvidedRepository contentRepository) { - this.contentRepository = contentRepository; - } - -} -- 2.30.2