import jalview.jbgui.*;
import jalview.schemes.*;
import jalview.ws.*;
+import jalview.ws.jws2.Jws2Discoverer;
/**
* DOCUMENT ME!
{
final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws
.get(i);
- jalview.ws.WSClient impl = jalview.ws.Discoverer
+ jalview.ws.WSMenuEntryProviderI impl = jalview.ws.Discoverer
.getServiceClient(sh);
impl.attachWSMenuEntry(msawsmenu, this);
{
final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) secstrpr
.get(i);
- jalview.ws.WSClient impl = jalview.ws.Discoverer
+ jalview.ws.WSMenuEntryProviderI impl = jalview.ws.Discoverer
.getServiceClient(sh);
impl.attachWSMenuEntry(secstrmenu, this);
}
{
final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) seqsrch
.elementAt(i);
- jalview.ws.WSClient impl = jalview.ws.Discoverer
+ jalview.ws.WSMenuEntryProviderI impl = jalview.ws.Discoverer
.getServiceClient(sh);
impl.attachWSMenuEntry(seqsrchmenu, this);
}
wsmenu.add(seqsrchmenu);
}
+ // TODO: move into separate menu builder class.
+ {
+ Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
+ if (jws2servs!=null && jws2servs.hasServices())
+ {
+ JMenu jws2men = new JMenu("Jalview 2 Services");
+ jws2servs.attachWSMenuEntry(jws2men, this);
+ wsmenu.add(jws2men);
+ }
+ }
// finally, add the whole shebang onto the webservices menu
resetWebServiceMenu();
for (int i = 0, j = wsmenu.size(); i < j; i++)
-/*\r
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)\r
- * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle\r
- * \r
- * This file is part of Jalview.\r
- * \r
- * Jalview is free software: you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License \r
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\r
- * \r
- * Jalview is distributed in the hope that it will be useful, but \r
- * WITHOUT ANY WARRANTY; without even the implied warranty \r
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
- * PURPOSE. See the GNU General Public License for more details.\r
- * \r
- * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-package jalview.ws;\r
-\r
-import javax.swing.*;\r
-\r
-import jalview.bin.*;\r
-import jalview.datamodel.*;\r
-import jalview.gui.*;\r
-import jalview.gui.FeatureRenderer.FeatureRendererSettings;\r
-\r
-public abstract class WSThread extends Thread\r
-{\r
- /**\r
- * Generic properties for Web Service Client threads.\r
- */\r
- /**\r
- * view that this job was associated with\r
- */\r
- AlignmentI currentView = null;\r
-\r
- /**\r
- * feature settings from view that job was associated with\r
- */\r
- FeatureRendererSettings featureSettings = null;\r
-\r
- /**\r
- * metadata about this web service\r
- */\r
- WebserviceInfo wsInfo = null;\r
-\r
- /**\r
- * original input data for this job\r
- */\r
- AlignmentView input = null;\r
-\r
- /**\r
- * dataset sequence relationships to be propagated onto new results\r
- */\r
- AlignedCodonFrame[] codonframe = null;\r
-\r
- /**\r
- * are there jobs still running in this thread.\r
- */\r
- boolean jobComplete = false;\r
-\r
- abstract class WSJob\r
- {\r
- /**\r
- * Generic properties for an individual job within a Web Service Client\r
- * thread\r
- */\r
- int jobnum = 0; // WebServiceInfo pane for this job\r
-\r
- String jobId; // ws job ticket\r
-\r
- /**\r
- * has job been cancelled\r
- */\r
- boolean cancelled = false;\r
-\r
- /**\r
- * number of exceptions left before job dies\r
- */\r
- int allowedServerExceptions = 3;\r
-\r
- /**\r
- * has job been submitted\r
- */\r
- boolean submitted = false;\r
-\r
- /**\r
- * are all sub-jobs complete\r
- */\r
- boolean subjobComplete = false;\r
-\r
- /**\r
- * \r
- * @return true if job has completed and valid results are available\r
- */\r
- abstract boolean hasResults();\r
-\r
- /**\r
- * \r
- * @return boolean true if job can be submitted.\r
- */\r
- abstract boolean hasValidInput();\r
-\r
- /**\r
- * The last result object returned by the service.\r
- */\r
- vamsas.objects.simple.Result result;\r
- }\r
-\r
- class JobStateSummary\r
- {\r
- /**\r
- * number of jobs running\r
- */\r
- int running = 0;\r
-\r
- /**\r
- * number of jobs queued\r
- */\r
- int queuing = 0;\r
-\r
- /**\r
- * number of jobs finished\r
- */\r
- int finished = 0;\r
-\r
- /**\r
- * number of jobs failed\r
- */\r
- int error = 0;\r
-\r
- /**\r
- * number of jobs stopped due to server error\r
- */\r
- int serror = 0;\r
-\r
- /**\r
- * number of jobs cancelled\r
- */\r
- int cancelled = 0;\r
-\r
- /**\r
- * number of jobs finished with results\r
- */\r
- int results = 0;\r
-\r
- /**\r
- * processes WSJob and updates job status counters and WebService status\r
- * displays\r
- * \r
- * @param wsInfo\r
- * @param OutputHeader\r
- * @param j\r
- */\r
- void updateJobPanelState(WebserviceInfo wsInfo, String OutputHeader,\r
- WSJob j)\r
- {\r
- if (j.result != null)\r
- {\r
- String progheader = "";\r
- // Parse state of job[j]\r
- if (j.result.isRunning())\r
- {\r
- running++;\r
- wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_RUNNING);\r
- }\r
- else if (j.result.isQueued())\r
- {\r
- queuing++;\r
- wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_QUEUING);\r
- }\r
- else if (j.result.isFinished())\r
- {\r
- finished++;\r
- j.subjobComplete = true;\r
- if (j.hasResults())\r
- {\r
- results++;\r
- }\r
- wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_OK);\r
- }\r
- else if (j.result.isFailed())\r
- {\r
- progheader += "Job failed.\n";\r
- j.subjobComplete = true;\r
- wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);\r
- error++;\r
- }\r
- else if (j.result.isServerError())\r
- {\r
- serror++;\r
- j.subjobComplete = true;\r
- wsInfo.setStatus(j.jobnum,\r
- WebserviceInfo.STATE_STOPPED_SERVERERROR);\r
- }\r
- else if (j.result.isBroken() || j.result.isFailed())\r
- {\r
- error++;\r
- j.subjobComplete = true;\r
- wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);\r
- }\r
- // and pass on any sub-job messages to the user\r
- wsInfo.setProgressText(j.jobnum, OutputHeader);\r
- wsInfo.appendProgressText(j.jobnum, progheader);\r
- if (j.result.getStatus() != null)\r
- {\r
- wsInfo.appendProgressText(j.jobnum, j.result.getStatus());\r
- }\r
- }\r
- else\r
- {\r
- if (j.submitted && j.subjobComplete)\r
- {\r
- if (j.allowedServerExceptions == 0)\r
- {\r
- serror++;\r
- }\r
- else if (j.result == null)\r
- {\r
- error++;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * one or more jobs being managed by this thread.\r
- */\r
- WSJob jobs[] = null;\r
-\r
- /**\r
- * full name of service\r
- */\r
- String WebServiceName = null;\r
-\r
- String OutputHeader;\r
-\r
- String WsUrl = null;\r
-\r
- /**\r
- * query web service for status of job. on return, job.result must not be null\r
- * - if it is then it will be assumed that the job status query timed out and\r
- * a server exception will be logged.\r
- * \r
- * @param job\r
- * @throws Exception\r
- * will be logged as a server exception for this job\r
- */\r
- abstract void pollJob(WSJob job) throws Exception;\r
-\r
- public void run()\r
- {\r
- JobStateSummary jstate = null;\r
- if (jobs == null)\r
- {\r
- jobComplete = true;\r
- }\r
- while (!jobComplete)\r
- {\r
- jstate = new JobStateSummary();\r
- for (int j = 0; j < jobs.length; j++)\r
- {\r
-\r
- if (!jobs[j].submitted && jobs[j].hasValidInput())\r
- {\r
- StartJob(jobs[j]);\r
- }\r
-\r
- if (jobs[j].submitted && !jobs[j].subjobComplete)\r
- {\r
- try\r
- {\r
- pollJob(jobs[j]);\r
- if (jobs[j].result == null)\r
- {\r
- throw (new Exception(\r
- "Timed out when communicating with server\nTry again later.\n"));\r
- }\r
- jalview.bin.Cache.log.debug("Job " + j + " Result state "\r
- + jobs[j].result.getState() + "(ServerError="\r
- + jobs[j].result.isServerError() + ")");\r
- } catch (Exception ex)\r
- {\r
- // Deal with Transaction exceptions\r
- wsInfo.appendProgressText(jobs[j].jobnum, "\n" + WebServiceName\r
- + " Server exception!\n" + ex.getMessage());\r
- Cache.log.warn(WebServiceName + " job(" + jobs[j].jobnum\r
- + ") Server exception: " + ex.getMessage());\r
-\r
- if (jobs[j].allowedServerExceptions > 0)\r
- {\r
- jobs[j].allowedServerExceptions--;\r
- Cache.log.debug("Sleeping after a server exception.");\r
- try\r
- {\r
- Thread.sleep(5000);\r
- } catch (InterruptedException ex1)\r
- {\r
- }\r
- }\r
- else\r
- {\r
- Cache.log.warn("Dropping job " + j + " " + jobs[j].jobId);\r
- jobs[j].subjobComplete = true;\r
- wsInfo.setStatus(jobs[j].jobnum,\r
- WebserviceInfo.STATE_STOPPED_SERVERERROR);\r
- }\r
- } catch (OutOfMemoryError er)\r
- {\r
- jobComplete = true;\r
- jobs[j].subjobComplete = true;\r
- jobs[j].result = null; // may contain out of date result object\r
- wsInfo.setStatus(jobs[j].jobnum,\r
- WebserviceInfo.STATE_STOPPED_ERROR);\r
- Cache.log.error("Out of memory when retrieving Job " + j\r
- + " id:" + WsUrl + "/" + jobs[j].jobId, er);\r
- new jalview.gui.OOMWarning("retrieving result for "\r
- + WebServiceName, er);\r
- System.gc();\r
- }\r
- }\r
- jstate.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);\r
- }\r
- // Decide on overall state based on collected jobs[] states\r
- if (jstate.running > 0)\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);\r
- }\r
- else if (jstate.queuing > 0)\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);\r
- }\r
- else\r
- {\r
- jobComplete = true;\r
- if (jstate.finished > 0)\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);\r
- }\r
- else if (jstate.error > 0)\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);\r
- }\r
- else if (jstate.serror > 0)\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);\r
- }\r
- }\r
- if (!jobComplete)\r
- {\r
- try\r
- {\r
- Thread.sleep(5000);\r
- } catch (InterruptedException e)\r
- {\r
- Cache.log\r
- .debug("Interrupted sleep waiting for next job poll.", e);\r
- }\r
- // System.out.println("I'm alive "+alTitle);\r
- }\r
- }\r
- if (jobComplete && jobs != null)\r
- {\r
- parseResult(); // tidy up and make results available to user\r
- }\r
- else\r
- {\r
- Cache.log\r
- .debug("WebServiceJob poll loop finished with no jobs created.");\r
- wsInfo.setFinishedNoResults();\r
- }\r
- }\r
-\r
- /**\r
- * submit job to web service\r
- * \r
- * @param job\r
- */\r
- abstract void StartJob(WSJob job);\r
-\r
- /**\r
- * process the set of WSJob objects into a set of results, and tidy up.\r
- */\r
- abstract void parseResult();\r
-\r
- /**\r
- * helper function to conserve dataset references to sequence objects returned\r
- * from web services 1. Propagates AlCodonFrame data from\r
- * <code>codonframe</code> to <code>al</code>\r
- * \r
- * @param al\r
- */\r
- protected void propagateDatasetMappings(Alignment al)\r
- {\r
- if (codonframe != null)\r
- {\r
- SequenceI[] alignment = al.getSequencesArray();\r
- for (int sq = 0; sq < alignment.length; sq++)\r
- {\r
- for (int i = 0; i < codonframe.length; i++)\r
- {\r
- if (codonframe[i] != null\r
- && codonframe[i].involvesSequence(alignment[sq]))\r
- {\r
- al.addCodonFrame(codonframe[i]);\r
- codonframe[i] = null;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * \r
- * @param alignFrame\r
- * reference for copying mappings across\r
- * @param wsInfo\r
- * gui attachment point\r
- * @param input\r
- * input data for the calculation\r
- * @param webServiceName\r
- * name of service\r
- * @param wsUrl\r
- * url of the service being invoked\r
- */\r
- public WSThread(AlignFrame alignFrame, WebserviceInfo wsinfo,\r
- AlignmentView input, String webServiceName, String wsUrl)\r
- {\r
- this(alignFrame, wsinfo, input, wsUrl);\r
- WebServiceName = webServiceName;\r
- }\r
-\r
- char defGapChar = '-';\r
-\r
- /**\r
- * \r
- * @return gap character to use for any alignment generation\r
- */\r
- public char getGapChar()\r
- {\r
- return defGapChar;\r
- }\r
-\r
- /**\r
- * \r
- * @param alframe\r
- * - reference for copying mappings and display styles across\r
- * @param wsinfo2\r
- * - gui attachment point\r
- * @param alview\r
- * - input data for the calculation\r
- * @param wsurl2\r
- * - url of the service being invoked\r
- */\r
- public WSThread(AlignFrame alframe, WebserviceInfo wsinfo2,\r
- AlignmentView alview, String wsurl2)\r
- {\r
- super();\r
- // this.alignFrame = alframe;\r
- currentView = alframe.getCurrentView().getAlignment();\r
- featureSettings = alframe.getFeatureRenderer().getSettings();\r
- defGapChar = alframe.getViewport().getGapCharacter();\r
- this.wsInfo = wsinfo2;\r
- this.input = alview;\r
- WsUrl = wsurl2;\r
- if (alframe != null)\r
- {\r
- AlignedCodonFrame[] cf = alframe.getViewport().getAlignment()\r
- .getCodonFrames();\r
- if (cf != null)\r
- {\r
- codonframe = new AlignedCodonFrame[cf.length];\r
- System.arraycopy(cf, 0, codonframe, 0, cf.length);\r
- }\r
- }\r
- }\r
-}\r
+package jalview.ws;
+
+import jalview.bin.Cache;
+import jalview.datamodel.AlignedCodonFrame;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.WebserviceInfo;
+import jalview.gui.FeatureRenderer.FeatureRendererSettings;
+
+public abstract class AWSThread extends Thread
+{
+
+ /**
+ * view that this job was associated with
+ */
+ protected AlignmentI currentView = null;
+ /**
+ * feature settings from view that job was associated with
+ */
+ protected FeatureRendererSettings featureSettings = null;
+ /**
+ * metadata about this web service
+ */
+ protected WebserviceInfo wsInfo = null;
+ /**
+ * original input data for this job
+ */
+ protected AlignmentView input = null;
+ /**
+ * dataset sequence relationships to be propagated onto new results
+ */
+ protected AlignedCodonFrame[] codonframe = null;
+ /**
+ * are there jobs still running in this thread.
+ */
+ protected boolean jobComplete = false;
+ /**
+ * one or more jobs being managed by this thread.
+ */
+ protected AWsJob jobs[] = null;
+ /**
+ * full name of service
+ */
+ protected String WebServiceName = null;
+ protected char defGapChar = '-';
+ /**
+ * header prepended to all output from job
+ */
+ protected String OutputHeader;
+
+ /**
+ * only used when reporting a web service out of memory error - the job ID will be concatenated to the URL
+ */
+ protected String WsUrl = null;
+
+ /**
+ * generic web service job/subjob poll loop
+ */
+ public void run()
+ {
+ JobStateSummary jstate = null;
+ if (jobs == null)
+ {
+ jobComplete = true;
+ }
+ while (!jobComplete)
+ {
+ jstate = new JobStateSummary();
+ for (int j = 0; j < jobs.length; j++)
+ {
+
+ if (!jobs[j].submitted && jobs[j].hasValidInput())
+ {
+ StartJob(jobs[j]);
+ }
+
+ if (jobs[j].submitted && !jobs[j].subjobComplete)
+ {
+ try
+ {
+ pollJob(jobs[j]);
+ if (!jobs[j].hasResponse())
+ {
+ throw (new Exception(
+ "Timed out when communicating with server\nTry again later.\n"));
+ }
+ jalview.bin.Cache.log.debug("Job " + j + " Result state "
+ + jobs[j].getState() + "(ServerError="
+ + jobs[j].isServerError() + ")");
+ } catch (Exception ex)
+ {
+ if (Cache.log.isDebugEnabled())
+ {
+ Cache.log.debug(ex);
+ }
+ // Deal with Transaction exceptions
+ wsInfo.appendProgressText(jobs[j].jobnum, "\n" + WebServiceName
+ + " Server exception!\n" + ex.getMessage());
+ Cache.log.warn(WebServiceName + " job(" + jobs[j].jobnum
+ + ") Server exception: " + ex.getMessage());
+
+ if (jobs[j].allowedServerExceptions > 0)
+ {
+ jobs[j].allowedServerExceptions--;
+ Cache.log.debug("Sleeping after a server exception.");
+ try
+ {
+ Thread.sleep(5000);
+ } catch (InterruptedException ex1)
+ {
+ }
+ }
+ else
+ {
+ Cache.log.warn("Dropping job " + j + " " + jobs[j].jobId);
+ jobs[j].subjobComplete = true;
+ wsInfo.setStatus(jobs[j].jobnum,
+ WebserviceInfo.STATE_STOPPED_SERVERERROR);
+ }
+ } catch (OutOfMemoryError er)
+ {
+ jobComplete = true;
+ jobs[j].subjobComplete = true;
+ jobs[j].clearResponse(); // may contain out of date result data
+ wsInfo.setStatus(jobs[j].jobnum,
+ WebserviceInfo.STATE_STOPPED_ERROR);
+ Cache.log.error("Out of memory when retrieving Job " + j
+ + " id:" + WsUrl + "/" + jobs[j].jobId, er);
+ new jalview.gui.OOMWarning("retrieving result for "
+ + WebServiceName, er);
+ System.gc();
+ }
+ }
+ jstate.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
+ }
+ // Decide on overall state based on collected jobs[] states
+ if (jstate.running > 0)
+ {
+ wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
+ }
+ else if (jstate.queuing > 0)
+ {
+ wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
+ }
+ else
+ {
+ jobComplete = true;
+ if (jstate.finished > 0)
+ {
+ wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
+ }
+ else if (jstate.error > 0)
+ {
+ wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+ }
+ else if (jstate.serror > 0)
+ {
+ wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
+ }
+ }
+ if (!jobComplete)
+ {
+ try
+ {
+ Thread.sleep(5000);
+ } catch (InterruptedException e)
+ {
+ Cache.log
+ .debug("Interrupted sleep waiting for next job poll.", e);
+ }
+ // System.out.println("I'm alive "+alTitle);
+ }
+ }
+ if (jobComplete && jobs != null)
+ {
+ parseResult(); // tidy up and make results available to user
+ }
+ else
+ {
+ Cache.log
+ .debug("WebServiceJob poll loop finished with no jobs created.");
+ wsInfo.setFinishedNoResults();
+ }
+ }
+
+
+ public AWSThread()
+ {
+ super();
+ }
+
+ public AWSThread(Runnable target)
+ {
+ super(target);
+ }
+
+ public AWSThread(String name)
+ {
+ super(name);
+ }
+
+ public AWSThread(ThreadGroup group, Runnable target)
+ {
+ super(group, target);
+ }
+
+ public AWSThread(ThreadGroup group, String name)
+ {
+ super(group, name);
+ }
+
+ public AWSThread(Runnable target, String name)
+ {
+ super(target, name);
+ }
+
+ public AWSThread(ThreadGroup group, Runnable target, String name)
+ {
+ super(group, target, name);
+ }
+
+ /**
+ * query web service for status of job. on return, job.result must not be null
+ * - if it is then it will be assumed that the job status query timed out and
+ * a server exception will be logged.
+ *
+ * @param job
+ * @throws Exception
+ * will be logged as a server exception for this job
+ */
+ public abstract void pollJob(AWsJob job) throws Exception;
+
+ /**
+ * submit job to web service
+ *
+ * @param job
+ */
+ public abstract void StartJob(AWsJob job);
+
+ /**
+ * process the set of AWsJob objects into a set of results, and tidy up.
+ */
+ public abstract void parseResult();
+
+ /**
+ * helper function to conserve dataset references to sequence objects returned
+ * from web services 1. Propagates AlCodonFrame data from
+ * <code>codonframe</code> to <code>al</code>
+ * TODO: refactor to datamodel
+ * @param al
+ */
+ public void propagateDatasetMappings(Alignment al)
+ {
+ if (codonframe != null)
+ {
+ SequenceI[] alignment = al.getSequencesArray();
+ for (int sq = 0; sq < alignment.length; sq++)
+ {
+ for (int i = 0; i < codonframe.length; i++)
+ {
+ if (codonframe[i] != null
+ && codonframe[i].involvesSequence(alignment[sq]))
+ {
+ al.addCodonFrame(codonframe[i]);
+ codonframe[i] = null;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public AWSThread(ThreadGroup group, Runnable target, String name,
+ long stackSize)
+ {
+ super(group, target, name, stackSize);
+ }
+
+ /**
+ *
+ * @return gap character to use for any alignment generation
+ */
+ public char getGapChar()
+ {
+ return defGapChar;
+ }
+
+ /**
+ *
+ * @param alignFrame
+ * reference for copying mappings across
+ * @param wsInfo
+ * gui attachment point
+ * @param input
+ * input data for the calculation
+ * @param webServiceName
+ * name of service
+ * @param wsUrl
+ * url of the service being invoked
+ */
+ public AWSThread(AlignFrame alignFrame, WebserviceInfo wsinfo,
+ AlignmentView input, String webServiceName, String wsUrl)
+ {
+ this(alignFrame, wsinfo, input, wsUrl);
+ WebServiceName = webServiceName;
+ }
+
+ /**
+ *
+ * @param alframe
+ * - reference for copying mappings and display styles across
+ * @param wsinfo2
+ * - gui attachment point
+ * @param alview
+ * - input data for the calculation
+ * @param wsurl2
+ * - url of the service being invoked
+ */
+ public AWSThread(AlignFrame alframe, WebserviceInfo wsinfo2,
+ AlignmentView alview, String wsurl2)
+ {
+ super();
+ // this.alignFrame = alframe;
+ currentView = alframe.getCurrentView().getAlignment();
+ featureSettings = alframe.getFeatureRenderer().getSettings();
+ defGapChar = alframe.getViewport().getGapCharacter();
+ this.wsInfo = wsinfo2;
+ this.input = alview;
+ WsUrl = wsurl2;
+ if (alframe != null)
+ {
+ AlignedCodonFrame[] cf = alframe.getViewport().getAlignment()
+ .getCodonFrames();
+ if (cf != null)
+ {
+ codonframe = new AlignedCodonFrame[cf.length];
+ System.arraycopy(cf, 0, codonframe, 0, cf.length);
+ }
+ }
+ }
+}
--- /dev/null
+package jalview.ws;
+
+/**
+ * Generic properties for an individual job within a Web Service Client thread.
+ * Derived from jalview web services version 1 statuses, and revised for Jws2.
+ */
+
+public abstract class AWsJob
+{
+ protected int jobnum = 0;
+
+ protected String jobId;
+
+ /**
+ * @param jobId the jobId to set
+ */
+ public void setJobId(String jobId)
+ {
+ this.jobId = jobId;
+ }
+
+ /**
+ * has job been cancelled
+ */
+ protected boolean cancelled = false;
+
+ /**
+ * number of exceptions left before job dies
+ */
+ int allowedServerExceptions = 3;
+
+ /**
+ * @param allowedServerExceptions the allowedServerExceptions to set
+ */
+ public void setAllowedServerExceptions(int allowedServerExceptions)
+ {
+ this.allowedServerExceptions = allowedServerExceptions;
+ }
+
+ /**
+ * has job been submitted to server ? if false, then no state info is
+ * available.
+ */
+ protected boolean submitted = false;
+
+ /**
+ * @param jobnum the jobnum to set
+ */
+ public void setJobnum(int jobnum)
+ {
+ this.jobnum = jobnum;
+ }
+
+ /**
+ * @param submitted the submitted to set
+ */
+ public void setSubmitted(boolean submitted)
+ {
+ this.submitted = submitted;
+ }
+
+ /**
+ * @param subjobComplete the subjobComplete to set
+ */
+ public void setSubjobComplete(boolean subjobComplete)
+ {
+ this.subjobComplete = subjobComplete;
+ }
+
+ /**
+ * @return the jobnum
+ */
+ public int getJobnum()
+ {
+ return jobnum;
+ }
+
+ /**
+ * @return the jobId
+ */
+ public String getJobId()
+ {
+ return jobId;
+ }
+
+ /**
+ * @return the cancelled
+ */
+ public boolean isCancelled()
+ {
+ return cancelled;
+ }
+
+ /**
+ * @return the allowedServerExceptions
+ */
+ public int getAllowedServerExceptions()
+ {
+ return allowedServerExceptions;
+ }
+
+ /**
+ * @return the submitted
+ */
+ public boolean isSubmitted()
+ {
+ return submitted;
+ }
+
+ /**
+ * @return the subjobComplete
+ */
+ public boolean isSubjobComplete()
+ {
+ return subjobComplete;
+ }
+
+ /**
+ * are all sub-jobs complete
+ */
+ protected boolean subjobComplete = false;
+
+ public AWsJob()
+ {
+ }
+
+ /**
+ *
+ * @return true if job has completed and valid results are available
+ */
+ abstract public boolean hasResults();
+
+ /**
+ *
+ * @return boolean true if job can be submitted.
+ */
+ public abstract boolean hasValidInput();
+
+ /**
+ *
+ * @return true if job is running
+ */
+ abstract public boolean isRunning();
+
+ /**
+ *
+ * @return true if job is queued
+ */
+ abstract public boolean isQueued();
+
+ /**
+ *
+ * @return true if job has finished
+ */
+ abstract public boolean isFinished();
+
+ /**
+ *
+ * @return true if the job failed due to some problem with the input data or
+ * parameters.
+ */
+ abstract public boolean isFailed();
+
+ /**
+ *
+ * @return true if job failed due to an unhandled technical issue
+ */
+ abstract public boolean isBroken();
+
+ /**
+ *
+ * @return true if there was a problem contacting the server.
+ */
+ abstract public boolean isServerError();
+
+ /**
+ *
+ * @return true if the job has status text.
+ */
+ abstract public boolean hasStatus();
+
+ /**
+ *
+ * @return status text for job to be displayed to user.
+ */
+ abstract public String getStatus();
+
+ abstract public boolean hasResponse();
+ abstract public void clearResponse();
+ abstract public String getState();
+ /**
+ * generates response using the abstract service flags.
+ * @return a standard state response
+ */
+ protected String _defaultState() {
+
+ String state = "";
+ return state;
+ }
+}
\ No newline at end of file
*/
private static Hashtable serviceClientBindings;
- public static WSClient getServiceClient(ServiceHandle sh)
+ public static WS1Client getServiceClient(ServiceHandle sh)
{
if (serviceClientBindings == null)
{
serviceClientBindings.put("SecStrPred", new JPredClient());
serviceClientBindings.put("SeqSearch", new SeqSearchWSClient());
}
- WSClient instance = (WSClient) serviceClientBindings.get(sh
+ WS1Client instance = (WS1Client) serviceClientBindings.get(sh
.getAbstractName());
if (instance == null)
{
import jalview.datamodel.*;
import jalview.gui.*;
-public class JPredClient extends WSClient
+public class JPredClient extends WS1Client
{
/**
* crate a new GUI JPred Job
import jalview.analysis.*;\r
import jalview.bin.*;\r
import jalview.datamodel.*;\r
-import jalview.datamodel.Alignment;\r
import jalview.gui.*;\r
import jalview.io.*;\r
import jalview.util.*;\r
import vamsas.objects.simple.JpredResult;\r
\r
-class JPredThread extends WSThread implements WSClientI\r
+class JPredThread extends JWS1Thread implements WSClientI\r
{\r
// TODO: put mapping between JPredJob input and input data here -\r
// JNetAnnotation adding is done after result parsing.\r
- class JPredJob extends WSThread.WSJob\r
+ class JPredJob extends WSJob\r
{\r
// TODO: make JPredJob deal only with what was sent to and received from a\r
// JNet service\r
return false;\r
}\r
\r
- boolean hasValidInput()\r
+ public boolean hasValidInput()\r
{\r
if (sequence != null)\r
{\r
}\r
}\r
\r
- void StartJob(WSJob j)\r
+ public void StartJob(AWsJob j)\r
{\r
if (!(j instanceof JPredJob))\r
{\r
}\r
}\r
\r
- void parseResult()\r
+ public void parseResult()\r
{\r
int results = 0; // number of result sets received\r
JobStateSummary finalState = new JobStateSummary();\r
}\r
}\r
\r
- void pollJob(WSJob job) throws Exception\r
+ public void pollJob(AWsJob job) throws Exception\r
{\r
- job.result = server.getresult(job.jobId);\r
+ ((JPredJob)job).result = server.getresult(job.jobId);\r
}\r
\r
public boolean isCancellable()\r
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
+ * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview 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.
+ *
+ * Jalview 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 Jalview. If not, see <http://www.gnu.org/licenses/>.
+ */
+package jalview.ws;
+
+import javax.swing.*;
+
+import jalview.bin.*;
+import jalview.datamodel.*;
+import jalview.gui.*;
+
+/**
+ * specific methods for Jalview WS1 web service jobs
+ * (will probably disappear)
+ * @author JimP
+ *
+ */
+public abstract class JWS1Thread extends AWSThread
+{
+
+ public JWS1Thread(AlignFrame alFrame, WebserviceInfo wsinfo,
+ AlignmentView alview, String wsname, String wsUrl)
+ {
+ super(alFrame, wsinfo, alview, wsname, wsUrl);
+ }
+
+ public JWS1Thread(AlignFrame alframe, WebserviceInfo wsinfo,
+ AlignmentView alview, String wsurl)
+ {
+ super(alframe, wsinfo, alview, wsurl);
+ }
+
+}
--- /dev/null
+package jalview.ws;
+
+import jalview.gui.WebserviceInfo;
+
+/**
+ * bookkeeper class for the WebServiceInfo GUI, maintaining records of web
+ * service jobs handled by the window and reflecting any status updates.
+ *
+ * @author JimP
+ *
+ */
+public class JobStateSummary
+{
+ /**
+ * number of jobs running
+ */
+ int running = 0;
+
+ /**
+ * number of jobs queued
+ */
+ int queuing = 0;
+
+ /**
+ * number of jobs finished
+ */
+ int finished = 0;
+
+ /**
+ * number of jobs failed
+ */
+ int error = 0;
+
+ /**
+ * number of jobs stopped due to server error
+ */
+ int serror = 0;
+
+ /**
+ * number of jobs cancelled
+ */
+ int cancelled = 0;
+
+ /**
+ * number of jobs finished with results
+ */
+ int results = 0;
+
+ /**
+ * processes an AWSJob's status and updates job status counters and WebService
+ * status displays
+ *
+ * @param wsInfo
+ * @param OutputHeader
+ * @param j
+ */
+ public void updateJobPanelState(WebserviceInfo wsInfo, String OutputHeader,
+ AWsJob j)
+ {
+ if (j.submitted)
+ {
+ String progheader = "";
+ // Parse state of job[j]
+ if (j.isRunning())
+ {
+ running++;
+ wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_RUNNING);
+ }
+ else if (j.isQueued())
+ {
+ queuing++;
+ wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_QUEUING);
+ }
+ else if (j.isFinished())
+ {
+ finished++;
+ j.subjobComplete = true;
+ if (j.hasResults())
+ {
+ results++;
+ }
+ wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_OK);
+ }
+ else if (j.isFailed())
+ {
+ progheader += "Job failed.\n";
+ j.subjobComplete = true;
+ wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
+ error++;
+ }
+ else if (j.isServerError())
+ {
+ serror++;
+ j.subjobComplete = true;
+ wsInfo
+ .setStatus(j.jobnum,
+ WebserviceInfo.STATE_STOPPED_SERVERERROR);
+ }
+ else if (j.isBroken())
+ {
+ progheader += "Job was broken.\n";
+ error++;
+ j.subjobComplete = true;
+ wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
+ }
+ // and pass on any sub-job messages to the user
+ wsInfo.setProgressText(j.jobnum, OutputHeader);
+ wsInfo.appendProgressText(j.jobnum, progheader);
+ if (j.hasStatus())
+ {
+ wsInfo.appendProgressText(j.jobnum, j.getStatus());
+ }
+ }
+ else
+ {
+ if (j.submitted && j.subjobComplete)
+ {
+ if (j.allowedServerExceptions == 0)
+ {
+ serror++;
+ }
+ else if (!j.hasResults())
+ {
+ error++;
+ }
+ }
+ }
+ }
+}
* @author $author$
* @version $Revision$
*/
-public class MsaWSClient extends WSClient
+public class MsaWSClient extends WS1Client
{
/**
* server is a WSDL2Java generated stub for an archetypal MsaWSI service.
import jalview.analysis.*;\r
import jalview.bin.*;\r
import jalview.datamodel.*;\r
-import jalview.datamodel.Alignment;\r
import jalview.gui.*;\r
import vamsas.objects.simple.MsaResult;\r
\r
* @author not attributable\r
* @version 1.0\r
*/\r
-class MsaWSThread extends WSThread implements WSClientI\r
+class MsaWSThread extends JWS1Thread implements WSClientI\r
{\r
boolean submitGaps = false; // pass sequences including gaps to alignment\r
\r
\r
// order\r
\r
- class MsaWSJob extends WSThread.WSJob\r
+ class MsaWSJob extends WSJob\r
{\r
// hold special input for this\r
vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple.SequenceSet();\r
* \r
* @return boolean true if job can be submitted.\r
*/\r
- boolean hasValidInput()\r
+ public boolean hasValidInput()\r
{\r
if (seqs.getSeqs() != null)\r
{\r
}\r
}\r
\r
- void pollJob(WSJob job) throws Exception\r
+ public void pollJob(AWsJob job) throws Exception\r
{\r
((MsaWSJob) job).result = server.getResult(((MsaWSJob) job).jobId);\r
}\r
\r
- void StartJob(WSJob job)\r
+ public void StartJob(AWsJob job)\r
{\r
if (!(job instanceof MsaWSJob))\r
{\r
return msa;\r
}\r
\r
- void parseResult()\r
+ public void parseResult()\r
{\r
int results = 0; // number of result sets received\r
JobStateSummary finalState = new JobStateSummary();\r
&& jobs[j].hasResults())\r
{\r
results++;\r
- vamsas.objects.simple.Alignment valign = ((MsaResult) jobs[j].result)\r
+ vamsas.objects.simple.Alignment valign = ((MsaResult)((MsaWSJob) jobs[j]).result)\r
.getMsa();\r
if (valign != null)\r
{\r
* @author $author$\r
* @version $Revision$\r
*/\r
-public class SeqSearchWSClient extends WSClient\r
+public class SeqSearchWSClient extends WS1Client\r
{\r
/**\r
* server is a WSDL2Java generated stub for an archetypal MsaWSI service.\r
* @author not attributable\r
* @version 1.0\r
*/\r
-class SeqSearchWSThread extends WSThread implements WSClientI\r
+class SeqSearchWSThread extends JWS1Thread implements WSClientI\r
{\r
String dbs = null;\r
\r
boolean profile = false;\r
\r
- class SeqSearchWSJob extends WSThread.WSJob\r
+ class SeqSearchWSJob extends WSJob\r
{\r
// hold special input for this\r
vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple.SequenceSet();\r
* \r
* @return boolean true if job can be submitted.\r
*/\r
- boolean hasValidInput()\r
+ public boolean hasValidInput()\r
{\r
if (seqs.getSeqs() != null)\r
{\r
}\r
}\r
\r
- void pollJob(WSJob job) throws Exception\r
+ public void pollJob(AWsJob job) throws Exception\r
{\r
((SeqSearchWSJob) job).result = server\r
.getResult(((SeqSearchWSJob) job).jobId);\r
}\r
\r
- void StartJob(WSJob job)\r
+ public void StartJob(AWsJob job)\r
{\r
if (!(job instanceof SeqSearchWSJob))\r
{\r
return msa;\r
}\r
\r
- void parseResult()\r
+ public void parseResult()\r
{\r
int results = 0; // number of result sets received\r
JobStateSummary finalState = new JobStateSummary();\r
&& jobs[j].hasResults())\r
{\r
results++;\r
- vamsas.objects.simple.Alignment valign = ((SeqSearchResult) jobs[j].result)\r
+ vamsas.objects.simple.Alignment valign = ((SeqSearchResult) ((SeqSearchWSJob)jobs[j]).result)\r
.getAlignment();\r
if (valign != null)\r
{\r
--- /dev/null
+/**
+ *
+ */
+package jalview.ws;
+
+import jalview.gui.AlignFrame;
+import jalview.gui.WebserviceInfo;
+
+import javax.swing.JMenu;
+
+import ext.vamsas.ServiceHandle;
+
+/**
+ * JWS1 Specific UI attributes and methods
+ * @author JimP
+ *
+ */
+public abstract class WS1Client extends WSClient implements WSMenuEntryProviderI
+{
+
+ /**
+ * original service handle that this client was derived from
+ */
+ ServiceHandle serviceHandle = null;
+
+ /**
+ * default constructor
+ */
+ public WS1Client()
+ {
+ super();
+ }
+
+ /**
+ * initialise WSClient service information attributes from the service handle
+ *
+ * @param sh
+ * @return the service instance information GUI for this client and job.
+ */
+ protected WebserviceInfo setWebService(ServiceHandle sh)
+ {
+ return setWebService(sh, false);
+ }
+
+ /**
+ * initialise WSClient service information attributes from the service handle
+ *
+ * @param sh
+ * @param headless
+ * true implies no GUI objects will be created.
+ * @return the service instance information GUI for this client and job.
+ */
+ protected WebserviceInfo setWebService(ServiceHandle sh, boolean headless)
+ {
+ WebServiceName = sh.getName();
+ if (ServiceActions.containsKey(sh.getAbstractName()))
+ {
+ WebServiceJobTitle = sh.getName(); // TODO: control sh.Name specification
+ // properly
+ // add this for short names. +(String)
+ // ServiceActions.get(sh.getAbstractName());
+ }
+ else
+ {
+ WebServiceJobTitle = sh.getAbstractName() + " using " + sh.getName();
+
+ }
+ WebServiceReference = sh.getDescription();
+ WsURL = sh.getEndpointURL();
+ WebserviceInfo wsInfo = null;
+ if (!headless)
+ {
+ wsInfo = new WebserviceInfo(WebServiceJobTitle, WebServiceReference);
+ }
+ return wsInfo;
+ }
+
+ /**
+ * convenience method to pass the serviceHandle reference that instantiated
+ * this service on to the menu entry constructor
+ *
+ * @param wsmenu
+ * the menu to which any menu entries/sub menus are to be attached
+ * @param alignFrame
+ * the alignFrame instance that provides input data for the service
+ */
+ public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
+ {
+ if (serviceHandle == null)
+ {
+ throw new Error(
+ "IMPLEMENTATION ERROR: cannot attach WS Menu Entry without service handle reference!");
+ }
+ attachWSMenuEntry(wsmenu, serviceHandle, alignFrame);
+ }
+
+ /**
+ * method implemented by each concrete WS1Client implementation that creates menu
+ * entries that enact their service using data from alignFrame.
+ *
+ * @param wsmenu
+ * where new menu entries (and submenus) are to be attached
+ * @param serviceHandle
+ * the serviceHandle document for the service that entries are
+ * created for
+ * @param alignFrame
+ */
+ public abstract void attachWSMenuEntry(JMenu wsmenu, final ServiceHandle serviceHandle,
+ final AlignFrame alignFrame);
+
+}
*/
package jalview.ws;
-import javax.swing.JMenu;
-import ext.vamsas.*;
import jalview.gui.*;
-public abstract class WSClient implements WSMenuEntryProviderI
+public abstract class WSClient // implements WSMenuEntryProviderI
{
/**
* WSClient holds the basic attributes that are displayed to the user for all
public WSClient()
{
}
-
- /**
- * initialise WSClient service information attributes from the service handle
- *
- * @param sh
- * @return the service instance information GUI for this client and job.
- */
- protected WebserviceInfo setWebService(ServiceHandle sh)
- {
- return setWebService(sh, false);
- }
-
- /**
- * original service handle that this client was derived from
- */
- ServiceHandle serviceHandle = null;
-
- /**
- * initialise WSClient service information attributes from the service handle
- *
- * @param sh
- * @param headless
- * true implies no GUI objects will be created.
- * @return the service instance information GUI for this client and job.
- */
- protected WebserviceInfo setWebService(ServiceHandle sh, boolean headless)
- {
- WebServiceName = sh.getName();
- if (ServiceActions.containsKey(sh.getAbstractName()))
- {
- WebServiceJobTitle = sh.getName(); // TODO: control sh.Name specification
- // properly
- // add this for short names. +(String)
- // ServiceActions.get(sh.getAbstractName());
- }
- else
- {
- WebServiceJobTitle = sh.getAbstractName() + " using " + sh.getName();
-
- }
- WebServiceReference = sh.getDescription();
- WsURL = sh.getEndpointURL();
- WebserviceInfo wsInfo = null;
- if (!headless)
- {
- wsInfo = new WebserviceInfo(WebServiceJobTitle, WebServiceReference);
- }
- return wsInfo;
- }
-
- /**
- * convenience method to pass the serviceHandle reference that instantiated
- * this service on to the menu entry constructor
- *
- * @param wsmenu
- * the menu to which any menu entries/sub menus are to be attached
- * @param alignFrame
- * the alignFrame instance that provides input data for the service
- */
- public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
- {
- if (serviceHandle == null)
- {
- throw new Error(
- "IMPLEMENTATION ERROR: cannot attach WS Menu Entry without service handle reference!");
- }
- attachWSMenuEntry(wsmenu, serviceHandle, alignFrame);
- }
-
- /**
- * method implemented by each WSClient implementation that creates menu
- * entries that enact their service using data from alignFrame.
- *
- * @param wsmenu
- * where new menu entries (and submenus) are to be attached
- * @param serviceHandle
- * the serviceHandle document for the service that entries are
- * created for
- * @param alignFrame
- */
- public abstract void attachWSMenuEntry(JMenu wsmenu,
- final ServiceHandle serviceHandle, final AlignFrame alignFrame);
}
--- /dev/null
+/**
+ *
+ */
+package jalview.ws;
+
+abstract class WSJob extends AWsJob
+{
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#clearResponse()
+ */
+ @Override
+ public void clearResponse()
+ {
+ result = null;
+ }
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#hasResponse()
+ */
+ @Override
+ public boolean hasResponse()
+ {
+ return result!=null;
+ }
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#hasStatus()
+ */
+ @Override
+ public boolean hasStatus()
+ {
+ return result!=null && result.getStatus()!=null;
+ }
+
+ /**
+ * The last result object returned by the service.
+ */
+ vamsas.objects.simple.Result result;
+
+ /**
+ * @return
+ * @see vamsas.objects.simple.Result#getStatus()
+ */
+ public String getStatus()
+ {
+ return result==null ? null : result.getStatus();
+ }
+
+ public String getState() {
+ return result==null ? "NULL result" : ""+result.getState();
+ }
+ /**
+ * @return
+ * @see vamsas.objects.simple.Result#isBroken()
+ */
+ public boolean isBroken()
+ {
+ return result!=null && result.isBroken();
+ }
+
+ /**
+ * @return
+ * @see vamsas.objects.simple.Result#isFailed()
+ */
+ public boolean isFailed()
+ {
+ return result!=null && result.isFailed();
+ }
+
+ /**
+ * @return
+ * @see vamsas.objects.simple.Result#isFinished()
+ */
+ public boolean isFinished()
+ {
+ return result!=null && result.isFinished();
+ }
+
+ /**
+ * @return
+ * @see vamsas.objects.simple.Result#isInvalid()
+ */
+ public boolean isInvalid()
+ {
+ return result!=null && result.isInvalid();
+ }
+
+ /**
+ * @return
+ * @see vamsas.objects.simple.Result#isJobFailed()
+ */
+ public boolean isJobFailed()
+ {
+ return result!=null && result.isJobFailed();
+ }
+
+ /**
+ * @return
+ * @see vamsas.objects.simple.Result#isQueued()
+ */
+ public boolean isQueued()
+ {
+ return result!=null && result.isQueued();
+ }
+
+ /**
+ * @return
+ * @see vamsas.objects.simple.Result#isRunning()
+ */
+ public boolean isRunning()
+ {
+ return result!=null && result.isRunning();
+ }
+
+ /**
+ * @return
+ * @see vamsas.objects.simple.Result#isServerError()
+ */
+ public boolean isServerError()
+ {
+ return result!=null && result.isServerError();
+ }
+}
\ No newline at end of file
--- /dev/null
+package jalview.ws.jws2;
+
+import jalview.datamodel.AlignmentView;
+import jalview.gui.AlignFrame;
+import jalview.gui.WebserviceInfo;
+
+abstract public class AWS2Thread extends jalview.ws.AWSThread
+{
+
+ public AWS2Thread(AlignFrame alFrame, WebserviceInfo wsinfo,
+ AlignmentView alview, String wsname, String wsUrl)
+ {
+ super(alFrame, wsinfo, alview, wsname, wsUrl);
+ }
+
+}
--- /dev/null
+/**
+ *
+ */
+package jalview.ws.jws2;
+
+import compbio.metadata.JobStatus;
+
+import jalview.ws.AWsJob;
+
+/**
+ * job status processing for JWS2 jobs.
+ * @author JimP
+ *
+ */
+public abstract class JWs2Job extends AWsJob
+{
+ JobStatus status=null;
+ public void setjobStatus(JobStatus jobStatus)
+ {
+ status = jobStatus;
+ // update flags
+ }
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#clearResponse()
+ */
+ @Override
+ public void clearResponse()
+ {
+ status = null;
+ }
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#getState()
+ */
+ @Override
+ public String getState()
+ {
+ return status==null ? ("Unknown") : status.toString();
+ }
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#hasResponse()
+ */
+ @Override
+ public boolean hasResponse()
+ {
+ // TODO Auto-generated method stub
+ return status!=null;
+ }
+ /*
+ StringBuffer statusBuffer = null;
+ * (non-Javadoc)
+ * @see jalview.ws.AWsJob#getStatus()
+ *
+ @Override
+ public String getStatus()
+ {
+ return statusBuffer.toString();
+ }
+ * (non-Javadoc)
+ * @see jalview.ws.AWsJob#hasStatus()
+ *
+ @Override
+ public boolean hasStatus()
+ {
+ return statusBuffer!=null;
+ }
+*/
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#isBroken()
+ */
+ @Override
+ public boolean isBroken()
+ {
+ return status.equals(status.UNDEFINED);
+ }
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#isFailed()
+ */
+ @Override
+ public boolean isFailed()
+ {
+ return status.equals(status.FAILED);
+ }
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#isFinished()
+ */
+ @Override
+ public boolean isFinished()
+ {
+ return status.equals(status.FINISHED);
+ }
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#isQueued()
+ */
+ @Override
+ public boolean isQueued()
+ {
+ return status.equals(status.SUBMITTED) || status.equals(status.PENDING);
+ }
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#isRunning()
+ */
+ @Override
+ public boolean isRunning()
+ {
+ // TODO Auto-generated method stub
+ return status.equals(status.RUNNING) || status.equals(status.STARTED);
+ }
+
+ /* (non-Javadoc)
+ * @see jalview.ws.AWsJob#isServerError()
+ */
+ @Override
+ public boolean isServerError()
+ {
+ // server errors are raised as exceptions on the service method calls.
+ return false; // status.equals(status.FAILED);
+ }
+
+}
--- /dev/null
+package jalview.ws.jws2;
+
+import javax.swing.JMenu;
+
+import jalview.gui.AlignFrame;
+import jalview.gui.WebserviceInfo;
+import jalview.ws.jws2.Jws2Discoverer.Jws2Instance;
+
+/**
+ * provides metadata for a jws2 service instance - resolves names, etc.
+ *
+ * @author JimP
+ *
+ */
+public abstract class Jws2Client extends jalview.ws.WSClient
+{
+ protected WebserviceInfo setWebService(Jws2Instance serv, boolean b)
+ {
+ // serviceHandle = serv;
+ String serviceInstance = serv.service.getClass().getName();
+ WebServiceName = serv.serviceType;
+ WebServiceJobTitle = serv.serviceType;
+ WsURL = serv.hosturl;
+ if (!b)
+ {
+ return new WebserviceInfo(WebServiceJobTitle, WebServiceJobTitle
+ + " using service hosted at " + serv.hosturl);
+ }
+ return null;
+ }
+ /*
+ Jws2Instance serviceHandle;
+ * (non-Javadoc)
+ * @see jalview.ws.WSMenuEntryProviderI#attachWSMenuEntry(javax.swing.JMenu, jalview.gui.AlignFrame)
+ *
+ @Override
+ public void attachWSMenuEntry(JMenu wsmenu, AlignFrame alignFrame)
+ {
+ if (serviceHandle==null)
+ {
+ throw new Error("Implementation error: No service handle for this Jws2 service.");
+ }
+ attachWSMenuEntry(wsmenu, serviceHandle, alignFrame);
+ }*/
+ /**
+ * add the menu item for a particular jws2 service instance
+ * @param wsmenu
+ * @param service
+ * @param alignFrame
+ */
+ abstract void attachWSMenuEntry(JMenu wsmenu,
+ final Jws2Instance service, final AlignFrame alignFrame);
+
+}
--- /dev/null
+package jalview.ws.jws2;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashSet;
+import java.util.Vector;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+
+import org.apache.log4j.Level;
+
+import jalview.bin.Cache;
+import jalview.datamodel.AlignmentView;
+import jalview.gui.AlignFrame;
+import jalview.ws.WSMenuEntryProviderI;
+import compbio.data.msa.MsaWS;
+import compbio.ws.client.Jws2Base;
+import compbio.ws.client.Jws2Base.Services;
+
+/**
+ * discoverer for jws2 services. Follows the lightweight service discoverer
+ * pattern (archetyped by EnfinEnvision2OneWay)
+ *
+ * @author JimP
+ *
+ */
+public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
+{
+ compbio.data.msa.MsaWS service;
+ boolean running=false;
+ @Override
+ public void run()
+ {
+ if (running)
+ {
+ return;
+ }
+ running=true;
+// Cache.initLogger();
+// Cache.log.setLevel(Level.DEBUG);
+ // TODO: Document and PACK JWS2
+ String jwsservers = Cache.getDefault("JWS2HOSTURLS",
+ "http://webservices.compbio.dundee.ac.uk:8084/jws2");
+ try
+ {
+ if (Jws2Base.validURL(jwsservers))
+ {
+ // look for services
+ for (Services srv : Jws2Base.Services.values())
+ {
+ MsaWS service = null;
+ try
+ {
+ service = Jws2Base.connect(jwsservers, srv);
+ } catch (Exception e)
+ {
+ }
+ ;
+ if (service != null)
+ {
+ addService(jwsservers, srv, service);
+ }
+ }
+
+ }
+ else
+ {
+ Cache.log.info("Ignoring invalid Jws2 service url " + jwsservers);
+ }
+ } catch (Exception e)
+ {
+ Cache.log.warn("Exception when discovering Jws2 services.", e);
+ } catch (Error e)
+ {
+ Cache.log.error("Exception when discovering Jws2 services.", e);
+ }
+ running=false;
+
+ }
+
+ /**
+ * record this service endpoint so we can use it
+ *
+ * @param jwsservers
+ * @param srv
+ * @param service2
+ */
+ private void addService(String jwsservers, Services srv, MsaWS service2)
+ {
+ Cache.log.debug("Discovered service: " + jwsservers + " "
+ + srv.toString());
+ if (services==null) {
+ services = new Vector<Jws2Instance>();
+ }
+ services.add(new Jws2Instance(jwsservers, "Align with "
+ + srv.toString(), service2));
+ }
+
+ public class Jws2Instance
+ {
+ String hosturl;
+
+ String serviceType;
+
+ MsaWS service;
+
+ public Jws2Instance(String hosturl, String serviceType, MsaWS service)
+ {
+ super();
+ this.hosturl = hosturl;
+ this.serviceType = serviceType;
+ this.service = service;
+ }
+
+ };
+
+ /**
+ * holds list of services.
+ */
+ Vector<Jws2Instance> services;
+
+ @Override
+ public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
+ {
+ if (running || services==null || services.size() == 0)
+ {
+ return;
+ }
+ /**
+ * eventually, JWS2 services will appear under the same align/etc submenus.
+ * for moment we keep them separate.
+ */
+ JMenu jws2 = new JMenu("JWS2 Alignment");
+ MsaWSClient msacl = new MsaWSClient();
+ for (final Jws2Instance service : services)
+ {
+ msacl.attachWSMenuEntry(jws2, service, alignFrame);
+ /*JMenuItem sitem = new JMenuItem(service.serviceType);
+ sitem.setToolTipText("Hosted at " + service.hosturl);
+ sitem.addActionListener(new ActionListener()
+ {
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ AlignmentView msa = alignFrame.gatherSequencesForAlignment();
+ MsaWSClient client = new MsaWSClient(service,
+ "JWS2 Alignment of " + alignFrame.getTitle(), msa, false,
+ true, alignFrame.getViewport().getAlignment().getDataset(),
+ alignFrame);
+ }
+ });*/
+ }
+ if (services.size()>0)
+ {
+ wsmenu.add(jws2);
+ }
+
+ }
+ public static void main(String[] args)
+ {
+ Thread runner = new Thread(getDiscoverer());
+ runner.start();
+ while (runner.isAlive())
+ {
+ try
+ {
+ Thread.sleep(50);
+ } catch (InterruptedException e)
+ {
+ }
+ ;
+ }
+ }
+ private static Jws2Discoverer discoverer;
+ public static Jws2Discoverer getDiscoverer()
+ {
+ if (discoverer==null)
+ {
+ discoverer = new Jws2Discoverer();
+ }
+ return discoverer;
+ }
+
+ public boolean hasServices()
+ {
+ // TODO Auto-generated method stub
+ return services!=null && services.size()>0;
+ }
+
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
+ * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview 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.
+ *
+ * Jalview 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 Jalview. If not, see <http://www.gnu.org/licenses/>.
+ */
+package jalview.ws.jws2;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.*;
+
+import jalview.datamodel.*;
+import jalview.gui.*;
+import compbio.data.msa.MsaWS;
+import jalview.ws.jws2.Jws2Discoverer.Jws2Instance;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+public class MsaWSClient extends Jws2Client
+{
+ /**
+ * server is a WSDL2Java generated stub for an archetypal MsaWSI service.
+ */
+ MsaWS server;
+ AlignFrame alignFrame;
+
+ /**
+ * Creates a new MsaWSClient object that uses a service given by an externally
+ * retrieved ServiceHandle
+ *
+ * @param sh
+ * service handle of type AbstractName(MsaWS)
+ * @param altitle
+ * DOCUMENT ME!
+ * @param msa
+ * DOCUMENT ME!
+ * @param submitGaps
+ * DOCUMENT ME!
+ * @param preserveOrder
+ * DOCUMENT ME!
+ */
+
+ public MsaWSClient(Jws2Discoverer.Jws2Instance sh, String altitle,
+ jalview.datamodel.AlignmentView msa, boolean submitGaps,
+ boolean preserveOrder, Alignment seqdataset,
+ AlignFrame _alignFrame)
+ {
+ super();
+ alignFrame = _alignFrame;
+ if (!(sh.service instanceof MsaWS))
+ {
+ // redundant at mo - but may change
+ JOptionPane
+ .showMessageDialog(
+ Desktop.desktop,
+ "The Service called \n"
+ + sh.serviceType
+ + "\nis not a \nMultiple Sequence Alignment Service !",
+ "Internal Jalview Error", JOptionPane.WARNING_MESSAGE);
+
+ return;
+ }
+ server = sh.service;
+ if ((wsInfo = setWebService(sh, false)) == null)
+ {
+ JOptionPane.showMessageDialog(Desktop.desktop,
+ "The Multiple Sequence Alignment Service named "
+ + sh.serviceType + " is unknown",
+ "Internal Jalview Error", JOptionPane.WARNING_MESSAGE);
+
+ return;
+ }
+ startMsaWSClient(altitle, msa, submitGaps, preserveOrder, seqdataset);
+
+ }
+
+ public MsaWSClient()
+ {
+ super();
+ // add a class reference to the list
+ }
+
+ private void startMsaWSClient(String altitle, AlignmentView msa,
+ boolean submitGaps, boolean preserveOrder, Alignment seqdataset)
+ {
+ //if (!locateWebService())
+ // {
+ // return;
+ // }
+
+ wsInfo.setProgressText(((submitGaps) ? "Re-alignment" : "Alignment")
+ + " of " + altitle + "\nJob details\n");
+ String jobtitle = WebServiceName.toLowerCase();
+ if (jobtitle.endsWith("alignment"))
+ {
+ if (submitGaps
+ && (!jobtitle.endsWith("realignment") || jobtitle
+ .indexOf("profile") == -1))
+ {
+ int pos = jobtitle.indexOf("alignment");
+ jobtitle = WebServiceName.substring(0, pos) + "re-alignment of "
+ + altitle;
+ }
+ else
+ {
+ jobtitle = WebServiceName + " of " + altitle;
+ }
+ }
+ else
+ {
+ jobtitle = WebServiceName + (submitGaps ? " re" : " ")
+ + "alignment of " + altitle;
+ }
+
+ MsaWSThread msathread = new MsaWSThread(server, WsURL, wsInfo,
+ alignFrame, WebServiceName, jobtitle, msa, submitGaps,
+ preserveOrder, seqdataset);
+ wsInfo.setthisService(msathread);
+ msathread.start();
+ }
+
+ protected String getServiceActionKey()
+ {
+ return "MsaWS";
+ }
+
+ protected String getServiceActionDescription()
+ {
+ return "Multiple Sequence Alignment";
+ }
+
+ /**
+ * look at ourselves and work out if we are a service that can take a profile
+ * and align to it
+ *
+ * @return true if we can send gapped sequences to the alignment service
+ */
+ private boolean canSubmitGaps()
+ {
+ // TODO: query service or extract service handle props to check if we can
+ // realign
+ return (WebServiceName.indexOf("lustal") > -1); // cheat!
+ }
+
+ public void attachWSMenuEntry(JMenu msawsmenu,
+ final Jws2Instance service, final AlignFrame alignFrame)
+ {
+ setWebService(service, true); // headless
+ JMenuItem method = new JMenuItem(WebServiceName);
+ method.setToolTipText(WsURL);
+ method.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ AlignmentView msa = alignFrame.gatherSequencesForAlignment();
+ new MsaWSClient(service, alignFrame.getTitle(),
+ msa, false, true, alignFrame.getViewport().getAlignment()
+ .getDataset(), alignFrame);
+
+ }
+
+ });
+ msawsmenu.add(method);
+ if (canSubmitGaps())
+ {
+ // We know that ClustalWS can accept partial alignments for refinement.
+ final JMenuItem methodR = new JMenuItem(WebServiceName
+ + " (With Gaps)");
+ methodR.setToolTipText(WsURL);
+ methodR.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ AlignmentView msa = alignFrame.gatherSequencesForAlignment();
+ new MsaWSClient(service, alignFrame.getTitle(),
+ msa, true, true, alignFrame.getViewport().getAlignment()
+ .getDataset(), alignFrame);
+
+ }
+
+ });
+ msawsmenu.add(methodR);
+
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
+ * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview 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.
+ *
+ * Jalview 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 Jalview. If not, see <http://www.gnu.org/licenses/>.
+ */
+package jalview.ws.jws2;
+
+import java.util.*;
+
+import compbio.data.msa.MsaWS;
+import compbio.data.sequence.AlignmentMetadata;
+import compbio.data.sequence.Program;
+import compbio.metadata.ChunkHolder;
+import compbio.metadata.JobStatus;
+
+import jalview.analysis.*;
+import jalview.bin.*;
+import jalview.datamodel.*;
+import jalview.gui.*;
+import jalview.ws.AWsJob;
+import jalview.ws.WSClientI;
+import jalview.ws.JobStateSummary;
+
+/**
+ * <p>
+ * Title:
+ * </p>
+ *
+ * <p>
+ * Description:
+ * </p>
+ *
+ * <p>
+ * Copyright: Copyright (c) 2004
+ * </p>
+ *
+ * <p>
+ * Company: Dundee University
+ * </p>
+ *
+ * @author not attributable
+ * @version 1.0
+ */
+class MsaWSThread extends AWS2Thread implements WSClientI
+{
+ boolean submitGaps = false; // pass sequences including gaps to alignment
+
+ // service
+
+ boolean preserveOrder = true; // and always store and recover sequence
+
+ // order
+
+ class MsaWSJob extends JWs2Job
+ {
+ long lastChunk=0;
+
+ /**
+ * input
+ */
+ ArrayList<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
+ /**
+ * output
+ */
+ compbio.data.sequence.Alignment alignment;
+ // set if the job didn't get run - then the input is simply returned to the user
+ private boolean returnInput=false;
+
+ /**
+ * MsaWSJob
+ *
+ * @param jobNum
+ * int
+ * @param jobId
+ * String
+ */
+ public MsaWSJob(int jobNum, SequenceI[] inSeqs)
+ {
+ this.jobnum = jobNum;
+ if (!prepareInput(inSeqs, 2))
+ {
+ submitted = true;
+ subjobComplete = true;
+ returnInput = true;
+ }
+
+ }
+
+ Hashtable<String,Map> SeqNames = new Hashtable();
+
+ Vector<String[]> emptySeqs = new Vector();
+
+ /**
+ * prepare input sequences for MsaWS service
+ *
+ * @param seqs
+ * jalview sequences to be prepared
+ * @param minlen
+ * minimum number of residues required for this MsaWS service
+ * @return true if seqs contains sequences to be submitted to service.
+ */
+ // TODO: return compbio.seqs list or nothing to indicate validity.
+ private boolean prepareInput(SequenceI[] seqs, int minlen)
+ {
+ int nseqs = 0;
+ if (minlen < 0)
+ {
+ throw new Error(
+ "Implementation error: minlen must be zero or more.");
+ }
+ for (int i = 0; i < seqs.length; i++)
+ {
+ if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
+ {
+ nseqs++;
+ }
+ }
+ boolean valid = nseqs > 1; // need at least two seqs
+ compbio.data.sequence.FastaSequence seq;
+ for (int i = 0, n = 0; i < seqs.length; i++)
+ {
+
+ String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
+ // for
+ // any
+ // subjob
+ SeqNames.put(newname, jalview.analysis.SeqsetUtils
+ .SeqCharacterHash(seqs[i]));
+ if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
+ {
+ // make new input sequence with or without gaps
+ seq = new compbio.data.sequence.FastaSequence(newname,
+ (submitGaps) ? seqs[i].getSequenceAsString()
+ : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
+ seqs[i].getSequenceAsString()));
+ this.seqs.add(seq);
+ }
+ else
+ {
+ String empty = null;
+ if (seqs[i].getEnd() >= seqs[i].getStart())
+ {
+ empty = (submitGaps) ? seqs[i].getSequenceAsString() : AlignSeq
+ .extractGaps(jalview.util.Comparison.GapChars, seqs[i]
+ .getSequenceAsString());
+ }
+ emptySeqs.add(new String[]
+ { newname, empty });
+ }
+ }
+ return valid;
+ }
+
+ /**
+ *
+ * @return true if getAlignment will return a valid alignment result.
+ */
+ public boolean hasResults()
+ {
+ if (subjobComplete && isFinished() && (alignment!=null || (emptySeqs!=null && emptySeqs.size()>0)))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ *
+ * get the alignment including any empty sequences in the original order with original ids. Caller must access the alignment.getMetadata() object to annotate the final result passsed to the user.
+ * @return { SequenceI[], AlignmentOrder }
+ */
+ public Object[] getAlignment()
+ {
+ // is this a generic subjob or a Jws2 specific Object[] return signature
+ if (hasResults())
+ {
+ SequenceI[] alseqs = null;
+ char alseq_gapchar = '-';
+ int alseq_l = 0;
+ if (alignment.getSequences().size()>0)
+ {
+ alseqs = new SequenceI[alignment.getSequences().size()];
+ for (compbio.data.sequence.FastaSequence seq: alignment.getSequences())
+ {
+ alseqs[alseq_l++] = new Sequence(seq.getId(),seq.getSequence());
+ }
+ alseq_gapchar = alignment.getMetadata().getGapchar();
+
+ }
+ // add in the empty seqs.
+ if (emptySeqs.size() > 0)
+ {
+ SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
+ // get width
+ int i, w = 0;
+ if (alseq_l > 0)
+ {
+ for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
+ {
+ if (w < alseqs[i].getLength())
+ {
+ w = alseqs[i].getLength();
+ }
+ t_alseqs[i] = alseqs[i];
+ alseqs[i] = null;
+ }
+ }
+ // check that aligned width is at least as wide as emptySeqs width.
+ int ow = w, nw = w;
+ for (i = 0, w = emptySeqs.size(); i < w; i++)
+ {
+ String[] es = (String[]) emptySeqs.get(i);
+ if (es != null && es[1] != null)
+ {
+ int sw = es[1].length();
+ if (nw < sw)
+ {
+ nw = sw;
+ }
+ }
+ }
+ // make a gapped string.
+ StringBuffer insbuff = new StringBuffer(w);
+ for (i = 0; i < nw; i++)
+ {
+ insbuff.append(alseq_gapchar);
+ }
+ if (ow < nw)
+ {
+ for (i = 0; i < alseq_l; i++)
+ {
+ int sw = t_alseqs[i].getLength();
+ if (nw > sw)
+ {
+ // pad at end
+ alseqs[i].setSequence(t_alseqs[i].getSequenceAsString()
+ + insbuff.substring(0, sw - nw));
+ }
+ }
+ }
+ for (i = 0, w = emptySeqs.size(); i < w; i++)
+ {
+ String[] es = (String[]) emptySeqs.get(i);
+ if (es[1] == null)
+ {
+ t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0],
+ insbuff.toString(), 1, 0);
+ }
+ else
+ {
+ if (es[1].length() < nw)
+ {
+ t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
+ es[0],
+ es[1] + insbuff.substring(0, nw - es[1].length()),
+ 1, 1 + es[1].length());
+ }
+ else
+ {
+ t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
+ es[0], es[1]);
+ }
+ }
+ }
+ alseqs = t_alseqs;
+ }
+ AlignmentOrder msaorder = new AlignmentOrder(alseqs);
+ // always recover the order - makes parseResult()'s life easier.
+ jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
+ // account for any missing sequences
+ jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
+ return new Object[]
+ { alseqs, msaorder };
+ }
+ return null;
+ }
+
+ /**
+ * mark subjob as cancelled and set result object appropriatly
+ */
+ void cancel()
+ {
+ cancelled = true;
+ subjobComplete = true;
+ alignment = null;
+ }
+
+ /**
+ *
+ * @return boolean true if job can be submitted.
+ */
+ public boolean hasValidInput()
+ {
+ // TODO: get attributes for this MsaWS instance to check if it can do two sequence alignment.
+ if (seqs != null && seqs.size()>=2) // two or more sequences is valid ?
+ {
+ return true;
+ }
+ return false;
+ }
+ StringBuffer jobProgress=new StringBuffer();
+ public void setStatus(String string)
+ {
+ jobProgress.setLength(0);
+ jobProgress.append(string);
+ }
+
+ @Override
+ public String getStatus()
+ {
+ return jobProgress.toString();
+ }
+
+ @Override
+ public boolean hasStatus()
+ {
+ return jobProgress!=null;
+ }
+
+ /**
+ * @return the lastChunk
+ */
+ public long getLastChunk()
+ {
+ return lastChunk;
+ }
+
+ /**
+ * @param lastChunk the lastChunk to set
+ */
+ public void setLastChunk(long lastChunk)
+ {
+ this.lastChunk = lastChunk;
+ }
+
+ }
+
+ String alTitle; // name which will be used to form new alignment window.
+
+ Alignment dataset; // dataset to which the new alignment will be
+
+ // associated.
+
+ @SuppressWarnings("unchecked")
+ MsaWS server = null;
+
+ /**
+ * set basic options for this (group) of Msa jobs
+ *
+ * @param subgaps
+ * boolean
+ * @param presorder
+ * boolean
+ */
+ MsaWSThread(MsaWS server, String wsUrl,
+ WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame,
+ AlignmentView alview, String wsname, boolean subgaps,
+ boolean presorder)
+ {
+ super(alFrame, wsinfo, alview, wsname, wsUrl);
+ this.server = server;
+ this.submitGaps = subgaps;
+ this.preserveOrder = presorder;
+ }
+
+ /**
+ * create one or more Msa jobs to align visible seuqences in _msa
+ *
+ * @param title
+ * String
+ * @param _msa
+ * AlignmentView
+ * @param subgaps
+ * boolean
+ * @param presorder
+ * boolean
+ * @param seqset
+ * Alignment
+ */
+ MsaWSThread(MsaWS server2, String wsUrl,
+ WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame,
+ String wsname, String title, AlignmentView _msa, boolean subgaps,
+ boolean presorder, Alignment seqset)
+ {
+ this(server2,wsUrl, wsinfo, alFrame, _msa, wsname, subgaps, presorder);
+ OutputHeader = wsInfo.getProgressText();
+ alTitle = title;
+ dataset = seqset;
+
+ SequenceI[][] conmsa = _msa.getVisibleContigs('-');
+ if (conmsa != null)
+ {
+ int njobs = conmsa.length;
+ jobs = new MsaWSJob[njobs];
+ for (int j = 0; j < njobs; j++)
+ {
+ if (j != 0)
+ {
+ jobs[j] = new MsaWSJob(wsinfo.addJobPane(), conmsa[j]);
+ }
+ else
+ {
+ jobs[j] = new MsaWSJob(0, conmsa[j]);
+ }
+ if (njobs > 0)
+ {
+ wsinfo
+ .setProgressName("region " + jobs[j].getJobnum(),
+ jobs[j].getJobnum());
+ }
+ wsinfo.setProgressText(jobs[j].getJobnum(), OutputHeader);
+ }
+ }
+ }
+
+ public boolean isCancellable()
+ {
+ return true;
+ }
+
+ public void cancelJob()
+ {
+ if (!jobComplete && jobs != null)
+ {
+ boolean cancelled = true;
+ for (int job = 0; job < jobs.length; job++)
+ {
+ if (jobs[job].isSubmitted() && !jobs[job].isSubjobComplete())
+ {
+ String cancelledMessage = "";
+ try
+ {
+ boolean cancelledJob = server
+ .cancelJob(jobs[job].getJobId());
+ if (cancelledJob)
+ {
+ // CANCELLED_JOB
+ cancelledMessage = "Job cancelled.";
+ ((MsaWSJob) jobs[job]).cancel(); // TODO: refactor to avoid this ugliness -
+ wsInfo.setStatus(jobs[job].getJobnum(),
+ WebserviceInfo.STATE_CANCELLED_OK);
+ }
+ else
+ {
+ // VALID UNSTOPPABLE JOB
+ cancelledMessage += "Server cannot cancel this job. just close the window.\n";
+ cancelled = false;
+ // wsInfo.setStatus(jobs[job].jobnum,
+ // WebserviceInfo.STATE_RUNNING);
+ }
+ } catch (Exception exc)
+ {
+ cancelledMessage += ("\nProblems cancelling the job : Exception received...\n"
+ + exc + "\n");
+ Cache.log.warn(
+ "Exception whilst cancelling " + jobs[job].getJobId(), exc);
+ }
+ wsInfo.setProgressText(jobs[job].getJobnum(), OutputHeader
+ + cancelledMessage + "\n");
+ }
+ }
+ if (cancelled)
+ {
+ wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
+ jobComplete = true;
+ }
+ this.interrupt(); // kick thread to update job states.
+ }
+ else
+ {
+ if (!jobComplete)
+ {
+ wsInfo
+ .setProgressText(OutputHeader
+ + "Server cannot cancel this job because it has not been submitted properly. just close the window.\n");
+ }
+ }
+ }
+
+ public void pollJob(AWsJob job) throws Exception
+ {
+ // TODO: investigate if we still need to cast here in J1.6
+ MsaWSJob j=((MsaWSJob) job);
+ j.setjobStatus(server.getJobStatus(job.getJobId()));
+ StringBuffer response = j.jobProgress;
+ ChunkHolder chunk = server.pullExecStatistics(job.getJobId(), j.getLastChunk());
+ response.append(chunk.getChunk());
+ j.setLastChunk(chunk.getNextPosition());
+
+ }
+
+ public void StartJob(AWsJob job)
+ {
+ // boiler plate template
+ if (!(job instanceof MsaWSJob))
+ {
+ throw new Error("StartJob(MsaWSJob) called on a WSJobInstance "
+ + job.getClass());
+ }
+ MsaWSJob j = (MsaWSJob) job;
+ if (j.isSubmitted())
+ {
+ if (Cache.log.isDebugEnabled())
+ {
+ Cache.log.debug("Tried to submit an already submitted job "
+ + j.getJobId());
+ }
+ return;
+ }
+ // end boilerplate
+
+ if (j.seqs == null || j.seqs.size()==0)
+ {
+ // special case - selection consisted entirely of empty sequences...
+ j.setjobStatus(JobStatus.FINISHED);
+ j.setStatus("Empty Alignment Job");
+ }
+ try
+ {
+ // TODO: get the parameters (if any) for this job and submit the job
+ j.setJobId(server.align(j.seqs));
+
+ if (j.getJobId()!= null)
+ {
+ j.setSubmitted(true);
+ j.setSubjobComplete(false);
+ // System.out.println(WsURL + " Job Id '" + jobId + "'");
+ }
+ else
+ {
+ throw new Exception(
+ "Server at "
+ + WsUrl
+ + " returned null string for job id, it probably cannot be contacted. Try again later ?");
+ }
+ } catch (Exception e)
+ {
+ // Boilerplate code here
+ // TODO: JBPNote catch timeout or other fault types explicitly
+ // For unexpected errors
+ System.err
+ .println(WebServiceName
+ + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
+ + "When contacting Server:" + WsUrl + "\n"
+ + e.toString() + "\n");
+ j.setAllowedServerExceptions(0);
+ wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
+ wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_SERVERERROR);
+ wsInfo
+ .appendProgressText(
+ j.getJobnum(),
+ "Failed to submit sequences for alignment.\n"
+ + "It is most likely that there is a problem with the server.\n"
+ + "Just close the window\n");
+
+ // e.printStackTrace(); // TODO: JBPNote DEBUG
+ }
+ }
+
+
+ public void parseResult()
+ {
+ int results = 0; // number of result sets received
+ JobStateSummary finalState = new JobStateSummary();
+ try
+ {
+ for (int j = 0; j < jobs.length; j++)
+ {
+ MsaWSJob msjob = ((MsaWSJob) jobs[j]);
+ if (jobs[j].isFinished() && msjob.alignment==null)
+ {
+ try {
+ msjob.alignment = server.getResult(msjob.getJobId());
+ }
+ catch (Exception e)
+ {
+ Cache.log.error("Couldn't get Alignment for job.",e);
+ }
+ }
+ finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
+ if (jobs[j].isSubmitted() && jobs[j].isSubjobComplete()
+ && jobs[j].hasResults())
+ {
+ results++;
+ compbio.data.sequence.Alignment alignment = ((MsaWSJob) jobs[j]).alignment;
+ if (alignment != null)
+ {
+ wsInfo.appendProgressText(jobs[j].getJobnum(),
+ "\nAlignment Object Method Notes\n");
+ wsInfo.appendProgressText(jobs[j].getJobnum(), "Calculated with "+alignment.getMetadata().getProgram().toString());
+ // JBPNote The returned files from a webservice could be
+ // hidden behind icons in the monitor window that,
+ // when clicked, pop up their corresponding data
+ }
+ }
+ }
+ } catch (Exception ex)
+ {
+
+ Cache.log.error("Unexpected exception when processing results for "
+ + alTitle, ex);
+ wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+ }
+ if (results > 0)
+ {
+ wsInfo.showResultsNewFrame
+ .addActionListener(new java.awt.event.ActionListener()
+ {
+ public void actionPerformed(java.awt.event.ActionEvent evt)
+ {
+ displayResults(true);
+ }
+ });
+ wsInfo.mergeResults
+ .addActionListener(new java.awt.event.ActionListener()
+ {
+ public void actionPerformed(java.awt.event.ActionEvent evt)
+ {
+ displayResults(false);
+ }
+ });
+ wsInfo.setResultsReady();
+ }
+ else
+ {
+ wsInfo.setFinishedNoResults();
+ }
+ }
+
+ void displayResults(boolean newFrame)
+ {
+ // view input or result data for each block
+ Vector alorders = new Vector();
+ SequenceI[][] results = new SequenceI[jobs.length][];
+ AlignmentOrder[] orders = new AlignmentOrder[jobs.length];
+ String lastProgram = null;
+ MsaWSJob msjob;
+ for (int j = 0; j < jobs.length; j++)
+ {
+ if (jobs[j].hasResults())
+ {
+ msjob = (MsaWSJob)jobs[j];
+ Object[] res = msjob.getAlignment();
+ lastProgram = msjob.alignment.getMetadata().getProgram().name();
+ alorders.add(res[1]);
+ results[j] = (SequenceI[]) res[0];
+ orders[j] = (AlignmentOrder) res[1];
+
+ // SequenceI[] alignment = input.getUpdated
+ }
+ else
+ {
+ results[j] = null;
+ }
+ }
+ Object[] newview = input.getUpdatedView(results, orders, getGapChar());
+ // trash references to original result data
+ for (int j = 0; j < jobs.length; j++)
+ {
+ results[j] = null;
+ orders[j] = null;
+ }
+ SequenceI[] alignment = (SequenceI[]) newview[0];
+ ColumnSelection columnselection = (ColumnSelection) newview[1];
+ Alignment al = new Alignment(alignment);
+ // TODO: add 'provenance' property to alignment from the method notes
+ if (lastProgram!=null) {
+ al.setProperty("Alignment Program", lastProgram);
+ }
+ // accompanying each subjob
+ if (dataset != null)
+ {
+ al.setDataset(dataset);
+ }
+
+ propagateDatasetMappings(al);
+ // JBNote- TODO: warn user if a block is input rather than aligned data ?
+
+ if (newFrame)
+ {
+ AlignFrame af = new AlignFrame(al, columnselection,
+ AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+
+ // initialise with same renderer settings as in parent alignframe.
+ af.getFeatureRenderer().transferSettings(this.featureSettings);
+ // update orders
+ if (alorders.size() > 0)
+ {
+ if (alorders.size() == 1)
+ {
+ af.addSortByOrderMenuItem(WebServiceName + " Ordering",
+ (AlignmentOrder) alorders.get(0));
+ }
+ else
+ {
+ // construct a non-redundant ordering set
+ Vector names = new Vector();
+ for (int i = 0, l = alorders.size(); i < l; i++)
+ {
+ String orderName = new String(" Region " + i);
+ int j = i + 1;
+
+ while (j < l)
+ {
+ if (((AlignmentOrder) alorders.get(i))
+ .equals(((AlignmentOrder) alorders.get(j))))
+ {
+ alorders.remove(j);
+ l--;
+ orderName += "," + j;
+ }
+ else
+ {
+ j++;
+ }
+ }
+
+ if (i == 0 && j == 1)
+ {
+ names.add(new String(""));
+ }
+ else
+ {
+ names.add(orderName);
+ }
+ }
+ for (int i = 0, l = alorders.size(); i < l; i++)
+ {
+ af.addSortByOrderMenuItem(WebServiceName
+ + ((String) names.get(i)) + " Ordering",
+ (AlignmentOrder) alorders.get(i));
+ }
+ }
+ }
+
+ Desktop.addInternalFrame(af, alTitle, AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT);
+
+ }
+ else
+ {
+ System.out.println("MERGE WITH OLD FRAME");
+ // TODO: modify alignment in original frame, replacing old for new
+ // alignment using the commands.EditCommand model to ensure the update can
+ // be undone
+ }
+ }
+
+ public boolean canMergeResults()
+ {
+ return false;
+ }
+}