atg.service.util
Class TableInfo

java.lang.Object
  extended by atg.nucleus.logging.VariableArgumentApplicationLoggingImpl
      extended by atg.nucleus.GenericService
          extended by atg.service.util.TableInfo
All Implemented Interfaces:
atg.naming.AbsoluteNameable, NameContextBindingListener, NameContextElement, atg.naming.NameContextParentable, NameResolver, AdminableService, atg.nucleus.Configured, ApplicationLogging, atg.nucleus.logging.ApplicationLoggingSender, atg.nucleus.logging.TraceApplicationLogging, VariableArgumentApplicationLogging, ComponentNameResolver, Service, ServiceListener, java.util.EventListener

public class TableInfo
extends GenericService

This class maintains a collection of information useful when building sortable tables in JHTML where each column in the table displays some property of an object, and where the user interface wishes to allow the user to sort the table on one or more columns.

It represents one or more table columns and the sort direction associated with each column, which may be "ascending", "descending", or "none".

In addition to values of "ascending", "descending", or "none", callers can apply the values "toggle" (which switches between ascending and descending for a given property), "cycle_up" (which switches between none, ascending, and descending, in that order), and "cycle_down" (which switches between none, descending, and ascending, in that order).

Three additional values allow fine tuning the bahavior of sortable tables: "toggle_if_primary" toggles the sort direction if the property in question is currently the primary sort key, otherwise it sets the direction to the default value (normally "ascending") and makes it the primary sort key. The value "cycle_up_if_primary" behaves similarly, cycling the sort direction upward if the property is the primary sort key or setting it to the default value otherwise, while "cycle_down_if_primary" does the same thing cycling downward.

This makes it easy to build tables that have the common behavior where clicking on a column heading once makes that column the primary sort key with an ascending sort, clicking a second time reverses the order and sorts by descending values, and clicking a third time removes that column from the sort criteria.

Finally, this class includes convenience methods that generate strings suitable for use with the sortProperties parameter of droplets such as ForEach.

Defining Table Columns

You define the list of column names and the corresponding sort properties for a table by specifying a value for the TableInfo's columns property. The value of columns is a Properties object where each key is a column name, and the corresponding value is a property expression to use when displaying and sorting on that column in a ForEach-style droplet.

For example, a table displaying user information might configure the TableColumns by saying:


 columns=\
    First Name=firstName,\
    Last Name=lastName,\
    Login=login,\
    City=mailingAddress.city
 

Note that subproperty expressions can be used in the table info. TableColumns does not make any attempt to interpret these property names, but simply uses them to construct sortProperties strings that may be passed to droplets like ForEach that implement sorting.

Separating the Display and Sort Properties

In most cases the property you wish to display in a table column is the same as the property on which you wish to sort that column, but in exceptional cases this may not be true.

In cases where the display property and the sort property are different you can list both property names, separated by a ; character, on the right hand side of a column specifier. For example, if the display property for a column is named "displayName" but you prefer to sort that column on a property named "sortableValue", you could specify the column settings as:


 columns=\
    Widget=displayName ; sortableValue,\
    Price=listPrice
 

You can include optional whitespace before and after the ; to improve the readability of properties files.

Internationalization

Applications that support multiple locales will generally want to localize the column headings displayed in their tables. The optional columnHeadings property allows you to map column names to locale-specific display headings. columnHeadings is a dictionary whose keys are locale-specific variants of a column name, and whose values are the column headers to use for the corresponding locale.

TableInfo computes the headings for each column as follows:

If columnHeadings has not been set, the column's heading is the same as its name. This would typically be the case in single-locale applications.

Otherwise, TableInfo first tries to determine the current locale using the following rules:

Once a locale is selected, TableInfo examines the keys in the columnHeadings dictionary looking for a locale-specific variant of the column name. It applies the same logic as java.util.ResourceBundle when looking for resource bundles. For example, if the column's name is "price" and the locale is "fr_FR", TableInfo will search columnHeadings for keys named price_fr_FR, price_fr, and price, in that order. The value corresponding to the first matching key becomes the column's heading. If no matching key is found, the column's name is used as its heading.

Example:

