package jalview.ws2.operations; import java.io.IOException; 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.JMenu; import javax.swing.JMenuItem; import jalview.bin.Cache; import jalview.gui.AlignFrame; import jalview.gui.WsJobParameters; import jalview.io.AnnotationFile; import jalview.io.FeaturesFile; import jalview.util.MathUtils; 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.WebServiceI; import jalview.ws2.WebServiceWorkerI; import jalview.ws2.utils.WSJobList; import static java.lang.String.format; /** * * @author mmwarowny * */ public class AnnotationOperation implements Operation { final WebServiceI service; final String typeName; final ResultSupplier annotationSupplier; final ResultSupplier featuresSupplier; public AnnotationOperation(WebServiceI service, ResultSupplier annotSupplier, ResultSupplier featSupplier, String operationName) { this.service = service; this.annotationSupplier = annotSupplier; this.featuresSupplier = featSupplier; this.typeName = operationName; } @Override public String getName() { return service.getName(); } @Override public String getTypeName() { return typeName; } @Override public String getHostName() { return service.getHostName(); } @Override public int getMinSequences() { return 0; } @Override public int getMaxSequences() { return Integer.MAX_VALUE; } @Override public boolean canSubmitGaps() { return false; } @Override public boolean isProteinOperation() { return true; } @Override public boolean isNucleotideOperation() { return true; } @Override public boolean isInteractive() { return false; } @Override public MenuEntryProviderI getMenuBuilder() { return this::buildMenu; } protected void buildMenu(JMenu parent, AlignFrame frame) { final var calcName = service.getName(); WebServiceExecutor wsExecutor = frame.getViewport().getWSExecutor(); { var item = new JMenuItem(MessageManager.formatMessage( "label.calcname_with_default_settings", calcName)); item.addActionListener((event) -> { WebServiceWorkerI worker = new AnnotationWorker(); wsExecutor.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_running_calculation")); item.addActionListener((event) -> { openEditParamsDialog(service, null, null) .thenAcceptAsync((arguments) -> { if (arguments != null) { } }); }); } } 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); if (preset != null) { jobParams.setName(MessageManager.getString( "label.adjusting_parameters_for_calculation")); } 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; } }); } private class AnnotationWorker implements WebServiceWorkerI { private long uid = MathUtils.getUID(); private WSJobList jobs = new WSJobList(); private HashMap 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 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 } } }