comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/BedQualityD50TimeRangeConfig.java @ 9532:8e6b9cb9486a

Fixed BedQuality finder
author gernotbelger
date Tue, 02 Oct 2018 18:19:44 +0200
parents 23d97d60b889
children ba0561906f81
comparison
equal deleted inserted replaced
9531:267ac3012150 9532:8e6b9cb9486a
9 */ 9 */
10 package org.dive4elements.river.artifacts.sinfo.tkhstate; 10 package org.dive4elements.river.artifacts.sinfo.tkhstate;
11 11
12 import java.io.File; 12 import java.io.File;
13 import java.io.IOException; 13 import java.io.IOException;
14 import java.util.ArrayList;
14 import java.util.Calendar; 15 import java.util.Calendar;
16 import java.util.Collection;
15 import java.util.Date; 17 import java.util.Date;
16 import java.util.HashMap; 18 import java.util.HashMap;
17 import java.util.List; 19 import java.util.List;
18 import java.util.Map; 20 import java.util.Map;
21 import java.util.TimeZone;
19 22
20 import org.dive4elements.river.artifacts.model.Calculation; 23 import org.dive4elements.river.artifacts.model.Calculation;
21 import org.dive4elements.river.artifacts.model.DateRange; 24 import org.dive4elements.river.artifacts.model.DateRange;
22 import org.dive4elements.river.artifacts.sinfo.tkhcalculation.BedQualityD50KmValueFinder; 25 import org.dive4elements.river.artifacts.sinfo.tkhcalculation.BedQualityD50KmValueFinder;
23 import org.dive4elements.river.artifacts.sinfo.tkhstate.TsvHelper.TsvReaderException; 26 import org.dive4elements.river.artifacts.sinfo.tkhstate.TsvHelper.TsvReaderException;
30 */ 33 */
31 public final class BedQualityD50TimeRangeConfig { 34 public final class BedQualityD50TimeRangeConfig {
32 35
33 private static final String CONFIG_FILE = "d50_sohlkorndurchmesser_%s.tsv"; 36 private static final String CONFIG_FILE = "d50_sohlkorndurchmesser_%s.tsv";
34 37
35 private final Map<String, DateRange> cache = new HashMap<>(); 38 private final Map<String, CalRange[]> cache = new HashMap<>();
36 39
37 private static BedQualityD50TimeRangeConfig INSTANCE = new BedQualityD50TimeRangeConfig(); 40 private static BedQualityD50TimeRangeConfig INSTANCE = new BedQualityD50TimeRangeConfig();
38 41
39 public static class BedQualityParseException extends Exception { 42 private static class BedQualityParseException extends Exception {
40 43
41 private static final long serialVersionUID = 1L; 44 private static final long serialVersionUID = 1L;
42 45
43 BedQualityParseException(final String message) { 46 public BedQualityParseException(final String message, final Throwable cause) {
44 super(message);
45 }
46
47 BedQualityParseException(final String message, final Throwable cause) {
48 super(message, cause); 47 super(message, cause);
49 } 48 }
50 } 49 }
51 50
52 public static synchronized DateRange getDefaults(final River river, final int soundingYear, final Calculation problems) 51 public static synchronized DateRange getDefaults(final River river, final int soundingYear, final Calculation problems) {
53 throws BedQualityParseException {
54 return INSTANCE.getBedHeightDefaultsForRiver(river, soundingYear, problems); 52 return INSTANCE.getBedHeightDefaultsForRiver(river, soundingYear, problems);
55 } 53 }
56 54
57 private synchronized DateRange getBedHeightDefaultsForRiver(final River river, final int soundingYear, final Calculation problems) 55 private synchronized DateRange getBedHeightDefaultsForRiver(final River river, final int soundingYear, final Calculation problems) {
58 throws BedQualityParseException { 56
59 final String rivername = river.getName(); 57 final String rivername = river.getName();
60 final String cacheKey = new StringBuilder().append(rivername).append(";").append(soundingYear).toString();
61 if (!this.cache.containsKey(cacheKey)) {
62 final File file = TsvHelper.makeFile2(CONFIG_FILE, rivername);
63 final File fileCheck = TsvHelper.checkFile(file);
64 if (fileCheck == null)
65 return null; // automatically dateRange min/max wil be taken
66 58
67 List<String[]> results = null; 59 final CalRange[] ranges = getRanges(rivername, problems);
68 try { 60 if (ranges == null)
69 results = TsvHelper.readTsv(file, 4); 61 return null;
70 }
71 catch (final TsvReaderException | IOException e) {
72 problems.addProblem("sinfo.bedqualityd50config.configfile.loaderror", file.getPath(), e.getStackTrace());
73 }
74 if (results != null) {
75 for (final String[] line : results) {
76 final CalRange range = new CalRange(parseInput(line[0]), parseInput(line[1]), parseInput(line[2]), parseInput(line[3]));
77 if (range.isSoundingYearInRange(soundingYear)) {
78 final DateRange dateRange = new DateRange(range.getStartTimeQuery(), range.getEndTimeQuery());
79 this.cache.put(cacheKey, dateRange);
80 62
81 } 63 for (final CalRange range : ranges) {
82 } 64 if (range.isSoundingYearInRange(soundingYear))
83 } 65 return new DateRange(range.getStartTimeQuery(), range.getEndTimeQuery());
84 problems.addProblem("sinfo.bedqualityd50config.configfile.loaderror", file.getPath(), 66 }
85 " Die angegebene d50-sohlkorndurchmesser-config-file enthält keinen gültigen Bereich für das konfigurierte Peiljahr."); 67
68 // Message for admin, not translated
69 final File file = TsvHelper.makeFile2(CONFIG_FILE, rivername);
70 final String message = "Die angegebene d50-Sohlkorndurchmesser Konfigurationsdatei enthält keinen gültigen Bereich für das konfigurierte Peiljahr."; //$NON-NLS-1$
71 problems.addProblem("sinfo.bedqualityd50config.configfile.loaderror", file.getPath(), message);
72 return null;
73 }
74
75 private CalRange[] getRanges(final String rivername, final Calculation problems) {
76
77 if (this.cache.containsKey(rivername))
78 return this.cache.get(rivername);
79
80 final CalRange[] ranges = loadRanges(rivername, problems);
81 if (ranges == null) {
82 /* do not cache so we always get the problem message again */
86 return null; 83 return null;
87 } 84 }
88 return this.cache.get(cacheKey); 85
86 this.cache.put(rivername, ranges);
87 return ranges;
88 }
89
90 private CalRange[] loadRanges(final String rivername, final Calculation problems) {
91 final File file = TsvHelper.makeFile2(CONFIG_FILE, rivername);
92 final File fileCheck = TsvHelper.checkFile(file);
93 if (fileCheck == null)
94 return new CalRange[] { new CalRange(null, null, null, null) }; // automatically dateRange min/max will be taken
95
96 try {
97 final List<String[]> results = TsvHelper.readTsv(file, 4);
98
99 final Collection<CalRange> ranges = new ArrayList<>(results.size());
100
101 for (final String[] line : results)
102 ranges.add(new CalRange(parseInput(line[0]), parseInput(line[1]), parseInput(line[2]), parseInput(line[3])));
103
104 return ranges.toArray(new CalRange[ranges.size()]);
105 }
106 catch (final TsvReaderException | IOException | BedQualityParseException e) {
107 problems.addProblem("sinfo.bedqualityd50config.configfile.loaderror", file.getPath(), e.getLocalizedMessage());
108 return null;
109 }
89 } 110 }
90 111
91 private static Integer parseInput(final String raw) throws BedQualityParseException { 112 private static Integer parseInput(final String raw) throws BedQualityParseException {
113
92 final String value = raw.trim(); 114 final String value = raw.trim();
93 if (value.toUpperCase().equals("MIN") || value.toUpperCase().equals("MAX")) 115 if (value.toUpperCase().equals("MIN") || value.toUpperCase().equals("MAX"))
94 return null; 116 return null;
117
95 try { 118 try {
96
97 return Integer.valueOf(value); 119 return Integer.valueOf(value);
98 } 120 }
99 catch (final NumberFormatException e) { 121 catch (final NumberFormatException e) {
100 throw new BedQualityParseException("Invalid input; should be year ('yyyy') or 'MIN' or 'MAX'", e); 122 throw new BedQualityParseException("Invalid input; should be year ('yyyy') or 'MIN' or 'MAX'", e);
101 } 123 }
105 private final long startTimeSounding; 127 private final long startTimeSounding;
106 private final long endTimeSounding; 128 private final long endTimeSounding;
107 129
108 private final long startTimeQuery; 130 private final long startTimeQuery;
109 private final long endTimeQuery; 131 private final long endTimeQuery;
110
111 private final static Calendar cal = Calendar.getInstance();
112 132
113 public Date getStartTimeQuery() { 133 public Date getStartTimeQuery() {
114 return new Date(this.startTimeQuery); 134 return new Date(this.startTimeQuery);
115 } 135 }
116 136
124 this.startTimeQuery = (startYearQuery != null) ? getLongValForYear(startYearQuery, 0, 1) : BedQualityD50KmValueFinder.MIN_DATE.getTime(); 144 this.startTimeQuery = (startYearQuery != null) ? getLongValForYear(startYearQuery, 0, 1) : BedQualityD50KmValueFinder.MIN_DATE.getTime();
125 this.endTimeSounding = (endYearSounding != null) ? getLongValForYear(endYearSounding, 11, 31) : BedQualityD50KmValueFinder.MAX_DATE.getTime(); 145 this.endTimeSounding = (endYearSounding != null) ? getLongValForYear(endYearSounding, 11, 31) : BedQualityD50KmValueFinder.MAX_DATE.getTime();
126 this.endTimeQuery = (endYearQuery != null) ? getLongValForYear(endYearQuery, 11, 31) : BedQualityD50KmValueFinder.MAX_DATE.getTime(); 146 this.endTimeQuery = (endYearQuery != null) ? getLongValForYear(endYearQuery, 11, 31) : BedQualityD50KmValueFinder.MAX_DATE.getTime();
127 } 147 }
128 148
129 private long getLongValForYear(final int year, final int month0based, final int dayOfMonth) { 149 private static long getLongValForYear(final int year, final int month0based, final int dayOfMonth) {
150 final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+1"));
130 cal.clear(); 151 cal.clear();
131 cal.set(year, month0based, dayOfMonth); 152 cal.set(year, month0based, dayOfMonth);
132 153
133 return cal.getTimeInMillis(); 154 return cal.getTimeInMillis();
134 } 155 }
135 156
136 public boolean isSoundingYearInRange(final int soundingYear) { 157 public boolean isSoundingYearInRange(final int soundingYear) {
137 cal.clear();
138 158
139 cal.set(soundingYear, 5, 5); // random date in the middle of the year 159 final long time = getLongValForYear(soundingYear, 5, 5); // random date in the middle of the year
140
141 final Long time = cal.getTimeInMillis();
142
143 if (time > this.startTimeSounding && time < this.endTimeSounding) 160 if (time > this.startTimeSounding && time < this.endTimeSounding)
144 return true; 161 return true;
145 162
146 return false; 163 return false;
147 } 164 }

http://dive4elements.wald.intevation.org