Merge branch 'JAL-3878_ws-overhaul-3' into with_ws_overhaul-3
[jalview.git] / src / jalview / gui / RestInputParamEditDialog.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.gui;
22
23 import java.util.ArrayList;
24 import java.util.Hashtable;
25
26 import javax.swing.JPanel;
27 import javax.swing.event.ListSelectionEvent;
28
29 import jalview.jbgui.GRestInputParamEditDialog;
30 import jalview.ws.params.InvalidArgumentException;
31 import jalview.ws.params.OptionI;
32 import jalview.ws.params.ParameterI;
33 import jalview.ws.rest.InputType;
34 import jalview.ws.rest.RestServiceDescription;
35 import net.miginfocom.swing.MigLayout;
36
37 public class RestInputParamEditDialog extends GRestInputParamEditDialog
38         implements OptsParametersContainerI
39 {
40   Hashtable<String, Class> typeclass = new Hashtable<String, Class>();
41
42   Hashtable<String, ArrayList<JPanel>> typeopts = new Hashtable<String, ArrayList<JPanel>>();
43
44   Hashtable<String, OptsAndParamsPage> opanps = new Hashtable<String, OptsAndParamsPage>();
45
46   private InputType getTypeFor(String name)
47   {
48     try
49     {
50       return (InputType) (typeclass.get(name).getConstructor()
51               .newInstance());
52     } catch (Throwable x)
53     {
54       System.err.println(
55               "Unexpected exception when instantiating rest input type.");
56       x.printStackTrace();
57     }
58     return null;
59   }
60
61   int reply;
62
63   JalviewDialog frame = new JalviewDialog()
64   {
65
66     @Override
67     protected void raiseClosed()
68     {
69
70     }
71
72     @Override
73     protected void okPressed()
74     {
75       reply = JvOptionPane.OK_OPTION;
76     }
77
78     @Override
79     protected void cancelPressed()
80     {
81       reply = JvOptionPane.CANCEL_OPTION;
82
83     }
84   };
85
86   InputType old, current;
87
88   public RestInputParamEditDialog(
89           RestServiceEditorPane restServiceEditorPane,
90           RestServiceDescription currentservice, InputType toedit)
91   {
92     initFor(restServiceEditorPane, currentservice, toedit);
93     frame.waitForInput();
94     // TODO: warn user if they are about to overwrite an existing parameter
95     // because they have used the same name when editing a different parameter.
96     // TODO: make any press of the return key cause 'OK' to be pressed
97   }
98
99   private void initFor(RestServiceEditorPane restServiceEditorPane,
100           RestServiceDescription currentservice, InputType toedit)
101   {
102     okcancel.add(frame.cancel);
103     okcancel.add(frame.ok);
104     frame.initDialogFrame(dpane, true, true,
105             "Edit parameter for service " + currentservice.getName(), 600,
106             800);
107
108     initTypeLists();
109     reply = JvOptionPane.CANCEL_OPTION;
110     old = toedit;
111     current = null;
112     if (old != null)
113     {
114       setStateFor(old);
115     }
116     updated = updated && reply == JvOptionPane.OK_OPTION;
117     frame.validate();
118   }
119
120   public RestInputParamEditDialog(
121           RestServiceEditorPane restServiceEditorPane,
122           RestServiceDescription currentservice, String string)
123   {
124     initFor(restServiceEditorPane, currentservice, null);
125     tok.setText(string);
126     frame.waitForInput();
127   }
128
129   private void setStateFor(InputType current)
130   {
131     tok.setText(current.token);
132     OptsAndParamsPage opanp = opanps.get(current.getURLtokenPrefix());
133     for (OptionI ops : current.getOptions())
134     {
135       if (ops instanceof ParameterI)
136       {
137         opanp.setParameter((ParameterI) ops);
138       }
139       else
140       {
141         if (ops.getValue() != null && ops.getValue().length() > 0)
142         {
143           opanp.selectOption(ops, ops.getValue());
144         }
145       }
146     }
147     typeList.setSelectedValue(current.getURLtokenPrefix(), true);
148     type_SelectionChangedActionPerformed(null);
149   }
150
151   private void updateCurrentType()
152   {
153     if (typeList.getSelectedValue() != null)
154     {
155       InputType newType = getTypeFor((String) typeList.getSelectedValue());
156       if (newType != null)
157       {
158         newType.token = tok.getText().trim();
159         try
160         {
161           newType.configureFromArgumentI(opanps
162                   .get(newType.getURLtokenPrefix()).getCurrentSettings());
163           current = newType;
164           updated = true;
165         } catch (InvalidArgumentException ex)
166         {
167           System.err.println(
168                   "IMPLEMENTATION ERROR: Invalid argument for type : "
169                           + typeList.getSelectedValue() + "\n");
170           ex.printStackTrace();
171         }
172       }
173     }
174
175   }
176
177   private void initTypeLists()
178   {
179     ArrayList<String> types = new ArrayList<String>();
180     // populate type list
181     for (Class type : RestServiceDescription.getInputTypes())
182     {
183
184       InputType jtype = null;
185       try
186       {
187         JPanel inopts = new JPanel(new MigLayout());
188         ArrayList<JPanel> opts = new ArrayList<JPanel>(),
189                 prms = new ArrayList<JPanel>();
190         jtype = (InputType) (type.getConstructor().newInstance());
191         typeclass.put(jtype.getURLtokenPrefix(), type);
192         // and populate parameters from this type
193         OptsAndParamsPage opanp = new OptsAndParamsPage(this, true);
194         opanps.put(jtype.getURLtokenPrefix(), opanp);
195         for (OptionI opt : jtype.getOptions())
196         {
197
198           if (opt instanceof ParameterI)
199           {
200             prms.add(opanp.addParameter((ParameterI) opt));
201           }
202           else
203           {
204             opts.add(opanp.addOption(opt));
205           }
206         }
207         // then tag the params at the end of the options.
208         for (JPanel pnl : prms)
209         {
210           opts.add(pnl);
211         }
212         typeopts.put(jtype.getURLtokenPrefix(), opts);
213         types.add(jtype.getURLtokenPrefix());
214       } catch (Throwable x)
215       {
216         System.err.println(
217                 "Unexpected exception when instantiating rest input type.");
218         x.printStackTrace();
219       }
220     }
221     typeList.setListData(types.toArray());
222
223   }
224
225   @Override
226   protected void type_SelectionChangedActionPerformed(ListSelectionEvent e)
227   {
228     options.removeAll();
229     String typen = (String) typeList.getSelectedValue();
230     if (typeopts.get(typen) != null)
231     {
232       for (JPanel opt : typeopts.get(typen))
233       {
234         opt.setOpaque(true);
235         options.add(opt, "wrap");
236       }
237       options.invalidate();
238       optionsPanel.setVisible(true);
239     }
240     else
241     {
242       optionsPanel.setVisible(false);
243     }
244     dpane.revalidate();
245     updateCurrentType();
246   }
247
248   boolean updated = false;
249
250   public boolean wasUpdated()
251   {
252     return updated;
253   }
254
255   @Override
256   public void refreshParamLayout()
257   {
258     options.invalidate();
259     dpane.revalidate();
260   }
261
262   @Override
263   protected void tokChanged_actionPerformed()
264   {
265     if (tok.getText().trim().length() > 0)
266     {
267       if (current != null)
268       {
269         current.token = tok.getText().trim();
270         updated = true;
271       }
272     }
273   }
274
275   @Override
276   public void argSetModified(Object modifiedElement, boolean b)
277   {
278     updated = updated | b;
279     if (updated)
280     {
281       updateCurrentType();
282     }
283   }
284
285 }