Commit 0fc2acf1 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Added catalog endpoint to dcat.

parent 4644356a
...@@ -21,3 +21,4 @@ from flask_restplus import Api ...@@ -21,3 +21,4 @@ from flask_restplus import Api
from .api import blueprint, api from .api import blueprint, api
from .datasets import Dataset from .datasets import Dataset
from .catalog import Catalog
# Copyright 2018 Markus Scheidgen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an"AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from flask_restplus import Resource, reqparse, fields
from flask import Response
from elasticsearch_dsl import Q
from nomad import search
from .api import api
from .mapping import Mapping
ns = api.namespace('catalog', description='The API for DCAT catalog.')
iso8601 = fields.DateTime(dt_format='iso8601')
arg_parser = reqparse.RequestParser()
arg_parser.add_argument('format', type=str, choices=[
'xml',
'n3',
'turtle',
'nt',
'pretty-xml',
'trig'])
arg_parser.add_argument('after', type=str)
arg_parser.add_argument(
'modified_since', type=lambda x: iso8601.parse(x),
help='A yyyy-MM-ddTHH:mm:ss (RFC3339) maximum entry time (e.g. upload time)')
@ns.route('/')
class Catalog(Resource):
@api.doc('get_dcat_datasets')
@api.expect(arg_parser)
@api.produces(['application/xml'])
@api.response(404, 'There is no entry with the given id.')
@api.response(401, 'This entry is not publically accessible.')
@api.response(200, 'Data send', headers={'Content-Type': 'application/xml'})
def get(self):
''' Returns a page of DCAT datasets. '''
args = arg_parser.parse_args()
format_ = args.get('format')
if format_ is None:
format_ = 'xml'
modified_since = args.get('modified_since', None)
modified_since = iso8601.parse(modified_since) if modified_since is not None else None
after = args.get('after', None)
search_request = search.SearchRequest().owner('public')
if modified_since is not None:
modified_clause = Q('range', upload_time=dict(gte=modified_since))
modified_clause |= Q('range', last_edit=dict(gte=modified_since))
modified_clause |= Q('range', last_processing=dict(gte=modified_since))
search_request.q &= modified_clause
es_search = search_request._search.query(search_request.q)
if after is not None:
es_search = es_search.extra(search_after=[after], sort='calc_id')
es_response = es_search.execute()
mapping = Mapping()
mapping.map_catalog(es_response.hits)
return Response(
mapping.g.serialize(format=format_).decode('utf-8'), 200,
{'Content-Type': 'application/xml'})
...@@ -36,6 +36,12 @@ class Mapping(): ...@@ -36,6 +36,12 @@ class Mapping():
self.persons = {} self.persons = {}
def map_catalog(self, entries):
catalog = URIRef(url('catalog'))
self.g.add((catalog, RDF.type, DCAT.Catalog))
for entry in entries:
self.g.add((catalog, DCT.dataset, self.map_entry(entry)))
def map_entry(self, entry: EntryMetadata): def map_entry(self, entry: EntryMetadata):
dataset = URIRef(url('datasets', entry.calc_id)) dataset = URIRef(url('datasets', entry.calc_id))
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
import pytest import pytest
from datetime import datetime from datetime import datetime
from nomad import infrastructure, config
from nomad.datamodel import EntryMetadata from nomad.datamodel import EntryMetadata
from nomad.app.dcat.mapping import Mapping from nomad.app.dcat.mapping import Mapping
...@@ -59,3 +60,20 @@ def test_get_dataset(elastic_infra, api, example_entry): ...@@ -59,3 +60,20 @@ def test_get_dataset(elastic_infra, api, example_entry):
assert rv.status_code == 200 assert rv.status_code == 200
clear_elastic(elastic_infra) clear_elastic(elastic_infra)
def test_get_catalog(elastic_infra, api, example_entry):
clear_elastic(elastic_infra)
for i in range(1, 11):
example_entry.calc_id = 'test-id-%d' % i
example_entry.upload_time = datetime(2000, 1, 1)
example_entry.last_processing = datetime(2020, 1, i)
example_entry.a_elastic.index()
infrastructure.elastic_client.indices.refresh(index=config.elastic.index_name)
rv = api.get('/catalog/?after=test-id-3&modified_since=2020-01-07&format=nt')
assert rv.status_code == 200
clear_elastic(elastic_infra)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment