Mercurial > dive4elements > river
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 } |