62f076a284f9595aa0b31cb1ca549812bbf81b2e
[jalview.git] / src / jalview / ws / MsaWSThread.java
1 package jalview.ws;
2
3 import java.util.*;
4
5 import jalview.analysis.*;
6 import jalview.bin.*;
7 import jalview.datamodel.*;
8 import jalview.datamodel.Alignment;
9 import jalview.datamodel.Sequence;
10 import jalview.gui.*;
11 import vamsas.objects.simple.MsaResult;
12
13 /**
14  * <p>
15  * Title:
16  * </p>
17  *
18  * <p>
19  * Description:
20  * </p>
21  *
22  * <p>
23  * Copyright: Copyright (c) 2004
24  * </p>
25  *
26  * <p>
27  * Company: Dundee University
28  * </p>
29  *
30  * @author not attributable
31  * @version 1.0
32  */
33 class MsaWSThread
34     extends WSThread implements WSClientI
35 {
36   boolean submitGaps = false; // pass sequences including gaps to alignment
37
38   // service
39
40   boolean preserveOrder = true; // and always store and recover sequence
41
42   // order
43
44   class MsaWSJob extends WSThread.WSJob
45   {
46     // hold special input for this
47     vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple.
48         SequenceSet();
49
50     /**
51      * MsaWSJob
52      *
53      * @param jobNum
54      *            int
55      * @param jobId
56      *            String
57      */
58     public MsaWSJob(int jobNum, SequenceI[] inSeqs)
59     {
60       this.jobnum = jobNum;
61       if (!prepareInput(inSeqs, 2))
62       {
63         submitted = true;
64         subjobComplete = true;
65         result = new MsaResult();
66         result.setFinished(true);
67         result.setStatus("Job never ran - input returned to user.");
68       }
69
70     }
71
72     Hashtable SeqNames = new Hashtable();
73     Vector emptySeqs = new Vector();
74     /**
75      * prepare input sequences for MsaWS service
76      * @param seqs jalview sequences to be prepared
77      * @param minlen minimum number of residues required for this MsaWS service
78      * @return true if seqs contains sequences to be submitted to service.
79      */
80     private boolean prepareInput(SequenceI[] seqs, int minlen)
81     {
82       int nseqs = 0;
83       if (minlen < 0)
84       {
85         throw new Error("Implementation error: minlen must be zero or more.");
86       }
87       for (int i = 0; i < seqs.length; i++)
88       {
89         if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
90         {
91           nseqs++;
92         }
93       }
94       boolean valid = nseqs > 1; // need at least two seqs
95       vamsas.objects.simple.Sequence[] seqarray =
96           (valid)
97           ? new vamsas.objects.simple.Sequence[nseqs]
98           : null;
99       for (int i = 0, n = 0; i < seqs.length; i++)
100       {
101
102         String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
103         // for
104         // any
105         // subjob
106         SeqNames.put(newname, jalview.analysis.SeqsetUtils
107                      .SeqCharacterHash(seqs[i]));
108         if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
109         {
110           seqarray[n] = new vamsas.objects.simple.Sequence();
111           seqarray[n].setId(newname);
112           seqarray[n++].setSeq( (submitGaps) ? seqs[i].getSequence()
113                                : AlignSeq.extractGaps(
114                                    jalview.util.Comparison.GapChars, seqs[i]
115                                    .getSequence()));
116         }
117         else
118         {
119           String empty = null;
120           if (seqs[i].getEnd() >= seqs[i].getStart())
121           {
122             empty = (submitGaps) ? seqs[i].getSequence()
123                 : AlignSeq.extractGaps(
124                     jalview.util.Comparison.GapChars, seqs[i]
125                     .getSequence());
126           }
127           emptySeqs.add(new String[]
128                         {newname, empty});
129         }
130       }
131       this.seqs = new vamsas.objects.simple.SequenceSet();
132       this.seqs.setSeqs(seqarray);
133       return valid;
134     }
135
136     /**
137      *
138      * @return true if getAlignment will return a valid alignment result.
139      */
140     public boolean hasResults()
141     {
142       if (subjobComplete && result != null && result.isFinished()
143           && ((MsaResult) result).getMsa() != null && ((MsaResult) result).getMsa().getSeqs() != null)
144       {
145         return true;
146       }
147       return false;
148     }
149
150     public Object[] getAlignment()
151     {
152
153       if (result != null && result.isFinished())
154       {
155         SequenceI[] alseqs = null;
156         char alseq_gapchar = '-';
157         int alseq_l = 0;
158         if (((MsaResult) result).getMsa() != null)
159         {
160           alseqs = getVamsasAlignment(((MsaResult) result).getMsa());
161           alseq_gapchar = ((MsaResult) result).getMsa().getGapchar().charAt(0);
162           alseq_l = alseqs.length;
163         }
164         if (emptySeqs.size() > 0)
165         {
166           SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
167           // get width
168           int i, w = 0;
169           if (alseq_l > 0)
170           {
171             for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
172             {
173               if (w < alseqs[i].getLength())
174               {
175                 w = alseqs[i].getLength();
176               }
177               t_alseqs[i] = alseqs[i];
178               alseqs[i] = null;
179             }
180           }
181           // check that aligned width is at least as wide as emptySeqs width.
182           int ow = w, nw = w;
183           for (i = 0, w = emptySeqs.size(); i < w; i++)
184           {
185             String[] es = (String[]) emptySeqs.get(i);
186             if (es != null && es[1] != null)
187             {
188               int sw = es[1].length();
189               if (nw < sw)
190               {
191                 nw = sw;
192               }
193             }
194           }
195           // make a gapped string.
196           StringBuffer insbuff = new StringBuffer(w);
197           for (i = 0; i < nw; i++)
198           {
199             insbuff.append(alseq_gapchar);
200           }
201           if (ow < nw)
202           {
203             for (i = 0; i < alseq_l; i++)
204             {
205               int sw = t_alseqs[i].getLength();
206               if (nw > sw)
207               {
208                 // pad at end
209                 alseqs[i].setSequence(t_alseqs[i].getSequence() +
210                                       insbuff.substring(0, sw - nw));
211               }
212             }
213           }
214           for (i = 0, w = emptySeqs.size(); i < w; i++)
215           {
216             String[] es = (String[]) emptySeqs.get(i);
217             if (es[1] == null)
218             {
219               t_alseqs[i +
220                   alseq_l] = new jalview.datamodel.Sequence(es[0],
221                   insbuff.toString(), 1, 0);
222             }
223             else
224             {
225               if (es[1].length() < nw)
226               {
227                 t_alseqs[i +
228                     alseq_l] = new jalview.datamodel.Sequence(es[0],
229                     es[1] + insbuff.substring(0, nw - es[1].length()), 1,
230                     1 + es[1].length());
231               }
232               else
233               {
234                 t_alseqs[i +
235                     alseq_l] = new jalview.datamodel.Sequence(es[0], es[1]);
236               }
237             }
238           }
239           alseqs = t_alseqs;
240         }
241         AlignmentOrder msaorder = new AlignmentOrder(alseqs);
242         // always recover the order - makes parseResult()'s life easier.
243         jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
244         // account for any missing sequences
245         jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
246         return new Object[]
247             {
248             alseqs, msaorder};
249       }
250       return null;
251     }
252     /**
253      * mark subjob as cancelled and set result object appropriatly
254      */
255     void cancel() {
256       cancelled=true;
257       subjobComplete = true;
258       result = null;
259     }
260     /**
261      *
262      * @return boolean true if job can be submitted.
263      */
264     boolean hasValidInput() {
265       if (seqs.getSeqs()!=null)
266         return true;
267       return false;
268     }
269   }
270
271
272   String alTitle; // name which will be used to form new alignment window.
273   Alignment dataset; // dataset to which the new alignment will be
274
275   // associated.
276
277   ext.vamsas.MuscleWS server = null;
278   /**
279    * set basic options for this (group) of Msa jobs
280    *
281    * @param subgaps
282    *            boolean
283    * @param presorder
284    *            boolean
285    */
286   MsaWSThread(ext.vamsas.MuscleWS server, String wsUrl,
287               WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame,
288               AlignmentView alview,
289               String wsname, boolean subgaps, boolean presorder)
290   {
291     this.server = server;
292     this.WsUrl = wsUrl;
293     this.wsInfo = wsinfo;
294     this.WebServiceName = wsname;
295     this.input = alview;
296     this.submitGaps = subgaps;
297     this.preserveOrder = presorder;
298     this.alignFrame = alFrame;
299   }
300
301   /**
302    * create one or more Msa jobs to align visible seuqences in _msa
303    *
304    * @param title
305    *            String
306    * @param _msa
307    *            AlignmentView
308    * @param subgaps
309    *            boolean
310    * @param presorder
311    *            boolean
312    * @param seqset
313    *            Alignment
314    */
315   MsaWSThread(ext.vamsas.MuscleWS server, String wsUrl,
316               WebserviceInfo wsinfo, jalview.gui.AlignFrame alFrame,
317               String wsname, String title, AlignmentView _msa, boolean subgaps,
318               boolean presorder, Alignment seqset)
319   {
320     this(server, wsUrl, wsinfo, alFrame, _msa, wsname, subgaps, presorder);
321     OutputHeader = wsInfo.getProgressText();
322     alTitle = title;
323     dataset = seqset;
324     SeqCigar[] msa = _msa.getSequences();
325     int[] contigs = _msa.getContigs();
326     int njobs = 1;
327     if (contigs != null && contigs.length > 0)
328     {
329       int start = 0;
330       njobs = 0;
331       int width = _msa.getWidth();
332       for (int contig = 0; contig < contigs.length; contig += 3)
333       {
334         if ( (contigs[contig + 1] - start) > 0)
335         {
336           njobs++;
337         }
338         width += contigs[contig + 2]; // end up with full region width (including hidden regions)
339         start = contigs[contig + 1] + contigs[contig + 2];
340       }
341       if (start < width)
342       {
343         njobs++;
344       }
345       jobs = new MsaWSJob[njobs];
346       start = 0;
347       int j = 0;
348       for (int contig = 0; contig < contigs.length; contig += 3)
349       {
350         if (contigs[contig + 1] - start > 0)
351         {
352           SequenceI mseq[] = new SequenceI[msa.length];
353           for (int s = 0; s < mseq.length; s++)
354           {
355             mseq[s] = msa[s].getSeq('-').getSubSequence(start,
356                 contigs[contig + 1]);
357           }
358           if (j != 0)
359           {
360             jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq);
361           }
362           else
363           {
364             jobs[j] = new MsaWSJob(0, mseq);
365           }
366           wsinfo.setProgressName("region " + jobs[j].jobnum, jobs[j].jobnum);
367           wsinfo.setProgressText(jobs[j].jobnum, OutputHeader);
368           j++;
369         }
370         start = contigs[contig + 1] + contigs[contig + 2];
371       }
372       if (start < width)
373       {
374         SequenceI mseq[] = new SequenceI[msa.length];
375         for (int s = 0; s < mseq.length; s++)
376         {
377           mseq[s] = msa[s].getSeq('-').getSubSequence(start,
378               width + 1);
379         }
380         if (j != 0)
381         {
382           jobs[j] = new MsaWSJob(wsinfo.addJobPane(), mseq);
383         }
384         else
385         {
386           jobs[j] = new MsaWSJob(0, mseq);
387         }
388         wsinfo.setProgressName("region " + jobs[j].jobnum, jobs[j].jobnum);
389         wsinfo.setProgressText(jobs[j].jobnum, OutputHeader);
390         j++;
391       }
392     }
393     else
394     {
395       SequenceI mseq[] = new SequenceI[msa.length];
396       for (int s = 0; s < mseq.length; s++)
397       {
398         mseq[s] = msa[s].getSeq('-');
399       }
400       jobs = new MsaWSJob[1];
401       wsinfo.setProgressText(OutputHeader); // ensures default text
402       jobs[0] = new MsaWSJob(0, mseq);
403     }
404   }
405
406   public boolean isCancellable()
407   {
408     return true;
409   }
410
411   public void cancelJob()
412   {
413     if (!jobComplete && jobs != null)
414     {
415       boolean cancelled = true;
416       for (int job = 0; job < jobs.length; job++)
417       {
418         if (jobs[job].submitted && !jobs[job].subjobComplete)
419         {
420           String cancelledMessage = "";
421           try
422           {
423             vamsas.objects.simple.WsJobId cancelledJob = server
424                 .cancel(jobs[job].jobId);
425             if (cancelledJob.getStatus() == 2)
426             {
427               // CANCELLED_JOB
428               cancelledMessage = "Job cancelled.";
429               ((MsaWSJob) jobs[job]).cancel();
430               wsInfo.setStatus(jobs[job].jobnum,
431                                WebserviceInfo.STATE_CANCELLED_OK);
432             }
433             else if (cancelledJob.getStatus() == 3)
434             {
435               // VALID UNSTOPPABLE JOB
436               cancelledMessage +=
437                   "Server cannot cancel this job. just close the window.\n";
438               cancelled = false;
439               // wsInfo.setStatus(jobs[job].jobnum,
440               //                 WebserviceInfo.STATE_RUNNING);
441             }
442
443             if (cancelledJob.getJobId() != null)
444             {
445               cancelledMessage += ("[" + cancelledJob.getJobId() + "]");
446             }
447
448             cancelledMessage += "\n";
449           }
450           catch (Exception exc)
451           {
452             cancelledMessage +=
453                 ("\nProblems cancelling the job : Exception received...\n"
454                  + exc + "\n");
455             Cache.log.warn("Exception whilst cancelling "+jobs[job].jobId,exc);
456           }
457           wsInfo.setProgressText(jobs[job].jobnum, OutputHeader
458                                  + cancelledMessage + "\n");
459         }
460       }
461       if (cancelled)
462       {
463         wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
464         jobComplete = true;
465       }
466       this.interrupt(); // kick thread to update job states.
467     }
468     else
469     {
470       if (!jobComplete)
471       {
472         wsInfo
473             .setProgressText(OutputHeader
474                              + "Server cannot cancel this job because it has not been submitted properly. just close the window.\n");
475       }
476     }
477   }
478   void pollJob(WSJob job) throws Exception {
479     ((MsaWSJob) job).result = server.getResult(((MsaWSJob) job).jobId);
480   }
481   void StartJob(WSJob job)
482   {
483     if (!(job instanceof MsaWSJob)) {
484       throw new Error("StartJob(MsaWSJob) called on a WSJobInstance "+job.getClass());
485     }
486     MsaWSJob j = (MsaWSJob) job;
487     if (j.submitted)
488     {
489       if (Cache.log.isDebugEnabled())
490       {
491         Cache.log.debug("Tried to submit an already submitted job " + j.jobId);
492       }
493       return;
494     }
495     if (j.seqs.getSeqs() == null)
496     {
497       // special case - selection consisted entirely of empty sequences...
498       j.submitted = true;
499       j.result = new MsaResult();
500       j.result.setFinished(true);
501       j.result.setStatus("Empty Alignment Job");
502       ((MsaResult) j.result).setMsa(null);
503     }
504     try
505     {
506       vamsas.objects.simple.WsJobId jobsubmit = server.align(j.seqs);
507
508       if ( (jobsubmit != null) && (jobsubmit.getStatus() == 1))
509       {
510         j.jobId = jobsubmit.getJobId();
511         j.submitted = true;
512         j.subjobComplete = false;
513         // System.out.println(WsURL + " Job Id '" + jobId + "'");
514       }
515       else
516       {
517         if (jobsubmit == null)
518         {
519           throw new Exception(
520               "Server at "
521               + WsUrl
522               +
523               " returned null object, it probably cannot be contacted. Try again later ?");
524         }
525
526         throw new Exception(jobsubmit.getJobId());
527       }
528     }
529     catch (Exception e)
530     {
531       // TODO: JBPNote catch timeout or other fault types explicitly
532       // For unexpected errors
533       System.err
534           .println(WebServiceName
535                    + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
536                    + "When contacting Server:" + WsUrl + "\n"
537                    + e.toString() + "\n");
538       j.allowedServerExceptions = 0;
539       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
540       wsInfo.setStatus(j.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
541       wsInfo
542           .appendProgressText(
543               j.jobnum,
544               "Failed to submit sequences for alignment.\n"
545               + "It is most likely that there is a problem with the server.\n"
546               + "Just close the window\n");
547
548       // e.printStackTrace(); // TODO: JBPNote DEBUG
549     }
550   }
551
552   private jalview.datamodel.Sequence[] getVamsasAlignment(
553       vamsas.objects.simple.Alignment valign)
554   {
555     vamsas.objects.simple.Sequence[] seqs = valign.getSeqs().getSeqs();
556     jalview.datamodel.Sequence[] msa = new jalview.datamodel.Sequence[seqs.
557         length];
558
559     for (int i = 0, j = seqs.length; i < j; i++)
560     {
561       msa[i] = new jalview.datamodel.Sequence(seqs[i].getId(), seqs[i]
562                                               .getSeq());
563     }
564
565     return msa;
566   }
567
568   void parseResult()
569   {
570     int results = 0; // number of result sets received
571     JobStateSummary finalState = new JobStateSummary();
572     try
573     {
574       for (int j = 0; j < jobs.length; j++)
575       {
576         finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
577         if (jobs[j].submitted && jobs[j].subjobComplete && jobs[j].hasResults())
578         {
579           results++;
580           vamsas.objects.simple.Alignment valign = ((MsaResult) jobs[j].result).getMsa();
581           if (valign != null)
582           {
583             wsInfo.appendProgressText(jobs[j].jobnum,
584                                       "\nAlignment Object Method Notes\n");
585             String[] lines = valign.getMethod();
586             for (int line = 0; line < lines.length; line++)
587             {
588               wsInfo.appendProgressText(jobs[j].jobnum, lines[line] + "\n");
589             }
590             // JBPNote The returned files from a webservice could be
591             //  hidden behind icons in the monitor window that,
592             // when clicked, pop up their corresponding data
593           }
594         }
595       }
596     }
597     catch (Exception ex)
598     {
599
600       Cache.log.error("Unexpected exception when processing results for " +
601                       alTitle, ex);
602       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
603     }
604     if (results > 0)
605     {
606       wsInfo.showResultsNewFrame
607           .addActionListener(new java.awt.event.ActionListener()
608       {
609         public void actionPerformed(
610             java.awt.event.ActionEvent evt)
611         {
612           displayResults(true);
613         }
614       });
615       wsInfo.mergeResults
616           .addActionListener(new java.awt.event.ActionListener()
617       {
618         public void actionPerformed(
619             java.awt.event.ActionEvent evt)
620         {
621           displayResults(false);
622         }
623       });
624       wsInfo.setResultsReady();
625     } else
626       wsInfo.setFinishedNoResults();
627   }
628
629   void displayResults(boolean newFrame)
630   {
631     // view input or result data for each block
632     // warn user if a block is input rather than aligned data ?
633
634     int contigs[] = input.getContigs();
635     SeqCigar[] seqs = input.getSequences();
636     SequenceI[] alignment = new SequenceI[seqs.length];
637     ColumnSelection columnselection = new ColumnSelection();
638     Vector alorders = new Vector();
639     if (contigs != null && contigs.length > 0)
640     {
641       int start = 0;
642       int nwidth = 0;
643       int owidth = input.getWidth();
644       int j = 0;
645       for (int contig = 0; contig < contigs.length; contig += 3)
646       {
647         owidth += contigs[contig + 2]; // recover final column width
648         if (contigs[contig + 1] - start > 0)
649         {
650           int width = 0; // subalignment width
651           if (jobs[j].hasResults())
652           {
653             Object[] subalg = ((MsaWSJob) jobs[j++]).getAlignment();
654             alorders.add(subalg[1]);
655             SequenceI mseq[] = (SequenceI[]) subalg[0];
656             width = mseq[0].getLength();
657             for (int s = 0; s < mseq.length; s++)
658             {
659               if (alignment[s] == null)
660               {
661                 alignment[s] = mseq[s];
662               }
663               else
664               {
665                 alignment[s].setSequence(alignment[s].getSequence() +
666                                          mseq[s].getSequence());
667                 if (mseq[s].getStart() <= mseq[s].getEnd())
668                 {
669                   alignment[s].setEnd(mseq[s].getEnd());
670                 }
671                 ( (AlignmentOrder) subalg[1]).updateSequence(mseq[s],
672                     alignment[s]);
673               }
674             }
675           }
676           else
677           {
678             // recover input data or place gaps
679             if (true)
680             {
681               // recover input data
682               for (int s = 0; s < seqs.length; s++)
683               {
684                 SequenceI oseq = seqs[s].getSeq('-').getSubSequence(start,
685                     contigs[contig + 1]);
686                 if (width < oseq.getLength())
687                 {
688                   width = oseq.getLength();
689                 }
690                 if (alignment[s] == null)
691                 {
692                   alignment[s] = oseq;
693                 }
694                 else
695                 {
696                   alignment[s].setSequence(alignment[s].getSequence() +
697                                            oseq.getSequence());
698                   if (oseq.getEnd() >= oseq.getStart())
699                   {
700                     alignment[s].setEnd(oseq.getEnd());
701                   }
702                 }
703               }
704
705             }
706             j++;
707           }
708           nwidth += width;
709         }
710         // advance to begining of visible region
711         start = contigs[contig + 1] + contigs[contig + 2];
712         // add hidden segment to right of next region
713         for (int s = 0; s < seqs.length; s++)
714         {
715           SequenceI hseq = seqs[s].getSeq('-').getSubSequence(contigs[contig +
716               1], start);
717           if (alignment[s] == null)
718           {
719             alignment[s] = hseq;
720           }
721           else
722           {
723             alignment[s].setSequence(alignment[s].getSequence() +
724                                      hseq.getSequence());
725             if (hseq.getEnd() >= hseq.getStart())
726             {
727               alignment[s].setEnd(hseq.getEnd());
728             }
729           }
730         }
731         // mark hidden segment as hidden in the new alignment
732         columnselection.hideColumns(nwidth, nwidth + contigs[contig + 2] - 1);
733         nwidth += contigs[contig + 2];
734       }
735       // Do final job - if it exists
736       if (j < jobs.length)
737       {
738         int width = 0;
739         if (jobs[j].hasResults())
740         {
741           Object[] subalg = ((MsaWSJob) jobs[j]).getAlignment();
742           alorders.add(subalg[1]);
743           SequenceI mseq[] = (SequenceI[]) subalg[0];
744           width = mseq[0].getLength();
745           for (int s = 0; s < mseq.length; s++)
746           {
747             if (alignment[s] == null)
748             {
749               alignment[s] = mseq[s];
750             }
751             else
752             {
753               alignment[s].setSequence(alignment[s].getSequence() +
754                                        mseq[s].getSequence());
755               if (mseq[s].getEnd() >= mseq[s].getStart())
756               {
757                 alignment[s].setEnd(mseq[s].getEnd());
758               }
759               ( (AlignmentOrder) subalg[1]).updateSequence(mseq[s], alignment[s]);
760             }
761           }
762         }
763         else
764         {
765           if (start < owidth)
766           {
767             // recover input data or place gaps
768             if (true)
769             {
770               // recover input data
771               for (int s = 0; s < seqs.length; s++)
772               {
773                 SequenceI oseq = seqs[s].getSeq('-').getSubSequence(start,
774                     owidth + 1);
775                 if (width < oseq.getLength())
776                 {
777                   width = oseq.getLength();
778                 }
779                 if (alignment[s] == null)
780                 {
781                   alignment[s] = oseq;
782                 }
783                 else
784                 {
785                   alignment[s].setSequence(alignment[s].getSequence() +
786                                            oseq.getSequence());
787                   if (oseq.getEnd() >= oseq.getStart())
788                   {
789                     alignment[s].setEnd(oseq.getEnd());
790                   }
791                 }
792               }
793               nwidth += width;
794             }
795             else
796             {
797               // place gaps.
798               throw new Error("Padding not yet implemented.");
799             }
800           }
801         }
802       }
803     }
804     else
805     {
806       if (jobs[0].hasResults())
807       {
808         Object[] alg = ((MsaWSJob) jobs[0]).getAlignment();
809         alignment = (SequenceI[]) alg[0];
810         alorders.add(alg[1]);
811       }
812       else
813       {
814         alignment = SeqCigar.createAlignmentSequences(seqs, '-',
815             columnselection, null);
816       }
817     }
818     Alignment al = new Alignment(alignment);
819     if (dataset != null)
820     {
821       al.setDataset(dataset);
822     }
823
824     if (newFrame)
825     {
826       AlignFrame af = new AlignFrame(al, columnselection);
827
828       // >>>This is a fix for the moment, until a better solution is
829       // found!!<<<
830       af.getFeatureRenderer().transferSettings(
831           alignFrame.getFeatureRenderer());
832       if (alorders.size() > 0)
833       {
834         if (alorders.size() == 1)
835         {
836           af.addSortByOrderMenuItem(WebServiceName + " Ordering",
837                                     (AlignmentOrder) alorders.get(0));
838         }
839         else
840         {
841           // construct a non-redundant ordering set
842           Vector names = new Vector();
843           for (int i = 0, l = alorders.size(); i < l; i++)
844           {
845             String orderName = new String(" Region " + i);
846             int j = i + 1;
847             int r = l;
848             while (j < l)
849             {
850               if ( ( (AlignmentOrder) alorders.get(i)).equals( ( (
851                   AlignmentOrder) alorders.get(j))))
852               {
853                 alorders.remove(j);
854                 l--;
855                 orderName += "," + j;
856               }
857               else
858               {
859                 j++;
860               }
861             }
862
863             if (i == 0 && j == 1)
864             {
865               names.add(new String(""));
866             }
867             else
868             {
869               names.add(orderName);
870             }
871           }
872           for (int i = 0, l = alorders.size(); i < l; i++)
873           {
874             af.addSortByOrderMenuItem(WebServiceName
875                                       +( (String) names.get(i)) +
876                                       " Ordering",
877                                       (AlignmentOrder) alorders.get(i));
878           }
879         }
880       }
881
882       Desktop.addInternalFrame(af, alTitle,
883                                AlignFrame.NEW_WINDOW_WIDTH,
884                                AlignFrame.NEW_WINDOW_HEIGHT);
885
886     }
887     else
888     {
889       System.out.println("MERGE WITH OLD FRAME");
890
891     }
892   }
893 }