Intégration

To use BlueIron in SAINET, when declaring a new GridAdvancedFormater, set its type to ‘blueiron’.

<GridAdvancedFormater ID="CHAECH_PRES1_FORMATTER" type="blueiron">
  ...
</GridAdvancedFormater>

Besides the BlueIron descriptor itself contained in the formatter, SAINET supports also other tags to enhance the rendering (see below).

<GridAdvancedFormater ID="CHAECH_PRES1_FORMATTER" type="blueiron" [multithreading="true"]>
  <init>...</init>
  <columns>...</column>
  <header>...</header>
  <footer>...</footer>
  <inputs>...</inputs>
  <blueiron>...</blueiron>
  <handles>...</handles>
</GridAdvancedFormater>

The multithread attribute allows BlueIron to read the input and process it with multiple threads (false by default). This is possible if there is no database access during the processing.

Init

The tag is optional and can contain mixed content in JavaScript. This script will be invoked before data retrieval from the database.

In this script, all the datafield values of the HeaderDescriptor will be injected as String. Moreover, the following variables will be declared:

Variable Description
userSession The UserSession.
grid The GridDescriptor that is currently used.
selector The Selector of the GridDescriptor for a quick usage.
options The HeaderDescriptor.

With this tag, it is possible to dynamically add constraint to the data retrieved from the database (see CHA72):

<init>
    selector.addAndWhere("$CHAECH.DATECR_PK <= '" + CHA_LAST_DATE +"'");
    if(CHA_SOLDE_PREC == '0') { selector.addAndWhere("$CHAECH.DATECR_PK >= '" + CHA_FIRST_DATE +"'"); }
</init>

Columns

It is possible to create new columns in BlueIron, but since they won’t be attached to any known datafield in SAINET, it is needed to do this mapping manually. This is done with the tag.

This tag can contain one or many tag with the following attributes:

Name Type Description
id* String ID of the new column created by BlueIron. This attribute is mandatory.
format String Defines the format of the output column and will also impact how the data will be displayed.
width Integer or ‘Auto’ Defines the size of the column.
datafieldId String Defines the datafield ID to map to. It will be used as fallback if the format or label is not defined.
label String Defines an i18n String for the label of the column.
enumName String Defines the EnumName.
displayCode String TextOnly,CodeOnly or CodeAndText. Only for enums.

Here is an exemple used in CHA72:

<columns>
  <column id="DATE_DEBUT_PERIODE" format="Date" width="0" />
  <column id="DATE_FIN_PERIODE" format="Date" width="0" />
  <column id="DATE_ECRITURE_LBL" format="String" width="9" label="FR={Date} DE={Datum}" />
  <column id="DATE_ECRITURE_LBL" format="String" width="9" label="FR={Date} DE={Datum}" />
  <column id="DISPLAY" format="Boolean" width="0" label="Affiche" />
  <column id="QUANTITE" format="Financial" width="10" label="FR={Quantité} DE={Menge}" />
  <column id="DEBIT" format="Financial" width="10" label="FR={Débit} DE={Debit}" />
  <column id="CREDIT" format="Financial" width="10" label="FR={Crédit} DE={Kredit}" />
  <column id="SOLDE" format="Financial" width="10" label="FR={Solde} DE={Saldo}" />
  <column id="NB_ROWS" format="Integer" width="0" label="N" />
</columns>

This section allows to declare a header/footer that will be placed on the top/bottom of the list. The structure is a <table> but is independant of the list’s table, however it uses the list’s data for its content. Like a standard html table, one can declare one or more <tr> tags in which one or more <td> tags can be declared. The same number of <td> must be declared in each <tr> tag !

The <header> node supports the following attributes:

Name Description
macroId ID of a UNI93 macro. In this case, no <tr>/<td> nodes are expected.
withinTable Defines if the header/footer is embedded in <thread>/<tfoot> or is generated outside the whole <table>. When true, the header/footer will be displayed on all the pages when printing. This value is false by default.

Supported attributes are for <tr> and <td>:

Name Description
class A list of css classes spearated by spaces. Thoses classes has to be declared in UNI_GEN.
style A list of css styles spearated by semicolumns.
colspan Colspan of the cell (only for <td>).

The <td> can contain mixed content which is:

  • Simple text.
  • Internationalized text with the format FR={...} DE={...}.
  • Reference to a column id of the list with the format ${columnId}.

Here is an exemple (still the CHA72):

<header withinTable="true">
  <tr>
    <td style="width:75px">No Chantier</td>
    <td style="width:250px" class="grag">${NO_CHAN}</td>
    <td style="width:75px">Période du</td>
    <td style="width:250px" class="grag">${DATE_DEBUT_PERIODE}</td>
  </tr>
  <tr>
    <td>Désignation</td>
    <td class="grag">${NOM_CHAN}</td>
    <td>Période au</td>
    <td class="grag">${DATE_FIN_PERIODE}</td>
  </tr>
  <tr style="height:15px">
    <td />
    <td />
    <td />
    <td />
  </tr>
</header>

It is also possible to delegate the creation of the header/footer to a velocity macro (UNI93) with the following snippet:

<header macroId="HEADER_MACRO" />

And the corresponding macro in UNI93:

#macro(header_macro)
 #set($dossier = $VELOHLP.getEntity("ADRDOS.ID_PK", $ID))
 <table>
   <tr class="norg">
     <td>ID:</td>
     <td>$dossier.ID_PK</td>
   </tr>
   <tr class="norg">
     <td>Dossier:</td>
     <td>$dossier.DLABEL</td>
   </tr>
 </table>
#end
Info:

All the columns of the breaking row are directly available (for instance $ID above will point the the ID column).

In order to genrerate a break, a call to outputRow.breakHeader(boolean) is necessary. It will generate a page break before the outputRow and the latter will be used as source to fill the header. The boolean of the breakHeader method defines if the outputRow must be hidden or not.

It is also possible to use the methods outputRow.pageBreakBefore() or outputRow.pageBreakAfter() if the header/footer don’t need any data from the inner grid.

Inputs

It is possible to define extra grid-based inputs in this node to gather other data from the application. Those ids will then referencable in the BlueIron descriptor as source of step.

<inputs>
  <grid id="SAL04_N2" selector="FROM $SALEMP WHERE $SALEMP.ID_PK = '101'" />
  <grid id="SAL04_N22" gridViewId="SAL04_N2" />
  <grid id="SAL04_N3" taskId="SALV4" raw="true" />
</inputs>

All the defined grids will be sequentially filled by calling get[Raw]GridData before the BlueIron processing is actually done (hence, they will be filled even if not used).

Here are the attributes of the grid node:

Name Type Description
id* String ID of the input. If gridViewId is not defined, this has to be the ID of an existing GridView.
gridViewId String The GridView ID of the input. If not defined, this will be the id value.
taskId String The ID of the task to use to fille the GridView. If not defined, then the current task will be used.
raw Boolean Tells if the getGridData call to fill the GridView must be raw or not. false by default.
selector String Defines the full selector of the GridView (FROM $<table> WHERE ...).
predicate String Defines a single predicate that willbe ORed with all the values.

About the selector

There are some special values that can be put in the selector attribute.

In order to have the same selector as the main grid, use the value sameAsSource. It is needed that both the main grid and the extra input grid are based on the same table otherwise error will occur if some datafield don’t exist.

Since the main grid will be filled before all, it is possible to use some special constructs in the selector of the input grid by using ${<column_id>}. For instance, it is possible to define the following input grid:

<grid id="SAL04_N2" selector="FROM $SALEMP WHERE $SALEMP.ID_PK IN (${ID_PK})" />

In the example above, the value ${ID_PK} will be replaced by a SQL string containing all the values of the column ID_PK in the main grid, resulting in something like this: FROM $SALEMP WHERE $SALEMP.ID_PK IN ('100','101','200').

About the predicate

The predicate content can only have one single variable. Then the predicate will be repeated for every values in the corresponding column.

<grid id="SAL04_N2" predicate="$SALEMP.ID_PK LIKE '${ID_PK}%'" />

