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 :

http://dive4elements.wald.intevation.org