Skip to content

Commit

Permalink
add support for EDR instances
Browse files Browse the repository at this point in the history
  • Loading branch information
tomkralidis committed Dec 23, 2024
1 parent c379f22 commit 175140b
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 7 deletions.
171 changes: 169 additions & 2 deletions pygeoapi/api/environmental_data_retrieval.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,14 @@

from pygeoapi import l10n
from pygeoapi.plugin import load_plugin, PLUGINS
from pygeoapi.provider.base import ProviderGenericError
from pygeoapi.provider.base import (
ProviderGenericError, ProviderItemNotFoundError)
from pygeoapi.util import (
filter_providers_by_type, get_provider_by_type, render_j2_template,
to_json, filter_dict_by_key_value
)

from . import (APIRequest, API, F_COVERAGEJSON, F_HTML, F_JSONLD,
from . import (APIRequest, API, F_COVERAGEJSON, F_HTML, F_JSON, F_JSONLD,
validate_datetime, validate_bbox)

LOGGER = logging.getLogger(__name__)
Expand All @@ -64,6 +65,172 @@
]


def get_collection_edr_instances(api: API, request: APIRequest, dataset,
instance_id=None) -> Tuple[dict, int, str]:
"""
Queries collection EDR instances
:param request: APIRequest instance with query params
:param dataset: dataset name
:returns: tuple of headers, status code, content
"""

data = {
'instances': [],
'links': []
}

if not request.is_valid(PLUGINS['formatter'].keys()):
return api.get_format_exception(request)
headers = request.get_response_headers(api.default_locale,
**api.api_headers)
collections = filter_dict_by_key_value(api.config['resources'],
'type', 'collection')

if dataset not in collections.keys():
msg = 'Collection not found'
return api.get_exception(
HTTPStatus.NOT_FOUND, headers, request.format, 'NotFound', msg)

uri = f'{api.get_collections_url()}/{dataset}'

LOGGER.debug('Loading provider')
try:
p = load_plugin('provider', get_provider_by_type(
collections[dataset]['providers'], 'edr'))
except ProviderGenericError as err:
return api.get_exception(
err.http_status_code, headers, request.format,
err.ogc_exception_code, err.message)

if instance_id is not None:
try:
instances = [p.get_instance(instance_id)]
except ProviderItemNotFoundError:
msg = 'Instance not found'
return api.get_exception(
HTTPStatus.NOT_FOUND, headers, request.format, 'NotFound', msg)
else:
instances = p.instances()

for instance in instances:
instance_dict = {
'id': instance,
'links': [{
'href': f'{uri}/instances/{instance}?f={F_JSON}',
'rel': request.get_linkrel(F_JSON),
'type': 'application/json'
}, {
'href': f'{uri}/instances/{instance}?f={F_HTML}',
'rel': request.get_linkrel(F_HTML),
'type': 'text/html'
}, {
'href': f'{uri}?f={F_HTML}',
'rel': 'collection',
'title': collections[dataset]['title'],
'type': 'text/html'
}, {
'href': f'{uri}?f={F_JSON}',
'rel': 'collection',
'title': collections[dataset]['title'],
'type': 'application/json'
}],
'data_queries': {}
}

for qt in p.get_query_types():
if qt == 'instances':
continue
data_query = {
'link': {
'href': f'{uri}/instances/{instance}/{qt}',
'rel': 'data',
'title': f'{qt} query'
}
}
instance_dict['data_queries'][qt] = data_query

data['instances'].append(instance_dict)

if instance_id is not None:
data = data['instances'][0]
data.pop('instances', None)
links_uri = f'{uri}/instances/{instance_id}'
else:
links_uri = f'{uri}/instances'

if instance_id is None:
data['links'].extend([{
'href': f'{links_uri}?f={F_JSON}',
'rel': request.get_linkrel(F_JSON),
'type': 'application/json'
}, {
'href': f'{links_uri}?f={F_HTML}',
'rel': request.get_linkrel(F_HTML),
'type': 'text/html'
}])

