diff --git a/concessioni-lifecycle/src/main/java/org/gcube/application/cms/concessioni/plugins/ConcessioniLifeCycleManager.java b/concessioni-lifecycle/src/main/java/org/gcube/application/cms/concessioni/plugins/ConcessioniLifeCycleManager.java index 37aec02..373c2df 100644 --- a/concessioni-lifecycle/src/main/java/org/gcube/application/cms/concessioni/plugins/ConcessioniLifeCycleManager.java +++ b/concessioni-lifecycle/src/main/java/org/gcube/application/cms/concessioni/plugins/ConcessioniLifeCycleManager.java @@ -87,11 +87,13 @@ public class ConcessioniLifeCycleManager implements LifecycleManager { public StepExecutionReport performStep(StepExecutionRequest request) throws StepException { log.info("Serving Request {}",request); StepExecutionReport report=new StepExecutionReport(); - LifecycleInformation info=request.getDocument().getLifecycleInformation(); + report.setTheRequest(request); + report.setStatus(Report.Status.OK); + report.setToSetLifecycleInformation(new LifecycleInformation()); + + LifecycleInformation info=report.getToSetLifecycleInformation(); info.setLastOperationStatus(LifecycleInformation.Status.OK); info.setLastInvokedStep(request.getStep()); - report.setRequest(request); - report.setResult(request.getDocument()); try { switch (request.getStep()) { case "SUBMIT-FOR-REVIEW" :{ @@ -108,7 +110,7 @@ public class ConcessioniLifeCycleManager implements LifecycleManager { params.put("workspace", Files.fixFilename(workspace)); - matReq.setParameters(params); + matReq.setCallParameters(params); MaterializationReport matRep = plugin.materialize(matReq); @@ -153,8 +155,11 @@ public class ConcessioniLifeCycleManager implements LifecycleManager { throw e; }catch (Throwable t){ log.error("Unable to perform step "+request.getStep(),t); - report.getResult().getLifecycleInformation().setLastOperationStatus(LifecycleInformation.Status.ERROR); - report.getResult().getLifecycleInformation().addErrorMessage("Unable to execute Step "+request.getStep()+". Error was "+t.getMessage()); + String msg = "Unable to execute Step "+request.getStep()+". Error was "+t.getMessage(); + report.setStatus(Report.Status.ERROR); + report.putMessage(msg); + info.setLastOperationStatus(LifecycleInformation.Status.ERROR); + info.addErrorMessage(msg); } return report; } @@ -164,9 +169,14 @@ public class ConcessioniLifeCycleManager implements LifecycleManager { public EventExecutionReport onEvent(EventExecutionRequest request) throws EventException { log.info("Executing Event {}",request); EventExecutionReport report=new EventExecutionReport(); - report.setRequest(request); - report.setResult(request.getDocument()); + report.setTheRequest(request); + + TriggeredEvents info=new TriggeredEvents(); + info.setEvent(request.getEvent()); + info.setLastOperationStatus(LifecycleInformation.Status.OK); + report.setStatus(Report.Status.OK); + try { switch(request.getEvent()){ case EventExecutionRequest.Events.ON_INIT_DOCUMENT: @@ -187,10 +197,13 @@ public class ConcessioniLifeCycleManager implements LifecycleManager { throw e; }catch (Throwable t){ log.error("Unable to execute on event "+request.getEvent(),t); + String msg = "Unable to execute on event "+request.getEvent()+". Error was "+t.getMessage(); info.setLastOperationStatus(LifecycleInformation.Status.ERROR); - info.addErrorMessage("Unable to execute on event "+request.getEvent()+". Error was "+t.getMessage()); + info.addErrorMessage(msg); + report.setStatus(Report.Status.ERROR); + report.putMessage(msg); }finally{ - report.getResult().getLifecycleInformation().addEventReport(info); + report.getToSetLifecycleInformation().addEventReport(info); } return report; } diff --git a/concessioni-lifecycle/src/main/java/org/gcube/application/cms/concessioni/plugins/SDIMaterializerPlugin.java b/concessioni-lifecycle/src/main/java/org/gcube/application/cms/concessioni/plugins/SDIMaterializerPlugin.java index 693f403..363c73f 100644 --- a/concessioni-lifecycle/src/main/java/org/gcube/application/cms/concessioni/plugins/SDIMaterializerPlugin.java +++ b/concessioni-lifecycle/src/main/java/org/gcube/application/cms/concessioni/plugins/SDIMaterializerPlugin.java @@ -141,8 +141,8 @@ public class SDIMaterializerPlugin implements MaterializationPlugin { } } - profiledDocument.setTheDocument(Document.parse(documentNavigator.getValueCTX().jsonString())); - report.setResultDocument(profiledDocument); + + report.setResultingDocument(Document.parse(documentNavigator.getValueCTX().jsonString())); report.setStatus(Report.Status.OK); }catch (SDIInteractionException e){ log.error("Unable to materialize "+request,e); diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/document/lifecycle/LifecycleInformation.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/document/lifecycle/LifecycleInformation.java index fa229c4..bbf3ba3 100644 --- a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/document/lifecycle/LifecycleInformation.java +++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/document/lifecycle/LifecycleInformation.java @@ -29,19 +29,31 @@ public class LifecycleInformation { private List triggeredEvents; - public void addErrorMessage(String msg){ + public LifecycleInformation addErrorMessage(String msg){ if(errorMessages==null) errorMessages=new ArrayList<>(); errorMessages.add(msg); + return this; } - public void addWarningMessage(String msg){ + public LifecycleInformation addWarningMessage(String msg){ if(warningMessages==null) warningMessages=new ArrayList<>(); warningMessages.add(msg); + return this; } - public void addEventReport(TriggeredEvents info){ + public LifecycleInformation addEventReport(TriggeredEvents info){ if(triggeredEvents==null) triggeredEvents=new ArrayList<>(); triggeredEvents.add(info); + return this; + } + + public LifecycleInformation cleanState(){ + setLastOperationStatus(null); + setLastInvokedStep(null); + setTriggeredEvents(new ArrayList<>()); + setErrorMessages(new ArrayList<>()); + setWarningMessages(new ArrayList<>()); + return this; } } diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ProfiledMongoManager.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ProfiledMongoManager.java index 9cbe316..73bcdcc 100644 --- a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ProfiledMongoManager.java +++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ProfiledMongoManager.java @@ -13,7 +13,9 @@ import org.gcube.application.cms.plugins.LifecycleManager; import org.gcube.application.cms.plugins.faults.EventException; import org.gcube.application.cms.plugins.faults.StepException; import org.gcube.application.cms.plugins.model.PluginDescriptor; +import org.gcube.application.cms.plugins.reports.DocumentHandlingReport; import org.gcube.application.cms.plugins.reports.EventExecutionReport; +import org.gcube.application.cms.plugins.reports.Report; import org.gcube.application.cms.plugins.reports.StepExecutionReport; import org.gcube.application.cms.plugins.requests.EventExecutionRequest; import org.gcube.application.cms.plugins.requests.StepExecutionRequest; @@ -51,13 +53,11 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.InvalidParameterException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.function.Consumer; +import static org.gcube.application.cms.plugins.reports.Report.*; import static org.gcube.application.cms.serialization.Serialization.*; @Slf4j @@ -135,7 +135,6 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< ProfiledDocument toRegister = new ProfiledDocument(); toRegister.setTheDocument(toRegisterDoc); - PublicationInfo pubInfo=new PublicationInfo(); pubInfo.setCreationInfo(UserUtils.getCurrent().asInfo()); @@ -152,13 +151,14 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< toRegister.setVersion(new Semver("1.0.0")); - LifecycleInformation draftInfo=new LifecycleInformation(); + LifecycleInformation draftInfo=new LifecycleInformation().cleanState(); draftInfo.setPhase(LifecycleInformation.DRAFT_PHASE); + draftInfo.setLastOperationStatus(LifecycleInformation.Status.OK); toRegister.setLifecycleInformation(draftInfo); - // Apply Lifecycle - toRegister = triggerEvent(toRegister,EventExecutionRequest.Events.ON_INIT_DOCUMENT,null).getResult(); + // Apply Lifecycle + toRegister = triggerEvent(toRegister,EventExecutionRequest.Events.ON_INIT_DOCUMENT,null); log.debug("Going to register {} ",toRegister); @@ -174,6 +174,7 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< log.trace("Replacing {} ",toSet); ProfiledDocument toUpdate=getByID(id); toUpdate.setTheDocument(toSet); + toUpdate.getLifecycleInformation().cleanState(); toUpdate=onUpdate(toUpdate); ProfiledDocument toReturn =convert(replace(asDocumentWithId(toUpdate),new ObjectId(id),getCollectionName()),ProfiledDocument.class); @@ -186,10 +187,11 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< UserUtils.AuthenticatedUser u = UserUtils.getCurrent(); toUpdate.getInfo().setLastEditInfo(u.asInfo()); toUpdate.setVersion(toUpdate.getVersion().withIncPatch()); - return triggerEvent(toUpdate,EventExecutionRequest.Events.ON_INIT_DOCUMENT,null).getResult(); + return triggerEvent(toUpdate,EventExecutionRequest.Events.ON_INIT_DOCUMENT,null); } - @Override + + @Override public void delete(String id,boolean force) throws DeletionException { log.debug("Deleting by ID {}, force {}",id,force); try{ @@ -254,8 +256,8 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< public ProfiledDocument performStep(String id, String step, Document options) throws StepException, JsonProcessingException { ProfiledDocument document = getByID(id); try{ - StepExecutionReport report = step(document, step, options); - document = report.getResult(); + document.getLifecycleInformation().cleanState(); + document = step(document, step, options); } catch(Throwable t){ log.error("[Profile {} ] ERROR Invoking Step {} on document {}" ,profile.getId(),step,id,t); LifecycleInformation info = new LifecycleInformation(); @@ -265,6 +267,10 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< info.setLastInvokedStep(step); document.setLifecycleInformation(info); }finally{ + log.info("Storing {} [Profile {}] After Step {}, Status : {} " ,id,profile.getId(), + step,document.getLifecycleInformation().getLastOperationStatus()); + log.debug("LifecycleInformation is {} ",document.getLifecycleInformation()); + if(log.isTraceEnabled())log.trace("Document is {} ",Serialization.write(document)); return convert(replace(asDocumentWithId(document),new ObjectId(id),getCollectionName()),ProfiledDocument.class); } } @@ -290,6 +296,9 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< List files=request.getStreams(); Document attributes =request.getAttributes(); ProfiledDocument doc=getByID(id); + doc.getLifecycleInformation().cleanState(); + doc.getLifecycleInformation().setLastOperationStatus(LifecycleInformation.Status.OK); + WorkspaceManager ws=new WorkspaceManager(); StorageUtils storage=ImplementationProvider.get().getStorageProvider().getObject(); @@ -359,6 +368,10 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< log.info("Deleting Fileset for {} [profile ID {}], at {} [force {} ]",id,profile.getId(),path,force); ProfiledDocument doc = getByID(id); + doc.getLifecycleInformation().cleanState(); + doc.getLifecycleInformation().cleanState().setLastOperationStatus(LifecycleInformation.Status.OK); + + JSONPathWrapper wrapper = new JSONPathWrapper(doc.getTheDocument().toJson()); List matchingPaths=wrapper.getMatchingPaths(path); if(matchingPaths.isEmpty()) throw new WebApplicationException("No Registered FileSet found at "+path,Response.Status.BAD_REQUEST); @@ -381,8 +394,9 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< } - private StepExecutionReport step(ProfiledDocument theDocument, String step, Document callParameters) throws StepException { - log.info("[Profile {}] Invoking Step {} on {}" ,profile.getId(),step,getManager().getDescriptor()); + private ProfiledDocument step(ProfiledDocument theDocument, String step, Document callParameters){ + try{ + log.info("[Profile {}] Invoking Step {} on {}" ,profile.getId(),step,getManager().getDescriptor()); StepExecutionRequest request=new StepExecutionRequest(); request.setCallParameters(callParameters); request.setDocument(theDocument); @@ -393,14 +407,41 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< request.setContext(user.getContext()); log.debug("Requesting Step Execution {}",request); + StepExecutionReport report= getManager().performStep(request); + ProfiledDocument toReturn = report.prepareResult(); - StepExecutionReport report= getManager().performStep(request); - log.debug("Report is {}",report); - if(report.getResult()==null) throw new StepException("Report result is null"); - return report; + // EVENTS + if(report.getToTriggerEvents()!=null) { + Iterator eventIT = report.getToTriggerEvents().listIterator(); + while (!toReturn.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.ERROR) + && eventIT.hasNext()) { + EventExecutionRequest triggerRequest = eventIT.next(); + log.info("Triggering {} ", triggerRequest); + toReturn = triggerEvent(toReturn, triggerRequest.getEvent(), triggerRequest.getCallParameters()); + } + } + + // STEPS + if(report.getCascadeSteps()!=null) { + Iterator stepIT = report.getCascadeSteps().listIterator(); + while (!toReturn.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.ERROR) + && stepIT.hasNext()) { + StepExecutionRequest triggerRequest = stepIT.next(); + log.info("Triggering {} ", triggerRequest); + toReturn = step(toReturn, triggerRequest.getStep(), triggerRequest.getCallParameters()); + } + } + return report.prepareResult(); + }catch(Throwable t){ + log.error("Unable to perform step "+step,t); + theDocument.getLifecycleInformation().addErrorMessage("Unable to perform step "+step+" cause : "+ t.getMessage()); + theDocument.getLifecycleInformation().setLastOperationStatus(LifecycleInformation.Status.ERROR); + return theDocument; + } } - private EventExecutionReport triggerEvent(ProfiledDocument theDocument, String event, Document parameters) throws EventException { + private ProfiledDocument triggerEvent(ProfiledDocument theDocument, String event, Document parameters) { + try{ log.info("[Profile {}] triggering event {} on {}" ,profile.getId(),event,getManager().getDescriptor()); EventExecutionRequest request= new EventExecutionRequest(); request.setEvent(event); @@ -408,7 +449,14 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< request.setCallParameters(parameters); request.setDocument(theDocument); log.debug("Triggering {}",request); - return getManager().onEvent(request); + DocumentHandlingReport report = getManager().onEvent(request); + return report.prepareResult(); + } catch (Throwable t){ + log.error("Unable to trigger event "+event,t); + theDocument.getLifecycleInformation().addErrorMessage("Unable to trigger "+event+" cause : "+ t.getMessage()); + theDocument.getLifecycleInformation().setLastOperationStatus(LifecycleInformation.Status.ERROR); + return theDocument; + } } diff --git a/geoportal-service/src/test/java/org/gcube/application/geoportal/service/AbstractProfiledDocumentsTests.java b/geoportal-service/src/test/java/org/gcube/application/geoportal/service/AbstractProfiledDocumentsTests.java index 40ea7f6..c277145 100644 --- a/geoportal-service/src/test/java/org/gcube/application/geoportal/service/AbstractProfiledDocumentsTests.java +++ b/geoportal-service/src/test/java/org/gcube/application/geoportal/service/AbstractProfiledDocumentsTests.java @@ -84,13 +84,53 @@ public abstract class AbstractProfiledDocumentsTests extends BasicServiceTestUni // @@@@@@@@@@@@@@@ Routines protected ProfiledDocument createNew(Document content) throws Exception { - return check(baseTarget().request(MediaType.APPLICATION_JSON). + ProfiledDocument doc =check(baseTarget().request(MediaType.APPLICATION_JSON). post(Entity.entity(content, MediaType.APPLICATION_JSON)),ProfiledDocument.class); + validate(doc); + assertTrue(doc.getLifecycleInformation().getPhase().equals(LifecycleInformation.DRAFT_PHASE)); + return doc; } + protected void validate (ProfiledDocument doc){ + assertTrue(doc!=null); + assertTrue(doc.get_id()!=null); + assertTrue(doc.getLifecycleInformation().getPhase()!=null); + assertTrue(doc.getLifecycleInformation().getLastOperationStatus()!=null); + if(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.ERROR)) + assertTrue(doc.getLifecycleInformation().getErrorMessages().size()>0); + if(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.WARNING)) + assertTrue(doc.getLifecycleInformation().getWarningMessages().size()>0); + + if(doc.getLifecycleInformation().getTriggeredEvents()!=null) + doc.getLifecycleInformation().getTriggeredEvents().forEach(triggeredEvents -> { + assertTrue(triggeredEvents.getEvent()!=null); + assertTrue(triggeredEvents.getLastOperationStatus()!=null); + if(triggeredEvents.getLastOperationStatus().equals(LifecycleInformation.Status.ERROR)) + assertTrue(triggeredEvents.getErrorMessages().size()>0); + if(triggeredEvents.getLastOperationStatus().equals(LifecycleInformation.Status.WARNING)) + assertTrue(triggeredEvents.getWarningMessages().size()>0); + }); + + + assertTrue(doc.getInfo()!=null); + assertTrue(doc.getInfo().getCreationInfo()!=null); + assertTrue(doc.getInfo().getCreationInfo().getContext()!=null); + assertTrue(doc.getInfo().getCreationInfo().getContext().getId()!=null); + assertTrue(doc.getInfo().getCreationInfo().getContext().getName()!=null); + assertTrue(doc.getInfo().getCreationInfo().getInstant()!=null); + assertTrue(doc.getInfo().getCreationInfo().getInstant()!=null); + assertTrue(doc.getInfo().getCreationInfo().getUser()!=null); + assertTrue(doc.getInfo().getCreationInfo().getUser().getUsername()!=null); + + assertTrue(doc.getTheDocument()!=null); + } + + protected ProfiledDocument update(String id, Document newContent)throws Exception { - return check(baseTarget().path(id).request(MediaType.APPLICATION_JSON). + ProfiledDocument doc = check(baseTarget().path(id).request(MediaType.APPLICATION_JSON). put(Entity.entity(newContent, MediaType.APPLICATION_JSON)),ProfiledDocument.class); + validate(doc); + return doc; } protected ProfiledDocument upload(StorageUtils storage, @@ -108,9 +148,11 @@ public abstract class AbstractProfiledDocumentsTests extends BasicServiceTestUni for(String file:files) builder.add(storage.putOntoStorage(new File(TestConcessioniModel.getBaseFolder(),file),file)); - return check(baseTarget().path(InterfaceConstants.Methods.REGISTER_FILES_PATH).path(id).request(MediaType.APPLICATION_JSON). + ProfiledDocument doc = check(baseTarget().path(InterfaceConstants.Methods.REGISTER_FILES_PATH).path(id).request(MediaType.APPLICATION_JSON). post(Entity.entity(Serialization.write(builder.getTheRequest()), MediaType.APPLICATION_JSON)),ProfiledDocument.class); + validate(doc); + return doc; } @@ -119,7 +161,7 @@ public abstract class AbstractProfiledDocumentsTests extends BasicServiceTestUni path(InterfaceConstants.Methods.STEP).path(id).request(MediaType.APPLICATION_JSON). post(Entity.entity(Serialization.write(request), MediaType.APPLICATION_JSON)),ProfiledDocument.class); - + validate(toReturn); assertTrue(toReturn.getLifecycleInformation().getLastInvokedStep().equals(request.getStepID())); return toReturn; } diff --git a/geoportal-service/src/test/java/org/gcube/application/geoportal/service/DummyProfiledDocumentTest.java b/geoportal-service/src/test/java/org/gcube/application/geoportal/service/DummyProfiledDocumentTest.java index 33f5001..7008b87 100644 --- a/geoportal-service/src/test/java/org/gcube/application/geoportal/service/DummyProfiledDocumentTest.java +++ b/geoportal-service/src/test/java/org/gcube/application/geoportal/service/DummyProfiledDocumentTest.java @@ -36,10 +36,7 @@ public class DummyProfiledDocumentTest extends AbstractProfiledDocumentsTests{ public void registerNew() throws Exception { ProfiledDocument doc = createNew(new Document("field","value")); - assertTrue(doc!=null); - assertTrue(doc.get_id()!=null); - assertTrue(doc.getLifecycleInformation().getPhase().equals(LifecycleInformation.DRAFT_PHASE)); - assertTrue(doc.getTheDocument()!=null); + assertTrue(doc.getTheDocument().containsKey("field")); assertTrue(doc.getTheDocument().getString("field").equals("value")); } @@ -126,13 +123,15 @@ public class DummyProfiledDocumentTest extends AbstractProfiledDocumentsTests{ } assertTrue(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.OK)); + JSONPathWrapper wrapper = new JSONPathWrapper(doc.getTheDocument().toJson()); RegisteredFileSet fs = Serialization.convert(wrapper.getByPath("$..fileset").get(0),RegisteredFileSet.class); + assertTrue(fs!=null); assertTrue(fs.getPayloads().size()==2); assertTrue(fs.getMaterializations().size()>0); - for(Object matObj : wrapper.getByPath("$..fileset."+RegisteredFileSet.MATERIALIZATIONS)){ + for(Object matObj : wrapper.getByPath("$..fileset."+RegisteredFileSet.MATERIALIZATIONS,List.class).get(0)){ GCubeSDILayer layer = Serialization.convert(matObj, GCubeSDILayer.class); System.out.println("Checking Layer : "+layer); assertTrue(layer.getType().equals(GCubeSDILayer.GCUBE_SDY_LAYER_TYPE)); diff --git a/geoportal-service/src/test/resources/logback.xml b/geoportal-service/src/test/resources/logback.xml index 8ec1f7c..13c9645 100644 --- a/geoportal-service/src/test/resources/logback.xml +++ b/geoportal-service/src/test/resources/logback.xml @@ -7,7 +7,7 @@ - +