view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/minfo/SedimentLoadFactory.java @ 4655:cd44d28d0fbc

Move the access to artifact data to the Access object Use BedHeightAccess class to receive the data from the artifact. This abstracts the data access from the actual artifact.
author Björn Ricks <bjoern.ricks@intevation.de>
date Tue, 11 Dec 2012 09:44:04 +0100
parents 2fadc6c5cdad
children b195fede1c3b
line wrap: on
line source
package de.intevation.flys.artifacts.model.minfo;

import gnu.trove.TDoubleArrayList;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.apache.log4j.Logger;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.type.StandardBasicTypes;

import de.intevation.flys.artifacts.cache.CacheFactory;
import de.intevation.flys.artifacts.model.StaticSedimentLoadCacheKey;
import de.intevation.flys.backend.SessionHolder;


public class SedimentLoadFactory
{
    /** Private logger to use here. */
    private static Logger log = Logger.getLogger(SedimentLoadFactory.class);

    public static final String LOADS_CACHE_NAME = "sedimentloads";
    public static final String LOAD_DATA_CACHE_NAME = "sedimentload-data";

    /** Query to get km and ws for wst_id and column_pos. */
    public static final String SQL_SELECT_SINGLES =
        "SELECT DISTINCT " +
        "       sy.description AS description, " +
        "       ti.start_time AS year " +
        "   FROM     sediment_yield sy " +
        "       JOIN rivers r ON sy.river_id = r.id " +
        "       JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " +
        "       JOIN time_intervals ti ON sy.time_interval_id = ti.id " +
        "   WHERE   r.name = :name " +
        "       AND ti.stop_time IS NULL " +
        "       AND syv.station BETWEEN :startKm AND :endKm";

    /** Query to get name for wst_id and column_pos. */
    public static final String SQL_SELECT_EPOCHS =
        "SELECT DISTINCT " +
        "       sy.description AS description, " +
        "       ti.start_time AS start, " +
        "       ti.stop_time AS end " +
        "   FROM     sediment_yield sy " +
        "       JOIN rivers r ON sy.river_id = r.id " +
        "       JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " +
        "       JOIN time_intervals ti ON sy.time_interval_id = ti.id " +
        "   WHERE   r.name = :name " +
        "       AND ti.stop_time IS NOT NULL " +
        "       AND syv.station BETWEEN :startKm AND :endKm";

    public static final String SQL_SELECT_SINGLES_DATA =
        "SELECT" +
        "       sy.description AS description, " +
        "       ti.start_time AS year, " +
        "       syv.value AS load, " +
        "       syv.station AS km " +
        "   FROM     sediment_yield sy " +
        "       JOIN rivers r ON sy.river_id = r.id " +
        "       JOIN time_intervals ti ON sy.time_interval_id = ti.id " +
        "       JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " +
        "       JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " +
        "   WHERE   r.name = :name " +
        "       AND ti.start_time BETWEEN :begin AND :end " +
        "       AND ti.stop_time IS NULL " +
        "       AND gf.name = :grain " +
        "       AND syv.station BETWEEN :startKm AND :endKm";

    public static final String SQL_SELECT_EPOCHS_DATA =
        "SELECT" +
        "       sy.description AS description, " +
        "       ti.start_time AS startYear, " +
        "       syv.value AS load, " +
        "       syv.station AS km," +
        "       ti.stop_time AS endYear " +
        "   FROM     sediment_yield sy " +
        "       JOIN rivers r ON sy.river_id = r.id " +
        "       JOIN time_intervals ti ON sy.time_interval_id = ti.id " +
        "       JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " +
        "       JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " +
        "   WHERE   r.name = :name " +
        "       AND ti.start_time BETWEEN :sbegin AND :send " +
        "       AND ti.stop_time BETWEEN :ebegin AND :eend " +
        "       AND gf.name = :grain " +
        "       AND syv.station BETWEEN :startKm AND :endKm";

    private SedimentLoadFactory() {
    }

