1 package jalview.ws2.gui;
5 import javax.swing.SwingUtilities;
7 import jalview.bin.Console;
8 import jalview.datamodel.Alignment;
9 import jalview.datamodel.AlignmentAnnotation;
10 import jalview.datamodel.AlignmentI;
11 import jalview.gui.AlignFrame;
12 import jalview.gui.Desktop;
13 import jalview.gui.JvOptionPane;
14 import jalview.gui.WebserviceInfo;
15 import jalview.util.ArrayUtils;
16 import jalview.util.MessageManager;
17 import jalview.ws2.actions.api.ActionI;
18 import jalview.ws2.actions.api.JobI;
19 import jalview.ws2.actions.api.TaskEventListener;
20 import jalview.ws2.actions.api.TaskI;
21 import jalview.ws2.api.JobStatus;
22 import jalview.ws2.api.WebService;
23 import jalview.ws2.helpers.WSClientTaskWrapper;
25 import static java.lang.String.format;
27 class SearchServiceGuiHandler implements TaskEventListener<AlignmentI>
29 private final AlignFrame parentFrame;
31 private final ActionI<?> action;
33 private final WebService<?> service;
35 private WebserviceInfo infoPanel;
37 private JobI[] jobs = new JobI[0];
39 private int[] tabs = new int[0];
41 private int[] logOffset = new int[0];
43 private int[] errLogOffset = new int[0];
45 public SearchServiceGuiHandler(ActionI<?> action, AlignFrame parentFrame)
47 this.parentFrame = parentFrame;
49 this.service = action.getWebService();
50 var info = String.format("%s search using service at %s%n%s",
51 service.getName(), service.getUrl(), service.getDescription());
52 this.infoPanel = new WebserviceInfo(service.getName(), info, false);
56 public void taskStarted(TaskI<AlignmentI> source,
57 List<? extends JobI> subJobs)
59 Console.debug(format("task %s#%x started with %d sub-jobs",
60 service.getName(), source.getUid(), subJobs.size()));
61 jobs = subJobs.toArray(new JobI[subJobs.size()]);
62 tabs = new int[subJobs.size()];
63 logOffset = new int[subJobs.size()];
64 errLogOffset = new int[subJobs.size()];
65 for (int i = 0; i < subJobs.size(); i++)
68 int tabIndex = infoPanel.addJobPane();
70 infoPanel.setProgressName(format("region %d", i), tabIndex);
71 infoPanel.setProgressText(tabIndex, "Job details:\n");
72 // jobs should not have states other than invalid or ready at this point
73 if (job.getStatus() == JobStatus.INVALID)
74 infoPanel.setStatus(tabIndex, WebserviceInfo.STATE_STOPPED_OK);
75 else if (job.getStatus() == JobStatus.READY)
76 infoPanel.setStatus(tabIndex, WebserviceInfo.STATE_QUEUING);
81 public void taskStatusChanged(TaskI<AlignmentI> source, JobStatus status)
83 Console.debug(format("task %s#%x status changed to %s",
84 service.getName(), source.getUid(), status));
88 infoPanel.setVisible(false);
89 JvOptionPane.showMessageDialog(parentFrame,
90 MessageManager.getString("info.invalid_search_input"),
91 MessageManager.getString("info.invalid_search_input"),
92 JvOptionPane.INFORMATION_MESSAGE);
95 infoPanel.setthisService(new WSClientTaskWrapper(source));
96 infoPanel.setVisible(true);
97 // intentional no break
100 infoPanel.setStatus(WebserviceInfo.STATE_QUEUING);
103 case UNKNOWN: // unsure what to do with unknown
104 infoPanel.setStatus(WebserviceInfo.STATE_RUNNING);
107 infoPanel.setProgressBar(
108 MessageManager.getString("status.collecting_job_results"),
109 jobs[0].getInternalId());
110 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_OK);
113 infoPanel.removeProgressBar(jobs[0].getInternalId());
114 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
117 infoPanel.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
120 infoPanel.removeProgressBar(jobs[0].getInternalId());
121 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
127 public void taskCompleted(TaskI<AlignmentI> source, AlignmentI result)
129 Console.debug(format("task %s#%x completed", service.getName(),
131 SwingUtilities.invokeLater(
132 () -> infoPanel.removeProgressBar(jobs[0].getInternalId()));
135 SwingUtilities.invokeLater(infoPanel::setFinishedNoResults);
138 infoPanel.showResultsNewFrame.addActionListener(evt -> {
139 // copy alignment for each frame to have its own instance
140 var alnCpy = new Alignment(result);
141 alnCpy.setGapCharacter(result.getGapCharacter());
142 alnCpy.setDataset(result.getDataset());
143 for (AlignmentAnnotation annotation : result.getAlignmentAnnotation())
144 alnCpy.addAnnotation(new AlignmentAnnotation(annotation));
145 displayResultsNewFrame(alnCpy);
147 SwingUtilities.invokeLater(infoPanel::setResultsReady);
150 private void displayResultsNewFrame(AlignmentI aln)
152 AlignFrame frame = new AlignFrame(aln, AlignFrame.DEFAULT_WIDTH,
153 AlignFrame.DEFAULT_HEIGHT);
154 frame.getFeatureRenderer().transferSettings(
155 parentFrame.getFeatureRenderer().getSettings());
156 var actionName = action.getName() != null ? action.getName() : "Search";
157 var title = String.format("%s %s of %s", service.getName(), actionName,
158 parentFrame.getTitle());
159 Desktop.addInternalFrame(frame, title, AlignFrame.DEFAULT_WIDTH,
160 AlignFrame.DEFAULT_HEIGHT);
164 public void taskException(TaskI<AlignmentI> source, Exception e)
166 Console.error(format("Task %s#%x raised an exception.",
167 service.getName(), source.getUid()), e);
168 infoPanel.appendProgressText(e.getMessage());
172 public void taskRestarted(TaskI<AlignmentI> source)
174 // search services non-restartable
178 public void subJobStatusChanged(TaskI<AlignmentI> source, JobI job,
181 Console.debug(format("sub-job %x status changed to %s",
182 job.getInternalId(), status));
183 int i = ArrayUtils.indexOf(jobs, job);
184 assert i >= 0 : "job does not exist";
186 // safeguard that should not happen irl
193 wsStatus = WebserviceInfo.STATE_STOPPED_OK;
198 wsStatus = WebserviceInfo.STATE_QUEUING;
202 wsStatus = WebserviceInfo.STATE_RUNNING;
205 wsStatus = WebserviceInfo.STATE_STOPPED_ERROR;
208 wsStatus = WebserviceInfo.STATE_CANCELLED_OK;
211 wsStatus = WebserviceInfo.STATE_STOPPED_SERVERERROR;
214 throw new AssertionError("Non-exhaustive switch statement");
216 infoPanel.setStatus(tabs[i], wsStatus);
220 public void subJobLogChanged(TaskI<AlignmentI> source, JobI job,
223 int i = ArrayUtils.indexOf(jobs, job);
224 assert i >= 0 : "job does not exist";
226 // safeguard that should never happen
228 infoPanel.appendProgressText(tabs[i], log.substring(logOffset[i]));
232 public void subJobErrorLogChanged(TaskI<AlignmentI> source, JobI job,
235 int i = ArrayUtils.indexOf(jobs, job);
236 assert i >= 0 : "job does not exist";
238 // safeguard that should never happen
240 infoPanel.appendProgressText(tabs[i], log.substring(errLogOffset[i]));