package org.genedb.web.mvc.controller.download;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import javax.mail.MessagingException;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.genedb.db.dao.SequenceDao;
import org.genedb.querying.core.QueryException;
import org.genedb.querying.tmpquery.GeneDetail;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import uk.co.flamingpenguin.jewel.cli.ArgumentValidationException;
import uk.co.flamingpenguin.jewel.cli.CliFactory;
import uk.co.flamingpenguin.jewel.cli.Option;
public class DownloadProcess {
private static Logger logger = Logger.getLogger(DownloadProcess.class);
OutputFormat outputFormat = OutputFormat.CSV;
//String[] custFields = new String[0];
OutputDestination outputDestination = OutputDestination.TO_EMAIL;
SequenceType sequenceType = SequenceType.UNSPLICED_DNA;
boolean includeHeader = true;
String fieldSeparator = "\t";
String blankField = "--";
String fieldInternalSeparator;
int prime3;
int prime5;
String email;
List<OutputOption> outputOptions = new ArrayList<OutputOption>();
List<GeneDetail> results;
List<String> uniqueNames;
String historyItemName;
String description;
String url;
//private BerkeleyMapFactory bmf;
private SequenceDao sequenceDao;
private DownloadProcessUtil util;
interface IDownloadProcess {
@Option(shortName="f", longName="outputFormat", description="The format for generating output.")
OutputFormat getOutputFormat();
void setOutputFormat(OutputFormat outputFormat);
@Option(shortName="c", longName="custFields", description="The fields to be exported.")
List<String> getCustFields();
void setCustFields(List<String> custFields);
@Option(shortName="d", longName="outputDestination", description="Whether to send it to the browser, the file or to an email.")
OutputDestination getOutputDestination();
void setOutputDestination(OutputDestination outputDestination);
@Option(shortName="t", longName="sequenceType", description="The kind of sequence.")
SequenceType getSequenceType();
void setSequenceType(SequenceType sequenceType);
@Option(shortName="h", longName="includeHeader", description="Whether or not to include a header line.")
boolean getIncludeHeader();
void setIncludeHeader(SequenceType includeHeader);
@Option(shortName="s", longName="fieldSeparator", description="The field separator.")
String getFieldSeparator();
void setFieldSeparator(String fieldSeparator);
@Option(shortName="b", longName="blankField", description="The blank field value.")
String getBlankField();
void setBlankField(String blankField);
@Option(shortName="i", longName="fieldInternalSeparator", description="The internal field separator.")
String getFieldInternalSeparator();
void setFieldInternalSeparator(String fieldInternalSeparator);
@Option(shortName="3", longName="prime3", description="The prime3 value.")
int getPrime3();
void setPrime3(int prime3);
@Option(shortName="5", longName="prime5", description="The prime5 value.")
int getPrime5();
void setPrime5(int prime3);
@Option(shortName="e", longName="email", description="The email address.")
String getEmail();
void setEmail(String email);
@Option(shortName="u", longName="uniqueNames", description="The unique names to be exported.")
List<String> getUniqueNames();
void setUniqueNames(List<String> uniqueNames);
@Option(shortName="n", longName="historyItemName", description="The name of the history item.")
String getHistoryItemName();
void setHistoryItemName(String historyItemName);
@Option(shortName="ds", longName="description", description="The HTML description of the query.")
String getDescription();
void setDescription(String description);
@Option(shortName="r", longName="url", description="The base url of the site.")
String getUrl();
void setUrl(String url);
}
/**
* @param args
* @throws ArgumentValidationException
* @throws ArgumentValidationException
* @throws MessagingException
* @throws IOException
* @throws QueryException
* @throws QueryException
* @throws IOException
* @throws MessagingException
*/
public static void main(String[] args) throws ArgumentValidationException, QueryException, IOException, MessagingException {
PropertyConfigurator.configure("resources/classpath/log4j.download.properties");
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {"classpath:Load.xml", "classpath:Download.xml"});
try {
IDownloadProcess cliArgs = CliFactory.parseArguments(IDownloadProcess.class, args);
DownloadProcess process = new DownloadProcess(cliArgs, ctx.getBean("downloadProcessUtil", DownloadProcessUtil.class));
logger.debug(cliArgs.getOutputFormat());
logger.debug(cliArgs.getCustFields());
logger.debug(cliArgs.getOutputDestination());
logger.debug(cliArgs.getSequenceType());
logger.debug(cliArgs.getIncludeHeader());
logger.debug(cliArgs.getFieldSeparator());
logger.debug(cliArgs.getBlankField());
logger.debug(cliArgs.getFieldInternalSeparator());
logger.debug(cliArgs.getPrime3());
logger.debug(cliArgs.getPrime5());
logger.debug(cliArgs.getEmail());
logger.debug(cliArgs.getUniqueNames());
logger.debug(cliArgs.getHistoryItemName());
logger.debug(cliArgs.getDescription());
logger.debug(cliArgs.getUrl());
if (process.outputDestination == OutputDestination.TO_BROWSER) {
logger.debug("Cannot send to browser from command line.");
System.exit(1);
}
if (process.outputDestination == OutputDestination.TO_EMAIL && process.email == null) {
logger.debug("You must supply an email address.");
System.exit(1);
}
process.run();
} catch (ArgumentValidationException e) {
logger.debug(e.getMessage());
System.exit(1);
}
}
public void run() throws QueryException, IOException, MessagingException {
String fileName = historyItemName + "." + util.getTime() + "." + outputFormat.name().toLowerCase();
String filePath = util.gettDownloadTmpFolder() + "/" + fileName;
File file = new File(filePath);
switch (outputFormat) {
case CSV:
generateCSV(file);
break;
case HTML:
generateHTML(file);
break;
case FASTA:
generateFASTA(file);
break;
case XLS:
generateXLS(file);
break;
}
System.gc();
File zipFile = util.zip(file);
if (outputDestination == OutputDestination.TO_EMAIL) {
util.sendEmail(email, historyItemName, "Please find your " + outputFormat.name() + " results." + description, zipFile, url);
}
// don't need to keep the unzipped version
file.delete();
}
/**
* Constructor for use in command line request.
*
* @param args
*/
public DownloadProcess(IDownloadProcess args, DownloadProcessUtil util) {
this.outputFormat = args.getOutputFormat();
for (String custField : args.getCustFields()) {
outputOptions.add(OutputOption.valueOf(custField));
}
this.outputDestination = args.getOutputDestination();
this.sequenceType = args.getSequenceType();
this.includeHeader = args.getIncludeHeader();
this.fieldSeparator = determineFieldSeparator(args.getFieldSeparator(), outputFormat);
this.blankField = args.getBlankField();
this.fieldInternalSeparator = args.getFieldInternalSeparator();
this.prime3 = args.getPrime3();
this.prime5 = args.getPrime5();
this.email = args.getEmail();
this.uniqueNames = args.getUniqueNames();
this.historyItemName = args.getHistoryItemName();
this.description = args.getDescription();
this.url = args.getUrl();
this.util = util;
sequenceDao = util.getSequenceDao();
}
/**
* Constructor for use in web request.
*
* @param outputFormat
* @param custFields
* @param outputDestination
* @param sequenceType
* @param includeHeader
* @param fieldSeparator
* @param blankField
* @param fieldInternalSeparator
* @param prime3
* @param prime5
* @param email
* @param uniqueNames
* @param historyItemName
* @throws QueryException
*/
public DownloadProcess(
OutputFormat outputFormat,
String[] custFields,
OutputDestination outputDestination,
SequenceType sequenceType,
boolean includeHeader,
String fieldSeparator,
String blankField,
String fieldInternalSeparator,
int prime3,
int prime5,
String email,
List<String> uniqueNames,
String historyItemName,
String description,
DownloadProcessUtil util,
String url
) throws QueryException {
this.outputFormat = outputFormat;
for (String custField : custFields) {
outputOptions.add(OutputOption.valueOf(custField));
}
this.outputDestination = outputDestination;
this.sequenceType = sequenceType;
this.includeHeader = includeHeader;
this.fieldSeparator = determineFieldSeparator(fieldSeparator, outputFormat);
this.blankField = blankField;
this.fieldInternalSeparator = fieldInternalSeparator;
this.prime3 = prime3;
this.prime5 = prime5;
this.email = email;
this.uniqueNames = uniqueNames;
this.historyItemName = historyItemName;
this.description = description;
this.util = util;
sequenceDao = util.getSequenceDao();
this.url = url;
}
public void generateXLS(File file) throws IOException, QueryException {
OutputStream stream = new FileOutputStream(file);
generateXLS(stream);
}
public void generateXLS(OutputStream stream) throws IOException, QueryException {
results = util.getResults(uniqueNames);
FormatExcel excelFormatter = new FormatExcel();
excelFormatter.setFieldInternalSeparator(fieldInternalSeparator);
excelFormatter.setOutputOptions(outputOptions);
excelFormatter.setOutputStream(stream);
excelFormatter.setSequenceDao(sequenceDao);
excelFormatter.setTransactionTemplate(util.getTransactionTemplate());
excelFormatter.format(results);
}
public void generateCSV(File file) throws IOException, QueryException {
Writer writer = new FileWriter(file);
generateCSV(writer);
writer.close();
}
public void generateCSV(Writer writer) throws IOException, QueryException {
results = util.getResults(uniqueNames);
FormatCSV csvFormatter = new FormatCSV();
csvFormatter.setBlankField(blankField);
csvFormatter.setHeader(includeHeader);
csvFormatter.setFieldInternalSeparator(fieldInternalSeparator);
csvFormatter.setFieldSeparator(fieldSeparator);
csvFormatter.setOutputOptions(outputOptions);
csvFormatter.setWriter(writer);
csvFormatter.setSequenceDao(sequenceDao);
csvFormatter.setTransactionTemplate(util.getTransactionTemplate());
csvFormatter.format(results);
}
public void generateHTML(File file) throws IOException, QueryException {
Writer writer = new FileWriter(file);
generateHTML(writer);
writer.close();
}
public void generateHTML(Writer writer) throws IOException, QueryException {
results = util.getResults(uniqueNames);
FormatHTML htmlFormatter = new FormatHTML();
htmlFormatter.setBlankField(blankField);
htmlFormatter.setHeader(includeHeader);
htmlFormatter.setFieldInternalSeparator(fieldInternalSeparator);
htmlFormatter.setOutputOptions(outputOptions);
htmlFormatter.setWriter(writer);
htmlFormatter.setSequenceDao(sequenceDao);
htmlFormatter.setTransactionTemplate(util.getTransactionTemplate());
htmlFormatter.format(results);
}
public void generateFASTA(File file) throws IOException, QueryException {
Writer writer = new FileWriter(file);
generateFASTA(writer);
writer.close();
}
public void generateFASTA(Writer writer) throws IOException, QueryException {
results = util.getResults(uniqueNames);
FormatFASTA fastaFormatter = new FormatFASTA();
fastaFormatter.setBlankField(blankField);
fastaFormatter.setHeader(includeHeader);
fastaFormatter.setFieldInternalSeparator(fieldInternalSeparator);
fastaFormatter.setFieldSeparator(fieldSeparator);
fastaFormatter.setOutputOptions(outputOptions);
fastaFormatter.setWriter(writer);
fastaFormatter.setPrime3(prime3);
fastaFormatter.setPrime5(prime5);
fastaFormatter.setSequenceType(sequenceType);
fastaFormatter.setSequenceDao(sequenceDao);
fastaFormatter.setTransactionTemplate(util.getTransactionTemplate());
fastaFormatter.format(results);
}
private String determineFieldSeparator(String fieldSeparator, OutputFormat outputFormat) {
if (fieldSeparator.equals("default")) {
switch (outputFormat) {
case CSV:
fieldSeparator = "\t";
break;
case FASTA:
fieldSeparator = "|";
break;
}
}
else if (fieldSeparator.equals("tab")) {
fieldSeparator = "\t";
}
return fieldSeparator;
}
}