package com.aggrepoint.dao; import java.lang.reflect.Method; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.aggrepoint.dao.annotation.Like; import com.aggrepoint.dao.annotation.Replace; /** * * @author Jiangming Yang (yangjm@gmail.com) * */ public class QueryPart { static Pattern P_PARAM = Pattern .compile(":([\\w\\d]+(\\___[\\w\\d\\_]+)?(\\[.*\\])?)"); static Pattern P_REPLACE = Pattern.compile("^[\\w\\d\\s\\.,=]*$"); boolean optional; String part; String[] paramDepends; Hashtable<String, String> replace = new Hashtable<String, String>(); Hashtable<String, String> depends = new Hashtable<String, String>(); public QueryPart(Method method, boolean optional, String part, HashSet<String> params, Hashtable<String, Like> likes, Hashtable<String, Replace> replaces, Hashtable<String, Func> funcs) { this.optional = optional; this.part = part; HashSet<String> vecParam = new HashSet<String>(); Matcher m = P_PARAM.matcher(part); while (m.find()) { String p = m.group(1); if (funcs.containsKey(p)) { depends.put(m.group(0), p); continue; } else if (params.contains(p) || likes.containsKey(p)) { vecParam.add(p); continue; } else if (replaces.containsKey(p)) { replace.put(m.group(0), p); continue; } throw new IllegalArgumentException( "Hql reference an undefined parameter '" + p + "' on " + method.getDeclaringClass().getName() + "." + method.getName()); } paramDepends = vecParam.toArray(new String[vecParam.size()]); } public String[] getParamDepends() { return paramDepends; } static boolean nullOrEmptyArray(Object o) { if (o == null) return true; if (o.getClass().isArray()) { return (((Object[]) o).length == 0); } return false; } public String get(HashMap<String, Object> values) { if (optional) { for (String param : paramDepends) { Object v = values.get(param); if (nullOrEmptyArray(v)) return null; } // replace - can't be null for (String param : replace.values()) if (nullOrEmptyArray(values.get(param))) return null; // function - can't be null for (String func : depends.values()) if (nullOrEmptyArray(values.get(func))) return null; } String part = this.part; for (String r : replace.keySet()) { // SQL Injection handling Object val = values.get(replace.get(r)); if (val == null) val = ""; String str = val.toString(); if (!P_REPLACE.matcher(str).find()) throw new IllegalArgumentException( "Invalid characters are used in replace string: '" + str + "'."); part = part.replaceAll(r, str); } for (String func : depends.keySet()) { Object val = values.get(depends.get(func)); if (val == null) val = ""; String str = val.toString(); part = part.replaceAll(Pattern.quote(func), str); } return part; } }