Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsOverview.java @ 4221:480de0dbca8e
Extended location input helper.
The locationpicker has now an attribute whether the input is distance or
location to display one or two clickable columns.
Replaced the record click handler with cell click handler.
author | Raimund Renkert <rrenkert@intevation.de> |
---|---|
date | Tue, 23 Oct 2012 13:17:20 +0200 |
parents | 278b5508567e |
children | 658dc517fd7b |
line wrap: on
line source
package de.intevation.flys.artifacts.model; import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.type.StandardBasicTypes; import org.w3c.dom.Document; import org.w3c.dom.Element; public class FixingsOverview implements Serializable { private static Logger log = Logger.getLogger(FixingsOverview.class); public static final double EPSILON = 1e-2; public static final String DATE_FORMAT = "dd.MM.yyyy"; public static final String SQL_RIVER_ID = "SELECT" + " id AS river_id," + " km_up " + "FROM rivers " + "WHERE" + " name = :name"; public static final String SQL_FIXINGS = "SELECT" + " id AS wst_id," + " description " + "FROM wsts " + "WHERE" + " river_id = :river_id AND kind = 2"; public static final String SQL_FIXING_COLUMNS = "SELECT" + " wc.id AS wst_column_id," + " ti.start_time AS start_time," + " wc.name AS name " + "FROM wst_columns wc" + " JOIN time_intervals ti ON wc.time_interval_id = ti.id " + "WHERE" + " wc.wst_id = :wst_id " + "ORDER BY position"; public static final String SQL_FIXING_COLUMN_Q_RANGES = "SELECT" + " wqr.q AS q," + " r.a AS start_km," + " r.b AS stop_km " + "FROM wst_column_q_ranges wcqr" + " JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id = wqr.id" + " JOIN ranges r ON wqr.range_id = r.id " + "WHERE" + " wcqr.wst_column_id = :column_id " + "ORDER BY r.a"; public static final String SQL_FIXING_COLUMN_KM_RANGE = "SELECT" + " MIN(position) AS start_km," + " MAX(position) AS stop_km " + "FROM" + " wst_column_values " + "WHERE" + " wst_column_id = :column_id"; public static class QRange extends Range { protected double q; public QRange() { } public QRange(double start, double end, double q) { super(start, end); this.q = q; } } // class QRange public static class SectorRange extends Range { protected int sector; public SectorRange() { } public SectorRange(SectorRange other) { start = other.start; end = other.end; sector = other.sector; } public SectorRange(Range range) { super(range); } public SectorRange(double start, double end, int sector) { super(start, end); this.sector = sector; } public int getSector() { return sector; } public void setSector(int sector) { this.sector = sector; } public boolean enlarge(SectorRange other) { if (sector == other.sector && Math.abs(end-other.start) < FixingsOverview.EPSILON) { end = other.end; return true; } return false; } } // class SectorRange public static class Fixing implements Serializable { public static final Comparator<Column> DATE_CMP = new Comparator<Column>() { @Override public int compare(Column a, Column b) { return a.startTime.compareTo(b.startTime); } }; public interface Filter { boolean accept(Column column); } // interface Filter public class Column extends Range { protected int columnId; protected Date startTime; protected String name; protected List<SectorRange> sectors; public Column() { } public Column(int columnId, Date startTime, String name) { this.columnId = columnId; this.startTime = startTime; this.name = name; sectors = new ArrayList<SectorRange>(); } public int getId() { return columnId; } public Fixing getFixing() { return Fixing.this; } public Date getStartTime() { return startTime; } public String getName() { return name; } public String getDescription() { return Fixing.this.description + "/" + name; } public List<SectorRange> getSectors() { return sectors; } public List<SectorRange> getSectors(Range range) { List<SectorRange> result = new ArrayList<SectorRange>(sectors.size()); for (SectorRange src: sectors) { SectorRange dst = new SectorRange(src); if (range == null || dst.clip(range)) { result.add(dst); } } return result; } public int findQSector(double km) { for (SectorRange sector: sectors) { if (sector.inside(km)) { return sector.getSector(); } } return -1; } public void buildSectors( GaugeFinder gaugeFinder, List<QRange> qRanges ) { for (QRange qRange: qRanges) { for (GaugeRange gRange: gaugeFinder.getGauges()) { SectorRange sector = new SectorRange(qRange); if (!sector.clip(gRange)) { continue; } sector.setSector(gRange.classify(qRange.q)); if (sectors.isEmpty() || !sectors.get(sectors.size()-1).enlarge(sector)) { sectors.add(sector); } } // for all gauges } // for all Q ranges } public void loadKmRange(SQLQuery query) { query.setInteger("column_id", columnId); List<Object []> kms = query.list(); if (kms.isEmpty()) { log.warn("No km range for column " + columnId + "."); } else { Object [] obj = kms.get(0); start = (Double)obj[0]; end = (Double)obj[1]; } } public void loadQRanges( SQLQuery query, GaugeFinder gaugeFinder ) { query.setInteger("column_id", columnId); List<Object []> list = query.list(); List<QRange> qRanges = new ArrayList<QRange>(list.size()); for (Object [] row: list) { double q = (Double)row[0]; double start = (Double)row[1]; double end = (Double)row[2]; QRange qRange = new QRange(start, end, q); if (qRange.clip(this)) { qRanges.add(qRange); } } buildSectors(gaugeFinder, qRanges); } } // class Column protected int wstId; protected String description; protected List<Column> columns; public Fixing() { } public int getId() { return wstId; } public String getDescription() { return description; } public Fixing(int wstId, String description) { this.wstId = wstId; this.description = description; columns = new ArrayList<Column>(); } public void loadColumns(SQLQuery query) { query.setInteger("wst_id", wstId); List<Object []> list = query.list(); for (Object [] row: list) { int columnId = (Integer)row[0]; Date startTime = (Date) row[1]; String name = (String) row[2]; columns.add(new Column(columnId, startTime, name)); } } public void loadColumnsKmRange(SQLQuery query) { for (Column column: columns) { column.loadKmRange(query); } } public void adjustExtent(Range extent) { for (Column column: columns) { extent.extend(column); } } public void loadColumnsQRanges( SQLQuery query, GaugeFinder gaugeFinder ) { for (Column column: columns) { column.loadQRanges(query, gaugeFinder); } } public void addAllColumns( List<Column> allColumns, Range range, Filter filter ) { for (Column column: columns) { if ((range == null || column.intersects(range)) && (filter == null || filter.accept(column))) { allColumns.add(column); } } } } // class Fixing protected String riverName; protected int riverId; protected boolean isKmUp; protected List<Fixing> fixings; protected Range extent; public FixingsOverview() { fixings = new ArrayList<Fixing>(); extent = new Range(Double.MAX_VALUE, -Double.MAX_VALUE); } public FixingsOverview(String riverName) { this(); this.riverName = riverName; } protected boolean loadRiver(Session session) { SQLQuery query = session.createSQLQuery(SQL_RIVER_ID) .addScalar("river_id", StandardBasicTypes.INTEGER) .addScalar("km_up", StandardBasicTypes.BOOLEAN); query.setString("name", riverName); List<Object []> list = query.list(); if (list.isEmpty()) { log.warn("No river '" + riverName + "' found."); return false; } Object [] row = list.get(0); riverId = (Integer)row[0]; isKmUp = (Boolean)row[1]; return true; } protected void loadFixings(Session session) { SQLQuery query = session.createSQLQuery(SQL_FIXINGS) .addScalar("wst_id", StandardBasicTypes.INTEGER) .addScalar("description", StandardBasicTypes.STRING); query.setInteger("river_id", riverId); List<Object []> list = query.list(); if (list.isEmpty()) { log.warn("River " + riverId + " has no fixings."); // Its pretty fine to have no fixings. } for (Object [] row: list) { int wstId = (Integer)row[0]; String description = (String) row[1]; Fixing fixing = new Fixing(wstId, description); fixings.add(fixing); } } protected void loadFixingsColumns(Session session) { SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMNS) .addScalar("wst_column_id", StandardBasicTypes.INTEGER) .addScalar("start_time", StandardBasicTypes.DATE) .addScalar("name", StandardBasicTypes.STRING); for (Fixing fixing: fixings) { fixing.loadColumns(query); } } protected void loadFixingsColumnsKmRange(Session session) { SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_KM_RANGE) .addScalar("start_km", StandardBasicTypes.DOUBLE) .addScalar("stop_km", StandardBasicTypes.DOUBLE); for (Fixing fixing: fixings) { fixing.loadColumnsKmRange(query); } } protected void loadFixingsColumnsQRanges( Session session, GaugeFinder gaugeFinder ) { SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_Q_RANGES) .addScalar("q", StandardBasicTypes.DOUBLE) .addScalar("start_km", StandardBasicTypes.DOUBLE) .addScalar("stop_km", StandardBasicTypes.DOUBLE); for (Fixing fixing: fixings) { fixing.loadColumnsQRanges(query, gaugeFinder); } } protected void adjustExtent() { for (Fixing fixing: fixings) { fixing.adjustExtent(extent); } } public boolean load(Session session) { if (!loadRiver(session)) { return false; } GaugeFinderFactory gff = GaugeFinderFactory.getInstance(); GaugeFinder gaugeFinder = gff.getGaugeFinder(riverId, isKmUp); if (gaugeFinder == null) { return false; } loadFixings(session); loadFixingsColumns(session); loadFixingsColumnsKmRange(session); adjustExtent(); loadFixingsColumnsQRanges(session, gaugeFinder); return true; } public static final Range FULL_EXTENT = new Range(-Double.MAX_VALUE, Double.MAX_VALUE); public static final Fixing.Filter ACCEPT = new Fixing.Filter() { @Override public boolean accept(Fixing.Column column) { return true; } }; public static class NotFilter implements Fixing.Filter { protected Fixing.Filter child; public NotFilter(Fixing.Filter child) { this.child = child; } @Override public boolean accept(Fixing.Column column) { return !child.accept(column); } } // class NotFilter public static abstract class ComponentFilter implements Fixing.Filter { protected List<Fixing.Filter> children; public ComponentFilter() { children = new ArrayList<Fixing.Filter>(); } public ComponentFilter(List<Fixing.Filter> children) { this.children = children; } public ComponentFilter add(Fixing.Filter filter) { children.add(filter); return this; } } // class ComponentFilter public static class OrFilter extends ComponentFilter { public OrFilter() { } public OrFilter(List<Fixing.Filter> children) { super(children); } @Override public boolean accept(Fixing.Column column) { for (Fixing.Filter child: children) { if (child.accept(column)) { return true; } } return false; } } // class OrFilter public static class AndFilter extends ComponentFilter { public AndFilter() { } public AndFilter(List<Fixing.Filter> children) { super(children); } @Override public boolean accept(Fixing.Column column) { for (Fixing.Filter child: children) { if (!child.accept(column)) { return false; } } return true; } } // class AndFilter public static class IdFilter implements Fixing.Filter { protected int columnId; public IdFilter(int columnId) { this.columnId = columnId; } @Override public boolean accept(Fixing.Column column) { return column.getId() == columnId; } } // class IdFilter public static class IdsFilter implements Fixing.Filter { protected int [] columnIds; public IdsFilter(int [] columnIds) { this.columnIds = columnIds; } @Override public boolean accept(Fixing.Column column) { int cid = column.getId(); for (int i = columnIds.length-1; i >= 0; --i) { if (columnIds[i] == cid) { return true; } } return false; } } // class IdFilter public static class DateFilter implements Fixing.Filter { protected Date date; public DateFilter(Date date) { this.date = date; } @Override public boolean accept(Fixing.Column column) { return date.equals(column.getStartTime()); } } // class DateFilter public static class DateRangeFilter implements Fixing.Filter { protected Date start; protected Date end; public DateRangeFilter(Date start, Date end) { this.start = start; this.end = end; } @Override public boolean accept(Fixing.Column column) { Date date = column.getStartTime(); return start.compareTo(date) <= 0 && end.compareTo(date) >= 0; } } // class DateRangeFilter public static class SectorFilter implements Fixing.Filter { protected int sector; public SectorFilter(int sector) { this.sector = sector; } @Override public boolean accept(Fixing.Column column) { for (SectorRange s: column.getSectors()) { if (s.getSector() == sector) { return true; } } return false; } } // class SectorFilter public static class SectorRangeFilter implements Fixing.Filter { protected int min; protected int max; public SectorRangeFilter(int min, int max) { this.min = Math.min(min, max); this.max = Math.max(min, max); } @Override public boolean accept(Fixing.Column column) { for (SectorRange s: column.getSectors()) { int v = s.getSector(); if (v >= min && v <= max) { return true; } } return false; } } // class SectorRangeFilter public static class KmFilter implements Fixing.Filter { protected double km; public KmFilter(double km) { this.km = km; } @Override public boolean accept(Fixing.Column column) { for (SectorRange s: column.getSectors()) { if (s.inside(km)) { return true; } } return false; } } // class KmFilter public void generateOverview(Document document) { generateOverview(document, FULL_EXTENT, ACCEPT); } public List<Fixing.Column> filter(Range range, Fixing.Filter filter) { List<Fixing.Column> allColumns = new ArrayList<Fixing.Column>(); for (Fixing fixing: fixings) { fixing.addAllColumns(allColumns, range, filter); } Collections.sort(allColumns, Fixing.DATE_CMP); return allColumns; } protected static Range realRange(List<Fixing.Column> columns) { Range range = null; for (Fixing.Column column: columns) { if (range == null) { range = new Range(column); } else { range.extend(column); } } return range; } protected Element intersectingGauges(Document document, Range range) { Element gauges = document.createElement("gauges"); if (range == null) { return gauges; } GaugeFinderFactory gff = GaugeFinderFactory.getInstance(); GaugeFinder gf = gff.getGaugeFinder(riverId, isKmUp); if (gf == null) { return gauges; } for (GaugeRange gr: gf.getGauges()) { if (gr.intersects(range)) { Element gauge = document.createElement("gauge"); gauge.setAttribute("from", String.valueOf(gr.getStart())); gauge.setAttribute("to", String.valueOf(gr.getEnd())); gauge.setAttribute("name", gr.getName()); gauges.appendChild(gauge); } } return gauges; } public void generateOverview( Document document, Range range, Fixing.Filter filter ) { List<Fixing.Column> allColumns = filter(range, filter); Element fixingsElement = document.createElement("fixings"); Element riverElement = document.createElement("river"); riverElement.setAttribute("from", String.valueOf(extent.start)); riverElement.setAttribute("to", String.valueOf(extent.end)); riverElement.setAttribute("rid", String.valueOf(riverId)); riverElement.setAttribute("name", riverName); fixingsElement.appendChild(riverElement); fixingsElement.appendChild( intersectingGauges( document, realRange(allColumns))); SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); Element esE = document.createElement("events"); for (Fixing.Column column: allColumns) { List<SectorRange> sectors = column.getSectors(range); if (!sectors.isEmpty()) { Element eE = document.createElement("event"); eE.setAttribute("description", String.valueOf(column.getDescription())); eE.setAttribute("cid", String.valueOf(column.columnId)); eE.setAttribute("date", df.format(column.startTime)); for (SectorRange sector: sectors) { Element sE = document.createElement("sector"); sE.setAttribute("from", String.valueOf(sector.start)); sE.setAttribute("to", String.valueOf(sector.end)); sE.setAttribute("class", String.valueOf(sector.sector)); eE.appendChild(sE); } esE.appendChild(eE); } } fixingsElement.appendChild(esE); document.appendChild(fixingsElement); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :