# HG changeset patch # User Sascha L. Teichmann # Date 1306248405 0 # Node ID 07640ab913fd5f238042a0b71c19c5562f0f4776 # Parent a9af60c84dcae39ca4e9195d8196183c8d6c0b2a First part of storing qs in ranges flys-artifacts/trunk@1997 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r a9af60c84dca -r 07640ab913fd flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Tue May 24 13:24:24 2011 +0000 +++ b/flys-artifacts/ChangeLog Tue May 24 14:46:45 2011 +0000 @@ -1,3 +1,20 @@ +2011-05-24 Sascha L. Teichmann + + * src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory.java: + Moved cache name to WstValueTableCacheKey. Do not cache null references. + + * src/main/java/de/intevation/flys/artifacts/model/WstValueTableCacheKey.java: + Moved cache name into this class. + + * src/main/java/de/intevation/flys/artifacts/model/WstValueTable.java: + Store QRangeTree for each column of value table. TODO: Use them! + + * src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory2.java: + Intended as a replacement for WstValueTableFactory, but is work in progress. + + * src/main/java/de/intevation/flys/artifacts/model/QRangeTree.java: Fixed + index errors and added methods to dump as graphviz graph. + 2011-05-24 Ingo Weinzierl * src/main/java/de/intevation/flys/artifacts/states/WQSelect.java: diff -r a9af60c84dca -r 07640ab913fd flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QRangeTree.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QRangeTree.java Tue May 24 13:24:24 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/QRangeTree.java Tue May 24 14:46:45 2011 +0000 @@ -105,7 +105,7 @@ public QRangeTree() { } - /** wstQRanges need to sorted by range.a */ + /** wstQRanges need to be sorted by range.a */ public QRangeTree(List wstQRanges) { if (wstQRanges.isEmpty()) { @@ -124,23 +124,52 @@ wstQRange.getQ().doubleValue()); } + root = wireTree(nodes); + } + + public QRangeTree(List qRanges, int start, int stop) { + + if (stop <= start) { + return; + } + + Node [] nodes = new Node[stop-start]; + for (int i = 0; i < nodes.length; ++i) { + Object [] qRange = qRanges.get(i + start); + Double q = (Double)qRange[1]; + Double a = (Double)qRange[2]; + Double b = (Double)qRange[3]; + + nodes[i] = new Node( + a != null ? a.doubleValue() : -Double.MAX_VALUE, + b != null ? b.doubleValue() : Double.MAX_VALUE, + q.doubleValue()); + } + + root = wireTree(nodes); + } + + protected static Node wireTree(Node [] nodes) { for (int i = 0; i < nodes.length; ++i) { Node node = nodes[i]; if (i > 0 ) node.prev = nodes[i-1]; if (i < nodes.length-1) node.next = nodes[i+1]; } - root = buildTree(nodes, 0, nodes.length-1); + return buildTree(nodes, 0, nodes.length-1); } protected static Node buildTree(Node [] nodes, int lo, int hi) { + + if (lo > hi) { + return null; + } + int mid = (lo + hi) >> 1; Node parent = nodes[mid]; - if (hi > lo) { - parent.left = buildTree(nodes, lo, mid-1); - parent.right = buildTree(nodes, mid+1, hi); - } + parent.left = buildTree(nodes, lo, mid-1); + parent.right = buildTree(nodes, mid+1, hi); return parent; } @@ -148,5 +177,40 @@ public double findQ(double pos) { return root != null ? root.findQ(pos) : Double.NaN; } + + private static final String name(Object o) { + return String.valueOf(System.identityHashCode(o) & 0xffffffffL); + } + + public String toGraph() { + StringBuilder sb = new StringBuilder(); + sb.append("subgraph c"); + sb.append(name(this)); + sb.append(" {\n"); + if (root != null) { + java.util.Stack stack = new java.util.Stack(); + stack.push(root); + while (!stack.empty()) { + Node current = stack.pop(); + String name = "n" + name(current); + sb.append(name); + sb.append(" [label=\""); + sb.append(current.a).append(", ").append(current.b); + sb.append(": ").append(current.q).append("\"]\n"); + if (current.left != null) { + String leftName = name(current.left); + sb.append(name).append(" -- n").append(leftName).append("\n"); + stack.push(current.left); + } + if (current.right != null) { + String rightName = name(current.right); + sb.append(name).append(" -- n").append(rightName).append("\n"); + stack.push(current.right); + } + } + } + sb.append("}\n"); + return sb.toString(); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r a9af60c84dca -r 07640ab913fd flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTable.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTable.java Tue May 24 13:24:24 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTable.java Tue May 24 14:46:45 2011 +0000 @@ -30,6 +30,8 @@ { protected String name; + protected QRangeTree qRangeTree; + public Column() { } @@ -44,6 +46,14 @@ public void setName(String name) { this.name = name; } + + public QRangeTree getQRangeTree() { + return qRangeTree; + } + + public void setQRangeTree(QRangeTree qRangeTree) { + this.qRangeTree = qRangeTree; + } } // class Column diff -r a9af60c84dca -r 07640ab913fd flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableCacheKey.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableCacheKey.java Tue May 24 13:24:24 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableCacheKey.java Tue May 24 14:46:45 2011 +0000 @@ -5,6 +5,8 @@ public final class WstValueTableCacheKey implements Serializable { + public static final String CACHE_NAME = "wst-value-table"; + private int riverId; private int kind; diff -r a9af60c84dca -r 07640ab913fd flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory.java Tue May 24 13:24:24 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory.java Tue May 24 14:46:45 2011 +0000 @@ -28,8 +28,6 @@ { private static Logger log = Logger.getLogger(WstValueTableFactory.class); - public static final String CACHE_NAME = "wst-value-table"; - // TODO: put this into a property file public static final String SQL_POS_WQ = "SELECT position, w, q, column_pos" + @@ -45,7 +43,7 @@ public static WstValueTable getTable(River river, int kind) { - Cache cache = CacheFactory.getCache(CACHE_NAME); + Cache cache = CacheFactory.getCache(WstValueTableCacheKey.CACHE_NAME); WstValueTableCacheKey cacheKey; @@ -63,7 +61,7 @@ WstValueTable valueTable = getTableUncached(river, kind); - if (cacheKey != null) { + if (valueTable != null && cacheKey != null) { log.debug("store wst value table in cache"); Element element = new Element(cacheKey, valueTable); cache.put(element); diff -r a9af60c84dca -r 07640ab913fd flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory2.java Tue May 24 14:46:45 2011 +0000 @@ -0,0 +1,186 @@ +package de.intevation.flys.artifacts.model; + +import java.util.List; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import de.intevation.flys.artifacts.cache.CacheFactory; + +import de.intevation.flys.backend.SessionHolder; + +import org.apache.log4j.Logger; + +import de.intevation.flys.model.River; +import de.intevation.flys.model.Wst; + +import org.hibernate.Session; +import org.hibernate.Query; +import org.hibernate.SQLQuery; + +import org.hibernate.type.StandardBasicTypes; + +public class WstValueTableFactory2 +{ + private static Logger log = Logger.getLogger(WstValueTableFactory2.class); + + public static final int DEFAULT_KIND = 0; + + // TODO: put this into a property file + + public static final String HQL_WST = + "from Wst where river=:river and kind=:kind"; + + public static final String SQL_SELECT_NAMES_POS = + "SELECT position, name FROM wst_columns " + + "WHERE wst_id = :wst_id ORDER BY position"; + + public static final String SQL_SELECT_QS = + "SELECT column_pos, q, a, b FROM wst_q_values " + + "WHERE wst_id = :wst_id"; + + public static final String SQL_SELECT_WS = + "SELECT km, w, column_pos FROM wst_w_values " + + "WHERE wst_id = :wst_id"; + + private WstValueTableFactory2() { + } + + public static WstValueTable getTable(River river) { + return getTable(river, DEFAULT_KIND); + } + + public static WstValueTable getTable(River river, int kind) { + + Cache cache = CacheFactory.getCache(WstValueTableCacheKey.CACHE_NAME); + + WstValueTableCacheKey cacheKey; + + if (cache != null) { + cacheKey = new WstValueTableCacheKey(river.getId(), kind); + Element element = cache.get(cacheKey); + if (element != null) { + log.debug("got wst value table from cache"); + return (WstValueTable)element.getValue(); + } + } + else { + cacheKey = null; + } + + WstValueTable valueTable = getTableUncached(river, kind); + + if (valueTable != null && cacheKey != null) { + log.debug("store wst value table in cache"); + Element element = new Element(cacheKey, valueTable); + cache.put(element); + } + + return valueTable; + } + + public static WstValueTable getTableUncached(River river) { + return getTableUncached(river, DEFAULT_KIND); + } + + public static WstValueTable getTableUncached(River river, int kind) { + + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery(HQL_WST); + query.setParameter("river", river); + query.setInteger("kind", kind); + + List wsts = query.list(); + + if (wsts.isEmpty()) { + return null; + } + + Wst wst = wsts.get(0); + + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_NAMES_POS) + .addScalar("position", StandardBasicTypes.INTEGER) + .addScalar("name", StandardBasicTypes.STRING); + + sqlQuery.setInteger("wst_id", wst.getId()); + + List columnNames = sqlQuery.list(); + + WstValueTable.Column [] columns = + new WstValueTable.Column[columnNames.size()]; + + for (int i = 0; i < columns.length; ++i) { + columns[i] = new WstValueTable.Column( + (String)columnNames.get(i)[1]); + } + + sqlQuery = session.createSQLQuery(SQL_SELECT_QS) + .addScalar("column_pos", StandardBasicTypes.INTEGER) + .addScalar("q", StandardBasicTypes.DOUBLE) + .addScalar("a", StandardBasicTypes.DOUBLE) + .addScalar("b", StandardBasicTypes.DOUBLE); + + sqlQuery.setInteger("wst_id", wst.getId()); + + Integer lastColumn = null; + + List qRanges = sqlQuery.list(); + int start = -1; + + int Q = qRanges.size(); + + for (int i = 0; i < Q; ++i) { + Object [] qRange = qRanges.get(i); + Integer columnId = (Integer)qRange[0]; + if (lastColumn == null) { + lastColumn = columnId; + start = i; + } + else if (!lastColumn.equals(columnId)) { + QRangeTree qRangeTree = new QRangeTree(qRanges, start, i); + columns[lastColumn].setQRangeTree(qRangeTree); + lastColumn = columnId; + start = i; + } + } + + if (start != -1) { + QRangeTree qRangeTree = new QRangeTree(qRanges, start, Q); + columns[lastColumn].setQRangeTree(qRangeTree); + } + + /* This is debug code to visualize the q ranges trees + + java.io.PrintWriter out = null; + try { + out = new java.io.PrintWriter( + new java.io.FileWriter( + "/tmp/qranges" + System.currentTimeMillis() + ".dot")); + + out.println("graph \"Q ranges trees\" {"); + + for (int i = 0; i < columns.length; ++i) { + QRangeTree tree = columns[i].getQRangeTree(); + out.println(tree.toGraph()); + } + + out.println("}"); + + out.flush(); + } + catch (java.io.IOException ioe) { + log.error(ioe); + } + finally { + if (out != null) { + out.close(); + } + } + */ + // TODO: Implement me! + + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :