1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.scxml.model;
18
19 import java.io.IOException;
20 import java.util.Collection;
21
22 import javax.xml.parsers.DocumentBuilderFactory;
23 import javax.xml.parsers.FactoryConfigurationError;
24 import javax.xml.parsers.ParserConfigurationException;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.commons.scxml.Context;
29 import org.apache.commons.scxml.ErrorReporter;
30 import org.apache.commons.scxml.Evaluator;
31 import org.apache.commons.scxml.EventDispatcher;
32 import org.apache.commons.scxml.PathResolver;
33 import org.apache.commons.scxml.SCInstance;
34 import org.apache.commons.scxml.SCXMLExpressionException;
35 import org.apache.commons.scxml.SCXMLHelper;
36 import org.apache.commons.scxml.TriggerEvent;
37 import org.apache.commons.scxml.semantics.ErrorConstants;
38 import org.w3c.dom.Document;
39 import org.w3c.dom.Node;
40 import org.xml.sax.SAXException;
41
42
43
44
45
46
47 public class Assign extends Action implements PathResolverHolder {
48
49
50
51
52 private static final long serialVersionUID = 1L;
53
54
55
56
57
58 private String name;
59
60
61
62
63
64 private String location;
65
66
67
68
69 private String src;
70
71
72
73
74 private String expr;
75
76
77
78
79 private PathResolver pathResolver;
80
81
82
83
84 public Assign() {
85 super();
86 }
87
88
89
90
91
92
93 public String getName() {
94 return name;
95 }
96
97
98
99
100
101
102 public void setName(final String name) {
103 this.name = name;
104 }
105
106
107
108
109
110
111 public String getExpr() {
112 return expr;
113 }
114
115
116
117
118
119
120 public void setExpr(final String expr) {
121 this.expr = expr;
122 }
123
124
125
126
127
128
129 public String getLocation() {
130 return location;
131 }
132
133
134
135
136
137
138 public void setLocation(final String location) {
139 this.location = location;
140 }
141
142
143
144
145
146
147 public String getSrc() {
148 return src;
149 }
150
151
152
153
154
155
156 public void setSrc(final String src) {
157 this.src = src;
158 }
159
160
161
162
163
164
165 public PathResolver getPathResolver() {
166 return pathResolver;
167 }
168
169
170
171
172
173
174 public void setPathResolver(final PathResolver pathResolver) {
175 this.pathResolver = pathResolver;
176 }
177
178
179
180
181 public void execute(final EventDispatcher evtDispatcher,
182 final ErrorReporter errRep, final SCInstance scInstance,
183 final Log appLog, final Collection derivedEvents)
184 throws ModelException, SCXMLExpressionException {
185 TransitionTarget parentTarget = getParentTransitionTarget();
186 Context ctx = scInstance.getContext(parentTarget);
187 Evaluator eval = scInstance.getEvaluator();
188 ctx.setLocal(getNamespacesKey(), getNamespaces());
189
190 if (!SCXMLHelper.isStringEmpty(location)) {
191 Node oldNode = eval.evalLocation(ctx, location);
192 if (oldNode != null) {
193
194
195 Node newNode = null;
196 try {
197 if (src != null && src.trim().length() > 0) {
198 newNode = getSrcNode();
199 } else {
200 newNode = eval.evalLocation(ctx, expr);
201 }
202
203 Node removeChild = oldNode.getFirstChild();
204 while (removeChild != null) {
205 Node nextChild = removeChild.getNextSibling();
206 oldNode.removeChild(removeChild);
207 removeChild = nextChild;
208 }
209 if (newNode != null) {
210
211 for (Node child = newNode.getFirstChild();
212 child != null;
213 child = child.getNextSibling()) {
214 Node importedNode = oldNode.getOwnerDocument().
215 importNode(child, true);
216 oldNode.appendChild(importedNode);
217 }
218 }
219 } catch (SCXMLExpressionException see) {
220
221 Object valueObject = eval.eval(ctx, expr);
222 SCXMLHelper.setNodeValue(oldNode, valueObject.toString());
223 }
224 if (appLog.isDebugEnabled()) {
225 appLog.debug("<assign>: data node '" + oldNode.getNodeName()
226 + "' updated");
227 }
228 TriggerEvent ev = new TriggerEvent(name + ".change",
229 TriggerEvent.CHANGE_EVENT);
230 derivedEvents.add(ev);
231 } else {
232 appLog.error("<assign>: location does not point to"
233 + " a <data> node");
234 }
235 } else {
236
237 if (!ctx.has(name)) {
238 errRep.onError(ErrorConstants.UNDEFINED_VARIABLE, name
239 + " = null", parentTarget);
240 } else {
241 Object varObj = null;
242 if (src != null && src.trim().length() > 0) {
243 varObj = getSrcNode();
244 } else {
245 varObj = eval.eval(ctx, expr);
246 }
247 ctx.set(name, varObj);
248 if (appLog.isDebugEnabled()) {
249 appLog.debug("<assign>: Set variable '" + name + "' to '"
250 + String.valueOf(varObj) + "'");
251 }
252 TriggerEvent ev = new TriggerEvent(name + ".change",
253 TriggerEvent.CHANGE_EVENT);
254 derivedEvents.add(ev);
255 }
256 }
257 ctx.setLocal(getNamespacesKey(), null);
258 }
259
260
261
262
263
264
265 private Node getSrcNode() {
266 String resolvedSrc = src;
267 if (pathResolver != null) {
268 resolvedSrc = pathResolver.resolvePath(src);
269 }
270 Document doc = null;
271 try {
272 doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().
273 parse(resolvedSrc);
274 } catch (FactoryConfigurationError t) {
275 logError(t);
276 } catch (SAXException t) {
277 logError(t);
278 } catch (IOException t) {
279 logError(t);
280 } catch (ParserConfigurationException t) {
281 logError(t);
282 }
283 if (doc == null) {
284 return null;
285 }
286 return doc.getDocumentElement();
287 }
288
289
290
291
292 private void logError(Throwable throwable) {
293 org.apache.commons.logging.Log log = LogFactory.getLog(Assign.class);
294 log.error(throwable.getMessage(), throwable);
295 }
296
297 }