Chapter 5. REST API

Table of Contents

5.1. GET Export Report

5.1.1. Overview

Exports the Pull Report identified by the [catalog id] and [report id] path elements to the export format identified by the format parameter. See the parameters documentation to learn to how to filter, sort, and join in additional data.

URL

/[context]/pullreports/catalog/[catalog id]/report/[report id]/export

URL Components
/[context]

The web application context path of the WAR which contains the Pull Reports™ JAR. Typically this is the name of the WAR file.

/pullreports

The URL path to the PullReportsServlet. This path is configured automatically web.xml when installing Pull Reports™.

/catalog/[catalog id]

The id of the <catalog> as configured in Pull Reports™ XML Catalog files.

/report/[report id]

The id of the <report> as configured in the encompassing <catalog>.

/export

The export end point.

Errors

The export report service returns a 400 response status code if it detects an error in parameter input such as an incorrectly formatted filter or columns parameter. Similarly, the service returns a 500 response status code if it experiences a server error such as a communication problem with the underlying database.

The structure of the response body for non-200 Response Status Codes varies by format. See the detailed format documentation below for more information

Error Logging

In addition to returning error messages within the HTTP response, Pull Reportslogs all errors.

5.1.2. Parameters

5.1.2.1. columns

Semicolon (;) separated list of table or column resource paths to join, in order, into the report results. Pull Reports™ will construct all necessary SQL joins to the referenced database tables based on the <report>'s <relationship> configuration.

The columns parameter follows these rules:

Default behavior

If the parameter is not specified, then the export result contains the <column>s as ordered within the <export_config> defaultColumns attribute if it is specified or all exportable <column>s from the report's base table if defaultColumns is not specified.

Base table columns added if missing base table path

If the columns parameter is specified but the base table path is not included within the semicolon separated list, then the <column>s as ordered within the <export_config> defaultColumns attribute if it is specified or all exportable <column>s from the report's base table if defaultColumns is not specified are included as the first columns within the export result.

For example, given a base table path of /base, a child, relationship table path of /base/child, and a defaultColumns value of id,name, these columns parameter values are equivalent:

/base@id,name;/base/child
/base/child

All exportable columns included by default

If a table resource path within the semicolon separated list is specified without additional column ids, all <column>s from the table not attributed as export='false' are included within the result.

For example, given a table path of /person with child <column>s with ids of id, name, and age, these columns parameter values are equivalent:

/person
/person@id,name,age

Including and ordering individual columns within a table

To specify the exact columns to be exported from a <table>, specify a comma separated list of column id's after the table resource path preceeded by an @ sign. The order of column ids within the list will be respected within the export result.

For example, this columns value returns the id and name columns from /base and the type column from /base/child:

/base@id,name;/base/child@type

<column>s set to export='false' may not be included

When specifying exact columns via the @ sign, no id's of <column>s attributed as export='false' may be included.

For example, if the /base table's is_active column was attributed with export='false', the following columns parameter would return a 400 error because the is_active column is not exportable:

/base@id,name,is_active #Bad!

Example 5.1. columns parameter usage

The following example exports, in order, the name <column> from the base <table>, the birth_date <column> from the parent relationship <table>, and the id, address_street, and address_state <column>s from the base <table>:

/pullreports/catalog/my-catalog/report/my-report/export?columns=@name;/parent@birth_date;@id,address_street,address_state


5.1.2.2. distinct

If true, removes duplicative records from the export results. If not specified, the default is false.

Example 5.2. distinct parameter usage

The following example ensures that the export results are distinct:

/pullreports/catalog/my-catalog/report/my-report/export?distinct=true


5.1.2.3. filter

Filter(s) to restrict the exported results. This parameter may be specified zero to many times. Each filter is independently AND'ed to the Pull Reports™ SQL query. A single filter parameter may have multiple filter terms separated by the or keyword.

See the filters section below to learn how to construct filters.

Note

Filters applied via the filter HTTP parameter are applied in addition to filters set as <pre_filter>s within the Pull Reports™ XML Catalog file.

Example 5.3. distinct parameter usage

The following example filters the export results to those records whose base <table>'s active <column> is of value true and whose employer relationship <table>'s employer <column>'s value is greater than 2000 or whose relationship employer/countries <table>'s name <column>'s value is US or Mexico.

/pullreports/catalog/my-catalog/report/my-report/export?filter=@active+%3D+true&filter=/employer@employees+%3E+2000+or+/employer/countries@name+in+('US','Mexico')


5.1.2.4. format

The format of the exported results. Valid values are xml ,json ,html ,htmltable ,kml ,geojson ,map ,or csv. If not specified, the default is json.

Example 5.4. format parameter usage

The following example exports the results in the map format:

/pullreports/catalog/my-catalog/report/my-report/export?format=map


5.1.2.5. limit

Optional non-negative integer indicating the maximum number of records returned. If not specified, the maximum number of results defaults to the export.report.maxResults installation parameter.

Example 5.5. limit parameter usage

The following example limits the export results to 5 records:

/pullreports/catalog/my-catalog/report/my-report/export?limit=5


5.1.2.6. offset

Optional non-negative integer indicating the offset of the exported results.

Note

Some database vendors do not support offset without limit. In this case, a 500 HTTP response status is returned.

Example 5.6. offset parameter usage

The following example excludes the first 50 records from the export result:

/pullreports/catalog/my-catalog/report/my-report/export?offset=50


5.1.2.7. sort

Semicolon (;) separated list of column resource paths which specify, in order, the desired sort of the exported data. The specified columns must be either associated with the report base table or a table resource path included in the columns parameter.

The default order is ascending. Appending desc to a column resource path will set the order to be descending. Appending asc to a column resource path will give the same result as the default.

If not specified, the results will sort based on the defaultSort attribute of the <report>'s <export_config>, if specified.

The base table path is optional in sort parameter

It is unnecessary to include the base table path within the sort parameter column resource paths. Because of this, the following sort parameter values are equivalient if the <report>'s base table has id="base" with a <column> of id="name":

  • sort=@name

  • sort=/base@name

  • sort=/base@name asc

Example 5.7. sort parameter usage

The following example sorts the results first by ascending name column on the base table and then descending birth_date column on the parent relationship table:

sort=@name;/parent@birth_date desc


5.1.3. XML Format

Format Type:  xml

Response Content-Type:  application/xml

The xml format writes XML to the HTTP response body.

XML filename: The Content-Disposition HTTP header is set to the value of the <report> name attribute with underscore characters (_), substituted for any spaces plus the .xml extension.

5.1.3.1. OK Response

Status Code:  200

XML responses without error have this DTD structure:

<!DOCTYPE results [
<!ELEMENT results (meta,data)>

<!-- meta: contains meta information about the results. -->
<!ELEMENT meta (filters?,columns,totalCount)>

<!-- filters: (Optional) contains information about the filters applied to this 
     result set if applicable. -->
<!ELEMENT filters (filter+)>

<!-- filter: Contains information about one filter applied to this result set. -->
<!ELEMENT filter (source,readable)>

<!-- source: String representation of the original filter parameter. -->
<!ELEMENT source (#PCDATA)>

<!-- readable: Contains the readable filter String with Table and Column 
     DisplayName's substituted for id's. -->
<!ELEMENT readable (#PCDATA)>

<!-- columns: meta information about the columns of the result set. The order 
     of child <column> elements matches the order of <v> elements in each 
     <data> <row>. -->
<!ELEMENT columns (column+)>

<!-- column: meta information about one the columns of the result set -->
<!ELEMENT column (id,tablePath,displayName)>

<!-- id: The id of the column -->
<!ELEMENT id (#PCDATA)>

<!-- tablePath: The table resource path to the column -->
<!ELEMENT tablePath (#PCDATA)>

<!-- displayName: The displayName of the column -->
<!ELEMENT displayName (#PCDATA)>

<!-- totalCount:  The total number of results to be returned based on the 
     filter and columns parameters. This can differ from the length of the 
     data array if the limit and offset parameters are specified. -->
<!ELEMENT totalCount (#PCDATA)>

<!-- row: One row of results -->
<!ELEMENT row (v+)>

<!-- v: One "cell" of results. "v" means "value" -->
<!ELEMENT v (#PCDATA)>

<!-- attribute v:url: The url of the value as configured by the <column>'s 
     <url_template> -->
<!ATTLIST v url CDATA #IMPLIED>
]>
Example 5.8. Example XML Output Format
<?xml version="1.0" encoding="UTF-8"?>
<results>
<meta>
    <filters>
         <filter>
             <source>/student@fname like 'J%'</source>
             <readable>'Student', 'First Name' like 'J%'</readable>
         </filter>
         <filter>
             <source>/student@lname = 'Hernadez'</source>
             <readable>'Student', 'Last Name' = 'Hernandez'</readable>
         </filter>
    </filters>
    <columns>
        <column>
            <id>id</id>
            <displayName>Student ID</displayName>
            <tablePath>/student</tablePath>
        </column>
        <column>
            <id>fname</id>
            <displayName>First Name</displayName>
            <tablePath>/student</tablePath>
        </column>
        <column>
            <id>lname</id>
            <displayName>Last Name</displayName>
            <tablePath>/student</tablePath>
        </column>
    </columns>
    <totalCount>2</totalCount>
</meta>
<data>
    <row>
        <v>177</v>
        <v>Joe</v>
        <v url="/some/url/177">Hernandez</v>
    </row>
    <row>
        <v>213</v>
        <v>Julia</v>
        <v url="/some/url/213">Hernandez</v>
    </row>
</data>
</results>

5.1.3.2. Error Response

Status Code:  400 and 500

XML responses with error have this DTD structure:

<!DOCTYPE messages [
<!-- messages: The set of error messages -->
<!ELEMENT messages (message+)>

<!-- message: one error message -->
<!ELEMENT message (#PCDATA)>
]>
Example 5.9. Example XML Error Output Format
<?xml version="1.0" encoding="UTF-8"?>
<messages>
    <message>The filter "/student@id &amp; 173" does not match filter grammar. The "Operator" definition is missing or unparseable.</message>
</messages>

5.1.4. JSON Format

Format Type:  json

Response Content-Type:  application/json

The json format writes JSON to the HTTP response body.

5.1.4.1. OK Response

Status Code:  200

JSON responses without error have this structure:

{
// meta: contains meta information about the results. 
"meta":{
    // filters: (Optional) contains information about the filters applied to this 
    // result set if applicable. 
    "filters": [
          {"source":string    // String representation of the original filter parameter.
           ,"readable":string // Contains the readable filter String with Table and Column 
                              // DisplayName's substituted for id's.
          },...
    ]
    // columns: meta information about the columns of the result set. The order 
    // of child objects matches the order of array elements in each 
    // "data" array.
    ,"columns": [
          {"id":string           // The id of the <column>
           ,"displayName":string // The displayName of the <column>
           ,"tablePath":string   // The table resource path to the <column>
           }
           ...
    ]
    // The total number of results to be returned based on the filter and columns
    // parameters. This can differ from the length of the data array
    // if the limit and offset parameters are specified. 
    ,"totalCount":integer
}
// data: array of arrays representing the results
// All values are coerced to a JavaScript type appropriate for their database type
// (i.e. String, date, number). <column>s with a <url_template> are represented via
// a JavaScript Object with attributes "url" and "value"
,"data": [
   [value1, value2, {"url":string,"value":string},...]
   ,...
]
}
Example 5.10. Example JSON Output Format
{
"meta": {
    "filters":[
         {
             "source":"/student@fname like 'J%'"
             ,"readable":"'Student', 'First Name' like 'J%'"
         }
         ,{
             "source":"/student@lname = 'Hernadez'"
             ,"readable":"'Student', 'Last Name' = 'Hernandez'"
         }
    ]
    ,"columns":[
         {
             "id":"id"
             ,"displayName":"Student ID"
             ,"tablePath":"/student"
         }
         ,{
             "id":"fname"
             ,"displayName":"First Name"
             ,"tablePath":"/student"
         }
         ,{
             "id":"lname"
             ,"displayName":"Last Name"
             ,"tablePath":"/student"
         }
    ]
    ,"totalCount":2
}
"data":[
    {
        177
        ,"Joe"
        ,{"url":"/some/url/177","value":"Hernandez"}
    }
    ,{
        213
        ,"Julia"
        ,{"url":"/some/url/213","value":"Hernandez"}
    }
]
}

5.1.4.2. Error Response

Status Code:  400 and 500

JSON responses with error have this structure:

{
 // messages: array of message Strings.
 "messages":[
     ...
 ]
}
Example 5.11. Example JSON Error Output Format
{
 "messages":[
      "The filter \"/student@id & 173\" does not match filter grammar. The \"Operator\" definition is missing or unparseable."
  ]
}

5.1.5. HTML Format

Format Type:  html

Response Content-Type:  text/html

The html format writes a complete HTML document to the HTTP response body. This format extends the HTML Table format and decorates the result <table> with HTML <body> and <html> tags to make the result valid HTML. Additionaly, the HTML Format titles the HTML with the Pull Report name and includes the Pull Reports™ CSS stylesheet and <div> elements for basic formatting.

5.1.5.1. Decorating the returned HTML

See the administration chapter for information on how to decorate (wrap) the exported HTML with additional HTML elements such as a custom header and footer.

5.1.5.2. OK Response

Status Code:  200

HTML format responses without error are valid HTML5 documents. The HTML result <table> is identical to that returned by the HTML Table format except the addition of a style class attribute. The exact format of the document may vary slightly between Pull Reports™ releases, but a reference example is provided below.

Example 5.12. Example HTML Output Format
<!DOCTYPE html>
<html>
    <head>
        <title>Student Report</title>
        <link rel='stylesheet' href='/mycontext/assets/pullreports.min.css'></link>
    </head>
    <body>
        <div class="container-fluid">
            <div class="row">
                <div class="col-xs-12">
                    <h1>Student Report</h1>
                    <table class="table table-striped table-bordered">
                        <caption>
                            <aside>2 Rows</aside>
                            <h5>Filters</h5>
                            <ul>
                                <li>'Student', 'First Name' like 'J%'</li>
                                <li>'Student', 'Last Name' = 'Hernandez'</li>
                            </ul>
                        </caption>
                        <thead>
                            <tr>
                                <th data-tablePath="/student" data-columnId="id">Student ID</th>
                                <th data-tablePath="/student" data-columnId="fname">First Name</th>
                                <th data-tablePath="/student" data-columnId="lname">Last Name</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>177</td>
                                <td>Joe</td>
                                <td><a href="/some/url/177">Hernadez</a></td>
                            </tr>
                            <tr>
                                <td>213</td>
                                <td>Julia</td>
                                <td><a href="/some/url/213">Hernadez</a></td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </body>
</html>

5.1.5.3. Error Response

Status Code:  400 and 500

HTML format responses with error have the same structure as Error responses from the HTML Table format with the addition of valid HTML decoration.

Example 5.13. Example HTML Table Error Output Format
<!DOCTYPE html>
<html>
    <head>
        <link rel='stylesheet' href='/[context]/assets/pullreports.min.css'></link>
    </head>
    <body>
        <ul class="error">
            <li>The filter "/student@id &amp; 173" does not match filter grammar. The "Operator" definition is missing or unparseable.</li>
        </ul>
    </body>
</html>

5.1.6. HTML Table Format

Format Type:  htmltable

Response Content-Type:  text/html

The htmltable format writes HTML to the HTTP response body. The returned HTML is internally valid XML but not valid HTML since it is neither encapsulated with <html> nor <body> tags. This allows the returned HTML to be embedded within the DOM of an HTML Document.

5.1.6.1. OK Response

Status Code:  200

HTML Table responses without error have this DTD structure:

<!DOCTYPE table [
<!ELEMENT table (caption?,thead,tbody)>

<!ELEMENT caption (aside,h5,ul)>

<!-- aside: Contains the total row count -->
<!ELEMENT aside (#PCDATA)>

<!-- h5 and ul: optionally rendered if at least one filter is applied to the results. The 
     h5 contains the 'Filters' title, and the ul contains human readable filters (with table and 
     column displayName substituted for id's) in a bulleted list -->
<!ELEMENT h5 (#PCDATA)>
<!ATTLIST h5 class CDATA>

<!ELEMENT ul (li)>

<!ELEMENT li (#PCDATA|em|samp)>
<!ELEMENT em (#PCDATA)>
<!ELEMENT samp (#PCDATA)>

<!ELEMENT thead (tr)>

<!ELEMENT tbody (tr)>

<!ELEMENT tr (th|td)>

<!-- th: Contains the <column> displayName -->
<!ELEMENT th (#PCDATA)>

<!-- th attributes: The 'tablePath' and 'columnId' value of each column is added as a data 
     attribute for every column header. This makes it possible to find the column associated
     with a given tablePath and columnId with a selector tool like JQuery. -->
<!ATTLIST th data-tablePath CDATA>
<!ATTLIST th data-columnId CDATA >

<!-- td: Contains the row value -->
<!ELEMENT td (#PCDATA|a)>

<!-- a: <column>'s with a <url_template> have their values surrounded with an HTML anchor
     tag (a) with the filled URL template as the value of the href attribute. -->
<!ELEMENT a (#PCDATA)>
<!ATTLIST a href CDATA>

]>
Example 5.14. Example HTML Table Output Format
<table>
    <caption>
        <aside>2 Rows</aside>
        <h5 class='filters-title'>Filters</h5>
        <ul>
            <li>Table: <em>Student</em>, Column: <em>First Name</em> <samp>like</samp> 'J%'</li>
            <li>Table: <em>Student</em>, Column: <em>Last Name</em> <samp>=</samp> 'Hernandez'</li>
        </ul>
    </caption>
    <thead>
        <tr>
            <th data-tablePath="/student" data-columnId="id">Student ID</th>
            <th data-tablePath="/student" data-columnId="fname">First Name</th>
            <th data-tablePath="/student" data-columnId="lname">Last Name</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>177</td>
            <td>Joe</td>
            <td><a href="/some/url/177">Hernadez</a></td>
        </tr>
        <tr>
            <td>213</td>
            <td>Julia</td>
            <td><a href="/some/url/213">Hernadez</a></td>
        </tr>
    </tbody>
</table>

5.1.6.2. Error Response

Status Code:  400 and 500

HTML Table responses with error have this structure:

<!DOCTYPE ul [
<!ELEMENT ul(li)>
<!ATTLIST ul class CDATA "error">

<!ELEMENT li(#PCDATA)>
]>
Example 5.15. Example HTML Table Error Output Format
<ul class="error">
    <li>The filter "/student@id &amp; 173" does not match filter grammar. The "Operator" definition is missing or unparseable.</li>
</ul>

5.1.7. KML Format

Format Type:  kml

Response Content-Type:  application/vnd.google-earth.kml+xml

The KML format writes KML to the HTTP response body following these guidelines:

Geometry configured via <kml> The geometry value of each KML <Placemark> (such as a <Point>, <LineString> , or <Polygon>) for each result row is the value of the base table column designated by the <report>'s <kml> geometryColumnPath attribute. The KML export format will only create a <Placemark> for result rows with a non-null value for the column referenced by geometryColumnPath.

If no <kml> geometryColumnPath is designated, the format will return a 400 HTTP response status.

Geometry uniqueness respective to base table:  The kml format will create a single KML geometry per unique result row. Uniqueness is determined by the aggregate equality of the base table <column> values. This means that even if the columns parameter creates a join condition such that the base table <column> values are repeated across multiple result rows, only one KML geometry will be present in the KML results for each, unique base table row.

Value of <Document> <name> For OK responses, the <Document> <name>: value is:

Export from: [<catalog> name]:[<report> name]

Additionally, if at least one filter parameter is specified, filters applied is appended to the <name> value.

For Error responses, the value is:

Error in Export. See description.

Value of the <Document> <description> For OK responses, if at least one filter parameter is specified, the <description> contains a bulleted list of human readable filter definitions with table and column displayName substituted for id's.

For Error responses, the <description> contains a bulleted list of error messages.

Additional columns as <ExtendedData> Each base table column of the exported result row is included as a child <Data> element of the <Placemark>'s <ExtendedData> element. Each <Data>'s name attribute is the corresponding <column>'s column resource path. Each <Data>'s child <displayName> and <value> elements contain the <column>'s displayName and result row value respectively.

Any <column>s with a <url_template> have their values surrounded with an HTML anchor tag (a) with the filled URL template as the value of the href attribute.

Customizing <Placemark> <name>s:  By default, the <name> element of each <Placemark> is the name of the <report> plus the word "Geometry". Specify the <report>'s <placemark_name_template> element to customize the <name> element based on values from the result row.

5.1.7.1. OK Response

Status Code: 200

KML responses without error follow this example:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <name>Export from: Class Information:Student Report &lt;i&gt;filters applied&lt;/i&gt;</name>
    <!-- Human readable filter definitions are only included in the <description>
         if at least one filter parameter is specified. Otherwise the <description>
         is empty. -->
    <description><![CDATA[<ul>
        <li>'Student', 'First Name' like 'J%'</li>
        <li>'Student', 'Last Name' = 'Hernandez'</li>
    </ul>]]></description> 
    <Placemark>
      <!-- In this example, the <Placemark> <name> is customized via:
      <placemark_name_template>${@fname} ${@lname} Home</placemark_name_template> -->
      <name>Joe Hernandez Home</name>
      <ExtendedData>
        <Data name="/student@id">
          <displayName>Student ID</displayName>
          <value>177</value>
        </Data>
        <Data name="/student@fname">
          <displayName>First Name</displayName>
          <value>Joe</value>
        </Data>
        <Data name="/student@lname">
          <displayName>Last Name</displayName>
          <value>&lt;a href="/some/url/177"&gt;Hernandez&lt;/a&gt;</value>
        </Data>
      </ExtendedData>
      <!-- The geometry value is the value of the base table column specified by
           <kml geometryColumnPath="..."> -->
      <Point>
        <coordinates>-105.0906227,40.5656519,0</coordinates>
      </Point>
    </Placemark>
    <Placemark>
      <name>Julia Hernandez Home</name>
      <ExtendedData>
        <Data name="/student@id">
          <displayName>Student ID</displayName>
          <value>213</value>
        </Data>
        <Data name="/student@fname">
          <displayName>First Name</displayName>
          <value>Julia</value>
        </Data>
        <Data name="/student@lname">
          <displayName>Last Name</displayName>
          <value>&lt;a href="/some/url/213"&gt;Hernandez&lt;/a&gt;</value>
        </Data>
      </ExtendedData>
      <Point>
        <coordinates>-105.0994311,40.5673064,0</coordinates>
      </Point>
    </Placemark>
  </Document>
  </kml>

5.1.7.2. Error Response

Status Code: 400 and 500

KML responses with error follow this example:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <name>Error in Export. See description.</name>
    <description><![CDATA[
    <ul>
        <li>The filter "/student@id & 173" does not match filter grammar. The "Operator" definition is missing or unparseable.</li>
    </ul>
    ]]></description>
  </Document>
</kml>

5.1.8. GeoJSON Format

Format Type: geojson

Response Content-Type: application/vnd.geo+json

The GeoJSON format writes GeoJSON to the HTTP response body following these guidelines:

Geometry configured via <geojson>: The geometry value of each GeoJSON feature (such as a Point, LineString , or Polygon) for each result row is the value of the base table column designated by the <report>'s <geojson> geometryColumnPath attribute. The GeoJSON export format will only create a feature for result rows with a non-null value for the column referenced by geometryColumnPath.

If no <geojson> geometryColumnPath is designated, the format will return a 400 HTTP response status.

Feature uniqueness respective to base table: The geojson format will create a single GeoJSON feature per unique result row. Uniqueness is determined by the aggregate equality of the base table <column> values. This means that even if the columns parameter creates a join condition such that the base table <column> values are repeated across multiple result rows, only one GeoJSON feature will be present in the GeoJSON results for each, unique base table row.

FeatureCollection name property: For OK responses, the GeoJSON FeatureCollection has a name property that is:

Export from: [<catalog> name]:[<report> name]

"name" is a non-standard GeoJSON property.

FeatureCollection filters property: For OK responses, if at least one filter parameter is specified, the GeoJSON FeatureCollection has a filters property that is an array of Objects each with a source and readable property whose values are, respectfully, the original filter parameter and human readable filter definitions with table and column displayName substituted for id's.

"filters" is a non-standard GeoJSON property.

FeatureCollection totalCount property: For OK responses, the GeoJSON FeatureCollection has a totalCount property that is the total number of results to be returned based on the filter and columns parameters. This can differ from the length of the features array if the limit and offset parameters are specified or if there are records without GeoJSON geometry.

"totalCount" is a non-standard GeoJSON property.

Additional columns as feature properties: Each base table column of the exported result row is included as a property name/value pair in the properties Map of each feature. The property name is the <column>'s displayName and the value is the <column>'s result row value.

The property value of <column>s with a <url_template> is a JavaScript Object with attributes "url" and "value" corresponding to the filled URL template and result row value respectively.

5.1.8.1. OK Response

Status Code: 200

GeoJSON responses without error follow this example:

{"type": "FeatureCollection"
    ,"name":"Export from: Class Information:Student Report"
    ,"totalCount":2
    "filters":[
         {
             "source":"/student@fname like 'J%'"
             ,"readable":"'Student', 'First Name' like 'J%'"
         }
         ,{
             "source":"/student@lname = 'Hernadez'"
             ,"readable":"'Student', 'Last Name' = 'Hernandez'"
         }
    ]
    ,"features": [
        {
            "type": "Feature"
            ,"geometry":{
               "type": "Point"
               ,"coordinates": [-105.0906227,40.5656519]
            }
            ,"properties":{
               "Student ID":177
               ,"First Name":"Joe"
               ,"Last Name":{"url":"/some/url/177","value":"Hernandez"}
            }
        }
        ,{
            "type": "Feature"
            ,"geometry":{
               "type": "Point"
               ,"coordinates": [-105.0994311,40.5673064]
            }
            ,"properties":{
               "Student ID":213
               ,"First Name":"Julia"
               ,"Last Name":{"url":"/some/url/213","value":"Hernandez"}
            }
        }
    ]
}

5.1.8.2. Error Response

Status Code: 400 and 500

GeoJSON responses with error follow this example:

{
 // messages: array of message Strings.
 "messages":[
     ...
 ]
}
Example 5.16. Example GeoJSON Error Output Format
{
 "messages":[
      "The filter \"/student@id & 173\" does not match filter grammar. The \"Operator\" definition is missing or unparseable."
  ]
}

5.1.9. Map Format

Format Type: map

Response Content-Type: text/html

The map format writes an HTML document to the HTTP response body with an embedded Leaflet map which displays the GeoJSON results from the GeoJSON format. Like the GeoJSON format, the map format is only available if the report has a valid <geojson> element.

5.1.9.1. Decorating the returned HTML

See the administration chapter for information on how to decorate (wrap) the exported HTML with additional HTML elements such as a custom header and footer.

5.1.9.2. Customizing the Leaflet mapper

In order to control the behavior of the map format's embedded Leaflet mapper, decorate the returned HTML and define an global JavaScript variable within the <head> of the DOM named mapConfig. mapConfig must be a JavaScript object with one or more of the properties below. The map format JavaScript will detect this variable and use it during initialization of the Leaflet Mapper.

mapConfig object properties
initCallback

A JavaScript function to be invoked after map initialization. The arguments to the function are:

  • map: The Leaflet map.

  • geoJsonLayer: The Leaflet markercluster layer which contains the GeoJSON Layer which in turn contains the GeoJSON result of the Export REST API, geojson format.

geoJsonOptions

A JavaScript object to be passed to the Leaflet GeoJSON layer upon construction. See the Leaflet GeoJSON documentation for a complete list of configuration options.

If not specified, Pull Reports™ will set the following default GeoJSON layer option values:

  • onEachFeature: Set to a function which binds a Leaflet popup to the layer for each feature. The content of the popup is a two column table of GeoJSON feature property names to values. The property names and values are the exported <column>s of the report's base table.

options

A JavaScript object to be passed to the Leaflet map upon construction. See the Leaflet map options documentation for a complete list of configuration options.

If not specified, Pull Reports™ will set the following default map option values:

  • center: Set to the geographic center of the lower 48 United States.

  • layers: Set to an array with a single Open Street Map base layer.

  • zoom: Set to 4

Example 5.17. Example map format customization

This example customizes the map format Leaflet mapper by adding a Leaflet Layers control to the map with the ability to toggle between two base tile layers and toggle the visibility of the report's GeoJSON layer. The example uses the Servlet include technique to include custom JavaScript within the returned HTML <head> element.

To begin, create a text document called mapConfig.html within the installation WAR's WEB-INF/context directory. This document will define the mapConfig global variable within an HTML <script> element. The example below uses the mapConfig options and initCallback properties to set the default map layers and add a Layers control respectively.

<script>
    var baseLayers = [];
    baseLayers['ESRI World Topo'] = 
        L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}', {
        attribution: 'Tiles &copy; Esri &mdash; Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community'
        ,maxZoom:18
    });
    baseLayers['Open Street Map'] = 
        L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors'
        ,maxZoom: 18
    });
    
    function initializeMap(map,geojsonLayer){
        L.control.layers(baseLayers, {'My Report Data':geojsonLayer}).addTo(map);
    }

    var mapConfig = {
        options: {
            layers:[baseLayers['Open Street Map']]
        }
        ,initCallback:initializeMap
    };
</script>

To include this file within the map format HTML <head> element, set the export.report.include.map.head.end configuration property in pullreports.properties to the WAR relative location of mapConfig.html like so:

export.report.include.map.head.end=/WEB-INF/content/mapConfig.html

Pull Reports™ will then insert the mapConfig.html fragment into every map format response and use the mapConfig variable to customize the Leaflet map.


5.1.9.3. OK Response

Status Code: 200

Map format responses without error are valid HTML5 documents into which the output of the GeoJSON format is written as a JavaScript variable and displayed within an embedded Leaflet map.

5.1.9.4. Error Response

Status Code: 400 and 500

Map format responses with error have the same structure as Error responses from the HTML format.

5.1.10. CSV Format

Format Type: csv

Response Content-Type: text/csv

The CSV format writes double quoted Comma Separated Values with to the HTTP response body following these guidelines:

<column> displayName values as first row: The first row of the CSV is the displayNames values for each <column> included in the exported results. If any <column> contains a <url_template>, an additional column titled displayName + "_url" immediately follows the <column> with the <url_template>. The additional column contains the value of the filled <url_template> for each result row.

CSV filename: The Content-Disposition HTTP header is set to the value of the <report> name attribute with underscore characters (_), substituted for any spaces plus the .csv extension. If an error occurs, the Content-Disposition filename is Error.csv.

5.1.10.1. OK Response

Status Code: 200

CSV responses without error follow this example:

"Student ID","First Name","Last Name","Last Name_url"
"177","Joe","Hernandez","/some/url/177"
"213","Julia","Hernandez","/some/url/213"

5.1.10.2. Error Response

Status Code: 400 and 500

CSV responses with error write the error messages to the HTTP response body as a line break separated list. For example:

Example 5.18. Example CSV Error Output Format
The filter "/student@id & 173" does not match filter grammar. The "Operator" definition is missing or unparseable.

5.1.11. Filters

filter parameters follow the pattern:

[Filter Term] (or [Filter Term])*

where a Filter Term is:

[Column Resource Path] [Operator] (Values)?

Within one [Filter Term], the [Column Resource Path] is the path to the <column> on which to apply the filter. The [Operator] is the comparison function to apply to the filter. The (Values)? clause is required for some Operators but not for others. For instance, the not null operator does not take a value while the equality, =, operator does.

Multiple [Filter Term]s may be separated by the or keyword in a single filter parameter to indicate the terms should be logically or'ed together in the resultant query.

Example 5.19. filter parameter usage

Assuming this Pull Reports™ XML Catalog file:

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.pullreports.com/catalog-1.3.0" 
    id="class" name="Class Reports">
    <report id="student-information" name="Student Information Report">
        <export_config defaultColumns="id"/>
        <table id="student" name="person" displayName="Person Info"> 
            <column id="id" name="student" paramType="java.lang.Integer"/>
            <column id="age" name="age" paramType="java.lang.Integer"/>
            <column id="address_state" name="state"/>
            <relationship join="left" cardinality="many">
                <join_table name="student_parent">
                    <join_columns>
                        <join_column columnName="student_id" referencedColumnName="id" />
                    </join_columns>
                    <inverse_join_columns>
                        <join_column columnName="parent_id" referencedColumnName="id" />
                   </inverse_join_columns>
                </join_table>
                <table id="parent" name="parent" displayName="Parent">
                    <column id="id" name="student" paramType="java.lang.Integer"/>
                    <column id="first_name" name="first_name"/>
                    <column id="last_name" name="last_name"/>
                </table>
            </relationship>
        </table>
    </report>
</catalog>

Create a filter for students greater than age 8 ...

filter=/student@age > 8

... and another for students whose parent's last name starts with 'H' or whose address is in 'Colorado':

filter=/student/parent@last_name like 'H%' or /student@address_state = 'Colorado'

Put the two filters together in an export URL query string:

/[context]/pullreports/catalog/class/report/student-information/export?filter=/student@age > 8&filter=/student/parent@last_name like 'H%' or /student@address_state = 'Colorado'

and finally URL encode it:

/[context]/pullreports/catalog/class/report/student-information/export?filter=%2Fstudent%40age%20%3E%208&filter=%2Fstudent%2Fparent%40last_name%20like%20%27H%25%27%20or%20%2Fstudent%40address_state%20%3D%20%27Colorado%27


5.1.11.1. Filter Operators

The following table lists the available filter operators. The filter parameter examples reference column resource paths from this example Pull Reports™ XML Catalog file:

Table 5.1. Filter Operators
OperatorDescription
=, !=, or <>

Equality / Inequality.

Example 5.20. Equality / Inequality examples:

/student@id = 145
/student@name = 'Frank Smith'
@name = 'Frank Smith'
/student/parent@id = 2291
/student/employer@name = 'Full Draft'
/student@active = true
@active = true
@bdate = '1976-04-23'
/student@id != 145
/student@name <> 'Frank Smith'
/student/parent@id <> 2291
/parent@id <> 2291
/student/employer@name != 'Full Draft'
/student@active != true


<, >, <=, or >=

Comparison.

Example 5.21. Comparison examples:

/student@id < 145
/student@name > 'F'
@name > 'F'
/student/parent@id < 2291
/student@bdate < '2008-09-28'
/student/employer@name >= 'Full Draft'


between X and Y

Range Comparison.

Example 5.22. Range Comparison examples:

/student@id between 145 and 203
/student@name between 'F' and 'H'
/student/parent@id between 2291 and 3000
@bdate between '2000-01-01 00:00:00' and '2000-01-01 23:59:59'


in (...)

Equal to at least one of.

Example 5.23. Equal to at least one of examples:

/student@id in (33,39,1039)
/student@name in ('Forest','Robert','Maricela')
@name in ('Forest','Robert','Maricela')


not in (...)

Unequal to all of.

Example 5.24. Unequal to all of examples:

/student@id not in (33,39,1039)
/student@name not in ('Forest','Robert','Maricela')
@name not in ('Forest','Robert','Maricela')


like or not like

String pattern search.

Example 5.25. String pattern search examples:

/student@name like 'Smi%'
/student/parent@name not like '%-%'


is null or is not null

Null value.

Example 5.26. Null value examples:

/student@name is null
/student/parent@name is not null
/parent@name is not null



5.1.11.2. Value syntax

Values within filters parameters are of one of the following types:

Table 5.2. Filter value types
TypeDescription
NumericMay be any integer or floating point number. For example: 22, 31.72, or -0.22. Commas (,) within numeric values are not supported.
StringA single quoted value. Escape single quotes with a single quote. For example: 'Foo' or 'Mister Jones'' watermelon'.
Booleantrue or false. Because Boolean values are case insensitive, TRUE or FALSE are also valid.

In order to pass filter values to the JDBC driver, Pull Reports™ will coerce values to the referenced <column>'s paramType attribute via the following rules:

Table 5.3. Filter value coercion
Value Type<column> paramTypeCoercion
Numericjava.lang.StringNumber will be turned into String
 java.sql.Date, java.sql.Time, java.sql.TimestampLong value of number used as the number of milliseconds since the Epoch (January 1st, 1970). For instance:

return new java.sql.Date(value)

 java.lang.BooleanIf value equals 1, coerce to true. If value equals 0, coerce to false.
Stringjava.lang.Long, java.lang.Integer, java.lang.Float, or java.lang.DoubleString will be parsed to a Number
 java.sql.DateString will be parsed to a java.sql.Date by the java.text.SimpleDateFormat class using the yyyy-MM-dd format pattern.
 java.sql.TimeString will be parsed to a Date via one of the following format patterns from the java.text.SimpleDateFormat class. Pull Reports™ will choose the pattern whose length matches the value length.

HH:mm:ss
HH:mm:ss.SSS

 java.sql.TimestampString will be parsed to a java.sql.Timestamp via one of the following format patterns from the java.text.SimpleDateFormat class. Pull Reports™ will choose the pattern whose length matches the value length.

yyyy-MM-dd
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm:ss.SSS

 java.lang.BooleanIf value equals '1' or case insensitive 'true', then coerce to true, else, coerce to false.
Booleanjava.lang.Long, java.lang.Integer, java.lang.Float, or java.lang.DoubleIf value equals true, then coerce to 1. If value equals false, then coerce to 0.
 java.lang.StringIf value equals true, then coerce to 'true'. If value equals false, then coerce to 'false'.

5.2. GET Export Parse Parameters

5.2.1. Overview

GET Export Parse Parameters is a utility end point used by the Pull ReportsAd Hoc Report Creator to validate and parse parameters of the GET Export Report endpoint which contain column resource paths such as filter, columns, and sort. The end point returns a JSON representation of valid parameters and error information regarding invalid parameters.

Unlike the GET Export Report end point, this end point returns a 200, OK response when a parameter is invalid and captures the parse error in the errors property of the returned JSON.

URL

/[context]/pullreports/catalog/[catalog id]/report/[report id]/export/parseParams

5.2.2. Parameters

5.2.2.1. columns, filter, sort

These three parameters have the same definition as the corresponding parameters in the GET Export Report endpoint. Each parameter will be parsed and represented as a member of the columns, filters, and sorts arrays respectively in the JSON result.

5.2.3. Response Format

Response Content-Type:  application/json

5.2.3.1. OK Response

Status Code:  200

JSON responses without error have this structure:

{
    // The "columns" property is an array of column objects which
    // represent the successfully parsed column resource path terms in 
    // the semicolon (;) separated list of terms from the columns parameter.
    "columns":[{
        "tablePath":string
        ,"columnIds":[string]
    },...]

    // The "filters" property is an array of filter objects which
    // represent the successfully parsed filter parameters.
    "filters":[{
        // The "terms" array holds the parsed filter terms
        // to be OR'ed together.
        "terms":[{
            "tablePath":string
            ,"columnId":string
            ,"operator":string
            ,"values":[...]
        },...]
        ,"source":string // The value of the "filter" parameter.
    },...]

    // The "sorts" property is an array of sort objects which
    // represent the successfully parsed sort terms in the semicolon (;)
    // separated list of terms from the sort parameter.
    // The "sorts" property will only be non-null if the "columns"
    // parameter parses without error.
    ,"sorts":[{
        "tablePath":string
        ,"columnId":string
        ,"direction":string
        ,"source":string // the value of the "sort" term.
    },...]

    // The "errors" property captures any errors that occur when
    // parsing the columns, filter, and sort parameters.
    ,"errors": [
        {"param":string  // Either "columns", "filter", or "sort".
         "value":string  // The value of the parameter that was in error.
         "message"string // A description of the error.
        },...
    ]
}
Example 5.27. Example JSON Output Format

The GET Export Parse Parameters end point returns the following response for a request structured like so:

/[context]/pullreports/catalog/[catalog id]/report/[report id]/export/parseParams?columns=/parent@columnA,columnC;/parent/child;&filter=/parent@columnB+=+3&filter=/parent/child@columnW+in+('foo','bar')+or+/parent@columnA+is+not+null&sort=/parent/child@columnZ+desc;/parent@columnA

{
    "columns": [
        {"tablePath":"/parent"
         ,"columnIds":["columnA","columnC"]
        }
        ,{"tablePath":"/parent/child"}
    ]
    ,"filters": [
        {"terms": [
            {"tablePath":"/parent"
            ,"columnId":"columnB"
            ,"operator":"="
            ,"values":[3]}
         ],
         "source":"/parent@columnB = 3"
         }
        ,{"terms": [
            {"tablePath":"/parent/child"
            ,"columnId":"columnW"
            ,"operator":"in"
            ,"values":["foo","bar"]}
            ,{"tablePath":"/parent"
            ,"columnId":"columnA"
            ,"operator":"is not null"}
         ],
         "source":"/parent/child@columnW in ('foo','bar') or /parent@columnA is not null"
         }
    ]
    ,"sorts":[{
        "tablePath":"/parent/child"
        ,"columnId":"columnZ"
        ,"direction":"desc"
        ,"source":"/parent/child@columnZ desc"
        }
        ,{"tablePath":"/parent"
        ,"columnId":"columnA"
        ,"direction":"asc"
        ,"source":"/parent@columnA"
        }
    ]
}

5.3. GET Export SQL

5.3.1. Overview

GET Export SQL returns the SQL to be sent to the database if the GET Export Report API were requested with identical parameters. This end point is useful for administrators requiring visibility into Pull Reports™ SQL queries.

Because this end point may aid attackers hoping to mount SQL based attacks against the <report> data structure, the GET Export SQL end point is disabled by default. Activate the end point via the export.sql.active configuration property after appropriately securing the end point to permitted users.

Securing the GET Export SQL

Since the GET Export SQL end point is prefixed with the /pullreports/admin directory path, it is easy to secure all requests to the endpoint with the /pullreports/admin/* URL pattern. For instance, assuming Servlet Container based security, the following <security-constraint> in the Pull Reports™ installation WAR's web.xml restricts access to users with the ADMINISTRATOR role.

<security-constraint>
    <display-name>User</display-name>
       <web-resource-collection>
            <web-resource-name>PullReports Administration</web-resource-name>
            <url-pattern>/pullreports/admin/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>ADMINISTRATOR</role-name>
    </auth-constraint>
</security-constraint>
<security-role>
    <role-name>ADMINISTRATOR</role-name>
</security-role>
 

URL

/[context]/pullreports/admin/catalog/[catalog id]/report/[report id]/export/sql(.json)

URL Components
/[context]

The web application context path of the WAR which contains the Pull Reports™ JAR. Typically this is the name of the WAR file.

/pullreports

The URL path to the PullReportsServlet. This path is configured automatically web.xml when installing Pull Reports™.

/admin

Defines the administrative directory space.

/catalog/[catalog id]

The id of the <catalog> as configured in Pull Reports™ XML Catalog files.

/report/[report id]

The id of the <report> as configured in the encompassing <catalog>.

/export/sql

The export SQL end point.

(.json)

Optionally appending .json to the URL or setting the HTTP Accept header to application/json returns the JSON format response.

5.3.2. Parameters

5.3.2.1. format, columns, distinct, filter, limit, offset, sort

These seven parameters have the same definition as the corresponding parameters in the GET Export Report endpoint.

What does the format parameter do?

Since the Export SQL varies slightly by GET Export Report format parameter value, use this parameter to view the SQL per format. If not specified, the default value is json.

5.3.3. HTML Format

Format Type:  html

Response Content-Type:  text/html

The html format writes a complete HTML document to the HTTP response body. The query SQL is written within the HTML document.

5.3.4. JSON Format

Format Type:  json

Response Content-Type:  application/json

The json format writes JSON to the HTTP response body.

5.3.4.1. OK Response

Status Code:  200

JSON responses without error have this structure:

{
    "query":{
        "sql":string
        // The parameters property is an array of values to be substituted
        // at the respective positions of "?" characters in the Prepared
        // JDBC query. 
        ,"parameters":[object]
    }
}
Example 5.28. Example JSON Output Format
{
    "query": {
        "sql": "select t1.id, t1.name from table_name t1 where 1=1 and t1.last_updated > ?"
        ,"parameters":["2015-09-29T00:00:00.000Z"]
    }
}

5.3.4.2. Error Response

Status Code:  500

HTTP responses with error return a 500 status code, have an empty HTTP response body, and write information about the error to the com.pullreports.ADMIN logger.

5.4. GET Catalog Information

5.4.1. Overview

Returns meta information about <catalog>s including id, name and child <report>s. When requested with a [catalog id], returns information for just one <catalog>. When requested at the /catalog root resource path, returns meta information for all <catalog>s.

URL: single catalog

/[context]/pullreports/catalog/[catalogId].json

URL: all catalogs

/[context]/pullreports/catalog.json

Instead of to appending .json to the end of the URL, it is permitted to use the application/json Accept request header.

5.4.2. Parameters

5.4.2.1. pretty

If true, formats the returned JSON with white space and end-of-line characters.

5.4.3. OK Response

Status Code: 200

Response Content type: application/json

JSON responses without error have this structure:

Example 5.29. 
{
    "data":[   // Array of the configured <catalog>s
        {
            "id":"string"     // The id of the <catalog>
            ,"name":"string"  // The name of the <catalog>
            ,"reports":[      // Array of <report>s within this <catalog>
                {
                    "id":"string"    // The id of the <report>
                    ,"name":"string" // The name of the <report>
                }
            ]
        }
    ]
}

5.5. GET Report Information

5.5.1. Overview

Returns meta information about a <report>.

URL:

/[context]/pullreports/catalog/[catalogId]/report/[reportId].json

Instead of to appending .json to the end of the URL, it is permitted to use the application/json Accept request header.

5.5.2. Parameters

5.5.2.1. pretty

If true, formats the returned JSON with white space and end-of-line characters.

5.5.3. OK Response

Status Code: 200

Response Content type: application/json

Responses without error have this structure:

Example 5.30. 
{
    "id":string
    ,"name":string
    ,"description":string
    ,"formats":[string]   // Array of of available export formats
    ,"defaultColumns":[string] // Array of default base table column ids
    ,"exportSqlIsActive":boolean  // True if the report supports the Export SQL end point
    ,"catalog": {           // The <catalog> of the <report>
        "id":string
        ,"name":string
        ,"reports":[{
            "id":string 
            ,"name":string
        }]
    ,"global" {
        "exportReportMaxResults":integer
    }
    ,"table":{
        "id":string      
        ,"displayName":string
        ,"description":string
        ,"path":string    // The table's resource path
        ,"columns":[{
            "id":string
            ,"displayName":string
            ,"description":string
            ,"paramType":string
            // If a string, the id of the <global_label_value_list>
            // If boolean, true if the <column> has a child <label_value_list>
            ,"labelValueList":string|boolean
            ,"export":boolean
        }]
        ,"preFilters":[{
            "columnId":string
            ,"operator":string
            ,"values":[string]
        }]
        ,"relationships":[{
            "join":string
            ,"cardinality":string
            ,"table":{table object}
        }]
    }
}

5.6. GET Label Value List

5.6.1. Overview

Returns a JSON representation of a <label_value_list>. Since <label_value_list>s may be specified as global to the <catalog> or local to a <column>, there are two REST end points.

5.6.1.1. Errors

Errors in both Label Value List services caused by invalid HTTP parameters (400 status code) or SQL problems (500 status code) have this structure:

{
 // messages: array of message Strings.
 "messages":[
     ...
 ]
}

5.6.2. GET Global Label Value List

Returns a JSON representation of a <global_label_value_list>.

URL:

/[context]/pullreports/catalog/[catalogId]/labelValueList/[labelValueListId].json

Instead of to appending .json to the end of the URL, it is permitted to use the application/json Accept request header.

5.6.2.1. OK Response

Status Code: 200

Response Content type: application/json

Responses without error have this structure:

Example 5.31. 
{
    // "lvl_id" represents the <global_label_value_list> id
    "lvl_id":[{ 
        label:string
        ,value:string
        ,group:string // nullable
    }]
}

5.6.3. GET Column Label Value List

Returns a JSON representation of a <label_value_list>.

URL:

/[context]/pullreports/catalog/[catalogId]/report/[reportId]/labelValueList

5.6.3.1. Parameters

column

The full column resource path to the parent <column> of the <label_value_list>. This parameter may be specified once.

5.6.3.2. OK Response

Status Code: 200

Response Content type: application/json

Responses without error have this structure:

Example 5.32. 
{
    // "/tableA/tableB@columnId" represents the column resource path of the parent <column>
    "/tableA/tableB@columnId":[{ 
        label:string
        ,value:string
        ,group:string // nullable
    }]
}