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.util.Collection;
20
21 import javax.xml.parsers.DocumentBuilderFactory;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.commons.scxml.Context;
26 import org.apache.commons.scxml.ErrorReporter;
27 import org.apache.commons.scxml.Evaluator;
28 import org.apache.commons.scxml.EventDispatcher;
29 import org.apache.commons.scxml.PathResolver;
30 import org.apache.commons.scxml.SCInstance;
31 import org.apache.commons.scxml.SCXMLExpressionException;
32 import org.apache.commons.scxml.SCXMLHelper;
33 import org.apache.commons.scxml.TriggerEvent;
34 import org.apache.commons.scxml.semantics.ErrorConstants;
35 import org.w3c.dom.Document;
36 import org.w3c.dom.Node;
37
38 /***
39 * The class in this SCXML object model that corresponds to the
40 * <assign> SCXML element.
41 *
42 */
43 public class Assign extends Action implements PathResolverHolder {
44
45 /***
46 * Serial version UID.
47 */
48 private static final long serialVersionUID = 1L;
49
50 /***
51 * Left hand side expression evaluating to a previously
52 * defined variable.
53 */
54 private String name;
55
56 /***
57 * Left hand side expression evaluating to a location within
58 * a previously defined XML data tree.
59 */
60 private String location;
61
62 /***
63 * The source where the new XML instance for this location exists.
64 */
65 private String src;
66
67 /***
68 * Expression evaluating to the new value of the variable.
69 */
70 private String expr;
71
72 /***
73 * {@link PathResolver} for resolving the "src" result.
74 */
75 private PathResolver pathResolver;
76
77 /***
78 * Constructor.
79 */
80 public Assign() {
81 super();
82 }
83
84 /***
85 * Get the variable to be assigned a new value.
86 *
87 * @return Returns the name.
88 */
89 public String getName() {
90 return name;
91 }
92
93 /***
94 * Get the variable to be assigned a new value.
95 *
96 * @param name The name to set.
97 */
98 public void setName(final String name) {
99 this.name = name;
100 }
101
102 /***
103 * Get the expr that will evaluate to the new value.
104 *
105 * @return Returns the expr.
106 */
107 public String getExpr() {
108 return expr;
109 }
110
111 /***
112 * Set the expr that will evaluate to the new value.
113 *
114 * @param expr The expr to set.
115 */
116 public void setExpr(final String expr) {
117 this.expr = expr;
118 }
119
120 /***
121 * Get the location for a previously defined XML data tree.
122 *
123 * @return Returns the location.
124 */
125 public String getLocation() {
126 return location;
127 }
128
129 /***
130 * Set the location for a previously defined XML data tree.
131 *
132 * @param location The location.
133 */
134 public void setLocation(final String location) {
135 this.location = location;
136 }
137
138 /***
139 * Get the source where the new XML instance for this location exists.
140 *
141 * @return Returns the source.
142 */
143 public String getSrc() {
144 return src;
145 }
146
147 /***
148 * Set the source where the new XML instance for this location exists.
149 *
150 * @param src The source.
151 */
152 public void setSrc(final String src) {
153 this.src = src;
154 }
155
156 /***
157 * Get the {@link PathResolver}.
158 *
159 * @return Returns the pathResolver.
160 */
161 public PathResolver getPathResolver() {
162 return pathResolver;
163 }
164
165 /***
166 * Set the {@link PathResolver}.
167 *
168 * @param pathResolver The pathResolver to set.
169 */
170 public void setPathResolver(final PathResolver pathResolver) {
171 this.pathResolver = pathResolver;
172 }
173
174 /***
175 * {@inheritDoc}
176 */
177 public void execute(final EventDispatcher evtDispatcher,
178 final ErrorReporter errRep, final SCInstance scInstance,
179 final Log appLog, final Collection derivedEvents)
180 throws ModelException, SCXMLExpressionException {
181 State parentState = getParentState();
182 Context ctx = scInstance.getContext(parentState);
183 Evaluator eval = scInstance.getEvaluator();
184 ctx.setLocal(getNamespacesKey(), getNamespaces());
185
186 if (!SCXMLHelper.isStringEmpty(location)) {
187 Node oldNode = eval.evalLocation(ctx, location);
188 if (oldNode != null) {
189
190
191 Node newNode = null;
192 try {
193 if (src != null && src.trim().length() > 0) {
194 newNode = getSrcNode();
195 } else {
196 newNode = eval.evalLocation(ctx, expr);
197 }
198 if (newNode != null) {
199
200 for (Node child = newNode.getFirstChild();
201 child != null;
202 child = child.getNextSibling()) {
203 Node importedNode = oldNode.getOwnerDocument().
204 importNode(child, true);
205 oldNode.appendChild(importedNode);
206 }
207 }
208 } catch (SCXMLExpressionException see) {
209
210 Object valueObject = eval.eval(ctx, expr);
211 SCXMLHelper.setNodeValue(oldNode, valueObject.toString());
212 }
213 if (appLog.isDebugEnabled()) {
214 appLog.debug("<assign>: data node '" + oldNode.getNodeName()
215 + "' updated");
216 }
217 TriggerEvent ev = new TriggerEvent(name + ".change",
218 TriggerEvent.CHANGE_EVENT);
219 derivedEvents.add(ev);
220 } else {
221 appLog.error("<assign>: location does not point to"
222 + " a <data> node");
223 }
224 } else {
225
226 if (!ctx.has(name)) {
227 errRep.onError(ErrorConstants.UNDEFINED_VARIABLE, name
228 + " = null", parentState);
229 } else {
230 Object varObj = null;
231 if (src != null && src.trim().length() > 0) {
232 varObj = getSrcNode();
233 } else {
234 varObj = eval.eval(ctx, expr);
235 }
236 ctx.set(name, varObj);
237 if (appLog.isDebugEnabled()) {
238 appLog.debug("<assign>: Set variable '" + name + "' to '"
239 + String.valueOf(varObj) + "'");
240 }
241 TriggerEvent ev = new TriggerEvent(name + ".change",
242 TriggerEvent.CHANGE_EVENT);
243 derivedEvents.add(ev);
244 }
245 }
246 ctx.setLocal(getNamespacesKey(), null);
247 }
248
249 /***
250 * Get the {@link Node} the "src" attribute points to.
251 *
252 * @return The node the "src" attribute points to.
253 */
254 private Node getSrcNode() {
255 String resolvedSrc = src;
256 if (pathResolver != null) {
257 resolvedSrc = pathResolver.resolvePath(src);
258 }
259 Document doc = null;
260 try {
261 doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().
262 parse(resolvedSrc);
263 } catch (Throwable t) {
264 org.apache.commons.logging.Log log = LogFactory.
265 getLog(Assign.class);
266 log.error(t.getMessage(), t);
267 }
268 if (doc == null) {
269 return null;
270 }
271 return doc.getDocumentElement();
272 }
273
274 }