Clover icon

Coverage Report

  1. Project Clover database Wed Dec 3 2025 17:03:17 GMT
  2. Package jalview.ws2.gui

File AlignmentServiceGuiHandler.java

 

Coverage histogram

../../../img/srcFileCovDistChart0.png
60% of files have more coverage

Code metrics

42
139
10
1
293
263
53
0.38
13.9
10
5.3

Classes

Class Line # Actions
AlignmentServiceGuiHandler 37 139 53
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    package jalview.ws2.gui;
2   
3    import java.util.ArrayList;
4    import java.util.Arrays;
5    import java.util.BitSet;
6    import java.util.HashMap;
7    import java.util.LinkedHashMap;
8    import java.util.LinkedList;
9    import java.util.List;
10   
11    import javax.swing.JInternalFrame;
12    import javax.swing.SwingUtilities;
13   
14    import jalview.bin.Cache;
15    import jalview.bin.Console;
16    import jalview.datamodel.Alignment;
17    import jalview.datamodel.AlignmentI;
18    import jalview.datamodel.AlignmentOrder;
19    import jalview.datamodel.HiddenColumns;
20    import jalview.gui.AlignFrame;
21    import jalview.gui.Desktop;
22    import jalview.gui.JvOptionPane;
23    import jalview.gui.SplitFrame;
24    import jalview.gui.WebserviceInfo;
25    import jalview.util.ArrayUtils;
26    import jalview.util.MessageManager;
27    import jalview.util.Pair;
28    import jalview.ws2.actions.alignment.AlignmentAction;
29    import jalview.ws2.actions.alignment.AlignmentResult;
30    import jalview.ws2.actions.api.JobI;
31    import jalview.ws2.actions.api.TaskEventListener;
32    import jalview.ws2.actions.api.TaskI;
33    import jalview.ws2.api.JobStatus;
34    import jalview.ws2.api.WebService;
35    import jalview.ws2.helpers.WSClientTaskWrapper;
36   
 
37    class AlignmentServiceGuiHandler
38    implements TaskEventListener<AlignmentResult>
39    {
40    private final WebService<?> service;
41   
42    private final AlignFrame frame;
43   
44    private WebserviceInfo infoPanel;
45   
46    private String alnTitle; // title of the alignment used in new window
47   
48    private JobI[] jobs = new JobI[0];
49   
50    private int[] tabs = new int[0];
51   
52    private int[] logOffset = new int[0];
53   
54    private int[] errLogOffset = new int[0];
55   
 
56  0 toggle public AlignmentServiceGuiHandler(AlignmentAction action, AlignFrame frame)
57    {
58  0 this.service = action.getWebService();
59  0 this.frame = frame;
60  0 String panelInfo = String.format("%s using service hosted at %s%n%s",
61    service.getName(), service.getUrl(), service.getDescription());
62  0 infoPanel = new WebserviceInfo(service.getName(), panelInfo, false);
63  0 String actionName = action.getName() != null ? action.getName() : "Alignment";
64  0 alnTitle = String.format("%s %s of %s", service.getName(), actionName,
65    frame.getTitle());
66    }
67   
 
68  0 toggle @Override
69    public void taskStatusChanged(TaskI<AlignmentResult> source, JobStatus status)
70    {
71  0 switch (status)
72    {
73  0 case INVALID:
74  0 infoPanel.setVisible(false);
75  0 JvOptionPane.showMessageDialog(frame,
76    MessageManager.getString("info.invalid_msa_input_mininfo"),
77    MessageManager.getString("info.invalid_msa_notenough"),
78    JvOptionPane.INFORMATION_MESSAGE);
79  0 break;
80  0 case READY:
81  0 infoPanel.setthisService(new WSClientTaskWrapper(source));
82  0 infoPanel.setVisible(true);
83    // intentional no break
84  0 case SUBMITTED:
85  0 case QUEUED:
86  0 infoPanel.setStatus(WebserviceInfo.STATE_QUEUING);
87  0 break;
88  0 case RUNNING:
89  0 case UNKNOWN: // unsure what to do with unknown
90  0 infoPanel.setStatus(WebserviceInfo.STATE_RUNNING);
91  0 break;
92  0 case COMPLETED:
93  0 infoPanel.setProgressBar(
94    MessageManager.getString("status.collecting_job_results"),
95    jobs[0].getInternalId());
96  0 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_OK);
97  0 break;
98  0 case FAILED:
99  0 infoPanel.removeProgressBar(jobs[0].getInternalId());
100  0 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
101  0 break;
102  0 case CANCELLED:
103  0 infoPanel.setStatus(WebserviceInfo.STATE_CANCELLED_OK);
104  0 break;
105  0 case SERVER_ERROR:
106  0 infoPanel.removeProgressBar(jobs[0].getInternalId());
107  0 infoPanel.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
108  0 break;
109    }
110    }
111   
 
