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 :

http://dive4elements.wald.intevation.org