This example demonstrates how to localize column headings of a two-column table for the English and French languages:


 # Define the basic table layout, using symbolic names for each column
 
 columns=\
    name=book.displayName,\
    price=book.listPrice

 # Now create localized column headings for each column

 columnHeadings=\
    name=Title,\
    name_fr=Titre,\
    price=List Price,\
    price_fr=Prix Courant

 

(The example ignores the country and variant parts of the French locale, but country- and variant-specific column headings can be included by using entries like "name_fr_FR=Prix", etc.)

To support additional locales, all you need to do is add their column headings to the columnHeadings list.

Of course, you can also localize column headings without using the columnHeadings property, simply by defining and configuring multiple instances of TableInfo, one for each locale. Your JHTML or JSP pages can then refer explicitly to the appropriate instance, based on the language of the page or the user's locale. For example, an English-language page might say

to import a version of the table with English column names, while a German-language page might say to import a version of the table with German column names instead. Both pages could then refer to the item table's TableInfo component as bean:ItemTable, but each page would use its own locale-specific version of the component.

Using the single-component approach and setting columnHeadings allows Dynamo to automatically search for the best available match to the user's preferred language and locale, but some people may find it easier to manage a component per language and to forego automatic selection of the column headings. Which approach you take it largely a matter of personal preference.


Nested Class Summary
 class TableInfo.Column
          Inner class that represents all the information about a table column -- its name, column heading, the corresponding sort property, the current sort direction, and the position of this column's property relative to others when doing multi-column sorting.
 
Field Summary
static java.lang.String ASCENDING
           
static java.lang.String CLASS_VERSION
           
static java.lang.String CYCLE_DOWN
           
static java.lang.String CYCLE_DOWN_IF_PRIMARY
           
static java.lang.String CYCLE_UP
           
static java.lang.String CYCLE_UP_IF_PRIMARY
           
static java.lang.String DESCENDING
           
protected  TableInfo.Column[] mColumns
          mColumns is a list of Column objects in the order they were defined by tableInfo
protected  java.lang.String mPrimarySortString
           
protected  java.util.LinkedList mSortColumns
          mSortColumns is list that contains the same Column objects as mColumns, but listed in the order in which the columns are sorted.
protected  java.lang.String mSortString
           
static java.lang.String NONE
           
static java.lang.String TOGGLE
           
static java.lang.String TOGGLE_IF_PRIMARY
           
 
Fields inherited from class atg.nucleus.GenericService
SERVICE_INFO_KEY
 
Fields inherited from interface atg.nucleus.logging.TraceApplicationLogging
DEFAULT_LOG_TRACE_STATUS
 
Fields inherited from interface atg.nucleus.logging.ApplicationLogging
DEFAULT_LOG_DEBUG_STATUS, DEFAULT_LOG_ERROR_STATUS, DEFAULT_LOG_INFO_STATUS, DEFAULT_LOG_WARNING_STATUS
 
Constructor Summary
TableInfo()
          Default constructor.
 
Method Summary
protected  void applyDirection(TableInfo.Column pColumn, java.lang.String pDirectionType)
          Set the sort direction for a property in the list of sort criteria.
protected  void clearSortStrings()
          Clear the cached sort strings returned by getPrimarySortString and getSortString.
protected  java.lang.String columnHeading(java.lang.String pName, java.util.Locale pLocale)
          Get the column heading to use for a column with the specified name, to be displayed in the specified locale.
protected  int cycleDown(int pDirection)
          Return the direction code that results from cycling pDirection from none -> descending -> ascending -> none.
protected  int cycleUp(int pDirection)
          Return the direction code that results from cycling pDirection from none -> ascending -> descending -> none.
 void doStartService()
          Build the table column descriptors from the current table information and column headings.
 java.util.Properties getColumnHeadings()
          Get the mapping from column names in the columns dictionary to localized display names for each column.
 java.lang.String getDefaultDirection()
          Set the default sort direction for items when a sort direction is not specified explicitly.
 java.lang.String getDefaultPrimarySortString()
          Get the default primary sort string for this table.
 java.lang.String getDefaultSortString()
          Get the default sort string for this table.
protected  java.util.Locale getMessageLocale()
          Get the locale to use when looking up display names for each column.
