37add58a045d6fa7bf01e5b3786874056ab272cd
[jalview.git] / src / jalview / ws / rest / RestClient.java
1 /**
2  * 
3  */
4 package jalview.ws.rest;
5
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8 import java.util.Hashtable;
9
10 import javax.swing.JMenu;
11 import javax.swing.JMenuItem;
12 import javax.swing.JOptionPane;
13 import javax.swing.event.MenuEvent;
14 import javax.swing.event.MenuListener;
15
16 import jalview.datamodel.AlignmentView;
17 import jalview.gui.AlignFrame;
18 import jalview.gui.AlignViewport;
19 import jalview.gui.AlignmentPanel;
20 import jalview.gui.Desktop;
21 import jalview.gui.WebserviceInfo;
22 import jalview.io.packed.DataProvider.JvDataType;
23 import jalview.ws.WSClient;
24 import jalview.ws.WSClientI;
25 import jalview.ws.WSMenuEntryProviderI;
26
27 /**
28  * @author JimP
29  * 
30  */
31 public class RestClient extends WSClient implements WSClientI,
32         WSMenuEntryProviderI
33 {
34   RestServiceDescription service;
35
36   public RestClient(RestServiceDescription rsd)
37   {
38     service = rsd;
39   }
40
41   /**
42    * parent alignframe for this job
43    */
44   AlignFrame af;
45
46   /**
47    * alignment view which provides data for job.
48    */
49   AlignViewport av;
50
51   /**
52    * get the alignFrame for the associated input data if it exists.
53    * 
54    * @return
55    */
56   protected AlignFrame recoverAlignFrameForView()
57   {
58     return jalview.gui.Desktop.getAlignFrameFor(av);
59   }
60
61   public RestClient(RestServiceDescription service2, AlignFrame alignFrame)
62   {
63     service = service2;
64     af = alignFrame;
65     av = alignFrame.getViewport();
66     constructJob();
67   }
68
69   public void setWebserviceInfo(boolean headless)
70   {
71     WebServiceJobTitle = service.details.Action + " using "
72             + service.details.Name;
73     WebServiceName = service.details.Name;
74     WebServiceReference = "No reference - go to url for more info";
75     if (service.details.description != null)
76     {
77       WebServiceReference = service.details.description;
78     }
79     if (!headless)
80     {
81       wsInfo = new WebserviceInfo(WebServiceJobTitle, WebServiceName + "\n"
82               + WebServiceReference);
83       wsInfo.setRenderAsHtml(true);
84     }
85
86   }
87
88   @Override
89   public boolean isCancellable()
90   {
91     // TODO define process for cancelling rsbws jobs
92     return false;
93   }
94
95   @Override
96   public boolean canMergeResults()
97   {
98     // TODO process service definition to identify if the results might be
99     // mergeable
100     // TODO: change comparison for annotation merge
101     return false;
102   }
103
104   @Override
105   public void cancelJob()
106   {
107     System.err.println("Cannot cancel this job type: " + service);
108   }
109
110   @Override
111   public void attachWSMenuEntry(final JMenu wsmenu,
112           final AlignFrame alignFrame)
113   {
114     JMenuItem submit = new JMenuItem(service.details.Name);
115     submit.setToolTipText(service.details.Action+" using "+service.details.Name);
116     submit.addActionListener(new ActionListener()
117     {
118
119       @Override
120       public void actionPerformed(ActionEvent e)
121       {
122         new RestClient(service, alignFrame);
123       }
124
125     });
126     wsmenu.add(submit);
127     // TODO: menu listener should enable/disable entry depending upon selection
128     // state of the alignment
129     wsmenu.addMenuListener(new MenuListener()
130     {
131
132       @Override
133       public void menuSelected(MenuEvent e)
134       {
135         // TODO Auto-generated method stub
136
137       }
138
139       @Override
140       public void menuDeselected(MenuEvent e)
141       {
142         // TODO Auto-generated method stub
143
144       }
145
146       @Override
147       public void menuCanceled(MenuEvent e)
148       {
149         // TODO Auto-generated method stub
150
151       }
152
153     });
154
155   }
156
157   /**
158    * record of initial undoredo hash for the alignFrame providing data for this
159    * job.
160    */
161   long[] undoredo = null;
162
163   /**
164    * Compare the original input data to the data currently presented to the
165    * user. // LOGIC: compare undo/redo - if same, merge regardless (coping with
166    * any changes in hidden columns as normal) // if different undo/redo then
167    * compare region that was submitted // if same, then merge as before, if
168    * different then prompt user to open a new window.
169    * 
170    * @return
171    */
172   protected boolean isAlignmentModified()
173   {
174     if (undoredo == null || av==null || av.getAlignment()==null)
175     {
176       // always return modified if we don't have access to live GUI elements anymore.
177       return true;
178     }
179     if (av.isUndoRedoHashModified(undoredo))
180     {
181       // alignment has been modified in some way. 
182       return true;
183     }
184     // TODO: look deeper into modification of selection state, etc that may affect RestJobThread.realiseResults(boolean merge); 
185     return false;
186
187   }
188
189   /**
190    * TODO: combine to form a dataset+alignment+annotation context
191    */
192   AlignmentView _input;
193
194   /**
195    * input data context
196    */
197   jalview.io.packed.JalviewDataset jds;
198
199   protected void constructJob()
200   {
201     service.setInvolvesFlags();
202     
203     // record all aspects of alignment view so we can merge back or recreate
204     // later
205     undoredo = av.getUndoRedoHash();
206     /**
207      * delete ? Vector sgs = av.getAlignment().getGroups(); if (sgs!=null) {
208      * _sgs = new SequenceGroup[sgs.size()]; sgs.copyInto(_sgs); } else { _sgs =
209      * new SequenceGroup[0]; }
210      */
211     boolean selExists = (av.getSelectionGroup() != null)
212             && (av.getSelectionGroup().getSize() > 1);
213     // TODO: revise to full focus+context+dataset input data staging model
214     if (selExists)
215     {
216       if (service.partitiondata)
217       {
218         if (av.getAlignment().getGroups()!=null && av.getAlignment().getGroups().size() > 0)
219         {
220           // intersect groups with selected region
221           _input = new AlignmentView(av.getAlignment(), 
222                   av.getColumnSelection(), 
223                   av.getSelectionGroup(), 
224                   av.hasHiddenColumns(), 
225                   true, 
226                   true);
227         }
228         else
229         {
230           // use selected region to partition alignment
231           _input = new AlignmentView(av.getAlignment(), 
232                   av.getColumnSelection(), 
233                   av.getSelectionGroup(), 
234                   av.hasHiddenColumns(), 
235                   false, 
236                   true);
237         }
238         // TODO: verify that some kind of partition can be constructed from input
239       }
240       else
241       {
242         // just take selected region intersection
243         _input = new AlignmentView(av.getAlignment(), 
244                 av.getColumnSelection(), 
245                 av.getSelectionGroup(), 
246                 av.hasHiddenColumns(), 
247                 true, 
248                 true);
249       }
250     } else {
251       // standard alignment view without selection present
252       _input = new AlignmentView(av.getAlignment(), 
253               av.getColumnSelection(), 
254               null, 
255               av.hasHiddenColumns(), 
256               false, 
257               true);
258     }
259     
260     RestJobThread jobsthread = new RestJobThread(this);
261     
262     if (jobsthread.isValid())
263     {
264       setWebserviceInfo(false);
265       wsInfo.setthisService(this);
266       jobsthread.setWebServiceInfo(wsInfo);
267       jobsthread.start();
268     }
269     else
270     {
271       // TODO: try to tell the user why the job couldn't be started.
272       JOptionPane.showMessageDialog(Desktop.desktop,
273               "Unable to start web service analysis",
274               "Internal Jalview Error", JOptionPane.WARNING_MESSAGE);
275     }
276   }
277
278   public static RestClient makeShmmrRestClient()
279   {
280     String action = "Analyse", description = "Sequence Harmony and Multi-Relief (UNSTABLE!)", name = "Sequence Harmony";
281     Hashtable<String, InputType> iparams = new Hashtable<String, InputType>();
282     jalview.ws.rest.params.JobConstant toolp;
283     //toolp = new jalview.ws.rest.JobConstant("tool","jalview");
284     //iparams.put(toolp.token, toolp);
285     toolp = new jalview.ws.rest.params.JobConstant("mbjob[method]","shmr");
286     iparams.put(toolp.token, toolp);
287     toolp = new jalview.ws.rest.params.JobConstant("mbjob[description]","step 1");
288     iparams.put(toolp.token, toolp);
289     toolp = new jalview.ws.rest.params.JobConstant("start_search","1");
290     iparams.put(toolp.token, toolp);
291     toolp = new jalview.ws.rest.params.JobConstant("blast","0");
292     iparams.put(toolp.token, toolp);
293     
294     jalview.ws.rest.params.Alignment aliinput = new jalview.ws.rest.params.Alignment();
295     aliinput.token = "ali";//_file";
296     aliinput.writeAsFile=false;//true;
297     //aliinput.token = "ali_file";
298     //aliinput.writeAsFile=true;
299     iparams.put(aliinput.token, aliinput);
300     jalview.ws.rest.params.SeqGroupIndexVector sgroups = new jalview.ws.rest.params.SeqGroupIndexVector();
301     sgroups.minsize=2;
302     iparams.put("groups", sgroups);
303     sgroups.token = "groups";
304     sgroups.sep = " ";
305     RestServiceDescription shmrService = new RestServiceDescription(
306             action,
307             description,
308             name,
309             "http://www.ibi.vu.nl/programs/shmrwww/index.php?tool=jalview",// ?tool=jalview&mbjob[method]=shmr&mbjob[description]=step1",
310             "?tool=jalview", iparams, true, false, '-');
311     // a priori knowledge of the data returned from the service
312     shmrService.addResultDatatype(JvDataType.ANNOTATION);
313     return new RestClient(shmrService);
314   }
315
316   public AlignmentPanel recoverAlignPanelForView()
317   {
318     AlignmentPanel[] aps = Desktop.getAlignmentPanels(av.getSequenceSetId());
319     for (AlignmentPanel alp:aps)
320     {
321       if (alp.av == av)
322       {
323         return alp;
324       }
325     }
326     return null;
327   }
328
329   public boolean isShowResultsInNewView()
330   {
331     // TODO make this a property of the service
332     return true;
333   }
334
335 }