Skip to content

Commit 616090c

Browse files
authored
Merge pull request #380 from ckan/320-wkt-support-spatial
[#320] Support geometries defined as WKT
2 parents 0209972 + 05eff64 commit 616090c

2 files changed

Lines changed: 82 additions & 13 deletions

File tree

ckanext/dcat/profiles/base.py

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ def _add_agent_to_graph(self, subject_ref, predicate, agent_dict):
972972
self.g.add((org_ref, FOAF.name, Literal(sub_org["name"])))
973973

974974
return agent_ref
975-
975+
976976
def _add_contact_to_graph(self, subject, predicate, contact):
977977
contact_uri = contact.get("uri")
978978
if contact_uri:
@@ -1008,43 +1008,78 @@ def _add_contact_to_graph(self, subject, predicate, contact):
10081008
"url",
10091009
_type=URIRef,
10101010
)
1011-
10121011

10131012
def _add_spatial_value_to_graph(self, spatial_ref, predicate, value):
10141013
"""
1015-
Adds spatial triples to the graph. Assumes that value is a GeoJSON string
1016-
or object.
1014+
Adds spatial triples to the graph. Assumes that value is a WKT string or a
1015+
GeoJSON string or object.
10171016
"""
1017+
value_is_wkt = None
1018+
value_is_geojson = None
1019+
10181020
spatial_formats = aslist(
10191021
config.get("ckanext.dcat.output_spatial_format", DEFAULT_SPATIAL_FORMATS)
10201022
)
10211023

10221024
if isinstance(value, str):
10231025
try:
1024-
value = json.loads(value)
1026+
value = json.dumps(json.loads(value))
1027+
value_is_geojson = True
10251028
except (TypeError, ValueError):
1026-
return
1029+
try:
1030+
wkt.loads(value)
1031+
value_is_wkt = True
1032+
except ValueError:
1033+
return
1034+
elif isinstance(value, dict):
1035+
value = json.dumps(value)
1036+
value_is_geojson = True
1037+
else:
1038+
return
10271039

10281040
if "wkt" in spatial_formats:
1029-
# WKT, because GeoDCAT-AP says so
1030-
try:
1041+
if value_is_geojson:
1042+
# Transform geojson -> wkt
1043+
try:
1044+
wkt_value = wkt.dumps(json.loads(value), decimals=4)
1045+
except (TypeError, ValueError, InvalidGeoJSONException):
1046+
wkt_value = None
1047+
else:
1048+
wkt_value = value
1049+
1050+
if wkt_value:
10311051
self.g.add(
10321052
(
10331053
spatial_ref,
10341054
predicate,
10351055
Literal(
1036-
wkt.dumps(value, decimals=4),
1056+
wkt_value,
10371057
datatype=GSP.wktLiteral,
10381058
),
10391059
)
10401060
)
1041-
except (TypeError, ValueError, InvalidGeoJSONException):
1042-
pass
10431061

10441062
if "geojson" in spatial_formats:
1045-
# GeoJSON
1046-
self.g.add((spatial_ref, predicate, Literal(json.dumps(value), datatype=GEOJSON_IMT)))
1063+
if value_is_wkt:
1064+
# Transform wkt -> geojson
1065+
try:
1066+
geojson_value = json.dumps(wkt.loads(value))
1067+
except (TypeError, ValueError, InvalidGeoJSONException):
1068+
geojson_value = None
1069+
else:
1070+
geojson_value = value
10471071

1072+
if geojson_value:
1073+
self.g.add(
1074+
(
1075+
spatial_ref,
1076+
predicate,
1077+
Literal(
1078+
geojson_value,
1079+
datatype=GEOJSON_IMT
1080+
)
1081+
)
1082+
)
10481083

10491084
def _add_spatial_to_dict(self, dataset_dict, key, spatial):
10501085
if spatial.get(key):

ckanext/dcat/tests/profiles/dcat_ap_2/test_euro_dcatap_2_profile_serialize.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,40 @@ def test_spatial(self):
198198
wkt_cent = wkt.dumps(json.loads(extras['spatial_centroid']), decimals=4)
199199
assert self._triple(g, spatial, DCAT.centroid, wkt_cent, GSP.wktLiteral)
200200

201+
def test_spatial_input_in_wkt(self):
202+
dataset = {
203+
'id': '4b6fe9ca-dc77-4cec-92a4-55c6624a5bd6',
204+
'name': 'test-dataset',
205+
'extras': [
206+
{'key': 'spatial_uri', 'value': 'http://sws.geonames.org/6361390/'},
207+
{'key': 'spatial_text', 'value': 'Tarragona'},
208+
{'key': 'spatial', 'value': 'POLYGON ((1.1871 41.0786, 1.1871 41.1655, 1.3752 41.1655, 1.3752 41.0786, 1.1871 41.0786))'},
209+
{'key': 'spatial_bbox', 'value': 'POLYGON ((1.1871 41.0786, 1.1871 41.1655, 1.3752 41.1655, 1.3752 41.0786, 1.1871 41.0786))'},
210+
{'key': 'spatial_centroid', 'value': 'POINT (2.2811 42.122)'},
211+
212+
]
213+
}
214+
extras = self._extras(dataset)
215+
216+
s = RDFSerializer(profiles=DCAT_AP_PROFILES)
217+
g = s.g
218+
219+
dataset_ref = s.graph_from_dataset(dataset)
220+
221+
spatial = self._triple(g, dataset_ref, DCT.spatial, None)[2]
222+
assert spatial
223+
assert str(spatial) == extras['spatial_uri']
224+
assert self._triple(g, spatial, RDF.type, DCT.Location)
225+
assert self._triple(g, spatial, SKOS.prefLabel, extras['spatial_text'])
226+
227+
assert len([t for t in g.triples((spatial, LOCN.geometry, None))]) == 1
228+
assert len([t for t in g.triples((spatial, DCAT.bbox, None))]) == 1
229+
assert len([t for t in g.triples((spatial, DCAT.centroid, None))]) == 1
230+
231+
assert self._triple(g, spatial, LOCN.geometry, extras['spatial'], GSP.wktLiteral)
232+
assert self._triple(g, spatial, DCAT.bbox, extras['spatial_bbox'], GSP.wktLiteral)
233+
assert self._triple(g, spatial, DCAT.centroid, extras['spatial_centroid'], GSP.wktLiteral)
234+
201235
@pytest.mark.ckan_config("ckanext.dcat.output_spatial_format", "geojson")
202236
def test_spatial_geojson(self):
203237
dataset = {

0 commit comments

Comments
 (0)