Mercurial > dive4elements > river
comparison flys-client/src/main/java/org/dive4elements/river/client/server/ArtifactDescriptionFactory.java @ 5834:f507086aa94b
Repaired internal references.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Thu, 25 Apr 2013 12:31:32 +0200 |
parents | flys-client/src/main/java/de/intevation/flys/client/server/ArtifactDescriptionFactory.java@f6c73ee1b7f1 |
children | 821a02bbfb4e |
comparison
equal
deleted
inserted
replaced
5833:a2bdc0f524e8 | 5834:f507086aa94b |
---|---|
1 package de.intevation.flys.client.server; | |
2 | |
3 import java.util.ArrayList; | |
4 import java.util.List; | |
5 | |
6 import javax.xml.xpath.XPathConstants; | |
7 | |
8 import org.w3c.dom.Document; | |
9 import org.w3c.dom.Element; | |
10 import org.w3c.dom.Node; | |
11 import org.w3c.dom.NodeList; | |
12 | |
13 import org.apache.log4j.Logger; | |
14 | |
15 import de.intevation.artifacts.common.ArtifactNamespaceContext; | |
16 import de.intevation.artifacts.common.utils.ClientProtocolUtils; | |
17 import de.intevation.artifacts.common.utils.XMLUtils; | |
18 | |
19 import de.intevation.flys.client.shared.model.ArtifactDescription; | |
20 import de.intevation.flys.client.shared.model.DataItem; | |
21 import de.intevation.flys.client.shared.model.DataList; | |
22 import de.intevation.flys.client.shared.model.DefaultArtifactDescription; | |
23 import de.intevation.flys.client.shared.model.DefaultData; | |
24 import de.intevation.flys.client.shared.model.DefaultDataItem; | |
25 import de.intevation.flys.client.shared.model.DefaultOutputMode; | |
26 import de.intevation.flys.client.shared.model.DoubleArrayData; | |
27 import de.intevation.flys.client.shared.model.DoubleRangeData; | |
28 import de.intevation.flys.client.shared.model.IntegerArrayData; | |
29 import de.intevation.flys.client.shared.model.IntegerRangeData; | |
30 import de.intevation.flys.client.shared.model.IntegerOptionsData; | |
31 import de.intevation.flys.client.shared.model.LongRangeData; | |
32 import de.intevation.flys.client.shared.model.OutputMode; | |
33 import de.intevation.flys.client.shared.model.Recommendation; | |
34 import de.intevation.flys.client.shared.model.WQDataItem; | |
35 | |
36 | |
37 /** | |
38 * This factory class helps creating an {@link ArtifactDescription} based on the | |
39 * DESCRIBE document of an artifact returned by the artifact server. Use the | |
40 * {@link createArtifactDescription(org.w3c.dom.Document)} method with the | |
41 * DESCRIBE document to create such an {@link ArtifactDescription}. | |
42 * | |
43 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | |
44 */ | |
45 public class ArtifactDescriptionFactory { | |
46 | |
47 private static final Logger logger = | |
48 Logger.getLogger(ArtifactDescriptionFactory.class); | |
49 | |
50 | |
51 public static final String XPATH_STATE_NAME = "@art:name"; | |
52 | |
53 public static final String XPATH_UIPROVIDER = "@art:uiprovider"; | |
54 | |
55 public static final String XPATH_HELP_TEXT = "@art:helpText"; | |
56 | |
57 public static final String XPATH_REACHABLE_STATE = "art:state"; | |
58 | |
59 public static final String XPATH_STATIC_STATE_NODE = "art:state"; | |
60 | |
61 public static final String XPATH_STATIC_DATA_NODE = "art:data"; | |
62 | |
63 public static final String XPATH_STATIC_ITEM_NODE = "art:item"; | |
64 | |
65 public static final String XPATH_RECOMMENDED_ARTIFACTS = | |
66 "/art:result/art:recommended-artifacts//*[@factory]"; | |
67 | |
68 /** | |
69 * This method creates the {@link ArtifactDescription} of the DESCRIBE | |
70 * document <i>doc</i>. | |
71 * | |
72 * @param doc A DESCRIBE document. | |
73 * | |
74 * @return the {@link ArtifactDescription}. | |
75 */ | |
76 public static ArtifactDescription createArtifactDescription(Document doc) { | |
77 logger.debug("ArtifactDescriptionFactory.createArtifactDescription"); | |
78 | |
79 Node currentState = ClientProtocolUtils.getCurrentState(doc); | |
80 Node staticNode = ClientProtocolUtils.getStaticUI(doc); | |
81 Node dynamicNode = ClientProtocolUtils.getDynamicUI(doc); | |
82 Node reachable = ClientProtocolUtils.getReachableStates(doc); | |
83 NodeList outputs = ClientProtocolUtils.getOutputModes(doc); | |
84 | |
85 String state = (String) XMLUtils.xpath( | |
86 currentState, | |
87 XPATH_STATE_NAME, | |
88 XPathConstants.STRING, | |
89 ArtifactNamespaceContext.INSTANCE); | |
90 | |
91 logger.debug("Current state name: " + state); | |
92 | |
93 DataList currentData = extractCurrentData(dynamicNode, state); | |
94 DataList[] old = extractOldData(staticNode); | |
95 String[] states = extractReachableStates(reachable); | |
96 OutputMode[] outs = extractOutputModes(outputs); | |
97 Recommendation[] rec = extractRecommendedArtifacts(doc); | |
98 | |
99 return new DefaultArtifactDescription( | |
100 old, | |
101 currentData, | |
102 state, | |
103 states, | |
104 outs, | |
105 rec); | |
106 } | |
107 | |
108 | |
109 /** | |
110 * This method extracts the data that the user is able to enter in the | |
111 * current state of the artifact. | |
112 * | |
113 * @param dynamicNode The dynamic node of the DESCRIBE document. | |
114 * @param state The name of the current state. | |
115 * | |
116 * @return A {@link Data} object that represents the data which might be | |
117 * entered by the user in the current state or null, if no data might be | |
118 * entered. | |
119 */ | |
120 protected static DataList extractCurrentData(Node dynamicNode, String state) { | |
121 logger.debug("ArtifactDescriptionFactory.extractCurrentData"); | |
122 | |
123 NodeList data = ClientProtocolUtils.getSelectNode(dynamicNode); | |
124 String help = extractHelpText(dynamicNode); | |
125 String uiProvider = extractUIProvider(dynamicNode); | |
126 | |
127 if (data == null || data.getLength() == 0) { | |
128 return null; | |
129 } | |
130 | |
131 int dataNum = data.getLength(); | |
132 DataList list = new DataList(state, dataNum, uiProvider, null, help); | |
133 | |
134 for (int i = 0; i < dataNum; i++) { | |
135 Element d = (Element) data.item(i); | |
136 String label = ClientProtocolUtils.getLabel(d); | |
137 String name = XMLUtils.xpathString( | |
138 d, "@art:name", ArtifactNamespaceContext.INSTANCE); | |
139 String type = XMLUtils.xpathString( | |
140 d, "@art:type", ArtifactNamespaceContext.INSTANCE); | |
141 | |
142 logger.debug("Create new IntegerRangeData object for: " + name); | |
143 logger.debug("New Data is from type: " + type); | |
144 | |
145 // TODO replace with DataFactory. | |
146 | |
147 if (type == null || type.length() == 0) { | |
148 NodeList choices = ClientProtocolUtils.getItemNodes(d); | |
149 DataItem[] dataItems = extractCurrentDataItems(choices); | |
150 DataItem def = extractDefaultDataItem(d); | |
151 | |
152 list.add(new DefaultData(name, label, null, dataItems, def)); | |
153 } | |
154 else if (type.equals("intrange")) { | |
155 String min = ClientProtocolUtils.getMinNode(d); | |
156 String max = ClientProtocolUtils.getMaxNode(d); | |
157 | |
158 String defMin = ClientProtocolUtils.getDefMin(d); | |
159 String defMax = ClientProtocolUtils.getDefMax(d); | |
160 | |
161 try { | |
162 int lower = Integer.parseInt(min); | |
163 int upper = Integer.parseInt(max); | |
164 | |
165 if (defMin != null && defMax != null) { | |
166 list.add(new IntegerRangeData( | |
167 name, label, | |
168 lower, upper, | |
169 Integer.parseInt(defMin), | |
170 Integer.parseInt(defMax))); | |
171 } | |
172 else { | |
173 list.add( | |
174 new IntegerRangeData(name, label, lower, upper)); | |
175 } | |
176 } | |
177 catch (NumberFormatException nfe) { | |
178 logger.warn("NumberFormatException: ", nfe); | |
179 } | |
180 } | |
181 else if (type.equals("longrange")) { | |
182 String min = ClientProtocolUtils.getMinNode(d); | |
183 String max = ClientProtocolUtils.getMaxNode(d); | |
184 | |
185 String defMin = ClientProtocolUtils.getDefMin(d); | |
186 String defMax = ClientProtocolUtils.getDefMax(d); | |
187 | |
188 try { | |
189 long lower = Long.valueOf(min); | |
190 long upper = Long.valueOf(max); | |
191 | |
192 if (defMin != null && defMax != null) { | |
193 list.add(new LongRangeData( | |
194 name, label, | |
195 lower, upper, | |
196 Long.valueOf(defMin), | |
197 Long.valueOf(defMax))); | |
198 } | |
199 } | |
200 catch (NumberFormatException nfe) { | |
201 logger.warn("NumberFormatException: ", nfe); | |
202 } | |
203 } | |
204 else if (type.equals("intarray")) { | |
205 list.add(new IntegerArrayData(name, label, null)); | |
206 } | |
207 else if (type.equals("intoptions") && uiProvider.equals("parameter-matrix")) { | |
208 list.add(DataFactory.createIntegerOptionsData(d, name, label)); | |
209 } | |
210 else if (type.equals("options")) { | |
211 list.add(DataFactory.createStringOptionsData(d, name, label)); | |
212 } | |
213 else if (type.equals("intoptions")) { | |
214 NodeList choices = ClientProtocolUtils.getItemNodes(d); | |
215 DataItem[] opts = extractCurrentDataItems(choices); | |
216 | |
217 list.add(new IntegerOptionsData(name, label, opts)); | |
218 } | |
219 else if (type.equals("doublearray")) { | |
220 list.add(new DoubleArrayData(name, label, null)); | |
221 } | |
222 else { | |
223 logger.warn("Unrecognized Dynamic data type."); | |
224 NodeList choices = ClientProtocolUtils.getItemNodes(d); | |
225 DataItem[] dataItems = extractCurrentDataItems(choices); | |
226 DataItem def = extractDefaultDataItem(d); | |
227 | |
228 String min = ClientProtocolUtils.getMinNode(d); | |
229 String max = ClientProtocolUtils.getMaxNode(d); | |
230 if (min != null && max != null) { | |
231 list.add(new DoubleRangeData( | |
232 name, label, | |
233 Double.valueOf(min), Double.valueOf(max), | |
234 Double.valueOf(min), Double.valueOf(max))); | |
235 } | |
236 | |
237 list.add(new DefaultData(name, label, null, dataItems, def)); | |
238 } | |
239 | |
240 } | |
241 | |
242 return list; | |
243 } | |
244 | |
245 | |
246 /** | |
247 * This method extracts the default value of a Data object. | |
248 * | |
249 * @param data The data object node. | |
250 * | |
251 * @return the default DataItem. | |
252 */ | |
253 protected static DataItem extractDefaultDataItem(Node data) { | |
254 logger.debug("ArtifactDescriptionFactory.extractDefaultDataItem"); | |
255 | |
256 String value = XMLUtils.xpathString( | |
257 data, "@art:defaultValue", ArtifactNamespaceContext.INSTANCE); | |
258 | |
259 String label = XMLUtils.xpathString( | |
260 data, "@art:defaultLabel", ArtifactNamespaceContext.INSTANCE); | |
261 | |
262 if (value != null && label != null) { | |
263 return new DefaultDataItem(label, null, value); | |
264 } | |
265 | |
266 return null; | |
267 } | |
268 | |
269 | |
270 /** | |
271 * This method extract the {@link DataItem}s of the DESCRIBE document. | |
272 * | |
273 * @param items The items in the DESCRIBE document. | |
274 * | |
275 * @return the {@link DataItem}s. | |
276 */ | |
277 protected static DataItem[] extractCurrentDataItems(NodeList items) { | |
278 logger.debug("ArtifactDescriptionFactory.extractCurrentDataItems"); | |
279 | |
280 if (items == null || items.getLength() == 0) { | |
281 logger.debug("No data items found."); | |
282 return null; | |
283 } | |
284 | |
285 int count = items.getLength(); | |
286 | |
287 List<DataItem> dataItems = new ArrayList<DataItem>(count); | |
288 | |
289 for (int i = 0; i < count; i++) { | |
290 Node item = items.item(i); | |
291 String label = ClientProtocolUtils.getLabel(item); | |
292 String value = ClientProtocolUtils.getValue(item); | |
293 | |
294 double[] mmQ = extractMinMaxQValues(item); | |
295 double[] mmW = extractMinMaxWValues(item); | |
296 | |
297 if (mmQ != null || mmW != null) { | |
298 dataItems.add(new WQDataItem(label, null, value, mmQ, mmW)); | |
299 } | |
300 else { | |
301 dataItems.add(new DefaultDataItem(label, null, value)); | |
302 } | |
303 } | |
304 | |
305 return dataItems.toArray(new DataItem[count]); | |
306 } | |
307 | |
308 | |
309 protected static double[] extractMinMaxQValues(Node item) { | |
310 logger.debug("ArtifactDescriptionFactory.extractMinMaxQValues"); | |
311 | |
312 if (item == null) { | |
313 logger.debug("This node is empty - no min/max Q values."); | |
314 return null; | |
315 } | |
316 | |
317 Node node = (Node) XMLUtils.xpath( | |
318 item, | |
319 "art:range[@art:type='Q']", | |
320 XPathConstants.NODE, | |
321 ArtifactNamespaceContext.INSTANCE); | |
322 | |
323 if (node == null) { | |
324 logger.debug("No min/max Q values found."); | |
325 return null; | |
326 } | |
327 | |
328 return extractMinMaxValues(node); | |
329 } | |
330 | |
331 | |
332 protected static double[] extractMinMaxWValues(Node item) { | |
333 logger.debug("ArtifactDescriptionFactory.extractMinMaxWValues"); | |
334 | |
335 if (item == null) { | |
336 logger.debug("This node is empty - no min/max W values."); | |
337 return null; | |
338 } | |
339 | |
340 Node node = (Node) XMLUtils.xpath( | |
341 item, | |
342 "art:range[@art:type='W']", | |
343 XPathConstants.NODE, | |
344 ArtifactNamespaceContext.INSTANCE); | |
345 | |
346 if (node == null) { | |
347 logger.debug("No min/max W values found."); | |
348 return null; | |
349 } | |
350 | |
351 return extractMinMaxValues(node); | |
352 } | |
353 | |
354 | |
355 protected static double[] extractMinMaxValues(Node node) { | |
356 logger.debug("ArtifactDescriptionFactory.extractMinMaxValues"); | |
357 | |
358 String minStr = XMLUtils.xpathString( | |
359 node, "art:min/text()", ArtifactNamespaceContext.INSTANCE); | |
360 | |
361 String maxStr = XMLUtils.xpathString( | |
362 node, "art:max/text()", ArtifactNamespaceContext.INSTANCE); | |
363 | |
364 if (maxStr == null || minStr == null) { | |
365 logger.debug("No min/max values found."); | |
366 return null; | |
367 } | |
368 | |
369 try { | |
370 double min = Double.valueOf(minStr); | |
371 double max = Double.valueOf(maxStr); | |
372 | |
373 return new double[] { min, max }; | |
374 } | |
375 catch (NumberFormatException nfe) { | |
376 logger.debug("Error while parsing min/max values."); | |
377 } | |
378 | |
379 return null; | |
380 } | |
381 | |
382 | |
383 /** | |
384 * This method extracts the data objects from the data node of the static ui | |
385 * part of the DESCRIBE document. | |
386 * | |
387 * @param staticNode The static ui node of the DESCRIBE. | |
388 * | |
389 * @return the DataList objects. | |
390 */ | |
391 protected static DataList[] extractOldData(Node staticNode) { | |
392 logger.debug("ArtifactDescriptionFactory.extractOldData()"); | |
393 | |
394 NodeList stateNodes = (NodeList) XMLUtils.xpath( | |
395 staticNode, | |
396 XPATH_STATIC_STATE_NODE, | |
397 XPathConstants.NODESET, | |
398 ArtifactNamespaceContext.INSTANCE); | |
399 | |
400 if (stateNodes == null || stateNodes.getLength() == 0) { | |
401 logger.debug("No old items found."); | |
402 return null; | |
403 } | |
404 | |
405 int count = stateNodes.getLength(); | |
406 DataList[] data = new DataList[count]; | |
407 | |
408 for (int i = 0; i < count; i++) { | |
409 Node tmp = stateNodes.item(i); | |
410 | |
411 String name = XMLUtils.xpathString( | |
412 tmp, "@art:name", ArtifactNamespaceContext.INSTANCE); | |
413 String uiprovider = XMLUtils.xpathString( | |
414 tmp, "@art:uiprovider", ArtifactNamespaceContext.INSTANCE); | |
415 String label = XMLUtils.xpathString( | |
416 tmp, "@art:label", ArtifactNamespaceContext.INSTANCE); | |
417 String help = XMLUtils.xpathString( | |
418 tmp, "@art:helpText", ArtifactNamespaceContext.INSTANCE); | |
419 | |
420 NodeList dataNodes = (NodeList) XMLUtils.xpath( | |
421 tmp, | |
422 XPATH_STATIC_DATA_NODE, | |
423 XPathConstants.NODESET, | |
424 ArtifactNamespaceContext.INSTANCE); | |
425 | |
426 if (dataNodes == null || dataNodes.getLength() == 0) { | |
427 continue; | |
428 } | |
429 | |
430 int size = dataNodes.getLength(); | |
431 DataList list = new DataList(name, size, uiprovider, label, help); | |
432 | |
433 for (int j = 0; j < size; j++) { | |
434 Node dataNode = dataNodes.item(j); | |
435 | |
436 list.add(DataFactory.createDataFromElement((Element) dataNode)); | |
437 | |
438 data[i] = list; | |
439 } | |
440 } | |
441 | |
442 return data; | |
443 } | |
444 | |
445 | |
446 /** | |
447 * This method extracts the UIProvider specified by the data node. | |
448 * | |
449 * @param data The data node. | |
450 * | |
451 * @return the UIProvider that is specified in the data node. | |
452 */ | |
453 protected static String extractUIProvider(Node ui) { | |
454 return (String) XMLUtils.xpath( | |
455 ui, | |
456 XPATH_UIPROVIDER, | |
457 XPathConstants.STRING, | |
458 ArtifactNamespaceContext.INSTANCE); | |
459 } | |
460 | |
461 | |
462 /** | |
463 * This method extracts the help text specified by the data node. | |
464 * | |
465 * @param ui The data node. | |
466 * | |
467 * @return the help text. | |
468 */ | |
469 protected static String extractHelpText(Node ui) { | |
470 return (String) XMLUtils.xpath( | |
471 ui, | |
472 XPATH_HELP_TEXT, | |
473 XPathConstants.STRING, | |
474 ArtifactNamespaceContext.INSTANCE); | |
475 } | |
476 | |
477 | |
478 /** | |
479 * This method extracts the reachable states of the current artifact. | |
480 * | |
481 * @param reachable The reachable states node. | |
482 * | |
483 * @return an array with identifiers of reachable states. | |
484 */ | |
485 protected static String[] extractReachableStates(Node reachable) { | |
486 logger.debug("ArtifactDescriptionFactory.extractReachableStates()"); | |
487 | |
488 NodeList list = (NodeList) XMLUtils.xpath( | |
489 reachable, | |
490 XPATH_REACHABLE_STATE, | |
491 XPathConstants.NODESET, | |
492 ArtifactNamespaceContext.INSTANCE); | |
493 | |
494 if (list == null || list.getLength() == 0) { | |
495 return null; | |
496 } | |
497 | |
498 int count = list.getLength(); | |
499 | |
500 String[] states = new String[count]; | |
501 | |
502 for (int i = 0; i < count; i++) { | |
503 Node state = list.item(i); | |
504 | |
505 String name = XMLUtils.xpathString( | |
506 state, "@art:name", ArtifactNamespaceContext.INSTANCE); | |
507 | |
508 states[i] = name; | |
509 } | |
510 | |
511 return states; | |
512 } | |
513 | |
514 | |
515 /** | |
516 * This method extract available output modes of the the current artifact. | |
517 * | |
518 * @param outputs A list of nodes that contain information about output | |
519 * modes. | |
520 * | |
521 * @return an array of Output modes. | |
522 */ | |
523 protected static OutputMode[] extractOutputModes(NodeList outputs) { | |
524 logger.debug("ArtifactDescriptionFactory.extractOutputModes"); | |
525 | |
526 if (outputs == null || outputs.getLength() == 0) { | |
527 return null; | |
528 } | |
529 | |
530 int size = outputs.getLength(); | |
531 | |
532 List<OutputMode> outs = new ArrayList<OutputMode>(size); | |
533 | |
534 for (int i = 0; i < size; i++) { | |
535 Node out = outputs.item(i); | |
536 | |
537 String name = XMLUtils.xpathString( | |
538 out, "@art:name", ArtifactNamespaceContext.INSTANCE); | |
539 String desc = XMLUtils.xpathString( | |
540 out, "@art:description", ArtifactNamespaceContext.INSTANCE); | |
541 String mimeType = XMLUtils.xpathString( | |
542 out, "@art:mime-type", ArtifactNamespaceContext.INSTANCE); | |
543 | |
544 if (name != null) { | |
545 outs.add(new DefaultOutputMode(name, desc, mimeType)); | |
546 } | |
547 else { | |
548 logger.debug("Found an invalid output mode."); | |
549 } | |
550 } | |
551 | |
552 return (OutputMode[]) outs.toArray(new OutputMode[size]); | |
553 } | |
554 | |
555 | |
556 protected static Recommendation[] extractRecommendedArtifacts(Document doc){ | |
557 logger.debug("ArtifactDescriptionFactory.extractRecommendedArtifacts."); | |
558 | |
559 NodeList list = (NodeList) XMLUtils.xpath( | |
560 doc, | |
561 XPATH_RECOMMENDED_ARTIFACTS, | |
562 XPathConstants.NODESET, | |
563 ArtifactNamespaceContext.INSTANCE); | |
564 | |
565 int num = list != null ? list.getLength() : 0; | |
566 | |
567 Recommendation[] rec = new Recommendation[num]; | |
568 | |
569 for (int i = 0; i < num; i++) { | |
570 Element e = (Element) list.item(i); | |
571 String factory = e.getAttribute("factory"); | |
572 String index = e.getAttribute("ids"); | |
573 | |
574 if (factory != null && factory.length() > 0) { | |
575 rec[i] = new Recommendation(factory, index); | |
576 } | |
577 } | |
578 | |
579 return rec; | |
580 } | |
581 } | |
582 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |