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.datamodel.HiddenColumns;
12 import jalview.gui.AlignFrame;
13 import jalview.gui.Desktop;
14 import jalview.gui.JvOptionPane;
15 import jalview.gui.WebserviceInfo;
16 import jalview.util.ArrayUtils;
17 import jalview.util.MessageManager;
18 import jalview.ws2.actions.api.ActionI;
19 import jalview.ws2.actions.api.JobI;
20 import jalview.ws2.actions.api.TaskEventListener;
21 import jalview.ws2.actions.api.TaskI;
22 import jalview.ws2.api.JobStatus;
23 import jalview.ws2.api.WebService;
24 import jalview.ws2.helpers.WSClientTaskWrapper;
26 import static java.lang.String.format;
28 class SearchServiceGuiHandler implements TaskEventListener<AlignmentI>
30 private final AlignFrame parentFrame;
32 private final ActionI<?> action;
34 private final WebService<?> service;
36 private WebserviceInfo infoPanel;
38 private JobI[] jobs = new JobI[0];
40 private int[] tabs = new int[0];
42 private int[] logOffset = new int[0];
44 private int[] errLogOffset = new int[0];
46 public SearchServiceGuiHandler(ActionI<?> action, AlignFrame parentFrame)
48 this.parentFrame = parentFrame;
50 this.service = action.getWebService();
51 var info = String.format("%s search using service at %s%n%s",
52 service.getName(), service.getUrl(), service.getDescription());
53 this.infoPanel = new WebserviceInfo(service.getName(), info, false);
57 public void taskStarted(TaskI<AlignmentI> source,
58 List<? extends JobI> subJobs)
60 Console.debug(format("task %s#%x started with %d sub-jobs",
61 service.getName(), source.getUid(), subJobs.size()));
62 jobs = subJobs.toArray(new JobI[subJobs.size()]);
63 tabs = new int[subJobs.size()];
64 logOffset = new int[subJobs.size()];
65 errLogOffset = new int[subJobs.size()];
66 for (int i = 0; i < subJobs.size(); i++)
69 int tabIndex = infoPanel.addJobPane();
71 infoPanel.setProgressName(format("region %d", i), tabIndex);
72 infoPanel.setProgressText(tabIndex, "Job details:\n");
73 // jobs should not have states other than invalid or ready at this point
74 if (job.getStatus() == JobStatus.INVALID)
75 infoPanel.setStatus(tabIndex, WebserviceInfo.STATE_STOPPED_OK);
76 else if (job.getStatus() == JobStatus.READY)
77 infoPanel.setStatus(tabIndex, WebserviceInfo.STATE_QUEUING);
82 public void taskStatusChanged(TaskI<AlignmentI> source, JobStatus status)
84 Console.debug(format("task %s#%x status changed to %s",
85 service.getName(), source.getUid(), status));
89 infoPanel.setVisible(false);
90 JvOptionPane.showMessageDialog(parentFrame,
91 MessageManager.getString("info.invalid_search_input"),
92 MessageManager.getString("info.invalid_search_input"),
93 JvOptionPane.INFORMATION_MESSAGE);
96 infoPanel.setthisService(new WSClientTaskWrapper(source));
97 infoPanel.setVisible(true);
98 // intentional no break
101 infoPanel.setStatus(WebserviceInfo.STATE_QUEUING);
104 case UNKNOWN: // unsure what to do with unknown
105 infoPanel.setStatus(WebserviceInfo.STATE_RUNNING);
108 infoPanel.setProgressBar(
109 MessageManager.getString("status.collecting_job_results"),
110 jobs[0].getInternalId());
111 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_OK);
114 infoPanel.removeProgressBar(jobs[0].getInternalId());
115 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
118 infoPanel.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
121 infoPanel.removeProgressBar(jobs[0].getInternalId());
122 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
128 public void taskCompleted(TaskI<AlignmentI> source, AlignmentI result)
130 Console.debug(format("task %s#%x completed", service.getName(),
132 SwingUtilities.invokeLater(
133 () -> infoPanel.removeProgressBar(jobs[0].getInternalId()));
136 SwingUtilities.invokeLater(infoPanel::setFinishedNoResults);
139 infoPanel.showResultsNewFrame.addActionListener(evt -> {
140 // copy alignment for each frame to have its own instance
141 var alnCpy = new Alignment(result);
142 alnCpy.setGapCharacter(result.getGapCharacter());
143 alnCpy.setDataset(result.getDataset());
144 for (AlignmentAnnotation annotation : result.getAlignmentAnnotation())
145 alnCpy.addAnnotation(new AlignmentAnnotation(annotation));
146 if (result.hasSeqrep())
148 int idx = result.findIndex(result.getSeqrep());
150 alnCpy.setSeqrep(alnCpy.getSequenceAt(idx));
152 if (result.getHiddenColumns() != null)
153 alnCpy.setHiddenColumns(new HiddenColumns(result.getHiddenColumns()));
154 displayResultsNewFrame(alnCpy);
156 SwingUtilities.invokeLater(infoPanel::setResultsReady);
159 private void displayResultsNewFrame(AlignmentI aln)
161 AlignFrame frame = new AlignFrame(aln, AlignFrame.DEFAULT_WIDTH,
162 AlignFrame.DEFAULT_HEIGHT);
163 frame.getFeatureRenderer().transferSettings(
164 parentFrame.getFeatureRenderer().getSettings());
165 var actionName = action.getName() != null ? action.getName() : "Search";
166 var title = String.format("%s %s of %s", service.getName(), actionName,
167 parentFrame.getTitle());
168 Desktop.addInternalFrame(frame, title, AlignFrame.DEFAULT_WIDTH,
169 AlignFrame.DEFAULT_HEIGHT);
173 public void taskException(TaskI<AlignmentI> source, Exception e)
175 Console.error(format("Task %s#%x raised an exception.",
176 service.getName(), source.getUid()), e);
177 infoPanel.appendProgressText(e.getMessage());
181 public void subJobStatusChanged(TaskI<AlignmentI> source, JobI job,
184 Console.debug(format("sub-job %x status changed to %s",
185 job.getInternalId(), status));
186 int i = ArrayUtils.indexOf(jobs, job);
187 assert i >= 0 : "job does not exist";
189 // safeguard that should not happen irl
196 wsStatus = WebserviceInfo.STATE_STOPPED_OK;
201 wsStatus = WebserviceInfo.STATE_QUEUING;
205 wsStatus = WebserviceInfo.STATE_RUNNING;
208 wsStatus = WebserviceInfo.STATE_STOPPED_ERROR;
211 wsStatus = WebserviceInfo.STATE_CANCELLED_OK;
214 wsStatus = WebserviceInfo.STATE_STOPPED_SERVERERROR;
217 throw new AssertionError("Non-exhaustive switch statement");
219 infoPanel.setStatus(tabs[i], wsStatus);
223 public void subJobLogChanged(TaskI<AlignmentI> source, JobI job,
226 int i = ArrayUtils.indexOf(jobs, job);
227 assert i >= 0 : "job does not exist";
229 // safeguard that should never happen
231 infoPanel.appendProgressText(tabs[i], log.substring(logOffset[i]));
235 public void subJobErrorLogChanged(TaskI<AlignmentI> source, JobI job,
238 int i = ArrayUtils.indexOf(jobs, job);
239 assert i >= 0 : "job does not exist";
241 // safeguard that should never happen
243 infoPanel.appendProgressText(tabs[i], log.substring(errLogOffset[i]));