112  0 toggle @Override
113    public void taskStarted(TaskI<AlignmentResult> source, List<? extends JobI> subJobs)
114    {
115  0 jobs = subJobs.toArray(new JobI[0]);
116  0 tabs = new int[subJobs.size()];
117  0 logOffset = new int[subJobs.size()];
118  0 errLogOffset = new int[subJobs.size()];
119  0 for (int i = 0; i < subJobs.size(); i++)
120    {
121  0 JobI job = jobs[i];
122  0 int tabIndex = infoPanel.addJobPane();
123  0 tabs[i] = tabIndex;
124  0 infoPanel.setProgressName(String.format("region %d", i), tabIndex);
125  0 infoPanel.setProgressText(tabIndex, alnTitle + "\nJob details\n");
126    // jobs should not have states other than invalid or ready at this point
127  0 if (job.getStatus() == JobStatus.INVALID)
128  0 infoPanel.setStatus(tabIndex, WebserviceInfo.STATE_STOPPED_OK);
129  0 else if (job.getStatus() == JobStatus.READY)
130  0 infoPanel.setStatus(tabIndex, WebserviceInfo.STATE_QUEUING);
131    }
132    }
133   
 
134  0 toggle @Override
135    public void taskCompleted(TaskI<AlignmentResult> source, AlignmentResult result)
136    {
137  0 SwingUtilities.invokeLater(() -> infoPanel.removeProgressBar(jobs[0].getInternalId()));
138  0 if (result == null)
139    {
140  0 SwingUtilities.invokeLater(infoPanel::setFinishedNoResults);
141  0 return;
142    }
143  0 infoPanel.showResultsNewFrame.addActionListener(evt -> {
144  0 var aln = result.getAlignment();
145    // copy alignment for each frame to have its own isntance
146  0 var alnCpy = new Alignment(aln);
147  0 alnCpy.setGapCharacter(aln.getGapCharacter());
148  0 alnCpy.setDataset(aln.getDataset());
149  0 displayResultsNewFrame(alnCpy, result.getAlignmentOrders(),
150    result.getHiddenColumns());
151    });
152  0 SwingUtilities.invokeLater(infoPanel::setResultsReady);
153    }
154   
 
