Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/artifacts/GNVArtifactBase.java @ 1119:7c4f81f74c47
merged gnv-artifacts
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:00 +0200 |
parents | c01c220312d0 |
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.artifacts; | |
10 | |
11 import de.intevation.artifacts.common.utils.Config; | |
12 import de.intevation.artifactdatabase.ProxyArtifact; | |
13 import de.intevation.artifacts.common.utils.XMLUtils; | |
14 | |
15 import de.intevation.artifacts.Artifact; | |
16 import de.intevation.artifacts.ArtifactDatabase; | |
17 import de.intevation.artifacts.ArtifactFactory; | |
18 import de.intevation.artifacts.ArtifactNamespaceContext; | |
19 import de.intevation.artifacts.CallContext; | |
20 import de.intevation.artifacts.CallMeta; | |
21 import de.intevation.artifacts.GlobalContext; | |
22 | |
23 import de.intevation.gnv.artifacts.context.GNVArtifactContext; | |
24 | |
25 import de.intevation.gnv.artifacts.fis.product.Product; | |
26 | |
27 import de.intevation.gnv.artifacts.ressource.RessourceFactory; | |
28 | |
29 import de.intevation.gnv.state.AutoResumeState; | |
30 import de.intevation.gnv.state.DefaultInputData; | |
31 import de.intevation.gnv.state.ExportMode; | |
32 import de.intevation.gnv.state.InputData; | |
33 import de.intevation.gnv.state.InputValue; | |
34 import de.intevation.gnv.state.OutputMode; | |
35 import de.intevation.gnv.state.OutputState; | |
36 import de.intevation.gnv.state.State; | |
37 import de.intevation.gnv.state.StateFactory; | |
38 | |
39 import de.intevation.gnv.state.exception.StateException; | |
40 | |
41 import de.intevation.gnv.transition.Transition; | |
42 import de.intevation.gnv.transition.TransitionFactory; | |
43 | |
44 import de.intevation.gnv.utils.ArtifactXMLUtilities; | |
45 | |
46 import java.io.IOException; | |
47 import java.io.OutputStream; | |
48 | |
49 import java.util.ArrayList; | |
50 import java.util.Collection; | |
51 import java.util.HashMap; | |
52 import java.util.Iterator; | |
53 import java.util.List; | |
54 import java.util.Locale; | |
55 import java.util.Map; | |
56 | |
57 import javax.xml.xpath.XPathConstants; | |
58 | |
59 import org.apache.log4j.Logger; | |
60 | |
61 import org.w3c.dom.Document; | |
62 import org.w3c.dom.Element; | |
63 import org.w3c.dom.Node; | |
64 import org.w3c.dom.NodeList; | |
65 | |
66 /** | |
67 * This is the major gnv artifact and handles the requests specified in | |
68 * <code>de.intevation.artifactdatabase.Artifact</code>. | |
69 * | |
70 * @author <a href="mailto:tim.englich@intevation.de">Tim Englich</a> | |
71 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | |
72 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> | |
73 */ | |
74 public abstract class GNVArtifactBase extends GNVDefaultArtifact | |
75 implements PreSettingArtifact { | |
76 | |
77 /** | |
78 * the logger, used to log exceptions and additonaly information | |
79 */ | |
80 private static Logger log = Logger.getLogger(GNVArtifactBase.class); | |
81 /** | |
82 * The UID of this Class | |
83 */ | |
84 private static final long serialVersionUID = -8907096744400741458L; | |
85 | |
86 /** | |
87 * The Identifier for the Replacement of the Artifactname | |
88 */ | |
89 public static final String XPATH_IDENTIFIER_REPLACE = "IDENTIFIER"; | |
90 | |
91 /** | |
92 * The XPATH to the XML-Fragment that should be used for the Configuration | |
93 */ | |
94 public static final String XPATH_ARTIFACT_CONFIGURATION = "/artifact-database/artifacts/artifact[@name='" | |
95 + XPATH_IDENTIFIER_REPLACE | |
96 + "']"; | |
97 | |
98 public static final String XPATH_STATIC_NODE = "/art:result/art:ui/art:static"; | |
99 | |
100 public static final String XPATH_INPUT_DATA = "/art:action/art:data/art:input"; | |
101 | |
102 public static final String XPATH_INCLUDE_UI = "/art:action/art:include-ui"; | |
103 | |
104 public static final String XPATH_TARGET_NAME = "/art:action/art:target/@name"; | |
105 | |
106 public static final String XPATH_OUTPUT_NAME = "/art:action/art:out/@name"; | |
107 | |
108 public static final String XPATH_OUTPUT_PARAMS = "/art:action/art:out/art:params/art:input"; | |
109 | |
110 public static final String INITIAL_STATE = "product"; | |
111 | |
112 /** | |
113 * The current State | |
114 */ | |
115 protected State current = null; | |
116 | |
117 /** | |
118 * The States that can be used | |
119 */ | |
120 protected Map<String, State> states = null; | |
121 | |
122 /** | |
123 * The Transitions which can switch between the different States. | |
124 */ | |
125 protected Collection<Transition> transitions = null; | |
126 | |
127 /** | |
128 * The current product | |
129 */ | |
130 protected Product product; | |
131 | |
132 /** | |
133 * The Name of the Artifact | |
134 */ | |
135 protected String name = null; | |
136 | |
137 /** | |
138 * The Presettings of InputData which can be used to | |
139 * travel through the States in different Ways or | |
140 * manipulate the InputData | |
141 */ | |
142 private Map<String, InputData> preSettings = null; | |
143 | |
144 /** | |
145 * Constructor | |
146 */ | |
147 public GNVArtifactBase() { | |
148 super(); | |
149 } | |
150 | |
151 | |
152 /** | |
153 * This method handles request for changing the current state of an | |
154 * artifact. It is possible to step forward, backward, or to the initial | |
155 * state for choosing a fis. | |
156 */ | |
157 @Override | |
158 public Document advance(Document target, CallContext context) { | |
159 log.debug("GNVArtifactBase.advance()"); | |
160 | |
161 Document result = XMLUtils.newDocument(); | |
162 String targetState = XMLUtils.xpathString( | |
163 target, XPATH_TARGET_NAME, ArtifactNamespaceContext.INSTANCE | |
164 ); | |
165 | |
166 // no current state... | |
167 if (current == null) { | |
168 log.warn("No current state. Advance not possible."); | |
169 | |
170 result = createReport( | |
171 result, | |
172 "exceptionreport", | |
173 "exception", | |
174 "No State activated." | |
175 ); | |
176 | |
177 return result; | |
178 } | |
179 | |
180 State next = null; | |
181 | |
182 try { | |
183 | |
184 // step forward | |
185 if (isStateCurrentlyReachable(targetState)) { | |
186 | |
187 next = states.get(targetState); | |
188 | |
189 boolean success = go2NextState(context, result, next); | |
190 | |
191 if (success){ | |
192 result = createReport( | |
193 result, "result", "success", "Advance success" | |
194 ); | |
195 }else{ | |
196 result = ArtifactXMLUtilities. | |
197 createExceptionReport("Error while going to next State.", | |
198 XMLUtils.newDocument()); | |
199 } | |
200 } | |
201 | |
202 // step backward | |
203 else if((next = getPreviousState(current, targetState, context)) | |
204 != null) | |
205 { | |
206 | |
207 if (current != null) { | |
208 current.endOfLife(context.globalContext()); | |
209 } | |
210 | |
211 current = next; | |
212 | |
213 // 2. Transfer Results | |
214 current.reset(identifier); | |
215 | |
216 result = createReport( | |
217 result, "result", "success", "Advance success" | |
218 ); | |
219 } | |
220 | |
221 // goto initial step | |
222 else if(targetState.equals(INITIAL_STATE)) { | |
223 | |
224 String fis = product.getArtifactFactory(); | |
225 ArtifactDatabase db = context.getDatabase(); | |
226 GNVProductArtifactFactory fac = (GNVProductArtifactFactory) | |
227 db.getInternalArtifactFactory(fis); | |
228 | |
229 Artifact select = fac.createArtifact( | |
230 identifier, | |
231 (GlobalContext) context.globalContext(), | |
232 context.getMeta(), | |
233 null); | |
234 | |
235 context.putContextValue(ProxyArtifact.REPLACE_PROXY, select); | |
236 | |
237 result = createReport( | |
238 result, "result", "success", "Advance success" | |
239 ); | |
240 } | |
241 | |
242 // advance not possible | |
243 else { | |
244 log.warn("advance not possible for target: " + targetState); | |
245 result = createReport( | |
246 result, | |
247 "exceptionreport", | |
248 "exception", | |
249 "Statetransition not supported" | |
250 ); | |
251 } | |
252 } | |
253 catch (StateException se) { | |
254 log.error(se, se); | |
255 result = createReport( | |
256 result, | |
257 "exceptionreport", | |
258 "exception", | |
259 se.getLocalizedMessage() | |
260 ); | |
261 } | |
262 | |
263 return result; | |
264 } | |
265 | |
266 | |
267 private boolean go2NextState(CallContext context, Document result, | |
268 State next) throws StateException { | |
269 // 2. Transfer Results | |
270 next.putInputData(current.getInputData(), identifier); | |
271 next.setParent(current); | |
272 next.setPreSettings(this.preSettings); | |
273 | |
274 // 3. Switch to next State | |
275 current = next; | |
276 | |
277 // 4. Initialize next Step | |
278 current.initialize(identifier, context); | |
279 | |
280 return true; | |
281 } | |
282 | |
283 | |
284 protected Document createReport( | |
285 Document document, | |
286 String nodeName, | |
287 String state, | |
288 String msg | |
289 ) { | |
290 XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( | |
291 document, | |
292 ArtifactNamespaceContext.NAMESPACE_URI, | |
293 ArtifactNamespaceContext.NAMESPACE_PREFIX | |
294 ); | |
295 | |
296 Element reportNode = creator.create(nodeName); | |
297 Element stateNode = creator.create(state); | |
298 | |
299 stateNode.setTextContent(msg); | |
300 reportNode.appendChild(stateNode); | |
301 document.appendChild(reportNode); | |
302 | |
303 return document; | |
304 | |
305 } | |
306 | |
307 | |
308 /** | |
309 * Step back to the previous state specified by <code>name</code>. | |
310 */ | |
311 protected State getPreviousState( | |
312 State current, String name, CallContext context) | |
313 { | |
314 if (current == null) { | |
315 return null; | |
316 } | |
317 | |
318 if (current.getID().equals(name)) { | |
319 return current; | |
320 } | |
321 else { | |
322 current.endOfLife(context); | |
323 return getPreviousState(current.getParent(), name, context); | |
324 } | |
325 } | |
326 | |
327 | |
328 private boolean isStateCurrentlyReachable(String stateid){ | |
329 Iterator<Transition> it = this.transitions.iterator(); | |
330 String from = this.current.getID(); | |
331 while (it.hasNext()){ | |
332 Transition transition = it.next(); | |
333 if (transition.getFrom().equals(from)){ | |
334 if (transition.getTo().equals(stateid) && transition.isValid(this.current)){ | |
335 return true; | |
336 } | |
337 } | |
338 } | |
339 return false; | |
340 } | |
341 | |
342 | |
343 public Document initialize(CallContext context) { | |
344 Document result = XMLUtils.newDocument(); | |
345 try { | |
346 this.current.initialize(super.identifier, context); | |
347 | |
348 if (this.current instanceof AutoResumeState){ | |
349 // Jump to next State using the Transitions. | |
350 State next = this.getNextReachableState(this.current); | |
351 if (next != null){ | |
352 boolean success = go2NextState(context, result, next); | |
353 if (success){ | |
354 result = ArtifactXMLUtilities | |
355 .createSuccessReport("Initialize success", | |
356 XMLUtils.newDocument()); | |
357 }else{ | |
358 result = ArtifactXMLUtilities. | |
359 createExceptionReport( | |
360 "Error while going to next State.", | |
361 XMLUtils.newDocument()); | |
362 } | |
363 }else{ | |
364 result = ArtifactXMLUtilities. | |
365 createExceptionReport("No propper State found.", | |
366 XMLUtils.newDocument()); | |
367 } | |
368 }else{ | |
369 result = ArtifactXMLUtilities | |
370 .createSuccessReport("Initialize success", | |
371 XMLUtils.newDocument()); | |
372 } | |
373 } catch (StateException e) { | |
374 log.error(e,e); | |
375 result = ArtifactXMLUtilities.createExceptionReport(e | |
376 .getLocalizedMessage(), XMLUtils.newDocument()); | |
377 } | |
378 return result; | |
379 } | |
380 | |
381 /** | |
382 * Step forward to the next reachable state. | |
383 * @param current Current state. | |
384 * @return Reachable state. | |
385 */ | |
386 protected State getNextReachableState(State current){ | |
387 Iterator<Transition> it = this.transitions.iterator(); | |
388 String from = current.getID(); | |
389 while (it.hasNext()){ | |
390 Transition transition = it.next(); | |
391 if (transition.getFrom().equals(from)){ | |
392 if (transition.isValid(current)){ | |
393 return this.states.get(transition.getTo()); | |
394 } | |
395 } | |
396 } | |
397 return null; | |
398 } | |
399 | |
400 | |
401 protected String readStateName(Document document) { | |
402 String returnValue = XMLUtils.xpathString( | |
403 document, XPATH_TARGET_NAME, ArtifactNamespaceContext.INSTANCE); | |
404 return returnValue; | |
405 } | |
406 | |
407 | |
408 protected Node getConfigurationFragment(Document document) { | |
409 log.debug("GNVArtifactBase.getConfigurationFragment"); | |
410 String xpathQuery = XPATH_ARTIFACT_CONFIGURATION.replaceAll( | |
411 XPATH_IDENTIFIER_REPLACE, this.name); | |
412 | |
413 Element configurationNode = (Element)Config.getNodeXPath(document, xpathQuery); | |
414 | |
415 String link = configurationNode.getAttribute("xlink:href"); | |
416 if (link != null ){ | |
417 String absolutFileName = Config.replaceConfigDir(link); | |
418 configurationNode = (Element)new ArtifactXMLUtilities().readConfiguration(absolutFileName); | |
419 } | |
420 | |
421 return configurationNode; | |
422 } | |
423 | |
424 /** | |
425 * Insert new data included in <code>target</code> into the current state. | |
426 * @param target XML document which contains data. | |
427 * @param context CallContext | |
428 * @return XML document with success or error message. | |
429 */ | |
430 @Override | |
431 public Document feed(Document target, CallContext context) { | |
432 log.debug("GNVArtifactBase.feed"); | |
433 RessourceFactory fac = RessourceFactory.getInstance(); | |
434 Locale[] locales = fac.getLocales(); | |
435 Locale locale = context.getMeta().getPreferredLocale(locales); | |
436 Document result = XMLUtils.newDocument(); | |
437 | |
438 try { | |
439 if (this.current != null) { | |
440 Collection<InputData> inputData = this.parseInputData( | |
441 target, | |
442 XPATH_INPUT_DATA); | |
443 | |
444 if (!inputData.isEmpty()){ | |
445 result = current.feed(context, inputData, super.identifier); | |
446 }else{ | |
447 //String msg = "No Inputdata given. Please select at least one Entry."; | |
448 String msg = fac.getRessource( | |
449 locale, | |
450 EXCEPTION_NO_INPUT, | |
451 EXCEPTION_NO_INPUT); | |
452 | |
453 log.warn(msg); | |
454 result = ArtifactXMLUtilities.createInputExceptionReport( | |
455 msg, | |
456 XMLUtils.newDocument()); | |
457 } | |
458 } else { | |
459 String msg = "No State instantiated"; | |
460 log.warn(msg); | |
461 result = ArtifactXMLUtilities.createExceptionReport(msg, | |
462 XMLUtils.newDocument()); | |
463 } | |
464 } catch (StateException e) { | |
465 log.error(e, e); | |
466 result = ArtifactXMLUtilities.createExceptionReport(e | |
467 .getLocalizedMessage(), XMLUtils.newDocument()); | |
468 } | |
469 return result; | |
470 } | |
471 | |
472 | |
473 /** | |
474 * Describe the current artifact. | |
475 * @return The description of the current artifact. | |
476 */ | |
477 @Override | |
478 public Document describe(Document data, CallContext context) { | |
479 log.debug("GNVArtifactBase.describe"); | |
480 | |
481 Document document = createDescibeOutput( | |
482 context, | |
483 identifier, | |
484 getIncludeUIFromDocument(data) | |
485 ); | |
486 | |
487 return document; | |
488 } | |
489 | |
490 /** | |
491 * Initialse this artifact and insert some data if <code>data</code> | |
492 * contains necessary information for this artifact. | |
493 */ | |
494 @Override | |
495 public void setup( | |
496 String identifier, | |
497 ArtifactFactory factory, | |
498 Object context, | |
499 CallMeta meta, | |
500 Document data | |
501 ) { | |
502 log.debug("GNVArtifactBase.setup"); | |
503 super.setup(identifier, factory, context, meta, data); | |
504 | |
505 Object localContext = context; | |
506 if (context instanceof CallContext) { | |
507 localContext = ((CallContext) context).globalContext(); | |
508 | |
509 } | |
510 | |
511 if (localContext instanceof GNVArtifactContext) { | |
512 GNVArtifactContext gnvContext = (GNVArtifactContext) localContext; | |
513 Document doc = gnvContext.getConfig(); | |
514 Node artifactNode = this.getConfigurationFragment(doc); | |
515 | |
516 NodeList stateList = Config.getNodeSetXPath(artifactNode, | |
517 "states/state"); | |
518 this.states = new HashMap<String, State>(stateList | |
519 .getLength()); | |
520 for (int i = 0; i < stateList.getLength(); i++) { | |
521 State tmpState = StateFactory.getInstance() | |
522 .createState(stateList.item(i)); | |
523 if (tmpState != null) { | |
524 log.debug("Initiate new state: " + tmpState.getID()); | |
525 this.states.put(tmpState.getID(), tmpState); | |
526 if (this.current == null) { | |
527 this.current = tmpState; | |
528 } | |
529 } | |
530 } | |
531 | |
532 NodeList transitionList = Config.getNodeSetXPath(artifactNode, | |
533 "states/transition"); | |
534 this.transitions = new ArrayList<Transition>(transitionList.getLength()); | |
535 for (int i = 0; i < transitionList.getLength(); i++) { | |
536 Transition tmpTransition = TransitionFactory.getInstance() | |
537 .createTransition(transitionList.item(i)); | |
538 if (tmpTransition != null) { | |
539 this.transitions.add(tmpTransition); | |
540 } | |
541 } | |
542 | |
543 } | |
544 } | |
545 | |
546 | |
547 /** | |
548 * Create the xml document returned in {@link #describe(org.w3c.dom.Document, | |
549 * de.intevation.artifacts.CallContext)} | |
550 */ | |
551 protected Document createDescibeOutput( | |
552 CallContext context, | |
553 String uuid, | |
554 boolean incudeUI | |
555 ) { | |
556 log.debug("GNVArtifactBase.createDescibeOutput"); | |
557 Document document = XMLUtils.newDocument(); | |
558 | |
559 XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( | |
560 document, | |
561 ArtifactNamespaceContext.NAMESPACE_URI, | |
562 ArtifactNamespaceContext.NAMESPACE_PREFIX | |
563 ); | |
564 Element rootNode = this.createRootNode(creator, document); | |
565 this.createHeader(creator, rootNode, document, "describe"); | |
566 this.createOutputs(creator, rootNode, document); | |
567 this.createCurrentState(creator, rootNode, document); | |
568 this.createReachableStates(creator, rootNode, document); | |
569 this.createModel(creator, rootNode, document); | |
570 if (incudeUI){ | |
571 this.createUserInterface(creator, rootNode, document, context, uuid); | |
572 } | |
573 | |
574 return document; | |
575 } | |
576 | |
577 /** | |
578 * Determine the wish to append the user interface description to the | |
579 * describe document. | |
580 * | |
581 * @return True, if the user interface description should be appended, | |
582 * otherwise false. | |
583 */ | |
584 protected boolean getIncludeUIFromDocument(Document document){ | |
585 String value = XMLUtils.xpathString( | |
586 document, XPATH_INCLUDE_UI, ArtifactNamespaceContext.INSTANCE); | |
587 | |
588 boolean includeUI = false; | |
589 if (value != null){ | |
590 includeUI = Boolean.parseBoolean(value); | |
591 } | |
592 return includeUI; | |
593 } | |
594 | |
595 | |
596 protected Element createRootNode( | |
597 XMLUtils.ElementCreator creator, | |
598 Document document | |
599 ) { | |
600 Element rootNode = creator.create("result"); | |
601 document.appendChild(rootNode); | |
602 return rootNode; | |
603 } | |
604 | |
605 /** | |
606 * Append information about the current artifact (uuid, hash). | |
607 */ | |
608 protected void createHeader( | |
609 XMLUtils.ElementCreator creator, | |
610 Element parent, | |
611 Document document, | |
612 String documentType | |
613 ) { | |
614 Element typeNode = creator.create("type"); | |
615 creator.addAttr(typeNode, "name", documentType); | |
616 parent.appendChild(typeNode); | |
617 | |
618 Element uuidNode = creator.create("uuid"); | |
619 creator.addAttr(uuidNode, "value", super.identifier); | |
620 parent.appendChild(uuidNode); | |
621 | |
622 Element hashNode = creator.create("hash"); | |
623 creator.addAttr(hashNode, "value", this.hash()); | |
624 parent.appendChild(hashNode); | |
625 } | |
626 | |
627 /** | |
628 * Create the fis select box. | |
629 */ | |
630 protected Element createSelectBox( | |
631 XMLUtils.ElementCreator artCreator, | |
632 XMLUtils.ElementCreator creator, | |
633 Document document, | |
634 CallContext context | |
635 ) { | |
636 RessourceFactory resource = RessourceFactory.getInstance(); | |
637 CallMeta callMeta = (CallMeta) context.getMeta(); | |
638 String productName = product.getName(); | |
639 | |
640 Element selectNode = creator.create("select1"); | |
641 creator.addAttr(selectNode, "ref", "product"); | |
642 artCreator.addAttr(selectNode, "state", INITIAL_STATE, true); | |
643 | |
644 | |
645 Element labelNode = creator.create("label"); | |
646 labelNode.setTextContent( | |
647 resource.getRessource(callMeta.getLanguages(), "product", "product") | |
648 ); | |
649 | |
650 Element choicesNode = creator.create("choices"); | |
651 | |
652 Element itemNode = creator.create("item"); | |
653 creator.addAttr(itemNode, "selected", "true"); | |
654 | |
655 Element choiceLabel = creator.create("label"); | |
656 choiceLabel.setTextContent(resource.getRessource( | |
657 callMeta.getLanguages(), | |
658 productName, | |
659 productName | |
660 )); | |
661 | |
662 Element choiceValue = creator.create("value"); | |
663 choiceValue.setTextContent(productName); | |
664 | |
665 itemNode.appendChild(choiceLabel); | |
666 itemNode.appendChild(choiceValue); | |
667 choicesNode.appendChild(itemNode); | |
668 | |
669 selectNode.appendChild(labelNode); | |
670 selectNode.appendChild(choicesNode); | |
671 | |
672 return selectNode; | |
673 } | |
674 | |
675 | |
676 /** | |
677 * Insert all reachable states into the describe document returned by | |
678 * {@link #describe(org.w3c.dom.Document, de.intevation.artifacts.CallContext)} | |
679 */ | |
680 protected void createReachableStates( | |
681 XMLUtils.ElementCreator creator, | |
682 Element parent, | |
683 Document document | |
684 ) { | |
685 Element stateNode = creator.create("reachable-states"); | |
686 if (this.current != null) { | |
687 | |
688 // add future states | |
689 Iterator<Transition> transitions = this.transitions.iterator(); | |
690 while (transitions.hasNext()) { | |
691 Transition tmpTransition = transitions.next(); | |
692 if (tmpTransition.getFrom().equals(current.getID()) && | |
693 tmpTransition.isValid(this.current)){ | |
694 Element currentNode = creator.create("state"); | |
695 creator.addAttr(currentNode, "name", tmpTransition.getTo()); | |
696 creator.addAttr( | |
697 currentNode, | |
698 "description", | |
699 this.states.get(tmpTransition.getTo()).getDescription()); | |
700 stateNode.appendChild(currentNode); | |
701 } | |
702 } | |
703 | |
704 | |
705 // add old states | |
706 appendOldReachableStates(creator, stateNode, current); | |
707 } | |
708 parent.appendChild(stateNode); | |
709 } | |
710 | |
711 | |
712 /** | |
713 * Insert states which have been visited by this artifact into the xml | |
714 * document returned by {@link #describe(org.w3c.dom.Document, | |
715 * de.intevation.artifacts.CallContext)} | |
716 */ | |
717 protected void appendOldReachableStates( | |
718 XMLUtils.ElementCreator creator, | |
719 Element parent, | |
720 State state | |
721 ) { | |
722 if (state == null) | |
723 return; | |
724 | |
725 while (state != null) { | |
726 Element currentNode = creator.create("state"); | |
727 creator.addAttr(currentNode, "name", state.getID()); | |
728 creator.addAttr(currentNode, "description", state.getDescription()); | |
729 parent.appendChild(currentNode); | |
730 | |
731 state = state.getParent(); | |
732 } | |
733 } | |
734 | |
735 | |
736 /** | |
737 * Insert the current state into the xml document returned by | |
738 * {@link #describe(org.w3c.dom.Document, de.intevation.artifacts.CallContext)} | |
739 */ | |
740 protected void createCurrentState( | |
741 XMLUtils.ElementCreator creator, | |
742 Element parent, | |
743 Document document | |
744 ) { | |
745 Element stateNode = creator.create("state"); | |
746 creator.addAttr(stateNode, "name", this.current.getID()); | |
747 creator.addAttr(stateNode, "description", this.current.getDescription()); | |
748 parent.appendChild(stateNode); | |
749 } | |
750 | |
751 | |
752 protected void createModel( | |
753 XMLUtils.ElementCreator creator, | |
754 Element parent, | |
755 Document document | |
756 ) { | |
757 Element modelNode = creator.create("model"); | |
758 if (this.current != null) { | |
759 Collection<InputValue> inputValues = this.current | |
760 .getRequiredInputValues(); | |
761 if (inputValues != null) { | |
762 Iterator<InputValue> it = inputValues.iterator(); | |
763 while (it.hasNext()) { | |
764 InputValue inputValue = it.next(); | |
765 Element inputNode = creator.create("input"); | |
766 creator.addAttr(inputNode, "name", inputValue.getName()); | |
767 creator.addAttr(inputNode, "type", inputValue.getType()); | |
768 modelNode.appendChild(inputNode); | |
769 } | |
770 } | |
771 } | |
772 parent.appendChild(modelNode); | |
773 } | |
774 | |
775 /** | |
776 * Append the user interface description to the document returned by | |
777 * {@link #describe(org.w3c.dom.Document, de.intevation.artifacts.CallContext)} | |
778 * @param creator XML element creator. | |
779 * @param parent New elements are appended to this node. | |
780 * @param document Current document. | |
781 * @param context CallContext | |
782 * @param uuid The uuid of the artifact. | |
783 */ | |
784 protected void createUserInterface( | |
785 XMLUtils.ElementCreator creator, | |
786 Element parent, | |
787 Document document, | |
788 CallContext context, | |
789 String uuid | |
790 ) { | |
791 XMLUtils.ElementCreator xCreator = new XMLUtils.ElementCreator( | |
792 document, | |
793 XMLUtils.XFORM_URL, | |
794 XMLUtils.XFORM_PREFIX | |
795 ); | |
796 | |
797 Element uiNode = creator.create("ui"); | |
798 Element staticNode = creator.create("static"); | |
799 Element dynamic = creator.create("dynamic"); | |
800 | |
801 uiNode.appendChild(staticNode); | |
802 uiNode.appendChild(dynamic); | |
803 | |
804 parent.appendChild(uiNode); | |
805 | |
806 // append fis to dynamic part | |
807 appendFis(document, staticNode, context, product.getArtifactFactory()); | |
808 | |
809 if (this.current != null) { | |
810 Element staticUI = createSelectBox( | |
811 creator, xCreator, document, context | |
812 ); | |
813 staticNode.appendChild(staticUI); | |
814 | |
815 this.current.describe( | |
816 document, uiNode, context, uuid | |
817 ); | |
818 } | |
819 } | |
820 | |
821 | |
822 /** | |
823 * Append possible output targets to the document returned by | |
824 * {@link #describe(org.w3c.dom.Document, de.intevation.artifacts.CallContext)} | |
825 * @param creator Used to create xml elements. | |
826 * @param parent New elements are appended to this node. | |
827 * @param document The current document. | |
828 */ | |
829 protected void createOutputs( | |
830 XMLUtils.ElementCreator creator, | |
831 Element parent, | |
832 Document document | |
833 ) { | |
834 log.debug("GNVArtifactBase.createOutputs"); | |
835 Element outputsNode = creator.create("outputs"); | |
836 if (this.current instanceof OutputState) { | |
837 Collection<OutputMode> outputModes = ((OutputState) this.current) | |
838 .getOutputModes(); | |
839 if (outputModes != null) { | |
840 Iterator<OutputMode> it = outputModes.iterator(); | |
841 while (it.hasNext()) { | |
842 OutputMode outputMode = it.next(); | |
843 log.debug("Write Outputnode for " + outputMode.toString()); | |
844 Element outputModeNode = creator.create("output"); | |
845 creator.addAttr( | |
846 outputModeNode, "name", outputMode.getName()); | |
847 creator.addAttr( | |
848 outputModeNode, "description", outputMode.getDescription()); | |
849 creator.addAttr( | |
850 outputModeNode, "mime-type", outputMode.getMimeType()); | |
851 outputsNode.appendChild(outputModeNode); | |
852 | |
853 Collection<InputValue> inputParameters = outputMode | |
854 .getInputParameters(); | |
855 if (inputParameters != null) { | |
856 Element inputParametersNode = creator.create("parameter"); | |
857 outputModeNode.appendChild(inputParametersNode); | |
858 Iterator<InputValue> it2 = inputParameters.iterator(); | |
859 while (it2.hasNext()) { | |
860 InputValue inputValue = it2.next(); | |
861 Element inputParameterNode = | |
862 creator.create("parameter"); | |
863 creator.addAttr( | |
864 inputParameterNode, "name", inputValue.getName()); | |
865 creator.addAttr( | |
866 inputParameterNode, "type", inputValue.getType()); | |
867 creator.addAttr( | |
868 inputParameterNode, "value", inputValue.getDefaultValue()); | |
869 inputParametersNode.appendChild(inputParameterNode); | |
870 } | |
871 } | |
872 | |
873 // append export modes | |
874 List<ExportMode> exportModes = outputMode.getExportModes(); | |
875 if (exportModes != null) { | |
876 Element exports = creator.create("exports"); | |
877 outputModeNode.appendChild(exports); | |
878 | |
879 for (ExportMode exp: exportModes) { | |
880 Element export = creator.create("export"); | |
881 creator.addAttr( | |
882 export, "name", exp.getName()); | |
883 creator.addAttr( | |
884 export, "description", exp.getDescription()); | |
885 creator.addAttr( | |
886 export, "mime-type", exp.getMimeType()); | |
887 | |
888 exports.appendChild(export); | |
889 } | |
890 } | |
891 } | |
892 } else { | |
893 log.warn("No Outputmodes given."); | |
894 } | |
895 } | |
896 parent.appendChild(outputsNode); | |
897 } | |
898 | |
899 /** | |
900 * Parse input data from feed-document. | |
901 * @param document Feed-document | |
902 * @param xPath Path to input data. | |
903 * @return A collection with InputData objects. | |
904 */ | |
905 protected Collection<InputData> parseInputData(Document document, | |
906 String xPath) { | |
907 HashMap<String, InputData> returnValue = null; | |
908 | |
909 NodeList inputElemets = (NodeList) XMLUtils.xpath(document, xPath, | |
910 XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); | |
911 if (inputElemets != null) { | |
912 returnValue = new HashMap<String, InputData>(); | |
913 | |
914 for (int i = 0; i < inputElemets.getLength(); i++) { | |
915 Element inputDataNode = (Element)inputElemets.item(i); | |
916 String name = inputDataNode.getAttribute("name"); | |
917 String value = inputDataNode.getAttribute("value"); | |
918 | |
919 if (returnValue.containsKey(name)) { | |
920 InputData inputData = returnValue.get(name); | |
921 inputData.concartValue(value); | |
922 log.debug(inputData.toString()); | |
923 returnValue.put(name, inputData); | |
924 } else { | |
925 InputData inputData = new DefaultInputData(name, value); | |
926 | |
927 returnValue.put(name, inputData); | |
928 } | |
929 } | |
930 } | |
931 return returnValue.values(); | |
932 } | |
933 | |
934 /** | |
935 * Call an output target (e.g. chart, wms, etc.) | |
936 * @param format XML document which contains some further information about | |
937 * the desired output. | |
938 * @param outputStream Stream used for writing the output. | |
939 * @param context CallContext | |
940 * @throws IOException If an error occured while writing the result to the | |
941 * output stream. | |
942 */ | |
943 @Override | |
944 public void out(Document format, OutputStream outputStream, | |
945 CallContext context) throws IOException { | |
946 log.debug("TGNVArtifactBase.out"); | |
947 try { | |
948 | |
949 if (current != null && current instanceof OutputState) { | |
950 ((OutputState) current) | |
951 .out(format, this.parseInputData( | |
952 format, XPATH_OUTPUT_PARAMS), | |
953 outputStream, super.identifier, context); | |
954 } | |
955 } catch (StateException e) { | |
956 log.error(e, e); | |
957 throw new IOException(e.getMessage()); | |
958 } | |
959 } | |
960 | |
961 | |
962 protected static String readOutputType(Document document) { | |
963 String value = XMLUtils.xpathString( | |
964 document, XPATH_OUTPUT_NAME, ArtifactNamespaceContext.INSTANCE); | |
965 return value; | |
966 } | |
967 | |
968 | |
969 /** | |
970 * The the current product. | |
971 * @param product New product. | |
972 */ | |
973 public void setProduct(Product product) { | |
974 this.product = product; | |
975 } | |
976 | |
977 /** | |
978 * Call endOfLife of parent class and the current state. | |
979 */ | |
980 @Override | |
981 public void endOfLife(Object globalContext) { | |
982 super.endOfLife(globalContext); | |
983 | |
984 if (current != null) { | |
985 current.endOfLife(globalContext); | |
986 } | |
987 } | |
988 | |
989 /** | |
990 * Retrieves a map with given InputData which have been inserted into the | |
991 * current artifact before the parameterization began. | |
992 */ | |
993 public Map<String, InputData> getPreSettings() { | |
994 return this.preSettings; | |
995 } | |
996 | |
997 /** | |
998 * Set InputData which are used in later states. | |
999 */ | |
1000 public void setPreSettings(Map<String, InputData> preSettings) { | |
1001 this.preSettings = preSettings; | |
1002 if (this.current != null){ | |
1003 this.current.setPreSettings(preSettings); | |
1004 } | |
1005 } | |
1006 } | |
1007 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |