import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
-import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.TreeMap;
import java.util.concurrent.CompletionStage;
import javax.swing.ToolTipManager;
import javax.swing.border.EmptyBorder;
+import jalview.bin.Console;
+import jalview.datamodel.AlignmentI;
import jalview.gui.AlignFrame;
import jalview.gui.Desktop;
import jalview.gui.JvSwingUtils;
import jalview.ws.params.ArgumentI;
import jalview.ws.params.ParamDatastoreI;
import jalview.ws.params.WsParamSetI;
+import jalview.ws2.actions.BaseTask;
+import jalview.ws2.actions.PollingTaskExecutor;
import jalview.ws2.actions.alignment.AlignmentAction;
+import jalview.ws2.actions.alignment.AlignmentResult;
+import jalview.ws2.actions.annotation.AlignCalcWorkerAdapter;
import jalview.ws2.actions.annotation.AnnotationAction;
import jalview.ws2.actions.api.ActionI;
+import jalview.ws2.actions.api.TaskEventListener;
import jalview.ws2.actions.api.TaskI;
+import jalview.ws2.actions.hmmer.PhmmerAction;
import jalview.ws2.api.Credentials;
import jalview.ws2.api.WebService;
import jalview.ws2.client.api.WebServiceProviderI;
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNullElse;
-
public class WebServicesMenuManager
{
private final JMenu menu;
noServicesItem.setEnabled(false);
}
- private Map<String, WeakReference<TaskI<?>>> interactiveTasks = new HashMap<>();
-
public WebServicesMenuManager(String name, AlignFrame frame)
{
this.frame = frame;
private void addOneshotEntries(List<WebService<?>> services, JMenu menu)
{
- services.sort(Comparator
- .<WebService<?>, String> comparing(s -> s.getUrl().toString())
- .thenComparing(WebService::getName));
+ // Workaround. Comparator methods not working in j2s
+ services.sort((ws1, ws2) -> {
+ var res = ws1.getUrl().toString().compareTo(ws2.getUrl().toString());
+ if (res == 0)
+ res = ws1.getName().compareTo(ws2.getName());
+ return res;
+ });
URL lastHost = null;
for (WebService<?> service : services)
{
{
actionsByCategory
.computeIfAbsent(
- Objects.requireNonNullElse(action.getSubcategory(), ""),
+ action.getSubcategory() != null ? action.getSubcategory() : "",
k -> new ArrayList<>())
.add(action);
}
- actionsByCategory.forEach((k, v) -> {
+ for (var entry : actionsByCategory.entrySet())
+ {
+ var category = entry.getKey();
+ var actions = entry.getValue();
// create submenu named {subcategory} with {service} or use root menu
- var atMenu = k.isEmpty() ? menu : new JMenu(String.format("%s with %s", k, service.getName()));
+ var atMenu = category.isEmpty() ? menu : new JMenu(String.format("%s with %s", category, service.getName()));
if (atMenu != menu)
menu.add(atMenu); // add only if submenu
// sort actions by name pulling nulls to the front
- v.sort(Comparator.comparing(
+ actions.sort(Comparator.comparing(
ActionI::getName, Comparator.nullsFirst(Comparator.naturalOrder())));
- for (ActionI<?> action : v)
+ for (int i = 0; i < actions.size(); i++)
{
- addEntriesForAction(action, atMenu, atMenu == menu);
+ addEntriesForAction(actions.get(i), atMenu, atMenu == menu);
}
- });
+ }
}
}
private void addEntriesForAction(ActionI<?> action, JMenu menu, boolean isTopLevel)
{
+ var enabled = isActionEnabled(action);
var service = action.getWebService();
String itemName;
if (isTopLevel)
if (datastore.hasParameters() || datastore.hasPresets())
text += " with defaults";
JMenuItem item = new JMenuItem(text);
+ item.setEnabled(enabled);
item.addActionListener(e -> {
runAction(action, frame.getCurrentView(), Collections.emptyList(),
Credentials.empty());
if (datastore.hasParameters())
{
JMenuItem item = new JMenuItem("Edit settings and run...");
+ item.setEnabled(enabled);
item.addActionListener(e -> {
openEditParamsDialog(datastore, null, null).thenAccept(args -> {
if (args != null)
{
final var presetsMenu = new JMenu(MessageManager.formatMessage(
"label.run_with_preset_params", service.getName()));
+ presetsMenu.setEnabled(enabled);
final int dismissDelay = ToolTipManager.sharedInstance()
.getDismissDelay();
final int QUICK_TOOLTIP = 1500;
private void buildAlternativesMenu(List<WebService<?>> services)
{
var menu = alternativesMenu;
- services.sort(Comparator
- .<WebService<?>, String> comparing(s -> s.getUrl().toString())
- .thenComparing(s -> s.getName()));
+ services.sort((ws1, ws2) -> {
+ var res = ws1.getUrl().toString().compareTo(ws2.getUrl().toString());
+ if (res == 0)
+ res = ws1.getName().compareTo(ws2.getName());
+ return res;
+ });
URL lastHost = null;
for (var service : services)
{
{
actionsByCategory
.computeIfAbsent(
- requireNonNullElse(action.getSubcategory(), ""),
+ action.getSubcategory() != null ? action.getSubcategory() : "",
k -> new ArrayList<>())
.add(action);
}
for (ActionI<?> action : actions)
{
var item = new JMenuItem(action.getFullName());
+ item.setEnabled(isActionEnabled(action));
item.addActionListener(e -> setAlternative(action));
atMenu.add(item);
}
serviceItem.removeActionListener(l);
WebService<?> service = action.getWebService();
serviceItem.addActionListener(e -> {
- if (serviceItem.getState())
- {
- cancelAndRunInteractive(action, frame.getCurrentView(), arguments,
- Credentials.empty());
- }
- else
- {
- cancelInteractive(service.getName());
- }
+ runAction(action, frame.getCurrentView(), arguments,
+ Credentials.empty());
});
serviceItem.setSelected(true);
lastPreset[0] = null;
arguments.clear();
arguments.addAll(args);
- cancelAndRunInteractive(action, frame.getCurrentView(),
+ runAction(action, frame.getCurrentView(),
arguments, Credentials.empty());
}
});
var item = new JMenuItem(preset.getName());
item.addActionListener(e -> {
lastPreset[0] = preset;
- cancelAndRunInteractive(action, frame.getCurrentView(),
+ runAction(action, frame.getCurrentView(),
preset.getArguments(), Credentials.empty());
});
presetsMenu.add(item);
}
}
- cancelAndRunInteractive(action, frame.getCurrentView(), arguments,
+ runAction(action, frame.getCurrentView(), arguments,
Credentials.empty());
}
}
}
- private void cancelInteractive(String wsName)
- {
- var taskRef = interactiveTasks.get(wsName);
- if (taskRef != null && taskRef.get() != null)
- taskRef.get().cancel();
- interactiveTasks.put(wsName, null);
- }
-
- private void cancelAndRunInteractive(ActionI<?> action,
- AlignmentViewport viewport, List<ArgumentI> args, Credentials credentials)
+ private boolean isActionEnabled(ActionI<?> action)
{
- var wsName = action.getWebService().getName();
- cancelInteractive(wsName);
- var task = runAction(action, viewport, args, credentials);
- interactiveTasks.put(wsName, new WeakReference<>(task));
+ var isNa = frame.getViewport().getAlignment().isNucleotide();
+ return ((isNa && action.doAllowNucleotide()) ||
+ (!isNa && action.doAllowProtein()));
}
- private TaskI<?> runAction(ActionI<?> action, AlignmentViewport viewport,
+ private void runAction(ActionI<?> action, AlignmentViewport viewport,
List<ArgumentI> args, Credentials credentials)
{
// casting and instance checks can be avoided with some effort,
// TODO: test if selection contains enough sequences
var _action = (AlignmentAction) action;
var handler = new AlignmentServiceGuiHandler(_action, frame);
- return _action.perform(viewport, args, credentials, handler);
+ BaseTask<?, AlignmentResult> task = _action.createTask(viewport, args, credentials);
+ var executor = PollingTaskExecutor.fromPool(viewport.getServiceExecutor());
+ task.addTaskEventListener(handler);
+ var future = executor.submit(task);
+ task.setCancelAction(() -> { future.cancel(true); });
+ return;
}
if (action instanceof AnnotationAction)
{
+ var calcManager = viewport.getCalcManager();
+
var _action = (AnnotationAction) action;
+ var worker = new AlignCalcWorkerAdapter(viewport, frame.alignPanel,
+ _action, args, credentials);
var handler = new AnnotationServiceGuiHandler(_action, frame);
- return _action.perform(viewport, args, credentials, handler);
+ worker.setWorkerListener(handler);
+ for (var w : calcManager.getWorkers())
+ {
+ if (worker.getCalcName() != null && worker.getCalcName().equals(w.getCalcName()))
+ {
+ calcManager.cancelWorker(w);
+ calcManager.removeWorker(w);
+ }
+ }
+ if (action.getWebService().isInteractive())
+ calcManager.registerWorker(worker);
+ else
+ calcManager.startWorker(worker);
+ return;
+ }
+ if (action instanceof PhmmerAction)
+ {
+ var _action = (PhmmerAction) action;
+ var handler = new SearchServiceGuiHandler(_action, frame);
+ TaskI<AlignmentI> task = _action.createTask(viewport, args, credentials);
+ var executor = PollingTaskExecutor.fromPool(viewport.getServiceExecutor());
+ task.addTaskEventListener(handler);
+ _action.perform(viewport, args, credentials, handler);
+ return;
}
- throw new IllegalArgumentException(
- String.format("Illegal action type %s", action.getClass().getName()));
+ Console.warn(String.format(
+ "No known handler for action type %s. All output will be discarded.",
+ action.getClass().getName()));
+ var task = action.createTask(viewport, args, credentials);
+ task.addTaskEventListener(TaskEventListener.nullListener());
+ PollingTaskExecutor.fromPool(viewport.getServiceExecutor())
+ .submit(task);
}
private static CompletionStage<List<ArgumentI>> openEditParamsDialog(
{
final WsJobParameters jobParams;
if (preset == null && arguments != null && arguments.size() > 0)
- jobParams = new WsJobParameters(paramStore, preset, arguments);
+ jobParams = new WsJobParameters(paramStore, null, arguments);
else
jobParams = new WsJobParameters(paramStore, preset, null);
if (preset != null)