Mercurial > dive4elements > river
diff flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory.java @ 443:5d65fe4c08d5
Separated the WST table loading logic from the calculations.
flys-artifacts/trunk@1931 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 17 May 2011 08:55:38 +0000 |
parents | |
children | 523a256451cd |
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/model/WstValueTableFactory.java Tue May 17 08:55:38 2011 +0000 @@ -0,0 +1,193 @@ +package de.intevation.flys.artifacts.model; + +import java.io.Serializable; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Collections; + +import org.hibernate.Session; +import org.hibernate.Query; +import org.hibernate.SQLQuery; + +import org.hibernate.type.StandardBasicTypes; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.apache.log4j.Logger; + +import de.intevation.flys.model.River; +import de.intevation.flys.model.Wst; +import de.intevation.flys.model.WstColumn; + +import de.intevation.flys.artifacts.cache.CacheFactory; + +import de.intevation.flys.backend.SessionHolder; + +public class WstValueTableFactory +{ + 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" + + " FROM wst_value_table" + + " WHERE wst_id = :wst_id"; + + public static final class CacheKey + implements Serializable + { + private int riverId; + private int kind; + + public CacheKey(int riverId, int kind) { + this.riverId = riverId; + this.kind = kind; + } + + public int hashCode() { + return (riverId << 8) | kind; + } + + public boolean equals(Object other) { + if (!(other instanceof CacheKey)) { + return false; + } + CacheKey o = (CacheKey)other; + return riverId == o.riverId && kind == o.kind; + } + } // class CacheKey + + private WstValueTableFactory() { + } + + public static WstValueTable getTable(River river) { + return getTable(river, 0); + } + + public static WstValueTable getTable(River river, int kind) { + + Cache cache = CacheFactory.getCache(CACHE_NAME); + + CacheKey cacheKey; + + if (cache != null) { + cacheKey = new CacheKey(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 (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, int kind) { + + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from Wst where river=:river and kind=:kind"); + query.setParameter("river", river); + query.setInteger("kind", kind); + + List<Wst> wsts = query.list(); + + if (wsts.isEmpty()) { + return null; + } + + Wst wst = wsts.get(0); + + // TODO: Do this sorting at database level + List<WstColumn> wstColumns = new ArrayList(wst.getColumns()); + Collections.sort(wstColumns, new Comparator<WstColumn>() { + public int compare(WstColumn a, WstColumn b) { + int pa = a.getPosition(); + int pb = b.getPosition(); + if (pa < pb) return -1; + if (pa > pb) return +1; + return 0; + } + }); + + WstValueTable.Column [] columns = + new WstValueTable.Column[wstColumns.size()]; + + for (int i = 0; i < columns.length; ++i) { + columns[i] = new WstValueTable.Column(wstColumns.get(i).getName()); + } + + // using native SQL here to avoid myriad of small objects. + SQLQuery sqlQuery = session.createSQLQuery(SQL_POS_WQ) + .addScalar("position", StandardBasicTypes.DOUBLE) + .addScalar("w", StandardBasicTypes.DOUBLE) + .addScalar("q", StandardBasicTypes.DOUBLE) + .addScalar("column_pos", StandardBasicTypes.INTEGER); + + sqlQuery.setInteger("wst_id", wst.getId()); + + WstValueTable valueTable = new WstValueTable(columns); + + int lastColumnNo = -1; + WstValueTable.Row row = null; + + Double lastQ = -Double.MAX_VALUE; + boolean qSorted = true; + + for (Object r: sqlQuery.list()) { + Object[] result = (Object[]) r; + + double km = (Double) result[0]; + Double w = (Double) result[1]; + Double q = (Double) result[2]; + int columnNo = (Integer)result[3]; + + if (columnNo > lastColumnNo) { // new row + if (row != null) { + row.qSorted = qSorted; + valueTable.rows.add(row); + } + row = new WstValueTable.Row( + km, + new double[columnNo+1], + new double[columnNo+1]); + lastQ = -Double.MAX_VALUE; + qSorted = true; + } + + row.ws[columnNo] = w != null ? w : Double.NaN; + row.qs[columnNo] = q != null ? q : Double.NaN; + + if (qSorted && (q == null || lastQ > q)) { + qSorted = false; + } + lastQ = q; + + lastColumnNo = columnNo; + } + + if (row != null) { + valueTable.rows.add(row); + } + + return valueTable; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :