Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java @ 122:d3b8b0b1d010
Implemented the step-forward part of the advance operation.
flys-artifacts/trunk@1446 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Thu, 10 Mar 2011 05:56:17 +0000 |
parents | e0ded17a4846 |
children | ebb1cb69d847 |
comparison
equal
deleted
inserted
replaced
121:e0ded17a4846 | 122:d3b8b0b1d010 |
---|---|
1 package de.intevation.flys.artifacts; | 1 package de.intevation.flys.artifacts; |
2 | 2 |
3 import java.util.HashMap; | 3 import java.util.HashMap; |
4 import java.util.List; | 4 import java.util.List; |
5 import java.util.Map; | 5 import java.util.Map; |
6 import java.util.Set; | |
7 import java.util.Vector; | |
6 | 8 |
7 import javax.xml.xpath.XPathConstants; | 9 import javax.xml.xpath.XPathConstants; |
8 | 10 |
9 import org.apache.log4j.Logger; | 11 import org.apache.log4j.Logger; |
10 | 12 |
22 import de.intevation.artifactdatabase.DefaultArtifact; | 24 import de.intevation.artifactdatabase.DefaultArtifact; |
23 import de.intevation.artifactdatabase.data.DefaultStateData; | 25 import de.intevation.artifactdatabase.data.DefaultStateData; |
24 import de.intevation.artifactdatabase.data.StateData; | 26 import de.intevation.artifactdatabase.data.StateData; |
25 import de.intevation.artifactdatabase.state.State; | 27 import de.intevation.artifactdatabase.state.State; |
26 import de.intevation.artifactdatabase.state.StateEngine; | 28 import de.intevation.artifactdatabase.state.StateEngine; |
29 import de.intevation.artifactdatabase.transition.TransitionEngine; | |
27 | 30 |
28 import de.intevation.flys.artifacts.context.FLYSContext; | 31 import de.intevation.flys.artifacts.context.FLYSContext; |
29 | 32 |
30 | 33 |
31 /** | 34 /** |
41 | 44 |
42 /** The XPath that points to the input data elements of the FEED document.*/ | 45 /** The XPath that points to the input data elements of the FEED document.*/ |
43 public static final String XPATH_FEED_INPUT = | 46 public static final String XPATH_FEED_INPUT = |
44 "/art:action/art:data/art:input"; | 47 "/art:action/art:data/art:input"; |
45 | 48 |
49 /** The XPath that points to the name of the target state of ADVANCE.*/ | |
50 public static final String XPATH_ADVANCE_TARGET = | |
51 "/art:action/art:target/@art:name"; | |
52 | |
53 /** The constant string that shows that an operation was successful.*/ | |
54 public static final String OPERATION_SUCCESSFUL = "SUCCESS"; | |
55 | |
56 /** The constant string that shows that an operation failed.*/ | |
57 public static final String OPERATION_FAILED = "FAILURE"; | |
58 | |
46 | 59 |
47 /** The identifier of the current state. */ | 60 /** The identifier of the current state. */ |
48 protected String currentStateId; | 61 protected String currentStateId; |
49 | 62 |
63 /** The identifiers of previous states on a stack.*/ | |
64 protected Vector<String> previousStateIds; | |
65 | |
50 /** The name of the artifact.*/ | 66 /** The name of the artifact.*/ |
51 protected String name; | 67 protected String name; |
52 | 68 |
53 /** The data that have been inserted into this artifact.*/ | 69 /** The data that have been inserted into this artifact.*/ |
54 protected Map<String, StateData> data; | 70 protected Map<String, StateData> data; |
56 | 72 |
57 /** | 73 /** |
58 * The default constructor that creates an empty FLYSArtifact. | 74 * The default constructor that creates an empty FLYSArtifact. |
59 */ | 75 */ |
60 public FLYSArtifact() { | 76 public FLYSArtifact() { |
61 data = new HashMap<String, StateData>(); | 77 data = new HashMap<String, StateData>(); |
78 previousStateIds = new Vector<String>(); | |
62 } | 79 } |
63 | 80 |
64 | 81 |
65 /** | 82 /** |
66 * Returns the name of the concrete artifact. | 83 * Returns the name of the concrete artifact. |
137 Element result = creator.create("result"); | 154 Element result = creator.create("result"); |
138 doc.appendChild(result); | 155 doc.appendChild(result); |
139 | 156 |
140 try { | 157 try { |
141 saveData(target, XPATH_FEED_INPUT); | 158 saveData(target, XPATH_FEED_INPUT); |
142 creator.addAttr(result, "type", "SUCCESS", true); | 159 creator.addAttr(result, "type", OPERATION_SUCCESSFUL, true); |
143 } | 160 } |
144 catch (IllegalArgumentException iae) { | 161 catch (IllegalArgumentException iae) { |
145 creator.addAttr(result, "type", "FAILURE", true); | 162 creator.addAttr(result, "type", OPERATION_FAILED, true); |
146 | 163 |
147 // TODO I18N this message - getMessage() returns a lookup string, no | 164 // TODO I18N this message - getMessage() returns a lookup string, no |
148 // human readable error message | 165 // human readable error message |
149 result.setTextContent(iae.getMessage()); | 166 result.setTextContent(iae.getMessage()); |
150 } | 167 } |
168 | |
169 return doc; | |
170 } | |
171 | |
172 | |
173 /** | |
174 * This method handles request for changing the current state of an | |
175 * artifact. It is possible to step forward or backward. | |
176 * | |
177 * @param target The incoming ADVANCE document. | |
178 * @param context The CallContext. | |
179 * | |
180 * @return a document that contains a SUCCESS or FAILURE message. | |
181 */ | |
182 public Document advance(Document target, CallContext context) { | |
183 Document doc = XMLUtils.newDocument(); | |
184 | |
185 XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( | |
186 doc, | |
187 ArtifactNamespaceContext.NAMESPACE_URI, | |
188 ArtifactNamespaceContext.NAMESPACE_PREFIX); | |
189 | |
190 Element result = ec.create("result"); | |
191 doc.appendChild(result); | |
192 | |
193 String targetState = XMLUtils.xpathString( | |
194 target, XPATH_ADVANCE_TARGET, ArtifactNamespaceContext.INSTANCE); | |
195 | |
196 if (isStateReachable(targetState, context)) { | |
197 logger.debug("Advance: Step forward."); | |
198 | |
199 Vector<String> prev = getPreviousStateIds(); | |
200 prev.add(getCurrentStateId()); | |
201 | |
202 setCurrentStateId(targetState); | |
203 | |
204 ec.addAttr(result, "type", OPERATION_SUCCESSFUL, true); | |
205 | |
206 return doc; | |
207 } | |
208 | |
209 // TODO IMPLEMENT STEP BACK! | |
210 | |
211 logger.warn("Advance: Cannot advance to '" + targetState + "'"); | |
212 | |
213 ec.addAttr(result, "type", OPERATION_FAILED, true); | |
151 | 214 |
152 return doc; | 215 return doc; |
153 } | 216 } |
154 | 217 |
155 | 218 |
199 return engine.getState(getCurrentStateId()); | 262 return engine.getState(getCurrentStateId()); |
200 } | 263 } |
201 | 264 |
202 | 265 |
203 /** | 266 /** |
267 * Returns the vector of previous state identifiers. | |
268 * | |
269 * @return the vector of previous state identifiers. | |
270 */ | |
271 protected Vector<String> getPreviousStateIds() { | |
272 return previousStateIds; | |
273 } | |
274 | |
275 | |
276 /** | |
204 * Adds a new StateData item to the data pool of this artifact. | 277 * Adds a new StateData item to the data pool of this artifact. |
205 * | 278 * |
206 * @param name the name of the data object. | 279 * @param name the name of the data object. |
207 * @param data the data object itself. | 280 * @param data the data object itself. |
208 */ | 281 */ |
209 protected void addData(String name, StateData data) { | 282 protected void addData(String name, StateData data) { |
210 this.data.put(name, data); | 283 this.data.put(name, data); |
284 } | |
285 | |
286 | |
287 /** | |
288 * This method returns a specific StateData object that is stored in the | |
289 * data pool of this artifact. | |
290 * | |
291 * @param name The name of the data object. | |
292 * | |
293 * @return the StateData object if existing, otherwise null. | |
294 */ | |
295 protected StateData getData(String name) { | |
296 return data.get(name); | |
211 } | 297 } |
212 | 298 |
213 | 299 |
214 /** | 300 /** |
215 * This method stores the data that is contained in the FEED document. | 301 * This method stores the data that is contained in the FEED document. |
251 // TODO ADD INPUT VALIDATION! | 337 // TODO ADD INPUT VALIDATION! |
252 addData(name, new DefaultStateData(name, null, null, value)); | 338 addData(name, new DefaultStateData(name, null, null, value)); |
253 } | 339 } |
254 } | 340 } |
255 } | 341 } |
342 | |
343 | |
344 /** | |
345 * This method fills a state object with the data that have been inserted to | |
346 * this artifact. This is necessary to use the isStateReachable() method, | |
347 * because the Transitions need to know about the inserted data. | |
348 * | |
349 * @param state The state that needs to be filled with data. | |
350 * | |
351 * @return the filled state. | |
352 */ | |
353 protected State fillState(State state) { | |
354 Map<String, StateData> stateData = state.getData(); | |
355 Set<String> keys = stateData.keySet(); | |
356 | |
357 for (String key: keys) { | |
358 StateData tmp = getData(key); | |
359 | |
360 if (tmp != null) { | |
361 StateData data = stateData.get(key); | |
362 data.setValue(tmp.getValue()); | |
363 } | |
364 } | |
365 | |
366 return state; | |
367 } | |
368 | |
369 | |
370 /** | |
371 * Determines if the state with the identifier <i>stateId</i> is reachable | |
372 * from the current state. The determination itself takes place in the | |
373 * TransitionEngine. | |
374 * | |
375 * @param stateId The identifier of a state. | |
376 * @param context The context object. | |
377 * | |
378 * @return true, if the state specified by <i>stateId</i> is reacahble, | |
379 * otherwise false. | |
380 */ | |
381 protected boolean isStateReachable(String stateId, Object context) { | |
382 logger.debug("Determine if the state '" + stateId + "' is reachable."); | |
383 | |
384 FLYSContext flysContext = getFlysContext(context); | |
385 | |
386 State currentState = fillState(getCurrentState(context)); | |
387 StateEngine sEngine = (StateEngine) flysContext.get( | |
388 FLYSContext.STATE_ENGINE_KEY); | |
389 | |
390 TransitionEngine tEngine = (TransitionEngine) flysContext.get( | |
391 FLYSContext.TRANSITION_ENGINE_KEY); | |
392 | |
393 return tEngine.isStateReachable(stateId, currentState, sEngine); | |
394 } | |
256 } | 395 } |
257 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : | 396 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |