openxava / documentation / Chapter 4: Tabular data XML (classic)

1.Introduction XML | 2.Model XML | 3.View XML | 4.Tab XML | 5.Mapping XML | 6.Aspects XML

Table of contents

Chapter 4: Tabular data XML (classic)
Initial properties and emphasize rows
Filters and base condition
Partial select (new in v5.6)
Pure SQL select
Default order
Default values for tabs at application level (new in v4m4)
Column summation (new in v4.1)
Choosing an editor (new in v4.6)
Several presentation formats using editors (new in v5.7)
Removing the Charts from list mode (new in v5.7)
Support for XML components was dropped in v7.0, although the below syntax is still use for tabs-default-values.xml definition
Tabular data is data that is displayed in table format. If you create a conventional OpenXava module, then the user can manage the component data with a list like this:
tab_en010.jpg
This list allows user to:
The default list is enough for many cases, moreover the user can customize it. Nevertheless, sometimes it is convenient to modify the list behavior. For this you have the element <tab/> within the component definition.
The syntax of tab is:
<tab
    name="name"           <!-- 1 -->
    editor="editor"       <!-- 2  New in v4.6 -->
    editores="editores"   <!-- 3  New in v5.7 -->
>
   <filter ... />         <!-- 4 -->
   <row-style ... /> ...  <!-- 5 -->
   <properties ... />     <!-- 6 -->
   <base-condition ... /> <!-- 7 -->
   <default-order ... />  <!-- 8 -->
</tab>
  1. name (optional): You can define several tabs in a component, and set a name for each one. This name is used to indicate the tab that you want to use (usually in application.xml).
  2. editor (optional): (New in v4.6) Editor from default-editors.xml or editors.xml used to display the list. It's used for the default format, if the list has several formats the other formats are not affected.
  3. editores (optional): (New in v5.7) Comma separated list of editors used to display the list. Each editor corresponds to an available format for the users. The editors are declared in default-editors.xml or editors.xml.
  4. filter (one, optional): Allows to define programmatically some logic to apply to the values entered by user when he filters the list data.
  5. row-style (several, optional): A simple way to specify a different visual style for some rows. Normally to emphasize rows that fulfill certain condition.
  6. properties (one, optional): The list of properties to show initially. Can be qualified (that is you can specify referenceName.propertyName at any depth level). The suffix + (new in v4.1) can be added to a property to show the sum of the column at bottom.
  7. base-condition (one, optional): Condition to be fulfilled by the displayed data. It's added to the user condition if needed.
  8. default-order (one, optional): To specify the initial order for data.

Initial properties and emphasize rows

The most simple customization is to indicate the properties to show initially:
<tab>
 <row-style style="row-highlight" property="type" value="steady"/>
 <properties>
 name, type, seller.name, address.city, seller.level.description
 </properties>
</tab>
These properties are shown the first time the module is executed, after that the user will have the option to change the properties to display. Also you see how you can use qualified properties (properties of references) in any level.
In this case you can see also how to indicate a <row-style/>; you are saying that the object which property type has the value steady will use the style row-highlight. The style has to be defined in the CSS style-sheet. The row-highlight (in versions previous to v4m3 it was highlight) style are already defined in OpenXava, but you can define more.
The visual effect of above is:
tab_en020.jpg

Filters and base condition

A common technique is to combine a filter with a base condition:
<tab name="Current">
 <filter class="org.openxava.test.filters.CurrentYearFilter"/>
 <properties>
 year, number, amountsSum, vat, detailsCount, paid, customer.name
 </properties>
 <base-condition>${year} = ?</base-condition>
</tab>
The condition has to have SQL syntax, you can use ? for arguments and the property names inside ${}. In this case a filter is used to set the value of the argument. The filter code is:
package org.openxava.test.filters;
import java.util.*;
import org.openxava.filters.*;
/**
 * @author Javier Paniza
 */
