diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/RegisterFileSetRequest.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/RegisterFileSetRequest.java index 4fbd5eb..dde48c1 100644 --- a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/RegisterFileSetRequest.java +++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/RegisterFileSetRequest.java @@ -25,8 +25,9 @@ public class RegisterFileSetRequest { REPLACE_EXISTING,MERGE_EXISTING, APPEND } - private String fieldPath; - private String destinationPath; + private String fieldDefinitionPath; + private String parentPath; + private String fieldName; private List streams; private Document attributes; 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 a45177d..78cd8f0 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 @@ -1,6 +1,7 @@ package org.gcube.application.geoportal.service.engine.mongo; import com.fasterxml.jackson.core.JsonProcessingException; +import com.jayway.jsonpath.JsonPath; import com.mongodb.client.MongoDatabase; import com.vdurmont.semver4j.Semver; import lombok.Getter; @@ -284,81 +285,67 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< */ @Override public ProfiledDocument registerFileSet(String id,RegisterFileSetRequest request) throws ConfigurationException, StorageHubException, StorageException, StepException, JsonProcessingException, DeletionException, EventException { + log.info("Registering Fileset for {} [profile ID {}], Request is {} ",id,profile.getId(),request); + List files=request.getStreams(); - Document attributes =request.getAttributes(); - - log.info("Registering Fileset for {}, Request is {} ",id,request); - ProfiledDocument doc=getByID(id); WorkspaceManager ws=new WorkspaceManager(); StorageUtils storage=ImplementationProvider.get().getStorageProvider().getObject(); - log.debug("Checking {}  path against profile {}",request.getFieldPath(),profile.getId()); - JSONPathWrapper schemaWrapper= new JSONPathWrapper(profile.getSchema().toJson()); + log.debug("Checking field {} definition in {}",request.getFieldDefinitionPath(),profile.getId()); + Field fieldDefinition=getFieldDefinition(profile,request.getFieldDefinitionPath()); - List fieldDefinitions=schemaWrapper.getByPath(request.getFieldPath(),Field.class); - if(fieldDefinitions==null || fieldDefinitions.isEmpty()) - throw new WebApplicationException("No Field found in schema "+profile.getId()+" at "+request.getFieldPath(), Response.Status.BAD_REQUEST); - if(fieldDefinitions.size()>1) - throw new WebApplicationException("Multiple field definitions ("+fieldDefinitions.size()+") found in "+profile.getId()+" for "+request.getFieldPath(),Response.Status.BAD_REQUEST); - Field fieldDefinition=Serialization.convert(fieldDefinitions.get(0),Field.class); - if(fieldDefinition==null) - throw new WebApplicationException("Found field is null ["+profile.getId()+" for "+request.getFieldPath()+"]",Response.Status.BAD_REQUEST); - - log.debug("Field definition is {}",fieldDefinition); JSONPathWrapper docWrapper=new JSONPathWrapper(doc.getTheDocument().toJson()); - List matchingPaths = docWrapper.getMatchingPaths(request.getDestinationPath()); - if(matchingPaths.size()>1&&!request.getClashOption().equals(RegisterFileSetRequest.ClashOptions.APPEND)) - System.out.println(); + List 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); + + String parentMatchingPath = matchingPaths.get(0); + Document parent = Serialization.asDocument(docWrapper.getByPath(parentMatchingPath).get(0)); + // PREPARE REGISTERED FS - List found=docWrapper.getByPath(request.getDestinationPath(),RegisteredFileSet.class); - - - Object toSet=null; - Document toSetAttributes=attributes; - - // Manage clash options - - if(!found.isEmpty()) + // MANAGE CLASH switch (request.getClashOption()){ case REPLACE_EXISTING: { - if(found.size()>1) - throw new WebApplicationException("Cannot replace multiple items at "+request.getDestinationPath()+".",Response.Status.BAD_REQUEST); - deleteFileSetRoutine(doc,request.getDestinationPath(),false,ws); - break; - }case MERGE_EXISTING: { - if(found.size()>1) - throw new WebApplicationException("Cannot merge multiple items at "+request.getDestinationPath()+".",Response.Status.BAD_REQUEST); - toSetAttributes=Serialization.asDocument(found.get(0)); - if(attributes!=null) toSetAttributes.putAll(attributes); - deleteFileSetRoutine(doc,request.getDestinationPath(),false,ws); - break; - }case APPEND: { + 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); + + RegisteredFileSet fs = prepareRegisteredFileSet(doc.getInfo(),doc.get_id(),profile.getId(), request.getAttributes(),files,storage,ws); + log.debug("Registered Fileset for [ID {} profile {}] is {} ",fs,doc.get_id(),doc.getProfileID()); + 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); + RegisteredFileSet fs = prepareRegisteredFileSet(doc.getInfo(),doc.get_id(),profile.getId(), toUseAttributes,files,storage,ws); + log.debug("Registered Fileset for [ID {} profile {}] is {} ",fs,doc.get_id(),doc.getProfileID()); + docWrapper.putElement(parentMatchingPath,request.getFieldName(),fs); + break;} + case APPEND: { if(!fieldDefinition.isCollection()) - throw new WebApplicationException("Cannot append to "+request.getDestinationPath()+" : field "+request.getFieldPath()+" is not collection.", - Response.Status.BAD_REQUEST); - break; - } + throw new WebApplicationException("Cannot add to single field "+request.getFieldDefinitionPath()+".",Response.Status.BAD_REQUEST); + RegisteredFileSet fs = prepareRegisteredFileSet(doc.getInfo(),doc.get_id(),profile.getId(), request.getAttributes(),files,storage,ws); + log.debug("Registered Fileset for [ID {} profile {}] is {} ",fs,doc.get_id(),doc.getProfileID()); + + 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);} } - // Actually register Files - RegisteredFileSet registeredFileSet = prepareRegisteredFileSet(doc,profile,request.getDestinationPath(), - toSetAttributes,files,storage,ws); - if(fieldDefinition.isCollection()&&(request.getClashOption().equals(RegisterFileSetRequest.ClashOptions.APPEND))){ - List actualList= found.isEmpty()?new ArrayList<>():(List)found.get(0); - actualList.add(registeredFileSet); - toSet=actualList; - }else toSet = registeredFileSet; - - - docWrapper.set(request.getDestinationPath(),toSet); - log.debug("Setting result on profiled document"); doc.setTheDocument(Document.parse(docWrapper.getValueCTX().jsonString())); @@ -368,9 +355,19 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< } @Override - public ProfiledDocument deleteFileSet(String id, String destination, Boolean force) throws ConfigurationException, StorageHubException, JsonProcessingException, DeletionException, EventException { + public ProfiledDocument deleteFileSet(String id, String path, Boolean force) throws ConfigurationException, StorageHubException, JsonProcessingException, DeletionException, EventException { + log.info("Deleting Fileset for {} [profile ID {}], at {} [force {} ]",id,profile.getId(),path,force); + ProfiledDocument doc = getByID(id); - doc=deleteFileSetRoutine(doc,destination,force,new WorkspaceManager()); + 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); + 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); doc=onUpdate(doc); return convert(replace(asDocumentWithId(doc),new ObjectId(id),getCollectionName()),ProfiledDocument.class); } @@ -415,24 +412,35 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< } - private static final RegisteredFileSet prepareRegisteredFileSet(ProfiledDocument doc, Profile profile,String destination, + private static final RegisteredFileSet prepareRegisteredFileSet(PublicationInfo defaultPublicationInfo,String docID, String profileID, Document attributes,List files, StorageUtils storage,WorkspaceManager ws) throws StorageHubException, StorageException { log.debug("Preparing Registered FileSet.."); RegisteredFileSet toReturn = new RegisteredFileSet(); if(attributes!=null) toReturn.putAll(attributes); - toReturn.put(RegisteredFileSet.UUID, UUID.randomUUID().toString()); - toReturn.put(RegisteredFileSet.CREATION_INFO,UserUtils.getCurrent().asInfo()); - toReturn.putIfAbsent(RegisteredFileSet.ACCESS,doc.getInfo().getAccess()); - FolderContainer base=ws.createFolder(new WorkspaceManager.FolderOptions( - doc.get_id(),"Base Folder for profiled document. Profile "+profile.getId(),null)); + String uuid = UUID.randomUUID().toString(); + toReturn.putIfAbsent(RegisteredFileSet.UUID, uuid); + toReturn.putIfAbsent(RegisteredFileSet.CREATION_INFO,UserUtils.getCurrent().asInfo()); + toReturn.putIfAbsent(RegisteredFileSet.ACCESS,defaultPublicationInfo.getAccess()); - FolderContainer sectionFolder=ws.createFolder(new WorkspaceManager.FolderOptions( - doc.get_id()+destination,"Registered Fileset at path "+destination,base)); - - toReturn.put(RegisteredFileSet.FOLDER_ID,sectionFolder.getId()); + // 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( + docID, "Base Folder for profiled document. Profile " + profileID, null)); + 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); + } ArrayList registeredFiles=new ArrayList<>(); + if(toReturn.containsKey(RegisteredFileSet.PAYLOADS)) + registeredFiles.addAll(toReturn.getPayloads()); + for (TempFile f : files) { InputStream is=null; try{ @@ -452,25 +460,37 @@ public class ProfiledMongoManager extends MongoManager implements MongoManagerI< } } toReturn.put(RegisteredFileSet.PAYLOADS,registeredFiles); - toReturn.remove(RegisteredFileSet.MATERIALIZATIONS); + // TODO MERGE + //toReturn.remove(RegisteredFileSet.MATERIALIZATIONS); return toReturn; } - private static ProfiledDocument deleteFileSetRoutine(ProfiledDocument doc,String fileSetPath, Boolean force, WorkspaceManager ws) throws DeletionException, StorageHubException { - log.info("Document ID {} : deleting fileset at {} [force : {}]",doc.get_id(),fileSetPath,force); - JSONPathWrapper wrapper =new JSONPathWrapper(doc.getTheDocument().toJson()); - RegisteredFileSet toDelete = Serialization.convert(wrapper.getByPath(fileSetPath).get(0),RegisteredFileSet.class); - if(toDelete.getMaterializations()!=null && !toDelete.getMaterializations().isEmpty()){ - if(!force) throw new DeletionException("Fileset (Document ID "+doc.get_id()+", path "+fileSetPath+") already materialized. Use force = true"); + 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"); else throw new RuntimeException("Implement this"); // TODO manager force deletion // NB handlers for materialization types } - log.debug("Document ID {} : deleting ws folder {}",doc.get_id(),toDelete.getFolderId()); - if(toDelete.getPayloads()!=null) - ws.deleteItem(toDelete.getFolderId()); - doc.setTheDocument(Document.parse(wrapper.set(fileSetPath,null).getValueCTX().jsonString())); - return doc; + log.trace("FileSet ID {} : deleting ws folder {}",fs.getUUID(),fs.getFolderId()); + if(fs.getPayloads()!=null) + ws.deleteItem(fs.getFolderId()); + } + + + private static Field getFieldDefinition(Profile profile,String fieldPath)throws WebApplicationException{ + JSONPathWrapper schemaWrapper= new JSONPathWrapper(profile.getSchema().toJson()); + List fieldDefinitions=schemaWrapper.getByPath(fieldPath,Field.class); + if(fieldDefinitions==null || fieldDefinitions.isEmpty()) + throw new WebApplicationException("No Field found in schema "+profile.getId()+" at "+fieldPath, Response.Status.BAD_REQUEST); + if(fieldDefinitions.size()>1) + throw new WebApplicationException("Multiple field definitions ("+fieldDefinitions.size()+") found in "+profile.getId()+" for "+fieldPath,Response.Status.BAD_REQUEST); + Field fieldDefinition=Serialization.convert(fieldDefinitions.get(0),Field.class); + if(fieldDefinition==null) + throw new WebApplicationException("Found field is null ["+profile.getId()+" for "+fieldPath+"]",Response.Status.BAD_REQUEST); + log.trace("Field definition is {}",fieldDefinition); + return fieldDefinition; } }