import org.argeo.api.acr.Content;
import org.argeo.api.acr.ContentSession;
-import org.argeo.api.acr.DName;
import org.argeo.api.acr.NamespaceUtils;
import org.argeo.api.acr.ldap.LdapAttr;
import org.argeo.api.acr.search.AndFilter;
import org.argeo.app.api.EntityName;
import org.argeo.app.api.EntityType;
import org.argeo.app.api.WGS84PosName;
+import org.argeo.app.api.geo.FeatureAdapter;
import org.argeo.app.geo.CqlUtils;
-import org.argeo.app.geo.GeoJSon;
+import org.argeo.app.geo.GeoJson;
+import org.argeo.app.geo.GeoUtils;
import org.argeo.app.geo.GpxUtils;
import org.argeo.app.geo.JTS;
+import org.argeo.cms.acr.json.AcrJsonUtils;
import org.argeo.cms.http.HttpHeader;
import org.argeo.cms.http.server.HttpServerUtils;
import org.argeo.cms.util.LangUtils;
-import org.geotools.data.DataUtilities;
-import org.geotools.data.geojson.GeoJSONWriter;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.NameImpl;
-import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
-import org.geotools.geometry.jts.JTSFactoryFinder;
+import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.wfs.GML;
import org.geotools.wfs.GML.Version;
import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.opengis.feature.GeometryAttribute;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.Name;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
final static String OUTPUT_FORMAT = "outputFormat";
final static String TYPE_NAMES = "typeNames";
final static String CQL_FILTER = "cql_filter";
+ final static String BBOX = "bbox";
private final Map<QName, FeatureAdapter> featureAdapters = new HashMap<>();
ContentSession session = HttpServerUtils.getContentSession(contentRepository, exchange);
// Content content = session.get(path);
+ // PARAMETERS
Map<String, List<String>> parameters = HttpServerUtils.parseParameters(exchange);
String cql = getKvpParameter(parameters, CQL_FILTER);
String typeNamesStr = getKvpParameter(parameters, TYPE_NAMES);
if (outputFormat == null) {
outputFormat = "application/json";
}
+ String bboxStr = getKvpParameter(parameters, BBOX);
+ log.debug(bboxStr);
+ final Envelope bbox;
+ if (bboxStr != null) {
+ String srs;
+ String[] arr = bboxStr.split(",");
+ // TODO check SRS and convert to WGS84
+ double minLat = Double.parseDouble(arr[0]);
+ double minLon = Double.parseDouble(arr[1]);
+ double maxLat = Double.parseDouble(arr[2]);
+ double maxLon = Double.parseDouble(arr[3]);
+ if (arr.length == 5) {
+ srs = arr[4];
+ } else {
+ srs = null;
+ }
+
+ if (srs != null && !srs.equals(GeoUtils.EPSG_4326)) {
+ try {
+ // TODO optimise
+ CoordinateReferenceSystem sourceCRS = CRS.decode(srs);
+ CoordinateReferenceSystem targetCRS = CRS.decode(GeoUtils.EPSG_4326);
+ MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
+ bbox = org.geotools.geometry.jts.JTS.transform(
+ new Envelope(new Coordinate(minLat, minLon), new Coordinate(maxLat, maxLon)), transform);
+ } catch (FactoryException | TransformException e) {
+ throw new IllegalArgumentException("Cannot convert bounding box", e);
+ // bbox = null;
+ }
+ } else {
+ bbox = new Envelope(new Coordinate(minLat, minLon), new Coordinate(maxLat, maxLon));
+ }
+ } else {
+ bbox = null;
+ }
switch (outputFormat) {
case "application/json" -> {
if (typeNames.size() > 1)
throw new UnsupportedOperationException("Only one type name is currently supported");
+ // QUERY
Stream<Content> res = session.search((search) -> {
if (cql != null) {
CqlUtils.filter(search.from(path), cql);
} else {
- search.from(path).where((and) -> {
- });
+ search.from(path);
}
-// search.getWhere().any((f) -> {
for (QName typeName : typeNames) {
FeatureAdapter featureAdapter = featureAdapters.get(typeName);
if (featureAdapter == null)
// f.isContentClass(typeName);
featureAdapter.addConstraintsForFeature((AndFilter) search.getWhere(), typeName);
}
-// });
+
+ if (bbox != null) {
+ search.getWhere().any((or) -> {
+ or.all((and) -> {
+ and.gte(EntityName.minLat, bbox.getMinX());
+ and.gte(EntityName.minLon, bbox.getMinY());
+ and.lte(EntityName.maxLat, bbox.getMaxX());
+ and.lte(EntityName.maxLon, bbox.getMaxY());
+ });
+ or.all((and) -> {
+ and.gte(WGS84PosName.lat, bbox.getMinX());
+ and.gte(WGS84PosName.lon, bbox.getMinY());
+ and.lte(WGS84PosName.lat, bbox.getMaxX());
+ and.lte(WGS84PosName.lon, bbox.getMaxY());
+ });
+ });
+ }
});
exchange.sendResponseHeaders(200, 0);
featureAdapter = featureAdapters.get(typeName);
}
- Geometry defaultGeometry = featureAdapter != null ? featureAdapter.getDefaultGeometry(c, typeName)
- : getDefaultGeometry(c);
- if (defaultGeometry == null)
- return;
- generator.writeStartObject();
- generator.write("type", "Feature");
- String featureId = getFeatureId(c);
- if (featureId != null)
- generator.write("id", featureId);
- GeoJSon.writeBBox(generator, defaultGeometry);
- GeoJSon.writeGeometry(generator, defaultGeometry);
-
- generator.writeStartObject("properties");
- writeTimeProperties(generator, c);
- writeProperties(generator, c);
+ boolean geometryWritten = false;
+// if (typeName.getLocalPart().equals("fieldSimpleFeature")) {
+// Content area = c.getContent("place.geom.json").orElse(null);
+// if (area != null) {
+// generator.writeStartObject();
+// generator.write("type", "Feature");
+// String featureId = getFeatureId(c);
+// if (featureId != null)
+// generator.write("id", featureId);
+//
+// generator.flush();
+// try (InputStream in = area.open(InputStream.class)) {
+// out.write(",\"geometry\":".getBytes());
+// StreamUtils.copy(in, out);
+// //out.flush();
+// } catch (Exception e) {
+// log.error(c.getPath() + " : " + e.getMessage());
+// } finally {
+// }
+// geometryWritten = true;
+// }else {
+// return;
+// }
+// }
+
+ if (!geometryWritten) {
+
+ Geometry defaultGeometry = featureAdapter != null ? featureAdapter.getDefaultGeometry(c, typeName)
+ : getDefaultGeometry(c);
+ if (defaultGeometry == null)
+ return;
+ generator.writeStartObject();
+ generator.write("type", "Feature");
+ String featureId = getFeatureId(c);
+ if (featureId != null)
+ generator.write("id", featureId);
+
+ GeoJson.writeBBox(generator, defaultGeometry);
+ generator.writeStartObject(GeoJson.GEOMETRY);
+ GeoJson.writeGeometry(generator, defaultGeometry);
+ generator.writeEnd();// geometry object
+ }
+ generator.writeStartObject(GeoJson.PROPERTIES);
+ AcrJsonUtils.writeTimeProperties(generator, c);
if (featureAdapter != null)
featureAdapter.writeProperties(generator, c, typeName);
+ else
+ writeProperties(generator, c);
generator.writeEnd();// properties object
generator.writeEnd();// feature object
return uuid;
}
- private final QName JCR_CREATED = NamespaceUtils.parsePrefixedName("jcr:created");
-
- private final QName JCR_LAST_MODIFIED = NamespaceUtils.parsePrefixedName("jcr:lastModified");
-
- protected void writeTimeProperties(JsonGenerator g, Content content) {
- String creationDate = content.attr(DName.creationdate);
- if (creationDate == null)
- creationDate = content.attr(JCR_CREATED);
- if (creationDate != null)
- g.write(DName.creationdate.get(), creationDate);
- String lastModified = content.attr(DName.getlastmodified);
- if (lastModified == null)
- lastModified = content.attr(JCR_LAST_MODIFIED);
- if (lastModified != null)
- g.write(DName.getlastmodified.get(), lastModified);
- }
-
- protected void writeProperties(JsonGenerator generator, Content content) {
+ public void writeProperties(JsonGenerator generator, Content content) {
String path = content.getPath();
generator.write("path", path);
if (content.hasContentClass(EntityType.local)) {
}
- protected void encodeCollectionAsGeoJSonOld(Stream<Content> features, OutputStream out) throws IOException {
-
- // BODY PROCESSING
- try (GeoJSONWriter geoJSONWriter = new GeoJSONWriter(out)) {
- geoJSONWriter.setPrettyPrinting(true);
- geoJSONWriter.setEncodeFeatureBounds(true);
-
- boolean gpx = true;
- SimpleFeatureType TYPE;
- try {
- if (gpx)
- TYPE = DataUtilities.createType("Content",
- "the_geom:Polygon:srid=4326,path:String,type:String,name:String");
- else
- TYPE = DataUtilities.createType("Content",
- "the_geom:Point:srid=4326,path:String,type:String,name:String");
- } catch (SchemaException e) {
- throw new RuntimeException(e);
- }
- SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
- GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
-
- features.forEach((c) -> {
- Geometry the_geom;
- if (gpx) {// experimental
- Content area = c.getContent("gpx/area.gpx").orElse(null);
- if (area == null)
- return;
- try (InputStream in = area.open(InputStream.class)) {
- SimpleFeature feature = GpxUtils.parseGpxToPolygon(in);
- the_geom = (Geometry) feature.getDefaultGeometry();
- } catch (IOException e) {
- throw new UncheckedIOException("Cannot parse " + c, e);
- }
- } else {
- if (!c.hasContentClass(EntityType.geopoint))
- return;
-
- double latitude = c.get(WGS84PosName.lat, Double.class).get();
- double longitude = c.get(WGS84PosName.lon, Double.class).get();
-
- Coordinate coordinate = new Coordinate(longitude, latitude);
- the_geom = geometryFactory.createPoint(coordinate);
-
- }
-
- featureBuilder.add(the_geom);
- String pth = c.getPath();
- featureBuilder.add(pth);
- if (c.hasContentClass(EntityType.local)) {
- String type = c.attr(EntityName.type);
- featureBuilder.add(type);
- } else {
- List<QName> contentClasses = c.getContentClasses();
- if (!contentClasses.isEmpty()) {
- featureBuilder.add(NamespaceUtils.toPrefixedName(contentClasses.get(0)));
- }
- }
- featureBuilder.add(NamespaceUtils.toPrefixedName(c.getName()));
-
- String uuid = c.attr(LdapAttr.entryUUID);
-
- SimpleFeature feature = featureBuilder.buildFeature(uuid);
- try {
- geoJSONWriter.write(feature);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- });
- }
- }
-
protected void encodeCollectionAsGML(Stream<Content> features, OutputStream out) throws IOException {
String entityType = "entity";
URL schemaLocation = getClass().getResource("/org/argeo/app/api/entity.xsd");