Skip to content
Robert Costello edited this page Mar 19, 2024 · 98 revisions

CommCare 2.0 Suite Definition

This document outlines the structure for CommCare 2.0 suite files, which define the core structure of a CommCare application. Suites are responsible for providing the details about what external files (xforms, locale, etc) are included in an application, as well as the structure of an application's menus, what data needs to be chosen before a form is entered, and how to select it.

Abstract Data Type Definitions

Resources

XForms, Locale Files, and the Suite Registration files that are used for externalization all share common traits.

  • External Definition (controlled by suite writers)
  • Need for versioning
  • Are parsed once retrieved, and then stored locally in a quick to use format
  • May rely on other resources

These files will be considered resources in the external framework. Resources are files which are made available in suites, and are retrieved, processed, and persisted in a processed form.

Resource file definitions are contained inside of suites, providing a unique resource identifier along with a set of possible locations for the file in increasing levels of locality (cache, local, remote).

Suites

A suite defines a set of resources and application behavior which is dependent on those resources. At a high level a suite generally resembles something akin to "BRAC Household Visit", containing the XForms for manipulating a household visit case, the menu options availabe in the suite menu

Suites (being resources) are parsed and persisted in a processed form on a device, a uniquely identified suite absolutely defines an abstract datatype rather than a particular file, although a suite should generally be uniquely and fully described by an XML definition.

Suites contain definitions for the following high level data types:

In depth specifications for some elements:

The Session

