You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2012/12/06 18:42:18 UTC
[36/52] [partial] ISIS-188: moving framework/ subdirs up to parent
http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/src/docbkx/guide/isis-bdd-integration.xml
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/src/docbkx/guide/isis-bdd-integration.xml b/component/viewer/bdd/src/docbkx/guide/isis-bdd-integration.xml
new file mode 100644
index 0000000..299256b
--- /dev/null
+++ b/component/viewer/bdd/src/docbkx/guide/isis-bdd-integration.xml
@@ -0,0 +1,4170 @@
+<?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.
+-->
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"file:./src/docbkx/dtd-4.5/docbookx.dtd">
+<book>
+ <bookinfo>
+ <title><?eval ${docbkxGuideTitle}?></title>
+
+ <subtitle><?eval ${docbkxGuideSubTitle}?></subtitle>
+
+ <releaseinfo><?eval ${project.version}?></releaseinfo>
+
+ <authorgroup>
+ <author>
+ <firstname>Dan</firstname>
+
+ <surname>Haywood</surname>
+ </author>
+ </authorgroup>
+
+ <legalnotice>
+ <para>Permission is granted to make and distribute verbatim copies of
+ this manual provided that the copyright notice and this permission
+ notice are preserved on all copies.</para>
+ </legalnotice>
+ </bookinfo>
+
+ <!-- front matter -->
+
+ <toc></toc>
+
+ <preface id="preface">
+ <title>Preface</title>
+
+ <para>Behaviour-driven development is a means to drive the development of
+ an application through stories and scenarios. These are expressed in a
+ semi-formal textual form that can be understood (or indeed be written) by
+ the domain expert/business analyst, but which can then be used to directly
+ exercise the system under test as it is developed.</para>
+
+ <para>A number of frameworks exist to streamline this process. Generally
+ these require the developer to write glue code that acts as a bridge from
+ the textual specification and the system under test.</para>
+
+ <para>The <emphasis>BDD Viewer</emphasis> module for <emphasis>Apache
+ Isis</emphasis> aims to allow <acronym>BDD</acronym> stories/scenarios to
+ be written against the domain model of an Isis application, without the
+ developer having to write any glue code. It consists of a common library
+ that abstracts the interaction with the Isis metamodel, along with an
+ integration (that uses this common library) for one particular
+ <acronym>BDD</acronym> framework, namely <ulink
+ url="http://concordion.org">Concordion</ulink>. There is also outline
+ coverage of the <ulink url="http://fitnesse.org">FitNesse</ulink>
+ integration (part of <ulink
+ url="http://code.google.com/a/apache-extras.org/p/isis-extras">isis-extras</ulink>).</para>
+
+ <para>This user guide describes how to use the
+ <emphasis>Concordion</emphasis> integration, along with details of the
+ common library so that other <acronym>BDD</acronym> frameworks can be
+ integrated if required.</para>
+
+ <para><emphasis>Apache Isis</emphasis> is licensed under <ulink
+ url="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software
+ License v2</ulink>. However, although <emphasis>Concordion</emphasis>
+ itself licensed under Apache License v2, it in turn depends upon an XML
+ library called <ulink url="http://xom.nu">XOM</ulink>, which unfortunately
+ has an <ulink url="http://www.gnu.org/licenses/lgpl-2.1.html">LGPL
+ 2.1</ulink> license. Apache projects are <ulink
+ url="http://www.apache.org/legal/resolved.html#category-x">not
+ allowed</ulink> to have dependencies on <acronym>LGPL</acronym> projects.
+ </para>
+
+ <para>The workaround that we have adopted is to exclude the
+ <acronym>XOM</acronym> dependency in Isis' own
+ <filename>pom.xml</filename> files, meaning that they are compliant with
+ Apache's licensing restrictions. However, any application code that uses
+ the <emphasis>BDD Viewer</emphasis> must explicitly add its own dependency
+ to the <acronym>XOM</acronym> library. You'll find that the
+ <filename>pom.xml</filename> files generated by the quickstart archetype
+ do indeed do this.</para>
+
+ <para>However, If you are unhappy to introduce this dependency to
+ <acronym>LGPL</acronym> in your own code, then you will not be able to use
+ the <emphasis>Concordion</emphasis> integration. </para>
+ </preface>
+
+ <!-- main content -->
+
+ <chapter>
+ <title>Introduction</title>
+
+ <abstract>
+ <para>An introduction to the idea of behaviour driven development, and
+ the components that make up <emphasis>Isis</emphasis>' integration with
+ <acronym>BDD</acronym> frameworks.</para>
+ </abstract>
+
+ <sect1>
+ <title>Behaviour-driven Development</title>
+
+ <para>Prior to agile development, requirements gathering for systems was
+ traditionally performed by business analysts discussing requirements
+ with the business, and expressing those requirements in documentation,
+ such as Word specs and perhaps spreadsheets. The acceptance criteria for
+ such requirements were often only sketched out, if at all; it would
+ normally fall to the system testers to write acceptance tests for the
+ requirements, through a mixture of consulting the original (by now
+ out-of-date) requirements documentation and (as often as not)
+ reverse-engineering the implementation.</para>
+
+ <para>Behaviour-driven development combines requirements capture and the
+ acceptance test criteria in a single form, through scenarios. As before,
+ these requirements are in a form that a non-technical domain expert from
+ the business can understand. What differs though is that these scenarios
+ can be used to directly exercise the system, and so also represent the
+ acceptance tests for the correct implementation of the requirement.
+ Moreover, the results of these tests are rendered in such a way that the
+ business can understand, and thus can help determine if the code is at
+ fault or the test. Once implemented, the acceptance tests also act as a
+ regression suite for the system.</para>
+
+ <para>Scenario tests tend to act against a complete system, or sometimes
+ at a subsystem-level. At any rate the tests must be at a granularity
+ that still makes sense to a non-technical businesss person. Compare this
+ to unit testing which exercises the behaviour / method of a single
+ class.</para>
+
+ <para>Another commonly-used name for scenario testing is "agile
+ acceptance testing". We've chosen to use the term "scenario testing"
+ though; it's a somewhat less clumsy term.</para>
+ </sect1>
+
+ <sect1 id="sec.CommonLibrary">
+ <title>Common Library</title>
+
+ <para><emphasis>Apache Isis</emphasis> integrates with
+ <acronym>BDD</acronym> frameworks through the services of a common
+ library. The main concepts that the common library exposes are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the <classname>Scenario</classname> class, which provides the
+ context for a single scenario of a story</para>
+ </listitem>
+
+ <listitem>
+ <para>the <classname>AliasRegistry</classname>, which allows a
+ user-friendly alias (eg "fredCustomer") to be assigned to any domain
+ object and to be referenced subsequently</para>
+ </listitem>
+
+ <listitem>
+ <para>the <classname>StoryCell</classname> interface, which is an
+ abstraction over a single element of data</para>
+
+ <para>The default implementation just wraps a
+ <classname>java.lang.String</classname>, but some frameworks might
+ provide alternative implementations. For example,
+ <emphasis>FitNesse</emphasis> has an implementation that maps to its
+ internal representation of a cell (<classname>fit.Parse</classname>
+ class).</para>
+ </listitem>
+
+ <listitem>
+ <para>the <classname>CellBinding</classname> interface, which binds
+ a column of a table to a property or to an alias</para>
+
+ <para>Many of the <acronym>BDD</acronym> frameworks (eg
+ <emphasis>Concordion</emphasis>, <emphasis>FitNesse</emphasis>)
+ encourage the use of tables as a means of succinctly capturing
+ scenario actions. This is reflected in the design of several of the
+ classes provided by the common library. The
+ <classname>CellBinding</classname> interface is used to wire the
+ values in the rows of the table to the properties specified in the
+ header.</para>
+
+ <para>Each <classname>CellBinding</classname> has a name (eg "on
+ object") and some alternative names (eg "using"). This is useful for
+ <acronym>BDD</acronym> frameworks (such as
+ <emphasis>FitNesse</emphasis>) where the provided text from the
+ scenario needs to be parsed in some way, matching up headings of
+ columns within a tabular structure. The relevant methods for
+ <acronym>BDD</acronym> framework integrations that must do this are
+ <methodname>#matches(...)</methodname>,
+ <methodname>#setHeadColumn(..)</methodname> and
+ <methodname>#createHeadColumn(..)</methodname>. Note though that not
+ every <acronym>BDD</acronym> framework integration needs this
+ particular feature; the <emphasis>Concordion</emphasis> integration
+ for example calls pre-canned methods so the matching is done simply
+ by parameter position to these method.</para>
+
+ <para>The other main method provided by
+ <classname>CellBinding</classname> is
+ <methodname>#captureCurrent(..)</methodname>. This is used (by all
+ framework integrations) to capture the current value for the column
+ which this binding represents. For example, for a column
+ representing a property name, it might hold the value
+ "firstName".</para>
+
+ <para>The library provides a default implementation of
+ <classname>CellBinding</classname>, though subclasses can override
+ if required. (For example, the <emphasis>FitNesse</emphasis>
+ integration has its own implementation to map to its data structures
+ representing cells in the FIT tables).</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>One way of thinking of all these framework integrations is as a
+ replacement presentation layer, hitting the underlying domain model in
+ the same way that the regular <acronym>UI</acronym> would. (This is why
+ we call this module is called the <acronym>BDD</acronym><emphasis>
+ viewer</emphasis>).</para>
+
+ <para>In the following chapter (<xref
+ linkend="chp.IntroducingTheFramework" />), details are provided of how
+ the services of the common library are used by each of the supported
+ <acronym>BDD</acronym> framework integrations.</para>
+ </sect1>
+
+ <sect1>
+ <title>Concordion Integration</title>
+
+ <sect2>
+ <title>Introduction to Concordion</title>
+
+ <para><ulink url="http://concordion.org">Concordion</ulink> is a
+ framework to enable scenario testing. It is implemented as a <ulink
+ url="http://junit.org">JUnit4</ulink> test runner, with the test form
+ being written in <acronym>XHTML</acronym>. The domain expert /
+ business analyst authors new stories using an <acronym>XML</acronym>
+ editor; once executed as tests, the results are shown as the same
+ <acronym>XHTML</acronym> document, annotated to indicate which
+ assertions have succeeded, and which have failed. It also creates an
+ efficient feedback loop; a <emphasis>Concordion</emphasis> test will
+ "keep on going" even if it hits a failure. Thus the developer can
+ identify several issues and fix them in a single pass.</para>
+
+ <para><emphasis>Concordion</emphasis> works using a "convention over
+ configuration" approach, matching the <acronym>XHTML</acronym> text
+ file with a corresponding JUnit4 test run set up to run using
+ <emphasis>Concordion</emphasis>'s
+ <classname>ConcordionRunner</classname>, The developer then annotates
+ the <acronym>XHTML</acronym> using special (namespaced) attributes in
+ order identify the inputs to and expected results of the test. This is
+ used by the <classname>ConcordionRunner</classname> to call into
+ corresponding methods in the test.</para>
+
+ <para>For example:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Suppose the analyst writes a scenario test called
+ <filename>CustomerPlacesOrderScenario.xhtml</filename>.</para>
+
+ <para>In the <acronym>XHTML</acronym> the analyst has identified
+ the details of the customer doing the ordering (customer ref 4321,
+ say), the product being ordered (product code 1234), the fact that
+ the customer initially has no orders, and that the customer has no
+ invoices outstanding. The test concludes with an assertion that
+ there is now an unfulfilled order for the customer, and that the
+ customer now has an invoice to be paid.</para>
+ </listitem>
+
+ <listitem>
+ <para>The developer in turn edits the <acronym>XHTML</acronym>,
+ identifying the customer and the product.</para>
+
+ <para>He then further edits the <acronym>XHTML</acronym> to call a
+ method in the JUnit4 test representing the placing of an order:
+ <methodname>placeOrder()</methodname>, say. And he finishes by
+ annotating the <acronym>XHTML</acronym> to make assertions about
+ the post conditions (unfulfilled order, new invoice to be paid
+ etc).</para>
+ </listitem>
+
+ <listitem>
+ <para>Then, the developer writes a JUnit4 test alongside the
+ <acronym>XHTML</acronym>; in this example it would be called
+ <filename>CustomerPlacesOrderScenario.java</filename>.
+ <emphasis>Concordion</emphasis> calls into this JUnit4 test as it
+ comes across the annotations in the <acronym>XHTML</acronym>, and
+ the JUnit4 test mediates with the system under test.</para>
+ </listitem>
+
+ <listitem>
+ <para>When the test runs, <emphasis>Concordion</emphasis>
+ generates a copy of the <acronym>XHTML</acronym> in an output
+ directory which can then made available for inspection by the
+ business analyst (eg published on a website).</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The <emphasis>Concordion</emphasis> website has a good <ulink
+ url="http://concordion.org/Tutorial.html">tutorial</ulink> that
+ demonstrates all the above, and can be completed in 20~30
+ minutes.</para>
+
+ <para>One slight downside of using <emphasis>Concordion</emphasis> is
+ in having to write tests in <acronym>XHTML</acronym>. One editor that
+ we recommend (commercial, but also with a free version for personal
+ use) is <ulink url="http://xmlmind.net">XmlMind</ulink>. More detailed
+ guidance is provided in <xref linkend="apx.UsingXmlMind" />.</para>
+ </sect2>
+
+ <sect2 id="sec.HowTheIsisConcordionIntegrationWorks">
+ <title>How the Isis/Concordion Integration Works</title>
+
+ <para>Although you could test an <emphasis>Apache Isis</emphasis>
+ application using vanilla <emphasis>Concordion</emphasis>, this would
+ entail you having to write all the glue code yourself to interact with
+ the domain objects. You would also need to encode the rules that are
+ normally implemented by an <emphasis>Isis</emphasis> viewer, eg so
+ that a hidden action cannot be invoked, and an invalid value for a
+ property cannot be set.</para>
+
+ <para>The <emphasis>BDD viewer</emphasis> integration provided by
+ <emphasis>Apache Isis</emphasis> works by providing a superclass for
+ the JUnit4 test, called
+ <classname>AbstractIsisConcordionScenario</classname>. This exposes
+ methods to perform all the tasks necessary for exercising an
+ application. The precise features are outlined in <xref
+ linkend="chp.IntroducingTheFramework" />.</para>
+
+ <para>For each <acronym>XHTML</acronym> scenario test, the developer
+ writes subclasses the
+ <classname>AbstractIsisConcordionScenario</classname>, creating a name
+ matching the scenario test (ie as per regular
+ <emphasis>Concordion</emphasis>). He then annotates the original
+ <acronym>XHTML</acronym>, either calling directly into the inherited
+ methods, or writing small simple methods to delegate to these
+ inherited methods as required. The <emphasis>Concordion</emphasis>
+ website has some <ulink
+ url="http://concordion.org/Technique.html">hints and tips</ulink> to
+ help you find the right balance between these two approaches.</para>
+
+ <para>The <acronym>XHTML</acronym> script that you write should have
+ the following namespace declaration:</para>
+
+ <programlisting><html
+ xmlns:concordion="http://www.concordion.org/2007/concordion"
+ xmlns:isis="http://isis.apache.org/2010/concordion">
+ ...
+</html></programlisting>
+
+ <para>The <literal>concordion</literal> namespace is the usual
+ namespace required by <emphasis>Concordion</emphasis>. The
+ <literal>isis</literal> namespace is defined for a similar reason: to
+ allow certain commands provided by the Isis/Concordion integration to
+ be invoked. More on this in <xref
+ linkend="chp.UserInteraction" />.</para>
+ </sect2>
+
+ <sect2>
+ <title>Specifying the Output Directory</title>
+
+ <para>The directory for the generated output can be specified
+ either:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>by overriding the <methodname>outputDir()</methodname>
+ method in <classname>AbstractIsisConcordionScenario</classname>;
+ or</para>
+ </listitem>
+
+ <listitem>
+ <para>by setting the <varname>concordion.output.dir</varname>
+ system property</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>If not specified, then the output directory defaults to
+ <filename>/tmp/concordion</filename>.</para>
+ </sect2>
+
+ <sect2>
+ <title>Providing a CSS File</title>
+
+ <para>By default, Concordion will copy over the
+ <acronym>HTML</acronym> for every scenario into the output directory,
+ but it won't copy over any <acronym>CSS</acronym> resources. If you
+ want any <acronym>CSS</acronym> to be copied over, then:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>override the <methodname>customCssPackage()</methodname>
+ method in <classname>AbstractIsisConcordionScenario</classname> to
+ return any class in the package that holds the CSS file.</para>
+ </listitem>
+
+ <listitem>
+ <para>override the <methodname>customCss()</methodname> method to
+ specify the name of the <acronym>CSS</acronym> file to copy over.
+ If none is specified, then concordion.css is used.</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2>
+ <title>Configuring the Maven Surefire (test) plugin</title>
+
+ <para>The standard boilerplate to run <emphasis>Concordion</emphasis>
+ under <emphasis>Maven</emphasis> is as follows:</para>
+
+ <programlisting><plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <systemPropertyVariables>
+ <concordion.output.dir>
+ ${project.build.directory}/concordion
+ </concordion.output.dir>
+ </systemPropertyVariables>
+ <includes>
+ <include>**/*Scenario.java</include>
+ <include>**/Scenario*.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+</plugins>y</programlisting>
+
+ <para>There are a couple of points worth noting here.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>first, the <literal>systemPropertyVariables</literal>
+ element can be used to define the
+ <varname>concordion.output.dir</varname> system property, thereby
+ specifying the directory for the generated output</para>
+ </listitem>
+
+ <listitem>
+ <para>second, the <literal>includes</literal> element can be used
+ to only run classes with either a prefix or suffix
+ "<literal>Scenario</literal>". This allows common fixtures that
+ have been factored out to be ignored.</para>
+
+ <para>An alternative approach is to have a top-level "suite" page
+ that references all scenarios underneath (probably grouped into
+ stories). In this case the only test class that would be run
+ included is the top-level suite page. See <xref
+ linkend="sec.TopLevelSuitePage" /> for further discussion.</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+ </sect1>
+
+ <sect1 id="sec.FitNesseIntegration">
+ <title>FitNesse Integration</title>
+
+ <para>Due to licensing restrictions, the <emphasis>FitNesse</emphasis>
+ integration is not part of <emphasis>Apache Isis</emphasis> proper.
+ However, it is available on the companion Apache Extras' <ulink
+ url="http://code.google.com/a/apache-extras.org/p/isis-extras/"><emphasis>isis-extras</emphasis></ulink>
+ site. Check that site for its release status (it is not guaranteed to be
+ in sync with <emphasis>Isis</emphasis> releases).</para>
+
+ <para>An outline of the <emphasis>FitNesse</emphasis> integration is
+ provided here, if only to help compare and contrast the means by which
+ two different frameworks integrate with the common library. We hope that
+ this will make it easier to integrate other <acronym>BDD</acronym>
+ frameworks in the future.</para>
+ </sect1>
+ </chapter>
+
+ <chapter id="chp.IntroducingTheFramework">
+ <title>Introducing the Framework</title>
+
+ <abstract>
+ <para>An introduction to the features provided by the framework. The
+ subsequent chapters provide more detailed coverage.</para>
+ </abstract>
+
+ <para>This chapter outlines the main features of the common library and
+ their support by the framework-specific integrations. The subsequent
+ chapters provide more detailed coverage.</para>
+
+ <para>Note that due to licensing restrictions the
+ <emphasis>FitNesse</emphasis> integration is not part of <emphasis>Apache
+ Isis</emphasis>. Nevertheless, an outline of the
+ <emphasis>FitNesse</emphasis> integration is provided here, if only to
+ help compare and contrast the means by which two different frameworks
+ integrate with the common library. We hope that this will make it easier
+ to integrate other <acronym>BDD</acronym> frameworks in the future.</para>
+
+ <sect1>
+ <title>Introduction</title>
+
+ <para>Broadly speaking, the framework provides the ability to bootstrap
+ and initialize an <emphasis>Isis</emphasis> application and allow the
+ domain services and objects within that application to be exercised in
+ the same way that a user would interact with the system through a
+ viewer.</para>
+
+ <para>The common library defines these abilities in terms of "fixture"
+ classes, each of which performs a single function. For example, there is
+ a fixture class to bootstrap <emphasis>Isis</emphasis>, another to setup
+ objects, and another to describe the actual interactions by the user
+ (check a property, invoke an action etc).</para>
+
+ <para>The fixture classes in the common library are oriented around a
+ tabular approach to specifying behaviour, making it easy to integrate
+ frameworks such as <emphasis>FitNesse</emphasis> that adopt a
+ table-oriented approach. Such an approach equally supports frameworks
+ such as <emphasis>Concordion</emphasis> that allow specifications to be
+ written both as tables and in free-form text. Admittedly, this does make
+ the implementation of framework integrations a little more complex than
+ it might otherwise have been ... but this is only a problem for the
+ framework integrator, not the business analyst actually writing the
+ scenarios.</para>
+ </sect1>
+
+ <sect1>
+ <title>Fixtures</title>
+
+ <para>The following chapters describe the fixtures available in detail.
+ In summary, they are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>it bootstrap an instance of <emphasis>Apache Isis</emphasis>
+ system using the in-memory object store (see <xref
+ linkend="chp.BootstrapAndTeardown" />);</para>
+ </listitem>
+
+ <listitem>
+ <para>setting up the system state ready for the scenario (see <xref
+ linkend="chp.SetUp" />):</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>specify the date/time format</para>
+ </listitem>
+
+ <listitem>
+ <para>initialize the system with a set of services, picked up
+ from the <filename>isis.properties</filename> configuration
+ file</para>
+ </listitem>
+
+ <listitem>
+ <para>allow fixtures (domain objects) to be installed into the
+ object store</para>
+ </listitem>
+
+ <listitem>
+ <para>login a specific user</para>
+ </listitem>
+
+ <listitem>
+ <para>specify the date</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>allow the user to interact with services and domain objects
+ (see <xref linkend="chp.UserInteraction" />):</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>asserting on the value of properties and the contents of
+ collections</para>
+ </listitem>
+
+ <listitem>
+ <para>setting the value of a property (if valid) and adding
+ to/removing from a collection (if valid)</para>
+ </listitem>
+
+ <listitem>
+ <para>invoking actions</para>
+ </listitem>
+
+ <listitem>
+ <para>asserting on the state of a class member (hidden, disabled
+ or enabled)</para>
+ </listitem>
+
+ <listitem>
+ <para>assert on the state of properties</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>assert on the state of collections, either of an object, or
+ returned from an action (see <xref
+ linkend="chp.AssertingOnCollections" />);</para>
+ </listitem>
+
+ <listitem>
+ <para>tearing down the system at the end of the test (see <xref
+ linkend="chp.BootstrapAndTeardown" />)</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>There are also fixtures to help with debugging (see <xref
+ linkend="chp.Debugging" />).</para>
+
+ <para>For each fixture, you'll find there's a discussion about the
+ capabilities provided by the common fixture, and then details as to the
+ support for that fixture by each of the <acronym>BDD</acronym> framework
+ integrations (<emphasis>Concordion</emphasis> and
+ <emphasis>FitNesse</emphasis>).</para>
+ </sect1>
+ </chapter>
+
+ <chapter id="chp.BootstrapAndTeardown">
+ <title>Bootstrapping & Teardown</title>
+
+ <abstract>
+ <para>The fixtures provided for bootstrapping at the start of a
+ scenario, and tearing down at the end</para>
+ </abstract>
+
+ <para>In order to test an <emphasis>Apache Isis</emphasis> domain
+ application, a running instance of an <classname>IsisSystem</classname>
+ must be bootstrapped, with the appropriate configuration.</para>
+
+ <sect1>
+ <title>Scenario Context</title>
+
+ <para>The common library provides a context object which holds a
+ reference to a running <classname>IsisSystem</classname>. Moreover, it
+ tracks such things as the date/time that the scenario is running as, the
+ user that is logged-in, and managing the aliases of objects so that they
+ can be interacted with.</para>
+
+ <sect2>
+ <title>Common</title>
+
+ <para>An instance of the <classname>Scenario</classname> class
+ provides a context for the scenario. Framework integrations are
+ expected to instantiate this class, and then use it as the primary
+ means to interact with the system.</para>
+
+ <para>The <classname>Scenario</classname> class has a public no-arg
+ constructor. Instantiating the <classname>Scenario</classname> does
+ not do anything; it must also be bootstrapped (see <xref
+ linkend="sec.BootstrappingIsis" />).</para>
+ </sect2>
+
+ <sect2>
+ <title>Concordion</title>
+
+ <para>The <classname>AbstractIsisConcordionScenario</classname>
+ instantiates the <classname>Scenario</classname> object (from the
+ common library) automatically and binding it to a threadlocal. In
+ addition, <classname>AbstractIsisConcordionScenario</classname>
+ provides methods that can be invoked from within
+ <acronym>XHTML</acronym> (ie taking
+ <classname>String</classname>s).</para>
+
+ <para>Test cases should inherit from this abstract class, with the
+ <acronym>XHTML</acronym> typically calling to the inherited methods
+ directly. The developer may optionally add small helper methods to be
+ called from the <acronym>XHTML</acronym> instead; these can factor out
+ any boilerplate in the script.</para>
+ </sect2>
+
+ <sect2>
+ <title>FitNesse</title>
+
+ <para>Every <emphasis>FitNesse</emphasis> scenario must reference the
+ <classname>ScenarioFixture</classname> fixture which provides the
+ overall context for the framework. This instantiates a
+ <classname>Scenario</classname> object from the common library and
+ binding it to a thread-local.</para>
+
+ <para>Whereas other <emphasis>FitNesse</emphasis> fixtures are
+ instantiated once per table, the
+ <classname>ScenarioFixture</classname> is a <acronym>FIT</acronym>
+ <classname>DoFixture</classname> that exists for the duration of the
+ test page. It should typically be referenced in the test suite's setup
+ page, and should appear first within this setup:</para>
+
+ <informaltable>
+ <tgroup cols="1">
+ <colspec />
+
+ <tbody>
+ <row>
+ <entry><classname>Scenario Fixture</classname></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </sect2>
+ </sect1>
+
+ <sect1 id="sec.BootstrappingIsis">
+ <title>Bootstrapping Isis</title>
+
+ <para>An <emphasis>Isis</emphasis> runtime can be bootstrapped with a
+ single call. This installs no-op implementations of some of the main
+ components, along with an in-memory object store.</para>
+
+ <sect2>
+ <title>Common</title>
+
+ <para>The <methodname>Scenario#bootstrapIsis(String configDirectory,
+ DeploymentType deploymentType)</methodname> is used to bootstrap the
+ <emphasis>Isis</emphasis> runtime:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The specified config directory contains
+ <filename>isis.properties</filename> config file, from which the
+ services are registered. Any fixtures in that properties file are
+ ignored (the <acronym>BDD</acronym> integration requires that any
+ objects are created through the test scripts, see <xref
+ linkend="sec.SetUpObjects" /> and <xref
+ linkend="chp.UserInteraction" />).</para>
+ </listitem>
+
+ <listitem>
+ <para>The deployment type must be either EXPLORATION (meaning
+ exploration actions are enabled) or PROTOTYPE; no other values are
+ valid).</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Even if running in exploration mode, you must still logon (see
+ <xref linkend="sec.LogonAsSwitchUserTo" />) in order to indicate which
+ user account to run the scenario as.</para>
+ </sect2>
+
+ <sect2>
+ <title>Concordion</title>
+
+ <para>The <classname>AbstractIsisConcordionScenario</classname> class
+ provides two overloaded versions of
+ <methodname>bootstrapIsis(...)</methodname> method:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>#bootstrapIsis(String configDirectory,
+ DeploymentType deploymentType)</methodname></para>
+
+ <para>Intended to be called from within an <methodname>@Before
+ setUp()</methodname> method, when there's no particular need to
+ document the bootstrapping process within the scenario;</para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>#bootstrapIsis(String configDirectory, String
+ deploymentType):boolean</methodname></para>
+
+ <para>Intended to be called from the <acronym>XHTML</acronym>
+ page, allowing the scenario document the bootstrapping process.
+ For example, to bootstrap in exploration mode, use:</para>
+
+ <programlisting><p concordion:execute="#result=bootstrapIsis(#configDir,#deploymentType)">
+Isis system <span concordion:assertTrue="#result">bootstrapped</span>
+from config directory <span concordion:set="#configDir">../quickrun/config</span>
+and running in <span concordion:set="#deploymentType">exploration</span> mode.
+</p></programlisting>
+
+ <para>The method always returns <literal>true</literal>, but any
+ runtime exception will propagate to the generated page.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Whichever method is used, they both delegate to the common
+ <methodname>Scenario#bootstrapIsis(...)</methodname> method.</para>
+ </sect2>
+
+ <sect2>
+ <title>FitNesse</title>
+
+ <para>The <classname>BootstrapIsisConfiguredFromInMode</classname>
+ fixture is used to bootstrap <emphasis>Isis</emphasis>. It takes the
+ form:</para>
+
+ <informaltable>
+ <tgroup cols="4">
+ <colspec colwidth="3*" />
+
+ <tbody>
+ <row>
+ <entry><classname>Bootstrap Isis Configured
+ From</classname></entry>
+
+ <entry><emphasis>config Directory</emphasis></entry>
+
+ <entry><methodname>In Mode</methodname></entry>
+
+ <entry><emphasis>deployment Type</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>This delegates to the common
+ <methodname>Scenario#bootstrapIsis(...)</methodname> method.</para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="sec.ShutdownIsis">
+ <title>Shutdown Isis</title>
+
+ <para>This fixture shuts down the <emphasis>Isis</emphasis> runtime,
+ releasing memory and so on. A good place to put this is in the test's
+ teardown.</para>
+
+ <sect2>
+ <title>Common</title>
+
+ <para>The <methodname>Scenario#shutdownIsis()</methodname> method is
+ used to shutdown <emphasis>Isis</emphasis> runtime.</para>
+ </sect2>
+
+ <sect2>
+ <title>Concordion</title>
+
+ <para>To shutdown <emphasis>Isis</emphasis> from within
+ <emphasis>Concordion</emphasis>, use the
+ <methodname>AbstractIsisConcordionScenario#shutdownIsis()</methodname>
+ method. This just delegates to the common library's
+ <classname>Scenario#shutdownIsis()</classname> method.</para>
+ </sect2>
+
+ <sect2>
+ <title>FitNesse</title>
+
+ <para>To shutdown Isis from FitNesse, use the
+ <classname>ShutdownIsis</classname> fixture:</para>
+
+ <informaltable>
+ <tgroup cols="1">
+ <colspec colwidth="3*" />
+
+ <tbody>
+ <row>
+ <entry><classname>Shutdown Isis</classname></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>This just delegates to the common library's
+ <methodname>Scenario#shutdownIsis()</methodname> method.</para>
+ </sect2>
+ </sect1>
+ </chapter>
+
+ <chapter id="chp.SetUp">
+ <title>Scenario Set Up</title>
+
+ <abstract>
+ <para>Once <emphasis>Isis</emphasis> has been bootstrapped, the
+ application state must be setup.</para>
+ </abstract>
+
+ <para>The setup fixtures are used to specify the initial state of the
+ running application for a particular scenario's. Specifically, this means
+ setting up the services that define the application, the effective date
+ and the effective user. It also allows the setup of arbitrary objects
+ (typically reference/static data objects; for transactional objects see
+ <xref linkend="chp.UserInteraction" />).</para>
+
+ <sect1 id="sec.LogonAsSwitchUserTo">
+ <title>Logging On / Switching User</title>
+
+ <para>Used to specify the currently logged-on user. Should always be
+ called near the top of the scenario, as part of the "given". Can also be
+ used for switching the current user later on in the scenario, eg to
+ check a workflow between different users.</para>
+
+ <sect2>
+ <title>Common</title>
+
+ <para>The common library provides two overloaded methods, depending on
+ whether the roles for the user need to be specified or not:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>Scenario#logonAsOrSwitchUserTo(String
+ userName)</methodname></para>
+
+ <para>Logs on / switch user to as a specific user.</para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>Scenario#logonAsOrSwitchUserTo(String userName,
+ List<String> roleNames)</methodname></para>
+
+ <para>Logs on to a specific user, with specified roles. Part of
+ the initialization for a particular scenario's setup, and
+ typically referenced in the test suite or scenario's own setup
+ page.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The username and roles are not validated against.</para>
+ </sect2>
+
+ <sect2>
+ <title>Concordion</title>
+
+ <para>The <emphasis>Concordion</emphasis> integration provides two
+ sets of overloaded methods in
+ <classname>AbstractIsisConcordionScenario</classname>:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>#logonAs(String userName)</methodname> and
+ <methodname>#logonAs(String userName, String
+ roleListStr)</methodname></para>
+
+ <para>Intended to be called in the initial setup, as part of the
+ scenario's "given".</para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>#switchUserTo(String userName)</methodname> and
+ <methodname>#switchUserTo(String userName, String
+ roleListStr)</methodname></para>
+
+ <para>(Optional); intended to be called later on in the scenario,
+ eg, to test workflow.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Each of these is intended to be called from the
+ <acronym>XHTML</acronym>. For example:</para>
+
+ <programlisting><p concordion:execute="#result=logonAs(#userName)"><span concordion:assertTrue="#result">logged on</span> as <span concordion:set="#userName">fsmith</span></p></programlisting>
+
+ <para>The role list, if specified, should be comma-separated (any
+ white space will be ignored).</para>
+ </sect2>
+
+ <sect2>
+ <title>FitNesse</title>
+
+ <para>The FitNesse integration provides two sets of overloaded
+ fixtures:</para>
+
+ <informaltable>
+ <tgroup cols="2">
+ <colspec />
+
+ <tbody>
+ <row>
+ <entry><classname>Logon As</classname></entry>
+
+ <entry><emphasis>user name</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <informaltable>
+ <tgroup cols="4">
+ <colspec />
+
+ <tbody>
+ <row>
+ <entry><classname>Logon As</classname></entry>
+
+ <entry><emphasis>user name</emphasis></entry>
+
+ <entry><classname>With Roles</classname></entry>
+
+ <entry><emphasis>role list</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>Intended to be called in the initial setup, as part of the
+ scenario's "given".</para>
+
+ <informaltable>
+ <tgroup cols="2">
+ <colspec />
+
+ <tbody>
+ <row>
+ <entry><classname>Switch User To</classname></entry>
+
+ <entry><emphasis>user name</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <informaltable>
+ <tgroup cols="4">
+ <colspec />
+
+ <tbody>
+ <row>
+ <entry><classname>Switch User To</classname></entry>
+
+ <entry><emphasis>user name</emphasis></entry>
+
+ <entry><classname>With Roles</classname></entry>
+
+ <entry><emphasis>role list</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>Optional; intended to be called later on in the scenario, eg, to
+ test workflow.</para>
+
+ <para>The role list, if specified, should be comma-separated (any
+ white space will be ignored).</para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="sec.DateAndTimeFormat">
+ <title>Date and Time Format</title>
+
+ <para><acronym>BDD</acronym> tests often rely on exact dates and/or time
+ to be specified, but any such date/time must be specified in text form.
+ In order that tests do not fail when run with different locales, the
+ common library allows a date/time format to be specified.</para>
+
+ <para>This fixture is typically called only once in the scenario.</para>
+
+ <para><note>
+ <para>Date/time formats are based on the currently used locale. By
+ default, Isis will use the current locale. To change this, set the
+ relevant locale within <filename>isis.properties</filename>. For
+ example:</para>
+
+ <programlisting>isis.locale=de_DE</programlisting>
+ </note><note>
+ <para>Dates are always intepreted strictly as UTC dates. This means
+ that you shouldn't need to worry about the timezone in which the
+ tests are being run.</para>
+ </note></para>
+
+ <sect2>
+ <title>Common</title>
+
+ <para>The <classname>Scenario</classname> class provides two methods
+ to specify date and time formats:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>#usingDateFormat(String)</methodname> is used to
+ specify the date format.</para>
+
+ <para>If not called, the format defaults to "dd-MMM-yyyy", eg
+ 02-Aug-2010.</para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>#usingTimeFormat(String)</methodname> is used to
+ specify the time format.</para>
+
+ <para>If not called, the time format defaults to "hh:mm" (a 24
+ hour clock, eg 14:45 for 2.45pm)</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Typically the scenario will have both date and also time
+ specified (in <xref linkend="sec.SettingDateAndTime" />), but
+ assertions against domain objects will often care only about date, or
+ may occasionally care only about time. Therefore, whenever text
+ representing a date must be parsed, the following is used:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>parse against date+time (eg "dd-MMM-yyyy hh:mm")</para>
+ </listitem>
+
+ <listitem>
+ <para>if that fails, parse against just date (eg
+ "dd-MMM-yyyy")</para>
+ </listitem>
+
+ <listitem>
+ <para>if that fails, parse against just time (eg "hh:mm")</para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2>
+ <title>Concordion</title>
+
+ <para>The <classname>AbstractIsisConcordionScenario</classname>
+ provides two corresponding methods:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>#usingDateFormat(String)</methodname></para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>#usingTimeFormat(String)</methodname></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>For example:</para>
+
+ <programlisting><p concordion:execute="#result=timeIs(#dateTime)">The <span concordion:assertTrue="#result">date/time</span> is <span concordion:set="#dateTime">2 mar 2007 09:20</span>.</p> </programlisting>
+
+ <para>These just delegate to the corresponding methods in the
+ <classname>Scenario</classname> class.</para>
+ </sect2>
+
+ <sect2>
+ <title>FitNesse</title>
+
+ <para>Not implemented at this time.</para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="sec.SettingDateAndTime">
+ <title>Setting Date and Time</title>
+
+ <para><acronym>BDD</acronym> scenarios often rely on an exact date and
+ time, and the date/time that a scenario is being run upon can be
+ specified using this fixture. For example, with the date/time set,
+ functionality that checks the a property is defaulted to "today" can
+ then be easily verified.</para>
+
+ <para>This fixture will typically be called only once in a scenario.
+ However, more advanced scenarios might require the date/time to be
+ called different places. For example, a scenario might raise an
+ <classname>Invoice</classname>, then move the clock forward by 30 days
+ to test functionality relating to the handling of
+ <classname>Invoice</classname>s unpaid for more than 28 days.</para>
+
+ <sect2>
+ <title>Common</title>
+
+ <para>The
+ <methodname>Scenario#dateAndTimeIs(String)</methodname>method allows
+ the scenario to specify the date and time. Note that a
+ <classname>String</classname> is passed in rather than a
+ <classname>java.util.Date</classname>, so that the scenario can parse
+ the date according to the date/time format (see <xref
+ linkend="sec.DateAndTimeFormat" />).</para>
+
+ <para>The fixture installs the <classname>FixtureClock</classname> as
+ the implementation of the <classname>Clock</classname> singleton (in
+ the applib). Every call to the <classname>Clock</classname> will
+ return the same date/time until the method is called again.</para>
+
+ <para>If this fixture is not called, then the default system clock is
+ used, which gets the time from the host computer. The
+ <methodname>Scenario#debugClock()</methodname> method (<xref
+ linkend="sec.DebugClock" />) can be used to verify the clock
+ state.</para>
+ </sect2>
+
+ <sect2>
+ <title>Concordion</title>
+
+ <para>The <emphasis>Concordion</emphasis> integration provides a
+ number of overloaded methods, all designed to be called from the
+ <acronym>XHTML</acronym>:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>#dateIs(String
+ dateAndTimeStr)</methodname></para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>#timeIs(String
+ dateAndTimeStr)</methodname></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>For example:</para>
+
+ <programlisting><p concordion:execute="#result=timeIs(#dateTime)">
+ The <span concordion:assertTrue="#result">date/time</span>
+ is <span concordion:set="#dateTime">02-mar-2007 09:20</span>.
+</p> </programlisting>
+
+ <para>The overloaded forms are just for convenience; sometimes the
+ scenario will want to emphasis the date, other times the time.</para>
+ </sect2>
+
+ <sect2>
+ <title>FitNesse</title>
+
+ <para>The <emphasis>FitNesse</emphasis> integration provides four
+ versions (overloaded only so reads well in the page):</para>
+
+ <informaltable>
+ <tgroup cols="2">
+ <colspec />
+
+ <tbody>
+ <row>
+ <entry><classname>Date Is</classname></entry>
+
+ <entry><emphasis>date and time</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <informaltable>
+ <tgroup cols="2">
+ <colspec />
+
+ <tbody>
+ <row>
+ <entry><classname>Date Is Now</classname></entry>
+
+ <entry><emphasis>date and time</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <informaltable>
+ <tgroup cols="2">
+ <colspec />
+
+ <tbody>
+ <row>
+ <entry><classname>Time Is</classname></entry>
+
+ <entry><emphasis>date and time</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <informaltable>
+ <tgroup cols="2">
+ <colspec />
+
+ <tbody>
+ <row>
+ <entry><classname>Time Is Now</classname></entry>
+
+ <entry><emphasis>date and time</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>In each case the date/time provided is parsed against the format
+ 'dd MMM yyyy hh:mm'</para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="sec.AliasServices">
+ <title>Aliasing Services</title>
+
+ <para>Specifies an alias to a service in order to invoke actions upon
+ it. Typically this will be done for most if not all of the registered
+ repositories. The class name (as defined in
+ <filename>isis.properties</filename>) is used as the key; the alias
+ defines a simple handle.</para>
+
+ <para>For example, a service
+ <classname>com.mycompany.customers.defaults.CustomerRepositoryDefault</classname>
+ can be mapped to "customers".</para>
+
+ <sect2>
+ <title>Common</title>
+
+ <para>The common library provides two methods:<itemizedlist>
+ <listitem>
+ <para><methodname>Scenario#getAliasRegistry()</methodname></para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>AliasRegistry#aliasService(String aliasAs,
+ String serviceClassName)</methodname></para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>The <acronym>BDD</acronym> framework integration is expected to
+ obtain the <classname>AliasRegistry</classname> from the
+ <classname>Scenario</classname>, and then use the
+ <classname>AliasRegisty</classname> to register the alias.</para>
+ </sect2>
+
+ <sect2>
+ <title>Concordion</title>
+
+ <para>The <methodname>Concordion</methodname> integration provides a
+ corresponding method, <methodname>#aliasService(aliasAs, String
+ serviceClassName)</methodname>. This returns <literal>true</literal>
+ if the service was found, false otherwise. Call within a table to
+ alias multiple services, for example:<programlisting><table concordion:execute="#result=aliasService(#aliasAs, #className)">
+ <tr>
+ <th concordion:set="#className">Class Name</th>
+ <th concordion:set="#aliasAs">aliasAs</th>
+ <th concordion:assertTrue="#result"/>
+ </tr>
+ <tr>
+ <td>com.mycompany.myapp.objstore.dflt.claim.ClaimRepositoryDefault</td>
+ <td>claims</td>
+ <td>ok</td>
+ </tr>
+ <tr>
+ <td>com.mycompany.myapp.objstore.dflt.employee.EmployeeRepositoryDefault</td>
+ <td>employees</td>
+ <td>ok</td>
+ </tr>
+</table></programlisting></para>
+ </sect2>
+
+ <sect2>
+ <title>FitNesse</title>
+
+ <para>The <emphasis>FitNesse</emphasis> integration provides an
+ implementation of a <classname>ColumnFixture</classname>, which is
+ used as follows:</para>
+
+ <para><informaltable>
+ <tgroup cols="2">
+ <colspec colname="_1" />
+
+ <colspec colname="_2" />
+
+ <tbody>
+ <row>
+ <entry nameend="_2" namest="_1"><classname>Alias
+ Services</classname></entry>
+ </row>
+
+ <row>
+ <entry><classname>class name</classname></entry>
+
+ <entry><classname>alias=</classname></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>com.mycompany.myapp.objstore.dflt.claim.ClaimRepositoryDefault</emphasis></entry>
+
+ <entry><emphasis>claims</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable></para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="sec.SetUpObjects">
+ <title>Setting Up Objects</title>
+
+ <para>Virtually every scenario will require some initial objects to work
+ on, be it a <classname>Customer</classname>, an
+ <classname>Order</classname> or just some reference data. However, by
+ design the <acronym>BDD</acronym> viewer runs against an in-memory
+ object store, meaning that the application having been bootstrapped has
+ nothing in its persistent object store.</para>
+
+ <para>This fixture, therefore, is used to create objects, and persists
+ them to the object store. It is typically used for immutable
+ reference/standing data objects. It can also be to setup used for
+ transaction/operational data objects, though
+ <classname>UsingIsisViewerForSetup</classname>, <xref
+ linkend="chp.UserInteraction" />, is generallly to be preferred).</para>
+
+ <para>The <classname>DebugObjectStore</classname> fixture (<xref
+ linkend="sec.DebugObjectStore" />) can be used to check the state of
+ objects created. You can also use the RunViewer fixture (<xref
+ linkend="sec.RunViewer" />) to visually inspect the state of the system
+ using the DnD viewer.</para>
+
+ <sect2>
+ <title>Common</title>
+
+ <para>The common library support for setting up objects using the
+ <classname>SetUpObjectsPeer</classname> class. This represents the
+ context for creating a set of objects all of the same type, and is
+ usually called multiple times (eg corresponding to a table structure
+ in the scenario text itself).</para>
+
+ <para>The constructor for this class takes the following
+ arguments:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><classname>AliasRegistry</classname>
+ <varname>aliasRegistry</varname></para>
+
+ <para>the alias registry which is used to lookup aliases to
+ existing objects, and is populated with aliases for the new
+ created objects (if an alias binding is specified; see
+ below).</para>
+ </listitem>
+
+ <listitem>
+ <para><classname>String</classname>
+ <varname>className</varname></para>
+
+ <para>This is the fully qualified class name of the object to be
+ instantiated</para>
+ </listitem>
+
+ <listitem>
+ <para><classname>SetUpObjectsPeer.Mode</classname>
+ <varname>mode</varname></para>
+
+ <para>This is whether the object is to be persisted or not</para>
+ </listitem>
+
+ <listitem>
+ <para><classname>CellBinding</classname>
+ <varname>aliasBinding</varname></para>
+
+ <para>This object represents a binding to a cell that will hold
+ the reference to each newly created object. It can be left
+ <literal>null</literal> if required.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Different methods are available for <acronym>BDD</acronym>
+ framework integrations to call. Typically the <acronym>BDD</acronym>
+ framework is expected to setup header information (the names of the
+ properties), and then process each row.</para>
+
+ <para>On the header of the table, the main method to call
+ is:<itemizedlist>
+ <listitem>
+ <para><methodname>#definePropertyOrAlias(String
+ propertyNameOrAlias, int colNum)</methodname></para>
+
+ <para>This associates each column with a property of the class,
+ or an alias for the object overall</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>When processing each row, typically the main methods to call
+ are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>#addPropertyValueOrAlias(String
+ propertyOrAliasValue)</methodname></para>
+
+ <para>This provides the value of each property of the object to be
+ created, or the alias to know the object by once created. The
+ property value can either be an existing alias, else must be
+ parseable (nb: Isis' own value types itself perform the parsing,
+ so there's no additional work to be done here)</para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>#createObject()</methodname></para>
+
+ <para>This actually instantiates the object, either persistent or
+ non-persistent as specified in the constructor, and assigns it an
+ alias</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>That said, there are some other public methods that are
+ available for more complex integrations (notably:
+ <emphasis>FitNesse</emphasis>).</para>
+ </sect2>
+
+ <sect2>
+ <title>Concordion</title>
+
+ <para>The <emphasis>Concordion</emphasis> framework integration
+ provides:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>#setUpObject(String className, String aliasAs,
+ String propertyName1, String propertyName2,
+ ...)</methodname></para>
+
+ <para>There are 10 overloaded versions of this method, to account
+ for setting up different types of objects that have up to 10
+ properties.</para>
+
+ <para>The method returns a string "ok" if has worked, otherwise it
+ returns exception text. This might seem a little odd, but allows a
+ meaningful message to be shown in the
+ <acronym>XHTML</acronym>.</para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>#setUpObjectVarArgs(String className, String
+ aliasAs, ...)</methodname></para>
+
+ <para>This (protected, not public) method is to cater for setting
+ up objects that require more than 10 properties to be setup. In
+ these cases, the developer should write their own method and call
+ into the <methodname>#setUpObjectsVarargs(...)</methodname> as
+ required.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Note that this method should be called from the
+ <acronym>XHTML</acronym> using <literal>isis:execute</literal>, not
+ with <literal>concordion:execute</literal>. The difference between the
+ two is that <literal>isis:execute</literal> is called on the header
+ row as well as each body row, whereas concordion:execute only calls
+ for each body row. The integration requires the header row to be
+ called in order to read the names of the properties to be used to
+ initialize the objects.</para>
+
+ <para>For example, here's how to setup a set of three
+ <classname>Employee</classname> objects:</para>
+
+ <programlisting><p>With Employees (<span concordion:set="#className">com.mycompany.myapp.dom.employee.Employee</span>):
+</p>
+<table isis:execute="#result=setUpObject(#className, #aliasAs, #name, #approver)">
+ <tr>
+ <th concordion:set="#name">Name</th>
+ <th concordion:set="#approver">Approver</th>
+ <th concordion:set="#aliasAs">aliasAs</th>
+ <th concordion:assertEquals="#result"/>
+ </tr>
+ <tr>
+ <td>Fred Smith</td>
+ <td></td>
+ <td>Employee:Fred Smith</td>
+ <td>ok</td>
+ </tr>
+ <tr>
+ <td>Tom Brown</td>
+ <td>Employee:Fred Smith</td>
+ <td>Employee:Tom Brown</td>
+ <td>ok</td>
+ </tr>
+ <tr>
+ <td>Sam Jones</td>
+ <td>Employee:Fred Smith</td>
+ <td>Employee:Sam Jones</td>
+ <td>ok</td>
+ </tr>
+</table></programlisting>
+
+ <para>In this example, we've chosen the convention that the alias is
+ "Employee:<emphasis>FirstName LastName</emphasis>". This is though
+ just a convention; the alias could be anything you want.</para>
+ </sect2>
+
+ <sect2>
+ <title>FitNesse</title>
+
+ <para>The <emphasis>FitNesse</emphasis> integration uses the "Set Up
+ Objects" table, called like so:</para>
+
+ <informaltable>
+ <tgroup cols="3">
+ <colspec colname="_1" />
+
+ <colspec colname="_2" />
+
+ <colspec colname="_3" />
+
+ <tbody>
+ <row>
+ <entry><classname>Set Up Objects</classname></entry>
+
+ <entry nameend="_3"
+ namest="_2"><emphasis>com.mycompany.myapp.dom.employee.Employee</emphasis></entry>
+ </row>
+
+ <row>
+ <entry><classname>Name</classname></entry>
+
+ <entry><classname>Approver</classname></entry>
+
+ <entry><classname>alias as</classname></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>Fred Smith</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><emphasis>Employee:Fred Smith</emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>Tom Brown</emphasis></entry>
+
+ <entry><emphasis>Employee:Fred Smith</emphasis></entry>
+
+ <entry><emphasis>Employee:Tom Brown</emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>Sam Jones</emphasis></entry>
+
+ <entry><emphasis>Employee:Fred Smith</emphasis></entry>
+
+ <entry><emphasis>Employee:Sam Jones</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </sect2>
+ </sect1>
+ </chapter>
+
+ <chapter id="chp.UserInteraction">
+ <title>User Interaction</title>
+
+ <abstract>
+ <para>Fixtures to describe interactions with the domain objects,
+ mimicking the way in which an end-user using an Isis viewer would
+ interact.</para>
+ </abstract>
+
+ <para>The user interaction fixtures are the centrepiece of the
+ <acronym>BDD</acronym> framework, simulating the interaction with domain
+ objects as if through a viewer. Using this fixtures, the scenario can
+ interact with objects, check their state, and alias referenced or returned
+ objects for subsequent interactions</para>
+
+ <para>There is basically just one fixture used to describe user
+ interactions, namely "Using Isis Viewer". There is also a "For Setup"
+ version (ie "Using Isis Viewer For Setup") that disables checks for
+ visibility and usability, making it easier to reuse functionality for
+ setting up objects prior to a test scenario (the "given").</para>
+
+ <para>The <classname>DebugObjectStore</classname> fixture (<xref
+ linkend="sec.DebugObjectStore" />) can be used to check the state of
+ objects created.</para>
+
+ <sect1>
+ <title>Common</title>
+
+ <para>The common library provides the
+ <classname>UsingIsisViewerPeer</classname> class as a means by which the
+ <acronym>BDD</acronym> framework integration can interact with
+ <emphasis>Apache Isis</emphasis> runtime.</para>
+
+ <para>The <classname>UsingIsisViewerPeer</classname> class is generally
+ called from within a table format, with each row representing a specific
+ interaction with the domain object. For example, a row might invoke an
+ action, or could check that a class member is unavailable.</para>
+
+ <para>Some interactions can be used to create or assign aliases to
+ domain objects. For example, invoking a non-void action will return a
+ result. If the result is a domain object, then the alias can be used
+ directly subsequently in the scenario. If the result is a collection,
+ then typically it is the scenario will make an assertion on that
+ collection using "Check List" (see <xref linkend="sec.CheckList" />) or
+ alias an object out of that list using "Alias Items In List" (see <xref
+ linkend="sec.AliasItemsInList" />).</para>
+
+ <sect2>
+ <title>Constructor</title>
+
+ <para>Because <classname>UsingIsisViewerPeer</classname> is
+ table-oriented, it uses <classname>CellBinding</classname>s (see <xref
+ linkend="sec.CommonLibrary" />) to bind table headers to rows. The
+ constructor takes the following parameters:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><classname>AliasRegistry</classname></para>
+
+ <para>Used to access aliases for existing domain objects, and to
+ register aliases for newly created/found objects.</para>
+ </listitem>
+
+ <listitem>
+ <para><classname>Perform.Mode</classname></para>
+
+ <para>Whether to actually perform the interactions or not</para>
+ </listitem>
+
+ <listitem>
+ <para><classname>CellBinding</classname>s for each of the columns
+ of the table.</para>
+
+ <para>Cell bindings are discussed immediately below.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Each of the framework integrations is expected to instantiate
+ the <classname>UsingIsisViewerPeer</classname> at the beginning of the
+ table, and then call into the same instance for each row in the
+ table.</para>
+
+ <sect3>
+ <title>Cell Bindings</title>
+
+ <para>The <classname>CellBinding</classname>s passed into the
+ constructor correspond to the standard columns of the table.
+ Although all must be passed in, not all are needed for every
+ interaction; in these cases the value can be left blank. The
+ <classname>CellBinding</classname>s correspond to the following
+ column names:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the "on object" column (can also use 'object', or 'on' if
+ parsing column name provided by scenario text)</para>
+
+ <para>The (alias of) the object to interact with. A value must
+ always be provided.</para>
+ </listitem>
+
+ <listitem>
+ <para>the "alias result as" column (can also use "result=",
+ "alias=", "alias as")</para>
+
+ <para>The alias to assign the result of any interaction.</para>
+ </listitem>
+
+ <listitem>
+ <para>the "perform" column (can also use "do", "interaction",
+ "interaction type")</para>
+
+ <para>the interaction to perform; discussed further below</para>
+ </listitem>
+
+ <listitem>
+ <para>the "on member" column (can also use "member", "using
+ member", using")</para>
+
+ <para>the property, collection or action to use</para>
+ </listitem>
+
+ <listitem>
+ <para>the "that it" column (can also use "that", "verb")</para>
+
+ <para>optional qualifier for interactions that make checks;
+ discussed below</para>
+ </listitem>
+
+ <listitem>
+ <para>the "with arguments" (can also "arguments", "parameters",
+ "with parameters", "for", "value", "for parameters", "value",
+ "reference")</para>
+
+ <para>the first argument, to the interaction, if any. It is
+ possible to perform interactions with multiple arguments (for
+ example, invoking an action); but the
+ <classname>UsingIsisViewerPeer</classname> needs to have a
+ binding for the first argument so that it can knows to interpret
+ any following columns as further arguments.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The actual values that go into each of these columns are
+ listed below (<xref linkend="sec.SupportedInteractions" />).</para>
+ </sect3>
+
+ <sect3>
+ <title>The "Perform" Binding</title>
+
+ <para>Of all of the bindings discussed above, the "perform" binding
+ is the most critical because it determines the actual type of
+ interaction to be performed. The valid values that can be provided
+ for the "perform" binding are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>check property / check collection / check add to
+ collection / check remove from collection / check action</para>
+
+ <para>These are combined with a value in the "that it" binding;
+ for example "check property XXX is hidden", or "check action XXX
+ is valid for (<emphasis>some argument list</emphasis>)"</para>
+ </listitem>
+
+ <listitem>
+ <para>get property / set property / clear property</para>
+
+ <para>Read from or write to a collection. If setting, a single
+ argument is required</para>
+ </listitem>
+
+ <listitem>
+ <para>get collection / add to collection / remove from
+ collection</para>
+
+ <para>Read or write from a collection. If writing, a single
+ argument is required</para>
+ </listitem>
+
+ <listitem>
+ <para>invoke action</para>
+
+ <para>Invoke action, with 0 to many arguments</para>
+ </listitem>
+
+ <listitem>
+ <para>get property default / get property choices / get action
+ parameter default / get action choices</para>
+
+ <para>To enable the testing of the
+ <methodname>choicesXxx()</methodname> and
+ <methodname>defaultXxx()</methodname> supporting methods</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Again, see the sections below (<xref
+ linkend="sec.SupportedInteractions" />) for specifics..</para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Capture Current</title>
+
+ <para>Once the bindings have been setup, the fixture peer should be
+ called for each row in the table. The
+ <classname>CellBinding</classname> class provides the
+ <methodname>#captureCurrent(...)</methodname> method to capture the
+ relevant value for each row (with the
+ <classname>CellBinding</classname>s obtained directory from the
+ <classname>Scenario</classname> class, eg
+ <methodname>Scenario#getOnObjectBinding()</methodname>).</para>
+
+ <para>For some framework integrations (eg
+ <methodname>Concordion</methodname>) this design introduces a little
+ more complexity than strictly necessary, because the knowledge is
+ already known as to which value relates to which binding. But for
+ other frameworks (eg FitNesse), the <classname>CellBinding</classname>
+ provides a useful abstraction that makes it easy to associate values
+ with each column.</para>
+ </sect2>
+
+ <sect2>
+ <title>Validate</title>
+
+ <para>Once the values for the current row have been captured, they can
+ be validated. The <classname>UsingIsisViewerPeer</classname> class
+ provides the following methods for this:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><methodname>#validateOnObject():
+ ObjectAdapter</methodname></para>
+
+ <para>Verifies that the current value of the "on object" binding
+ corresponds to a known alias</para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>#validateAliasAs(): String</methodname></para>
+
+ <para>Verifies that the current value of the "alias as" binding is
+ not already in use</para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>#validateOnMember():
+ ObjectMember</methodname></para>
+
+ <para>Verifies that the current value of the "on member" binding
+ corresponds to the name of a member (property name, collection
+ name or action name) of the type of the object being interacted
+ with (ie, as specified in the "on object" binding)</para>
+ </listitem>
+
+ <listitem>
+ <para><methodname>#validatePerform(): Perform</methodname></para>
+
+ <para>Verifies that the current value of the "perform" binding
+ corresponds to a known interaction type for the particular type of
+ member.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Again, see the sections below (<xref
+ linkend="sec.SupportedInteractions" />) for specifics.</para>
+ </sect2>
+
+ <sect2>
+ <title>Perform Command</title>
+
+ <para>Once all the validation has been performed, the command can
+ actually be performed. This is done with the
+ <classname>UsingIsisViewerPeer</classname>'s
+ <methodname>#performCommand(ObjectAdapter onObject, String aliasAs,
+ ObjectMember onMember, Perform perform, List<ScenarioCell>
+ args)</methodname> method.</para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="sec.SupportedInteractions">
+ <title>Supported Interactions</title>
+
+ <para>The valid values for the various bindings when interacting with a
+ class members are summarized in the following sections.</para>
+
+ <para>Note:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the <acronym>API</acronym> provided by the common library is
+ not type-safe; the values (as provided in
+ <classname>ScenarioCell</classname>) must match the values given
+ here. While it is tempting to refactor the common library to use
+ type safe enums, this would move the need to translate scenario text
+ into each and every <acronym>BDD</acronym> framework integration.
+ The <acronym>API</acronym> is probably correct as it is, even though
+ it is reliant on the exact string phrases that appear in the tables
+ above.</para>
+ </listitem>
+ </itemizedlist>
+
+ <sect2 id="sec.InteractingWithProperties">
+ <title>Interaction with Properties</title>
+
+ <para>The valid values for the various bindings when interacting with
+ a property are summarized below:</para>
+
+ <table>
+ <title>Supported Interactions for Properties</title>
+
+ <tgroup cols="6">
+ <colspec colname="_4" colnum="4" />
+
+ <colspec colname="_5" />
+
+ <colspec colname="_6" />
+
+ <thead>
+ <row>
+ <entry align="center">on object</entry>
+
+ <entry align="center">alias as</entry>
+
+ <entry align="center">perform</entry>
+
+ <entry align="center">using member</entry>
+
+ <entry align="center">that it</entry>
+
+ <entry align="center">value</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry nameend="_6" namest="_5"><classname>is
+ hidden</classname><emphasis> </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry nameend="_6" namest="_5"><classname>is
+ visible</classname><emphasis> </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry nameend="_6" namest="_5"><classname>is
+ disabled</classname><emphasis> </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry nameend="_6" namest="_5"><classname>is
+ enabled</classname><emphasis> </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry nameend="_6" namest="_5"><classname>is
+ empty</classname><emphasis> </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry nameend="_6" namest="_5"><classname>is not
+ empty</classname><emphasis> </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry><classname>contains</classname></entry>
+
+ <entry><emphasis>value or object alias</emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry><classname>does not contain</classname></entry>
+
+ <entry><emphasis>value or object alias</emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check set property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry><classname>is valid for</classname></entry>
+
+ <entry><emphasis>value or object alias </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check set property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry><classname>is not valid for</classname></entry>
+
+ <entry><emphasis> value or object alias</emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check clear property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry nameend="_6" namest="_5"><classname>is
+ valid</classname><emphasis> </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check clear property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry nameend="_6" namest="_5"><classname>is not
+ valid</classname></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>set property</classname></entry>
+
+ <entry><emphasis>property name</emphasis></entry>
+
+ <entry><classname> </classname></entry>
+
+ <entry><emphasis>value or object alias </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>clear property</classname></entry>
+
+ <entry nameend="_6" namest="_4"><emphasis>property
+ name</emphasis><emphasis> </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis>alias for referenced object
+ </emphasis></entry>
+
+ <entry><classname>get property</classname></entry>
+
+ <entry nameend="_6" namest="_4"><emphasis>property
+ name</emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis>alias for default object </emphasis></entry>
+
+ <entry><classname>get property default</classname></entry>
+
+ <entry nameend="_6" namest="_4"><emphasis>property
+ name</emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis>alias for list of choices</emphasis></entry>
+
+ <entry><classname>get property choices</classname></entry>
+
+ <entry nameend="_6" namest="_4"><emphasis>property
+ name</emphasis><emphasis> </emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>Obtaining a alias for the (value of) a property only makes sense
+ if the property is a reference type, not value type.</para>
+ </sect2>
+
+ <sect2 id="sec.InteractingWithCollections">
+ <title>Interacting with Collections</title>
+
+ <para>The valid values for the various bindings when interacting with
+ a collection are summarized below:</para>
+
+ <table>
+ <title>Supported Interactions for Collections</title>
+
+ <tgroup cols="6">
+ <colspec colname="_4" colnum="4" />
+
+ <colspec colname="_5" />
+
+ <colspec colname="_6" />
+
+ <thead>
+ <row>
+ <entry align="center">on object</entry>
+
+ <entry align="center">alias as</entry>
+
+ <entry align="center">perform</entry>
+
+ <entry align="center">using member</entry>
+
+ <entry align="center">that it</entry>
+
+ <entry align="center">reference</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><emphasis>object alias</emphasis></entry>
+
+ <entry><emphasis> </emphasis></entry>
+
+ <entry><classname>check collection</classname></entry>
+
+ <entry><emphasis>collection name</emphasis></entry>
+
+ <entry nameend="_6" namest="_5"><classname>is
+ hidden</classname><emphasis> </emphasis></entry>
+ </row>
+
+ <row>
+ <entry><emphasis
<TRUNCATED>