Skip to content

Commit 78d1104

Browse files
committed
feat: generate the csw config
1 parent abe3312 commit 78d1104

2 files changed

Lines changed: 118 additions & 28 deletions

File tree

src/datasync/dms.py

Lines changed: 114 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from pygeometa.schemas.iso19139 import ISO19139OutputSchema
55

66
from .libs.helpers import get_anytext
7-
from .settings import log
7+
from .settings import DMS_DATASETS_BASE, log
88

99
app = typer.Typer()
1010

@@ -13,19 +13,17 @@
1313

1414
def to_iso19139(metadata: dict) -> str:
1515
loaded = orjson.loads(metadata)
16-
log.debug(loaded, id=loaded.get("identification").get("identifier"))
16+
log.debug(loaded, id=loaded.get("identification", {}).get("identifier"))
1717
try:
1818
xml = iso.write(loaded)
1919
return xml
2020
except Exception as e:
21-
log.exception(e, id=loaded.get("identification").get("identifier"))
21+
log.exception(e, id=loaded.get("identification", {}).get("identifier"))
2222
return ""
2323

2424

2525
@app.command()
26-
def generate_csw_metadata(
27-
base_url: str = "https://s3-int-1/dms-test/dms/tables/", lang="en"
28-
):
26+
def generate_csw_metadata(base_url: str = DMS_DATASETS_BASE, lang="en"):
2927
# TODO: localize the output based on the language in input
3028