The basic workflow through a CommCare application is that a user navigates through to an or action which launches an XForm (loaded from a ). 's and 's can specify that certain data is needed before the form can be launched (the ID of Pregnant Mother's case, for instance), and specify what definitions should be used to view that data. The XForm to be entered, along with the data requested comprises a CommCare Session.

CommCare prioritizes the most relevant piece of information to be determined by the user at any given time. For example: If a user selects that they want to enter a menu which contains three entry events which all require a pregnant mother's ID, CommCare will have the user select the pregnant mother and place that information into the Session before requesting that the user select a form.

Implementation Details

All of the datatypes described here will have a couple of concrete implementations. The most concrete implementation consists of the XML definition files which describe a suite. In addition to this implementation, there will be an internal definition for each datatype on the phone's RMS, along with the representation of the various resources (Locale files, etc). Maintaining an atomic definition for a module is one of the primary concerns of the system.

XPath, Instances, and Data Declarations

Many definitions inside of a suite call for the use of XPath to access data. Since there is no "main" instance, in the context of an CommCare application as there would be in an XForm, these XPath expressions are almost always evaluated against the abstract instances listed in the CommCare 2.0 spec, or a relative context defined elsewhere.

XML Definitions

The general definition of the datatypes in XML are as follows:

Text

Text nodes are used in multiple definitions to label text for an element. This is a surprisingly difficult operation, since the following are all use cases that need to be covered

  • Localized Strings
  • Strings pulled from xml data instances
  • Raw Strings

Since all of these elements need to be supported, there is a fairly rich text definition capability which utilizes the XPath query language. The essential definition follows this format

<text>                     <!----------- Exactly one. Will be present wherever text can be defined. Contains a sequential list of string elements to be concatenated to form the text body.-->
    <xpath function="">   <!------------ 0 or More. An xpath function whose result is a string. References a data model if used in a context where one exists. -->
        <variable name=""/> <!------------ 0 or More. Variable for the localized string. Variable elements can support any child elements that <body> can. -->
    </xpath>
    <locale id="">         <!------------ 0 or More. A localized string. id can be referenced here or as a child-->
        <id/>              <!------------ At Most One. The id of the localized string (if not provided as an attribute -->
        <argument key=""/> <!------------ 0 or More. Arguments for the localized string. Key is optional. Arguments can support any child elements that <body> can. -->
    </locale>
</text>

Suite

<suite version="">

<resource/>                    <!----------- 0 or More -->
<media/>                       <!----------- 0 or More -->
<entry/>                       <!----------- 0 or More -->
<detail/>                      <!----------- 0 or More -->
<display/>                     <!----------- 0 or More -->
<menu/>                        <!----------- 0 or More -->
<fixture/>                     <!----------- 0 or More -->

</suite>

Resource

Resource definitions are declarative. This means that upon completely installing a suite, the resource definition will be true. This mechanism allows for suites to define that remote resources should be cached or locally stored.

<resource id="" version="" descriptor=""> <!----------- A resource which needs to be present and managed for this suite to be functional. 
                                                        Version should be a monotonically increasing integer, type should be one of the set of (xform, locale, suite). 
                                                        (Since 2.9) - Descriptor should be a plaintext description of this resource that can be used in error messages and other user facing text.-->
    <location authority="">               <!----------- At Least One. A location where this resource can be retrieved. -->
    </location>
</resource>

Individual resource types use this definition to describe themselves

<xform>
    <resource/>
</xform>

<locale language="">
    <resource/>
</locale>

<suite>
    <resource/>
</suite>

<user-restore>                           <!----------- (Since 2.31) -->
    <resource/>
</user-restore>

Media

NOTE: Still only partially compliant

Media resources are used to describe the location of media files which need to be present in the local context in order to properly function. These files are accessed using javarosa URI's in the format jr://media/. Each media declaration block defines a set of resource files against a relative local root.

<media path="">                          <!----------- path is an optional attribute -->
    <resource id="" version="">          <!----------- 1 or more -->
        <location authority="">          <!----------- At Least One. A location where this resource can be retrieved. -->
        </location>
    </resource>
</media>

The path defines a step on the URI so that the same filename can be used for different media files. For instance

<media path="en">
    <resource id="intro" version="1">
        <location authority="remote">./english/intro.mp3</location>
    </resource>
    <resource id="confirm" version="1">
        <location authority="remote">./english/confirm.mp3</location>
    </resource>
</media>

<media path="ak">
    <resource id="intro" version="1">
        <location authority="remote">./afrikaans/intro.mp3</location>
    </resource>
    <resource id="confirm" version="1">
        <location authority="remote">./afrikaans/confirm.mp3</location>
    </resource>
</media>

These resources would be available at their respective URIs:

  • jr://media/en/intro.mp3
  • jr://media/en/confirm.mp3
  • jr://media/ak/intro.mp3
  • jr://media/ak/confirm.mp3

Entry

<entry>                   
    <form/>                 <!----------- Exactly One. Namespace of the form to be used for data entry -->
    <command id="">         <!----------- Exactly One. ID is for menus. -->
        <text/>             <!----------- NOTE: Deprecated, <display> blocks with no form attribute should be used instead of a <text> block. At Most One. Well formed text as defined above.  One of <text> or <display> must be present. -->
        <display/>          <!----------- At Most One. A Display unit element. One of <text> or <display> must be present -->
    </command>
    <instance id="" src=""/><!----------- 0 or More: instances which will be referenced by the session while selecting data -->
    <session>               <!----------- At Most One. Data which must be collected or determined before a form can be entered -->

        <!-- datum definitions can take one of the following two forms and can be used interchangably -->

        <datum              <!----------- 0 or More. A specific item to collect --> 
        id=""               <!----------- Required: The id if this item, will be the element name in the session instance. Should be unique per entity type. --> 
        nodeset=""          <!----------- Required: An XPath expression which defines a set of nodes which are the basis of values to be selected. -->
        value=""            <!----------- Required: Once an element from the nodeset is chosen, this value is a relative path to the indexed nodeset which defines the value to be placed into the session datum -->
        detail-select=""    <!----------- Required: the ID of a <detail> which will structure the screen for selecting the items from the nodeset -->
        detail-confirm=""   <!----------- Optional: the ID of a <detail> which will structure the screen for displaying a selected item for confirmation. If not present, no detail screen will be shown and the item selection will occur immediately -->
        detail-persistent=""    <!----------- Optional: the ID of a <detail> which defines a small display of the selected entity on screen persistently after it is selected -->
        detail-inline=""   <!----------- Optional: the ID of a "confirm" styled <detail> which can be invoked from a persistent detail to provide more context about the selected entity -->

        autoselect="" />    <!----------- Optional: If set to true, this datum will have the property that, when the session is waiting for a selection from this datum's nodeset, and there is exactly 1 available case in the nodeset, that 1 case will be auto-selected and the user will not see the entity select screen -->

        <instance-datum     <!----------- 0 or More. Set of items to collect from the given nodeset using a single multi-select screen -->
        id=""               <!----------- Required: The id if this item, will be the element name in the session instance. Should be unique per entity type. --> 
        nodeset=""          <!----------- Required: An XPath expression which defines a set of nodes which are the basis of values to be selected. -->
        value=""            <!----------- Required: Once elements from the nodeset is chosen, this value is a relative path to the indexed nodeset which defines the values to be placed into the session datum -->
        detail-select=""    <!----------- Required: the ID of a <detail> which will structure the screen for selecting the items from the nodeset -->
        detail-confirm=""   <!----------- Optional: the ID of a <detail> which will structure the screen for displaying a selected item for confirmation. If not present, no detail screen will be shown and the item selection will occur immediately -->
        detail-persistent=""    <!----------- Optional: the ID of a <detail> which defines a small display of the selected entity on screen persistently after it is selected -->
        detail-inline=""   <!----------- Optional: the ID of a "confirm" styled <detail> which can be invoked from a persistent detail to provide more context about the selected entity -->
        autoselect="" />    <!----------- Optional: If set to true, this datum will have the property that, when the session is waiting for a selection from this datum's nodeset, and there is exactly 1 available case in the nodeset, that 1 case will be auto-selected and the user will not see the entity select screen -->

        <datum              <!----------- 0 or More. A specific item to collect --> 
        id=""               <!----------- Required: The id if this item, will be the element name in the session instance. Should be unique per entity type. --> 
        function=""/>       <!----------- Required: An XPath expression which will be evaluated to produce the value of this datum.-->  
        <query/>            <!----------- 0 or More. A query for additional instance data for the session. See specification below --> 
    </session>
    <stack/>                <!----------- (Since 2.9) Arbitrarily Many: Session stack operations to be performed upon completion of this form (see stack specification). Stack operations are run against the current stack _before_ it is released, and the next frame (if any) is executed. -->
    <assertions>            <!----------- (Since 2.9) 0 or 1. A list of assertions to be tested before form entry begins -->
        <assert test="">    <!----------- (Since 2.9) 0 or More. A test to be run and confirmed true before the form can be entered. (For instance, testing that an external instance is defined). Form entry will not begin until all assertions pass.
                                           @test - An xpath expression containing a result that evaluates to a boolean. The test will fail if EITHER the expression returns false, OR if there is any sort of error while running the test. -->
            <text/>         <!----------- A message to be displayed to the user in the event that the assertion fails. -->
        </assert>
    </assertions>
</entry>

Display

A Display element is essentially a holder for both a text element and a media component that is used in entry's and menu blocks

<display>
    <text form="" />                        <!-- One for each value of 'form' - The text to be displayed for this element. @form should either be not present or one of "image", "audio", or "badge". "badge" indicates that the text is intended to be displayed within a module badge; a text element of this form should not evaluate to more than 2 characters, or else it will get cut off in order to fit. -->
</display>
Deprecated Display
<display>
    <text/>                                 <!-- Exactly One - The text to be displayed for this element -->
    <media image="" audio=""/>              <!-- At Most One - The jr:// URI's for media to display along with this item. Images and Audio are supported.-->
</display>

Detail

Technical Note: Detail screens are called to display elements of a nodeset. Inside of a detail, all xpath expressions are evaluated in the context of the element which referenced it.

<detail 
   id="" 
   nodeset="" 
   force-landscape=""
   fit-across="" 
   uniform-units=""/>                                                  <!----------- @nodeset is an optional xpath expression. If provided, it will be applied to the entry element, and then all fields in this detail will be evaluated in that context, rather than in the context of the entry element alone. @force-landscape is an option boolean. If set to true, the device screen will be forced to display in landscape mode when the entity list screen for this detail is loaded. @fit-across is an optional numeric value, which if specified will display that number of details in a single row (the default is 1). @uniform-units is an optional boolean field that only applies if this detail is being shown using <grid> specifications (see below). If so, setting uniform-units to true will indicate that the height of a single cell in the grid layout should be treated as equal to its width, rather than being computed independently. -->
    <title form="">                                                    <!----------- Exactly One. Form is optional and is only relevant if this detail has child details. In that case, form may be "image" or omitted. -->
        <text/>                                                        <!----------- Alternatively, may be a display block, as defined by entry element, to include audio and/or an image. -->
    </title> 
    <no_items_text><text/></no_items_text>                             <!----------- At Most One. Only relevant for short detail. Used when case list contains no items. -->
    <variables>                                                        <!----------- At Most One. Selects values from each item being iterated through to work around context shifts and prevent duplicating logic. Computed in order (so variables can exist based on the variables before them in the block) -->
        <* function=""/>                                               <!----------- 1 or More. Element name will be the name of the variable. function is required and provides an xpath calculation whose output is the value of the variable -->
    </variables>
    <focus function=""/>                                               <!----------- At Most One. Provides an xpath function that defines the element that should be focused upon when this detail is being used to display a nodeset list. -->
    <action/>                                                          <!----------- At Most One. (see spec below) An action defines a full stack operation that can be completed from inside of the detail screen. This can be used to perform tasks like registration in the same workflow as select. -->
    <field sort="" relevant="">                                        <!----------- 1 or More. sort is one of (default) and specifies the default sort order and is obsolete, the sort element should be used instead. relevant (introduced in 2.14) is an optional xpath calculation. If provided, this field will be ignored whenever it evaluates to false.-->
        <style font-size="" horz-align="" vert-align="" css-id="" show-border='false'>     <!----------- Optional. Style attributes are only  applied if a <grid> element is present.-->
            <grid grid-x="" grid-y="" grid-width="" grid-height=""/>   <!----------- Optional. If a grid element is specified in any field, all other fields in the detail are expected to contain a <grid> element as well. If a detail uses <grid> specifications, it is laid out in a special way; the space which the detail takes up is treated as a grid that is 12 units across and a custom number of units down (determined by the largest value of @grid-y of any field in the detail), with (0,0) being the top left corner. Each field is then placed such that its top left corner is at coordinate (@grid-x,@grid-y), taking up @grid-width units across and @grid-height units down from that point. -->
        </style>
        <header form="" width=""><text/></header>                      <!----------- Exactly One. The header to be used to describe the field. Form is an optional hint which provides a hint for whether rich media should be displayed based on <text> returning a URI. Width is an optional hint for how much of the screen should be consumed by this field in percent or in pixels: "50%", "115", etc.-->
        <template form=""  width=""><text/></template>                 <!----------- Same as above -->
        <sort order="" direction="" type="" blanks=""><text/></sort>   <!----------- (Since 2.2) - Specify the sort parameters for the field. The text will be used to sort relative to other entries (useful for integers/dates whose pretty-print does not sort alphanumerically), if it is not present, the template form is used. 
                                                                           @order is an optional integer which specifies the priority of the sort. "1" will be used to sort by default. The behavior of "sort" values smaller than 1 is unspecified.
                                                                           @direction is one of (ascending, descending) for the default sorting. direction is optional. ascending will be assumed by default
                                                                           @type is optional and is one of (int, string, double) and will perform the appropriate comparison for that datatype. Note that care should be taken to ensure that the sort text returns a value which can be cast to this datatype.
                                                                           @blanks (Since 2.35) is optional and is one of (first, last). This specifies where nodes for which the sort property is empty should appear in the list -->
        <endpoint_action endpoint_id="" background="true"/>            <!----------- (Since 2.54) optional action to trigger that links to a session endpoint defined in the suite file using "@endpoint_id". @background specify whether the action needs to be in background without taking user away from the current screen -->
        <alt_text><text/></alt_text>                                   <!----------- (Since 2.54) Optional element to specify accessible alt text for case list icons and clickable icons, relevant when template form is "enum-image" or "clickable-icon". -->
    </field>
    <select_text><text/></select_text>                                 <!----------- (Since 2.54) Optional element to customize the text displayed in the button for selecting cases in a multi-select case list (by default the button displays "Continue"). -->
</detail>

Form: The form for a header or template may be image or audio. Templates may also have the form graph, which then requires specifying a graph configuration, or markdown.

Nested details: Details may contain either a list of fields or a list of child details (not both fields and child details). The example above shows a detail containing a list of fields. The example below shows a detail containing child details. Child details each follow the same format as above, except that they do not require an id and they may not contain child details themselves, only fields.

<detail id="">
    <title><text/></title>
    <detail>
        <title><text/></title>
        <field>
            <header form="" width=""><text/></header>
            <template form=""  width=""><text/></template>
        </field>
    </detail>
    <detail>
        <title><text/></title>
        <field>
            <header form="" width=""><text/></header>
            <template form=""  width=""><text/></template>
        </field>
    </detail>
</detail>

Detail - Grid View

CommCareODK Only: An alternate Detail format is available in Case Lists that describes how to display an entity in a grid rather than in the standard row format. This spec shares much with the Detail spec described above. If any of the blocks are present in the block, CommCareODK will attempt to render the detail as a grid.

<detail>      						<!-- As above -->
    <field>
      <style 						
	   horz-align='' 			<!-- @horz-align: one of left, center, or right determining where content is placed horizontally in its grid -->
	   vert-align='' 			<!-- @vert-align: one of top, center, bottom determining where content is placed vertically in its grid -->
	   font-size='' 			<!-- @font-size: one of small, medium, large, xlarge determining the size of the text -->
	   show-border='true'>			<!-- @show-border: whether to show a border around the field or not. Also affects the padding and margin of all the fields in the tile. -->
      	<grid 						<!-- Describes the grid blocks this entity should take up. There are 6 rows and 12 columns by default.	-->
		grid-height="2" 		<!-- @grid-height: how many rows vertically this grid entry should take up -->
		grid-width="4" 			<!-- @grid-width: how many columns horizontally this grid entry should take up -->
		grid-x="0" 				<!-- @grid-x: as described above, the zero indexed starting X location of the grid entry -->
		grid-y="0"/> 			<!-- @grid-y: as described above, the zero indexed starting Y location of the grid entry -->
       </style>
      <header>              		<!-- As above -->
        <text>
          <locale id="m1.case_short.case_name_1.header"/>
        </text>
      </header>
      <template>  					<!-- As above -->
        <text>
          <xpath function="case_name"/>
        </text>
      </template>
      <group function="string(index/parent)" header-rows="2" /> <!-- 1. Only relevant for short detail. Defines how the entity will be grouped.
                                                                  @header-rows: Integer indicating how many rows of the grid to use as the group header. Min 1. -->
    </field>
</detail>

Detail - Adding Lookup to Case List

Support optional: Within the case list it is possible to make external call-outs and filtering the case list based on the results passed back. Support for attaching result data to cases in the list was added in CommCare 2.28.

<detail>
    <lookup                                              <!-- At Most One. Describes external lookup procedure. --> 
        type=""                                          <!-- Describes the MIME type (on Android platform) --> 
        action=""                                        <!-- Action to perform on lookup invocation --> 
        image=""                                         <!-- Reference to image used in displaying lookup --> 
        name="">                                         <!-- Text used in displaying lookup --> 

        <extra value="" key=""/>                         <!-- O or more. Key/value string pairs to be included in lookup --> 
        <response key=""/>                               <!-- O or more. Key that specifies value present in lookup result --> 

        <field>                                          <!-- At Most One. Used to describe how returned lookup data displayed and associated with entries --> 
            <header width=""><text/></header>            <!-- Exactly One. The header text associated with the lookup data. Width is an optional hint for how much of the screen should be consumed by this field in percent or in pixels: "50%", "115", etc.--> 
            <template>                                   <!-- Exactly One. -->
                <text><xpath function=""/><text/>        <!-- The function is the expression evaluated on each entry to get the key for mapping lookup results to entries-->
            </template>
        </field>
    </lookup>
</detail>

Menu

<menu id="" root="" relevant="" style="">  <!----------- id is a unique ID for this menu. if set to "root", the menu will attempt to be present at the root level. Relevant is an xpath expression which evaluates whether the menu item should be displayed. It should be based on the session. 
                                                         @style:since 2.24 - An optional cue for how this menu thinks it should be displayed, currently implemented options are 'list' and 'grid'. If multiple menus match an ID, the app should only respect the style if it is identical to each menu-->
    <text/>                                <!----------- 1. A well structured text for this menu. -->
    <command id="" relevant=""/>           <!----------- 0 or more. A list of commands which should be displayed on this menu. The commands will be presented in the order that they are defined here. Relevant is an xpath expression which evaluates whether the menu item should be displayed. It should be based on the session. -->
</menu>

Stack

Session Stack operations are optional for CommCare implementations.

Stack operations were introduced in CommCare 2.9.

For an outline of using Stack operations, see the documentation page.

<stack>                              <!----------- stack is a wrapper for executing a potential set of stack operations -->
    <create id="" if="">             <!----------- 0 or More : Creates and pushes a frame onto the stack. This operation will only be run if the if condition (if one is present) evaluates to true, and if no frame exists with the provided id. The elements will be added to the frame in order (if relevant). -->
         <datum id="" value=""/>     <!----------- 0 or More : Adds a datum with to the session frame. 
                                                                    @id - required - The id of the datum
                                                                    @value - optional - Required if the element does not have a single non-empty text value -->
         <query id="" value="">      <!----------- 0 or More : Adds a query datum to the session frame.
                                                                    @id - required - The id of the Virtual Session Instance where the result of the request can be queried.
                                                                    @value - required - The URL endpoint for the GET query request -->

             <data key="" ref=""/>   <!----------- 0 or More : key value pair for a parameters which will always be included in the search regardless of user input
                                                                    @key - required - String literal key value
                                                                    @ref - required - XPath expression which will be evaluated to calculate the value -->
         </query>
         <command value=""/>         <!----------- 0 or More : Adds a command with to the session frame. 
                                                                    @value - At most one. Required if the element does not have a single non-empty text value -->
         <mark/>                     <!----------- 0 or More : marks a point to rewind to. When it is added to a stack frame the current needed datum for that frame is computed and stored with it -->
         <rewind value=""/>          <!----------- 0 or More : when encountered all steps in between it and the nearest 'mark' above it will be cleared and the needed datum at the mark will be set to the value -->
         <jump id="">                <!----------- 0 or 1 : when encountered the user should be redirected to a specific URL -->
             <url>
                 <text/>
             </url>
         </jump>
    </create>

    <push if=""/>                    <!----------- 0 or More :(Since 2.13) Adds values onto the current session frame. Supports the same children as create. -->

    <clear frame="" if=""/>          <!----------- 0 or More. Removes a frame from the stack if it exists.
                                                 @frame - The ID of the frame to be removed. -->
</stack>

mark/rewind added as of CommCare 2.31. More examples of mark and rewind found here.

query/jump added as of CommCare 2.53. More details on jump found here.

Action

Since CommCare 2.13

Action definitions provide a mechanism for manipulating the user's workflow and stack directly based on user input.

<action relevant="" >  <!-- relevant (introduced in 2.30) is an optional xpath expression which evaluates whether the action should be displayed. -->
    <display/>  <!-- Standard display block as defined in entry elements -->
    <stack/>    <!-- Stack manipulations that should be fired upon the user choosing the action -->
</action>

Fixtures

Fixtures which are not user specific can be included straight in the suite file. The format for the fixture declaration can be found in the fixture documentation.

Remote-Request

Since CommCare 2.29

A remote-request node defines a session template in the same format as an node. Rather than defining a session path with ends in form entry, however, it defines a user path which ends in a POST request to a server with data collected during the session. This is used for synchronous search and case claiming.

Suite File Specification

e.g.

<remote-request>
    <post url="" relevant="">     <!----------- (Exactly 1) - Defines the post request that will execute when the path is completed
                                                              @url - Exactly 1 - The POST endpoint to be used
                                                              @relevant - At Most 1 - an xpath expression that is evaluated before performing the post request. If it evaluates to false, the request is not made. -->
        <data                     <!----------- (0 or more) - key value pairs to be included as POST data -->
              key=""              <!----------- Exactly 1 - String literal key value  -->
              ref=""              <!----------- Exactly 1 - XPath expression which will be evaluated to calculate the value -->
              nodeset=""          <!----------- (optional) - An XPath expression which defines a set of nodes which are the basis of values to be selected by @ref -->
              exclude=""/>        <!----------- (optional) - Any XPath expression used to determine if the value or current node should be included -->                      
    </post>
    <instance/>                   <!----------- As per the <entry> specification -->
    <command id="...">            <!----------- As per the <entry> specification -->
        <display/>
    </command>
    <session/>                    <!----------- As per the <entry> specification, note the <query> datum definition below which is common in remote-requests -->
    <stack/>                      <!----------- As per the <entry> specification -->
</remote-request>

Query Datum

Since CommCare 2.29

Inside of a session's step declarations, an app can define a query step to perform a synchronous get request to a remote server, and inject the response payload into a virtual instance which will persist for the remainder of the session.

When executing a CommCare Session, a query step should present a set of prompts to the user to enter search parameters and provide a trigger to then execute a query request with the included data and place the response payload into a virtual instance before proceeding to the next step.

Query steps are most commonly used in sessions, but can be included in any session template.

Currently this is used to support searching for remote cases to claim with a remote request.

<query 
    url=""                   <!----------- required - The URL endpoint for the GET query request -->
    storage-instance=""      <!----------- required - The id of the Virtual Session Instance where the result of the request can be queried -->
    template=""              <!----------- optional - The ID of an instance template to use for the results to optimize performance. Only 'case' is currently supported -->
    default_search="">       <!----------- optional - One of ('true', 'false'). If true, when the session navigates to the query step, it should be performed immediately (using the <data> values) without requiring user input. -->
    
    <title>                  <!----------- optional - Title for the search screen. -->
        <text/>
    </title>
    
    <description>            <!----------- optional - Description/sub-heading for the search screen. -->
        <text/>
    </description>
    
    <data                    <!--------- (0 or more) - key value pairs to be included as POST data -->
        key=""               <!--------- Exactly 1 - String literal key value  -->
        ref=""               <!--------- Exactly 1 - XPath expression which will be evaluated to calculate the value -->
        nodeset=""           <!--------- (optional) - An XPath expression which defines a set of nodes which are the basis of values to be selected by @ref -->
        exclude=""/>         <!--------- (optional) - Any XPath expression used to determine if the value or current node should be included -->
    
    <group                   <!----------- (0 or more) - Defines group for prompt elements-->
        key="">              <!----------- required - String literal key value that a prompt's group_key matches to-->
            <display/>       <!----------- (Exactly 1) - Label for the group. Standard display block as defined in entry elements -->
    </group>

    <prompt                  <!----------- (0 or more) - key value pairs for parameters for the search whose value should be provided by user input -->
        key=""               <!----------- required - String literal key value -->
        input=""             <!----------- optional - A cue for the UI to provide the user with a widget to facilitate input. If not provided, the user should enter a value as a raw string.
                                                   Supported inputs:
                                                   select (Since CommCare 2.51) -  Provides a multi-select checkbox widget with choices defined by the nested 'itemset' node. Adds the selected choice values to the query request parameters. 
                                                   select1 - Provides a single-select dropdown widget with choices defined by the nested 'itemset' node. Adds the selected choice value to the query request parameters.
                                                   daterange - Allows user to select a range of date for the field. Adds the selected range in format '__range__startDate__endDate' to the query request parameters.
                                                   address - A geocoder widget that allows user to select an address to query with. -->
        appearance="".               <!----------- optional - Additional cue for the UI to provide the user with a widget to facilitate input. The only supported value for this at the moment is "barcode_scan" which adds a barcode scan UI element to input the prompt value from.
        default=""                   <!----------- optional - An XPath expression which should be executed before prompts are displayed to the user to pre-populate a value for the prompt -->
        receive=""                   <!----------- optional - Used in combination with a geocoder widget to retain a specific value like state or city from the geocoder result -->
        hidden=""                    <!----------- optional - Boolean value to hide a prompt from UI -->
        allow_blank_value=""         <!----------- optional - Boolean value that specify whether to accept empty input in the prompt -->
        exclude=""                   <!----------- optional - An XPath condition to exclude the prompt's value from search url -->
        group_key="">                <!----------- optional - String value that matches to the key of a group element and to determine grouping of prompts-->                       
            
            <display/>               <!---- (Exactly 1) - Label for the prompt. Standard display block as defined in entry elements -->
            <itemset/>               <!---- (At Most 1) - If the prompt is a select or select1 input, defines the choices to be used. Follows the XForm itemset definition -->
            <validation test="">     <!---- (At Most 1) - Specifies a validation condition that engine should run on user's input
                                                          @test - Xpath condition to validate -->
                <text/>              <!-- a custom error message to show in case of validation failing on input  -->
            </validation>
            
            <required test="">       <!---- (At Most 1) - Specifies an XPath condition to specify whether the input for the prompt is required to be able to search.
                                                          User should not be able to able to execute case search without specifying a value for required prompts
                                                          @test - Xpath condition to evaluate whether the prompt is required  -->
                <text/>              <!-- a custom error message to show in case a required input is not supplied by the user  -->
            </required>
    </prompt>
</query>

Note - Different platforms may have different support for input widgets. If an input widget isn't supported, the user will be presented with a raw input text field.

You can read more about configuring different remote-request workflows over here.

CommCare converts the user input for the query prompts defined by the 'remote-request' into a search-input instance at runtime that can be used to reference any of the user entered values for these prompts.

Endpoints

An endpoint defines a session state definition for a particular screen in the CommCare app. It's generally used to skip to a particular screen in the CommCare app without needing to know anything about the internal session state associated by the endpoint. Endpoint support was added in CommCare 2.51.

<endpoint id="">                     <!----------- id is a unique ID for this endpoint -->
    <argument id=""               <!----------- 0 or more. Defines the values an endpoint expects as inputs which can be further referenced in the stack block below with a $id syntax -->
              instance-id=""         <!-----------  Optional, set to process the endpoint argument into a virtual instance with this instance-id
              instance-src=""/>      <!-----------  Optional, set to process the endpoint argument into a virtual instance with this instance reference
    <stack/>                         <!----------- Stack manipulations that should be fired upon the endpoint launch --> 
</endpoint>

Life Cycle

Since CommCare applications will depend on many suites, managing resources and suite definitions is vital. This section defines how CommCare will install, manage, and use Suites.

Information about this process is contained In the Usage Guide

Examples

This section contains sample definitions for CommCare applications in this framework.

Household Visit

This is a sample pregnancy application with referrals, and cross references to different case types. Interesting or complex aspects of the suite are commented.

<suite version="1">

    <!-- Parse and cache the XForm -->
    <xform>
        <resource id="demo_pregnancy_registration" version="1">
           <location authority="local">./safe_mothers_registration.xml</location>
        </resource>
    </xform>

    <!-- Parse and cache the XForm -->
    <xform>
        <resource id="demo_pregnancy_followup" version="1">
           <location authority="local">./safe_mothers_followup.xml</location>
        </resource>
    </xform>

    <!-- Parse and cache the XForm -->
    <xform>
        <resource id="demo_pregnancy_referral" version="1">
     	   <location authority="local">./safe_mothers_referral.xml</location>
        </resource>
    </xform>
    
     <!-- Parse and cache the XForm -->
    <xform>
        <resource id="demo_pregnancy_close" version="1">
     	   <location authority="local">./safe_mothers_close.xml</location>
        </resource>
    </xform>
    
    <!-- Read and locally store the translation strings-->
    <locale language="default">
        <resource id="demo_cc_strings_default" version="1">
           <location authority="local">./demo_cc_en.txt</location>
           <location authority="remote">./demo_cc_en.txt</location>
        </resource>
    </locale>
    
    <!-- Read and locally store the translation strings-->
    <locale language="es">
        <resource id="demo_es_cc1" version="1">
           <location authority="local">./demo_cc_es.txt</location>
           <location authority="remote">./demo_cc_es.txt</location>
        </resource>
    </locale>
    
    <!-- Read and locally store the translation strings-->
    <locale language="es">
        <resource id="demo_strings_cc" version="1">
           <location authority="local">./messages_cc_default_es.txt</location>
           <location authority="remote">./messages_cc_default_es.txt</location>
        </resource>
    </locale>
    
    <!-- Define the short detail model for household cases -->
    <detail id="pregnancy_short">
        <title><text><locale id="entity.pregnancy"/></text></title>
        <field>
            <header width="60"><text><locale id="header.name"/></text></header>
            <template width="60"><text><xpath function="name"/></text></template>
        </field>
        <field>
            <header><text><locale id="header.id"/></text></header>
            <template><text><xpath function="@external-id"/></text></template>
        </field>
        <field>
            <header><text><locale id="header.age"/></text></header>
            <template><text><xpath function="age"/></text></template>
        </field>
    </detail>

    <!-- Define the long detail model for household cases -->
    <detail id="pregnancy_long">
        <title><text><locale id="entity.pregnancy"/></text></title>            
        <variables>
                <!---- Store the ID in a variable since we need to reference a separate case based on it -->
        	<caseid function="@case_id"/>
        </variables>
        <field>
            <header><text><locale id="header.name"/></text></header>
            <template><text><xpath function="name"/></text></template>
        </field>
        <field>
            <header><text><locale id="header.id"/></text></header>
            <template><text><xpath function="@external-id"/></text></template>
        </field>
        <field>
            <header><text><locale id="header.age"/></text></header>
            <template><text><xpath function="age"/></text></template>
        </field>
        <field>
            <header><text><locale id="header.opened"/></text></header>
            <template><text><xpath function="format_date(date(date-opened),'short')"/></text></template>
        </field>
        <field>
            <header><text><locale id="pregnancy.hirisk"/></text></header>
            <template><text><xpath function="if(prp_hrk=1,'Yes','No')"/></text></template>
        </field>
        <field>
            <header><text><locale id="pregnancy.openrefs"/></text></header>
            <!---- Count how many open referral cases there are which are associated with this case ---->
            <template><text><xpath function="count(instance('casedb')/casedb/case[@case_type='cc_demo_pregnancy_referral'][pregnancy_id=$caseid][@status='open'])"/></text></template>
        </field>
    </detail>
    
    <!-- Define the short detail model for household referrals -->
    <detail id="preg_ref_short">
        <title><text><locale id="referral"/></text></title>
        <variables>
                <!---- Store the ID in a variable since we need to reference a separate case based on it -->
        	<pregnancyid function="pregnancy_id"/>
        </variables>
        <field>
            <header width="60"><text><locale id="referral.header.name"/></text></header>
            <!---- Load the name of the pregnancy associated with this case ---->
            <template width="60"><text><xpath function="instance('casedb')/casedb/case[@case_id=$pregnancyid]/name"/></text></template>
        </field>
        <field>
            <header width="40"><text><locale id="header.dd"/></text></header>
            <template width="40"><text><xpath function="if(date(followup_date) - today() &lt;= 0,$today,
                                             if(date(followup_date) - today() &lt;= 1,$yesterday,
                                             format_date(date(followup_date),'short')))">
                                 <variable name="today">
	                             <locale id="pregnancy.suite.select.today"/>
	            	         </variable>
                                 <variable name="yesterday">
	                             <locale id="pregnancy.suite.select.yesterday"/>
	            	         </variable>
</xpath>
                                             </text></template>
        </field>
    </detail>

    <!-- Define the long detail model for household cases -->
    <detail id="preg_ref_long">    
    	<title><text><locale id="referral"/></text></title>
    	<variables>
                <!---- Store the ID in a variable since we need to reference a separate case based on it -->
        	<pregnancyid function="pregnancy_id"/>
        </variables>        
        <field>
            <header><text><locale id="header.name"/></text></header>
            <!---- Load the name of the pregnancy associated with this case ---->
            <template><text><xpath function="instance('casedb')/casedb/case[@case_id=$pregnancyid]/case_name"/></text></template>
        </field>
        <field>
            <header><text><locale id="referral.header.date_created"/></text></header>
            <template><text><xpath function="if(date(date-opened) - today() &lt;= 0,$today,
                                             if(date(date-opened) - today() &lt;= 1,$yesterday,
                                             format_date(date(date-opened),'short')))">
                                 <variable name="today">
	                             <locale id="pregnancy.suite.select.today"/>
	            	         </variable>
                                 <variable name="yesterday">
	                             <locale id="pregnancy.suite.select.yesterday"/>
	            	         </variable>
            </xpath></text></template>
        </field>
        <field>
            <header><text><locale id="header.dd"/></text></header>
            <template><text><xpath function="if(date(followup_date) - today() &lt;= 0,$today,
                                             if(date(followup_date) - today() &lt;= 1,$yesterday,
                                             format_date(date(followup_date),'short')))">
                                 <variable name="today">
	                             <locale id="pregnancy.suite.select.today"/>
	            	         </variable>
                                 <variable name="yesterday">
	                             <locale id="pregnancy.suite.select.yesterday"/>
	            	         </variable>
            </xpath></text></template>
        </field>
    </detail>

    <!-- Define entry actions for Household Visit Cases -->
    <entry>                   
        <form>http://dev.commcarehq.org/pregnancy-demo/registration</form>
        <command id="client-reg">
            <text><locale id="pregnancy.reg_new"/></text>
        </command>
    </entry>

    <entry>                   
        <form>http://dev.commcarehq.org/pregnancy-demo/followup</form>
        <command id="client-followup">
            <text><locale id="pregnancy.followup"/></text>
        </command>
         <session>
                <!---- Get the Case ID of a pregnancy case -->
        	<datum id="case_id" nodeset="instance('casedb')/casedb/case[@case_type='cc_demo_pregnancy']" value="./@case_id" detail-select="pregnancy_short" detail-confirm="pregnancy_long"/>
        </session>
    </entry>

    <entry>                   
        <form>http://dev.commcarehq.org/pregnancy-demo/referral</form>
        <command id="client-referral">
            <text><locale id="pregnancy.referral"/></text>
        </command>
        <session>
            <!---- First, list and select a pregnancy -->
            <datum id="pregnancy-case" nodeset="instance('casedb')/casedb/case[@case_type='cc_demo_pregnancy']" value="./@case_id" detail-select="pregnancy_short"/>
            <!---- Now, list all referrals which are bound to this pregnancy -->
            <datum id="case_id" nodeset="instance('casedb')/casedb/case[@case_type='cc_demo_pregnancy_referral'][pregnancy_id=instance('session')/session/data/pregnancy-case]" value="./@case_id" detail-select="preg_ref_short" detail-confirm="preg_ref_long"/>
        </session>
    </entry>
    
    <entry>
    	<form>http://dev.commcarehq.org/pregnancy-demo/close</form>
    	<command id="client-close">
            <text><locale id="pregnancy.close"/></text>
        </command>
        <session>
                <!---- Get the Case ID of a pregnancy case -->
        	<datum id="case_id" nodeset="instance('casedb')/casedb/case[@case_type='cc_demo_pregnancy']" value="./@case_id" detail-select="pregnancy_short" detail-confirm="pregnancy_long"/>                            
        </session>
    </entry>
    
    <menu id="client-visit">
    	<text><locale id="preg.menu"/></text>
    	<command id="client-reg"/>
    	<command id="client-followup"/>
    	<command id="client-referral"/>
    	<command id="client-close"/>
    </menu>
</suite>