In the example above, the resulting selector will be FROM $SALEMP WHERE (($SALEMP.ID_PK LIKE '05%') OR ($SALEMP.ID_PK LIKE '06%')).

Note that, unlike the selector attribute, the variable value isn’t encapsulated in quotes. The whole predicate string will be then ANDed with any existing predicates in the grid selector.

BlueIron

This tag will contains the real BlueIron descriptor.

It is not necessary to declare any InputStep because a special GridInputStep based on the GridView will be created with the same ID. Hence the root step must simply declare its source with the ID of the GridView.

<GridView ID="CHAECH_PRES1">
  ...
</GridView>
<blueiron output="final">
    <step id="final" source="CHAECH_PRES1">
    ...
    </step>
</blueiron>

It is also possible to use the generic identifier grid as the source of the step. This alias will reference the main GridDescriptor.

Then you will be able to reference a column of the GridView by using its ID.

Handles

Handles are intended to be small JavaScripts that are being executed for each outputted row from BlueIron. The goal is to be able to completely customize the output of the list (for instance, setting backgroud color, font size, css style, …).

One or more handle can be defined by the tag handle with the possible following attribute:

Name Type Description
column String Column to be referenced by the cell variable. It is possible for multiple handles to point to the same column.

If the column is not specified in the handle, then there will be no variable available relative to the cell.

The variables below will be defined in the script’s context:

Name Type Description
row Row (BlueIron) The BlueIron row being currently outputted.
outputRow Row (SAINet) The SAINet row being currently outputted. This will be generally the variable you’re interested in.
column Column (BlueIron) The BlueIron column (only if the column attribute is set).
cell Cell (SAINet) The SAINet Cell (only if the column attribute is set).
value Object The value of the Cell (only if the column attribute is set).
rowLevel Integer The level of the row, as defined in BlueIron (see here).
rowIndex Integer The index of the row, as defined in BlueIron (see here).
rowTypeIndex Integer The type index of the row, as defined in BlueIron (see here).
isTitleRow Boolean True if the row is a title row.
isTotalRow Boolean True if the row is a total row.
isDataRow Boolean True if the row is a data row.
options Map Pointer to the options.

Here are the default handles that are applied:

Property defaultValue Description
defaultStyles true Applies the default styles ruptitn on title rows and ruptotn on total rows.
maxLevelDefaultStyles 3 Defines the maximum level to apply the styles (the n in ruptitn and ruptotn). Starts from zero.
removeZeroValues true If a numerical value is zero in the output cell, this value will be replaced by an empty cell.
maxLevelRemoveZeroValues -1 If removeZeroValues is true, defines the maximum level to apply the styles (see maxLevelDefaultStyles). Starts from zero.
styleIfGreaterThanZero [null] Style to apply on numerical values that are greater than zero. The style applies only on the cell.
styleIfLessThanZero [null] Style to apply on numerical values that are bigger than zero. The style applies only on the cell.
duplicateKeys [null] Defines a list of key columns to identify duplicates. Constains column IDs, separated by commas.
duplicateColumns [null] Defines a list of columns where the value should be hidden if the row is identified as duplicate by using the duplicateKeys columns. It is possible to use #asInput or #asOutput.
mandatoryColumns [null] Defines a list of columns which must contain a value, othwerise the row is removed.
lenientColumns [null] Defines a list of columns in which at least one of them must contain a value, otherwise the row is removed.
hideEmptyColumns [null] Defines a list of columns which will be hidden if there is no value in the column at all.
rawStyleOnTotalRows true Defines the ‘rawNumber’ style on all the cells of a TOTAL row. This is espcially to avoid having a ‘tick’ on a total row cell.
applyDefault true Applies all the default handles listed above.
looseColumnSearch false Allow a column to be inexistant when using the duplicateKeys,duplicateColumns,mandatoryColumns or leniantColumns attributes.

Here is an example of handles implementation in CHA72:

<handles applyDefault="false">
  <handle column="DATE_ECRITURE_LBL"><![CDATA[if(isTitleRow && rowLevel==0) { outputRow.breakHeader(true); }]]></handle>
  <handle column="DATE_ECRITURE_LBL"><![CDATA[if(isTitleRow) { outputRow.addStyle("ruptit"+(rowLevel+1)+"g"); }]]></handle>
  <handle column="DATE_ECRITURE_LBL"><![CDATA[if(isTotalRow && rowLevel>0) { outputRow.addStyle("ruptot"+(rowLevel+1)+"d"); cell.addStyle("ruptot"+(rowLevel+1)+"g"); }]]></handle>
  <handle column="DATE_ECRITURE_LBL"><![CDATA[if(isTotalRow && rowTypeIndex<=2 && rowLevel==0) { outputRow.addStyle("grad"); cell.addStyle("grag"); }]]></handle>
  <handle column="DATE_ECRITURE_LBL"><![CDATA[if(isTotalRow && rowTypeIndex==2 && rowLevel==0) { outputRow.addStyle("ruptot1d"); cell.addStyle("ruptot1g"); }]]></handle>
  <handle column="DATE_ECRITURE_LBL"><![CDATA[if(isTotalRow) { cell.setColspan(4); }]]></handle>
  <handle column="SOLDE"><![CDATA[if(value!=null && value<0) { cell.addStyle("TXT_F00"); }]]></handle>
  <handle column="QUANTITE"><![CDATA[if(value!=null && value<0) { cell.addStyle("TXT_F00"); }]]></handle>
</handles>

Extended functions

SAINet injects new Jexl functions that can be used in BlueIron are listed below. There are other native functions (such as parse) also described here.

Date helpers (namespace date)

Function Return Description
date:addMillis(date) Date Adds one millisecond to date. A new date instance is returned.
date:addSecond(date) Date Adds one second to date. A new date instance is returned.
date:addMinute(date) Date Adds one minute to date. A new date instance is returned.
date:addHour(date) Date Adds one hour to date. A new date instance is returned.
date:addDay(date) Date Adds one day to date. A new date instance is returned.
date:addMonth(date) Date Adds one month to date. A new date instance is returned.
date:addYear(date) Date Adds one year to date. A new date instance is returned.
Function Return Description
date:addMillis(date, nb) Date Adds nb milliseconds to date. A new date instance is returned.
date:addSecond(date, nb) Date Adds nb seconds to date. A new date instance is returned.
date:addMinute(date, nb) Date Adds nb minutes to date. A new date instance is returned.
date:addHour(date, nb) Date Adds nb hours to date. A new date instance is returned.
date:addDay(date, nb) Date Adds nb days to date. A new date instance is returned.
date:addMonth(date, nb) Date Adds nb months to date. A new date instance is returned.
date:addYear(date, nb) Date Adds nb years to date. A new date instance is returned.
Function Return Description
date:setTime(date, hourOfDay, minute, second) Date Returns a new date with hourOfDay,minute and second (millis will be zero). The other values are the same as date.
date:setTime(date, hourOfDay, minute, second, millis) Date Returns a new date with hourOfDay,minute,second and millis. The other values are the same as date.
date:setDate(date, dayOfMonth, month, year) Date Returns a new date with dayOfMonth,month and year. The other values are the same as date.
Function Return Description
date:getDate(year, month, dayOfMonth) Date Returns a new date with year, month and dayOfMonth.
date:getDateTime(year, month, dayOfMonth, hour, minute, second) Date Returns a new date with year, month,dayOfMonth,hour,minute and second.
date:date(year, month, dayOfMonth) Date Alias of date:getDate.
date:date(year, month, dayOfMonth, hour, minute, second) Date Alias of date:getDateTime.
date:create(year, month, dayOfMonth, hour, minute, second) Date Alias of date:getDateTime.
date:now() Date Returns a ne date with the current timestamp.
Function Return Description
date:startOfDay(date) Date Returns a new date starting at 00:00:00 of the day.
date:startOfMonth(date) Date Returns a new date starting at 00:00:00 of the first day of the month.
date:startOfYear(date) Date Returns a new date starting at 00:00:00 of the first day of the year.
date:endOfDay(date) Date Returns a new date at 23:59:59 of the day.
date:endOfMonth(date) Date Returns a new date at 23:59:59 of the last day of the month.
date:endOfYear(date) Date Returns a new date at 23:59:59 of the last day of the year.
Function Return Description
date:year(date) int Returns a year of the date.
date:month(date) int Returns a month of the date.
date:date(date) int Returns a date (day of month) from date.
date:dayOfWeek(date) int Returns a day of week from date.
date:weekOfYear(date) int Returns a week of the year from date.
date:hour(date) int Returns the hour of the date.
date:minute(date) int Returns the minute the date.
date:second(date) int Returns the second of the date.
date:millis(date) int Returns the millisecond of the date.
Function Return Description
date:daysInMonth(year, month) int Returns the number of days in the month of the specified year.
date:daysInYear(year) int Returns the number of days in the specified year.
date:weeksInYear(year) int Returns the number of weeks in the specified year.
Function Return Description
date:yearsDiff(date1, date2) long Returns the number of years between date1 and date2.
date:monthsDiff(date1, date2) long Returns the number of months between date1 and date2.
date:daysDiff(date1, date2) long Returns the number of days between date1 and date2.
date:hoursDiff(date1, date2) long Returns the number of hours between date1 and date2.
date:minutesDiff(date1, date2) long Returns the number of minutes between date1 and date2.
date:secondsDiff(date1, date2) long Returns the number of seconds between date1 and date2.
date:millisDiff(date1, date2) long Returns the number of milliseconds between date1 and date2.
Function Return Description
date:yearsBetween(date1, date2) double Returns the rest of years between date1 and date2.
date:monthsBetween(date1, date2) double Returns the rest of months between date1 and date2.
date:daysBetween(date1, date2) double Returns the rest of days between date1 and date2.
date:hoursBetween(date1, date2) double Returns the rest of hours between date1 and date2.
date:minutesBetween(date1, date2) double Returns the rest of minutes between date1 and date2.
date:secondsBetween(date1, date2) double Returns the rest of seconds between date1 and date2.
date:millisBetween(date1, date2) double Returns the rest of millis between date1 and date2.

