View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  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  package org.apache.commons.scxml.invoke;
    18
    19  import java.io.IOException;
    20  import java.io.Serializable;
    21  import java.util.Iterator;
    22  import java.util.Map;
    23
    24  import org.apache.commons.scxml.Context;
    25  import org.apache.commons.scxml.Evaluator;
    26  import org.apache.commons.scxml.SCInstance;
    27  import org.apache.commons.scxml.SCXMLExecutor;
    28  import org.apache.commons.scxml.TriggerEvent;
    29  import org.apache.commons.scxml.env.SimpleDispatcher;
    30  import org.apache.commons.scxml.env.SimpleErrorHandler;
    31  import org.apache.commons.scxml.env.SimpleErrorReporter;
    32  import org.apache.commons.scxml.env.SimpleSCXMLListener;
    33  import org.apache.commons.scxml.io.SCXMLDigester;
    34  import org.apache.commons.scxml.model.ModelException;
    35  import org.apache.commons.scxml.model.SCXML;
    36  import org.xml.sax.SAXException;
    37
    38  /***
    39   * A simple {@link Invoker} for SCXML documents. Invoked SCXML document
    40   * may not contain external namespace elements, further invokes etc.
    41   */
    42  public class SimpleSCXMLInvoker implements Invoker, Serializable {
    43
    44      /*** Serial version UID. */
    45      private static final long serialVersionUID = 1L;
    46      /*** Parent state ID. */
    47      private String parentStateId;
    48      /*** Event prefix, all events sent to the parent executor must begin
    49       *  with this prefix. */
    50      private String eventPrefix;
    51      /*** Invoking document's SCInstance. */
    52      private SCInstance parentSCInstance;
    53      /*** The invoked state machine executor. */
    54      private SCXMLExecutor executor;
    55      /*** Cancellation status. */
    56      private boolean cancelled;
    57
    58      //// Constants
    59      /*** Prefix for all events sent to the parent state machine. */
    60      private static String invokePrefix = ".invoke.";
    61      /*** Suffix for invoke done event. */
    62      private static String invokeDone = "done";
    63      /*** Suffix for invoke cancel response event. */
    64      private static String invokeCancelResponse = "cancel.response";
    65
    66      /***
    67       * {@inheritDoc}.
    68       */
    69      public void setParentStateId(final String parentStateId) {
    70          this.parentStateId = parentStateId;
    71          this.eventPrefix = parentStateId + invokePrefix;
    72          this.cancelled = false;
    73      }
    74
    75      /***
    76       * {@inheritDoc}.
    77       */
    78      public void setSCInstance(final SCInstance scInstance) {
    79          this.parentSCInstance = scInstance;
    80      }
    81
    82      /***
    83       * {@inheritDoc}.
    84       */
    85      public void invoke(final String source, final Map params)
    86      throws InvokerException {
    87          SCXML scxml = null;
    88          try {
    89              scxml = SCXMLDigester.digest(source,
    90                  new SimpleErrorHandler(), null);
    91          } catch (ModelException me) {
    92              throw new InvokerException(me.getMessage(), me.getCause());
    93          } catch (IOException ioe) {
    94              throw new InvokerException(ioe.getMessage(), ioe.getCause());
    95          } catch (SAXException se) {
    96              throw new InvokerException(se.getMessage(), se.getCause());
    97          }
    98          Evaluator eval = parentSCInstance.getEvaluator();
    99          executor = new SCXMLExecutor(eval,
    100             new SimpleDispatcher(), new SimpleErrorReporter());
    101         Context rootCtx = eval.newContext(null);
    102         for (Iterator iter = params.entrySet().iterator(); iter.hasNext();) {
    103             Map.Entry entry = (Map.Entry) iter.next();
    104             rootCtx.setLocal((String) entry.getKey(), entry.getValue());
    105         }
    106         executor.setRootContext(rootCtx);
    107         executor.setStateMachine(scxml);
    108         executor.addListener(scxml, new SimpleSCXMLListener());
    109         try {
    110             executor.go();
    111         } catch (ModelException me) {
    112             throw new InvokerException(me.getMessage(), me.getCause());
    113         }
    114     }
    115
    116     /***
    117      * {@inheritDoc}.
    118      */
    119     public void parentEvents(final TriggerEvent[] evts)
    120     throws InvokerException {
    121         if (cancelled) {
    122             return; // no further processing should take place
    123         }
    124         boolean doneBefore = executor.getCurrentStatus().isFinal();
    125         try {
    126             executor.triggerEvents(evts);
    127         } catch (ModelException me) {
    128             throw new InvokerException(me.getMessage(), me.getCause());
    129         }
    130         if (!doneBefore && executor.getCurrentStatus().isFinal()) {
    131             TriggerEvent te = new TriggerEvent(eventPrefix + invokeDone,
    132                 TriggerEvent.SIGNAL_EVENT);
    133             new AsyncTrigger(parentSCInstance.getExecutor(), te);
    134         }
    135     }
    136
    137     /***
    138      * {@inheritDoc}.
    139      */
    140     public void cancel()
    141     throws InvokerException {
    142         cancelled = true;
    143         TriggerEvent te = new TriggerEvent(eventPrefix
    144             + invokeCancelResponse, TriggerEvent.SIGNAL_EVENT);
    145         new AsyncTrigger(parentSCInstance.getExecutor(), te);
    146     }
    147
    148 }
    149