package io.myweb.processor.model; import com.google.common.base.Joiner; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; import java.util.*; import io.myweb.Endpoint; import io.myweb.http.Method; public class ParsedMethod { public static final String MINUS_DEFAULT = "-1"; public static final String ZERO_LENGTH_DEFAULT = ""; public static final String EMPTY_DEFAULT = "[]"; public static final String NULL_DEFAULT = "null"; public static final String FALSE_DEFAULT = "false"; public static Map<String,String> DEFAULT_VALUES; static { Map<String, String> m = new HashMap<String, String>(10); m.put(Integer.class.getName(), MINUS_DEFAULT); m.put(Long.class.getName(), MINUS_DEFAULT); m.put(Float.class.getName(), MINUS_DEFAULT); m.put(Double.class.getName(), MINUS_DEFAULT); m.put(String.class.getName(), ZERO_LENGTH_DEFAULT); m.put(Boolean.class.getName(), FALSE_DEFAULT); m.put(Object.class.getName(), NULL_DEFAULT); m.put(JSONArray.class.getName(), EMPTY_DEFAULT); m.put(JSONObject.class.getName(), NULL_DEFAULT); DEFAULT_VALUES = Collections.unmodifiableMap(m); } private final String destClass; private final String destMethod; private final String destMethodRetType; private final List<ParsedParam> params; private final Method httpMethod; private final String httpUri; private final String produces; private final ServiceParam service; public ParsedMethod(String destClass, String destMethod, String destMethodRetType, List<ParsedParam> params, Method httpMethod, String httpUri, String produces, ServiceParam service) { this.destClass = destClass; this.destMethod = destMethod; this.destMethodRetType = destMethodRetType; this.params = Collections.unmodifiableList(params); this.httpMethod = httpMethod; this.httpUri = httpUri; this.produces = produces; this.service = service; } public String getDestClassSimple() { return getDestClass().substring(getDestClass().lastIndexOf(".") + 1).trim(); } public String getGeneratedClassName() { return getDestClassSimple() + "_" + getDestMethod(); } public String getDestClass() { return destClass; } public String getDestMethod() { return destMethod; } public String getDestMethodRetType() { return destMethodRetType; } public List<ParsedParam> getParsedParams() { return params; } public String getHttpMethod() { return httpMethod.toString(); } public String getHttpUri() { return httpUri; } public String getProduces() { return produces; } public ServiceParam getService() { return service; } public boolean isServicePresent() { return service != null; } public GeneratedPattern getGeneratedPattern() { // TODO handle errors String pathNoParams = cutParamsFromUrl(getHttpUri()); String[] pathSplit = pathNoParams.split("/"); StringBuilder patternSb = new StringBuilder(); List<GroupMapping> groupMapping = new LinkedList<GroupMapping>(); if (pathSplit.length == 0) { patternSb.append("[/]?"); } else { int curGroup = 1; // group indexing in regex starts from 1 for (String pathElm : pathSplit) { if ("".equals(pathElm)) { // NOP } else if (pathElm.startsWith(":")) { groupMapping.add(new GroupMapping(pathElm.substring(1), curGroup)); patternSb.append("/([^/]+)"); curGroup++; } else if (pathElm.startsWith("*")) { groupMapping.add(new GroupMapping(pathElm.substring(1), curGroup)); patternSb.append("[/]?(.*?)"); curGroup++; } else { patternSb.append("/").append(pathElm); } } } return new GeneratedPattern(patternSb.toString(), groupMapping); } public List<DefaultQueryParams> getDefaultQueryParams() { String queryString = queryParams(getHttpUri()); String[] nameAndValues = queryString.split("&"); List<DefaultQueryParams> result = new LinkedList<DefaultQueryParams>(); for (String nameAndVal : nameAndValues) { if (!"".equals(nameAndVal)) { String name, value; int idx = nameAndVal.indexOf("="); if (idx<0) { name = nameAndVal; value = ""; } else { name = nameAndVal.substring(0, idx); value = nameAndVal.substring(idx + 1, nameAndVal.length()); } if(name.startsWith(":")) name = name.substring(1); ParsedParam param = getParsedParamByName(name); if (param != null) { String typeName = toComplexTypeName(param.getTypeName()); if (value.length()==0) { value = DEFAULT_VALUES.get(typeName); } else if (!typeName.equals(String.class.getName())) { // check if default value type is OK try { Object obj = new JSONTokener(value).nextValue(); if (!Endpoint.classForName(typeName).isAssignableFrom(obj.getClass())) { throw new RuntimeException("Default value (" + value + ") for parameter " + name + " is not assignable!"); } } catch (JSONException e) { throw new RuntimeException("Invalid default value (" + value + ") for parameter " + name + "!",e); } catch (ClassNotFoundException e) { throw new RuntimeException(e.getMessage(),e); } } } result.add(new DefaultQueryParams(name, value)); } } return result; } private ParsedParam getParsedParamByName(String name) { for (ParsedParam param: params) { if (param.getName().equals(name)) return param; } return null; } private String queryParams(String url) { int i = url.indexOf("?"); String queryParams; if (i == -1) { queryParams = ""; } else { queryParams = url.substring(i + 1); } return queryParams; } private String cutParamsFromUrl(String url) { int i = url.indexOf("?"); String pattern; if (i == -1) { pattern = url; } else { pattern = url.substring(0, i); } return pattern; } public String getParamsJavaSrc() { String[] p = new String[params.size()]; int i = 0; for (ParsedParam param : params) { p[i++] = paramToJavaSrc(param); } return Joiner.on(", ").join(p); } private String paramToJavaSrc(ParsedParam param) { return "(" + toComplexTypeName(param.getTypeName()) + ")" + "ap[" + param.getId() + "].getVal()"; } private static String toComplexTypeName(String typeName) { if ("int".equals(typeName)) return Integer.class.getName(); if ("long".equals(typeName)) return Long.class.getName(); if ("float".equals(typeName)) return Float.class.getName(); if ("double".equals(typeName)) return Double.class.getName(); if ("boolean".equals(typeName)) return Boolean.class.getName(); return typeName; } }