protected  int getNextSortDirection(TableInfo.Column pColumn, java.lang.String pDirectionType)
          Return the direction that results from applying the requested directionType transformation (ascending, descending, none, toggle, cycle_up, cycle_down) to the specified Column.
 TableInfo.Column getPrimarySortColumn()
          Return the primary sort column for the table, or null if no columns are being sorted.
 java.lang.String getPrimarySortString()
          Get a string suitable for use with the sortProperties parameter of droplets like ForEach, representing the sort direction and property name for the first entry in the list of sort criteria.
 java.util.LinkedList getSortColumns()
          Return the list of columns that are being sorted.
 java.lang.String getSortString()
          Get a string suitable for use with the sortProperties parameter of droplets like ForEach, representing the sort direction and property name for all entries in the list of sort criteria.
 TableInfo.Column[] getTableColumns()
          Return the array of objects that represent the columns in the table.
 java.lang.String getUserLocale()
          Get the locale used to retreive user-visible error messages, if one has been set explicitly.
 boolean isPrimarySortColumn(TableInfo.Column pColumn)
          Return true if the specified Column is currently the primary sort column.
protected  java.lang.String makePrimarySortString()
          Create a string suitable for use with the sortProperties parameter of droplets like ForEach, representing the sort direction and property name for the first entry in the list of sort criteria.
protected  java.lang.String makeSortString()
          Create a string suitable for use with the sortProperties parameter of droplets like ForEach, representing the sort direction and property name for all entries in the list of sort criteria.
 void reset()
          Clear the entire list of sort criteria.
 void setColumnHeadings(java.util.Properties pColumnHeadings)
          Define a mapping from column names in the columns dictionary to localized display names for each column.
 void setColumns(atg.core.util.OrderedProperties pTableInfo)
          Set the list of column names and the corresponding sort properties for a table.
 void setDefaultDirection(java.lang.String pDefaultDirection)
          Set the default sort direction for items when a sort direction is not specified explicitly.
 void setDefaultSortString(java.lang.String pDefaultSortString)
          Set a default sort string for this table.
 void setPrimarySortColumn(TableInfo.Column pColumn)
          Make the specified column become the primary sort column.
 void setReset(java.lang.String pIgnored)
          Allow reset to be called from JHTML using
<setvalue bean="TableColumns.reset">
 void setUserLocale(java.lang.String pUserLocale)
          Set the locale used to retreive user-visible error messages.
protected  int toggle(int pDirection)
          Return the direction code that results from toggling pDirection.
protected  boolean updatesPrimarySortColumn(java.lang.String pDirectionType)
          Return true if the specified direction type is one of the transition types that may update the primary sort column (i.e., is one of toggle_if_primary, cycle_up_if_primary, or cycle_down_if_primary)
 
Methods inherited from class atg.nucleus.GenericService
addLogListener, createAdminServlet, doStopService, getAbsoluteName, getAdminServlet, getAdminServletOutputStreamEncoding, getLoggingForVlogging, getLogListenerCount, getLogListeners, getName, getNameContext, getNucleus, getRoot, getServiceConfiguration, getServiceInfo, isAdminServletUseServletOutputStream, isLoggingDebug, isLoggingError, isLoggingInfo, isLoggingTrace, isLoggingWarning, isRunning, logDebug, logDebug, logDebug, logError, logError, logError, logInfo, logInfo, logInfo, logTrace, logTrace, logTrace, logWarning, logWarning, logWarning, nameContextElementBound, nameContextElementUnbound, removeLogListener, reResolveThis, resolveName, resolveName, resolveName, resolveName, sendLogEvent, setAdminServletOutputStreamEncoding, setAdminServletUseServletOutputStream, setLoggingDebug, setLoggingError, setLoggingInfo, setLoggingTrace, setLoggingWarning, setNucleus, setServiceInfo, startService, stopService
 
Methods inherited from class atg.nucleus.logging.VariableArgumentApplicationLoggingImpl
vlogDebug, vlogDebug, vlogDebug, vlogDebug, vlogDebugTrace, vlogError, vlogError, vlogError, vlogError, vlogInfo, vlogInfo, vlogInfo, vlogInfo, vlogTrace, vlogTrace, vlogTrace, vlogTrace, vlogWarning, vlogWarning, vlogWarning, vlogWarning
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

CLASS_VERSION

public static java.lang.String CLASS_VERSION

mColumns

protected TableInfo.Column[] mColumns
mColumns is a list of Column objects in the order they were defined by tableInfo


mSortColumns

