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