gcube-cms-suite/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ProfiledMongoManager.java

572 lines
28 KiB
Java
Raw Normal View History

2021-09-20 16:47:35 +02:00
package org.gcube.application.geoportal.service.engine.mongo;
2021-12-01 11:13:34 +01:00
import com.fasterxml.jackson.core.JsonProcessingException;
2022-03-10 18:15:10 +01:00
import com.mongodb.client.MongoCollection;
2021-12-01 11:13:34 +01:00
import com.mongodb.client.MongoDatabase;
2022-01-17 18:19:40 +01:00
import com.vdurmont.semver4j.Semver;
2022-01-17 13:30:21 +01:00
import lombok.Getter;
2021-12-01 11:13:34 +01:00
import lombok.extern.slf4j.Slf4j;
2022-03-11 18:11:32 +01:00
import org.apache.commons.collections.ArrayStack;
2022-01-17 18:19:40 +01:00
import org.apache.commons.io.IOUtils;
2021-12-01 11:13:34 +01:00
import org.bson.Document;
import org.bson.types.ObjectId;
2021-12-07 16:12:43 +01:00
import org.gcube.application.cms.plugins.LifecycleManager;
2022-02-14 17:06:32 +01:00
import org.gcube.application.cms.plugins.faults.EventException;
2021-12-07 16:42:39 +01:00
import org.gcube.application.cms.plugins.faults.StepException;
2022-01-12 18:42:22 +01:00
import org.gcube.application.cms.plugins.model.PluginDescriptor;
2022-02-17 16:01:39 +01:00
import org.gcube.application.cms.plugins.reports.DocumentHandlingReport;
2022-02-14 12:23:13 +01:00
import org.gcube.application.cms.plugins.reports.StepExecutionReport;
2022-03-11 18:11:32 +01:00
import org.gcube.application.cms.plugins.requests.BaseRequest;
2022-02-14 17:06:32 +01:00
import org.gcube.application.cms.plugins.requests.EventExecutionRequest;
2021-12-07 16:42:39 +01:00
import org.gcube.application.cms.plugins.requests.StepExecutionRequest;
2022-01-17 18:19:40 +01:00
import org.gcube.application.geoportal.common.faults.StorageException;
2022-03-10 18:15:10 +01:00
import org.gcube.application.geoportal.common.model.configuration.Archive;
2022-03-11 18:11:32 +01:00
import org.gcube.application.geoportal.common.model.configuration.Index;
2021-12-07 16:42:39 +01:00
import org.gcube.application.geoportal.common.model.document.*;
2022-02-14 12:23:13 +01:00
import org.gcube.application.geoportal.common.model.document.access.Access;
import org.gcube.application.geoportal.common.model.document.access.AccessPolicy;
2022-02-14 17:06:32 +01:00
import org.gcube.application.geoportal.common.model.document.accounting.AccountingInfo;
2022-02-14 12:23:13 +01:00
import org.gcube.application.geoportal.common.model.document.accounting.PublicationInfo;
import org.gcube.application.geoportal.common.model.document.filesets.RegisteredFile;
import org.gcube.application.geoportal.common.model.document.filesets.RegisteredFileSet;
2022-02-14 17:06:32 +01:00
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
2022-03-04 14:23:20 +01:00
import org.gcube.application.geoportal.common.model.useCaseDescriptor.Field;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.HandlerDeclaration;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
2022-03-10 18:15:10 +01:00
import org.gcube.application.geoportal.common.model.configuration.Configuration;
2021-12-01 11:13:34 +01:00
import org.gcube.application.geoportal.common.model.rest.QueryRequest;
2022-01-27 15:02:53 +01:00
import org.gcube.application.geoportal.common.model.rest.RegisterFileSetRequest;
import org.gcube.application.geoportal.common.model.rest.TempFile;
2022-02-01 15:24:39 +01:00
import org.gcube.application.geoportal.common.model.JSONPathWrapper;
2022-03-10 18:15:10 +01:00
import org.gcube.application.geoportal.common.utils.ContextUtils;
2022-01-17 18:19:40 +01:00
import org.gcube.application.geoportal.common.utils.StorageUtils;
import org.gcube.application.cms.implementations.ImplementationProvider;
2022-01-17 18:19:40 +01:00
import org.gcube.application.geoportal.service.engine.WorkspaceManager;
2022-02-04 17:45:47 +01:00
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
2022-02-18 18:11:34 +01:00
import org.gcube.application.geoportal.service.engine.providers.PluginManager;
import org.gcube.application.geoportal.service.engine.providers.ProfileMapCache;
2021-12-01 11:13:34 +01:00
import org.gcube.application.geoportal.service.model.internal.faults.DeletionException;
2022-02-01 15:24:39 +01:00
import org.gcube.application.cms.serialization.Serialization;
2022-03-04 18:28:45 +01:00
import org.gcube.application.geoportal.service.model.internal.faults.RegistrationException;
2021-12-07 16:12:43 +01:00
import org.gcube.application.geoportal.service.utils.UserUtils;
2022-01-17 18:19:40 +01:00
import org.gcube.common.storagehub.client.dsl.FolderContainer;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
2021-09-20 16:47:35 +02:00
2021-12-07 11:16:26 +01:00
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
2021-12-01 11:13:34 +01:00
import java.io.IOException;
2022-01-17 18:19:40 +01:00
import java.io.InputStream;
import java.net.URL;
2021-12-07 11:16:26 +01:00
import java.security.InvalidParameterException;
2022-03-10 18:15:10 +01:00
import java.time.LocalDateTime;
2022-02-17 16:01:39 +01:00
import java.util.*;
2021-12-01 11:13:34 +01:00
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Consumer;
2022-02-01 15:24:39 +01:00
import static org.gcube.application.cms.serialization.Serialization.*;
2021-12-01 11:13:34 +01:00
@Slf4j
2022-03-04 14:23:20 +01:00
public class ProfiledMongoManager extends MongoManager implements MongoManagerI<Project>{
2021-12-01 11:13:34 +01:00
2022-01-18 12:01:33 +01:00
@Getter
2022-03-04 14:23:20 +01:00
UseCaseDescriptor useCaseDescriptor;
2022-03-11 16:42:33 +01:00
2021-12-07 16:12:43 +01:00
2022-03-07 17:59:06 +01:00
@Override
protected String mongoIDFieldName() {
return ID;
}
2021-12-07 11:16:26 +01:00
2022-03-04 18:28:45 +01:00
public ProfiledMongoManager(String profileId) throws ConfigurationException, RegistrationException {
2022-03-04 14:23:20 +01:00
// Check UseCaseDescriptor ID
log.info("Loading useCaseDescriptor ID {} ",profileId);
if(profileId==null) throw new InvalidParameterException("UseCaseDescriptor ID cannot be null");
2022-03-04 18:28:45 +01:00
Map<String, UseCaseDescriptor> profiles=ImplementationProvider.get().getEngineByManagedClass(ProfileMapCache.ProfileMap.class);
useCaseDescriptor = ImplementationProvider.get().getEngineByManagedClass(UCDManagerI.class).getById(profileId);
if(useCaseDescriptor == null )
2022-03-04 14:23:20 +01:00
throw new WebApplicationException("UseCaseDescriptor " + profileId + " not registered", Response.Status.NOT_FOUND);
2021-12-07 16:12:43 +01:00
2022-01-14 12:31:11 +01:00
// Connect to DB
2022-03-11 16:42:33 +01:00
init(getToUseCollectionName());
2022-01-14 12:31:11 +01:00
2022-03-11 16:42:33 +01:00
}
2022-03-04 14:23:20 +01:00
2022-03-11 16:42:33 +01:00
private String getToUseCollectionName(){
//TODO collection name in UCD
return useCaseDescriptor.getId();
2021-12-01 11:13:34 +01:00
}
2022-01-17 13:30:21 +01:00
@Getter(lazy = true)
2022-02-14 17:06:32 +01:00
private final LifecycleManager manager=getLCManager();
2021-12-07 16:12:43 +01:00
2022-01-17 13:30:21 +01:00
private LifecycleManager getLCManager() {
try{
LifecycleManager toReturn=null;
2022-03-04 14:23:20 +01:00
//Getting Lifecycle Manager declaration from UseCaseDescriptor
List<HandlerDeclaration> handlerDeclarations= useCaseDescriptor.getHandlersMapByType().get(PluginDescriptor.BaseTypes.LIFECYCLE_MANAGER);
if(handlerDeclarations==null || handlerDeclarations.isEmpty()) throw new ConfigurationException("No Lifecycle Handler defined for useCaseDescriptor ID "+ useCaseDescriptor.getId());
if(handlerDeclarations.size()>1) throw new ConfigurationException("Too many Lifecycle Handlers defined ("+handlerDeclarations+") in useCaseDescriptor ID "+ useCaseDescriptor.getId());
2022-01-17 13:30:21 +01:00
HandlerDeclaration lcHandlerDeclaration=handlerDeclarations.get(0);
// Loading Lifecycle Manager
log.debug("Looking for handler {} ",lcHandlerDeclaration);
2022-02-18 18:11:34 +01:00
toReturn=(LifecycleManager) ImplementationProvider.get().
2022-03-04 18:28:45 +01:00
getEngineByManagedClass(PluginManager.PluginMap.class).get(lcHandlerDeclaration.getId());
2022-01-17 13:30:21 +01:00
if(toReturn==null) throw new ConfigurationException("Unable to find Lifecycle Manager Plugin. ID "+lcHandlerDeclaration.getId());
return toReturn;
} catch(Throwable t){
log.warn("Unable to load LC Manager ",t);
return null;
}
}
2021-12-07 16:12:43 +01:00
2021-12-01 11:13:34 +01:00
@Override
2022-03-04 14:23:20 +01:00
public Project registerNew(Document toRegisterDoc) throws IOException, StepException, EventException {
log.info("Registering new document in {} ", useCaseDescriptor.getId());
2021-12-07 16:42:39 +01:00
log.debug("Going to register {}",toRegisterDoc.toJson());
2022-03-04 14:23:20 +01:00
Project toRegister = new Project();
2021-12-07 11:16:26 +01:00
toRegister.setTheDocument(toRegisterDoc);
2021-12-07 16:42:39 +01:00
PublicationInfo pubInfo=new PublicationInfo();
pubInfo.setCreationInfo(UserUtils.getCurrent().asInfo());
2022-03-04 14:23:20 +01:00
// TODO Set Access From UseCaseDescriptor
2021-12-07 16:42:39 +01:00
Access access=new Access();
access.setLicense("");
access.setPolicy(AccessPolicy.OPEN);
pubInfo.setAccess(access);
toRegister.setInfo(pubInfo);
2021-12-01 11:13:34 +01:00
2022-03-04 14:23:20 +01:00
toRegister.setProfileID(useCaseDescriptor.getId());
toRegister.setProfileVersion(useCaseDescriptor.getVersion());
2022-01-17 18:19:40 +01:00
toRegister.setVersion(new Semver("1.0.0"));
2021-12-01 11:13:34 +01:00
2022-02-14 17:06:32 +01:00
2022-02-17 16:01:39 +01:00
LifecycleInformation draftInfo=new LifecycleInformation().cleanState();
2022-02-15 19:02:44 +01:00
draftInfo.setPhase(LifecycleInformation.DRAFT_PHASE);
2022-02-17 16:01:39 +01:00
draftInfo.setLastOperationStatus(LifecycleInformation.Status.OK);
2022-02-14 17:06:32 +01:00
toRegister.setLifecycleInformation(draftInfo);
2021-12-01 11:13:34 +01:00
2022-02-17 16:01:39 +01:00
// Apply Lifecycle
toRegister = triggerEvent(toRegister,EventExecutionRequest.Events.ON_INIT_DOCUMENT,null);
2021-12-07 16:42:39 +01:00
log.debug("Going to register {} ",toRegister);
2021-12-01 11:13:34 +01:00
2021-12-15 19:10:19 +01:00
// Insert object
2022-03-11 16:42:33 +01:00
ObjectId id =insertDoc(asDocumentWithId(toRegister));
2021-12-07 16:12:43 +01:00
2021-12-07 16:42:39 +01:00
log.info("Obtained id {} ",id);
2021-12-07 16:12:43 +01:00
return getByID(id.toHexString());
2021-12-01 11:13:34 +01:00
}
@Override
2022-03-04 14:23:20 +01:00
public Project update(String id, Document toSet) throws IOException, EventException {
2021-12-01 11:13:34 +01:00
log.trace("Replacing {} ",toSet);
2022-03-04 14:23:20 +01:00
Project toUpdate=getByID(id);
2022-01-17 18:19:40 +01:00
toUpdate.setTheDocument(toSet);
2022-02-17 16:01:39 +01:00
toUpdate.getLifecycleInformation().cleanState();
2022-01-17 18:19:40 +01:00
toUpdate=onUpdate(toUpdate);
2022-03-11 16:42:33 +01:00
Project toReturn =convert(replaceDoc(asDocumentWithId(toUpdate),new ObjectId(id)), Project.class);
2022-03-04 14:23:20 +01:00
log.debug("Updated Project is {}",toReturn);
2022-01-27 15:02:53 +01:00
return toReturn;
2022-01-17 18:19:40 +01:00
}
2022-03-04 14:23:20 +01:00
private Project onUpdate(Project toUpdate) throws EventException {
2022-01-17 18:19:40 +01:00
UserUtils.AuthenticatedUser u = UserUtils.getCurrent();
toUpdate.getInfo().setLastEditInfo(u.asInfo());
toUpdate.setVersion(toUpdate.getVersion().withIncPatch());
2022-02-17 16:01:39 +01:00
return triggerEvent(toUpdate,EventExecutionRequest.Events.ON_INIT_DOCUMENT,null);
2021-12-01 11:13:34 +01:00
}
2022-02-17 16:01:39 +01:00
@Override
2021-12-01 11:13:34 +01:00
public void delete(String id,boolean force) throws DeletionException {
log.debug("Deleting by ID {}, force {}",id,force);
try{
2022-03-04 14:23:20 +01:00
Project doc =getByID(id);
2021-12-01 11:13:34 +01:00
2021-12-07 16:12:43 +01:00
// TODO INVOKE LIFECYCLE
2021-12-01 11:13:34 +01:00
//if(!force&&isPublished(id)) throw new Exception("Cannot delete published documents. Unpublish it or use force = true");
try{
// TODO CHECK PHASE AND STATUS
// DEINDEX
// DEMATERIALIZE
// DELETE CONTENT
// DELETE ENTRY
throw new DeletionException("IMPLEMENT THIS");
// delete(asId(id), getCollectionName());
}catch(DeletionException e) {
//storing updated - partially deleted
// concessione=onUpdate(concessione);
2022-01-27 15:02:53 +01:00
// replace(asDocumentWithId(concessione), collectionName);
2021-12-01 11:13:34 +01:00
throw e;
}
}catch(Throwable t){
throw new DeletionException("Unable to delete "+id,t);
}
}
@Override
2022-03-04 14:23:20 +01:00
public Project getByID(String id) throws WebApplicationException{
2022-03-11 16:42:33 +01:00
Document doc=getDocById(asId(id));
2022-01-17 18:19:40 +01:00
if(doc==null) throw new WebApplicationException("No document with ID "+id);
2022-03-04 14:23:20 +01:00
return convert(doc, Project.class);
2021-12-01 11:13:34 +01:00
}
@Override
2021-12-07 11:16:26 +01:00
public Iterable<Document> query(QueryRequest queryRequest) {
log.info("Querying {} ",queryRequest);
2022-03-04 18:28:45 +01:00
LinkedBlockingQueue queue=new LinkedBlockingQueue<Project>();
2022-03-11 16:42:33 +01:00
queryDoc(queryRequest).forEach(
2021-12-07 11:16:26 +01:00
(Consumer<? super Document>) (Document d)->{try{
queue.put(d);
}catch(Throwable t){log.warn("Unable to translate "+d);}});
log.info("Returned {} elements ",queue.size());
return queue;
}
@Override
2022-03-04 14:23:20 +01:00
public Iterable<Project> filter(QueryRequest queryRequest) {
2021-12-01 11:13:34 +01:00
log.info("Searching concessione for filter {} ",queryRequest);
2022-03-04 18:28:45 +01:00
LinkedBlockingQueue queue=new LinkedBlockingQueue<Project>();
2022-03-11 16:42:33 +01:00
queryDoc(queryRequest).forEach(
2021-12-01 11:13:34 +01:00
(Consumer<? super Document>) (Document d)->{try{
queue.put(d);
}catch(Throwable t){log.warn("Unable to translate "+d);}});
log.info("Returned {} elements ",queue.size());
return queue;
}
@Override
2022-03-04 14:23:20 +01:00
public Project performStep(String id, String step, Document options) throws StepException, JsonProcessingException {
Project document = getByID(id);
2022-02-14 17:06:32 +01:00
try{
2022-02-17 16:01:39 +01:00
document.getLifecycleInformation().cleanState();
document = step(document, step, options);
2022-02-14 17:06:32 +01:00
} catch(Throwable t){
2022-03-04 14:23:20 +01:00
log.error("[UseCaseDescriptor {} ] ERROR Invoking Step {} on document {}" , useCaseDescriptor.getId(),step,id,t);
2022-02-14 17:06:32 +01:00
LifecycleInformation info = new LifecycleInformation();
info.setPhase(document.getLifecycleInformation().getPhase());
info.setLastOperationStatus(LifecycleInformation.Status.ERROR);
info.addErrorMessage(t.getMessage());
info.setLastInvokedStep(step);
document.setLifecycleInformation(info);
}finally{
2022-03-04 14:23:20 +01:00
log.info("Storing {} [UseCaseDescriptor {}] After Step {}, Status : {} " ,id, useCaseDescriptor.getId(),
2022-02-17 16:01:39 +01:00
step,document.getLifecycleInformation().getLastOperationStatus());
log.debug("LifecycleInformation is {} ",document.getLifecycleInformation());
if(log.isTraceEnabled())log.trace("Document is {} ",Serialization.write(document));
2022-03-11 16:42:33 +01:00
return convert(replaceDoc(asDocumentWithId(document),new ObjectId(id)), Project.class);
2022-02-14 17:06:32 +01:00
}
2021-12-01 11:13:34 +01:00
}
2022-01-17 18:19:40 +01:00
/**
* NB Put at path :
*
2022-01-27 15:02:53 +01:00
* Path Examples
* artifact
* images
* images[1]
2022-02-15 19:02:44 +01:00
* layers[?(@.name = 'myName')].fileset
2022-01-27 15:02:53 +01:00
*
2022-01-17 18:19:40 +01:00
*
*
*/
2021-12-01 11:13:34 +01:00
@Override
2022-03-04 14:23:20 +01:00
public Project registerFileSet(String id, RegisterFileSetRequest request) throws ConfigurationException, StorageHubException, StorageException, StepException, JsonProcessingException, DeletionException, EventException {
log.info("Registering Fileset for {} [useCaseDescriptor ID {}], Request is {} ",id, useCaseDescriptor.getId(),request);
2022-01-27 15:02:53 +01:00
2022-02-16 14:54:48 +01:00
List<TempFile> files=request.getStreams();
2022-01-27 15:02:53 +01:00
Document attributes =request.getAttributes();
2022-03-04 14:23:20 +01:00
Project doc=getByID(id);
2022-02-17 16:01:39 +01:00
doc.getLifecycleInformation().cleanState();
doc.getLifecycleInformation().setLastOperationStatus(LifecycleInformation.Status.OK);
2022-01-17 18:19:40 +01:00
WorkspaceManager ws=new WorkspaceManager();
2022-03-04 18:28:45 +01:00
StorageUtils storage=ImplementationProvider.get().getEngineByManagedClass(StorageUtils.class);
2022-01-17 18:19:40 +01:00
2022-03-04 14:23:20 +01:00
log.debug("Checking field {} definition in {}",request.getFieldDefinitionPath(), useCaseDescriptor.getId());
Field fieldDefinition=getFieldDefinition(useCaseDescriptor,request.getFieldDefinitionPath());
2022-02-15 19:02:44 +01:00
2022-01-17 18:19:40 +01:00
JSONPathWrapper docWrapper=new JSONPathWrapper(doc.getTheDocument().toJson());
2022-02-01 15:24:39 +01:00
2022-02-16 14:54:48 +01:00
List<String> matchingPaths = docWrapper.getMatchingPaths(request.getParentPath());
if(matchingPaths.size()>1) throw new WebApplicationException("Multiple Destination matching parent path "+request.getParentPath(),Response.Status.BAD_REQUEST);
if(matchingPaths.isEmpty()) throw new WebApplicationException("PArent path not found at "+request.getParentPath(),Response.Status.BAD_REQUEST);
2022-02-15 19:02:44 +01:00
2022-02-16 14:54:48 +01:00
String parentMatchingPath = matchingPaths.get(0);
2022-03-04 11:30:48 +01:00
List<Object> foundElementsByMatchingPaths = docWrapper.getByPath(parentMatchingPath);
if(foundElementsByMatchingPaths == null || foundElementsByMatchingPaths.isEmpty())
throw new WebApplicationException("No element found at "+ parentMatchingPath,Response.Status.BAD_REQUEST);
Document parent = Serialization.asDocument(foundElementsByMatchingPaths.get(0));
2022-01-17 18:19:40 +01:00
2022-02-16 14:54:48 +01:00
// PREPARE REGISTERED FS
2022-01-17 18:19:40 +01:00
2022-02-16 14:54:48 +01:00
// MANAGE CLASH
2022-01-27 15:02:53 +01:00
switch (request.getClashOption()){
case REPLACE_EXISTING: {
2022-02-16 14:54:48 +01:00
if(fieldDefinition.isCollection())
throw new WebApplicationException("Cannot replace repeatable field "+request.getFieldDefinitionPath()+".",Response.Status.BAD_REQUEST);
// DELETE EXISTING AND PUT
RegisteredFileSet toDelete = Serialization.convert(parent.get(request.getFieldName()),RegisteredFileSet.class);
if(!(toDelete == null)&&!(toDelete.isEmpty()))
deleteFileSetRoutine(toDelete,false,ws);
2022-03-04 14:23:20 +01:00
RegisteredFileSet fs = prepareRegisteredFileSet(doc.getInfo(),doc.getId(), useCaseDescriptor.getId(), request.getAttributes(),files,storage,ws);
log.debug("Registered Fileset for [ID {} useCaseDescriptor {}] is {} ",fs,doc.getId(),doc.getProfileID());
2022-02-16 14:54:48 +01:00
docWrapper.putElement(parentMatchingPath,request.getFieldName(),fs);
break;}
case MERGE_EXISTING: {
if(fieldDefinition.isCollection())
throw new WebApplicationException("Cannot merge repeatable field "+request.getFieldDefinitionPath()+".",Response.Status.BAD_REQUEST);
RegisteredFileSet original = Serialization.convert(parent.get(request.getFieldName()),RegisteredFileSet.class);
// MERGE ATTRIBUTES AND PUT
Document toUseAttributes=request.getAttributes();
if(original!=null) toUseAttributes.putAll(original);
2022-03-04 14:23:20 +01:00
RegisteredFileSet fs = prepareRegisteredFileSet(doc.getInfo(),doc.getId(), useCaseDescriptor.getId(), toUseAttributes,files,storage,ws);
log.debug("Registered Fileset for [ID {} useCaseDescriptor {}] is {} ",fs,doc.getId(),doc.getProfileID());
2022-02-16 14:54:48 +01:00
docWrapper.putElement(parentMatchingPath,request.getFieldName(),fs);
break;}
case APPEND: {
2022-01-27 15:02:53 +01:00
if(!fieldDefinition.isCollection())
2022-02-16 14:54:48 +01:00
throw new WebApplicationException("Cannot add to single field "+request.getFieldDefinitionPath()+".",Response.Status.BAD_REQUEST);
2022-03-04 14:23:20 +01:00
RegisteredFileSet fs = prepareRegisteredFileSet(doc.getInfo(),doc.getId(), useCaseDescriptor.getId(), request.getAttributes(),files,storage,ws);
log.debug("Registered Fileset for [ID {} useCaseDescriptor {}] is {} ",fs,doc.getId(),doc.getProfileID());
2022-01-27 15:02:53 +01:00
2022-02-16 14:54:48 +01:00
docWrapper.addElementToArray(String.format("%1ds['%2$s']",parentMatchingPath,request.getFieldName()),fs);
break;}
default: {throw new WebApplicationException("Unexpected clash policy "+request.getClashOption(),Response.Status.BAD_REQUEST);}
}
2022-01-27 15:02:53 +01:00
2022-01-17 18:19:40 +01:00
log.debug("Setting result on profiled document");
2022-02-15 19:02:44 +01:00
doc.setTheDocument(Document.parse(docWrapper.getValueCTX().jsonString()));
2022-01-17 18:19:40 +01:00
doc=onUpdate(doc);
2022-03-11 16:42:33 +01:00
return convert(replaceDoc(asDocumentWithId(doc),new ObjectId(id)), Project.class);
2021-12-01 11:13:34 +01:00
}
2021-12-15 19:10:19 +01:00
2022-01-18 12:01:33 +01:00
@Override
2022-03-04 14:23:20 +01:00
public Project deleteFileSet(String id, String path, Boolean force) throws ConfigurationException, StorageHubException, JsonProcessingException, DeletionException, EventException {
log.info("Deleting Fileset for {} [useCaseDescriptor ID {}], at {} [force {} ]",id, useCaseDescriptor.getId(),path,force);
2022-02-16 14:54:48 +01:00
2022-03-04 14:23:20 +01:00
Project doc = getByID(id);
2022-02-17 16:01:39 +01:00
doc.getLifecycleInformation().cleanState();
doc.getLifecycleInformation().cleanState().setLastOperationStatus(LifecycleInformation.Status.OK);
2022-02-16 14:54:48 +01:00
JSONPathWrapper wrapper = new JSONPathWrapper(doc.getTheDocument().toJson());
List<String> matchingPaths=wrapper.getMatchingPaths(path);
if(matchingPaths.isEmpty()) throw new WebApplicationException("No Registered FileSet found at "+path,Response.Status.BAD_REQUEST);
if(matchingPaths.size()>1) throw new WebApplicationException("Multiple Fileset ("+matchingPaths.size()+") matching "+path,Response.Status.BAD_REQUEST);
RegisteredFileSet fs = Serialization.convert(wrapper.getByPath(path),RegisteredFileSet.class);
log.debug("Going to delete {}",fs);
deleteFileSetRoutine(fs,force,new WorkspaceManager());
log.debug("Removing FS from document [ID : ] by path {}",id,path);
wrapper.setElement(path,null);
2022-02-01 15:24:39 +01:00
doc=onUpdate(doc);
2022-03-11 16:42:33 +01:00
return convert(replaceDoc(asDocumentWithId(doc),new ObjectId(id)), Project.class);
2022-01-18 12:01:33 +01:00
}
2022-01-17 18:19:40 +01:00
2022-02-04 17:45:47 +01:00
@Override
public Configuration getConfiguration() throws ConfigurationException {
2022-03-04 14:23:20 +01:00
log.debug("Asking configuration for {} in {} ", useCaseDescriptor.getId(), UserUtils.getCurrent().getContext());
2022-03-10 18:15:10 +01:00
Configuration toReturn= new Configuration();
List<Archive> archives = new ArrayList<>();
2022-03-11 18:11:32 +01:00
List<Index> indexes=new ArrayList<>();
2022-03-10 18:15:10 +01:00
// Set Basic Info
toReturn.setArchives(archives);
toReturn.setProfileId(this.getUseCaseDescriptor().getId());
toReturn.setContext(ContextUtils.getCurrentScope());
toReturn.setLastUpdatedTime(LocalDateTime.now());
// Add Mongo Info
Archive mongoArchive = new Archive("DOCUMENT-STORE-COLLECTION");
2022-03-11 16:42:33 +01:00
MongoCollection coll=getCollection();
2022-03-10 18:15:10 +01:00
mongoArchive.put("count",coll.count());
2022-03-11 16:42:33 +01:00
mongoArchive.put("collection_name",getToUseCollectionName());
2022-03-10 18:15:10 +01:00
archives.add(mongoArchive);
2022-03-11 18:11:32 +01:00
// TODO ADD TEXT INDEXES
2022-03-10 18:15:10 +01:00
// Set WS Info
try {
archives.add(new WorkspaceManager().getConfiguration());
}catch (StorageHubException e) {
throw new ConfigurationException("Unable to get WS Configuration",e);
}
2022-03-11 18:11:32 +01:00
// ADD LC Infos
AccountingInfo user = UserUtils.getCurrent().asInfo();
Configuration lcConfig = getLCManager().getCurrentConfiguration(new BaseRequest(useCaseDescriptor,user.getUser(),user.getContext()));
if(lcConfig.getArchives()!=null)
archives.addAll(lcConfig.getArchives());
if(lcConfig.getIndexes()!=null)
indexes.addAll(lcConfig.getIndexes());
2022-02-04 17:45:47 +01:00
log.debug("Returning current configuration {}",toReturn);
return toReturn;
}
2022-01-17 18:19:40 +01:00
2022-03-04 14:23:20 +01:00
private Project step(Project theDocument, String step, Document callParameters){
2022-02-17 16:01:39 +01:00
try{
2022-03-04 14:23:20 +01:00
log.info("[UseCaseDescriptor {}] Invoking Step {} on {}" , useCaseDescriptor.getId(),step,getManager().getDescriptor());
2022-02-14 17:06:32 +01:00
AccountingInfo user= UserUtils.getCurrent().asInfo();
2022-03-11 18:11:32 +01:00
StepExecutionRequest request=new StepExecutionRequest(useCaseDescriptor,user.getUser(),user.getContext(),theDocument,step);
2022-02-14 17:06:32 +01:00
2022-02-16 17:12:54 +01:00
log.debug("Requesting Step Execution {}",request);
2022-02-17 16:01:39 +01:00
StepExecutionReport report= getManager().performStep(request);
2022-03-04 14:23:20 +01:00
Project toReturn = report.prepareResult();
2022-02-17 16:01:39 +01:00
// EVENTS
if(report.getToTriggerEvents()!=null) {
Iterator<EventExecutionRequest> 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());
}
}
2022-02-14 17:06:32 +01:00
2022-02-17 16:01:39 +01:00
// STEPS
if(report.getCascadeSteps()!=null) {
Iterator<StepExecutionRequest> 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;
}
2021-12-15 19:10:19 +01:00
}
2022-01-17 18:19:40 +01:00
2022-03-04 14:23:20 +01:00
private Project triggerEvent(Project theDocument, String event, Document parameters) {
2022-02-17 16:01:39 +01:00
try{
2022-03-04 14:23:20 +01:00
log.info("[UseCaseDescriptor {}] triggering event {} on {}" , useCaseDescriptor.getId(),event,getManager().getDescriptor());
2022-03-11 18:11:32 +01:00
AccountingInfo user= UserUtils.getCurrent().asInfo();
EventExecutionRequest request= new EventExecutionRequest(useCaseDescriptor,user.getUser(),user.getContext(),theDocument,event);
2022-02-16 17:12:54 +01:00
log.debug("Triggering {}",request);
2022-02-17 16:01:39 +01:00
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;
}
2022-02-14 17:06:32 +01:00
}
2022-01-17 18:19:40 +01:00
2022-02-16 14:54:48 +01:00
private static final RegisteredFileSet prepareRegisteredFileSet(PublicationInfo defaultPublicationInfo,String docID, String profileID,
2022-01-17 18:19:40 +01:00
Document attributes,List<TempFile> files, StorageUtils storage,WorkspaceManager ws) throws StorageHubException, StorageException {
log.debug("Preparing Registered FileSet..");
2022-02-01 15:24:39 +01:00
RegisteredFileSet toReturn = new RegisteredFileSet();
if(attributes!=null) toReturn.putAll(attributes);
2022-02-16 14:54:48 +01:00
String uuid = UUID.randomUUID().toString();
toReturn.putIfAbsent(RegisteredFileSet.UUID, uuid);
toReturn.putIfAbsent(RegisteredFileSet.CREATION_INFO,UserUtils.getCurrent().asInfo());
toReturn.putIfAbsent(RegisteredFileSet.ACCESS,defaultPublicationInfo.getAccess());
// FOLDER
String folderID=toReturn.getFolderId();
log.trace("Folder ID is {} ",folderID);
FolderContainer sectionFolder=null;
if(folderID==null || folderID.isEmpty()) {
FolderContainer base = ws.createFolder(new WorkspaceManager.FolderOptions(
2022-03-04 14:23:20 +01:00
docID, "Base Folder for profiled document. UseCaseDescriptor " + profileID, null));
2022-02-16 14:54:48 +01:00
sectionFolder = ws.createFolder(new WorkspaceManager.FolderOptions(
docID + "_" + uuid, "Registered Fileset uuid " + uuid, base));
toReturn.put(RegisteredFileSet.FOLDER_ID, sectionFolder.getId());
}else {
sectionFolder = ws.getFolderById(folderID);
}
2022-01-17 18:19:40 +01:00
ArrayList<RegisteredFile> registeredFiles=new ArrayList<>();
2022-02-16 14:54:48 +01:00
if(toReturn.containsKey(RegisteredFileSet.PAYLOADS))
registeredFiles.addAll(toReturn.getPayloads());
2022-01-17 18:19:40 +01:00
for (TempFile f : files) {
InputStream is=null;
try{
log.debug("Opening temp file {}",f);
String fileUrl=storage.getURL(f.getId());
log.debug("Got URL {} from ID {}",fileUrl,f.getId());
is=new URL(fileUrl).openStream();
RegisteredFile registered=ws.registerFile(new WorkspaceManager.FileOptions(f.getFilename(),is,
"Imported via gcube CMS service ", sectionFolder));
log.debug("Registered "+registered);
registeredFiles.add(registered);
}catch(StorageHubException | IOException e){
throw new StorageException("Unable to store "+f,e);
}finally{
if(is!=null)
IOUtils.closeQuietly(is);
}
}
2022-02-01 15:24:39 +01:00
toReturn.put(RegisteredFileSet.PAYLOADS,registeredFiles);
2022-02-16 14:54:48 +01:00
// TODO MERGE
//toReturn.remove(RegisteredFileSet.MATERIALIZATIONS);
2022-02-01 15:24:39 +01:00
return toReturn;
2022-01-17 18:19:40 +01:00
}
2022-01-31 13:09:54 +01:00
2022-02-16 14:54:48 +01:00
private static void deleteFileSetRoutine(RegisteredFileSet fs, Boolean force, WorkspaceManager ws) throws DeletionException, StorageHubException {
log.debug("Deleting Registered FS {}");
if(fs.getMaterializations()!=null && !fs.getMaterializations().isEmpty()){
if(!force) throw new DeletionException("Fileset (uuid "+fs.getUUID()+") already materialized. Use force = true");
2022-01-31 13:09:54 +01:00
else throw new RuntimeException("Implement this");
// TODO manager force deletion
// NB handlers for materialization types
}
2022-02-16 14:54:48 +01:00
log.trace("FileSet ID {} : deleting ws folder {}",fs.getUUID(),fs.getFolderId());
if(fs.getPayloads()!=null)
ws.deleteItem(fs.getFolderId());
}
2022-03-04 14:23:20 +01:00
private static Field getFieldDefinition(UseCaseDescriptor useCaseDescriptor, String fieldPath)throws WebApplicationException{
JSONPathWrapper schemaWrapper= new JSONPathWrapper(useCaseDescriptor.getSchema().toJson());
2022-02-16 14:54:48 +01:00
List<Field> fieldDefinitions=schemaWrapper.getByPath(fieldPath,Field.class);
if(fieldDefinitions==null || fieldDefinitions.isEmpty())
2022-03-04 14:23:20 +01:00
throw new WebApplicationException("No Field found in schema "+ useCaseDescriptor.getId()+" at "+fieldPath, Response.Status.BAD_REQUEST);
2022-02-16 14:54:48 +01:00
if(fieldDefinitions.size()>1)
2022-03-04 14:23:20 +01:00
throw new WebApplicationException("Multiple field definitions ("+fieldDefinitions.size()+") found in "+ useCaseDescriptor.getId()+" for "+fieldPath,Response.Status.BAD_REQUEST);
2022-02-16 14:54:48 +01:00
Field fieldDefinition=Serialization.convert(fieldDefinitions.get(0),Field.class);
if(fieldDefinition==null)
2022-03-04 14:23:20 +01:00
throw new WebApplicationException("Found field is null ["+ useCaseDescriptor.getId()+" for "+fieldPath+"]",Response.Status.BAD_REQUEST);
2022-02-16 14:54:48 +01:00
log.trace("Field definition is {}",fieldDefinition);
return fieldDefinition;
2022-01-31 13:09:54 +01:00
}
2021-09-20 16:47:35 +02:00
}