blob: a5b20a1b757697dbebbb48dd043e18b9eb77babe [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package net.sf.taverna.t2.commandline.data;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import net.sf.taverna.t2.commandline.CommandLineResultListener;
import net.sf.taverna.t2.invocation.InvocationContext;
import net.sf.taverna.t2.invocation.WorkflowDataToken;
import net.sf.taverna.t2.reference.ErrorDocument;
import net.sf.taverna.t2.reference.ExternalReferenceSPI;
import net.sf.taverna.t2.reference.Identified;
import net.sf.taverna.t2.reference.IdentifiedList;
import net.sf.taverna.t2.reference.ReferenceSet;
import net.sf.taverna.t2.reference.T2Reference;
import net.sf.taverna.t2.reference.T2ReferenceType;
import org.apache.log4j.Logger;
/**
* Handles all recording of results as they are received by the {@link CommandLineResultListener}
* or when the workflow enactment has completed.
* This includes saving as a Baclava Document, or storing individual results.
*
* @author Stuart Owen
* @see BaclavaDocumentHandler
* @see CommandLineResultListener
*
*/
public class SaveResultsHandler {
private final Map<String, Integer> portsAndDepth;
private HashMap<String, Integer> depthSeen;
private final File rootDirectory;
private static Logger logger = Logger
.getLogger(CommandLineResultListener.class);
private final File outputDocumentFile;
public SaveResultsHandler(Map<String, Integer> portsAndDepth,
File rootDirectory, File outputDocumentFile) {
this.portsAndDepth = portsAndDepth;
this.rootDirectory = rootDirectory;
this.outputDocumentFile = outputDocumentFile;
depthSeen = new HashMap<String, Integer>();
for (String portName : portsAndDepth.keySet()) {
depthSeen.put(portName, -1);
}
}
public void tokenReceived(WorkflowDataToken token, String portName) {
if (rootDirectory != null) { //only save individual results if a directory is specified
if (portsAndDepth.containsKey(portName)) {
int[] index = token.getIndex();
if (depthSeen.get(portName) == -1)
depthSeen.put(portName, index.length);
if (index.length >= depthSeen.get(portName)) {
storeToken(token, portName);
}
} else {
logger
.error("Result recieved for unexpected Port: "
+ portName);
}
}
}
public void saveOutputDocument(Map<String,WorkflowDataToken> allResults) throws Exception {
if (outputDocumentFile!=null) {
new BaclavaDocumentHandler().storeDocument(allResults, outputDocumentFile);
}
}
protected void storeToken(WorkflowDataToken token, String portName) {
if (token.getData().getReferenceType() == T2ReferenceType.IdentifiedList) {
saveList(token, portName);
} else {
File dataDirectory = rootDirectory;
File dataFile = null;
if (token.getIndex().length > 0) {
dataDirectory = new File(rootDirectory, portName);
for (int i = 0; i < token.getIndex().length - 1; i++) {
dataDirectory = new File(dataDirectory, String
.valueOf(token.getIndex()[i] + 1));
}
dataFile = new File(dataDirectory, String.valueOf(token
.getIndex()[token.getIndex().length - 1] + 1));
} else {
dataFile = new File(dataDirectory, portName);
}
if (!dataDirectory.exists()) {
dataDirectory.mkdirs();
}
if (dataFile.exists()) {
System.err.println("There is already data saved to: "
+ dataFile.getAbsolutePath());
System.exit(-1);
}
saveIndividualDataFile(token.getData(), dataFile, token
.getContext());
}
}
private void saveList(WorkflowDataToken token, String portName) {
File dataDirectory = null;
int[] index = token.getIndex();
if (index.length > 0) {
dataDirectory = new File(rootDirectory, portName);
for (int i = 0; i < index.length - 1; i++) {
dataDirectory = new File(dataDirectory, String.valueOf(token
.getIndex()[i] + 1));
}
dataDirectory = new File(dataDirectory, String.valueOf(token
.getIndex()[index.length - 1]+ 1));
} else {
dataDirectory = new File(rootDirectory, portName);
}
T2Reference reference = token.getData();
IdentifiedList<T2Reference> list = token.getContext()
.getReferenceService().getListService().getList(reference);
saveListItems(token.getContext(), dataDirectory, list);
}
private void saveListItems(InvocationContext context, File dataDirectory,IdentifiedList<T2Reference> list) {
int c = 0;
if (!dataDirectory.exists()) {
dataDirectory.mkdirs();
}
for (T2Reference id : list) {
File dataFile = new File(dataDirectory, String.valueOf(c+1));
if (id.getReferenceType() == T2ReferenceType.IdentifiedList) {
IdentifiedList<T2Reference> innerList = context
.getReferenceService().getListService().getList(id);
saveListItems(context, dataFile, innerList);
}
else {
saveIndividualDataFile(id, dataFile, context);
}
c++;
}
}
protected void saveIndividualDataFile(T2Reference reference, File dataFile,
InvocationContext context) {
if (dataFile.exists()) {
System.err.println("There is already data saved to: "
+ dataFile.getAbsolutePath());
System.exit(-1);
}
Object data = null;
if (reference.containsErrors()) {
ErrorDocument errorDoc = context.getReferenceService()
.getErrorDocumentService().getError(reference);
data = ErrorDocumentHandler.buildErrorDocumentString(errorDoc, context);
dataFile = new File(dataFile.getAbsolutePath()+".error");
} else {
// FIXME: this really should be done using a stream rather
// than an instance of the object in memory
Identified identified = context.getReferenceService().resolveIdentifier(reference, null, context);
ReferenceSet referenceSet = (ReferenceSet) identified;
if (referenceSet.getExternalReferences().isEmpty()) {
data = context.getReferenceService().renderIdentifier(reference,
Object.class, context);
}
else {
ExternalReferenceSPI externalReference = referenceSet.getExternalReferences().iterator().next();
data = externalReference.openStream(context);
}
}
FileOutputStream fos;
try {
fos = new FileOutputStream(dataFile);
if (data instanceof InputStream) {
InputStream inStream = (InputStream)data;
int c;
while ( ( c = inStream.read() ) != -1 ) {
fos.write( (char) c);
}
fos.flush();
fos.close();
}
if (data instanceof byte[]) {
fos.write((byte[]) data);
fos.flush();
fos.close();
} else {
PrintWriter out = new PrintWriter(new OutputStreamWriter(fos));
out.print(data.toString());
out.flush();
out.close();
}
} catch (FileNotFoundException e) {
logger.error("Unable to find the file: '"
+ dataFile.getAbsolutePath() + "' for writing results", e);
} catch (IOException e) {
logger.error("IO Error writing resuts to: '"
+ dataFile.getAbsolutePath(), e);
}
}
}