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;
sascha@174: import javax.persistence.JoinColumn;
sascha@168: import javax.persistence.GenerationType;
sascha@168: 
sascha@174: import java.util.List;
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@168:     private Integer id;
sascha@167: 
sascha@168:     private String  name;
sascha@167: 
sascha@505:     private boolean kmUp;
sascha@505: 
sascha@174:     private List<Gauge> gauges;
sascha@174: 
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@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: 
sascha@169:     public River(String name) {
sascha@169:         this.name = name;
sascha@169:     }
sascha@174: 
sascha@174:     @OneToMany
sascha@174:     @JoinColumn(name="river_id")
sascha@174:     public List<Gauge> getGauges() {
sascha@174:         return gauges;
sascha@174:     }
sascha@174: 
sascha@174:     public void setGauges(List<Gauge> gauges) {
sascha@174:         this.gauges = gauges;
sascha@174:     }
sascha@188: 
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 <i>a</i> and
ingo@488:      * <i>b</i>,
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<Gauge> 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<Gauge> 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<Gauge> 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<Gauge> 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<Gauge> gauges = query.list();
sascha@757:         return gauges.isEmpty() ? null : gauges.get(0);
sascha@757:     }
sascha@757: 
ingo@488: 
ingo@488:     /**
ingo@472:      * This method returns the first gauge that is intersected by <i>a</i> and
ingo@472:      * <i>b</i>,
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<Gauge> gauges = determineGauges(a, b);
ingo@472: 
sascha@756:         return gauges.isEmpty() ? null : gauges.get(0);
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() {
ingo@465:         if (gauges == null) {
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: 
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@167: }
sascha@167: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :