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;
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;
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;
/**
*/
public class AlignmentOperation implements Operation
{
- final WebServiceI service;
+ private final WebServiceI service;
- final ResultSupplier<AlignmentI> supplier;
+ private final ResultSupplier<AlignmentI> supplier;
+
- public AlignmentOperation(WebServiceI service,
- ResultSupplier<AlignmentI> supplier)
+ public AlignmentOperation(
+ WebServiceI service,
+ ResultSupplier<AlignmentI> supplier)
{
this.service = service;
this.supplier = supplier;
{
return service.getName();
}
+
+ @Override
+ public String getDescription()
+ {
+ return service.getDescription();
+ }
@Override
public String getTypeName()
{
return service.getHostName();
}
+
+ @Override
+ public boolean hasParameters()
+ {
+ return service.hasParameters();
+ }
+
+ @Override
+ public ParamDatastoreI getParamStore()
+ {
+ return service.getParamStore();
+ }
@Override
public int getMinSequences()
public boolean canSubmitGaps()
{
// hack copied from original jabaws code, don't blame me
- return service.getName().contains("lustal");
+ return getName().contains("lustal");
}
@Override
@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("<strong>%s</strong><br/>%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<List<ArgumentI>> openEditParamsDialog(
- WebServiceI service, WsParamSetI preset,
- List<ArgumentI> 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
* @author mmwarowny
*
*/
- private class AlignmentWorker implements WebServiceWorkerI
+ public class AlignmentWorker implements WebServiceWorkerI
{
private long uid = MathUtils.getUID();
private Map<Long, JobInput> inputs = new LinkedHashMap<>();
- private WebserviceInfo wsInfo;
-
private Map<Long, Integer> exceptionCount = new HashMap<>();
-
+
private final int MAX_RETRY = 5;
- AlignmentWorker(AlignmentView msa, List<ArgumentI> args,
+ public AlignmentWorker(AlignmentView msa, List<ArgumentI> 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<AlignedCodonFrame> cf = Objects.requireNonNullElse(
- alignment.getCodonFrames(), Collections.emptyList());
+ viewport.getAlignment().getCodonFrames(), Collections.emptyList());
this.codonFrame.addAll(cf);
this.args = args;
this.alnTitle = alnTitle;
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
}
@Override
- public List<WSJob> 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;
}
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();
}
}
} 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)
}
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<Long, AlignmentI> results = new LinkedHashMap<>();
for (WSJob job : getJobs())
{
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);
}
}
}
- 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<AlignmentOrder> alorders;
-
- HiddenColumns hidden;
-
- OutputWrapper(AlignmentI aln, List<AlignmentOrder> alorders,
- HiddenColumns hidden)
- {
- this.aln = aln;
- this.alorders = alorders;
- this.hidden = hidden;
- }
- }
-
- private OutputWrapper prepareOutput(Map<Long, AlignmentI> alignments)
+ private AlignmentResult prepareResult(Map<Long, AlignmentI> alignments)
{
List<AlignmentOrder> alorders = new ArrayList<>();
SequenceI[][] results = new SequenceI[jobs.size()][];
aln.setDataset(dataset);
propagateDatasetMappings(aln);
- return new OutputWrapper(aln, alorders, hidden);
+ return new AlignmentResult(aln, alorders, hidden);
// displayNewFrame(aln, alorders, hidden);
}
}
}
}
+
+ private Consumer<AlignmentResult> resultConsumer;
+
+ public void setResultConsumer(Consumer<AlignmentResult> consumer)
+ {
+ this.resultConsumer = consumer;
+ }
- private void displayNewFrame(AlignmentI aln,
- List<AlignmentOrder> 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<String> 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<AlignmentOrder> alorders;
- Desktop.addInternalFrame(frame, alnTitle, AlignFrame.DEFAULT_WIDTH,
- AlignFrame.DEFAULT_HEIGHT);
+ HiddenColumns hidden;
+
+ AlignmentResult(AlignmentI aln, List<AlignmentOrder> alorders,
+ HiddenColumns hidden)
+ {
+ this.aln = aln;
+ this.alorders = alorders;
+ this.hidden = hidden;
}
- private List<List<Integer>> sortOrders(List<?> alorders)
+ public AlignmentI getAln()
{
- List<List<Integer>> regions = new ArrayList<>();
- for (int i = 0; i < alorders.size(); i++)
- {
- List<Integer> 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<AlignmentOrder> getAlorders()
+ {
+ return alorders;
+ }
+
+ public HiddenColumns getHidden()
+ {
+ return hidden;
}
}