From a2daa682c712ac57e5977b4396842bdec8ba15d0 Mon Sep 17 00:00:00 2001
From: Kenzo-Hugo Hillion <hillion.kenzo@posteo.net>
Date: Fri, 16 Apr 2021 11:23:16 +0200
Subject: [PATCH] detailed source from doi.org

---
 .../api/catalog/qparams_validators/source.py  |  7 ++++
 .../metagenedb/api/catalog/views/source.py    | 33 +++++++++++++++++--
 .../common/utils/external_api/doi_api.py      | 27 +++++++++++++++
 frontend/src/views/genedetail/genedetail.html |  2 +-
 4 files changed, 66 insertions(+), 3 deletions(-)
 create mode 100644 backend/metagenedb/api/catalog/qparams_validators/source.py
 create mode 100644 backend/metagenedb/common/utils/external_api/doi_api.py

diff --git a/backend/metagenedb/api/catalog/qparams_validators/source.py b/backend/metagenedb/api/catalog/qparams_validators/source.py
new file mode 100644
index 0000000..7bdd0a2
--- /dev/null
+++ b/backend/metagenedb/api/catalog/qparams_validators/source.py
@@ -0,0 +1,7 @@
+from marshmallow import fields
+
+from metagenedb.common.django_default.qparams_validators import PaginatedQueryParams
+
+
+class SourceQueryParams(PaginatedQueryParams):
+    detailed = fields.Boolean()
diff --git a/backend/metagenedb/api/catalog/views/source.py b/backend/metagenedb/api/catalog/views/source.py
index fe888f8..6781dbb 100644
--- a/backend/metagenedb/api/catalog/views/source.py
+++ b/backend/metagenedb/api/catalog/views/source.py
@@ -1,7 +1,12 @@
 from drf_yasg.utils import swagger_auto_schema
+from marshmallow.exceptions import ValidationError
+from rest_framework.response import Response
+from rest_framework.status import HTTP_422_UNPROCESSABLE_ENTITY
 
 from metagenedb.apps.catalog.models import Source
 from metagenedb.apps.catalog.serializers import SourceSerializer
+from metagenedb.api.catalog.qparams_validators.source import SourceQueryParams
+from metagenedb.common.utils.external_api.doi_api import GetDOIExternalInfo
 
 from .base import BulkViewSet
 
@@ -10,6 +15,7 @@ class SourceViewSet(BulkViewSet):
     queryset = Source.objects.all()
     serializer_class = SourceSerializer
     lookup_field = 'slug'
+    query_params_parser = SourceQueryParams
 
     @swagger_auto_schema(
         operation_description="List all gene sources",
@@ -19,13 +25,36 @@ class SourceViewSet(BulkViewSet):
     def list(self, *args, **kwargs):
         return super().list(*args, **kwargs)
 
+    def _get_external_info(self, db_data):
+        detailed_info_retriever = GetDOIExternalInfo(db_data['doi'])
+        try:
+            detailed_data = detailed_info_retriever.get_details()
+        except NotImplementedError as not_implemented_error:
+            logger.warning("Could not found API for the source, returning item from the DB. Error: %s" %
+                           not_implemented_error)
+            detailed_data = db_data
+        return detailed_data
+
     @swagger_auto_schema(
         operation_description="Retrieve gene source from a name",
         operation_summary="API to retrieve gene source.",
         tags=['Source'],
     )
-    def retrieve(self, *args, **kwargs):
-        return super().retrieve(*args, **kwargs)
+    def retrieve(self, request, *args, **kwargs):
+        try:
+            query_params = self.query_params_parser().load(request.query_params)
+        except ValidationError as validation_error:
+            error_message = validation_error.normalized_messages()
+            error_message.update({
+                'allowed_query_params': ', '.join(self.query_params_parser().declared_fields.keys())
+            })
+            return Response(error_message, status=HTTP_422_UNPROCESSABLE_ENTITY)
+        instance = self.get_object()
+        serializer = self.get_serializer(instance)
+        returned_data = serializer.data
+        if query_params.get('detailed', False) is True:
+            returned_data = self._get_external_info(returned_data)
+        return Response(returned_data)
 
     @swagger_auto_schema(
         tags=['Source'],
diff --git a/backend/metagenedb/common/utils/external_api/doi_api.py b/backend/metagenedb/common/utils/external_api/doi_api.py
new file mode 100644
index 0000000..98de500
--- /dev/null
+++ b/backend/metagenedb/common/utils/external_api/doi_api.py
@@ -0,0 +1,27 @@
+import logging
+
+from django.conf import settings
+
+from dabeplech import DOIAPI
+
+
+logger = logging.getLogger(__name__)
+
+
+class GetDOIExternalInfo:
+
+    def __init__(self, doi: str):
+        self.doi = doi
+
+    def get_details(self):
+        """
+        Get detailed information from DOI.
+        """
+        logger.info("Retrieving information from DOI")
+        api = DOIAPI()
+        response = api.get(self.doi)
+        response[settings.API_KEY_ADDITIONAL_INFO] = {
+            'comment': f"Information retrieved from external source: {api.url}",
+            'url': f"{api.last_url_requested}"
+        }
+        return response
diff --git a/frontend/src/views/genedetail/genedetail.html b/frontend/src/views/genedetail/genedetail.html
index e2b9a97..a37e07c 100644
--- a/frontend/src/views/genedetail/genedetail.html
+++ b/frontend/src/views/genedetail/genedetail.html
@@ -69,7 +69,7 @@
               <v-toolbar class="tertiary white--text" dense>
                 <v-icon class="white--text">format_list_bulleted</v-icon>
                 <v-toolbar-title>
-                  Gene source
+                  Gene catalog
                 </v-toolbar-title>
               </v-toolbar>
               <!-- Simple information -->
-- 
GitLab