if request.format == F_HTML: # render
api.set_dataset_templates(dataset)

serialized_query_params = ''
for k, v in request.params.items():
if k != 'f':
serialized_query_params += '&'
serialized_query_params += urllib.parse.quote(k, safe='')
serialized_query_params += '='
serialized_query_params += urllib.parse.quote(str(v), safe=',')

if instance_id is None:
uri = f'{uri}/instances'
else:
uri = f'{uri}/instances/{instance_id}'

data['query_type'] = 'instances'
data['query_path'] = uri
data['title'] = collections[dataset]['title']
data['description'] = collections[dataset]['description']
data['keywords'] = collections[dataset]['keywords']
data['collections_path'] = api.get_collections_url()

if instance_id is None:
data['dataset_path'] = data['collections_path'] + '/' + uri.split('/')[-2] # noqa
template = 'collections/edr/instances.html'
else:
data['dataset_path'] = data['collections_path'] + '/' + uri.split('/')[-3] # noqa
template = 'collections/edr/instance.html'

data['links'] = [{
'rel': 'collection',
'title': collections[dataset]['title'],
'href': f"{data['dataset_path']}?f={F_JSON}",
'type': 'text/html'
}, {
'rel': 'collection',
'title': collections[dataset]['title'],
'href': f"{data['dataset_path']}?f={F_HTML}",
'type': 'application/json'
}, {
'type': 'application/json',
'rel': 'alternate',
'title': l10n.translate('This document as JSON', request.locale),
'href': f'{uri}?f={F_JSON}{serialized_query_params}'
}, {
'type': 'application/ld+json',
'rel': 'alternate',
'title': l10n.translate('This document as JSON-LD', request.locale), # noqa
'href': f'{uri}?f={F_JSONLD}{serialized_query_params}'
}]

content = render_j2_template(api.tpl_config, template, data,
api.default_locale)
else:
content = to_json(data, api.pretty_print)

return headers, HTTPStatus.OK, content


def get_collection_edr_query(api: API, request: APIRequest,
dataset, instance, query_type,
location_id=None) -> Tuple[dict, int, str]:
Expand Down
17 changes: 13 additions & 4 deletions pygeoapi/flask_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,8 @@ def get_job_result(job_id=None):
@BLUEPRINT.route('/collections/<path:collection_id>/radius')
@BLUEPRINT.route('/collections/<path:collection_id>/trajectory')
@BLUEPRINT.route('/collections/<path:collection_id>/corridor')
@BLUEPRINT.route('/collections/<path:collection_id>/locations/<location_id>') # noqa
@BLUEPRINT.route('/collections/<path:collection_id>/locations') # noqa
@BLUEPRINT.route('/collections/<path:collection_id>/locations/<location_id>')
@BLUEPRINT.route('/collections/<path:collection_id>/locations')
@BLUEPRINT.route('/collections/<path:collection_id>/instances/<instance_id>/position') # noqa
@BLUEPRINT.route('/collections/<path:collection_id>/instances/<instance_id>/area') # noqa
@BLUEPRINT.route('/collections/<path:collection_id>/instances/<instance_id>/cube') # noqa
Expand All @@ -475,6 +475,8 @@ def get_job_result(job_id=None):
@BLUEPRINT.route('/collections/<path:collection_id>/instances/<instance_id>/corridor') # noqa
@BLUEPRINT.route('/collections/<path:collection_id>/instances/<instance_id>/locations/<location_id>') # noqa
@BLUEPRINT.route('/collections/<path:collection_id>/instances/<instance_id>/locations') # noqa
@BLUEPRINT.route('/collections/<path:collection_id>/instances/<instance_id>')
@BLUEPRINT.route('/collections/<path:collection_id>/instances')
def get_collection_edr_query(collection_id, instance_id=None,
location_id=None):
"""
Expand All @@ -487,15 +489,22 @@ def get_collection_edr_query(collection_id, instance_id=None,
:returns: HTTP response
"""

if (request.path.endswith('instances') or
(instance_id is not None and
request.path.endswith(instance_id))):
return execute_from_flask(
edr_api.get_collection_edr_instances, request, collection_id,
instance_id
)

if location_id:
query_type = 'locations'
else:
query_type = request.path.split('/')[-1]

return execute_from_flask(
edr_api.get_collection_edr_query, request, collection_id, instance_id,
query_type, location_id,
skip_valid_check=True,
query_type, location_id, skip_valid_check=True
)


Expand Down
2 changes: 1 addition & 1 deletion pygeoapi/provider/base_edr.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(self, provider_def):

super().__init__(provider_def)

self.instances = []
# self.instances = []

@classmethod
def register(cls):
Expand Down
42 changes: 42 additions & 0 deletions pygeoapi/templates/collections/edr/instance.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{% extends "_base.html" %}
{% block title %}{{ super() }} {{ data['title'] }} {% endblock %}
{% block crumbs %}{{ super() }}
/ <a href="{{ data['collections_path'] }}">{% trans %}Collections{% endtrans %}</a>
{% for link in data['links'] %}
{% if link.rel == 'collection' %} /
<a href="{{ data['dataset_path'] }}">{{ link['title'] | truncate( 25 ) }}</a>
{% set col_title = link['title'] %}
{% endif %}
{% endfor %}
/ <a href="{{ data['dataset_path'] }}/instances">{% trans %}Instances{% endtrans %}</a>
/ <a href="{{ data['dataset_path'] }}/instances/{{ data['id'] }}">{{ data['id'] }}</a>
{% endblock %}
{% block body %}
<section id="collection">
<h1>{{ data['title'] }}</h1>
<p>{{ data['description'] }}</p>
<p>
{% for kw in data['keywords'] %}
<span class="badge text-bg-primary bg-primary">{{ kw }}</span>
{% endfor %}
</p>
<h3>{% trans %}Instance{% endtrans %} {{ data['id'] }}</h3>
</section>
<h3>{% trans %}Links{% endtrans %}</h3>
<ul>
{% for key, value in data['data_queries'].items() %}
<li>
<a title="{{ value['link']['rel'] }}" href="{{ value['link']['href'] }}">
<span>{{ value['link']['title'] }}</span>
</a>
</li>
{% endfor %}
{% for link in data['links'] %}
<li>
<a title="{{ link['rel'] }}" href="{{ link['href'] }}">
<span>{{ link['title'] }}</span> (<span>{{ link['type'] }}</span>)
</a>
</li>
{% endfor %}
</ul>
{% endblock %}
29 changes: 29 additions & 0 deletions pygeoapi/templates/collections/edr/instances.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{% extends "_base.html" %}
{% block title %}{{ super() }} {{ data['title'] }} {% endblock %}
{% block crumbs %}{{ super() }}
/ <a href="{{ data['collections_path'] }}">{% trans %}Collections{% endtrans %}</a>
{% for link in data['links'] %}
{% if link.rel == 'collection' %} /
<a href="{{ data['dataset_path'] }}">{{ link['title'] | truncate( 25 ) }}</a>
{% set col_title = link['title'] %}
{% endif %}
{% endfor %}
/ <a href="{{ data['dataset_path'] }}/instances">{% trans %}Instances{% endtrans %}</a>
{% endblock %}
{% block body %}
<section id="collection">
<h1>{{ data['title'] }}</h1>
<p>{{ data['description'] }}</p>
<p>
{% for kw in data['keywords'] %}
<span class="badge text-bg-primary bg-primary">{{ kw }}</span>
{% endfor %}
</p>
<h3>{% trans %}Instances{% endtrans %}</h3>
<ul>
{% for instance in data['instances'] %}
<li><a href="./instances/{{ instance['id'] }}">{{ instance['id'] }} </a></li>
{% endfor %}
</ul>
</section>
{% endblock %}

0 comments on commit 175140b

Please sign in to comment.