package jalview.ws2.operations;
-import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletionStage;
+import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
-import jalview.bin.Cache;
+import jalview.api.AlignCalcManagerI2;
+import jalview.api.AlignmentViewPanel;
+import jalview.datamodel.AlignmentAnnotation;
import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
import jalview.gui.WsJobParameters;
-import jalview.io.AnnotationFile;
import jalview.io.FeaturesFile;
-import jalview.util.MathUtils;
+import jalview.util.Format;
import jalview.util.MessageManager;
import jalview.ws.params.ArgumentI;
import jalview.ws.params.WsParamSetI;
import jalview.ws2.MenuEntryProviderI;
import jalview.ws2.ResultSupplier;
-import jalview.ws2.WSJob;
-import jalview.ws2.WSJobStatus;
-import jalview.ws2.WebServiceExecutor;
+import jalview.ws2.PollingTaskExecutor;
import jalview.ws2.WebServiceI;
-import jalview.ws2.WebServiceWorkerI;
-import jalview.ws2.utils.WSJobList;
-
-import static java.lang.String.format;
/**
- *
+ *
* @author mmwarowny
*
*/
final String typeName;
- final ResultSupplier<AnnotationFile> annotationSupplier;
+ final ResultSupplier<List<AlignmentAnnotation>> annotationSupplier;
final ResultSupplier<FeaturesFile> featuresSupplier;
+ boolean alignmentAnalysis = false;
+
+ boolean interactive = false;
+
+ /*
+ * Is it fine to get rid of AlignAnalysisUIText?
+ */
+
public AnnotationOperation(WebServiceI service,
- ResultSupplier<AnnotationFile> annotSupplier,
+ ResultSupplier<List<AlignmentAnnotation>> annotSupplier,
ResultSupplier<FeaturesFile> featSupplier, String operationName)
{
this.service = service;
@Override
public boolean isInteractive()
{
+ return interactive;
+ }
+
+ public void setInteractive(boolean value)
+ {
+ this.interactive = value;
+ }
+
+ @Override
+ public boolean isAlignmentAnalysis()
+ {
+ return alignmentAnalysis;
+ }
+
+ public void setAlignmentAnalysis(boolean value)
+ {
+ this.alignmentAnalysis = value;
+ }
+
+ @Override
+ public boolean getFilterNonStandardSymbols()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean getNeedsAlignedSequences()
+ {
return false;
}
@Override
public MenuEntryProviderI getMenuBuilder()
{
- return this::buildMenu;
+ if (isInteractive())
+ return this::buildInteractiveMenu;
+ else
+ return this::buildClassicMenu;
}
- protected void buildMenu(JMenu parent, AlignFrame frame)
+ protected void buildClassicMenu(JMenu parent, AlignFrame frame)
{
final var calcName = service.getName();
- WebServiceExecutor wsExecutor = frame.getViewport().getWSExecutor();
+ PollingTaskExecutor wsExecutor = frame.getViewport().getWSExecutor();
+ final var calcManager = frame.getViewport().getCalcManager();
{
var item = new JMenuItem(MessageManager.formatMessage(
"label.calcname_with_default_settings", calcName));
item.addActionListener((event) -> {
- WebServiceWorkerI worker = new AnnotationWorker();
- wsExecutor.submit(worker);
+ var worker = createWorker(Collections.emptyList(), frame, calcManager);
+ calcManager.startWorker(worker);
});
parent.add(item);
}
.thenAcceptAsync((arguments) -> {
if (arguments != null)
{
-
+ var worker = createWorker(arguments, frame, calcManager);
+ calcManager.startWorker(worker);
}
});
});
+ parent.add(item);
}
}
+ protected void buildInteractiveMenu(JMenu parent, AlignFrame frame)
+ {
+ final var calcName = service.getName();
+ final var calcManager = frame.getViewport().getCalcManager();
+ final var arguments = new ArrayList<ArgumentI>();
+ final JCheckBoxMenuItem runItem;
+ {
+ // TODO use MessageManager and set tool tip text
+ runItem = new JCheckBoxMenuItem(
+ String.format("%s calculations", calcName));
+ runItem.addActionListener((event) -> {
+ calcManager.removeWorkersForName(calcName);
+ var worker = createWorker(arguments, frame, calcManager);
+ calcManager.registerWorker(worker);
+ });
+ parent.add(runItem);
+ }
+ JMenuItem _editItem = null;
+ if (service.hasParameters())
+ {
+ // TODO use MessageManager and set tool tip text
+ _editItem = new JMenuItem(
+ String.format("Edit %s settings", calcName));
+ _editItem.addActionListener((event) -> {
+ openEditParamsDialog(service, null, null)
+ .thenAcceptAsync((args) -> {
+ if (arguments != null)
+ {
+ arguments.clear();
+ arguments.addAll(args);
+ calcManager.removeWorkersForName(calcName);
+ var worker = createWorker(arguments, frame, calcManager);
+ calcManager.registerWorker(worker);
+ }
+ });
+ });
+ parent.add(_editItem);
+ }
+ final var editItem = _editItem;
+
+ parent.addMenuListener(new MenuListener()
+ {
+ @Override
+ public void menuSelected(MenuEvent e)
+ {
+ var isNuc = frame.getViewport().getAlignment().isNucleotide();
+ var menuEnabled = (isNuc && isNucleotideOperation()) ||
+ (!isNuc && isProteinOperation());
+ runItem.setEnabled(menuEnabled);
+ if (editItem != null)
+ editItem.setEnabled(menuEnabled);
+ boolean currentlyRunning = calcManager.getWorkersForName(calcName).size() > 0;
+ runItem.setSelected(currentlyRunning);
+ }
+
+ @Override
+ public void menuDeselected(MenuEvent e) {}
+
+ @Override
+ public void menuCanceled(MenuEvent e) {}
+ });
+ }
+
+ private AnnotationServiceWorker createWorker(
+ List<ArgumentI> arguments, AlignFrame frame, AlignCalcManagerI2 calcManager)
+ {
+ /* What is the purpose of AlignViewport and AlignmentViewPanel? */
+ AlignViewport viewport = frame.getCurrentView();
+ AlignmentViewPanel alignPanel = frame.alignPanel;
+ return new AnnotationServiceWorker(this, service,
+ arguments, viewport, alignPanel, frame, frame,
+ calcManager);
+ }
+
private CompletionStage<List<ArgumentI>> openEditParamsDialog(
WebServiceI service, WsParamSetI preset, List<ArgumentI> arguments)
{
});
}
- private class AnnotationWorker implements WebServiceWorkerI
- {
- private long uid = MathUtils.getUID();
-
- private WSJobList jobs = new WSJobList();
-
- private HashMap<Long, Integer> exceptionCount = new HashMap<>();
-
- private static final int MAX_RETRY = 5;
-
- @Override
- public long getUID()
- {
- return uid;
- }
-
- @Override
- public WebServiceI getWebService()
- {
- return service;
- }
-
- @Override
- public List<WSJob> getJobs()
- {
- return Collections.unmodifiableList(jobs);
- }
-
- @Override
- public void startJobs() throws IOException
- {
-
- }
-
- @Override
- public boolean pollJobs() throws IOException
- {
- boolean done = true;
- for (WSJob job : getJobs())
- {
- if (!job.getStatus().isDone() && !job.getStatus().isFailed())
- {
- Cache.log.debug(format("Polling job %s", job));
- try
- {
- service.updateProgress(job);
- exceptionCount.remove(job.getUid());
- } catch (IOException e)
- {
- Cache.log.error(format("Polling job %s failed.", job), e);
- int count = exceptionCount.getOrDefault(job.getUid(),
- MAX_RETRY);
- if (--count <= 0)
- {
- job.setStatus(WSJobStatus.SERVER_ERROR);
- Cache.log.warn(format(
- "Attempts limit exceeded. Droping job %s.", job));
- }
- exceptionCount.put(job.getUid(), count);
- } catch (OutOfMemoryError e)
- {
- job.setStatus(WSJobStatus.BROKEN);
- Cache.log.error(
- format("Out of memory when retrieving job %s", job), e);
- }
- Cache.log.debug(
- format("Job %s status is %s", job, job.getStatus()));
- }
- done &= job.getStatus().isDone() || job.getStatus().isFailed();
- }
- return done;
- }
-
- @Override
- public void done()
- {
- // TODO Auto-generated method stub
-
- }
-
- }
}