comparison artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java @ 9708:93389a05119e

zu Nachtrag - BezugsWST in intell. Datenkorb
author dnt_bjoernsen <d.tironi@bjoernsen.de>
date Fri, 22 Jan 2021 18:45:39 +0100
parents 3f49835a00c3
children
comparison
equal deleted inserted replaced
9707:23702537fb4f 9708:93389a05119e
14 import java.util.List; 14 import java.util.List;
15 15
16 import org.apache.commons.lang.math.DoubleRange; 16 import org.apache.commons.lang.math.DoubleRange;
17 import org.apache.log4j.Logger; 17 import org.apache.log4j.Logger;
18 import org.dive4elements.artifacts.CallContext; 18 import org.dive4elements.artifacts.CallContext;
19 import org.dive4elements.river.artifacts.AbstractFixBunduArtifact;
19 import org.dive4elements.river.artifacts.D4EArtifact; 20 import org.dive4elements.river.artifacts.D4EArtifact;
20 import org.dive4elements.river.artifacts.FixationArtifact;
21 import org.dive4elements.river.artifacts.StaticWKmsArtifact; 21 import org.dive4elements.river.artifacts.StaticWKmsArtifact;
22 import org.dive4elements.river.artifacts.StaticWQKmsArtifact; 22 import org.dive4elements.river.artifacts.StaticWQKmsArtifact;
23 import org.dive4elements.river.artifacts.WINFOArtifact; 23 import org.dive4elements.river.artifacts.WINFOArtifact;
24 import org.dive4elements.river.artifacts.access.FixRealizingAccess; 24 import org.dive4elements.river.artifacts.access.FixRealizingAccess;
25 import org.dive4elements.river.artifacts.bundu.bezugswst.BezugswstCalculationResults;
26 import org.dive4elements.river.artifacts.bundu.bezugswst.BezugswstMainCalculationResult;
27 import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
25 import org.dive4elements.river.artifacts.model.Calculation; 28 import org.dive4elements.river.artifacts.model.Calculation;
26 import org.dive4elements.river.artifacts.model.CalculationResult; 29 import org.dive4elements.river.artifacts.model.CalculationResult;
27 import org.dive4elements.river.artifacts.model.Segment; 30 import org.dive4elements.river.artifacts.model.Segment;
28 import org.dive4elements.river.artifacts.model.WKms; 31 import org.dive4elements.river.artifacts.model.WKms;
29 import org.dive4elements.river.artifacts.model.WQKms; 32 import org.dive4elements.river.artifacts.model.WQKms;
34 import org.dive4elements.river.model.TimeInterval; 37 import org.dive4elements.river.model.TimeInterval;
35 import org.dive4elements.river.model.WstColumn; 38 import org.dive4elements.river.model.WstColumn;
36 import org.dive4elements.river.utils.RiverUtils; 39 import org.dive4elements.river.utils.RiverUtils;
37 40
38 /** 41 /**
39 * Helper class that accesses existing waterlevels (in most cases) from the data-cage. 42 * Helper class that accesses existing waterlevels (in most cases) from the
40 * This is mainly a refaktoring of org.dive4elements.river.artifacts.states.WDifferencesState.getWKms(String, 43 * data-cage. This is mainly a refaktoring of
44 * org.dive4elements.river.artifacts.states.WDifferencesState.getWKms(String,
41 * CallContext, double, double), adding more infos to the fetched water levels. 45 * CallContext, double, double), adding more infos to the fetched water levels.
42 * 46 *
43 * @author Gernot Belger 47 * @author Gernot Belger
44 */ 48 */
45 public class WaterlevelFetcher { 49 public class WaterlevelFetcher {
46 private static Logger log = Logger.getLogger(WaterlevelFetcher.class); 50 private static Logger log = Logger.getLogger(WaterlevelFetcher.class);
47 51
48 /** 52 /**
49 * @param simulationRange 53 * @param simulationRange
50 * This range is used to check if the found waterlevel covers it. It is NOT used to reduce the fetched data, 54 * This range is used to check if the found waterlevel covers it. It
51 * because in case of waterlevels we always need to full set in order to determine the relevant gauge. 55 * is NOT used to reduce the fetched data, because in case of
52 */ 56 * waterlevels we always need to full set in order to determine the
53 public WaterlevelData findWaterlevel(final CallContext context, final String mingle, final DoubleRange simulationRange, final Calculation problems) { 57 * relevant gauge.
54 58 */
55 final String[] def = mingle.split(";"); 59 public WaterlevelData findWaterlevel(final CallContext context, final String mingle,
56 final String uuid = def[0]; 60 final DoubleRange simulationRange, final Calculation problems) {
57 // final String factory = def[1]; 61
58 final int idx = Integer.parseInt(def[2]); 62 final String[] def = mingle.split(";");
59 final String name = def[3]; 63 final String uuid = def[0];
60 final D4EArtifact d4eArtifact = RiverUtils.getArtifact(uuid, context); 64 // final String factory = def[1];
61 if (d4eArtifact == null) 65 final int idx = Integer.parseInt(def[2]);
62 return null; 66 final String name = def[3];
63 67 final D4EArtifact d4eArtifact = RiverUtils.getArtifact(uuid, context);
64 final WaterlevelData data = fetchWaterlevelFromArtifact(context, d4eArtifact, idx, Double.NaN, Double.NaN); 68 if (d4eArtifact == null)
65 if (data == null) { 69 return null;
66 problems.addProblem("waterlevelfetcher.missing", mingle); 70
67 return null; 71 final WaterlevelData data = fetchWaterlevelFromArtifact(context, d4eArtifact, idx, Double.NaN, Double.NaN);
68 } 72 if (data == null) {
69 73 problems.addProblem("waterlevelfetcher.missing", mingle);
70 if (!data.covers(simulationRange)) { 74 return null;
71 problems.addProblem("waterlevelfetcher.empty", data.getName()); 75 }
72 return null; 76
73 } 77 if (!data.covers(simulationRange)) {
74 78 problems.addProblem("waterlevelfetcher.empty", data.getName());
75 return data.withName(name); 79 return null;
76 } 80 }
77 81
78 private WaterlevelData fetchWaterlevelFromArtifact(final CallContext context, final D4EArtifact d4eArtifact, final int idx, final double from, 82 return data.withName(name);
79 final double to) { 83 }
80 84
81 if (d4eArtifact instanceof StaticWKmsArtifact) 85 private WaterlevelData fetchWaterlevelFromArtifact(final CallContext context, final D4EArtifact d4eArtifact,
82 return fetchStaticWKmsArtifactWaterlevel((StaticWKmsArtifact) d4eArtifact, from, to); 86 final int idx, final double from, final double to) {
83 87
84 if (d4eArtifact instanceof StaticWQKmsArtifact) 88 if (d4eArtifact instanceof StaticWKmsArtifact)
85 return fetchStaticWQKmsArtifactWaterlevel((StaticWQKmsArtifact) d4eArtifact, from, to); 89 return fetchStaticWKmsArtifactWaterlevel((StaticWKmsArtifact) d4eArtifact, from, to);
86 90
87 if (d4eArtifact instanceof WINFOArtifact) 91 if (d4eArtifact instanceof StaticWQKmsArtifact)
88 return fetchWINFOArtifactWaterlevel(context, (WINFOArtifact) d4eArtifact, idx, from, to); 92 return fetchStaticWQKmsArtifactWaterlevel((StaticWQKmsArtifact) d4eArtifact, from, to);
89 93
90 if (d4eArtifact instanceof FixationArtifact) 94 if (d4eArtifact instanceof WINFOArtifact)
91 return fetchFixationArtifactWaterlevel(context, (FixationArtifact) d4eArtifact, idx, from, to); 95 return fetchWINFOArtifactWaterlevel(context, (WINFOArtifact) d4eArtifact, idx, from, to);
92 96
93 log.warn(String.format("Get Waterlevel from %s not implemented!", d4eArtifact.getClass().getSimpleName())); 97 if (d4eArtifact instanceof AbstractFixBunduArtifact) //including BUNDUArtifact
94 return null; 98 return fetchFixationArtifactWaterlevel(context, (AbstractFixBunduArtifact) d4eArtifact, idx, from, to);
95 } 99
96 100 log.warn(String.format("Get Waterlevel from %s not implemented!", d4eArtifact.getClass().getSimpleName()));
97 // REMARK: instead of several helper methods here this would be a good place for abstraction, in order to push 101 return null;
98 // this logic back to the corresponding artifacts. However this will most certainly break existing 102 }
99 // artifact-serialization 103
100 104 // REMARK: instead of several helper methods here this would be a good place for
101 private WaterlevelData fetchStaticWKmsArtifactWaterlevel(final StaticWKmsArtifact staticWKms, final double from, final double to) { 105 // abstraction, in order to push
102 106 // this logic back to the corresponding artifacts. However this will most
103 log.debug("WDifferencesState obtain data from StaticWKms"); 107 // certainly break existing
104 108 // artifact-serialization
105 final WKms wkms = staticWKms.getWKms(from, to); 109
106 110 private WaterlevelData fetchStaticWKmsArtifactWaterlevel(final StaticWKmsArtifact staticWKms, final double from,
107 if (wkms != null) { 111 final double to) {
108 final int year = fetchStaticWKmsYear(staticWKms); 112
109 return new WaterlevelData(wkms, year, false, false); 113 log.debug("WDifferencesState obtain data from StaticWKms");
110 } 114
111 115 final WKms wkms = staticWKms.getWKms(from, to);
112 log.error("No WKms from Static artifact for this range."); 116
113 return null; 117 if (wkms != null) {
114 } 118 final int year = fetchStaticWKmsYear(staticWKms);
115 119 return new WaterlevelData(wkms, year, false, false);
116 private WaterlevelData fetchStaticWQKmsArtifactWaterlevel(final StaticWQKmsArtifact staticWKms, final double from, final double to) { 120 }
117 121
118 log.debug("WDifferencesState obtain data from StaticWQKms"); 122 log.error("No WKms from Static artifact for this range.");
119 123 return null;
120 final WQKms wkms = staticWKms.getWQKms(from, to); 124 }
121 125
122 if (wkms != null) { 126 private WaterlevelData fetchStaticWQKmsArtifactWaterlevel(final StaticWQKmsArtifact staticWKms, final double from,
123 final int year = fetchStaticWKmsYear(staticWKms); 127 final double to) {
124 return new WaterlevelData(wkms, year, false, false); 128
125 } 129 log.debug("WDifferencesState obtain data from StaticWQKms");
126 130
127 log.error("No WKms from Static artifact for this range."); 131 final WQKms wkms = staticWKms.getWQKms(from, to);
128 return null; 132
129 } 133 if (wkms != null) {
130 134 final int year = fetchStaticWKmsYear(staticWKms);
131 private WaterlevelData fetchWINFOArtifactWaterlevel(final CallContext context, final WINFOArtifact flys, final int idx, final double from, 135 return new WaterlevelData(wkms, year, false, false);
132 final double to) { 136 }
133 log.debug("Get WKms from WINFOArtifact"); 137
134 138 log.error("No WKms from Static artifact for this range.");
135 final WKms[] wkms = (WKms[]) flys.getWaterlevelData(context).getData(); 139 return null;
136 140 }
137 if (wkms == null || wkms.length == 0) { 141
138 log.warn("no waterlevels in artifact"); 142 private WaterlevelData fetchWINFOArtifactWaterlevel(final CallContext context, final WINFOArtifact flys,
139 return null; 143 final int idx, final double from, final double to) {
140 } 144 log.debug("Get WKms from WINFOArtifact");
141 145
142 if (wkms.length < idx + 1) { 146 final WKms[] wkms = (WKms[]) flys.getWaterlevelData(context).getData();
143 log.warn("Not enough waterlevels in artifact."); 147
144 return null; 148 if (wkms == null || wkms.length == 0) {
145 } 149 log.warn("no waterlevels in artifact");
146 150 return null;
147 // REAMRK: W_INFO results does not know any 'year' 151 }
148 final int year = -1; 152
149 return new WaterlevelData(wkms[idx], year, false, true).filterByRange(from, to); 153 if (wkms.length < idx + 1) {
150 } 154 log.warn("Not enough waterlevels in artifact.");
151 155 return null;
152 private WaterlevelData fetchFixationArtifactWaterlevel(final CallContext context, final FixationArtifact fixation, final int idx, final double from, 156 }
153 final double to) { 157
154 158 // REAMRK: W_INFO results does not know any 'year'
155 log.debug("Get WKms from FixationArtifact."); 159 final int year = -1;
156 160 return new WaterlevelData(wkms[idx], year, false, true).filterByRange(from, to);
157 final CalculationResult r = (CalculationResult) fixation.compute(context, ComputeType.ADVANCE, false); 161 }
158 final FixRealizingResult frR = (FixRealizingResult) r.getData(); 162
159 163 // private WaterlevelData fetchBUNDUArtifactWaterlevel(final CallContext
160 // Get W/Q input per gauge for this case. 164 // context, final BUNDUArtifact flys,
161 final FixRealizingAccess fixAccess = new FixRealizingAccess(fixation); 165 // final int idx, final double from, final double to) {
162 final List<Segment> segments = fixAccess.getSegments(); 166 // log.debug("Get WKms from BUNDUArtifact");
163 final boolean isFixRealize = (segments != null && !segments.isEmpty()); 167 //
164 168 // final WKms[] wkms = (WKms[]) flys.getWaterlevelData(context).getData();
165 /* ugly but necessary to keep this logic at least a bit inside the FixRealizing stuff */ 169 //
166 final FixRealizingCalculationExtended calculation = new FixRealizingCalculationExtended(fixAccess); 170 // if (wkms == null || wkms.length == 0) {
167 final int year = calculation.determineMeanYear(); 171 // log.warn("no waterlevels in artifact");
168 172 // return null;
169 // REMARK: same logic as in WaterlevelExporter 173 // }
170 final boolean showAllGauges = isFixRealize; 174 //
171 175 // if (wkms.length < idx + 1) {
172 return new WaterlevelData(frR.getWQKms()[idx], year, showAllGauges, true).filterByRange(from, to); 176 // log.warn("Not enough waterlevels in artifact.");
173 } 177 // return null;
174 178 // }
175 /** 179 //
176 * Fetches the 'year' for a staticXXX-artifact. 180 // // REAMRK: W_INFO results does not know any 'year'
177 * REMARK: actually this should happen inside the staticWKms artifact and eventually in the WKmsFactory, but the code 181 // final int year = -1;
178 * there is already awful and it will also break the old artifact-serialization... 182 // return new WaterlevelData(wkms[idx], year, false, true).filterByRange(from,
179 */ 183 // to);
180 private int fetchStaticWKmsYear(final D4EArtifact staticWKms) { 184 // }
181 185
182 final int colPos = Integer.parseInt(staticWKms.getDataAsString("col_pos")); 186 private WaterlevelData fetchFixationArtifactWaterlevel(final CallContext context,
183 final int wstId = Integer.parseInt(staticWKms.getDataAsString("wst_id")); 187 final AbstractFixBunduArtifact artifact, final int idx, final double from, final double to) {
184 188
185 final WstColumn wstColumn = WstColumnFactory.getWstColumn(wstId, colPos); 189 log.debug("Get WKms from FixationArtifact or BUNDUArtifact.bezugswst");
186 final TimeInterval timeInterval = wstColumn.getTimeInterval(); 190
187 if (timeInterval == null) 191 final Object r = artifact.compute(context, ComputeType.ADVANCE, false);
188 return -1; 192 if (r instanceof CalculationResult) {
189 193 final Object frR = ((CalculationResult) r).getData();
190 final Date startTime = timeInterval.getStartTime(); 194
191 if (startTime == null) 195 ///For BezugsWST
192 return -1; 196 if (frR instanceof BezugswstCalculationResults) {
193 197 List<AbstractCalculationExportableResult> results = ((BezugswstCalculationResults)frR).getResults();
194 // REMARK: the times are stored without timezone in the DB, so it is unclear what hibernate makes of it. 198 BezugswstMainCalculationResult mainResult = this.getBezugsWstMainResultFromList(results);
195 // We simply use the default timezone here and hope we never get problems... 199 if (mainResult!=null) {
196 // Actually we always have 12:00 as time in the db data, so a smal timeshift due to winter/sommertime or UTC/GMT+1 will 200 //Taken FROM BezugswstCalculation
197 // no change anything regarding the year. 201 // We have no wst year as the wst is created by a calculation; we do not need it though
198 final Calendar cal = Calendar.getInstance(); 202 final int wspYear = -1;
199 cal.setTime(startTime); 203 // Remark: showAllGauges true for Fixierungsanalyse, false for WInfo, so true here as well
200 return cal.get(Calendar.YEAR); 204 final boolean showAllGauges = true;
201 } 205 return new WaterlevelData( mainResult.getWQKms() , wspYear, showAllGauges, true)
206 .filterByRange(from, to);
207 }
208 }
209
210 else if (frR instanceof FixRealizingResult) {
211 // Get W/Q input per gauge for this case.
212 final FixRealizingAccess fixAccess = new FixRealizingAccess(artifact);
213 final List<Segment> segments = fixAccess.getSegments();
214 final boolean isFixRealize = (segments != null && !segments.isEmpty());
215
216 /*
217 * ugly but necessary to keep this logic at least a bit inside the FixRealizing
218 * stuff
219 */
220 final FixRealizingCalculationExtended calculation = new FixRealizingCalculationExtended(fixAccess);
221 final int year = calculation.determineMeanYear();
222
223 // REMARK: same logic as in WaterlevelExporter
224 final boolean showAllGauges = isFixRealize;
225
226 return new WaterlevelData(((FixRealizingResult) frR).getWQKms()[idx], year, showAllGauges, true)
227 .filterByRange(from, to);
228 }
229 }
230 return null;
231 }
232
233 private BezugswstMainCalculationResult getBezugsWstMainResultFromList(List<AbstractCalculationExportableResult> results) {
234 for ( Object result : results)
235 if (result instanceof BezugswstMainCalculationResult)
236 return (BezugswstMainCalculationResult) result;
237 return null;
238 }
239
240 /**
241 * Fetches the 'year' for a staticXXX-artifact. REMARK: actually this should
242 * happen inside the staticWKms artifact and eventually in the WKmsFactory, but
243 * the code there is already awful and it will also break the old
244 * artifact-serialization...
245 */
246 private int fetchStaticWKmsYear(final D4EArtifact staticWKms) {
247
248 final int colPos = Integer.parseInt(staticWKms.getDataAsString("col_pos"));
249 final int wstId = Integer.parseInt(staticWKms.getDataAsString("wst_id"));
250
251 final WstColumn wstColumn = WstColumnFactory.getWstColumn(wstId, colPos);
252 final TimeInterval timeInterval = wstColumn.getTimeInterval();
253 if (timeInterval == null)
254 return -1;
255
256 final Date startTime = timeInterval.getStartTime();
257 if (startTime == null)
258 return -1;
259
260 // REMARK: the times are stored without timezone in the DB, so it is unclear
261 // what hibernate makes of it.
262 // We simply use the default timezone here and hope we never get problems...
263 // Actually we always have 12:00 as time in the db data, so a smal timeshift due
264 // to winter/sommertime or UTC/GMT+1 will
265 // no change anything regarding the year.
266 final Calendar cal = Calendar.getInstance();
267 cal.setTime(startTime);
268 return cal.get(Calendar.YEAR);
269 }
202 } 270 }

http://dive4elements.wald.intevation.org