5174b7aee84551937fc3adb1f29b0576be7a96b1
[jalview.git] / src / jalview / gui / RestServiceEditorPane.java
1 package jalview.gui;
2
3 import jalview.io.packed.DataProvider.JvDataType;
4 import jalview.jbgui.GRestServiceEditorPane;
5 import jalview.ws.rest.InputType;
6 import jalview.ws.rest.RestServiceDescription;
7
8 import java.awt.BorderLayout;
9 import java.awt.FlowLayout;
10 import java.awt.event.ActionEvent;
11 import java.awt.event.ActionListener;
12 import java.awt.event.ComponentEvent;
13 import java.awt.event.ComponentListener;
14 import java.awt.event.KeyEvent;
15 import java.awt.event.KeyListener;
16 import java.awt.event.MouseEvent;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Vector;
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23
24 import javax.swing.JFrame;
25 import javax.swing.JMenuItem;
26 import javax.swing.JPanel;
27 import javax.swing.JPopupMenu;
28 import javax.swing.event.ChangeEvent;
29 import javax.swing.event.ChangeListener;
30
31 public class RestServiceEditorPane extends GRestServiceEditorPane
32 {
33   /**
34    * the latest version of the service definition.
35    */
36   jalview.ws.rest.RestServiceDescription currentservice = null;
37
38   /**
39    * original service passed to editor if we are modifying an existing service
40    * definition
41    */
42   jalview.ws.rest.RestServiceDescription oldservice = null;
43
44   public RestServiceEditorPane()
45   {
46     super();
47     // begin with initial text description box enabled.
48     urldesc.addKeyListener(new KeyListener()
49     {
50       @Override
51       public void keyTyped(KeyEvent e)
52       {
53       }
54       
55       @Override
56       public void keyReleased(KeyEvent e)
57       {
58         refreshCutnPaste(true);        
59       }
60       
61       @Override
62       public void keyPressed(KeyEvent e)
63       {
64         
65       }
66     });
67     panels.addChangeListener(new ChangeListener()
68     {
69
70       /**
71        * last panel selected - used to decide whether the service or the GUI has the latest info
72        */
73       Object lastComp;
74       @Override
75       public void stateChanged(ChangeEvent e)
76       {
77         if (lastComp!=paste) {
78           updateServiceFromGui();
79           refreshCutnPaste(false);
80         } else {
81           refreshCutnPaste(true);
82         }
83         lastComp = panels.getSelectedComponent();
84         
85       }
86       });
87     currentservice = new RestServiceDescription("Analysis", "service description", "service name", "http://localhost/", "", null, false, false, '-');
88     initGuiWith(currentservice);
89     refreshCutnPaste(false);
90     updateButtons();
91   }
92
93   public RestServiceEditorPane(RestServiceDescription toedit)
94   {
95     this();
96     oldservice = toedit;
97     if (oldservice!=null)
98     {    currentservice = new RestServiceDescription(toedit);
99     } else {
100       currentservice = new RestServiceDescription("Analysis", "service description", "service name", "http://localhost/", "", null, false, false, '-');
101     }
102     initGuiWith(currentservice);
103     refreshCutnPaste(false);
104     updateButtons();
105   }
106
107   /**
108    * refresh the buttons based on model state
109    */
110   public void updateButtons()
111   {
112     cancelButton.setEnabled(true);
113     okButton.setEnabled(currentservice != null && currentservice.isValid());
114
115   }
116
117   Vector<String> _iparam = new Vector<String>();
118
119   Vector<String> _rparam = new Vector<String>();
120
121   /**
122    * generate an editable URL service string and parameter list using the
123    * service
124    * 
125    * @param currentservice2
126    */
127   private void initGuiWith(RestServiceDescription currentservice)
128   {
129     _iparam.clear();
130     _rparam.clear();
131     action.removeAllItems();
132     action.addItem("Alignment");
133     action.addItem("Analysis");
134     gapChar.removeAllItems();
135     gapChar.addItem(".");
136     gapChar.addItem(" ");
137     gapChar.addItem("-");
138     if (currentservice==null)
139     {
140       name.setText("");
141       descr.setText("");
142       url.setText("");
143       urlsuff.setText("");
144       action.setSelectedItem("Analysis");
145       gapChar.setSelectedItem("-");
146     } else {
147     name.setText(currentservice.getName());
148     descr.setText(currentservice.getDescription());
149     url.setText(currentservice.getPostUrl());
150     urlsuff.setText(currentservice.getUrlSuffix());
151     for (Map.Entry<String, InputType> inparam : currentservice
152             .getInputParams().entrySet())
153     {
154       _iparam.add(inparam.getKey() + " "
155               + inparam.getValue().getURLtokenPrefix() + ":"
156               + inparam.getValue().getURLEncodedParameter().toString());
157     }
158       
159     for (JvDataType oparam : currentservice.getResultDataTypes())
160     {
161       _rparam.add(oparam.name());
162     }
163     iprms.setListData(_iparam);
164     rdata.setListData(_rparam);
165
166     action.setSelectedItem(currentservice.getAction());
167
168     gapChar.setSelectedItem(""+currentservice.getGapCharacter());
169     }
170     revalidate();
171   }
172   private String getSelectedInputToken()
173   {
174     if (iprms.getSelectedIndex()>-1)
175     {
176     String toktoedit = (String) iprms.getSelectedValue();
177     toktoedit=toktoedit.substring(0, toktoedit.indexOf(" "));
178     return toktoedit;
179     }
180     return null;
181   }
182   @Override
183   protected void iprmListSelection_doubleClicked()
184   {
185     String toktoedit = getSelectedInputToken();
186     if (toktoedit!=null)
187     {
188       InputType toedit = currentservice.getInputParams().get(toktoedit);
189       String oldParam=toktoedit;
190       RestInputParamEditDialog dialog=new RestInputParamEditDialog(this, currentservice, toedit);
191       if (dialog.wasUpdated()) {
192         currentservice.getInputParams().remove(oldParam);
193         currentservice.getInputParams().put(dialog.current.token, dialog.current);
194         initGuiWith(currentservice);
195       }
196       
197     }
198   }
199   @Override
200   protected void iprmsAdd_actionPerformed(ActionEvent e)
201   {
202     RestInputParamEditDialog dialog=new RestInputParamEditDialog(this, currentservice, "param"+(1+currentservice.getInputParams().size()));
203     if (dialog.wasUpdated()) {
204       currentservice.getInputParams().put(dialog.current.token, dialog.current);
205       initGuiWith(currentservice);
206     }
207
208   }
209   @Override
210   protected void iprmsRem_actionPerformed(ActionEvent e)
211   {
212     String toktoedit = getSelectedInputToken();
213     if (toktoedit!=null)
214     {
215       currentservice.getInputParams().remove(toktoedit);
216       initGuiWith(currentservice);
217
218     }
219   }
220   @Override
221   protected void rdata_rightClicked(MouseEvent mouse)
222   {
223     final int rdatasel = rdata.getSelectedIndex();
224     if (rdatasel>-1)
225     {
226       JPopupMenu popup = new JPopupMenu("Select return type");
227       for (final JvDataType type:JvDataType.values()) {
228         popup.add(new JMenuItem(type.name())).addActionListener(new ActionListener()
229         {
230           
231           @Override
232           public void actionPerformed(ActionEvent e)
233           {
234             currentservice.getResultDataTypes().set(rdatasel, type);
235             initGuiWith(currentservice);   
236             rdata.setSelectedIndex(rdatasel);
237           }
238         });
239       }
240       popup.show(rdata, mouse.getX(), mouse.getY());
241     }
242   }
243   @Override
244   protected void rdataAdd_actionPerformed(ActionEvent e)
245   {
246     int p;
247     if ((p=rdata.getSelectedIndex())>-1)
248     {
249       currentservice.getResultDataTypes().add(p+1, JvDataType.ANNOTATION);
250     } else {
251       currentservice.addResultDatatype(JvDataType.ANNOTATION);
252     }
253     initGuiWith(currentservice);
254     rdata.setSelectedIndex(p==-1 ? currentservice.getResultDataTypes().size()-1 : p+1);
255   }
256   @Override
257   protected void rdataNdown_actionPerformed(ActionEvent e)
258   {
259     int p;
260     if ((p=rdata.getSelectedIndex())>-1 && p<_rparam.size()-1)
261     {
262       List<JvDataType> rtypes = currentservice.getResultDataTypes();
263       JvDataType below = rtypes.get(p+1);
264       rtypes.set(p+1, rtypes.get(p));
265       rtypes.set(p, below);
266       initGuiWith(currentservice);
267       rdata.setSelectedIndex(p+1);
268     }
269   }
270   @Override
271   protected void rdataNup_actionPerformed(ActionEvent e)
272   {
273     int p;
274     if ((p=rdata.getSelectedIndex())>0)
275     {
276       List<JvDataType> rtypes = currentservice.getResultDataTypes();
277       JvDataType above = rtypes.get(p-1);
278       rtypes.set(p-1, rtypes.get(p));
279       rtypes.set(p, above);
280       initGuiWith(currentservice);
281       rdata.setSelectedIndex(p-1);
282     }
283   }
284   @Override
285   protected void rdataRem_actionPerformed(ActionEvent e)
286   {
287     if (rdata.getSelectedIndex()>-1)
288     {
289       currentservice.getResultDataTypes().remove(rdata.getSelectedIndex());
290       initGuiWith(currentservice);
291     }
292   }
293
294   private boolean updateServiceFromGui() {
295     Map<String,InputType>inputTypes = new HashMap<String, InputType>();
296     StringBuffer warnings=new StringBuffer();
297     for (String its:_iparam)
298     {
299       Matcher mtch = Pattern.compile("(\\S+)\\s(\\S+):\\[(.+)]").matcher(its);
300       if (mtch.find()) {
301         if (!RestServiceDescription.parseTypeString(mtch.group(2)+":"+mtch.group(3), mtch.group(1), mtch.group(2),mtch.group(3), inputTypes, warnings))
302         {
303           System.err.println("IMPLEMENTATION PROBLEM: Cannot parse RestService input parameter string '"+its+"'"+"\n"+warnings);
304         }        
305       }
306     }
307     char gc = gapChar.getSelectedItem()==null ? ' ' : ((String)gapChar.getSelectedItem()).charAt(0);
308     RestServiceDescription newService = new RestServiceDescription((String) action.getSelectedItem(),
309           descr.getText().trim(), name.getText().trim(), url.getText().trim(), urlsuff.getText().trim(), inputTypes, hSeparable.isSelected(), vSeparable.isSelected(), gc);
310             
311     if (newService.isValid())
312     {
313       for (String its:_rparam)
314       {
315         JvDataType dtype;
316         try {
317           dtype = JvDataType.valueOf(its);
318           newService.addResultDatatype(dtype);
319         }
320         catch (Throwable x)
321         {
322
323           System.err.println("IMPLEMENTATION PROBLEM: Cannot parse RestService output parameter string '"+its+"'"+"\n"+warnings);
324         }
325       }
326       currentservice = newService;
327       return true;
328     } else {
329       System.err.println("IMPLEMENTATION PROBLEM: Restservice generated from GUI is invalid\n"+warnings);
330
331     }
332     return false;
333   }
334   protected void refreshCutnPaste(boolean reparse)
335   {
336     if (!reparse && currentservice.isValid())
337     {
338       urldesc.setText(currentservice.toString());
339       parseWarnings.setVisible(false);
340     }
341     else
342     {
343       if (reparse)
344       {
345         String txt = urldesc.getText().trim();
346         if (txt.length() > 0)
347         {
348           RestServiceDescription rsd = null;
349           try
350           {
351             rsd = new RestServiceDescription(txt);
352             if (rsd.isValid())
353             {
354               parseWarnings.setVisible(false);
355               parseRes.setText("");
356               initGuiWith(currentservice=rsd);
357             }
358             else
359             {
360               parseRes.setText("Parsing failed. Syntax errors shown below\n"
361                       + rsd.getInvalidMessage());
362               parseWarnings.setVisible(true);
363             }
364           } catch (Throwable e)
365           {
366             e.printStackTrace();
367             parseRes.setText("\nParsing failed. An unrecoverable exception was thrown:\n"
368                     + e.toString());
369             parseWarnings.setVisible(true);
370           }
371         }
372         paste.revalidate();
373       }
374     }
375     
376   }
377
378   public static void main(String[] args)
379   {
380     if (args.length == 0)
381     {
382       new Thread(new Runnable()
383       {
384         boolean visible = true;
385
386         public void run()
387         {
388           boolean nulserv=true;
389           while (visible)
390           {
391             final Thread runner = Thread.currentThread();
392             JFrame df = new JFrame();
393             df.getContentPane().setLayout(new BorderLayout());
394             df.getContentPane().add(
395                     (nulserv=!nulserv) ? new RestServiceEditorPane(jalview.ws.rest.RestClient
396                             .makeShmmrRestClient().getRestDescription()) : new RestServiceEditorPane(), 
397                     BorderLayout.CENTER);
398             df.setBounds(100, 100, 600, 400);
399             df.addComponentListener(new ComponentListener()
400             {
401
402               @Override
403               public void componentShown(ComponentEvent e)
404               {
405
406               }
407
408               @Override
409               public void componentResized(ComponentEvent e)
410               {
411
412               }
413
414               @Override
415               public void componentMoved(ComponentEvent e)
416               {
417
418               }
419
420               @Override
421               public void componentHidden(ComponentEvent e)
422               {
423                 visible = false;
424                 runner.interrupt();
425
426               }
427             });
428             df.setVisible(true);
429             while (visible)
430             {
431               try
432               {
433                 Thread.sleep(10000);
434               } catch (Exception x)
435               {
436               }
437               ;
438             }
439             visible = true;
440           }
441         }
442       }).start();
443
444     }
445   }
446   String finalService=null;
447   public void showDialog(String title)
448   {
449     if (oldservice!=null)
450     {
451       finalService = oldservice.toString();
452     }
453     JalviewDialog jvd = new JalviewDialog()
454     {
455       
456       @Override
457       protected void raiseClosed()
458       {
459         // TODO Auto-generated method stub
460         
461       }
462       
463       @Override
464       protected void okPressed()
465       {
466         updateServiceFromGui();
467         finalService = currentservice.toString();        
468       }
469       
470       @Override
471       protected void cancelPressed()
472       {
473         
474       }
475     };
476     JPanel pane = new JPanel(new BorderLayout()),okcancel=new JPanel(new FlowLayout());
477     pane.add(this,BorderLayout.CENTER);
478     okcancel.add(jvd.ok);
479     okcancel.add(jvd.cancel);
480     pane.add(okcancel, BorderLayout.SOUTH);
481     jvd.initDialogFrame(pane, true, true, title, 600,350);
482     jvd.waitForInput();
483   }
484
485   public String getEditedRestService()
486   {
487     return finalService;
488   }
489 }