diff --git a/catalogue-binding-plugin/pom.xml b/catalogue-binding-plugin/pom.xml
index 51d592a..8aad78d 100644
--- a/catalogue-binding-plugin/pom.xml
+++ b/catalogue-binding-plugin/pom.xml
@@ -58,6 +58,49 @@
provided
+
+ org.freemarker
+ freemarker
+ 2.3.32
+
+
+
+ org.gcube.application
+ geoportal-client
+ [1.1.0-SNAPSHOT, 2.0.0-SNAPSHOT)
+
+
+ javax.servlet
+ servlet-api
+
+
+ org.projectlombok
+ lombok
+
+
+ test
+
+
+
+ org.gcube.application
+ geoportal-data-mapper
+ [1.0.0, 2.0.0-SNAPSHOT)
+
+
+
+ org.gcube.contentmanagement
+ storage-manager-wrapper
+
+
+ org.gcube.contentmanagement
+ storage-manager-core
+
+
+ test
+
+
+
org.gcube.application.cms
cms-test-commons
diff --git a/catalogue-binding-plugin/src/test/.gitignore b/catalogue-binding-plugin/src/test/.gitignore
new file mode 100644
index 0000000..cb6eb2c
--- /dev/null
+++ b/catalogue-binding-plugin/src/test/.gitignore
@@ -0,0 +1 @@
+/resources/
diff --git a/catalogue-binding-plugin/src/test/java/geoportal_to_catalogue/GeoportalToCatalogue.java b/catalogue-binding-plugin/src/test/java/geoportal_to_catalogue/GeoportalToCatalogue.java
new file mode 100644
index 0000000..68d3500
--- /dev/null
+++ b/catalogue-binding-plugin/src/test/java/geoportal_to_catalogue/GeoportalToCatalogue.java
@@ -0,0 +1,155 @@
+package geoportal_to_catalogue;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bson.Document;
+import org.gcube.application.geoportal.client.utils.Serialization;
+import org.gcube.application.geoportal.common.model.document.Project;
+import org.gcube.application.geoportalcommon.geoportal.GeoportalClientCaller;
+import org.gcube.application.geoportalcommon.geoportal.ProjectsCaller;
+import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
+import org.gcube.common.scope.api.ScopeProvider;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import com.jayway.jsonpath.DocumentContext;
+import com.jayway.jsonpath.JsonPath;
+import com.jayway.jsonpath.spi.json.JsonOrgJsonProvider;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import test.TestContextConfig;
+
+public class GeoportalToCatalogue {
+
+ public final static String profileID = "profiledConcessioni";
+ public final static String projectID = "66714cdea08b3011b506e089";
+
+ public static void main(String[] args) {
+
+ try {
+
+ TestContextConfig.readContextSettings();
+
+ ScopeProvider.instance.set(TestContextConfig.CONTEXT);
+ SecurityTokenProvider.instance.set(TestContextConfig.TOKEN);
+
+ ProjectsCaller clientProjects = GeoportalClientCaller.projects();
+ Project theProject = clientProjects.getProjectByID(profileID, projectID);
+ Document asDocument = Serialization.asDocument(theProject);
+
+ //System.out.println(prettyPrintUsingGson(asDocument.toJson()));
+ applyMappingToCatalogue(asDocument.toJson());
+
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+
+ }
+
+ public static Map fmtJsonUtil(String json)
+ throws JsonParseException, JsonMappingException, IOException {
+ ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+ return OBJECT_MAPPER.readValue(json, new TypeReference>() {
+ });
+
+ }
+
+ public static void applyMappingToCatalogue(String json) {
+
+ // Create your Configuration instance, and specify if up to what FreeMarker
+ // version (here 2.3.32) do you want to apply the fixes that are not 100%
+ // backward-compatible. See the Configuration JavaDoc for details.
+ Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
+ System.out.println("Working Directory = " + System.getProperty("user.dir"));
+
+ Template template;
+ try {
+
+ // Specify the source where the template files come from. Here I set a
+ // plain directory for it, but non-file-system sources are possible too:
+ cfg.setDirectoryForTemplateLoading(
+ new File(System.getProperty("user.dir") + "/src/test/java/geoportal_to_catalogue"));
+
+ // From here we will set the settings recommended for new projects. These
+ // aren't the defaults for backward compatibilty.
+
+ // Set the preferred charset template files are stored in. UTF-8 is
+ // a good choice in most applications:
+ cfg.setDefaultEncoding("UTF-8");
+
+ template = cfg.getTemplate("d4gna_to_catalogue_template.ftl");
+
+ Map toJsonMap = fmtJsonUtil(json);
+ File tempFile = writeTempFile(json);
+ StringWriter stringWriter = new StringWriter();
+
+ Map root = new HashMap();
+ root.put("doc", toJsonMap);
+
+ template.process(root, stringWriter);
+ String toCatalogueJSON = stringWriter.toString();
+ System.out.println("\n\ntoCatalogueString:" + toCatalogueJSON);
+
+
+ //System.out.println(prettyPrintUsingGson(toCatalogueJSON));
+
+ com.jayway.jsonpath.Configuration configuration = com.jayway.jsonpath.Configuration.builder()
+ .jsonProvider(new JsonOrgJsonProvider()).build();
+
+ JSONObject theRootDocument = JSONObjectOrdered.instance();
+ theRootDocument.put("key", "Gis Link");
+ theRootDocument.put("value", "https://data.dev.d4science.org");
+
+ System.out.println("gis link: "+theRootDocument);
+
+ DocumentContext theDoc = JsonPath.parse(toCatalogueJSON,configuration);
+ theDoc.add("$.extras", theRootDocument);
+
+ System.out.println("\n\nTo pretty print JSON:");
+ //System.out.println("gis link: "+theDoc.jsonString());
+ System.out.println(prettyPrintUsingGson(theDoc.jsonString()));
+
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (TemplateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public static String prettyPrintUsingGson(String uglyJson) {
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ JsonElement jsonElement = new JsonParser().parse(uglyJson);
+ String prettyJsonString = gson.toJson(jsonElement);
+ return prettyJsonString;
+ }
+
+ public static File writeTempFile(String toWrite) throws IOException {
+ File tmpFile = File.createTempFile("test", ".tmp");
+ FileWriter writer = new FileWriter(tmpFile);
+ writer.write(toWrite);
+ writer.close();
+
+ return tmpFile;
+ }
+
+}
diff --git a/catalogue-binding-plugin/src/test/java/geoportal_to_catalogue/JSONObjectOrdered.java b/catalogue-binding-plugin/src/test/java/geoportal_to_catalogue/JSONObjectOrdered.java
new file mode 100644
index 0000000..0ec444b
--- /dev/null
+++ b/catalogue-binding-plugin/src/test/java/geoportal_to_catalogue/JSONObjectOrdered.java
@@ -0,0 +1,33 @@
+package geoportal_to_catalogue;
+
+import java.lang.reflect.Field;
+import java.util.LinkedHashMap;
+
+import org.json.JSONObject;
+
+/**
+ * The Class JSONObjecOrdered.
+ *
+ * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
+ *
+ * Mar 10, 2022
+ */
+public final class JSONObjectOrdered {
+
+ /**
+ * Instance.
+ *
+ * @return the JSON object
+ */
+ public static JSONObject instance() {
+ JSONObject jsonObject = new JSONObject();
+ try {
+ Field changeMap = jsonObject.getClass().getDeclaredField("map");
+ changeMap.setAccessible(true);
+ changeMap.set(jsonObject, new LinkedHashMap<>());
+ changeMap.setAccessible(false);
+ } catch (IllegalAccessException | NoSuchFieldException e) {
+ }
+ return jsonObject;
+ }
+}
diff --git a/catalogue-binding-plugin/src/test/java/geoportal_to_catalogue/d4gna_to_catalogue_template.ftl b/catalogue-binding-plugin/src/test/java/geoportal_to_catalogue/d4gna_to_catalogue_template.ftl
new file mode 100644
index 0000000..9ce045f
--- /dev/null
+++ b/catalogue-binding-plugin/src/test/java/geoportal_to_catalogue/d4gna_to_catalogue_template.ftl
@@ -0,0 +1,247 @@
+<#assign jsonProj=doc>
+<#assign theDocument=jsonProj._theDocument>
+
+<#assign resources=[]>
+<#assign groups=[]>
+<#assign tags=[]>
+<#assign extras=[]>
+
+<#-- Macro to assign Tags -->
+<#macro assignTag in_tags>
+<#if in_tags??>
+ <#if in_tags?is_sequence>
+ <#list in_tags as my_tag>
+ <#assign tags = tags + [my_tag] />
+ #list>
+ <#else>
+ <#assign tags = tags + [in_tags] />
+ #if>
+ #if>
+#macro>
+
+<#-- Macro to assign a Resource -->
+<#macro assignResource name url description format>
+<#if description??>
+<#else>
+<#assign description = ""/>
+#if>
+<#if url??>
+ <#assign resource = {"name": name, "url": url, "description": description, "format": format}>
+ <#assign resources = resources + [resource]/>
+#if>
+#macro>
+
+<#-- Macro to assign Groups -->
+<#macro assignGroup in_groups>
+<#if in_groups??>
+ <#if in_groups?is_sequence>
+ <#list in_groups as my_group>
+ <#assign groups = groups + [my_group] />
+ #list>
+ <#else>
+ <#assign groups = groups + [in_groups] />
+ #if>
+ #if>
+#macro>
+
+<#-- Macro to assign Extras field -->
+<#macro assignExtraField key value asObject>
+<#if key??>
+ <#assign extra = {"key": key, "value": value, "asObject": asObject}>
+ <#assign extras = extras + [extra]/>
+#if>
+#macro>
+
+<#-- Macro to build the tags as [{},{},..{}] -->
+<#macro buildTags the_tags>
+<#if the_tags??>
+ "tags": [
+ <#list the_tags as tag>
+ {
+ "name": "${tag}"
+ }
+ <#if tag?is_last==false>,#if>
+ #list>
+ ],
+#if>
+#macro>
+
+<#-- Macro to build the groups as [{},{},..{}] -->
+<#macro buildGroups the_groups>
+<#if the_groups??>
+ "groups": [
+ <#list the_groups as the_group>
+ {
+ "name": "${the_group}"
+ }
+ <#if the_group?is_last==false>,#if>
+ #list>
+ ],
+#if>
+#macro>
+
+<#-- Macro to build the resources as [{},{},..{}] -->
+<#macro buildResources the_resources>
+<#if the_resources??>
+ "resources": [
+ <#list the_resources as resource>
+ {
+ "name": "${resource.name}",
+ "url": "${resource.url}",
+ "description": "${resource.description}",
+ "format": "${resource.format}"
+ }
+ <#if resource?is_last==false>,#if>
+ #list>
+ ],
+#if>
+#macro>
+
+<#-- Macro to build the extras as [{},{},..{}] -->
+<#macro buildExtrasFields the_extras>
+<#if the_extras??>
+ "extras": [
+ <#list the_extras as extra>
+ <#if extra.asObject?? && extra.asObject>
+ {
+ "key": "${extra.key}",
+ "value": ${extra.value}
+ }
+ <#else>
+ {
+ "key": "${extra.key}",
+ "value": "${extra.value}"
+ }
+ #if>
+ <#if extra?is_last==false>,#if>
+ #list>
+ ]
+#if>
+#macro>
+
+
+<#--
+Starting document mapping to Catalogue
+-->
+
+{
+ "name": "${jsonProj._id}",
+ "title": "${theDocument.nome}",
+ "license_id": "CC-BY-SA-4.0",
+ "private": false,
+ <#assign description = theDocument.introduzione?trim />
+ <#assign sanitizedNotes = description?replace("\\n", "")>
+ "notes": "${sanitizedNotes}",
+
+<#--
+#######################################
+
+ RESOURCES
+
+#######################################
+-->
+
+<#-- Mapping "Relazione Scavo" as resource -->
+<#if theDocument.relazioneScavo?? && theDocument.relazioneScavo.fileset?? && theDocument.relazioneScavo.fileset._payloads??>
+<#assign payloads = theDocument.relazioneScavo.fileset._payloads>
+<#if payloads?size!=0>
+<#-- Getting the first payload -->
+<#assign payload = payloads[0]>
+<@assignResource name=payload._name url=payload._link description=theDocument.relazioneScavo.titolo format=payload._mimetype>@assignResource>
+#if>
+#if>
+
+<#-- Building Resources -->
+<@buildResources the_resources=resources>@buildResources>
+
+
+<#--
+#######################################
+
+ TAGS
+
+#######################################
+-->
+
+<#-- Mapping "paroleChiaveLibere" as tag -->
+<#if theDocument.paroleChiaveLibere??>
+<@assignTag in_tags=theDocument.paroleChiaveLibere>@assignTag>
+#if>
+
+<#-- Building tags -->
+<@buildTags the_tags=tags>@buildTags>
+
+
+<#--
+#######################################
+
+ GROUPS
+
+#######################################
+-->
+
+<#-- Mapping the year of the "dataInizioProgetto" as group -->
+<#assign dateString = theDocument.dataInizioProgetto?trim>
+<#assign year = dateString?split("-")[0]>
+<@assignGroup in_groups=year>@assignGroup>
+<#-- Building groups -->
+<@buildGroups the_groups=groups>@buildGroups>
+
+
+<#--
+#######################################
+
+ EXTRAS
+
+#######################################
+-->
+
+<#-- Mapping extras fields -->
+<#if theDocument.responsabile??>
+<@assignExtraField key="Responsabile dei contenuti" value=theDocument.responsabile asObject=false>@assignExtraField>
+#if>
+
+<#if theDocument.editore??>
+<@assignExtraField key="Ente responsabile del progetto" value=theDocument.editore asObject=false>@assignExtraField>
+#if>
+
+<#if theDocument.ufficioMic??>
+<@assignExtraField key="Ufficio MiC competente per territorio" value=theDocument.ufficioMic asObject=false>@assignExtraField>
+#if>
+
+<#if theDocument.fontiFinanziamento??>
+<@assignExtraField key="Fonte del finanziamento" value=theDocument.fontiFinanziamento asObject=false>@assignExtraField>
+#if>
+
+<#if theDocument.dataInizioProgetto??>
+<@assignExtraField key="Data inizio Campagna" value=theDocument.dataInizioProgetto?trim asObject=false>@assignExtraField>
+#if>
+
+<#if theDocument.dataFineProgetto??>
+<@assignExtraField key="Data fine Campagna" value=theDocument.dataFineProgetto?trim asObject=false>@assignExtraField>
+#if>
+
+<#if theDocument.modalitaIndividuazione??>
+<@assignExtraField key="Modalità di individuazione" value=theDocument.modalitaIndividuazione asObject=false>@assignExtraField>
+#if>
+
+<#if theDocument.statoAttuale??>
+<@assignExtraField key="Stato attuale" value=theDocument.statoAttuale asObject=false>@assignExtraField>
+#if>
+
+<#if theDocument.cronologiaMacrofase??>
+<@assignExtraField key="Cronologia (Macrofase)" value=theDocument.cronologiaMacrofase asObject=false>@assignExtraField>
+#if>
+
+<#-- spatial field -->
+<#if jsonProj._identificationReferences?? && jsonProj._identificationReferences?size!=0 && jsonProj._identificationReferences[0].geoJSON??>
+<#assign geoJSON = jsonProj._identificationReferences[0].geoJSON>
+<#assign spatialField = '{\\"type\\": \\"${geoJSON.type}\\", \\"coordinates\\": [${geoJSON.coordinates?join(", ")}]}'>
+<@assignExtraField key="spatial" value=spatialField asObject=false>@assignExtraField>
+#if>
+
+<#-- system:type -->
+<@assignExtraField key="system:type" value="D4GNA" asObject=true>@assignExtraField>
+<@buildExtrasFields the_extras=extras>@buildExtrasFields>
+}
+
diff --git a/catalogue-binding-plugin/src/test/java/test/TestContextConfig.java b/catalogue-binding-plugin/src/test/java/test/TestContextConfig.java
new file mode 100644
index 0000000..0ba11c0
--- /dev/null
+++ b/catalogue-binding-plugin/src/test/java/test/TestContextConfig.java
@@ -0,0 +1,41 @@
+package test;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+public class TestContextConfig {
+
+
+ private static final String GCUBE_CONFIG_PROPERTIES_FILENAME = "gcube_config.properties";
+ // APP Working Directory + /src/test/resources must be the location of
+ // gcube_config.properties
+ private static String gcube_config_path = String.format("%s/%s",
+ System.getProperty("user.dir") + "/src/test/resources", GCUBE_CONFIG_PROPERTIES_FILENAME);
+ public static String CONTEXT;
+ public static String TOKEN;
+
+ /**
+ * Read context settings.
+ */
+ public static void readContextSettings() {
+
+ try (InputStream input = new FileInputStream(gcube_config_path)) {
+
+ Properties prop = new Properties();
+
+ // load a properties file
+ prop.load(input);
+
+ CONTEXT = prop.getProperty("CONTEXT");
+ TOKEN = prop.getProperty("TOKEN");
+ // get the property value and print it out
+ System.out.println("CONTEXT: " + CONTEXT);
+ System.out.println("TOKEN: " + TOKEN);
+
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+}
diff --git a/catalogue-binding-plugin/src/test/resources/.gitignore b/catalogue-binding-plugin/src/test/resources/.gitignore
index a027843..6b28521 100644
--- a/catalogue-binding-plugin/src/test/resources/.gitignore
+++ b/catalogue-binding-plugin/src/test/resources/.gitignore
@@ -1 +1,2 @@
/tokens.properties
+/resources/