JAL-3878 Add jpred operation and worker to the services.
[jalview.git] / src / jalview / ws2 / gui / JPredMenuBuilder.java
1 package jalview.ws2.gui;
2
3 import static java.lang.String.format;
4
5 import java.util.Objects;
6 import java.util.function.Consumer;
7
8 import javax.swing.JMenu;
9 import javax.swing.JMenuItem;
10
11 import jalview.datamodel.Alignment;
12 import jalview.gui.AlignFrame;
13 import jalview.gui.Desktop;
14 import jalview.gui.WebserviceInfo;
15 import jalview.util.MessageManager;
16 import jalview.ws2.WSJob;
17 import jalview.ws2.operations.JPredOperation;
18 import jalview.ws2.operations.JPredWorker;
19 import jalview.ws2.operations.WebServiceWorkerI;
20 import jalview.ws2.operations.WebServiceWorkerListener;
21 import jalview.ws2.operations.JPredWorker.PredictionResult;
22
23 public class JPredMenuBuilder implements MenuEntryProviderI
24 {
25   private JPredOperation operation;
26
27   public JPredMenuBuilder(JPredOperation operation)
28   {
29     this.operation = operation;
30   }
31
32   public void buildMenu(JMenu menu, AlignFrame frame)
33   {
34     final JMenuItem mi = new JMenuItem(operation.getName());
35     mi.setToolTipText(operation.getHostName());
36     mi.addActionListener((event) -> {
37       String panelInfo = String.format("%s using service hosted at %s%n%s",
38           operation.getName(), operation.getHostName(),
39           Objects.requireNonNullElse(operation.getDescription(), ""));
40       var wsInfo = new WebserviceInfo(operation.getName(), panelInfo, false);
41
42       var alignView = frame.gatherSeqOrMsaForSecStrPrediction();
43       var worker = new JPredWorker(operation, alignView,
44           frame.getCurrentView());
45
46       var jpu = new JPredProgressUpdater(worker, wsInfo, frame);
47       worker.setResultConsumer(jpu);
48       worker.addListener(jpu);
49
50       frame.getViewport().getWSExecutor().submit(worker);
51     });
52     menu.add(mi);
53   }
54 }
55
56 class JPredProgressUpdater
57     implements WebServiceWorkerListener, Consumer<PredictionResult>
58 {
59   WebServiceWorkerI worker;
60
61   WebserviceInfo wsInfo;
62
63   AlignFrame frame;
64
65   private final WebServiceInfoUpdater wsInfoUpdater;
66
67   JPredProgressUpdater(WebServiceWorkerI worker, WebserviceInfo wsInfo,
68       AlignFrame frame)
69   {
70     this.worker = worker;
71     this.wsInfo = wsInfo;
72     this.frame = frame;
73     this.wsInfoUpdater = new WebServiceInfoUpdater(worker, wsInfo);
74   }
75
76   @Override
77   public void workerStarted(WebServiceWorkerI source)
78   {
79     wsInfo.setVisible(true);
80   }
81
82   @Override
83   public void workerNotStarted(WebServiceWorkerI source)
84   {
85     wsInfo.setVisible(true);
86     wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
87     wsInfo.setStatus(0, WebserviceInfo.STATE_STOPPED_SERVERERROR);
88     wsInfo.appendProgressText(0, MessageManager.getString(
89         "info.failed_to_submit_sequences_for_alignment"));
90   }
91
92   @Override
93   public void jobCreated(WebServiceWorkerI source, WSJob job)
94   {
95     wsInfo.addJobPane();
96     job.addPropertyChangeListener(wsInfoUpdater);
97   }
98
99   @Override
100   public void pollException(WebServiceWorkerI source, WSJob job, Exception e)
101   {
102     wsInfo.appendProgressText(job.getJobNum(),
103         MessageManager.formatMessage("info.server_exception",
104             source.getOperation().getName(), e.getMessage()));
105   }
106
107   @Override
108   public void workerCompleting(WebServiceWorkerI source)
109   {
110     wsInfo.setProgressBar(
111         MessageManager.getString("status.collecting_job_results"),
112         worker.getUID());
113   }
114
115   @Override
116   public void workerCompleted(WebServiceWorkerI source)
117   {
118     wsInfo.removeProgressBar(worker.getUID());
119   }
120
121   @Override
122   public void accept(PredictionResult result)
123   {
124     if (result != null)
125     {
126       wsInfo.showResultsNewFrame.addActionListener(
127           (evt) -> displayResults(result, true));
128       wsInfo.mergeResults.addActionListener(
129           (evt) -> displayResults(result, false));
130       wsInfo.setResultsReady();
131     }
132     else
133     {
134       wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
135       wsInfo.appendInfoText("No jobs ran.");
136       wsInfo.setFinishedNoResults();
137     }
138   }
139
140   private void displayResults(PredictionResult result, boolean newWindow)
141   {
142     if (newWindow)
143     {
144       Alignment alignment = new Alignment(result.getAlignment());
145       alignment.setSeqrep(alignment.getSequenceAt(0));
146       for (var annotation : result.getAlignment().getAlignmentAnnotation())
147       {
148         alignment.addAnnotation(annotation);
149       }
150       AlignFrame frame = new AlignFrame(alignment, result.getHiddenCols(),
151           AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
152       Desktop.addInternalFrame(frame, frame.getTitle(), AlignFrame.DEFAULT_WIDTH,
153           AlignFrame.DEFAULT_HEIGHT);
154     }
155   }
156
157 }