28bfda01d3acd94bb5115c98c511b8df23811440
[jalview.git] / src / jalview / ws / rest / InputType.java
1 package jalview.ws.rest;
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.io.OutputStreamWriter;
6 import java.io.PrintWriter;
7 import java.io.StringWriter;
8 import java.io.UnsupportedEncodingException;
9 import java.nio.charset.Charset;
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.regex.Matcher;
13 import java.util.regex.Pattern;
14
15 import org.apache.http.entity.mime.content.ContentBody;
16 import org.apache.http.entity.mime.content.StringBody;
17
18 import sun.io.CharacterEncoding;
19 import sun.misc.CharacterEncoder;
20
21 /***
22  * InputType is the abstract model of each input parameter that a rest service might take.
23  * It enables the engine to validate input by providing 
24  * { formatter for type, parser for type }
25  *  
26  */
27 public abstract class InputType {
28   /**
29    * not used yet
30    */
31   boolean replaceids;
32   public enum molType { NUC, PROT, MIX}
33   public String token;
34   public int min=1;
35   public int max=0; // unbounded
36   protected ArrayList<Class> inputData=new ArrayList<Class>();
37   /**
38    * initialise the InputType with a list of jalview data classes that the RestJob needs to be able to provide to it. 
39    * @param types
40    */
41   protected InputType(Class[] types)
42   {
43     if(types!=null)
44       {for (Class t:types)
45     {
46       inputData.add(t);
47     }
48       }
49   }
50   /**
51    * 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 
52    * @param restJob
53    * @return
54    */
55   public boolean validFor(RestJob restJob)
56   {
57     if (!validFor(restJob.rsd))
58       return false;
59     for (Class cl:inputData)
60     {
61       if (!restJob.hasDataOfType(cl))
62       {
63         return false;
64       }
65     }
66     return true;
67   }
68   
69   public boolean validFor(RestServiceDescription restServiceDescription)
70   {
71     if (!restServiceDescription.inputParams.values().contains(this))
72       return false;
73     
74     return true;
75   }
76   protected ContentBody utf8StringBody(String content, String type)
77   {
78     Charset utf8 = Charset.forName("UTF-8");
79     try {
80     if (type==null ) {
81       return new StringBody(utf8.encode(content).asCharBuffer().toString());
82     } else {
83       return new StringBody(utf8.encode(content).asCharBuffer().toString(), type, utf8);
84     }
85     } catch (Exception ex)
86     {
87       System.err.println("Couldn't transform string\n"+content+"\nException was :");
88       ex.printStackTrace(System.err);
89     }
90     return null;
91   }
92   /**
93    * 
94    * @param rj data from which input is to be extracted and formatted
95    * @return StringBody or FileBody ready for posting
96    */
97   abstract public ContentBody formatForInput(RestJob rj) throws UnsupportedEncodingException,NoValidInputDataException;
98   /**
99    * 
100    * @return true if no input data needs to be provided for this parameter
101    */
102   public boolean isConstant()
103   {
104     return (inputData==null || inputData.size()==0);
105   }
106   /**
107    * return a url encoded version of this parameter's value, or an empty string if the parameter has no ='value' content.
108    * @return
109    */
110   public abstract List<String> getURLEncodedParameter();
111   
112   /**
113    * set the property known as tok, possibly by assigning it with a given val
114    * @param tok
115    * @param val (may be empty or null)
116    * @param warnings place where parse warnings are reported
117    * @return true if property was set
118    */
119   public abstract boolean configureProperty(String tok, String val, StringBuffer warnings);
120   
121   /**
122    * Get unique key for this type of parameter in a URL encoding.
123    * @return the string that prefixes an input parameter of InputType<T> type in the string returned from getURLEncodedParameter
124    */
125   public abstract String getURLtokenPrefix();
126   /**
127    * parse the given token String and set InputParameter properties appropriately
128    * @param tokenstring - urlencoded parameter string as returned from getURLEncodedParameter
129    * @param warnings - place where any warning messages about bad property values are written
130    * @return true if configuration succeeded, false otherwise.
131    */
132   public boolean configureFromURLtokenString(List<String> tokenstring, StringBuffer warnings) {
133       boolean valid=true;
134       for (String tok:tokenstring)
135       {
136         Matcher mtch = Pattern.compile("^([^=]+)=?'?([^']*)?'?").matcher(tok);
137         if (mtch.find()) {
138           try {
139             if (mtch.group(1).equals("min"))
140             {
141               min = Integer.parseInt(mtch.group(2));
142               continue;
143               
144             } else 
145             if (mtch.group(1).equals("max"))
146             {
147                 max = Integer.parseInt(mtch.group(2));
148                 continue;
149               }
150             }
151           catch (NumberFormatException x)
152               {
153                 valid=false;
154                 warnings.append("Invalid value for parameter "+mtch.group(1).toLowerCase()+" '"+mtch.group(2)+"' (expected an integer)\n");
155             }
156           
157           valid = valid && configureProperty(mtch.group(1), mtch.group(2), warnings);
158         }
159         }
160       return valid;
161   }
162   public void addBaseParams(ArrayList<String> prms)
163   {
164     // todo : check if replaceids should be a global for the service, rather than for a specific parameter.
165     if (min!=1) {
166       prms.add("min='"+min+"'");
167     }
168     if (max!=0) {
169       prms.add("min='"+max+"'");
170     }
171   }
172 }