    /**
     *
     */
    public static SedimentLoad[] getLoads(
        String river,
        String type,
        double startKm,
        double endKm
    ) {
        log.debug("SedimentLoadFactory.getLoads");
        Cache cache = CacheFactory.getCache(LOADS_CACHE_NAME);

        if (cache == null) {
            log.debug("Cache not configured.");
            return getSedimentLoadsUncached(river, type, startKm, endKm);
        }

        StaticSedimentLoadCacheKey key =
            new StaticSedimentLoadCacheKey(river, startKm, endKm, 0, 0);

        Element element = cache.get(key);

        if (element != null) {
            log.debug("SedimentLoad found in cache");
            return (SedimentLoad[])element.getValue();
        }

        SedimentLoad[] values =
            getSedimentLoadsUncached(river, type, startKm, endKm);

        if (values != null && key != null) {
            log.debug("Store static sediment load values in cache.");
            element = new Element(key, values);
            cache.put(element);
        }
        return values;
    }

    public static SedimentLoad getLoadwithData(
        String river,
        String type,
        double startKm,
        double endKm,
        int syear,
        int eyear
    ) {
        log.debug("SedimentLoadFactory.getLoadWithData");
        Cache cache = CacheFactory.getCache(LOAD_DATA_CACHE_NAME);

        if (cache == null) {
            log.debug("Cache not configured.");
            return getSedimentLoadWithDataUncached(
                river,
                type,
                startKm,
                endKm,
                syear,
                eyear);
        }

        StaticSedimentLoadCacheKey key =
            new StaticSedimentLoadCacheKey(river, startKm, endKm, syear, eyear);

        Element element = cache.get(key);

        if (element != null) {
            log.debug("SedimentLoad found in cache");
            return (SedimentLoad)element.getValue();
        }

        SedimentLoad values = getSedimentLoadWithDataUncached(
            river,
            type,
            startKm,
            endKm,
            syear,
            eyear);

        if (values != null && key != null) {
            log.debug("Store static bed height values in cache.");
            element = new Element(key, values);
            cache.put(element);
        }
        return values;
    }

    /**
     * Get sediment loads from db.
     * @param river the river
     * @param type the sediment load type (year or epoch)
     * @return according sediment loads.
     */
    public static SedimentLoad[] getSedimentLoadsUncached(
        String river,
        String type,
        double startKm,
        double endKm
    ) {
        log.debug("SedimentLoadFactory.getSedimentLoadsUncached");

        Session session = SessionHolder.HOLDER.get();
        SQLQuery sqlQuery = null;

        if (type.equals("single")) {
            sqlQuery = session.createSQLQuery(SQL_SELECT_SINGLES)
                .addScalar("description", StandardBasicTypes.STRING)
                .addScalar("year", StandardBasicTypes.DATE);
            sqlQuery.setString("name", river);
            sqlQuery.setDouble("startKm", startKm);
            sqlQuery.setDouble("endKm", endKm);
            List<Object []> results = sqlQuery.list();
            SedimentLoad[] loads = new SedimentLoad[results.size()];
            for (int i = 0; i < results.size(); i++) {
                Object[] row = results.get(i);
                loads[i] = new SedimentLoad(
                    (String) row[0],
                    (Date) row[1],
                    null,
                    false);
            }
            return loads;
        }
        else if (type.equals("epoch")) {
            sqlQuery = session.createSQLQuery(SQL_SELECT_EPOCHS)
                .addScalar("description", StandardBasicTypes.STRING)
                .addScalar("start", StandardBasicTypes.DATE)
                .addScalar("end", StandardBasicTypes.DATE);
            sqlQuery.setString("name", river);
            sqlQuery.setDouble("startKm", startKm);
            sqlQuery.setDouble("endKm", endKm);
            List<Object []> results = sqlQuery.list();

            SedimentLoad[] loads = new SedimentLoad[results.size()];
            for (int i = 0; i < results.size(); i++) {
                Object[] row = results.get(i);
                loads[i] = new SedimentLoad(
                    (String) row[0],
                    (Date) row[1],
                    (Date) row[2],
                    true);
            }
            return loads;
        }
        return new SedimentLoad[0];
    }

