raimund@3274: package de.intevation.flys.artifacts.model;
raimund@3274: 
raimund@3274: import java.io.Serializable;
raimund@3274: 
raimund@3274: import java.text.SimpleDateFormat;
raimund@3274: 
raimund@3274: import java.util.ArrayList;
raimund@3274: import java.util.Date;
raimund@3274: import java.util.List;
raimund@3274: 
raimund@3274: import org.apache.log4j.Logger;
raimund@3274: 
raimund@3274: import org.hibernate.SQLQuery;
raimund@3274: import org.hibernate.Session;
raimund@3274: 
raimund@3274: import org.hibernate.type.StandardBasicTypes;
raimund@3274: 
raimund@3274: import org.w3c.dom.Document;
raimund@3274: import org.w3c.dom.Element;
raimund@3274: 
raimund@3274: import de.intevation.flys.utils.KMIndex;
raimund@3274: 
raimund@3274: public class SQOverview
raimund@3274: implements   Serializable
raimund@3274: {
raimund@3274: 
raimund@3274:     /**
sascha@3276:      * Serial version UId.
raimund@3274:      */
raimund@3274:     private static final long serialVersionUID = -8934372438968398508L;
raimund@3274: 
raimund@3274:     public interface Filter {
raimund@3274: 
raimund@3274:         boolean accept(KMIndex<List<Date>> entry);
raimund@3274: 
raimund@3274:     } // interface Filter
raimund@3274: 
raimund@3274: 
raimund@3274:     public static final Filter ACCEPT = new Filter() {
raimund@3274:         @Override
raimund@3274:         public boolean accept(KMIndex<List<Date>> entry) {
raimund@3274:             return true;
raimund@3274:         }
raimund@3274:     };
raimund@3274: 
raimund@3274:     public static class KmFilter implements Filter {
raimund@3274: 
raimund@3274:         protected double km;
raimund@3274: 
raimund@3274:         public KmFilter (double km) {
raimund@3274:             this.km = km;
raimund@3274:         }
raimund@3274:         @Override
raimund@3274:         public boolean accept(KMIndex<List<Date>> list) {
raimund@3274:             for (KMIndex.Entry<List<Date>> e: list){
raimund@3274:                 if (e.getKm() == km) {
raimund@3274:                     return true;
raimund@3274:                 }
raimund@3274:             }
raimund@3274:             return false;
raimund@3274:         }
raimund@3274:     };
raimund@3274: 
raimund@3274:     public static class DateFilter implements Filter {
raimund@3274: 
raimund@3274:         protected Date date;
raimund@3274: 
raimund@3274:         public DateFilter (Date date) {
raimund@3274:             this.date = date;
raimund@3274:         }
raimund@3274:         @Override
raimund@3274:         public boolean accept(KMIndex<List<Date>> list) {
raimund@3274:             for (KMIndex.Entry<List<Date>> e: list){
raimund@3274:                 if (e.getValue().equals(this.date)) {
raimund@3274:                     return true;
raimund@3274:                 }
raimund@3274:             }
raimund@3274:             return false;
raimund@3274:         }
raimund@3274:     };
raimund@3274: 
raimund@3274:     private static Logger log = Logger.getLogger(FixingsOverview.class);
raimund@3274: 
sascha@3275:     public static final double EPSILON = 1e-4;
raimund@3274: 
raimund@3274:     public static final String DATE_FORMAT = "dd.MM.yyyy";
raimund@3274: 
raimund@3274:     public static final String SQL_SQ =
raimund@3274:         "SELECT" +
sascha@3275:         "    s.km    AS km," +
sascha@3275:         "    m.datum AS datum " +
raimund@3274:         "FROM messung m " +
raimund@3274:         "    JOIN station s" +
sascha@3287:         "       ON m.stationid = s.stationid " +
raimund@3274:         "    JOIN gewaesser g " +
sascha@3287:         "       ON s.gewaesserid = g.gewaesserid " +
raimund@3274:         "WHERE" +
sascha@3389:         "    m.q_bpegel IS NOT NULL AND" +
raimund@3274:         "    g.name = :name " +
sascha@3287:         "ORDER by" +
sascha@3287:         "    s.km, m.datum";
raimund@3274: 
raimund@3274:     protected String       riverName;
raimund@3274: 
raimund@3274:     protected KMIndex<List<Date>> entries;
raimund@3274: 
raimund@3274:     public SQOverview() {
raimund@3274:         entries = new KMIndex<List<Date>>();
raimund@3274:     }
raimund@3274: 
raimund@3274:     public SQOverview(String riverName) {
raimund@3274:         this();
raimund@3274:         this.riverName = riverName;
raimund@3274:     }
raimund@3274: 
sascha@3275:     private static final boolean epsilonEquals(double a, double b) {
sascha@3275:         return Math.abs(a - b) < EPSILON;
sascha@3275:     }
sascha@3275: 
raimund@3274:     protected void loadData(Session session) {
raimund@3274:         SQLQuery query = session.createSQLQuery(SQL_SQ)
sascha@3289:             .addScalar("km",    StandardBasicTypes.DOUBLE)
sascha@3289:             .addScalar("datum", StandardBasicTypes.DATE);
raimund@3274: 
raimund@3274:         query.setString("name", riverName);
raimund@3274: 
raimund@3274:         List<Object []> list = query.list();
raimund@3274: 
raimund@3274:         if (list.isEmpty()) {
raimund@3274:             log.warn("No river '" + riverName + "' found.");
raimund@3274:         }
raimund@3274: 
sascha@3275:         Double prevKm = -Double.MAX_VALUE;
raimund@3274:         List<Date> dates = new ArrayList<Date>();
sascha@3275: 
sascha@3275:         for (Object [] row: list) {
sascha@3275:             Double km = (Double)row[0];
sascha@3275:             if (!epsilonEquals(km, prevKm) && !dates.isEmpty()) {
raimund@3274:                 entries.add(prevKm, dates);
raimund@3274:                 dates = new ArrayList<Date>();
raimund@3274:             }
sascha@3275:             dates.add((Date)row[1]);
raimund@3274:             prevKm = km;
raimund@3274:         }
sascha@3275: 
sascha@3275:         if (!dates.isEmpty()) {
sascha@3275:             entries.add(prevKm, dates);
sascha@3275:         }
raimund@3274:     }
raimund@3274: 
raimund@3274:     public boolean load(Session session) {
raimund@3274: 
raimund@3274:         loadData(session);
raimund@3274: 
raimund@3274:         return true;
raimund@3274:     }
raimund@3274: 
raimund@3274: 
raimund@3274:     public void generateOverview(Document document) {
raimund@3274:         generateOverview(document, ACCEPT);
raimund@3274:     }
raimund@3274: 
raimund@3274:     public KMIndex<List<Date>> filter(Filter f) {
sascha@3275:         // TODO: Apply filter
raimund@3274:         return entries;
raimund@3274:     }
raimund@3274: 
raimund@3274:     public void generateOverview(
raimund@3274:         Document document,
raimund@3274:         Filter   filter
raimund@3274:     ) {
raimund@3274:         KMIndex<List<Date>> filtered = filter(ACCEPT);
raimund@3274: 
raimund@3274:         Element sqElement = document.createElement("sq");
raimund@3274: 
raimund@3274:         Element riverElement = document.createElement("river");
raimund@3274: 
raimund@3274:         riverElement.setAttribute("name", riverName);
raimund@3274: 
raimund@3274:         sqElement.appendChild(riverElement);
raimund@3274: 
raimund@3274:         SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
raimund@3274: 
raimund@3274:         Element kmE = document.createElement("km");
raimund@3274: 
raimund@3274:         for (KMIndex.Entry<List<Date>> e: filtered) {
raimund@3274: 
raimund@3274:             List<Date> dates = e.getValue();
raimund@3274: 
raimund@3274:             if (!dates.isEmpty()) {
raimund@3274:                 Element dEs = document.createElement("dates");
raimund@3274: 
raimund@3274:                 for (Date d: dates) {
raimund@3274:                     Element dE = document.createElement("date");
raimund@3274: 
raimund@3274:                     dE.setAttribute("value", df.format(d));
raimund@3274: 
raimund@3274:                     dEs.appendChild(dE);
raimund@3274:                 }
raimund@3274: 
raimund@3274:                 kmE.appendChild(dEs);
raimund@3274:             }
raimund@3274:         }
raimund@3274: 
raimund@3274:         sqElement.appendChild(kmE);
raimund@3274: 
raimund@3274:         document.appendChild(sqElement);
raimund@3274:     }
raimund@3274: }
sascha@3275: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :