<?xml version="1.0" encoding="UTF-8"?>
<!--
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
-->

<document>

 <properties>
  <title>Using custom actions with Commons SCXML</title>
  <author email="dev@commons.apache.org">Commons Documentation Team</author>
 </properties>

 <body>

  <section name="What is a 'custom action'?">

   <p>Actions are SCXML elements that "do" something. Actions can be
      used where "executable content" is permissible, for example,
      within &lt;onentry&gt;, &lt;onexit&gt; and &lt;transition&gt;
      elements.</p>

   <p>The <a href="http://www.w3.org/TR/scxml/">SCXML specification</a>
      (currently a Working Draft) defines a set of "standard actions".
      These include &lt;var&gt;, &lt;assign&gt;, &lt;log&gt;, &lt;send&gt;,
      &lt;cancel&gt;, &lt;if&gt;, &lt;elseif&gt; and &lt;else&gt;.</p>

   <p>The specification also allows implementations to define "custom actions"
      in addition to the standard actions. What such actions "do" is
      upto the author of these actions, and these are therefore
      called "custom" since they are tied to a specific implementation
      of the SCXML specification.</p>

  </section>

  <section name="Custom actions with Commons SCXML">

   <p>Commons SCXML makes authoring custom actions fairly straightforward.</p>

   <subsection name="What can be done via a custom action">

    <p>A custom action in the Commons SCXML implementation has access to:
     <ul>
      <li>The current
          <a href="../apidocs/org/apache/commons/scxml/Context.html">Context</a>
          (and hence, the values of variables in the current Context).
      </li>
      <li>Any other Context within the document, provided the id of the
          parent &lt;state&gt; is known.
      </li>
      <li>The expression
          <a href="../apidocs/org/apache/commons/scxml/Evaluator.html">Evaluator</a>
          for this document, and hence the ability to evaluate a given
          expression against the current or a identifiable Context.
      </li>
      <li>The list of other actions in this
          <a href="../apidocs/org/apache/commons/scxml/model/Executable.html">Executable</a>
          .</li>
      <li>The "root" Context, to examine any variable values in the
          "document environment".</li>
      <li>The
          <a href="../apidocs/org/apache/commons/scxml/EventDispatcher.html">EventDispatcher</a>,
          to send or cancel events.</li>
      <li>The
          <a href="../apidocs/org/apache/commons/scxml/ErrorReporter.html">ErrorReporter</a>,
          to report any errors (that the ErrorReporter knows how to handle).</li>
      <li>The histories, for any identifiable &lt;history&gt;.</li>
      <li>The
          <a href="../apidocs/org/apache/commons/scxml/NotificationRegistry.html">NotificationRegistry</a>,
          to obtain the list of listeners attached to identifiable
          "observers".</li>
      <li>The engine log, to log any information it needs to.</li>
     </ul>
    </p>

   </subsection>

  </section>

  <section name="Walkthrough - Adding a 'hello world' custom action">

   <p>Lets walk through the development of a simple, custom "hello world"
      action.</p>

   <subsection name="Idea">

    <p>We need a &lt;hello&gt; action in our (fictitious) namespace
      "http://my.custom-actions.domain/CUSTOM". The action "tag" will
      have one attribute "name". The action simply logs a hello to the
      value of the name attribute when it executes.</p>

    <p>A simple example is
      <a href="http://svn.apache.org/repos/asf/commons/proper/scxml/trunk/src/test/java/org/apache/commons/scxml/custom-hello-world-01.xml">here</a>
      .</p>

   </subsection>

   <subsection name="Custom action implementation">

    <p>A custom action must extend the Commons SCXML
       <a href="../apidocs/org/apache/commons/scxml/model/Action.html">Action</a>
       abstract base class.</p>

    <p>Here is the Java source for our custom
       <a href="../xref-test/org/apache/commons/scxml/model/Hello.html">Hello</a>
       action. The execute() method contains the logging statement.</p>

   </subsection>

   <subsection name="Using a custom SCXML digester">

    <p>With the custom action(s) implemented, the document may be
    parsed using a custom SCXML digester that is aware of these actions
    like so:</p>

    <pre>
      // (1) Create a list of custom actions, add as many as are needed
      List customActions = new ArrayList();
      CustomAction ca =
            new CustomAction("http://my.custom-actions.domain/CUSTOM",
                             "hello", Hello.class);
      customActions.add(ca);

      // (2) Parse the SCXML document containing the custom action(s)
      SCXML scxml = null;
      try {
          scxml = SCXMLParser.parse(url, errorHandler, customActions);
          // Also see other methods in SCXMLParser API
          // "url" points to SCXML document
          // "errorHandler" is SAX ErrorHandler
      } catch (Exception e) {
          // bad document, take necessary action
      }
    </pre>

    <p>This approach can only be used if the custom
       rule has no body content (child "tags") or if the custom action
       implements the
       <a href="../apidocs/org/apache/commons/scxml/model/ExternalContent.html">ExternalContent</a>
       interface, in which case, any body content gets read into a list
       of DOM nodes. For any other requirements, the digester rules
       can be added by directly by obtaining a Digester instance with the
       "default" SCXML rules using the <code>newInstance()</code> methods
       and further directly adding the necessary rules using the
       <a href="http://commons.apache.org/digester/commons-digester-1.8/docs/api/">digester API</a>
       .</p>

   </subsection>

   <subsection name="Read in the 'custom' SCXML document">

    <p>For documents without custom actions, the utility methods of the
       <a href="../apidocs/org/apache/commons/scxml/io/SCXMLParser.html">SCXMLParser</a>
       should be used. That section is
       <a href="core-parser.html">here</a>.</p>

   </subsection>


   <subsection name="Launching the engine">

    <p>Having obtained the SCXML object beyond step (2) above,
       proceed as usual, see the section on the
       <a href="core-engine.html">Commons SCXML engine</a>
       for details.</p>

   </subsection>

  </section>

 </body>

</document>