    /**
     * Get sediment loads from db.
     * @param river the river
     * @param type the sediment load type (year or epoch)
     * @return according sediment loads.
     */
    public static SedimentLoad getSedimentLoadWithDataUncached(
        String river,
        String type,
        double startKm,
        double endKm,
        int syear,
        int eyear
    ) {
        log.debug("SedimentLoadFactory.getSedimentLoadWithDataUncached");
        Session session = SessionHolder.HOLDER.get();
        SQLQuery sqlQuery = null;

        Calendar start = Calendar.getInstance();
        start.set(syear - 1, 11, 31);
        Calendar end = Calendar.getInstance();
        end.set(syear, 11, 30);

        if (type.equals("year") || type.equals("epoch")) {
            sqlQuery = session.createSQLQuery(SQL_SELECT_SINGLES_DATA)
                .addScalar("description", StandardBasicTypes.STRING)
                .addScalar("year", StandardBasicTypes.DATE)
                .addScalar("load", StandardBasicTypes.DOUBLE)
                .addScalar("km", StandardBasicTypes.DOUBLE);
            sqlQuery.setString("name", river);
            sqlQuery.setDouble("startKm", startKm);
            sqlQuery.setDouble("endKm", endKm);
            sqlQuery.setDate("begin", start.getTime());
            sqlQuery.setDate("end", end.getTime());
            sqlQuery.setString("grain", "total");
            List<Object []> results = sqlQuery.list();
            SedimentLoad load = new SedimentLoad();
            Object[] row = results.get(0);
            load = new SedimentLoad(
                    (String) row[0],
                    (Date) row[1],
                    null,
                    false);
            getValues("coarse", sqlQuery, load);
            getValues("fine_middle", sqlQuery, load);
            getValues("sand", sqlQuery, load);
            getValues("suspended_sediment", sqlQuery, load);
            getValues("susp_sand_bed", sqlQuery, load);
            getValues("susp_sand", sqlQuery, load);
 
            return load;
        }
        else if (type.equals("off_epoch")) {
            Calendar toStart = Calendar.getInstance();
            toStart.set(eyear - 1, 11, 31);
            Calendar toEnd = Calendar.getInstance();
            toEnd.set(eyear, 11, 30);
            sqlQuery = session.createSQLQuery(SQL_SELECT_EPOCHS_DATA)
                .addScalar("description", StandardBasicTypes.STRING)
                .addScalar("startYear", StandardBasicTypes.DATE)
                .addScalar("load", StandardBasicTypes.DOUBLE)
                .addScalar("km", StandardBasicTypes.DOUBLE)
                .addScalar("endYear", StandardBasicTypes.DATE);
            sqlQuery.setString("name", river);
            sqlQuery.setDouble("startKm", startKm);
            sqlQuery.setDouble("endKm", endKm);
            sqlQuery.setDate("sbegin", start.getTime());
            sqlQuery.setDate("send", end.getTime());
            sqlQuery.setDate("ebegin",toStart.getTime());
            sqlQuery.setDate("eend", toEnd.getTime());
            sqlQuery.setString("grain", "total");

            List<Object[]> results = null;
            results = sqlQuery.list();

            SedimentLoad load = new SedimentLoad();
            Object[] row = results.get(0);
            load = new SedimentLoad(
                    (String) row[0],
                    (Date) row[1],
                    (Date) row[4],
                    true);
            TDoubleArrayList kms = new TDoubleArrayList();
            for (int i = 0; i < results.size(); i++) {
                row = results.get(i);
                kms.add((Double)row[3]);
                load.setLoadTotal((Double)row[3], (Double)row[2]);
            }
            getValues("coarse", sqlQuery, load);
            getValues("fine_middle", sqlQuery, load);
            getValues("sand", sqlQuery, load);
            getValues("suspended_sediment", sqlQuery, load);
            getValues("susp_sand_bed", sqlQuery, load);
            getValues("susp_sand", sqlQuery, load);
            return load;
        }
        return new SedimentLoad();
    }

    /**
     * 
     */
    protected static void getValues (
        String fraction,
        SQLQuery query,
        SedimentLoad load
    ) {
        query.setString("grain", fraction);
        List<Object[]> results = query.list();
        for (int i = 0; i < results.size(); i++) {
            Object[] row = results.get(i);
            double km = (Double)row[3];
            double v = -1;
            if (row[2] != null) {
                v = ((Double)row[2]).doubleValue();
            }
            if (fraction.equals("coarse")) {
                load.setCoarse(km, v);
            }
            else if (fraction.equals("sand")) {
                load.setSand(km, v);
            }
            else if (fraction.equals("fine_middle")) {
                load.setFineMiddle(km, v);
            }
            else if (fraction.equals("suspended_sediment")) {
                load.setSuspSediment(km, v);
            }
            else if (fraction.equals("susp_sand")) {
                load.setSuspSand(km, v);
            }
            else if (fraction.equals("susp_sand_bed")) {
                load.setSuspSandBed(km, v);
            }
        }
    }
}

http://dive4elements.wald.intevation.org