Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/artifacts/CrossSectionArtifact.java @ 9460:8d6e56e57c4a
log-Ausgaben crossSection isStart
author | gernotbelger |
---|---|
date | Wed, 29 Aug 2018 16:57:13 +0200 |
parents | 5e38e2924c07 |
children | da7b5f07303d |
comparison
equal
deleted
inserted
replaced
9459:f06e3766997f | 9460:8d6e56e57c4a |
---|---|
11 import java.util.ArrayList; | 11 import java.util.ArrayList; |
12 import java.util.List; | 12 import java.util.List; |
13 import java.util.NavigableMap; | 13 import java.util.NavigableMap; |
14 | 14 |
15 import org.apache.log4j.Logger; | 15 import org.apache.log4j.Logger; |
16 | 16 import org.dive4elements.artifactdatabase.state.Facet; |
17 import org.w3c.dom.Document; | 17 import org.dive4elements.artifactdatabase.state.FacetActivity; |
18 | 18 import org.dive4elements.artifactdatabase.state.State; |
19 import org.dive4elements.artifacts.Artifact; | 19 import org.dive4elements.artifacts.Artifact; |
20 import org.dive4elements.artifacts.ArtifactFactory; | 20 import org.dive4elements.artifacts.ArtifactFactory; |
21 import org.dive4elements.artifacts.CallMeta; | 21 import org.dive4elements.artifacts.CallMeta; |
22 | |
23 import org.dive4elements.river.artifacts.access.RangeAccess; | 22 import org.dive4elements.river.artifacts.access.RangeAccess; |
24 import org.dive4elements.river.artifacts.model.CrossSectionFacet; | 23 import org.dive4elements.river.artifacts.model.CrossSectionFacet; |
24 import org.dive4elements.river.artifacts.model.CrossSectionFactory; | |
25 import org.dive4elements.river.artifacts.model.FastCrossSectionLineFactory; | 25 import org.dive4elements.river.artifacts.model.FastCrossSectionLineFactory; |
26 | 26 import org.dive4elements.river.artifacts.services.CrossSectionKMService; |
27 import org.dive4elements.river.model.FastCrossSectionLine; | 27 import org.dive4elements.river.artifacts.states.StaticState; |
28 | |
29 import org.dive4elements.river.model.CrossSection; | 28 import org.dive4elements.river.model.CrossSection; |
30 import org.dive4elements.river.model.CrossSectionLine; | 29 import org.dive4elements.river.model.CrossSectionLine; |
31 import org.dive4elements.river.artifacts.model.CrossSectionFactory; | 30 import org.dive4elements.river.model.FastCrossSectionLine; |
32 | 31 import org.w3c.dom.Document; |
33 import org.dive4elements.river.artifacts.states.StaticState; | |
34 | |
35 import org.dive4elements.artifactdatabase.state.Facet; | |
36 import org.dive4elements.artifactdatabase.state.FacetActivity; | |
37 import org.dive4elements.artifactdatabase.state.State; | |
38 | |
39 import org.dive4elements.river.artifacts.services.CrossSectionKMService; | |
40 | |
41 | 32 |
42 /** | 33 /** |
43 * Artifact describing a cross-section. | 34 * Artifact describing a cross-section. |
44 */ | 35 */ |
45 public class CrossSectionArtifact extends StaticD4EArtifact { | 36 public class CrossSectionArtifact extends StaticD4EArtifact { |
58 | 49 |
59 /** Name of data item keeping the database id of this c.s.. */ | 50 /** Name of data item keeping the database id of this c.s.. */ |
60 public static final String DATA_DBID = "cross_section.dbid"; | 51 public static final String DATA_DBID = "cross_section.dbid"; |
61 | 52 |
62 /** Name of data item flagging whether we think that we are master. */ | 53 /** Name of data item flagging whether we think that we are master. */ |
63 public static final String DATA_IS_MASTER = "cross_section.master?"; | 54 private static final String DATA_IS_MASTER = "cross_section.master?"; |
64 | 55 |
65 /** Name of data item flagging whether we are the newest. */ | 56 /** Name of data item flagging whether we are the newest. */ |
66 public static final String DATA_IS_NEWEST = "cross_section.newest?"; | 57 private static final String DATA_IS_NEWEST = "cross_section.newest?"; |
67 | 58 |
68 /** Name of data item storing the previous possible km. */ | 59 /** Name of data item storing the previous possible km. */ |
69 public static final String DATA_PREV_KM = "cross_section.km.previous"; | 60 public static final String DATA_PREV_KM = "cross_section.km.previous"; |
70 | 61 |
71 /** Name of data item storing the next possible km. */ | 62 /** Name of data item storing the next possible km. */ |
72 public static final String DATA_NEXT_KM = "cross_section.km.next"; | 63 public static final String DATA_NEXT_KM = "cross_section.km.next"; |
73 | 64 |
74 /** Own log. */ | 65 /** Own log. */ |
75 private static final Logger log = | 66 private static final Logger log = Logger.getLogger(CrossSectionArtifact.class); |
76 Logger.getLogger(CrossSectionArtifact.class); | |
77 | 67 |
78 static { | 68 static { |
79 // TODO: Move to configuration. | 69 // TODO: Move to configuration. |
80 FacetActivity.Registry.getInstance().register( | 70 FacetActivity.Registry.getInstance().register(CS_ARTIFACT_NAME, new FacetActivity() { |
81 CS_ARTIFACT_NAME, | 71 @Override |
82 new FacetActivity() { | 72 public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String outputName) { |
83 @Override | 73 if (artifact instanceof D4EArtifact) { |
84 public Boolean isInitialActive( | 74 final D4EArtifact flys = (D4EArtifact) artifact; |
85 Artifact artifact, | 75 final String data = flys.getDataAsString(DATA_IS_NEWEST); |
86 Facet facet, | 76 return data != null && data.equals("1"); |
87 String outputName | |
88 ) { | |
89 if (artifact instanceof D4EArtifact) { | |
90 D4EArtifact flys = (D4EArtifact)artifact; | |
91 String data = flys.getDataAsString(DATA_IS_NEWEST); | |
92 return data != null && data.equals("1"); | |
93 } | |
94 return null; | |
95 } | 77 } |
96 }); | 78 return null; |
79 } | |
80 }); | |
97 } | 81 } |
98 | 82 |
99 /** Return given name. */ | 83 /** Return given name. */ |
100 @Override | 84 @Override |
101 public String getName() { | 85 public String getName() { |
102 return CS_ARTIFACT_NAME; | 86 return CS_ARTIFACT_NAME; |
103 } | 87 } |
104 | 88 |
105 | |
106 /** Store ids, create a CrossSectionFacet. */ | 89 /** Store ids, create a CrossSectionFacet. */ |
107 @Override | 90 @Override |
108 public void setup( | 91 public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data, |
109 String identifier, | 92 final List<Class> loadFacets) { |
110 ArtifactFactory factory, | |
111 Object context, | |
112 CallMeta callMeta, | |
113 Document data, | |
114 List<Class> loadFacets) | |
115 { | |
116 log.info("CrossSectionArtifact.setup"); | 93 log.info("CrossSectionArtifact.setup"); |
117 | 94 |
118 super.setup(identifier, factory, context, callMeta, data, loadFacets); | 95 super.setup(identifier, factory, context, callMeta, data, loadFacets); |
119 | 96 |
120 String ids = getDatacageIDValue(data); | 97 final String ids = getDatacageIDValue(data); |
121 | 98 |
122 if (ids != null && ids.length() > 0) { | 99 if (ids != null && ids.length() > 0) { |
123 addStringData(DATA_DBID, ids); | 100 addStringData(DATA_DBID, ids); |
124 log.debug("CrossSectionArtifacts db-id: " + ids); | 101 log.debug("CrossSectionArtifacts db-id: " + ids); |
125 } | 102 } else { |
126 else { | |
127 throw new IllegalArgumentException("No attribute 'ids' found!"); | 103 throw new IllegalArgumentException("No attribute 'ids' found!"); |
128 } | 104 } |
129 | 105 |
130 List<Facet> fs = new ArrayList<Facet>(); | 106 final List<Facet> fs = new ArrayList<>(); |
131 CrossSection cs = CrossSectionFactory.getCrossSection( | 107 final CrossSection cs = CrossSectionFactory.getCrossSection(Integer.parseInt(ids)); |
132 Integer.parseInt(ids)); | 108 |
133 | 109 final List<CrossSectionLine> csls = cs.getLines(); |
134 List<CrossSectionLine> csls = cs.getLines(); | |
135 if (!csls.isEmpty()) { | 110 if (!csls.isEmpty()) { |
136 CrossSectionLine csl = csls.get(0); | 111 final CrossSectionLine csl = csls.get(0); |
137 // Find min-km of cross sections, | 112 // Find min-km of cross sections, |
138 // then set DATA_KM to min(DATA_KM, minCross). | 113 // then set DATA_KM to min(DATA_KM, minCross). |
139 String dataKmValue = getDataAsString(DATA_KM); | 114 final String dataKmValue = getDataAsString(DATA_KM); |
140 double dataKm = (dataKmValue != null) | 115 final double dataKm = (dataKmValue != null) ? Double.valueOf(dataKmValue) : Double.MIN_VALUE; |
141 ? Double.valueOf(dataKmValue) | |
142 : Double.MIN_VALUE; | |
143 if (dataKm < csl.getKm().doubleValue()) { | 116 if (dataKm < csl.getKm().doubleValue()) { |
144 addStringData(DATA_KM, csl.getKm().toString()); | 117 addStringData(DATA_KM, csl.getKm().toString()); |
145 } | 118 } |
146 } | 119 } |
147 fs.add(new CrossSectionFacet(0, cs.getDescription())); | 120 fs.add(new CrossSectionFacet(0, cs.getDescription())); |
148 | 121 |
149 // Find out if we are newest and become master if so. | 122 // Find out if we are newest and become master if so. |
150 boolean isNewest = cs.shouldBeMaster(getParentKm()); | 123 final boolean isNewest = cs.shouldBeMaster(getParentKm()); |
151 String newString = (isNewest) ? "1" : "0"; | 124 final String newString = (isNewest) ? "1" : "0"; |
152 addStringData(DATA_IS_NEWEST, newString); | 125 addStringData(DATA_IS_NEWEST, newString); |
153 addStringData(DATA_IS_MASTER, newString); | 126 addStringData(DATA_IS_MASTER, newString); |
127 final StringBuilder builder = new StringBuilder(); | |
128 builder.append("CrossSectionArtifact line 128 cross_section_id = ").append(cs.getId()).append(" IS_START? : ").append(String.valueOf(isNewest)); | |
129 log.info(builder.toString()); // TODO: remove ALL | |
130 log.debug(builder.toString()); | |
131 log.warn(builder.toString()); | |
154 | 132 |
155 if (!fs.isEmpty()) { | 133 if (!fs.isEmpty()) { |
156 addFacets(getCurrentStateId(), fs); | 134 addFacets(getCurrentStateId(), fs); |
157 } | 135 } |
158 } | 136 } |
159 | 137 |
160 | |
161 /** Copy km where master-artifact "starts". */ | 138 /** Copy km where master-artifact "starts". */ |
162 @Override | 139 @Override |
163 protected void initialize( | 140 protected void initialize(final Artifact master, final Object context, final CallMeta callMeta) { |
164 Artifact master, | 141 final D4EArtifact masterArtifact = (D4EArtifact) master; |
165 Object context, | 142 |
166 CallMeta callMeta) | 143 final RangeAccess rangeAccess = new RangeAccess(masterArtifact); |
167 { | 144 final double[] range = rangeAccess.getKmRange(); |
168 D4EArtifact masterArtifact = (D4EArtifact) master; | |
169 | |
170 RangeAccess rangeAccess = new RangeAccess(masterArtifact); | |
171 double[] range = rangeAccess.getKmRange(); | |
172 if (range != null && range.length > 0) { | 145 if (range != null && range.length > 0) { |
173 this.addStringData(DATA_KM, Double.toString(range[0])); | 146 this.addStringData(DATA_KM, Double.toString(range[0])); |
174 this.addStringData(PARENT_KM, Double.toString(range[0])); | 147 this.addStringData(PARENT_KM, Double.toString(range[0])); |
175 } | 148 } |
176 } | 149 } |
177 | 150 |
178 | |
179 /** Returns next possible km for a cross-section. */ | 151 /** Returns next possible km for a cross-section. */ |
180 public Double getNextKm() { | 152 public Double getNextKm() { |
181 return getDataAsDouble(DATA_NEXT_KM); | 153 return getDataAsDouble(DATA_NEXT_KM); |
182 } | 154 } |
183 | 155 |
184 | |
185 /** Returns previous possible km for a cross-section. */ | 156 /** Returns previous possible km for a cross-section. */ |
186 public Double getPrevKm() { | 157 public Double getPrevKm() { |
187 return getDataAsDouble(DATA_PREV_KM); | 158 return getDataAsDouble(DATA_PREV_KM); |
188 } | 159 } |
189 | 160 |
190 | |
191 /** | 161 /** |
192 * Create and return a new StaticState with charting output. | 162 * Create and return a new StaticState with charting output. |
193 */ | 163 */ |
194 @Override | 164 @Override |
195 public State getCurrentState(Object cc) { | 165 public State getCurrentState(final Object cc) { |
196 final List<Facet> fs = getFacets(getCurrentStateId()); | 166 final List<Facet> fs = getFacets(getCurrentStateId()); |
197 | 167 |
198 StaticState state = new StaticState(STATIC_STATE_NAME) { | 168 final StaticState state = new StaticState(STATIC_STATE_NAME) { |
199 @Override | 169 @Override |
200 public Object staticCompute(List<Facet> facets) { | 170 public Object staticCompute(final List<Facet> facets) { |
201 if (facets != null) { | 171 if (facets != null) { |
202 facets.addAll(fs); | 172 facets.addAll(fs); |
203 } | 173 } |
204 return null; | 174 return null; |
205 } | 175 } |
208 state.addDefaultChartOutput("cross_section", fs); | 178 state.addDefaultChartOutput("cross_section", fs); |
209 | 179 |
210 return state; | 180 return state; |
211 } | 181 } |
212 | 182 |
213 | |
214 /** | 183 /** |
215 * Get a list containing the one and only State. | 184 * Get a list containing the one and only State. |
216 * @param context ignored. | 185 * |
186 * @param context | |
187 * ignored. | |
217 * @return list with one and only state. | 188 * @return list with one and only state. |
218 */ | 189 */ |
219 @Override | 190 @Override |
220 protected List<State> getStates(Object context) { | 191 protected List<State> getStates(final Object context) { |
221 ArrayList<State> states = new ArrayList<State>(); | 192 final ArrayList<State> states = new ArrayList<>(); |
222 states.add(getCurrentState(context)); | 193 states.add(getCurrentState(context)); |
223 | 194 |
224 return states; | 195 return states; |
225 } | 196 } |
226 | 197 |
227 // TODO all data access needs proper caching. | 198 // TODO all data access needs proper caching. |
228 | 199 |
229 /** | 200 /** |
230 * Get a DataItem casted to int (0 if fails). | 201 * Get a DataItem casted to int (0 if fails). |
231 */ | 202 */ |
232 public int getDataAsIntNull(String dataName) { | 203 public int getDataAsIntNull(final String dataName) { |
233 String val = getDataAsString(dataName); | 204 final String val = getDataAsString(dataName); |
234 try { | 205 try { |
235 return Integer.parseInt(val); | 206 return Integer.parseInt(val); |
236 } | 207 } |
237 catch (NumberFormatException e) { | 208 catch (final NumberFormatException e) { |
238 log.warn("Could not get data " + dataName + " as int", e); | 209 log.warn("Could not get data " + dataName + " as int", e); |
239 return 0; | 210 return 0; |
240 } | 211 } |
241 } | 212 } |
242 | |
243 | 213 |
244 /** Returns database-id of cross-section (from data). */ | 214 /** Returns database-id of cross-section (from data). */ |
245 protected int getDBID() { | 215 protected int getDBID() { |
246 return getDataAsIntNull(DATA_DBID); | 216 return getDataAsIntNull(DATA_DBID); |
247 } | 217 } |
248 | 218 |
249 | |
250 /** | 219 /** |
251 * Return position (km) from parent (initial km), 0 if not found. | 220 * Return position (km) from parent (initial km), 0 if not found. |
252 */ | 221 */ |
253 private double getParentKm() { | 222 private double getParentKm() { |
254 String val = getDataAsString(PARENT_KM); | 223 final String val = getDataAsString(PARENT_KM); |
255 if (val == null) { | 224 if (val == null) { |
256 log.warn("Empty data: " + PARENT_KM); | 225 log.warn("Empty data: " + PARENT_KM); |
257 return 0; | 226 return 0; |
258 } | 227 } |
259 try { | 228 try { |
260 return Double.valueOf(val); | 229 return Double.valueOf(val); |
261 } | 230 } |
262 catch (NumberFormatException e) { | 231 catch (final NumberFormatException e) { |
263 log.warn("Could not get data " + PARENT_KM + " as double", e); | 232 log.warn("Could not get data " + PARENT_KM + " as double", e); |
264 return 0; | 233 return 0; |
265 } | 234 } |
266 } | 235 } |
267 | 236 |
268 /** | 237 /** |
269 * Return position (km) from data, 0 if not found. | 238 * Return position (km) from data, 0 if not found. |
270 */ | 239 */ |
271 protected double getKm() { | 240 protected double getKm() { |
272 String val = getDataAsString(DATA_KM); | 241 final String val = getDataAsString(DATA_KM); |
273 try { | 242 try { |
274 return Double.valueOf(val); | 243 return Double.valueOf(val); |
275 } | 244 } |
276 catch (NumberFormatException e) { | 245 catch (final NumberFormatException e) { |
277 log.warn("Could not get data " + DATA_KM + " as double", e); | 246 log.warn("Could not get data " + DATA_KM + " as double", e); |
278 return 0; | 247 return 0; |
279 } | 248 } |
280 } | 249 } |
281 | 250 |
282 | 251 /** |
283 /** Returns true if artifact is set to be a "master" (other facets will | 252 * Returns true if artifact is set to be a "master" (other facets will |
284 * refer to this). */ | 253 * refer to this). |
254 */ | |
285 public boolean isMaster() { | 255 public boolean isMaster() { |
286 return !getDataAsString(DATA_IS_MASTER).equals("0"); | 256 return !getDataAsString(DATA_IS_MASTER).equals("0"); |
287 } | 257 } |
288 | |
289 | 258 |
290 /** | 259 /** |
291 * Get points of Profile of cross section at given kilometer. | 260 * Get points of Profile of cross section at given kilometer. |
292 * | 261 * |
293 * @return an array holding coordinates of points of profile ( | 262 * @return an array holding coordinates of points of profile ( |
294 * in the form {{x1, x2} {y1, y2}} ). | 263 * in the form {{x1, x2} {y1, y2}} ). |
295 */ | 264 */ |
296 public double [][] getCrossSectionData() { | 265 public double[][] getCrossSectionData() { |
297 log.info("getCrossSectionData() for cross_section.km " | 266 log.info("getCrossSectionData() for cross_section.km " + getDataAsString(DATA_KM)); |
298 + getDataAsString(DATA_KM)); | 267 final FastCrossSectionLine line = searchCrossSectionLine(); |
299 FastCrossSectionLine line = searchCrossSectionLine(); | 268 |
300 | 269 return line != null ? line.fetchCrossSectionProfile() : null; |
301 return line != null | 270 } |
302 ? line.fetchCrossSectionProfile() | |
303 : null; | |
304 } | |
305 | |
306 | 271 |
307 /** | 272 /** |
308 * Get CrossSectionLine spatially closest to what is specified in the data | 273 * Get CrossSectionLine spatially closest to what is specified in the data |
309 * "cross_section.km", null if considered too far. | 274 * "cross_section.km", null if considered too far. |
310 * | 275 * |
313 * | 278 * |
314 * @return CrossSectionLine closest to "cross_section.km", might be null | 279 * @return CrossSectionLine closest to "cross_section.km", might be null |
315 * if considered too far. | 280 * if considered too far. |
316 */ | 281 */ |
317 public FastCrossSectionLine searchCrossSectionLine() { | 282 public FastCrossSectionLine searchCrossSectionLine() { |
318 double TOO_FAR = 1d; | 283 final double TOO_FAR = 1d; |
319 CrossSection crossSection = CrossSectionFactory | 284 final CrossSection crossSection = CrossSectionFactory.getCrossSection(getDBID()); |
320 .getCrossSection(getDBID()); | |
321 | 285 |
322 if (log.isDebugEnabled()) { | 286 if (log.isDebugEnabled()) { |
323 log.debug("dbid " + getDBID() + " : " + crossSection); | 287 log.debug("dbid " + getDBID() + " : " + crossSection); |
324 } | 288 } |
325 | 289 |
326 NavigableMap<Double, Integer> kms = CrossSectionKMService | 290 final NavigableMap<Double, Integer> kms = CrossSectionKMService.getKms(crossSection.getId()); |
327 .getKms(crossSection.getId()); | 291 |
328 | 292 final Double wishKM = getKm(); |
329 Double wishKM = getKm(); | 293 |
330 | 294 final Double floor = kms.floorKey(wishKM); |
331 Double floor = kms.floorKey(wishKM); | 295 final Double ceil = kms.ceilingKey(wishKM); |
332 Double ceil = kms.ceilingKey(wishKM); | |
333 | 296 |
334 Double nextKm; | 297 Double nextKm; |
335 Double prevKm; | 298 Double prevKm; |
336 | 299 |
337 double floorD = floor != null | 300 final double floorD = floor != null ? Math.abs(floor - wishKM) : Double.MAX_VALUE; |
338 ? Math.abs(floor - wishKM) | 301 |
339 : Double.MAX_VALUE; | 302 final double ceilD = ceil != null ? Math.abs(ceil - wishKM) : Double.MAX_VALUE; |
340 | |
341 double ceilD = ceil != null | |
342 ? Math.abs(ceil - wishKM) | |
343 : Double.MAX_VALUE; | |
344 | 303 |
345 double km; | 304 double km; |
346 if (floorD < ceilD) { | 305 if (floorD < ceilD) { |
347 km = floor; | 306 km = floor; |
348 } | 307 } else { |
349 else { | |
350 km = ceil; | 308 km = ceil; |
351 } | 309 } |
352 | 310 |
353 // If we are too far from the wished km, return null. | 311 // If we are too far from the wished km, return null. |
354 if (Math.abs(km - wishKM) > TOO_FAR) { | 312 if (Math.abs(km - wishKM) > TOO_FAR) { |
367 } | 325 } |
368 | 326 |
369 addStringData(DATA_PREV_KM, prevKm.toString()); | 327 addStringData(DATA_PREV_KM, prevKm.toString()); |
370 addStringData(DATA_NEXT_KM, nextKm.toString()); | 328 addStringData(DATA_NEXT_KM, nextKm.toString()); |
371 | 329 |
372 return FastCrossSectionLineFactory | 330 return FastCrossSectionLineFactory.getCrossSectionLine(crossSection, km); |
373 .getCrossSectionLine(crossSection, km); | |
374 } | 331 } |
375 } | 332 } |
376 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : | 333 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |