/*
* Copyright (C) 2012 SeqWare
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sourceforge.seqware.webservice.resources.queries;
import io.seqware.common.model.WorkflowRunStatus;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import net.sourceforge.seqware.common.hibernate.WorkflowRunReport;
import net.sourceforge.seqware.common.hibernate.reports.WorkflowRunReportRow;
import net.sourceforge.seqware.common.model.File;
import net.sourceforge.seqware.common.model.Sample;
import net.sourceforge.seqware.common.util.Log;
import static net.sourceforge.seqware.webservice.resources.BasicResource.parseClientInt;
import net.sourceforge.seqware.webservice.resources.BasicRestlet;
import org.apache.log4j.Logger;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Status;
import org.restlet.resource.ResourceException;
/**
* <p>
* WorkflowRunReportResource class.
* </p>
*
* @author mtaschuk
* @version $Id: $Id
*/
public class WorkflowRunReportResource extends BasicRestlet {
private static final String STATUS = "status";
private final Logger logger = Logger.getLogger(WorkflowRunReportResource.class);
/**
* <p>
* Constructor for WorkflowRunReportResource.
* </p>
*
* @param context
* a {@link org.restlet.Context} object.
*/
public WorkflowRunReportResource(Context context) {
super(context);
}
/** {@inheritDoc} */
@Override
public void handle(Request request, Response response) {
boolean showStdErr = false;
boolean showStdOut = false;
authenticate(request.getChallengeResponse().getIdentifier());
init(request);
Object wrId = request.getAttributes().get("workflowRunId");
Object wId = request.getAttributes().get("workflowId");
String path = request.getResourceRef().getPath();
// checking if a user is requesting error log rather than summary report
if (path.contains("stderr")) {
showStdErr = true;
} else if (path.contains("stdout")) {
showStdOut = true;
}
Date earliestDate = new Date(0);
Date latestDate = new Date();
WorkflowRunStatus status = null;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
for (String key : queryValues.keySet()) {
logger.debug("queryValues: " + key + " " + queryValues.get(key));
}
if (queryValues.containsKey("earliestDate")) {
String dateString = queryValues.get("earliestDate");
try {
earliestDate = dateFormat.parse(dateString);
logger.debug("Earliest date: " + earliestDate.toString());
} catch (ParseException ex) {
logger.error("Improperly formatted earliest date. Should be in the form yyyyMMdd");
throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST,
"Improperly formatted earliest date. Should be in the form yyyyMMdd: " + ex.getMessage());
}
}
if (queryValues.containsKey("latestDate")) {
String dateString = queryValues.get("latestDate");
try {
latestDate = dateFormat.parse(dateString);
logger.debug("Earliest date: " + latestDate.toString());
} catch (ParseException ex) {
logger.error("Improperly formatted latest date. Should be in the form yyyyMMdd");
throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST,
"Improperly formatted latest date. Should be in the form yyyyMMdd: " + ex.getMessage());
}
}
if (queryValues.containsKey(STATUS)) {
try {
status = WorkflowRunStatus.valueOf(queryValues.get(STATUS));
} catch (IllegalArgumentException | NullPointerException e) {
logger.error("Improper workflow run status: " + queryValues.get(STATUS));
throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Improper status, should be one of "
+ Arrays.toString(WorkflowRunStatus.values()));
}
}
if (request.getMethod().compareTo(Method.GET) == 0) {
WorkflowRunReport cfc = new WorkflowRunReport();
cfc.setEarliestDate(earliestDate);
cfc.setLatestDate(latestDate);
cfc.setStatus(status);
StringBuilder builder = getHeader();
if (wId != null) {
Collection<WorkflowRunReportRow> rows = cfc.getRunsFromWorkflow(parseClientInt(wId.toString()));
for (WorkflowRunReportRow results : rows) {
toString(results, builder);
}
} else if (wrId != null) {
WorkflowRunReportRow results = cfc.getSingleWorkflowRun(parseClientInt(wrId.toString()));
// check to see if we're just returning the stderr/out or full report
if (showStdErr) {
builder = new StringBuilder();
outputLogString(true, results, builder);
} else if (showStdOut) {
builder = new StringBuilder();
outputLogString(false, results, builder);
} else { // full report
toString(results, builder);
}
} else if (status != null) {
Log.debug("getRunsByStatus " + status.toString());
Collection<WorkflowRunReportRow> runsByStatus = cfc.getRunsByStatus(status);
for (WorkflowRunReportRow results : runsByStatus) {
toString(results, builder);
}
} else if (wId == null && wrId == null) {
String errMsg = "Improperly formatted, you need to provide a workflow ID or workflowRun ID";
throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, errMsg);
} else {
Collection<WorkflowRunReportRow> rows = cfc.getAllRuns();
for (WorkflowRunReportRow results : rows) {
toString(results, builder);
}
}
response.setEntity(builder.toString(), MediaType.TEXT_PLAIN);
} else {
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
}
}
/**
* <p>
* getHeader.
* </p>
*
* @return a {@link java.lang.StringBuilder} object.
*/
public StringBuilder getHeader() {
StringBuilder builder = new StringBuilder();
builder.append("Workflow").append("\t");
builder.append("Workflow Run SWID").append("\t");
builder.append("Workflow Run Status").append("\t");
builder.append("Workflow Run Create Timestamp").append("\t");
builder.append("Workflow Run Host").append("\t");
builder.append("Workflow Run Working Dir").append("\t");
builder.append("Workflow Run Engine ID").append("\t");
builder.append("Library Sample Names").append("\t");
builder.append("Library Sample SWIDs").append("\t");
builder.append("Identity Sample Names").append("\t");
builder.append("Identity Sample SWIDs").append("\t");
// following three fields are for "all"
builder.append("Input File Meta-Types").append("\t");
builder.append("Input File SWIDs").append("\t");
builder.append("Input File Paths").append("\t");
builder.append("Immediate Input File Meta-Types").append("\t");
builder.append("Immediate Input File SWIDs").append("\t");
builder.append("Immediate Input File Paths").append("\t");
builder.append("Output File Meta-Types").append("\t");
builder.append("Output File SWIDs").append("\t");
builder.append("Output File Paths").append("\t");
builder.append("Workflow Run Time").append("\t");
builder.append("\n");
return builder;
}
/**
* <p>
* outputLogString.
* </p>
*
* @param stdErr
* a boolean.
* @param wrrr
* a {@link net.sourceforge.seqware.common.hibernate.reports.WorkflowRunReportRow} object.
* @param builder
* a {@link java.lang.StringBuilder} object.
* @return a {@link java.lang.String} object.
*/
public String outputLogString(boolean stdErr, WorkflowRunReportRow wrrr, StringBuilder builder) {
if (stdErr) {
builder.append(wrrr.getWorkflowRun().getStdErr());
} else {
builder.append(wrrr.getWorkflowRun().getStdOut());
}
builder.append("\n");
return builder.toString();
}
/**
* <p>
* toString.
* </p>
*
* @param wrrr
* a {@link net.sourceforge.seqware.common.hibernate.reports.WorkflowRunReportRow} object.
* @param builder
* a {@link java.lang.StringBuilder} object.
* @return a {@link java.lang.String} object.
*/
public String toString(WorkflowRunReportRow wrrr, StringBuilder builder) {
builder.append(wrrr.getWorkflowRun().getWorkflow().getName()).append(" ").append(wrrr.getWorkflowRun().getWorkflow().getVersion())
.append("\t");
builder.append(wrrr.getWorkflowRun().getSwAccession()).append("\t");
builder.append(wrrr.getWorkflowRun().getStatus()).append("\t");
builder.append(wrrr.getWorkflowRun().getCreateTimestamp().toString()).append("\t");
builder.append(wrrr.getWorkflowRun().getHost()).append("\t");
if (wrrr.getWorkflowRun().getCurrentWorkingDir() != null) builder.append(wrrr.getWorkflowRun().getCurrentWorkingDir());
builder.append("\t");
if (wrrr.getWorkflowRun().getStatusCmd() != null) builder.append(wrrr.getWorkflowRun().getStatusCmd());
builder.append("\t");
parseSamples(builder, wrrr.getLibrarySamples());
parseSamples(builder, wrrr.getIdentitySamples());
parseFiles(builder, wrrr.getAllInputFiles());
parseFiles(builder, wrrr.getImmediateInputFiles());
parseFiles(builder, wrrr.getOutputFiles());
builder.append(wrrr.getTimeTaken());
builder.append("\n");
return builder.toString();
}
private void parseSamples(StringBuilder builder, Collection<Sample> samples) {
StringBuilder sampleNames = new StringBuilder();
StringBuilder sampleSWIDs = new StringBuilder();
for (Sample s : samples) {
if (sampleNames.length() != 0) {
sampleNames.append(",");
}
if (sampleSWIDs.length() != 0) {
sampleSWIDs.append(",");
}
sampleNames.append(s.getName());
sampleSWIDs.append(s.getSwAccession());
}
builder.append(sampleNames.toString()).append("\t");
builder.append(sampleSWIDs.toString()).append("\t");
}
private void parseFiles(StringBuilder builder, Collection<File> files) {
StringBuilder fileTypes = new StringBuilder();
StringBuilder filePaths = new StringBuilder();
StringBuilder fileSWIDs = new StringBuilder();
for (File f : files) {
if (fileTypes.length() != 0) {
fileTypes.append(",");
}
if (filePaths.length() != 0) {
filePaths.append(",");
}
if (fileSWIDs.length() != 0) {
fileSWIDs.append(",");
}
fileTypes.append(f.getMetaType());
filePaths.append(f.getFilePath());
fileSWIDs.append(f.getSwAccession());
}
builder.append(fileTypes.toString()).append("\t");
builder.append(fileSWIDs.toString()).append("\t");
builder.append(filePaths.toString()).append("\t");
}
}