# HG changeset patch # User gernotbelger # Date 1531474825 -7200 # Node ID 68ff4087b987ccff7a7c5c819389339f90b673a4 # Parent eedb0bcf226b1f7fc2101a3d27e67e6337618b58# Parent c2a0028bfa9f258065158f97deb39e73883b10e7 Zusammenführen diff -r eedb0bcf226b -r 68ff4087b987 artifacts/doc/conf/artifacts/bundu.xml --- a/artifacts/doc/conf/artifacts/bundu.xml Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/doc/conf/artifacts/bundu.xml Fri Jul 13 11:40:25 2018 +0200 @@ -325,7 +325,7 @@ - + diff -r eedb0bcf226b -r 68ff4087b987 artifacts/doc/conf/artifacts/sinfo.xml --- a/artifacts/doc/conf/artifacts/sinfo.xml Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/doc/conf/artifacts/sinfo.xml Fri Jul 13 11:40:25 2018 +0200 @@ -307,18 +307,12 @@ - + - - - - - - - + - + @@ -372,7 +366,7 @@ - + diff -r eedb0bcf226b -r 68ff4087b987 artifacts/doc/conf/artifacts/uinfo.xml --- a/artifacts/doc/conf/artifacts/uinfo.xml Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/doc/conf/artifacts/uinfo.xml Fri Jul 13 11:40:25 2018 +0200 @@ -78,6 +78,18 @@ + + + + + + + + + + + + @@ -85,7 +97,9 @@ - + + + @@ -104,7 +118,7 @@ - + @@ -118,9 +132,10 @@ - + + @@ -343,7 +358,7 @@ - + diff -r eedb0bcf226b -r 68ff4087b987 artifacts/doc/conf/generators/generators.xml --- a/artifacts/doc/conf/generators/generators.xml Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/doc/conf/generators/generators.xml Fri Jul 13 11:40:25 2018 +0200 @@ -70,6 +70,8 @@ + + diff -r eedb0bcf226b -r 68ff4087b987 artifacts/doc/conf/jasper/templates/uinfo.salixline.jrxml --- a/artifacts/doc/conf/jasper/templates/uinfo.salixline.jrxml Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/doc/conf/jasper/templates/uinfo.salixline.jrxml Fri Jul 13 11:40:25 2018 +0200 @@ -1,6 +1,6 @@ - + @@ -54,6 +54,7 @@ + @@ -134,17 +135,11 @@ - + - - - - - - @@ -182,17 +177,6 @@ - - - - - - - - - - - diff -r eedb0bcf226b -r 68ff4087b987 artifacts/doc/conf/meta-data.xml --- a/artifacts/doc/conf/meta-data.xml Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/doc/conf/meta-data.xml Fri Jul 13 11:40:25 2018 +0200 @@ -142,9 +142,6 @@ - - - diff -r eedb0bcf226b -r 68ff4087b987 artifacts/doc/conf/themes.xml --- a/artifacts/doc/conf/themes.xml Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/doc/conf/themes.xml Fri Jul 13 11:40:25 2018 +0200 @@ -448,11 +448,9 @@ - - diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractExportContext.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractExportContext.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractExportContext.java Fri Jul 13 11:40:25 2018 +0200 @@ -23,7 +23,7 @@ private NumberFormat qFormat = null; private NumberFormat flowDepthFormat = null; - + private NumberFormat salixScenFormat = null; private NumberFormat kmFormat = null; /** The CallContext object. */ @@ -70,6 +70,13 @@ return this.flowDepthFormat; } + public final NumberFormat getSalixScenFormatter() { + if (this.salixScenFormat == null) + this.salixScenFormat = Formatter.getSalixLine(this.context); + + return this.salixScenFormat; + } + protected String msg(final String key) { return Resources.getMsg(this.context.getMeta(), key, key); } diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java Fri Jul 13 11:40:25 2018 +0200 @@ -147,7 +147,8 @@ SC("sinfo_collision"), // SFDUR("sinfo_flood_duration"), // STKH("sinfo_tkk"), // - SFW("sinfo_flood_height"); + SFW("sinfo_flood_height"), // + SFDC("sinfo_floodduration_curve"); private final String chartTypeString; diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java Fri Jul 13 11:40:25 2018 +0200 @@ -22,7 +22,6 @@ import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; import org.dive4elements.river.model.River; -import org.dive4elements.river.model.sinfo.Infrastructure; /** * Calculation of the flood durations of the infrastructures of the km range of a river @@ -49,21 +48,19 @@ final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange); final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name()); - final Infrastructure infrasSeries = Infrastructure.getSeries(river); - final String infrasType = (infrasSeries != null) ? infrasSeries.getType().getName() : "?"; - final String label = infrasType + ", " + Resources.getMsg(this.context.getMeta(), access.getRiverside().getKey()); + final String label = Resources.getMsg(this.context.getMeta(), access.getRiverside().getKey()); final Calculation problems = new Calculation(); // Calculate the selected main values, if any /* misuse winfo-artifact to calculate waterlevels in the same way */ final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo); - // TODO Aktivieren wenn Step-Eingabe im Workflow weg: winfo.addStringData("ld_step", "100"); + winfo.addStringData("ld_mode", "distance"); + winfo.addStringData("ld_step", "100"); final FloodDurationCalculationResults results = new FloodDurationCalculationResults(calcModeLabel, user, riverInfo, calcRange); - final FloodDurationCalculationResult result = calculateResult(label, calcRange, infoProvider, access.getRiverside(), problems, winfo); - results.addResult(result, problems); + calculateResult(label, calcRange, infoProvider, access.getRiverside(), problems, winfo, results); return new CalculationResult(results, problems); } @@ -71,10 +68,10 @@ /** * Calculates the flood durations of the infrastructures of a km range of a river */ - private FloodDurationCalculationResult calculateResult(final String label, final DoubleRange calcRange, final RiverInfoProvider riverInfoProvider, - final RiversideChoiceKey riverside, final Calculation problems, final WINFOArtifact winfo) { + private void calculateResult(final String label, final DoubleRange calcRange, final RiverInfoProvider riverInfoProvider, + final RiversideChoiceKey riverside, final Calculation problems, final WINFOArtifact winfo, final FloodDurationCalculationResults results) { final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, riverInfoProvider); - return calculator.execute(problems, label, calcRange, riverside, winfo); + calculator.execute(problems, label, calcRange, riverside, winfo, results); } } \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResult.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResult.java Fri Jul 13 11:40:25 2018 +0200 @@ -76,8 +76,7 @@ if (this.mainvalueLabels.length >= 1) { // "##METADATEN WASSERSPIEGELLAGE" exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL); - for (int i = 1; i <= getWaterlevelCount(); // this.mainvalueLabels.length; - i++) { + for (int i = 1; i <= getWaterlevelCount(); i++) { // "# Bezeichnung der Wasserspiegellage: " final String label = this.getMainValueLabel(i - 1); exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_NAME, String.format("%d: %s", i, label)); diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java Fri Jul 13 11:40:25 2018 +0200 @@ -11,6 +11,7 @@ import org.apache.commons.lang.math.DoubleRange; import org.dive4elements.river.artifacts.common.AbstractCalculationResults; +import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; /** @@ -23,4 +24,14 @@ public FloodDurationCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange) { super(calcModeLabel, user, river, calcRange); } + + private CalculationResult durationCurve; + + public CalculationResult getDurationCurve() { + return this.durationCurve; + } + + public void setDurationCurve(final CalculationResult durationCurve) { + this.durationCurve = durationCurve; + } } \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java Fri Jul 13 11:40:25 2018 +0200 @@ -25,6 +25,7 @@ import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.artifacts.model.Calculation.Problem; import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WQDay; import org.dive4elements.river.artifacts.model.WQKms; import org.dive4elements.river.artifacts.sinfo.common.GaugeDurationValuesFinder; import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; @@ -60,8 +61,8 @@ /** * Calculate the infrastructures flood duration result rows */ - public FloodDurationCalculationResult execute(final Calculation problems, final String label, final DoubleRange calcRange, - final RiversideChoiceKey riverside, final WINFOArtifact winfo) { + public void execute(final Calculation problems, final String label, final DoubleRange calcRange, + final RiversideChoiceKey riverside, final WINFOArtifact winfo, final FloodDurationCalculationResults results) { // Find all gauges of the calc range, and create the duration finders final Map durFinders = new HashMap<>(); @@ -113,8 +114,29 @@ this.rows.add(row2); } } + results.addResult(new FloodDurationCalculationResult(label, mainValueLabels, this.rows), problems); + calcWQDays(problems, stationsSorted[0], AttributeKey.LEFT, winfo, results); + } - return new FloodDurationCalculationResult(label, mainValueLabels, this.rows); + public void calcWQDays(final Calculation problems, final double station, final AttributeKey riverside, final WINFOArtifact winfo, + final FloodDurationCalculationResults results) { + + winfo.addStringData("ld_locations", Double.toString(station)); + final CalculationResult res = winfo.getDurationCurveData(); + final WQDay underflow = (WQDay) res.getData(); + // Transform underflow days into overflow days and re-sort + final int[] days = new int[underflow.getWs().length]; + final double[] ws = new double[days.length]; + final double[] qs = new double[days.length]; + for (int i = 0, j = days.length - 1; i <= days.length - 1; i++, j--) { + days[j] = 365 - underflow.getDay(i); + ws[j] = underflow.getW(i); + qs[j] = underflow.getQ(i); + } + res.setData(new WQDay(days, ws, qs)); + // TODO Infrastrukturhoehe + // TODO WSPL/Hauptwerte + results.setDurationCurve(res); } /** diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,120 @@ +/* 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.sinfo.flood_duration; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.dive4elements.artifactdatabase.state.DefaultFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.D4EArtifact; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.WQDay; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +/** + * Data of a duration curve. + */ +public class FloodDurationCurveFacet extends DefaultFacet { + + private static Logger log = Logger.getLogger(FloodDurationCurveFacet.class); + + /** Blackboard data provider key for durationcurve (wqday) data. */ + public static String BB_DURATIONCURVE = "durationcurve"; + + /** Blackboard data provider key for km of durationcurve. */ + public static String BB_DURATIONCURVE_KM = "durationcurve.km"; + + public FloodDurationCurveFacet() { + } + + public FloodDurationCurveFacet(final String name, final String description) { + super(0, name, description); + } + + + /** + * Expose state computation from SINFOArtifact. + */ + @Override + public Object getData(final Artifact artifact, final CallContext context) { + + log.debug("Get data for flood duration curve data"); + + final D4EArtifact flys = (D4EArtifact) artifact; + + final CalculationResult res = (CalculationResult) flys.compute(context, ComputeType.ADVANCE, false); + + final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData(); + + return data.getDurationCurve(); + // return getTestData(); + } + + private WQDay getTestData() { + final int[] days = new int[366]; + final double[] ws = new double[366]; + final double[] qs = new double[366]; + for (int i = 0; i <= 365; i++) { + days[i] = i; + final double x = (i - 182.5) / 182.5; + ws[i] = 102.0 - (Math.pow(x, 5) + x); + qs[i] = 1600.0 - 800 * (Math.pow(x, 9) + x); + } + return new WQDay(days, ws, qs); + } + + + @Override + public List getStaticDataProviderKeys(final Artifact art) { + final List list = new ArrayList(); + list.add(BB_DURATIONCURVE); + list.add(BB_DURATIONCURVE_KM); + return list; + } + + + /** + * Can provide whatever getData returns and additionally the location. + * @param key will respond on BB_DURATIONCURVE +KM + * @param param ignored + * @param context ignored + * @return whatever getData delivers or location. + */ + @Override + public Object provideBlackboardData(final Artifact artifact, + final Object key, + final Object param, + final CallContext context + ) { + if (key.equals(BB_DURATIONCURVE)) { + return getData(artifact, context); + } + else if (key.equals(BB_DURATIONCURVE_KM)) { + return ((D4EArtifact)artifact).getDataAsString("ld_locations"); + } + else { + return null; + } + } + + + /** Create a deep copy. */ + @Override + public Facet deepCopy() { + final FloodDurationCurveFacet copy = new FloodDurationCurveFacet(); + copy.set(this); + return copy; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveGenerator.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,258 @@ +/* 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.sinfo.flood_duration; + +import java.awt.Font; +import java.awt.geom.Point2D; + +import org.apache.log4j.Logger; +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQDay; +import org.dive4elements.river.exports.IdentifiableNumberAxis; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.RiverAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.Range; +import org.jfree.data.xy.XYSeries; + + +/** + * An OutGenerator that generates duration curves. + * + * @author Ingo Weinzierl + */ +public class FloodDurationCurveGenerator +extends XYChartGenerator +implements FacetTypes +{ + public static enum YAXIS { + W(0), + Q(1); + public int idx; + private YAXIS(final int c) { + this.idx = c; + } + } + + /** Local log. */ + private static Logger log = + Logger.getLogger(FloodDurationCurveGenerator.class); + + public static final String I18N_CHART_TITLE = "sinfo.chart.flood_duration.curve.section.title"; + + public static final String I18N_CHART_SUBTITLE = "chart.duration.curve.subtitle"; + + public static final String I18N_XAXIS_LABEL = "sinfo.chart.flood_duration.curve.xaxis.label"; + + public static final String I18N_YAXIS_LABEL_W = "chart.duration.curve.yaxis.label.w"; + + public static final String I18N_YAXIS_LABEL_Q = "chart.duration.curve.yaxis.label.q"; + + public static final String I18N_CHART_TITLE_DEFAULT = "Dauerlinie"; + + public static final String I18N_XAXIS_LABEL_DEFAULT = "Überflutungsdauer [d/a]"; + + + public FloodDurationCurveGenerator() { + super(); + } + + + /** + * Create Axis for given index. + * @return axis with according internationalized label. + */ + @Override + protected NumberAxis createYAxis(final int index) { + final Font labelFont = new Font("Tahoma", Font.BOLD, 14); + final String label = getYAxisLabel(index); + + final NumberAxis axis = createNumberAxis(index, label); + if (index == YAXIS.W.idx) { + axis.setAutoRangeIncludesZero(false); + } + axis.setLabelFont(labelFont); + return axis; + } + + + @Override + protected String getDefaultChartTitle(final CallContext context) { + return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); + } + + + @Override + protected String getDefaultChartSubtitle(final CallContext context) { + + final double[] dist = getRange(); + return msg(I18N_CHART_SUBTITLE, "", getRiverName(), dist[0]); + } + + + @Override + protected String getDefaultXAxisLabel(final CallContext context) { + return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT); + } + + + @Override + protected String getDefaultYAxisLabel(final int index) { + + String label = "default"; + if (index == YAXIS.W.idx) { + label = msg(I18N_YAXIS_LABEL_W, I18N_YAXIS_LABEL_W, getRiverUnit()); + } + else if (index == YAXIS.Q.idx) { + label = msg(I18N_YAXIS_LABEL_Q); + } + return label; + } + + + @Override + protected boolean zoomX(final XYPlot plot, final ValueAxis axis, final Bounds bounds, final Range x) { + + final boolean zoomin = super.zoom(plot, axis, bounds, x); + if (!zoomin) + axis.setLowerBound(0d); + // axis.setUpperBound(364); + return zoomin; + } + + + /** + * This method overrides the method in the parent class to set the lower + * bounds of the Q axis to 0. This axis should never display negative + * values on its own. + */ + @Override + protected boolean zoomY(final XYPlot plot, final ValueAxis axis, final Bounds bounds, final Range x) { + + final boolean zoomin = super.zoom(plot, axis, bounds, x); + if (!zoomin && axis instanceof IdentifiableNumberAxis) { + final String id = ((IdentifiableNumberAxis) axis).getId(); + if (YAXIS.Q.toString().equals(id)) + axis.setLowerBound(0d); + } + return zoomin; + } + + + @Override + public void doOut(final ArtifactAndFacet artifactFacet, final ThemeDocument attr, final boolean visible) { + + final String name = artifactFacet.getFacetName(); + + log.debug("FloodDurationCurveGenerator.doOut: " + name); + + if (name == null || name.length() == 0) { + log.error("No facet given. Cannot create dataset."); + return; + } + + final CallContext context = getContext(); + + if (name.equals(DURATION_W)) { + doWOut((WQDay) ((CalculationResult) artifactFacet.getData(context)).getData(), artifactFacet, attr, visible); + } + else if (name.equals(DURATION_Q)) { + doQOut((WQDay) ((CalculationResult) artifactFacet.getData(context)).getData(), artifactFacet, attr, visible); + } + else if (name.equals(MAINVALUES_Q) || name.equals(MAINVALUES_W)) { + doAnnotations((RiverAnnotation) artifactFacet.getData(context), artifactFacet, attr, visible); + } + else if (name.equals(RELATIVE_POINT)) { + doPointOut((Point2D) artifactFacet.getData(context), artifactFacet, attr, visible); + } + else if (FacetTypes.IS.MANUALPOINTS(name)) { + doPoints(artifactFacet.getData(context), artifactFacet, attr, visible, YAXIS.W.idx); + } + else { + log.warn("Unknown facet name: " + name); + return; + } + } + + /** + * Creates the series for a duration curve's W facet. + * + * @param wqdays The WQDay store that contains the Ws. + * @param theme + */ + protected void doWOut(final WQDay wqdays, final ArtifactAndFacet aaf, final ThemeDocument theme, final boolean visible) { + + // log.debug("DurationCurveGenerator.doWOut"); + final XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + final int size = wqdays.size(); + for (int i = 0; i < size; i++) { + final int day = wqdays.getDay(i); + final double w = wqdays.getW(i); + series.add(day, w); + } + addAxisSeries(series, YAXIS.W.idx, visible); + } + + protected void doPointOut(final Point2D point, final ArtifactAndFacet aandf, final ThemeDocument theme, final boolean visible) { + + // log.debug("DurationCurveGenerator.doPointOut"); + final XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + series.add(point.getX(), point.getY()); + addAxisSeries(series, YAXIS.W.idx, visible); + } + + + /** + * Creates the series for a duration curve's Q facet. + * + * @param wqdays The WQDay store that contains the Qs. + * @param theme + */ + protected void doQOut(final WQDay wqdays, final ArtifactAndFacet aaf, final ThemeDocument theme, final boolean visible) { + + // log.debug("DurationCurveGenerator.doQOut"); + final XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + final int size = wqdays.size(); + for (int i = 0; i < size; i++) { + final int day = wqdays.getDay(i); + final double q = wqdays.getQ(i); + series.add(day, q); + } + addAxisSeries(series, YAXIS.Q.idx, visible); + } + + + @Override + protected YAxisWalker getYAxisWalker() { + return new YAxisWalker() { + @Override + public int length() { + return YAXIS.values().length; + } + + @Override + public String getId(final int idx) { + final YAXIS[] yaxes = YAXIS.values(); + return yaxes[idx].toString(); + } + }; + } + + // MainValue-Annotations should be visualized by + // a line that goes to the curve itself. +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveInfoGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveInfoGenerator.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,26 @@ +/* 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.sinfo.flood_duration; + +import org.dive4elements.river.exports.ChartInfoGenerator; + +/** + * A ChartInfoGenerator that generates meta information for specific duration + * curves. + * + * @author Ingo Weinzierl + */ +public class FloodDurationCurveInfoGenerator +extends ChartInfoGenerator +{ + public FloodDurationCurveInfoGenerator() { + super(new FloodDurationCurveGenerator()); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveProcessor.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,74 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.sinfo.flood_duration; + +import java.util.HashSet; +import java.util.Set; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.common.AbstractCalculationResult; +import org.dive4elements.river.exports.DiagramGenerator; +import org.dive4elements.river.exports.DurationCurveGenerator; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.exports.process.DefaultProcessor; +import org.dive4elements.river.themes.ThemeDocument; + +/** + * Processor to generate the facet and data series of a flood duration curve + * + * @author Matthias Schäfer + * + */ +public final class FloodDurationCurveProcessor extends DefaultProcessor { + + private static final String FACET_FLOOD_DURATION_W = "duration_curve.w"; + + private static final String FACET_FLOOD_DURATION_Q = "duration_curve.q"; + + private static final Set HANDLED_FACET_TYPES = new HashSet<>(); + + static { + HANDLED_FACET_TYPES.add(FACET_FLOOD_DURATION_W); + HANDLED_FACET_TYPES.add(FACET_FLOOD_DURATION_Q); + } + + public static Facet createFloodDurationWCurveFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result, + final int facetIndex, final int resultIndex, final String description) { + + return new FloodDurationCurveFacet(FACET_FLOOD_DURATION_W, description); + } + + public static Facet createFloodDurationQCurveFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result, + final int facetIndex, final int resultIndex, final String description) { + + return new FloodDurationCurveFacet(FACET_FLOOD_DURATION_Q, description); + } + + /** + * Processes data to generate a chart. + */ + @Override + public void doOut(final XYChartGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible, final int index) { + + } + + @Override + public final String getAxisLabel(final DiagramGenerator generator) { + return generator.msg(DurationCurveGenerator.I18N_YAXIS_LABEL_W); + } + + @Override + public final boolean canHandle(final String facettype) { + return HANDLED_FACET_TYPES.contains(facettype); + } +} \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationState.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationState.java Fri Jul 13 11:40:25 2018 +0200 @@ -20,6 +20,7 @@ import org.dive4elements.river.artifacts.model.EmptyFacet; import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.ReportFacet; +import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; import org.dive4elements.river.artifacts.sinfo.flood_duration.RiversideRadioChoice.RiversideChoiceKey; import org.dive4elements.river.artifacts.states.DefaultState; @@ -94,7 +95,7 @@ for (int j = 0; j < waterlevelCount; j++) { - final String waterlevelLabel = result.getMainValueLabel(j); + // final String waterlevelLabel = result.getMainValueLabel(j); // FIXME: use label as label for theme // final int facetIndex, final int resultIndex, final int dataIndex @@ -104,6 +105,11 @@ themeCount++; } + final String nameW = Resources.getMsg(context.getMeta(), "sinfo.chart.flood_duration.curve.w"); + final String nameQ = Resources.getMsg(context.getMeta(), "sinfo.chart.flood_duration.curve.q"); + facets.add(FloodDurationCurveProcessor.createFloodDurationWCurveFacet(context, hash, this.id, result, 0, resultIndex, nameW)); + facets.add(FloodDurationCurveProcessor.createFloodDurationQCurveFacet(context, hash, this.id, result, 1, resultIndex, nameQ)); + facets.add(new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id)); facets.add(new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id)); diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/commons/UInfoResultType.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/commons/UInfoResultType.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/commons/UInfoResultType.java Fri Jul 13 11:40:25 2018 +0200 @@ -40,6 +40,69 @@ return null; } + public static final UInfoResultType customMultiRowColSalixRegionalValue_Dwspl = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.scenario") { + private static final long serialVersionUID = 1L; + + @Override + public String exportValue(final CallContext context, final Object value) { + throw new UnsupportedOperationException(); + } + + @Override + protected NumberFormat createFormatter(final CallContext context) { + throw new UnsupportedOperationException(); + } + }; + + public static final UInfoResultType salix_line_scenario = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.scenario") { + private static final long serialVersionUID = 1L; + + @Override + public String exportValue(final CallContext context, final Object value) { + final double doubleValue = asDouble(value); + return exportDoubleValue(context, doubleValue); + } + + @Override + protected NumberFormat createFormatter(final CallContext context) { + // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of + // digits. + return Formatter.getSalixLine(context); + } + }; + + public static final UInfoResultType salix_line_scenario_dwspl = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.scenario_dwspl") { + private static final long serialVersionUID = 1L; + + @Override + public String exportValue(final CallContext context, final Object value) { + final String valueStr = String.valueOf(value); + return exportStringValue(valueStr); + } + + @Override + protected NumberFormat createFormatter(final CallContext context) { + + return Formatter.getIntegerFormatter(context); + } + }; + public static final UInfoResultType salix_delta_mw = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.delta_mw") { + private static final long serialVersionUID = 1L; + + @Override + public String exportValue(final CallContext context, final Object value) { + final double doubleValue = asDouble(value); + return exportDoubleValue(context, doubleValue); + } + + @Override + protected NumberFormat createFormatter(final CallContext context) { + // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of + // digits. + return Formatter.getSalixLine(context); + } + }; + public static final UInfoResultType salixline = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.salix_line") { private static final long serialVersionUID = 1L; @@ -74,23 +137,6 @@ } }; - public static final UInfoResultType salixlinescen = new UInfoResultType(null, "uinfo.export.salix_line.csv.header.scen") { - private static final long serialVersionUID = 1L; - - @Override - public String exportValue(final CallContext context, final Object value) { - final double doubleValue = asDouble(value); - return exportDoubleValue(context, doubleValue); - } - - @Override - protected NumberFormat createFormatter(final CallContext context) { - // REMARK: other modules use Formatter.getWaterlevelW(context) instead, but that format with a variable number of - // digits. - return Formatter.getSalixLine(context); - } - }; - public static final UInfoResultType vegname = new UInfoResultType(null, "uinfo.export.csv.meta.header.veg.name") { private static final long serialVersionUID = 1L; diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/DistanceOnlyPartHistoricalSelect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/DistanceOnlyPartHistoricalSelect.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,188 @@ +/* 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.uinfo.salix; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.log4j.Logger; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.AddTableDataHelper; +import org.dive4elements.river.artifacts.states.DistanceOnlySelect; +import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; +import org.dive4elements.river.model.BedHeight; +import org.dive4elements.river.model.River; +import org.dive4elements.river.utils.Formatter; +import org.w3c.dom.Element; + +public class DistanceOnlyPartHistoricalSelect extends DistanceOnlySelect { + + private static final long serialVersionUID = 1L; + private static Logger log = Logger.getLogger(DistanceOnlyPartHistoricalSelect.class); + + List bhs = null; + Integer epoch = null; + Integer year = null; + Double lowerKm = null; + Double upperKm = null; + River river = null; + + @Override + protected String getUIProvider() { + return "distance_only_part_historical_panel"; + } + + @Override + protected String getTitle(final CallContext context) { + // REMARK: that is how it should be: return Resources.getMsg(context.getMeta(), getID()); + return Resources.getMsg(context.getMeta(), "state.title.distance_part_state"); + } + + @Override + protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) { + final String datakey = "bedheights_for_part"; + + try { + if (datakey.equals(name)) { + makeDataSourceYearEpoch(artifact, creator, select, context, getBedheights(artifact)); // ist nur n test + } else if (name.equals("ld_from_part")) { + + final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact); + final double lowerSoundings = this.getLowerUpperKmRange(getBedheights(artifact))[0]; + final double lowerKm = access.getLowerKm() > lowerSoundings ? access.getLowerKm() : lowerSoundings; + + creator.addAttr(select, "type", "options", true); + + final Element item = creator.create("item"); + creator.addAttr(item, "label", "from_test", true); + creator.addAttr(item, "value", String.valueOf(lowerKm), true); + + select.appendChild(item); + } + + else if (name.equals("ld_to_part")) { + final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact); + final double upperSoundings = this.getLowerUpperKmRange(getBedheights(artifact))[1]; + final double upperKm = access.getUpperKm() < upperSoundings ? access.getUpperKm() : upperSoundings; + + creator.addAttr(select, "type", "options", true); + + final Element item = creator.create("item"); + creator.addAttr(item, "label", "to_test", true); + creator.addAttr(item, "value", String.valueOf(upperKm), true); + + select.appendChild(item); + + } + } + catch ( + + final IllegalArgumentException iae) { + iae.printStackTrace(); + } + } + + private List getBedheights(final Artifact artifact) { + + final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact); // improved lazy-loading + final Integer year = access.getYear(); + final Integer epoch = access.getEpoch(); + final River river = access.getRiver(); // comparable? workflow does not allow return and change anyway... + final Double lower = access.getLowerKm(); + final Double upper = access.getUpperKm(); + if (!(this.year == year && this.epoch == epoch && this.river == river && this.lowerKm == lower && this.upperKm == upper)) { + this.bhs = null; + } + if (this.bhs == null) { + final boolean isEpoch = epoch == null ? false : true; + this.bhs = BedHeight.getBedHeightYearEpoch(isEpoch, isEpoch ? epoch : year, river, lower, upper); + this.year = year; + this.epoch = epoch; + this.river = river; + this.lowerKm = lower; + this.upperKm = upper; + } + return this.bhs; + + } + + private static final void makeDataSourceYearEpoch(final Artifact artifact, final ElementCreator creator, final Element select, final CallContext context, + final List bedheights) { + + final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta()); + + // TODO: probably aggregating results, no sound-row, output as single row + + int year = 0; // hässlich, aber kommt vermutlich eh bald weg + if (bedheights != null && bedheights.size() > 0) + year = bedheights.get(0).getYear(); // das jahr/epoche ist immer dasselbe + + helper.addColumn(0, "year", "60", "year", "INTEGER", "LEFT", null); + helper.addColumn(1, "range", "130", "state.uinfo.salix.historical.km_range_part", "STRING", "LEFT", null); + helper.addColumn(2, "description", "500", "uinfo.salix.sounding", "STRING", "LEFT", null); + + final TreeMap bedHeightSorted = new TreeMap<>(); + final double min = Double.MAX_VALUE; + final double max = -Double.MAX_VALUE; + final java.text.NumberFormat formatter = Formatter.getCalculationKm(context.getMeta()); + + for (final BedHeight bh : bedheights) { + final org.dive4elements.river.model.Range range = BedHeight.getRangeFromBedHeights(bh); + final Double from = range.getA().doubleValue(); // NullPointer check?? + final Double to = range.getB().doubleValue(); + + bedHeightSorted.put(bh.getDescription(), formatter.format(from) + " - " + formatter.format(to)); + } + final Iterator iterator = bedHeightSorted.keySet().iterator(); + while (iterator.hasNext()) { + final String descr = iterator.next(); + final String fromTo = bedHeightSorted.get(descr); + final Map row = new HashMap<>(); + row.put("year", String.valueOf(year)); + row.put("range", fromTo); + row.put("description", descr); + helper.addRow(row); + } + + helper.submitMapToXml(); + } + + private double[] getLowerUpperKmRange(final List bedheights) { + double min = Double.MAX_VALUE; + double max = -Double.MAX_VALUE; + + for (final BedHeight bh : bedheights) { + final org.dive4elements.river.model.Range range = BedHeight.getRangeFromBedHeights(bh); + try { + final Double from = range.getA().doubleValue(); // NullPointer check?? -> try catch + final Double to = range.getB().doubleValue(); + + final double upper = to > from ? to : from; + final double lower = from < to ? from : to; + if (upper > max) + max = upper; + + if (lower < min) + min = lower; + } + catch (final Exception e) { + e.printStackTrace(); + } + + } + return new double[] { min, max }; + } + +} diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadScenarioSelectLimit5.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadScenarioSelectLimit5.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadScenarioSelectLimit5.java Fri Jul 13 11:40:25 2018 +0200 @@ -45,16 +45,10 @@ if (datakey.equals(name)) { final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "cm", context.getMeta()); - // no input help wanted - // helper.addColumn(0, "pinfrom", "40", "common.client.ui.from", "ICON", "CENTER", "from"); - // helper.addColumn(1, "pinto", "40", "common.client.ui.to", "ICON", "CENTER", "to"); - // helper.addColumn(1, "cm", "60", "Delta [cm]", "INTEGER", "RIGHT", null); - for (int i = -200; i < 210; i = i + 10) { final Map row = new HashMap<>(); row.put("cm", Integer.toString(i)); helper.addRow(row); - } helper.submitMapToXml(); } diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadSingleEpochSelectState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadSingleEpochSelectState.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadSingleEpochSelectState.java Fri Jul 13 11:40:25 2018 +0200 @@ -9,7 +9,10 @@ package org.dive4elements.river.artifacts.uinfo.salix; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.TreeMap; import org.apache.log4j.Logger; import org.dive4elements.artifacts.Artifact; @@ -17,6 +20,8 @@ import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; import org.dive4elements.river.artifacts.states.AddTableDataHelper; import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; +import org.dive4elements.river.model.BedHeight; import org.w3c.dom.Element; public class LoadSingleEpochSelectState extends DefaultState { @@ -32,38 +37,18 @@ @Override protected String getUIProvider() { - return "common.load_single_epoch_select"; + return "uinfo.salix.load_single_year_pseudo_epoch_select"; } @Override protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) { final String datakey = "singleepoch"; - // TODO: MAKE DATASOURCE + try { if (datakey.equals(name)) { - - final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta()); - - helper.addColumn(0, "pinfrom", "40", "common.client.ui.from", "ICON", "CENTER", "from"); - helper.addColumn(1, "pinto", "40", "common.client.ui.to", "ICON", "CENTER", "to"); - helper.addColumn(2, "year", "60", "year", "INTEGER", "LEFT", null); - helper.addColumn(3, "sounding", "200", "uinfo.salix.soundings", "STRING", "LEFT", null); - // final CollisionAccess access = new CollisionAccess((SINFOArtifact) artifact); // Der River wurde im vorigen State - // bereits gesetzt - - // final List collisions = CollisionHibernateFactory.getCollisionsByRiver(access.getRiver()); - // for (final Collision coll : collisions) { // TODO: Filter on Range (?) - // final Integer year = coll.getYear(); - // for (final Collision coll : collisions) { - for (int i = 0; i < 3; i++) {// : Collision.getYearsOfRiver(access.getRiver())) { - // final Integer year = coll.getYear(); - final Map row = new HashMap<>(); - row.put("year", String.valueOf(1995 + i)); // Nullpointer? - row.put("sounding", "TODO: Peilungen für das Jahr in dieser Zelle auflisten."); - helper.addRow(row); - } - // } - helper.submitMapToXml(); + final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact); + final List bhs = BedHeight.getBedHeightEpochs(access.getRiver(), access.getLowerKm(), access.getUpperKm()); + makeDataSourceYearEpoch(artifact, creator, select, context, bhs); } } catch ( @@ -72,4 +57,34 @@ iae.printStackTrace(); } } + + public static final void makeDataSourceYearEpoch(final Artifact artifact, final ElementCreator creator, final Element select, final CallContext context, + final List bedheights) { // TODO: maybe move to appropriate helper... + + final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta()); + + helper.addColumn(0, "pinfrom", "40", "common.client.ui.from", "ICON", "CENTER", "from"); + helper.addColumn(1, "year", "60", "year", "INTEGER", "LEFT", null); + helper.addColumn(2, "sounding", "500", "uinfo.salix.soundings", "STRING", "LEFT", null); + + final TreeMap bedHeightSorted = new TreeMap<>(); + + for (final BedHeight bh : bedheights) { + final int year = bh.getYear(); + final String soundings = bedHeightSorted.containsKey(year) ? bedHeightSorted.get(year) + ", " : ""; + bedHeightSorted.put(year, soundings + bh.getDescription()); + } + final Iterator iterator = bedHeightSorted.keySet().iterator(); + while (iterator.hasNext()) { + final int year = iterator.next(); + final String soundings = bedHeightSorted.get(year); + final Map row = new HashMap<>(); + row.put("year", String.valueOf(year)); + row.put("sounding", soundings); + helper.addRow(row); + } + + helper.submitMapToXml(); + } + } diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadSingleYearSelectState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadSingleYearSelectState.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/LoadSingleYearSelectState.java Fri Jul 13 11:40:25 2018 +0200 @@ -8,15 +8,15 @@ package org.dive4elements.river.artifacts.uinfo.salix; -import java.util.HashMap; -import java.util.Map; +import java.util.List; import org.apache.log4j.Logger; import org.dive4elements.artifacts.Artifact; import org.dive4elements.artifacts.CallContext; import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; -import org.dive4elements.river.artifacts.states.AddTableDataHelper; import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; +import org.dive4elements.river.model.BedHeight; import org.w3c.dom.Element; /** State in which to fetch years for sedminent load calculation. */ @@ -39,35 +39,21 @@ @Override protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) { - // TODO: MAKE DATASOURCE - try { - final String dataKeyofState = "singleyear";// siehe .xml - if (dataKeyofState.equals(name)) { - - final AddTableDataHelper helper = new AddTableDataHelper(creator, select, "year", context.getMeta()); // "year" not to be confused with datakey - helper.addColumn(0, "pinfrom", "60", "common.client.ui.selection", "ICON", "CENTER", "from"); - helper.addColumn(1, "year", "60", "year", "INTEGER", "LEFT", null); - helper.addColumn(2, "sounding", "200", "uinfo.salix.soundings", "STRING", "LEFT", null); - // TODO: MAKE DATASOURCE - // final CollisionAccess access = new CollisionAccess((SINFOArtifact) artifact); // TODO: MAKE DATASOURCE - // TODO: MAKE DATASOURCE - // final List collisions = CollisionHibernateFactory.getCollisionsByRiver(access.getRiver()); - // for (final Collision coll : collisions) { - for (int i = 0; i < 3; i++) {// : Collision.getYearsOfRiver(access.getRiver())) { - // final Integer year = coll.getYear(); - final Map row = new HashMap<>(); - row.put("year", String.valueOf(1995 + i)); // Nullpointer? - row.put("sounding", "TODO: Peilungen für das Jahr in dieser Zelle auflisten."); - helper.addRow(row); - } - helper.submitMapToXml(); + final String dataKeyofState = "singleyear";// siehe .xml + try { + if (dataKeyofState.equals(name)) { + final SalixLineAccess access = new SalixLineAccess((UINFOArtifact) artifact); + final List bhs = BedHeight.getBedHeightYear(access.getRiver(), access.getLowerKm(), access.getUpperKm()); + LoadSingleEpochSelectState.makeDataSourceYearEpoch(artifact, creator, select, context, bhs); } } - catch (final IllegalArgumentException iae) { + catch ( + + final IllegalArgumentException iae) { iae.printStackTrace(); } + } - } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineAccess.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineAccess.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineAccess.java Fri Jul 13 11:40:25 2018 +0200 @@ -58,4 +58,36 @@ public Double getToPart() { return getDouble("ld_to_part"); } + + public int[] getRegionalScenarioIntegers() { + // super.getIntArray("sedimentheight"); DOES NOT WORK! + final String ints = super.getString("sedimentheight"); + if (ints != null) { + final String[] intsSplit = ints.split(" "); + final int[] values = new int[intsSplit.length]; + for (int i = 0; i < intsSplit.length; i++) { + values[i] = Integer.valueOf(intsSplit[i]); + } + return values; + } + return null; + } + + public String getSupraRegionalString() { + return super.getString("supraregional_table"); + } + + public Integer getYear() { + if (getString("ye_select").equals("state.uinfo.year")) { + return super.getInteger("singleyear"); + } + return null; + } + + public Integer getEpoch() { + if (getString("ye_select").equals("state.uinfo.epoch")) { + return super.getInteger("singleepoch"); + } + return null; + } } \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java Fri Jul 13 11:40:25 2018 +0200 @@ -11,6 +11,10 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import org.apache.commons.lang.math.DoubleRange; import org.dive4elements.artifacts.CallContext; @@ -53,6 +57,9 @@ final String selectedScenario = accessSalix.getScenario(); final Double fromPart = accessSalix.getFromPart(); final Double toPart = accessSalix.getToPart(); + + final boolean useSCenario = accessSalix.getUseScenario(); + final String scenario = accessSalix.getScenario(); // calculation_mode // ld_from , ld_to // use_scenario (boolean) @@ -64,26 +71,88 @@ final SalixLineCalculationResults results = new SalixLineCalculationResults(calcModeLabel, user, riverInfo, range); final Collection rows = new ArrayList<>(); - + SalixLineCalculationNoScenarioResult result = null; // verzweigung etwas ungünstig. möglicherweise auch die Abstraktion. ist erstmal nur ne idee final ResultRow row1 = ResultRow.create(). // putValue(GeneralResultType.station, 100).// putValue(UInfoResultType.salixline, 28).// - putValue(UInfoResultType.salixlinehist, 2).// - putValue(UInfoResultType.salixlinescen, 82); - rows.add(row1); + putValue(UInfoResultType.salix_delta_mw, 2); - final ResultRow row2 = ResultRow.create(). // - putValue(GeneralResultType.station, 200). // - putValue(UInfoResultType.salixline, 3). // - putValue(UInfoResultType.salixlinehist, 2).// - putValue(UInfoResultType.salixlinescen, 822); + if (!useScenario) { - rows.add(row2); + rows.add(row1); + result = new SalixLineCalculationNoScenarioResult("Ergebnis 1", null, rows); + } else { - final SalixLineCalculationResult result = new SalixLineCalculationResult("Ergebnis 1", null, rows); + if (scenario.equals("scenarioType.option1")) { // REGIONAL + final int[] scenarios = accessSalix.getRegionalScenarioIntegers(); + final List list = new ArrayList<>(); + for (final int scen_val : scenarios) { + list.add(new SalixScenario(scen_val, 666.));// TODO: replace 666 by real calculated value + } + row1.putValue(UInfoResultType.customMultiRowColSalixRegionalValue_Dwspl, list);// + rows.add(row1); + result = new SalixLineCalculationRegionalResult("Ergebnis 1 regional test", null, rows, scenarios); + + } else if (scenario.equals("scenarioType.option2")) { // SUPRA-REGIONAL + + final String supraRegional = accessSalix.getSupraRegionalString(); + final List list = SalixZone.parse(supraRegional); + + final Map rangeScenarioMap = new HashMap<>(); + // make double range + for (int i = 0; i < list.size(); i++) { + final SalixZone zone = list.get(i); + final double upper = i < list.size() - 1 ? (zone.getUpperFromTo() - 0.0001) : zone.getUpperFromTo() + 0.0001;// "halboffenes Intervall + + final DoubleRange zonerange = new DoubleRange((double) zone.getLowerFromTo(), upper); + final double salixValue = 666.;// TODO: calculate the salix value + final SalixScenario salixscen = new SalixScenario(zone.getDwsplValue(), salixValue); + + rangeScenarioMap.put(zonerange, salixscen); + } + + // make calculation + double currentKm = range.getMinimumDouble(); + final double step = 0.1; // TODO: get from global setting? + while (currentKm < range.getMaximumDouble()) { + final ResultRow rowSupraRegional = ResultRow.create(). // + putValue(GeneralResultType.station, currentKm).// + putValue(UInfoResultType.salixline, 28).// + putValue(UInfoResultType.salix_delta_mw, 2); + + final SalixScenario scenarioCurrentKm = findScenarioByKm(currentKm, rangeScenarioMap); + + if (scenarioCurrentKm != null) { // should not happen, scenarioCurrentKm == null -> BUG + rowSupraRegional.putValue(UInfoResultType.salix_line_scenario, scenarioCurrentKm.getSalixValue()); + rowSupraRegional.putValue(UInfoResultType.salix_line_scenario_dwspl, scenarioCurrentKm.getDwspl()); + } + rows.add(rowSupraRegional); + + currentKm = currentKm + step; + } + + result = new SalixLineCalculationSupraRegionalResult("Ergebnis 1 supra regional test", null, rows); + + } else if (scenario.equals("scenarioType.option3")) { // HISTORICAL + row1.putValue(UInfoResultType.salixlinehist, 66).// + putValue(UInfoResultType.salix_line_scenario_dwspl, 88); + rows.add(row1); + result = new SalixLineCalculationHistoricalResult("Ergebnis 1 historical test", null, rows); + } + } results.addResult(result, problems); - return new CalculationResult(results, problems); } + + private SalixScenario findScenarioByKm(final double km, final Map rangeScenarioMap) { + final Iterator rangeIterator = rangeScenarioMap.keySet().iterator(); + while (rangeIterator.hasNext()) { + final DoubleRange range = rangeIterator.next(); + if (range.containsDouble(km + 0.0001)) { + return rangeScenarioMap.get(range); + } + } + return null; + } } \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationHistoricalResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationHistoricalResult.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,89 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.uinfo.salix; + +import java.text.NumberFormat; +import java.util.Collection; + +import org.dive4elements.river.artifacts.common.ExportContextCSV; +import org.dive4elements.river.artifacts.common.IExportContext; +import org.dive4elements.river.artifacts.common.ResultRow; +import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; +import org.dive4elements.river.artifacts.sinfo.util.WstInfo; +import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType; + +/** + * @author Domenico Nardi Tironi + */ +final class SalixLineCalculationHistoricalResult extends SalixLineCalculationNoScenarioResult { + + private static final long serialVersionUID = 1L; + + public SalixLineCalculationHistoricalResult(final String label, final WstInfo wst, final Collection rows) { + super(label, wst, rows); + + } + + @Override + public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) { + + final Collection header = super.writeNoScenarioHeader(exportContextCSV); + + header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salixlinehist)); + header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salix_line_scenario_dwspl)); + + exportContextCSV.writeCSVLine(header.toArray(new String[header.size()])); + } + + @Override + protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) { + writeHistoricalViewCSVMetadata(exportContextCSV); + exportContextCSV.writeBlankLine(); + + } + + @Override + protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) { + + return formatRow(exportContextCSV, row); + } + + private String[] formatRow(final IExportContext context, final ResultRow row) { + + final Collection lines = super.getNoScenarioFormat(row, context); + + if (context instanceof ExportContextCSV) { // enum gespart - pdf-export hat ja nur die drei spalten + final NumberFormat formatter = ((ExportContextCSV) context).getSalixScenFormatter(); + + lines.add(context.formatRowValue(row, UInfoResultType.salixlinehist)); + lines.add(context.formatRowValue(row, UInfoResultType.salix_line_scenario_dwspl)); + + } + return lines.toArray(new String[lines.size()]); + } + + // TODO: move to historical class and delete here + private void writeHistoricalViewCSVMetadata(final ExportContextCSV exportContextCSV) { + final String main = "uinfo.export.csv.meta.header.salix.historical"; + // "##Historische Betrachtung" + exportContextCSV.writeCSVMetaEntry(main); + + final String mainSub = "uinfo.export.csv.meta.header.salix"; + // "# Szenariotyp: " + exportContextCSV.writeCSVMetaEntry(mainSub + ".szenariotyp"); + // "# Teilabschnitt: " + exportContextCSV.writeCSVMetaEntry(mainSub + ".teilabschnitt"); + + // "# Art des Zeitraums: " + exportContextCSV.writeCSVMetaEntry(main + ".zeitart"); + // "# Historischer Zeitpunkt: " + exportContextCSV.writeCSVMetaEntry(main + ".zeitpunkt"); + } +} \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationNoScenarioResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationNoScenarioResult.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,136 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.uinfo.salix; + +import java.util.ArrayList; +import java.util.Collection; + +import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult; +import org.dive4elements.river.artifacts.common.ExportContextCSV; +import org.dive4elements.river.artifacts.common.ExportContextPDF; +import org.dive4elements.river.artifacts.common.GeneralResultType; +import org.dive4elements.river.artifacts.common.IExportContext; +import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource; +import org.dive4elements.river.artifacts.common.ResultRow; +import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; +import org.dive4elements.river.artifacts.sinfo.util.WstInfo; +import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType; + +/** + * @author Domenico Nardi Tironi + */ +class SalixLineCalculationNoScenarioResult extends AbstractCalculationExportableResult { + + private static final long serialVersionUID = 1L; + private static final String JASPER_FILE = "/jasper/templates/uinfo.salixline.jrxml"; + + public SalixLineCalculationNoScenarioResult(final String label, final WstInfo wst, final Collection rows) { + super(label, rows); + } + + @Override + public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) { + final Collection header = writeNoScenarioHeader(exportContextCSV); + exportContextCSV.writeCSVLine(header.toArray(new String[header.size()])); + + } + + protected final Collection writeNoScenarioHeader(final ExportContextCSV exportContextCSV) { + final Collection header = new ArrayList<>(); + header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station)); + header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salixline)); + header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salix_delta_mw)); + return header; + } + + @Override + protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) { + + return formatRow(exportContextCSV, row); + } + + @Override + protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) { + + return formatRow(exportContextPDF, row); + } + + @Override + protected String getJasperFile() { + + return this.JASPER_FILE; + } + + @Override + protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) { + + /* additional column headings */ + exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station); + exportContextPDF.addJRMetadata(source, "salix_line", UInfoResultType.salixline); + exportContextPDF.addJRMetadata(source, "salix_delta_mw", UInfoResultType.salix_delta_mw); + + } + + private String[] formatRow(final IExportContext context, final ResultRow row) { + + final Collection lines = getNoScenarioFormat(row, context); + + // // ?? + // // wenn "historisch" gewählt wurde, nur "historisch" anzeigen; sonst für jeden scen-wert ne neue Spalte und "hist" + // // ausblenden!...!..!! + // lines.add(context.formatRowValue(row, UInfoResultType.salixlinehist)); + // lines.add(context.formatRowValue(row, UInfoResultType.salixlinescen)); + + return lines.toArray(new String[lines.size()]); + } + + protected final Collection getNoScenarioFormat(final ResultRow row, final IExportContext context) { + final Collection lines = new ArrayList<>(); + lines.add(context.formatRowValue(row, GeneralResultType.station)); + lines.add(context.formatRowValue(row, UInfoResultType.salixline)); + lines.add(context.formatRowValue(row, UInfoResultType.salix_delta_mw)); + + return lines; + + } + + protected final void writeRegionalCommonCSVMeta(final ExportContextCSV exportContextCSV) { + final String main = "uinfo.export.csv.meta.header.salix"; + // "# Szenariotyp: " + exportContextCSV.writeCSVMetaEntry(main + ".szenariotyp"); + // "# Teilabschnitt: " + exportContextCSV.writeCSVMetaEntry(main + ".teilabschnitt"); + // "# Mittelwasserspiegellagenänderung: " + exportContextCSV.writeCSVMetaEntry(main + ".mwspiegellaenderung"); + } + + @Override + protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) { + // do nothing. subclass may override + + } + + // private void writeHistoricalViewCSVMetadata(final ExportContextCSV exportContextCSV) { + // final String main = "uinfo.export.csv.meta.header.salix.historical"; + // // "##Historische Betrachtung" + // exportContextCSV.writeCSVMetaEntry(main); + // + // final String mainSub = "uinfo.export.csv.meta.header.salix"; + // // "# Szenariotyp: " + // exportContextCSV.writeCSVMetaEntry(mainSub + ".szenariotyp"); + // // "# Teilabschnitt: " + // exportContextCSV.writeCSVMetaEntry(mainSub + ".teilabschnitt"); + // + // // "# Art des Zeitraums: " + // exportContextCSV.writeCSVMetaEntry(main + ".zeitart"); + // // "# Historischer Zeitpunkt: " + // exportContextCSV.writeCSVMetaEntry(main + ".zeitpunkt"); + // } +} \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationRegionalResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationRegionalResult.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,113 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.uinfo.salix; + +import java.text.NumberFormat; +import java.util.Collection; +import java.util.List; + +import org.dive4elements.river.artifacts.common.ExportContextCSV; +import org.dive4elements.river.artifacts.common.IExportContext; +import org.dive4elements.river.artifacts.common.ResultRow; +import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; +import org.dive4elements.river.artifacts.sinfo.util.WstInfo; +import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType; + +/** + * @author Domenico Nardi Tironi + */ +final class SalixLineCalculationRegionalResult extends SalixLineCalculationNoScenarioResult { + + private static final long serialVersionUID = 1L; + private final int[] scenarioValues; + + public SalixLineCalculationRegionalResult(final String label, final WstInfo wst, final Collection rows, final int[] scenarioValues) { + super(label, wst, rows); + this.scenarioValues = scenarioValues; // TODO: diese values müssen eigentlich nur ne anzahl sein, oder so. Ergibt sihc in der Berech + } + + @Override + public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) { + + final Collection header = super.writeNoScenarioHeader(exportContextCSV); + + for (int i = 0; i < this.scenarioValues.length; i++) { + // index wurde verworfen, stattdessen 2 spalten + + header.add(exportContextCSV.msg(SalixScenario.getScenarioValueHeader()) + " (" + (i + 1) + ")"); // index kann auch weg, war nur ne idee + header.add(exportContextCSV.msg(SalixScenario.getDwsplHeader()) + " (" + (i + 1) + ")"); + } + exportContextCSV.writeCSVLine(header.toArray(new String[header.size()])); + } + + @Override + protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) { + writeRegionalEffectsCSVMetadata(exportContextCSV); + exportContextCSV.writeBlankLine(); + + } + + @Override + protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) { + + return formatRow(exportContextCSV, row); + } + + private String[] formatRow(final IExportContext context, final ResultRow row) { + + final Collection lines = super.getNoScenarioFormat(row, context); + + if (context instanceof ExportContextCSV) { // enum gespart - pdf-export hat ja nur die drei spalten + final NumberFormat formatter = ((ExportContextCSV) context).getSalixScenFormatter(); + final List scenList = (List) row.getValue(UInfoResultType.customMultiRowColSalixRegionalValue_Dwspl); + + for (final SalixScenario scenario : scenList) { + // scenario unused; index wurde ja verworfen, stattdessen 2 spalten + lines.add(scenario.getSalixValueFormatted(formatter)); + lines.add(scenario.getDwsplFormatted()); + } + } + return lines.toArray(new String[lines.size()]); + } + + private void writeRegionalEffectsCSVMetadata(final ExportContextCSV exportContextCSV) { + final String main = "uinfo.export.csv.meta.header.salix.regional"; + // "##Regional wirkende Eingriffe" + exportContextCSV.writeCSVMetaEntry(main); + writeRegionalCommonCSVMeta(exportContextCSV); + } + + // TODO: move to SupraRegionalEffectsResult-Class; remove here + // private void writeExtendedRegionalEffectsCSVMetadata(final ExportContextCSV exportContextCSV) { + // final String main = "uinfo.export.csv.meta.header.salix.regionalextended"; + // // "##Überregional wirkende Eingriffe" + // exportContextCSV.writeCSVMetaEntry(main); + // + // writeRegionalCommonCSVMeta(exportContextCSV); + // } + + // TODO: move to historical class and delete here + // private void writeHistoricalViewCSVMetadata(final ExportContextCSV exportContextCSV) { + // final String main = "uinfo.export.csv.meta.header.salix.historical"; + // // "##Historische Betrachtung" + // exportContextCSV.writeCSVMetaEntry(main); + // + // final String mainSub = "uinfo.export.csv.meta.header.salix"; + // // "# Szenariotyp: " + // exportContextCSV.writeCSVMetaEntry(mainSub + ".szenariotyp"); + // // "# Teilabschnitt: " + // exportContextCSV.writeCSVMetaEntry(mainSub + ".teilabschnitt"); + // + // // "# Art des Zeitraums: " + // exportContextCSV.writeCSVMetaEntry(main + ".zeitart"); + // // "# Historischer Zeitpunkt: " + // exportContextCSV.writeCSVMetaEntry(main + ".zeitpunkt"); + // } +} \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationResult.java Fri Jul 06 13:18:51 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde - * Software engineering by - * Björnsen Beratende Ingenieure GmbH - * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt - * - * 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.uinfo.salix; - -import java.util.ArrayList; -import java.util.Collection; - -import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult; -import org.dive4elements.river.artifacts.common.ExportContextCSV; -import org.dive4elements.river.artifacts.common.ExportContextPDF; -import org.dive4elements.river.artifacts.common.GeneralResultType; -import org.dive4elements.river.artifacts.common.IExportContext; -import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource; -import org.dive4elements.river.artifacts.common.ResultRow; -import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; -import org.dive4elements.river.artifacts.sinfo.util.WstInfo; -import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType; - -/** - * @author Domenico Nardi Tironi - */ -final class SalixLineCalculationResult extends AbstractCalculationExportableResult { - - private static final long serialVersionUID = 1L; - private static final String JASPER_FILE = "/jasper/templates/uinfo.salixline.jrxml"; - - public SalixLineCalculationResult(final String label, final WstInfo wst, final Collection rows) { - super(label, rows); - } - - @Override - public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) { - - final Collection header = new ArrayList<>(4); - - header.add(exportContextCSV.formatCsvHeader(GeneralResultType.station)); - // header.add(msgUnit(SInfoResultType.flowdepth, SInfoResultType.flowdepth.getUnit())); - - header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salixline)); - // wenn "historisch" gewählt wurde, nur "historisch" anzeigen; sonst für jeden scen-wert ne neue Spalte und "hist" - // ausblenden!...!..!! - header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salixlinehist)); - header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salixlinescen)); - exportContextCSV.writeCSVLine(header.toArray(new String[header.size()])); - - } - - @Override - protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) { - writeRegionalEffectsCSVMetadata(exportContextCSV); - exportContextCSV.writeBlankLine(); - writeExtendedRegionalEffectsCSVMetadata(exportContextCSV); - exportContextCSV.writeBlankLine(); - writeHistoricalViewCSVMetadata(exportContextCSV); - exportContextCSV.writeBlankLine(); - - } - - @Override - protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) { - - return formatRow(exportContextCSV, row); - } - - @Override - protected String[] formatPDFRow(final ExportContextPDF exportContextPDF, final ResultRow row) { - - return formatRow(exportContextPDF, row); - } - - @Override - protected String getJasperFile() { - - return this.JASPER_FILE; - } - - @Override - protected void addJRTableHeader(final ExportContextPDF exportContextPDF, final MetaAndTableJRDataSource source) { - - /* additional column headings */ - exportContextPDF.addJRMetadata(source, "station_header", GeneralResultType.station); - - exportContextPDF.addJRMetadata(source, "salix_line", UInfoResultType.salixline); - // wenn "historisch" gewählt wurde, nur "historisch" anzeigen; sonst für jeden scen-wert ne neue Spalte und "hist" - // ausblenden!...!..!! - exportContextPDF.addJRMetadata(source, "salix_line_hist", UInfoResultType.salixlinehist); - exportContextPDF.addJRMetadata(source, "salix_line_scen", UInfoResultType.salixlinescen); - - } - - private String[] formatRow(final IExportContext context, final ResultRow row) { - - final Collection lines = new ArrayList<>(3); - - lines.add(context.formatRowValue(row, GeneralResultType.station)); - lines.add(context.formatRowValue(row, UInfoResultType.salixline)); - - // wenn "historisch" gewählt wurde, nur "historisch" anzeigen; sonst für jeden scen-wert ne neue Spalte und "hist" - // ausblenden!...!..!! - lines.add(context.formatRowValue(row, UInfoResultType.salixlinehist)); - lines.add(context.formatRowValue(row, UInfoResultType.salixlinescen)); - return lines.toArray(new String[lines.size()]); - } - - private void writeRegionalEffectsCSVMetadata(final ExportContextCSV exportContextCSV) { - final String main = "uinfo.export.csv.meta.header.salix.regional"; - // "##Regional wirkende Eingriffe" - exportContextCSV.writeCSVMetaEntry(main); - writeRegionalCommonCSVMeta(exportContextCSV); - } - - private void writeRegionalCommonCSVMeta(final ExportContextCSV exportContextCSV) { - final String main = "uinfo.export.csv.meta.header.salix"; - // "# Szenariotyp: " - exportContextCSV.writeCSVMetaEntry(main + ".szenariotyp"); - // "# Teilabschnitt: " - exportContextCSV.writeCSVMetaEntry(main + ".teilabschnitt"); - // "# Mittelwasserspiegellagenänderung: " - exportContextCSV.writeCSVMetaEntry(main + ".mwspiegellaenderung"); - } - - private void writeExtendedRegionalEffectsCSVMetadata(final ExportContextCSV exportContextCSV) { - final String main = "uinfo.export.csv.meta.header.salix.regionalextended"; - // "##Überregional wirkende Eingriffe" - exportContextCSV.writeCSVMetaEntry(main); - - writeRegionalCommonCSVMeta(exportContextCSV); - } - - private void writeHistoricalViewCSVMetadata(final ExportContextCSV exportContextCSV) { - final String main = "uinfo.export.csv.meta.header.salix.historical"; - // "##Historische Betrachtung" - exportContextCSV.writeCSVMetaEntry(main); - - final String mainSub = "uinfo.export.csv.meta.header.salix"; - // "# Szenariotyp: " - exportContextCSV.writeCSVMetaEntry(mainSub + ".szenariotyp"); - // "# Teilabschnitt: " - exportContextCSV.writeCSVMetaEntry(mainSub + ".teilabschnitt"); - - // "# Art des Zeitraums: " - exportContextCSV.writeCSVMetaEntry(main + ".zeitart"); - // "# Historischer Zeitpunkt: " - exportContextCSV.writeCSVMetaEntry(main + ".zeitpunkt"); - } -} \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationResults.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationResults.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationResults.java Fri Jul 13 11:40:25 2018 +0200 @@ -17,7 +17,7 @@ * @author Domenico Nardi Tironi * */ -final class SalixLineCalculationResults extends AbstractCalculationResults { +final class SalixLineCalculationResults extends AbstractCalculationResults { private static final long serialVersionUID = 1L; diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationSupraRegionalResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculationSupraRegionalResult.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,97 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.uinfo.salix; + +import java.text.NumberFormat; +import java.util.Collection; + +import org.dive4elements.river.artifacts.common.ExportContextCSV; +import org.dive4elements.river.artifacts.common.IExportContext; +import org.dive4elements.river.artifacts.common.ResultRow; +import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; +import org.dive4elements.river.artifacts.sinfo.util.WstInfo; +import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType; + +/** + * @author Domenico Nardi Tironi + */ +final class SalixLineCalculationSupraRegionalResult extends SalixLineCalculationNoScenarioResult { + + private static final long serialVersionUID = 1L; + + public SalixLineCalculationSupraRegionalResult(final String label, final WstInfo wst, final Collection rows) { + super(label, wst, rows); + + } + + @Override + public void writeCSVHeader(final ExportContextCSV exportContextCSV, final RiverInfo river) { + + final Collection header = super.writeNoScenarioHeader(exportContextCSV); + + header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salix_line_scenario)); + header.add(exportContextCSV.formatCsvHeader(UInfoResultType.salix_line_scenario_dwspl)); + + exportContextCSV.writeCSVLine(header.toArray(new String[header.size()])); + } + + @Override + protected void writeCSVResultMetadata(final ExportContextCSV exportContextCSV) { + writeExtendedRegionalEffectsCSVMetadata(exportContextCSV); + exportContextCSV.writeBlankLine(); + + } + + @Override + protected String[] formatCSVRow(final ExportContextCSV exportContextCSV, final ResultRow row) { + + return formatRow(exportContextCSV, row); + } + + private String[] formatRow(final IExportContext context, final ResultRow row) { + + final Collection lines = super.getNoScenarioFormat(row, context); + + if (context instanceof ExportContextCSV) { // enum gespart - pdf-export hat ja nur die drei spalten + final NumberFormat formatter = ((ExportContextCSV) context).getSalixScenFormatter(); + + lines.add(context.formatRowValue(row, UInfoResultType.salix_line_scenario)); + lines.add(context.formatRowValue(row, UInfoResultType.salix_line_scenario_dwspl)); + + } + return lines.toArray(new String[lines.size()]); + } + + private void writeExtendedRegionalEffectsCSVMetadata(final ExportContextCSV exportContextCSV) { + final String main = "uinfo.export.csv.meta.header.salix.regionalextended"; + // "##Überregional wirkende Eingriffe" + exportContextCSV.writeCSVMetaEntry(main); + + writeRegionalCommonCSVMeta(exportContextCSV); + } + + // TODO: move to historical class and delete here + // private void writeHistoricalViewCSVMetadata(final ExportContextCSV exportContextCSV) { + // final String main = "uinfo.export.csv.meta.header.salix.historical"; + // // "##Historische Betrachtung" + // exportContextCSV.writeCSVMetaEntry(main); + // + // final String mainSub = "uinfo.export.csv.meta.header.salix"; + // // "# Szenariotyp: " + // exportContextCSV.writeCSVMetaEntry(mainSub + ".szenariotyp"); + // // "# Teilabschnitt: " + // exportContextCSV.writeCSVMetaEntry(mainSub + ".teilabschnitt"); + // + // // "# Art des Zeitraums: " + // exportContextCSV.writeCSVMetaEntry(main + ".zeitart"); + // // "# Historischer Zeitpunkt: " + // exportContextCSV.writeCSVMetaEntry(main + ".zeitpunkt"); + // } +} \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineExporter.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineExporter.java Fri Jul 13 11:40:25 2018 +0200 @@ -12,24 +12,18 @@ import org.dive4elements.river.artifacts.common.AbstractCommonExporter; import org.dive4elements.river.artifacts.common.ExportContextCSV; import org.dive4elements.river.artifacts.common.ExportContextPDF; -import org.dive4elements.river.artifacts.common.I18NStrings; import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource; /** * @author Domenico Nardi Tironi * */ -public class SalixLineExporter extends AbstractCommonExporter { +public class SalixLineExporter extends AbstractCommonExporter { @Override protected void writeCSVGlobalMetadata(final ExportContextCSV exportContextCSV, final SalixLineCalculationResults results) { /* write as csv */ - exportContextCSV.writeCSVGlobalMetadataDefaults(); // ggf auslagern innerhalb dieser Klasse - - // break line ? - - // "# Höhensystem des Flusses: " - exportContextCSV.writeCSVMetaEntry(I18NStrings.CSV_META_HEIGHT_UNIT_RIVER, results.getRiver().getWstUnit()); + exportContextCSV.writeCSVGlobalMetadataDefaults(); // Add Auswerter, Bezugspegel, Jahr/Zeitraum der Wasserspiegellage @@ -39,9 +33,7 @@ exportContextCSV.writeCSVMetaEntry("uinfo.export.salix_line.csv.meta.header.waterlevel.gauge", "wst.getGauge()"); // "# Jahr/Zeitraum der Wasserspiegellage: " - // final int year = wst.getYear(); - // if (year > 0) - exportContextCSV.writeCSVMetaEntry("uinfo.export.salix_line.csv.meta.header.waterlevel.year", "Integer.toString(year)"); + exportContextCSV.writeCSVMetaEntry("uinfo.export.salix_line.csv.meta.header.waterlevel.year", "TODO..."); } diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineState.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineState.java Fri Jul 13 11:40:25 2018 +0200 @@ -77,7 +77,7 @@ final SalixLineCalculationResults results = (SalixLineCalculationResults) res.getData(); - final List resultList = results.getResults(); + final List resultList = results.getResults(); if (!resultList.isEmpty()) { final Facet csv = new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id); diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixScenario.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixScenario.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,55 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.uinfo.salix; + +import java.io.Serializable; +import java.text.NumberFormat; + +/** + * @author Domenico Nardi Tironi + * + */ +public class SalixScenario implements Serializable { + + private static final long serialVersionUID = 1L; + + private final double salix_value; + private final int dwspl; + + public SalixScenario(final int scen_val, final double salix_value) { + this.dwspl = scen_val; + this.salix_value = salix_value; + } + + public double getSalixValue() { + return this.salix_value; + } + + public int getDwspl() { + return this.dwspl; + } + + public String getDwsplFormatted() { + return String.valueOf(this.dwspl); + } + + public String getSalixValueFormatted(final NumberFormat formatter) { + return formatter.format(this.salix_value); + } + + public static final String getScenarioValueHeader() { + return "uinfo.export.salix_line.csv.header.scenario"; + } + + public static final String getDwsplHeader() { + return "uinfo.export.salix_line.csv.header.scenario_dwspl"; + } + +} diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixZone.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixZone.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,176 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.uinfo.salix; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + +/** + * @author Domenico Nardi Tironi + * + */ +public class SalixZone implements Comparable { + + // IMMER ABGLEICHEN Server Client SalixZone.java + private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR"; + private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR"; + private final int dwsplValue; + private final double fromKm; + private final double toKm; + + private final static double DELTA = 0.0001; + + public static List parse(final String zonesRaw) { + final List resultList = new ArrayList<>(); + + final List results = new ArrayList<>(); + if (zonesRaw.contains(TABLE_ROW_SEPARATOR)) { + final String[] rows = zonesRaw.split(TABLE_ROW_SEPARATOR); + for (final String row : rows) { + if (row.contains(TABLE_CELL_SEPARATOR)) { + final String[] result = row.split(TABLE_CELL_SEPARATOR); + results.add(result); + } + } + } + for (final String[] zone : results) { + final SalixZone helper = new SalixZone(Integer.valueOf(zone[0]), Double.valueOf(zone[1]), Double.valueOf(zone[2])); + resultList.add(helper); + } + return resultList; + } + + public static SalixZone createFromTableEntry(final String dwspl, final String from, final String to) { + return new SalixZone(Integer.valueOf(dwspl), Double.valueOf(from), Double.valueOf(to)); // Error-Handling? + } + + private SalixZone(final int dwsplValue, final double fromKm, final double toKm) { + this.dwsplValue = dwsplValue; + this.fromKm = fromKm; + this.toKm = toKm; + } + + public Double getToKm() { + return this.toKm; + } + + public int getDwsplValue() { + return this.dwsplValue; + } + + public Double getFromKm() { + return this.fromKm; + } + + public static final String parseListToDataString(final List list) { + + java.util.Collections.sort(list); + final StringBuilder builder = new StringBuilder(); + for (final SalixZone zone : list) { + builder.append(zone.getDwsplValue()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getFromKm()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getToKm()); + builder.append(TABLE_ROW_SEPARATOR); + } + return builder.toString(); + } + + public static final boolean zonesAreOverlapping(final List list) { + for (final SalixZone zone : list) { + for (final SalixZone zoneOther : list) { + if (zone != zoneOther) { + final boolean overlaps = zone.overlaps(zoneOther); + if (overlaps) { + return overlaps; // cancel. only one zone has to overlap + } + } + } + } + + return false; + } + + public static final boolean hasGaps(final List list, final double lower, final double upper) { + + if (((upper - lower) > DELTA) && list.size() == 0) + return true; + + final TreeSet treeList = new TreeSet<>(); + treeList.addAll(list); + double lowerCompare = lower + DELTA; + for (final SalixZone zone : treeList) { + if ((zone.getUpperFromTo() - zone.getLowerFromTo()) > DELTA) { + if (zone.getLowerFromTo() > lowerCompare) { + return true; + } + lowerCompare = zone.getUpperFromTo() + DELTA; + } + } + if ((lowerCompare + DELTA) < upper) + return true; // am Ende nicht geschlossen + + return false; + } + + public Double getLowerFromTo() { + return this.fromKm < this.toKm ? this.fromKm : this.toKm; // Math. is forbidden :-( + } + + public Double getUpperFromTo() { + return this.fromKm > this.toKm ? this.fromKm : this.toKm;// Math. is forbidden :-( + } + + private boolean overlaps(final SalixZone otherZone) { + final double otherLower = otherZone.getLowerFromTo(); + final double otherUpper = otherZone.getUpperFromTo(); + + final double upper = getUpperFromTo(); + final double lower = getLowerFromTo(); + final double otherSchwerpunkt = (otherLower + otherUpper) / 2; + if ((otherUpper < upper && otherUpper > lower)) { + return true; + } else if (otherLower > lower && otherLower < upper) { + return true; + } else if (otherSchwerpunkt > (lower - DELTA) && otherSchwerpunkt < (upper + DELTA)) { + return true; + } + return false; + } + + @Override + public int compareTo(final SalixZone o) { + final int basicCompare = this.getLowerFromTo().compareTo(o.getLowerFromTo()); + if (basicCompare == 0) { + return 1; // necessary for the treeSet! + } + return basicCompare; + } + + public static boolean isValidAnschlussRange(final double fromTest, final double toTest, final List list, final double minKm) { + final SalixZone zone = new SalixZone(0, fromTest, toTest); + final double lower = zone.getLowerFromTo(); + final double anschluss = getAnschluss(list, minKm); + final double differenceAbs = (lower - anschluss) > 0 ? (lower - anschluss) : (anschluss - lower); // no Math.abs allowed :-( + if (differenceAbs > DELTA) { + return false; + } + return true; + } + + private static double getAnschluss(final List list, final double minKm) { + if (list.size() > 0) { + return list.get(list.size() - 1).getUpperFromTo(); + } + return minKm; + } +} diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SupraRegionalTableState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SupraRegionalTableState.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,54 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.uinfo.salix; + +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; +import org.dive4elements.river.artifacts.D4EArtifact; +import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.river.artifacts.states.DefaultState; +import org.w3c.dom.Element; + +/** + * @author Domenico Nardi Tironi + */ +public class SupraRegionalTableState extends DefaultState { + + private static final long serialVersionUID = 1L; + + @Override + protected String getUIProvider() { + return "uinfo.salix.supraregional.table"; + } + + @Override + protected Element[] createItems(final ElementCreator cr, final Artifact artifact, final String name, final CallContext context) { + final String datakey = "supraregional_table"; + if (name.equals(datakey)) { + + final D4EArtifact flys = (D4EArtifact) artifact; + final String s = flys.getDataAsString(datakey); + + final RangeAccess ra = new RangeAccess((D4EArtifact) artifact); + + final Element item = createItem(cr, new String[] { "salix_zones", s }); + final Element min = createItem(cr, new String[] { "salix_zones_min", new Double(ra.getFrom()).toString() }); + + final Element max = createItem(cr, new String[] { "salix_zones_max", new Double(ra.getTo()).toString() }); + + return new Element[] { min, max, item }; + + } + + return new Element[] {}; + } + +} \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/java/org/dive4elements/river/exports/AbstractChartGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/AbstractChartGenerator.java Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/AbstractChartGenerator.java Fri Jul 13 11:40:25 2018 +0200 @@ -721,7 +721,7 @@ return Resources.getMsg(this.context.getMeta(), key, key); } - public final String msg(final String key, final String def, final Object[] args) { + public final String msg(final String key, final String def, final Object... args) { return Resources.getMsg(this.context.getMeta(), key, def, args); } diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/resources/messages.properties --- a/artifacts/src/main/resources/messages.properties Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/resources/messages.properties Fri Jul 13 11:40:25 2018 +0200 @@ -76,6 +76,7 @@ state.minfo.m3_per_a = m\u00b3/a state.uinfo.vegetation_zones.table = Einteilung der Vegetationszonen und \u00dcberflutungsdauern (\u00dcFD) +state.uinfo.salix.supraregional = \u00dcberregional wirkende Eingriffe state.uinfo.year_totalepoch = Year/Gesamter Zeitraum state.uinfo.year_epoch = Year/Epoch @@ -1087,10 +1088,13 @@ mainvalue.w.description = Wasserstand/Wasserspiegel-lage ({0}) mainvalue.duration = \u00dcberflutungsdauer mainvalue.duration.description = \u00dcberflutungsdauer ({0}) +state.uinfo.salix.historical.km_range_part = Ausgewertete Strecke +uinfo.salix.sounding= Peilung uinfo.salix.soundings= Soundings +uinfo.export.salix_line.csv.header.scenario_dwspl = \u0394MW [cm] +uinfo.export.salix_line.csv.header.scenario = Salix-Linie_Szenario [m] uinfo.export.salix_line.csv.header.salix_line = Salix-Linie [m] -uinfo.export.salix_line.csv.header.delta_mw = (MW-MNW)x(-1) [m] -uinfo.export.salix_line.csv.header.scen = Salix-Linie [m] Szenario dMW={0} cm +uinfo.export.salix_line.csv.header.delta_mw = (MW-MNW)x(-1) [m] uinfo.export.salix_line.csv.header.hist = Salix-Linie [m] historisch uinfo.export.salix_line.csv.meta.header.evaluator = # Auswerter: {0} uinfo.export.salix_line.csv.meta.header.waterlevel.year = # Jahr/Zeitraum der Wasserspiegellage: {0} @@ -1149,6 +1153,10 @@ sinfo.chart.flood_duration.height.section.title = H\u00f6he Infrastrukturen BWaStr sinfo_facet_flood_height = Geod\u00e4tische H\u00f6he Infrastrukturen BWaStr sinfo_facet_flood_height.description = Geod\u00e4tische H\u00f6he Infrastrukturen BWaStr ({0}) +sinfo.chart.flood_duration.curve.section.title = \u00dcberflutungsdauer Infrastrukturen BWaStr - Dauerlinie +sinfo.chart.flood_duration.curve.xaxis.label = \u00dcberflutungsdauer [d/a] +sinfo.chart.flood_duration.curve.w = Wasserstandsdauerlinie +sinfo.chart.flood_duration.curve.q = Abflussdauerlinie bundu_bezugswst = Bezugswasserst\u00e4nde bundu_analysis = Fixinganalysis diff -r eedb0bcf226b -r 68ff4087b987 artifacts/src/main/resources/messages_de.properties --- a/artifacts/src/main/resources/messages_de.properties Fri Jul 06 13:18:51 2018 +0200 +++ b/artifacts/src/main/resources/messages_de.properties Fri Jul 13 11:40:25 2018 +0200 @@ -76,6 +76,7 @@ state.minfo.m3_per_a = m\u00b3/a state.uinfo.vegetation_zones.table = Einteilung der Vegetationszonen und \u00dcberflutungsdauern (\u00dcFD) +state.uinfo.salix.supraregional = \u00dcberregional wirkende Eingriffe state.uinfo.year_totalepoch = Jahr/Gesamter Zeitraum state.uinfo.year_epoch = Jahr/Epoche @@ -1087,10 +1088,13 @@ mainvalue.w.description = Wasserstand/Wasserspiegel-lage ({0}) mainvalue.duration = \u00dcberflutungsdauer mainvalue.duration.description = \u00dcberflutungsdauer ({0}) +state.uinfo.salix.historical.km_range_part = Ausgewertete Strecke +uinfo.salix.sounding= Peilung uinfo.salix.soundings= Peilungen +uinfo.export.salix_line.csv.header.scenario_dwspl = \u0394MW [cm] +uinfo.export.salix_line.csv.header.scenario = Salix-Linie_Szenario [m] uinfo.export.salix_line.csv.header.salix_line = Salix-Linie [m] -uinfo.export.salix_line.csv.header.delta_mw = (MW-MNW)x(-1) [m] -uinfo.export.salix_line.csv.header.scen = Salix-Linie [m] Szenario dMW={0} cm +uinfo.export.salix_line.csv.header.delta_mw = (MW-MNW)x(-1) [m] uinfo.export.salix_line.csv.header.hist = Salix-Linie [m] historisch uinfo.export.salix_line.csv.meta.header.evaluator = # Auswerter: {0} uinfo.export.salix_line.csv.meta.header.waterlevel.year = # Jahr/Zeitraum der Wasserspiegellage: {0} @@ -1149,6 +1153,10 @@ sinfo.chart.flood_duration.height.section.title = H\u00f6he Infrastrukturen BWaStr sinfo_facet_flood_height = Geod\u00e4tische H\u00f6he Infrastrukturen BWaStr sinfo_facet_flood_height.description = Geod\u00e4tische H\u00f6he Infrastrukturen BWaStr ({0}) +sinfo.chart.flood_duration.curve.section.title = \u00dcberflutungsdauer Infrastrukturen BWaStr - Dauerlinie +sinfo.chart.flood_duration.curve.xaxis.label = \u00dcberflutungsdauer [d/a] +sinfo.chart.flood_duration.curve.w = Wasserstandsdauerlinie +sinfo.chart.flood_duration.curve.q = Abflussdauerlinie bundu_bezugswst = Bezugswasserst\u00e4nde bundu_analysis = Fixierungsanalyse diff -r eedb0bcf226b -r 68ff4087b987 backend/src/main/java/org/dive4elements/river/model/BedHeight.java --- a/backend/src/main/java/org/dive4elements/river/model/BedHeight.java Fri Jul 06 13:18:51 2018 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/BedHeight.java Fri Jul 13 11:40:25 2018 +0200 @@ -9,6 +9,7 @@ package org.dive4elements.river.model; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; import javax.persistence.Column; @@ -207,11 +208,8 @@ public static List getBedHeights(final River river, final double kmLo, final double kmHi) { final Session session = SessionHolder.HOLDER.get(); - final Query query = session.createQuery("from BedHeight" - + " where river=:river" - + " and id in (select bedHeight.id from BedHeightValue" - + " where station between :kmfrom and :kmto" - + " group by bedHeight.id)"); + final Query query = session.createQuery("from BedHeight" + " where river=:river" + " and id in (select bedHeight.id from BedHeightValue" + + " where station between :kmfrom and :kmto" + " group by bedHeight.id)"); query.setParameter("river", river); query.setParameter("kmfrom", kmLo); @@ -238,11 +236,8 @@ final Session session = SessionHolder.HOLDER.get(); - final Query query = session.createQuery("FROM BedHeight" - + " WHERE (TRIM(description)=:description) AND river=:river" - + " AND id IN (SELECT bedHeight.id FROM BedHeightValue" - + " WHERE station BETWEEN :kmfrom AND :kmto" - + " GROUP BY bedHeight.id)"); + final Query query = session.createQuery("FROM BedHeight" + " WHERE (TRIM(description)=:description) AND river=:river" + + " AND id IN (SELECT bedHeight.id FROM BedHeightValue" + " WHERE station BETWEEN :kmfrom AND :kmto" + " GROUP BY bedHeight.id)"); query.setParameter("river", river); query.setParameter("description", description); query.setParameter("kmfrom", startKm); @@ -252,4 +247,78 @@ return ((singles != null) && !singles.isEmpty()) ? singles.get(0) : null; } + + public static List getBedHeightEpochs(final River river, final double startKm, final double endKm) { + + final Session session = SessionHolder.HOLDER.get(); + final String description = "epoch"; + final Query query = session.createQuery("FROM BedHeight" + " WHERE lower(description) LIKE :description AND " + "river=:river" + + " AND id IN (SELECT bedHeight.id FROM BedHeightValue" + " WHERE station BETWEEN :kmfrom AND :kmto" + " GROUP BY bedHeight.id)"); + query.setParameter("river", river); + query.setParameter("description", "%" + description + "%"); + query.setParameter("kmfrom", startKm); + query.setParameter("kmto", endKm); + + final List singles = query.list(); + + return ((singles != null) && !singles.isEmpty()) ? singles : null; + } + + public static List getBedHeightYear(final River river, final double startKm, final double endKm) { + + final Session session = SessionHolder.HOLDER.get(); + final String description = "epoch"; + final Query query = session.createQuery("FROM BedHeight" + " WHERE lower(description) NOT LIKE :description AND " + "river=:river" + + " AND id IN (SELECT bedHeight.id FROM BedHeightValue" + " WHERE station BETWEEN :kmfrom AND :kmto" + " GROUP BY bedHeight.id)"); + query.setParameter("river", river); + query.setParameter("description", "%" + description + "%"); + query.setParameter("kmfrom", startKm); + query.setParameter("kmto", endKm); + + final List singles = query.list(); + + return ((singles != null) && !singles.isEmpty()) ? singles : null; + } + + public static Range getRangeFromBedHeights(final BedHeight bh) { + final List ranges = new ArrayList<>(); + + final Session session = SessionHolder.HOLDER.get(); + + final Query query = session.createQuery("FROM Range" + " WHERE id=:range_id)"); + query.setParameter("range_id", bh.getRange().getId()); + + final List singles = query.list(); + + return ((singles != null) && !singles.isEmpty()) ? singles.get(0) : null; + } + + public static List getBedHeightYearEpoch(final boolean isEpoch, final Integer year, final River river, final double lowerKm, + final double upperKm) { + + final Session session = SessionHolder.HOLDER.get(); + final String description = "epoch"; + + final StringBuilder builder = new StringBuilder(); + builder.append("FROM BedHeight"); + if (isEpoch) { + builder.append(" WHERE lower(description) LIKE :description "); + } else { + builder.append(" WHERE lower(description) NOT LIKE :description "); + } + builder.append(" AND year =:year"); + + builder.append( + " AND river=:river AND id IN (SELECT bedHeight.id FROM BedHeightValue WHERE station BETWEEN :kmfrom AND :kmto GROUP BY bedHeight.id )"); + final Query query = session.createQuery(builder.toString()); + query.setParameter("river", river); + query.setParameter("year", year); + query.setParameter("description", "%" + description + "%"); + query.setParameter("kmfrom", lowerKm); + query.setParameter("kmto", upperKm); + + final List singles = query.list(); + + return ((singles != null) && !singles.isEmpty()) ? singles : null; + } } \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Fri Jul 13 11:40:25 2018 +0200 @@ -1556,4 +1556,22 @@ String sinfo_sounding_waterlevel_select_waterlevel(); String sinfo_deactivate_intelligent_datacord(); + + String sinfo_floodduration_curve(); + + String uinfo_salix_dmwspl_short(); + + String uinfo_salix_invalid_double(); + + String uinfo_salix_km_limit_exceed(); + + String uinfo_salix_km_overlap(); + + String uinfo_salix_km_has_gaps(); + + String uinfo_salix_km_anschluss(); + + String uinfo_salix_input_complete(); + + String common_input_hint_year(); } \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Fri Jul 13 11:40:25 2018 +0200 @@ -89,6 +89,7 @@ sedimentload_ls = Sediment Load welcome = Welcome to Flusshydrologische Software welcome_open_or_create = Please open a project from the project list or create a +common_input_hint_year = YYYY # Header images flysLogo = images/flys_logo.gif @@ -813,10 +814,12 @@ sinfo_collisions = Grundber\u00fchrungen sinfo_collision = Grundber\u00fchrungen -sinfo_flood_duration = \u00dcberflutungsdauer Infrastruktur BWaStr -sinfo_flood_height = H\u00f6he Infrastruktur BWaStr +sinfo_flood_duration = \u00dcberflutungsdauer Infrastrukturen BWaStr +sinfo_flood_height = H\u00f6he Infrastrukturen BWaStr +sinfo_floodduration_curve = \u00dcberflutungsdauer Infrastrukturen BWaStr - Dauerlinie uinfo = U-INFO +uinfo_salix_dmwspl_short = \u0394MW [cm] uinfo_inundation_duration_export = \u00dcberflutungsdauern Export uinfo_salix_line_export = Salix-Linie Export uinfo_vegetation_zones_export = Vegetationszonen Export @@ -829,6 +832,12 @@ uinfo_vegetation_zones_validation_range = Werte m\u00fcssen zwischen 0 und 365 liegen. uinfo_vegetation_zones_validation_from_greater_to = Der Wert f\u00fcr "\u00dcfd von" muss kleiner als "\u00dcfd bis". uinfo_vegetation_zones_invalid_integer = Nur Ganzzahlen erlaubt. +uinfo_salix_invalid_double = Nur Zahlen erlaubt. +uinfo_salix_km_limit_exceed = Die Zahl ist au\u00dferhalb des g\u00fcltigen km-Bereichs. +uinfo_salix_km_overlap = Km-Bereiche \u00fcberlappen. +uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt. +uinfo_salix_km_anschluss = Der eingegebene Bereich schlie\u00dft nicht an den letzten Wert an. +uinfo_salix_input_complete = Die gesamte Strecke ist bereits mit Werten belegt. bundu = Betrieb und Unterhaltung diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Fri Jul 13 11:40:25 2018 +0200 @@ -89,6 +89,7 @@ sedimentload_ls = Sediment Fracht welcome = Willkommen bei der Flusshydrologischen Software welcome_open_or_create = Bitte \u00f6ffnen Sie ein bestehendes Projekt aus der Projektliste oder erstellen Sie ein +common_input_hint_year = JJJJ # Header images flysLogo = images/flys_logo.gif @@ -813,10 +814,12 @@ sinfo_collisions = Grundber\u00fchrungen sinfo_collision = Grundber\u00fchrungen -sinfo_flood_duration = \u00dcberflutungsdauer Infrastruktur BWaStr -sinfo_flood_height = H\u00f6he Infrastruktur BWaStr +sinfo_flood_duration = \u00dcberflutungsdauer Infrastrukturen BWaStr +sinfo_flood_height = H\u00f6he Infrastrukturen BWaStr +sinfo_floodduration_curve = \u00dcberflutungsdauer Infrastrukturen BWaStr - Dauerlinie uinfo = U-INFO +uinfo_salix_dmwspl_short = \u0394MW [cm] uinfo_inundation_duration_export = \u00dcberflutungsdauern Export uinfo_salix_line_export = Salix-Linie Export uinfo_vegetation_zones_export = Vegetationszonen Export @@ -829,6 +832,12 @@ uinfo_vegetation_zones_validation_range = Werte m\u00fcssen zwischen 0 und 365 liegen. uinfo_vegetation_zones_validation_from_greater_to = Der Wert f\u00fcr "\u00dcfd von" muss kleiner als "\u00dcfd bis". uinfo_vegetation_zones_invalid_integer = Nur Ganzzahlen erlaubt. +uinfo_salix_invalid_double = Nur Zahlen erlaubt. +uinfo_salix_km_limit_exceed = Die Zahl ist au\u00dferhalb des g\u00fcltigen km-Bereichs. +uinfo_salix_km_overlap = Km-Bereiche \u00fcberlappen. +uinfo_salix_km_has_gaps = Der Km-Bereich ist nicht vollst. belegt. +uinfo_salix_km_anschluss = Der eingegebene Bereich schlie\u00dft nicht an den letzten Wert an. +uinfo_salix_input_complete = Die gesamte Strecke ist bereits mit Werten belegt. bundu = Betrieb und Unterhaltung diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractSingleItemPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractSingleItemPanel.java Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractSingleItemPanel.java Fri Jul 13 11:40:25 2018 +0200 @@ -226,20 +226,23 @@ switch (this.type) { case multi: - - final String[] sValues = sValue.trim().split(" "); - for (final String value : sValues) { - errors.addAll(this.validateSingleInput(value)); + if (sValue != null) { + final String[] sValues = sValue.trim().split(" "); + for (final String value : sValues) { + errors.addAll(this.validateSingleInput(value)); + } } break; case limit5: - final String[] values = sValue.trim().split(" "); - if (values.length > 5) { - errors.add(this.MSG.error_limit_exceeded_salix());// TODO generalize if needed - } - for (int i = 0; i < values.length; i++) { - if (i < 5) - errors.addAll(this.validateNumber(values[i])); + if (sValue != null) { + final String[] values = sValue.trim().split(" "); + if (values.length > 5) { + errors.add(this.MSG.error_limit_exceeded_salix());// TODO generalize if needed + } + for (int i = 0; i < values.length; i++) { + if (i < 5) + errors.addAll(this.validateNumber(values[i])); + } } break; case single: diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java Fri Jul 13 11:40:25 2018 +0200 @@ -331,5 +331,11 @@ * @return the selected data. */ protected abstract Data[] getData(); + + protected String getRiverName() { + final ArtifactDescription adescr = this.artifact.getArtifactDescription(); + return adescr.getRiver(); + } + } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistanceOnlyPartHistoricalPanel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistanceOnlyPartHistoricalPanel.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,61 @@ +/* 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.client.client.ui; + +import java.util.List; + +import org.dive4elements.river.client.shared.model.Data; +import org.dive4elements.river.client.shared.model.DataList; + +import com.smartgwt.client.widgets.Canvas; + +public class DistanceOnlyPartHistoricalPanel extends DistanceOnlyPartPanel { + + private static final long serialVersionUID = 1L; + private List validInputs; + + @Override + protected void initHelperPanel(final DataList data) { + final FromToTableHelperPanel helper = new FromToTableHelperPanel(data, "bedheights_for_part", this.MSG, null, null); + final Canvas table = helper.getTable(); + this.validInputs = helper.getKeycolEntries(); + + this.helperContainer.addMember(table); + + } + + @Override + protected void initMinMaxValues(final DataList data) { + try { + for (final Data item : data.getAll()) { + if (item.getLabel().equals("ld_from_part"))// misuse ld_from_part for max container + this.min = Double.valueOf(item.getItems()[0].getStringValue()); + + if (item.getLabel().equals("ld_to_part"))// misuse ld_to_part for max container + this.max = Double.valueOf(item.getItems()[0].getStringValue()); + } + } + catch (final NumberFormatException nfe) { + this.min = -Double.MAX_VALUE; + this.max = Double.MAX_VALUE; + } + } + + @Override + protected void initDefaultFrom(final DataList data) { + final double from = (this.min < -99999.) ? 0 : this.min; + this.distancePanel.setFrom(from); + } + + @Override + protected void initDefaultTo(final DataList data) { + final double to = (this.max > 99999.) ? 0 : this.max; + this.distancePanel.setTo(to); + } +} diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanel.java Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanel.java Fri Jul 13 11:40:25 2018 +0200 @@ -9,18 +9,9 @@ package org.dive4elements.river.client.client.ui; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; -import org.dive4elements.river.client.client.Config; import org.dive4elements.river.client.client.FLYSConstants; -import org.dive4elements.river.client.client.event.FilterHandler; -import org.dive4elements.river.client.client.event.RangeFilterEvent; -import org.dive4elements.river.client.client.event.StringFilterEvent; -import org.dive4elements.river.client.client.ui.range.DistanceInfoDataSource; -import org.dive4elements.river.client.client.ui.range.LocationsTable; -import org.dive4elements.river.client.client.ui.range.RangeTable; -import org.dive4elements.river.client.shared.model.ArtifactDescription; import org.dive4elements.river.client.shared.model.Data; import org.dive4elements.river.client.shared.model.DataItem; import org.dive4elements.river.client.shared.model.DataList; @@ -29,34 +20,22 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.NumberFormat; -import com.smartgwt.client.data.AdvancedCriteria; -import com.smartgwt.client.data.Criteria; -import com.smartgwt.client.data.Criterion; import com.smartgwt.client.data.Record; -import com.smartgwt.client.types.Alignment; -import com.smartgwt.client.types.OperatorId; import com.smartgwt.client.util.SC; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.Label; -import com.smartgwt.client.widgets.form.DynamicForm; -import com.smartgwt.client.widgets.form.fields.SelectItem; import com.smartgwt.client.widgets.form.fields.StaticTextItem; import com.smartgwt.client.widgets.form.fields.events.BlurEvent; import com.smartgwt.client.widgets.form.fields.events.BlurHandler; -import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; -import com.smartgwt.client.widgets.form.fields.events.ChangedHandler; import com.smartgwt.client.widgets.grid.ListGrid; import com.smartgwt.client.widgets.grid.events.RecordClickEvent; import com.smartgwt.client.widgets.grid.events.RecordClickHandler; import com.smartgwt.client.widgets.layout.HLayout; import com.smartgwt.client.widgets.layout.VLayout; -import com.smartgwt.client.widgets.tab.Tab; import com.smartgwt.client.widgets.tab.TabSet; -import com.smartgwt.client.widgets.tab.events.TabSelectedEvent; -import com.smartgwt.client.widgets.tab.events.TabSelectedHandler; /** Panel to allow input of distance for calculation range. */ -public class DistancePanel extends AbstractUIProvider implements BlurHandler, FilterHandler { +public class DistancePanel extends AbstractUIProvider implements BlurHandler { private static final long serialVersionUID = -883142387908664588L; @@ -68,8 +47,8 @@ protected FLYSConstants MSG = GWT.create(FLYSConstants.class); - protected RangeTable distancesTable; - protected LocationsTable locationsTable; + // protected RangeTable distancesTable; + // protected LocationsTable locationsTable; protected DoubleRangePanel distancePanel; @@ -110,7 +89,7 @@ initMinMaxValues(data); initDefaultValues(data); - initHelperPanel(); + initHelperPanel(data); return layout; } @@ -299,11 +278,6 @@ return new DefaultData(field, null, null, new DataItem[] { item }); } - @Override - public void onBlur(final BlurEvent event) { - this.distancePanel.validateForm(); - } - protected void initMinMaxValues(final DataList data) { final Data f = getData(data.getAll(), getLowerField()); final Data t = getData(data.getAll(), getUpperField()); @@ -392,20 +366,11 @@ return Double.valueOf(defValue); } - protected void initHelperPanel() { - this.distancesTable = new RangeTable(); - this.locationsTable = new LocationsTable(); + protected void initHelperPanel(final DataList data) { - final Config config = Config.getInstance(); - final String url = config.getServerUrl(); - final String river = getRiverName(); + final DistancePanelInputHelper helper = new DistancePanelInputHelper(this.MSG, this.helperContainer, this.getRiverName()); - this.distancesTable.setAutoFetchData(true); - this.locationsTable.setAutoFetchData(true); - this.distancesTable.setDataSource(new DistanceInfoDataSource(url, river, "distances")); - this.locationsTable.setDataSource(new DistanceInfoDataSource(url, river, "locations")); - - this.distancesTable.addRecordClickHandler(new RecordClickHandler() { + helper.getDistancesTable().addRecordClickHandler(new RecordClickHandler() { @Override public void onRecordClick(final RecordClickEvent e) { final Record r = e.getRecord(); @@ -423,7 +388,7 @@ } }); - this.locationsTable.addRecordClickHandler(new RecordClickHandler() { + helper.getLocationsTable().addRecordClickHandler(new RecordClickHandler() { @Override public void onRecordClick(final RecordClickEvent e) { final Record r = e.getRecord(); @@ -447,151 +412,11 @@ } }); - this.tabs = new TabSet(); - this.tabs.setWidth100(); - this.tabs.setHeight100(); - - final Tab locations = new Tab(this.MSG.locations()); - final Tab distances = new Tab(this.MSG.distance()); - - locations.setPane(this.locationsTable); - distances.setPane(this.distancesTable); - - this.tabs.addTab(locations, 0); - this.tabs.addTab(distances, 1); - - this.filterResultCount = new StaticTextItem(this.MSG.resultCount()); - this.filterResultCount.setTitleAlign(Alignment.LEFT); - this.filterResultCount.setTitleStyle("color: #000"); - - this.filterDescription = new TableFilter(); - this.filterDescription.setHeight("30px"); - this.filterDescription.addFilterHandler(this); - - this.filterRange = new RangeTableFilter(); - this.filterRange.setHeight("30px"); - this.filterRange.addFilterHandler(this); - this.filterRange.setVisible(false); - - final SelectItem filterCriteria = new SelectItem(); - filterCriteria.setShowTitle(false); - filterCriteria.setWidth(100); - filterCriteria.addChangedHandler(new ChangedHandler() { - @Override - public void onChanged(final ChangedEvent e) { - if (e.getValue().toString().equals("range")) { - DistancePanel.this.filterRange.setVisible(true); - DistancePanel.this.filterDescription.setVisible(false); - DistancePanel.this.filterDescription.clear(); - } else { - DistancePanel.this.filterRange.setVisible(false); - DistancePanel.this.filterRange.clear(); - DistancePanel.this.filterDescription.setVisible(true); - } - } - }); - - final LinkedHashMap filterMap = new LinkedHashMap(); - filterMap.put("description", this.MSG.description()); - filterMap.put("range", this.MSG.range()); - filterCriteria.setValueMap(filterMap); - filterCriteria.setValue("description"); - - final DynamicForm form = new DynamicForm(); - form.setFields(filterCriteria); - - final DynamicForm form2 = new DynamicForm(); - form2.setFields(this.filterResultCount); - - final HLayout filterLayout = new HLayout(); - filterLayout.addMember(form); - filterLayout.addMember(this.filterDescription); - filterLayout.addMember(this.filterRange); - filterLayout.setHeight(30); - this.tabs.addTabSelectedHandler(new TabSelectedHandler() { - @Override - public void onTabSelected(final TabSelectedEvent evt) { - DistancePanel.this.filterDescription.clear(); - DistancePanel.this.filterRange.clear(); - DistancePanel.this.filterResultCount.setValue(""); - - final Canvas c = evt.getTabPane(); - if (c instanceof ListGrid) { - DistancePanel.this.currentFiltered = (ListGrid) c; - } - } - }); - - this.helperContainer.addMember(this.tabs); - this.helperContainer.addMember(filterLayout); - this.helperContainer.addMember(form2); } @Override - public void onFilterCriteriaChanged(final StringFilterEvent event) { - final String search = event.getFilter(); - - if (search != null && search.length() > 0) { - final Criteria c = new Criteria("description", search); - this.locationsTable.filterData(c); - this.distancesTable.filterData(c); - this.filterResultCount.setValue(this.currentFiltered.getRecords().length); - } else { - this.locationsTable.clearCriteria(); - this.distancesTable.clearCriteria(); - this.filterResultCount.setValue(""); - } - } - - @Override - public void onFilterCriteriaChanged(final RangeFilterEvent event) { - final Float from = event.getFrom() - 0.001f; - final Float to = event.getTo() + 0.001f; - - Criterion combinedFilter = null; - Criterion locationFilter = null; - - if (from.equals(Float.NaN) && to.equals(Float.NaN)) { - this.locationsTable.clearCriteria(); - this.distancesTable.clearCriteria(); - this.filterResultCount.setValue(""); - return; - } - - if (from.equals(Float.NaN)) { - combinedFilter = new Criterion("to", OperatorId.LESS_OR_EQUAL, to); - - locationFilter = new Criterion("from", OperatorId.LESS_OR_EQUAL, to); - - this.locationsTable.filterData(locationFilter); - this.distancesTable.filterData(combinedFilter); - this.filterResultCount.setValue(this.currentFiltered.getRecords().length); - return; - } - - if (to.equals(Float.NaN)) { - combinedFilter = new Criterion("from", OperatorId.GREATER_OR_EQUAL, from); - } else { - final AdvancedCriteria c1 = new AdvancedCriteria(OperatorId.AND, - new Criterion[] { new Criterion("from", OperatorId.GREATER_OR_EQUAL, from), new Criterion("from", OperatorId.LESS_OR_EQUAL, to) }); - - final AdvancedCriteria c2 = new AdvancedCriteria(OperatorId.AND, - new Criterion[] { new Criterion("to", OperatorId.GREATER_OR_EQUAL, from), new Criterion("to", OperatorId.LESS_OR_EQUAL, to) }); - - final AdvancedCriteria c3 = new AdvancedCriteria(OperatorId.AND, - new Criterion[] { new Criterion("from", OperatorId.LESS_OR_EQUAL, to), new Criterion("to", OperatorId.GREATER_OR_EQUAL, from) }); - - combinedFilter = new AdvancedCriteria(OperatorId.OR, new Criterion[] { c1, c2, c3 }); - } - this.locationsTable.filterData(combinedFilter); - this.distancesTable.filterData(combinedFilter); - this.filterResultCount.setValue(this.currentFiltered.getRecords().length); - - } - - protected String getRiverName() { - final ArtifactDescription adescr = this.artifact.getArtifactDescription(); - return adescr.getRiver(); + public void onBlur(final BlurEvent event) { + this.distancePanel.validateForm(); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanelInputHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DistancePanelInputHelper.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,229 @@ +/* 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.client.client.ui; + +import java.util.LinkedHashMap; + +import org.dive4elements.river.client.client.Config; +import org.dive4elements.river.client.client.FLYSConstants; +import org.dive4elements.river.client.client.event.FilterHandler; +import org.dive4elements.river.client.client.event.RangeFilterEvent; +import org.dive4elements.river.client.client.event.StringFilterEvent; +import org.dive4elements.river.client.client.ui.range.DistanceInfoDataSource; +import org.dive4elements.river.client.client.ui.range.LocationsTable; +import org.dive4elements.river.client.client.ui.range.RangeTable; + +import com.smartgwt.client.data.AdvancedCriteria; +import com.smartgwt.client.data.Criteria; +import com.smartgwt.client.data.Criterion; +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.types.OperatorId; +import com.smartgwt.client.widgets.Canvas; +import com.smartgwt.client.widgets.form.DynamicForm; +import com.smartgwt.client.widgets.form.fields.SelectItem; +import com.smartgwt.client.widgets.form.fields.StaticTextItem; +import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; +import com.smartgwt.client.widgets.form.fields.events.ChangedHandler; +import com.smartgwt.client.widgets.grid.ListGrid; +import com.smartgwt.client.widgets.layout.HLayout; +import com.smartgwt.client.widgets.layout.VLayout; +import com.smartgwt.client.widgets.tab.Tab; +import com.smartgwt.client.widgets.tab.TabSet; +import com.smartgwt.client.widgets.tab.events.TabSelectedEvent; +import com.smartgwt.client.widgets.tab.events.TabSelectedHandler; + +/** Panel to allow input of distance for calculation range. */ +public class DistancePanelInputHelper implements FilterHandler { + + private RangeTable distancesTable; + private LocationsTable locationsTable; + private TabSet tabs; + private StaticTextItem filterResultCount; + private TableFilter filterDescription; + private RangeTableFilter filterRange; + private ListGrid currentFiltered; + protected final VLayout helperContainer; + private final FLYSConstants MSG; + private final String river; + + public DistancePanelInputHelper(final FLYSConstants MSG, final VLayout helperContainer, final String river) { + this.MSG = MSG; + this.helperContainer = helperContainer; + this.river = river; + + initHelperPanel(); // copy from DistancePanel + } + + protected void initHelperPanel() { + this.distancesTable = new RangeTable(); + this.locationsTable = new LocationsTable(); + + final Config config = Config.getInstance(); + final String url = config.getServerUrl(); + // final String river = getRiverName(); + + this.distancesTable.setAutoFetchData(true); + this.locationsTable.setAutoFetchData(true); + this.distancesTable.setDataSource(new DistanceInfoDataSource(url, this.river, "distances")); + this.locationsTable.setDataSource(new DistanceInfoDataSource(url, this.river, "locations")); + + // recordClickHandlers were here + + this.tabs = new TabSet(); + this.tabs.setWidth100(); + this.tabs.setHeight100(); + + final Tab locations = new Tab(this.MSG.locations()); + final Tab distances = new Tab(this.MSG.distance()); + + locations.setPane(this.locationsTable); + distances.setPane(this.distancesTable); + + this.tabs.addTab(locations, 0); + this.tabs.addTab(distances, 1); + + this.filterResultCount = new StaticTextItem(this.MSG.resultCount()); + this.filterResultCount.setTitleAlign(Alignment.LEFT); + this.filterResultCount.setTitleStyle("color: #000"); + + this.filterDescription = new TableFilter(); + this.filterDescription.setHeight("30px"); + this.filterDescription.addFilterHandler(this); + + this.filterRange = new RangeTableFilter(); + this.filterRange.setHeight("30px"); + this.filterRange.addFilterHandler(this); + this.filterRange.setVisible(false); + + final SelectItem filterCriteria = new SelectItem(); + filterCriteria.setShowTitle(false); + filterCriteria.setWidth(100); + filterCriteria.addChangedHandler(new ChangedHandler() { + @Override + public void onChanged(final ChangedEvent e) { + if (e.getValue().toString().equals("range")) { + DistancePanelInputHelper.this.filterRange.setVisible(true); + DistancePanelInputHelper.this.filterDescription.setVisible(false); + DistancePanelInputHelper.this.filterDescription.clear(); + } else { + DistancePanelInputHelper.this.filterRange.setVisible(false); + DistancePanelInputHelper.this.filterRange.clear(); + DistancePanelInputHelper.this.filterDescription.setVisible(true); + } + } + }); + + final LinkedHashMap filterMap = new LinkedHashMap(); + filterMap.put("description", this.MSG.description()); + filterMap.put("range", this.MSG.range()); + filterCriteria.setValueMap(filterMap); + filterCriteria.setValue("description"); + + final DynamicForm form = new DynamicForm(); + form.setFields(filterCriteria); + + final DynamicForm form2 = new DynamicForm(); + form2.setFields(this.filterResultCount); + + final HLayout filterLayout = new HLayout(); + filterLayout.addMember(form); + filterLayout.addMember(this.filterDescription); + filterLayout.addMember(this.filterRange); + filterLayout.setHeight(30); + this.tabs.addTabSelectedHandler(new TabSelectedHandler() { + @Override + public void onTabSelected(final TabSelectedEvent evt) { + DistancePanelInputHelper.this.filterDescription.clear(); + DistancePanelInputHelper.this.filterRange.clear(); + DistancePanelInputHelper.this.filterResultCount.setValue(""); + + final Canvas c = evt.getTabPane(); + if (c instanceof ListGrid) { + DistancePanelInputHelper.this.currentFiltered = (ListGrid) c; + } + } + }); + + this.helperContainer.addMember(this.tabs); + this.helperContainer.addMember(filterLayout); + this.helperContainer.addMember(form2); + } + + @Override + public void onFilterCriteriaChanged(final StringFilterEvent event) { + final String search = event.getFilter(); + + if (search != null && search.length() > 0) { + final Criteria c = new Criteria("description", search); + this.locationsTable.filterData(c); + this.distancesTable.filterData(c); + this.filterResultCount.setValue(this.currentFiltered.getRecords().length); + } else { + this.locationsTable.clearCriteria(); + this.distancesTable.clearCriteria(); + this.filterResultCount.setValue(""); + } + } + + @Override + public void onFilterCriteriaChanged(final RangeFilterEvent event) { + final Float from = event.getFrom() - 0.001f; + final Float to = event.getTo() + 0.001f; + + Criterion combinedFilter = null; + Criterion locationFilter = null; + + if (from.equals(Float.NaN) && to.equals(Float.NaN)) { + this.locationsTable.clearCriteria(); + this.distancesTable.clearCriteria(); + this.filterResultCount.setValue(""); + return; + } + + if (from.equals(Float.NaN)) { + combinedFilter = new Criterion("to", OperatorId.LESS_OR_EQUAL, to); + + locationFilter = new Criterion("from", OperatorId.LESS_OR_EQUAL, to); + + this.locationsTable.filterData(locationFilter); + this.distancesTable.filterData(combinedFilter); + this.filterResultCount.setValue(this.currentFiltered.getRecords().length); + return; + } + + if (to.equals(Float.NaN)) { + combinedFilter = new Criterion("from", OperatorId.GREATER_OR_EQUAL, from); + } else { + final AdvancedCriteria c1 = new AdvancedCriteria(OperatorId.AND, + new Criterion[] { new Criterion("from", OperatorId.GREATER_OR_EQUAL, from), new Criterion("from", OperatorId.LESS_OR_EQUAL, to) }); + + final AdvancedCriteria c2 = new AdvancedCriteria(OperatorId.AND, + new Criterion[] { new Criterion("to", OperatorId.GREATER_OR_EQUAL, from), new Criterion("to", OperatorId.LESS_OR_EQUAL, to) }); + + final AdvancedCriteria c3 = new AdvancedCriteria(OperatorId.AND, + new Criterion[] { new Criterion("from", OperatorId.LESS_OR_EQUAL, to), new Criterion("to", OperatorId.GREATER_OR_EQUAL, from) }); + + combinedFilter = new AdvancedCriteria(OperatorId.OR, new Criterion[] { c1, c2, c3 }); + } + this.locationsTable.filterData(combinedFilter); + this.distancesTable.filterData(combinedFilter); + this.filterResultCount.setValue(this.currentFiltered.getRecords().length); + + } + + public ListGrid getDistancesTable() { + return this.distancesTable; + } + + public ListGrid getLocationsTable() { + return this.locationsTable; + } + +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/PanelHelper.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/PanelHelper.java Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/PanelHelper.java Fri Jul 13 11:40:25 2018 +0200 @@ -9,10 +9,18 @@ */ package org.dive4elements.river.client.client.ui; +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.types.ListGridFieldType; import com.smartgwt.client.widgets.form.fields.IntegerItem; import com.smartgwt.client.widgets.form.fields.TextItem; +import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator; import com.smartgwt.client.widgets.form.validator.IsIntegerValidator; import com.smartgwt.client.widgets.form.validator.Validator; +import com.smartgwt.client.widgets.grid.ListGrid; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.SortNormalizer; +import com.smartgwt.client.widgets.grid.events.RecordClickEvent; +import com.smartgwt.client.widgets.grid.events.RecordClickHandler; import com.smartgwt.client.widgets.layout.VLayout; /** @@ -63,4 +71,48 @@ return inputItem; } + + public static final ListGridField createRemoveField(final ListGrid table, final String icon) { + final ListGridField removeField = new ListGridField("_removeRecord", "Remove Record") { + { + setType(ListGridFieldType.ICON); + setIcon(icon); + setCanEdit(false); + setCanFilter(false); + setCanSort(false); + setCanGroupBy(false); + setCanFreeze(false); + setWidth(25); + setCanDragResize(false); + super.setCanToggle(false); + } + }; + table.addRecordClickHandler(new RecordClickHandler() { + @Override + public void onRecordClick(final RecordClickEvent event) { + // Just handle remove-clicks + if (!event.getField().getName().equals(removeField.getName())) { + return; + } + event.getViewer().removeData(event.getRecord()); + } + }); + + return removeField; + } + + public static final ListGridField createIntTableField(final String key, final String msg, final boolean canSort, final SortNormalizer normalizer, + final IntegerRangeValidator validators) { + final ListGridField intField = new ListGridField(key, msg); + intField.setType(ListGridFieldType.INTEGER); + intField.setValidators(validators); + intField.setWidth(90); + intField.setAlign(Alignment.RIGHT); + intField.setSortNormalizer(normalizer); + intField.setCanSort(canSort); + intField.setCanDragResize(false); + + return intField; + } + } diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/UIProviderFactory.java Fri Jul 13 11:40:25 2018 +0200 @@ -30,8 +30,9 @@ import org.dive4elements.river.client.client.ui.sinfo.FlowDepthTwinPanel; import org.dive4elements.river.client.client.ui.sq.SQPeriodPanel; import org.dive4elements.river.client.client.ui.uinfo.LoadSedimentHeightPanel; -import org.dive4elements.river.client.client.ui.uinfo.LoadSingleEpochSelect; import org.dive4elements.river.client.client.ui.uinfo.LoadSingleYearPanel; +import org.dive4elements.river.client.client.ui.uinfo.LoadSingleYearPseudoEpochPanel; +import org.dive4elements.river.client.client.ui.uinfo.SupraRegionalTablePanel; import org.dive4elements.river.client.client.ui.uinfo.VegetationzonesTableEditPanel; import org.dive4elements.river.client.client.ui.uinfo.VegetationzonesTablePanel; import org.dive4elements.river.client.shared.model.User; @@ -71,6 +72,8 @@ return new DistanceOnlyPanel(); } else if (uiProvider.equals("distance_only_part_panel")) { return new DistanceOnlyPartPanel(); + } else if (uiProvider.equals("distance_only_part_historical_panel")) { + return new DistanceOnlyPartHistoricalPanel(); } else if (uiProvider.equals("waterlevel_ground_panel")) { return new WaterlevelGroundPanel(); } else if (uiProvider.equals("wq_panel")) { @@ -165,8 +168,10 @@ return new CollisionLoadEpochPanel(); } else if (uiProvider.equals("common.state.load_single_year_select")) { return new LoadSingleYearPanel(); - } else if (uiProvider.equals("common.load_single_epoch_select")) { - return new LoadSingleEpochSelect(); + } else if (uiProvider.equals("common.state.load_single_year_select.show_hint")) { + return new LoadSingleYearPanel(true); + } else if (uiProvider.equals("uinfo.salix.load_single_year_pseudo_epoch_select")) { + return new LoadSingleYearPseudoEpochPanel(); } else if (uiProvider.equals("minfo.sedimentload_sqti_select")) { return new SedLoadSQTiPanel(); } else if (uiProvider.equals("uinfo.sedimentheight_select")) { @@ -179,6 +184,8 @@ return new UserRGDProvider(); } else if (uiProvider.equals("static_sqrelation")) { return new StaticDataPanel(); + } else if (uiProvider.equals("uinfo.salix.supraregional.table")) { + return new SupraRegionalTablePanel(); } if ("sinfo_flowdepth_twin_panel".equals(uiProvider)) diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WaterlevelGroundPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WaterlevelGroundPanel.java Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WaterlevelGroundPanel.java Fri Jul 13 11:40:25 2018 +0200 @@ -121,7 +121,7 @@ } @Override - protected void initHelperPanel() { + protected void initHelperPanel(final DataList data) { // We don't need a helper panel here. But we have to override this // method to avoid the table creation in the parent class. } diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/LoadSingleEpochSelect.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/LoadSingleEpochSelect.java Fri Jul 06 13:18:51 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* 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.client.client.ui.uinfo; - -import org.dive4elements.river.client.client.ui.AbstractEpochPanel; -import org.dive4elements.river.client.client.ui.PanelHelper; -import org.dive4elements.river.client.shared.model.DataList; - -import com.smartgwt.client.widgets.Canvas; -import com.smartgwt.client.widgets.Label; -import com.smartgwt.client.widgets.form.DynamicForm; -import com.smartgwt.client.widgets.form.fields.TextItem; -import com.smartgwt.client.widgets.layout.VLayout; - -public class LoadSingleEpochSelect extends AbstractEpochPanel { - - private static final long serialVersionUID = 1L; - - public LoadSingleEpochSelect() { - super(Type.single); - } - - @Override - protected String getDatakey() { - return "singleepoch"; - } - - @Override - protected Canvas createWidget(final DataList data) { - final VLayout root = new VLayout(); - - final Label title = new Label(data.get(0).getDescription()); - title.setHeight("25px"); - - final DynamicForm form = new DynamicForm(); - form.setNumCols(4); - final TextItem start = createStartInputItem(this.MSG.from()); - start.setCanEdit(false); - - final TextItem end = createEndInputItem(this.MSG.to()); - end.setCanEdit(false); - - form.setFields(start, end); - - root.addMember(title); - root.addMember(PanelHelper.getSpacer(10)); - root.addMember(form); - - return root; - } - -} diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/LoadSingleYearPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/LoadSingleYearPanel.java Fri Jul 06 13:18:51 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/LoadSingleYearPanel.java Fri Jul 13 11:40:25 2018 +0200 @@ -19,10 +19,18 @@ public class LoadSingleYearPanel extends AbstractSingleItemPanel { + private static final long serialVersionUID = 1L; + private boolean showHint = false; + public LoadSingleYearPanel() { super(Type.single); } + public LoadSingleYearPanel(final boolean showHint) { + super(Type.single); + this.showHint = showHint; + } + @Override protected String getDatakey() { return "singleyear"; @@ -44,6 +52,9 @@ form.setNumCols(4); final TextItem inputItem = createInputItem("YEAR_INPUT"); + inputItem.setShowHint(this.showHint); + inputItem.setHint(this.MSG.common_input_hint_year()); + inputItem.setShowHintInField(true); inputItem.setShowTitle(false); form.setFields(inputItem); diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/LoadSingleYearPseudoEpochPanel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/LoadSingleYearPseudoEpochPanel.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,25 @@ +/* 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.client.client.ui.uinfo; + +public class LoadSingleYearPseudoEpochPanel extends LoadSingleYearPanel { + + private static final long serialVersionUID = 1L; + + @Override + protected String getDatakey() { + return "singleepoch"; + } + + @Override + protected String errorForItemMsg() { + return this.MSG.no_data_for_year();// NO DATA FOR EPOCH TODO möglicherweise, wenn der ablauf klar ist + } + +} \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/SupraRegionalTablePanel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/uinfo/SupraRegionalTablePanel.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,423 @@ +/* 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.client.client.ui.uinfo; + +import java.util.ArrayList; +import java.util.List; + +import org.dive4elements.river.client.client.ui.AbstractUIProvider; +import org.dive4elements.river.client.client.ui.DistancePanelInputHelper; +import org.dive4elements.river.client.client.ui.PanelHelper; +import org.dive4elements.river.client.shared.model.Data; +import org.dive4elements.river.client.shared.model.DataItem; +import org.dive4elements.river.client.shared.model.DataList; +import org.dive4elements.river.client.shared.model.DefaultData; +import org.dive4elements.river.client.shared.model.DefaultDataItem; +import org.dive4elements.river.client.shared.model.SalixZone; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.i18n.client.NumberFormat; +import com.google.gwt.user.client.ui.Label; +import com.smartgwt.client.data.Record; +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.util.SC; +import com.smartgwt.client.widgets.Button; +import com.smartgwt.client.widgets.Canvas; +import com.smartgwt.client.widgets.events.ClickEvent; +import com.smartgwt.client.widgets.events.ClickHandler; +import com.smartgwt.client.widgets.form.DynamicForm; +import com.smartgwt.client.widgets.form.fields.TextItem; +import com.smartgwt.client.widgets.grid.CellEditValueFormatter; +import com.smartgwt.client.widgets.grid.CellFormatter; +import com.smartgwt.client.widgets.grid.ListGrid; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.grid.events.CellSavedEvent; +import com.smartgwt.client.widgets.grid.events.CellSavedHandler; +import com.smartgwt.client.widgets.grid.events.RecordClickEvent; +import com.smartgwt.client.widgets.grid.events.RecordClickHandler; +import com.smartgwt.client.widgets.layout.HLayout; +import com.smartgwt.client.widgets.layout.Layout; +import com.smartgwt.client.widgets.layout.VLayout; + +public class SupraRegionalTablePanel extends AbstractUIProvider { + private static final long serialVersionUID = 1L; + + private Double minKm, maxKm = -1.; + // private String tableData = ""; + private ListGrid table; + private final String datakey = "supraregional_table"; + final Label validationLabel = new Label(); + + private final NumberFormat format = NumberFormat.getDecimalFormat(); + + @Override + public Canvas createOld(final DataList dataList) { + final HLayout layout = new HLayout(); + layout.setWidth("400px"); + final VLayout vLayout = new VLayout(); + vLayout.setWidth(130); + final Label label = new Label(dataList.getLabel()); + label.setWidth("200px"); + label.setHeight("25px"); + + final List items = dataList.getAll(); + final Data str = getData(items, this.datakey); + final DataItem[] strItems = str.getItems(); + + final List entries = SalixZone.parse(strItems[0].getLabel()); + + for (final SalixZone entry : entries) { + final Label dateLabel = new Label( + entry.getDwsplValue() + " (" + this.format.format(entry.getFromKm()) + "-" + this.format.format(entry.getToKm()) + " km)"); + dateLabel.setHeight("20px"); + vLayout.addMember(dateLabel); + } + final Canvas back = getBackButton(dataList.getState()); + layout.addMember(label); + layout.addMember(vLayout); + layout.addMember(back); + + return layout; + } + + @Override + public Canvas create(final DataList data) { + + final Data dataItem = data.getAll().get(0); + String tableData = ""; + for (final DataItem item : dataItem.getItems()) { + final String label = item.getLabel(); + if (label.equals("salix_zones_min")) + this.minKm = Double.valueOf(item.getStringValue()); + else if (label.equals("salix_zones_max")) + this.maxKm = Double.valueOf(item.getStringValue()); + else if (label.equals("salix_zones")) + tableData = item.getStringValue(); + } + + if (this.minKm > this.maxKm) { + final double temp = this.minKm; + this.minKm = this.maxKm; + this.maxKm = temp; + } + + final VLayout layout = new VLayout(); + final Canvas submit = getNextButton(); + + final VLayout root = new VLayout(); + root.setWidth(420); + createWidget(root, data, tableData); + + layout.addMember(root); + layout.addMember(submit); + + validateRangeOverlap();// init Text + return layout; + } + + @Override + protected Data[] getData() { + final List data = new ArrayList(); + + final ListGridRecord[] lgr = this.table.getRecords(); + if (lgr == null) { + return new Data[0]; + } + final List zoneList = getSalixZones(lgr); + final DataItem item = new DefaultDataItem(this.datakey, null, SalixZone.parseListToDataString(zoneList)); + data.add(new DefaultData(this.datakey, null, null, new DataItem[] { item })); + return data.toArray(new Data[data.size()]); + } + + private List getSalixZones(final ListGridRecord[] lgr) { + final List zoneList = new ArrayList(); + for (final ListGridRecord element : lgr) { + final Record r = element; + final SalixZone zone = SalixZone.createFromTableEntry(r.getAttribute("dmwspl"), r.getAttribute("from"), r.getAttribute("to")); + zoneList.add(zone); + } + return zoneList; + } + + public Canvas createWidget(final Layout root, final DataList data, final String tableData) { + + this.table = createTable(root, data, tableData); + final TextItem dwspl = PanelHelper.createItem("_label_dwspl", this.MSG.uinfo_salix_dmwspl_short(), "50"); + final TextItem start = PanelHelper.createIntegerItem("_from_dwspl", getLabelFromTo(this.MSG.from()), "50"); + final TextItem end = PanelHelper.createIntegerItem("_to_dwspl", getLabelFromTo(this.MSG.to()), "50"); + + final HLayout fields = new HLayout(); + + final Button add = new Button(this.MSG.add_date()); // TODO: make key more generic or change to more specific + + final DynamicForm newEntryForm = new DynamicForm(); + newEntryForm.setWidth(320); + newEntryForm.setNumCols(12); + newEntryForm.setFields(start, end, dwspl); + + add.addClickHandler(new ClickHandler() { + @Override + public void onClick(final ClickEvent ce) { + final String v1 = start.getValueAsString(); + final String v2 = end.getValueAsString(); + final String v3 = dwspl.getValueAsString(); + final String message = validate(v1, v2, v3); + if (message != null) { + SC.warn(message); + return; + } + final ListGridRecord r = new ListGridRecord(); + r.setAttribute("dmwspl", v3); + r.setAttribute("from", SupraRegionalTablePanel.this.format.parse(v1)); + r.setAttribute("to", SupraRegionalTablePanel.this.format.parse(v2)); + SupraRegionalTablePanel.this.table.addData(r); + validateRangeOverlap(); + } + }); + + fields.addMember(newEntryForm); + + root.addMember(fields); + root.addMember(PanelHelper.getSpacer(10)); + + initHelperPanel(start, end); + + root.addMember(add); + root.addMember(PanelHelper.getSpacer(20)); + return root; + } + + private String getLabelFromTo(final String fromOrTo) { + return new StringBuilder().append(fromOrTo).append(" [").append(this.MSG.dpUnitFrom()).append("]").toString(); + } + + protected void initHelperPanel(final TextItem start, final TextItem end) { + final DistancePanelInputHelper helper = new DistancePanelInputHelper(this.MSG, this.helperContainer, this.getRiverName()); + + helper.getDistancesTable().addRecordClickHandler(new RecordClickHandler() { + @Override + public void onRecordClick(final RecordClickEvent e) { + final Record r = e.getRecord(); + + final String from = r.getAttribute("from"); + final String to = r.getAttribute("to"); + + try { + start.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(from))); + end.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(to))); + } + catch (final NumberFormatException nfe) { + SC.warn(SupraRegionalTablePanel.this.MSG.wrongFormat()); + } + } + }); + + helper.getLocationsTable().addRecordClickHandler(new RecordClickHandler() { + @Override + public void onRecordClick(final RecordClickEvent e) { + final Record r = e.getRecord(); + final int field = e.getFieldNum(); + + try { + final String value = r.getAttribute("from"); + switch (field) { + case 0: + start.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(value))); + break; + case 1: + end.setValue(SupraRegionalTablePanel.this.format.format(Double.valueOf(value))); + break; + } + } + catch (final NumberFormatException nfe) { + SC.warn(SupraRegionalTablePanel.this.MSG.wrongFormat()); + } + } + }); + + } + + protected final ListGrid createTable(final Layout root, final DataList data, final String tableData) { + + final Label title = new Label(data.get(0).getDescription()); + title.setHeight("35px"); + this.validationLabel.setHeight("10px"); + this.validationLabel.getElement().getStyle().setColor("red"); + final ListGrid elements = new ListGrid(); + elements.setWidth(320); + elements.setHeight(300); + elements.setShowHeaderContextMenu(false); + elements.setCanReorderFields(false); + elements.setCanResizeFields(false); + elements.setCanEdit(true); + elements.setCanSort(false); + elements.setCanResizeFields(false); + + final ListGridField dmwsplField = new ListGridField("dmwspl", this.MSG.uinfo_salix_dmwspl_short()); + dmwsplField.setAlign(Alignment.RIGHT); + dmwsplField.setWidth(95); + dmwsplField.addCellSavedHandler(new CellSavedHandler() { + @Override + public void onCellSaved(final CellSavedEvent event) { + final Object value = event.getNewValue(); + event.getRecord().setAttribute("dmwspl", event.getOldValue()); + try { + final int intValue = Integer.valueOf(String.valueOf(value)); + event.getRecord().setAttribute("dmwspl", intValue); + } + catch (final NumberFormatException e) { + e.printStackTrace(); + } + } + }); + final ListGridField fromField = createDoubleTableField("from", getLabelFromTo(this.MSG.from())); + final ListGridField toField = createDoubleTableField("to", getLabelFromTo(this.MSG.to())); + final ListGridField removeField = PanelHelper.createRemoveField(elements, GWT.getHostPageBaseURL() + this.MSG.removeFeature()); + elements.addRecordClickHandler(new RecordClickHandler() { // adding another custom record-Remove-Handler which is not included in the Panelhelper + @Override + public void onRecordClick(final RecordClickEvent event) { + if (event.getField().getName().equals(removeField.getName())) { + validateRangeOverlap(); + } + } + }); + elements.setFields(fromField, toField, dmwsplField, removeField); + addDataInit(elements, tableData); + + root.addMember(title); + root.addMember(elements); + root.addMember(PanelHelper.getSpacer(3)); + root.addMember(this.validationLabel); + root.addMember(PanelHelper.getSpacer(4)); + return elements; + } + + private void addDataInit(final ListGrid table, final String tableData) { + if (tableData != null) { + final List rows = SalixZone.parse(tableData); + for (final SalixZone row : rows) { + table.addData(createEntry(row)); + } + } + } + + public final ListGridRecord createEntry(final SalixZone row) { + + final Integer dwspl = row.getDwsplValue(); + final Double from = row.getFromKm(); + final Double to = row.getToKm(); + + if (dwspl == null || from == null || to == null) { + return null; + } + + final ListGridRecord r = new ListGridRecord(); + r.setAttribute("dmwspl", dwspl); + r.setAttribute("from", from); + r.setAttribute("to", to); + + return r; + + } + + private ListGridField createDoubleTableField(final String key, final String msg) { + final ListGridField field = new ListGridField(key, msg); + field.setAlign(Alignment.RIGHT); + field.setWidth(90); + field.addCellSavedHandler(new CellSavedHandler() { + @Override + public void onCellSaved(final CellSavedEvent event) { + final Object value = event.getNewValue(); + event.getRecord().setAttribute(key, event.getOldValue()); + try { + final double d = SupraRegionalTablePanel.this.format.parse(String.valueOf(value)); + if (d > SupraRegionalTablePanel.this.maxKm) { + event.getRecord().setAttribute(key, SupraRegionalTablePanel.this.maxKm); + } else if (d < SupraRegionalTablePanel.this.minKm) { + event.getRecord().setAttribute(key, SupraRegionalTablePanel.this.minKm); + } else { + event.getRecord().setAttribute(key, d); + } + validateRangeOverlap(); + } + catch (final NumberFormatException e) { + e.printStackTrace(); + } + } + }); + + field.setEditValueFormatter(new CellEditValueFormatter() { + @Override + public Object format(final Object value, final ListGridRecord record, final int rowNum, final int colNum) { + if (!(value instanceof Float || value instanceof Double)) { + try { + return (float) SupraRegionalTablePanel.this.format.parse(String.valueOf(value)); + } + catch (final Exception e2) { + return record.getAttribute(key); + } + } else { + return SupraRegionalTablePanel.this.format.format((Double) value); + } + } + }); + field.setCellFormatter(new CellFormatter() { + @Override + public String format(final Object value, final ListGridRecord record, final int rowNum, final int colNum) { + return SupraRegionalTablePanel.this.format.format(Double.valueOf(String.valueOf(value))); + } + }); + return field; + } + + private String validate(final String fromInput, final String toInput, final String dmwspl) { + + final List zones = getSalixZones(this.table.getRecords()); + + if (fromInput == null || toInput == null || dmwspl == null || fromInput.trim().isEmpty() || toInput.trim().isEmpty() || dmwspl.trim().isEmpty()) + return this.MSG.uinfo_vegetation_zones_validation_empty(); + + try { + final Double from = this.format.parse(fromInput); + final Double to = this.format.parse(toInput); + Integer.valueOf(dmwspl); + + if (!SalixZone.hasGaps(zones, this.minKm, this.maxKm)) + return this.MSG.uinfo_salix_input_complete(); + + if (from < this.minKm || from > this.maxKm || to > this.maxKm || to < this.minKm) + return this.MSG.uinfo_salix_km_limit_exceed(); + + // range anschluss + if (!SalixZone.isValidAnschlussRange(from, to, zones, this.minKm)) { + return this.MSG.uinfo_salix_km_anschluss(); + } + return null; + } + catch (final NumberFormatException e) { + return this.MSG.wrongFormat(); + } + } + + @Override + public List validate() { + final List errors = new ArrayList(); + + if (SalixZone.zonesAreOverlapping(this.getSalixZones(this.table.getRecords()))) + errors.add(this.MSG.uinfo_salix_km_overlap()); + if (SalixZone.hasGaps(this.getSalixZones(this.table.getRecords()), this.minKm, this.maxKm)) + errors.add(this.MSG.uinfo_salix_km_has_gaps());// "Der Km-Bereich wird nicht vollst. abgedeckt."; + return errors; + } + + private void validateRangeOverlap() { + this.validationLabel.setText(validate().toString().replace("[", "").replace("]", "").replace(",", "")); + } +} \ No newline at end of file diff -r eedb0bcf226b -r 68ff4087b987 gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SalixZone.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/SalixZone.java Fri Jul 13 11:40:25 2018 +0200 @@ -0,0 +1,177 @@ +/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde + * Software engineering by + * Björnsen Beratende Ingenieure GmbH + * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt + * + * 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.client.shared.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; + +/** + * @author Domenico Nardi Tironi + * + */ +public class SalixZone implements Comparable { + + // IMMER ABGLEICHEN Server Client SalixZone.java + private static final String TABLE_CELL_SEPARATOR = "TABLE_CELL_SEPARATOR"; + private static final String TABLE_ROW_SEPARATOR = "TABLE_ROW_SEPARATOR"; + private final int dwsplValue; + private final double fromKm; + private final double toKm; + + private final static double DELTA = 0.0001; + + public static List parse(final String zonesRaw) { + final List resultList = new ArrayList(); + + final List results = new ArrayList(); + if (zonesRaw.contains(TABLE_ROW_SEPARATOR)) { + final String[] rows = zonesRaw.split(TABLE_ROW_SEPARATOR); + for (final String row : rows) { + if (row.contains(TABLE_CELL_SEPARATOR)) { + final String[] result = row.split(TABLE_CELL_SEPARATOR); + results.add(result); + } + } + } + for (final String[] zone : results) { + final SalixZone helper = new SalixZone(Integer.valueOf(zone[0]), Double.valueOf(zone[1]), Double.valueOf(zone[2])); + resultList.add(helper); + } + return resultList; + } + + public static SalixZone createFromTableEntry(final String dwspl, final String from, final String to) { + return new SalixZone(Integer.valueOf(dwspl), Double.valueOf(from), Double.valueOf(to)); // Error-Handling? + } + + private SalixZone(final int dwsplValue, final double fromKm, final double toKm) { + this.dwsplValue = dwsplValue; + this.fromKm = fromKm; + this.toKm = toKm; + } + + public Double getToKm() { + return this.toKm; + } + + public int getDwsplValue() { + return this.dwsplValue; + } + + public Double getFromKm() { + return this.fromKm; + } + + public static final String parseListToDataString(final List list) { + + java.util.Collections.sort(list); + final StringBuilder builder = new StringBuilder(); + for (final SalixZone zone : list) { + builder.append(zone.getDwsplValue()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getFromKm()); + builder.append(TABLE_CELL_SEPARATOR); + builder.append(zone.getToKm()); + builder.append(TABLE_ROW_SEPARATOR); + } + return builder.toString(); + } + + public static final boolean zonesAreOverlapping(final List list) { + for (final SalixZone zone : list) { + for (final SalixZone zoneOther : list) { + if (zone != zoneOther) { + final boolean overlaps = zone.overlaps(zoneOther); + if (overlaps) { + return overlaps; // cancel. only one zone has to overlap + } + } + } + } + + return false; + } + + public static final boolean hasGaps(final List list, final double lower, final double upper) { + + if (((upper - lower) > DELTA) && list.size() == 0) + return true; + + final TreeSet treeList = new TreeSet(); + treeList.addAll(list); + double lowerCompare = lower + DELTA; + for (final SalixZone zone : treeList) { + if ((zone.getUpperFromTo() - zone.getLowerFromTo()) > DELTA) { + if (zone.getLowerFromTo() > lowerCompare) { + return true; + } + lowerCompare = zone.getUpperFromTo() + DELTA; + } + } + if ((lowerCompare + DELTA) < upper) + return true; // am Ende nicht geschlossen + + return false; + } + + public Double getLowerFromTo() { + return this.fromKm < this.toKm ? this.fromKm : this.toKm; // Math. is forbidden :-( + } + + public Double getUpperFromTo() { + return this.fromKm > this.toKm ? this.fromKm : this.toKm;// Math. is forbidden :-( + } + + private boolean overlaps(final SalixZone otherZone) { + final double otherLower = otherZone.getLowerFromTo(); + final double otherUpper = otherZone.getUpperFromTo(); + + final double upper = getUpperFromTo(); + final double lower = getLowerFromTo(); + final double otherSchwerpunkt = (otherLower + otherUpper) / 2; + if ((otherUpper < upper && otherUpper > lower)) { + return true; + } else if (otherLower > lower && otherLower < upper) { + return true; + } else if (otherSchwerpunkt > (lower - DELTA) && otherSchwerpunkt < (upper + DELTA)) { + return true; + } + return false; + } + + @Override + public int compareTo(final SalixZone o) { + final int basicCompare = this.getLowerFromTo().compareTo(o.getLowerFromTo()); + if (basicCompare == 0) { + return 1; // necessary for the treeSet! + } + return basicCompare; + } + + public static boolean isValidAnschlussRange(final double fromTest, final double toTest, final List list, final double minKm) { + final SalixZone zone = new SalixZone(0, fromTest, toTest); + final double lower = zone.getLowerFromTo(); + final double anschluss = getAnschluss(list, minKm); + final double differenceAbs = (lower - anschluss) > 0 ? (lower - anschluss) : (anschluss - lower); // no Math.abs allowed :-( + if (differenceAbs > DELTA) { + return false; + } + return true; + } + + private static double getAnschluss(final List list, final double minKm) { + if (list.size() > 0) { + return list.get(list.size() - 1).getUpperFromTo(); + } + return minKm; + } +}