package org.bridgedb.util.taverna;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bridgedb.BridgeDb;
import org.bridgedb.DataSource;
import org.bridgedb.IDMapper;
import org.bridgedb.IDMapperException;
import org.bridgedb.Xref;
import org.bridgedb.bio.BioDataSource;
import net.sf.taverna.t2.invocation.InvocationContext;
import net.sf.taverna.t2.reference.ReferenceService;
import net.sf.taverna.t2.reference.T2Reference;
import net.sf.taverna.t2.workflowmodel.processor.activity.AbstractAsynchronousActivity;
import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
import net.sf.taverna.t2.workflowmodel.processor.activity.AsynchronousActivity;
import net.sf.taverna.t2.workflowmodel.processor.activity.AsynchronousActivityCallback;
public class BridgeDbActivity extends
AbstractAsynchronousActivity<BridgeDbActivityConfigurationBean>
implements AsynchronousActivity<BridgeDbActivityConfigurationBean> {
/*
* Best practice: Keep port names as constants to avoid misspelling. This
* would not apply if port names are looked up dynamically from the service
* operation, like done for WSDL services.
*/
private static final String IN_ID = "identifier";
private static final String IN_DS = "source datasource";
private static final String IN_DESTDS = "target datasource";
private static final String OUT_IDS = "identifiers";
private static final String OUT_DSS = "datasources";
private BridgeDbActivityConfigurationBean configBean;
private IDMapper mapper;
private boolean isTargetted;
@Override
public void configure(BridgeDbActivityConfigurationBean configBean)
throws ActivityConfigurationException {
// Any pre-config sanity checks
if (configBean.getConnectionString().equals("")) {
}
// Store for getConfiguration(), but you could also make
// getConfiguration() return a new bean from other sources
this.configBean = configBean;
// OPTIONAL:
synchronized(this)
{
String className = configBean.getDriverClass();
String connectionString = configBean.getConnectionString();
BioDataSource.init();
try
{
Class.forName(className);
mapper = BridgeDb.connect (connectionString);
}
catch (ClassNotFoundException ex)
{
throw new ActivityConfigurationException(
"Could not find BridgeDb driver class '" +
className + "'", ex);
}
catch (IDMapperException ex)
{
throw new ActivityConfigurationException(
"Could not establish connection to mapping source '" +
connectionString + "'", ex);
}
}
// REQUIRED: (Re)create input/output ports depending on configuration
configurePorts();
}
protected void configurePorts() {
// In case we are being reconfigured - remove existing ports first
// to avoid duplicates
removeInputs();
removeOutputs();
// FIXME: Replace with your input and output port definitions
// Hard coded input port, expecting a single String
addInput(IN_ID, 0, true, null, String.class);
addInput(IN_DS, 0, true, null, String.class);
// Optional ports depending on configuration
if (isTargetted) {
addInput(IN_DESTDS, 0, true, null, String.class);
}
// Single value output port (depth 0)
// Output port with list of values (depth 1)
addOutput(OUT_IDS, 1);
addOutput(OUT_DSS, 1);
}
@SuppressWarnings("unchecked")
@Override
public void executeAsynch(final Map<String, T2Reference> inputs,
final AsynchronousActivityCallback callback) {
// Don't execute service directly now, request to be run ask to be run
// from thread pool and return asynchronously
callback.requestRun(new Runnable() {
public void run() {
InvocationContext context = callback
.getContext();
ReferenceService referenceService = context
.getReferenceService();
// Resolve inputs
String id = (String) referenceService.renderIdentifier(inputs.get(IN_ID),
String.class, context);
String ds = (String) referenceService.renderIdentifier(inputs.get(IN_DS),
String.class, context);
String targetDs = null;
if (isTargetted)
{
targetDs = (String)referenceService.renderIdentifier(inputs.get(IN_DESTDS),
String.class, context);
}
Set<Xref> result;
Xref srcRef = new Xref (id, DataSource.getByFullName(ds));
try
{
synchronized (this)
{
if (isTargetted)
{
result = mapper.mapID(srcRef, DataSource.getByFullName(targetDs));
}
else
{
result = mapper.mapID(srcRef);
}
}
}
catch (IDMapperException ex)
{
callback.fail("ID mapping of " + srcRef + " failed.", ex);
return;
}
// Register outputs
Map<String, T2Reference> outputs = new HashMap<String, T2Reference>();
String simpleValue = "simple";
T2Reference simpleRef = referenceService.register(simpleValue, 0, true, context);
outputs.put(OUT_IDS, simpleRef);
// For list outputs, only need to register the top level list
List<String> ids = new ArrayList<String>();
List<String> dss = new ArrayList<String>();
for (Xref ref : result)
{
ids.add (ref.getId());
dss.add (ref.getDataSource().getFullName());
}
T2Reference idsRef = referenceService.register(ids, 1, true, context);
outputs.put(OUT_IDS, idsRef);
T2Reference dssRef = referenceService.register(dss, 1, true, context);
outputs.put(OUT_DSS, dssRef);
// if (optionalPorts) {
// // Populate our optional output port
// // NOTE: Need to return output values for all defined output ports
// String report = "Everything OK";
// outputs.put(OUT_DSS, referenceService.register(report,
// 0, true, context));
// }
// return map of output data, with empty index array as this is
// the only and final result (this index parameter is used if
// pipelining output)
callback.receiveResult(outputs, new int[0]);
}
});
}
@Override
public BridgeDbActivityConfigurationBean getConfiguration() {
return this.configBean;
}
}