gcube-cms-suite/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/NotificationsPlugin.java

402 lines
14 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package org.gcube.application.cms.notifications;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.bson.Document;
import org.gcube.application.cms.implementations.utils.UserUtils;
import org.gcube.application.cms.notifications.config.SubscribeNotificationEvent;
import org.gcube.application.cms.notifications.manage.ManageDoActionNotification;
import org.gcube.application.cms.notifications.substitutor.NMessagesPlaceholdersSubstitutorUtil;
import org.gcube.application.cms.plugins.EventListenerPluginInterface;
import org.gcube.application.cms.plugins.events.EventListener;
import org.gcube.application.cms.plugins.events.EventManager;
import org.gcube.application.cms.plugins.events.EventManager.Event;
import org.gcube.application.cms.plugins.events.ItemObserved;
import org.gcube.application.cms.plugins.faults.InitializationException;
import org.gcube.application.cms.plugins.faults.MaterializationException;
import org.gcube.application.cms.plugins.faults.ShutDownException;
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;
import com.vdurmont.semver4j.Semver;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
/**
* The Class NotificationsPlugin.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Jan 30, 2024
*/
@Slf4j
public class NotificationsPlugin extends AbstractPlugin implements EventListenerPluginInterface {
public static final String SUBSCRIBE_NOTIFICATIONS_CONFIG = "subscribeNotifications";
public static final String PLUGIN_ID = "Notifications-Plugin";
public static final String PLUGIN_TYPE = "EventListener";
public static final PluginDescriptor DESCRIPTOR = new PluginDescriptor(PLUGIN_ID, PLUGIN_TYPE);
static {
DESCRIPTOR.setVersion(new Semver("1.0.0"));
DESCRIPTOR.setDescription("Manage the notification from Geoportal engine");
}
// This is a map "<Context,<UCD_ID,NotificationEventsSubscribedConfig>"
protected Map<String, Map<String, NotificationEventsSubscribedConfig>> notificationEventsBindingMap = null;
/**
* Inits the.
*
* @return the initialization report
* @throws InitializationException the initialization exception
*/
@Override
public InitializationReport init() throws InitializationException {
log.debug("Called init");
InitializationReport report = null;
try {
// Creating all listeners
EventListener<ItemObserved<Project>> listenerCreated = new EventListener<ItemObserved<Project>>() {
@Override
public void updated(ItemObserved<Project> observerd) {
log.info("listenerCreated fired on item: {} ", observerd);
boolean subscribed = checkIfSubscribedEvent(observerd);
if (subscribed) {
doAction(observerd);
}
}
};
EventListener<ItemObserved<Project>> listenerUpdated = new EventListener<ItemObserved<Project>>() {
@Override
public void updated(ItemObserved<Project> observerd) {
log.info("listenerUpdated fired on item: {} ", observerd);
boolean subscribed = checkIfSubscribedEvent(observerd);
if (subscribed) {
doAction(observerd);
}
}
};
EventListener<ItemObserved<Project>> listenerDeleted = new EventListener<ItemObserved<Project>>() {
@Override
public void updated(ItemObserved<Project> observerd) {
log.info("listenerDeleted fired on item: {} ", observerd);
boolean subscribed = checkIfSubscribedEvent(observerd);
if (subscribed) {
doAction(observerd);
}
}
};
EventListener<ItemObserved<Project>> listenerLCStepPerformed = new EventListener<ItemObserved<Project>>() {
@Override
public void updated(ItemObserved<Project> observerd) {
log.info("listenerLCStepPerformed fired on item: {} ", observerd);
boolean subscribed = checkIfSubscribedEvent(observerd);
if (subscribed) {
doAction(observerd);
}
}
};
// Subscribing all events
EventManager eventMngInst = EventManager.getInstance();
eventMngInst.subscribe(Event.PROJECT_CREATED, listenerCreated);
eventMngInst.subscribe(Event.PROJECT_UPDATED, listenerUpdated);
eventMngInst.subscribe(Event.PROJECT_DELETED, listenerDeleted);
eventMngInst.subscribe(Event.LIFECYCLE_STEP_PERFORMED, listenerLCStepPerformed);
report = new InitializationReport(Status.OK, PLUGIN_ID + " init performed");
} catch (Exception e) {
InitializationException exc = new InitializationException("Unable to initialize " + DESCRIPTOR.getId(), e);
log.error("init error: {} ", exc);
throw exc;
}
return report;
}
/**
* Gets the descriptor.
*
* @return the descriptor
*/
@Override
public PluginDescriptor getDescriptor() {
return DESCRIPTOR;
}
/**
* Inits the in context.
*
* @return the initialization report
* @throws InitializationException the initialization exception
*/
@Override
@Synchronized
public InitializationReport initInContext() throws InitializationException {
InitializationReport report = new InitializationReport();
try {
String context = UserUtils.getCurrent().getContext();
if (getNotificationBindingMapPerContext() == null) {
log.info("Initializing in " + context);
notificationEventsBindingMap.put(context, new HashMap<String, NotificationEventsSubscribedConfig>());
}
report.setStatus(Report.Status.OK);
report.putMessage("Initialized " + DESCRIPTOR.getId() + " in the " + context);
} catch (Exception e) {
InitializationException exc = new InitializationException("Unable to initialize " + DESCRIPTOR.getId(), e);
log.error("initInContext error: {} ", exc);
throw exc;
}
return report;
}
/**
* Check if subscribed event.
*
* @param observerd the observerd
* @return true, if successful
*/
public boolean checkIfSubscribedEvent(ItemObserved<Project> observerd) {
log.info("Checking if {} is an subscribed event", observerd.getEvent());
try {
NotificationEventsSubscribedConfig eventsSub = readNotificationsSubscribedFromConfigurationInTheUCD(
observerd.getUseCaseDescriptor());
if (eventsSub != null) {
List<SubscribeNotificationEvent> listEvents = eventsSub.getListNotificationEventSubscribed();
log.info("List events is {}", listEvents);
if (listEvents != null
&& listEvents.stream().anyMatch(sne -> sne.getEvent().equals(observerd.getEvent()))) {
log.info("the event {} is subscribed from config ", observerd.getEvent());
return true;
}
log.info("the event {} is not subscribed from config ", observerd.getEvent());
return false;
}
log.info("the event {} is not subscribed from config ", observerd.getEvent());
return false;
} catch (Exception e) {
log.error("Exception, Error on checking subscribed events", e);
return false;
}
}
/**
* Gets the notification binding map per context.
*
* @return the notification binding map per context
*/
protected Map<String, NotificationEventsSubscribedConfig> getNotificationBindingMapPerContext() {
String context = UserUtils.getCurrent().getContext();
log.debug("Getting {} from cache map for context {}", NotificationsPlugin.PLUGIN_ID, context);
if (notificationEventsBindingMap == null) {
notificationEventsBindingMap = new LinkedHashMap<String, Map<String, NotificationEventsSubscribedConfig>>();
}
// read notification events binding subscribed in the context
Map<String, NotificationEventsSubscribedConfig> map = notificationEventsBindingMap.get(context);
return map == null ? new LinkedHashMap<String, NotificationEventsSubscribedConfig>() : map;
}
/**
* Sets the notification binding map per context.
*
* @param context the context
* @param ucd the ucd
* @param notification the notification
*/
private void setNotificationBindingMapPerContext(String context, UseCaseDescriptor ucd,
NotificationEventsSubscribedConfig notification) {
Map<String, NotificationEventsSubscribedConfig> mapNotificationConfig = notificationEventsBindingMap
.get(context);
if (mapNotificationConfig == null) {
mapNotificationConfig = new LinkedHashMap<String, NotificationEventsSubscribedConfig>();
}
mapNotificationConfig.put(ucd.getId(), notification);
notificationEventsBindingMap.put(context, mapNotificationConfig);
}
/**
* Read notifications subscribed from configuration in the UCD.
*
* @param useCaseDescriptor the use case descriptor
* @return the notification events subscribed config
* @throws Exception the exception
*/
public NotificationEventsSubscribedConfig readNotificationsSubscribedFromConfigurationInTheUCD(
UseCaseDescriptor useCaseDescriptor) throws Exception {
log.debug("Reading subscribed events from UCD");
NotificationEventsSubscribedConfig notificationMapPerContext = null;
if (useCaseDescriptor == null)
throw new Exception("Error reading UCD null found");
try {
String context = UserUtils.getCurrent().getContext();
Map<String, NotificationEventsSubscribedConfig> mapPerContext = getNotificationBindingMapPerContext();
notificationMapPerContext = mapPerContext.get(useCaseDescriptor.getId());
if (notificationMapPerContext == null) {
notificationMapPerContext = new NotificationEventsSubscribedConfig();
setNotificationBindingMapPerContext(context, useCaseDescriptor, notificationMapPerContext);
}
List<SubscribeNotificationEvent> listNotificationEventsSubscribedPerUCD = notificationMapPerContext
.getListNotificationEventSubscribed();
if (listNotificationEventsSubscribedPerUCD == null) {
listNotificationEventsSubscribedPerUCD = new ArrayList<SubscribeNotificationEvent>();
Document profileConfiguration = getConfigurationFromProfile(useCaseDescriptor).getConfiguration();
log.debug("UseCaseDescriptor Configuration is {} ", profileConfiguration);
// JSONPathWrapper schemaNavigator = new
// JSONPathWrapper(useCaseDescriptor.getSchema().toJson());
if (profileConfiguration != null) {
for (Object fsConfigObj : profileConfiguration.get(SUBSCRIBE_NOTIFICATIONS_CONFIG, List.class)) {
log.debug("Managing {} ", fsConfigObj);
SubscribeNotificationEvent fsConfig = Serialization.convert(fsConfigObj,
SubscribeNotificationEvent.class);
log.debug("Converted config {}", fsConfig);
try {
Event theEventSubsribed = Serialization.convert(fsConfig.getEvent(), Event.class);
if (theEventSubsribed == null)
throw new MaterializationException(
"Invalid Field Definition path in configuration [NO MATCH] : "
+ theEventSubsribed);
} catch (Exception e) {
log.error("MaterializationException: ", e);
throw new MaterializationException(
"Invalid Event Definition path in configuration [NO MATCH Event] : "
+ Event.values());
}
listNotificationEventsSubscribedPerUCD.add(fsConfig);
}
notificationMapPerContext.setUcd(useCaseDescriptor);
notificationMapPerContext
.setListNotificationEventSubscribed(listNotificationEventsSubscribedPerUCD);
String linkToMessages = profileConfiguration.get("link_to_notifications_messages", String.class);
notificationMapPerContext.setLinkToNotificationsMessages(linkToMessages);
}
setNotificationBindingMapPerContext(context, useCaseDescriptor, notificationMapPerContext);
log.info("Events subscribed read from config {} ", notificationMapPerContext);
}
} catch (Exception e) {
log.error("Unable to read configuration for " + NotificationsPlugin.PLUGIN_ID, e);
} catch (Throwable t) {
log.error("Exception, Unable to read configuration ", t);
}
return notificationMapPerContext;
}
/**
* Shutdown.
*
* @throws ShutDownException the shut down exception
*/
@Override
public void shutdown() throws ShutDownException {
// TODO Auto-generated method stub
}
/**
* Do action.
*
* @param itemObserved the item observed
*/
@Override
public void doAction(ItemObserved<Project> itemObserved) {
log.debug("doAction called...");
boolean isSubscribedEvent = checkIfSubscribedEvent(itemObserved);
log.info("Is the event {} subscribed in notification plugin configured in the UCD: {} ",
itemObserved.getEvent(), isSubscribedEvent);
if (isSubscribedEvent) {
// Map (UCD_ID, Notification)
Map<String, NotificationEventsSubscribedConfig> notificationMapPerContext = getNotificationBindingMapPerContext();
NotificationEventsSubscribedConfig subscribedConfig = notificationMapPerContext
.get(itemObserved.getUCD_Id());
String linkToFileWithMessages = subscribedConfig.getLinkToNotificationsMessages();
List<SubscribeNotificationEvent> list = subscribedConfig.getListNotificationEventSubscribed();
//Filtering list of SubscribeNotificationEvent for itemObserved Event
List<SubscribeNotificationEvent> filterList = list.stream()
.filter(sne -> sne.getEvent().equals(itemObserved.getEvent())).collect(Collectors.toList());
log.debug(linkToFileWithMessages);
NMessagesPlaceholdersSubstitutorUtil nMPlaceholdersSUtil = null;
try {
nMPlaceholdersSUtil = new NMessagesPlaceholdersSubstitutorUtil(linkToFileWithMessages);
} catch (IOException e) {
log.error("Error instancing the {}. Please check the URL {}. Returning!!", NMessagesPlaceholdersSubstitutorUtil.class.getSimpleName(), linkToFileWithMessages);
return;
}
ManageDoActionNotification mdoact = new ManageDoActionNotification(itemObserved, nMPlaceholdersSUtil, filterList);
mdoact.manage();
// for (SubscribeNotificationEvent subscribeNotificationEvent : filterList) {
// List<NotificationFor> listNotificationFor = subscribeNotificationEvent.getNotificationFor();
//
// UserUtils.getCurrent().getRoles();
//
// for (NotificationFor notificationFor : listNotificationFor) {
// notificationFor.getRoles();
// }
// }
}
}
}