comparison gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java @ 1119:7c4f81f74c47

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

http://dive4elements.wald.intevation.org