comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WstValueTable.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 909196be11a0
children 523a256451cd
comparison
equal deleted inserted replaced
442:c1ef5f63278e 443:5d65fe4c08d5
1 package de.intevation.flys.artifacts.model; 1 package de.intevation.flys.artifacts.model;
2 2
3 import java.io.Serializable; 3 import java.io.Serializable;
4 4
5 import de.intevation.flys.model.River;
6 import de.intevation.flys.model.Wst;
7 import de.intevation.flys.model.WstColumn;
8 5
9 import de.intevation.flys.artifacts.math.LinearRemap; 6 import de.intevation.flys.artifacts.math.LinearRemap;
10
11 import de.intevation.flys.artifacts.cache.CacheFactory;
12
13 import de.intevation.flys.backend.SessionHolder;
14 7
15 import java.util.Arrays; 8 import java.util.Arrays;
16 import java.util.ArrayList; 9 import java.util.ArrayList;
17 import java.util.Comparator;
18 import java.util.List; 10 import java.util.List;
19 import java.util.Collections; 11 import java.util.Collections;
20 12
21 import org.apache.log4j.Logger; 13 import org.apache.log4j.Logger;
22 14
23 import org.apache.commons.math.analysis.interpolation.SplineInterpolator; 15 import org.apache.commons.math.analysis.interpolation.SplineInterpolator;
24 16
25 import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; 17 import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
26 18
27 import org.apache.commons.math.ArgumentOutsideDomainException; 19 import org.apache.commons.math.ArgumentOutsideDomainException;
28
29 import org.hibernate.Session;
30 import org.hibernate.Query;
31 import org.hibernate.SQLQuery;
32
33 import org.hibernate.type.StandardBasicTypes;
34
35 import net.sf.ehcache.Cache;
36 import net.sf.ehcache.Element;
37 20
38 public class WstValueTable 21 public class WstValueTable
39 implements Serializable 22 implements Serializable
40 { 23 {
41 private static Logger log = Logger.getLogger(WstValueTable.class); 24 private static Logger log = Logger.getLogger(WstValueTable.class);
42
43 public static final String CACHE_NAME = "wst-value-table";
44
45 // TODO: put this into a property file
46 public static final String SQL_POS_WQ =
47 "SELECT position, w, q, column_pos" +
48 " FROM wst_value_table" +
49 " WHERE wst_id = :wst_id";
50 25
51 public static final int DEFAULT_Q_STEPS = 500; 26 public static final int DEFAULT_Q_STEPS = 500;
52 27
53 public static class Column 28 public static class Column
54 implements Serializable 29 implements Serializable
664 r1.storeWQ(r2, kms[i], qPosition, ws, qs, i); 639 r1.storeWQ(r2, kms[i], qPosition, ws, qs, i);
665 } 640 }
666 641
667 return qPosition; 642 return qPosition;
668 } 643 }
669
670 public static WstValueTable getTable(River river) {
671 return getTable(river, 0);
672 }
673
674 public static final class CacheKey
675 implements Serializable
676 {
677 private int riverId;
678 private int kind;
679
680 public CacheKey(int riverId, int kind) {
681 this.riverId = riverId;
682 this.kind = kind;
683 }
684
685 public int hashCode() {
686 return (riverId << 8) | kind;
687 }
688
689 public boolean equals(Object other) {
690 if (!(other instanceof CacheKey)) {
691 return false;
692 }
693 CacheKey o = (CacheKey)other;
694 return riverId == o.riverId && kind == o.kind;
695 }
696 } // class CacheKey
697
698 public static WstValueTable getTable(River river, int kind) {
699
700 Cache cache = CacheFactory.getCache(CACHE_NAME);
701
702 CacheKey cacheKey;
703
704 if (cache != null) {
705 cacheKey = new CacheKey(river.getId(), kind);
706 Element element = cache.get(cacheKey);
707 if (element != null) {
708 log.debug("got wst value table from cache");
709 return (WstValueTable)element.getValue();
710 }
711 }
712 else {
713 cacheKey = null;
714 }
715
716 WstValueTable valueTable = getTableUncached(river, kind);
717
718 if (cacheKey != null) {
719 log.debug("store wst value in cache");
720 Element element = new Element(cacheKey, valueTable);
721 cache.put(element);
722 }
723
724 return valueTable;
725 }
726
727 public static WstValueTable getTableUncached(River river, int kind) {
728
729 Session session = SessionHolder.HOLDER.get();
730
731 Query query = session.createQuery(
732 "from Wst where river=:river and kind=:kind");
733 query.setParameter("river", river);
734 query.setInteger("kind", kind);
735
736 List<Wst> wsts = query.list();
737
738 if (wsts.isEmpty()) {
739 return null;
740 }
741
742 Wst wst = wsts.get(0);
743
744 // TODO: Do this sorting at database level
745 List<WstColumn> wstColumns = new ArrayList(wst.getColumns());
746 Collections.sort(wstColumns, new Comparator<WstColumn>() {
747 public int compare(WstColumn a, WstColumn b) {
748 int pa = a.getPosition();
749 int pb = b.getPosition();
750 if (pa < pb) return -1;
751 if (pa > pb) return +1;
752 return 0;
753 }
754 });
755
756 Column [] columns = new Column[wstColumns.size()];
757 for (int i = 0; i < columns.length; ++i) {
758 columns[i] = new Column(wstColumns.get(i).getName());
759 }
760
761 // using native SQL here to avoid myriad of small objects.
762 SQLQuery sqlQuery = session.createSQLQuery(SQL_POS_WQ)
763 .addScalar("position", StandardBasicTypes.DOUBLE)
764 .addScalar("w", StandardBasicTypes.DOUBLE)
765 .addScalar("q", StandardBasicTypes.DOUBLE)
766 .addScalar("column_pos", StandardBasicTypes.INTEGER);
767
768 sqlQuery.setInteger("wst_id", wst.getId());
769
770 WstValueTable valueTable = new WstValueTable(columns);
771
772 int lastColumnNo = -1;
773 Row row = null;
774
775 Double lastQ = -Double.MAX_VALUE;
776 boolean qSorted = true;
777
778 for (Object r: sqlQuery.list()) {
779 Object[] result = (Object[]) r;
780
781 double km = (Double) result[0];
782 Double w = (Double) result[1];
783 Double q = (Double) result[2];
784 int columnNo = (Integer)result[3];
785
786 if (columnNo > lastColumnNo) { // new row
787 if (row != null) {
788 row.qSorted = qSorted;
789 valueTable.rows.add(row);
790 }
791 row = new Row(
792 km,
793 new double[columnNo+1],
794 new double[columnNo+1]);
795 lastQ = -Double.MAX_VALUE;
796 qSorted = true;
797 }
798
799 row.ws[columnNo] = w != null ? w : Double.NaN;
800 row.qs[columnNo] = q != null ? q : Double.NaN;
801
802 if (qSorted && (q == null || lastQ > q)) {
803 qSorted = false;
804 }
805 lastQ = q;
806
807 lastColumnNo = columnNo;
808 }
809
810 if (row != null) {
811 valueTable.rows.add(row);
812 }
813
814 return valueTable;
815 }
816 } 644 }
817 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : 645 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org