X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fws%2FMsaWSClient.java;h=7d65cebb08cfd5f3b3476a2ea288fb3b0968fc95;hb=6fc9aca27f606f6e3a0121597896e1a5dae35c36;hp=91f8ebbfd4d751f3055d015fd2d49f9569d8900d;hpb=24ad8bbb87343e317452c0dcb22efd800e7986d6;p=jalview.git diff --git a/src/jalview/ws/MsaWSClient.java b/src/jalview/ws/MsaWSClient.java index 91f8ebb..7d65ceb 100755 --- a/src/jalview/ws/MsaWSClient.java +++ b/src/jalview/ws/MsaWSClient.java @@ -1,88 +1,212 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer + * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ package jalview.ws; -import org.apache.axis.client.*; -import javax.xml.namespace.QName; -import java.util.*; +import ext.vamsas.*; + +import jalview.analysis.AlignSeq; + import jalview.datamodel.*; + import jalview.gui.*; -import javax.swing.*; + import java.util.*; -import java.awt.*; -import jalview.analysis.AlignSeq; -import ext.vamsas.*; -import vamsas.objects.*; +import javax.swing.*; + +/** + * DOCUMENT ME! + * + * @author $author$ + * @version $Revision$ + */ public class MsaWSClient + extends WSClient { - int jobsRunning = 0; + /** + * server is a WSDL2Java generated stub for an archetypal MsaWSI service. + */ ext.vamsas.MuscleWS server; - WebserviceInfo wsInfo; + AlignFrame alignFrame; + + /** - * MsaWSClient + * Creates a new MsaWSClient object that uses a service + * given by an externally retrieved ServiceHandle * - * @param msa SequenceI[] + * @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(SequenceI[] msa) + + public MsaWSClient(ext.vamsas.ServiceHandle sh, String altitle, + SequenceI[] msa, + boolean submitGaps, boolean preserveOrder, + Alignment seqdataset, + AlignFrame _alignFrame) { - wsInfo = new jalview.gui.WebserviceInfo("Muscle Alignment job", - "Edgar, Robert C. (2004), MUSCLE: multiple sequence alignment with high accuracy and high throughput, Nucleic Acids Research 32(5), 1792-97."); + alignFrame = _alignFrame; + if (!sh.getAbstractName().equals("MsaWS")) + { + JOptionPane.showMessageDialog(Desktop.desktop, + "The Service called \n" + sh.getName() + + "\nis not a \nMultiple Sequence Alignment Service !", + "Internal Jalview Error", + JOptionPane.WARNING_MESSAGE); - wsInfo.setProgressText("Job details\n"); + return; + } + if ((wsInfo = this.setWebService(sh))==null) + { + JOptionPane.showMessageDialog(Desktop.desktop, + "The Multiple Sequence Alignment Service named " + + sh.getName() + + " is unknown", "Internal Jalview Error", + JOptionPane.WARNING_MESSAGE); - MuscleWSServiceLocator loc = new MuscleWSServiceLocator(); // Default - try { - this.server = (MuscleWS) loc.getMuscleWS(); // JBPNote will be set from properties - } - catch (Exception ex) { - wsInfo.setProgressText("Serious! MuscleWS Service location failed\nfor URL :" - +loc.getMuscleWSAddress()+"\n"+ex.getMessage()); - ex.printStackTrace(); + return; + } + startMsaWSClient(altitle, msa, submitGaps, preserveOrder, seqdataset); + + } + + + private void startMsaWSClient(String altitle, SequenceI[] msa, + boolean submitGaps, boolean preserveOrder, Alignment seqdataset) + { + if (!locateWebService()) + { + return; } - MsaWSThread musclethread = new MsaWSThread(msa); + wsInfo.setProgressText( ( (submitGaps) ? "Re-alignment" : "Alignment") + + " of " + altitle + "\nJob details\n"); + + MsaWSThread musclethread = new MsaWSThread(WebServiceName + + " alignment of " + altitle, msa, + submitGaps, preserveOrder, seqdataset); wsInfo.setthisService(musclethread); musclethread.start(); } - - protected class MsaWSThread extends Thread implements WSClientI + /** + * Initializes the server field with a valid service implementation. + * + * @return true if service was located. + */ + private boolean locateWebService() { - String ServiceName = "MuscleWS"; - public boolean isCancellable() + // TODO: MuscleWS transmuted to generic MsaWS client + MuscleWSServiceLocator loc = new MuscleWSServiceLocator(); // Default + + try { - return true; + this.server = (MuscleWS) loc.getMuscleWS(new java.net.URL(WsURL)); + ( (MuscleWSSoapBindingStub)this.server).setTimeout(60000); // One minute timeout + } + catch (Exception ex) + { + wsInfo.setProgressText("Serious! " + WebServiceName + + " Service location failed\nfor URL :" + WsURL + + "\n" + + ex.getMessage()); + wsInfo.setStatus(WebserviceInfo.ERROR); + ex.printStackTrace(); + + return false; } + loc.getEngine().setOption("axis", "1"); + + return true; + } + + protected class MsaWSThread + extends Thread implements WSClientI + { + String ServiceName = WebServiceName; String OutputHeader; vamsas.objects.simple.MsaResult result = null; vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple. SequenceSet(); + Hashtable SeqNames = null; + boolean submitGaps = false; // pass sequences including gaps to alignment service + boolean preserveOrder = true; // and always store and recover sequence order String jobId; + String alTitle; // name which will be used to form new alignment window. int allowedServerExceptions = 3; // thread dies if too many exceptions. - MsaWSThread(SequenceI[] msa) + boolean jobComplete = false; + + Alignment dataset; // dataset to which the new alignment will be associated. + + MsaWSThread(String title, SequenceI[] msa, boolean subgaps, + boolean presorder, Alignment seqset) { + alTitle = title; + submitGaps = subgaps; + preserveOrder = presorder; + dataset = seqset; OutputHeader = wsInfo.getProgressText(); + SeqNames = new Hashtable(); + vamsas.objects.simple.Sequence[] seqarray = new vamsas.objects.simple. Sequence[msa.length]; + for (int i = 0; i < msa.length; i++) { + String newname = jalview.analysis.SeqsetUtils.unique_name(i); + + // uniquify as we go + // TODO: JBPNote: this is a ubiquitous transformation - set of jalview seq objects to vamsas sequences with name preservation + SeqNames.put(newname, + jalview.analysis.SeqsetUtils.SeqCharacterHash(msa[i])); seqarray[i] = new vamsas.objects.simple.Sequence(); - seqarray[i].setId(msa[i].getName()); - seqarray[i].setSeq(AlignSeq.extractGaps("-. ", msa[i].getSequence())); + seqarray[i].setId(newname); + seqarray[i].setSeq( (submitGaps) ? msa[i].getSequence() + : AlignSeq.extractGaps( + jalview.util.Comparison.GapChars, + msa[i].getSequence())); } + this.seqs = new vamsas.objects.simple.SequenceSet(); this.seqs.setSeqs(seqarray); } - boolean jobComplete = false; + public boolean isCancellable() + { + return true; + } + + public void cancelJob() + { + if ( (jobId != null) && !jobId.equals("") && !jobComplete) + { + String cancelledMessage = ""; - public void cancelJob() { - if (!jobComplete) { - String cancelledMessage=""; - try { + try + { vamsas.objects.simple.WsJobId cancelledJob = server.cancel(jobId); + if (cancelledJob.getStatus() == 2) { // CANCELLED_JOB @@ -92,68 +216,158 @@ public class MsaWSClient jobsRunning--; result = null; } - else - if (cancelledJob.getStatus() == 3) + else if (cancelledJob.getStatus() == 3) { // VALID UNSTOPPABLE JOB cancelledMessage += "Server cannot cancel this job. just close the window.\n"; } + if (cancelledJob.getJobId() != null) - cancelledMessage += "[" + cancelledJob.getJobId() + "]"; - cancelledMessage +="\n"; - } catch (Exception exc) { - cancelledMessage +="\nProblems cancelling the job : Exception received...\n"+exc+"\n"; + { + cancelledMessage += ("[" + cancelledJob.getJobId() + + "]"); + } + + cancelledMessage += "\n"; + } + catch (Exception exc) + { + cancelledMessage += + ("\nProblems cancelling the job : Exception received...\n" + + exc + "\n"); exc.printStackTrace(); } - wsInfo.setProgressText(OutputHeader + cancelledMessage+"\n"); + + wsInfo.setProgressText(OutputHeader + cancelledMessage + "\n"); + } + 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() { - StartJob(); while (!jobComplete && (allowedServerExceptions > 0)) { try { - result = server.getResult(jobId); - - if( result.isRunning() ) - wsInfo.setStatus(WebserviceInfo.STATE_RUNNING); - else if( result.isQueued() ) - wsInfo.setStatus(WebserviceInfo.STATE_QUEUING); + if ( (result = server.getResult(jobId)) == null) + { + throw (new Exception( + "Timed out when communicating with server\nTry again later.\n")); + } + jalview.bin.Cache.log.debug("Result state " + result.getState() + + "(ServerError=" + result.isServerError() + + ")"); + if (result.isRunning()) + { + wsInfo.setStatus(WebserviceInfo.STATE_RUNNING); + } + else if (result.isQueued()) + { + wsInfo.setStatus(WebserviceInfo.STATE_QUEUING); + } if (result.isFinished()) { + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK); parseResult(); jobComplete = true; jobsRunning--; } else { - wsInfo.setProgressText(OutputHeader + "\n" + result.getStatus()); - if (! (result.isJobFailed() || result.isServerError())) + if (result.getStatus() != null) + { + wsInfo.setProgressText(OutputHeader + "\n"+ result.getStatus()); + } + if (result.isServerError()) + { + jobComplete = true; + jobsRunning--; + + break; + } + if (! (result.isJobFailed() || result.isServerError() || + result.isBroken() || result.isFailed())) { Thread.sleep(5000); + // System.out.println("I'm alive "+seqid+" "+jobid); } + else + { + jobComplete = true; + jobsRunning--; + break; + } } } catch (Exception ex) { allowedServerExceptions--; - wsInfo.appendProgressText("\n"+ServiceName+" Server exception!\n" + ex.getMessage()); - ex.printStackTrace(); + wsInfo.appendProgressText("\n" + ServiceName + + " Server exception!\n" + ex.getMessage()); + System.err.println(ServiceName + " Server exception: " + + ex.getMessage()); + + // ex.printStackTrace(); JBPNote Debug + try + { + if (allowedServerExceptions > 0) + { + Thread.sleep(5000); + } + } + catch (InterruptedException ex1) + { + } + } + catch(OutOfMemoryError er) + { + jobComplete = true; + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); + JOptionPane.showInternalMessageDialog(Desktop.desktop, + "Out of memory handling result!!" + +"\nSee help files for increasing Java Virtual Machine memory." + ,"Out of memory", JOptionPane.WARNING_MESSAGE ); + System.out.println("MsaWSClient: "+er); + System.gc(); } } - if (! (result!=null && (result.isJobFailed() || result.isServerError()))) - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK); + if (allowedServerExceptions == 0) + { + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); + } else - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); + { + if (result != null) + { + if ( !(result.isJobFailed() || result.isServerError())) + { + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK); + } + + if (result.isBroken() || result.isFailed()) + { + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); + } + + if (result.isServerError()) + { + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); + } + } + } } void StartJob() @@ -161,74 +375,126 @@ public class MsaWSClient try { vamsas.objects.simple.WsJobId jobsubmit = server.align(seqs); - if (jobsubmit.getStatus()==1) { - System.out.println(jobId=jobsubmit.getJobId()); - } else { + + if ( (jobsubmit != null) && (jobsubmit.getStatus() == 1)) + { + jobId = jobsubmit.getJobId(); + 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) { - System.out.println(ServiceName + " Client: Failed to submit the prediction\n" + - e.toString() + "\n"); - e.printStackTrace(); + // 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"); + this.allowedServerExceptions = 0; + wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); + wsInfo.appendProgressText( + "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 void addFloatAnnotations(Alignment al, int[] gapmap, Vector values, String Symname, String Visname, float min, float max, int winLength) { + 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]; - Annotation[] annotations = new Annotation[al.getWidth()]; - for (int j = 0; j < values.size(); j++) + for (int i = 0, j = seqs.length; i < j; i++) { - float value = Float.parseFloat(values.get(j).toString()); - annotations[gapmap[j]] = new Annotation("", value+"",' ',value); + msa[i] = new jalview.datamodel.Sequence(seqs[i].getId(), + seqs[i].getSeq()); } - al.addAnnotation(new AlignmentAnnotation(Symname, Visname, annotations, min, max, winLength)); - } - 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