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