view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTableFactory.java @ 632:07640ab913fd

First part of storing qs in ranges flys-artifacts/trunk@1997 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 24 May 2011 14:46:45 +0000
parents e3ee131d5dd3
children d08f77e7f7e8
line wrap: on
line source
package de.intevation.flys.artifacts.model;

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);

    // 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";

    private WstValueTableFactory() {
    }

    public static WstValueTable getTable(River river) {
        return getTable(river, 0);
    }

    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, 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);
        }

        // XXX: should not be necessary
        valueTable.sortRows();

        return valueTable;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org