This commit is contained in:
Francesco Mangiacrapa 2024-06-20 11:35:05 +02:00
parent ca3b5c9355
commit c475532f21
8 changed files with 387 additions and 84 deletions

View File

@ -64,6 +64,13 @@
<version>2.3.32</version>
</dependency>
<!-- JSON PARSER -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20090211</version>
</dependency>
<dependency>
<groupId>org.gcube.application</groupId>
<artifactId>geoportal-client</artifactId>

View File

@ -8,6 +8,7 @@ import java.util.Map;
import org.bson.Document;
import org.gcube.application.cms.cataloguebinding.config.SubscribeEventsConfig;
import org.gcube.application.cms.cataloguebinding.doaction.BindingAction;
import org.gcube.application.cms.cataloguebinding.util.SerializationUtil;
import org.gcube.application.cms.implementations.utils.UserUtils;
import org.gcube.application.cms.plugins.EventListenerPluginInterface;
import org.gcube.application.cms.plugins.events.EventListener;
@ -22,7 +23,6 @@ import org.gcube.application.cms.plugins.implementations.AbstractPlugin;
import org.gcube.application.cms.plugins.reports.InitializationReport;
import org.gcube.application.cms.plugins.reports.Report;
import org.gcube.application.cms.plugins.reports.Report.Status;
import org.gcube.application.cms.serialization.Serialization;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.model.plugins.PluginDescriptor;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
@ -232,14 +232,14 @@ public class CatalogueBindingPlugin extends AbstractPlugin implements EventListe
for (Object fsConfigObj : profileConfiguration.get(SUBSCRIBE_EVENTS_CONFIG, List.class)) {
log.debug("Managing {} ", fsConfigObj);
SubscribeEventsConfig fsConfig = Serialization.convert(fsConfigObj, SubscribeEventsConfig.class);
SubscribeEventsConfig fsConfig = SerializationUtil.convert(fsConfigObj, SubscribeEventsConfig.class);
log.debug("Converted config {}", fsConfig);
String theEventSubsribed = fsConfig.getEvent();
if (theEventSubsribed == null || theEventSubsribed.isEmpty())
throw new MaterializationException(
"Invalid Field Definition path in configuration [NO MATCH] : " + fsConfig.getEvent());
Event event = Serialization.convert(theEventSubsribed, Event.class);
Event event = SerializationUtil.convert(theEventSubsribed, Event.class);
log.debug("Added event {} to list ", event);
listEventsSubscribedPerUCD.add(event);
}

View File

