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 ErrorHTTP 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
+}