protected java.util.LinkedList mSortColumns
mSortColumns is list that contains the same Column objects as mColumns, but listed in the order in which the columns are sorted. It is only used internally, to help maintain the index properties of the Column objects as different columns become the primary sort key and others are shifted downward on the list, and to build the sortProperties strings for use with ForEach droplets and their kin.


ASCENDING

public static final java.lang.String ASCENDING
See Also:
Constant Field Values

DESCENDING

public static final java.lang.String DESCENDING
See Also:
Constant Field Values

NONE

public static final java.lang.String NONE
See Also:
Constant Field Values

CYCLE_UP

public static final java.lang.String CYCLE_UP
See Also:
Constant Field Values

CYCLE_DOWN

public static final java.lang.String CYCLE_DOWN
See Also:
Constant Field Values

TOGGLE

public static final java.lang.String TOGGLE
See Also:
Constant Field Values

CYCLE_UP_IF_PRIMARY

public static final java.lang.String CYCLE_UP_IF_PRIMARY
See Also:
Constant Field Values

CYCLE_DOWN_IF_PRIMARY

public static final java.lang.String CYCLE_DOWN_IF_PRIMARY
See Also:
Constant Field Values

TOGGLE_IF_PRIMARY

public static final java.lang.String TOGGLE_IF_PRIMARY
See Also:
Constant Field Values

mPrimarySortString

protected java.lang.String mPrimarySortString

mSortString

protected java.lang.String mSortString
Constructor Detail

TableInfo

public TableInfo()
Default constructor.

Method Detail

setColumns

public void setColumns(atg.core.util.OrderedProperties pTableInfo)
Set the list of column names and the corresponding sort properties for a table.


setColumnHeadings

public void setColumnHeadings(java.util.Properties pColumnHeadings)
Define a mapping from column names in the columns dictionary to localized display names for each column. This feature is used when creating TableInfo objects that support multiple locales.


getColumnHeadings

public java.util.Properties getColumnHeadings()
Get the mapping from column names in the columns dictionary to localized display names for each column.


doStartService

public void doStartService()
                    throws ServiceException
Build the table column descriptors from the current table information and column headings.

Overrides:
doStartService in class GenericService
Throws:
ServiceException - if the Service had a problem starting up

getTableColumns

public TableInfo.Column[] getTableColumns()
Return the array of objects that represent the columns in the table. A column provides the ability to retrieve its name, its sort property, its current sort direction (which will be one of "ascending", "descending", or "none"), its index relative to other columns being sorted, etc.

The columns are returned in the same order they were defined in tableInfo.


getSortColumns

public java.util.LinkedList getSortColumns()
Return the list of columns that are being sorted.


setDefaultDirection

public void setDefaultDirection(java.lang.String pDefaultDirection)
                         throws java.lang.IllegalArgumentException
Set the default sort direction for items when a sort direction is not specified explicitly. The value must be either "ascending" or "descending".

Throws:
java.lang.IllegalArgumentException - if pDefaultDirection is not either "ascending" or "descending"

getDefaultDirection

public java.lang.String getDefaultDirection()
Set the default sort direction for items when a sort direction is not specified explicitly. The value will be either "ascending" or "descending".


setDefaultSortString

public void setDefaultSortString(java.lang.String pDefaultSortString)
Set a default sort string for this table. If no explicit sort directions have been set for the table, then calling getSortString will return defaultSortString and calling getPrimarySortString will return the first comma-separated token from defaultSortString.

Examples:

If defaultSortString is set to the string "+name", calling getSortString will return "+name", as will calling getPrimarySortString.

If defaultSortString is set to the string "+name,-price", calling getSortString will return "+name,-price", but calling getPrimarySortString will return only "+name".

The value of defaultSortString does not affect either the sortColumns property or the sort direction of any column. In the absence of explicit sort directions, calling getSortColumns() will return an empty list, and asking for the sort direction of any column will return none, even if that column appears in the default sort string.


getDefaultSortString

public java.lang.String getDefaultSortString()
Get the default sort string for this table.

See Also:
setDefaultSortString

getDefaultPrimarySortString

public java.lang.String getDefaultPrimarySortString()
Get the default primary sort string for this table. If the value of defaultSortString is null or the empty string, or consists of a single token, then the default primary sort string will be the same as the default sort string. If the default sort string consists of multiple comma-separated tokens, the default primary sort string will be the first token in the list.

