X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fws2%2Foperations%2FAlignmentOperation.java;h=1f0a6022ce9d0a75597bd0642de6a72981900fea;hb=12dc7e70977962f00e584b39eda098897d51f432;hp=89aeb794fb509f8fbf552aca5061883b8f038432;hpb=9a5c8af21bd813e0c62ffcd7e4c0c3e2c33b9947;p=jalview.git diff --git a/src/jalview/ws2/operations/AlignmentOperation.java b/src/jalview/ws2/operations/AlignmentOperation.java index 89aeb79..1f0a602 100644 --- a/src/jalview/ws2/operations/AlignmentOperation.java +++ b/src/jalview/ws2/operations/AlignmentOperation.java @@ -14,11 +14,14 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletionStage; +import java.util.function.Consumer; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.ToolTipManager; +import org.eclipse.jetty.http.HttpGenerator.Result; + import jalview.analysis.AlignSeq; import jalview.analysis.AlignmentSorter; import jalview.analysis.SeqsetUtils; @@ -40,6 +43,7 @@ import jalview.gui.WsJobParameters; import jalview.util.MathUtils; import jalview.util.MessageManager; import jalview.ws.params.ArgumentI; +import jalview.ws.params.ParamDatastoreI; import jalview.ws.params.WsParamSetI; import jalview.ws2.MenuEntryProviderI; import jalview.ws2.ResultSupplier; @@ -49,6 +53,9 @@ import jalview.ws2.PollingTaskExecutor; import jalview.ws2.WebServiceI; import jalview.ws2.WebServiceInfoUpdater; import jalview.ws2.WebServiceWorkerI; +import jalview.ws2.WebServiceWorkerListener; +import jalview.ws2.WebServiceWorkerListenersList; +import jalview.ws2.gui.AlignmentMenuBuilder; import jalview.ws2.utils.WSJobList; /** @@ -58,12 +65,14 @@ import jalview.ws2.utils.WSJobList; */ public class AlignmentOperation implements Operation { - final WebServiceI service; + private final WebServiceI service; - final ResultSupplier supplier; + private final ResultSupplier supplier; + - public AlignmentOperation(WebServiceI service, - ResultSupplier supplier) + public AlignmentOperation( + WebServiceI service, + ResultSupplier supplier) { this.service = service; this.supplier = supplier; @@ -74,6 +83,12 @@ public class AlignmentOperation implements Operation { return service.getName(); } + + @Override + public String getDescription() + { + return service.getDescription(); + } @Override public String getTypeName() @@ -86,6 +101,18 @@ public class AlignmentOperation implements Operation { return service.getHostName(); } + + @Override + public boolean hasParameters() + { + return service.hasParameters(); + } + + @Override + public ParamDatastoreI getParamStore() + { + return service.getParamStore(); + } @Override public int getMinSequences() @@ -121,7 +148,7 @@ public class AlignmentOperation implements Operation public boolean canSubmitGaps() { // hack copied from original jabaws code, don't blame me - return service.getName().contains("lustal"); + return getName().contains("lustal"); } @Override @@ -145,164 +172,9 @@ public class AlignmentOperation implements Operation @Override public MenuEntryProviderI getMenuBuilder() { - return this::buildMenu; - } - - protected void buildMenu(JMenu parent, AlignFrame frame) - { - if (canSubmitGaps()) - { - var alignSubmenu = new JMenu(service.getName()); - buildMenu(alignSubmenu, frame, false); - parent.add(alignSubmenu); - var realignSubmenu = new JMenu(MessageManager.formatMessage( - "label.realign_with_params", service.getName())); - realignSubmenu.setToolTipText(MessageManager - .getString("label.align_sequences_to_existing_alignment")); - buildMenu(realignSubmenu, frame, true); - parent.add(realignSubmenu); - } - else - { - buildMenu(parent, frame, false); - } + return new AlignmentMenuBuilder(this); } - protected void buildMenu(JMenu parent, AlignFrame frame, - boolean submitGaps) - { - final String action = submitGaps ? "Align" : "Realign"; - final var calcName = service.getName(); - - String title = frame.getTitle(); - PollingTaskExecutor executor = frame.getViewport().getWSExecutor(); - { - var item = new JMenuItem(MessageManager.formatMessage( - "label.calcname_with_default_settings", calcName)); - item.setToolTipText(MessageManager - .formatMessage("label.action_with_default_settings", action)); - item.addActionListener((event) -> { - final AlignmentView msa = frame.gatherSequencesForAlignment(); - final AlignViewport viewport = frame.getViewport(); - final AlignmentI alignment = frame.getViewport().getAlignment(); - if (msa != null) - { - WebServiceWorkerI worker = new AlignmentWorker(msa, - Collections.emptyList(), title, submitGaps, true, - alignment, viewport); - executor.submit(worker); - } - }); - parent.add(item); - } - - if (service.hasParameters()) - { - var item = new JMenuItem( - MessageManager.getString("label.edit_settings_and_run")); - item.setToolTipText(MessageManager.getString( - "label.view_and_change_parameters_before_alignment")); - item.addActionListener((event) -> { - final AlignmentView msa = frame.gatherSequencesForAlignment(); - final AlignViewport viewport = frame.getViewport(); - final AlignmentI alignment = frame.getViewport().getAlignment(); - if (msa != null) - { - openEditParamsDialog(service, null, null) - .thenAcceptAsync((arguments) -> { - if (arguments != null) - { - WebServiceWorkerI worker = new AlignmentWorker(msa, - arguments, title, submitGaps, true, alignment, - viewport); - executor.submit(worker); - } - }); - } - }); - parent.add(item); - } - - var presets = service.getParamStore().getPresets(); - if (presets != null && presets.size() > 0) - { - final var presetList = new JMenu(MessageManager - .formatMessage("label.run_with_preset_params", calcName)); - final var showToolTipFor = ToolTipManager.sharedInstance() - .getDismissDelay(); - for (final var preset : presets) - { - var item = new JMenuItem(preset.getName()); - final int QUICK_TOOLTIP = 1500; - item.addMouseListener(new MouseAdapter() - { - @Override - public void mouseEntered(MouseEvent e) - { - ToolTipManager.sharedInstance().setDismissDelay(QUICK_TOOLTIP); - } - - @Override - public void mouseExited(MouseEvent e) - { - ToolTipManager.sharedInstance().setDismissDelay(showToolTipFor); - } - }); - String tooltip = JvSwingUtils.wrapTooltip(true, - format("%s
%s", - MessageManager.getString( - preset.isModifiable() ? "label.user_preset" - : "label.service_preset"), - preset.getDescription())); - item.setToolTipText(tooltip); - item.addActionListener((event) -> { - final AlignmentView msa = frame.gatherSequencesForAlignment(); - final AlignViewport viewport = frame.getViewport(); - final AlignmentI alignment = frame.getViewport().getAlignment(); - if (msa != null) - { - WebServiceWorkerI worker = new AlignmentWorker(msa, - preset.getArguments(), title, submitGaps, true, - alignment, viewport); - executor.submit(worker); - } - }); - presetList.add(item); - } - parent.add(presetList); - } - } - - private CompletionStage> openEditParamsDialog( - WebServiceI service, WsParamSetI preset, - List arguments) - { - WsJobParameters jobParams; - if (preset == null && arguments != null && arguments.size() > 0) - jobParams = new WsJobParameters(service.getParamStore(), preset, - arguments); - else - jobParams = new WsJobParameters(service.getParamStore(), preset, - null); - var stage = jobParams.showRunDialog(); - return stage.thenApply((startJob) -> { - if (startJob) - { - if (jobParams.getPreset() == null) - { - return jobParams.getJobParams(); - } - else - { - return jobParams.getPreset().getArguments(); - } - } - else - { - return null; - } - }); - } /** * Implementation of the web service worker performing multiple sequence @@ -311,7 +183,7 @@ public class AlignmentOperation implements Operation * @author mmwarowny * */ - private class AlignmentWorker implements WebServiceWorkerI + public class AlignmentWorker implements WebServiceWorkerI { private long uid = MathUtils.getUID(); @@ -338,20 +210,18 @@ public class AlignmentOperation implements Operation private Map inputs = new LinkedHashMap<>(); - private WebserviceInfo wsInfo; - private Map exceptionCount = new HashMap<>(); - + private final int MAX_RETRY = 5; - AlignmentWorker(AlignmentView msa, List args, + public AlignmentWorker(AlignmentView msa, List args, String alnTitle, boolean submitGaps, boolean preserveOrder, - AlignmentI alignment, AlignViewport viewport) + AlignViewport viewport) { this.msa = msa; - this.dataset = alignment.getDataset(); + this.dataset = viewport.getAlignment().getDataset(); List cf = Objects.requireNonNullElse( - alignment.getCodonFrames(), Collections.emptyList()); + viewport.getAlignment().getCodonFrames(), Collections.emptyList()); this.codonFrame.addAll(cf); this.args = args; this.alnTitle = alnTitle; @@ -359,11 +229,6 @@ public class AlignmentOperation implements Operation this.preserveOrder = preserveOrder; this.viewport = viewport; this.gapCharacter = viewport.getGapCharacter(); - - String panelInfo = String.format("%s using service hosted at %s%n%s", - service.getName(), service.getHostName(), - Objects.requireNonNullElse(service.getDescription(), "")); - wsInfo = new WebserviceInfo(service.getName(), panelInfo, false); } @Override @@ -379,40 +244,30 @@ public class AlignmentOperation implements Operation } @Override - public List getJobs() + public WSJobList getJobs() { - return Collections.unmodifiableList(jobs); + return jobs; } @Override public void start() throws IOException { Cache.log.info(format("Starting new %s job.", service.getName())); - String outputHeader = String.format("%s of %s%nJob details%n", - submitGaps ? "Re-alignment" : "Alignment", alnTitle); SequenceI[][] conmsa = msa.getVisibleContigs('-'); if (conmsa == null) { return; } - WebServiceInfoUpdater updater = new WebServiceInfoUpdater(wsInfo); - updater.setOutputHeader(outputHeader); int numValid = 0; for (int i = 0; i < conmsa.length; i++) { JobInput input = JobInput.create(conmsa[i], 2, submitGaps); WSJob job = new WSJob(service.getProviderName(), service.getName(), service.getHostName()); - job.setJobNum(wsInfo.addJobPane()); - if (conmsa.length > 1) - { - wsInfo.setProgressName(String.format("region %d", i), - job.getJobNum()); - } - wsInfo.setProgressText(job.getJobNum(), outputHeader); - job.addPropertyChangeListener(updater); + job.setJobNum(i); inputs.put(job.getUid(), input); jobs.add(job); + listeners.fireJobCreated(job); if (input.isInputValid()) { int count; @@ -450,17 +305,11 @@ public class AlignmentOperation implements Operation } if (numValid > 0) { - // wsInfo.setThisService() should happen here - wsInfo.setVisible(true); + listeners.fireWorkerStarted(); } else { - wsInfo.setVisible(false); - // TODO show notification dialog. - // JvOptionPane.showMessageDialog(frame, - // MessageManager.getString("info.invalid_msa_input_mininfo"), - // MessageManager.getString("info.invalid_msa_notenough"), - // JvOptionPane.INFORMATION_MESSAGE); + listeners.fireWorkerNotStarted(); } } @@ -480,9 +329,7 @@ public class AlignmentOperation implements Operation } catch (IOException e) { Cache.log.error(format("Polling job %s failed.", job), e); - wsInfo.appendProgressText(job.getJobNum(), - MessageManager.formatMessage("info.server_exception", - service.getName(), e.getMessage())); + listeners.firePollException(job, e); int count = exceptionCount.getOrDefault(job.getUid(), MAX_RETRY); if (--count <= 0) @@ -503,45 +350,14 @@ public class AlignmentOperation implements Operation } done &= job.getStatus().isDone() || job.getStatus().isFailed(); } - updateWSInfoGlobalStatus(); return done; } - private void updateWSInfoGlobalStatus() - { - if (jobs.countRunning() > 0) - { - wsInfo.setStatus(WebserviceInfo.STATE_RUNNING); - } - else if (jobs.countQueuing() > 0 - || jobs.countSubmitted() < jobs.size()) - { - wsInfo.setStatus(WebserviceInfo.STATE_QUEUING); - } - else - { - if (jobs.countSuccessful() > 0) - { - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK); - } - else if (jobs.countCancelled() > 0) - { - wsInfo.setStatus(WebserviceInfo.STATE_CANCELLED_OK); - } - else if (jobs.countFailed() > 0) - { - wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR); - } - } - } @Override public void done() { - long progbarId = MathUtils.getUID(); - wsInfo.setProgressBar( - MessageManager.getString("status.collecting_job_results"), - progbarId); + listeners.fireWorkerCompleting(); Map results = new LinkedHashMap<>(); for (WSJob job : getJobs()) { @@ -549,7 +365,8 @@ public class AlignmentOperation implements Operation continue; try { - AlignmentI alignment = supplier.getResult(job, dataset.getSequences(), viewport); + AlignmentI alignment = supplier.getResult(job, + dataset.getSequences(), viewport); if (alignment != null) { results.put(job.getUid(), alignment); @@ -564,39 +381,19 @@ public class AlignmentOperation implements Operation } } } - updateWSInfoGlobalStatus(); if (results.size() > 0) { - OutputWrapper out = prepareOutput(results); - wsInfo.showResultsNewFrame.addActionListener(evt -> displayNewFrame( - new Alignment(out.aln), out.alorders, out.hidden)); - wsInfo.setResultsReady(); + AlignmentResult out = prepareResult(results); + resultConsumer.accept(out); } else { - wsInfo.setFinishedNoResults(); + resultConsumer.accept(null); } - wsInfo.removeProgressBar(progbarId); + listeners.fireWorkerCompleted(); } - private class OutputWrapper - { - AlignmentI aln; - - List alorders; - - HiddenColumns hidden; - - OutputWrapper(AlignmentI aln, List alorders, - HiddenColumns hidden) - { - this.aln = aln; - this.alorders = alorders; - this.hidden = hidden; - } - } - - private OutputWrapper prepareOutput(Map alignments) + private AlignmentResult prepareResult(Map alignments) { List alorders = new ArrayList<>(); SequenceI[][] results = new SequenceI[jobs.size()][]; @@ -665,7 +462,7 @@ public class AlignmentOperation implements Operation aln.setDataset(dataset); propagateDatasetMappings(aln); - return new OutputWrapper(aln, alorders, hidden); + return new AlignmentResult(aln, alorders, hidden); // displayNewFrame(aln, alorders, hidden); } @@ -691,65 +488,53 @@ public class AlignmentOperation implements Operation } } } + + private Consumer resultConsumer; + + public void setResultConsumer(Consumer consumer) + { + this.resultConsumer = consumer; + } - private void displayNewFrame(AlignmentI aln, - List alorders, HiddenColumns hidden) + private WebServiceWorkerListenersList listeners = + new WebServiceWorkerListenersList(this); + + @Override + public void addListener(WebServiceWorkerListener listener) { - AlignFrame frame = new AlignFrame(aln, hidden, - AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); - // TODO store feature renderer settings in worker object - // frame.getFeatureRenderer().transferSettings(featureSettings); - var regions = sortOrders(alorders); - if (alorders.size() == 1) - { - frame.addSortByOrderMenuItem( - format("%s Ordering", service.getName()), alorders.get(0)); - } - else - { - for (int i = 0; i < alorders.size(); i++) - { - final int j = i; - Iterable iter = () -> regions.get(j).stream() - .map(it -> Integer.toString(it)).iterator(); - var orderName = format("%s Region %s Ordering", service.getName(), - String.join(",", iter)); - frame.addSortByOrderMenuItem(orderName, alorders.get(i)); - } - } + listeners.addListener(listener); + } + } + + public class AlignmentResult + { + AlignmentI aln; - /* TODO - * If alignment was requested from one half of a SplitFrame, show in a - * SplitFrame with the other pane similarly aligned. - */ + List alorders; - Desktop.addInternalFrame(frame, alnTitle, AlignFrame.DEFAULT_WIDTH, - AlignFrame.DEFAULT_HEIGHT); + HiddenColumns hidden; + + AlignmentResult(AlignmentI aln, List alorders, + HiddenColumns hidden) + { + this.aln = aln; + this.alorders = alorders; + this.hidden = hidden; } - private List> sortOrders(List alorders) + public AlignmentI getAln() { - List> regions = new ArrayList<>(); - for (int i = 0; i < alorders.size(); i++) - { - List regs = new ArrayList<>(); - regs.add(i); - int j = i + 1; - while (j < alorders.size()) - { - if (alorders.get(i).equals(alorders.get(j))) - { - alorders.remove(j); - regs.add(j); - } - else - { - j++; - } - } - regions.add(regs); - } - return regions; + return aln; + } + + public List getAlorders() + { + return alorders; + } + + public HiddenColumns getHidden() + { + return hidden; } }