1 package org
.argeo
.app
.geo
.acr
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
5 import java
.io
.InputStreamReader
;
6 import java
.io
.OutputStream
;
8 import java
.io
.UncheckedIOException
;
9 import java
.nio
.charset
.StandardCharsets
;
10 import java
.util
.ArrayList
;
11 import java
.util
.Collections
;
12 import java
.util
.List
;
14 import javax
.xml
.namespace
.QName
;
16 import org
.argeo
.api
.acr
.Content
;
17 import org
.argeo
.api
.acr
.ContentName
;
18 import org
.argeo
.api
.acr
.DName
;
19 import org
.argeo
.api
.acr
.QNamed
;
20 import org
.argeo
.api
.cms
.CmsLog
;
21 import org
.argeo
.app
.api
.EntityName
;
22 import org
.argeo
.app
.api
.EntityType
;
23 import org
.argeo
.app
.api
.WGS84PosName
;
24 import org
.argeo
.app
.geo
.GeoJson
;
25 import org
.argeo
.app
.geo
.JTS
;
26 import org
.locationtech
.jts
.geom
.Coordinate
;
27 import org
.locationtech
.jts
.geom
.Envelope
;
28 import org
.locationtech
.jts
.geom
.Geometry
;
29 import org
.locationtech
.jts
.geom
.GeometryCollection
;
30 import org
.locationtech
.jts
.geom
.Point
;
32 import jakarta
.json
.Json
;
33 import jakarta
.json
.JsonObject
;
34 import jakarta
.json
.JsonReader
;
35 import jakarta
.json
.stream
.JsonGenerator
;
36 import jakarta
.json
.stream
.JsonParsingException
;
38 /** Utilities around entity types related to geography. */
39 public class GeoEntityUtils
{
40 private final static CmsLog log
= CmsLog
.getLog(GeoEntityUtils
.class);
42 public static final String _GEOM_JSON
= ".geom.json";
44 public static void putGeometry(Content c
, QNamed name
, Geometry geometry
) {
45 putGeometry(c
, name
.qName(), geometry
);
48 public static void putGeometry(Content c
, QName name
, Geometry geometry
) {
49 QName jsonFileName
= getJsonFileName(name
);
50 Content geom
= c
.soleChild(jsonFileName
).orElseGet(
51 () -> c
.add(jsonFileName
, Collections
.singletonMap(DName
.getcontenttype
.qName(), "application/json")));
52 try (OutputStream out
= geom
.open(OutputStream
.class)) {
53 JsonGenerator g
= Json
.createGenerator(out
);
55 GeoJson
.writeGeometry(g
, geometry
);
58 } catch (IOException e
) {
59 throw new UncheckedIOException("Cannot add geometry " + name
+ " to " + c
, e
);
62 // try (BufferedReader in = new BufferedReader(
63 // new InputStreamReader(geom.open(InputStream.class), StandardCharsets.UTF_8))) {
64 // System.out.println(in.readLine());
65 // } catch (IOException e) {
66 // throw new UncheckedIOException("Cannot parse " + c, e);
71 public static boolean hasGeometry(Content c
, QNamed name
) {
72 return hasGeometry(c
, name
.qName());
75 public static boolean hasGeometry(Content c
, QName name
) {
76 QName jsonFileName
= getJsonFileName(name
);
77 return c
.hasChild(jsonFileName
);
80 public static <T
extends Geometry
> T
getGeometry(Content c
, QNamed name
, Class
<T
> clss
) {
81 return getGeometry(c
, name
.qName(), clss
);
84 public static <T
extends Geometry
> T
getGeometry(Content c
, QName name
, Class
<T
> clss
) {
85 QName jsonFileName
= getJsonFileName(name
);
86 Content geom
= c
.soleChild(jsonFileName
).orElse(null);
89 // try (Reader in = new InputStreamReader(geom.open(InputStream.class), StandardCharsets.UTF_8)) {
90 // String json = StreamUtils.toString(new BufferedReader(in));
91 // System.out.println("JSON:\n" + json);
92 // } catch (IOException e1) {
93 // // TODO Auto-generated catch block
94 // e1.printStackTrace();
96 try (Reader in
= new InputStreamReader(geom
.open(InputStream
.class), StandardCharsets
.UTF_8
)) {
97 JsonReader jsonReader
= Json
.createReader(in
);
98 JsonObject jsonObject
= jsonReader
.readObject();
99 T readGeom
= GeoJson
.readGeometry(jsonObject
, clss
);
101 } catch (IOException e
) {
102 throw new UncheckedIOException("Cannot parse " + c
, e
);
103 } catch (JsonParsingException e
) {
104 if (log
.isTraceEnabled())
105 log
.warn("Invalid GeoJson for " + geom
);
106 // json is invalid, returning null
111 private static QName
getJsonFileName(QName name
) {
112 QName jsonFileName
= new ContentName(name
.getNamespaceURI(), name
.getLocalPart() + _GEOM_JSON
);
116 public static Point
toPoint(Content c
) {
117 if (c
.containsKey(WGS84PosName
.lon
) && c
.containsKey(WGS84PosName
.lat
)) {
118 Double lat
= c
.get(WGS84PosName
.lat
, Double
.class).orElseThrow();
119 Double lon
= c
.get(WGS84PosName
.lon
, Double
.class).orElseThrow();
120 return JTS
.GEOMETRY_FACTORY_WGS84
.createPoint(new Coordinate(lat
, lon
));
121 // Double alt = c.get(WGS84PosName.alt, Double.class).orElse(null);
122 // return JTS.GEOMETRY_FACTORY_WGS84
123 // .createPoint(alt != null ? new Coordinate(lat, lon, alt) : new Coordinate(lat, lon));
128 public static GeometryCollection
getGeometries(Content entity
) {
129 List
<Geometry
> geoms
= new ArrayList
<>();
130 Point geoPoint
= toPoint(entity
);
131 if (geoPoint
!= null)
134 Geometry place
= getGeometry(entity
, EntityName
.place
.qName(), Geometry
.class);
140 GeometryCollection geometryCollection
= JTS
.GEOMETRY_FACTORY_WGS84
141 .createGeometryCollection(geoms
.toArray(new Geometry
[geoms
.size()]));
142 return geometryCollection
;
145 public static void updateBoundingBox(Content entity
) {
146 GeometryCollection geometryCollection
= getGeometries(entity
);
147 if (geometryCollection
== null)
149 entity
.addContentClasses(EntityType
.geobounded
.qName());
151 Envelope bbox
= geometryCollection
.getEnvelopeInternal();
152 entity
.put(EntityName
.minLat
, bbox
.getMinX());
153 entity
.put(EntityName
.minLon
, bbox
.getMinY());
154 entity
.put(EntityName
.maxLat
, bbox
.getMaxX());
155 entity
.put(EntityName
.maxLon
, bbox
.getMaxY());
158 public static void updateBoundingBox(Content entity
, QName prop
) {
159 Geometry geom
= getGeometry(entity
, prop
, Geometry
.class);
162 entity
.addContentClasses(EntityType
.geobounded
.qName());
164 Envelope bbox
= geom
.getEnvelopeInternal();
165 entity
.put(EntityName
.minLat
, bbox
.getMinX());
166 entity
.put(EntityName
.minLon
, bbox
.getMinY());
167 entity
.put(EntityName
.maxLat
, bbox
.getMaxX());
168 entity
.put(EntityName
.maxLon
, bbox
.getMaxY());
172 private GeoEntityUtils() {