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