259bdcabdbec0c8d6b02e7c7a8af6a28c429217c
[jalview.git] / src / jalview / ws2 / params / SimpleParamDatastore.java
1 package jalview.ws2.params;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.IOException;
5 import java.io.StringReader;
6 import java.net.URL;
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.List;
10
11 import javax.xml.bind.JAXBContext;
12 import javax.xml.bind.JAXBException;
13 import javax.xml.bind.Marshaller;
14 import javax.xml.bind.Unmarshaller;
15
16 import jalview.bin.Cache;
17 import jalview.util.MessageManager;
18 import jalview.ws.params.ArgumentI;
19 import jalview.ws.params.ParamDatastoreI;
20 import jalview.ws.params.ParamManager;
21 import jalview.ws.params.WsParamSetI;
22
23 /**
24  * A web client agnostic parameters datastore that provides view of the
25  * parameters and delegates parameters storage to {@link ParamManager}
26  * if given. Parameter datastore maintains the applicable service url
27  * the list of service parameters and both presets and user defined
28  * parameter sets 
29  */
30 public class SimpleParamDatastore implements ParamDatastoreI
31 {
32   protected URL serviceUrl;
33   protected List<ArgumentI> parameters;
34   protected List<SimpleParamSet> servicePresets;
35   protected List<SimpleParamSet> userPresets = new ArrayList<>();
36   protected ParamManager manager;
37
38   /**
39    * Create new parameter datastore bound to the specified url with
40    * given service parameters and presets. Additionally, a parameters
41    * manager may be provided that will be used to load and store
42    * user parameter sets.
43    *  
44    * @param serviceUrl applicable url
45    * @param parameters service parameters
46    * @param presets unmodifiable service presets
47    * @param manager parameter manager used to load and store user presets
48    */
49   public SimpleParamDatastore(URL serviceUrl, List<ArgumentI> parameters,
50       List<? extends WsParamSetI> presets, ParamManager manager)
51   {
52     this.serviceUrl = serviceUrl;
53     this.parameters = Collections.unmodifiableList(new ArrayList<>(parameters));
54     this.servicePresets = new ArrayList<>(presets.size());
55     for (var preset : presets)
56     {
57       if (preset instanceof SimpleParamSet)
58         servicePresets.add((SimpleParamSet) preset);
59       else
60         servicePresets.add(new SimpleParamSet(preset));
61     }
62     this.servicePresets = Collections.unmodifiableList(this.servicePresets);
63     this.manager = manager;
64     if (manager != null)
65       _initManager(manager);
66   }
67   
68   private void _initManager(ParamManager manager)
69   {
70     manager.registerParser(serviceUrl.toString(), this);
71     WsParamSetI[] paramSets = manager.getParameterSet(null, serviceUrl.toString(),
72         true, false);
73     if (paramSets != null)
74     {
75       for (WsParamSetI paramSet : paramSets)
76       {
77         // TODO: handle mismatch between preset and current parameters
78         if (paramSet instanceof SimpleParamSet)
79           userPresets.add((SimpleParamSet) paramSet);
80         else
81         {
82           userPresets.add(new SimpleParamSet(paramSet));
83           Cache.log.warn(String.format(
84               "Parameter set instance type %s is not applicable to service"
85               + "at %s.", paramSet.getClass(), serviceUrl));
86         }
87       }
88     }
89   }
90   
91   @Override
92   public List<WsParamSetI> getPresets()
93   {
94     List<WsParamSetI> presets = new ArrayList<>();
95     presets.addAll(servicePresets);
96     presets.addAll(userPresets);
97     return presets;
98   }
99
100   @Override
101   public SimpleParamSet getPreset(String name)
102   {
103     SimpleParamSet preset = null;
104     preset = getUserPreset(name);
105     if (preset != null)
106       return preset;
107     preset = getServicePreset(name);
108     if (preset != null)
109       return preset;
110     return null;
111   }
112   
113   public SimpleParamSet getUserPreset(String name)
114   {
115     for (SimpleParamSet preset : userPresets)
116     {
117       if (name.equals(preset.getName()))
118         return preset;
119     }
120     return null;
121   }
122   
123   public SimpleParamSet getServicePreset(String name)
124   {
125     for (SimpleParamSet preset : servicePresets)
126     {
127       if (name.equals(preset.getName()))
128         return preset;
129     }
130     return null;
131   }
132
133   @Override
134   public List<ArgumentI> getServiceParameters()
135   {
136     return parameters;
137   }
138
139   @Override
140   public boolean presetExists(String name)
141   {
142     return getPreset(name) != null;
143   }
144
145   @Override
146   public void deletePreset(String name)
147   {
148     var userPreset = getUserPreset(name);
149     if (userPreset != null)
150     {
151       userPresets.remove(userPreset);
152       if (manager != null)
153       {
154         manager.deleteParameterSet(userPreset);
155       }
156     }
157     else if (getServicePreset(name) != null)
158     {
159       throw new RuntimeException(MessageManager.getString(
160           "error.implementation_error_attempt_to_delete_service_preset"));
161     }
162     else
163     {
164       Cache.log.warn("Implementation error: no preset to delete");
165     }
166   }
167
168   @Override
169   public void storePreset(String presetName, String text, List<ArgumentI> jobParams)
170   {
171     var builder = SimpleParamSet.newBuilder();
172     builder.name(presetName);
173     builder.description(text);
174     builder.arguments(jobParams);
175     builder.url(serviceUrl.toString());
176     builder.modifiable(true);
177     var preset = builder.build();
178     userPresets.add(preset);
179     if (manager != null)
180       manager.storeParameterSet(preset);
181   }
182
183   @Override
184   public void updatePreset(String oldName, String newName, String text, List<ArgumentI> jobParams)
185   {
186     var preset = getPreset(oldName != null ? oldName : newName);
187     if (preset == null)
188       throw new RuntimeException(MessageManager.formatMessage(
189           "error.implementation_error_cannot_locate_oldname_presetname",
190           oldName, newName));
191     preset.setName(newName);
192     preset.setDescription(text);
193     preset.setArguments(jobParams);
194     preset.setApplicableUrls(new String[] { serviceUrl.toString() });
195     if (manager != null)
196       manager.storeParameterSet(preset);
197   }
198
199   @Override
200   public WsParamSetI parseServiceParameterFile(String name, String description,
201       String[] serviceURL, String parameters)
202       throws IOException
203   {
204     var builder = SimpleParamSet.newBuilder();
205     builder.name(name);
206     builder.description(description);
207     builder.urls(serviceURL);
208     builder.modifiable(true);
209     Unmarshaller unmarshaller;
210     try
211     {
212       var ctx = JAXBContext.newInstance(ArgumentBeanList.class);
213       unmarshaller = ctx.createUnmarshaller();
214     } catch (JAXBException e)
215     {
216       throw new RuntimeException(e);
217     }
218     ArgumentBeanList argList;
219     try
220     {
221       argList = (ArgumentBeanList) unmarshaller.unmarshal(new StringReader(parameters));
222     } catch (JAXBException | ClassCastException e)
223     {
224       throw new IOException("Unable to load parameters from file", e);
225     }
226     builder.arguments(argList.arguments);
227     return builder.build();
228   }
229
230   @Override
231   public String generateServiceParameterFile(WsParamSetI pset) throws IOException
232   {
233     Marshaller marshaller;
234     try 
235     {
236       var ctx = JAXBContext.newInstance(ArgumentBeanList.class);
237       marshaller = ctx.createMarshaller();
238       marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
239       marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
240     } catch (JAXBException e)
241     {
242       throw new RuntimeException(e);
243     }
244     ArgumentBeanList argList = ArgumentBeanList.fromList(pset.getArguments());
245     var out = new ByteArrayOutputStream();
246     try
247     {
248       marshaller.marshal(argList, out);
249     } catch (JAXBException e)
250     {
251       throw new IOException("Unable to generate parameters file", e);
252     }
253     return out.toString();
254   }
255
256 }