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
199 for (Node child = oldNode.getFirstChild();
200 child != null;
201 child = child.getNextSibling()) {
202 oldNode.removeChild(child);
203 }
204 if (newNode != null) {
205
206 for (Node child = newNode.getFirstChild();
207 child != null;
208 child = child.getNextSibling()) {
209 Node importedNode = oldNode.getOwnerDocument().
210 importNode(child, true);
211 oldNode.appendChild(importedNode);
212 }
213 }
214 } catch (SCXMLExpressionException see) {
215
216 Object valueObject = eval.eval(ctx, expr);
217 SCXMLHelper.setNodeValue(oldNode, valueObject.toString());
218 }
219 if (appLog.isDebugEnabled()) {
220 appLog.debug("<assign>: data node '" + oldNode.getNodeName()
221 + "' updated");
222 }
223 TriggerEvent ev = new TriggerEvent(name + ".change",
224 TriggerEvent.CHANGE_EVENT);
225 derivedEvents.add(ev);
226 } else {
227 appLog.error("<assign>: location does not point to"
228 + " a <data> node");
229 }
230 } else {
231
232 if (!ctx.has(name)) {
233 errRep.onError(ErrorConstants.UNDEFINED_VARIABLE, name
234 + " = null", parentState);
235 } else {
236 Object varObj = null;
237 if (src != null && src.trim().length() > 0) {
238 varObj = getSrcNode();
239 } else {
240 varObj = eval.eval(ctx, expr);
241 }
242 ctx.set(name, varObj);
243 if (appLog.isDebugEnabled()) {
244 appLog.debug("<assign>: Set variable '" + name + "' to '"
245 + String.valueOf(varObj) + "'");
246 }
247 TriggerEvent ev = new TriggerEvent(name + ".change",
248 TriggerEvent.CHANGE_EVENT);
249 derivedEvents.add(ev);
250 }
251 }
252 ctx.setLocal(getNamespacesKey(), null);
253 }
254
255 /***
256 * Get the {@link Node} the "src" attribute points to.
257 *
258 * @return The node the "src" attribute points to.
259 */
260 private Node getSrcNode() {
261 String resolvedSrc = src;
262 if (pathResolver != null) {
263 resolvedSrc = pathResolver.resolvePath(src);
264 }
265 Document doc = null;
266 try {
267 doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().
268 parse(resolvedSrc);
269 } catch (Throwable t) {
270 org.apache.commons.logging.Log log = LogFactory.
271 getLog(Assign.class);
272 log.error(t.getMessage(), t);
273 }
274 if (doc == null) {
275 return null;
276 }
277 return doc.getDocumentElement();
278 }
279
280 }