diff --git a/gCube CMS.ipynb b/gCube CMS.ipynb new file mode 100644 index 0000000..fcc5729 --- /dev/null +++ b/gCube CMS.ipynb @@ -0,0 +1,1729 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "64e0639b-c024-49eb-93ef-3c67539dec34", + "metadata": { + "tags": [] + }, + "source": [ + "# gCube CMS\n", + "\n", + "gCube CMS is a software application that allows users to collaborate in the creation, editing, and production of complex digital components called Projects." + ] + }, + { + "cell_type": "markdown", + "id": "be945c2c-1b00-44a9-890f-bde5be45ad38", + "metadata": {}, + "source": [ + "The application is built on top of gCube Infrastructure features, for maximum integration with Virtual Research Environments (VREs) and supports : \n", + "- Complex Data Management : Projects are made of core Metadata, custom Metadata, multiple linked FileSets\n", + "- Versioning, Workflows, Access Policies integrated with the Infrastructure User Role Management\n", + "- Materializations (e.g. SDI Layer, Image Thumbnail, DBMS)\n", + "- Indexing (e.g. GIS Catalogues, Centroids Layer, CKAN catalogue)\n", + "- Event Triggering (e.g. Notifications)\n", + "\n", + "The application is comprised of various components, including : \n", + "- GUIs to facilitate end users in managing and consuming Projects\n", + "- Service implemented the core business logic\n", + "- Plugins set of modular logic implementations (both general-purpose and custom-made) aimed at dealing with Projects Lifecycle Phases and Events\n", + "\n", + "![Concept](https://gcube.wiki.gcube-system.org/images_gcube/a/a3/DataCube.png)" + ] + }, + { + "cell_type": "markdown", + "id": "6c2330c5-12d7-49c6-ad50-c66e6d548e7d", + "metadata": { + "tags": [] + }, + "source": [ + "## Parameters Init\n", + "\n", + "Customize this section for different notebook behaviour and initialization." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "fcc15ae5-fc3f-4146-b77c-bf23231c9ae6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: rich[jupyter] in /opt/conda/lib/python3.9/site-packages (12.2.0)\n", + "Requirement already satisfied: pygments<3.0.0,>=2.6.0 in /opt/conda/lib/python3.9/site-packages (from rich[jupyter]) (2.11.2)\n", + "Requirement already satisfied: commonmark<0.10.0,>=0.9.0 in /opt/conda/lib/python3.9/site-packages (from rich[jupyter]) (0.9.1)\n", + "Requirement already satisfied: ipywidgets<8.0.0,>=7.5.1 in /opt/conda/lib/python3.9/site-packages (from rich[jupyter]) (7.7.0)\n", + "Requirement already satisfied: traitlets>=4.3.1 in /opt/conda/lib/python3.9/site-packages (from ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (5.1.1)\n", + "Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /opt/conda/lib/python3.9/site-packages (from ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (1.1.0)\n", + "Requirement already satisfied: ipykernel>=4.5.1 in /opt/conda/lib/python3.9/site-packages (from ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (6.11.0)\n", + "Requirement already satisfied: nbformat>=4.2.0 in /opt/conda/lib/python3.9/site-packages (from ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (5.2.0)\n", + "Requirement already satisfied: ipython-genutils~=0.2.0 in /opt/conda/lib/python3.9/site-packages (from ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.2.0)\n", + "Requirement already satisfied: widgetsnbextension~=3.6.0 in /opt/conda/lib/python3.9/site-packages (from ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (3.6.0)\n", + "Requirement already satisfied: ipython>=4.0.0 in /opt/conda/lib/python3.9/site-packages (from ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (8.2.0)\n", + "Requirement already satisfied: jupyter-client>=6.1.12 in /opt/conda/lib/python3.9/site-packages (from ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (7.2.1)\n", + "Requirement already satisfied: debugpy>=1.0 in /opt/conda/lib/python3.9/site-packages (from ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (1.5.1)\n", + "Requirement already satisfied: setuptools>=60 in /opt/conda/lib/python3.9/site-packages (from ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (61.3.1)\n", + "Requirement already satisfied: nest-asyncio in /opt/conda/lib/python3.9/site-packages (from ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (1.5.5)\n", + "Requirement already satisfied: psutil in /opt/conda/lib/python3.9/site-packages (from ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (5.9.0)\n", + "Requirement already satisfied: matplotlib-inline>=0.1 in /opt/conda/lib/python3.9/site-packages (from ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.1.3)\n", + "Requirement already satisfied: tornado>=6.1 in /opt/conda/lib/python3.9/site-packages (from ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (6.1)\n", + "Requirement already satisfied: decorator in /opt/conda/lib/python3.9/site-packages (from ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (5.1.1)\n", + "Requirement already satisfied: stack-data in /opt/conda/lib/python3.9/site-packages (from ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.2.0)\n", + "Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /opt/conda/lib/python3.9/site-packages (from ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (3.0.27)\n", + "Requirement already satisfied: pickleshare in /opt/conda/lib/python3.9/site-packages (from ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.7.5)\n", + "Requirement already satisfied: jedi>=0.16 in /opt/conda/lib/python3.9/site-packages (from ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.18.1)\n", + "Requirement already satisfied: pexpect>4.3 in /opt/conda/lib/python3.9/site-packages (from ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (4.8.0)\n", + "Requirement already satisfied: backcall in /opt/conda/lib/python3.9/site-packages (from ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.2.0)\n", + "Requirement already satisfied: jsonschema!=2.5.0,>=2.4 in /opt/conda/lib/python3.9/site-packages (from nbformat>=4.2.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (4.4.0)\n", + "Requirement already satisfied: jupyter-core in /opt/conda/lib/python3.9/site-packages (from nbformat>=4.2.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (4.9.2)\n", + "Requirement already satisfied: notebook>=4.4.1 in /opt/conda/lib/python3.9/site-packages (from widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (6.4.10)\n", + "Requirement already satisfied: parso<0.9.0,>=0.8.0 in /opt/conda/lib/python3.9/site-packages (from jedi>=0.16->ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.8.3)\n", + "Requirement already satisfied: pyrsistent!=0.17.0,!=0.17.1,!=0.17.2,>=0.14.0 in /opt/conda/lib/python3.9/site-packages (from jsonschema!=2.5.0,>=2.4->nbformat>=4.2.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.18.1)\n", + "Requirement already satisfied: attrs>=17.4.0 in /opt/conda/lib/python3.9/site-packages (from jsonschema!=2.5.0,>=2.4->nbformat>=4.2.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (21.4.0)\n", + "Requirement already satisfied: entrypoints in /opt/conda/lib/python3.9/site-packages (from jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.4)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in /opt/conda/lib/python3.9/site-packages (from jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (2.8.2)\n", + "Requirement already satisfied: pyzmq>=22.3 in /opt/conda/lib/python3.9/site-packages (from jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (22.3.0)\n", + "Requirement already satisfied: nbconvert>=5 in /opt/conda/lib/python3.9/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (6.4.5)\n", + "Requirement already satisfied: jinja2 in /opt/conda/lib/python3.9/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (3.1.1)\n", + "Requirement already satisfied: Send2Trash>=1.8.0 in /opt/conda/lib/python3.9/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (1.8.0)\n", + "Requirement already satisfied: prometheus-client in /opt/conda/lib/python3.9/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.13.1)\n", + "Requirement already satisfied: terminado>=0.8.3 in /opt/conda/lib/python3.9/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.13.3)\n", + "Requirement already satisfied: argon2-cffi in /opt/conda/lib/python3.9/site-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (21.3.0)\n", + "Requirement already satisfied: ptyprocess>=0.5 in /opt/conda/lib/python3.9/site-packages (from pexpect>4.3->ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.7.0)\n", + "Requirement already satisfied: wcwidth in /opt/conda/lib/python3.9/site-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.2.5)\n", + "Requirement already satisfied: executing in /opt/conda/lib/python3.9/site-packages (from stack-data->ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.8.3)\n", + "Requirement already satisfied: asttokens in /opt/conda/lib/python3.9/site-packages (from stack-data->ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (2.0.5)\n", + "Requirement already satisfied: pure-eval in /opt/conda/lib/python3.9/site-packages (from stack-data->ipython>=4.0.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.2.2)\n", + "Requirement already satisfied: MarkupSafe>=2.0 in /opt/conda/lib/python3.9/site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (2.1.1)\n", + "Requirement already satisfied: nbclient<0.6.0,>=0.5.0 in /opt/conda/lib/python3.9/site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.5.13)\n", + "Requirement already satisfied: defusedxml in /opt/conda/lib/python3.9/site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.7.1)\n", + "Requirement already satisfied: mistune<2,>=0.8.1 in /opt/conda/lib/python3.9/site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.8.4)\n", + "Requirement already satisfied: jupyterlab-pygments in /opt/conda/lib/python3.9/site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.1.2)\n", + "Requirement already satisfied: pandocfilters>=1.4.1 in /opt/conda/lib/python3.9/site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (1.5.0)\n", + "Requirement already satisfied: beautifulsoup4 in /opt/conda/lib/python3.9/site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (4.10.0)\n", + "Requirement already satisfied: testpath in /opt/conda/lib/python3.9/site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.6.0)\n", + "Requirement already satisfied: bleach in /opt/conda/lib/python3.9/site-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (4.1.0)\n", + "Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.9/site-packages (from python-dateutil>=2.8.2->jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (1.16.0)\n", + "Requirement already satisfied: argon2-cffi-bindings in /opt/conda/lib/python3.9/site-packages (from argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (21.2.0)\n", + "Requirement already satisfied: cffi>=1.0.1 in /opt/conda/lib/python3.9/site-packages (from argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (1.15.0)\n", + "Requirement already satisfied: soupsieve>1.2 in /opt/conda/lib/python3.9/site-packages (from beautifulsoup4->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (2.3.1)\n", + "Requirement already satisfied: packaging in /opt/conda/lib/python3.9/site-packages (from bleach->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (21.3)\n", + "Requirement already satisfied: webencodings in /opt/conda/lib/python3.9/site-packages (from bleach->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (0.5.1)\n", + "Requirement already satisfied: pycparser in /opt/conda/lib/python3.9/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (2.21)\n", + "Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /opt/conda/lib/python3.9/site-packages (from packaging->bleach->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets<8.0.0,>=7.5.1->rich[jupyter]) (3.0.7)\n" + ] + } + ], + "source": [ + "import requests\n", + "import json\n", + "\n", + "# These parameters should be discovered / initialized by common gcube libraries. \n", + "gcube_token = \"...\"\n", + "service_base_endpoint =\"https://geoportal.dev.int.d4science.net/geoportal-service/srv\"\n", + "\n", + "# Actual customizable parameters\n", + "ucid = \"basic\"\n", + "\n", + "\n", + "#NB The following should not be changed \n", + "projects_endpoint = service_base_endpoint + \"/projects/\"+ucid\n", + "ucd_endpoint = service_base_endpoint + \"/ucd/\"\n", + "plugins_endpoint=service_base_endpoint + \"/plugins/\"\n", + "\n", + "\n", + "## Import Rich text support for pretty json \n", + "!pip install rich[jupyter]\n", + "import rich\n", + "from rich import print_json\n", + "\n", + "## Define utility function for HTTP requests logging\n", + "def send(dest,data=None,method=\"GET\",params={}):\n", + " print(\"GOING TO SEND \"+method+\" REQUEST TO \"+dest)\n", + " headers={\n", + " 'Content-type':'application/json', \n", + " 'Accept':'*/*',\n", + " 'gcube-token':gcube_token\n", + " }\n", + " if data is not None : print(\"Data is \"+str(data))\n", + " if method == \"GET\" : response = requests.get(url=dest,params=params,headers=headers)\n", + " if method == \"PUT\" : response = requests.put(url=dest,data=data,params=params,headers=headers)\n", + " if method == \"POST\" : response = requests.post(url=dest,data=data,params=params,headers=headers)\n", + " if method == \"DELETE\" : response = requests.delete(url=dest,data=data,params=params,headers=headers)\n", + " print(\"RESPONSE STATUS \"+str(response.status_code)) \n", + " if response.status_code<200 or response.status_code>=300 : \n", + " print(\"CAUSE \"+str(response.reason))\n", + " print(response.text)\n", + " return json.loads(response.text)\n", + "\n", + "#print(send(method=\"GET\",dest=\"http://geoportal.dev.int.d4science.net/geoportal-service/srv/mongo-concessioni/\"))" + ] + }, + { + "cell_type": "markdown", + "id": "2b565fd2-4884-4a01-a6f7-300ea8fd7028", + "metadata": { + "tags": [] + }, + "source": [ + "# Projects\n", + "\n", + "Projects are the main entities in gCube CMS. They represent a complex document comprising of its metadata, its datasets, and related information aimed at properly consume them.\\ \n", + "The present section guides through the management of CMS Projects, explaining it's model and all supported operations." + ] + }, + { + "cell_type": "markdown", + "id": "be47ca27-fc7b-42f5-9a54-0d01d59221e3", + "metadata": {}, + "source": [ + "Projects enacapsulate user's JSON Document in a richer format comprising : \n", + "- Core Metadata : Metadata information used by the service to manage the project lifecycle\n", + "- The Document : A JSON Object compliant to user's defined schema, reporting both \n", + " - The actual metadata regarding the managed documents\n", + " - Attachments references to payloads and generated materializations\n", + "\n", + "Projects are linked to Use Case Descriptors (UCD), which define how its Document contents are gonna be treated in the system.\n", + "\n", + "More detailed informations can be found at https://gcube.wiki.gcube-system.org/gcube/GeoPortal_Service\n", + "\n", + "NB: In this notebook we are going to use the UCD \"basicUCD\". If you want to learn more about UCDs, please refer to wiki pages or related notebooks.\n", + "\n", + "NB: User can experiment with different UCDs but they need to be published in the current infrastructure's Context." + ] + }, + { + "cell_type": "markdown", + "id": "0a949821-435a-4b33-8ed0-2e45049be441", + "metadata": { + "tags": [] + }, + "source": [ + "## Create New\n", + "Start This tutorial by creating your new Project." + ] + }, + { + "cell_type": "markdown", + "id": "ecabb6d7-d86c-4682-8c01-5024e7bf76a1", + "metadata": {}, + "source": [ + "In this section we are going to create a new simple document and inspect the result. \n", + "You will learn the basic sections of a Project Metadata and their meaning.\n", + "\n", + "It is sufficient to perform a post operation with our document as the body.\n", + "\n", + "The REST base endpoint for managing projects is SERVICE_BASE_ENDPOINT/projects/UCID where:\\\n", + "- SERVICE_BASE_ENDPOINT should be discovered from the infrastructure's Information System\n", + "- UCID is the ID of the Use Case Descriptor to be used with this project" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "1cf34b3e-56ca-43c7-8206-3e16cebb80e0", + "metadata": {}, + "outputs": [], + "source": [ + "# Edit this section to customize your document\n", + "doc={\"myTitle\":\"Some Big Title\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ba665887-9718-44ee-be51-62283fa2dbb2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GOING TO SEND POST REQUEST TO https://geoportal.dev.int.d4science.net/geoportal-service/srv/projects/basic\n", + "Data is {\"myTitle\": \"Some Big Title\"}\n", + "RESPONSE STATUS 200\n", + "Resulting project is \n" + ] + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"_id\": \"62502e8902ad3d59dffb098e\",\n",
+       "  \"_version\": \"1.0.0\",\n",
+       "  \"_info\": {\n",
+       "    \"_creationInfo\": {\n",
+       "      \"_user\": {\n",
+       "        \"_username\": \"FAKE\"\n",
+       "      },\n",
+       "      \"_context\": {\n",
+       "        \"_id\": \"/gcube/devsec/devVRE\",\n",
+       "        \"_name\": \"/devVRE\"\n",
+       "      },\n",
+       "      \"_instant\": \"2022-04-08T14:46:01.718\"\n",
+       "    },\n",
+       "    \"_lastEditInfo\": null,\n",
+       "    \"_access\": {\n",
+       "      \"_policy\": \"OPEN\",\n",
+       "      \"_license\": \"\"\n",
+       "    }\n",
+       "  },\n",
+       "  \"_profileID\": \"basic\",\n",
+       "  \"_profileVersion\": \"1.0.0\",\n",
+       "  \"_lifecycleInformation\": {\n",
+       "    \"_phase\": \"DRAFT\",\n",
+       "    \"_lastInvokedStep\": null,\n",
+       "    \"_lastOperationStatus\": \"OK\",\n",
+       "    \"_errorMessages\": [],\n",
+       "    \"_warningMessages\": [],\n",
+       "    \"_triggeredEvents\": [\n",
+       "      {\n",
+       "        \"event\": \"INIT_DOCUMENT\",\n",
+       "        \"lastOperationStatus\": \"OK\",\n",
+       "        \"errorMessages\": null,\n",
+       "        \"warningMessages\": null\n",
+       "      }\n",
+       "    ],\n",
+       "    \"_notes\": null\n",
+       "  },\n",
+       "  \"_relationships\": null,\n",
+       "  \"_spatialReference\": null,\n",
+       "  \"_temporalReference\": null,\n",
+       "  \"_theDocument\": {\n",
+       "    \"myTitle\": \"Some Big Title\"\n",
+       "  },\n",
+       "  \"_lock\": null\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_id\"\u001b[0m: \u001b[32m\"62502e8902ad3d59dffb098e\"\u001b[0m,\n", + " \u001b[1;34m\"_version\"\u001b[0m: \u001b[32m\"1.0.0\"\u001b[0m,\n", + " \u001b[1;34m\"_info\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_creationInfo\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_user\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_username\"\u001b[0m: \u001b[32m\"FAKE\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"_context\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_id\"\u001b[0m: \u001b[32m\"/gcube/devsec/devVRE\"\u001b[0m,\n", + " \u001b[1;34m\"_name\"\u001b[0m: \u001b[32m\"/devVRE\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"_instant\"\u001b[0m: \u001b[32m\"2022-04-08T14:46:01.718\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"_lastEditInfo\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"_access\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_policy\"\u001b[0m: \u001b[32m\"OPEN\"\u001b[0m,\n", + " \u001b[1;34m\"_license\"\u001b[0m: \u001b[32m\"\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"_profileID\"\u001b[0m: \u001b[32m\"basic\"\u001b[0m,\n", + " \u001b[1;34m\"_profileVersion\"\u001b[0m: \u001b[32m\"1.0.0\"\u001b[0m,\n", + " \u001b[1;34m\"_lifecycleInformation\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_phase\"\u001b[0m: \u001b[32m\"DRAFT\"\u001b[0m,\n", + " \u001b[1;34m\"_lastInvokedStep\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"_lastOperationStatus\"\u001b[0m: \u001b[32m\"OK\"\u001b[0m,\n", + " \u001b[1;34m\"_errorMessages\"\u001b[0m: \u001b[1m[\u001b[0m\u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"_warningMessages\"\u001b[0m: \u001b[1m[\u001b[0m\u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"_triggeredEvents\"\u001b[0m: \u001b[1m[\u001b[0m\n", + " \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"event\"\u001b[0m: \u001b[32m\"INIT_DOCUMENT\"\u001b[0m,\n", + " \u001b[1;34m\"lastOperationStatus\"\u001b[0m: \u001b[32m\"OK\"\u001b[0m,\n", + " \u001b[1;34m\"errorMessages\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"warningMessages\"\u001b[0m: \u001b[3;35mnull\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"_notes\"\u001b[0m: \u001b[3;35mnull\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"_relationships\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"_spatialReference\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"_temporalReference\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"_theDocument\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"myTitle\"\u001b[0m: \u001b[32m\"Some Big Title\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"_lock\"\u001b[0m: \u001b[3;35mnull\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "project= send(method=\"POST\",dest=projects_endpoint,data=json.dumps(doc))\n", + "\n", + "print(\"Resulting project is \")\n", + "print_json(data=project)" + ] + }, + { + "cell_type": "markdown", + "id": "6c58326a-7f6f-45cf-a963-4fdb19fe42e0", + "metadata": { + "tags": [] + }, + "source": [ + "## Core Metadata Section\n", + "Registered JSON Documents are wrapped in Projects, which Let's inspect the registered JSON object structure and the most useful information in it." + ] + }, + { + "cell_type": "markdown", + "id": "62cbd63b-0007-428c-82d6-643b6da4577e", + "metadata": {}, + "source": [ + "The field _theDocument represents our document of interest.\n", + "\n", + "NB : Depending on the linked UCD, the returned document might be different from the output.\\\n", + "This is due to the fact that the UCD is configured to automatically perform some operation at creation time (e.g. \"set defaults values\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2b0076fa-0ab5-44a5-b069-2fdc0d6d70be", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
{\n",
+       "  \"myTitle\": \"Some Big Title\"\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"myTitle\"\u001b[0m: \u001b[32m\"Some Big Title\"\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "print_json(data=project[\"_theDocument\"])" + ] + }, + { + "cell_type": "markdown", + "id": "e2388067-b608-4932-8a9a-573bb07547c4", + "metadata": { + "tags": [] + }, + "source": [ + "### ID\n", + "The field _id is the unique identifier of the project.\\\n", + "We are gonna use it for all REST operations that involves our project." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8e2fd339-4117-49d4-9a3c-d9463d35ba2d", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\"62502e8902ad3d59dffb098e\"\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[32m\"62502e8902ad3d59dffb098e\"\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "print_json(data=project[\"_id\"])" + ] + }, + { + "cell_type": "markdown", + "id": "d6e89eb2-8eaa-40c3-a058-dd9f44de3d12", + "metadata": { + "tags": [] + }, + "source": [ + "### Accounting Information\n", + "\n", + "The field _info contains the following accounting information related to the project : \n", + "- _creationInfo : user, context and instant of creation\n", + "- _lastEditInfo : user, context and instant of last edit operation\n", + "- _access : project access policy (can be OPEN, RESTRICTED or EMBARGOED), project license" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "228daf3a-ec36-403c-84f4-dc7ff1fde026", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
{\n",
+       "  \"_creationInfo\": {\n",
+       "    \"_user\": {\n",
+       "      \"_username\": \"FAKE\"\n",
+       "    },\n",
+       "    \"_context\": {\n",
+       "      \"_id\": \"/gcube/devsec/devVRE\",\n",
+       "      \"_name\": \"/devVRE\"\n",
+       "    },\n",
+       "    \"_instant\": \"2022-04-08T14:46:01.718\"\n",
+       "  },\n",
+       "  \"_lastEditInfo\": null,\n",
+       "  \"_access\": {\n",
+       "    \"_policy\": \"OPEN\",\n",
+       "    \"_license\": \"\"\n",
+       "  }\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_creationInfo\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_user\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_username\"\u001b[0m: \u001b[32m\"FAKE\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"_context\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_id\"\u001b[0m: \u001b[32m\"/gcube/devsec/devVRE\"\u001b[0m,\n", + " \u001b[1;34m\"_name\"\u001b[0m: \u001b[32m\"/devVRE\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"_instant\"\u001b[0m: \u001b[32m\"2022-04-08T14:46:01.718\"\u001b[0m\n", + " \u001b[1m}\u001b[0m,\n", + " \u001b[1;34m\"_lastEditInfo\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"_access\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_policy\"\u001b[0m: \u001b[32m\"OPEN\"\u001b[0m,\n", + " \u001b[1;34m\"_license\"\u001b[0m: \u001b[32m\"\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "print_json(data=project[\"_info\"])" + ] + }, + { + "cell_type": "markdown", + "id": "5153e2ae-931c-4040-bb15-481a58a6d755", + "metadata": { + "tags": [] + }, + "source": [ + "### Lifecycle Information \n", + "The field _lifecycleInformation contains the a structured report of the status of the project containing: \n", + "- _phase : The workflow phase in which the document is at the moment\n", + "- _lastInvokedStep : Report on the last executed workflow STEP\n", + "- _triggeredEvents : Collections of reports regarding the triggered events\n", + "- _notes : User defined notes on the status of the project\n", + "- _errorMessages : Human readable error messages, if any\n", + "- _warningMessages : Human readable warning messages, if any\n", + "\n", + "See Plugins section for more information." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "d2059a6e-b1a5-484a-a48e-16158d6015d5", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
{\n",
+       "  \"_phase\": \"DRAFT\",\n",
+       "  \"_lastInvokedStep\": null,\n",
+       "  \"_lastOperationStatus\": \"OK\",\n",
+       "  \"_errorMessages\": [],\n",
+       "  \"_warningMessages\": [],\n",
+       "  \"_triggeredEvents\": [\n",
+       "    {\n",
+       "      \"event\": \"INIT_DOCUMENT\",\n",
+       "      \"lastOperationStatus\": \"OK\",\n",
+       "      \"errorMessages\": null,\n",
+       "      \"warningMessages\": null\n",
+       "    }\n",
+       "  ],\n",
+       "  \"_notes\": null\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"_phase\"\u001b[0m: \u001b[32m\"DRAFT\"\u001b[0m,\n", + " \u001b[1;34m\"_lastInvokedStep\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"_lastOperationStatus\"\u001b[0m: \u001b[32m\"OK\"\u001b[0m,\n", + " \u001b[1;34m\"_errorMessages\"\u001b[0m: \u001b[1m[\u001b[0m\u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"_warningMessages\"\u001b[0m: \u001b[1m[\u001b[0m\u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"_triggeredEvents\"\u001b[0m: \u001b[1m[\u001b[0m\n", + " \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"event\"\u001b[0m: \u001b[32m\"INIT_DOCUMENT\"\u001b[0m,\n", + " \u001b[1;34m\"lastOperationStatus\"\u001b[0m: \u001b[32m\"OK\"\u001b[0m,\n", + " \u001b[1;34m\"errorMessages\"\u001b[0m: \u001b[3;35mnull\u001b[0m,\n", + " \u001b[1;34m\"warningMessages\"\u001b[0m: \u001b[3;35mnull\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[1;34m\"_notes\"\u001b[0m: \u001b[3;35mnull\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "print_json(data=project[\"_lifecycleInformation\"])" + ] + }, + { + "cell_type": "markdown", + "id": "14e0d68a-df8f-434c-9f82-d04bd2ea31d2", + "metadata": {}, + "source": [ + "### Spatial Reference\n", + "The field _spatialReference contains a GEOJSON geometry identifying the Project." + ] + }, + { + "cell_type": "markdown", + "id": "454d5dab-73aa-4fe7-ac44-f42aff1ba679", + "metadata": {}, + "source": [ + "E.g. like the following : \n", + "\n", + "```json\n", + "\"_spatialReference\":\n", + " {\n", + " \"type\": \"Point\",\n", + " \"bbox\":\n", + " [\n", + " 8.621178639172953,\n", + " 40.62975046683799,\n", + " 40.630257904721645,\n", + " 8.62091913167495\n", + " ],\n", + " \"coordinates\":\n", + " [\n", + " -32.00907926554869,\n", + " -32.00883133516304\n", + " ]\n", + " }\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "id": "a533d6f9-6b3d-429f-acfd-d35c6f1f83c1", + "metadata": {}, + "source": [ + "### Temporal Reference \n", + "TBD" + ] + }, + { + "cell_type": "markdown", + "id": "83850b57-8d2c-47e5-ba48-c213f53493fa", + "metadata": { + "tags": [] + }, + "source": [ + "## Editing a project\n", + "Edit the Document section of a Project. " + ] + }, + { + "cell_type": "markdown", + "id": "e38ae8ec-6aa9-4932-b052-69f8a6a9132a", + "metadata": {}, + "source": [ + "The Document section is the actual document that needs to be managed, and the most basic operation is updating it.\\\n", + "To do this it's sufficient to perform a put operation with our document as the body, specifying our project's ID\n", + "\n", + "The endpoint for this operation is going to be SERVICE_BASE_ENDPOINT/projects/UCID/ID where:\n", + "- SERVICE_BASE_ENDPOINT should be discovered from the infrastructure's Information System\n", + "- UCID is the ID of the Use Case Descriptor to be used with this project\n", + "- ID is our project Unique Identifier" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "4323986d-218f-4997-9fe0-c9ba9e3e3c84", + "metadata": {}, + "outputs": [], + "source": [ + "#We update our document nesting a sub section in it\n", + "doc={\n", + " \"myTitle\":\"My newer edited title\",\n", + " \"section\":{\"sectionTitle\":\"My new SubSection\"}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "6123e5e5-9150-47bd-a49a-b2bc21915d34", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GOING TO SEND PUT REQUEST TO https://geoportal.dev.int.d4science.net/geoportal-service/srv/projects/basic/62502e8902ad3d59dffb098e\n", + "Data is {\"myTitle\": \"My newer edited title\", \"section\": {\"sectionTitle\": \"My new SubSection\"}}\n", + "RESPONSE STATUS 200\n" + ] + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"myTitle\": \"My newer edited title\",\n",
+       "  \"section\": {\n",
+       "    \"sectionTitle\": \"My new SubSection\"\n",
+       "  }\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"myTitle\"\u001b[0m: \u001b[32m\"My newer edited title\"\u001b[0m,\n", + " \u001b[1;34m\"section\"\u001b[0m: \u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"sectionTitle\"\u001b[0m: \u001b[32m\"My new SubSection\"\u001b[0m\n", + " \u001b[1m}\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# NB uncomment to actually perform edit\n", + "project = send(method=\"PUT\",data=json.dumps(doc),dest=projects_endpoint+\"/\"+str(project[\"_id\"]))\n", + "print_json(data=project[\"_theDocument\"])" + ] + }, + { + "cell_type": "markdown", + "id": "5a3d20fc-dd8a-4d14-ab9b-36d80bad77fc", + "metadata": { + "tags": [] + }, + "source": [ + "## Upload Attachments : FileSets\n", + "Projects' documents can contain multiple collections of files called FileSet." + ] + }, + { + "cell_type": "markdown", + "id": "11dfedd2-bebd-420e-87b5-06b37bdd9327", + "metadata": {}, + "source": [ + "We use the concept of FileSet to identify a collection of files that should be managed together (e.g. GIS shape file along with its SHX file).\\\n", + "In this section we are going to register a FileSet in our project.\\\n", + "\n", + "The operations triggers :\n", + "- the upload and archive of passed data streams\n", + "- registration of the file in \"_theDocument\", precisely at the JSON path declared in the request\n", + "\n", + "NB Please beware that FileSet JSON paths MUST be deined in our UCD schema section." + ] + }, + { + "cell_type": "markdown", + "id": "e2bdb963-6746-4131-9607-de84b1f8a035", + "metadata": {}, + "source": [ + "In order to perform this operation we are going to create a JSON object request with at least the following information : \n", + "- fieldDefinitionPath : a JSON path pointing to the field definition in UCD schema [NB root is \"schema\"]\n", + "- parentPath : a JSON path pointing to the parent of our target element [NB root is \"_theDocument\"]\n", + "- fieldName : the target element name at which the FileSet is going to be registered\n", + "- streams : a collection of JSON objects, each containing\n", + " - id : the infrastructure STORAGE volatile ID of our File\n", + " - url : [Alternative to ID] the url at which our File can be downloaded.\n", + " - filename : our File name" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "07965581-532d-45e8-bbf8-0bbec1a15273", + "metadata": {}, + "outputs": [], + "source": [ + "registerFilesetRequest={\n", + " \"fieldDefinitionPath\":\"$.section._children[?(@.fileset)]\",\n", + " \"parentPath\":\"$.section\",\n", + " \"fieldName\":\"fileset\",\n", + " \"streams\":[{\"url\":\"https://www.cnr.it/sites/all/themes/custom/cnr03_theme/img/cnrlogo.svg\",\"filename\":\"myLogo.svg\"}]\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "1ee75f2a-1db1-497a-8ec3-cb51fd11a1f1", + "metadata": {}, + "source": [ + "Once our request is ready we can send it to server with a POST request at SERVICE_BASE_ENDPOINT/projects/UCID/registerFiles/ID where:\\\n", + "- SERVICE_BASE_ENDPOINT should be discovered from the infrastructure's Information System\n", + "- UCID is the ID of the Use Case Descriptor to be used with this project\n", + "- ID is our project Unique Identifier" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "832e043c-870b-4509-be92-d90865cfd105", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GOING TO SEND POST REQUEST TO https://geoportal.dev.int.d4science.net/geoportal-service/srv/projects/basic/registerFiles/62502e8902ad3d59dffb098e\n", + "Data is {\"fieldDefinitionPath\": \"$.section._children[?(@.fileset)]\", \"parentPath\": \"$.section\", \"fieldName\": \"fileset\", \"streams\": [{\"url\": \"https://www.cnr.it/sites/all/themes/custom/cnr03_theme/img/cnrlogo.svg\", \"filename\": \"myLogo.svg\"}]}\n", + "RESPONSE STATUS 500\n", + "CAUSE \n", + "HTTP Status 500 – Internal Server Error

HTTP Status 500 – Internal Server Error


Type Status Report

Message Internal Server Error

Description The server encountered an unexpected condition that prevented it from fulfilling the request.


Apache Tomcat/8.5.39 (Ubuntu)

\n" + ] + }, + { + "ename": "JSONDecodeError", + "evalue": "Expecting value: line 1 column 1 (char 0)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mJSONDecodeError\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [11]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m project \u001b[38;5;241m=\u001b[39m \u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mPOST\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43mdest\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprojects_endpoint\u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m/registerFiles/\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mproject\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m_id\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43mdata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mjson\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdumps\u001b[49m\u001b[43m(\u001b[49m\u001b[43mregisterFilesetRequest\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOur Registered FileSet\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 4\u001b[0m print_json(data\u001b[38;5;241m=\u001b[39mproject[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_theDocument\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msection\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfileset\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n", + "Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36msend\u001b[0;34m(dest, data, method, params)\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCAUSE \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m+\u001b[39m\u001b[38;5;28mstr\u001b[39m(response\u001b[38;5;241m.\u001b[39mreason))\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28mprint\u001b[39m(response\u001b[38;5;241m.\u001b[39mtext)\n\u001b[0;32m---> 40\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mjson\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloads\u001b[49m\u001b[43m(\u001b[49m\u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtext\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/opt/conda/lib/python3.9/json/__init__.py:346\u001b[0m, in \u001b[0;36mloads\u001b[0;34m(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)\u001b[0m\n\u001b[1;32m 341\u001b[0m s \u001b[38;5;241m=\u001b[39m s\u001b[38;5;241m.\u001b[39mdecode(detect_encoding(s), \u001b[38;5;124m'\u001b[39m\u001b[38;5;124msurrogatepass\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 343\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 344\u001b[0m parse_int \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m parse_float \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 345\u001b[0m parse_constant \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_pairs_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m kw):\n\u001b[0;32m--> 346\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_default_decoder\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 347\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 348\u001b[0m \u001b[38;5;28mcls\u001b[39m \u001b[38;5;241m=\u001b[39m JSONDecoder\n", + "File \u001b[0;32m/opt/conda/lib/python3.9/json/decoder.py:337\u001b[0m, in \u001b[0;36mJSONDecoder.decode\u001b[0;34m(self, s, _w)\u001b[0m\n\u001b[1;32m 332\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mdecode\u001b[39m(\u001b[38;5;28mself\u001b[39m, s, _w\u001b[38;5;241m=\u001b[39mWHITESPACE\u001b[38;5;241m.\u001b[39mmatch):\n\u001b[1;32m 333\u001b[0m \u001b[38;5;124;03m\"\"\"Return the Python representation of ``s`` (a ``str`` instance\u001b[39;00m\n\u001b[1;32m 334\u001b[0m \u001b[38;5;124;03m containing a JSON document).\u001b[39;00m\n\u001b[1;32m 335\u001b[0m \n\u001b[1;32m 336\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 337\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraw_decode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43midx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_w\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mend\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 338\u001b[0m end \u001b[38;5;241m=\u001b[39m _w(s, end)\u001b[38;5;241m.\u001b[39mend()\n\u001b[1;32m 339\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m end \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28mlen\u001b[39m(s):\n", + "File \u001b[0;32m/opt/conda/lib/python3.9/json/decoder.py:355\u001b[0m, in \u001b[0;36mJSONDecoder.raw_decode\u001b[0;34m(self, s, idx)\u001b[0m\n\u001b[1;32m 353\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mscan_once(s, idx)\n\u001b[1;32m 354\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[0;32m--> 355\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m JSONDecodeError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExpecting value\u001b[39m\u001b[38;5;124m\"\u001b[39m, s, err\u001b[38;5;241m.\u001b[39mvalue) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28mNone\u001b[39m\n\u001b[1;32m 356\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m obj, end\n", + "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)" + ] + } + ], + "source": [ + "project = send(method=\"POST\",dest=projects_endpoint+\"/registerFiles/\"+str(project[\"_id\"]),data=json.dumps(registerFilesetRequest))\n", + "\n", + "print(\"Our Registered FileSet\")\n", + "print_json(data=project[\"_theDocument\"][\"section\"][\"fileset\"])" + ] + }, + { + "cell_type": "markdown", + "id": "a7cb592f-da3f-4c71-a37d-d38a41b4a250", + "metadata": { + "tags": [] + }, + "source": [ + "## Workflow operation : Execute STEP\n", + "Execute operations on a Project in order to manage its lifecycle" + ] + }, + { + "cell_type": "markdown", + "id": "aab7d25c-ed43-4491-a2c5-0e21e99df69c", + "metadata": {}, + "source": [ + "Projects lifecycle may involve a lot of operations (usually perfomed by different users), that should be perfomed in a pre defined order eg : \n", + "- registration\n", + "- approval\n", + "- rejection\n", + "- validation\n", + "- notifications\n", + "- processing : \n", + " - materialization of Fileset in dedicated engines in order to properyl consume them (e.g. GIS, DBs, Catalogues, Data Analytics..)\n", + " - data analytics\n", + "\n", + "We can then visualize our document as passing through different PHASES of it lifecycle (e.g. DRAFT,APPROVED ...).\n", + "We call STEPs the operations that may later the PHASE of a project by : \n", + "- performing a predefined operation on our document\n", + "- [optionally]triggering generic events (e.g. notifications)\n", + "- altering a Project lifecycle information (reporting outcome, status, messages etc.)\n", + "\n", + "STEPS are implemented in LifecycleManager plugins.\n", + "The suite comes with a default set of a pre defined, general-purpose plugins that can help manage the user's project.\n", + "This set can be extended for custom implementations.\n", + "\n", + "NB : Projects lifecycles are configured in linked Use Case Descriptors.\\\n", + "Each Project starts in Draft PHASE and then changes according to configured Lifecycle Manager." + ] + }, + { + "cell_type": "markdown", + "id": "e288d77d-70f6-48bc-b78b-16e673d38100", + "metadata": {}, + "source": [ + "Once our request is ready we can send it to server with a POST request at SERVICE_BASE_ENDPOINT/projects/UCID/step/STEPID/<\\strong>ID where:\\\n", + "- SERVICE_BASE_ENDPOINT should be discovered from the infrastructure's Information System\n", + "- UCID is the ID of the Use Case Descriptor to be used with this project\n", + "- ID is our project Unique Identifier\n", + "- ID is our project Unique Identifier\n", + "\n", + "Depending on implementations and configurations, invoked STEP may expect/require some additional parameters.\\\n", + "These can be specified in the request body as a simple JSON object.\n", + "Please refere to specific plugin documentation for details." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "c1b72a2d-ce83-4e3d-94e0-8f3fd0638bd0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GOING TO SEND POST REQUEST TO https://geoportal.dev.int.d4science.net/geoportal-service/srv/projects/basic/step/62502e8902ad3d59dffb098e\n", + "Data is {\"stepID\": \"PUBLISH\"}\n", + "RESPONSE STATUS 400\n", + "CAUSE \n", + "Error (400) : this resource cannot process this request because it is malformed\n", + "Stacktrace:\n", + "org.gcube.smartgears.handlers.application.request.RequestException: error contating authorization for polices\n", + "\tat org.gcube.smartgears.handlers.application.request.RequestError.toException(RequestError.java:110)\n", + "\tat org.gcube.smartgears.handlers.application.request.RequestError.fire(RequestError.java:94)\n", + "\tat org.gcube.smartgears.handlers.application.request.RequestValidator.validatePolicy(RequestValidator.java:130)\n", + "\tat org.gcube.smartgears.handlers.application.request.RequestValidator.handleRequest(RequestValidator.java:62)\n", + "\tat org.gcube.smartgears.handlers.application.RequestHandler.onEvent(RequestHandler.java:58)\n", + "\tat org.gcube.smartgears.handlers.application.RequestHandler.onEvent(RequestHandler.java:21)\n", + "\tat org.gcube.smartgears.handlers.Pipeline.forward(Pipeline.java:65)\n", + "\tat org.gcube.smartgears.handlers.Pipeline.forward(Pipeline.java:72)\n", + "\tat org.gcube.smartgears.managers.RequestManager.doFilter(RequestManager.java:89)\n", + "\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\n", + "\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\n", + "\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)\n", + "\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)\n", + "\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)\n", + "\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)\n", + "\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)\n", + "\tat org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:660)\n", + "\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)\n", + "\tat org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:679)\n", + "\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\n", + "\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)\n", + "\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)\n", + "\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806)\n", + "\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)\n", + "\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n", + "\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n", + "\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n", + "\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n", + "\tat java.lang.Thread.run(Thread.java:748)\n", + "\n" + ] + }, + { + "ename": "JSONDecodeError", + "evalue": "Expecting value: line 1 column 1 (char 0)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mJSONDecodeError\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [15]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m#NB Assuming UCID = \"basic\"\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;66;03m#Prepare STEP execution request\u001b[39;00m\n\u001b[1;32m 3\u001b[0m STEPrequest\u001b[38;5;241m=\u001b[39m{\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstepID\u001b[39m\u001b[38;5;124m\"\u001b[39m : \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPUBLISH\u001b[39m\u001b[38;5;124m\"\u001b[39m}\n\u001b[0;32m----> 4\u001b[0m project\u001b[38;5;241m=\u001b[39m \u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mPOST\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43mdest\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprojects_endpoint\u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m/step/\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mproject\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m_id\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43mdata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mjson\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdumps\u001b[49m\u001b[43m(\u001b[49m\u001b[43mSTEPrequest\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOur resulting project new lifecycle information\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 7\u001b[0m print_json(data\u001b[38;5;241m=\u001b[39mproject[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_lifecycleInformation\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n", + "Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36msend\u001b[0;34m(dest, data, method, params)\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCAUSE \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m+\u001b[39m\u001b[38;5;28mstr\u001b[39m(response\u001b[38;5;241m.\u001b[39mreason))\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28mprint\u001b[39m(response\u001b[38;5;241m.\u001b[39mtext)\n\u001b[0;32m---> 40\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mjson\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloads\u001b[49m\u001b[43m(\u001b[49m\u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtext\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/opt/conda/lib/python3.9/json/__init__.py:346\u001b[0m, in \u001b[0;36mloads\u001b[0;34m(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)\u001b[0m\n\u001b[1;32m 341\u001b[0m s \u001b[38;5;241m=\u001b[39m s\u001b[38;5;241m.\u001b[39mdecode(detect_encoding(s), \u001b[38;5;124m'\u001b[39m\u001b[38;5;124msurrogatepass\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 343\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 344\u001b[0m parse_int \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m parse_float \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m 345\u001b[0m parse_constant \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_pairs_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m kw):\n\u001b[0;32m--> 346\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_default_decoder\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 347\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 348\u001b[0m \u001b[38;5;28mcls\u001b[39m \u001b[38;5;241m=\u001b[39m JSONDecoder\n", + "File \u001b[0;32m/opt/conda/lib/python3.9/json/decoder.py:337\u001b[0m, in \u001b[0;36mJSONDecoder.decode\u001b[0;34m(self, s, _w)\u001b[0m\n\u001b[1;32m 332\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mdecode\u001b[39m(\u001b[38;5;28mself\u001b[39m, s, _w\u001b[38;5;241m=\u001b[39mWHITESPACE\u001b[38;5;241m.\u001b[39mmatch):\n\u001b[1;32m 333\u001b[0m \u001b[38;5;124;03m\"\"\"Return the Python representation of ``s`` (a ``str`` instance\u001b[39;00m\n\u001b[1;32m 334\u001b[0m \u001b[38;5;124;03m containing a JSON document).\u001b[39;00m\n\u001b[1;32m 335\u001b[0m \n\u001b[1;32m 336\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 337\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraw_decode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43midx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_w\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mend\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 338\u001b[0m end \u001b[38;5;241m=\u001b[39m _w(s, end)\u001b[38;5;241m.\u001b[39mend()\n\u001b[1;32m 339\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m end \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28mlen\u001b[39m(s):\n", + "File \u001b[0;32m/opt/conda/lib/python3.9/json/decoder.py:355\u001b[0m, in \u001b[0;36mJSONDecoder.raw_decode\u001b[0;34m(self, s, idx)\u001b[0m\n\u001b[1;32m 353\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mscan_once(s, idx)\n\u001b[1;32m 354\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[0;32m--> 355\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m JSONDecodeError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExpecting value\u001b[39m\u001b[38;5;124m\"\u001b[39m, s, err\u001b[38;5;241m.\u001b[39mvalue) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28mNone\u001b[39m\n\u001b[1;32m 356\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m obj, end\n", + "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)" + ] + } + ], + "source": [ + "#NB Assuming UCID = \"basic\"\n", + "#Prepare STEP execution request\n", + "STEPrequest={\"stepID\" : \"PUBLISH\"}\n", + "project= send(method=\"POST\",dest=projects_endpoint+\"/step/\"+str(project[\"_id\"]),data=json.dumps(STEPrequest))\n", + "\n", + "print(\"Our resulting project new lifecycle information\")\n", + "print_json(data=project[\"_lifecycleInformation\"])" + ] + }, + { + "cell_type": "markdown", + "id": "10f2bfd5-30b0-4182-b8b9-3db158cf7b0c", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "## Materialization\n", + "Learn how Filesets are materialized into enhanced resources (e.g. GIS Layers, DBMS Tables, Algorithms..)" + ] + }, + { + "cell_type": "markdown", + "id": "9d9c127c-ff7c-4b29-8a4d-df693cbb6288", + "metadata": {}, + "source": [ + "As discussed above, Fileset may need to be managed in order to : \n", + "- materialize them in dedicated engines in order to properyl consume them (e.g. GIS, DBs, Catalogues, Data Analytics..)\n", + "- perform data analytics tasks\n", + "\n", + "If these processes generates some kind of consumable resources, they are registered in the Fileset as Materializations\n", + "\n", + "If the above execution went well (check for errors in the displayed lifecycle information), our fileset should have been materialized as a layer in our infrastructure SDI.\\\n", + "See below the enhanced fileset with new generated information about our new layer.\n", + "\n", + "NB Each FileSet Materialization type has a different structure, in order to adapt to the needs of the application." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8cb51f8c-7d55-496f-8787-fb66765d7d3d", + "metadata": {}, + "outputs": [], + "source": [ + "print_json(data=project[\"_theDocument\"][\"section\"][\"fileset\"])" + ] + }, + { + "cell_type": "markdown", + "id": "70363a51-e830-49b1-8b7f-1c35697dba2c", + "metadata": {}, + "source": [ + "### Gcube SDI Layers\n", + "GCUBE SDI Layers are materializations of a filesets in a gCube SDI.\n", + "They expose the following informations, allowing applications and users to consume the generated resources: \n", + "- _ogcLinks : Open Geospatial Consortium standard URLs\n", + "- _bbox\n", + "- _platformInfo : collection of platform - specific JSON objects\n", + "\n", + "Known platform info types are : \n", + "- GeoServer\n", + "- GeoNetwork (TBD)\n", + "- Thredds (TBD)\n", + "\n", + "Here is the layer generated in the above STEP execution" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8cb1e877-e262-4ee8-966d-c37e9bd8256b", + "metadata": {}, + "outputs": [], + "source": [ + "#pipenv install arcgis\n", + "# try and visualize GIS " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed6c9cb5-de1c-4b93-ada4-3445b189c5ac", + "metadata": {}, + "outputs": [], + "source": [ + "print_json(data=project[\"_theDocument\"][\"section\"][\"fileset\"][\"materializations\"][0])" + ] + }, + { + "cell_type": "markdown", + "id": "5e8e04cd-0e44-46a7-9984-4d863b8b3a2b", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "## Accessing Projects\n", + "The service allows for both access and querying against the internal Document archive." + ] + }, + { + "cell_type": "markdown", + "id": "c3990c67-f239-4b27-9136-7ea198f907bb", + "metadata": { + "tags": [] + }, + "source": [ + "### Querying" + ] + }, + { + "cell_type": "markdown", + "id": "32631682-7928-4432-8cfd-fbfb8fa738f2", + "metadata": {}, + "source": [ + "Queries can be perfomed with a POST HTTP Request at SERVICE_BASE_ENDPOINT/projects/UCID/query with a JSON body with the following fields : \n", + "- filter : the JSON filter to apply (see MongoDB documentation for more details)\n", + "- projection : the target format to use to represent the returned JSON objects (see MongoDB documentation for more details)\n", + "- ordering : determines ordering behaviour \n", + "-- direction : allowed values are ASCENDING and DESCENDING\n", + "-- fields : list of fields used for ordering\n", + "- paging : determines the paged request's window\n", + "-- offset\n", + "-- limit\n", + "\n", + "This feature heavily relies on the underlying Document Store Engine, currently mongoDB.\\\n", + "Please refer to mongoDB documentation for more details.\n", + "\n", + "The following sections provide some Query example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "09c86283-3afd-4199-a461-c54a33be2247", + "metadata": {}, + "outputs": [], + "source": [ + "#Query All\n", + "queryAll = {}\n", + "\n", + "# Query All with PHASE = PUBLISHED\n", + "queryPublished = {\n", + " \"filter\" : {\"_lifecycleInformation._phase\": {\"$eq\" : \"PUBLISHED\"}}\n", + "}\n", + "#ADD Ordering\n", + "queryOrdering = {\n", + " \"filter\" : {\"_lifecycleInformation._phase\": {\"$eq\" : \"PUBLISHED\"}},\n", + " \"ordering\" :{\"direction\":\"ASCENDING\",\"fields\":[{\"_theDocument.title\"}]}\n", + "}\n", + "#GET ONLY FIRST ELEMENT\n", + "queryFirst = {\n", + " \"filter\" : {\"_lifecycleInformation._phase\": {\"$eq\" : \"PUBLISHED\"}},\n", + " \"ordering\" :{\"direction\":\"ASCENDING\",\"fields\":[{\"_theDocument.title\"}]},\n", + " \"paging\" : {\"offset\":0,\"limit\":1}\n", + "}\n", + "#GET ONLY TITLE AND AUTHOR\n", + "queryTitleAndAuthor = {\n", + " \"filter\" : {\"_lifecycleInformation._phase\": {\"$eq\" : \"PUBLISHED\"}},\n", + " \"ordering\" :{\"direction\":\"ASCENDING\",\"fields\":[{\"_theDocument.title\"}]},\n", + " \"paging\" : {\"offset\":0,\"limit\":1},\n", + " \"projection\" :{\"_theDocument.title\":1,\"_info.creationUser.username\":1}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d09ab0b9-bf4d-425e-9509-588dd09cea72", + "metadata": {}, + "outputs": [], + "source": [ + "#Actually performing query\n", + "found = send(dest=projects_endpoint+\"/query\",data=json.dumps(queryAll),method=\"POST\")\n", + "print(\"Result Count :\"+str(len(found)))" + ] + }, + { + "cell_type": "markdown", + "id": "756a64e1-7938-40fe-9653-53a84778fe63", + "metadata": { + "tags": [] + }, + "source": [ + "### Get By ID \n", + "\n", + "As standard REST agreement, Projects can be obtained by their ID with a POST HTTP Request at SERVICE_BASE_ENDPOINT/projects/UCID/ID" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ea3a59a-eaeb-4e40-9b85-f84a0ae558d1", + "metadata": {}, + "outputs": [], + "source": [ + "#Lets take an id from previous query\n", + "projectId=found[0][\"_id\"]\n", + "project = send(method=\"GET\",dest=projects_endpoint+projectId)\n", + "print_json(data=project)" + ] + }, + { + "cell_type": "markdown", + "id": "d20b6e2c-1de4-4e39-8ed1-d4a2b445f2bd", + "metadata": { + "tags": [] + }, + "source": [ + "### Runtime Configuration\n", + "\n", + "Learn about how the service exposes information on how to access and consume generated resources." + ] + }, + { + "cell_type": "markdown", + "id": "e9befa01-4e51-4045-bf22-98b75e7e32f9", + "metadata": {}, + "source": [ + "As a collateral effect of workflow management, the following resources may be generated at runtime and managed by the service : \n", + "- Uploaded file archive : Based on gCube Workspace\n", + "- Document archive : Document store based archive of Projects\n", + "- Indexes : GIS, Textual, Documental indexes, DBMS\n", + "\n", + "These resources are not linked to one particular Project, but are related to the management of a specific UCD.\\\n", + "Applications that need to access these resources (e.g. GUIs) can access a Configuration report at SERVICE_BASE_ENDPOINT/projects/UCID/configuration." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e744a7de-c0f8-4268-9116-d54f6e01b0c5", + "metadata": {}, + "outputs": [], + "source": [ + "print_json(data=send(dest=projects_endpoint+\"/configuration\",method=\"GET\"))" + ] + }, + { + "cell_type": "markdown", + "id": "053cd583-abbe-423d-a77b-62601700c2f0", + "metadata": { + "tags": [] + }, + "source": [ + "# Use Case Descriptors - UCD\n", + "\n", + "Use Case Descriptors (UCDs) are JSON documents containing the configuration settings needed for the management of our Projects, from the creation to their consumption.\n", + "\n", + "In this section we are going to inspect both generic configurations (e.g. Data Access Policies) and some common Plugin configuration (e.g. Lifecycle Management)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "491c9be8-3d26-4f6e-8ddc-c2842cc5011f", + "metadata": {}, + "outputs": [], + "source": [ + "# loads UCD from service\n", + "queryUCDByID = {\"filter\" : {\"_id\":{\"$eq\":ucid}}}\n", + "\n", + "UCD = send(method=\"POST\",data=json.dumps(queryUCDByID),dest=ucd_endpoint+\"query\")\n", + "\n", + "print_json(data=UCD)" + ] + }, + { + "cell_type": "markdown", + "id": "0e1d658d-6701-4ee3-84a1-bccbfbc4e11b", + "metadata": { + "tags": [] + }, + "source": [ + "## UCD Format\n", + "UCD content can be expanded in order to satisfy involved components needs, but its basic structure is fixed." + ] + }, + { + "cell_type": "markdown", + "id": "007dffd2-9135-4701-9774-2d7fbc55cef9", + "metadata": {}, + "source": [ + "UCD most notable fields are : \n", + "- _id : the Unique Identifier of the UCD\n", + "- _schema : the schema of the document to be handled in Projects (see \"_theDocument\") linked to this UCD\n", + "- _creationInfo : accounting information about author, time of creation, Infrastructure Context\n", + "- _dataAccessPolicies : access rules based on user Role\n", + "- _handlers : specific configurations for all involved components (both Plugins and GUIs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa3ed543-6ef1-4611-ab61-a82ce5d375f1", + "metadata": {}, + "outputs": [], + "source": [ + "print_json(data=UCD)" + ] + }, + { + "cell_type": "markdown", + "id": "497028f0-b828-4e0f-b508-5b203ee98368", + "metadata": { + "tags": [] + }, + "source": [ + "### Schema\n", + "\n", + "This section represents the expected structure of a managed Document inside a Project linked to the present UCD." + ] + }, + { + "cell_type": "markdown", + "id": "cce26369-b73c-45fd-bda9-784e954f5bd5", + "metadata": {}, + "source": [ + "In general it's an optional section of a UCD, but most Handlers and features (e.g. FileSet operations) rely on this section.\n", + "\n", + "It is represented as a map of extensible Field objects with at least the following information : \n", + "- _type : String\n", + "- _max : Integer Maximum cardinality : (Default is 1)\n", + "- _min : Integer Minimum cardinality : (Default is 0)\n", + "- _label : String Human Readable Label\n", + "- _children : Field Collection Nested fields definition" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62c98f90-6a1c-4264-98bb-59fd6f2eda30", + "metadata": {}, + "outputs": [], + "source": [ + "print_json(data=UCD[\"_schema\"])" + ] + }, + { + "cell_type": "markdown", + "id": "799e8a1f-f7c1-495f-a518-4b44acc73c92", + "metadata": {}, + "source": [ + "### Data Access Policies\n", + "\n", + "Data Access Policies determine both READ and WRITE authorization on Projects, based on the user's Role\n", + "\n", + "Section _dataAccessPolicies of UCD contains a list of Rules in the following format : \n", + "- _policy [Mandatory] : contains read and write operation policy for the present Rule (allowed values are any,own and none)\n", + "- _roles [Mandatory] : Collections of users roles for witch the present Rule should be applied\n", + "- _enforcer : Additional conditions that should be always applied when accessing data (allowed value is filter)\n", + "\n", + "E.g. \n", + "The following rule : \n", + "- Applies as default (no roles are specified)\n", + "- Denies any WRITE operation\n", + "- Allows read operations to any Project\n", + "- Filters any access to Projects selecting only the one which Phase is Published\n", + "\n", + "\n", + "```json\n", + "{\"_policy\" : {\"_read\" : \"any\", \"_write\" : \"none\"}, \"_roles\":[],\n", + " \"_enforcer\": {\"_filter\" : {\"_lifecycleInformation._phase\" : {\"$eq\" : \"Published\"}}}},\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85981b69-cc66-4beb-9c8e-2b212ef3ab3f", + "metadata": {}, + "outputs": [], + "source": [ + "print_json(data=UCD[\"_dataAccessPolicies\"])" + ] + }, + { + "cell_type": "markdown", + "id": "03e461e2-bed8-4949-9262-97cf91e9262d", + "metadata": {}, + "source": [ + "### Handlers Configuration\n", + "\n", + "Handler configurations are simple JSON objects that wrap specific configuration for sw components that are going to consume our Projects.\n", + "\n", + "Its default structure is : \n", + "- _id : identifies the target plugin\n", + "- _type : declares the target plugin type\n", + "- _configuration : defines the actual plugin configuration (plugin specific)\n", + "\n", + "Please refere to the specific plugin guide for more information" + ] + }, + { + "cell_type": "markdown", + "id": "5d4971f4-c3c6-4f6f-ada8-b9b44f4088e7", + "metadata": { + "tags": [] + }, + "source": [ + "## Access and Querying\n", + "UCDs are also cached in the underlying document store Database, allwoing for the same querying capabilities as for Projects." + ] + }, + { + "cell_type": "markdown", + "id": "55cf0f3f-5681-4efe-8ca4-cdf90b43b9c8", + "metadata": {}, + "source": [ + "UCDs can be accessed by their cached MongoID at the following endpoint : SERVICE_BASE_ENDPOINT/ucd/MongoID" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a9289e7-2bfc-4d74-a8a7-b8cc3e237264", + "metadata": {}, + "outputs": [], + "source": [ + "#Perform get UCD by ID \n", + "print_json(data=send(method=\"GET\",dest=ucd_endpoint+str(UCD[\"_mongoId\"])))" + ] + }, + { + "cell_type": "markdown", + "id": "2997dd2b-db2e-4190-b99a-3a7254a33c86", + "metadata": {}, + "source": [ + "However, applications might want to perform one of the following queries or a more specific one.\\\n", + "Check Accessing Projects section for more details." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28393a1b-5019-4143-bef9-2c437823af66", + "metadata": {}, + "outputs": [], + "source": [ + "#Query BY UCID\n", + "query = {\"filter\" : {\"_id\":{\"$eq\":ucid}}}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45770051-0e3b-4546-9284-86378c148c14", + "metadata": {}, + "outputs": [], + "source": [ + "#Actually perform query\n", + "print(send(method=\"POST\",data=query,dest=ucd_endpoint+\"query\"))" + ] + }, + { + "cell_type": "markdown", + "id": "4e9068c1-2a16-4890-8f4d-9966c0352f0c", + "metadata": { + "tags": [] + }, + "source": [ + "# Plugins\n", + "\n", + "The CMS service itself only deals with generic logic of Projects lifecycle management. The actual hard work is performed by the Plugins configured in the linked Use Case Descriptor." + ] + }, + { + "cell_type": "markdown", + "id": "d51c4141-9139-48f9-938c-43823fede4a9", + "metadata": {}, + "source": [ + "In more details, the the basic service logic relies on a Lifecycle Manager for the execution of STEPS and EVENT handling, which in turn may exploit other plugins for its purposes.\\\n", + "Projects and document are only actually updated by the service logic, granting full centralized error management.\n", + "\n", + "![Lifecycle](https://gcube.wiki.gcube-system.org/images_gcube/1/10/LC_Management.png)\n", + "\n", + "In this section we are going to introduce some of the most common plugins that can be configured in UCDs.\\\n", + "NB : Plugin set can be expanded by the community both from scratch and by extending the already implemented behaviour" + ] + }, + { + "cell_type": "markdown", + "id": "13fe4942-e7cb-4590-b76d-5d8448041eae", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "## Lifecycle Managers\n", + "Lifecycle Managers are the main responsible for the execution of a Project workflow." + ] + }, + { + "cell_type": "markdown", + "id": "aa53f525-f9ba-4ea4-b14d-d66433c3a93f", + "metadata": {}, + "source": [ + "They define the support for STEPs, EVENTs and the resulting document PHASE, so basically they define the Workflow itself.\n", + "\n", + "However customizable, workflows shares some basic behaviour : \n", + "- Each Project starts in DRAFT PHASE, then it evolves depending on the configured Lifecycle Manager.\n", + "- The following EVENTS are always triggered (even if they can be implemented as NO-OP) :\n", + " - ON INIT\n", + " - ON UPDATE\n", + " - ON DELETE\n", + " - ON DELETE FILESET\n", + "\n", + "NB : ROLE based access to STEPs is entrusted to Lifecycle Managers. Provided implementations exploit the feature BasicRoleManager documented below.\n", + "\n", + "The service is distributed with some default implementations in order to provide support for common situations." + ] + }, + { + "cell_type": "markdown", + "id": "c37b85e1-f5fd-48e9-8c78-6ca507c8f11b", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "### DEFAULT-SINGLE-STEP\n", + "DEFAULT-SINGLE-STEP Lifecycle Manager is a simple workflow implementation consisting of a single STEP \"Publish\". " + ] + }, + { + "cell_type": "markdown", + "id": "58bd9215-2b29-4d5c-b8a9-7ea8c34ea05e", + "metadata": {}, + "source": [ + "PUBLISH step:\n", + "- materializes GIS Resources exploiting SDI-Default-Materializer plugin\n", + "- indexes GIS resources in a centroid layers exploiting SDI-Indexer-Plugin plugin\n", + "- sets the Project PHASE to \"PUBLISHED\"\n", + "- [optionally] sends notifications via Notification plugin \n", + "\n", + "The following events are also managed :\n", + "- ON INIT (basic validation, basic default values evaluation)\n", + "- ON UPDATE (basic validation, basic default values evaluation)\n", + "- ON DELETE (delete all materializations and index references)\n", + "- ON DELETE FILESET (delete Fileset materializations and update index references)\n", + "\n", + "It exploits the feature BasicRoleManager documented below." + ] + }, + { + "cell_type": "markdown", + "id": "1d6c5a2a-fe5d-447f-b2c4-63abbee49abb", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "### DEFAULT-3PHASE\n", + "DEFAULT-3PHASE Lifecycle Manager is a moderated workflow implementation which allows for approval a rejection of submitted Drafts." + ] + }, + { + "cell_type": "markdown", + "id": "8ce769bb-0581-4ca9-bbd3-b356186cd41d", + "metadata": {}, + "source": [ + "It can be summarized with the following diagram :\n", + "\n", + "![3Phase](https://support.d4science.org/attachments/download/6070/3PhaseLC.png)\n", + "\n", + "It is built on top of DEFAULT-SINGLE-STEP, extending its behavior in order to : \n", + "- Manage different indexes (restricted and public) for documets in PHASES \"Awaiting Approval\" and \"Published\"\n", + "- Allow for iterative editing cycle between submitting user and moderators\n", + "\n", + "It exploits the feature BasicRoleManager documented below." + ] + }, + { + "cell_type": "markdown", + "id": "0a408c93-621b-4f77-ab47-f3c1941bec6b", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "### Basic Role Manager\n", + "\n", + "Basic role manager is an internal feature of the CMS service. It restricts execution of STEPs based on user Role.\n", + "It reads the Lifecycle manager configuration expecting a collection of rules like in the following example." + ] + }, + { + "cell_type": "markdown", + "id": "d11d003c-a83a-45bb-80fb-ec6749d65a94", + "metadata": {}, + "source": [ + "The following configuration allows users with Editor role to only SUBMIT projects, while Moderator and DataAdmin can also PUBLISH\n", + "\n", + "```json\n", + "{\n", + " \"_id\" : \"DEFAULT-SINGLE-STEP\",\n", + " \"_type\" : \"LifecycleManagement\",\n", + " \"_configuration\" : {\n", + " ...\n", + " \"step_access\" : [\n", + " {\"STEP\" : \"PUBLISH\", \"roles\" :[ \"Moderator\",\"DataAdmin\"]},\n", + " {\"STEP\" : \"SUBMIT\", \"roles\" :[ \"Editor\",\"Moderator\",\"DataAdmin\"]}\n", + " ]\n", + " }\n", + " }\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "2bd5318e-3652-4785-9aba-25dfdb85f6de", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "## Indexer Plugins\n", + "Indexer plugins are in charge of managing resources (Indexes)that contain references to the Projects in order to provide some kind of browsing experience through them.\\\n", + "They use the information on the selected Project to manage Index entries and (optionally) generate spatialReferences and temporalReferences." + ] + }, + { + "cell_type": "markdown", + "id": "bbdb399a-9c07-49bf-877f-2b5d284f0bd7", + "metadata": {}, + "source": [ + "### SDI-Indexer-Plugin\n", + "This plugin manages centroids layers in the SDI GeoServer, generating the Project spatialReference.\n", + "\n", + "It expects following UCD Handler Configuration : \n", + "- bboxEvaluation Collection of JSONPaths to use in order to evaluate the Project centroid\n", + "- explicitFieldMapping Collection of JSON Object defining the centroid record fields along with JSONPath for their evaluation\n", + "- additionalLayers Collection of JSON Objects defining additional layers to use for cross-reference querying of the centroid layers\n", + "\n", + "A typycal configuration might be as following : \n", + "```json\n", + " {\n", + " \"_id\" : \"SDI-Indexer-Plugin\",\n", + " \"_type\" : \"Indexer\",\n", + " \"_configuration\" : {\n", + " \"bboxEvaluation\" : [\"$.._bbox\"],\n", + " \"explicitFieldMapping\" : [\n", + " {\"name\" : \"titolo\", \"path\" : \"$._theDocument.title\", \"type\" : \"TEXT\"}\n", + " ],\n", + " \"jslt\" : {},\n", + " \"additionalLayers\" : [\n", + " {\"source\" : {\"url\" : \"...\"},\"toSetTitle\":\"\"}\n", + " ]\n", + " }\n", + " }\n", + "```\n", + "\n", + "It also expects the Lifecycle manager to provide the following call Parameters : \n", + "- Indexing request\n", + " - indexName : must be unique (table in postgis)\n", + " - worksapce : GeoServer Workspace\n", + " - centroidRecord : optionally declare the record to index instead of evaluating it" + ] + }, + { + "cell_type": "markdown", + "id": "889e6e56-1d5c-48ad-ad09-c8a6861315ca", + "metadata": { + "tags": [] + }, + "source": [ + "## Materializer Plugins\n", + "Materializer plugins are in charge of generating resources representing FileSets, and producing their references to be set in the Document itself." + ] + }, + { + "cell_type": "markdown", + "id": "22799978-5c63-487d-badc-3a1adff27e13", + "metadata": { + "tags": [] + }, + "source": [ + "### SDI-Indexer-Plugin\n", + "This plugin orchestrate the creation and publication of GIS Layers in the infrastructure's SDI, registering FileSets in its specific target engine (depending on data formats)." + ] + }, + { + "cell_type": "markdown", + "id": "afe3d19c-7984-4418-88a5-3157d415adff", + "metadata": {}, + "source": [ + "Currently supported data formats are : \n", + "- SHP : shape files (along with SHX files if present)\n", + "\n", + "It expects the following UCD Handler Configuration : \n", + "- registeredFileSetPaths Collection of JSONPaths pairs pointing to the FileSets to be Materialized by this plugin.\n", + "\n", + "A typycal configuration might be as following : \n", + "```json\n", + " {\n", + " \"_id\" : \"SDI-Default-Materializer\",\n", + " \"_type\" : \"Materializer\",\n", + " \"_configuration\" : {\n", + " \"registeredFileSetPaths\" : [\n", + " {\"schemaField\" : \"pianteFineScavo\",\"documentPath\" : \"pianteFineScavo[*].fileset\"},\n", + " {\"schemaField\" : \"posizionamentoScavo\",\"documentPath\" : \"posizionamentoScavo.fileset\"}\n", + " ]\n", + " }\n", + " }\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "0542d2bd-cf63-4a20-a87e-fa5276168e7b", + "metadata": {}, + "source": [ + "## Getting installed plugins\n", + "The service allows for inspaction and management of installed plugins." + ] + }, + { + "cell_type": "markdown", + "id": "4666c8ce-d45f-4bb4-9f0b-76a646b7bb6d", + "metadata": {}, + "source": [ + "Installed plugins descriptors can be obtained at SERVICE_BASE_ENDPOINT/plugins and SERVICE_BASE_ENDPOINT/plugins/pluginID" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "194b9dc7-1b55-4a7f-b25e-18ad2b2795ea", + "metadata": {}, + "outputs": [], + "source": [ + "print_json(data=send(method=\"GET\",dest=plugins_endpoint))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "763e69ec-7b03-44af-afc7-d1eaaedfc4c2", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.10" + }, + "toc-autonumbering": true, + "toc-showtags": false + }, + "nbformat": 4, + "nbformat_minor": 5 +}