
org.molgenis.gavin.controller.GavinController Maven / Gradle / Ivy
The newest version!
package org.molgenis.gavin.controller;
import static java.io.File.separator;
import static java.text.MessageFormat.format;
import static org.molgenis.gavin.controller.GavinController.URI;
import static org.molgenis.gavin.job.GavinJobExecutionMetaData.GAVIN_JOB_EXECUTION;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import javax.servlet.http.HttpServletResponse;
import org.molgenis.data.DataService;
import org.molgenis.data.MolgenisDataException;
import org.molgenis.file.FileStore;
import org.molgenis.gavin.job.GavinJob;
import org.molgenis.gavin.job.GavinJobExecution;
import org.molgenis.gavin.job.GavinJobFactory;
import org.molgenis.security.user.UserAccountService;
import org.molgenis.ui.MolgenisPluginController;
import org.molgenis.util.ErrorMessageResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MultipartFile;
@Controller
@RequestMapping(URI)
@EnableScheduling
public class GavinController extends MolgenisPluginController
{
private static final Logger LOG = LoggerFactory.getLogger(GavinController.class);
public static final String GAVIN_APP = "gavin-app";
public static final String URI = PLUGIN_URI_PREFIX + GAVIN_APP;
public GavinController()
{
super(URI);
}
@Autowired
private DataService dataService;
@Autowired
private ExecutorService executorService;
@Autowired
private GavinJobFactory gavinJobFactory;
@Autowired
private FileStore fileStore;
@Autowired
private UserAccountService userAccountService;
/**
* Shows the gavin page.
*
* @return the view name
*/
@SuppressWarnings(
{ "SameReturnValue", "UnusedReturnValue" })
@RequestMapping(method = RequestMethod.GET)
public String init(Model model)
{
List annotatorsWithMissingResources = gavinJobFactory.getAnnotatorsWithMissingResources();
if (!annotatorsWithMissingResources.isEmpty())
{
model.addAttribute("annotatorsWithMissingResources", annotatorsWithMissingResources);
}
return "view-gavin";
}
/**
* Starts a job to annotate a VCF file
*
* @param inputFile
* the input file, should be VCF
* @param entityName
* the name of the file, the download will be
* @return the URL where the job progress can be monitored
* @throws IOException
*/
@RequestMapping(value = "/annotate-file", method = POST)
@ResponseBody
public String annotateFile(@RequestParam(value = "file") MultipartFile inputFile, @RequestParam String entityName)
throws IOException
{
final GavinJobExecution gavinJobExecution = new GavinJobExecution(dataService);
gavinJobExecution.setFilename(entityName + "-gavin.vcf");
gavinJobExecution.setUser(userAccountService.getCurrentUser().getUsername());
final GavinJob gavinJob = gavinJobFactory.createJob(gavinJobExecution);
final String gavinJobIdentifier = gavinJobExecution.getIdentifier();
fileStore.createDirectory(GAVIN_APP);
final String jobDir = format("{0}{1}{2}", GAVIN_APP, separator, gavinJobIdentifier);
fileStore.createDirectory(jobDir);
final String fileName = format("{0}{1}input.vcf", jobDir, separator);
fileStore.writeToFile(inputFile.getInputStream(), fileName);
executorService.submit(gavinJob);
return "/api/v2/GavinJobExecution/" + gavinJobIdentifier;
}
/**
* Downloads the result of a gavin annotation job.
*
* @param response
* {@link HttpServletResponse} to write the Content-Disposition header to with the filename
* @param jobIdentifier
* GAVIN_APP of the annotation job
* @return {@link FileSystemResource} with the annotated file
*/
@RequestMapping(value = "/result/{jobIdentifier}", method = GET, produces = APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public FileSystemResource result(HttpServletResponse response,
@PathVariable(value = "jobIdentifier") String jobIdentifier)
{
GavinJobExecution jobExecution = dataService.findOne(GAVIN_JOB_EXECUTION, jobIdentifier,
GavinJobExecution.class);
File file = fileStore.getFile(GAVIN_APP + separator + jobIdentifier + separator + "gavin-result.vcf");
if (!file.exists())
{
LOG.warn(format("File {0} not found for job {1}", file.getName(), jobIdentifier));
throw new MolgenisDataException("No output file found for this job.");
}
response.setHeader("Content-Disposition", format("inline; filename=\"{0}\"", jobExecution.getFilename()));
return new FileSystemResource(file);
}
@ExceptionHandler(RuntimeException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorMessageResponse handleRuntimeException(RuntimeException e)
{
LOG.warn(e.getMessage(), e);
return new ErrorMessageResponse(new ErrorMessageResponse.ErrorMessage(e.getMessage()));
}
/**
* Removes the working directory from the file store.
*/
@Scheduled(cron = "0 0 0 * * *")
public void cleanUp()
{
LOG.info("Clean up working directory in the file store...");
try
{
fileStore.deleteDirectory(GAVIN_APP);
LOG.info("Done.");
}
catch (IOException e)
{
LOG.error("Failed to clean up working directory", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy