<?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>Datamodels in Commons SCXML</title>
  <author email="dev@commons.apache.org">Commons Documentation Team</author>
 </properties>

 <body>

  <section name="Data in SCXML documents">

   <p>SCXML documents contain numerous expressions, such as when describing
   the guard conditions for &lt;transition&gt; elements, the expressions
   that are logged via the &lt;log&gt; element, assignments etc. The data
   portions in these expressions can come from a couple of sources.</p>

   <subsection name="The datamodel element">

    <p>SCXML gives authors the ability to define a first-class data model as
    part of the SCXML document. A data model consists of a &lt;datamodel&gt;
    element containing one or more &lt;data&gt; element, each of which may
    contain an XML data tree (i.e. it is recommended that each &lt;data&gt;
    element contain <b>only one child element</b>).</p>

    <p>Also, SCXML documents are <b>namespace-aware</b>. Therefore, the root
    of the data tree should define one or more namespaces as needed, and must
    <b>not</b> itself be in the SCXML namespace.</p>

    <p>For example, the document level data model for a SCXML document
    defining the states in a travel reservation system may look like this:</p>

    <pre>
     &lt;scxml xmlns="http://www.w3.org/2005/07/scxml"
               version="1.0"
               initialstate="init-travel-plan"&gt;

      &lt;datamodel&gt;
        &lt;data name="airlineticket"&gt;
          &lt;!-- Note namespace declaration in line below --&gt;
          &lt;flight xmlns=""&gt;
            &lt;origin/&gt;
            &lt;destination/&gt;
            &lt;!-- default values for trip and class --&gt;
            &lt;trip&gt;round&lt;/trip&gt;
            &lt;class&gt;economy&lt;/class&gt;
            &lt;meal/&gt;
          &lt;/flight&gt;
        &lt;/data&gt;
        &lt;data name="hotelbooking"&gt;
          &lt;hotel xmlns=""&gt;
            &lt;stay&gt;
              &lt;startdate/&gt;
              &lt;enddate/&gt;
            &lt;/stay&gt;
            &lt;adults&gt;1&lt;/adults&gt;
            &lt;children&gt;0&lt;/children&gt;
            &lt;rooms&gt;1&lt;/rooms&gt;
            &lt;rate/&gt;
          &lt;/hotel&gt;
        &lt;/data&gt;
      &lt;/datamodel&gt;

      &lt;state id="init-travel-plan"&gt;
        &lt;!-- content for the init-travel-plan state --&gt;
      &lt;/state&gt;

      &lt;!-- and so on ... --&gt;

     &lt;/scxml&gt;
    </pre>

    <p>A &lt;data&gt; element may also contain a string literal or number,
    which can be considered as a degenerate XML data tree with a single
    leaf node:</p>

    <pre>
     &lt;data name="foo" expr='bar'" /&gt;
    </pre>

   </subsection>

   <subsection name="Scratch space variables">

    <p>SCXML also allows document authors to define scratch space variables.
    These may be defined only where executable content is permissible,
    that is within an &lt;onentry&gt;, &lt;onexit&gt; or &lt;transition&gt;
    element. A &lt;var&gt; element is used for such definition, like so:</p>
    
    <pre>
     &lt;onentry&gt;
      &lt;var name="foo" expr="'bar'" /&gt;
     &lt;/onentry&gt;
    </pre>

    <p>The difference between the use of a var element as shown above and
    the degenerate use of a data element (where it contains a single string
    literal or number, rather than an XML tree) is that the data element
    is part of the first class datamodel for the document (or state) but
    the var isn't. This subtlety manifests as different behavior when
    the SCXML engine is reset, whereby the scratch space variables (var)
    are lost or deleted, whereas the first class data model elements
    are restored to their initial value.</p>

   </subsection>

   <subsection name="Distributing the data model">

    <p>The &lt;datamodel&gt; element can be "distributed" through the SCXML
    document. It can be placed as a child element of either the &lt;scxml&gt;
    element (document root) or any &lt;state&gt; element. This is meant
    to be an authoring convenience in order to allow parts of the data model
    to be placed closer to the location in the document where they will be
    accessed (via expressions, for example).</p>

    <p>For example, the above travel reservation datamodel may be
    authored as follows:</p>

    <pre>
     &lt;scxml xmlns="http://www.w3.org/2005/07/scxml"
               version="1.0"
               initialstate="airline-ticket"&gt;

      &lt;state id="airline-ticket"&gt;
        &lt;datamodel&gt;
          &lt;data name="airlineticket"&gt;
            &lt;flight xmlns=""&gt;
              &lt;origin/&gt;
              &lt;destination/&gt;
              &lt;!-- default values for trip and class --&gt;
              &lt;trip&gt;round&lt;/trip&gt;
              &lt;class&gt;economy&lt;/class&gt;
              &lt;meal/&gt;
            &lt;/flight&gt;
          &lt;/data&gt;
        &lt;/datamodel&gt;

        &lt;!-- other content for the airline-ticket state --&gt;

        &lt;!-- event names on transitions arbitrarily chosen
                for illustration--&gt;

        &lt;transition event="done.flight.reservation" target="hotel-booking" /&gt;
      &lt;/state&gt;

      &lt;state id="hotel-booking"&gt;
        &lt;datamodel&gt;
          &lt;data name="hotelbooking"&gt;
            &lt;hotel xmlns=""&gt;
              &lt;stay&gt;
                &lt;startdate/&gt;
                &lt;enddate/&gt;
              &lt;/stay&gt;
              &lt;adults&gt;1&lt;/adults&gt;
              &lt;children&gt;0&lt;/children&gt;
              &lt;rooms&gt;1&lt;/rooms&gt;
              &lt;rate/&gt;
            &lt;/hotel&gt;
          &lt;/data&gt;
        &lt;/datamodel&gt;

        &lt;!-- other content for the hotel-booking state --&gt;

        &lt;transition event="done.hotel.booking" target="hotel-booking" /&gt;
      &lt;/state&gt;

      &lt;!-- other states ... --&gt;

     &lt;/scxml&gt;
    </pre>

    <p>Commons SCXML creates a new
    <a href="../apidocs/org/apache/commons/scxml/Context.html">Context</a>
    for each state that needs one, and each data element may be thought of
    as a <code>org.w3c.dom.Node</code> object placed in the corresponding
    Context. The datamodel element at the document root populates the
    root context. See <a href="contexts-evaluators.html">contexts and evaluators</a>
    section of this user guide for more on contexts, evaluators and root
    contexts.</p>

   </subsection>

   <a name="datafn"/>
  </section>

  <section name="References to data in expressions">

   <p>Since the data elements contain XML data trees, the straightforward
   way to refer to bits inside these in expressions is to use XPath or an
   equivalent language. Commons SCXML currently supports expression languages
   such as Commons JEXL and Commons EL, which do not have any inherent
   understanding of XPath. Therefore, Commons SCXML defines a <b>Data()</b>
   function for use in JEXL or EL expressions, for example:</p>

   <pre>
    &lt;var name="arrival" expr="Data(hotelbooking, 'hotel/stay/arrival')" /&gt;
   </pre>

   <p>The above expression extracts the arrival date from the hotelbooking
   data in the documents datamodel and stores it in a scratch space variable
   named "arrival". The first argument is value of the name attribute of the
   &lt;data&gt; element and the second is the String value of the XPath
   expression. If more than one matching nodes are found, the first one
   is returned.</p>

   <a name="assign"/>
  </section>

  <section name="Assignments">

   <p>Assignments are done via the SCXML &lt;assign&gt; action, which can
   only be placed in an &lt;onentry&gt;, &lt;onexit&gt; or &lt;transition&gt;
   element. Based on the left hand side value (lvalue) and right hand side
   value (rvalue) in the assignment, Commons SCXML supports three kinds
   of assignments:</p>

   <ol>

    <li><p><b>Assigning to a scratch space variable</b> - Here, the lvalue is
    a variable defined via a &lt;var&gt; element.
    <pre>
      &lt;assign name="foo" expr="some-expression" /&gt;
    </pre>
    The expression may return a value of any type, which becomes the new
    value for the variable named "foo".</p>
    </li>

    <li><p><b>Assigning a literal to a data subtree</b> - In this case, the
    lvalue is a node in a data tree and the rvalue is a String literal
    or a number.
    <pre>
      &lt;assign location="Data(hotelbooking, 'hotel/rooms')" expr="2" /&gt;
    </pre>
    Or more usefully, the rvalue is some expression that evaluates to the
    numeric constant (2). In such cases, the literal (String or number)
    is added as a child text node to the node the lvalue points to.</p>
    </li>

    <li><p><b>Assigning a XML tree to a data subtree</b> - Here, the lvalue is
    a node in a data tree and the rvalue is also a node (in a data tree or
    otherwise). As an illustration, consider we also had data related to car
    rentals in the above example, and in certain situations (probably
    common) the car rental reservation dates coincide with the hotel booking
    dates, such a data "copy" is performed as:
    <pre>
      &lt;assign location="Data(carrental, 'car/dates')"
                 expr="Data(hotelbooking, 'hotel/stay')" /&gt;

      &lt;!-- deletes all children of &lt;dates&gt; and then copies
              over all children of &lt;stay&gt;, the &lt;startdate&gt;
              and &lt;enddate&gt; in this case --&gt;
    </pre>
    In these cases, the children of the node pointed by the expression are
    first cloned, and then added as children to the node the lvalue points
    to.</p>
    </li>

   </ol>

  </section>

 </body>

</document>

