| <?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 <transition> elements, the expressions |
| that are logged via the <log> 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 <datamodel> |
| element containing one or more <data> element, each of which may |
| contain a XML data tree. 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> |
| <scxml xmlns="http://www.w3.org/2005/07/scxml" |
| version="1.0" |
| initialstate="init-travel-plan"> |
| |
| <datamodel> |
| <data name="airlineticket"> |
| <flight> |
| <origin/> |
| <destination/> |
| <!-- default values for trip and class --> |
| <trip>round</trip> |
| <class>economy</class> |
| <meal/> |
| </flight> |
| </data> |
| <data name="hotelbooking"> |
| <hotel> |
| <stay> |
| <startdate/> |
| <enddate/> |
| </stay> |
| <adults>1</adults> |
| <children>0</children> |
| <rooms>1</rooms> |
| <rate/> |
| </hotel> |
| </data> |
| </datamodel> |
| |
| <state id="init-travel-plan"> |
| <!-- content for the init-travel-plan state --> |
| </state> |
| |
| <!-- and so on ... --> |
| |
| </scxml> |
| </pre> |
| |
| <p>A <data> 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> |
| <data name="foo" expr='bar'" /> |
| </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 <onentry>, <onexit> or <transition> |
| element. A <var> element is used for such definition, like so:</p> |
| |
| <pre> |
| <onentry> |
| <var name="foo" expr="'bar'" /> |
| </onentry> |
| </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 <datamodel> element can be "distributed" through the SCXML |
| document. It can be placed as a child element of either the <scxml> |
| element (document root) or any <state> 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> |
| <scxml xmlns="http://www.w3.org/2005/07/scxml" |
| version="1.0" |
| initialstate="airline-ticket"> |
| |
| <state id="airline-ticket"> |
| <datamodel> |
| <data name="airlineticket"> |
| <flight> |
| <origin/> |
| <destination/> |
| <!-- default values for trip and class --> |
| <trip>round</trip> |
| <class>economy</class> |
| <meal/> |
| </flight> |
| </data> |
| </datamodel> |
| |
| <!-- other content for the airline-ticket state --> |
| |
| <!-- event names on transitions arbitrarily chosen |
| for illustration--> |
| |
| <transition event="done.flight.reservation" target="hotel-booking" /> |
| </state> |
| |
| <state id="hotel-booking"> |
| <datamodel> |
| <data name="hotelbooking"> |
| <hotel> |
| <stay> |
| <startdate/> |
| <enddate/> |
| </stay> |
| <adults>1</adults> |
| <children>0</children> |
| <rooms>1</rooms> |
| <rate/> |
| </hotel> |
| </data> |
| </datamodel> |
| |
| <!-- other content for the hotel-booking state --> |
| |
| <transition event="done.hotel.booking" target="hotel-booking" /> |
| </state> |
| |
| <!-- other states ... --> |
| |
| </scxml> |
| </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> |
| <var name="arrival" expr="Data(hotelbooking, 'hotel/stay/arrival')" /> |
| </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 |
| <data> 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 <assign> action, which can |
| only be placed in an <onentry>, <onexit> or <transition> |
| 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 <var> element. |
| <pre> |
| <assign name="foo" expr="some-expression" /> |
| </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> |
| <assign location="Data(hotelbooking, 'hotel/rooms')" expr="2" /> |
| </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> |
| <assign location="Data(carrental, 'car/dates')" |
| expr="Data(hotelbooking, 'hotel/stay')" /> |
| |
| <!-- deletes all children of <dates> and then copies |
| over all children of <stay>, the <startdate> |
| and <enddate> in this case --> |
| </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> |
| |