public class CurrentYearFilter implements IFilter { // 1
 public Object filter(Object o) throws FilterException { // 2
 Calendar cal = Calendar.getInstance();
 cal.setTime(new java.util.Date());
 Integer year = new Integer(cal.get(Calendar.YEAR));
 Object [] r = null;
 if (o == null) { // 3
 r = new Object[1];
 r[0] = year;
 }
 else if (o instanceof Object []) { // 4
 Object [] a = (Object []) o;
 r = new Object[a.length + 1];
 r[0] = year;
 for (int i = 0; i < a.length; i++) {
 r[i+1]=a[i];
 }
 }
 else { // 5
 r = new Object[2];
 r[0] = year;
 r[1] = o;
 }
 return r;
 }
}
A filter gets the arguments of user type for filtering in lists and for processing, it returns the value that is sent to OpenXava to execute the query. As you see it must implement IFilter (1), this force it to have a method named filter (2) that receives a object with the value of arguments and returns the filtered value that will be used as query argument. These arguments can be null (3), if the user does not type values, a simple object (5), if the user types a single value or an object array (4), if the user types several values. The filter must consider all cases. The filter of this example adds the current year as first argument, and this value is used for filling the arguments in the base-condition of tab.
To sum up, the tab that you see above only shows the invoices of the current year.
Another case:
<tab name="DefaultYear">
 <filter class="org.openxava.test.filters.DefaultYearFilter"/>
 <properties>
 year, number, customer.number,
 customer.name, amountsSum, vat, detailsCount, paid, importance
 </properties>
 <base-condition>${year} = ?</base-condition>
</tab>
In this case the filter is:
package org.openxava.test.filters;
import java.util.*;
import org.openxava.filters.*;
/**
 * @author Javier Paniza
 */
public class DefaultYearFilter extends BaseContextFilter { // 1
 public Object filter(Object o) throws FilterException {
 if (o == null) {
 return new Object [] { getDefaultYear() }; // 2
 }
 if (o instanceof Object []) {
 List c = new ArrayList(Arrays.asList((Object []) o));
 c.add(0, getDefaultYear()); // 2
 return c.toArray();
 }
 else {
 return new Object [] { getDefaultYear(), o }; // 2
 }
 }
 private Integer getDefaultYear() throws FilterException {
 try {
 return getInteger("xavatest_defaultYear"); // 3
 }
 catch (Exception ex) {
 ex.printStackTrace();
 throw new FilterException(
 "Impossible to obtain default year associated with the session");
 }
 }
}
This filter extends BaseContextFilter, this allow you to access to the session objects of OpenXava. You can see how it uses a method getDefaultYear() (2) that call to getInteger() (3) which (as getString(), getLong() or the more generic get()) that allows you to access to value of the session object xavatest_defaultYear. This object is defined in controllers.xml this way:
<object name="xavatest_defaultYear" class="java.lang.Integer" value="1999"/>
The actions can modify it and its life is the user session life but it's private for each module. This issue is treated in more detail in controllers chapter.
This is a good technique for data shown in list mode to depend on the user or the configuration that he has chosen.
Also it's possible to access environment variables inside a filter (new in v2.0) of type BaseContextFilter, using getEnvironment() method, just in this way:
new Integer(getEnvironment().getValue("XAVATEST_DEFAULT_YEAR"));
For learning more about environment variables see the controllers chapter.

Partial select (new in v5.6)

In baseCondition you can write the select statement from the FROM clause, to do that just start the condition with from using SQL syntax:
<tab name="FromAlaska">
    <base-condition>
        from XAVATEST.CUSTOMER
        inner join XAVATEST.CUSTOMER_STATE states1_
            on XAVATEST.CUSTOMER.NUMBER=states1_.CUSTOMER
        inner join XAVATEST.STATE state2_
            on states1_.STATE=state2_.ID
        inner join XAVATEST.STATE T_address_state
            on XAVATEST.CUSTOMER.STATE=T_address_state.ID
        where state2_.ID='AK'
    </base-condition>
</tab>
This is better option than using the complete select because the list of properties is generated by OpenXava, so the user can customize the list while the developer still has the option of creating sophisticated queries.

Pure SQL select

You can write the complete select statement to obtain the tab data:
<tab name="CompleteSelect">
 <properties>number, description, family</properties>
 <base-condition>
 select ${number}, ${description}, XAVATEST@separator@FAMILY.DESCRIPTION
 from XAVATEST@separator@SUBFAMILY, XAVATEST@separator@FAMILY
 where XAVATEST@separator@SUBFAMILY.FAMILY =
 XAVATEST@separator@FAMILY.NUMBER
 </base-condition>
</tab>
Use it only in extreme cases. Normally it is not necessary, and if you use this technique the user cannot customize his list.

Default order

Finally, setting a default order is very easy:
<tab name="Simple">
 <properties>year, number, date</properties>
 <default-order>${year} desc, ${number} desc</default-order>
</tab>
This specified the initial order and the user can choose any other order by clicking in the heading of a column.

Default values for tabs at application level (new in v4m4)

This feature works for XML Component just in the same way that for JPA entities.

Column summation (new in v4.1)

To show the sum of all the value of a column at the bottom of the list you only have to add the + symbol to the property name, as following:
<tab >
    <properties>year, number, description, amount+</properties>
</tab>
In this case the sum of the amount column will be shown just as in the next figure:
tab_en030.jpg
The summation is only allowed for not calculated numeric properties.

Choosing an editor (new in v4.6)

An editor is the actual code (usually a JSP) that displays the list to the user. By default, the editor OpenXava uses for displaying tabular data is a list with pagination, filtering, ordering and search, but you can specify your own editor to display a concrete tab using the atribute editor in <tab/>.
For example, if you have a list of a Customer entities and you want to display it using a custom user interface, such as a row of cards, you can do it in this way:
<tab name="Cards" editor="CustomerCardList">
    <properties>number, name, type, address.city, address.state.name</properties>
</tab>
In this case the CustomerCardList editor will be used for displaying/editing the tab data, instead of the default one. You must define your CustomerCardList editor in the xava/editors.xml file of your project:
<editor name="CustomerCardList" url="customerCardListEditor.jsp"/>
Also you have to write the JSP code for your editor in customerCardListEditor.jsp.
This feature is for changing the editor for a concrete tab in a concrete entity. If you want to change the editor for all tabs of a certain entity type at application level then it's better to configure it using xava/editors.xml file.
Learn more on Editors for tabs section of chapter 9.

Several presentation formats using editors (new in v5.7)

The same data can be displayed with different presentation formats, for example, using a list, charts, cards, etc. The user can choose the format using the buttons on the right of top button bar:
tab050.png
The available formats are all the editors assigned to tab (using <for-tabs/>) in default-editors.xml or editors.xml. However, you can change the editors available for a specific tab with the editors attribute (new in v5.7) of <@<tab/> in your XML component. For example, if you write a <tab/> like this:
<tab name="WithCards" editors="List, Charts, CustomerCardList">
    <properties>number, name, type, address.city, address.state.name</properties>
</tab>
This tab will have List and Charts formats, that are standard, and a custom format, CustomerCardList. CustomerCardList is a custom editor defined in editors.xml.
To know how to define the editors for tabs, read the customization documentation.

Removing the Charts from list mode (new in v5.7)

<tab editors=/> also allows you to remove the Charts (and any other list format) from list mode, in this way:
<tab name="OnlyList" editors="List">
    <properties>number, name, type, address.city, address.state.name</properties>
</tab>
Thus you can get a module without charts, just the plain original OpenXava list. Given that there are only one editor, no button for selecting format is shown.
The difference between editor and editors, is that with editor we indicate the editor for the default format, while with editors we specify all the available formats.