sascha@167: package de.intevation.flys.model; sascha@167: sascha@167: import java.io.Serializable; sascha@167: ingo@465: import java.math.BigDecimal; sascha@768: import java.math.MathContext; ingo@465: sascha@168: import javax.persistence.Entity; sascha@168: import javax.persistence.Id; sascha@168: import javax.persistence.Table; sascha@168: import javax.persistence.GeneratedValue; sascha@168: import javax.persistence.Column; sascha@168: import javax.persistence.SequenceGenerator; sascha@174: import javax.persistence.OneToMany; ingo@2347: import javax.persistence.OneToOne; sascha@174: import javax.persistence.JoinColumn; sascha@168: import javax.persistence.GenerationType; sascha@168: sascha@174: import java.util.List; sascha@2383: import java.util.Comparator; sascha@2383: import java.util.Map; sascha@2383: import java.util.TreeMap; sascha@174: ingo@472: import org.hibernate.Session; ingo@472: import org.hibernate.Query; ingo@472: ingo@472: import de.intevation.flys.backend.SessionHolder; ingo@472: ingo@472: sascha@168: @Entity sascha@168: @Table(name = "rivers") sascha@167: public class River sascha@167: implements Serializable sascha@167: { sascha@768: public static final MathContext PRECISION = new MathContext(6); sascha@768: sascha@2383: public static final double EPSILON = 1e-5; sascha@2383: sascha@2383: public static final Comparator KM_CMP = new Comparator() { sascha@2383: @Override sascha@2383: public int compare(Double a, Double b) { sascha@2383: double diff = a - b; sascha@2383: if (diff < -EPSILON) return -1; sascha@2383: if (diff > EPSILON) return +1; sascha@2383: return 0; sascha@2383: } sascha@2383: }; sascha@2383: sascha@168: private Integer id; sascha@167: sascha@3946: private Long officialNumber; sascha@3946: sascha@168: private String name; sascha@167: sascha@505: private boolean kmUp; sascha@505: sascha@174: private List gauges; sascha@174: ingo@2347: private Unit wstUnit; ingo@2347: sascha@168: @Id sascha@168: @SequenceGenerator( sascha@171: name = "SEQUENCE_RIVERS_ID_SEQ", sascha@169: sequenceName = "RIVERS_ID_SEQ", sascha@169: allocationSize = 1) sascha@168: @GeneratedValue( sascha@168: strategy = GenerationType.SEQUENCE, sascha@171: generator = "SEQUENCE_RIVERS_ID_SEQ") sascha@168: @Column(name = "id") sascha@168: public Integer getId() { sascha@168: return id; sascha@168: } sascha@168: sascha@168: public void setId(Integer id) { sascha@167: this.id = id; sascha@167: } sascha@167: sascha@3946: @Column(name = "official_number") sascha@3946: public Long getOfficialNumber() { sascha@3946: return officialNumber; sascha@3946: } sascha@3946: sascha@3946: public void setOfficialNumber(Long officialNumber) { sascha@3946: this.officialNumber = officialNumber; sascha@3946: } sascha@3946: sascha@168: @Column(name = "name") sascha@168: public String getName() { sascha@168: return name; sascha@167: } sascha@167: sascha@167: public void setName(String name) { sascha@167: this.name = name; sascha@167: } sascha@167: sascha@505: @Column(name = "km_up") sascha@505: public boolean getKmUp() { sascha@505: return kmUp; sascha@505: } sascha@505: sascha@505: public void setKmUp(boolean kmUp) { sascha@505: this.kmUp = kmUp; sascha@505: } sascha@505: sascha@167: public River() { sascha@167: } sascha@169: ingo@2347: public River(String name, Unit wstUnit) { ingo@2347: this.name = name; ingo@2347: this.wstUnit = wstUnit; sascha@169: } sascha@174: sascha@174: @OneToMany sascha@174: @JoinColumn(name="river_id") sascha@174: public List getGauges() { sascha@174: return gauges; sascha@174: } sascha@174: sascha@174: public void setGauges(List gauges) { sascha@174: this.gauges = gauges; sascha@174: } sascha@188: ingo@2347: ingo@2347: @OneToOne ingo@2347: @JoinColumn(name = "wst_unit_id" ) ingo@2347: public Unit getWstUnit() { ingo@2347: return wstUnit; ingo@2347: } ingo@2347: ingo@2347: public void setWstUnit(Unit wstUnit) { ingo@2347: this.wstUnit = wstUnit; ingo@2347: } ingo@2347: ingo@2347: ingo@2347: sascha@188: public String toString() { sascha@188: return name != null ? name : ""; sascha@188: } ingo@465: ingo@472: ingo@472: /** ingo@488: * This method returns the gauges that intersect with a and ingo@488: * b, ingo@488: * ingo@488: * @param a A start point. ingo@488: * @param b An end point. ingo@488: * ingo@488: * @return the intersecting gauges. ingo@488: */ ingo@488: public List determineGauges(double a, double b) { ingo@488: Session session = SessionHolder.HOLDER.get(); ingo@488: sascha@756: if (a > b) { double t = a; a = b; b = t; } sascha@756: ingo@488: Query query = session.createQuery( ingo@488: "from Gauge where river=:river " + ingo@488: "and not (range.a > :b or range.b < :a) order by a"); ingo@488: query.setParameter("river", this); sascha@769: query.setParameter("a", new BigDecimal(a, PRECISION)); sascha@769: query.setParameter("b", new BigDecimal(b, PRECISION)); ingo@488: ingo@488: return query.list(); ingo@488: } ingo@488: sascha@769: public Gauge maxOverlap(double a, double b) { sascha@769: List gauges = determineGauges(a, b); sascha@769: if (gauges == null) { sascha@769: return null; sascha@769: } sascha@769: sascha@769: if (a > b) { double t = a; a = b; b = t; } sascha@769: sascha@769: double max = -Double.MAX_VALUE; sascha@769: sascha@769: Gauge result = null; sascha@769: sascha@769: for (Gauge gauge: gauges) { sascha@769: Range r = gauge.getRange(); sascha@769: double c = r.getA().doubleValue(); sascha@769: double d = r.getB().doubleValue(); sascha@769: sascha@769: double start = c >= a ? c : a; sascha@769: double stop = d <= b ? d : b; sascha@769: sascha@769: double length = stop - start; sascha@769: sascha@769: if (length > max) { sascha@769: max = length; sascha@769: result = gauge; sascha@769: } sascha@769: } sascha@769: sascha@769: return result; sascha@769: } sascha@769: sascha@767: public Gauge determineGaugeByName(String name) { sascha@767: Session session = SessionHolder.HOLDER.get(); sascha@767: Query query = session.createQuery( sascha@767: "from Gauge where river=:river and name=:name"); sascha@767: query.setParameter("river", this); sascha@767: query.setParameter("name", name); sascha@767: List gauges = query.list(); sascha@767: return gauges.isEmpty() ? null : gauges.get(0); sascha@767: } sascha@767: sascha@764: public Gauge determineGaugeByPosition(double p) { sascha@764: Session session = SessionHolder.HOLDER.get(); sascha@764: Query query = session.createQuery( sascha@768: "from Gauge g where river=:river " + sascha@768: "and :p between g.range.a and g.range.b"); sascha@764: query.setParameter("river", this); sascha@768: query.setParameter("p", new BigDecimal(p, PRECISION)); sascha@764: List gauges = query.list(); sascha@764: return gauges.isEmpty() ? null : gauges.get(0); sascha@764: } sascha@764: sascha@757: public Gauge determineGaugeByStation(double a, double b) { sascha@757: sascha@757: if (a > b) { double t = a; a = b; b = t; } sascha@757: sascha@757: Session session = SessionHolder.HOLDER.get(); sascha@757: sascha@757: Query query = session.createQuery( sascha@757: "from Gauge where river.id=:river " + sascha@757: "and station between :a and :b"); sascha@757: query.setParameter("river", getId()); sascha@757: query.setParameter("a", new BigDecimal(a)); sascha@757: query.setParameter("b", new BigDecimal(b)); sascha@757: sascha@757: List gauges = query.list(); sascha@757: return gauges.isEmpty() ? null : gauges.get(0); sascha@757: } sascha@757: bjoern@3794: public double[] determineMinMaxQ() { bjoern@3794: Session session = SessionHolder.HOLDER.get(); bjoern@3794: bjoern@3794: Query query = session.createQuery( bjoern@3795: "select min(wqr.q) as min, max(wqr.q) as max " + bjoern@3795: "from Wst as w " + bjoern@3795: "join w.columns as wc " + bjoern@3795: "join wc.columnQRanges as wcqr " + bjoern@3795: "join wcqr.wstQRange as wqr " + bjoern@3795: "where w.kind = 0 and river_id = :river"); bjoern@3794: bjoern@3794: query.setParameter("river", getId()); bjoern@3794: bjoern@3794: double minmax[] = new double[] { Double.MAX_VALUE, Double.MIN_VALUE }; bjoern@3794: bjoern@3794: List results = query.list(); bjoern@3794: bjoern@3794: if (!results.isEmpty()) { bjoern@3794: Object[] arr = (Object[]) results.get(0); bjoern@3794: BigDecimal minq = (BigDecimal)arr[0]; bjoern@3794: BigDecimal maxq = (BigDecimal)arr[1]; bjoern@3794: minmax[0] = minq.doubleValue(); bjoern@3794: minmax[1] = maxq.doubleValue(); bjoern@3794: } bjoern@3794: bjoern@3794: return minmax; bjoern@3794: } bjoern@3794: ingo@488: ingo@488: /** ingo@472: * This method returns the first gauge that is intersected by a and ingo@472: * b, ingo@472: * ingo@472: * @param a A start point. ingo@472: * @param b An end point. ingo@472: * ingo@472: * @return the first intersecting gauge. ingo@472: */ ingo@472: public Gauge determineGauge(double a, double b) { ingo@488: List gauges = determineGauges(a, b); ingo@472: ingo@2345: int idx = a < b ? 0 : gauges.size() - 1; ingo@2345: ingo@2345: return gauges.isEmpty() ? null : gauges.get(idx); ingo@472: } ingo@472: ingo@465: /** ingo@465: * Returns the min and max distance of this river. The first position in the ingo@465: * resulting array contains the min distance, the second position the max ingo@465: * distance. ingo@465: * ingo@465: * @return the min and max distance of this river. ingo@465: */ ingo@465: public double[] determineMinMaxDistance() { sascha@2373: List gauges = getGauges(); sascha@2373: sascha@2373: if (gauges == null || gauges.isEmpty()) { ingo@465: return null; ingo@465: } ingo@465: ingo@465: double minmax[] = new double[] { Double.MAX_VALUE, Double.MIN_VALUE }; ingo@465: ingo@465: for (Gauge g: gauges) { ingo@465: Range r = g.getRange(); ingo@465: sascha@2373: if (r == null) { sascha@2373: continue; sascha@2373: } sascha@2373: ingo@465: double a = r.getA().doubleValue(); ingo@465: minmax[0] = minmax[0] < a ? minmax[0] : a; ingo@465: ingo@465: BigDecimal bigB = r.getB(); ingo@465: if (bigB != null) { ingo@465: double b = bigB.doubleValue(); ingo@465: minmax[1] = minmax[1] > b ? minmax[1] : b; ingo@465: } ingo@465: } ingo@465: ingo@465: return minmax; ingo@465: } sascha@2383: felix@2384: public Map queryGaugeDatumsKMs() { sascha@2383: List gauges = getGauges(); sascha@2383: Map result = new TreeMap(KM_CMP); sascha@2383: sascha@2383: for (Gauge gauge: gauges) { sascha@2383: BigDecimal km = gauge.getStation(); sascha@2383: BigDecimal datum = gauge.getDatum(); sascha@2383: if (km != null && datum != null) { sascha@2383: result.put(km.doubleValue(), datum.doubleValue()); sascha@2383: } sascha@2383: } sascha@2383: sascha@2383: return result; sascha@2383: } bjoern@3944: bjoern@3944: /** bjoern@3944: * Returns a HTTP URL for additional information about this river bjoern@3944: */ bjoern@3945: public String fetchInfoURL() { bjoern@3944: //FIXME fetch url from the database bjoern@3944: return "https://flys-intern.intevation.de/Flys-3.0/"; bjoern@3944: } sascha@167: } sascha@167: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :