Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixingsOverview.java @ 9646:0380717105ba
Implemented alternative fitting strategy for Log-Linear function.
author | Gernot Belger <g.belger@bjoernsen.de> |
---|---|
date | Mon, 02 Dec 2019 17:56:15 +0100 |
parents | 9744ce3c3853 |
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.artifacts.model.fixings; import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import org.dive4elements.river.artifacts.model.GaugeFinder; import org.dive4elements.river.artifacts.model.GaugeFinderFactory; import org.dive4elements.river.artifacts.model.GaugeRange; import org.dive4elements.river.artifacts.model.Range; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.type.StandardBasicTypes; import org.w3c.dom.Document; import org.w3c.dom.Element; /** Generate Fixings Table overview data structure to be stored in cache. */ public class FixingsOverview implements Serializable { private static final long serialVersionUID = 1L; static Logger log = Logger.getLogger(FixingsOverview.class); static final String DATE_FORMAT = "dd.MM.yyyy"; private static final String SQL_RIVER_ID = "SELECT" + " id AS river_id," + " km_up " + "FROM rivers " + "WHERE" + " name = :name"; /** All kind-2 wsts from given river. */ private static final String SQL_FIXINGS = "SELECT" + " id AS wst_id," + " description " + "FROM wsts " + "WHERE" + " river_id = :river_id AND kind = 2"; /** Helper class to store data from batching fixing columns. */ static final class FixColumn { int columnId; Date startTime; String name; FixColumn(final int columnId, final Date startTime, final String name) { this.columnId = columnId; this.startTime = startTime; this.name = name; } } private String riverName; private int riverId; private boolean isKmUp; private final List<Fixing> fixings; private final Range extent; public FixingsOverview() { this.fixings = new ArrayList<>(); this.extent = new Range(Double.MAX_VALUE, -Double.MAX_VALUE); } public FixingsOverview(final String riverName) { this(); this.riverName = riverName; } private boolean loadRiver(final Session session) { final SQLQuery query = session.createSQLQuery(SQL_RIVER_ID).addScalar("river_id", StandardBasicTypes.INTEGER).addScalar("km_up", StandardBasicTypes.BOOLEAN); query.setString("name", this.riverName); final List<Object[]> list = query.list(); if (list.isEmpty()) { log.warn("No river '" + this.riverName + "' found."); return false; } final Object[] row = list.get(0); this.riverId = (Integer) row[0]; this.isKmUp = (Boolean) row[1]; return true; } private void loadFixings(final Session session) { final SQLQuery query = session.createSQLQuery(SQL_FIXINGS).addScalar("wst_id", StandardBasicTypes.INTEGER).addScalar("description", StandardBasicTypes.STRING); query.setInteger("river_id", this.riverId); final List<Object[]> list = query.list(); if (list.isEmpty()) { log.warn("River " + this.riverId + " has no fixings."); // Its pretty fine to have no fixings. } for (final Object[] row : list) { final int wstId = (Integer) row[0]; final String description = (String) row[1]; final Fixing fixing = new Fixing(wstId, description); this.fixings.add(fixing); } } private void loadFixingsColumns(final Session session) { final FixColumnLoader loader = new FixColumnLoader(allFixingIds(), session); for (final Fixing fixing : this.fixings) { fixing.loadColumns(loader); } } private List<Integer> allFixingIds() { final List<Integer> ids = new ArrayList<>(this.fixings.size()); for (final Fixing fixing : this.fixings) { ids.add(fixing.getId()); } return ids; } private List<Integer> allColumnIds() { final List<Integer> cIds = new ArrayList<>(); for (final Fixing fixing : this.fixings) { fixing.allColumnIds(cIds); } return cIds; } private void loadFixingsColumnsKmRange(final Session session) { final KMRangeLoader loader = new KMRangeLoader(allColumnIds(), session); for (final Fixing fixing : this.fixings) { fixing.loadColumnsKmRange(loader); } } private void loadFixingsColumnsQRanges(final Session session, final GaugeFinder gaugeFinder) { final ColumnQRangeLoader loader = new ColumnQRangeLoader(allColumnIds(), session); for (final Fixing fixing : this.fixings) { fixing.loadColumnsQRanges(loader, gaugeFinder); } } private void adjustExtent() { for (final Fixing fixing : this.fixings) { fixing.adjustExtent(this.extent); } } boolean load(final Session session) { if (!loadRiver(session)) { return false; } final GaugeFinderFactory gff = GaugeFinderFactory.getInstance(); final GaugeFinder gaugeFinder = gff.getGaugeFinder(this.riverId, this.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 FixingColumnFilter ACCEPT = new FixingColumnFilter() { @Override public boolean accept(final FixingColumn column) { return true; } }; public static class NotFilter implements FixingColumnFilter { protected FixingColumnFilter child; public NotFilter(final FixingColumnFilter child) { this.child = child; } @Override public boolean accept(final FixingColumn column) { return !this.child.accept(column); } } // class NotFilter public static abstract class ComponentFilter implements FixingColumnFilter { protected List<FixingColumnFilter> children; public ComponentFilter() { this.children = new ArrayList<>(); } public ComponentFilter(final List<FixingColumnFilter> children) { this.children = children; } public ComponentFilter add(final FixingColumnFilter filter) { this.children.add(filter); return this; } } // class ComponentFilter public static class OrFilter extends ComponentFilter { public OrFilter() { } public OrFilter(final List<FixingColumnFilter> children) { super(children); } @Override public boolean accept(final FixingColumn column) { for (final FixingColumnFilter child : this.children) { if (child.accept(column)) { return true; } } return false; } } // class OrFilter public static class AndFilter extends ComponentFilter { public AndFilter() { } public AndFilter(final List<FixingColumnFilter> children) { super(children); } @Override public boolean accept(final FixingColumn column) { for (final FixingColumnFilter child : this.children) { if (!child.accept(column)) { return false; } } return true; } } // class AndFilter public static class IdFilter implements FixingColumnFilter { protected int columnId; public IdFilter(final int columnId) { this.columnId = columnId; } @Override public boolean accept(final FixingColumn column) { return column.getId() == this.columnId; } } // class IdFilter /** Accept Fixing columns whose id is in id list. */ public static class IdsFilter implements FixingColumnFilter { protected int[] columnIds; public IdsFilter(final int[] columnIds) { this.columnIds = columnIds; } @Override public boolean accept(final FixingColumn column) { final int cid = column.getId(); for (int i = this.columnIds.length - 1; i >= 0; --i) { if (this.columnIds[i] == cid) { return true; } } return false; } } // class IdFilter public static class DateFilter implements FixingColumnFilter { protected Date date; public DateFilter(final Date date) { this.date = date; } @Override public boolean accept(final FixingColumn column) { return this.date.equals(column.getStartTime()); } } // class DateFilter public static class DateRangeFilter implements FixingColumnFilter { protected Date start; protected Date end; public DateRangeFilter(final Date start, final Date end) { if (start.before(end)) { this.start = start; this.end = end; } else { this.start = end; this.end = start; } } @Override public boolean accept(final FixingColumn column) { final Date date = column.getStartTime(); // start <= date <= end return !(date.before(this.start) || date.after(this.end)); } } // class DateRangeFilter public static class SectorFilter implements FixingColumnFilter { protected int sector; public SectorFilter(final int sector) { this.sector = sector; } @Override public boolean accept(final FixingColumn column) { for (final SectorRange s : column.getSectors()) { if (s.getSector() == this.sector) { return true; } } return false; } } // class SectorFilter public static class SectorRangeFilter implements FixingColumnFilter { protected int min; protected int max; public SectorRangeFilter(final int min, final int max) { this.min = Math.min(min, max); this.max = Math.max(min, max); } @Override public boolean accept(final FixingColumn column) { for (final SectorRange s : column.getSectors()) { final int v = s.getSector(); if (v < this.min || v > this.max) { return false; } } return true; } } // class SectorRangeFilter public static class KmFilter implements FixingColumnFilter { protected double km; public KmFilter(final double km) { this.km = km; } @Override public boolean accept(final FixingColumn column) { for (final SectorRange s : column.getSectors()) { if (s.inside(this.km)) { return true; } } return false; } } // class KmFilter public void generateOverview(final Document document) { generateOverview(document, FULL_EXTENT, ACCEPT); } /** * @param range * can be null. */ public List<FixingColumn> filter(final Range range, final FixingColumnFilter filter) { final List<FixingColumn> allColumns = new ArrayList<>(); for (final Fixing fixing : this.fixings) { fixing.addAllColumns(allColumns, range, filter); } Collections.sort(allColumns, Fixing.DATE_CMP); return allColumns; } private static Range realRange(final List<FixingColumn> columns) { Range range = null; for (final FixingColumn column : columns) { if (range == null) { range = new Range(column); } else { range.extend(column); } } return range; } private Element intersectingGauges(final Document document, final Range range) { final Element gauges = document.createElement("gauges"); if (range == null) { return gauges; } final GaugeFinderFactory gff = GaugeFinderFactory.getInstance(); final GaugeFinder gf = gff.getGaugeFinder(this.riverId, this.isKmUp); if (gf == null) { return gauges; } for (final GaugeRange gr : gf.getGauges()) { if (gr.intersects(range)) { final 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; } /** Populate document with fixings, filtered by range and filter. */ public void generateOverview(final Document document, final Range range, final FixingColumnFilter filter) { final List<FixingColumn> allColumns = filter(range, filter); final Element fixingsElement = document.createElement("fixings"); final Element riverElement = document.createElement("river"); riverElement.setAttribute("from", String.valueOf(this.extent.getStart())); riverElement.setAttribute("to", String.valueOf(this.extent.getEnd())); riverElement.setAttribute("rid", String.valueOf(this.riverId)); riverElement.setAttribute("name", this.riverName); fixingsElement.appendChild(riverElement); fixingsElement.appendChild(intersectingGauges(document, realRange(allColumns))); final SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); final Element esE = document.createElement("events"); for (final FixingColumn column : allColumns) { final List<SectorRange> sectors = column.getSectors(range); if (!sectors.isEmpty()) { final Element eE = document.createElement("event"); eE.setAttribute("description", String.valueOf(column.getDescription())); eE.setAttribute("cid", String.valueOf(column.getId())); eE.setAttribute("date", df.format(column.getStartTime())); for (final SectorRange sector : sectors) { final Element sE = document.createElement("sector"); sE.setAttribute("from", String.valueOf(sector.getStart())); sE.setAttribute("to", String.valueOf(sector.getEnd())); sE.setAttribute("class", String.valueOf(sector.getSector())); eE.appendChild(sE); } esE.appendChild(eE); } } fixingsElement.appendChild(esE); document.appendChild(fixingsElement); } public Range getExtent() { return this.extent; } }