From f10efa7ba9ad0ee2ab934963a4d563cf20c09130 Mon Sep 17 00:00:00 2001
From: Christian Boettcher <c.boettcher@fz-juelich.de>
Date: Wed, 5 May 2021 11:55:37 +0200
Subject: [PATCH] add storage interface + json implementation (see #1 and #4)

---
 api-server/.gitignore                |  1 +
 api-server/JsonFileStorageAdapter.py | 64 ++++++++++++++++++++++++++++
 api-server/LocationStorage.py        | 29 +++++++++++++
 3 files changed, 94 insertions(+)
 create mode 100644 api-server/JsonFileStorageAdapter.py
 create mode 100644 api-server/LocationStorage.py

diff --git a/api-server/.gitignore b/api-server/.gitignore
index c18dd8d..d3b0ad4 100644
--- a/api-server/.gitignore
+++ b/api-server/.gitignore
@@ -1 +1,2 @@
 __pycache__/
+app/
\ No newline at end of file
diff --git a/api-server/JsonFileStorageAdapter.py b/api-server/JsonFileStorageAdapter.py
new file mode 100644
index 0000000..c3c8c50
--- /dev/null
+++ b/api-server/JsonFileStorageAdapter.py
@@ -0,0 +1,64 @@
+import os
+import json
+import uuid
+
+from LocationStorage import AbstractLocationDataStorageAdapter, LocationData, LocationDataType
+
+
+DEFAULT_JSON_FILEPATH: str = "./app/data"
+
+class JsonFileStorageAdapter(AbstractLocationDataStorageAdapter):
+    data_dir: str
+
+    def __init__(self, data_directory: str = DEFAULT_JSON_FILEPATH):
+        AbstractLocationDataStorageAdapter.__init__(self)
+        self.data_dir = data_directory
+        if not (os.path.exists(self.data_dir) and os.path.isdir(self.data_dir)):
+            raise Exception('Data Directory \"' + self.data_dir + '\" does not exist.')
+
+    def getList(self, type: LocationDataType):
+        localpath = os.path.join(self.data_dir, type.value)
+        if not (os.path.isdir(localpath)):
+            # This type has apparently not yet been used at all, create its directory and return an empty json file
+            os.mkdir(localpath)
+            return {}
+        else:
+            allFiles = [f for f in os.listdir(localpath) if os.path.isfile(os.path.join(localpath, f))]
+            # now each file has to be checked for its filename (= id) and the LocationData name (which is inside the json)
+            retList = []
+            for f in allFiles:
+                with open(os.path.join(localpath, f)) as file:
+                    data = json.load(file)
+                    retList.append({data['name'] : f})
+            return retList
+
+    def addNew(self, type: LocationDataType, data: LocationData):
+        localpath = os.path.join(self.data_dir, type.value)
+        if not (os.path.isdir(localpath)):
+            # This type has apparently not yet been used at all, therefore we need to create its directory
+            os.mkdir(localpath)
+        # create a unique id, by randomly generating one, and re-choosing if it is already taken
+        id = str(uuid.uuid4())
+        while (os.path.exists(os.path.join(localpath, id))):
+            id = str(uuid.uuid4())
+        with open(os.path.join(localpath, id), 'w') as json_file:
+            json.dump(data.__dict__, json_file)
+        return {id : data}
+
+    def getDetails(self, type: LocationDataType, id: str):
+        localpath = os.path.join(self.data_dir, type.value)
+        fullpath = os.path.join(localpath, id)
+        if not os.path.isfile(fullpath):
+            raise FileNotFoundError('The requested Object does not exist.')
+        with open(fullpath) as file:
+            data = json.load(file)
+        return data
+
+    def updateDetails(self, type:LocationDataType, id:str, data: LocationData):
+        localpath = os.path.join(self.data_dir, type.value)
+        fullpath = os.path.join(localpath, id)
+        if not os.path.isfile(fullpath):
+            raise FileNotFoundError('The requested Object does not exist.')
+        with open(fullpath, 'w') as file:
+            json.dump(data.__dict__, file)
+        return {id : data}
diff --git a/api-server/LocationStorage.py b/api-server/LocationStorage.py
new file mode 100644
index 0000000..6b5e5ca
--- /dev/null
+++ b/api-server/LocationStorage.py
@@ -0,0 +1,29 @@
+
+from pydantic import BaseModel
+
+from typing import Optional
+from typing import Dict
+from enum import Enum
+
+class LocationDataType(Enum):
+    DATASET: str = 'dataset'
+    STORAGETARGET: str = 'storage_target'
+
+class LocationData(BaseModel):
+    name: str
+    url: str
+    metadata: Optional[Dict[str, str]]
+
+
+class AbstractLocationDataStorageAdapter:
+    def getList(self, type: LocationDataType):
+        raise NotImplementedError()
+
+    def addNew(self, type: LocationDataType, data: LocationData):
+        raise NotImplementedError()
+
+    def getDetails(self, type: LocationDataType, id: str):
+        raise NotImplementedError()
+
+    def updateDetails(self, type:LocationDataType, id:str, data: LocationData):
+        raise NotImplementedError()
-- 
GitLab