2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
21 package jalview.ws.rest;
23 import java.util.Locale;
25 import jalview.ws.params.ArgumentI;
26 import jalview.ws.params.InvalidArgumentException;
27 import jalview.ws.params.OptionI;
28 import jalview.ws.params.ParameterI;
29 import jalview.ws.params.simple.IntegerParameter;
30 import jalview.ws.params.simple.Option;
32 import java.io.UnsupportedEncodingException;
33 import java.nio.charset.Charset;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.regex.Matcher;
37 import java.util.regex.Pattern;
39 import org.apache.http.entity.mime.content.ContentBody;
40 import org.apache.http.entity.mime.content.StringBody;
43 * InputType is the abstract model of each input parameter that a rest service
44 * might take. It enables the engine to validate input by providing { formatter
45 * for type, parser for type }
48 public abstract class InputType
50 private static final Pattern URL_PATTERN = Pattern
51 .compile("^([^=]+)=?'?([^']*)?'?");
62 public static List<String> toStringValues()
64 List<String> c = new ArrayList<>();
65 for (molType type : values())
67 c.add(type.toString());
77 public int max = 0; // unbounded
79 protected List<Class> inputData = new ArrayList<>();
82 * initialise the InputType with a list of jalview data classes that the
83 * RestJob needs to be able to provide to it.
87 protected InputType(Class[] types)
99 * do basic tests to ensure the job's service takes this parameter, and the
100 * job's input data can be used to generate the input data
105 public boolean validFor(RestJob restJob)
107 if (!validFor(restJob.rsd))
111 for (Class cl : inputData)
113 if (!restJob.hasDataOfType(cl))
121 public boolean validFor(RestServiceDescription restServiceDescription)
123 if (!restServiceDescription.inputParams.values().contains(this))
131 protected ContentBody utf8StringBody(String content, String type)
133 Charset utf8 = Charset.forName("UTF-8");
138 return new StringBody(
139 utf8.encode(content).asCharBuffer().toString());
143 return new StringBody(
144 utf8.encode(content).asCharBuffer().toString(), type, utf8);
146 } catch (Exception ex)
148 System.err.println("Couldn't transform string\n" + content
149 + "\nException was :");
150 ex.printStackTrace(System.err);
158 * data from which input is to be extracted and formatted
159 * @return StringBody or FileBody ready for posting
161 abstract public ContentBody formatForInput(RestJob rj)
162 throws UnsupportedEncodingException, NoValidInputDataException;
166 * @return true if no input data needs to be provided for this parameter
168 public boolean isConstant()
170 return (inputData == null || inputData.size() == 0);
174 * return a url encoded version of this parameter's value, or an empty string
175 * if the parameter has no ='value' content.
179 public abstract List<String> getURLEncodedParameter();
182 * set the property known as tok, possibly by assigning it with a given val
186 * (may be empty or null)
188 * place where parse warnings are reported
189 * @return true if property was set
191 public abstract boolean configureProperty(String tok, String val,
192 StringBuffer warnings);
195 * Get unique key for this type of parameter in a URL encoding.
197 * @return the string that prefixes an input parameter of InputType<T> type in
198 * the string returned from getURLEncodedParameter
200 public abstract String getURLtokenPrefix();
203 * parse the given token String and set InputParameter properties
207 * - urlencoded parameter string as returned from
208 * getURLEncodedParameter
210 * - place where any warning messages about bad property values are
212 * @return true if configuration succeeded, false otherwise.
214 public boolean configureFromURLtokenString(List<String> tokenstring,
215 StringBuffer warnings)
217 boolean valid = true;
218 for (String tok : tokenstring)
220 Matcher mtch = URL_PATTERN.matcher(tok);
225 if (mtch.group(1).equals("min"))
227 min = Integer.parseInt(mtch.group(2));
231 else if (mtch.group(1).equals("max"))
233 max = Integer.parseInt(mtch.group(2));
236 } catch (NumberFormatException x)
239 warnings.append("Invalid value for parameter "
240 + mtch.group(1).toLowerCase(Locale.ROOT) + " '"
241 + mtch.group(2) + "' (expected an integer)\n");
244 if (!configureProperty(mtch.group(1), mtch.group(2), warnings))
246 if (warnings.length() == 0)
248 warnings.append("Failed to configure InputType :"
249 + getURLtokenPrefix() + " with property string: '"
250 + mtch.group(0) + "'\n (token is '" + mtch.group(1)
251 + "' and value is '" + mtch.group(2) + "')\n");
260 public void addBaseParams(ArrayList<String> prms)
262 // todo : check if replaceids should be a global for the service, rather
263 // than for a specific parameter.
266 prms.add("min='" + min + "'");
270 prms.add("max='" + max + "'");
274 public abstract List<OptionI> getOptions();
276 public List<OptionI> getBaseOptions()
278 ArrayList<OptionI> opts = new ArrayList<>();
279 opts.add(new IntegerParameter("min",
280 "Minimum number of data of this type", true, 1, min, 0, -1));
281 opts.add(new IntegerParameter("max",
282 "Maximum number of data of this type", false, 0, max, 0, -1));
287 * make a copy of this InputType
289 * @return may not be needed public abstract InputType copy();
293 * parse a set of configuration options
295 * @param currentSettings
296 * - modified settings originally from getOptions
297 * @throws InvalidArgumentException
298 * thrown if currentSettings contains invalid options for this type.
300 public void configureFromArgumentI(List<ArgumentI> currentSettings)
301 throws InvalidArgumentException
303 List<String> urltoks = new ArrayList<>();
305 for (ArgumentI arg : currentSettings)
307 if (arg instanceof ParameterI)
309 rg = arg.getName() + "='" + arg.getValue() + "'";
313 // TODO: revise architecture - this is counter intuitive - options with
314 // different values to their names are actually parameters
315 rg = (arg.getValue().length() > 0)
316 ? (arg.getValue().equals(arg.getName()) ? arg.getName()
317 : arg.getName() + "='" + arg.getValue() + "'")
325 StringBuffer warnings;
326 if (!configureFromURLtokenString(urltoks,
327 warnings = new StringBuffer()))
329 throw new InvalidArgumentException(warnings.toString());
333 protected OptionI createMolTypeOption(String name, String descr,
334 boolean req, molType curType, molType defType)
336 return new Option(name, descr, req,
337 defType == null ? "" : defType.toString(),
338 curType == null ? "" : curType.toString(),
339 molType.toStringValues(), null);