teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts.model.minfo; raimund@3614: raimund@3614: raimund@3614: import java.util.List; raimund@3614: raimund@3614: import net.sf.ehcache.Cache; raimund@3614: import net.sf.ehcache.Element; raimund@3614: raimund@3614: import org.apache.log4j.Logger; raimund@3614: import org.hibernate.SQLQuery; raimund@3614: import org.hibernate.Session; raimund@3614: import org.hibernate.type.StandardBasicTypes; raimund@3614: teichmann@5831: import org.dive4elements.river.artifacts.cache.CacheFactory; teichmann@5831: import org.dive4elements.river.backend.SessionHolder; raimund@3614: felix@6765: felix@6765: /** Create BedHeights from database. */ raimund@3614: public class BedHeightFactory { teichmann@8202: /** Private log to use here. */ raimund@3614: private static Logger log = Logger.getLogger(BedHeightFactory.class); raimund@3614: raimund@3614: /** Query to get km and ws for wst_id and column_pos. */ raimund@3614: public static final String SQL_SELECT_SINGLE = tom@8554: "SELECT bhsv.height, bhsv.station, bhsv.data_gap," + tom@8554: " bhsv.sounding_width, bhs.year" + raimund@3897: " FROM bed_height_single bhs" + andre@8544: " JOIN bed_height_single_values bhsv on bhsv.bed_height_single_id = bhs.id"; andre@8544: andre@8544: public static final String ID_CLAUSE = rrenkert@6275: " WHERE bhs.id = :height_id" + rrenkert@6275: " ORDER BY bhsv.station"; rrenkert@6275: andre@8544: public static final String ID_STATION_CLAUSE = andre@8544: " WHERE bhs.id = :height_id AND" + andre@8544: " bhsv.station BETWEEN :fromkm AND :tokm" + andre@8544: " ORDER BY bhsv.station"; raimund@3614: raimund@3614: /** Query to get name (description) for wst_id. */ raimund@3614: public static final String SQL_SELECT_DESCR_SINGLE = raimund@3614: "SELECT description FROM bed_height_single "+ raimund@3614: "WHERE id = :height_id"; raimund@3614: raimund@3614: private BedHeightFactory() { raimund@3614: } raimund@3614: raimund@3614: /** felix@7391: * Get BedHeightData for given type and height_id, caring about the cache. andre@8544: * If from or to are NaN all values are returned. Otherwise only get andre@8544: * values with stations between from and to. raimund@3614: */ andre@8544: public static BedHeightData getHeight(String type, int height_id, double from, double to) { raimund@3614: log.debug("BedHeightFactory.getHeight"); tom@8151: Cache cache = CacheFactory.getCache("bedheight-value-table-static"); raimund@3614: andre@8544: String cacheKey = Integer.toString(height_id) + ":" + andre@8544: Double.toString(from) + ":" + Double.toString(to); raimund@3614: raimund@3614: if (cache != null) { andre@8544: /* We could be more intelligent here and reuse cached values for andre@8544: * a complete river and filter the other stations out afterwards. andre@8544: * It might even be better to cache all values first and filter andre@8544: * later. */ raimund@3614: Element element = cache.get(cacheKey); raimund@3614: if (element != null) { raimund@3614: log.debug("Got static bedheight values from cache"); felix@7391: return (BedHeightData)element.getValue(); raimund@3614: } raimund@3614: } raimund@3614: else { raimund@3614: cacheKey = null; raimund@3614: } raimund@3614: andre@8544: BedHeightData values = getBedHeightUncached(type, height_id, from, to); raimund@3614: raimund@3614: if (values != null && cacheKey != null) { raimund@3614: log.debug("Store static bed height values in cache."); raimund@3614: Element element = new Element(cacheKey, values); raimund@3614: cache.put(element); raimund@3614: } raimund@3614: return values; raimund@3614: } raimund@3614: andre@8544: /** andre@8544: * Get BedHeightData for given type and height_id, caring about the cache. andre@8544: */ andre@8544: public static BedHeightData getHeight(String type, int height_id) { andre@8544: return getHeight(type, height_id, Double.NaN, Double.NaN); andre@8544: } andre@8544: felix@6563: /** Get name for a BedHeight. */ raimund@3614: public static String getHeightName(String type, int height_id) { raimund@3614: log.debug("BedHeightFactory.getHeightName height_id/" + height_id); raimund@3614: raimund@3614: String name = null; raimund@3614: Session session = SessionHolder.HOLDER.get(); raimund@3614: raimund@3614: SQLQuery nameQuery = null; raimund@3614: if (type.equals("single")) { raimund@3614: nameQuery = session.createSQLQuery(SQL_SELECT_DESCR_SINGLE) raimund@3614: .addScalar("description", StandardBasicTypes.STRING); raimund@3614: nameQuery.setInteger("height_id", height_id); raimund@3614: } raimund@3614: else { raimund@3614: return "none"; raimund@3614: } raimund@3614: List names = nameQuery.list(); teichmann@4051: if (!names.isEmpty()) { raimund@3614: name = names.get(0); raimund@3614: } raimund@3614: raimund@3614: return name; raimund@3614: } raimund@3614: raimund@3614: raimund@3614: /** felix@7391: * Get BedHeightData from db. andre@8544: * andre@8544: * If from or to are negative all stations are returned. Otherwise andre@8544: * only the values with a station betweend from and to. felix@6562: * @param height_id database id of the bed_height andre@8544: * @param from minimum station value or NaN andre@8544: * @param to maximum station value or NaN felix@6562: * @return according BedHeight. raimund@3614: */ felix@7391: public static BedHeightData getBedHeightUncached( raimund@3614: String type, andre@8544: int height_id, andre@8544: double from, andre@8544: double to) raimund@3614: { raimund@3614: if (log.isDebugEnabled()) { raimund@3614: log.debug("BedHeightFactory.getBedHeightUncached"); raimund@3614: } raimund@3614: raimund@3614: Session session = SessionHolder.HOLDER.get(); raimund@3614: SQLQuery sqlQuery = null; raimund@3614: if (type.equals("single")) { tom@8568: BedHeightData height = tom@8568: new BedHeightData(getHeightName(type, height_id)); andre@8544: String queryString = SQL_SELECT_SINGLE; andre@8544: if (Double.isNaN(from) || Double.isNaN(to)) { andre@8544: queryString += ID_CLAUSE; andre@8544: } else { andre@8544: queryString += ID_STATION_CLAUSE; andre@8544: } andre@8544: sqlQuery = session.createSQLQuery(queryString) raimund@3614: .addScalar("height", StandardBasicTypes.DOUBLE) raimund@3614: .addScalar("station", StandardBasicTypes.DOUBLE) raimund@3886: .addScalar("data_gap", StandardBasicTypes.DOUBLE) raimund@3886: .addScalar("sounding_width", StandardBasicTypes.DOUBLE) raimund@3886: .addScalar("year", StandardBasicTypes.INTEGER); raimund@3614: sqlQuery.setInteger("height_id", height_id); andre@8544: if (!Double.isNaN(from) && !Double.isNaN(to)) { andre@8544: sqlQuery.setDouble("fromkm", from); andre@8544: sqlQuery.setDouble("tokm", to); andre@8544: } raimund@3614: List results = sqlQuery.list(); raimund@3614: teichmann@7254: for (Object [] row: results) { raimund@3897: log.debug("got station: " + (Double)row[1]); rrenkert@6352: Double row0 = row[0] != null ? (Double)row[0] : Double.NaN; rrenkert@6352: Double row1 = row[1] != null ? (Double)row[1] : Double.NaN; rrenkert@6352: Double row2 = row[2] != null ? (Double)row[2] : Double.NaN; rrenkert@6352: Double row3 = row[3] != null ? (Double)row[3] : Double.NaN; tom@8554: height.add(row0, row1, row2, row3, (Integer) row[4]); raimund@3614: } raimund@3886: return height; raimund@3614: } felix@7391: return new BedHeightData(); raimund@3614: } raimund@3614: } raimund@3614: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :