1 package jalview.ws.rest;
3 import jalview.ws.params.ArgumentI;
4 import jalview.ws.params.InvalidArgumentException;
5 import jalview.ws.params.OptionI;
6 import jalview.ws.params.ParameterI;
7 import jalview.ws.params.simple.IntegerParameter;
8 import jalview.ws.params.simple.Option;
9 import jalview.ws.rest.params.SeqGroupIndexVector;
11 import java.io.IOException;
12 import java.io.OutputStream;
13 import java.io.OutputStreamWriter;
14 import java.io.PrintWriter;
15 import java.io.StringWriter;
16 import java.io.UnsupportedEncodingException;
17 import java.nio.charset.Charset;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.List;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
25 import org.apache.http.entity.mime.content.ContentBody;
26 import org.apache.http.entity.mime.content.StringBody;
28 import sun.io.CharacterEncoding;
29 import sun.misc.CharacterEncoder;
32 * InputType is the abstract model of each input parameter that a rest service might take.
33 * It enables the engine to validate input by providing
34 * { formatter for type, parser for type }
37 public abstract class InputType {
42 public enum molType { NUC, PROT, MIX;
44 public static Collection<String> toStringValues()
46 Collection<String> c = new ArrayList<String>();
47 for (molType type:values())
49 c.add(type.toString());
55 public int max=0; // unbounded
56 protected ArrayList<Class> inputData=new ArrayList<Class>();
58 * initialise the InputType with a list of jalview data classes that the RestJob needs to be able to provide to it.
61 protected InputType(Class[] types)
71 * do basic tests to ensure the job's service takes this parameter, and the job's input data can be used to generate the input data
75 public boolean validFor(RestJob restJob)
77 if (!validFor(restJob.rsd))
79 for (Class cl:inputData)
81 if (!restJob.hasDataOfType(cl))
89 public boolean validFor(RestServiceDescription restServiceDescription)
91 if (!restServiceDescription.inputParams.values().contains(this))
96 protected ContentBody utf8StringBody(String content, String type)
98 Charset utf8 = Charset.forName("UTF-8");
101 return new StringBody(utf8.encode(content).asCharBuffer().toString());
103 return new StringBody(utf8.encode(content).asCharBuffer().toString(), type, utf8);
105 } catch (Exception ex)
107 System.err.println("Couldn't transform string\n"+content+"\nException was :");
108 ex.printStackTrace(System.err);
114 * @param rj data from which input is to be extracted and formatted
115 * @return StringBody or FileBody ready for posting
117 abstract public ContentBody formatForInput(RestJob rj) throws UnsupportedEncodingException,NoValidInputDataException;
120 * @return true if no input data needs to be provided for this parameter
122 public boolean isConstant()
124 return (inputData==null || inputData.size()==0);
127 * return a url encoded version of this parameter's value, or an empty string if the parameter has no ='value' content.
130 public abstract List<String> getURLEncodedParameter();
133 * set the property known as tok, possibly by assigning it with a given val
135 * @param val (may be empty or null)
136 * @param warnings place where parse warnings are reported
137 * @return true if property was set
139 public abstract boolean configureProperty(String tok, String val, StringBuffer warnings);
142 * Get unique key for this type of parameter in a URL encoding.
143 * @return the string that prefixes an input parameter of InputType<T> type in the string returned from getURLEncodedParameter
145 public abstract String getURLtokenPrefix();
147 * parse the given token String and set InputParameter properties appropriately
148 * @param tokenstring - urlencoded parameter string as returned from getURLEncodedParameter
149 * @param warnings - place where any warning messages about bad property values are written
150 * @return true if configuration succeeded, false otherwise.
152 public boolean configureFromURLtokenString(List<String> tokenstring, StringBuffer warnings) {
154 for (String tok:tokenstring)
156 Matcher mtch = Pattern.compile("^([^=]+)=?'?([^']*)?'?").matcher(tok);
159 if (mtch.group(1).equals("min"))
161 min = Integer.parseInt(mtch.group(2));
165 if (mtch.group(1).equals("max"))
167 max = Integer.parseInt(mtch.group(2));
171 catch (NumberFormatException x)
174 warnings.append("Invalid value for parameter "+mtch.group(1).toLowerCase()+" '"+mtch.group(2)+"' (expected an integer)\n");
177 if (!configureProperty(mtch.group(1), mtch.group(2), warnings)) {
178 if (warnings.length()==0)
180 warnings.append("Failed to configure InputType :"+getURLtokenPrefix()+" with property string: '"+mtch.group(0)+"'\n (token is '"+mtch.group(1)+"' and value is '"+mtch.group(2)+"')\n");
188 public void addBaseParams(ArrayList<String> prms)
190 // todo : check if replaceids should be a global for the service, rather than for a specific parameter.
192 prms.add("min='"+min+"'");
195 prms.add("max='"+max+"'");
199 public abstract List<OptionI> getOptions();
200 public List<OptionI> getBaseOptions()
202 ArrayList<OptionI> opts = new ArrayList<OptionI>();
203 opts.add(new IntegerParameter("min","Minimum number of data of this type",true,1,min,0,-1));
204 opts.add(new IntegerParameter("max","Maximum number of data of this type",false,0,max,0,-1));
208 * make a copy of this InputType
211 public abstract InputType copy();
215 * parse a set of configuration options
216 * @param currentSettings - modified settings originally from getOptions
217 * @throws InvalidArgumentException thrown if currentSettings contains invalid options for this type.
219 public void configureFromArgumentI(List<ArgumentI> currentSettings) throws InvalidArgumentException
221 ArrayList<String> urltoks = new ArrayList<String>();
223 for (ArgumentI arg: currentSettings)
225 if (arg instanceof ParameterI)
227 rg=arg.getName()+"='"+arg.getValue()+"'";
229 // TODO: revise architecture - this is counter intuitive - options with different values to their names are actually parameters
230 rg=(arg.getValue().length()>0) ? (arg.getValue().equals(arg.getName()) ? arg.getName():arg.getName()+"='"+arg.getValue()+"'")
237 StringBuffer warnings;
238 if (!configureFromURLtokenString(urltoks, warnings=new StringBuffer()))
240 throw new InvalidArgumentException(warnings.toString());
243 protected OptionI createMolTypeOption(String name, String descr,
244 boolean req, molType curType, molType defType)
246 return new Option(name,descr, req, defType==null ? "" : defType.toString(), curType==null ? "" : curType.toString(),molType.toStringValues(),