@ -5,6 +5,7 @@ import java.net.MalformedURLException;
import org.gcube.application.cms.cataloguebinding.EventsSubscribed;
import org.gcube.application.cms.cataloguebinding.freemarker.FreemarkerConfig;
import org.gcube.application.cms.cataloguebinding.freemarker.MappingToCatalogue;
import org.gcube.application.cms.plugins.events.ItemObserved;
import org.gcube.application.geoportal.common.model.document.Project;
@ -24,6 +25,9 @@ public class BindingAction {
try {
FreemarkerConfig fmc = new FreemarkerConfig(eventsSubscribed.getFreemarker_template_host());
Template fmTemplate = fmc.getTemplate(eventsSubscribed.getFreemarker_template_path());
String toCatalogueJSON = MappingToCatalogue.apply(fmTemplate, itemObserved.getProject(), itemObserved.getUseCaseDescriptor());
} catch (MalformedURLException e) {
log.error("Error: ", e);
} catch (TemplateException e) {

View File

@ -0,0 +1,105 @@
package org.gcube.application.cms.cataloguebinding.freemarker;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import org.bson.Document;
import org.gcube.application.cms.cataloguebinding.util.JSONObjectOrdered;
import org.gcube.application.cms.cataloguebinding.util.SerializationUtil;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
import org.json.JSONException;
import org.json.JSONObject;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.spi.json.JsonOrgJsonProvider;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MappingToCatalogue {
private static final String SYSTEM_TYPE = "system:type";
private static final String GIS_LINK = "Gis Link";
public static String apply(Template fmTemplate, Project theProject, UseCaseDescriptor ucd)
throws JsonProcessingException {
try {
Document asDocument = SerializationUtil.asDocument(theProject);
String json = asDocument.toJson();
Map toJsonMap = fmtJsonUtil(json);
StringWriter stringWriter = new StringWriter();
Map root = new HashMap();
root.put("doc", toJsonMap);
fmTemplate.process(root, stringWriter);
String toCatalogueJSON = stringWriter.toString();
System.out.println("\n\ntoCatalogueString:" + toCatalogueJSON);
com.jayway.jsonpath.Configuration configuration = com.jayway.jsonpath.Configuration.builder()
.jsonProvider(new JsonOrgJsonProvider()).build();
DocumentContext theDoc = JsonPath.parse(toCatalogueJSON, configuration);
// GIS LINK
JSONObject theGisLinkObj = JSONObjectOrdered.instance();
try {
theGisLinkObj.put("key", GIS_LINK);
theGisLinkObj.put("value", "https://data.dev.d4science.org/test/my_gis_link");
theDoc.add("$.extras", theGisLinkObj);
} catch (JSONException e) {
log.warn("Error occurrend on adding " + GIS_LINK);
log.debug("Error occurrend on adding " + GIS_LINK, e);
}
// system:type
try {
JSONObject theSystemType = JSONObjectOrdered.instance();
theSystemType.put("key", SYSTEM_TYPE);
theSystemType.put("value", ucd.getName());
theDoc.add("$.extras", theSystemType);
} catch (JSONException e) {
log.warn("Error occurrend on adding " + SYSTEM_TYPE);
log.debug("Error occurrend on adding " + SYSTEM_TYPE, e);
}
System.out.println("\n\nTo pretty print JSON:");
String toCatalogueObject = theDoc.jsonString();
// System.out.println("gis link: "+theDoc.jsonString());
System.out.println(toCatalogueObject);
return toCatalogueObject;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TemplateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static Map<String, Object> fmtJsonUtil(String json)
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper OBJECT_MAPPER = new ObjectMapper();
return OBJECT_MAPPER.readValue(json, new TypeReference<HashMap<String, Object>>() {
});
}
}

View File

@ -0,0 +1,33 @@
package org.gcube.application.cms.cataloguebinding.util;
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;
}
}

View File

@ -0,0 +1,117 @@
package org.gcube.application.cms.cataloguebinding.util;
import java.io.IOException;
import org.bson.Document;
import org.bson.types.ObjectId;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.vdurmont.semver4j.Semver;
public class SerializationUtil {
public static ObjectMapper mapper;
static {
mapper=new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.registerModule(new JavaTimeModule());
SimpleModule s=new SimpleModule();
s.addDeserializer(ObjectId.class,new ObjectIdDeserializer());
s.addSerializer(ObjectId.class,new ObjectIdSerializer());
s.addDeserializer(Semver.class,new SemverDeserializer());
s.addSerializer(Semver.class,new SemverSerializer());
mapper.registerModule(s);
}
public static String write(Object toWrite) throws JsonProcessingException {
String toReturn= mapper.writeValueAsString(toWrite);
return toReturn;
}
//**** PROFILED DOCUMENTS
public static final <T> T convert(Object d,Class<T> clazz){
return mapper.convertValue(d,clazz);
}
public static final Document asDocument(Object obj) throws JsonProcessingException {
return Document.parse(mapper.writeValueAsString(obj));
}
// ***** SerializationUtil Exceptions
// OBJECT ID
private static class ObjectIdSerializer extends JsonSerializer<ObjectId> {
@Override
public void serialize(ObjectId objectId, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
if (objectId == null) jsonGenerator.writeNull();
else jsonGenerator.writeString(objectId.toString());
}
@Override
public Class<ObjectId> handledType() {
return ObjectId.class;
}
}
private static class ObjectIdDeserializer extends JsonDeserializer<ObjectId> {
@Override
public ObjectId deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String value=jsonParser.getValueAsString();
if(value==null || value.isEmpty() || value.equals("null"))
return null;
else return new ObjectId(value);
}
@Override
public Class<ObjectId> handledType() {
return ObjectId.class;
}
}
//Sem Version
private static class SemverSerializer extends JsonSerializer<Semver> {
@Override
public void serialize(Semver semver, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
if (semver == null) jsonGenerator.writeNull();
else jsonGenerator.writeString(semver.getValue());
}
@Override
public Class<Semver> handledType() {
return Semver.class;
}
}
private static class SemverDeserializer extends JsonDeserializer<Semver> {
@Override
public Semver deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String value=jsonParser.getValueAsString();
if(value==null || value.isEmpty() || value.equals("null"))
return null;
else return new Semver(value);
}
@Override
public Class<Semver> handledType() {
return Semver.class;
}
}
}

View File

@ -8,8 +8,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bson.BsonDocument;
import org.bson.BsonString;
import org.bson.Document;
import org.gcube.application.geoportal.client.utils.Serialization;
import org.gcube.application.cms.cataloguebinding.util.SerializationUtil;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
import org.gcube.application.geoportalcommon.geoportal.GeoportalClientCaller;
@ -42,30 +44,64 @@ public class GeoportalToCatalogue {
public final static String profileID = "profiledConcessioni";
public final static String projectID = "66697afda08b3011b506ddb6";
public static void main(String[] args) {
// 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 = SerializationUtil.asDocument(theProject);
//
//
// UseCaseDescriptor ucd = GeoportalClientCaller.useCaseDescriptors().getUCDForId(profileID);
//
//
// System.out.println("Source JSON:");
// System.out.println(prettyPrintUsingGson(asDocument.toJson()));
// applyMappingToCatalogue(theProject, ucd);
//
// } catch (Exception e) {
// // TODO: handle exception
// }
//
// }
public static void main(String[] args) throws JsonProcessingException, JSONException {
StringWriter stringWriter = new StringWriter();
stringWriter.append("{\"extras\":[]}");
String toCatalogueJSON = stringWriter.toString();
System.out.println("\n\ntoCatalogueString:" + toCatalogueJSON);
try {
com.jayway.jsonpath.Configuration configuration = com.jayway.jsonpath.Configuration.builder()
.jsonProvider(new JsonOrgJsonProvider()).build();
// GIS LINK
JSONObject theGisLinkObj = new JSONObject();
theGisLinkObj.put("key", "Gis Link");
theGisLinkObj.put("value","https://data.dev.d4science.org/test/my_gis_link");
DocumentContext theDoc = JsonPath.parse(toCatalogueJSON, configuration);
System.out.println("json: "+theGisLinkObj.toString());
theDoc.add("$.extras", theGisLinkObj);
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);
UseCaseDescriptor ucd = GeoportalClientCaller.useCaseDescriptors().getUCDForId(profileID);
System.out.println("Source JSON:");
System.out.println(prettyPrintUsingGson(asDocument.toJson()));
applyMappingToCatalogue(theProject, ucd);
} catch (Exception e) {
// TODO: handle exception
}
// system:type
JSONObject theSystemType = new JSONObject();
theSystemType.put("key", "system:type");
theSystemType.put("value", "ucd name");
System.out.println("json: "+theSystemType);
theDoc.add("$.extras", theSystemType);
System.out.println(theDoc.jsonString());
}
@ -111,7 +147,7 @@ public class GeoportalToCatalogue {
public static void applyMappingToCatalogue(Project theProject, UseCaseDescriptor ucd) throws JsonProcessingException {
Document asDocument = Serialization.asDocument(theProject);
Document asDocument = SerializationUtil.asDocument(theProject);
String json = asDocument.toJson();
@ -155,12 +191,12 @@ public class GeoportalToCatalogue {
com.jayway.jsonpath.Configuration configuration = com.jayway.jsonpath.Configuration.builder()
.jsonProvider(new JsonOrgJsonProvider()).build();
DocumentContext theDoc = JsonPath.parse(toCatalogueJSON, configuration);
// GIS LINK
JSONObject theGisLinkObj = JSONObjectOrdered.instance();
theGisLinkObj.put("key", "Gis Link");
theGisLinkObj.put("value", "https://data.dev.d4science.org/test/my_gis_link");
DocumentContext theDoc = JsonPath.parse(toCatalogueJSON, configuration);
theDoc.add("$.extras", theGisLinkObj);
// system:type

View File

@ -1,7 +1,9 @@
package junit;
import org.bson.Document;
import org.gcube.application.cms.cataloguebinding.CatalogueBindingPlugin;
import org.gcube.application.cms.cataloguebinding.EventsSubscribed;
import org.gcube.application.cms.cataloguebinding.util.SerializationUtil;
import org.gcube.application.cms.implementations.utils.UserUtils;
import org.gcube.application.cms.plugins.events.EventManager;
import org.gcube.application.cms.plugins.events.EventManager.Event;
@ -17,11 +19,20 @@ import org.gcube.application.geoportal.common.model.document.accounting.User;
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
import org.gcube.application.geoportal.common.utils.tests.GCubeTest;
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.junit.Test;
import test.TestContextConfig;
public class CatalogueBindingPluginTest extends BasicPluginTest {
//@Test
public final static String profileID = "profiledConcessioni";
public final static String projectID = "642d4288c2133270c058ec39";
// @Test
public void checkPlugin() {
org.junit.Assume.assumeTrue(GCubeTest.isTestInfrastructureEnabled());
CatalogueBindingPlugin plugin = (CatalogueBindingPlugin) plugins.get(CatalogueBindingPlugin.DESCRIPTOR.getId());
@ -41,11 +52,11 @@ public class CatalogueBindingPluginTest extends BasicPluginTest {
}
//@Test
// @Test
public void checkPluginConfig() {
org.junit.Assume.assumeTrue(GCubeTest.isTestInfrastructureEnabled());
CatalogueBindingPlugin plugin = (CatalogueBindingPlugin) plugins.get(CatalogueBindingPlugin.DESCRIPTOR.getId());
UseCaseDescriptor descriptor = TestProfiles.profiles.get("profiledConcessioni");
UseCaseDescriptor descriptor = TestProfiles.profiles.get(profileID);
try {
plugin.init();
@ -67,7 +78,7 @@ public class CatalogueBindingPluginTest extends BasicPluginTest {
}
}
/**
* Check notifications SUBMIT_FOR_REVIEW to USERS
*/
@ -75,7 +86,7 @@ public class CatalogueBindingPluginTest extends BasicPluginTest {
public void checkNotify() {
org.junit.Assume.assumeTrue(GCubeTest.isTestInfrastructureEnabled());
CatalogueBindingPlugin plugin = (CatalogueBindingPlugin) plugins.get(CatalogueBindingPlugin.DESCRIPTOR.getId());
UseCaseDescriptor descriptor = TestProfiles.profiles.get("profiledConcessioni");
UseCaseDescriptor descriptor = TestProfiles.profiles.get(profileID);
try {
plugin.init();
@ -95,39 +106,44 @@ public class CatalogueBindingPluginTest extends BasicPluginTest {
} catch (Exception e) {
e.printStackTrace();
}
ItemObserved<Project> item = mockItemObserverd();
//Setting creator
User creator = new User();
creator.setUsername("francesco.mangiacrapa");
item.getProject().getInfo().getCreationInfo().setUser(creator);
EventManager.Event event = Event.PROJECT_CREATED;
item.setEvent(event);
LifecycleInformation lifecycleInfo = item.getProject().getLifecycleInformation();
//Test Stage (Pending Approval, "SUBMIT-FOR-REVIEW")
lifecycleInfo.setPhase("Pending Approval");
lifecycleInfo.setLastInvokedStep("SUBMIT-FOR-REVIEW");
System.out.println("By notifying event " + event + " project " + item.getProjectId());
EventManager.getInstance().notify(event, item);
ItemObserved<Project> item;
try {
EventManager.Event event = Event.PROJECT_CREATED;
item = mockItemObserverd(event);
// Setting creator
User creator = new User();
creator.setUsername("francesco.mangiacrapa");
item.getProject().getInfo().getCreationInfo().setUser(creator);
LifecycleInformation lifecycleInfo = item.getProject().getLifecycleInformation();
// Test Stage (Pending Approval, "SUBMIT-FOR-REVIEW")
lifecycleInfo.setPhase("Pending Approval");
lifecycleInfo.setLastInvokedStep("SUBMIT-FOR-REVIEW");
System.out.println("By notifying event " + event + " project " + item.getProjectId());
EventManager.getInstance().notify(event, item);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Mock item observerd.
*
* @return the item observed
* @throws Exception
*/
private static ItemObserved<Project> mockItemObserverd() {
UseCaseDescriptor descriptor = TestProfiles.profiles.get("profiledConcessioni");
private static ItemObserved<Project> mockItemObserverd(EventManager.Event event) throws Exception {
UseCaseDescriptor descriptor = TestProfiles.profiles.get(profileID);
// notifying the Event.PROJECT_CREATED;
ItemObserved<Project> item = new ItemObserved<Project>();
EventManager.Event event = Event.LIFECYCLE_STEP_PERFORMED;
AccountingInfo user = UserUtils.getCurrent().asInfo();
// System.out.println(user.getUser());
// sysOut(user);
@ -138,31 +154,16 @@ public class CatalogueBindingPluginTest extends BasicPluginTest {
item.setEvent(event);
item.setUseCaseDescriptor(descriptor);
// MOCK PROJECT
Project testProject = new Project();
testProject.setId("655489965bdd5478cca320ea");
testProject.setProfileID(descriptor.getId());
PublicationInfo info = new PublicationInfo(descriptor.getCreationInfo(), null, null);
testProject.setInfo(info);
Document theDocument = new Document();
theDocument.append("name", "My Great Project");
testProject.setTheDocument(theDocument);
LifecycleInformation lifecycleInfo = new LifecycleInformation();
//Pending Approval, "SUBMIT-FOR-REVIEW"
// lifecycleInfo.setPhase("Pending Approval");
// lifecycleInfo.setLastInvokedStep("SUBMIT-FOR-REVIEW");
lifecycleInfo.setPhase("DRAFT");
lifecycleInfo.setLastInvokedStep("REJECT-DRAFT");
testProject.setLifecycleInformation(lifecycleInfo);
item.setProject(testProject);
item.setOptional(OPTIONAL_FIELD.message, "Il mio grande progetto");
TestContextConfig.readContextSettings();
ScopeProvider.instance.set(TestContextConfig.CONTEXT);
SecurityTokenProvider.instance.set(TestContextConfig.TOKEN);
ProjectsCaller clientProjects = GeoportalClientCaller.projects();
Project theProject = clientProjects.getProjectByID(profileID, projectID);
item.setProject(theProject);
return item;
}