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   * &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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 &lt;send&gt; 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