*/\r
package jalview.gui;\r
\r
-import jalview.jbgui.*;\r
+import java.util.*;\r
\r
import java.awt.*;\r
import java.awt.event.*;\r
import java.awt.image.*;\r
-\r
import javax.swing.*;\r
\r
+import jalview.jbgui.*;\r
+\r
\r
/**\r
* Base class for web service client thread and gui\r
*/\r
public class WebserviceInfo extends GWebserviceInfo\r
{\r
+\r
/** Job is Queued */\r
public static final int STATE_QUEUING = 0;\r
\r
jalview.ws.WSClientI thisService;\r
boolean serviceIsCancellable;\r
JInternalFrame frame;\r
-\r
+ JTabbedPane subjobs=null;\r
+ java.util.Vector jobPanes = null;\r
+ // tabbed or not\r
+ public synchronized int addJobPane() {\r
+ JScrollPane jobpane = new JScrollPane();\r
+ JTextArea progressText = new JTextArea();\r
+ progressText.setFont(new java.awt.Font("Verdana", 0, 10));\r
+ progressText.setBorder(null);\r
+ progressText.setEditable(false);\r
+ progressText.setText("WS Job");\r
+ progressText.setLineWrap(true);\r
+ progressText.setWrapStyleWord(true);\r
+ jobpane.setName("JobPane");\r
+ jobpane.getViewport().add(progressText, null);\r
+ jobpane.setBorder(null);\r
+ if (jobPanes==null) {\r
+ jobPanes = new Vector();\r
+ }\r
+ int newpane = jobPanes.size();\r
+ jobPanes.add(jobpane);\r
+\r
+ if (newpane==0) {\r
+ this.add(jobpane, BorderLayout.CENTER);\r
+ } else {\r
+ if (newpane==1) {\r
+ // revert to a tabbed pane.\r
+ JScrollPane firstpane;\r
+ this.remove(firstpane=(JScrollPane) jobPanes.get(0));\r
+ subjobs=new JTabbedPane();\r
+ this.add(subjobs, BorderLayout.CENTER);\r
+ subjobs.add(firstpane);\r
+ subjobs.setTitleAt(0, firstpane.getName());\r
+ }\r
+ subjobs.add(jobpane);\r
+ }\r
+ return newpane; // index for accessor methods below\r
+ }\r
/**\r
* Creates a new WebserviceInfo object.\r
*\r
{\r
currentStatus = status;\r
}\r
-\r
+ /**\r
+ * subjob status indicator\r
+ * @param jobpane\r
+ * @param status\r
+ */\r
+ public void setStatus(int jobpane, int status) {\r
+ if (jobpane<0 || jobpane>=jobPanes.size()) {\r
+ throw new Error("setStatus called for non-existent job pane."+jobpane);\r
+ }\r
+ switch (status) {\r
+ case STATE_QUEUING:\r
+ setProgressText(jobpane, "QUEUED");\r
+ break;\r
+ case STATE_RUNNING:\r
+ setProgressText(jobpane, "RUNNING");\r
+ break;\r
+ case STATE_STOPPED_OK:\r
+ setProgressText(jobpane, "FINISHED");\r
+ break;\r
+ case STATE_CANCELLED_OK:\r
+ setProgressText(jobpane, "CANCELLED");\r
+ break;\r
+ case STATE_STOPPED_ERROR:\r
+ setProgressText(jobpane, "BROKEN");\r
+ break;\r
+ case STATE_STOPPED_SERVERERROR:\r
+ setProgressText(jobpane, "ALERT");\r
+ break;\r
+ default:\r
+ setProgressText(jobpane, "UNKNOWN STATE");\r
+ }\r
+ }\r
/**\r
* DOCUMENT ME!\r
*\r
{\r
infoText.append(text);\r
}\r
-\r
/**\r
* DOCUMENT ME!\r
*\r
* @return DOCUMENT ME!\r
*/\r
- public String getProgressText()\r
+ public String getProgressText(int which)\r
{\r
- return progressText.getText();\r
+ if (jobPanes == null)\r
+ addJobPane();\r
+ return ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport().\r
+ getComponent(0)).getText();\r
}\r
-\r
/**\r
* DOCUMENT ME!\r
*\r
* @param text DOCUMENT ME!\r
*/\r
- public void setProgressText(String text)\r
+ public void setProgressText(int which, String text)\r
{\r
- progressText.setText(text);\r
+ if (jobPanes == null)\r
+ addJobPane();\r
+ ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport().\r
+ getComponent(0)).setText(text);\r
}\r
\r
/**\r
*\r
* @param text DOCUMENT ME!\r
*/\r
+ public void appendProgressText(int which, String text)\r
+ {\r
+ if (jobPanes == null)\r
+ addJobPane();\r
+ ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport().\r
+ getComponent(0)).append(text);\r
+ }\r
+ /**\r
+ * setProgressText(0, text)\r
+ */\r
+ public void setProgressText(String text)\r
+ {\r
+ setProgressText(0, text);\r
+ }\r
+ /**\r
+ * appendProgressText(0, text)\r
+ */\r
public void appendProgressText(String text)\r
{\r
- progressText.append(text);\r
+ appendProgressText(0, text);\r
+ }\r
+ /**\r
+ * getProgressText(0)\r
+ */\r
+ public String getProgressText()\r
+ {\r
+ return getProgressText(0);\r
+ }\r
+ /**\r
+ * get the tab title for a subjob\r
+ * @param which int\r
+ * @return String\r
+ */\r
+ public String getProgressName(int which) {\r
+ if (jobPanes==null)\r
+ addJobPane();\r
+ if (subjobs!=null)\r
+ return subjobs.getTitleAt(which);\r
+ else\r
+ return ((JScrollPane) jobPanes.get(which)).getViewport().getComponent(0).getName();\r
+ }\r
+ /**\r
+ * set the tab title for a subjob\r
+ * @param name String\r
+ * @param which int\r
+ */\r
+ public void setProgressName(String name, int which) {\r
+ if (subjobs!=null)\r
+ subjobs.setTitleAt(which, name);\r
+ else\r
+ ((JScrollPane) jobPanes.get(which)).getViewport().getComponent(0).setName(name);\r
}\r
\r
/**\r
}\r
\r
\r
- class AnimatedPanel extends JPanel implements Runnable\r
+ class AnimatedPanel extends JPanel implements Runnable\r
{\r
long startTime = 0;\r
BufferedImage offscreen;\r
* @version $Revision$\r
*/\r
public class MsaWSClient\r
- extends WSClient\r
+ extends WSClient \r
{\r
/**\r
* server is a WSDL2Java generated stub for an archetypal MsaWSI service.\r
Alignment seqdataset,\r
AlignFrame _alignFrame)\r
{\r
-\r
+ super();\r
alignFrame = _alignFrame;\r
if (!sh.getAbstractName().equals("MsaWS"))\r
{\r
return;\r
}\r
\r
- if ((wsInfo = this.setWebService(sh))==null)\r
+ if ((wsInfo = setWebService(sh))==null)\r
{\r
JOptionPane.showMessageDialog(Desktop.desktop,\r
"The Multiple Sequence Alignment Service named " +\r
wsInfo.setProgressText( ( (submitGaps) ? "Re-alignment" : "Alignment") +\r
" of " + altitle + "\nJob details\n");\r
\r
- MsaWSThread musclethread = new MsaWSThread(WebServiceName +\r
- " alignment of " + altitle, msa,\r
+ MsaWSThread musclethread = new MsaWSThread(server, WsURL, wsInfo, alignFrame,\r
+ WebServiceName,\r
+ WebServiceName+" alignment of " + altitle,\r
+ msa,\r
submitGaps, preserveOrder, seqdataset);\r
wsInfo.setthisService(musclethread);\r
musclethread.start();\r
{\r
return "Multiple Sequence Alignment";\r
}\r
-\r
- protected class MsaWSThread\r
- extends Thread implements WSClientI\r
- {\r
- String ServiceName = WebServiceName;\r
- String OutputHeader;\r
- vamsas.objects.simple.MsaResult result = null;\r
- vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple.\r
- SequenceSet();\r
- Hashtable SeqNames = null;\r
- boolean submitGaps = false; // pass sequences including gaps to alignment service\r
- boolean preserveOrder = true; // and always store and recover sequence order\r
- String jobId;\r
- String alTitle; // name which will be used to form new alignment window.\r
- int allowedServerExceptions = 3; // thread dies if too many exceptions.\r
- boolean jobComplete = false;\r
-\r
- Alignment dataset; // dataset to which the new alignment will be associated.\r
-\r
- MsaWSThread(String title, AlignmentView _msa, boolean subgaps,\r
- boolean presorder, Alignment seqset)\r
- {\r
- // jbpnote - transformation should be above here - this is per sequence set contig, not for many contigs.\r
- alTitle = title;\r
- submitGaps = subgaps;\r
- preserveOrder = presorder;\r
- dataset = seqset;\r
- OutputHeader = wsInfo.getProgressText();\r
- SeqNames = new Hashtable();\r
- SeqCigar[] msa = _msa.getSequences();\r
- vamsas.objects.simple.Sequence[] seqarray = new vamsas.objects.simple.\r
- Sequence[msa.length];\r
-\r
- for (int i = 0,n=0; i < msa.length; i++)\r
- {\r
- String newname = jalview.analysis.SeqsetUtils.unique_name(i);\r
- SequenceI mseq = msa[i].getSeq('-');\r
- // uniquify as we go\r
- // TODO: JBPNote: this is a ubiquitous transformation - set of jalview seq objects to vamsas sequences with name preservation\r
- SeqNames.put(newname,\r
- jalview.analysis.SeqsetUtils.SeqCharacterHash(mseq));\r
- seqarray[i] = new vamsas.objects.simple.Sequence();\r
- seqarray[i].setId(newname);\r
- seqarray[i].setSeq( (submitGaps) ? mseq.getSequence()\r
- : AlignSeq.extractGaps(\r
- jalview.util.Comparison.GapChars,\r
- mseq.getSequence()));\r
- }\r
-\r
- this.seqs = new vamsas.objects.simple.SequenceSet();\r
- this.seqs.setSeqs(seqarray);\r
- }\r
-\r
- public boolean isCancellable()\r
- {\r
- return true;\r
- }\r
-\r
- public void cancelJob()\r
- {\r
- if ( (jobId != null) && !jobId.equals("") && !jobComplete)\r
- {\r
- String cancelledMessage = "";\r
-\r
- try\r
- {\r
- vamsas.objects.simple.WsJobId cancelledJob = server.cancel(jobId);\r
-\r
- if (cancelledJob.getStatus() == 2)\r
- {\r
- // CANCELLED_JOB\r
- cancelledMessage = "Job cancelled.";\r
- wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK);\r
- jobComplete = true;\r
- jobsRunning--;\r
- result = null;\r
- }\r
- else if (cancelledJob.getStatus() == 3)\r
- {\r
- // VALID UNSTOPPABLE JOB\r
- cancelledMessage +=\r
- "Server cannot cancel this job. just close the window.\n";\r
- }\r
-\r
- if (cancelledJob.getJobId() != null)\r
- {\r
- cancelledMessage += ("[" + cancelledJob.getJobId() +\r
- "]");\r
- }\r
-\r
- cancelledMessage += "\n";\r
- }\r
- catch (Exception exc)\r
- {\r
- cancelledMessage +=\r
- ("\nProblems cancelling the job : Exception received...\n" +\r
- exc + "\n");\r
- exc.printStackTrace();\r
- }\r
-\r
- wsInfo.setProgressText(OutputHeader + cancelledMessage + "\n");\r
- }\r
- else\r
- {\r
- if (!jobComplete)\r
- {\r
- wsInfo.setProgressText(OutputHeader +\r
- "Server cannot cancel this job because it has not been submitted properly. just close the window.\n");\r
- }\r
- }\r
- }\r
-\r
- public void run()\r
- {\r
- StartJob();\r
-\r
- while (!jobComplete && (allowedServerExceptions > 0))\r
- {\r
- try\r
- {\r
- if ( (result = server.getResult(jobId)) == null)\r
- {\r
- throw (new Exception(\r
- "Timed out when communicating with server\nTry again later.\n"));\r
- }\r
- jalview.bin.Cache.log.debug("Result state " + result.getState() +\r
- "(ServerError=" + result.isServerError() +\r
- ")");\r
- if (result.isRunning())\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);\r
- }\r
- else if (result.isQueued())\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);\r
- }\r
-\r
- if (result.isFinished())\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);\r
- wsInfo.showResultsNewFrame.addActionListener(new java.awt.event.ActionListener()\r
- {\r
- public void actionPerformed(java.awt.event.ActionEvent evt)\r
- {\r
- displayResults(true);\r
- }\r
- });\r
- wsInfo.mergeResults.addActionListener(new java.awt.event.ActionListener()\r
- {\r
- public void actionPerformed(java.awt.event.ActionEvent evt)\r
- {\r
- displayResults(false);\r
- }\r
- });\r
- wsInfo.setResultsReady();\r
- parseResult();\r
- jobComplete = true;\r
- jobsRunning--;\r
- }\r
- else\r
- {\r
- if (result.getStatus() != null)\r
- {\r
- wsInfo.setProgressText(OutputHeader + "\n"+ result.getStatus());\r
- }\r
- if (result.isServerError())\r
- {\r
- jobComplete = true;\r
- jobsRunning--;\r
-\r
- break;\r
- }\r
- if (! (result.isJobFailed() || result.isServerError() ||\r
- result.isBroken() || result.isFailed()))\r
- {\r
- Thread.sleep(5000);\r
-\r
- // System.out.println("I'm alive "+seqid+" "+jobid);\r
- }\r
- else\r
- {\r
- jobComplete = true;\r
- jobsRunning--;\r
- break;\r
- }\r
- }\r
- }\r
- catch (Exception ex)\r
- {\r
- allowedServerExceptions--;\r
- wsInfo.appendProgressText("\n" + ServiceName +\r
- " Server exception!\n" + ex.getMessage());\r
- System.err.println(ServiceName + " Server exception: " +\r
- ex.getMessage());\r
-\r
- // ex.printStackTrace(); JBPNote Debug\r
- try\r
- {\r
- if (allowedServerExceptions > 0)\r
- {\r
- Thread.sleep(5000);\r
- }\r
- }\r
- catch (InterruptedException ex1)\r
- {\r
- }\r
- }\r
- catch(OutOfMemoryError er)\r
- {\r
- jobComplete = true;\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);\r
- JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
- "Out of memory handling result!!"\r
- +"\nSee help files for increasing Java Virtual Machine memory."\r
- ,"Out of memory", JOptionPane.WARNING_MESSAGE );\r
- System.out.println("MsaWSClient: "+er);\r
- System.gc();\r
- }\r
- }\r
-\r
- if (allowedServerExceptions == 0)\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);\r
- }\r
- else\r
- {\r
- if (result != null)\r
- {\r
- if ( !(result.isJobFailed() || result.isServerError()))\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);\r
- }\r
-\r
- if (result.isBroken() || result.isFailed())\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);\r
- }\r
-\r
- if (result.isServerError())\r
- {\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);\r
- }\r
- }\r
- }\r
- }\r
-\r
- void StartJob()\r
- {\r
- try\r
- {\r
- vamsas.objects.simple.WsJobId jobsubmit = server.align(seqs);\r
-\r
- if ( (jobsubmit != null) && (jobsubmit.getStatus() == 1))\r
- {\r
- jobId = jobsubmit.getJobId();\r
- System.out.println(WsURL + " Job Id '" + jobId + "'");\r
- }\r
- else\r
- {\r
- if (jobsubmit == null)\r
- {\r
- throw new Exception("Server at " + WsURL +\r
- " returned null object, it probably cannot be contacted. Try again later ?");\r
- }\r
-\r
- throw new Exception(jobsubmit.getJobId());\r
- }\r
- }\r
- catch (Exception e)\r
- {\r
- // TODO: JBPNote catch timeout or other fault types explicitly\r
- // For unexpected errors\r
- System.err.println(WebServiceName +\r
- "Client: Failed to submit the sequences for alignment (probably a server side problem)\n" +\r
- "When contacting Server:" + WsURL + "\n" +\r
- e.toString() +\r
- "\n");\r
- this.allowedServerExceptions = 0;\r
- wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);\r
- wsInfo.appendProgressText(\r
- "Failed to submit sequences for alignment.\n" +\r
- "It is most likely that there is a problem with the server.\n" +\r
- "Just close the window\n");\r
-\r
- // e.printStackTrace(); // TODO: JBPNote DEBUG\r
- }\r
- }\r
-\r
- private jalview.datamodel.Sequence[] getVamsasAlignment(\r
- vamsas.objects.simple.Alignment valign)\r
- {\r
- vamsas.objects.simple.Sequence[] seqs = valign.getSeqs().getSeqs();\r
- jalview.datamodel.Sequence[] msa = new jalview.datamodel.Sequence[seqs.\r
- length];\r
-\r
- for (int i = 0, j = seqs.length; i < j; i++)\r
- {\r
- msa[i] = new jalview.datamodel.Sequence(seqs[i].getId(),\r
- seqs[i].getSeq());\r
- }\r
-\r
- return msa;\r
- }\r
-\r
- void parseResult()\r
- {\r
-\r
- try\r
- {\r
- // OutputHeader = output.getText();\r
- if (result.isFailed())\r
- {\r
- OutputHeader += "Job failed.\n";\r
- }\r
-\r
- if (result.getStatus() != null)\r
- {\r
- OutputHeader += ("\n" + result.getStatus());\r
- }\r
-\r
- if (result.getMsa() != null)\r
- {\r
- OutputHeader += "\nAlignment Object Method Notes\n";\r
-\r
- String[] lines = result.getMsa().getMethod();\r
-\r
- for (int line = 0; line < lines.length; line++)\r
- {\r
- OutputHeader += (lines[line] + "\n");\r
- }\r
-\r
- // JBPNote The returned files from a webservice could be\r
- // hidden behind icons in the monitor window that,\r
- // when clicked, pop up their corresponding data\r
- }\r
-\r
- wsInfo.setProgressText(OutputHeader);\r
- }\r
- catch (Exception ex)\r
- {\r
- ex.printStackTrace();\r
- }\r
- }\r
-\r
- void displayResults(boolean newFrame)\r
- {\r
- SequenceI [] seqs = getVamsasAlignment(result.getMsa());\r
-\r
- if (seqs != null)\r
- {\r
- AlignmentOrder msaorder = new AlignmentOrder(seqs);\r
-\r
- if (preserveOrder)\r
- {\r
- jalview.analysis.AlignmentSorter.recoverOrder(seqs);\r
- }\r
-\r
- jalview.analysis.SeqsetUtils.deuniquify(SeqNames, seqs);\r
-\r
- Alignment al = new Alignment(seqs);\r
- if (dataset!=null)\r
- {\r
- al.setDataset(dataset);\r
- }\r
-\r
- if(newFrame)\r
- {\r
- // TODO: JBPNote Should also rename the query sequence sometime...\r
- AlignFrame af = new AlignFrame(al);\r
-\r
- //>>>This is a fix for the moment, until a better solution is found!!<<<\r
- af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());\r
-\r
- af.addSortByOrderMenuItem(ServiceName + " Ordering",\r
- msaorder);\r
-\r
- Desktop.addInternalFrame(af, alTitle,\r
- AlignFrame.NEW_WINDOW_WIDTH,\r
- AlignFrame.NEW_WINDOW_HEIGHT);\r
-\r
- }\r
- else\r
- {\r
- System.out.println("MERGE WITH OLD FRAME");\r
-\r
- }\r
- }\r
- }\r
- }\r
}\r
--- /dev/null
+package jalview.ws;
+
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.AlignmentOrder;
+import jalview.datamodel.ColumnSelection;
+import jalview.gui.WebserviceInfo;
+import jalview.analysis.AlignSeq;
+import jalview.bin.Cache;
+import jalview.gui.AlignFrame;
+import javax.swing.JOptionPane;
+
+import vamsas.objects.simple.MsaResult;
+import vamsas.objects.simple.Result;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.SeqCigar;
+import jalview.gui.Desktop;
+import jalview.datamodel.SequenceI;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * <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 Thread implements WSClientI {
+ jalview.gui.AlignFrame alignFrame;
+
+ WebserviceInfo wsInfo = null;
+
+ String WebServiceName = null;
+
+ String OutputHeader;
+ AlignmentView input;
+ boolean submitGaps = false; // pass sequences including gaps to alignment
+
+ // service
+
+ boolean preserveOrder = true; // and always store and recover sequence
+
+ // order
+
+ class MsaWSJob {
+ int jobnum = 0; // WebServiceInfo pane for this job
+
+ String jobId; // ws job ticket
+
+ vamsas.objects.simple.MsaResult result = null;
+
+ vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple.SequenceSet();
+
+ /**
+ * MsaWSJob
+ *
+ * @param jobNum
+ * int
+ * @param jobId
+ * String
+ */
+ public MsaWSJob(int jobNum, SequenceI[] inSeqs) {
+ this.jobnum = jobNum;
+ prepareInput(inSeqs);
+ }
+
+ int allowedServerExceptions = 3; // thread dies if too many
+
+ // exceptions.
+ boolean submitted=false;
+ boolean subjobComplete = false;
+
+ Hashtable SeqNames = new Hashtable();
+ Vector emptySeqs = new Vector();
+ private void prepareInput(SequenceI[] seqs) {
+ int nseqs = 0;
+ for (int i = 0; i < seqs.length; i++) {
+ if (seqs[i].getStart() < seqs[i].getEnd()) {
+ nseqs++;
+ }
+ }
+ vamsas.objects.simple.Sequence[] seqarray =
+ (nseqs>0)
+ ? new vamsas.objects.simple.Sequence[nseqs]
+ :null;
+ 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 (seqs[i].getStart() < seqs[i].getEnd()) {
+ seqarray[n] = new vamsas.objects.simple.Sequence();
+ seqarray[n].setId(newname);
+ seqarray[n++].setSeq((submitGaps) ? seqs[i].getSequence()
+ : AlignSeq.extractGaps(
+ jalview.util.Comparison.GapChars, seqs[i]
+ .getSequence()));
+ } else {
+ emptySeqs.add(newname);
+ }
+ }
+ this.seqs = new vamsas.objects.simple.SequenceSet();
+ this.seqs.setSeqs(seqarray);
+ }
+ public Object[] getAlignment() {
+
+ if (result!=null) {
+ SequenceI[] alseqs=null;
+ char alseq_gapchar='-';
+ int alseq_l=0;
+ if (result.getMsa() != null) {
+ alseqs = getVamsasAlignment(result.getMsa());
+ alseq_gapchar=result.getMsa().getGapchar().charAt(0);
+ alseq_l = alseqs.length;
+ }
+ 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;
+ }
+ }
+ // make a gapped string.
+ StringBuffer insbuff=new StringBuffer(w);
+ for (i=0; i<w; i++)
+ insbuff.append(alseq_gapchar);
+ for (i=0, w=emptySeqs.size(); i<w; i++) {
+ t_alseqs[i+alseqs.length] = new jalview.datamodel.Sequence((String)emptySeqs.get(i), insbuff.toString());
+ }
+ 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;
+ }
+ }
+ MsaWSJob jobs[] = null;
+
+ String alTitle; // name which will be used to form new alignment window.
+
+ boolean jobComplete = false;
+
+ Alignment dataset; // dataset to which the new alignment will be
+
+ // associated.
+
+ ext.vamsas.MuscleWS server = null;
+
+ String WsUrl = null;
+
+ /**
+ * set basic options for this (group) of Msa jobs
+ *
+ * @param subgaps
+ * boolean
+ * @param presorder
+ * boolean
+ */
+ MsaWSThread(ext.vamsas.MuscleWS server, String wsUrl,
+ WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame, AlignmentView alview,
+ String wsname, boolean subgaps, boolean presorder) {
+ this.server = server;
+ this.WsUrl = wsUrl;
+ this.wsInfo = wsinfo;
+ this.WebServiceName = wsname;
+ this.input = alview;
+ this.submitGaps = subgaps;
+ this.preserveOrder = presorder;
+ this.alignFrame = alFrame;
+ }
+
+ /**
+ * 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(ext.vamsas.MuscleWS server, String wsUrl,
+ WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame,
+ String wsname, String title, AlignmentView _msa, boolean subgaps,
+ boolean presorder, Alignment seqset) {
+ this(server, wsUrl, wsinfo, alFrame, _msa, wsname, subgaps, presorder);
+ OutputHeader = wsInfo.getProgressText();
+ alTitle = title;
+ dataset = seqset;
+ SeqCigar[] msa = _msa.getSequences();
+ int[] contigs = _msa.getContigs();
+ int njobs=1;
+ if (contigs != null && contigs.length > 0) {
+ int start = 0;
+ njobs=0;
+ int width = _msa.getWidth();
+ for (int contig = 0; contig < contigs.length; contig += 3) {
+ if ((contigs[contig+1] - start) > 0) {
+ njobs++;
+ }
+ width+=contigs[contig+2];// end up with full region width (including hidden regions)
+ start = contigs[contig+1] + contigs[contig + 2];
+ }
+ if (start<width) {
+ njobs++;
+ }
+ jobs = new MsaWSJob[njobs];
+ start=0;
+ int j=0;
+ for (int contig = 0; contig < contigs.length; contig += 3) {
+ if (contigs[contig+1] - start > 0) {
+ SequenceI mseq[] = new SequenceI[msa.length];
+ for (int s = 0; s < mseq.length; s++) {
+ mseq[s] = msa[s].getSeq('-').getSubSequence(start,
+ contigs[contig+1]);
+ }
+ if (j!=0) {
+ jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq);
+ } else {
+ jobs[j] = new MsaWSJob(0, mseq);
+ }
+ wsinfo.setProgressName("region "+jobs[j].jobnum,jobs[j].jobnum);
+ wsinfo.setProgressText(jobs[j].jobnum, OutputHeader);
+ j++;
+ }
+ start = contigs[contig+1] + contigs[contig + 2];
+ }
+ if (start<width) {
+ SequenceI mseq[] = new SequenceI[msa.length];
+ for (int s = 0; s < mseq.length; s++) {
+ mseq[s] = msa[s].getSeq('-').getSubSequence(start,
+ width+1);
+ }
+ if (j!=0) {
+ jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq);
+ } else {
+ jobs[j] = new MsaWSJob(0, mseq);
+ }
+ wsinfo.setProgressName("region "+jobs[j].jobnum,jobs[j].jobnum);
+ wsinfo.setProgressText(jobs[j].jobnum, OutputHeader);
+ j++;
+ }
+ } else {
+ SequenceI mseq[] = new SequenceI[msa.length];
+ for (int s = 0; s < mseq.length; s++) {
+ mseq[s] = msa[s].getSeq('-');
+ }
+ jobs = new MsaWSJob[1];
+ wsinfo.setProgressText(OutputHeader); // ensures default text
+ jobs[0] = new MsaWSJob(0, mseq);
+ }
+ }
+
+ 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].submitted && !jobs[job].subjobComplete)
+ {
+ String cancelledMessage = "";
+ try {
+ vamsas.objects.simple.WsJobId cancelledJob = server
+ .cancel(jobs[job].jobId);
+ if (cancelledJob.getStatus() == 2) {
+ // CANCELLED_JOB
+ cancelledMessage = "Job cancelled.";
+ jobs[job].subjobComplete = true;
+ jobs[job].result = null;
+ wsInfo.setStatus(jobs[job].jobnum, WebserviceInfo.STATE_CANCELLED_OK);
+ } else if (cancelledJob.getStatus() == 3) {
+ // VALID UNSTOPPABLE JOB
+ cancelledMessage += "Server cannot cancel this job. just close the window.\n";
+ cancelled = false;
+ wsInfo.setStatus(jobs[job].jobnum, WebserviceInfo.STATE_CANCELLED_OK);
+ }
+
+ if (cancelledJob.getJobId() != null) {
+ cancelledMessage += ("[" + cancelledJob.getJobId() + "]");
+ }
+
+ cancelledMessage += "\n";
+ } catch (Exception exc) {
+ cancelledMessage += ("\nProblems cancelling the job : Exception received...\n"
+ + exc + "\n");
+ exc.printStackTrace();
+ }
+ wsInfo.setProgressText(jobs[job].jobnum, OutputHeader
+ + cancelledMessage + "\n");
+ }
+ }
+ if (cancelled) {
+ wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
+ jobComplete = true;
+ }
+ } 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 run() {
+
+ while (!jobComplete) {
+ int running=0;
+ int queuing=0;
+ int finished=0;
+ int error=0;
+ int serror=0;
+ for (int j=0; j<jobs.length; j++) {
+
+ if (!jobs[j].submitted && jobs[j].seqs.getSeqs()!=null)
+ StartJob(jobs[j]);
+
+ if (jobs[j].submitted && !jobs[j].subjobComplete) {
+ try {
+ if ((jobs[j].result = server.getResult(jobs[j].jobId)) == null) {
+ throw (new Exception(
+ "Timed out when communicating with server\nTry again later.\n"));
+ }
+ jalview.bin.Cache.log.debug("Job "+j+" Result state " + jobs[j].result.getState()
+ + "(ServerError=" + jobs[j].result.isServerError() + ")");
+ } catch (Exception 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].result=null; // may contain out of date result object
+ wsInfo.setStatus(jobs[j].jobnum,
+ WebserviceInfo.STATE_STOPPED_ERROR);
+ JOptionPane
+ .showInternalMessageDialog(
+ Desktop.desktop,
+ "Out of memory handling result for job !!"
+ + "\nSee help files for increasing Java Virtual Machine memory.",
+ "Out of memory", JOptionPane.WARNING_MESSAGE);
+ Cache.log.error("Out of memory when retrieving Job "+j+" id:" + WsUrl+"/"+jobs[j].jobId, er);
+ System.gc();
+ }
+ }
+ if (jobs[j].result!=null) {
+ String progheader="";
+ // Parse state of job[j]
+ if (jobs[j].result.isRunning()) {
+ running++;
+ wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_RUNNING);
+ } else if (jobs[j].result.isQueued()) {
+ queuing++;
+ wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_QUEUING);
+ } else if (jobs[j].result.isFinished()) {
+ finished++;
+ jobs[j].subjobComplete = true;
+ wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_OK);
+ } else if (jobs[j].result.isFailed()) {
+ progheader += "Job failed.\n";
+ jobs[j].subjobComplete=true;
+ wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_ERROR);
+ error++;
+ } else if (jobs[j].result.isServerError()) {
+ serror++;
+ jobs[j].subjobComplete = true;
+ wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_SERVERERROR);
+ } else if (jobs[j].result.isBroken() || jobs[j].result.isFailed()) {
+ error++;
+ jobs[j].subjobComplete=true;
+ wsInfo.setStatus(jobs[j].jobnum,WebserviceInfo.STATE_STOPPED_ERROR);
+ }
+ // and pass on any sub-job messages to the user
+ wsInfo.setProgressText(jobs[j].jobnum, OutputHeader);
+ wsInfo.appendProgressText(jobs[j].jobnum, progheader);
+ if (jobs[j].result.getStatus() != null) {
+ wsInfo.appendProgressText(jobs[j].jobnum, jobs[j].result.getStatus());
+ }
+ } else {
+ if (jobs[j].submitted && jobs[j].subjobComplete) {
+ if (jobs[j].allowedServerExceptions==0) {
+ serror++;
+ } else if (jobs[j].result==null) {
+ error++;
+ }
+ }
+ }
+ }
+ // Decide on overall state based on collected jobs[] states
+ if (running>0) {
+ wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
+ } else if (queuing>0) {
+ wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
+ } else {
+ jobComplete=true;
+ if (finished>0) {
+ wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
+ } else if (error>0) {
+ wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+ } else if (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) {
+ parseResult(); // tidy up and make results available to user
+ }
+ }
+
+ void StartJob(MsaWSJob j) {
+ if (j.submitted) {
+ if (Cache.log.isDebugEnabled()) {
+ Cache.log.debug("Tried to submit an already submitted job "+j.jobId);
+ }
+ return;
+ }
+ if (j.seqs.getSeqs()==null) {
+ // special case - selection consisted entirely of empty sequences...
+ j.submitted=true;
+ j.result=new MsaResult();
+ j.result.setFinished(true);
+ j.result.setStatus("Empty Alignment Job");
+ j.result.setMsa(null);
+ }
+ try {
+ vamsas.objects.simple.WsJobId jobsubmit = server.align(j.seqs);
+
+ if ((jobsubmit != null) && (jobsubmit.getStatus() == 1)) {
+ j.jobId = jobsubmit.getJobId();
+ j.submitted=true;
+ j.subjobComplete = false;
+ // System.out.println(WsURL + " Job Id '" + jobId + "'");
+ } else {
+ if (jobsubmit == null) {
+ throw new Exception(
+ "Server at "
+ + WsUrl
+ + " returned null object, it probably cannot be contacted. Try again later ?");
+ }
+
+ throw new Exception(jobsubmit.getJobId());
+ }
+ } catch (Exception e) {
+ // 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.allowedServerExceptions = 0;
+ wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
+ wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
+ wsInfo
+ .appendProgressText(
+ j.jobnum,
+ "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
+ }
+ }
+
+ private jalview.datamodel.Sequence[] getVamsasAlignment(
+ vamsas.objects.simple.Alignment valign) {
+ vamsas.objects.simple.Sequence[] seqs = valign.getSeqs().getSeqs();
+ jalview.datamodel.Sequence[] msa = new jalview.datamodel.Sequence[seqs.length];
+
+ for (int i = 0, j = seqs.length; i < j; i++) {
+ msa[i] = new jalview.datamodel.Sequence(seqs[i].getId(), seqs[i]
+ .getSeq());
+ }
+
+ return msa;
+ }
+
+ void parseResult() {
+ try {
+ for (int j=0; j<jobs.length; j++) {
+ if (jobs[j].submitted && jobs[j].subjobComplete) {
+ if (jobs[j].result!=null) {
+ vamsas.objects.simple.Alignment valign = jobs[j].result.getMsa();
+ if (valign!= null) {
+ wsInfo.appendProgressText(jobs[j].jobnum,"\nAlignment Object Method Notes\n");
+ String[] lines = valign.getMethod();
+ for (int line = 0; line < lines.length; line++) {
+ wsInfo.appendProgressText(jobs[j].jobnum, lines[line] + "\n");
+ }
+ // 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);
+ }
+
+ 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();
+ }
+ void displayResults(boolean newFrame) {
+ int contigs[] = input.getContigs();
+ SeqCigar[] seqs = input.getSequences();
+ SequenceI[] alignment = new SequenceI[seqs.length];
+ ColumnSelection columnselection = new ColumnSelection();
+ Vector alorders=new Vector();
+ if (contigs != null && contigs.length > 0) {
+ int cshift=0;
+ int start = 0;
+ int nwidth = 0;
+ int j=0;
+ for (int contig = 0; contig < contigs.length; contig += 3) {
+ if (cshift+contigs[contig] - start > 0) {
+ Object[] subalg = jobs[j++].getAlignment();
+ alorders.add(subalg[1]);
+ SequenceI mseq[] = (SequenceI[]) subalg[0];
+ int width = mseq[0].getLength();
+ for (int s = 0; s < mseq.length; s++) {
+ if (alignment[s]==null) {
+ alignment[s] = mseq[s];
+ } else {
+ alignment[s].setSequence(alignment[s].getSequence()+mseq[s].getSequence());
+ if (alignment[s].getEnd()<mseq[s].getEnd())
+ alignment[s].setEnd(mseq[s].getEnd());
+ ((AlignmentOrder) subalg[1]).updateSequence(mseq[s], alignment[s]);
+ }
+ }
+ nwidth+=width;
+ }
+ // advance to begining of visible region
+ start = cshift+contigs[contig] + contigs[contig + 2];
+ // add hidden segment to right of next region
+ for (int s=0; s<seqs.length; s++) {
+ SequenceI hseq = seqs[s].getSeq('-').getSubSequence(cshift+contigs[contig], start);
+ if (alignment[s]==null) {
+ alignment[s] = hseq;
+ } else {
+ alignment[s].setSequence(alignment[s].getSequence()+hseq.getSequence());
+ alignment[s].setEnd(hseq.getEnd());
+ }
+ }
+ // mark hidden segment as hidden in the new alignment
+ columnselection.hideColumns(nwidth, nwidth+contigs[contig+2]-1);
+ nwidth+=contigs[contig+2];
+ cshift+=contigs[contig+2];
+ }
+ // Do final job - if it exists
+ if (j<jobs.length) {
+ Object[] subalg = jobs[j].getAlignment();
+ alorders.add(subalg[1]);
+ SequenceI mseq[] = (SequenceI[]) subalg[0];
+ int width = mseq[0].getLength();
+ for (int s = 0; s < mseq.length; s++) {
+ if (alignment[s]==null) {
+ alignment[s] = mseq[s];
+ } else {
+ alignment[s].setSequence(alignment[s].getSequence()+mseq[s].getSequence());
+ alignment[s].setEnd(mseq[s].getEnd());
+ ((AlignmentOrder) subalg[1]).updateSequence(mseq[s], alignment[s]);
+ }
+ }
+ nwidth+=width;
+ }
+ } else {
+ if (jobs[0].subjobComplete && jobs[0].result!=null) {
+ Object[] alg = jobs[0].getAlignment();
+ alignment = (SequenceI[]) alg[0];
+ alorders.add(alg[1]);
+ } else {
+ alignment = SeqCigar.createAlignmentSequences(seqs, '-', columnselection,null);
+ }
+ }
+ Alignment al = new Alignment(alignment);
+ if (dataset != null) {
+ al.setDataset(dataset);
+ }
+
+ if (newFrame) {
+ // TODO: JBPNote Should also rename the query sequence
+ // sometime...
+ AlignFrame af = new AlignFrame(al,columnselection);
+
+ // >>>This is a fix for the moment, until a better solution is
+ // found!!<<<
+ af.getFeatureRenderer().transferSettings(
+ alignFrame.getFeatureRenderer());
+ if (alorders.size()>0) {
+ if (alorders.size()==1) {
+ af.addSortByOrderMenuItem(WebServiceName + " Ordering",
+ (AlignmentOrder) alorders.get(0));
+ } else {
+ for (int i=0,l=alorders.size(); i<l; i++) {
+ af.addSortByOrderMenuItem(WebServiceName + " Region "+i+" Ordering",
+ (AlignmentOrder) alorders.get(i));
+ }
+ }
+ }
+
+ Desktop.addInternalFrame(af, alTitle,
+ AlignFrame.NEW_WINDOW_WIDTH,
+ AlignFrame.NEW_WINDOW_HEIGHT);
+
+ } else {
+ System.out.println("MERGE WITH OLD FRAME");
+
+ }
+ }
+}