43
43
#
44
44
# =================================================================
45
45
46
- from datetime import date , datetime
47
46
import json
48
47
import logging
49
48
import os
50
49
from typing import Union
51
50
52
51
from pygeometa .core import get_charstring
53
- from pygeometa .helpers import json_dumps
52
+ from pygeometa .helpers import generate_datetime , json_dumps
54
53
from pygeometa .schemas .base import BaseOutputSchema
55
54
56
55
THISDIR = os .path .dirname (os .path .realpath (__file__ ))
@@ -123,7 +122,8 @@ def import_(self, metadata: str) -> dict:
123
122
elif geo ['@type' ] == 'GeoShape' :
124
123
mcf ['spatial' ]['datatype' ] = 'vector'
125
124
mcf ['spatial' ]['geomtype' ] = 'polygon'
126
- bbox = geo ['box' ].split ()
125
+ bt = geo ['box' ].split ()
126
+ bbox = bt [1 ], bt [0 ], bt [3 ], bt [2 ]
127
127
128
128
mcf ['identification' ]['extents' ]['spatial' ].append ({
129
129
'bbox' : bbox ,
@@ -198,8 +198,7 @@ def write(self, mcf: dict, stringify: str = True) -> Union[dict, str]:
198
198
:param stringify: whether to return a string representation (default)
199
199
else native (dict, etree)
200
200
201
-
202
- :returns: `dict` or `str` of MCF as an OARec record representation
201
+ :returns: `dict` or `str` of MCF as Schema.org
203
202
"""
204
203
205
204
self .lang1 = mcf ['metadata' ].get ('language' )
@@ -216,34 +215,22 @@ def write(self, mcf: dict, stringify: str = True) -> Union[dict, str]:
216
215
217
216
LOGGER .debug ('Generating baseline record' )
218
217
record = {
219
- 'id' : mcf ['metadata' ]['identifier' ],
220
- 'conformsTo' : [
221
- 'http://www.opengis.net/spec/ogcapi-records-1/1.0/conf/record-core' , # noqa
222
- ],
223
- 'type' : 'Feature' ,
224
- 'geometry' : {
225
- 'type' : 'Polygon' ,
226
- 'coordinates' : [[
227
- [minx , miny ],
228
- [minx , maxy ],
229
- [maxx , maxy ],
230
- [maxx , miny ],
231
- [minx , miny ]
232
- ]]
233
- },
234
- 'properties' : {
235
- 'title' : title [0 ],
236
- 'description' : description [0 ],
237
- 'themes' : [],
238
- 'type' : mcf ['metadata' ]['hierarchylevel' ],
239
- },
240
- 'links' : []
218
+ 'identifier' : mcf ['metadata' ]['identifier' ],
219
+ '@type' : dict (zip (TYPES .values (), TYPES .keys ()))[mcf ['metadata' ]['hierarchylevel' ]], # noqa
220
+ 'spatialCoverage' : [{
221
+ '@type' : 'Place' ,
222
+ 'geo' : {
223
+ '@type' : 'GeoShape' ,
224
+ 'box' : f'{ miny } ,{ minx } { maxy } ,{ maxx } '
225
+ }
226
+ }],
227
+ 'title' : title [0 ],
228
+ 'description' : description [0 ],
229
+ 'distribution' : []
241
230
}
242
231
243
232
if self .lang1 is not None :
244
- record ['properties' ]['language' ] = {
245
- 'code' : self .lang1
246
- }
233
+ record ['inLanguage' ] = self .lang1
247
234
248
235
LOGGER .debug ('Checking for temporal' )
249
236
try :
@@ -265,44 +252,22 @@ def write(self, mcf: dict, stringify: str = True) -> Union[dict, str]:
265
252
elif [begin , end ] == ['..' , '..' ]:
266
253
pass
267
254
else :
268
- record ['time' ] = {
269
- 'interval' : [begin , end ]
270
- }
271
-
272
- if 'resolution' in mcf ['identification' ]['extents' ]['temporal' ][0 ]: # noqa
273
- record ['time' ]['resolution' ] = mcf ['identification' ]['extents' ]['temporal' ][0 ]['resolution' ] # noqa
274
-
255
+ record ['temporalCoverage' ] = [f'{ begin } /{ end } ' ]
275
256
except (IndexError , KeyError ):
276
- record [ 'time' ] = None
257
+ pass
277
258
278
259
LOGGER .debug ('Checking for dates' )
279
260
280
- if 'dates' in mcf ['identification' ]:
281
- if 'creation' in mcf ['identification' ]['dates' ]:
282
- record ['properties' ]['created' ] = self .generate_date (mcf ['identification' ]['dates' ]['creation' ]) # noqa
283
-
284
- if 'revision' in mcf ['identification' ]['dates' ]:
285
- record ['properties' ]['updated' ] = self .generate_date (mcf ['identification' ]['dates' ]['revision' ]) # noqa
286
-
287
- rights = get_charstring (mcf ['identification' ].get ('rights' ),
288
- self .lang1 , self .lang2 )
289
-
290
- if rights != [None , None ]:
291
- record ['properties' ]['rights' ] = rights [0 ]
292
-
293
- formats = []
294
- for v in mcf ['distribution' ].values ():
295
- format_ = get_charstring (v .get ('format' ), self .lang1 , self .lang2 )
296
- if format_ [0 ] is not None :
297
- formats .append (format_ [0 ])
298
-
299
- LOGGER .debug ('Checking for formats' )
300
- if formats :
301
- formats2 = set (formats )
302
- record ['properties' ]['formats' ] = [{'name' : f } for f in formats2 ]
261
+ for key , value in mcf ['identification' ]['dates' ].items ():
262
+ if key == 'creation' :
263
+ record ['dateCreated' ] = generate_datetime (value )
264
+ elif key == 'revision' :
265
+ record ['dateModified' ] = generate_datetime (value )
266
+ elif key == 'publication' :
267
+ record ['datePublished' ] = generate_datetime (value )
303
268
304
269
LOGGER .debug ('Checking for contacts' )
305
- record ['properties' ][ ' contacts' ] = self .generate_contacts (
270
+ record ['contacts' ] = self .generate_contacts (
306
271
mcf ['contact' ])
307
272
308
273
all_keywords = []
@@ -332,13 +297,8 @@ def write(self, mcf: dict, stringify: str = True) -> Union[dict, str]:
332
297
333
298
theme ['scheme' ] = scheme
334
299
335
- record ['properties' ]['themes' ].append (theme )
336
-
337
300
if all_keywords :
338
- record ['properties' ]['keywords' ] = all_keywords
339
-
340
- if not record ['properties' ]['themes' ]:
341
- _ = record ['properties' ].pop ('themes' , None )
301
+ record ['keywords' ] = all_keywords
342
302
343
303
LOGGER .debug ('Checking for licensing' )
344
304
if mcf ['identification' ].get ('license' ) is not None :
@@ -352,14 +312,14 @@ def write(self, mcf: dict, stringify: str = True) -> Union[dict, str]:
352
312
'title' : license .get ('name' , 'license for this resource' ),
353
313
'url' : license ['url' ]
354
314
}
355
- record ['links ' ].append (self .generate_link (license_link ))
315
+ record ['distribution ' ].append (self .generate_link (license_link ))
356
316
else :
357
317
LOGGER .debug ('Encoding license as property' )
358
- record ['properties' ][ ' license' ] = license ['name' ]
318
+ record ['license' ] = license ['name' ]
359
319
360
320
LOGGER .debug ('Checking for distribution' )
361
321
for value in mcf ['distribution' ].values ():
362
- record ['links ' ].append (self .generate_link (value ))
322
+ record ['distribution ' ].append (self .generate_link (value ))
363
323
364
324
if stringify :
365
325
return json_dumps (record )
@@ -453,7 +413,7 @@ def generate_party(self, contact: dict,
453
413
rp ['roles' ].append (r )
454
414
455
415
if 'url' in contact :
456
- rp ['links ' ] = [{
416
+ rp ['distribution ' ] = [{
457
417
'rel' : 'canonical' ,
458
418
'type' : 'text/html' ,
459
419
'href' : contact ['url' ]
@@ -501,20 +461,18 @@ def generate_contacts(self, contact: dict) -> list:
501
461
502
462
def generate_link (self , distribution : dict ) -> dict :
503
463
"""
504
- Generates OARec link object from MCF distribution object
464
+ Generates Schema.org link object from MCF distribution object
505
465
506
466
:param distribution: `dict` of MCF distribution
507
467
508
- :returns: OARec link object
468
+ :returns: Schema.org link object
509
469
"""
510
470
511
- title = get_charstring (distribution .get ('title' ),
512
- self .lang1 , self .lang2 )
513
-
514
- name = get_charstring (distribution .get ('name' ), self .lang1 , self .lang2 )
471
+ name = get_charstring (distribution .get ('name' ),
472
+ self .lang1 , self .lang2 )
515
473
516
474
link = {
517
- 'href ' : distribution ['url' ]
475
+ 'contentUrl ' : distribution ['url' ]
518
476
}
519
477
520
478
if distribution .get ('type' ) is not None :
@@ -524,59 +482,9 @@ def generate_link(self, distribution: dict) -> dict:
524
482
if reltype is not None :
525
483
link ['rel' ] = reltype
526
484
527
- if title != [None , None ]:
528
- link ['title ' ] = title [0 ]
485
+ if name != [None , None ]:
486
+ link ['name ' ] = name [0 ]
529
487
elif name != [None , None ]:
530
- link ['title' ] = name [0 ]
531
-
532
- if all (x in distribution ['url' ] for x in ['{' , '}' ]):
533
- link ['templated' ] = True
534
-
535
- if 'channel' in distribution :
536
- link ['channel' ] = distribution ['channel' ]
488
+ link ['name' ] = name [0 ]
537
489
538
490
return link
539
-
540
- def generate_date (self , date_value : str ) -> str :
541
- """
542
- Helper function to derive RFC3339 date from MCF date type
543
-
544
- :param date_value: `str` of date value
545
-
546
- :returns: `str` of date-time value
547
- """
548
-
549
- value = None
550
-
551
- if isinstance (date_value , str ) and date_value != 'None' :
552
- if len (date_value ) == 10 : # YYYY-MM-DD
553
- format_ = '%Y-%m-%d'
554
- elif len (date_value ) == 7 : # YYYY-MM
555
- format_ = '%Y-%m'
556
- elif len (date_value ) == 4 : # YYYY
557
- format_ = '%Y'
558
- elif len (date_value ) == 19 : # YYYY-MM-DDTHH:MM:SS
559
- msg = 'YYYY-MM-DDTHH:MM:SS with no timezone; converting to UTC'
560
- LOGGER .debug (msg )
561
- format_ = '%Y-%m-%dT%H:%M:%S'
562
-
563
- LOGGER .debug ('date type found; expanding to date-time' )
564
- value = datetime .strptime (date_value , format_ ).strftime ('%Y-%m-%dT%H:%M:%SZ' ) # noqa
565
-
566
- elif isinstance (date_value , int ) and len (str (date_value )) == 4 :
567
- date_value2 = str (date_value )
568
- LOGGER .debug ('date type found; expanding to date-time' )
569
- format_ = '%Y'
570
- value = datetime .strptime (date_value2 , format_ ).strftime ('%Y-%m-%dT%H:%M:%SZ' ) # noqa
571
-
572
- elif isinstance (date_value , (date , datetime )):
573
- value = date_value .strftime ('%Y-%m-%dT%H:%M:%SZ' )
574
-
575
- elif date_value in [None , 'None' ]:
576
- value = datetime .now ().strftime ('%Y-%m-%dT%H:%M:%SZ' )
577
-
578
- else :
579
- msg = f'Unknown date string: { date_value } '
580
- raise RuntimeError (msg )
581
-
582
- return value
0 commit comments