package net.codjo.dataprocess.server.util; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Un parametre est notifi� par ${name} dans la requete. L'espace est obligatoire apr�s } * * Evolution : pouvoir mettre des expression java et un context * * ${System.currentTimeMillis()} ${age<18} */ public class ExtendedPreparedStatement { private static final String SELECT_PARAM_REGXEXP = "(\\$\\{[\\w|\\.]+\\})"; private Map<String, Object> parameters = new HashMap<String, Object>(); private Map<String, List<Integer>> parametersPositions = new HashMap<String, List<Integer>>(); private String originalSql; private String compiledSql; public ExtendedPreparedStatement(String sql) { originalSql = sql; compiledSql = compileSql(originalSql, parametersPositions); } public void setParameterValues(Object... args) throws IllegalArgumentException { if (args.length == 0 || args.length % 2 != 0) { throw new IllegalArgumentException( "args parameter must be like: setParameterValues(\"key1\",value1,\"key2\",value2 ... and so on"); } for (int index = 0; index < args.length / 2; index++) { String key = (String)args[index * 2]; Object value = args[index * 2 + 1]; setParameterValue(key, value); } } public void setParameterValue(String name, Object value) throws IllegalArgumentException { if (parametersPositions.get(name) == null) { throw new IllegalArgumentException("Unknown parameter name : '" + name + "'"); } parameters.put(name, value); } public PreparedStatement createAndSetPreparedStatement(Connection connection) throws SQLException { PreparedStatement preparedStatement = connection.prepareStatement(compiledSql); for (Entry<String, List<Integer>> entry : parametersPositions.entrySet()) { List<Integer> positions = entry.getValue(); Object value = parameters.get(entry.getKey()); for (int currentPosition : positions) { preparedStatement.setObject(currentPosition, value); } } return preparedStatement; } protected ExtendedPreparedStatement() { } protected String compileSql(String sql, Map<String, List<Integer>> positions) { StringBuilder resultSql = new StringBuilder(); int startPosition = 0; Pattern pattern = Pattern.compile(SELECT_PARAM_REGXEXP); Matcher matcher = pattern.matcher(sql); int groupIndex = 0; while (matcher.find()) { int matchedStart = matcher.start(); String matchedGroup = matcher.group(); resultSql.append(sql.substring(startPosition, matchedStart)); resultSql.append("?"); startPosition = matchedStart + matchedGroup.length(); String varName = matchedGroup.substring(2); varName = varName.substring(0, varName.length() - 1); List<Integer> positionList = positions.get(varName); if (positionList == null) { positionList = new ArrayList<Integer>(); positions.put(varName, positionList); } positionList.add(groupIndex + 1); groupIndex++; } resultSql.append(sql.substring(startPosition)); return resultSql.toString(); } public String getOriginalSql() { return originalSql; } public String getCompiledSql() { return compiledSql; } }