package org.gcube.application.cms.concessioni.plugins; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.bson.Document; import org.gcube.application.cms.custom.gna.concessioni.model.ProfiledConcessione; import org.gcube.application.cms.implementations.ImplementationProvider; import org.gcube.application.cms.implementations.ProjectAccess; import org.gcube.application.cms.plugins.LifecycleManager; import org.gcube.application.cms.plugins.faults.IndexingException; import org.gcube.application.cms.plugins.implementations.Default3PhaseManager; import org.gcube.application.cms.plugins.reports.EventExecutionReport; import org.gcube.application.cms.plugins.reports.Report; import org.gcube.application.cms.plugins.requests.IndexDocumentRequest; import org.gcube.application.cms.serialization.Serialization; import org.gcube.application.geoportal.common.model.JSONPathWrapper; import org.gcube.application.geoportal.common.model.document.Project; import org.gcube.application.geoportal.common.model.document.relationships.Relationship; import org.gcube.application.geoportal.common.model.document.relationships.RelationshipNavigationObject; import org.gcube.application.geoportal.common.model.legacy.report.ConstraintCheck; import com.vdurmont.semver4j.Semver; import lombok.extern.slf4j.Slf4j; @Slf4j /** * Overrides 3 Phases lifecycle with override of default values * */ public class ConcessioniLifeCycleManager extends Default3PhaseManager implements LifecycleManager { private static final String FOLLOWS = "follows"; private static final String PRECEDES = "precedes"; public ConcessioniLifeCycleManager() { DESCRIPTOR.setId("GNA-CONCESSIONI-LC"); DESCRIPTOR.setDescription( "GNA Concessioni. This plugin supports custom lifecycle management for the GNA Concessioni UseCase."); DESCRIPTOR.setVersion(new Semver("1.0.0")); } @Override public EventExecutionReport setDefault(EventExecutionReport currentReport) { EventExecutionReport report = super.setDefault(currentReport); try { report.setResultingDocument(setDefaults(report.getTheRequest().getDocument()).getTheDocument()); } catch (Throwable t) { log.error("Unable to evaluate defaults for concessione " + currentReport.getTheRequest().getDocument().getId(), t); log.debug("Object was {} ", report.getTheRequest().getDocument()); report.setStatus(Report.Status.ERROR); report.getMessages().add("Unable to evaluate defaults : " + t.getMessage()); } return report; } // STATIC ROUTINES static final Project setDefaults(Project document) throws IOException { log.info("Concessione ID {}, setting defaults..", document.getId()); log.debug("Full concessione is {}", document); ProfiledConcessione c = Serialization.convert(document, ProfiledConcessione.class); Document doc = c.getTheDocument(); doc.putIfAbsent(ProfiledConcessione.SOGGETTO, new String[] { "Research Excavation", "Archaeology" }); doc.putIfAbsent(ProfiledConcessione.DESCRIZIONE_CONTENUTO, "Relazione di fine scavo e relativo abstract; selezione di immagini rappresentative;" + " posizionamento topografico dell'area indagata, pianta di fine scavo."); // Super Section // TODO read from UCD c.getInfo().getAccess() .setLicense(ConstraintCheck.defaultFor(c.getInfo().getAccess().getLicense(), "CC0-1.0").evaluate()); // RELAZIONE Document rel = doc.containsKey(ProfiledConcessione.RELAZIONE_SCAVO) ? Serialization.convert(doc.get(ProfiledConcessione.RELAZIONE_SCAVO), Document.class) : new Document(); log.debug("Concessione {}, managing relazione {}", document.getId(), rel); rel.putIfAbsent(ProfiledConcessione.Sections.TITOLO, doc.getString(ProfiledConcessione.NOME) + " relazione di scavo"); rel.putIfAbsent(ProfiledConcessione.SOGGETTO, doc.get(ProfiledConcessione.SOGGETTO)); doc.put(ProfiledConcessione.RELAZIONE_SCAVO, rel); // ABSTRACT Relazione Document abs = doc.containsKey(ProfiledConcessione.ABSTRACT_RELAZIONE) ? Serialization.convert(doc.get(ProfiledConcessione.ABSTRACT_RELAZIONE), Document.class) : new Document(); log.debug("Concessione {}, managing abstract relazione {}", document.getId(), abs); abs.putIfAbsent(ProfiledConcessione.Sections.TITOLO, doc.getString(ProfiledConcessione.NOME) + " abstract relazione di scavo"); doc.put(ProfiledConcessione.ABSTRACT_RELAZIONE, abs); // Posizionamento scavo if (doc.containsKey(ProfiledConcessione.POSIZIONAMENTO_SCAVO)) { Document pos = Serialization.convert(doc.get(ProfiledConcessione.POSIZIONAMENTO_SCAVO), Document.class); log.debug("Concessione {}, managing posizionamento scavo {}", document.getId(), pos); pos.putIfAbsent(ProfiledConcessione.Sections.TITOLO, doc.getString(ProfiledConcessione.NOME) + " posizionamento scavo"); pos.putIfAbsent(ProfiledConcessione.Sections.ABSTRACT, "Posizionamento topografico georeferenziato dell’area interessata dalle indagini"); pos.putIfAbsent(ProfiledConcessione.Layers.TOPIC, "Society"); pos.putIfAbsent(ProfiledConcessione.Layers.SUB_TOPIC, "Archeology"); pos.putIfAbsent(ProfiledConcessione.PAROLE_CHIAVE_LIBERE, doc.get(ProfiledConcessione.PAROLE_CHIAVE_LIBERE)); pos.putIfAbsent(ProfiledConcessione.PAREOLE_CHIAVE_ICCD, doc.get(ProfiledConcessione.PAREOLE_CHIAVE_ICCD)); // BBOX in registered filesets pos.put(ProfiledConcessione.RESPONSABILE, doc.get(ProfiledConcessione.RESPONSABILE)); doc.put(ProfiledConcessione.POSIZIONAMENTO_SCAVO, pos); } // IMMAGINI RAPPRESENTATIVE JSONPathWrapper wrapper = new JSONPathWrapper(Serialization.write(doc)); if (doc.containsKey(ProfiledConcessione.IMMAGINI_RAPPRESENTATIVE)) { List imgs = wrapper.getByPath("$." + ProfiledConcessione.IMMAGINI_RAPPRESENTATIVE, List.class).get(0); log.debug("Concessione {}, found imgs {}", document.getId(), imgs.size()); for (int i = 0; i < imgs.size(); i++) { Document imgDoc = Serialization.asDocument(imgs.get(i)); imgDoc.putIfAbsent(ProfiledConcessione.SOGGETTO, doc.get(ProfiledConcessione.SOGGETTO)); wrapper.setElement("$." + ProfiledConcessione.IMMAGINI_RAPPRESENTATIVE + "[" + i + "]", imgDoc); } } // Layers if (doc.containsKey(ProfiledConcessione.PIANTE_FINE_SCAVO)) { List piante = wrapper.getByPath("$." + ProfiledConcessione.PIANTE_FINE_SCAVO, List.class).get(0); log.debug("Concessione {}, found piante {}", document.getId(), piante.size()); for (int i = 0; i < piante.size(); i++) { Document piantaDoc = Serialization.asDocument(piante.get(i)); log.debug("Concessione {}, managing pianta {}", document.getId(), piantaDoc); piantaDoc.putIfAbsent(ProfiledConcessione.Sections.TITOLO, doc.getString(ProfiledConcessione.NOME) + " pianta fine scavo"); piantaDoc.putIfAbsent(ProfiledConcessione.Sections.ABSTRACT, "Planimetria georeferenziata dell'area indagata al termine delle attività"); piantaDoc.putIfAbsent(ProfiledConcessione.Layers.TOPIC, "Society"); piantaDoc.putIfAbsent(ProfiledConcessione.Layers.SUB_TOPIC, "Archeology"); piantaDoc.putIfAbsent(ProfiledConcessione.PAROLE_CHIAVE_LIBERE, doc.get(ProfiledConcessione.PAROLE_CHIAVE_LIBERE)); piantaDoc.putIfAbsent(ProfiledConcessione.PAREOLE_CHIAVE_ICCD, doc.get(ProfiledConcessione.PAREOLE_CHIAVE_ICCD)); // BBOX in registered filesets piantaDoc.put(ProfiledConcessione.RESPONSABILE, doc.get(ProfiledConcessione.RESPONSABILE)); wrapper.setElement("$." + ProfiledConcessione.PIANTE_FINE_SCAVO + "[" + i + "]", piantaDoc); } } c.setTheDocument(Serialization.read(wrapper.getValueCTX().jsonString(), Document.class)); return c; } /** * New method implemented by Francesco */ @Override protected Document evaluateAdditionalIndexParameters(IndexDocumentRequest request) throws IndexingException { Document toReturn = super.evaluateAdditionalIndexParameters(request); if (toReturn == null) toReturn = new Document(); Project indexingProject = request.getDocument(); // Evaluate to display project IDs log.info("Evaluating relationship chain. Current ID is {}", indexingProject.getId()); try { ArrayList projects = new ArrayList<>(); ProjectAccess access = ImplementationProvider.get().getProvidedObjectByClass(ProjectAccess.class); // get Last ID in relation chain projects.add(indexingProject); if (!indexingProject.getRelationshipsByName(PRECEDES).isEmpty()) scanRelation(projects, access .getRelations(indexingProject.getProfileID(), indexingProject.getId(), PRECEDES, true).get(0), false); if (!indexingProject.getRelationshipsByName(FOLLOWS).isEmpty()) scanRelation(projects, access .getRelations(indexingProject.getProfileID(), indexingProject.getId(), FOLLOWS, true).get(0), false); log.debug("Produced full chain [size : {}] from {}, evaluating last available for PHASE {} ", projects.size(), indexingProject.getId(), indexingProject.getLifecycleInformation().getPhase()); log.info("projects are: " + projects.size()); List toDisplayId = new ArrayList<>(); List toHideIds = new ArrayList<>(); // Reverse Order means from the last FOLLOW to the first one (temporal reverse // order) Collections.sort(projects, Collections.reverseOrder(new ProjectRelationComparator())); if (log.isInfoEnabled()) { int j = 0; log.info("Printing project reverse order...."); for (Project theProject : projects) { log.info(++j + ") " + theProject.getId() + " data inizio: " + theProject.getTheDocument().get("dataInizioProgetto")); } } log.trace("Checking from LAST.. "); for (int i = 0; i < projects.size(); i++) { Project p = projects.get(i); String phase = p.getLifecycleInformation().getPhase(); // IS TO DISPLAY EMPTY? Step into only once. // Indexing the first project that is in PENDING APPROVAL or PUBLISHED or // updating the phase of the indexing (selected) project if (toDisplayId.isEmpty()) { // IF PHASE IS PENDING APPROVAL OR PUBLISHED adding toDisplayId if ((phase.equals(Phases.PENDING_APPROVAL) || phase.equals(Phases.PUBLISHED))) { toDisplayId.add(p.getId()); } else if (p.getId().compareTo(indexingProject.getId()) == 0) { // Means that the operation has been called on the indexing project from DRAFT // phase to PENDING_APPROVAL or PUBLISH toDisplayId.add(p.getId()); } } else { // Hides the centroid regardless of project phase toHideIds.add(p.getId()); } } toReturn.put("_toHideIds", toHideIds); toReturn.put("_toDisplayIds", toDisplayId); log.info( "Indexing request for " + indexingProject.getProfileID() + " [ID {}] with to _toHideIds {} and _toDisplayIds {} ", indexingProject.getId(), toHideIds, toDisplayId); return toReturn; } catch (Exception e) { log.error("Unable to evaluate to Hide and Display Ids ", e); throw new IndexingException("Unable to evaluate chain ids to hide / display", e); } } private static void scanRelation(ArrayList chain, RelationshipNavigationObject obj, boolean putBefore) { if (putBefore) chain.add(0, obj.getTarget()); else chain.add(obj.getTarget()); if (obj.getChildren() != null) obj.getChildren().forEach(r -> scanRelation(chain, r, putBefore)); } public static class ProjectRelationComparator implements Comparator { @Override public int compare(Project p1, Project p2) { if (p1 == null) return 1; if (p2 == null) return -1; Integer compareResult = null; compareResult = compareProjectAgainstRelations(p1, p2); log.trace("p1 & p2, comparator result: {}", compareResult); if (compareResult == null) { log.debug("No relations beetween p1 & p2, checking inverted relations"); compareResult = compareProjectAgainstRelations(p2, p1); log.trace("p2 & p1, comparator result: {}", compareResult); if (compareResult == null) { log.trace("p1 & p2, are not comparable, returning 0"); compareResult = 0; } } log.debug("p1 & p2, comparator result, returns: {}", compareResult); return compareResult; } } public static Integer compareProjectAgainstRelations(Project source, Project target) { log.debug("comparing source {} and target {}", source.getId(), target.getId()); List listRel = source.getRelationships(); log.debug("relationships of {} are : {}", source.getId(), listRel); if (listRel != null) { String targetId = target.getId(); for (Relationship relationship : listRel) { String relTargetId = relationship.getTargetID(); if (targetId.compareTo(relTargetId) == 0) { String relationName = relationship.getRelationshipName(); if (relationName.equals(PRECEDES)) { log.debug("source {} [rel {} ] target {}, so source < target ", source.getId(), PRECEDES, target.getId()); // source < target return -1; } else if (relationName.equals(FOLLOWS)) { log.debug("source {} [rel {} ] target {}, so source > target ", source.getId(), FOLLOWS, target.getId()); // source > target return 1; } } } } log.debug("No relations beetween a & b"); return null; } }