/* * 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 ext.vamsas.*; import jalview.analysis.AlignSeq; import jalview.datamodel.*; import jalview.gui.*; import java.util.*; import javax.swing.*; /** * DOCUMENT ME! * * @author $author$ * @version $Revision$ */ public class MsaWSClient extends WSClient { /** * server is a WSDL2Java generated stub for an archetypal MsaWSI service. */ ext.vamsas.MuscleWS server; /** * 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(ext.vamsas.ServiceHandle sh, String altitle, SequenceI[] msa, boolean submitGaps, boolean preserveOrder, Alignment seqdataset) { 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); 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); return; } startMsaWSClient(altitle, msa, submitGaps, preserveOrder, seqdataset); } private void startMsaWSClient(String altitle, SequenceI[] msa, boolean submitGaps, boolean preserveOrder, Alignment seqdataset) { if (!locateWebService()) { return; } 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(); } /** * Initializes the server field with a valid service implementation. * * @return true if service was located. */ private boolean locateWebService() { // TODO: MuscleWS transmuted to generic MsaWS client MuscleWSServiceLocator loc = new MuscleWSServiceLocator(); // Default try { 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. 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(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); } public boolean isCancellable() { return true; } public void cancelJob() { if ( (jobId != null) && !jobId.equals("") && !jobComplete) { String cancelledMessage = ""; try { vamsas.objects.simple.WsJobId cancelledJob = server.cancel(jobId); if (cancelledJob.getStatus() == 2) { // CANCELLED_JOB cancelledMessage = "Job cancelled."; wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK); jobComplete = true; jobsRunning--; result = null; } 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"); exc.printStackTrace(); } 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 { 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 { 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()); 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 (allowedServerExceptions == 0) { wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR); } else { 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() { try { vamsas.objects.simple.WsJobId jobsubmit = server.align(seqs); 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) { // 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 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() { SequenceI[] seqs = null; try { // OutputHeader = output.getText(); if (result.isFailed()) { OutputHeader += "Job failed.\n"; } if (result.getStatus() != null) { OutputHeader += ("\n" + result.getStatus()); } if (result.getMsa() != null) { OutputHeader += "\nAlignment Object Method Notes\n"; String[] lines = result.getMsa().getMethod(); for (int line = 0; line < lines.length; line++) { OutputHeader += (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 seqs = getVamsasAlignment(result.getMsa()); } wsInfo.setProgressText(OutputHeader); if (seqs != null) { AlignmentOrder msaorder = new AlignmentOrder(seqs); if (preserveOrder) { jalview.analysis.AlignmentSorter.recoverOrder(seqs); } jalview.analysis.SeqsetUtils.deuniquify(SeqNames, seqs); Alignment al = new Alignment(seqs); if (dataset!=null) { al.setDataset(dataset); } // TODO: JBPNote Should also rename the query sequence sometime... AlignFrame af = new AlignFrame(al); af.addSortByOrderMenuItem(ServiceName + " Ordering", msaorder); Desktop.addInternalFrame(af, alTitle, AlignFrame.NEW_WINDOW_WIDTH, AlignFrame.NEW_WINDOW_HEIGHT); } } catch (Exception ex) { ex.printStackTrace(); } } } }