6ac21dff3fd38f182afa6c79f63abeb763f81838
[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 = param.isArray() ? (List<String>) ovalue : List.of((String) ovalue);
100         args.addAll(createChoiceOptions((Parameter.ChoiceParameter) param, lvalue));
101       }
102       else if (param instanceof Parameter.FileParameter)
103       {
104         // args.add(createOption((Parameter.FileParameter) param, null));
105       }
106       else
107       {
108         args.add(createOption(param, values.get(param.getId())));
109       }
110     }
111     return args;
112   }
113
114   private Option createOption(Parameter.IntegerParameter param, Integer value)
115   {
116     var builder = IntegerParameter.newBuilder();
117     setCommonProperties(param, builder);
118     builder.setDefaultValue((Integer) param.getDefault());
119     builder.setValue(value);
120     builder.setBounds(param.getMin(), param.getMax());
121     return builder.build();
122   }
123
124   private Option createOption(Parameter.DecimalParameter param, Double value)
125   {
126     var builder = DoubleParameter.newBuilder();
127     setCommonProperties(param, builder);
128     builder.setDefaultValue((Double) param.getDefault());
129     builder.setValue(value);
130     builder.setBounds(param.getMin(), param.getMax());
131     return builder.build();
132   }
133
134   private Option createOption(Parameter.TextParameter param, String value)
135   {
136     var builder = StringParameter.newBuilder();
137     setCommonProperties(param, builder);
138     builder.setDefaultValue((String) param.getDefault());
139     builder.setValue(value);
140     return builder.build();
141   }
142
143   private Option createOption(Parameter.FlagParameter param, Boolean value)
144   {
145     var builder = BooleanOption.newBuilder();
146     setCommonProperties(param, builder);
147     builder.setDefaultValue((Boolean) param.getDefault());
148     builder.setValue(value);
149     return builder.build();
150   }
151
152   private List<Option> createChoiceOptions(Parameter.ChoiceParameter param, List<String> value)
153   {
154     value = requireNonNullElse(value, Collections.emptyList());
155     if (param.isArray())
156     {
157       /*
158        * Array parameter means that multiple values can be provided.
159        * Use multiple boolean checkboxes to represent the value.
160        */
161       List<Option> options = new ArrayList<>();
162       List<?> selected = requireNonNullElse(
163           (List<?>) param.getDefault(), Collections.emptyList());
164       int i = 0;
165       var builder = BooleanOption.newBuilder();
166       setCommonProperties(param, builder);
167       for (String choice : param.getChoices())
168       {
169         builder.setName(String.format("%s$%d", param.getId(), i++));
170         builder.setLabel(choice);
171         builder.setDefaultValue(selected.contains(choice));
172         builder.setValue(value.contains(choice));
173         builder.setReprValue(choice);
174         options.add(builder.build());
175       }
176       return options;
177     }
178     else
179     {
180       /*
181        * Single value parameter means a single string with limited possible
182        * values can be used.
183        */
184       var builder = StringParameter.newBuilder();
185       setCommonProperties(param, builder);
186       builder.setDefaultValue((String) param.getDefault());
187       if (value.size() > 0)
188         builder.setValue(value.get(0));
189       builder.setPossibleValues(param.getChoices());
190       return List.of(builder.build());
191     }
192   }
193
194   private Option createOption(Parameter.FileParameter param, File value)
195   {
196     throw new NotImplementedError("file paramters are not implemented for slivka");
197   }
198
199   private Option createOption(Parameter param, Object value)
200   {
201     var builder = StringParameter.newBuilder();
202     setCommonProperties(param, builder);
203     if (param.getDefault() != null)
204       builder.setDefaultValue(param.getDefault().toString());
205     if (value != null)
206       builder.setValue(value.toString());
207     return builder.build();
208   }
209
210   private void setCommonProperties(Parameter param, Option.Builder builder)
211   {
212     builder.setName(param.getId());
213     builder.setLabel(param.getName());
214     builder.setDescription(param.getDescription());
215     builder.setRequired(param.isRequired());
216     try
217     {
218       builder.setDetailsUrl(service.getUrl().toURL());
219     } catch (MalformedURLException e)
220     {
221       Cache.log.warn("invalid service url " + service.getUrl(), e);
222     }
223   }
224 }