/**
*
*/
package net.sourceforge.seqware.pipeline.plugins;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import joptsimple.OptionException;
import net.sourceforge.seqware.common.factory.DBAccess;
import net.sourceforge.seqware.common.metadata.Metadata;
import net.sourceforge.seqware.common.metadata.MetadataDB;
import net.sourceforge.seqware.common.module.ReturnValue;
import net.sourceforge.seqware.common.util.Log;
import net.sourceforge.seqware.pipeline.plugin.Plugin;
import net.sourceforge.seqware.pipeline.plugin.PluginInterface;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.lookup.ServiceProvider;
/**
* <p>
* This plugin does the initial population of workflow run files in order to track input files when migrating from SeqWare 0.13.6.X to
* 1.0.X.
*
* </p>
*
* @author dyuen ProviderFor(PluginInterface.class)
* @version $Id: $Id
*/
@ServiceProvider(service = PluginInterface.class)
public class WorkflowRunFilesInitialPopulationPlugin extends Plugin {
/**
* <p>
* Constructor for HelloWorld.
* </p>
*/
public WorkflowRunFilesInitialPopulationPlugin() {
super();
parser.acceptsAll(Arrays.asList("skip", "s"), "Optional: comma separated list of module/plugin names to skip").requiresArgument();
parser.acceptsAll(Arrays.asList("modules", "m"), "Optional: if provided will list out modules instead of plugins.");
parser.acceptsAll(Arrays.asList("help", "h", "?"), "Provides this help message.");
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#setConfig(java.util.Map)
*/
/**
* {@inheritDoc}
*
* @param config
*/
@Override
public void setConfig(Map<String, String> config) {
/**
* explicitly no nothing
*/
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#setParams(java.util.List)
*/
/**
* {@inheritDoc}
*
* @param params
*/
@Override
public void setParams(List<String> params) {
this.params = params.toArray(new String[params.size()]);
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#setMetadata(net.sourceforge.seqware.pipeline.metadata.Metadata)
*/
/**
* {@inheritDoc}
*
* @param metadata
*/
@Override
public void setMetadata(Metadata metadata) {
// println("Setting Metadata: " + metadata);
this.metadata = metadata;
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#get_syntax()
*/
/**
* {@inheritDoc}
*
* @return
*/
@Override
public String get_syntax() {
try {
parser.printHelpOn(System.err);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.fatal(e);
}
return ("");
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#parse_parameters()
*/
/**
* {@inheritDoc}
*
* @return
*/
@Override
public ReturnValue parse_parameters() {
ReturnValue ret = new ReturnValue();
try {
options = parser.parse(params);
} catch (OptionException e) {
get_syntax();
ret.setExitStatus(ReturnValue.INVALIDARGUMENT);
}
return ret;
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#init()
*/
/**
* {@inheritDoc}
*
* @return
*/
@Override
public ReturnValue init() {
return new ReturnValue();
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#do_test()
*/
/**
* {@inheritDoc}
*
* @return
*/
@Override
public ReturnValue do_test() {
return new ReturnValue();
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#do_run()
*/
/**
* {@inheritDoc}
*
* @return
*/
@Override
public ReturnValue do_run() {
ReturnValue ret = new ReturnValue();
ResultSet rs = null;
MetadataDB mdb = null;
PreparedStatement prepareStatement = null;
try {
String query = new StringBuilder()
.append("select w.sw_accession, w.workflow_run_id, w.status, f.* FROM workflow_run w LEFT OUTER JOIN workflow_run_input_files f ")
.append("ON w.workflow_run_id = f.workflow_run_id WHERE (status = 'completed' OR status= 'failed') AND ")
.append("f.workflow_run_id IS NULL ORDER BY w.sw_accession;").toString();
Log.info("Executing query: " + query);
mdb = DBAccess.get();
List<int[]> ids = mdb.executeQuery(query, new ResultSetHandler<List<int[]>>() {
@Override
public List<int[]> handle(ResultSet rs) throws SQLException {
List<int[]> ids = new ArrayList<>();
while (rs.next()) {
ids.add(new int[] { rs.getInt("sw_accession"), rs.getInt("workflow_run_id") });
}
return ids;
}
});
mdb.getDb().setAutoCommit(false);
prepareStatement = mdb.getDb().prepareStatement("INSERT INTO workflow_run_input_files (workflow_run_id, file_id) VALUES(?,?)");
for (int[] i : ids) {
int workflowSWID = i[0];
int workflowRunID = i[1];
Log.stdout("Working on workflow_run " + workflowSWID);
// populate input files
List<Integer> listOfFiles = this.getListOfFiles(workflowSWID);
Log.stdout("Found " + listOfFiles.size() + " input files for workflow_run " + workflowSWID);
// insert into new workflow_run_input_files table
for (Integer fSWID : listOfFiles) {
Integer fileID = this.metadata.getFile(fSWID).getFileId();
prepareStatement.setInt(1, workflowRunID);
prepareStatement.setInt(2, fileID);
prepareStatement.executeUpdate();
}
}
Log.stdout("Success!");
mdb.getDb().commit();
return ret;
} catch (SQLException ex) {
Log.fatal("Population failed, aborting.");
Logger.getLogger(WorkflowRunFilesInitialPopulationPlugin.class.getName()).log(Level.SEVERE, null, ex);
ret.setExitStatus(ReturnValue.FAILURE);
} finally {
if (mdb != null) {
DbUtils.closeQuietly(mdb.getDb(), mdb.getSql(), rs);
}
DBAccess.close();
DbUtils.closeQuietly(prepareStatement);
}
ret.setExitStatus(ReturnValue.FAILURE);
return ret;
}
/**
* Given a workflowRunAcc returns a list of file paths that were used in that run using effectively, the workflow run reporter.
*
* Hopefully, this is the last we'll use this approach!
*
* @param workflowRunAcc
* @param filesToRun
* @return
*/
private List<Integer> getListOfFiles(int workflowRunAcc) {
Map<String, String> map = generateWorkflowRunMap(workflowRunAcc);
List<Integer> ranOnList = new ArrayList<>();
if (map.isEmpty()) {
return ranOnList;
}
String ranOnString = map.get("Immediate Input File SWIDs");
if (ranOnString == null) {
return ranOnList;
}
String[] ranOnArr = ranOnString.split(",");
if (ranOnString.isEmpty()) {
return ranOnList;
}
for (String i : ranOnArr) {
ranOnList.add(Integer.valueOf(i.trim()));
Log.trace("Adding item: " + i);
}
Log.debug("Got list of files: " + StringUtils.join(ranOnList, ','));
return ranOnList;
}
/**
* Report an actual launch of a workflow for testing purpose
*
* @return false iff we don't actually want to launch
*/
protected boolean reportLaunch() {
return true;
}
private Map<String, String> generateWorkflowRunMap(int workflowRunAcc) {
String report = metadata.getWorkflowRunReport(workflowRunAcc);
Map<String, String> map = new TreeMap<>();
if (report == null) {
return map;
}
String[] lines = report.split("\n");
String[] reportHeader = lines[0].split("\t");
String[] data = lines[1].split("\t");
for (int i = 0; i < reportHeader.length && i < data.length; i++) {
map.put(reportHeader[i].trim(), data[i].trim());
}
return map;
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#clean_up()
*/
/**
* {@inheritDoc}
*
* @return
*/
@Override
public ReturnValue clean_up() {
ReturnValue ret = new ReturnValue();
return ret;
}
/**
* <p>
* get_description.
* </p>
*
* @return a {@link java.lang.String} object.
*/
@Override
public String get_description() {
return ("This plugin does the initial population of workflow run files in order to track input files.");
}
public static void main(String[] args) {
WorkflowRunFilesInitialPopulationPlugin mp = new WorkflowRunFilesInitialPopulationPlugin();
mp.init();
List<String> arr = new ArrayList<>();
mp.setParams(arr);
mp.parse_parameters();
mp.do_run();
}
}