package org.gcube.application.cms.cataloguebinding; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.bson.Document; import org.gcube.application.cms.cataloguebinding.doaction.BindingAction; import org.gcube.application.cms.implementations.utils.UserUtils; 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.InvalidProfileException; 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.Data; import lombok.Synchronized; import lombok.extern.slf4j.Slf4j; /** * The Class CatalogueBindingPlugin. * * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it * * Jan 19, 2024 */ @Slf4j public class CatalogueBindingPlugin extends AbstractPlugin implements EventListenerPluginInterface { public static final String SUBSCRIBE_EVENTS_CONFIG = "subscribeEvents"; public static final String PLUGIN_ID = "Catalogue-Binding-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 data binding from geoportal to catalogue"); } /** * Gets the descriptor. * * @return the descriptor */ @Override public PluginDescriptor getDescriptor() { return DESCRIPTOR; } @Data public class SubscribeEventsConfig { private String event; } /** * 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> listenerCreated = new EventListener>() { @Override public void updated(ItemObserved observerd) { log.info("listenerCreated fired on item: {} " + observerd); boolean subscribed = checkIfSubscribedEvent(observerd); if (subscribed) { doAction(observerd); } } }; EventListener> listenerUpdated = new EventListener>() { @Override public void updated(ItemObserved observerd) { log.info("listenerUpdated fired on item: {} " + observerd); boolean subscribed = checkIfSubscribedEvent(observerd); if (subscribed) { doAction(observerd); } } }; EventListener> listenerDeleted = new EventListener>() { @Override public void updated(ItemObserved observerd) { log.info("listenerDeleted fired on item: {} " + observerd); boolean subscribed = checkIfSubscribedEvent(observerd); if (subscribed) { doAction(observerd); } } }; EventListener> listenerLCStepPerformed = new EventListener>() { @Override public void updated(ItemObserved 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; } /** * 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 (getCatalogueBindingMapPerContext() == null) { log.info("Initializing in " + context); catalogueBindingMap.put(context, new EventsSubscribed()); } 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; } protected Map catalogueBindingMap = null; /** * Gets the catalogue binding map per context. * * @return the catalogue binding map per context */ protected EventsSubscribed getCatalogueBindingMapPerContext() { String context = UserUtils.getCurrent().getContext(); log.debug("Getting {} from cache map for context {}", CatalogueBindingPlugin.PLUGIN_ID, context); if (catalogueBindingMap == null) catalogueBindingMap = new LinkedHashMap(); return catalogueBindingMap.get(context); } /** * Read events subscribed from configuration in the UCD. * * @param useCaseDescriptor the use case descriptor * @return the events subscribed * @throws Exception the exception */ public EventsSubscribed readEventsSubscribedFromConfigurationInTheUCD(UseCaseDescriptor useCaseDescriptor) throws Exception { log.debug("Reading subscribed events from UCD"); EventsSubscribed eventsSubscrInTheUCD = new EventsSubscribed(); if (useCaseDescriptor == null) throw new Exception("Error reading UCD null found"); try { String context = UserUtils.getCurrent().getContext(); eventsSubscrInTheUCD = getCatalogueBindingMapPerContext(); List listEventsSubscribedPerUCD = new ArrayList(); if (eventsSubscrInTheUCD == null || listEventsSubscribedPerUCD.isEmpty()) { Document profileConfiguration = getConfigurationFromProfile(useCaseDescriptor).getConfiguration(); log.debug("UseCaseDescriptor Configuration is {} ", profileConfiguration); // JSONPathWrapper schemaNavigator = new // JSONPathWrapper(useCaseDescriptor.getSchema().toJson()); for (Object fsConfigObj : profileConfiguration.get(SUBSCRIBE_EVENTS_CONFIG, List.class)) { log.debug("Managing {} ", fsConfigObj); SubscribeEventsConfig fsConfig = Serialization.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); log.debug("Added event {} to list ", event); listEventsSubscribedPerUCD.add(event); } eventsSubscrInTheUCD = new EventsSubscribed(); eventsSubscrInTheUCD.setContext(context); eventsSubscrInTheUCD.setListEventSubscribed(listEventsSubscribedPerUCD); catalogueBindingMap.put(context, eventsSubscrInTheUCD); log.info("Events subscribed read from config {} ", eventsSubscrInTheUCD); } } catch (InvalidProfileException e) { log.warn("Unable to read configuration for {} in the UCD {}", CatalogueBindingPlugin.PLUGIN_ID, useCaseDescriptor.getId()); } catch (Exception e) { log.error("Unable to read configuration ", e); } catch (Throwable t) { log.error("Exception, Unable to read configuration ", t); } return eventsSubscrInTheUCD; } /** * Check if subscribed event. * * @param observerd the observerd * @return true, if successful */ public boolean checkIfSubscribedEvent(ItemObserved observerd) { log.info("Checking if {} is an subscribed event", observerd.getEvent()); try { EventsSubscribed eventsSub = readEventsSubscribedFromConfigurationInTheUCD( observerd.getUseCaseDescriptor()); List listEvents = eventsSub.getListEventSubscribed(); log.info("List events is {}", listEvents); if(listEvents==null) { log.info("no event subscribed, returing false"); return false; } if (listEvents.contains(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; } catch (Exception e) { log.error("Exception, Error on checking subscribed events", e); return false; } } /** * Shutdown. * * @throws ShutDownException the shut down exception */ @Override public void shutdown() throws ShutDownException { // TODO Auto-generated method stub } /** * Do action. * * @param observerd the observerd */ @Override public void doAction(ItemObserved observerd) { new BindingAction().doAction(observerd); } }