1 package jalview.ws2.gui;
5 import javax.swing.SwingUtilities;
7 import jalview.analysis.AlignmentUtils;
8 import jalview.bin.Console;
9 import jalview.datamodel.Alignment;
10 import jalview.datamodel.AlignmentAnnotation;
11 import jalview.datamodel.AlignmentI;
12 import jalview.datamodel.HiddenColumns;
13 import jalview.gui.AlignFrame;
14 import jalview.gui.Desktop;
15 import jalview.gui.JvOptionPane;
16 import jalview.gui.WebserviceInfo;
17 import jalview.util.ArrayUtils;
18 import jalview.util.MessageManager;
19 import jalview.ws2.actions.api.ActionI;
20 import jalview.ws2.actions.api.JobI;
21 import jalview.ws2.actions.api.TaskEventListener;
22 import jalview.ws2.actions.api.TaskI;
23 import jalview.ws2.api.JobStatus;
24 import jalview.ws2.api.WebService;
25 import jalview.ws2.helpers.WSClientTaskWrapper;
27 import static java.lang.String.format;
29 class SearchServiceGuiHandler implements TaskEventListener<AlignmentI>
31 private final AlignFrame parentFrame;
33 private final ActionI<?> action;
35 private final WebService<?> service;
37 private WebserviceInfo infoPanel;
39 private JobI[] jobs = new JobI[0];
41 private int[] tabs = new int[0];
43 private int[] logOffset = new int[0];
45 private int[] errLogOffset = new int[0];
47 public SearchServiceGuiHandler(ActionI<?> action, AlignFrame parentFrame)
49 this.parentFrame = parentFrame;
51 this.service = action.getWebService();
52 var info = String.format("%s search using service at %s%n%s",
53 service.getName(), service.getUrl(), service.getDescription());
54 this.infoPanel = new WebserviceInfo(service.getName(), info, false);
58 public void taskStarted(TaskI<AlignmentI> source,
59 List<? extends JobI> subJobs)
61 Console.debug(format("task %s#%x started with %d sub-jobs",
62 service.getName(), source.getUid(), subJobs.size()));
63 jobs = subJobs.toArray(new JobI[subJobs.size()]);
64 tabs = new int[subJobs.size()];
65 logOffset = new int[subJobs.size()];
66 errLogOffset = new int[subJobs.size()];
67 for (int i = 0; i < subJobs.size(); i++)
70 int tabIndex = infoPanel.addJobPane();
72 infoPanel.setProgressName(format("region %d", i), tabIndex);
73 infoPanel.setProgressText(tabIndex, "Job details:\n");
74 // jobs should not have states other than invalid or ready at this point
75 if (job.getStatus() == JobStatus.INVALID)
76 infoPanel.setStatus(tabIndex, WebserviceInfo.STATE_STOPPED_OK);
77 else if (job.getStatus() == JobStatus.READY)
78 infoPanel.setStatus(tabIndex, WebserviceInfo.STATE_QUEUING);
83 public void taskStatusChanged(TaskI<AlignmentI> source, JobStatus status)
85 Console.debug(format("task %s#%x status changed to %s",
86 service.getName(), source.getUid(), status));
90 infoPanel.setVisible(false);
91 JvOptionPane.showMessageDialog(parentFrame,
92 MessageManager.getString("info.invalid_search_input"),
93 MessageManager.getString("info.invalid_search_input"),
94 JvOptionPane.INFORMATION_MESSAGE);
97 infoPanel.setthisService(new WSClientTaskWrapper(source));
98 infoPanel.setVisible(true);
99 // intentional no break
102 infoPanel.setStatus(WebserviceInfo.STATE_QUEUING);
105 case UNKNOWN: // unsure what to do with unknown
106 infoPanel.setStatus(WebserviceInfo.STATE_RUNNING);
109 infoPanel.setProgressBar(
110 MessageManager.getString("status.collecting_job_results"),
111 jobs[0].getInternalId());
112 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_OK);
115 infoPanel.removeProgressBar(jobs[0].getInternalId());
116 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
119 infoPanel.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
122 infoPanel.removeProgressBar(jobs[0].getInternalId());
123 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
129 public void taskCompleted(TaskI<AlignmentI> source, AlignmentI result)
131 Console.debug(format("task %s#%x completed", service.getName(),
133 SwingUtilities.invokeLater(
134 () -> infoPanel.removeProgressBar(jobs[0].getInternalId()));
137 SwingUtilities.invokeLater(infoPanel::setFinishedNoResults);
140 infoPanel.showResultsNewFrame.addActionListener(evt -> {
141 // copy alignment for each frame to have its own instance
142 var alnCpy = AlignmentUtils.deepCopyAlignment(result);
143 displayResultsNewFrame(alnCpy);
145 SwingUtilities.invokeLater(infoPanel::setResultsReady);
148 private void displayResultsNewFrame(AlignmentI aln)
150 AlignFrame frame = new AlignFrame(aln, AlignFrame.DEFAULT_WIDTH,
151 AlignFrame.DEFAULT_HEIGHT);
152 frame.getFeatureRenderer().transferSettings(
153 parentFrame.getFeatureRenderer().getSettings());
154 var actionName = action.getName() != null ? action.getName() : "Search";
155 var title = String.format("%s %s of %s", service.getName(), actionName,
156 parentFrame.getTitle());
157 Desktop.addInternalFrame(frame, title, AlignFrame.DEFAULT_WIDTH,
158 AlignFrame.DEFAULT_HEIGHT);
162 public void taskException(TaskI<AlignmentI> source, Exception e)
164 Console.error(format("Task %s#%x raised an exception.",
165 service.getName(), source.getUid()), e);
166 infoPanel.appendProgressText(e.getMessage());
170 public void subJobStatusChanged(TaskI<AlignmentI> source, JobI job,
173 Console.debug(format("sub-job %x status changed to %s",
174 job.getInternalId(), status));
175 int i = ArrayUtils.indexOf(jobs, job);
176 assert i >= 0 : "job does not exist";
178 // safeguard that should not happen irl
185 wsStatus = WebserviceInfo.STATE_STOPPED_OK;
190 wsStatus = WebserviceInfo.STATE_QUEUING;
194 wsStatus = WebserviceInfo.STATE_RUNNING;
197 wsStatus = WebserviceInfo.STATE_STOPPED_ERROR;
200 wsStatus = WebserviceInfo.STATE_CANCELLED_OK;
203 wsStatus = WebserviceInfo.STATE_STOPPED_SERVERERROR;
206 throw new AssertionError("Non-exhaustive switch statement");
208 infoPanel.setStatus(tabs[i], wsStatus);
212 public void subJobLogChanged(TaskI<AlignmentI> source, JobI job,
215 int i = ArrayUtils.indexOf(jobs, job);
216 assert i >= 0 : "job does not exist";
218 // safeguard that should never happen
220 infoPanel.appendProgressText(tabs[i], log.substring(logOffset[i]));
224 public void subJobErrorLogChanged(TaskI<AlignmentI> source, JobI job,
227 int i = ArrayUtils.indexOf(jobs, job);
228 assert i >= 0 : "job does not exist";
230 // safeguard that should never happen
232 infoPanel.appendProgressText(tabs[i], log.substring(errLogOffset[i]));