See Also:
setDefaultSortString

getPrimarySortString

public java.lang.String getPrimarySortString()
Get a string suitable for use with the sortProperties parameter of droplets like ForEach, representing the sort direction and property name for the first entry in the list of sort criteria. For example, if the sort criteria consist of "date descending, author ascending", this method will return the string "-date".


makePrimarySortString

protected java.lang.String makePrimarySortString()
Create a string suitable for use with the sortProperties parameter of droplets like ForEach, representing the sort direction and property name for the first entry in the list of sort criteria.


getSortString

public java.lang.String getSortString()
Get a string suitable for use with the sortProperties parameter of droplets like ForEach, representing the sort direction and property name for all entries in the list of sort criteria. For example, if if the sort criteria consist of "date descending, author ascending", this method will return the string "-date,+author".


makeSortString

protected java.lang.String makeSortString()
Create a string suitable for use with the sortProperties parameter of droplets like ForEach, representing the sort direction and property name for all entries in the list of sort criteria.


clearSortStrings

protected void clearSortStrings()
Clear the cached sort strings returned by getPrimarySortString and getSortString.


reset

public void reset()
Clear the entire list of sort criteria.


setReset

public void setReset(java.lang.String pIgnored)
Allow reset to be called from JHTML using
<setvalue bean="TableColumns.reset">


applyDirection

protected void applyDirection(TableInfo.Column pColumn,
                              java.lang.String pDirectionType)
Set the sort direction for a property in the list of sort criteria. This method may reorder the list if pDirectionType is one of the transition types ("toggle_if_primary", "cycle_up_if_primary", or "cycle_down_if_primary"), and will also recompute the relative indices for all column.

Parameters:
pColumn - The column entry being modified
pDirectionType - The desired modification to the sort type, which may be any of the following strings: ascending, descending, none, toggle, cycle_up, cycle_down, toggle_if_primary, cycle_up_if_primary, or cycle_down_if_primary.

getNextSortDirection

protected int getNextSortDirection(TableInfo.Column pColumn,
                                   java.lang.String pDirectionType)
Return the direction that results from applying the requested directionType transformation (ascending, descending, none, toggle, cycle_up, cycle_down) to the specified Column.


toggle

protected int toggle(int pDirection)
Return the direction code that results from toggling pDirection.


cycleUp

protected int cycleUp(int pDirection)
Return the direction code that results from cycling pDirection from none -> ascending -> descending -> none.


cycleDown

protected int cycleDown(int pDirection)
Return the direction code that results from cycling pDirection from none -> descending -> ascending -> none.


updatesPrimarySortColumn

protected boolean updatesPrimarySortColumn(java.lang.String pDirectionType)
Return true if the specified direction type is one of the transition types that may update the primary sort column (i.e., is one of toggle_if_primary, cycle_up_if_primary, or cycle_down_if_primary)


setPrimarySortColumn

public void setPrimarySortColumn(TableInfo.Column pColumn)
Make the specified column become the primary sort column.


getPrimarySortColumn

public TableInfo.Column getPrimarySortColumn()
Return the primary sort column for the table, or null if no columns are being sorted.


isPrimarySortColumn

public boolean isPrimarySortColumn(TableInfo.Column pColumn)
Return true if the specified Column is currently the primary sort column.


setUserLocale

public void setUserLocale(java.lang.String pUserLocale)
Set the locale used to retreive user-visible error messages. If not specified, the default behavior is to use the request locale if possible, or the server's default locale if no request locale has been specified for the current request.


getUserLocale

public java.lang.String getUserLocale()
Get the locale used to retreive user-visible error messages, if one has been set explicitly. If this method returns null, the default behavior is to use the request locale if present, or the server's default locale if not.


getMessageLocale

protected java.util.Locale getMessageLocale()
Get the locale to use when looking up display names for each column. Returns the locale specified by the userLocale property if set, otherwise returns the request locale from the current Dynamo servlet request if a request exists and its locale has been set, otherwise returns the default server locale.

Subclasses may override this method to change the strategy for choosing a locale.


columnHeading

protected java.lang.String columnHeading(java.lang.String pName,
                                         java.util.Locale pLocale)
Get the column heading to use for a column with the specified name, to be displayed in the specified locale. If the locale is null, or no locale-specific heading has been specified, the name is returned.