BigDecimal helpers (namespace bd)

Function Return Description
bd:round(value, unitStr) BigDecimal Returns a new BigDecimal, which is the rounded value with the given unitStr (string unit).
bd:round(value, unit) BigDecimal Returns a new BigDecimal, which is the rounded value with the given unit.
bd:round(value, unit, mode) BigDecimal Returns a new BigDecimal, which is the rounded value with the given unit and mode (CEILING, DOWN, FLOOR, HALF_DOWN, HALF_UP, HALF_EVEN, UP).
Function Return Description
bd:scale(value, scale) BigDecimal Returns a new BigDecimal, which is the scaled value with the given scale.
bd:scale(value, scale, mode) BigDecimal Returns a new BigDecimal, which is the scaled value with the given scale and mode (CEILING, DOWN, FLOOR, HALF_DOWN, HALF_UP, HALF_EVEN, UP).

Resources helpers (namespace res)

Function Return Description
res:getCombo(comboId) Map<String,String> Returns the Combo content of comboId.

Header helpers (namespace header)

Function Return Description
header:hasHeader(gridViewId, keyMapping) boolean Returns true if there is a header content.
header:generate(gridViewId, keyMapping) boolean Generates the header, based on the gridViewId and the keyMapping.
header:generateAndTagRow(outputRow, gridViewId, keyMapping) boolean Generates the header, based on the gridViewId and the keyMapping. The output row will be tagged with a property ‘sainet_header’ that will be set as the style on the SAINet row.

The gridViewId must be declared in the <inputs> node.

The keyMapping variable is a list of pairs that is used to find the corresponding header row in the GridView. The first part of the pair is the column ID in gridViewId and the second one is its corresponding value.

The outputRow is the BlueIron output row available in the execution context.

Here is an example:

header:generate("REG05_HEADER", ["ID", NOCPTE])