View Javadoc

1   /*
2    *
3    *   Copyright 2005-2006 The Apache Software Foundation.
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   *
17   */
18  package org.apache.commons.scxml.model;
19  
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.StringTokenizer;
26  
27  import org.apache.commons.logging.Log;
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.SCInstance;
33  import org.apache.commons.scxml.SCXMLExpressionException;
34  import org.apache.commons.scxml.SCXMLHelper;
35  import org.apache.commons.scxml.TriggerEvent;
36  
37  /***
38   * The class in this SCXML object model that corresponds to the
39   * <send> SCXML element.
40   *
41   */
42  public class Send extends Action implements ExternalContent {
43  
44      /***
45       * The default targettype.
46       */
47      private static final String TARGETTYPE_SCXML = "scxml";
48  
49      /***
50       * The spec mandated derived event when target cannot be reached
51       * for TARGETTYPE_SCXML.
52       */
53      private static final String EVENT_ERR_SEND_TARGETUNAVAILABLE =
54          "error.send.targetunavailable";
55  
56      /***
57       * The ID of the send message.
58       */
59      private String sendid;
60  
61      /***
62       * An expression returning the target location of the event.
63       */
64      private String target;
65  
66      /***
67       * The type of the Event I/O Processor that the event.
68       * should be dispatched to
69       */
70      private String targettype;
71  
72      /***
73       * The event is dispatched after the delay interval elapses.
74       */
75      private String delay;
76  
77      /***
78       * The data containing information which may be used by the
79       * implementing platform to configure the event processor.
80       */
81      private String hints;
82  
83      /***
84       * The namelist to the sent.
85       */
86      private String namelist;
87  
88      /***
89       * The list of external nodes associated with this <send> element.
90       */
91      private List externalNodes;
92  
93      /***
94       * The type of event being generated.
95       */
96      private String event;
97  
98      /***
99       * OutputFormat used to serialize external nodes.
100      *
101     private static final OutputFormat format;
102     static {
103         format = new OutputFormat();
104         format.setOmitXMLDeclaration(true);
105     }
106     */
107 
108     /***
109      * Constructor.
110      */
111     public Send() {
112         super();
113         this.externalNodes = new ArrayList();
114         this.targettype = TARGETTYPE_SCXML;
115     }
116 
117     /***
118      * Get the delay.
119      *
120      * @return Returns the delay.
121      */
122     public final String getDelay() {
123         return delay;
124     }
125 
126     /***
127      * Set the delay.
128      *
129      * @param delay The delay to set.
130      */
131     public final void setDelay(final String delay) {
132         this.delay = delay;
133     }
134 
135     /***
136      * Get the list of external namespaced child nodes.
137      *
138      * @return List Returns the list of externalnodes.
139      */
140     public final List getExternalNodes() {
141         return externalNodes;
142     }
143 
144     /***
145      * Set the list of external namespaced child nodes.
146      *
147      * @param externalNodes The externalnode to set.
148      */
149     public final void setExternalNodes(final List externalNodes) {
150         this.externalNodes = externalNodes;
151     }
152 
153     /***
154      * Get the hints for this <send> element.
155      *
156      * @return String Returns the hints.
157      */
158     public final String getHints() {
159         return hints;
160     }
161 
162     /***
163      * Set the hints for this <send> element.
164      *
165      * @param hints The hints to set.
166      */
167     public final void setHints(final String hints) {
168         this.hints = hints;
169     }
170 
171     /***
172      * Get the namelist.
173      *
174      * @return String Returns the namelist.
175      */
176     public final String getNamelist() {
177         return namelist;
178     }
179 
180     /***
181      * Set the namelist.
182      *
183      * @param namelist The namelist to set.
184      */
185     public final void setNamelist(final String namelist) {
186         this.namelist = namelist;
187     }
188 
189     /***
190      * Get the identifier for this <send> element.
191      *
192      * @return String Returns the sendid.
193      */
194     public final String getSendid() {
195         return sendid;
196     }
197 
198     /***
199      * Set the identifier for this <send> element.
200      *
201      * @param sendid The sendid to set.
202      */
203     public final void setSendid(final String sendid) {
204         this.sendid = sendid;
205     }
206 
207     /***
208      * Get the target for this <send> element.
209      *
210      * @return String Returns the target.
211      */
212     public final String getTarget() {
213         return target;
214     }
215 
216     /***
217      * Set the target for this <send> element.
218      *
219      * @param target The target to set.
220      */
221     public final void setTarget(final String target) {
222         this.target = target;
223     }
224 
225     /***
226      * Get the target type for this <send> element.
227      *
228      * @return String Returns the targettype.
229      */
230     public final String getTargettype() {
231         return targettype;
232     }
233 
234     /***
235      * Set the target type for this <send> element.
236      *
237      * @param targettype The targettype to set.
238      */
239     public final void setTargettype(final String targettype) {
240         this.targettype = targettype;
241     }
242 
243     /***
244      * Get the event to send.
245      *
246      * @param event The event to set.
247      */
248     public final void setEvent(final String event) {
249         this.event = event;
250     }
251 
252     /***
253      * Set the event to send.
254      *
255      * @return String Returns the event.
256      */
257     public final String getEvent() {
258         return event;
259     }
260 
261     /***
262      * {@inheritDoc}
263      */
264     public void execute(final EventDispatcher evtDispatcher,
265             final ErrorReporter errRep, final SCInstance scInstance,
266             final Log appLog, final Collection derivedEvents)
267     throws ModelException, SCXMLExpressionException {
268         // Lets see if we should handle it ourselves
269         if (targettype != null && targettype.trim().toLowerCase().
270                 equals(TARGETTYPE_SCXML)) {
271             if (SCXMLHelper.isStringEmpty(target)) {
272                 derivedEvents.add(new TriggerEvent(event,
273                     TriggerEvent.SIGNAL_EVENT));
274             } else {
275                 // We know of no other
276                 appLog.warn("<send>: Unavailable target - " + target);
277                 derivedEvents.add(new TriggerEvent(
278                     EVENT_ERR_SEND_TARGETUNAVAILABLE,
279                     TriggerEvent.ERROR_EVENT));
280             }
281             // short-circuit the EventDispatcher
282             return;
283         }
284         // Else, let the EventDispatcher take care of it
285         State parentState = getParentState();
286         Context ctx = scInstance.getContext(parentState);
287         Evaluator eval = scInstance.getEvaluator();
288         Object hintsValue = null;
289         if (!SCXMLHelper.isStringEmpty(hints)) {
290             hintsValue = eval.eval(ctx, hints);
291         }
292         Map params = null;
293         if (!SCXMLHelper.isStringEmpty(namelist)) {
294             StringTokenizer tkn = new StringTokenizer(namelist);
295             params = new HashMap(tkn.countTokens());
296             while (tkn.hasMoreTokens()) {
297                 String varName = tkn.nextToken();
298                 Object varObj = ctx.get(varName);
299                 if (varObj == null) {
300                     //considered as a warning here
301                     errRep.onError(ErrorReporter.UNDEFINED_VARIABLE,
302                             varName + " = null", parentState);
303                 }
304                 params.put(varName, varObj);
305             }
306         }
307         long wait = 0L;
308         if (delay != null && delay.length() > 0) {
309             try {
310                 wait = Long.parseLong(delay.trim());
311             } catch (NumberFormatException nfe) {
312                 appLog.warn("Could not parse delay for <send>, "
313                     + "it will be treated as immediate", nfe);
314             }
315         }
316         evtDispatcher.send(sendid, target, targettype, event, params,
317             hintsValue, wait, externalNodes);
318     }
319 
320 }
321