2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.ws.jws2;
23 import jalview.analysis.AlignSeq;
24 import jalview.bin.Cache;
25 import jalview.datamodel.Alignment;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.AlignmentOrder;
28 import jalview.datamodel.AlignmentView;
29 import jalview.datamodel.ColumnSelection;
30 import jalview.datamodel.Sequence;
31 import jalview.datamodel.SequenceI;
32 import jalview.gui.AlignFrame;
33 import jalview.gui.Desktop;
34 import jalview.gui.SplitFrame;
35 import jalview.gui.WebserviceInfo;
36 import jalview.util.MessageManager;
37 import jalview.ws.AWsJob;
38 import jalview.ws.JobStateSummary;
39 import jalview.ws.WSClientI;
40 import jalview.ws.jws2.dm.JabaWsParamSet;
41 import jalview.ws.params.WsParamSetI;
43 import java.util.ArrayList;
44 import java.util.Hashtable;
45 import java.util.List;
47 import java.util.Vector;
49 import javax.swing.JInternalFrame;
51 import compbio.data.msa.MsaWS;
52 import compbio.metadata.Argument;
53 import compbio.metadata.ChunkHolder;
54 import compbio.metadata.JobStatus;
55 import compbio.metadata.Preset;
57 class MsaWSThread extends AWS2Thread implements WSClientI
59 boolean submitGaps = false; // pass sequences including gaps to alignment
63 boolean preserveOrder = true; // and always store and recover sequence
67 class MsaWSJob extends JWs2Job
71 WsParamSetI preset = null;
73 List<Argument> arguments = null;
78 ArrayList<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
83 compbio.data.sequence.Alignment alignment;
85 // set if the job didn't get run - then the input is simply returned to the
87 private boolean returnInput = false;
97 public MsaWSJob(int jobNum, SequenceI[] inSeqs)
100 if (!prepareInput(inSeqs, 2))
103 subjobComplete = true;
109 Hashtable<String, Map> SeqNames = new Hashtable();
111 Vector<String[]> emptySeqs = new Vector();
114 * prepare input sequences for MsaWS service
117 * jalview sequences to be prepared
119 * minimum number of residues required for this MsaWS service
120 * @return true if seqs contains sequences to be submitted to service.
122 // TODO: return compbio.seqs list or nothing to indicate validity.
123 private boolean prepareInput(SequenceI[] seqs, int minlen)
130 .getString("error.implementation_error_minlen_must_be_greater_zero"));
132 for (int i = 0; i < seqs.length; i++)
134 if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
139 boolean valid = nseqs > 1; // need at least two seqs
140 compbio.data.sequence.FastaSequence seq;
141 for (int i = 0, n = 0; i < seqs.length; i++)
144 String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
148 SeqNames.put(newname,
149 jalview.analysis.SeqsetUtils.SeqCharacterHash(seqs[i]));
150 if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
152 // make new input sequence with or without gaps
153 seq = new compbio.data.sequence.FastaSequence(newname,
154 (submitGaps) ? seqs[i].getSequenceAsString()
155 : AlignSeq.extractGaps(
156 jalview.util.Comparison.GapChars,
157 seqs[i].getSequenceAsString()));
163 if (seqs[i].getEnd() >= seqs[i].getStart())
165 empty = (submitGaps) ? seqs[i].getSequenceAsString() : AlignSeq
166 .extractGaps(jalview.util.Comparison.GapChars,
167 seqs[i].getSequenceAsString());
169 emptySeqs.add(new String[] { newname, empty });
177 * @return true if getAlignment will return a valid alignment result.
179 public boolean hasResults()
183 && (alignment != null || (emptySeqs != null && emptySeqs
193 * get the alignment including any empty sequences in the original order
194 * with original ids. Caller must access the alignment.getMetadata() object
195 * to annotate the final result passsed to the user.
197 * @return { SequenceI[], AlignmentOrder }
199 public Object[] getAlignment()
201 // is this a generic subjob or a Jws2 specific Object[] return signature
204 SequenceI[] alseqs = null;
205 char alseq_gapchar = '-';
207 if (alignment.getSequences().size() > 0)
209 alseqs = new SequenceI[alignment.getSequences().size()];
210 for (compbio.data.sequence.FastaSequence seq : alignment
213 alseqs[alseq_l++] = new Sequence(seq.getId(), seq.getSequence());
215 alseq_gapchar = alignment.getMetadata().getGapchar();
218 // add in the empty seqs.
219 if (emptySeqs.size() > 0)
221 SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
226 for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
228 if (w < alseqs[i].getLength())
230 w = alseqs[i].getLength();
232 t_alseqs[i] = alseqs[i];
236 // check that aligned width is at least as wide as emptySeqs width.
238 for (i = 0, w = emptySeqs.size(); i < w; i++)
240 String[] es = emptySeqs.get(i);
241 if (es != null && es[1] != null)
243 int sw = es[1].length();
250 // make a gapped string.
251 StringBuffer insbuff = new StringBuffer(w);
252 for (i = 0; i < nw; i++)
254 insbuff.append(alseq_gapchar);
258 for (i = 0; i < alseq_l; i++)
260 int sw = t_alseqs[i].getLength();
264 alseqs[i].setSequence(t_alseqs[i].getSequenceAsString()
265 + insbuff.substring(0, sw - nw));
269 for (i = 0, w = emptySeqs.size(); i < w; i++)
271 String[] es = emptySeqs.get(i);
274 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0],
275 insbuff.toString(), 1, 0);
279 if (es[1].length() < nw)
281 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
283 es[1] + insbuff.substring(0, nw - es[1].length()),
284 1, 1 + es[1].length());
288 t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
295 AlignmentOrder msaorder = new AlignmentOrder(alseqs);
296 // always recover the order - makes parseResult()'s life easier.
297 jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
298 // account for any missing sequences
299 jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
300 return new Object[] { alseqs, msaorder };
306 * mark subjob as cancelled and set result object appropriatly
311 subjobComplete = true;
317 * @return boolean true if job can be submitted.
319 public boolean hasValidInput()
321 // TODO: get attributes for this MsaWS instance to check if it can do two
322 // sequence alignment.
323 if (seqs != null && seqs.size() >= 2) // two or more sequences is valid ?
330 StringBuffer jobProgress = new StringBuffer();
332 public void setStatus(String string)
334 jobProgress.setLength(0);
335 jobProgress.append(string);
339 public String getStatus()
341 return jobProgress.toString();
345 public boolean hasStatus()
347 return jobProgress != null;
351 * @return the lastChunk
353 public long getLastChunk()
360 * the lastChunk to set
362 public void setLastChunk(long lastChunk)
364 this.lastChunk = lastChunk;
367 String alignmentProgram = null;
369 public String getAlignmentProgram()
371 return alignmentProgram;
374 public boolean hasArguments()
376 return (arguments != null && arguments.size() > 0)
377 || (preset != null && preset instanceof JabaWsParamSet);
380 public List<Argument> getJabaArguments()
382 List<Argument> newargs = new ArrayList<Argument>();
383 if (preset != null && preset instanceof JabaWsParamSet)
385 newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
387 if (arguments != null && arguments.size() > 0)
389 newargs.addAll(arguments);
395 * add a progess header to status string containing presets/args used
397 public void addInitialStatus()
401 jobProgress.append("Using "
402 + (preset instanceof JabaPreset ? "Server" : "User")
403 + "Preset: " + preset.getName());
404 if (preset instanceof JabaWsParamSet)
406 for (Argument opt : ((JabaWsParamSet) preset).getjabaArguments())
408 jobProgress.append(opt.getName() + " " + opt.getDefaultValue()
413 if (arguments != null && arguments.size() > 0)
415 jobProgress.append("With custom parameters : \n");
416 // merge arguments with preset's own arguments.
417 for (Argument opt : arguments)
419 jobProgress.append(opt.getName() + " " + opt.getDefaultValue()
423 jobProgress.append("\nJob Output:\n");
426 public boolean isPresetJob()
428 return preset != null && preset instanceof JabaPreset;
431 public Preset getServerPreset()
433 return (isPresetJob()) ? ((JabaPreset) preset).p : null;
437 String alTitle; // name which will be used to form new alignment window.
439 Alignment dataset; // dataset to which the new alignment will be
443 @SuppressWarnings("unchecked")
447 * set basic options for this (group) of Msa jobs
454 private MsaWSThread(MsaWS server, String wsUrl, WebserviceInfo wsinfo,
455 jalview.gui.AlignFrame alFrame, AlignmentView alview,
456 String wsname, boolean subgaps, boolean presorder)
458 super(alFrame, wsinfo, alview, wsname, wsUrl);
459 this.server = server;
460 this.submitGaps = subgaps;
461 this.preserveOrder = presorder;
465 * create one or more Msa jobs to align visible seuqences in _msa
478 MsaWSThread(MsaWS server2, WsParamSetI preset, List<Argument> paramset,
479 String wsUrl, WebserviceInfo wsinfo,
480 jalview.gui.AlignFrame alFrame, String wsname, String title,
481 AlignmentView _msa, boolean subgaps, boolean presorder,
484 this(server2, wsUrl, wsinfo, alFrame, _msa, wsname, subgaps, presorder);
485 OutputHeader = wsInfo.getProgressText();
489 SequenceI[][] conmsa = _msa.getVisibleContigs('-');
492 int nvalid = 0, njobs = conmsa.length;
493 jobs = new MsaWSJob[njobs];
494 for (int j = 0; j < njobs; j++)
498 jobs[j] = new MsaWSJob(wsinfo.addJobPane(), conmsa[j]);
502 jobs[j] = new MsaWSJob(0, conmsa[j]);
504 if (((MsaWSJob) jobs[j]).hasValidInput())
508 ((MsaWSJob) jobs[j]).preset = preset;
509 ((MsaWSJob) jobs[j]).arguments = paramset;
510 ((MsaWSJob) jobs[j]).alignmentProgram = wsname;
513 wsinfo.setProgressName("region " + jobs[j].getJobnum(),
514 jobs[j].getJobnum());
516 wsinfo.setProgressText(jobs[j].getJobnum(), OutputHeader);
518 validInput = nvalid > 0;
522 boolean validInput = false;
526 * @return true if the thread will perform a calculation
528 public boolean hasValidInput()
533 public boolean isCancellable()
538 public void cancelJob()
540 if (!jobComplete && jobs != null)
542 boolean cancelled = true;
543 for (int job = 0; job < jobs.length; job++)
545 if (jobs[job].isSubmitted() && !jobs[job].isSubjobComplete())
547 String cancelledMessage = "";
550 boolean cancelledJob = server.cancelJob(jobs[job].getJobId());
551 if (true) // cancelledJob || true)
554 // if the Jaba server indicates the job can't be cancelled, its
555 // because its running on the server's local execution engine
556 // so we just close the window anyway.
557 cancelledMessage = "Job cancelled.";
558 ((MsaWSJob) jobs[job]).cancel(); // TODO: refactor to avoid this
560 wsInfo.setStatus(jobs[job].getJobnum(),
561 WebserviceInfo.STATE_CANCELLED_OK);
565 // VALID UNSTOPPABLE JOB
566 cancelledMessage += "Server cannot cancel this job. just close the window.\n";
568 // wsInfo.setStatus(jobs[job].jobnum,
569 // WebserviceInfo.STATE_RUNNING);
571 } catch (Exception exc)
573 cancelledMessage += ("\nProblems cancelling the job : Exception received...\n"
576 "Exception whilst cancelling " + jobs[job].getJobId(),
579 wsInfo.setProgressText(jobs[job].getJobnum(), OutputHeader
580 + cancelledMessage + "\n");
584 // if we hadn't submitted then just mark the job as cancelled.
585 jobs[job].setSubjobComplete(true);
586 wsInfo.setStatus(jobs[job].getJobnum(),
587 WebserviceInfo.STATE_CANCELLED_OK);
593 wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
596 this.interrupt(); // kick thread to update job states.
602 wsInfo.setProgressText(OutputHeader
603 + "Server cannot cancel this job because it has not been submitted properly. just close the window.\n");
608 public void pollJob(AWsJob job) throws Exception
610 // TODO: investigate if we still need to cast here in J1.6
611 MsaWSJob j = ((MsaWSJob) job);
612 // this is standard code, but since the interface doesn't comprise of a
613 // basic one that implements (getJobStatus, pullExecStatistics) we have to
614 // repeat the code for all jw2s services.
615 j.setjobStatus(server.getJobStatus(job.getJobId()));
616 updateJobProgress(j);
622 * @return true if more job progress data was available
625 protected boolean updateJobProgress(MsaWSJob j) throws Exception
627 StringBuffer response = j.jobProgress;
628 long lastchunk = j.getLastChunk();
629 boolean changed = false;
632 j.setLastChunk(lastchunk);
633 ChunkHolder chunk = server
634 .pullExecStatistics(j.getJobId(), lastchunk);
637 changed |= chunk.getChunk().length() > 0;
638 response.append(chunk.getChunk());
639 lastchunk = chunk.getNextPosition();
643 } catch (InterruptedException x)
649 } while (lastchunk >= 0 && j.getLastChunk() != lastchunk);
653 public void StartJob(AWsJob job)
655 Exception lex = null;
656 // boiler plate template
657 if (!(job instanceof MsaWSJob))
659 throw new Error(MessageManager.formatMessage(
660 "error.implementation_error_msawbjob_called",
661 new String[] { job.getClass().toString() }));
663 MsaWSJob j = (MsaWSJob) job;
666 if (Cache.log.isDebugEnabled())
668 Cache.log.debug("Tried to submit an already submitted job "
675 if (j.seqs == null || j.seqs.size() == 0)
677 // special case - selection consisted entirely of empty sequences...
678 j.setjobStatus(JobStatus.FINISHED);
679 j.setStatus(MessageManager.getString("label.empty_alignment_job"));
683 j.addInitialStatus(); // list the presets/parameters used for the job in
687 j.setJobId(server.presetAlign(j.seqs, j.getServerPreset()));
689 else if (j.hasArguments())
691 j.setJobId(server.customAlign(j.seqs, j.getJabaArguments()));
695 j.setJobId(server.align(j.seqs));
698 if (j.getJobId() != null)
700 j.setSubmitted(true);
701 j.setSubjobComplete(false);
702 // System.out.println(WsURL + " Job Id '" + jobId + "'");
707 throw new Exception(MessageManager.formatMessage(
708 "exception.web_service_returned_null_try_later",
709 new String[] { WsUrl }));
711 } catch (compbio.metadata.UnsupportedRuntimeException _lex)
714 wsInfo.appendProgressText(MessageManager.formatMessage(
715 "info.job_couldnt_be_run_server_doesnt_support_program",
716 new String[] { _lex.getMessage() }));
717 wsInfo.warnUser(_lex.getMessage(),
718 MessageManager.getString("warn.service_not_supported"));
719 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
720 wsInfo.setStatus(j.getJobnum(),
721 WebserviceInfo.STATE_STOPPED_SERVERERROR);
722 } catch (compbio.metadata.LimitExceededException _lex)
725 wsInfo.appendProgressText(MessageManager.formatMessage(
726 "info.job_couldnt_be_run_exceeded_hard_limit",
727 new String[] { _lex.getMessage() }));
728 wsInfo.warnUser(_lex.getMessage(),
729 MessageManager.getString("warn.input_is_too_big"));
730 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
731 wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
732 } catch (compbio.metadata.WrongParameterException _lex)
735 wsInfo.warnUser(_lex.getMessage(),
736 MessageManager.getString("warn.invalid_job_param_set"));
737 wsInfo.appendProgressText(MessageManager.formatMessage(
738 "info.job_couldnt_be_run_incorrect_param_setting",
739 new String[] { _lex.getMessage() }));
740 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
741 wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
744 // For unexpected errors
746 .println(WebServiceName
747 + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
748 + "When contacting Server:" + WsUrl + "\n");
749 e.printStackTrace(System.err);
750 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
751 wsInfo.setStatus(j.getJobnum(),
752 WebserviceInfo.STATE_STOPPED_SERVERERROR);
753 } catch (Exception e)
755 // For unexpected errors
757 .println(WebServiceName
758 + "Client: Failed to submit the sequences for alignment (probably a server side problem)\n"
759 + "When contacting Server:" + WsUrl + "\n");
760 e.printStackTrace(System.err);
761 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
762 wsInfo.setStatus(j.getJobnum(),
763 WebserviceInfo.STATE_STOPPED_SERVERERROR);
766 if (!j.isSubmitted())
768 // Boilerplate code here
769 // TODO: JBPNote catch timeout or other fault types explicitly
771 j.setAllowedServerExceptions(0);
772 wsInfo.appendProgressText(j.getJobnum(), MessageManager
773 .getString("info.failed_to_submit_sequences_for_alignment"));
778 public void parseResult()
780 long progbar = System.currentTimeMillis();
781 wsInfo.setProgressBar(
782 MessageManager.getString("status.collecting_job_results"),
784 int results = 0; // number of result sets received
785 JobStateSummary finalState = new JobStateSummary();
788 for (int j = 0; j < jobs.length; j++)
790 MsaWSJob msjob = ((MsaWSJob) jobs[j]);
791 if (jobs[j].isFinished() && msjob.alignment == null)
793 int nunchanged = 3, nexcept = 3;
794 boolean jpchanged = false, jpex = false;
799 jpchanged = updateJobProgress(msjob);
805 } catch (Exception e)
809 .warn("Exception when retrieving remaining Job progress data for job "
810 + msjob.getJobId() + " on server " + WsUrl);
814 // set flag remember that we've had an exception.
822 Thread.sleep(jpex ? 2400 : 1200); // wait a bit longer if we
823 // experienced an exception.
824 } catch (Exception ex)
830 } while (nunchanged > 0 && nexcept > 0);
832 if (Cache.log.isDebugEnabled())
834 System.out.println("Job Execution file for job: "
835 + msjob.getJobId() + " on server " + WsUrl);
836 System.out.println(msjob.getStatus());
837 System.out.println("*** End of status");
842 msjob.alignment = server.getResult(msjob.getJobId());
843 } catch (compbio.metadata.ResultNotAvailableException e)
845 // job has failed for some reason - probably due to invalid
848 .debug("Results not available for finished job - marking as broken job.",
851 .append("\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n"
852 + e.getLocalizedMessage());
853 msjob.setjobStatus(JobStatus.FAILED);
854 } catch (Exception e)
856 Cache.log.error("Couldn't get Alignment for job.", e);
857 // TODO: Increment count and retry ?
858 msjob.setjobStatus(JobStatus.UNDEFINED);
861 finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
862 if (jobs[j].isSubmitted() && jobs[j].isSubjobComplete()
863 && jobs[j].hasResults())
866 compbio.data.sequence.Alignment alignment = ((MsaWSJob) jobs[j]).alignment;
867 if (alignment != null)
869 // server.close(jobs[j].getJobnum());
870 // wsInfo.appendProgressText(jobs[j].getJobnum(),
871 // "\nAlignment Object Method Notes\n");
872 // wsInfo.appendProgressText(jobs[j].getJobnum(),
873 // "Calculated with "+alignment.getMetadata().getProgram().toString());
874 // JBPNote The returned files from a webservice could be
875 // hidden behind icons in the monitor window that,
876 // when clicked, pop up their corresponding data
880 } catch (Exception ex)
883 Cache.log.error("Unexpected exception when processing results for "
885 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
889 wsInfo.showResultsNewFrame
890 .addActionListener(new java.awt.event.ActionListener()
892 public void actionPerformed(java.awt.event.ActionEvent evt)
894 displayResults(true);
898 .addActionListener(new java.awt.event.ActionListener()
900 public void actionPerformed(java.awt.event.ActionEvent evt)
902 displayResults(false);
905 wsInfo.setResultsReady();
909 wsInfo.setFinishedNoResults();
911 updateGlobalStatus(finalState);
912 wsInfo.setProgressBar(null, progbar);
916 * Display alignment results in a new frame (or - not currently supported -
917 * added to an existing alignment).
921 void displayResults(boolean newFrame)
923 // view input or result data for each block
924 List<AlignmentOrder> alorders = new ArrayList<AlignmentOrder>();
925 SequenceI[][] results = new SequenceI[jobs.length][];
926 AlignmentOrder[] orders = new AlignmentOrder[jobs.length];
927 String lastProgram = null;
929 for (int j = 0; j < jobs.length; j++)
931 if (jobs[j].hasResults())
933 msjob = (MsaWSJob) jobs[j];
934 Object[] res = msjob.getAlignment();
935 lastProgram = msjob.getAlignmentProgram();
936 alorders.add((AlignmentOrder) res[1]);
937 results[j] = (SequenceI[]) res[0];
938 orders[j] = (AlignmentOrder) res[1];
940 // SequenceI[] alignment = input.getUpdated
947 Object[] newview = input.getUpdatedView(results, orders, getGapChar());
948 // trash references to original result data
949 for (int j = 0; j < jobs.length; j++)
954 SequenceI[] alignment = (SequenceI[]) newview[0];
955 ColumnSelection columnselection = (ColumnSelection) newview[1];
956 Alignment al = new Alignment(alignment);
957 // TODO: add 'provenance' property to alignment from the method notes
958 if (lastProgram != null)
960 al.setProperty("Alignment Program", lastProgram);
962 // accompanying each subjob
965 al.setDataset(dataset);
968 propagateDatasetMappings(al);
969 // JBNote- TODO: warn user if a block is input rather than aligned data ?
973 displayInNewFrame(al, alorders, columnselection);
978 // TODO 2.9.x feature
979 System.out.println("MERGE WITH OLD FRAME");
980 // TODO: modify alignment in original frame, replacing old for new
981 // alignment using the commands.EditCommand model to ensure the update can
987 * Display the alignment result in a new frame.
991 * @param columnselection
993 protected void displayInNewFrame(AlignmentI al,
994 List<AlignmentOrder> alorders, ColumnSelection columnselection)
996 AlignFrame af = new AlignFrame(al, columnselection,
997 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
999 // initialise with same renderer settings as in parent alignframe.
1000 af.getFeatureRenderer().transferSettings(this.featureSettings);
1002 if (alorders.size() > 0)
1004 addSortByMenuItems(af, alorders);
1007 // TODO: refactor retrieve and show as new splitFrame as Desktop method
1010 * If alignment was requested from one half of a SplitFrame, show in a
1011 * SplitFrame with the other pane similarly aligned.
1013 AlignFrame requestedBy = getRequestingAlignFrame();
1014 if (requestedBy != null
1015 && requestedBy.getSplitViewContainer() != null
1016 && requestedBy.getSplitViewContainer().getComplement(
1017 requestedBy) != null)
1019 AlignmentI complement = requestedBy.getSplitViewContainer()
1020 .getComplement(requestedBy);
1021 String complementTitle = requestedBy.getSplitViewContainer()
1022 .getComplementTitle(requestedBy);
1023 // becomes null if the alignment window was closed before the alignment
1025 AlignmentI copyComplement = new Alignment(complement);
1026 copyComplement.alignAs(al);
1027 if (copyComplement.getHeight() > 0)
1029 af.setTitle(alTitle);
1030 AlignFrame af2 = new AlignFrame(copyComplement,
1031 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
1032 af2.setTitle(complementTitle);
1033 String linkedTitle = MessageManager
1034 .getString("label.linked_view_title");
1035 JInternalFrame splitFrame = new SplitFrame(al.isNucleotide() ? af
1036 : af2, al.isNucleotide() ? af2 : af);
1037 Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
1043 * Not from SplitFrame, or failed to created a complementary alignment
1045 Desktop.addInternalFrame(af, alTitle, AlignFrame.DEFAULT_WIDTH,
1046 AlignFrame.DEFAULT_HEIGHT);
1050 * Add sort order options to the AlignFrame menus.
1055 protected void addSortByMenuItems(AlignFrame af,
1056 List<AlignmentOrder> alorders)
1059 if (alorders.size() == 1)
1061 af.addSortByOrderMenuItem(WebServiceName + " Ordering",
1066 // construct a non-redundant ordering set
1067 List<String> names = new ArrayList<String>();
1068 for (int i = 0, l = alorders.size(); i < l; i++)
1070 String orderName = " Region " + i;
1075 if (alorders.get(i).equals(alorders.get(j)))
1079 orderName += "," + j;
1087 if (i == 0 && j == 1)
1093 names.add(orderName);
1096 for (int i = 0, l = alorders.size(); i < l; i++)
1098 af.addSortByOrderMenuItem(WebServiceName + (names.get(i))
1099 + " Ordering", alorders.get(i));
1104 public boolean canMergeResults()