package jalview.ws.rest; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.http.entity.mime.content.ContentBody; import org.apache.http.entity.mime.content.StringBody; import sun.io.CharacterEncoding; import sun.misc.CharacterEncoder; /*** * InputType is the abstract model of each input parameter that a rest service might take. * It enables the engine to validate input by providing * { formatter for type, parser for type } * */ public abstract class InputType { /** * not used yet */ boolean replaceids; public enum molType { NUC, PROT, MIX} public String token; public int min=1; public int max=0; // unbounded protected ArrayList inputData=new ArrayList(); /** * initialise the InputType with a list of jalview data classes that the RestJob needs to be able to provide to it. * @param types */ protected InputType(Class[] types) { if(types!=null) {for (Class t:types) { inputData.add(t); } } } /** * 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 * @param restJob * @return */ public boolean validFor(RestJob restJob) { if (!validFor(restJob.rsd)) return false; for (Class cl:inputData) { if (!restJob.hasDataOfType(cl)) { return false; } } return true; } public boolean validFor(RestServiceDescription restServiceDescription) { if (!restServiceDescription.inputParams.values().contains(this)) return false; return true; } protected ContentBody utf8StringBody(String content, String type) { Charset utf8 = Charset.forName("UTF-8"); try { if (type==null ) { return new StringBody(utf8.encode(content).asCharBuffer().toString()); } else { return new StringBody(utf8.encode(content).asCharBuffer().toString(), type, utf8); } } catch (Exception ex) { System.err.println("Couldn't transform string\n"+content+"\nException was :"); ex.printStackTrace(System.err); } return null; } /** * * @param rj data from which input is to be extracted and formatted * @return StringBody or FileBody ready for posting */ abstract public ContentBody formatForInput(RestJob rj) throws UnsupportedEncodingException,NoValidInputDataException; /** * * @return true if no input data needs to be provided for this parameter */ public boolean isConstant() { return (inputData==null || inputData.size()==0); } /** * return a url encoded version of this parameter's value, or an empty string if the parameter has no ='value' content. * @return */ public abstract List getURLEncodedParameter(); /** * set the property known as tok, possibly by assigning it with a given val * @param tok * @param val (may be empty or null) * @param warnings place where parse warnings are reported * @return true if property was set */ public abstract boolean configureProperty(String tok, String val, StringBuffer warnings); /** * Get unique key for this type of parameter in a URL encoding. * @return the string that prefixes an input parameter of InputType type in the string returned from getURLEncodedParameter */ public abstract String getURLtokenPrefix(); /** * parse the given token String and set InputParameter properties appropriately * @param tokenstring - urlencoded parameter string as returned from getURLEncodedParameter * @param warnings - place where any warning messages about bad property values are written * @return true if configuration succeeded, false otherwise. */ public boolean configureFromURLtokenString(List tokenstring, StringBuffer warnings) { boolean valid=true; for (String tok:tokenstring) { Matcher mtch = Pattern.compile("^([^=]+)=?'?([^']*)?'?").matcher(tok); if (mtch.find()) { try { if (mtch.group(1).equals("min")) { min = Integer.parseInt(mtch.group(2)); continue; } else if (mtch.group(1).equals("max")) { max = Integer.parseInt(mtch.group(2)); continue; } } catch (NumberFormatException x) { valid=false; warnings.append("Invalid value for parameter "+mtch.group(1).toLowerCase()+" '"+mtch.group(2)+"' (expected an integer)\n"); } valid = valid && configureProperty(mtch.group(1), mtch.group(2), warnings); } } return valid; } public void addBaseParams(ArrayList prms) { // todo : check if replaceids should be a global for the service, rather than for a specific parameter. if (min!=1) { prms.add("min='"+min+"'"); } if (max!=0) { prms.add("min='"+max+"'"); } } }