Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java @ 875:5e9efdda6894
merged gnv-artifacts/1.0
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:13:56 +0200 |
parents | dfd02f8d3602 |
children | c07d9f9a738c |
comparison
equal
deleted
inserted
replaced
722:bb3ffe7d719e | 875:5e9efdda6894 |
---|---|
1 package de.intevation.gnv.state; | |
2 | |
3 import java.text.DateFormat; | |
4 import java.text.SimpleDateFormat; | |
5 | |
6 import java.util.ArrayList; | |
7 import java.util.Arrays; | |
8 import java.util.Collection; | |
9 import java.util.Date; | |
10 import java.util.GregorianCalendar; | |
11 import java.util.HashMap; | |
12 import java.util.Iterator; | |
13 import java.util.List; | |
14 import java.util.Locale; | |
15 import java.util.Map; | |
16 | |
17 import javax.xml.xpath.XPathConstants; | |
18 | |
19 import net.sf.ehcache.Cache; | |
20 | |
21 import org.apache.log4j.Logger; | |
22 import org.w3c.dom.Document; | |
23 import org.w3c.dom.Element; | |
24 import org.w3c.dom.Node; | |
25 import org.w3c.dom.NodeList; | |
26 | |
27 import de.intevation.artifactdatabase.Config; | |
28 import de.intevation.artifactdatabase.XMLUtils; | |
29 import de.intevation.artifacts.ArtifactNamespaceContext; | |
30 import de.intevation.artifacts.CallContext; | |
31 import de.intevation.artifacts.CallMeta; | |
32 import de.intevation.gnv.artifacts.cache.CacheFactory; | |
33 import de.intevation.gnv.artifacts.ressource.RessourceFactory; | |
34 import de.intevation.gnv.geobackend.base.Result; | |
35 import de.intevation.gnv.geobackend.base.query.QueryExecutor; | |
36 import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory; | |
37 import de.intevation.gnv.geobackend.base.query.exception.QueryException; | |
38 import de.intevation.gnv.geobackend.util.DateUtils; | |
39 import de.intevation.gnv.state.describedata.DefaultKeyValueDescribeData; | |
40 import de.intevation.gnv.state.describedata.KeyValueDescibeData; | |
41 import de.intevation.gnv.state.describedata.MinMaxDescribeData; | |
42 import de.intevation.gnv.state.describedata.NamedArrayList; | |
43 import de.intevation.gnv.state.describedata.NamedCollection; | |
44 import de.intevation.gnv.state.describedata.SingleValueDescribeData; | |
45 import de.intevation.gnv.state.exception.StateException; | |
46 import de.intevation.gnv.utils.ArtifactXMLUtilities; | |
47 import de.intevation.gnv.utils.InputValidator; | |
48 | |
49 /** | |
50 * This is the major implementation of <code>State</code>. Nearly every other | |
51 * state is derived by this class. | |
52 * | |
53 * @author <a href="mailto:tim.englich@intevation.de">Tim Englich</a> | |
54 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | |
55 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> | |
56 */ | |
57 public abstract class StateBase implements State { | |
58 | |
59 /** | |
60 * The UID of this Class | |
61 */ | |
62 private static final long serialVersionUID = 2411169179001645426L; | |
63 | |
64 /** | |
65 * the logger, used to log exceptions and additonaly information | |
66 */ | |
67 private static Logger log = Logger.getLogger(StateBase.class); | |
68 | |
69 protected final static String MINVALUEFIELDNAME = "minvalue"; | |
70 | |
71 protected final static String MAXVALUEFIELDNAME = "maxvalue"; | |
72 | |
73 private final static String NODATASELECTIONKEY = "n/n"; | |
74 | |
75 public final static String DESCRIBEDATAKEY = "_DESCRIBEDATA"; | |
76 | |
77 public final static String XPATH_STATIC_UI = "art:static"; | |
78 | |
79 public final static String XPATH_DYNAMIC_UI = "art:dynamic"; | |
80 | |
81 public static final String EXCEPTION_NO_INPUT = "no.input.data"; | |
82 | |
83 public static final String EXCEPTION_INVALID_INPUT = | |
84 "input.is.not.valid"; | |
85 | |
86 public final static String HASH_ID_SEPARATOR = "#"; | |
87 | |
88 /** input value names which should not be rendered from State itself */ | |
89 public final static String[] BLACKLIST = {"sourceid", "fisname"}; | |
90 | |
91 private String id = null; | |
92 | |
93 protected String hash; | |
94 | |
95 private String description = null; | |
96 | |
97 protected String dataName = null; | |
98 | |
99 protected String preSettingsName = null; | |
100 | |
101 protected boolean dataMultiSelect = false; | |
102 | |
103 protected boolean dataNoSelect = false; | |
104 | |
105 protected String queryID = null; | |
106 | |
107 protected Collection<String> inputValueNames = null; | |
108 | |
109 protected Map<String, InputValue> inputValues = null; | |
110 | |
111 protected State parent = null; | |
112 | |
113 protected Map<String, InputData> inputData = null; | |
114 | |
115 protected Map<String, InputData> preSettings = null; | |
116 | |
117 | |
118 /** | |
119 * The source date format as string. | |
120 */ | |
121 public static String srcDateFormat = "yyyy.MM.dd hh:mm:ss"; | |
122 | |
123 | |
124 /** | |
125 * The source date format used to read string represented strings. | |
126 */ | |
127 public static DateFormat srcFormat; | |
128 | |
129 | |
130 static { | |
131 srcFormat = new SimpleDateFormat(srcDateFormat); | |
132 } | |
133 | |
134 | |
135 /** | |
136 * Constructor | |
137 */ | |
138 public StateBase() { | |
139 super(); | |
140 } | |
141 | |
142 | |
143 public String getID() { | |
144 return this.id; | |
145 } | |
146 | |
147 | |
148 public String getDescription() { | |
149 return this.description; | |
150 } | |
151 | |
152 | |
153 public Collection<InputValue> getRequiredInputValues() { | |
154 return this.inputValues.values(); | |
155 } | |
156 | |
157 | |
158 public void reset(String uuid) { | |
159 inputData.remove(dataName); | |
160 } | |
161 | |
162 | |
163 public void setup(Node configuration) { | |
164 this.id = ((Element)configuration).getAttribute("id"); | |
165 this.description = ((Element)configuration).getAttribute("description"); | |
166 | |
167 log.info("State-ID = " + this.id); | |
168 | |
169 NodeList inputValuesNodes = Config.getNodeSetXPath(configuration, | |
170 "inputvalues/inputvalue"); | |
171 this.inputValues = new HashMap<String, InputValue>(inputValuesNodes | |
172 .getLength()); | |
173 this.inputValueNames = new ArrayList<String>(inputValuesNodes | |
174 .getLength()); | |
175 for (int i = 0; i < inputValuesNodes.getLength(); i++) { | |
176 Element inputValueNode = (Element)inputValuesNodes.item(i); | |
177 String usedinQueryValue = inputValueNode.getAttribute("usedinquery"); | |
178 int usedinQuery = 1; | |
179 if (usedinQueryValue != null) { | |
180 try { | |
181 usedinQuery = Integer.parseInt(usedinQueryValue); | |
182 } catch (NumberFormatException e) { | |
183 log | |
184 .warn("Used in Query Value cannot be transformed into a Number"); | |
185 } | |
186 } | |
187 InputValue inputValue = new DefaultInputValue(inputValueNode.getAttribute("name"), | |
188 inputValueNode.getAttribute("type"), | |
189 Boolean.parseBoolean(inputValueNode. | |
190 getAttribute("multiselect")), usedinQuery); | |
191 this.inputValues.put(inputValue.getName(), inputValue); | |
192 this.inputValueNames.add(inputValue.getName()); | |
193 } | |
194 | |
195 this.queryID = Config.getStringXPath(configuration, "queryID"); | |
196 log.info("QueryID ==> " + this.queryID); | |
197 | |
198 this.dataName = Config.getStringXPath(configuration, "dataname"); | |
199 | |
200 String dataMultiSelectValue = Config.getStringXPath(configuration, | |
201 "data-multiselect"); | |
202 if (dataMultiSelectValue != null) { | |
203 this.dataMultiSelect = Boolean.parseBoolean(dataMultiSelectValue); | |
204 } | |
205 | |
206 String dataNoSelectValue =Config.getStringXPath(configuration, | |
207 "data-noselect"); | |
208 if (dataNoSelectValue != null) { | |
209 this. dataNoSelect = Boolean.parseBoolean(dataNoSelectValue); | |
210 } | |
211 | |
212 this.preSettingsName = Config.getStringXPath(configuration, "presettings-name"); | |
213 | |
214 } | |
215 | |
216 | |
217 public State getParent() { | |
218 return this.parent; | |
219 } | |
220 | |
221 | |
222 public void setParent(State state) { | |
223 this.parent = state; | |
224 } | |
225 | |
226 | |
227 public Document feed( | |
228 CallContext context, | |
229 Collection<InputData> inputData, | |
230 String uuid) | |
231 throws StateException | |
232 { | |
233 RessourceFactory resFactory = RessourceFactory.getInstance(); | |
234 Locale[] serverLocales = resFactory.getLocales(); | |
235 Locale locale = context.getMeta().getPreferredLocale( | |
236 serverLocales); | |
237 | |
238 if (inputData != null) { | |
239 Iterator<InputData> it = inputData.iterator(); | |
240 InputValidator iv = new InputValidator(); | |
241 while (it.hasNext()) { | |
242 InputData tmpItem = it.next(); | |
243 InputValue inputValue = this.inputValues.get(tmpItem.getName()); | |
244 if (inputValue != null) { | |
245 if (this.inputData == null) { | |
246 this.inputData = new HashMap<String, InputData>( | |
247 inputData.size()); | |
248 } | |
249 | |
250 boolean valid = InputValidator.isInputValid(tmpItem.getValue(), | |
251 inputValue.getType()); | |
252 if (valid) { | |
253 | |
254 if (tmpItem.getName().equals(this.dataName)){ | |
255 String[] desc = getDescriptionForInputData(tmpItem, uuid); | |
256 tmpItem.setDescription(desc); | |
257 } | |
258 this.inputData.put(tmpItem.getName(), tmpItem); | |
259 } else { | |
260 String msg = resFactory.getRessource( | |
261 locale, | |
262 EXCEPTION_INVALID_INPUT, | |
263 EXCEPTION_INVALID_INPUT); | |
264 log.warn(msg); | |
265 return feedFailure(msg); | |
266 } | |
267 | |
268 } else { | |
269 String msg = resFactory.getRessource( | |
270 locale, | |
271 EXCEPTION_INVALID_INPUT, | |
272 EXCEPTION_INVALID_INPUT); | |
273 log.warn(msg); | |
274 return feedFailure(msg); | |
275 | |
276 } | |
277 } | |
278 | |
279 return feedSuccess(); | |
280 } else { | |
281 String msg = resFactory.getRessource( | |
282 locale, | |
283 EXCEPTION_NO_INPUT, | |
284 EXCEPTION_NO_INPUT); | |
285 log.warn(msg); | |
286 return feedFailure(msg); | |
287 } | |
288 } | |
289 | |
290 | |
291 protected Document feedSuccess() { | |
292 return ArtifactXMLUtilities.createSuccessReport( | |
293 "Initialize success", XMLUtils.newDocument()); | |
294 } | |
295 | |
296 | |
297 protected Document feedFailure(String msg) { | |
298 return ArtifactXMLUtilities.createInputExceptionReport( | |
299 msg, XMLUtils.newDocument()); | |
300 } | |
301 | |
302 | |
303 protected String[] getDescriptionForInputData(InputData data, String uuid) { | |
304 // there is only one element in the list, so take the first | |
305 Object obj = getDescibeData(uuid).get(0); | |
306 List descs = new ArrayList(); | |
307 | |
308 if (obj instanceof NamedArrayList) { | |
309 NamedArrayList list = (NamedArrayList) obj; | |
310 List selected = Arrays.asList(data.splitValue()); | |
311 int size = list.size(); | |
312 | |
313 for (int i = 0; i < size; i++) { | |
314 KeyValueDescibeData kv = (KeyValueDescibeData) list.get(i); | |
315 | |
316 // values are concatinated in InputData, so one InputData object can | |
317 // contain many input | |
318 String key = kv.getKey(); | |
319 int idx = selected.indexOf(key); | |
320 if (idx >= 0) { | |
321 descs.add(kv.getValue()); | |
322 | |
323 // XXX Workarround: I just wanted to remove the element at | |
324 // 'idx' from selected, but for any reason this is not | |
325 // possible (throws an exception) (iw) | |
326 List tmp = new ArrayList(); | |
327 for (int j = 0; j < selected.size(); j++) { | |
328 if (j != idx) | |
329 tmp.add(selected.get(j)); | |
330 } | |
331 | |
332 selected = tmp; | |
333 } | |
334 } | |
335 } | |
336 | |
337 return (String[]) descs.toArray(new String[descs.size()]); | |
338 } | |
339 | |
340 | |
341 public void putInputData(Collection<InputData> inputData, String uuid) | |
342 throws StateException { | |
343 if (inputData != null) { | |
344 Iterator<InputData> it = inputData.iterator(); | |
345 InputValidator iv = new InputValidator(); | |
346 while (it.hasNext()) { | |
347 InputData tmpItem = it.next(); | |
348 InputValue inputValue = this.inputValues.get(tmpItem.getName()); | |
349 if (inputValue != null) { | |
350 if (this.inputData == null) { | |
351 this.inputData = new HashMap<String, InputData>( | |
352 inputData.size()); | |
353 } | |
354 | |
355 boolean valid = InputValidator.isInputValid(tmpItem.getValue(), | |
356 inputValue.getType()); | |
357 if (valid) { | |
358 if (tmpItem.getName().equals(MINVALUEFIELDNAME)){ | |
359 String minValue = tmpItem.getValue(); | |
360 String maxValue = this.getInputValue4ID(inputData, MAXVALUEFIELDNAME); | |
361 valid = InputValidator.isInputValid(maxValue,inputValue.getType()); | |
362 if (!valid){ | |
363 String errMsg = "Wrong input for " + tmpItem.getValue() | |
364 + " is not an " + inputValue.getType() | |
365 + " Value."; | |
366 log.warn(errMsg); | |
367 throw new StateException(errMsg); | |
368 } | |
369 | |
370 valid = InputValidator.isInputValid(minValue, | |
371 maxValue, | |
372 inputValue.getType()); | |
373 if (!valid){ | |
374 String errMsg = "MaxValue-Input is less than MinValue-Input "; | |
375 log.warn(errMsg); | |
376 throw new StateException(errMsg); | |
377 } | |
378 }else if (tmpItem.getName().equals(MAXVALUEFIELDNAME)){ | |
379 String minValue = this.getInputValue4ID(inputData, MINVALUEFIELDNAME); | |
380 String maxValue = tmpItem.getValue(); | |
381 valid = InputValidator.isInputValid(minValue,inputValue.getType()); | |
382 if (!valid){ | |
383 String errMsg = "Wrong input for " + tmpItem.getValue() | |
384 + " is not an " + inputValue.getType() | |
385 + " Value."; | |
386 log.warn(errMsg); | |
387 throw new StateException(errMsg); | |
388 } | |
389 | |
390 valid = InputValidator.isInputValid(minValue, | |
391 maxValue, | |
392 inputValue.getType()); | |
393 if (!valid){ | |
394 String errMsg = "MaxValue-Input is less than MinValue-Input "; | |
395 log.warn(errMsg); | |
396 throw new StateException(errMsg); | |
397 } | |
398 } | |
399 this.inputData.put(tmpItem.getName(), tmpItem); | |
400 } else { | |
401 String errMsg = "Wrong input for " + tmpItem.getValue() | |
402 + " is not an " + inputValue.getType() | |
403 + " Value."; | |
404 log.warn(errMsg); | |
405 throw new StateException(errMsg); | |
406 } | |
407 | |
408 } else { | |
409 String errMsg = "No Inputvalue given for Inputdata " | |
410 + tmpItem.getName(); | |
411 log.warn(errMsg + "Value will be ignored"); | |
412 | |
413 } | |
414 } | |
415 } else { | |
416 log.warn("No Inputdata given"); | |
417 } | |
418 | |
419 setHash(uuid); | |
420 } | |
421 | |
422 | |
423 public void setPreSettings(Map<String, InputData> preSettings) { | |
424 this.preSettings = preSettings; | |
425 } | |
426 | |
427 | |
428 public Map<String, InputData> getPreSettings() { | |
429 return this.preSettings; | |
430 } | |
431 | |
432 | |
433 protected String getInputValue4ID(Collection<InputData> inputData, String inputName){ | |
434 Iterator<InputData> it = inputData.iterator(); | |
435 while (it.hasNext()) { | |
436 InputData tmpItem = it.next(); | |
437 if (tmpItem.getName().equals(inputName)){ | |
438 return tmpItem.getValue(); | |
439 } | |
440 } | |
441 return null; | |
442 } | |
443 | |
444 | |
445 public void advance(String uuid, CallContext context) | |
446 throws StateException | |
447 { | |
448 } | |
449 | |
450 | |
451 public void initialize(String uuid, CallContext context) | |
452 throws StateException | |
453 { | |
454 } | |
455 | |
456 | |
457 protected String[] generateFilterValuesFromInputData() { | |
458 List<String> list = new ArrayList<String>(); | |
459 Iterator<String> it = this.inputValueNames.iterator(); | |
460 while (it.hasNext()) { | |
461 String value = it.next(); | |
462 InputData data = this.inputData.get(value); | |
463 if (data != null | |
464 && this.inputValues.containsKey(data.getName())) { | |
465 int size = this.inputValues.get(data.getName()) | |
466 .usedInQueries(); | |
467 String type = this.inputValues.get(data.getName()) | |
468 .getType(); | |
469 String requestValue = data.getValue(); | |
470 if (type.equalsIgnoreCase("string")) { | |
471 requestValue = this | |
472 .prepareInputData4DBQuery(requestValue); | |
473 } else if (type.equalsIgnoreCase("date")) { | |
474 requestValue = this | |
475 .prepareInputData4DateDBQuery(requestValue); | |
476 } else if (type.equalsIgnoreCase("coordinate") || (type.equalsIgnoreCase("geometry") && requestValue.toLowerCase().startsWith("point"))){ | |
477 requestValue = this | |
478 .prepareInputData4RegionDBQuery(requestValue); | |
479 } | |
480 for (int j = 0; j < size; j++) { | |
481 list.add(requestValue); | |
482 } | |
483 } | |
484 } | |
485 String[] filterValues = list.toArray(new String[list.size()]); | |
486 return filterValues; | |
487 } | |
488 | |
489 | |
490 protected String prepareInputData4RegionDBQuery(String value){ | |
491 return value; | |
492 } | |
493 | |
494 private String prepareInputData4DateDBQuery(String value) { | |
495 if (value != null) { | |
496 String[] values = value.split(","); | |
497 String newValue = ""; | |
498 for (int i = 0; i < values.length; i++) { | |
499 if (newValue.length() > 0) { | |
500 newValue = newValue + " , "; | |
501 } | |
502 // TODO JUST HACK FIND A BETTER RESOLUTION | |
503 newValue = newValue + "to_date('" + values[i].trim() | |
504 + "', 'YYYY.MM.DD HH24:MI:SS')"; | |
505 } | |
506 return newValue; | |
507 } | |
508 | |
509 return value; | |
510 } | |
511 | |
512 private String prepareInputData4DBQuery(String value) { | |
513 if (value != null) { | |
514 String[] values = value.split(","); | |
515 String newValue = ""; | |
516 for (int i = 0; i < values.length; i++) { | |
517 if (newValue.length() > 0) { | |
518 newValue = newValue + " , "; | |
519 } | |
520 newValue = newValue + "'" + values[i].trim() + "'"; | |
521 } | |
522 return newValue; | |
523 } | |
524 | |
525 return value; | |
526 | |
527 } | |
528 | |
529 | |
530 protected List<Object> purifyResult(Collection<Result> result, String uuid) { | |
531 List<Object> describeData = new ArrayList<Object>(); | |
532 | |
533 NamedCollection<KeyValueDescibeData> keyValueDescibeData = | |
534 extractKVP(result, "KEY", "VALUE"); | |
535 | |
536 describeData.add(keyValueDescibeData); | |
537 | |
538 return describeData; | |
539 } | |
540 | |
541 | |
542 protected NamedCollection<KeyValueDescibeData> extractKVP(Collection<Result> result, | |
543 String keyid, | |
544 String valueid) { | |
545 Iterator<Result> rit = result.iterator(); | |
546 int dataSize = (this.dataNoSelect ? result.size()+1 : result.size()); | |
547 | |
548 NamedCollection<KeyValueDescibeData> keyValueDescibeData = new NamedArrayList<KeyValueDescibeData>( | |
549 this.dataName, dataSize); | |
550 keyValueDescibeData.setMultiSelect(this.dataMultiSelect); | |
551 | |
552 if (this.dataNoSelect){ | |
553 keyValueDescibeData.add(new DefaultKeyValueDescribeData( | |
554 NODATASELECTIONKEY, | |
555 "No Selection", | |
556 getID() | |
557 )); | |
558 } | |
559 | |
560 boolean initialized = false; | |
561 int keyPos = 0; | |
562 int valuePos = 1; | |
563 String previousKey = null; | |
564 InputData preSettingsData = | |
565 (this.preSettings != null && this.preSettingsName != null) | |
566 ? this.preSettings.get(this.preSettingsName) | |
567 : null; | |
568 boolean filterWithPresettings = preSettingsData != null; | |
569 | |
570 List<String> preSettingValues = null; | |
571 if(filterWithPresettings){ | |
572 preSettingValues = Arrays.asList(preSettingsData.splitValue()); | |
573 } | |
574 while (rit.hasNext()) { | |
575 Result resultValue = rit.next(); | |
576 if (!initialized){ | |
577 keyPos = resultValue.getResultDescriptor().getColumnIndex(keyid); | |
578 valuePos = resultValue.getResultDescriptor().getColumnIndex(valueid); | |
579 if (valuePos < 0){ | |
580 valuePos = 1; | |
581 } | |
582 initialized = true; | |
583 } | |
584 String tmpKey = resultValue.getString(keyPos); | |
585 | |
586 // TODO: FIXME: We have to do that because the arcsde does not | |
587 // support a distinct Query on Layers. | |
588 if (previousKey == null || !tmpKey.equals(previousKey)){ | |
589 previousKey = tmpKey; | |
590 if (!filterWithPresettings || preSettingValues.contains(tmpKey)){ | |
591 keyValueDescibeData.add( | |
592 new DefaultKeyValueDescribeData( | |
593 tmpKey, | |
594 resultValue.getString(valuePos), | |
595 getID()) | |
596 ); | |
597 } | |
598 } | |
599 } | |
600 return keyValueDescibeData; | |
601 } | |
602 | |
603 | |
604 public static boolean inBlackList(String key) { | |
605 int length = BLACKLIST.length; | |
606 for (int i = 0; i < length; i++) { | |
607 if (BLACKLIST[i].equals(key)) { | |
608 return true; | |
609 } | |
610 } | |
611 | |
612 return false; | |
613 } | |
614 | |
615 | |
616 public void describe( | |
617 Document document, | |
618 Node rootNode, | |
619 CallContext context, | |
620 String uuid) | |
621 { | |
622 XMLUtils.ElementCreator xCreator = new XMLUtils.ElementCreator( | |
623 document, | |
624 XMLUtils.XFORM_URL, | |
625 XMLUtils.XFORM_PREFIX | |
626 ); | |
627 | |
628 XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( | |
629 document, | |
630 ArtifactNamespaceContext.NAMESPACE_URI, | |
631 ArtifactNamespaceContext.NAMESPACE_PREFIX | |
632 ); | |
633 | |
634 // append dynamic node | |
635 Node dynamic = (Node) XMLUtils.xpath( | |
636 rootNode, | |
637 XPATH_DYNAMIC_UI, | |
638 XPathConstants.NODE, | |
639 ArtifactNamespaceContext.INSTANCE | |
640 ); | |
641 | |
642 describeDynamic( | |
643 creator, xCreator, document, dynamic, context, uuid); | |
644 | |
645 // append static nodes | |
646 Node staticNode = (Node) XMLUtils.xpath( | |
647 rootNode, | |
648 XPATH_STATIC_UI, | |
649 XPathConstants.NODE, | |
650 ArtifactNamespaceContext.INSTANCE | |
651 ); | |
652 | |
653 State parent = getParent(); | |
654 if (parent != null && parent instanceof StateBase) { | |
655 ((StateBase) parent).describeStatic( | |
656 creator,xCreator, document, staticNode, context,uuid); | |
657 } | |
658 } | |
659 | |
660 | |
661 protected void describeDynamic( | |
662 XMLUtils.ElementCreator artCreator, | |
663 XMLUtils.ElementCreator creator, | |
664 Document document, | |
665 Node dynamic, | |
666 CallContext context, | |
667 String uuid) | |
668 { | |
669 CallMeta callMeta = context.getMeta(); | |
670 | |
671 if (dataName == null) | |
672 return; | |
673 | |
674 List<Object> descibeData = getDescibeData(uuid); | |
675 if (descibeData != null) { | |
676 Iterator<Object> it = descibeData.iterator(); | |
677 | |
678 while (it.hasNext()) { | |
679 Object o = it.next(); | |
680 if ((!it.hasNext() && dataName != null)) { | |
681 appendToDynamicNode( | |
682 artCreator, creator, document, dynamic, callMeta, o); | |
683 } | |
684 } | |
685 } | |
686 } | |
687 | |
688 | |
689 protected void describeStatic( | |
690 XMLUtils.ElementCreator artCreator, | |
691 XMLUtils.ElementCreator creator, | |
692 Document document, | |
693 Node staticNode, | |
694 CallContext context, | |
695 String uuid) | |
696 { | |
697 State parent = getParent(); | |
698 if (parent != null && parent instanceof StateBase) { | |
699 ((StateBase) parent).describeStatic( | |
700 artCreator, creator, document, staticNode, context, uuid); | |
701 } | |
702 | |
703 CallMeta callMeta = context.getMeta(); | |
704 appendToStaticNode(artCreator, creator, document, staticNode, callMeta); | |
705 } | |
706 | |
707 | |
708 protected void appendToStaticNode( | |
709 XMLUtils.ElementCreator artCreator, | |
710 XMLUtils.ElementCreator creator, | |
711 Document document, | |
712 Node staticNode, | |
713 CallMeta callMeta | |
714 ) { | |
715 InputData data = inputData.get(dataName); | |
716 | |
717 if (data == null) { | |
718 return; | |
719 } | |
720 | |
721 Element selectNode = creator.create("select1"); | |
722 creator.addAttr(selectNode, "ref", dataName); | |
723 | |
724 Element lableNode = creator.create("label"); | |
725 lableNode.setTextContent(RessourceFactory.getInstance() | |
726 .getRessource(callMeta.getLanguages(), dataName, dataName)); | |
727 Element choiceNode = creator.create("choices"); | |
728 | |
729 artCreator.addAttr( | |
730 selectNode, "state", getID(), true | |
731 ); | |
732 | |
733 String[] descriptions = data.getDescription(); | |
734 int size = descriptions.length; | |
735 | |
736 for (int i = 0; i < size; i++) { | |
737 Element itemNode = creator.create("item"); | |
738 String value = data.getValue(); | |
739 String desc = descriptions[i]; | |
740 desc = desc == null ? value : desc; | |
741 | |
742 creator.addAttr(itemNode, "selected", "true"); | |
743 | |
744 Element choiceLableNode = creator.create("label"); | |
745 choiceLableNode.setTextContent(desc); | |
746 itemNode.appendChild(choiceLableNode); | |
747 | |
748 Element choiceValueNode = creator.create("value"); | |
749 choiceValueNode.setTextContent(value); | |
750 itemNode.appendChild(choiceValueNode); | |
751 choiceNode.appendChild(itemNode); | |
752 } | |
753 | |
754 selectNode.appendChild(lableNode); | |
755 selectNode.appendChild(choiceNode); | |
756 | |
757 staticNode.appendChild(selectNode); | |
758 } | |
759 | |
760 | |
761 protected void appendToDynamicNode( | |
762 XMLUtils.ElementCreator artCreator, | |
763 XMLUtils.ElementCreator creator, | |
764 Document document, | |
765 Node dynamicNode, | |
766 CallMeta callMeta, | |
767 Object o | |
768 ) { | |
769 if (o instanceof Collection<?>) { | |
770 String name = null; | |
771 boolean multiselect = false; | |
772 if (o instanceof NamedCollection<?>) { | |
773 NamedCollection<?> nc = ((NamedCollection<?>) o); | |
774 name = nc.getName(); | |
775 multiselect = nc.isMultiSelect(); | |
776 } else { | |
777 Object[] names = this.inputValueNames.toArray(); | |
778 name = names[names.length - 1].toString(); | |
779 } | |
780 | |
781 Element selectNode = creator.create(multiselect?"select":"select1"); | |
782 creator.addAttr(selectNode, "ref", name); | |
783 | |
784 Element lableNode = creator.create("label"); | |
785 lableNode.setTextContent(RessourceFactory.getInstance() | |
786 .getRessource(callMeta.getLanguages(), name, name)); | |
787 Element choiceNode = creator.create("choices"); | |
788 | |
789 Collection<KeyValueDescibeData> values = (Collection<KeyValueDescibeData>) o; | |
790 Iterator<KeyValueDescibeData> resultIt = values.iterator(); | |
791 while (resultIt.hasNext()) { | |
792 KeyValueDescibeData result = resultIt.next(); | |
793 Element itemNode = creator.create("item"); | |
794 | |
795 if (result.isSelected()) { | |
796 itemNode.setAttribute("selected", "true"); | |
797 } | |
798 | |
799 Element choiceLableNode = creator.create("label"); | |
800 choiceLableNode.setTextContent(result.getValue()); | |
801 itemNode.appendChild(choiceLableNode); | |
802 | |
803 Element choicValueNode = creator.create("value"); | |
804 choicValueNode.setTextContent("" + result.getKey()); | |
805 itemNode.appendChild(choicValueNode); | |
806 choiceNode.appendChild(itemNode); | |
807 } | |
808 selectNode.appendChild(lableNode); | |
809 selectNode.appendChild(choiceNode); | |
810 | |
811 dynamicNode.appendChild(selectNode); | |
812 } | |
813 else if (o instanceof MinMaxDescribeData) { | |
814 appendMinMaxDescribeData( | |
815 artCreator, | |
816 creator, | |
817 document, | |
818 dynamicNode, | |
819 callMeta, | |
820 o); | |
821 } | |
822 else if (o instanceof SingleValueDescribeData) { | |
823 appendSingleValueDescribeData( | |
824 artCreator, | |
825 creator, | |
826 document, | |
827 dynamicNode, | |
828 callMeta, | |
829 o); | |
830 } | |
831 } | |
832 | |
833 | |
834 protected void appendMinMaxDescribeData( | |
835 XMLUtils.ElementCreator artCreator, | |
836 XMLUtils.ElementCreator creator, | |
837 Document document, | |
838 Node node, | |
839 CallMeta callMeta, | |
840 Object o | |
841 ) { | |
842 MinMaxDescribeData minMaxDescibeData = (MinMaxDescribeData) o; | |
843 Object min = minMaxDescibeData.getMinValue(); | |
844 Object max = minMaxDescibeData.getMaxValue(); | |
845 if (min instanceof GregorianCalendar) { | |
846 Date d = ((GregorianCalendar) min).getTime(); | |
847 min = DateUtils.getPatternedDateAmer(d); | |
848 } | |
849 | |
850 if (max instanceof GregorianCalendar) { | |
851 Date d = ((GregorianCalendar) max).getTime(); | |
852 max = DateUtils.getPatternedDateAmer(d); | |
853 } | |
854 | |
855 Element groupNode = creator.create("group"); | |
856 artCreator.addAttr(groupNode, "state", minMaxDescibeData.getState(), true); | |
857 | |
858 creator.addAttr(groupNode, "ref", minMaxDescibeData.getName()); | |
859 Element groupNodeLableNode = creator.create("label"); | |
860 groupNodeLableNode.setTextContent(RessourceFactory | |
861 .getInstance().getRessource( | |
862 callMeta.getLanguages(), | |
863 minMaxDescibeData.getName(), | |
864 minMaxDescibeData.getName())); | |
865 groupNode.appendChild(groupNodeLableNode); | |
866 | |
867 Element inputMinNode = creator.create("input"); | |
868 creator.addAttr(inputMinNode, "ref", MINVALUEFIELDNAME); | |
869 Element inputMinLableNode = creator.create("label"); | |
870 inputMinLableNode.setTextContent(RessourceFactory | |
871 .getInstance().getRessource( | |
872 callMeta.getLanguages(), MINVALUEFIELDNAME, | |
873 MINVALUEFIELDNAME)); | |
874 inputMinNode.appendChild(inputMinLableNode); | |
875 | |
876 Element inputMinValueNode = creator.create("value"); | |
877 inputMinValueNode.setTextContent(min.toString()); | |
878 inputMinNode.appendChild(inputMinValueNode); | |
879 | |
880 Element inputMaxNode = creator.create("input"); | |
881 creator.addAttr(inputMaxNode, "ref", MAXVALUEFIELDNAME); | |
882 Element inputMaxLableNode = creator.create("label"); | |
883 inputMaxLableNode.setTextContent(RessourceFactory | |
884 .getInstance().getRessource( | |
885 callMeta.getLanguages(), MAXVALUEFIELDNAME, | |
886 MAXVALUEFIELDNAME)); | |
887 inputMaxNode.appendChild(inputMaxLableNode); | |
888 | |
889 Element inputMaxValueNode = creator.create("value"); | |
890 inputMaxValueNode.setTextContent(max.toString()); | |
891 inputMaxNode.appendChild(inputMaxValueNode); | |
892 | |
893 groupNode.appendChild(inputMinNode); | |
894 groupNode.appendChild(inputMaxNode); | |
895 | |
896 node.appendChild(groupNode); | |
897 } | |
898 | |
899 | |
900 protected void appendSingleValueDescribeData( | |
901 XMLUtils.ElementCreator artCreator, | |
902 XMLUtils.ElementCreator creator, | |
903 Document document, | |
904 Node node, | |
905 CallMeta callMeta, | |
906 Object o | |
907 ) { | |
908 SingleValueDescribeData svdb = (SingleValueDescribeData) o; | |
909 | |
910 Element groupNode = creator.create("group"); | |
911 artCreator.addAttr(groupNode, "state", svdb.getState(), true); | |
912 creator.addAttr(groupNode, "ref", svdb.getName()); | |
913 | |
914 Element groupNodeLableNode = creator.create("label"); | |
915 groupNodeLableNode.setTextContent(RessourceFactory | |
916 .getInstance().getRessource( | |
917 callMeta.getLanguages(), | |
918 svdb.getName(), | |
919 svdb.getName())); | |
920 groupNode.appendChild(groupNodeLableNode); | |
921 | |
922 Element inputNode = creator.create("input"); | |
923 creator.addAttr(inputNode, "ref", svdb.getName()); | |
924 | |
925 Element inputLableNode = creator.create("label"); | |
926 inputLableNode.setTextContent(""); | |
927 inputNode.appendChild(inputLableNode); | |
928 | |
929 Element inputValueNode = creator.create("value"); | |
930 inputValueNode.setTextContent(svdb.getValue()); | |
931 inputNode.appendChild(inputValueNode); | |
932 | |
933 groupNode.appendChild(inputNode); | |
934 | |
935 node.appendChild(groupNode); | |
936 } | |
937 | |
938 | |
939 protected void setHash(String uuid) { | |
940 this.hash = uuid + | |
941 HASH_ID_SEPARATOR + | |
942 id + | |
943 HASH_ID_SEPARATOR + | |
944 inputData.hashCode(); | |
945 } | |
946 | |
947 | |
948 protected String getHash() { | |
949 return this.hash; | |
950 } | |
951 | |
952 | |
953 public List<Object> getDescibeData(String uuid) { | |
954 CacheFactory factory = CacheFactory.getInstance(); | |
955 if (factory.isInitialized()) { | |
956 // we use a cache | |
957 log.debug("Using cache."); | |
958 Cache cache = factory.getCache(); | |
959 String key = getHash(); | |
960 | |
961 net.sf.ehcache.Element value = cache.get(key); | |
962 if (value != null) { | |
963 // element already in cache, so return it. | |
964 log.debug("Found element in cache."); | |
965 return (List<Object>) (value.getObjectValue()); | |
966 } | |
967 else { | |
968 // element is not in cache yet, so we need to fetch data from | |
969 // database and put it into cache right now | |
970 log.debug("Element not in cache, we need to ask the database"); | |
971 try { | |
972 String[] filterValues = generateFilterValuesFromInputData(); | |
973 List<Object> data = queryDatabase(filterValues, uuid); | |
974 | |
975 cache.put(new net.sf.ehcache.Element(key, data)); | |
976 return data; | |
977 } | |
978 catch (QueryException qe) { | |
979 log.error(qe, qe); | |
980 } | |
981 } | |
982 } | |
983 else { | |
984 // we don't use a cache, so we have to query the database every | |
985 // single time | |
986 log.debug("Not using cache."); | |
987 String[] filterValues = generateFilterValuesFromInputData(); | |
988 Collection<Result> result = null; | |
989 try { | |
990 return queryDatabase(filterValues, uuid); | |
991 } | |
992 catch (RuntimeException e) { | |
993 log.error(e, e); | |
994 } | |
995 catch (QueryException e) { | |
996 log.error(e, e); | |
997 } | |
998 } | |
999 | |
1000 return null; | |
1001 } | |
1002 | |
1003 | |
1004 protected List<Object> queryDatabase(String[] filterValues, String uuid) | |
1005 throws QueryException { | |
1006 Collection<Result> result = null; | |
1007 | |
1008 if (queryID != null) { | |
1009 QueryExecutor queryExecutor = | |
1010 QueryExecutorFactory.getInstance().getQueryExecutor(); | |
1011 | |
1012 result = queryExecutor.executeQuery(queryID, filterValues); | |
1013 } | |
1014 return purifyResult(result, uuid); | |
1015 } | |
1016 | |
1017 | |
1018 | |
1019 public Map<String, InputData> inputData() { | |
1020 return inputData; | |
1021 } | |
1022 | |
1023 | |
1024 public Collection<InputData> getInputData() throws StateException { | |
1025 return this.inputData != null ? this.inputData.values() : null; | |
1026 } | |
1027 | |
1028 | |
1029 public InputData getInputDataByName(String name) { | |
1030 State state = this; | |
1031 | |
1032 while (state != null) { | |
1033 InputData data = state.inputData().get(name); | |
1034 if (data != null) { | |
1035 return data; | |
1036 } | |
1037 | |
1038 state = state.getParent(); | |
1039 } | |
1040 | |
1041 return null; | |
1042 } | |
1043 | |
1044 | |
1045 public void endOfLife(Object globalContext) { | |
1046 } | |
1047 | |
1048 | |
1049 public void cleanup(Object context) { | |
1050 } | |
1051 } | |
1052 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |