Implicit Collections Processing
Explicit collections processing takes place by using the
ForEach and
MultiForEach tags. However, use of the tags can clutter the text box used for each
cell.
If JETT detects that an Expression contains operations on a Collection,
then it processes an implicit MultiForEach tag.
By default, implicit collections processing occurs on the entire row where the
collection or collections are found.
In this example, "employees" is a List of Employees. The List doesn't have the
properties "lastName", "firstName", "salary", and "manager" (methods
getLastName(), getFirstName(), getSalary(), and
getManager()). The implicit collections processing gets these properties
from each item of the "employees" list.
Employee |
Salary |
Manager |
${employees.lastName}, ${employees.firstName} |
${employees.salary} |
<jt:if test="${employees.getManager() != null}" then="${employees.manager.lastName}, ${employees.manager.firstName}"/> |
...gets transformed into...
Employee |
Salary |
Manager |
Stack, Robert |
$1000.00 |
|
Queue, Suzie |
$900.00 |
Stack, Robert |
Fudd, Elmer |
$800.00 |
Stack, Robert |
Bunny, Bugs |
$1500.00 |
|
Changing Behavior with Metadata
To change the default behavior of implicit collections processing, include
metadata at the end of an Expression that contains a reference to a
Collection. Metadata may influence the affected block of cells, either restricting the
affected columns, including additional rows, or both. To include metadata, append the
string "?@" plus key/value pairs to the end of the Expression, separated by semicolons.
Metadata Keys
- left: int Optional. Specify exactly how many cells to the
left of the current cell to include in implicit collections processing, defaulting
to zero.
- right: int Optional. Specify exactly how many cells to the
right of the current cell to include in implicit collections processing, defaulting
to zero.
- If neither "left" nor "right" is present, then JETT will include the entire row
of data for implicit collections processing.
- extraRows: int Optional. Specify how many extra rows are to
be included in the block for implicit collections processing below the current row,
defaulting to zero.
- copyRight: Boolean Optional. If true, then the block will be
copied to the right, instead of downward. Default: false (downward). This acts
just like the "copyRight" attribute of looping
tags.
- fixed: Boolean Optional. If true, then the content outside of
the block will not be shifted out of the way to make room for additional data.
Default: false (shifting will occur). This acts just like the "fixed" attribute of
looping tags.
- pastEndAction: String Optional. Determines what happens to
Cells that reference Collections that are exhausted and beyond iteration. This
acts just like the "pastEndAction" attribute of
looping tags. Here are the possible values:
- clear This works just like the "elseAction" attribute of the
if tag: remove the contents of the cells.
This is the default.
- remove This works just like the "elseAction" attribute of the
if tag: remove the cells, including cell contents,
formatting, borders, and merged regions.
- replaceExpr Don't delete the contents of the entire cell. Replace
any expressions that reference collections that have been exhausted with the
result of evaluating the replaceValue attribute.
- replaceExpr: String Optional. If the pastEndAction
is replaceExpr, then all expressions that reference collections that have
been exhausted are replaced with this value. This is ignored if
pastEndAction is not replaceExpr. Default: an empty
string. This acts just like the "replaceExpr" attribute of
looping tags.
- groupDir: String Optional. Create an Excel Group (Outline)
on the resultant rows or columns. This acts just like the "groupDir" attribute of
looping tags. Here are the possible values:
- rows Create an Excel Group (Outline) out of the resultant
rows.
- cols Create an Excel Group (Outline) out of the resultant
columns.
- none Do not create an Excel Group (Outline). This is the default.
- collapse: boolean Optional. This works just like the
"collapse" attribute of looping tags: This
determines whether the Excel Group (Outline) created is in a collapsed state. The
default is false (not collapsed).
- indexVar: int Optional. Expose a zero-based "looping"
variable name in the beans map. This acts just like the "indexVar" attribute of
the forEach tag and of the
multiForEach tag.
- limit: int Optional. Limit the number of collection items
displayed to this number, for all collections found. This acts just like the
"limit" attribute of the forEach tag and of the
multiForEach tag.
- onProcessed: TagListener Optional. Specify a TagListener or a
fully-qualified Java class name so that a TagListener will be called
when processing is complete. This acts just like the "onProcessed" attribute of
all built-in tags.
- onLoopProcessed: TagLoopListener Optional. Specify a
TagLoopListener or a fully-qualified Java class name so that a
TagLoopListener will be called each time a loop iteration has been
processed. This acts just like the "onLoopProcessed" attribute of
looping tags.
- varStatus: String Optional. Expose a variable in the beans map that
contains information about the current loop iteration -- the 0-based iteration
index, whether it's the first iteration, and whether it's the last iteration.
This acts just like the "varStatus" attribute of
looping tags.
Once JETT has determined the desired block of cells, it will scan the entire block
for any references to any Collections in any Expression. Then, it will process an
implicit multiForEach tag on the entire block.
In this example, notice how "Company: Whatsit" is not copied with the rest of the
block.
Company: Whatsit |
First Name: |
${employees.firstName}?@extraRows=1;left=1;right=2 |
Last Name: |
${employees.lastName} |
|
Salary: |
${employees.salary} |
Manager: |
<jt:if test="${employees.getManager() != null}" then="${employees.managerlastName}, ${emmployees.manager.firstName}"/> |
...gets transformed into...
Company: Whatsit |
First Name: |
Robert |
Last Name: |
Stack |
|
Salary: |
$1000.00 |
Manager: |
|
|
First Name: |
Suzie |
Last Name: |
Queue |
|
Salary: |
$900.00 |
Manager: |
Stack, Robert |
|
First Name: |
Elmer |
Last Name: |
Fudd |
|
Salary: |
$800.00 |
Manager: |
Stack, Robert |
|
First Name: |
Bugs |
Last Name: |
Bunny |
|
Salary: |
$1500.00 |
Manager: |
|
Turn Off Implicit Collections Processing
To access Collection items explicitly in an Expression, it is desirable to turn off
implicit collections processing on a collection name basis. To do this, use the
following method available in the ExcelTransformer class:
public void turnOffImplicitCollectionProcessing(String collName);
In this example, the following code is run before the transform method:
transformer.turnOffImplicitCollectionProcessing("employees");
The highest ranked employee is: |
${employees.get(0).fullName} |
... gets transformed into...
The highest ranked employee is: |
Bugs Bunny |
If implicit collections processing was allowed to occur on the "employees"
collection, then four rows would be generated, one for each employee, each attempting
to call "get(0)" directly on the Employee object, resulting in an error.
However, certain properties and method calls on Collections are recognized to be
actual Collections operations, so if any of the following operations are performed on a
Collection, then implicit collections processing does not occur:
- capacity
- contains
- element
- equals
- get
- hashCode
- indexOf
- isEmpty
- lastIndexOf
- size
- toString