JAL-3878 update branch from 2.12 merge from 2.11.2
[jalview.git] / src / jalview / ws2 / client / slivka / SlivkaParamStoreFactory.java
1 package jalview.ws2.client.slivka;
2
3 import static java.util.Objects.requireNonNullElse;
4
5 import java.io.File;
6 import java.net.MalformedURLException;
7 import java.net.URL;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.List;
11 import java.util.Map;
12
13 import com.stevesoft.pat.NotImplementedError;
14
15 import jalview.bin.Cache;
16 import jalview.bin.Console;
17 import jalview.ws.params.ArgumentI;
18 import jalview.ws.params.ParamDatastoreI;
19 import jalview.ws.params.ParamManager;
20 import jalview.ws.params.WsParamSetI;
21 import jalview.ws.params.simple.BooleanOption;
22 import jalview.ws.params.simple.DoubleParameter;
23 import jalview.ws.params.simple.IntegerParameter;
24 import jalview.ws.params.simple.Option;
25 import jalview.ws.params.simple.StringParameter;
26 import jalview.ws2.params.SimpleParamDatastore;
27 import jalview.ws2.params.SimpleParamSet;
28 import uk.ac.dundee.compbio.slivkaclient.Parameter;
29 import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
30
31 class SlivkaParamStoreFactory
32 {
33   private final SlivkaService service;
34   private final ParamManager manager;
35
36   SlivkaParamStoreFactory(SlivkaService service, ParamManager manager)
37   {
38     this.service = service;
39     this.manager = manager;
40   }
41   
42   ParamDatastoreI createParamDatastore()
43   {
44     URL url = null;
45     try
46     {
47       url = service.getUrl().toURL();
48     } catch (MalformedURLException e)
49     {
50       Console.warn("Invalid service url " + service.getUrl(), e);
51     }
52     List<WsParamSetI> presets = new ArrayList<>(service.getPresets().size());
53     for (var preset : service.getPresets())
54     {
55       presets.add(createPreset(preset));
56     }
57     List<ArgumentI> arguments = createPresetArguments(Collections.emptyMap());
58     return new SimpleParamDatastore(url, arguments, presets, manager);
59   }
60   
61   WsParamSetI createPreset(SlivkaService.Preset preset)
62   {
63     var builder = SimpleParamSet.newBuilder();
64     builder.name(preset.name);
65     builder.description(preset.description);
66     builder.url(service.getUrl().toString());
67     builder.modifiable(false);
68     builder.arguments(createPresetArguments(preset.values));
69     return builder.build();
70   }
71
72   List<ArgumentI> createPresetArguments(Map<String, Object> values)
73   {
74     var args = new ArrayList<ArgumentI>();
75     for (Parameter param : service.getParameters())
76     {
77       if (param instanceof Parameter.IntegerParameter)
78       {
79         args.add(createOption((Parameter.IntegerParameter) param,
80             (Integer) values.get(param.getId())));
81       }
82       else if (param instanceof Parameter.DecimalParameter)
83       {
84         args.add(createOption((Parameter.DecimalParameter) param,
85             (Double) values.get(param.getId())));
86       }
87       else if (param instanceof Parameter.TextParameter)
88       {
89         args.add(createOption((Parameter.TextParameter) param,
90             (String) values.get(param.getId())));
91       }
92       else if (param instanceof Parameter.FlagParameter)
93       {
94         args.add(createOption((Parameter.FlagParameter) param,
95             (Boolean) values.get(param.getId())));
96       }
97       else if (param instanceof Parameter.ChoiceParameter)
98       {
99         Object ovalue = values.get(param.getId());
100         List<String> lvalue = null;
101         if (param.isArray())
102           lvalue = (List<String>) ovalue;
103         else if (ovalue != null)
104           lvalue = List.of((String) ovalue);
105         args.addAll(createChoiceOptions((Parameter.ChoiceParameter) param, lvalue));
106       }
107       else if (param instanceof Parameter.FileParameter)
108       {
109         // args.add(createOption((Parameter.FileParameter) param, null));
110       }
111       else
112       {
113         args.add(createOption(param, values.get(param.getId())));
114       }
115     }
116     return args;
117   }
118
119   private Option createOption(Parameter.IntegerParameter param, Integer value)
120   {
121     var builder = IntegerParameter.newBuilder();
122     setCommonProperties(param, builder);
123     builder.setDefaultValue((Integer) param.getDefault());
124     builder.setValue(value);
125     builder.setBounds(param.getMin(), param.getMax());
126     return builder.build();
127   }
128
129   private Option createOption(Parameter.DecimalParameter param, Double value)
130   {
131     var builder = DoubleParameter.newBuilder();
132     setCommonProperties(param, builder);
133     builder.setDefaultValue((Double) param.getDefault());
134     builder.setValue(value);
135     builder.setBounds(param.getMin(), param.getMax());
136     return builder.build();
137   }
138
139   private Option createOption(Parameter.TextParameter param, String value)
140   {
141     var builder = StringParameter.newBuilder();
142     setCommonProperties(param, builder);
143     builder.setDefaultValue((String) param.getDefault());
144     builder.setValue(value);
145     return builder.build();
146   }
147
148   private Option createOption(Parameter.FlagParameter param, Boolean value)
149   {
150     var builder = BooleanOption.newBuilder();
151     setCommonProperties(param, builder);
152     builder.setDefaultValue((Boolean) param.getDefault());
153     builder.setValue(value);
154     return builder.build();
155   }
156
157   private List<Option> createChoiceOptions(Parameter.ChoiceParameter param, List<String> value)
158   {
159     value = requireNonNullElse(value, Collections.emptyList());
160     if (param.isArray())
161     {
162       /*
163        * Array parameter means that multiple values can be provided.
164        * Use multiple boolean checkboxes to represent the value.
165        */
166       List<Option> options = new ArrayList<>();
167       List<?> selected = requireNonNullElse(
168           (List<?>) param.getDefault(), Collections.emptyList());
169       int i = 0;
170       var builder = BooleanOption.newBuilder();
171       setCommonProperties(param, builder);
172       for (String choice : param.getChoices())
173       {
174         builder.setName(String.format("%s$%d", param.getId(), i++));
175         builder.setLabel(choice);
176         builder.setDefaultValue(selected.contains(choice));
177         builder.setValue(value.contains(choice));
178         builder.setReprValue(choice);
179         options.add(builder.build());
180       }
181       return options;
182     }
183     else
184     {
185       /*
186        * Single value parameter means a single string with limited possible
187        * values can be used.
188        */
189       var builder = StringParameter.newBuilder();
190       setCommonProperties(param, builder);
191       builder.setDefaultValue((String) param.getDefault());
192       if (value.size() > 0)
193         builder.setValue(value.get(0));
194       builder.setPossibleValues(param.getChoices());
195       return List.of(builder.build());
196     }
197   }
198
199   private Option createOption(Parameter.FileParameter param, File value)
200   {
201     throw new NotImplementedError("file paramters are not implemented for slivka");
202   }
203
204   private Option createOption(Parameter param, Object value)
205   {
206     var builder = StringParameter.newBuilder();
207     setCommonProperties(param, builder);
208     if (param.getDefault() != null)
209       builder.setDefaultValue(param.getDefault().toString());
210     if (value != null)
211       builder.setValue(value.toString());
212     return builder.build();
213   }
214
215   private void setCommonProperties(Parameter param, Option.Builder builder)
216   {
217     builder.setName(param.getId());
218     builder.setLabel(param.getName());
219     builder.setDescription(param.getDescription());
220     builder.setRequired(param.isRequired());
221     try
222     {
223       builder.setDetailsUrl(service.getUrl().toURL());
224     } catch (MalformedURLException e)
225     {
226       Console.warn("invalid service url " + service.getUrl(), e);
227     }
228   }
229 }