# HG changeset patch # User gernotbelger # Date 1538062904 -7200 # Node ID 7b4b66c7b3038972d2b7d66c36a7a23725fa2ca3 # Parent d6d5ca6d4af0ed0ab6f0f5b663f148de13a26e3b# Parent d8e753d0fdb9e773d02f10af2a8e5f2dab8e3580 Zusammenführen diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/doc/conf/jasper/templates/sinfo.floodduration.jrxml --- a/artifacts/doc/conf/jasper/templates/sinfo.floodduration.jrxml Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/doc/conf/jasper/templates/sinfo.floodduration.jrxml Thu Sep 27 17:41:44 2018 +0200 @@ -1,6 +1,6 @@ - - + + @@ -219,7 +219,7 @@ - + @@ -345,7 +345,7 @@ - + diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/doc/conf/jasper/templates/sinfo.floodduration2.jrxml --- a/artifacts/doc/conf/jasper/templates/sinfo.floodduration2.jrxml Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/doc/conf/jasper/templates/sinfo.floodduration2.jrxml Thu Sep 27 17:41:44 2018 +0200 @@ -1,6 +1,6 @@ - - + + @@ -267,7 +267,7 @@ - + @@ -481,7 +481,7 @@ - + diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/doc/conf/meta-data.xml --- a/artifacts/doc/conf/meta-data.xml Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/doc/conf/meta-data.xml Thu Sep 27 17:41:44 2018 +0200 @@ -142,10 +142,10 @@ - + + @@ -328,13 +328,13 @@ - + + @@ -348,8 +348,8 @@ - - + + @@ -465,6 +465,8 @@ + + Discharge curves @@ -1718,6 +1720,7 @@ + @@ -1742,9 +1745,12 @@ - + UINFO + + BUNDU + @@ -3527,7 +3533,7 @@ - + @@ -3775,5 +3781,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/doc/conf/themes/default.xml --- a/artifacts/doc/conf/themes/default.xml Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/doc/conf/themes/default.xml Thu Sep 27 17:41:44 2018 +0200 @@ -2971,16 +2971,9 @@ - - - - - - - - - - + + + diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/doc/conf/themes/second.xml --- a/artifacts/doc/conf/themes/second.xml Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/doc/conf/themes/second.xml Thu Sep 27 17:41:44 2018 +0200 @@ -2959,16 +2959,9 @@ - - - - - - - - - - + + + diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java Thu Sep 27 17:41:44 2018 +0200 @@ -86,7 +86,8 @@ this.missKmFrom = access.getMissingVolFrom(); this.missKmTo = access.getMissingVolTo(); - final BezugswstCalculationResults results = new BezugswstCalculationResults(calcModeLabel, user, riverInfo, access.getRange()); + final BezugswstCalculationResults results = new BezugswstCalculationResults(calcModeLabel, user, riverInfo, access.getRange(), + access.isCalculateMissingVolume()); final Calculation problems = new Calculation(); @@ -117,7 +118,7 @@ } // Compute the missing volumes - if (access.isCalculateMissingValue()) { + if (access.isCalculateMissingVolume()) { if ((bedHeightsFinder == null) || bedHeightsFinder.isNull()) return new CalculationResult(results, problems); computeMissingVolumes(problems); diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculationResults.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculationResults.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculationResults.java Thu Sep 27 17:41:44 2018 +0200 @@ -22,8 +22,16 @@ private static final long serialVersionUID = 1L; - public BezugswstCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange) { + private final boolean hasSounding; + + public BezugswstCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange, + final boolean hasSounding) { super(calcModeLabel, user, river, calcRange); + this.hasSounding = hasSounding; + } + + public boolean hasSounding() { + return this.hasSounding; } } \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstFixationFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstFixationFacet.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstFixationFacet.java Thu Sep 27 17:41:44 2018 +0200 @@ -11,6 +11,7 @@ import java.util.List; +import org.dive4elements.artifactdatabase.state.Facet; import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult; import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.WQKms; @@ -19,6 +20,8 @@ public class BezugswstFixationFacet extends FixWaterlevelFacet { + private static final long serialVersionUID = 1L; + public BezugswstFixationFacet() { } @@ -39,4 +42,14 @@ return null; } + /** Copy deeply. */ + @Override + public Facet deepCopy() { + final BezugswstFixationFacet copy = new BezugswstFixationFacet(); + copy.set(this); + copy.type = this.type; + copy.hash = this.hash; + copy.stateId = this.stateId; + return copy; + } } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstState.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstState.java Thu Sep 27 17:41:44 2018 +0200 @@ -89,19 +89,26 @@ if (!resultList.isEmpty()) { final BezugswstMainCalculationResult result = (BezugswstMainCalculationResult) resultList.get(0); - facets.add(BezugswstHeightProcessor.createChannelminFacet(context, hash, this.id, facetIndex++, 0)); - facets.add(BezugswstHeightProcessor.createBedheightFacet(context, hash, this.id, facetIndex++, 0, result.getBedHeightLabel())); + + final boolean hasSounding = results.hasSounding(); + final String nameQ = result.getWstLabel(); final String nameW = "W(" + nameQ + ")"; facets.add(new BezugswstFixationFacet(0, LONGITUDINAL_W, nameW, ComputeType.ADVANCE, hash, this.id)); facets.add(new BezugswstFixationFacet(0, LONGITUDINAL_Q, nameQ, ComputeType.ADVANCE, hash, this.id)); - for (int i = BedHeightValueType.FIELD_FIRST_INDEX; i <= BedHeightValueType.FIELD_LAST_INDEX; i++) - facets.add(BezugswstHeightProcessor.createFieldBedheightFacet(context, hash, this.id, facetIndex++, 0, i)); - facets.add(BezugswstDepthProcessor.createFlowdepthFilteredFacet(context, hash, this.id, facetIndex++, 0, result.getBedHeightLabel())); - facets.add(BezugswstDepthProcessor.createChanneldepthFacet(context, hash, this.id, facetIndex++, 0)); - for (int i = BedHeightValueType.FIELD_FIRST_INDEX; i <= BedHeightValueType.FIELD_LAST_INDEX; i++) - facets.add(BezugswstDepthProcessor.createFieldDepthFacet(context, hash, this.id, facetIndex++, 0, i)); + if (hasSounding) { + facets.add(BezugswstHeightProcessor.createChannelminFacet(context, hash, this.id, facetIndex++, 0)); + facets.add(BezugswstHeightProcessor.createBedheightFacet(context, hash, this.id, facetIndex++, 0, result.getBedHeightLabel())); + + for (int i = BedHeightValueType.FIELD_FIRST_INDEX; i <= BedHeightValueType.FIELD_LAST_INDEX; i++) + facets.add(BezugswstHeightProcessor.createFieldBedheightFacet(context, hash, this.id, facetIndex++, 0, i)); + + facets.add(BezugswstDepthProcessor.createFlowdepthFilteredFacet(context, hash, this.id, facetIndex++, 0, result.getBedHeightLabel())); + facets.add(BezugswstDepthProcessor.createChanneldepthFacet(context, hash, this.id, facetIndex++, 0)); + for (int i = BedHeightValueType.FIELD_FIRST_INDEX; i <= BedHeightValueType.FIELD_LAST_INDEX; i++) + facets.add(BezugswstDepthProcessor.createFieldDepthFacet(context, hash, this.id, facetIndex++, 0, i)); + } final Facet csv = new DataFacet(FacetTypes.CSV, "CSV data", ComputeType.ADVANCE, hash, this.id); final Facet pdf = new DataFacet(FacetTypes.PDF, "PDF data", ComputeType.ADVANCE, hash, this.id); diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduAccess.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduAccess.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduAccess.java Thu Sep 27 17:41:44 2018 +0200 @@ -72,20 +72,20 @@ } public Double getMissingVolFrom() { - if (isCalculateMissingValue()) + if (isCalculateMissingVolume()) return getDouble("ld_from_part"); else return null; } public Double getMissingVolTo() { - if (isCalculateMissingValue()) + if (isCalculateMissingVolume()) return getDouble("ld_to_part"); else return null; } - public boolean isCalculateMissingValue() { + public boolean isCalculateMissingVolume() { return getBoolean("missing_volume"); } @@ -93,7 +93,7 @@ final String data = getString("soundings"); - if (data == null || !isCalculateMissingValue()) { + if (data == null || !isCalculateMissingVolume()) { log.warn("No 'soundings' parameter specified!"); return null; } else { diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractProcessor.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractProcessor.java Thu Sep 27 17:41:44 2018 +0200 @@ -30,6 +30,8 @@ import org.dive4elements.river.exports.DiagramGenerator; import org.dive4elements.river.exports.StyledSeriesBuilder; import org.dive4elements.river.exports.process.DefaultProcessor; +import org.dive4elements.river.jfree.StripedAreaDataset; +import org.dive4elements.river.jfree.StripedAreaDataset.Stripe; import org.dive4elements.river.jfree.StyledAreaSeriesCollection; import org.dive4elements.river.jfree.StyledXYSeries; import org.dive4elements.river.themes.ThemeDocument; @@ -164,7 +166,20 @@ area.addSeries(seriesUp); area.addSeries(seriesDown); - generator.addAreaSeries(area, getAxisName(), visible); + generator.addAxisDataset(area, getAxisName(), visible); + + return null; + } + + protected final String buildStripedAreaSeries(final Stripe[] stripes, final DiagramGenerator generator, final ArtifactAndFacet bundle, + final ThemeDocument theme, final boolean visible) { + + final StripedAreaDataset dataset = new StripedAreaDataset(theme); + + for (final Stripe stripe : stripes) + dataset.addStripe(stripe); + + generator.addAxisDataset(dataset, getAxisName(), visible); return null; } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractResultType.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractResultType.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractResultType.java Thu Sep 27 17:41:44 2018 +0200 @@ -98,7 +98,7 @@ return formatter.format(value); } - private NumberFormat getFormatter(final CallContext context) { + protected NumberFormat getFormatter(final CallContext context) { final CallMeta meta = context.getMeta(); final Locale locale = Resources.getLocale(meta); diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWaterlevelFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWaterlevelFacet.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWaterlevelFacet.java Thu Sep 27 17:41:44 2018 +0200 @@ -9,51 +9,44 @@ package org.dive4elements.river.artifacts.model.fixings; import org.dive4elements.artifactdatabase.state.Facet; - import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.WQKmsResult; import org.dive4elements.river.artifacts.model.WaterlevelFacet; - import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; /** Waterlevel from fix realize compute. */ -public class FixWaterlevelFacet -extends WaterlevelFacet -{ +public class FixWaterlevelFacet extends WaterlevelFacet { public FixWaterlevelFacet() { } - public FixWaterlevelFacet(int index, String name, String description) { + public FixWaterlevelFacet(final int index, final String name, final String description) { super(index, name, description, ComputeType.ADVANCE, null, null); } - public FixWaterlevelFacet( - int index, - String name, - String description, - ComputeType type, - String hash, - String stateID - ) { + public FixWaterlevelFacet(final int index, final String name, final String description, final ComputeType type, final String hash, final String stateID) { // Note that in super, hash and stateID are on switched positions. // on super.super it is this way around again. super(index, name, description, type, stateID, hash); } @Override - protected WQKms [] getWQKms(CalculationResult res) { - FixRealizingResult fr = (FixRealizingResult)res.getData(); - return fr != null ? fr.getWQKms() : null; + protected WQKms[] getWQKms(final CalculationResult res) { + if (res.getData() instanceof WQKmsResult) { + final WQKmsResult fr = (WQKmsResult) res.getData(); + return fr != null ? fr.getWQKms() : null; + } + return null; } /** Copy deeply. */ @Override public Facet deepCopy() { - FixWaterlevelFacet copy = new FixWaterlevelFacet(); + final FixWaterlevelFacet copy = new FixWaterlevelFacet(); copy.set(this); - copy.type = type; - copy.hash = hash; - copy.stateId = stateId; + copy.type = this.type; + copy.hash = this.hash; + copy.stateId = this.stateId; return copy; } } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/services/DynamicMainValuesService.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DynamicMainValuesService.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DynamicMainValuesService.java Thu Sep 27 17:41:44 2018 +0200 @@ -61,12 +61,14 @@ throws MainValuesServiceException { // Query the gauge's daily Q values - final List qdvs = DailyDischargeValue.getValues(gauge, startTime, endTime, OrderByField.DAY); + final Date qStartTime = DateUtils.getAbflussYear(startTime)[0]; + final List qdvs = DailyDischargeValue.getValues(gauge, qStartTime, endTime, OrderByField.DAY); if (qdvs.isEmpty()) throw new MainValuesServiceException("no daily discharge values for gauge " + gauge.getName() + " in the requested time period"); // return; // Build yearly aggregates + final Date qYearEnd = DateUtils.getPreviousAbflussYear(endTime)[1]; final TDoubleArrayList mnqs = new TDoubleArrayList(); final TDoubleArrayList mqs = new TDoubleArrayList(); int mqcnt = 0; @@ -87,6 +89,8 @@ mqs.set(j, mqs.get(j) / mqcnt); j++; } + if (qdv.getDay().after(qYearEnd)) + break; // Start next year mnqs.add(qdv.getDischarge().doubleValue()); mhqs.add(qdv.getDischarge().doubleValue()); @@ -115,10 +119,12 @@ if (hsq2 != null) mainValues.add(hsq2); - // Query the gauge's daily Q values and build a list sorted by ascending Q + // Query the gauge's daily Q values from the first new year on, and build a list sorted by ascending Q final TDoubleArrayList qs = new TDoubleArrayList(); - for (final DailyDischargeValue qdv : qdvs) - qs.add(qdv.getDischarge().doubleValue()); + for (final DailyDischargeValue qdv : qdvs) { + if (qdv.getDay().compareTo(startTime) >= 0) + qs.add(qdv.getDischarge().doubleValue()); + } qs.sort(); // Step through the sorted Q list and get the duration discharges @@ -137,14 +143,22 @@ } /** - * Checks year equality of two dates (calendar year) + * Checks year equality of two dates (Abflussjahr) */ private boolean isSameQYear(final Date a, final Date b) { - final Calendar ca = Calendar.getInstance(); - ca.setTime(a); - final Calendar cb = Calendar.getInstance(); - cb.setTime(b); - return (ca.get(Calendar.YEAR) == cb.get(Calendar.YEAR)); + return (qYear(a) == qYear(b)); + } + + /** + * Gets the q year (Abflussjahr) of a date + */ + private int qYear(final Date day) { + final Calendar cal = Calendar.getInstance(); + cal.setTime(day); + if (cal.get(Calendar.MONTH) >= 10) + return cal.get(Calendar.YEAR) + 1; + else + return cal.get(Calendar.YEAR); } /** diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/services/DynamicMainValuesTimeRangeDeterminationService.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DynamicMainValuesTimeRangeDeterminationService.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DynamicMainValuesTimeRangeDeterminationService.java Thu Sep 27 17:41:44 2018 +0200 @@ -60,6 +60,10 @@ private static class GaugeInfo { protected final String errorMsg; protected final Gauge gauge; + /** + * New year of the first year for which the gauge has complete discharge data, including november+december of the year + * before + */ protected final Date startdate; protected final Date enddate; @@ -83,12 +87,13 @@ // Query the gauge's daily Q values String globalErrorMsg = ""; final List gaugeResults = new ArrayList<>(); - Date min = startTime; + final Date qStartTime = DateUtils.getAbflussYear(startTime)[0]; + Date min = qStartTime; Date max = endTime; for (final Gauge gauge : gauges) { - final Date[] gaugeDates = DailyDischargeValue.getTimePeriod(gauge, startTime, endTime); + final Date[] gaugeDates = DailyDischargeValue.getTimePeriod(gauge, qStartTime, endTime); if (gaugeDates[0] == null) { final String msg = Resources.getMsg(meta, "bundu.wst_no_data_at_all", "bundu.wst_no_data_at_all", gauge.getName()); final GaugeInfoResult.GaugeInfo gi = new GaugeInfoResult.GaugeInfo(msg, gauge, null, null); @@ -98,24 +103,26 @@ continue; } + final Date gaugeCalcStartDate = DateUtils.getNextAbflussYear(gaugeDates[0])[0]; if (gaugeDates[0].getTime() > min.getTime()) - min = gaugeDates[0]; + min = gaugeCalcStartDate; if (gaugeDates[1].getTime() < max.getTime()) max = gaugeDates[1]; String errormsg = null; - if ((gaugeDates[1].getTime() < endTime.getTime()) || (gaugeDates[0].getTime() > startTime.getTime())) - errormsg = makeDoesNotCoverErrorMsg(gaugeDates[0], gaugeDates[1], meta); + if ((gaugeDates[1].getTime() < endTime.getTime()) || (gaugeDates[0].getTime() > qStartTime.getTime())) + errormsg = makeDoesNotCoverErrorMsg(DateUtils.getAbflussYearFromDate(gaugeCalcStartDate), DateUtils.getYearFromDate(gaugeDates[1]), meta); - gaugeResults.add(new GaugeInfoResult.GaugeInfo(errormsg, gauge, gaugeDates[0], gaugeDates[1])); + gaugeResults.add(new GaugeInfoResult.GaugeInfo(errormsg, gauge, DateUtils.getNextNewYear(gaugeCalcStartDate), gaugeDates[1])); } // common Range and correct errorMsg + min = DateUtils.getNextNewYear(min); final List gaugeResultsSecondTurn = new ArrayList<>(); for (final GaugeInfoResult.GaugeInfo gi : gaugeResults) { gaugeResultsSecondTurn - .add(new GaugeInfoResult.GaugeInfo(gi.errorMsg, gi.gauge, gi.startdate != null ? min : null, gi.enddate != null ? max : null)); + .add(new GaugeInfoResult.GaugeInfo(gi.errorMsg, gi.gauge, gi.startdate != null ? min : null, gi.enddate != null ? max : null)); } if (globalErrorMsg.isEmpty() && (min.getTime() > max.getTime())) globalErrorMsg = getMsg(meta, "bundu.wst.gauge_timeranges_disjoint"); @@ -130,9 +137,9 @@ return result; } - private String makeDoesNotCoverErrorMsg(final Date start, final Date end, final CallMeta meta) { + private String makeDoesNotCoverErrorMsg(final int startYear, final int endYear, final CallMeta meta) { final String msgkey = "bundu.wst.range_does_not_cover"; - return Resources.getMsg(meta, msgkey, msgkey, DateUtils.getYearFromDate(start), DateUtils.getYearFromDate(end)); + return Resources.getMsg(meta, msgkey, msgkey, startYear, endYear); } @Override diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcFacet.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcFacet.java Thu Sep 27 17:41:44 2018 +0200 @@ -22,22 +22,22 @@ public class CollisionCalcFacet extends ResultFacet { private static final long serialVersionUID = 1; - private int year; + private String years; private CollisionCalcFacet() { super(); // required for clone operation deepCopy() } - public CollisionCalcFacet(final int facetIndex, final int resultIndex, final int year, final String name, final String description, + public CollisionCalcFacet(final int facetIndex, final int resultIndex, final String years, final String name, final String description, final String yAxisLabelKey, final ComputeType type, final String hash, final String stateId) { + super(facetIndex, resultIndex, name, description, yAxisLabelKey, type, stateId, hash); - - this.year = year; + this.years = years; } - public int getYear() { - return this.year; + public String getYears() { + return this.years; } /** Copy deeply. */ @@ -50,7 +50,7 @@ copy.type = this.type; copy.hash = this.hash; copy.stateId = this.stateId; - copy.year = this.year; + copy.years = this.years; return copy; } } \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcOverviewResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcOverviewResult.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcOverviewResult.java Thu Sep 27 17:41:44 2018 +0200 @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.List; import org.apache.commons.collections.Predicate; import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult; @@ -20,6 +21,7 @@ import org.dive4elements.river.artifacts.common.IResultType; import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource; import org.dive4elements.river.artifacts.common.ResultRow; +import org.dive4elements.river.artifacts.model.DateRange; import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType; import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; @@ -34,24 +36,31 @@ private static final String JASPER_FILE = "/jasper/templates/sinfo.collision.overview.jrxml"; - private final int[] singleYears; + private final boolean isEpochs; - public CollisionCalcOverviewResult(final String label, final int[] singleYears, final Collection rows) { + private final List years; + + public CollisionCalcOverviewResult(final String label, final boolean isEpochs, final Collection years, final Collection rows) { super(label, rows); - this.singleYears = singleYears; + this.isEpochs = isEpochs; + this.years = new ArrayList<>(years); } - public int[] getSingleYears() { - return this.singleYears; + public boolean getIsEpochs() { + return this.isEpochs; } - public double[][] getStationPointsByYear(final IResultType type, final int year) { + public List getYears() { + return this.years; + } + + public double[][] getStationPointsByYear(final IResultType type, final String years) { final Predicate filter = new Predicate() { @Override public boolean evaluate(final Object object) { final ResultRow row = (ResultRow) object; - return getSingleYears() == null || Integer.valueOf(row.getValue(SInfoResultType.years).toString()) == year; + return row.getValue(SInfoResultType.years).toString().equals(years); } }; diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcProcessor.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcProcessor.java Thu Sep 27 17:41:44 2018 +0200 @@ -60,11 +60,10 @@ protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) { final CollisionCalcFacet facet = (CollisionCalcFacet) bundle.getFacet(); - final int year = facet.getYear(); final CollisionCalcOverviewResult result = (CollisionCalcOverviewResult) getResult(generator, bundle); - final double[][] points = result.getStationPointsByYear(SInfoResultType.collisionCount, year); + final double[][] points = result.getStationPointsByYear(SInfoResultType.collisionCount, facet.getYears()); return buildSeriesForPoints(points, generator, bundle, theme, visible, null); } @@ -76,14 +75,9 @@ // result index; however name and index are used on client side as unique id. final CollisionCalcOverviewResult ccoResult = (CollisionCalcOverviewResult) result; - if (ccoResult.getSingleYears() == null) { - final String facetDescription = Resources.getMsg(context.getMeta(), I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, result.getLabel()); - return new CollisionCalcFacet(themeCount, resultIndex, -1, FACET_COLLISION_CALC_COUNT, facetDescription, I18N_AXIS_LABEL, ComputeType.ADVANCE, hash, - id); - } else { - final String facetDescription = Resources.getMsg(context.getMeta(), I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, Integer.toString(year)); - return new CollisionCalcFacet(themeCount, resultIndex, year, COLLISION_FACETS[themeCount % 3], facetDescription, I18N_AXIS_LABEL, - ComputeType.ADVANCE, hash, id); - } + final String years = CollisionCalculation.yearsToString(ccoResult.getIsEpochs(), ccoResult.getYears().get(themeCount)); + final String facetDescription = Resources.getMsg(context.getMeta(), I18N_SERIES_NAME_PATTERN, I18N_SERIES_NAME_PATTERN, years); + return new CollisionCalcFacet(themeCount, resultIndex, years, COLLISION_FACETS[themeCount % 3], facetDescription, I18N_AXIS_LABEL, + ComputeType.ADVANCE, hash, id); } } \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java Thu Sep 27 17:41:44 2018 +0200 @@ -12,7 +12,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.NavigableSet; +import java.util.TreeSet; import org.apache.commons.lang.math.DoubleRange; import org.dive4elements.artifacts.CallContext; @@ -66,14 +69,23 @@ final Collection overViewRows = new ArrayList<>(); + final List years = new ArrayList<>(); + final NavigableSet detailYears = new TreeSet<>(); if (access.getYears() != null) { - for (final int year : access.getYears()) + for (final int year : access.getYears()) { calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), year, year, false); + years.add(new DateRange(DateUtil.getStartDateFromYear(year), DateUtil.getEndDateFromYear(year))); + detailYears.add(Integer.valueOf(year)); + } } else { - for (final DateRange dr : access.getEpochs()) + for (final DateRange dr : access.getEpochs()) { calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), true); + years.add(dr); + detailYearsAdd(detailYears, dr); + } } - final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult(access.getYearsHeader(), access.getYears(), overViewRows); + final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult(access.getYearsHeader(), (access.getYears() == null), years, + overViewRows); results.addResult(overviewResult, problems); // create q-for-w-finders for all gauges of the calculation km range @@ -86,14 +98,9 @@ } final Collection detailsRows = new ArrayList<>(); - // calculate secondary results for each year or epoch - if (access.getYears() != null) { - for (final int year : access.getYears()) - calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), year, year, qFinders, zoneFinders); - } else { - for (final DateRange dr : access.getEpochs()) - calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), qFinders, zoneFinders); - } + // calculate secondary results for each year + for (final Integer year : detailYears) + calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), year, qFinders, zoneFinders); final CollisionCalcDetailResult detailResult = new CollisionCalcDetailResult("Details", detailsRows); results.addResult(detailResult, problems); @@ -101,6 +108,14 @@ } /** + * Adds all years of an epoch to a set + */ + private void detailYearsAdd(final NavigableSet detailYears, final DateRange epoch) { + for (int year = epoch.getFromYear(); year <= epoch.getToYear(); year++) + detailYears.add(Integer.valueOf(year)); + } + + /** * Calculates the collision counts for a km range of a river and a year or year range (epoch), * and adds them to a ResultRow collection */ @@ -108,19 +123,32 @@ final int toYear, final boolean isEpoch) { for (final CollisionAggregateValue aggregate : CollisionAggregateValue.getValuesByKm(river, fromKm, toKm, fromYear, toYear)) { rows.add(ResultRow.create().putValue(GeneralResultType.station, aggregate.getStation()) - .putValue(SInfoResultType.years, (isEpoch ? String.format("%d-%d", fromYear, toYear) : Integer.toString(fromYear))) + .putValue(SInfoResultType.years, yearsToString(isEpoch, fromYear, toYear)) .putValue(SInfoResultType.collisionCount, aggregate.getCount())); } } /** - * Calculates the collision details for a km range of a river and a year or year range (epoch), - * and adds them to a ResultRow collection + * Returns the string representation of a year or epoch + */ + public static String yearsToString(final boolean isEpoch, final DateRange years) { + return yearsToString(isEpoch, years.getFromYear(), years.getToYear()); + } + + /** + * Returns the string representation of a year or epoch + */ + public static String yearsToString(final boolean isEpoch, final int fromYear, final int toYear) { + return (isEpoch ? String.format("%d-%d", fromYear, toYear) : Integer.toString(fromYear)); + } + + /** + * Calculates the collision details for a km range of a river and a year, and adds them to a ResultRow collection */ private void calculateDetails(final Collection rows, final RiverInfoProvider riverInfo, final double fromKm, final double toKm, - final int fromYear, final int toYear, final Map qFinders, final Map zoneFinders) { - for (final CollisionValue collision : CollisionValue.getValues(riverInfo.getRiver(), fromKm, toKm, DateUtil.getStartDateFromYear(fromYear), - DateUtil.getEndDateFromYear(toYear))) { + final int year, final Map qFinders, final Map zoneFinders) { + for (final CollisionValue collision : CollisionValue.getValues(riverInfo.getRiver(), fromKm, toKm, DateUtil.getStartDateFromYear(year), + DateUtil.getEndDateFromYear(year))) { final Gauge gauge = riverInfo.getGauge(collision.getStation(), true); final double q = qFinders.get(gauge).getDischarge(collision.getGaugeW()); final double qOut = Double.isInfinite(q) ? Double.NaN : q; diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionState.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionState.java Thu Sep 27 17:41:44 2018 +0200 @@ -18,6 +18,7 @@ import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.model.DateRange; import org.dive4elements.river.artifacts.model.EmptyFacet; import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.ReportFacet; @@ -81,15 +82,8 @@ for (int index = 0; index < resultList.size(); index++) { if (resultList.get(index) instanceof CollisionCalcOverviewResult) { final CollisionCalcOverviewResult result = (CollisionCalcOverviewResult) resultList.get(index); - - final int[] singleYears = result.getSingleYears(); - - if (singleYears == null) - facets.add(CollisionCalcProcessor.createFacet(context, hash, this.id, result, index, -1, themeCount++)); - else { - for (final int singleYear : singleYears) - facets.add(CollisionCalcProcessor.createFacet(context, hash, this.id, result, index, singleYear, themeCount++)); - } + for (final DateRange dr : result.getYears()) + facets.add(CollisionCalcProcessor.createFacet(context, hash, this.id, result, index, dr.getFromYear(), themeCount++)); } } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/SInfoResultType.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/SInfoResultType.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/SInfoResultType.java Thu Sep 27 17:41:44 2018 +0200 @@ -12,6 +12,7 @@ import java.text.NumberFormat; import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.artifacts.common.AbstractResultType; import org.dive4elements.river.artifacts.common.I18NStrings; @@ -30,6 +31,8 @@ private static final long serialVersionUID = 1L; + protected static Logger log = Logger.getLogger(SInfoResultType.class); + protected SInfoResultType(final String unit, final String csvHeader) { super(unit, csvHeader, csvHeader); } @@ -209,6 +212,15 @@ @Override public String exportValue(final CallContext context, final Object value) { final double doubleValue = asDouble(value); + String rm; + try { + rm = getFormatter(context).getRoundingMode().toString(); + } + catch (final Exception e) { + rm = "?"; + } + log.trace(String.format("meanBedHeight.exportValue roundingmode: %s value: %f doubleValue: %f formatted to: %s", + rm, value, doubleValue, exportDoubleValue(context, doubleValue))); return exportDoubleValue(context, doubleValue); } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 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 Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResult.java Thu Sep 27 17:41:44 2018 +0200 @@ -55,6 +55,8 @@ private static final long serialVersionUID = 1L; + private final boolean isUseWspl; + private final String[] waterlevelLabels; private final int maxWaterlevelPdf = 3; @@ -67,9 +69,10 @@ pdf, csv } - public FloodDurationCalculationResult(final String label, final String[] mainvalueLabels, final Collection rows) { + public FloodDurationCalculationResult(final String label, final String[] mainvalueLabels, final Collection rows, final boolean isUseWspl) { super(label, rows); this.waterlevelLabels = mainvalueLabels; + this.isUseWspl = isUseWspl; } /** @@ -112,7 +115,7 @@ protected String[] formatRow(final AbstractExportContext exportContextCSV, final ResultRow row, final ExportMode mode) { - final Collection lines = new ArrayList<>(10); + final Collection lines = new ArrayList<>(20); lines.add(exportContextCSV.formatRowValue(row, GeneralResultType.station)); lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.riverside)); @@ -122,25 +125,33 @@ lines.add(exportContextCSV.formatRowValue(row, SInfoResultType.infrastructuretype)); final List waterlevelList = (List) row.getValue(SInfoResultType.customMultiRowColWaterlevel); - if (waterlevelList != null) { - final NumberFormat wFormatter = exportContextCSV.getFlowDepthFormatter(); - final NumberFormat qFormatter = exportContextCSV.getQFormatter(); - final NumberFormat durFormatter = exportContextCSV.getFloodDurationFormatter(); - - for (int i = 0; i < waterlevelList.size(); i++) { - if (i == this.maxWaterlevelPdf && mode == ExportMode.pdf) - break; + final int expectedSizetoGaugelabel = lines.size() + (waterlevelList.size() < 2 ? 4 : 12); // removing columns only works for fixed + // indices - final DurationWaterlevel item = waterlevelList.get(i); - lines.add(item.getWFormatted(wFormatter)); - lines.add(item.getFloodDurDaysPerYearFormatted(durFormatter)); - lines.add(item.getQFormatted(qFormatter)); - lines.add(item.getBezeichnung()); - } + final NumberFormat wFormatter = exportContextCSV.getFlowDepthFormatter(); + final NumberFormat qFormatter = exportContextCSV.getQFormatter(); + final NumberFormat durFormatter = exportContextCSV.getFloodDurationFormatter(); + + for (int i = 0; i < waterlevelList.size(); i++) { + + if (i == this.maxWaterlevelPdf && mode == ExportMode.pdf) + break; + + final DurationWaterlevel item = waterlevelList.get(i); + lines.add(item.getWFormatted(wFormatter)); + lines.add(item.getFloodDurDaysPerYearFormatted(durFormatter)); + lines.add(item.getQFormatted(qFormatter)); + lines.add(item.getBezeichnung()); } - lines.add(exportContextCSV.formatRowValue(row, GeneralResultType.gaugeLabel)); + final int lineSize = lines.size(); + while (mode == ExportMode.pdf && lines.size() < expectedSizetoGaugelabel) + lines.add(""); + + if (isUseWspl() || mode == ExportMode.pdf) + lines.add(exportContextCSV.formatRowValue(row, GeneralResultType.gaugeLabel)); // PDF: necessary, because if removed, location would not be shown! + lines.add(exportContextCSV.formatRowValue(row, GeneralResultType.location)); return lines.toArray(new String[lines.size()]); @@ -169,7 +180,9 @@ header.add(exportContextCSV.msg(DurationWaterlevel.getHeaderBezeichnCsv(), appendIndex)); } - header.add(exportContextCSV.formatCsvHeader(GeneralResultType.gaugeLabel)); + if (isUseWspl()) + header.add(exportContextCSV.formatCsvHeader(GeneralResultType.gaugeLabel)); + header.add(exportContextCSV.formatCsvHeader(GeneralResultType.location)); exportContextCSV.writeCSVLine(header.toArray(new String[header.size()])); @@ -265,4 +278,8 @@ return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() }; } + + public boolean isUseWspl() { + return this.isUseWspl; + } } \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 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 Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java Thu Sep 27 17:41:44 2018 +0200 @@ -66,8 +66,8 @@ /** * Calculate the infrastructures flood duration result rows */ - public void execute(final Calculation problems, final String label, final DoubleRange calcRange, final RiversideChoiceKey riverside, - final boolean withWspl, final WINFOArtifact winfo, final FloodDurationCalculationResults results) { + public void execute(final Calculation problems, final String label, final DoubleRange calcRange, final RiversideChoiceKey riverside, final boolean withWspl, + final WINFOArtifact winfo, final FloodDurationCalculationResults results) { // Find all gauges of the calc range, and create the duration finders final Map durFinders = new HashMap<>(); @@ -121,7 +121,7 @@ for (int i = 0; i <= wqkmsArray.length - 1; i++) wstLabels[i] = wqkmsArray[i].getName(); - results.addResult(new FloodDurationCalculationResult(label, wstLabels, this.rows), problems); + results.addResult(new FloodDurationCalculationResult(label, wstLabels, this.rows, withWspl), problems); } /** @@ -141,12 +141,14 @@ final double[] ows = new double[udays.length]; for (int i = 0, j = udays.length - 1; i <= udays.length - 1; i++, j--) { odays[j] = 365 - udays[i]; - oqs[j] = qs[i]; final QPosition qpos = wst.getQPosition(gauge.getStation().doubleValue(), qs[i]); - if (qpos != null) + if (qpos != null) { ows[j] = wst.interpolateW(station, qpos, problems); - else + oqs[j] = wst.getQ(qpos, station); + } else { ows[j] = Double.NaN; + oqs[j] = qs[i]; + } } return new WQDay(odays, ows, oqs); } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationExporter.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationExporter.java Thu Sep 27 17:41:44 2018 +0200 @@ -75,5 +75,8 @@ design.removeColumn("bezOpt"); design.removeColumn("durOpt"); } + + if (!result.isUseWspl()) + design.removeColumn("gauge_header"); } } \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java Thu Sep 27 17:41:44 2018 +0200 @@ -167,16 +167,18 @@ row.putValue(UInfoResultType.waterlevelMH5, hw5); // Calc salix-line and mw-mnw - row.putValue(UInfoResultType.salixline, calcSalix(mhw, mw)); + row.putValue(UInfoResultType.salixline, calcSalix(mhw, mw, 0.0)); row.putValue(UInfoResultType.salix_mw_mnw, calcMwmnw(mw, mnw)); - row.putValue(UInfoResultType.salixw, mhw - SALIX_DISTANCE.doubleValue()); + final double salixw = Formatter.roundW(mhw).subtract(SALIX_DISTANCE).doubleValue(); + row.putValue(UInfoResultType.salixw, salixw); // Calc scenario values (always all scenario types set, Result variant extracts the fields needed) final List scenarios = new ArrayList<>(); final List deltaws = getDeltaWs(station, rangeScenarios); for (final Double deltaw : deltaws) { if (deltaw != null) { - final double salix = calcSalix(mhw, mw + deltaw); - scenarios.add(new SalixScenario((int) (deltaw * 100), salix, mhw + deltaw - SALIX_DISTANCE.doubleValue())); + final double salix = calcSalix(mhw, mw, deltaw.doubleValue()); + final double scen = calcSalix(mhw, 0.0, deltaw.doubleValue()); + scenarios.add(new SalixScenario((int) (deltaw * 100), salix, scen)); } else { scenarios.add(null); @@ -199,10 +201,10 @@ /** * Calculates the salix value */ - private double calcSalix(final double mhw, final double mw) { + private double calcSalix(final double mhw, final double mw, final double deltamw) { if (Double.isNaN(mw) || Double.isInfinite(mw) || Double.isNaN(mhw) || Double.isInfinite(mhw)) - return mw; // preserving NaN or Infinity - return Formatter.roundW(mhw).subtract(SALIX_DISTANCE).subtract(Formatter.roundW(mw)).doubleValue(); + return mhw - mw; // preserving NaN or Infinity + return Formatter.roundW(mhw).subtract(SALIX_DISTANCE).subtract(Formatter.roundW(mw).add(Formatter.roundW(deltamw))).doubleValue(); } /** diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineProcessor.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineProcessor.java Thu Sep 27 17:41:44 2018 +0200 @@ -10,14 +10,14 @@ package org.dive4elements.river.artifacts.uinfo.salix; +import java.awt.Color; 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.D4EArtifact; -import org.dive4elements.river.artifacts.access.RangeAccess; +import org.dive4elements.artifacts.CallMeta; import org.dive4elements.river.artifacts.common.AbstractProcessor; import org.dive4elements.river.artifacts.model.CrossSectionWaterLineFacet; import org.dive4elements.river.artifacts.model.FacetTypes; @@ -26,6 +26,7 @@ import org.dive4elements.river.artifacts.uinfo.common.UInfoResultType; import org.dive4elements.river.artifacts.uinfo.salix.SalixLineCrossSectionIndexData.SalixWaterlevel; import org.dive4elements.river.exports.DiagramGenerator; +import org.dive4elements.river.jfree.StripedAreaDataset.Stripe; import org.dive4elements.river.themes.ThemeDocument; /** @@ -167,9 +168,6 @@ @Override protected String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) { - - // log.debug("Processing facet: " + bundle.getFacetName()); - if (bundle.getFacetName().equals(FACET_SALIX_SCENARIO_FILTERED) || bundle.getFacetName().equals(FACET_SALIX_SCENARIO_RAW)) { final CallContext context = generator.getContext(); final SalixLineCalculationResult data = (SalixLineCalculationResult) bundle.getData(context); @@ -179,19 +177,24 @@ } if (bundle.getFacetName().equals(FACET_SALIX_RANK)) { - final RangeAccess kmRange = new RangeAccess((D4EArtifact) bundle.getArtifact()); - // TODO get all rank data (5 ranks) from database - final double[][] points = new double[2][2]; - points[0][0] = kmRange.getLowerKm(); - points[0][1] = kmRange.getUpperKm(); - points[1][0] = 1.5; - points[1][1] = 1.5; - return buildSeriesForPoints(points, generator, bundle, theme, visible, null); + final CallMeta meta = generator.getContext().getMeta(); + final Stripe[] stripes = new Stripe[] { // + new Stripe(getSimpleMsg("uinfo_salix_rank.excellent", meta), Color.decode("#00B0F0"), -0.3, 0.3), // + new Stripe(getSimpleMsg("uinfo_salix_rank.good", meta), Color.decode("#00B050"), 0.3, 0.5), // + new Stripe(getSimpleMsg("uinfo_salix_rank.moderate", meta), Color.decode("#FFFF00"), 0.5, 1.0), // + new Stripe(getSimpleMsg("uinfo_salix_rank.bad", meta), Color.decode("#FFC000"), 1.0, 1.5), // + new Stripe(getSimpleMsg("uinfo_salix_rank.very_bad", meta), Color.decode("#FF0000"), 1.5, Double.NaN) }; + + return buildStripedAreaSeries(stripes, generator, bundle, theme, visible); } return buildSeriesForType(generator, bundle, theme, visible, doGetType(bundle.getFacetName()), GAP_DISTANCE); } + private String getSimpleMsg(final String code, final CallMeta meta) { + return Resources.getMsg(meta, code); + } + protected UInfoResultType doGetType(final String facetName) { if (FACET_SALIX_LINE_FILTERED.contentEquals(facetName)) diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixScenario.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixScenario.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixScenario.java Thu Sep 27 17:41:44 2018 +0200 @@ -58,11 +58,11 @@ return this.salixW; } - public String getSalixWFormatted() { + public String getSalixWFormatted(final NumberFormat formatter) { if (Double.isNaN(this.salixW)) return StringUtils.EMPTY; - return String.valueOf(this.salixW); + return formatter.format(this.salixW); } public static final String getScenarioValueHeader() { diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/exports/AbstractChartGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/AbstractChartGenerator.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/AbstractChartGenerator.java Thu Sep 27 17:41:44 2018 +0200 @@ -12,11 +12,7 @@ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; -import java.awt.Paint; import java.awt.Stroke; -import java.awt.TexturePaint; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.text.DateFormat; @@ -38,7 +34,6 @@ import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Settings; import org.dive4elements.artifacts.Artifact; -import org.dive4elements.artifacts.ArtifactCollection; import org.dive4elements.artifacts.ArtifactNamespaceContext; import org.dive4elements.artifacts.CallContext; import org.dive4elements.artifacts.CallMeta; @@ -56,12 +51,10 @@ import org.dive4elements.river.jfree.DoubleBounds; import org.dive4elements.river.jfree.EnhancedLineAndShapeRenderer; import org.dive4elements.river.jfree.RiverAnnotation; -import org.dive4elements.river.jfree.StableXYDifferenceRenderer; import org.dive4elements.river.jfree.Style; -import org.dive4elements.river.jfree.StyledAreaSeriesCollection; import org.dive4elements.river.jfree.StyledSeries; +import org.dive4elements.river.jfree.StyledXYDataset; import org.dive4elements.river.themes.ThemeDocument; -import org.dive4elements.river.utils.Formatter; import org.jfree.chart.JFreeChart; import org.jfree.chart.LegendItem; import org.jfree.chart.LegendItemCollection; @@ -478,7 +471,7 @@ addMetadataSubtitle(chart); /* add the real chart title, but as subtitle after the metadata */ - final String chartTitle = getChartTitle(this.context); + final String chartTitle = getChartTitle(this.context); if (chartTitle != null) { final TextTitle title = new TextTitle(chartTitle, JFreeChart.DEFAULT_TITLE_FONT); chart.addSubtitle(title); @@ -487,7 +480,6 @@ addSubtitles(this.context, chart); } - /** * Adds a metadata sub-title to the chart if it gets exported */ @@ -503,7 +495,7 @@ final TextTitle subtitle = new TextTitle(text, titleFont); subtitle.setHorizontalAlignment(HorizontalAlignment.LEFT); - subtitle.setMargin(new RectangleInsets(10,10,10,10)); + subtitle.setMargin(new RectangleInsets(10, 10, 10, 10)); chart.addSubtitle(subtitle); } @@ -517,9 +509,6 @@ return Collections.emptyList(); } - final CollectionCallContext ccc = (CollectionCallContext) this.context; - final ArtifactCollection collection = ccc.getCollection(); - final List subtitles = new ArrayList<>(); /* version */ @@ -817,7 +806,7 @@ plot.setDataset(datasetIndex, dataset); plot.mapDatasetToRangeAxis(datasetIndex, axisIndex); - applyThemes(plot, dataset, datasetIndex, axisDataset.isArea(dataset)); + applyThemes(plot, dataset, datasetIndex); datasetIndex++; } @@ -839,18 +828,21 @@ protected abstract NumberAxis createYAxis(final int index); /** - * @param idx + * @param datasetIndex * "index" of dataset/series (first dataset to be drawn has * index 0), correlates with renderer index. * @param isArea * true if the series describes an area and shall be rendered * as such. */ - private void applyThemes(final XYPlot plot, final XYDataset series, final int idx, final boolean isArea) { - if (isArea) - applyAreaTheme(plot, (StyledAreaSeriesCollection) series, idx); + private void applyThemes(final XYPlot plot, final XYDataset dataset, final int datasetIndex) { + + final Font legendFont = createLegendLabelFont(); + + if (dataset instanceof StyledXYDataset) + ((StyledXYDataset) dataset).applyTheme(this.context.getMeta(), plot, datasetIndex, legendFont); else - applyLineTheme(plot, series, idx); + applyLineTheme(plot, dataset, datasetIndex, legendFont); } /** @@ -883,12 +875,8 @@ * @return a new instance of EnhancedLineAndShapeRenderer. */ private XYLineAndShapeRenderer createRenderer(final XYPlot plot, final int idx) { - log.debug("Create EnhancedLineAndShapeRenderer for idx: " + idx); - final EnhancedLineAndShapeRenderer r = new EnhancedLineAndShapeRenderer(true, false); - r.setPlot(plot); - return r; } @@ -903,15 +891,14 @@ * The XYDataset which needs to support Series objects. * @param idx * The index of the renderer / dataset. + * @param legendFont2 */ - private void applyLineTheme(final XYPlot plot, final XYDataset dataset, final int idx) { + private void applyLineTheme(final XYPlot plot, final XYDataset dataset, final int idx, final Font legendFont) { log.debug("Apply LineTheme for dataset at index: " + idx); final LegendItemCollection lic = new LegendItemCollection(); final LegendItemCollection anno = plot.getFixedLegendItems(); - final Font legendFont = createLegendLabelFont(); - final XYLineAndShapeRenderer renderer = createRenderer(plot, idx); for (int s = 0, num = dataset.getSeriesCount(); s < num; s++) { @@ -951,64 +938,6 @@ plot.setRenderer(idx, renderer); } - /** - * @param plot - * The plot. - * @param area - * A StyledAreaSeriesCollection object. - * @param idx - * The index of the dataset. - */ - private final void applyAreaTheme(final XYPlot plot, final StyledAreaSeriesCollection area, final int idx) { - final LegendItemCollection lic = new LegendItemCollection(); - final LegendItemCollection anno = plot.getFixedLegendItems(); - - final Font legendFont = createLegendLabelFont(); - - log.debug("Registering an 'area'renderer at idx: " + idx); - - final StableXYDifferenceRenderer dRenderer = new StableXYDifferenceRenderer(); - - if (area.getMode() == StyledAreaSeriesCollection.FILL_MODE.UNDER) { - dRenderer.setPositivePaint(createTransparentPaint()); - } - - plot.setRenderer(idx, dRenderer); - - area.applyTheme(dRenderer); - - // i18n - dRenderer.setAreaLabelNumberFormat(Formatter.getFormatter(this.context.getMeta(), 2, 4)); - - dRenderer.setAreaLabelTemplate(Resources.getMsg(this.context.getMeta(), "area.label.template", "Area=%sm2")); - - final LegendItem legendItem = dRenderer.getLegendItem(idx, 0); - if (legendItem != null) { - legendItem.setLabelFont(legendFont); - lic.add(legendItem); - } else { - log.warn("Could not get LegentItem for renderer: " + idx + ", series-idx " + 0); - } - - if (anno != null) { - lic.addAll(anno); - } - - plot.setFixedLegendItems(lic); - } - - /** - * Returns a transparently textured paint. - * - * @return a transparently textured paint. - */ - private static Paint createTransparentPaint() { - // TODO why not use a transparent color? - final BufferedImage texture = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR); - - return new TexturePaint(texture, new Rectangle2D.Double(0d, 0d, 0d, 0d)); - } - private void preparePDFContext(final CallContext context) { final int[] dimension = getExportDimension(); @@ -1069,21 +998,27 @@ final Bounds[] xyBounds = ChartHelper.getBounds(dataset); - if (xyBounds == null) { - log.warn("Skip XYDataset for Axis (invalid ranges): " + idx); - return; - } + // if (xyBounds == null) { + // log.warn("Skip XYDataset for Axis (invalid ranges): " + idx); + // return; + // } if (visible) { if (log.isDebugEnabled()) { log.debug("Add new AxisDataset at index: " + idx); - log.debug("X extent: " + xyBounds[0]); - log.debug("Y extent: " + xyBounds[1]); + if (xyBounds != null) { + log.debug("X extent: " + xyBounds[0]); + log.debug("Y extent: " + xyBounds[1]); + } } axisDataset.addDataset(dataset); } + /* No range merging, for areas extending to infinity this causes problems. */ + if (xyBounds == null || StyledSeriesBuilder.isBigDoubleValue(xyBounds[1].getLower()) || StyledSeriesBuilder.isBigDoubleValue(xyBounds[1].getLower())) + return; + combineXBounds(xyBounds[0], 0); combineYBounds(xyBounds[1], idx); } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java Thu Sep 27 17:41:44 2018 +0200 @@ -37,7 +37,6 @@ import org.dive4elements.river.jfree.Bounds; import org.dive4elements.river.jfree.DoubleBounds; import org.dive4elements.river.jfree.RiverAnnotation; -import org.dive4elements.river.jfree.StyledAreaSeriesCollection; import org.dive4elements.river.jfree.XYMetaSeriesCollection; import org.dive4elements.river.themes.ThemeDocument; import org.jfree.chart.ChartFactory; @@ -51,7 +50,6 @@ import org.jfree.chart.plot.Marker; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.title.TextTitle; import org.jfree.data.Range; import org.jfree.data.general.Series; import org.jfree.data.xy.XYDataset; @@ -442,67 +440,6 @@ } /** - * Registers an area to be drawn. - * @param area Area to be drawn. - * @param axisName Name of the axis. - * @param visible Whether or not to be visible - * (important for range calculations). - */ - public void addAreaSeries( - StyledAreaSeriesCollection area, - String axisName, - boolean visible - ) { - addAreaSeries(area, diagramAttributes.getAxisIndex(axisName), visible); - } - - /** - * Registers an area to be drawn. - * @param area Area to be drawn. - * @param index 'axis index' - * @param visible Whether or not to be visible - * (important for range calculations). - */ - public void addAreaSeries( - StyledAreaSeriesCollection area, - int index, - boolean visible - ) { - if (area == null) { - log.warn("Cannot yet render above/under curve."); - return; - } - - AxisDataset axisDataset = (AxisDataset) getAxisDataset(index); - - Bounds[] xyBounds = ChartHelper.getBounds(area); - - if (xyBounds == null) { - log.warn("Skip XYDataset for Axis (invalid ranges): " + index); - return; - } - - - if (visible) { - if (log.isDebugEnabled()) { - log.debug("Add new AxisDataset at index: " + index); - log.debug("X extent: " + xyBounds[0]); - log.debug("Y extent: " + xyBounds[1]); - } - - axisDataset.addArea(area); - } - - /* No range merging, for areas extending to infinity this causes problems. */ - /* No range merging, for areas extending to infinity this causes problems. */ - if( StyledSeriesBuilder.isBigDoubleValue( xyBounds[1].getLower() ) || StyledSeriesBuilder.isBigDoubleValue( xyBounds[1].getLower() ) ) - return; - - combineXBounds(xyBounds[0], 0); - combineYBounds(xyBounds[1], index); - } - - /** * Add given series if visible, if not visible adjust ranges (such that * all points in data would be plotted once visible). * @param series the data series to include in plot. @@ -1134,7 +1071,7 @@ } protected final String getDefaultYAxisLabel(String axisName) { - Set labelSet = axesLabels.get(diagramAttributes.getAxisIndex(axisName)); + Set labelSet = axesLabels.get(diagramAttributes.getAxisIndex(axisName)); log.debug("Labels for axis: " + labelSet); if (labelSet != null && !labelSet.isEmpty()) { String label = StringUtils.join(labelSet, ", "); diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/exports/LegendProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/LegendProcessor.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/LegendProcessor.java Thu Sep 27 17:41:44 2018 +0200 @@ -19,25 +19,23 @@ import org.jfree.chart.LegendItemCollection; import org.jfree.chart.plot.XYPlot; - /** Class to process Plots legends. */ public abstract class LegendProcessor { /** (Empty) shape for aggregated Legend Items. */ - private static final Line2D.Double SPACE = new Line2D.Double(0,0,0,0); - + private static final Line2D.Double SPACE = new Line2D.Double(0, 0, 0, 0); /** Prevent instantiations. */ private LegendProcessor() { } - /** * Create a hash from a legenditem. * This hash can then be used to merge legend items labels. + * * @return hash for given legenditem to identify mergeables. */ - protected static String legendItemHash(LegendItem li) { + protected static String legendItemHash(final LegendItem li) { // TODO Do proper implementation. // Ensure that only mergable sets are created. // getFillPaint() @@ -55,46 +53,52 @@ // boolean isShapeFilled() // boolean isShapeOutlineVisible() // boolean isShapeVisible() - String hash = li.getLinePaint().toString(); + final String hash = li.getLinePaint().toString(); // XXX: DEAD CODE // String label = li.getLabel(); - /*if (label.startsWith("W (") || label.startsWith("W(")) { - hash += "-W-"; - } - else if (label.startsWith("Q(") || label.startsWith("Q (")) { - hash += "-Q-"; - }*/ + /* + * if (label.startsWith("W (") || label.startsWith("W(")) { + * hash += "-W-"; + * } + * else if (label.startsWith("Q(") || label.startsWith("Q (")) { + * hash += "-Q-"; + * } + */ // WQ.java holds example of using regex Matcher/Pattern. return hash; } - /** * Create new legend entries, dependent on settings. - * @param plot The plot for which to modify the legend. - * @param threshold How many items are needed for aggregation to - * be triggered? + * + * @param plot + * The plot for which to modify the legend. + * @param threshold + * How many items are needed for aggregation to + * be triggered? */ - public static void aggregateLegendEntries(XYPlot plot, int threshold) { - LegendItemCollection old = plot.getLegendItems(); + public static void aggregateLegendEntries(final XYPlot plot, final int threshold) { + final LegendItemCollection old = plot.getLegendItems(); // Find "similar" entries if aggregation is enabled. int maxListSize = 0; - int AGGR_THRESHOLD = threshold; + final int AGGR_THRESHOLD = threshold; - if (AGGR_THRESHOLD > old.getItemCount() || AGGR_THRESHOLD <= 0){ + if (AGGR_THRESHOLD > old.getItemCount() || AGGR_THRESHOLD <= 0) { return; } - HashMap> entries = - new LinkedHashMap>(); - for (Iterator i = old.iterator(); i.hasNext();) { - LegendItem item = i.next(); - String hash = legendItemHash(item); + final HashMap> entries = new LinkedHashMap<>(); + // for (Iterator i = old.iterator(); i.hasNext();) { + + final Iterator iterator = old.iterator(); + while (iterator.hasNext()) { + final LegendItem item = iterator.next(); + final String hash = legendItemHash(item); List itemList = entries.get(hash); if (itemList == null) { - itemList = new ArrayList(); + itemList = new ArrayList<>(); entries.put(hash, itemList); } itemList.add(item); @@ -111,8 +115,8 @@ // Run over collected entries, merge their names and create new // entry if needed. - LegendItemCollection newLegend = new LegendItemCollection(); - for (List itemList: entries.values()) { + final LegendItemCollection newLegend = new LegendItemCollection(); + for (final List itemList : entries.values()) { if (itemList.size() >= AGGR_THRESHOLD) { // Now do merging. // XXX: DEAD CODE // LegendItem item = itemList.get(0); @@ -124,41 +128,26 @@ // to prevent "overfill" of legenditemblock. for (int i = 0, I = itemList.size(); i < I; i++) { if (i != 0) { - LegendItem litem = itemList.get(i); + final LegendItem litem = itemList.get(i); // Make shape and line really small. - LegendItem merged = new LegendItem( - "," + litem.getLabel(), - litem.getDescription(), - litem.getToolTipText(), - litem.getURLText(), - false, - SPACE, - false, - litem.getFillPaint(), - false, - litem.getOutlinePaint(), - litem.getOutlineStroke(), - false, - SPACE, - litem.getLineStroke(), - litem.getLinePaint()); + final LegendItem merged = new LegendItem("," + litem.getLabel(), litem.getDescription(), litem.getToolTipText(), litem.getURLText(), + false, SPACE, false, litem.getFillPaint(), false, litem.getOutlinePaint(), litem.getOutlineStroke(), false, SPACE, + litem.getLineStroke(), litem.getLinePaint()); newLegend.add(merged); - } - else { + } else { newLegend.add(itemList.get(i)); } } - } - else { + } else { // Do not merge entries. - for (LegendItem li: itemList) { + for (final LegendItem li : itemList) { newLegend.add(li); } } } - plot.setFixedLegendItems (newLegend); + plot.setFixedLegendItems(newLegend); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java Thu Sep 27 17:41:44 2018 +0200 @@ -392,7 +392,7 @@ AxisDataset axisDataset = (AxisDataset) getAxisDataset(index); if (visible) { - axisDataset.addArea(area); + axisDataset.addDataset(area); } else { /* No range merging, for areas extending to infinity this diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/exports/process/AreaProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/AreaProcessor.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/AreaProcessor.java Thu Sep 27 17:41:44 2018 +0200 @@ -129,7 +129,7 @@ ? upperFacetName : lowerFacetName; /* Decide axis name based on facet name */ - generator.addAreaSeries(area, + generator.addAxisDataset(area, axisNameForFacet(facetNameForAxis), visible); } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/exports/process/DeltaWProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/DeltaWProcessor.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/DeltaWProcessor.java Thu Sep 27 17:41:44 2018 +0200 @@ -213,7 +213,7 @@ area.addSeries(upper); area.addSeries(lower); - generator.addAreaSeries(area, axisName, visible); + generator.addAxisDataset(area, axisName, visible); } protected void doReferenceDeviationOut( @@ -255,7 +255,7 @@ marker.setStroke(new BasicStroke(2)); marker.setPaint(Color.BLACK); generator.addValueMarker(marker); - generator.addAreaSeries(area, axisName, visible); + generator.addAxisDataset(area, axisName, visible); } @Override diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWAProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWAProcessor.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWAProcessor.java Thu Sep 27 17:41:44 2018 +0200 @@ -66,7 +66,7 @@ area.addSeries(seriesUp); area.addSeries(seriesDown); area.setMode(StyledAreaSeriesCollection.FILL_MODE.BETWEEN); - generator.addAreaSeries(area, axisName, visible); + generator.addAxisDataset(area, axisName, visible); } } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWProcessor.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FixDeltaWProcessor.java Thu Sep 27 17:41:44 2018 +0200 @@ -66,7 +66,7 @@ area.addSeries(seriesUp); area.addSeries(seriesDown); area.setMode(StyledAreaSeriesCollection.FILL_MODE.BETWEEN); - generator.addAreaSeries(area, axisName, visible); + generator.addAxisDataset(area, axisName, visible); } } diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java Thu Sep 27 17:41:44 2018 +0200 @@ -101,7 +101,7 @@ area.addSeries(seriesUp); area.addSeries(seriesDown); area.setMode(StyledAreaSeriesCollection.FILL_MODE.BETWEEN); - generator.addAreaSeries(area, axisName, visible); + generator.addAxisDataset(area, axisName, visible); } if (bundle.getFacetName().equals(FacetTypes.LONGITUDINAL_W) diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/java2d/ShapeUtils.java --- a/artifacts/src/main/java/org/dive4elements/river/java2d/ShapeUtils.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/java2d/ShapeUtils.java Thu Sep 27 17:41:44 2018 +0200 @@ -8,6 +8,7 @@ package org.dive4elements.river.java2d; +import java.awt.Color; import java.awt.Shape; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; @@ -24,7 +25,7 @@ private static Map scaledShapesCache = new HashMap<>(); - private static final Shape createCross(float size) { + private static final Shape createCross(final float size) { final GeneralPath p = new GeneralPath(); @@ -38,15 +39,15 @@ return p; } - private static Shape createBox(float size) { + private static Shape createBox(final float size) { return new Rectangle2D.Double(-size, -size, size * 2, size * 2); } - private static Shape createCircle(float size) { + private static Shape createCircle(final float size) { return new Ellipse2D.Float(-size, -size, size * 2, size * 2); } - private static final Shape createTriangle(float size) { + private static final Shape createTriangle(final float size) { final GeneralPath p = new GeneralPath(); p.moveTo(-size, size); @@ -57,7 +58,7 @@ return new Area(p); } - public static synchronized Shape getScaledShape(final ShapeType type, float size) { + public static synchronized Shape getScaledShape(final ShapeType type, final float size) { final Long hash = Long.valueOf((((long) type.ordinal()) << 32) | Float.floatToIntBits(size)); @@ -70,7 +71,7 @@ return newShape; } - private static Shape createScaledShape(ShapeType type, float size) { + private static Shape createScaledShape(final ShapeType type, final float size) { switch (type) { case measured: return createBox(size); @@ -86,4 +87,12 @@ return createCircle(size); } } + + public static Color withAlpha(final Color color, final int transparencyPercent) { + + if (transparencyPercent <= 0 || transparencyPercent > 100 || color == null) + return color; + + return new Color(color.getRed(), color.getGreen(), color.getBlue(), (int) ((100 - transparencyPercent) * 2.55f)); + } } \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/jfree/AxisDataset.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/AxisDataset.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/AxisDataset.java Thu Sep 27 17:41:44 2018 +0200 @@ -8,24 +8,18 @@ package org.dive4elements.river.jfree; +import java.util.ArrayList; import java.util.List; -import java.util.ArrayList; import org.jfree.data.Range; import org.jfree.data.RangeInfo; +import org.jfree.data.time.TimeSeriesCollection; import org.jfree.data.xy.XYDataset; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.jfree.data.time.TimeSeriesCollection; - -import org.apache.log4j.Logger; /** * Axis datasets. */ -public class AxisDataset -{ - private static Logger log = Logger.getLogger(AxisDataset.class); +public class AxisDataset { /** Symbolic integer, but also coding the priority (0 goes first). */ protected int axisSymbol; @@ -42,42 +36,39 @@ protected boolean rangeDirty; /** Create AxisDataset. */ - public AxisDataset(int symb) { - axisSymbol = symb; - datasets = new ArrayList(); + public AxisDataset(final int symb) { + this.axisSymbol = symb; + this.datasets = new ArrayList<>(); } /** Add a dataset to internal list for this axis. */ - public void addDataset(XYDataset dataset) { - datasets.add(dataset); - rangeDirty = true; + public void addDataset(final XYDataset dataset) { + this.datasets.add(dataset); + this.rangeDirty = true; } - /** Add a dataset. */ - public void addDataset(XYSeries series) { - addDataset(new XYSeriesCollection(series)); - } - - public void setRange(Range val) { - range = val; + public void setRange(final Range val) { + this.range = val; } /** Get Range for the range axis of this dataset. */ public Range getRange() { - if (range != null && !rangeDirty) { - return range; + if (this.range != null && !this.rangeDirty) { + return this.range; } /* Calculate the min / max of all series */ - for (XYDataset dataset: datasets) { + for (final XYDataset dataset : this.datasets) { Range newRange = null; if (dataset instanceof StyledAreaSeriesCollection) { final StyledAreaSeriesCollection areaSeries = (StyledAreaSeriesCollection) dataset; - if( areaSeries.shouldCalculateRange() ) + if (areaSeries.shouldCalculateRange()) newRange = areaSeries.getRangeBounds(false); else { - /* For most area themes, we do not include areas in the range calculation because + /* + * For most area themes, we do not include areas in the range calculation because * they are used with very large / small values to draw areas - * with axis boundaries */ + * with axis boundaries + */ continue; } } else if (dataset instanceof RangeInfo) { @@ -85,49 +76,37 @@ newRange = ((RangeInfo) dataset).getRangeBounds(false); } else if (dataset instanceof TimeSeriesCollection) { /* Lalala <3 Jfreechart's class hirarchy */ - newRange = ((TimeSeriesCollection)dataset) - .getRangeBounds(false); + newRange = ((TimeSeriesCollection) dataset).getRangeBounds(false); } /* Now we only expand as we also only add new data */ - if (range == null) { - range = newRange; + if (this.range == null) { + this.range = newRange; } else { - range = Range.combine(range, newRange); + this.range = Range.combine(this.range, newRange); } } - rangeDirty = false; - return range; + this.rangeDirty = false; + return this.range; } /** Get Array of Datasets. */ public XYDataset[] getDatasets() { - return datasets.toArray(new XYDataset[datasets.size()]); - } - - /** True if to be rendered as area. */ - public boolean isArea(XYDataset series) { - return (series instanceof StyledAreaSeriesCollection); + return this.datasets.toArray(new XYDataset[this.datasets.size()]); } /** True if no datasets given. */ public boolean isEmpty() { - return datasets.isEmpty(); + return this.datasets.isEmpty(); } /** Set the 'real' axis index that this axis is mapped to. */ - public void setPlotAxisIndex(int axisIndex) { - plotAxisIndex = axisIndex; + public void setPlotAxisIndex(final int axisIndex) { + this.plotAxisIndex = axisIndex; } /** Get the 'real' axis index that this axis is mapped to. */ public int getPlotAxisIndex() { - return plotAxisIndex; + return this.plotAxisIndex; } - - /** Add a Dataset that describes an area. */ - public void addArea(StyledAreaSeriesCollection series) { - addDataset(series); - } - -} +} \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/jfree/StripedAreaDataset.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StripedAreaDataset.java Thu Sep 27 17:41:44 2018 +0200 @@ -0,0 +1,133 @@ +/** 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.jfree; + +import java.awt.Color; +import java.awt.Font; +import java.util.ArrayList; +import java.util.List; + +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.java2d.ShapeUtils; +import org.dive4elements.river.themes.ThemeDocument; +import org.jfree.chart.LegendItem; +import org.jfree.chart.LegendItemCollection; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; + +/** + * @author Domenico Nardi Tironi + */ +public class StripedAreaDataset extends XYSeriesCollection implements StyledXYDataset { + + public static final class Stripe { + + private final String label; + + private final Color color; + + private final double lower; + + private final double upper; + + public Stripe(final String label, final Color color, final double lower, final double upper) { + this.label = label; + this.color = color; + this.lower = lower; + this.upper = upper; + } + + public String getLabel() { + return this.label; + } + + public Color getColor() { + return this.color; + } + + public double getLower() { + return this.lower; + } + + public double getUpper() { + return this.upper; + } + + } + + private static final long serialVersionUID = 1L; + + private final List stripes = new ArrayList<>(); + + private final ThemeDocument theme; + + public StripedAreaDataset(final ThemeDocument theme) { + this.theme = theme; + } + + public void addStripe(final Stripe stripe) { + + this.stripes.add(stripe); + + final XYSeries stripeSeries = new XYSeries(stripe.getLabel()); + // REMARK: we need at least one item, so the renderer method is called + stripeSeries.add(Double.NaN, Double.NaN); + super.addSeries(stripeSeries); + } + + @Override + public void addSeries(final XYSeries series) { + throw new UnsupportedOperationException(); + } + + Stripe getStripe(final int series) { + return this.stripes.get(series); + } + + @Override + public void applyTheme(final CallMeta callMeta, final XYPlot plot, final int datasetIndex, final Font legendFont) { + + final StripedAreaDatasetRenderer renderer = createRenderer(); + + plot.setRenderer(datasetIndex, renderer); + + final LegendItemCollection newItems = new LegendItemCollection(); + final LegendItemCollection oldItems = plot.getFixedLegendItems(); + + final int seriesCount = getSeriesCount(); + for (int i = 0; i < seriesCount; i++) { + final LegendItem legendItem = renderer.getLegendItem(datasetIndex, i); + if (legendItem != null) { + legendItem.setLabelFont(legendFont); + newItems.add(legendItem); + } + } + + if (oldItems != null) + newItems.addAll(oldItems); + + plot.setFixedLegendItems(newItems); + } + + private StripedAreaDatasetRenderer createRenderer() { + + final int transparency = this.theme.parseAreaTransparency(); + + final StripedAreaDatasetRenderer renderer = new StripedAreaDatasetRenderer(); + for (int i = 0; i < this.stripes.size(); i++) { + + final Color alphaPaint = ShapeUtils.withAlpha(this.stripes.get(i).getColor(), transparency); + renderer.setSeriesPaint(i, alphaPaint); + } + + return renderer; + } +} \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/jfree/StripedAreaDatasetRenderer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StripedAreaDatasetRenderer.java Thu Sep 27 17:41:44 2018 +0200 @@ -0,0 +1,69 @@ +/** 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.jfree; + +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Stroke; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; + +import org.dive4elements.river.jfree.StripedAreaDataset.Stripe; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CrosshairState; +import org.jfree.chart.plot.PlotRenderingInfo; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.AbstractXYItemRenderer; +import org.jfree.chart.renderer.xy.XYItemRendererState; +import org.jfree.data.xy.XYDataset; + +/** + * @author Domenico Nardi Tironi + */ +final class StripedAreaDatasetRenderer extends AbstractXYItemRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public void drawItem(final Graphics2D g2, final XYItemRendererState state, final Rectangle2D dataArea, final PlotRenderingInfo info, final XYPlot plot, + final ValueAxis domainAxis, final ValueAxis rangeAxis, final XYDataset dataset, final int series, final int item, + final CrosshairState crosshairState, final int pass) { + + if (item != 0) + return; + + final StripedAreaDataset stripedDataset = (StripedAreaDataset) dataset; + final Stripe stripe = stripedDataset.getStripe(series); + + final double lower = stripe.getLower(); + final double upper = stripe.getUpper(); + + final double transLower = Double.isNaN(lower) ? dataArea.getMaxY() : rangeAxis.valueToJava2D(lower, dataArea, plot.getRangeAxisEdge()); + final double transUpper = Double.isNaN(upper) ? dataArea.getMinY() : rangeAxis.valueToJava2D(upper, dataArea, plot.getRangeAxisEdge()); + + final double transLeft = dataArea.getMinX(); + final double transRight = dataArea.getMaxX(); + + final GeneralPath area = new GeneralPath(); + + area.moveTo(transLeft, transLower); + area.lineTo(transRight, transLower); + area.lineTo(transRight, transUpper); + area.lineTo(transLeft, transUpper); + area.closePath(); + + final Paint paint = getItemPaint(series, item); + final Stroke stroke = getItemStroke(series, item); + g2.setPaint(paint); + g2.setStroke(stroke); + + g2.fill(area); + } +} \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java Thu Sep 27 17:41:44 2018 +0200 @@ -10,6 +10,7 @@ import java.awt.BasicStroke; import java.awt.Color; +import java.awt.Font; import java.awt.Paint; import java.awt.Stroke; import java.awt.TexturePaint; @@ -17,7 +18,15 @@ import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import org.apache.log4j.Logger; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.java2d.ShapeUtils; import org.dive4elements.river.themes.ThemeDocument; +import org.dive4elements.river.utils.Formatter; +import org.jfree.chart.LegendItem; +import org.jfree.chart.LegendItemCollection; +import org.jfree.chart.plot.XYPlot; import org.jfree.data.xy.XYSeriesCollection; /** @@ -27,12 +36,17 @@ * The display options can be used to control the z-order and the axis of the * dataset. */ -// FIXME: bad abstraction: the only purpose of this derivation is to apply specific styles. This should rather be solved similar to the XYSTyle. -public class StyledAreaSeriesCollection extends XYSeriesCollection { +// FIXME: bad abstraction: the only purpose of this derivation is to apply specific styles. This should rather be solved +// similar to the XYSTyle. +public class StyledAreaSeriesCollection extends XYSeriesCollection implements StyledXYDataset { private static final long serialVersionUID = 5274940965666948237L; + private static final Logger log = Logger.getLogger(StyledAreaSeriesCollection.class); + /** Mode, how to draw/which areas to fill. */ - public enum FILL_MODE {UNDER, ABOVE, BETWEEN} + public enum FILL_MODE { + UNDER, ABOVE, BETWEEN + } /** MODE in use. */ private FILL_MODE mode; @@ -41,35 +55,83 @@ private final ThemeDocument theme; /** - * @param theme the theme-document. + * @param theme + * the theme-document. */ public StyledAreaSeriesCollection(final ThemeDocument theme) { this.theme = theme; this.mode = FILL_MODE.BETWEEN; } - /** Gets the Fill mode. */ - public FILL_MODE getMode() { + private FILL_MODE getMode() { return this.mode; } - /** Sets the Fill mode. */ public void setMode(final FILL_MODE fMode) { this.mode = fMode; } + @Override + public void applyTheme(final CallMeta callMeta, final XYPlot plot, final int datasetIndex, final Font legendFont) { + + final LegendItemCollection lic = new LegendItemCollection(); + final LegendItemCollection anno = plot.getFixedLegendItems(); + + log.debug("Registering an 'area'renderer at idx: " + datasetIndex); + + final StableXYDifferenceRenderer dRenderer = new StableXYDifferenceRenderer(); + + if (getMode() == StyledAreaSeriesCollection.FILL_MODE.UNDER) { + dRenderer.setPositivePaint(createTransparentPaint()); + } + + plot.setRenderer(datasetIndex, dRenderer); + + applyTheme(dRenderer); + + // i18n + dRenderer.setAreaLabelNumberFormat(Formatter.getFormatter(callMeta, 2, 4)); + + dRenderer.setAreaLabelTemplate(Resources.getMsg(callMeta, "area.label.template", "Area=%sm2")); + + final LegendItem legendItem = dRenderer.getLegendItem(datasetIndex, 0); + if (legendItem != null) { + legendItem.setLabelFont(legendFont); + lic.add(legendItem); + } else { + log.warn("Could not get LegentItem for renderer: " + datasetIndex + ", series-idx " + 0); + } + + if (anno != null) { + lic.addAll(anno); + } + + plot.setFixedLegendItems(lic); + } + + /** + * Returns a transparently textured paint. + * + * @return a transparently textured paint. + */ + private static Paint createTransparentPaint() { + // TODO why not use a transparent color? + final BufferedImage texture = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR); + + return new TexturePaint(texture, new Rectangle2D.Double(0d, 0d, 0d, 0d)); + } /** * Applies line color, size and type attributes to renderer, also * whether to draw lines and/or points. - * @param renderer Renderer to apply theme to. + * + * @param renderer + * Renderer to apply theme to. * @return \param renderer */ - public StableXYDifferenceRenderer applyTheme( - final StableXYDifferenceRenderer renderer - ) { + private StableXYDifferenceRenderer applyTheme(final StableXYDifferenceRenderer renderer) { applyFillColor(renderer); applyShowBorder(renderer); applyShowArea(renderer); @@ -81,16 +143,11 @@ applyPointStyle(renderer); applyShowMinimumMaximum(renderer); if (this.mode == FILL_MODE.UNDER) { - renderer.setAreaCalculationMode( - StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA); - } - else if (this.mode == FILL_MODE.ABOVE) { - renderer.setAreaCalculationMode( - StableXYDifferenceRenderer.CALCULATE_POSITIVE_AREA); - } - else { - renderer.setAreaCalculationMode( - StableXYDifferenceRenderer.CALCULATE_ALL_AREA); + renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA); + } else if (this.mode == FILL_MODE.ABOVE) { + renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_POSITIVE_AREA); + } else { + renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_ALL_AREA); } // Apply text style. @@ -115,13 +172,11 @@ if (paint != null && this.getMode() == FILL_MODE.ABOVE) { renderer.setPositivePaint(paint); - renderer.setNegativePaint(new Color(0,0,0,0)); - } - else if (paint != null && this.getMode() == FILL_MODE.UNDER) { + renderer.setNegativePaint(new Color(0, 0, 0, 0)); + } else if (paint != null && this.getMode() == FILL_MODE.UNDER) { renderer.setNegativePaint(paint); - renderer.setPositivePaint(new Color(0,0,0,0)); - } - else { + renderer.setPositivePaint(new Color(0, 0, 0, 0)); + } else { if (paint == null) paint = new Color(177, 117, 102); @@ -134,31 +189,19 @@ final Color paint = this.theme.parseAreaBackgroundColor(); final int transparency = this.theme.parseAreaTransparency(); - final Color alphaPaint = withAlpha(paint, transparency); + final Color alphaPaint = ShapeUtils.withAlpha(paint, transparency); final AreaFillPattern pattern = this.theme.parseAreaBackgroundPattern(); - if( pattern == null || pattern == AreaFillPattern.patternFill ) + if (pattern == null || pattern == AreaFillPattern.patternFill) return alphaPaint; final BufferedImage image = pattern.getImage(alphaPaint); - final Rectangle2D anchor = new Rectangle2D.Double(0,0, image.getWidth(), image.getHeight()); + final Rectangle2D anchor = new Rectangle2D.Double(0, 0, image.getWidth(), image.getHeight()); return new TexturePaint(image, anchor); } - private Color withAlpha(final Color color, final int transparency) { - - if (transparency <= 0 || color == null) - return color; - - return new Color( - color.getRed(), - color.getGreen(), - color.getBlue(), - (int)((100 - transparency) * 2.55f)); - } - private void applyShowBorder(final StableXYDifferenceRenderer renderer) { final boolean show = this.theme.parseAreaShowBorder(); renderer.setDrawOutline(show); @@ -195,20 +238,14 @@ private void applyOutlineStyle(final StableXYDifferenceRenderer renderer) { final float[] dashes = this.theme.parseLineStyle(); - final int size = this.theme.parseLineWidth(); + final int size = this.theme.parseLineWidth(); Stroke stroke = null; if (dashes.length <= 1) { stroke = new BasicStroke(Integer.valueOf(size)); - } - else { - stroke = new BasicStroke(Integer.valueOf(size), - BasicStroke.CAP_BUTT, - BasicStroke.JOIN_ROUND, - 1.0f, - dashes, - 0.0f); + } else { + stroke = new BasicStroke(Integer.valueOf(size), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dashes, 0.0f); } renderer.setOutlineStroke(stroke); @@ -219,10 +256,9 @@ final boolean showPoints = this.theme.parseShowPoints(); renderer.setShapesVisible(showPoints); - if( showPoints ) - { + if (showPoints) { final int size = this.theme.parsePointWidth(); - final int dim = 2 * size; + final int dim = 2 * size; final Ellipse2D pointShape = new Ellipse2D.Double(-size, -size, dim, dim); final Color pointColor = this.theme.parsePointColor(); diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYDataset.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYDataset.java Thu Sep 27 17:41:44 2018 +0200 @@ -0,0 +1,24 @@ +/** 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.jfree; + +import java.awt.Font; + +import org.dive4elements.artifacts.CallMeta; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.xy.XYDataset; + +/** + * @author Domenico Nardi Tironi + * + */ +public interface StyledXYDataset extends XYDataset { + void applyTheme(CallMeta callMeta, XYPlot plot, int datasetIndex, Font legendFont); +} \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/resources/messages.properties --- a/artifacts/src/main/resources/messages.properties Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/resources/messages.properties Thu Sep 27 17:41:44 2018 +0200 @@ -1198,6 +1198,11 @@ uinfo_salix_scenario_historical = historical uinfo_facet_salix_rank = Assessment Scheme uinfo_facet_salix_rank.description = Assessment Scheme +uinfo_salix_rank.excellent = Excellent +uinfo_salix_rank.good = Good +uinfo_salix_rank.moderate = Moderate +uinfo_salix_rank.bad = Bad +uinfo_salix_rank.very_bad = Very bad uinfo_salix_calc.warning.missing_mq = MQ (MW) missing at reference gauge, no calculation possible uinfo_salix_calc.warning.missing_mhq = MHQ (MHW) missing at reference gauge, no salix calculation possible uinfo_salix_calc.warning.missing_mnq = MNQ (MNW) missing at reference gauge, no (MW-MNW) calculation possible @@ -1324,13 +1329,13 @@ bundu.wst.gauge_no_ud_calc_available = No calculation of DNE available. bundu.chart.wspl.section.title = REFWL-Longitudinal Section -bundu_facet_bedheight.description = Mean Bed Height ({0}) +bundu_facet_bedheight.description = Mean Bed Height ({0}) bundu_facet_channelmin.description = Bed (Target) -bundu_facet_field_bedheight.description = Bed Height Field {0} +bundu_facet_field_bedheight.description = Bed Height Field {0} bundu.chart.depth.section.title = \u0394h-L\u00e4ngsschnitt bundu_facet_flowdepth.filtered.description = \u0394h (BZWS, {0}) bundu_facet_channeldepth.description = \u0394h (Target depth) -bundu_facet_field_depth.description = \u0394h Field {0} +bundu_facet_field_depth.description = \u0394h Field {0} bundu.channelfinder.empty = The database does not contain any values for the river and the reference year bundu.channelfinder.missing = no channel data available diff -r d6d5ca6d4af0 -r 7b4b66c7b303 artifacts/src/main/resources/messages_de.properties --- a/artifacts/src/main/resources/messages_de.properties Thu Sep 27 17:40:39 2018 +0200 +++ b/artifacts/src/main/resources/messages_de.properties Thu Sep 27 17:41:44 2018 +0200 @@ -1198,6 +1198,11 @@ uinfo_salix_scenario_historical = historisch uinfo_facet_salix_rank = Bewertungsschema uinfo_facet_salix_rank.description = Bewertungsschema +uinfo_salix_rank.excellent = Sehr gut +uinfo_salix_rank.good = Gut +uinfo_salix_rank.moderate = M\u00e4\u00dfig +uinfo_salix_rank.bad = Schlecht +uinfo_salix_rank.very_bad = Sehr schlecht uinfo_salix_calc.warning.missing_mq = MQ (MW) fehlt am Bezugspegel, Berechnung nicht m\u00f6glich uinfo_salix_calc.warning.missing_mhq = MHQ (MHW) fehlt am Bezugspegel, Berechnung des Iota nicht m\u00f6glich uinfo_salix_calc.warning.missing_mnq = MNQ (MNW) fehlt am Bezugspegel, Berechnung von (MW-MNW) nicht m\u00f6glich @@ -1324,13 +1329,13 @@ bundu.wst.gauge_no_ud_calc_available = Eine Berechnung der UD ist nicht m\u00f6glich. bundu.chart.wspl.section.title = BZWS-L\u00e4ngsschnitt -bundu_facet_bedheight.description = Mittlere Sohlh\u00f6he ({0}) +bundu_facet_bedheight.description = Mittlere Sohlh\u00f6he ({0}) bundu_facet_channelmin.description = Sohle (Sollzustand) -bundu_facet_field_bedheight.description = Sohlh\u00f6he Feld {0} +bundu_facet_field_bedheight.description = Sohlh\u00f6he Feld {0} bundu.chart.depth.section.title = \u0394h-L\u00e4ngsschnitt bundu_facet_flowdepth.filtered.description = \u0394h (BZWS, {0}) bundu_facet_channeldepth.description = \u0394h (Solltiefe) -bundu_facet_field_depth.description = \u0394h Feld {0} +bundu_facet_field_depth.description = \u0394h Feld {0} bundu.channelfinder.empty = Die Datenbank enth\u00e4lt keine Fahrrinnedaten f\u00fcr das Gew\u00e4sser und das Bezugsjahr bundu.channelfinder.missing = keine Fahrrinnedaten vorhanden diff -r d6d5ca6d4af0 -r 7b4b66c7b303 backend/src/main/java/org/dive4elements/river/importer/ImportAttribute.java --- a/backend/src/main/java/org/dive4elements/river/importer/ImportAttribute.java Thu Sep 27 17:40:39 2018 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/ImportAttribute.java Thu Sep 27 17:41:44 2018 +0200 @@ -59,6 +59,26 @@ if (this.peer != null) return this.peer; final Session session = ImporterSession.getInstance().getDatabaseSession(); + final Query query = session.createQuery("FROM Attribute WHERE value=:value"); + query.setString("value", this.value.trim()); + final List attributes = query.list(); + if (attributes.isEmpty()) { + this.peer = getPeerCaseInsensitive(); + if (this.peer == null) { + this.peer = new Attribute(this.value); + session.save(this.peer); + } + } + else { + this.peer = attributes.get(0); + } + return this.peer; + } + + private Attribute getPeerCaseInsensitive() { + if (this.peer != null) + return this.peer; + final Session session = ImporterSession.getInstance().getDatabaseSession(); final Query query = session.createQuery("FROM Attribute WHERE lower(value)=:value"); query.setString("value", this.value.trim().toLowerCase()); final List attributes = query.list(); diff -r d6d5ca6d4af0 -r 7b4b66c7b303 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 Thu Sep 27 17:40:39 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Thu Sep 27 17:41:44 2018 +0200 @@ -1616,4 +1616,6 @@ String gauge_list_grid_end(); String no_data_for_input(); + + String bundu_bezugswsts(); } \ No newline at end of file diff -r d6d5ca6d4af0 -r 7b4b66c7b303 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 Thu Sep 27 17:40:39 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Thu Sep 27 17:41:44 2018 +0200 @@ -858,6 +858,7 @@ bundu_ws_wq_info = The discharge values MNQ, MQ and MHQ are being calculated based on the daily discharge values. bundu_wspl_longitudinal_section = REFWL - Longitudinal Section bundu_depth_longitudinal_section = REFWL \u0394h - +bundu_bezugswsts = Reference Waterlevels chart_settings_export_metadata = Show Metadata export_csv_title = Title: diff -r d6d5ca6d4af0 -r 7b4b66c7b303 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 Thu Sep 27 17:40:39 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Thu Sep 27 17:41:44 2018 +0200 @@ -858,6 +858,7 @@ bundu_ws_wq_info = Die Abfl\u00fcsse MNQ, MQ und MHQ sind anhand der Tagesmittelwerte des Abflusses berechnet. bundu_wspl_longitudinal_section = BZWS - L\u00e4ngsschnitt bundu_depth_longitudinal_section = BZWS \u0394h - L\u00e4ngsschnitt +bundu_bezugswsts = Bezugswasserst\u00e4nde chart_settings_export_metadata = Metadaten anzeigen export_csv_title = Titel: diff -r d6d5ca6d4af0 -r 7b4b66c7b303 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractEpochPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractEpochPanel.java Thu Sep 27 17:40:39 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractEpochPanel.java Thu Sep 27 17:41:44 2018 +0200 @@ -210,7 +210,7 @@ switch (this.type) { case single: - data.add(buildResult(this.start.getValueAsString(), this.end.getValueAsString())); + data.add(resultToData(buildResult(this.start.getValueAsString(), this.end.getValueAsString()))); break; case multi: @@ -218,9 +218,13 @@ if (lgr.length == 0) { return new Data[0]; } + final StringBuilder resultBuilder = new StringBuilder(); for (final ListGridRecord element : lgr) { - data.add(buildResult(element.getAttribute("from"), element.getAttribute("to"))); + resultBuilder.append(buildResult(element.getAttribute("from"), element.getAttribute("to"))); + } + data.add(resultToData(resultBuilder.toString())); + break; default: throw new IllegalStateException(); @@ -228,14 +232,17 @@ return data.toArray(new Data[data.size()]); } - private final Data buildResult(final String startStr, final String endStr) { + private final String buildResult(final String startStr, final String endStr) { final StringBuilder builder = new StringBuilder(); builder.append(startStr); builder.append(","); builder.append(endStr); builder.append(";"); - final DataItem item = new DefaultDataItem(getDatakey(), null, builder.toString()); + return builder.toString(); + } + + final Data resultToData(final String resultStr) { + final DataItem item = new DefaultDataItem(getDatakey(), null, resultStr); return new DefaultData(getDatakey(), null, null, new DataItem[] { item }); } - }