3129
conn = duckdb.connect()
@@ -87,31 +85,58 @@ def generate_csw_metadata(
8785

8886
log.debug(spatial)
8987

90-
identification = resources.select("""
91-
id,
88+
descriptions_structure = datasets.aggregate(
89+
"json_group_structure(metadata->'$.descriptions[*]') as stucture"
90+
).fetchone()[0]
91+
92+
log.debug("Generated schema of abstract", structure=descriptions_structure)
93+
94+
descriptions = (
95+
resources.set_alias("r")
96+
.join(datasets.set_alias("d"), condition="r.dataset_id = d.id")
97+
.select(
98+
f"r.id, unnest(json_transform(d.metadata->'$.descriptions[*]', '{descriptions_structure}'), recursive := true)" # noqa: E501
99+
)
100+
)
101+
log.debug(descriptions)
102+
103+
abstracts = descriptions.filter(
104+
(
105+
duckdb.ColumnExpression("descriptionType")
106+
== duckdb.ConstantExpression("Abstract")
107+
)
108+
and (duckdb.ColumnExpression("lang") == duckdb.ConstantExpression(lang)),
109+
).aggregate("id, lang, string_agg(description, '\n') as description")
110+
log.debug(abstracts)
111+
112+
identification = conn.sql("""
113+
from resources as r
114+
join datasets as d on r.dataset_id = d.id
115+
left join abstracts as a on a.id = r.id
116+
select
117+
r.id,
92118
{
93-
identifier: id,
119+
identifier: r.id,
94120
-- TODO: these needs to be read from the dataset
95-
language: metadata->'language',
121+
language: d.metadata->'$.language',
96122
-- TODO: these is probably a combination
97-
title: title,
123+
title: r.title,
98124
fee: 'None',
99125
status: 'completed',
100126
-- TODO: these needs to be read from the dataset
101127
rights: '',
102-
-- TODO: these needs to be read from the dataset
103-
abstract: '',
104-
url: uri,
128+
abstract: a.description,
129+
url: r.uri,
105130
dates: {
106-
creation: created_at,
107-
revision: last_modified_at
131+
creation: r.created_at,
132+
revision: r.last_modified_at
108133
},
109134
extents: {
110-
spatial: case when extent is not null then [
135+
spatial: case when r.extent is not null then [
111136
{
112137
bbox: [
113-
ST_XMIN(extent), ST_YMIN(extent),
114-
ST_XMAX(extent), ST_YMAX(extent),
138+
ST_XMIN(r.extent), ST_YMIN(r.extent),
139+
ST_XMAX(r.extent), ST_YMAX(r.extent),
115140
],
116141
crs: 4326
117142
}
@@ -126,13 +151,14 @@ def generate_csw_metadata(
126151
},
127152
license: {
128153
-- need to join with dataset to read those!
129-
"name": coalesce(metadata->>'$.rightsList[0].rights', 'All rights reserved'),
130-
"uri": coalesce(metadata->>'$.rightsList[0].rightsUri', ''),
154+
"name": coalesce('All rights reserved'),
155+
"uri": coalesce(''),
131156
},
132157
keywords: {
133158
"default": {
134-
keywords_type: 'theme',
135-
keywords: [],
159+
-- need to join with dataset to read those!
160+
keywords_type: 'theme',
161+
keywords: [],
136162
}
137163
},
138164
}::json as identification
@@ -181,6 +207,13 @@ def generate_csw_metadata(
181207
)
182208
)
183209

210+
contributors_csw = contributions.aggregate(
211+
"dataset_id, string_agg(last_name || ', ' || first_name, ';') as contributors",
212+
group_expr="dataset_id",
213+
)
214+
215+
log.debug(contributors_csw)
216+
184217
log.debug(contacts)
185218

186219
distribution = resources.select("""
@@ -203,7 +236,8 @@ def generate_csw_metadata(
203236

204237
res = conn.sql(
205238
"""
206-
select m.id, {
239+
select r.* rename (metadata as res_metadata),
240+
{
207241
mcf: { version: 1.0 },
208242
metadata: m.metadata,
209243
identification: i.identification,
@@ -212,22 +246,74 @@ def generate_csw_metadata(
212246
distribution: d.distribution,
213247
contact: c.contact
214248
}::json as metadata
215-
from metadata as m
249+
from resources as r
250+
join metadata as m on r.id = m.id
216251
join identification as i on m.id = i.id
217252
join content_info as ci on ci.id = m.id
218253
join spatial as sp on sp.id = m.id
219254
join distribution as d on d.id = m.id
220255
join contacts as c on m.dataset_id = c.dataset_id
221-
222256
"""
223257
)
224258
log.debug(res)
225259

226-
iso_xml = res.select("id, to_iso19139(metadata) as xml")
260+
iso_xml = res.select("*, to_iso19139(metadata) as xml")
227261

228262
log.debug(iso_xml)
229263

230-
log.debug(iso_xml.select("*, xml_bag(xml) as fts_text"))
264+
csw = conn.sql("""
265+
select
266+
r.id as identifier,
267+
'gmd:MD_Metadata' as typename,
268+
'http://www.isotc211.org/2005/gmd' as schema,
269+
'local' as mdsource,
270+
coalesce(
271+
strftime(r.created_at, '%Y-%m-%d'),
272+
''
273+
) as insert_date,
274+
r.title,
275+
coalesce(
276+
strftime(r.last_modified_at, '%Y-%m-%d'),
277+
''
278+
) as date_modified,
279+
'dataset' as type,
280+
null::varchar as format,
281+
case
282+
when r.extent is not null then ST_AsText(r.extent)
283+
else st_makeEnvelope(4.99207807783, 58.0788841824, 31.29341841, 80.6571442736)
284+
end as wkt_geometry,
285+
r.xml as metadata,
286+
r.xml,
287+
coalesce(
288+
replace(
289+
list_aggregate(
290+
r.metadata->'$.identification.keywords.default.keywords[*]',
291+
'string_agg',
292+
','
293+
), '"', ''),
294+
''
295+
) as keywords,
296+
'application/xml' as metadata_type,
297+
xml_bag(r.xml) as anytext,
298+
coalesce(r.metadata->>'$.identification.abstract', '') as abstract,
299+
coalesce(
300+
strftime(r.last_modified_at, '%Y-%m-%d'),
301+
'',
302+
) as date,
303+
'Norsk institutt for naturforskning' as creator,
304+
'Norsk institutt for naturforskning' as publisher,
305+
coalesce(c.contributors, '') as contributor,
306+
([{
307+
name: r.title,
308+
url: r.uri,
309+
description: r.description,
310+
protocol: r.metadata->>'$.distribution.file.type'
311+
}]::json)::varchar as links
312+
from iso_xml as r
313+
left join contributors_csw as c on c.dataset_id = r.dataset_id
314+
""") # noqa: E501
315+
316+
log.debug(csw)
231317

232318

233319
if __name__ == "__main__":

src/datasync/settings.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@
3535
UBW_AWS_ENDPOINT = env("UBW_AWS_ENDPOINT", default="")
3636
UBW_BUCKET = env("UBW_BUCKET", default="")
3737
UBW_PREFIX = env("UBW_PREFIX", default="")
38+
39+
40+
# DMS
41+
DMS_DATASETS_BASE = env("DMS_DATASETS_BASE", default="")

0 commit comments

Comments
 (0)