Mercurial > dive4elements > river
diff flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/CompiledStatement.java @ 998:b81626b10cb7
Datacage: Moved templating in a better suited package.
flys-artifacts/trunk@2434 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 01 Aug 2011 08:31:09 +0000 |
parents | |
children | aca3b46160cb |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/templating/CompiledStatement.java Mon Aug 01 08:31:09 2011 +0000 @@ -0,0 +1,188 @@ +package de.intevation.flys.artifacts.datacage.templating; + +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.ArrayList; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Connection; +import java.sql.ResultSet; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import de.intevation.flys.artifacts.cache.CacheFactory; + +public class CompiledStatement +{ + public static final String DATACAGE_DB_CACHE = + "datacage.db"; + + public static final Pattern VAR = + Pattern.compile("\\$\\{([a-zA-Z0-9_-]+)\\}"); + + protected String original; + protected String statement; + + protected Map<String, List<Integer>> positions; + + protected int numVars; + + public class Instance { + + protected PreparedStatement preparedStatement; + + public Instance() { + } + + protected ResultData executeCached( + Cache cache, + Connection connection, + StackFrames frames + ) + throws SQLException + { + Object [] values = new Object[numVars]; + + StringBuilder sb = new StringBuilder(original); + + for (Map.Entry<String, List<Integer>> entry: positions.entrySet()) { + String key = entry.getKey(); + Object value = frames.get(key); + sb.append(';').append(key).append(':').append(value); + for (Integer index: entry.getValue()) { + values[index] = value; + } + } + + // XXX: Maybe too many collisions? + // String key = original + Arrays.hashCode(values); + String key = sb.toString(); + + Element element = cache.get(key); + + if (element != null) { + return (ResultData)element.getValue(); + } + + if (preparedStatement == null) { + preparedStatement = connection.prepareStatement(statement); + } + + for (int i = 0; i < values.length; ++i) { + preparedStatement.setObject(i+1, values[i]); + } + + ResultData data; + + ResultSet result = preparedStatement.executeQuery(); + try { + data = new ResultData(preparedStatement.getMetaData()) + .addAll(result); + } + finally { + result.close(); + } + + element = new Element(key, data); + cache.put(element); + + return data; + } + + protected ResultData executeUncached( + Connection connection, + StackFrames frames + ) + throws SQLException + { + if (preparedStatement == null) { + preparedStatement = connection.prepareStatement(statement); + } + + for (Map.Entry<String, List<Integer>> entry: positions.entrySet()) { + Object value = frames.get(entry.getKey()); + for (Integer index: entry.getValue()) { + preparedStatement.setObject(index+1, value); + } + } + + ResultSet result = preparedStatement.executeQuery(); + try { + return new ResultData(preparedStatement.getMetaData()) + .addAll(result); + } + finally { + result.close(); + } + } + + public ResultData execute(Connection connection, StackFrames frames) + throws SQLException + { + Cache cache = CacheFactory.getCache(DATACAGE_DB_CACHE); + + return cache != null + ? executeCached(cache, connection, frames) + : executeUncached(connection, frames); + } + + public void close() { + if (preparedStatement != null) { + try { + preparedStatement.close(); + } + catch (SQLException sqle) { + } + preparedStatement = null; + } + } + } // class Instance + + public CompiledStatement() { + } + + public CompiledStatement(String original) { + this.original = original; + // TreeMap to ensure order + positions = new TreeMap<String, List<Integer>>(); + compile(); + } + + protected void compile() { + + StringBuffer sb = new StringBuffer(); + + Matcher m = VAR.matcher(original); + + int index = 0; + + while (m.find()) { + String key = m.group(1); + List<Integer> indices = positions.get(key); + if (indices == null) { + indices = new ArrayList<Integer>(); + positions.put(key, indices); + } + indices.add(index); + m.appendReplacement(sb, "?"); + ++index; + } + + m.appendTail(sb); + + numVars = index; + + statement = sb.toString(); + } + + public String getStatement() { + return statement; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :