2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3 * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
18 package jalview.ws.rest;
20 import jalview.ws.params.ArgumentI;
21 import jalview.ws.params.InvalidArgumentException;
22 import jalview.ws.params.OptionI;
23 import jalview.ws.params.ParameterI;
24 import jalview.ws.params.simple.IntegerParameter;
25 import jalview.ws.params.simple.Option;
27 import java.io.UnsupportedEncodingException;
28 import java.nio.charset.Charset;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.List;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
35 import org.apache.http.entity.mime.content.ContentBody;
36 import org.apache.http.entity.mime.content.StringBody;
39 * InputType is the abstract model of each input parameter that a rest service
40 * might take. It enables the engine to validate input by providing { formatter
41 * for type, parser for type }
44 public abstract class InputType
55 public static Collection<String> toStringValues()
57 Collection<String> c = new ArrayList<String>();
58 for (molType type : values())
60 c.add(type.toString());
70 public int max = 0; // unbounded
72 protected ArrayList<Class> inputData = new ArrayList<Class>();
75 * initialise the InputType with a list of jalview data classes that the
76 * RestJob needs to be able to provide to it.
80 protected InputType(Class[] types)
92 * do basic tests to ensure the job's service takes this parameter, and the
93 * job's input data can be used to generate the input data
98 public boolean validFor(RestJob restJob)
100 if (!validFor(restJob.rsd))
102 for (Class cl : inputData)
104 if (!restJob.hasDataOfType(cl))
112 public boolean validFor(RestServiceDescription restServiceDescription)
114 if (!restServiceDescription.inputParams.values().contains(this))
120 protected ContentBody utf8StringBody(String content, String type)
122 Charset utf8 = Charset.forName("UTF-8");
127 return new StringBody(utf8.encode(content).asCharBuffer()
132 return new StringBody(utf8.encode(content).asCharBuffer()
133 .toString(), type, utf8);
135 } catch (Exception ex)
137 System.err.println("Couldn't transform string\n" + content
138 + "\nException was :");
139 ex.printStackTrace(System.err);
147 * data from which input is to be extracted and formatted
148 * @return StringBody or FileBody ready for posting
150 abstract public ContentBody formatForInput(RestJob rj)
151 throws UnsupportedEncodingException, NoValidInputDataException;
155 * @return true if no input data needs to be provided for this parameter
157 public boolean isConstant()
159 return (inputData == null || inputData.size() == 0);
163 * return a url encoded version of this parameter's value, or an empty string
164 * if the parameter has no ='value' content.
168 public abstract List<String> getURLEncodedParameter();
171 * set the property known as tok, possibly by assigning it with a given val
175 * (may be empty or null)
177 * place where parse warnings are reported
178 * @return true if property was set
180 public abstract boolean configureProperty(String tok, String val,
181 StringBuffer warnings);
184 * Get unique key for this type of parameter in a URL encoding.
186 * @return the string that prefixes an input parameter of InputType<T> type in
187 * the string returned from getURLEncodedParameter
189 public abstract String getURLtokenPrefix();
192 * parse the given token String and set InputParameter properties
196 * - urlencoded parameter string as returned from
197 * getURLEncodedParameter
199 * - place where any warning messages about bad property values are
201 * @return true if configuration succeeded, false otherwise.
203 public boolean configureFromURLtokenString(List<String> tokenstring,
204 StringBuffer warnings)
206 boolean valid = true;
207 for (String tok : tokenstring)
209 Matcher mtch = Pattern.compile("^([^=]+)=?'?([^']*)?'?").matcher(tok);
214 if (mtch.group(1).equals("min"))
216 min = Integer.parseInt(mtch.group(2));
220 else if (mtch.group(1).equals("max"))
222 max = Integer.parseInt(mtch.group(2));
225 } catch (NumberFormatException x)
228 warnings.append("Invalid value for parameter "
229 + mtch.group(1).toLowerCase() + " '" + mtch.group(2)
230 + "' (expected an integer)\n");
233 if (!configureProperty(mtch.group(1), mtch.group(2), warnings))
235 if (warnings.length() == 0)
237 warnings.append("Failed to configure InputType :"
238 + getURLtokenPrefix() + " with property string: '"
239 + mtch.group(0) + "'\n (token is '" + mtch.group(1)
240 + "' and value is '" + mtch.group(2) + "')\n");
249 public void addBaseParams(ArrayList<String> prms)
251 // todo : check if replaceids should be a global for the service, rather
252 // than for a specific parameter.
255 prms.add("min='" + min + "'");
259 prms.add("max='" + max + "'");
263 public abstract List<OptionI> getOptions();
265 public List<OptionI> getBaseOptions()
267 ArrayList<OptionI> opts = new ArrayList<OptionI>();
268 opts.add(new IntegerParameter("min",
269 "Minimum number of data of this type", true, 1, min, 0, -1));
270 opts.add(new IntegerParameter("max",
271 "Maximum number of data of this type", false, 0, max, 0, -1));
276 * make a copy of this InputType
278 * @return may not be needed public abstract InputType copy();
282 * parse a set of configuration options
284 * @param currentSettings
285 * - modified settings originally from getOptions
286 * @throws InvalidArgumentException
287 * thrown if currentSettings contains invalid options for this type.
289 public void configureFromArgumentI(List<ArgumentI> currentSettings)
290 throws InvalidArgumentException
292 ArrayList<String> urltoks = new ArrayList<String>();
294 for (ArgumentI arg : currentSettings)
296 if (arg instanceof ParameterI)
298 rg = arg.getName() + "='" + arg.getValue() + "'";
302 // TODO: revise architecture - this is counter intuitive - options with
303 // different values to their names are actually parameters
304 rg = (arg.getValue().length() > 0) ? (arg.getValue().equals(
305 arg.getName()) ? arg.getName() : arg.getName() + "='"
306 + arg.getValue() + "'") : arg.getName();
313 StringBuffer warnings;
314 if (!configureFromURLtokenString(urltoks, warnings = new StringBuffer()))
316 throw new InvalidArgumentException(warnings.toString());
320 protected OptionI createMolTypeOption(String name, String descr,
321 boolean req, molType curType, molType defType)
323 return new Option(name, descr, req, defType == null ? ""
324 : defType.toString(),
325 curType == null ? "" : curType.toString(),
326 molType.toStringValues(), null);