view backend/src/main/java/org/dive4elements/river/model/CrossSection.java @ 9464:c77255da734b

cross-section logs removed
author gernotbelger
date Thu, 30 Aug 2018 10:53:40 +0200
parents 80800fe126cd
children
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

package org.dive4elements.river.model;

import java.awt.geom.Point2D;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.apache.log4j.Logger;
import org.dive4elements.river.backend.SessionHolder;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.type.StandardBasicTypes;

@Entity
@Table(name = "cross_sections")
public class CrossSection implements Serializable {
    private static Logger log = Logger.getLogger(CrossSection.class);

    private static final MathContext PRECISION = new MathContext(6);

    private static final String SQL_FAST_CROSS_SECTION_LINES = "SELECT km, x, y, csl.id AS csl_id "
            + "FROM cross_section_lines csl JOIN cross_section_points csp " + "ON csp.cross_section_line_id = csl.id "
            + "WHERE csl.cross_section_id = :cs_id AND " + "km between :from_km AND :to_km " + "ORDER BY csl.km, csl.id, csp.col_pos";

    private static final String SQL_MIN_MAX = "SELECT * FROM ( " + "SELECT cross_section_id, MIN(km) AS minkm, MAX(km) AS maxkm " + "FROM cross_section_lines "
            + "WHERE cross_section_id IN " + " (SELECT id FROM cross_sections WHERE river_id = :river_id) " + "  GROUP BY cross_section_id" + ") cs_ranges "
            + "JOIN cross_sections cs ON cs_ranges.cross_section_id = cs.id " + "LEFT OUTER JOIN time_intervals "
            + "    ON cs.time_interval_id = time_intervals.id " + "WHERE :km BETWEEN minkm AND maxkm "
            + "ORDER BY stop_time desc, start_time desc, :km - minkm";
    // Order by time interval missing.

    private Integer id;
    private River river;
    private TimeInterval timeInterval;
    private String description;
    private List<CrossSectionLine> lines;

    public CrossSection() {
    }

    public CrossSection(final River river, final TimeInterval timeInterval, final String description) {
        this.river = river;
        this.timeInterval = timeInterval;
        this.description = description;
    }

    @Id
    @SequenceGenerator(name = "SEQUENCE_CROSS_SECTIONS_ID_SEQ", sequenceName = "CROSS_SECTIONS_ID_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_CROSS_SECTIONS_ID_SEQ")
    @Column(name = "id")
    public Integer getId() {
        return this.id;
    }

    public void setId(final Integer id) {
        this.id = id;
    }

    @OneToOne
    @JoinColumn(name = "river_id")
    public River getRiver() {
        return this.river;
    }

    public void setRiver(final River river) {
        this.river = river;
    }

    @OneToOne
    @JoinColumn(name = "time_interval_id")
    public TimeInterval getTimeInterval() {
        return this.timeInterval;
    }

    public void setTimeInterval(final TimeInterval timeInterval) {
        this.timeInterval = timeInterval;
    }

    @Column(name = "description")
    public String getDescription() {
        return this.description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    @OneToMany
    @OrderBy("km")
    @JoinColumn(name = "cross_section_id")
    public List<CrossSectionLine> getLines() {
        return this.lines;
    }

    public void setLines(final List<CrossSectionLine> lines) {
        this.lines = lines;
    }

    public List<CrossSectionLine> getLines(final double startKm, final double endKm) {
        final Session session = SessionHolder.HOLDER.get();
        final Query query = session.createQuery("from CrossSectionLine where crossSection=:crossSection " + "and km between :startKm and :endKm order by km");
        query.setParameter("crossSection", this);
        query.setParameter("startKm", new BigDecimal(startKm, PRECISION));
        query.setParameter("endKm", new BigDecimal(endKm, PRECISION));

        return query.list();
    }

    /** Get Lines from startkm to endkm, fast because direct usage of sql. */
    public List<FastCrossSectionLine> getFastLines(final double startKm, final double endKm) {
        final Session session = SessionHolder.HOLDER.get();

        final SQLQuery sqlQuery = session.createSQLQuery(SQL_FAST_CROSS_SECTION_LINES).addScalar("km", StandardBasicTypes.DOUBLE)
                .addScalar("x", StandardBasicTypes.DOUBLE).addScalar("y", StandardBasicTypes.DOUBLE).addScalar("csl_id", StandardBasicTypes.INTEGER);

        sqlQuery.setInteger("cs_id", getId()).setDouble("from_km", startKm).setDouble("to_km", endKm);

        final List<Object[]> results = sqlQuery.list();

        ArrayList<Point2D> points = new ArrayList<>(500);
        final ArrayList<FastCrossSectionLine> lines = new ArrayList<>();

        Integer lastId = null;
        Double lastKm = null;

        for (final Object[] result : results) {
            final Double km = (Double) result[0];
            final Double x = (Double) result[1];
            final Double y = (Double) result[2];
            final Integer id = (Integer) result[3];

            if (lastId != null && !lastId.equals(id)) {
                points.trimToSize();
                final FastCrossSectionLine line = new FastCrossSectionLine(lastKm, points);
                lines.add(line);
                points = new ArrayList<>(500);
            }

            points.add(new Point2D.Double(x, y));

            lastKm = km;
            lastId = id;
        }

        if (lastId != null) {
            points.trimToSize();
            final FastCrossSectionLine line = new FastCrossSectionLine(lastKm, points);
            lines.add(line);
        }

        lines.trimToSize();

        return lines;
    }

    /**
     * True if the given section is the "newest" for that river
     * and has values at km.
     *
     * @param km
     *            Given station.
     * @return true if the section has the most advanced end of its validity
     *         interval or the most advanced start of its validity interval.
     */
    public boolean shouldBeMaster(final double km) {
        final Session session = SessionHolder.HOLDER.get();

        final SQLQuery sqlQuery = session.createSQLQuery(SQL_MIN_MAX).addScalar("cross_section_id", StandardBasicTypes.INTEGER);

        sqlQuery.setInteger("river_id", getRiver().getId()).setDouble("km", km);

        final List<Integer> results = sqlQuery.list();

        if (results.size() >= 1) {
            final Integer result = results.get(0);
            if (result.equals(getId())) { // NIEMALS OBJEKTE MIT "==" VERGLEICHEN!
                return true;
            }
        } else {
            log.warn("No CS found that could be master.");
        }

        // TODO If there is none, might need a fallback.
        // Formerly this was the most current CS (issue1157).

        return false;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org