From c9b2a3b6f7bc1262554e940995e33cf631dbaaa8 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Fri, 26 Nov 2021 12:27:31 +0100 Subject: [PATCH] The moderation thread has been generalised form the implementation --- .../thread/FakeModerationThread.java | 32 +++++++ .../moderation/thread/ModerationThread.java | 87 +++++++++++++++++++ .../moderation/thread/zulip/ZulipStream.java | 74 +++------------- .../gcat/persistence/ckan/CKANPackage.java | 41 ++++----- 4 files changed, 154 insertions(+), 80 deletions(-) create mode 100644 src/main/java/org/gcube/gcat/moderation/thread/FakeModerationThread.java create mode 100644 src/main/java/org/gcube/gcat/moderation/thread/ModerationThread.java diff --git a/src/main/java/org/gcube/gcat/moderation/thread/FakeModerationThread.java b/src/main/java/org/gcube/gcat/moderation/thread/FakeModerationThread.java new file mode 100644 index 0000000..6cd31af --- /dev/null +++ b/src/main/java/org/gcube/gcat/moderation/thread/FakeModerationThread.java @@ -0,0 +1,32 @@ +package org.gcube.gcat.moderation.thread; + +import org.gcube.gcat.api.CMItemStatus; +import org.gcube.gcat.utils.ContextUtility; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Luca Frosini (ISTI - CNR) + */ +public class FakeModerationThread extends ModerationThread { + + private static final Logger logger = LoggerFactory.getLogger(FakeModerationThread.class); + + @Override + protected void postMessage(CMItemStatus cmItemStatus, String message) throws Exception { + logger.debug("gCat is sending a message to the {} for item '{}' (id={}). ItemStatus={}, Message=\"{}\"", + ModerationThread.class.getSimpleName(), itemName, itemID, cmItemStatus, message); + } + + @Override + public void postUserMessage(CMItemStatus cmItemStatus, String userMessage) throws Exception { + logger.debug("{} is sending a message to the {} for item '{}' (id={}). ItemStatus={}, Message=\"{}\"", + ContextUtility.getUsername(), ModerationThread.class.getSimpleName(), itemName, itemID, cmItemStatus, userMessage); + } + + @Override + protected void createModerationThread() throws Exception { + logger.debug("Creating {} for item '{}' (id={})", ModerationThread.class.getSimpleName(), itemName, itemID); + } + +} diff --git a/src/main/java/org/gcube/gcat/moderation/thread/ModerationThread.java b/src/main/java/org/gcube/gcat/moderation/thread/ModerationThread.java new file mode 100644 index 0000000..8884757 --- /dev/null +++ b/src/main/java/org/gcube/gcat/moderation/thread/ModerationThread.java @@ -0,0 +1,87 @@ +package org.gcube.gcat.moderation.thread; + +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.gcat.api.CMItemStatus; +import org.gcube.gcat.persistence.ckan.CKANUser; + +/** + * @author Luca Frosini (ISTI - CNR) + */ +public abstract class ModerationThread { + + protected String itemID; + protected String itemName; + + protected CKANUser ckanUser; + protected ObjectMapper objectMapper; + + public static ModerationThread getDefaultInstance() { + return new FakeModerationThread(); + } + + public ModerationThread() { + this.objectMapper = new ObjectMapper(); + } + + public void setItemCoordinates(String itemID, String itemName) { + this.itemID = itemID; + this.itemName = itemName; + } + + public void setCKANUser(CKANUser ckanUser) { + this.ckanUser = ckanUser; + } + + /** + * The message is sent as gCat + * @param cmItemStatus + * @param message + * @throws Exception + */ + protected abstract void postMessage(CMItemStatus cmItemStatus, String message) throws Exception; + + /** + * The message is sent as User + * @param cmItemStatus + * @param userMessage + * @throws Exception + */ + public abstract void postUserMessage(CMItemStatus cmItemStatus, String userMessage) throws Exception; + + protected abstract void createModerationThread() throws Exception ; + + public void postItemCreated() throws Exception{ + createModerationThread(); + String username = ckanUser.getPortalUser().getNameSurname(); + CMItemStatus cmItemStatus = CMItemStatus.PENDING; + String message = String.format("@**%s** has created the item with name '%s' (id='%s'). The item is now in **%s** state and must be moderated.", + username, itemName, itemID, cmItemStatus.getFancyValue()); + postMessage(cmItemStatus, message); + } + + public void postItemUpdated() throws Exception { + String username = ckanUser.getPortalUser().getNameSurname(); + CMItemStatus cmItemStatus = CMItemStatus.PENDING; + String message = String.format("@**%s** has updated the item with name '%s' (id='%s'). The item is now in **%s** state and must be moderated.", + username, itemName, itemID, cmItemStatus.getFancyValue()); + postMessage(cmItemStatus, message); + } + + public void postItemRejected(String userMessage) throws Exception { + String username = ckanUser.getPortalUser().getNameSurname(); + CMItemStatus cmItemStatus = CMItemStatus.REJECTED; + String message = String.format("@**%s** has **%s** the item with name '%s' (id='%s'). The author can delete the item or update it to try to meet moderators requests if any.", + username, cmItemStatus.getFancyValue(), itemName, itemID); + postMessage(cmItemStatus, message); + postUserMessage(cmItemStatus, userMessage); + } + + public void postItemApproved(String userMessage) throws Exception{ + String username = ckanUser.getPortalUser().getNameSurname(); + CMItemStatus cmItemStatus = CMItemStatus.APPROVED; + String message = String.format("@**%s** has **%s** the item with name '%s' (id='%s'). The item is now available in the catalogue.", + username, cmItemStatus.getFancyValue(), itemName, itemID); + postMessage(cmItemStatus, message); + postUserMessage(cmItemStatus, userMessage); + } +} diff --git a/src/main/java/org/gcube/gcat/moderation/thread/zulip/ZulipStream.java b/src/main/java/org/gcube/gcat/moderation/thread/zulip/ZulipStream.java index 353e05f..0cc6278 100644 --- a/src/main/java/org/gcube/gcat/moderation/thread/zulip/ZulipStream.java +++ b/src/main/java/org/gcube/gcat/moderation/thread/zulip/ZulipStream.java @@ -5,13 +5,12 @@ import java.util.Set; import javax.ws.rs.InternalServerErrorException; import org.gcube.com.fasterxml.jackson.databind.JsonNode; -import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; import org.gcube.gcat.api.CMItemStatus; import org.gcube.gcat.api.GCatConstants; +import org.gcube.gcat.moderation.thread.ModerationThread; import org.gcube.gcat.moderation.thread.zulip.ZulipResponse.Result; -import org.gcube.gcat.persistence.ckan.CKANUser; import org.gcube.gcat.social.SocialUsers; import org.gcube.gcat.utils.Constants; import org.gcube.gcat.utils.ContextUtility; @@ -28,7 +27,7 @@ import io.taliox.zulip.calls.streams.PostCreateStream; /** * @author Luca Frosini (ISTI - CNR) */ -public class ZulipStream { +public class ZulipStream extends ModerationThread { private static final Logger logger = LoggerFactory.getLogger(ZulipStream.class); @@ -40,25 +39,18 @@ public class ZulipStream { protected ZulipRestExecutor gCatZulipRestExecutor; protected ZulipRestExecutor userZulipRestExecutor; - protected String itemID; - protected String itemName; - protected String streamName; protected String streamDescription; - protected CKANUser ckanUser; - - protected ObjectMapper objectMapper; + public ZulipStream() { + super(); + } protected ZulipRestExecutor getZulipRestExecutor() { ZulipAuth zulipAuth = new ZulipAuth(ContextUtility.getUsername()); return new ZulipRestExecutor(zulipAuth.getEmail(), zulipAuth.getAPIKey(), zulipAuth.getSite()); } - public ZulipStream() { - this.objectMapper = new ObjectMapper(); - } - public ZulipRestExecutor getGCatZulipRestExecutor() { if(gCatZulipRestExecutor==null) { ApplicationMode applicationMode = new ApplicationMode(Constants.getCatalogueApplicationToken()); @@ -76,15 +68,6 @@ public class ZulipStream { return userZulipRestExecutor; } - public void setItemCoordinates(String itemID, String itemName) { - this.itemID = itemID; - this.itemName = itemName; - } - - public void setCKANUser(CKANUser ckanUser) { - this.ckanUser = ckanUser; - } - protected String getStreamName() { if(streamName==null) { streamName = String.format("Item '%s' moderation", itemID); @@ -117,7 +100,8 @@ public class ZulipStream { return zulipResponse; } - public void create() throws Exception { + @Override + protected void createModerationThread() throws Exception { ArrayNode streamsArrayNode = objectMapper.createArrayNode(); ObjectNode streamobjectNode = objectMapper.createObjectNode(); streamobjectNode.put("name", getStreamName()); @@ -145,8 +129,6 @@ public class ZulipStream { postCreateStream.setAnnounce(false); executeZulipCall(gCatZulipRestExecutor, postCreateStream); - - postItemCreated(); } protected void postMessageToStream(ZulipRestExecutor zulipRestExecutor, CMItemStatus cmItemStatus, String message) throws Exception { @@ -155,42 +137,14 @@ public class ZulipStream { executeZulipCall(zulipRestExecutor, postMessage); } - public void postUserMessageToStream(CMItemStatus cmItemStatus, String message) throws Exception { + @Override + protected void postMessage(CMItemStatus cmItemStatus, String message) throws Exception { + postMessageToStream(getGCatZulipRestExecutor(), cmItemStatus, message); + } + + @Override + public void postUserMessage(CMItemStatus cmItemStatus, String message) throws Exception { postMessageToStream(getUserZulipRestExecutor(), cmItemStatus, message); } - private void postItemCreated() throws Exception{ - String username = ckanUser.getPortalUser().getNameSurname(); - CMItemStatus cmItemStatus = CMItemStatus.PENDING; - String message = String.format("@**%s** has created the item with name '%s' (id='%s'). The item is now in **%s** state and must be moderated.", - username, itemName, itemID, cmItemStatus.getFancyValue()); - postMessageToStream(getGCatZulipRestExecutor(), cmItemStatus, message); - } - - public void postItemUpdated() throws Exception{ - String username = ckanUser.getPortalUser().getNameSurname(); - CMItemStatus cmItemStatus = CMItemStatus.PENDING; - String message = String.format("@**%s** has updated the item with name '%s' (id='%s'). The item is now in **%s** state and must be moderated.", - username, itemName, itemID, cmItemStatus.getFancyValue()); - postMessageToStream(getGCatZulipRestExecutor(), cmItemStatus, message); - } - - public void postItemRejected(String userMessage) throws Exception { - String username = ckanUser.getPortalUser().getNameSurname(); - CMItemStatus cmItemStatus = CMItemStatus.REJECTED; - String message = String.format("@**%s** has **%s** the item with name '%s' (id='%s'). The author can delete the item or update it to try to meet moderators requests if any.", - username, cmItemStatus.getFancyValue(), itemName, itemID); - postMessageToStream(getGCatZulipRestExecutor(), cmItemStatus, message); - postUserMessageToStream(cmItemStatus, userMessage); - } - - public void postItemApproved(String userMessage) throws Exception{ - String username = ckanUser.getPortalUser().getNameSurname(); - CMItemStatus cmItemStatus = CMItemStatus.APPROVED; - String message = String.format("@**%s** has **%s** the item with name '%s' (id='%s'). The item is now available in the catalogue.", - username, cmItemStatus.getFancyValue(), itemName, itemID); - postMessageToStream(getGCatZulipRestExecutor(), cmItemStatus, message); - postUserMessageToStream(cmItemStatus, userMessage); - } - } diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java index 4c7351a..2ae433c 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java @@ -29,7 +29,7 @@ import org.gcube.gcat.api.CMItemVisibility; import org.gcube.gcat.api.GCatConstants; import org.gcube.gcat.api.Role; import org.gcube.gcat.api.interfaces.Moderated; -import org.gcube.gcat.moderation.thread.zulip.ZulipStream; +import org.gcube.gcat.moderation.thread.ModerationThread; import org.gcube.gcat.oldutils.Validator; import org.gcube.gcat.profile.MetadataUtility; import org.gcube.gcat.social.PortalUser; @@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory; public class CKANPackage extends CKAN implements Moderated { private static final Logger logger = LoggerFactory.getLogger(CKANPackage.class); + /* // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_list public static final String ITEM_LIST = CKAN.CKAN_API_PATH + "package_list"; @@ -122,7 +123,7 @@ public class CKANPackage extends CKAN implements Moderated { protected final CKANInstance ckanInstance; protected final Set supportedOrganizations; - protected ZulipStream zulipStream; + protected ModerationThread moderationThread; public CKANPackage() { super(); @@ -642,7 +643,7 @@ public class CKANPackage extends CKAN implements Moderated { ArrayNode created = createResources(resourcesToBeCreated); ((ObjectNode) result).replace(RESOURCES_KEY, created); - createZulipStream(); + postItemCreated(); if(!isModerationEnabled()) { if(ckanInstance.getCurrentScopeBean().is(Type.VRE)) { @@ -718,7 +719,7 @@ public class CKANPackage extends CKAN implements Moderated { ckanResource.deleteFile(); } - postItemUpdatedToStream(); + postItemUpdated(); return getAsCleanedString(result); } catch(WebApplicationException e) { @@ -787,7 +788,7 @@ public class CKANPackage extends CKAN implements Moderated { ckanResource.deleteFile(); } - postItemUpdatedToStream(); + postItemUpdated(); return getAsCleanedString(result); } catch(WebApplicationException e) { @@ -906,9 +907,9 @@ public class CKANPackage extends CKAN implements Moderated { protected boolean isModerationEnabled() { boolean moderationEnabled = ckanInstance.isModerationEnabled(); - if(moderationEnabled && zulipStream==null) { - zulipStream = new ZulipStream(); - zulipStream.setCKANUser(ckanUser); + if(moderationEnabled && moderationThread==null) { + moderationThread = ModerationThread.getDefaultInstance(); + moderationThread.setCKANUser(ckanUser); } return moderationEnabled; } @@ -1146,11 +1147,11 @@ public class CKANPackage extends CKAN implements Moderated { ((ObjectNode) jsonNode).put(SEARCHABLE_KEY, true); } - private void createZulipStream() throws Exception { + private void postItemCreated() throws Exception { try { if(isModerationEnabled()) { - zulipStream.setItemCoordinates(itemID, name); - zulipStream.create(); + moderationThread.setItemCoordinates(itemID, name); + moderationThread.postItemCreated(); } } catch(WebApplicationException e) { throw e; @@ -1159,11 +1160,11 @@ public class CKANPackage extends CKAN implements Moderated { } } - private void postItemUpdatedToStream() { + private void postItemUpdated() { try { if(isModerationEnabled()) { - zulipStream.setItemCoordinates(itemID, name); - zulipStream.postItemUpdated(); + moderationThread.setItemCoordinates(itemID, name); + moderationThread.postItemUpdated(); } } catch(WebApplicationException e) { throw e; @@ -1195,8 +1196,8 @@ public class CKANPackage extends CKAN implements Moderated { String ret = sendPostRequest(ITEM_PATCH, getAsString(result)); result = mapper.readTree(ret); - zulipStream.setItemCoordinates(itemID, name); - zulipStream.postItemApproved(moderatorMessage); + moderationThread.setItemCoordinates(itemID, name); + moderationThread.postItemApproved(moderatorMessage); if(ckanInstance.getCurrentScopeBean().is(Type.VRE)) { // Actions performed after a package has been correctly created on ckan. @@ -1244,8 +1245,8 @@ public class CKANPackage extends CKAN implements Moderated { String ret = sendPostRequest(ITEM_PATCH, getAsString(result)); result = mapper.readTree(ret); - zulipStream.setItemCoordinates(itemID, name); - zulipStream.postItemRejected(moderatorMessage); + moderationThread.setItemCoordinates(itemID, name); + moderationThread.postItemRejected(moderatorMessage); break; default: @@ -1283,8 +1284,8 @@ public class CKANPackage extends CKAN implements Moderated { } CMItemStatus cmItemStatus = getCMItemStatus(); - zulipStream.setItemCoordinates(itemID, name); - zulipStream.postUserMessageToStream(cmItemStatus, message); + moderationThread.setItemCoordinates(itemID, name); + moderationThread.postUserMessage(cmItemStatus, message); return; } throw new MethodNotSupportedException("The message operation is available only in moderation mode");