package org.gcube.application.geoportal.service.rest; import com.webcohesion.enunciate.metadata.rs.RequestHeader; import com.webcohesion.enunciate.metadata.rs.RequestHeaders; import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.gcube.application.cms.implementations.ImplementationProvider; import org.gcube.application.geoportal.common.model.document.Project; import org.gcube.application.geoportal.common.model.configuration.Configuration; import org.gcube.application.geoportal.common.model.document.access.Access; 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.rest.QueryRequest; import org.gcube.application.geoportal.common.rest.InterfaceConstants; import org.gcube.application.geoportal.common.model.rest.RegisterFileSetRequest; import org.gcube.application.geoportal.common.model.rest.StepExecutionRequest; import org.gcube.application.geoportal.service.engine.mongo.ProfiledMongoManager; import org.gcube.application.geoportal.common.model.rest.ConfigurationException; import org.gcube.application.cms.serialization.Serialization; import org.gcube.application.geoportal.service.engine.providers.ConfigurationCache; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import java.util.ArrayList; import java.util.List; @Path(InterfaceConstants.Methods.PROJECTS+"/{"+InterfaceConstants.Parameters.UCID +"}") @Slf4j @RequestHeaders({ @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), @RequestHeader( name = "Content-Type", description = "application/json") }) public class ProfiledDocuments { private ProfiledMongoManager manager; public ProfiledDocuments(@PathParam(InterfaceConstants.Parameters.UCID) String profileID) throws ConfigurationException { log.info("Accessing profile "+profileID); manager=new GuardedMethod(){ @Override protected ProfiledMongoManager run() throws Exception { return new ProfiledMongoManager(profileID); } }.execute().getResult(); } @GET @Path(InterfaceConstants.Methods.CONFIGURATION_PATH) @Produces(MediaType.APPLICATION_JSON) public Configuration getConfiguration(@PathParam(InterfaceConstants.Parameters.UCID) String profileID){ return new GuardedMethod(){ @Override protected Configuration run() throws Exception, WebApplicationException { return ImplementationProvider.get().getProvidedObjectByClass(ConfigurationCache.ConfigurationMap.class).get(profileID); } }.execute().getResult(); } @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Project createNew(Document d) { return new GuardedMethod() { @Override protected Project run() throws Exception, WebApplicationException { log.info("Creating new Project ({})",manager.getUseCaseDescriptor().getId()); Project toReturn= manager.registerNew(d); log.info("Created new Project ({}, ID {})",manager.getUseCaseDescriptor().getId(),toReturn.getId()); return toReturn; } }.execute().getResult(); } @PUT @Path("{"+InterfaceConstants.Parameters.PROJECT_ID+"}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Project update(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String documentId, Document d) { return new GuardedMethod() { @Override protected Project run() throws Exception, WebApplicationException { log.info("Updating Project ({}, ID {})",manager.getUseCaseDescriptor().getId(),documentId); return manager.update(documentId,d); } }.execute().getResult(); } @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("{"+InterfaceConstants.Parameters.PROJECT_ID+"}") public Boolean delete(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id, @DefaultValue("false") @QueryParam(InterfaceConstants.Parameters.FORCE) Boolean force) { return new GuardedMethod() { @Override protected Boolean run() throws Exception, WebApplicationException { log.info("Deleting Project ({}, ID {}). Force is {}",manager.getUseCaseDescriptor().getId(),id,force); manager.delete(id,force); return true; } }.execute().getResult(); } @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/"+InterfaceConstants.Methods.REGISTER_FILES_PATH+"/{"+InterfaceConstants.Parameters.PROJECT_ID+"}") public Project registerFileSet(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id, RegisterFileSetRequest request) { return new GuardedMethod() { @Override protected Project run() throws Exception, WebApplicationException { log.info("UCD {} : Project {} Registering Fileset. Request is {}", manager.getUseCaseDescriptor().getId(), id,request); request.validate(); return manager.registerFileSet(id,request); } }.execute().getResult(); } @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/"+InterfaceConstants.Methods.DELETE_FILES_PATH+"/{"+InterfaceConstants.Parameters.PROJECT_ID+"}") public Project deleteFileSet( @PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id, @DefaultValue("false") @QueryParam(InterfaceConstants.Parameters.FORCE) Boolean force, String path) { return new GuardedMethod() { @Override protected Project run() throws Exception, WebApplicationException { log.info("Deleting FileSet of Project ({}, ID {}) at path {}. Force is {}", manager.getUseCaseDescriptor().getId(), id,path,force); return manager.deleteFileSet(id,path,force); } }.execute().getResult(); } @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/"+InterfaceConstants.Methods.STEP+"/{"+InterfaceConstants.Parameters.PROJECT_ID+"}") public Project performStep( @PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id, StepExecutionRequest request) { return new GuardedMethod() { @Override protected Project run() throws Exception, WebApplicationException { log.info("Executing step {} on Project ({},ID,{}) with options {}", request.getStepID(), manager.getUseCaseDescriptor().getId(), id,request.getOptions()); return manager.performStep(id,request.getStepID(),request.getOptions()); } }.execute().getResult(); } @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/"+InterfaceConstants.Methods.FORCE_UNLOCK+"/{"+InterfaceConstants.Parameters.PROJECT_ID+"}") public Project forceUnlock( @PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id){ return new GuardedMethod(){ @Override protected Project run() throws Exception, WebApplicationException { log.warn("UCD {}, forcing unlock for Project ID {}",manager.getUseCaseDescriptor().getId(),id); return manager.forceUnlock(id); } }.execute().getResult(); } @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/"+InterfaceConstants.Methods.SET_PROJECT_ACCESS_POLICY+"/{"+InterfaceConstants.Parameters.PROJECT_ID+"}") public Project setAccessPolicy( @PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id, Access toSet){ return new GuardedMethod(){ @Override protected Project run() throws Exception, WebApplicationException { log.warn("UCD {}, setting Policy {} Project ID {}",manager.getUseCaseDescriptor().getId(),toSet,id); return manager.setAccessPolicy(id,toSet); } }.execute().getResult(); } //********************************** READ @GET @Produces(MediaType.APPLICATION_JSON) public Iterable list() { return new GuardedMethod>() { protected Iterable run() throws Exception ,WebApplicationException { return manager.query(new QueryRequest()); }; }.execute().getResult(); } // BY ID @GET @Produces(MediaType.APPLICATION_JSON) @Path("{"+InterfaceConstants.Parameters.PROJECT_ID+"}") public Project getById(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id) { return new GuardedMethod() { @Override protected Project run() throws Exception, WebApplicationException { return manager.getByID(id); } }.execute().getResult(); } @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/"+InterfaceConstants.Methods.SEARCH_PATH) public String search(String filter){ return new GuardedMethod() { @Override protected String run() throws Exception, WebApplicationException { QueryRequest req=new QueryRequest(); req.setFilter(Document.parse(filter)); return Serialization.write(manager.query(req)); } }.execute().getResult(); } @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/"+InterfaceConstants.Methods.QUERY_PATH) public Iterable query(String queryString){ return new GuardedMethod>() { @Override protected Iterable run() throws Exception, WebApplicationException { return manager.query(Serialization.parseQuery(queryString)); } }.execute().getResult(); } // Relationships @GET @Produces(MediaType.APPLICATION_JSON) @Path("{"+InterfaceConstants.Methods.RELATIONSHIP+"}/{"+InterfaceConstants.Parameters.PROJECT_ID+"}" + "/{"+InterfaceConstants.Parameters.RELATIONSHIP_ID+"}") public String getRelationshipChain(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id, @PathParam(InterfaceConstants.Parameters.RELATIONSHIP_ID) String relationshipId, @DefaultValue("false") @QueryParam(InterfaceConstants.Parameters.DEEP) Boolean deep) { return new GuardedMethod(){ @Override protected String run() throws Exception, WebApplicationException { // recursive log.info("UCD {} : Getting Relationships List for {} [rel : {}, recurse {}]", manager.getUseCaseDescriptor().getId(),id,relationshipId,deep); Project current = manager.getByID(id); long startTime=System.currentTimeMillis(); List toReturn = getLinked(current,relationshipId,deep); log.info("Got {} relationship elements in {}ms",toReturn.size(),(System.currentTimeMillis()-startTime)); return Serialization.write(toReturn); } }.execute().getResult(); } @PUT @Produces(MediaType.APPLICATION_JSON) @Path("{"+InterfaceConstants.Methods.RELATIONSHIP+"}/{"+InterfaceConstants.Parameters.PROJECT_ID+"}" + "/{"+InterfaceConstants.Parameters.RELATIONSHIP_ID+"}") public Project setRelation(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id, @PathParam(InterfaceConstants.Parameters.RELATIONSHIP_ID) String relationshipId, @QueryParam(InterfaceConstants.Parameters.TARGET_ID) String targetId, @QueryParam(InterfaceConstants.Parameters.TARGET_UCD) String targetUCD) { return new GuardedMethod() { @Override protected Project run() throws Exception, WebApplicationException { log.info("Set relation from Project ({} : {}) [{}]-> ({} : {})", manager.getUseCaseDescriptor().getId(), id,relationshipId,targetUCD,targetId); String toUseTargetUCD=targetUCD; if(toUseTargetUCD==null || toUseTargetUCD.isEmpty()) { log.debug("Target UCD is null, forcing same UCD () as source ",manager.getUseCaseDescriptor().getId()); toUseTargetUCD = manager.getUseCaseDescriptor().getId(); } return manager.setRelation(id,relationshipId,toUseTargetUCD,targetId); } }.execute().getResult(); } @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("{"+InterfaceConstants.Methods.RELATIONSHIP+"}/{"+InterfaceConstants.Parameters.PROJECT_ID+"}" + "/{"+InterfaceConstants.Parameters.RELATIONSHIP_ID+"}") public Project deleteRelation(@PathParam(InterfaceConstants.Parameters.PROJECT_ID) String id, @PathParam(InterfaceConstants.Parameters.RELATIONSHIP_ID) String relationshipId, @QueryParam(InterfaceConstants.Parameters.TARGET_ID) String targetId, @QueryParam(InterfaceConstants.Parameters.TARGET_UCD) String targetUCD) { return new GuardedMethod() { @Override protected Project run() throws Exception, WebApplicationException { log.info("Deleting relation from Project ({} : {}) [{}]-> ({} : {})", manager.getUseCaseDescriptor().getId(), id,relationshipId,targetUCD,targetId); return manager.deleteRelation(id,relationshipId,targetUCD,targetId); } }.execute().getResult(); } private static List getLinked(Project current, String relationName, Boolean recurse)throws Exception{ log.debug("Getting Relationships Lists for {} [rel : {}, recurse {}]",current.getId(),relationName,recurse); ArrayList toReturn = new ArrayList<>(); List existing = current.getRelationshipsByName(relationName); for (Relationship relationship : existing) { try{ log.trace("Navigating from {} : {} to[rel {} ] {} : {}",relationship.getTargetUCD(), relationship.getTargetID(),relationship.getRelationshipName(),current.getProfileID(),current.getId()); RelationshipNavigationObject linkedProject = new RelationshipNavigationObject(); linkedProject.setTarget(new ProfiledMongoManager(relationship.getTargetUCD()).getByID(relationship.getTargetID())); if(recurse) linkedProject.setChildren(getLinked(linkedProject.getTarget(),relationName,recurse)); toReturn.add(linkedProject); } catch (Exception e) { log.warn("Unable to navigate from {} : {} to[rel {} ] {} : {}",relationship.getTargetUCD(), relationship.getTargetID(),relationship.getRelationshipName(),current.getProfileID(),current.getId(),e); } } return toReturn; } }