package net.sourceforge.seqware.pipeline.plugins.deletion;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.UniformInterfaceException;
import io.seqware.pipeline.SqwKeys;
import io.seqware.webservice.client.SeqWareWebServiceClient;
import io.seqware.webservice.controller.ModelAccessionIDTuple;
import io.seqware.webservice.generated.model.WorkflowRun;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import joptsimple.OptionSpec;
import net.sourceforge.seqware.common.module.ReturnValue;
import net.sourceforge.seqware.common.util.configtools.ConfigTools;
import net.sourceforge.seqware.pipeline.plugin.Plugin;
import net.sourceforge.seqware.pipeline.plugin.PluginInterface;
import org.apache.commons.io.FileUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.type.TypeReference;
import org.openide.util.lookup.ServiceProvider;
/**
* A workflow run deletion tool for your SeqWare metadb
*
* @author dyuen ProviderFor(PluginInterface.class)
* @version $Id: $Id
*/
@ServiceProvider(service = PluginInterface.class)
public final class DeletionDB extends Plugin {
private OptionSpec<Integer> workflowRunSpec;
private OptionSpec<String> inKeyFileSpec;
private OptionSpec<String> outKeyFileSpec;
private Integer workflow_run_target = null;
private File inKeyFile = null;
private String adminUrl = null;
private File outKeyFile = null;
/**
* <p>
* Constructor for HelloWorld.
* </p>
*/
public DeletionDB() {
super();
parser.acceptsAll(Arrays.asList("help", "h", "?"), "Provides this help message.");
workflowRunSpec = parser
.acceptsAll(Arrays.asList("workflowrun", "r"),
"Give a sequencer run, lane, or workflow run SWID in order to determine which workflow runs (processings,files) should be deleted.")
.withRequiredArg().ofType(Integer.class).required();
inKeyFileSpec = parser
.acceptsAll(Arrays.asList("key", "k"), "An existing key file will be used to guide an actual deletion process")
.withRequiredArg().ofType(String.class);
outKeyFileSpec = parser.acceptsAll(Arrays.asList("out", "o"), "The filename of the output key file").withRequiredArg()
.ofType(String.class);
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#init()
*/
/**
* {@inheritDoc}
*
* @return
*/
@Override
public final ReturnValue init() {
try {
HashMap<String, String> settings = (HashMap<String, String>) ConfigTools.getSettings();
this.adminUrl = settings.get(SqwKeys.SW_ADMIN_REST_URL.getSettingKey());
} catch (Exception e) {
ReturnValue ret = new ReturnValue();
ret.setExitStatus(ReturnValue.SETTINGSFILENOTFOUND);
return ret;
}
if (this.adminUrl == null) {
ReturnValue ret = new ReturnValue();
System.out.println("This utility requires access to the admin web service. Configure "
+ SqwKeys.SW_ADMIN_REST_URL.getSettingKey() + " in your .seqware/setttings");
ret.setExitStatus(ReturnValue.SETTINGSFILENOTFOUND);
return ret;
}
return new ReturnValue();
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#do_test()
*/
/**
* {@inheritDoc}
*
* @return
*/
@Override
public ReturnValue do_test() {
// TODO Auto-generated method stub
return new ReturnValue();
}
/*
* (non-Javadoc)
*
* @see net.sourceforge.seqware.pipeline.plugin.PluginInterface#do_run()
*/
/**
* {@inheritDoc}
*
* @return
*/
@Override
public final ReturnValue do_run() {
workflow_run_target = options.valueOf(workflowRunSpec);
if (options.has(inKeyFileSpec)) {
inKeyFile = new File(options.valueOf(inKeyFileSpec));
}
if (options.has(outKeyFileSpec)) {
outKeyFile = new File(options.valueOf(outKeyFileSpec));
}
SeqWareWebServiceClient client = null;
SeqWareWebServiceClient fileClient = null;
try {
ReturnValue ret = new ReturnValue();
ModelAccessionIDTuple tuple = translateToID(workflow_run_target);
client = new SeqWareWebServiceClient("workflowrun", adminUrl + "/webresources");
fileClient = new SeqWareWebServiceClient("file", adminUrl + "/webresources");
if (inKeyFile == null) {
// create a key file
Set<ModelAccessionIDTuple> findJSONrdelete = client.find_JSON_rdelete(Class.forName(tuple.getAdminModelClass()),
String.valueOf(tuple.getId()));
// add to a sorted set for easy viewing
SortedSet<ModelAccessionIDTuple> sortedSet = new TreeSet<>();
sortedSet.addAll(findJSONrdelete);
// output information for informational purposes
outputSummaryInformation(sortedSet, fileClient);
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter();
if (outKeyFile == null) {
outKeyFile = File.createTempFile("deletion", ".keyFile");
} else {
boolean createOutput = outKeyFile.createNewFile();
if (!createOutput) {
ret.setExitStatus(ReturnValue.FILENOTWRITABLE);
return ret;
}
}
writer.writeValue(outKeyFile, sortedSet);
System.out.println("Key File written to " + outKeyFile.getAbsolutePath());
} else {
ObjectMapper mapper = new ObjectMapper();
Set<ModelAccessionIDTuple> matchSet;
Set<String> filesToBeDeleted = new HashSet<>();
try {
matchSet = mapper.readValue(inKeyFile, new TypeReference<Set<ModelAccessionIDTuple>>() {
});
for (ModelAccessionIDTuple t : matchSet) {
if (t.getAdminModelClass().equals(io.seqware.webservice.generated.model.File.class.getName())) {
io.seqware.webservice.generated.model.File file = fileClient.find_JSON(
io.seqware.webservice.generated.model.File.class, String.valueOf(t.getId()));
filesToBeDeleted.add(file.getFilePath());
}
}
client.remove_rdelete(Class.forName(tuple.getAdminModelClass()), String.valueOf(tuple.getId()), matchSet);
client.close();
} catch (IOException ex) {
System.out.println("Invalid data in provided key file");
ret.setExitStatus(ReturnValue.INVALIDFILE);
return ret;
} catch (UniformInterfaceException ex) {
if (ex.getResponse().getClientResponseStatus().equals(Status.NOT_FOUND)) {
System.out.println("Accession not found");
ret.setExitStatus(ReturnValue.INVALIDPARAMETERS);
return ret;
} else if (ex.getResponse().getClientResponseStatus().equals(Status.CONFLICT)) {
System.out.println("KeyFile does not match current server content, could not delete.");
ret.setExitStatus(ReturnValue.INVALIDPARAMETERS);
return ret;
} else {
System.out.println("ClientResponseStatus: " + ex.getResponse().getClientResponseStatus());
System.out.println("ClientResponse: " + ex.getResponse().toString());
ret.setExitStatus(ReturnValue.FAILURE);
return ret;
}
}
System.out.println("Successful deletion of entities listed in " + inKeyFile.getAbsolutePath());
// output files as candidates for deletion
File fileListing = File.createTempFile("file", ".listing");
for (String path : filesToBeDeleted) {
FileUtils.write(fileListing, path + '\n', true);
}
System.out.println("File records deleted for files listed in " + fileListing.getAbsolutePath());
}
return ret;
} catch (UniformInterfaceException ex) {
if (ex.getResponse().getClientResponseStatus().equals(Status.NOT_FOUND)) {
System.out.println("Accession not found");
ReturnValue ret = new ReturnValue();
ret.setExitStatus(ReturnValue.INVALIDPARAMETERS);
return ret;
} else {
System.out.println("Exception message: " + ex.getMessage());
try {
String entity1 = ex.getResponse().getEntity(String.class);
System.out.println(entity1);
ReturnValue ret = new ReturnValue();
ret.setExitStatus(ReturnValue.INVALIDPARAMETERS);
return ret;
} catch (Exception e) {
/**
* ignore
*/
}
ReturnValue ret = new ReturnValue();
ret.setExitStatus(ReturnValue.FAILURE);
return ret;
}
} catch (ClientHandlerException ex) {
ReturnValue ret = new ReturnValue();
System.out.println("Error connecting to admin web service, check that you have access to SW_ADMIN_REST_URL");
ret.setExitStatus(ReturnValue.FAILURE);
return ret;
} catch (Exception ex) {
throw new RuntimeException("Client malfunction", ex);
} finally {
if (client != null) client.close();
if (fileClient != null) fileClient.close();
}
}
/**
* <p>
* get_description.
* </p>
*
* @return a {@link java.lang.String} object.
*/
@Override
public final String get_description() {
return ("A database deletion tool for your SeqWare metadb.");
}
public static void main(String[] args) throws IOException, URISyntaxException {
DeletionDB mp = new DeletionDB();
mp.init();
List<String> arr = new ArrayList<>();
mp.setParams(arr);
mp.parse_parameters();
mp.do_run();
}
@Override
public final ReturnValue clean_up() {
return new ReturnValue();
}
private ModelAccessionIDTuple translateToID(int targetAccession) {
SeqWareWebServiceClient client = new SeqWareWebServiceClient("workflowrun", adminUrl + "/webresources");
ModelAccessionIDTuple tuple = client.findTupleByAccession(String.valueOf(targetAccession));
if (tuple != null) {
return tuple;
}
throw new RuntimeException("Could not locate target, please double-check your SWID");
}
/**
* Output various convenient statistics and information on files for the end-user
*
* @param sortedSet
* @param fileClient
* @throws UniformInterfaceException
*/
private void outputSummaryInformation(SortedSet<ModelAccessionIDTuple> sortedSet, SeqWareWebServiceClient fileClient)
throws UniformInterfaceException {
// we can output some friendly summary statistics here
int workflowRunCount = 0;
Map<String, Integer> fileTypeCounts = new HashMap<>();
for (ModelAccessionIDTuple t : sortedSet) {
if (t.getAdminModelClass().equals(WorkflowRun.class.getName())) {
workflowRunCount++;
} else if (t.getAdminModelClass().equals(io.seqware.webservice.generated.model.File.class.getName())) {
io.seqware.webservice.generated.model.File file = fileClient.find_JSON(io.seqware.webservice.generated.model.File.class,
String.valueOf(t.getId()));
String metaType = file.getMetaType();
if (!fileTypeCounts.containsKey(metaType)) {
fileTypeCounts.put(metaType, 0);
}
fileTypeCounts.put(metaType, fileTypeCounts.get(metaType) + 1);
}
}
System.out.println("Key file contains " + workflowRunCount + " workflow runs.");
for (Entry<String, Integer> e : fileTypeCounts.entrySet()) {
System.out.println(" \t" + e.getValue() + " file" + (e.getValue() > 1 ? "s" : "") + " of type " + e.getKey());
}
if (fileTypeCounts.size() > 0) {
System.out.println("File paths for files to be deleted: ");
for (ModelAccessionIDTuple t : sortedSet) {
if (t.getAdminModelClass().equals(io.seqware.webservice.generated.model.File.class.getName())) {
io.seqware.webservice.generated.model.File file = fileClient.find_JSON(
io.seqware.webservice.generated.model.File.class, String.valueOf(t.getId()));
System.out.println("\t" + file.getFilePath());
}
}
}
}
}