155  0 toggle private void displayResultsNewFrame(Alignment aln,
156    List<AlignmentOrder> alorders, HiddenColumns hidden)
157    {
158  0 AlignFrame newFrame = new AlignFrame(aln, hidden, AlignFrame.DEFAULT_WIDTH,
159    AlignFrame.DEFAULT_HEIGHT);
160  0 newFrame.getFeatureRenderer().transferSettings(
161    frame.getFeatureRenderer().getSettings());
162  0 if (alorders.size() > 0)
163    {
164  0 addSortByMenuItems(newFrame, alorders);
165    }
166   
167  0 var requestingFrame = frame;
168  0 var splitContainer = requestingFrame.getSplitViewContainer();
169  0 if (splitContainer != null && splitContainer.getComplement(requestingFrame) != null)
170    {
171  0 AlignmentI complement = splitContainer.getComplement(requestingFrame);
172  0 String complementTitle = splitContainer.getComplementTitle(requestingFrame);
173  0 Alignment copyComplement = new Alignment(complement);
174  0 copyComplement.setGapCharacter(complement.getGapCharacter());
175  0 copyComplement.setDataset(complement.getDataset());
176  0 copyComplement.alignAs(aln);
177  0 if (copyComplement.getHeight() > 0)
178    {
179  0 newFrame.setTitle(alnTitle);
180  0 AlignFrame newFrame2 = new AlignFrame(copyComplement,
181    AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
182  0 newFrame2.setTitle(complementTitle);
183  0 String linkedTitle = MessageManager.getString("label.linked_view_title");
184  0 JInternalFrame splitFrame = new SplitFrame(
185  0 aln.isNucleotide() ? newFrame : newFrame2,
186  0 aln.isNucleotide() ? newFrame2 : newFrame);
187  0 Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
188  0 return;
189    }
190    }
191    // no split frame or failed to create complementary alignment
192  0 Desktop.addInternalFrame(newFrame, alnTitle, AlignFrame.DEFAULT_WIDTH,
193    AlignFrame.DEFAULT_HEIGHT);
194    }
195   
 
196  0 toggle private void addSortByMenuItems(AlignFrame frame, List<AlignmentOrder> alorders)
197    {
198  0 if (alorders.size() == 1)
199    {
200  0 frame.addSortByOrderMenuItem(service.getName() + " Ordering",
201    alorders.get(0));
202  0 return;
203    }
204  0 BitSet collected = new BitSet(alorders.size());
205  0 for (int i = 0, N = alorders.size(); i < N; i++)
206    {
207  0 if (collected.get(i))
208  0 continue;
209  0 var regions = new ArrayList<String>();
210  0 var order = alorders.get(i);
211  0 for (int j = i; j < N; j++)
212    {
213  0 if (!collected.get(j) && alorders.get(j).equals(order))
214    {
215  0 regions.add(Integer.toString(j + 1));
216  0 collected.set(j);
217    }
218    }
219  0 var orderName = String.format("%s Region %s Ordering",
220    service.getName(), String.join(",", regions));
221  0 frame.addSortByOrderMenuItem(orderName, order);
222    }
223    }
224   
 
225  0 toggle @Override
226    public void taskException(TaskI<AlignmentResult> source, Exception e)
227    {
228  0 Console.error(String.format("Service %s raised an exception.", service.getName()), e);
229  0 infoPanel.appendProgressText(e.getMessage());
230    }
231   
 
232  0 toggle @Override
233    public void subJobStatusChanged(TaskI<AlignmentResult> source, JobI job, JobStatus status)
234    {
235  0 int i = ArrayUtils.indexOf(jobs, job);
236  0 assert i >= 0 : "job does not exist";
237  0 if (i < 0)
238    // safeguard that should not happen irl
239  0 return;
240  0 int wsStatus;
241  0 switch (status)
242    {
243  0 case INVALID:
244  0 case COMPLETED:
245  0 wsStatus = WebserviceInfo.STATE_STOPPED_OK;
246  0 break;
247  0 case READY:
248  0 case SUBMITTED:
249  0 case QUEUED:
250  0 wsStatus = WebserviceInfo.STATE_QUEUING;
251  0 break;
252  0 case RUNNING:
253  0 case UNKNOWN:
254  0 wsStatus = WebserviceInfo.STATE_RUNNING;
255  0 break;
256  0 case FAILED:
257  0 wsStatus = WebserviceInfo.STATE_STOPPED_ERROR;
258  0 break;
259  0 case CANCELLED:
260  0 wsStatus = WebserviceInfo.STATE_CANCELLED_OK;
261  0 break;
262  0 case SERVER_ERROR:
263  0 wsStatus = WebserviceInfo.STATE_STOPPED_SERVERERROR;
264  0 break;
265  0 default:
266  0 throw new AssertionError("Non-exhaustive switch statement");
267    }
268  0 infoPanel.setStatus(tabs[i], wsStatus);
269    }
270   
 
271  0 toggle @Override
272    public void subJobLogChanged(TaskI<AlignmentResult> source, JobI job, String log)
273    {
274  0 int i = ArrayUtils.indexOf(jobs, job);
275  0 assert i >= 0 : "job does not exist";
276  0 if (i < 0)
277    // safeguard that should never happen
278  0 return;
279  0 infoPanel.appendProgressText(tabs[i], log.substring(logOffset[i]));
280    }
281   
 
282  0 toggle @Override
283    public void subJobErrorLogChanged(TaskI<AlignmentResult> source, JobI job, String log)
284    {
285  0 int i = ArrayUtils.indexOf(jobs, job);
286  0 assert i >= 0 : "job does not exist";
287  0 if (i < 0)
288    // safeguard that should never happen
289  0 return;
290  0 infoPanel.appendProgressText(tabs[i], log.substring(errLogOffset[i]));
291    }
292   
293    }