package water.api; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Map; import java.util.regex.Pattern; import water.util.Log; import dontweave.gson.JsonElement; import dontweave.gson.JsonObject; /** All statics for the Request api. * * Especially the JSON property names should be defined here. Some helper * functions too. * * @author peta */ public class RequestStatics extends Constants { /** Each request name is derived from name of class serving the request. */ public final String requestName() { return getClass().getSimpleName(); } /** Request type. * * Requests can have multiple types. Basic types include the plain json type * in which the result is returned as a JSON object, a html type that acts as * the webpage, or the help type that displays the extended help for the * request. * * The wiki type is also added that displays the markup of the wiki that * should be used to document the request as per Matt's suggestion. * * NOTE the requests are distinguished by their suffixes. Please make the * suffix start with the dot character to avoid any problems with request * names. */ public static enum RequestType { json(".json"), ///< json type request, a result is a JSON structure www(".html"), ///< webpage request help(".help"), ///< should display the help on the given request query(".query"), ///< Displays the query for the argument in html mode png(".png"), ///< image, e.g. plot txt(".txt"), ///< text, e.g. a script java(".java"), ///< java program xml(".xml"), ///< xml request ; /** Suffix of the request - extension of the URL. */ public final String _suffix; RequestType(String suffix) { _suffix = suffix; } /** Returns the request type of a given URL. JSON request type is the default * type when the extension from the URL cannot be determined. */ public static RequestType requestType(String requestUrl) { if (requestUrl.endsWith(www._suffix)) return www; if (requestUrl.endsWith(help._suffix)) return help; if (requestUrl.endsWith(query._suffix)) return query; if (requestUrl.endsWith(png._suffix)) return png; if (requestUrl.endsWith(txt._suffix)) return txt; if (requestUrl.endsWith(java._suffix)) return java; if (requestUrl.endsWith(xml._suffix)) return xml; return json; } /** Returns the name of the request, that is the request url without the * request suffix. */ public String requestName(String requestUrl) { String result = (requestUrl.endsWith(_suffix)) ? requestUrl.substring(0, requestUrl.length()-_suffix.length()) : requestUrl; return result; } } /** Returns the name of the JSON property pretty printed. That is spaces * instead of underscores and capital first letter. * @param name * @return */ public static String JSON2HTML(String name) { if( name.length() < 1 ) return name; if(name == "row") { return name.substring(0,1).toUpperCase()+ name.replace("_"," ").substring(1); } return name.substring(0,1)+name.replace("_"," ").substring(1); } public static String Str2JSON( String x ) { if( checkJsonName(x) ) return x; StringBuilder sb = new StringBuilder(); byte[] bs = x.getBytes(); if( bs.length==0 || !Character.isJavaIdentifierStart(bs[0]) ) sb.append("x"); for( byte b : bs ) if( Character.isJavaIdentifierPart(b) ) sb.append(Character.toLowerCase((char)b)); else if( Character.isWhitespace(b) ) sb.append('_'); else if( b=='-' ) sb.append('_'); String s = sb.toString(); assert checkJsonName(s); return s; } private static Pattern _correctJsonName = Pattern.compile("^[_a-z][_a-z0-9]*$"); /** Checks if the given JSON name is valid. A valid JSON name is a sequence of * small letters, numbers and underscores that does not start with number. */ public static boolean checkJsonName(String name) { return _correctJsonName.matcher(name).find(); } protected static JsonObject jsonError(String error) { JsonObject result = new JsonObject(); result.addProperty(ERROR, error); return result; } protected static String encodeRedirectArgs(JsonObject args, Object[] args2) { if( args == null && args2 == null ) return ""; if( args2 != null ) { StringBuilder sb = new StringBuilder(); assert (args2.length &1)==0 : "Number of arguments shoud be power of 2."; // Must be field-name / value pairs for( int i=0; i<args2.length; i+=2 ) { sb.append(i==0?'?':'&').append(args2[i]).append('='); try { sb.append(URLEncoder.encode(args2[i+1].toString(),"UTF-8")); } catch( UnsupportedEncodingException ex ) { throw Log.errRTExcept(ex); } } return sb.toString(); } StringBuilder sb = new StringBuilder(); sb.append("?"); for (Map.Entry<String,JsonElement> entry : args.entrySet()) { JsonElement e = entry.getValue(); if (sb.length()!=1) sb.append("&"); sb.append(entry.getKey()); sb.append("="); try { sb.append(URLEncoder.encode(e.getAsString(),"UTF-8")); } catch( UnsupportedEncodingException ex ) { throw Log.errRTExcept(ex); } } return sb.toString(); } }