Mercurial > dive4elements > river
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 : |