Soft References
and Table Colorizer
, which due to their complexity have been designated as Advanced Features.1 Soft References
Soft References
(or Filtering Helper) is a powerful tool to ease form data entry and to enable client side data validation.
It is useful when a form contains a field which value must be previously registered into a database table.
So, it helps in the selection of the field's value and integrity verification.
1.1 What is it?
Soft References
parameterization defined for a column enables a set of functionalities on Axional Studio Form Object
input fields corresponding to that column.
1.2 What can I do?
The main purposes of Filter helper are:
- Autocomplete
- Data validation
- Importing related data
- Object data selector
- Custom validation messages
1.2.1 Autocomplete
Field autocompletion evaluates the text typed by the user on those fields where Filtering Help is enabled. While the user is typing the form displays a list of matching values for helping the user to select the right value.
It exists a small delay between each autocomplention data request in order to soften network communication and server workload.
1.2.2 Data validation
After the user has filled the field, the system verifies that the entered data exists in the helper destination table, according to the Soft References
definition.
1.2.3 Import related data
After the user has filled the field the system could obtain some data related to the entered value for filling some other fields or views in form. For example, you can retrieve the bank account number after informing of the client's name.
Related data obtaining is executed together with data validation, in order to improve network communication and server workload.
1.2.4 Object data selector
In case of the user requires to execute complex queries, it is possible to access an Axional Studio SQL Report
for filtering and getting the
field value. So, that implementation takes profit of the power of Axional Studio Query By Example Form (QBE).
To directly access the object, click on the field Manage Existing .
1.2.5 Custom validation messages
It allows Soft References
to display data as selectable on autocomplention or object selector list, but once selected blocks the field with an error message.
It is useful, for example, for discarded or deprecated data. Hiding this data from list could be interpreted as the data doesn't exists on destination table;
through this implementation data is shown but it can not be selected.
1.3 What do I need?
In first place, Soft References
require the basic Axional Studio infrastructure, which includes:
- Axional Studio Server, properly set up.
- Dictionary database
- A target database
In second place, as they are applied to input fields in Axional Studio Form Object
, it is required to have any object that uses the column for which
a helper is defined as input field.
In third place, Soft References
definition involves the use of
Structured Query Language (SQL)
, which is supposed to be known by programmer before start developing Filtering Helpers.
1.4 Architecture
1.4.1 Flow of execution
The following chart tries to explain the architecture and the system behavior of fields filtering helper.
The graph includes the whole application flow, from the user interaction to the database access.
The purpose of this graph is to explain what processes intervene in the execution of Soft References
and where are executed (client/server).
1.4.2 Dictionary tables
Soft References
implementation only involves two parametrization tables:
- Soft reference helper definition (wic_jdic_softref_help)
- Soft reference relations (wic_jdic_softref_rel)
As it is explained bellow, Soft References
functionalities sometimes do not requires any parametrization; so the following tables are not indispensable, but very useful.
Soft reference helper definition
- Table* : physical table name that is the data source.
- Method* : code that in combination with table name identifies the soft reference.
-
Autocomplete statement
: by default, the autocomplete functionality should return a light list of records (20 or 25 rows).
Likewise, the speed of response is essential and therefore it must interrogate following indexes in the database.
The statement is defined with two fields. Usually:
- Value code that is incorporated into the field
- Accessory value description for easy search
The output sort is not preset and depends on the definition in this field. - Verify statement : SQL Statement which verifies input value and allows importing related data.
- Message : invalidate messages when an expression is fulfilled. See Invalidate Messages section.
-
Options:
- Table quick edition : with this table user can register a new record without having to access the original form that defines that field.
- Helper object column : column name from which get the value in the data selector object.
- Condition : filtering condition restricting displayed rows in the data selector object.
Soft references relations
- Table* : table code to apply the soft reference.
- Source column* : source column.
- Enable expression : Javascript expression to apply this helper.
- Filtering table:
- Method :
- SQL Vars (Form:SQL) :
- Column mapping (Form:SQL) :
- Disable clear :
1.5 Implementation
The implementation of Soft References
is achieved by adding some settings to the desired table and columns. According to this configuration,
the system handles to types of helpers:
- Automatic helpers (Hard Reference) are created from the database constraints configuration.
- Explicit helpers (Soft Reference) are defined by dictionary.
1.5.1 Automatic implementation (Hard Reference)
Axional Studio Forms automatically enables Soft References
for those fields in form having physical database foreign keys.
Filtering automatic implementation allows enabling powerful field facilities with very little configuration, which are very useful for simple tables.
Automatic helpers includes the three main Soft References
functionalities:
- Autocomplete
- Data validation
- Object data selector
Autocomplete
Autocomplete functionality is achieved by comparing the entered pattern with the destination table and column defined in the foreign key. The matching compare function accepts all rows which data pattern is contained in the destination column, not case sensitive. Matching function also considers the next alphanumeric column after the column defined by the foreign key. This column is also shown in the autocomplete list. These considerations allow the use of automatic helpers filtering by code and description just by defining the proper columns order on tables definition.
Imagine you have the following data structure:
So the SQL statement executed for the autocomplete would be like:
SELECT artistid, name FROM artist WHERE ( UPPER(artistid) LIKE UPPER(%'[Input text...]%') OR UPPER(name) LIKE UPPER('%[Input text...]%') )
Asuming that exists the following data in the artist table:
artistid | name |
---|---|
1 | AC/DC |
2 | Accept |
3 | Aerosmith |
4 | Alanis Morissette |
5 | Alice In Chains |
6 | Antônio Carlos Jobim |
7 | Apocalyptica |
8 | Audioslave |
9 | BackBeat |
10 | Billy Cobham |
11 | Black Label Society |
12 | Black Sabbath |
... | ... |
In first place, when the user types ' 3 ' in the input field, the autocomplete list will show the matching item ' Aerosmith ', which have the code ' 3 '.
In second place, when the user types ' Black ', the autocomplete list will show the following matches:
- Black Label Society
- Black Sabbath
- Banda Black Rio
- The Black Crowes
- Black Eyed Peas
Data validation
Data validation consists of a simple SQL statement that verifies that the entered data corresponds with a row from the destination table and column.
Taking the previous data structure, the SQL statement executed for the data validation would be like:
SELECT artistid FROM artist WHERE artistid = '[Input text...]'
Object data selector
If exists an Axional Studio SQL Report
which its code corresponds to the foreign key destination table, this object is accessible from the input field for selecting data from it.
Automatic helpers are always active for those columns having physical foreign keys. If requires a custom filtering settings or even if requires to not apply any filter it will be necessary to set an explicit filtering implementation (Soft Reference).
Representation
Form fields having the Hard Reference functionality enabled are identified with a dark lightning icon.
1.5.2 Explicit implementation (Soft References)
An explicit implementation of Soft References
(Filtering Helper) is necessary when business logic becomes more complex and filtering condition requires the implication of secondary tables and columns, or when
are necessary the whole functionalities of Soft References
:
- Autocomplete
- Data validation
- Importing related data (Only with Soft Reference)
- Object data selector
- Custom validation messages (Only with Soft Reference)
The implementation of Soft References
are defined by two entities:
-
Soft reference definition (wic_jdic_softref_help)
Menu path:Dictionary / Physical / Attributes / Soft references (definition)
-
Soft reference relationship (wic_jdic_softref_rel)
Menu path:Dictionary / Physical / Attributes / Soft references (relationship)
The first one defines the helpers available in system, which is mainly the definition of the SQL Statements executed to enable field Soft References
functionalities.
Whilst the latter is the assignment of those helper definitions to the fields.
Soft reference definition (helper)
The
Soft reference helper form
contains all the necessary fields and components to define and maintain Soft References
.
Each helper definition is identified by a table name and a method. The method generally corresponds to table column;
it is not necessary but is useful when using automatic statements as we will see bellow.
Autocomplete statement
Each time the user types a character in the input field having an explicit Soft References
, the Autocomplete statement is executed and the result of this statement is displayed to the user as an autocomplete list.
In first place, helper definition allows letting autocomplete statement in blank. In that case, the system builds an automatic statement using the helper definition table and method. As it happens with Hard Reference, the system already uses as description the next alphanumeric column in the statement.
Imagine you have the following data structure:
Automatic SQL autocomplete statement executed for helper with table customer and method customerid :
SELECT customerid, firstname FROM customer WHERE ( UPPER(customerid) LIKE UPPER(%'[Input text...]%') OR UPPER(firstname) LIKE UPPER('%[Input text...]%') )
If the automatic autocomplete statement doesn't covers the helpers requirements an specific statement can be defined. It is important to note that the autocomplete statement is executed frequently; for that reason, the statement must respect the triple 'E' premises:
- Efficiency , as its executed very often it must be very light and fast.
- Economy , the recursive execution of the statement implies lots of network communication; so, the lower data returned by the statement the better.
- Effectiveness , the values returned by the statement should be those the user expected when introduce the pattern.
The following code is a sample of an autocomplete SQL statement:
<select first='20'> <columns> customerid, firstname || ' ' || lastname </columns> <from table='customer' /> <where> ( UPPER(customerid) LIKE UPPER('%${q}%') OR UPPER(firstname) LIKE UPPER('%${q}%') OR UPPER(lastname) LIKE UPPER('%${q}%') ) AND state = 'A' </where> </select>
It is important to note the use of the
${q}
clause in the statement; which references the input pattern typed by the user when autocomplete is requested.
The use of the select clause
first='N'
is a good way to improve
Efficiency
and
Economy
.
Autocomplete SQL Statement accepts both native SQL or XSQL syntax, but
Axional Studio Functional Roles
will only be applied with the XSQL syntax.
Prevent autocomplention
Sometimes are necessary some Soft References
functionalities but not autocomplete; so it should be prevented.
For that situation, is possible to use a fake SQL Statement that returns the same value as the entered by the user.
Sample of a fake autocomplete SQL statement:
<select-one>${q}, ${q}</select-one>
Leaving the autocomplete statement blank not prevent autocompletion execution. It executes the automatic statement build from table and method definition. Preventing autocomplention is achieved by using a fake SQL Statement like the one shown in the sample.
Validation statement
The validation statement has two purposes: verify the integrity of the input value and gather some information related to the input value for filling the form with this data.
These purposes are achieved by executing the
Validation SQL statement
when the field value changes. Basically, execution of this statement is triggered by:
- The user has manually modified the field and leave it.
- The user selects a value from the autocomplete list.
- The user selects a value from object selector list.
- The field has been changed by the client side Javascript program.
As it happens with the autocomplete statement, leaving the
Validation SQL statement
blank entails the system to build an automatic statement using the helper definition table and method.
Automatic SQL validation statement executed for helper with table customer and method customerid :
SELECT customerid FROM customer WHERE customerid = '[Input text...]'
If the automatic statement doesn't covers the helper's requirements an specific statement can be defined. Even this statement is much less executed than the autocomplete one it is also executed quite often; so, triple 'E' premises are also applicable to this statement.
The following code is a sample of a validation SQL statement:
<select> <columns> customerid </columns> <from table='customer' /> <where> customerid = ${q} AND state = 'A' </where> </select>
Evaluation of validation SQL statement accepts the entered value as valid if the statement returns any row; otherwise, the field will be mark as invalid.
So, the validation statement should return zero or one row; if return more than one row the rows after the first will be ignored.
In the same way as autocomplete statement
${q}
references the input pattern typed by the user.
The previous statement just verifies data integrity, but doesn't gather any extra information. This functionality is achieved by selecting more columns in the statement. All columns returned by the validation SQL statement will be ready to be filled in the form. Those columns are mapped to the form by the following rules:
- Related columns . Columns mapping defined by helper relations to be updated in form from helper.
- Field Label . Field Label input type defined by an EJB-DATA-TABLE box component.
- Field Description . Field description defined by an EJB-DATA-FLOW box component.
- JOIN Columns . All columns defined in source Form Object which its table doesn't correspond to the primary table in Form Object primary SQL Statement an which column name matches with the columns returned by the statement.
The following code is a sample of a validation SQL statement having extra columns to fill a form:
<select> <columns> address, city, state, country, postalcode </columns> <from table='customer' /> <where> customerid = ${q} AND state = 'A' </where> </select>
Validation SQL Statement accepts both native SQL or XSQL syntax, but
Axional Studio Functional Roles
will only be applied with the XSQL syntax.
Prevent validation
Validation can be prevented, so the user can input a value which not exist in the destination table. However, autocomplete, object data selection and other filtering functionalities would be available. This behavior can be achieved by using a fake SQL Statement that returns any value independently of the input data.
Sample of a fake validation SQL statement:
<select-one>'Whatever'</select-one>
It could also be interesting to retrieve related information in case of the input value exists in destination but no mark the field with error if not exist. This can be achieved by taking profit of the fact that only the first row returned by the validation statement is considered. So, if use an union clause for adding both valid SQL Statement and a fake one, if the first select returns any data, this will be considered; otherwise, the statement will return empty data:
The following code is a sample of a validation SQL statement having extra columns to fill a form but prevents validation if input data doesn't exists:
<union type='all'> <select> <columns> address, city, state, country, postalcode </columns> <from table='customer' /> <where> customerid = ${q} AND state = 'A' </where> </select> <select-one> <cast type='char'>NULL</cast>, <cast type='char'>NULL</cast>, <cast type='char'>NULL</cast>, <cast type='char'>NULL</cast>, <cast type='char'>NULL</cast> </select-one> </union>
Leaving the validation statement blank not prevent field validation. It executes the automatic statement build from table and method definition. Preventing validation is achieved by using a fake SQL Statement like the one shown in the sample.
Variables
Variables brings dynamism to helpers by using them in helper expressions. Lack of variables would entails having more helpers with small differences between them. Variables can be used in:
- Autocomplete statement
- Validation statement
- Object condition
Variables are defined simply by using them, no previous definition in helper is required. Variables value will be defined later by the relations definition. If a variable has no value defined by the helper relation an error will occur. Variable names are arbitrary, they have no relation with the helper tables nor methods.
Sample of a validation SQL using variable ${country}:
<select> <columns> customerid </columns> <from table='customer' /> <where> customerid = ${q} AND country = ${country} AND state = 'A' </where> </select>
Built in functions
It exits the possibility to apply some build functions to the variable that enables extra functionalities:
Function | Description | Sample |
?uppercase | Convert the string to uppercase letters |
The values 'Mark' or 'mark' for the variable firstname will return the same response:
Copy
<select> <columns> customerid </columns> <from table='customer' /> <where> customerid = ${q} AND UPPER(firstname) = ${firstname?uppercase} AND state = 'A' </where> </select> |
?lowercase | Convert the string to lowercase letters |
The values 'Mark' or 'mark' for the variable firstname will return the same response:
Copy
<select> <columns> customerid </columns> <from table='customer' /> <where> customerid = ${q} AND LOWER(firstname) = ${firstname?lowercase} AND state = 'A' </where> </select> |
?length | Returns the length of a string |
Do not consider the comparison of firstname if its value has a lengt lower than 2:
Copy
<select> <columns> customerid </columns> <from table='customer' /> <where> customerid = ${q} AND (firstname = ${firstname} OR ${firstname?length} < 2) AND state = 'A' </where> </select> |
?literal | Literally replaces the value into the statement |
Literally replace the value of the variable condition :
Copy
<select> <columns> customerid </columns> <from table='customer' /> <where> customerid = ${q} AND ${condition?literal} </where> </select>
If the value of
condition
is
Copy
SELECT customerid FROM customer WHERE customerid = ? AND state = 'A' |
Constants
It exists a set of constants that can be also used in helper expressions. As it occurs with variables, constants can be used in:
- Autocomplete statement
- Validation statement
- Object condition
Constant | Description |
$CODE | Returns the code of the Axional Studio Form Object in which the helper is executing. |
$DBMS | Returns the application database in which the helper is executing. |
$LANG | Returns the user language codes, defined by ISO 639, an international standard that assigns two- and three-letter codes to most languages of the world. |
$USER | Returns the user code |
Constants are used with the sintax $CONSTNAME , directly in the helper statement.
Sample of a autocomplete SQL using constants:
<select first='20'> <columns> customerid, firstname || ' ' || lastname </columns> <from table='customer' /> <where> ( UPPER(customerid) LIKE UPPER('%${q}%') OR UPPER(firstname) LIKE UPPER('%${q}%') OR UPPER(lastname) LIKE UPPER('%${q}%') ) AND state = 'A' AND customerid != $USER </where> </select>
Object data selector
Soft References
enables the functionality to use Axional Studio Reports for selecting data for an input field.
Object data selector is much less intuitive than autocomplete and is also less efficient.
Besides, it causes adding extra buttons to the form which make it heavier for the eyesight.
In counterpart, enables the use of QBE queries to perform complex search.
Taking this into account, the use of object data selector must be rationed to those cases strictly necessary.
Object data selector is enabled by specifying a column in the
Help object
box.
If so, the object used as data selector corresponds with the table name identifying the helper.
The defined column references the column of the destination object to take the value from an place it in the source field.
Optionally, it could be defined a condition that will be added to the where clause of the destination object. The same way as helper statements, the object data selector condition can reference:
-
Input text:
${q}
-
Variables:
${varname}
-
Constants:
$CONSTNAME
The main difference is that those expressions are literally replaced in the condition to be send as an object condition clause. For that reason, when defining the condition it must be considered the type of the variables, possible nulls, etc. The main consideration is that alphanumeric variables should be placed between quotes.
Sample of a object data selector condition using variables:
customer.country = '${country}' AND customer.state = 'A'
Invalidate messages
Invalidate messages allows selecting values for the input field but blocking the field with a custom invalidate message. That is, both autocomplete list and object data selector display some values as selectable that won't be able to be chosen at the end. This functionally is useful when having invalid or deprecated values that must be shown to inform the user the row exists, but them must not be selected.
Invalidate messages is implemented by the Message box in the Helper definition form . The box provides a transactional table with two columns:
- Expression : UEL Expression evaluated with the data returned by the validation statement each time it is executed.
- Label : Localizable label to be shown as field error if the expression is evaluated to true .
That is, each time the validation statement is executed and some row is returned the system evaluates the messages tables; if founds any invalidate message that accomplish the expression shows the corresponding message as an error for the field.
Define relation
Once having a proper catalog of Soft References
is the time of telling each field what helper will
use and configure the relations between the form and the helper.
So, defining Soft Relations allows:
- Assign a
Soft References
to a field - Map form data with the corresponding variables used in helper.
- Assign data returned by helper validation statement to be filled in form fields.
Apply Expression
One form field could have assigned more than one helper. However, at the moment of validation only one helper would be applied to a field. So, the applied helper will be the one among the set of helpers defined by the field which the defined apply expression is evaluated to true depending on the state of the form.
Let the apply expression blank in a helper assignment implies that this helper will be applied in case that any other helpers apply expression is accomplished. Taking this into account, the following statements must be considered:
- In case of a field with only one helper the apply expression must be blank.
- In case of a field where none apply expression is accomplished during the form data entry, none helper will be applied.
- In case of more than one apply expression are accomplished, only one of them would be arbitrarily applied. So, apply expression should be exclusive.
Map form data to helper
As it is said before, helpers use variables in its statements to constraint the set of available rows for the field.
Those variables are collected from the source form, so it is required to define the relations between the form data and these variables.
These relations are defined in the
form to SQL mapping
using a
key/value
JSON syntax where the keys reference the data source and the values are the name
of the variables referenced by the helper.
The data source has different types: form fields, parent fields and constants. Each type is referenced using a different syntax:
Syntax | Type | Description | Sample |
---|---|---|---|
{ 'colname' : 'varname' } | Form field | Obtains the value from a field in form | { 'artistid' : 'artist' } |
{ 'adapter.colname' : 'varname' } | Main statement field | Obtains the value from the object main statement, in case it is not the main data, for example, in SQLTables | { 'adapter.albumid' : 'album' } |
{ 'parent.colname' : 'varname' } | Parent field | Obtains the value from a field in the parent form | { 'parent.albumid' : 'album' } |
{ 'constant.value' : 'varname' } | Constant | Sets a constant value to the variable | { 'constant.A' : 'state' } |
Update form fields from helper
Finally, helper validation statement, apart from validate the input value, gathers some others values that can be filled in the source form. This functionality requires two steps:
- Define a helper validation statement which select some columns.
- Define the relation between the columns defined in the validation statement and the source form fields.
The first step has been explained before in the Helper definition section. The second step is achieved by defining the SQL to form mapping field. Similar to the form to SQL mapping it uses a key/value JSON syntax, where the key references a field from the source form and the value references a column returned by the helper validation statement. Unlike form to SQL mapping , the SQL to form mapping can only reference form fields, so the syntax is simpler.
1.5.3 The QBE autocomplete statement
For each table and method it is possible to define, in addition to the autocomplete statement, the QBE statement. This statement will be applied exclusively on the QBE screen and follows the same implementation rules as the autocomplete statement, except that the QBE autocomplete statements don't apply Enable Expressions.
Order to be applied in QBE fields
If a table.column has more than one soft reference relation defined, the first soft reference to be applied in the QBE screen will be the first one with a defined QBE statement.
If there is no QBE statement defined, the first soft reference to be applied will be the first one without defined Enable Expressions.
1.5.4 Dictionary overriding
Axional Studio Soft References
allow dictionaries overriding.
That is, modifying the functionality of Soft References
defined in lower modules or dictionaries.
Soft Reference overriding can be achieved by overriding both helper
definition
(wic_jdic_softref_help) or helper
relation
(wic_jdic_softref_rel).
Even though, it is strongly recommended to use helper
relation
overriding.
On one hand, because it has a more simple structure; on the other hand, because helper
definition
overriding might cause some issues as it is shown on the sample cases bellow.
For the following examples, it is supposed that exists two dictionaries: wic_sample1, wic_sample2. Where wic_sample2 has higher priority than wic_sample1, so the definitions of wic_sample2 prevails over those of wic_sample1.
Good use
This case shows an example of good practice of overriding a helper
relation
.
Helper relation (wic_jdic_softref_rel):
Dictionary | Object | Source Column | Destiny table | Method |
---|---|---|---|---|
wic_sample1 | customer | supportrepid | employee | employee_fullname |
wic_sample2 | customer | supportrepid | employee | employee_fullname_cust |
Helper definition (wic_jdic_softref_help):
Dictionary | Table | Method | Autocomplete statement | Messages | ||||||
---|---|---|---|---|---|---|---|---|---|---|
wic_sample1 | employee | employee_fullname |
Copy
... Statement 1 |
|||||||
wic_sample2 | employee | employee_fullname_cust |
Copy
... Statement 2 |
|
Result:
Property | Value | ||||||
---|---|---|---|---|---|---|---|
Table | employee | ||||||
Method | employee_fullname_cust | ||||||
Autocomplete statement |
Copy
... Statement 2 |
||||||
Messages |
|
Notice that, as the high priority dictionary (wic_sample2) has overridden the helper
relation
by pointing to the
employee.employee_fullname_cust
it inherit all its properties.
Not recommended
This case shows a correct parameterization, but not recommended, of overriding a helper
definition
.
Helper relation (wic_jdic_softref_rel):
Dictionary | Object | Source Column | Destiny table | Method |
---|---|---|---|---|
wic_sample1 | customer | supportrepid | employee | employee_fullname |
Helper definition (wic_jdic_softref_help):
Dictionary | Table | Method | Autocomplete statement | Messages | ||||||
---|---|---|---|---|---|---|---|---|---|---|
wic_sample1 | employee | employee_fullname |
Copy
... Statement 1 |
|||||||
wic_sample2 | employee | employee_fullname |
Copy
... Statement 2 |
|
Result:
Property | Value | ||||||
---|---|---|---|---|---|---|---|
Table | employee | ||||||
Method | employee_fullname | ||||||
Autocomplete statement |
Copy
... Statement 2 |
||||||
Messages |
|
Notice that, as the high priority dictionary (wic_sample2) has overridden the helper
definition
employee.employee_fullname
it inherit its properties from the wic_sample2 dictionary.
Bad use
This case shows an incorrect parameterization of overriding a helper
definition
.
Helper relation (wic_jdic_softref_rel):
Dictionary | Object | Source Column | Destiny table | Method |
---|---|---|---|---|
wic_sample1 | customer | supportrepid | employee | employee_fullname |
Helper definition (wic_jdic_softref_help):
Dictionary | Table | Method | Autocomplete statement | Messages | ||||||
---|---|---|---|---|---|---|---|---|---|---|
wic_sample1 | employee | employee_fullname |
Copy
... Statement 1 |
|
||||||
wic_sample2 | employee | employee_fullname |
Copy
... Statement 2 |
Result:
Property | Value | ||||||
---|---|---|---|---|---|---|---|
Table | employee | ||||||
Method | employee_fullname | ||||||
Autocomplete statement |
Copy
... Statement 2 |
||||||
Messages |
|
Notice that, as the high priority dictionary (wic_sample2) has overridden the helper
definition
employee.employee_fullname
it inherit its properties from the wic_sample2 dictionary;
but it takes the messages from the wic_sample1 dictionary.
It happens because of the architecture of the application; as it not exists any data for the given table and method in wic_sample2 dictionary, the system searches in the other dictionaries.
The way to solve this issue is by using a helper
relation
override instead of overriding the helper
definition
.
Good use resolving the issue:
Helper relation (wic_jdic_softref_rel):
Dictionary | Object | Source Column | Destiny table | Method |
---|---|---|---|---|
wic_sample1 | customer | supportrepid | employee | employee_fullname |
wic_sample2 | customer | supportrepid | employee | employee_fullname_cust |
Helper definition (wic_jdic_softref_help):
Dictionary | Table | Method | Autocomplete statement | Messages | ||||||
---|---|---|---|---|---|---|---|---|---|---|
wic_sample1 | employee | employee_fullname |
Copy
... Statement 1 |
|
||||||
wic_sample2 | employee | employee_fullname_cust |
Copy
... Statement 2 |
Result:
Property | Value |
---|---|
Table | employee |
Method | employee_fullname_cust |
Autocomplete statement |
Copy
... Statement 2 |
Messages |
1.6 Samples
The following section presents a set of samples with the most interesting cases of uses of Axional Studio Soft References
implementations:
1.6.1 Filtering by first name and last name
Introduction
This sample shows how to implement a defined Soft References
in a
Customer
form for a field identifying the employee which give it support, so the user
could search the employee by its first or last name.
The current sample is based on the following data structure:
The following table shows the content of the table
employee
:
employeeid | lastname | firstname |
---|---|---|
1 | Adams | Andrew |
2 | Edwards | Nancy |
3 | Peacock | Jane |
4 | Park | Margaret |
5 | Johnson | Steve |
6 | Mitchell | Michael |
7 | King | Robert |
8 | Callahan | Laura |
Helper definition
The helper parametrization for that case consists of:
Column | Description | Value |
Table | Source of data table | employee |
Method | Identifying code of the current helper | employee_fullname |
Autocomplete statement | SQL Statement filtering by both first name and last name |
Copy
<select first='20'> <columns> employee.employeeid, employee.lastname || ', ' || employee.firstname </columns> <from table='employee' /> <where> (UPPER(employee.lastname) LIKE UPPER('%${q}%') OR UPPER(employee.firstname) LIKE UPPER('%${q}%')) </where> </select> |
Validation statement | SQL Statement verifying that the entered code corresponds with a valid employee. |
Copy
<select> <columns> employee.employeeid </columns> <from table='employee' /> <where> employee.employeeid = ${q} </where> </select> |
Define relation
The helper relation parametrization for that case consists of:
Column | Description | Value |
Object | Code of form object containing the field to assign the helper | customer |
Source Column | Name of the field to apply the helper | supportrepid |
Destiny table | Table identifying the applicable helper. Corresponds with the previously defined table. | employee |
Method | Method identifying the applicable helper. Corresponds with the previously defined method. | employee_fullname |
Execution
Once both helper and relation are defined, column ' Id. support ' in SQL Object ' customer ' allows the user to search the employee code by its first and last name. For example, of the user types ' ha ', the autocomplete list will show:
- Mic ha el, Mitchell
- Laura, Calla ha b
1.6.2 Fill form with related data
Introduction
This sample shows how to implement a defined Soft References
in an
Invoice
form, where the invoice customer could be selected by first and last name;
furthermore, after selecting the customer all the customer data will be automatically filled in the invoice form (Address, City, etc.).
The current sample is based on the following data structure:
The following table shows the content of the table
customer
:
customerid | address | city | state | country | postalcode |
---|---|---|---|---|---|
1 | Av. Brigadeiro Faria Lima, 2170 | São José dos Campos | SP | Brazil | 12227-000 |
2 | Theodor-Heuss-Straße 34 | Stuttgart | null | Germany | 70174 |
3 | 1498 rue Bélanger | Montréal | QC | Canada | H2G 1A7 |
4 | Ullevålsveien 14 | Oslo | null | Norway | 0171 |
5 | Klanova 9/506 | Prague | null | Czech Republic | 14700 |
6 | Rilská 3174/6 | Prague | null | Czech Republic | 14300 |
7 | Rotenturmstraße 4, 1010 Innere Stadt | Vienne | null | Austria | 1010 |
8 | Grétrystraat 63 | Brussels | null | Austria | 1010 |
9 | Sønder Boulevard 51 | Copenhagen | null | Denmark | 1720 |
... |
Helper definition
The helper parametrization for that case consists of:
Column | Description | Value |
Table | Source of data table | customer |
Method | Identifying code of the current helper | customerid |
Autocomplete statement | SQL Statement filtering by both first name and last name |
Copy
<select first='20'> <columns> customer.customerid, customer.firstname || ' ' || customer.lastname </columns> <from table='customer' /> <where> (UPPER(customer.firstname) LIKE UPPER('%${q}%') OR UPPER(customer.lastname) LIKE UPPER('%${q}%')) </where> </select> |
Validation statement | SQL Statement verifying that the entered code corresponds with a valid customer. Notice that the statement gather all the columns that will be filled in form. |
Copy
<select> <columns> customer.customerid, customer.address, customer.city, customer.state, customer.country, customer.postalcode </columns> <from table='customer' /> <where> customer.customerid = ${q} </where> </select> |
Define relation
The helper relation parametrization for that case consists of:
Column | Description | Value |
Object | Code of form object containing the field to assign the helper | invoice |
Source Column | Name of the field to apply the helper | customerid |
Destiny table | Table identifying the applicable helper. Corresponds with the previously defined table. | customer |
Method | Method identifying the applicable helper. Corresponds with the previously defined method. | customerid |
Column Mapping
(from SQL to Form) |
Mapping those columns returned by the validation SQL Statement that will be filled in form. |
Copy
{"billingaddress":"address", "billingcity":"city", "billingstate":"state", "billingcountry":"country", "billingpostalcode":"postalcode"} |
Execution
Once both helper and relation are defined, column '
Id. customer
' in SQL Object
Invoice
allows the user to search the customer code by its first and last name.
For example, of the user types '
Mark
', the autocomplete list will show:
- Mark Philips
- Mark Taylor
Furthermore, when choose one the two proposals the fields of the Invoicing will be filled the information of the selected customer.
1.6.3 Example III
From the previous example, show the steps to follow for can program a message, which, inform if the customer is given off sick in case to want select it in the form of invoice.
To start with it is necessary to go to the method 'customer id' in the soft reference helper of the table customer, to add the column of state in the code SQL of the sentence of verification. Now the code will remain of the following shape:
<select> <columns> customer.customerid, customer.address, customer.city, customer.state, customer.country, customer.postalcode, customer.status </columns> <from table='customer' /> <where> customer.customerid = ${q} </where> </select>
To continuation in the field Expression of the section Message declares the sentence SQL that will do it appear. For this defines that, whenever it put the identifier of a customer that is given off sick, show the message. Also it defines the field Labels, in which will indicate the code of the label of form the description of which, will be the text that will show the message.
-
Expression :
'${status}'== 'B'
-
Label :
LBL_CUSTOMER_DROP
To realize the testing has to situate in the form invoice, and tries aggregate one with the identifier of a customer that have off sick. In our case is the '9' and appears the message in addition to preventing aggregate the bill.
1.7 Frequently asked questions
1.7.1 How implementing the autocomplete in a field without verifying the integrity?
To define this type of soft reference shows an example in which to him object
Customer
, can happen a Id.Support without that it verify the integrity.
How the table of filter is
Employed
it is necessary to head to the Soft reference Helper and define it of the following shape:
Autocomplete statement
<select> <columns> employee.employeeid, employee.firstname || ', ' || employee.lastname </columns> <from table='employee' /> <where> (UPPER(employee.firstname) LIKE UPPER('%${q}%') OR UPPER(employee.lastname) LIKE UPPER('%${q}%') OR (employee.employeeid || <whitespace/>) LIKE ('%${q}%')) </where> </select>
Verification statement
<select-one>'' dummy</select-one>
In the reference relation indicates the relation of the table origin with the destiny method.
Finally if it goes to him object Customers to realize the checking, will be able to observe how in Id.Support follows appearing the autocomplete and in putting a nonexistent identifier, there is not integrity verification.
1.7.2 How defining the sentence integrity verification without the autocomplete?
To define this type of soft reference shows an example in which to him object Employee, can happen an addressee of the report without that it appear the autocomplete but, without that it do the integrity in case to put an identifier of employee that do not exist.
Head to the soft reference helper and define the sentences SQL of the following shape:
Autocomplete statement
<select> <columns> wic_dual.dummy </columns> <from table='wic_dual' /> <where> 1==0 </where> </select>
Verification statement
<select> <columns> employee.employeeid </columns> <from table='employee' /> <where> employee.employeeid || <whitespace/> = ${q} </where> </select>
In the reference relation indicates the relation of the table origin with the destiny method.
Finally if it goes to the object to realize the checking, can see how in Report recipient no longer appears the autocomplete, but in putting an identifier that does not exist the integrity verification if it works.
1.8 Text search queries
The system allow to realize Basic text search queries from Helpers. For this it is necessary to use the following tag:
<text-search table='product' column='product_name' fuzzy='y'>${q}</text-search>
The tag has the following attributes:
<text-search
table='table'
column='column'
fuzzy='yes|no'
/>
Attributes | |||||
---|---|---|---|---|---|
Name | Type | Required | Default | Description | |
Atable | string | The table to perform the query. | |||
Acolumn | string | The column to perform the query. | |||
Afuzzy | boolean | no | Indicates if the query is fuzzy or not. |
In order to use this feature it is necessary the database server must support Text Search Queries and that the column on which realizes the query has the suitable index.
For example:
<union> <select> <columns>*</columns> <from table='product' /> <where> <text-search table='product' column='product_name' fuzzy='y'>${q}</text-search> AND (${product_class_id} IS NULL OR product_class_id = ${product_class_id}) </where> </select> <select> <columns>*</columns> <from table='product' /> <where> <text-search table='product' column='brand_name'>${q}</text-search> AND (${product_class_id} IS NULL OR product_class_id = ${product_class_id}) </where> </select> </union>
See this documentation to how prepare the database to allow BTS queries over fields in Informix agent.
1.8.1 Fuzzy queries on Informix
A fuzzy search searches for text that matches a term closely instead of exactly. Fuzzy searches help you find relevant results even when the search terms are misspelled.
To perform a fuzzy search, append a tilde (~) at the end of the search term.
For example in Informix to search term bank~ will return rows that contain tank , benk or banks .
bts_contains(column, 'bank~')
You can use an optional parameter after the tilde in a fuzzy search to specify the degree of similarity. The value can be between 0 and 1, with a value closer to 1 requiring the highest degree of similarity. The default degree of similarity is 0.5, which means that words with a degree of similarity greater than 0.5 are included in the search.
The degree of similarity between a search term and a word in the index is determined by using the following formula:
similarity = 1 - (edit_distance / min ( len(term), len(word) ) )
The edit distance between the search term and the indexed word is calculated by using the Levenshtein Distance, or Edit Distance algorithm.
The
min()
function returns the minimum of the two values of the
len()
functions,
which return the length of the search term and the indexed word.
The following table shows the values used to calculate similarity and the resulting similarity between the search term
tone
and various indexed words.
Term | Length of term | Word | Length of word | Edit distance | Similarity |
---|---|---|---|---|---|
tone | 4 | tone | 4 | 0 | 1.00 |
tone | 4 | ton | 3 | 1 | 0.67 |
tone | 4 | tune | 4 | 1 | 0.75 |
tone | 4 | tones | 4 | 1 | 0.75 |
tone | 4 | once | 4 | 2 | 0.50 |
tone | 4 | tan | 3 | 2 | 0.33 |
tone | 4 | two | 3 | 3 | 0.00 |
tone | 4 | terrible | 8 | 6 | -0.50 |
tone | 4 | fundamental | 11 | 9 | -1.25 |
The following query searches for words with the default degree of similarity of greater than 0.50 to the search term tone:
bts_contains(text, 'tone~')
This query returns rows that contain these words: tone, ton, tune, and tones. Rows that contain the word onceare not included because the degree of similarity for once is exactly 0.50, not greater than 0.50. The following query would include the rows that contain the word once:
bts_contains(text, 'tone~0.49')
If the number of indexed tokens that match your fuzzy query exceed 1024, you receive the following error:
(BTSB0) - bts clucene error: Too Many Clauses
To solve this problem, you can make the query more restrictive or you can recreate the bts index with the max_clause_count index parameter set to a number greater than 1024.
2 Table Colorizer
2.1 Introduction
The Table Colorizer
feature is a grid parameterization for colorizing grid cells depending on its content, generally to emphasize the importance of a cell among a group of cells.
2.1.1 What is it?
Table Colorizer
is a tool to make grids easier to analyze at a glance.
Let's see an example of a simple grid with a table colorizer definition assigned:
As it looks, due to the colors of the grid, it becomes very easy to see which values ara bigger and which ones are not.
In addition, depending on the dataset that we want to deal with, there are different algorithms to deal with this data, and thus color the grid in the best possible way.
2.1.2 What can I do?
Table Colorizer
are mainly focused on the colorization of grids, such as those containing
SQL Tables
or grids contained in
Channels
.
Its use is interesting when:
- The dataset contains numeric values to be classified
- The dataset contains discrete values (numbers or strings) from which we want to obtain the frequency of appearance
The best thing of Color Palette is that it's very easy to colorize the grid, just by indicating a palette of colors and one of the defined algorithms we have enough. At the same time, it can be added complexity to the colorizer with the use of ranges.
2.1.3 What do I need?
In first place, Table Colorizer
requires the basic Axional Studio infrastructure, which includes:
- Axional Studio Server, properly set up.
- Dictionary database
- A target database
In second place, as they can be applied to
SQL Tables
in
Axional Studio Form Object
, it is required to have any object that uses an SQL Table with at least one column for which
a table colorizer is defined. And the same to
Channels
.
2.2 Architecture
2.2.1 Structure
2.2.2 Dictionary tables
Table Colorizer
implementation involves four parametrization tables:
- Table colorizer definition (wic_jdic_color_rule_def)
- Color palette (wic_jdic_color_palette)
- Table colorizer ranges (wic_jdic_color_rule_range)
- Labels (wic_jdic_lbldata)
As it is explained below, Table Colorizer
functionalities only requires always the table wic_jdic_color_rule_def; It will be explained when is necessary to use the other tables below.
Table colorizer definition
Color palette
If the method defined in a color rule definition is 'Simple distribution', 'Quartiles distribution' or 'Repetitions', another table to obtain the color palette will be needed:
wic_jdic_color_palette | |
---|---|
Label | Description |
Code | Identifier code of palette |
Name | Name of palette |
Colors | Colors of palette |
Table colorizer ranges
If the method defined in a color rule definition is 'By rank', another table to define the ranges will be needed:
wic_jdic_color_rule_range | |
---|---|
Label | Description |
seqno | Order |
Id | Join with wic_jdic_color_rule.rule_code |
Order | Indicate the order to execute the range expressions. |
Bg color |
|
Text color | Secondary color to be applied to the cell, in case the expression returns true. It should be a contrast color in relation to the main color, to guarantee a correct visibility. Generally, corresponds to the text color. It should contain a value such as #00FF00
|
Expression | UEL Expression which determine whether apply the current color or not. It must return a boolean value:
In order to give the maximum means for create versatil expressions, the system provides the following variables to the expression evaluator:
|
Label | Label describing the color functional meaning. It might be used in palette legend. It's value validates with wic_jdic_lbldata.label_code |
Labels
When the table colorizer has ranges defined, it is possible to set a label to the ranges with information about the range expression, to be shown on the tooltip legend.
wic_jdic_lbldata | |
---|---|
Label | Description |
Language | Language in which the descriptions referring to the labels are expressed. When the connection users to the system are defined through the configuration database ( wic_conf ), among other data, it is defined the language in which the application will be used and managed. Depending on the user and language indicated, you will use the description of the labels corresponding to that language.
|
Verified | It specifies if the text has been checked by an expert or translator. Never mind the current status, automatic processes will not affect it.
|
Code | Tag code that will be used to reference it from the form definition. |
Description | Description of the label in the indicated language. This description will be the one that is presented, dynamically and automatically, in the definition and construction of system forms. |
Information | Generally, the documentation implemented here is shown by a floating component or a large fixed component, so that the information can become very extensive, even in the form of a document with sections. |
Created by |
|
Date created |
|
Modified by |
|
Date updated |
|
2.3 Implementation
The implementation of Table Colorizer
is achieved by adding some color rule definitions to the desired columns in a table.
The implementation of Table Colorizer
is defined by one entity:
- Table colorizer definition (wic_jdic_color_rule_def)
The former defines the colorizer rule, and according to this rule involve another entities like table colorizer ranges (wic_jdic_color_rule_range) or color palettes (wic_jdic_color_palette).
2.3.1 Table colorizer definition
The Table colorizer definition contains all the necessary information to colorize a column of a table. Each colorizer definition is identified by a unique code, that can be use by more than one column in a table.
Defining a table colorizer
To start defining our colorizer, the following values will be indicated:
- Description (not required)
- Consider all columns
- Show histogram
- Method
- Palette
- Gradient
Description
The Description contains the functional description of the color rule definition. It is not required.
Consider all columns
The Consider all columns flag indicates which columns the colorizer considers for calculating the limit values like max, min, average, etc.
It can contain two values:
- 0 (false): It considers a single column.
- 1 (true): It considers all the columns of the grid with the same color rule definition.
If the flag is activated and all the columns of the table have the same color rule definition, the resulting grid will be the following:
Otherwise, if the flag is not activated, the resulting grid will be the following:
Show histogram
The Show histogram flag indicates if the header of the column will have a frequency histogram with a tooltip caption.
If the flag is activated in all the columns of the table, the following histograms will appear below the header:
Also, if we go over the histogram, a tooltip with the caption will appear:
The implementation of Table Colorizer
is achieved by adding some color rule definitions to the desired columns in a table. According to this configuration, the system handles two ways to colorize:
- By algorithm method: The user indicates a method to colorize automatically the grid.
- By ranges: The user indicates some ranges to colorize the grid according to the validation of certain expressions that can involve limit values, for example.
By algorithm method
The Color rule definitions contain the following automatic grid colorization algorithms:
-
For continuous values:
- Simple distribution
- Quantiles distribution
-
For discrete values:
- Repetitions
Simple distribution
Simple distribution algorithm distributes the data of the dataset by ranges with an amplitude determined by the following formula:
$$Amplitude = {max - min \over groups}$$This algorithm calculates the groups considering the range of the dataset, giving very good results when a large part of the data tend to be close to the arithmetic mean . Otherwise, it does not plow a good distinction when the are extreme data in out dataset.
This is a dataset with the following values:
- Max: 8000
- Min: 0
- Groups: 10
- Amplitude = 800
This is the resulting grid when it is applied the simple distribution algorithm to this dataset:
The distribution of the values by groups will be the following:
- 0 - 800: 90,83 %
- 801 - 1600: 8,33 %
- 7201 - 8000: 0,83 %
In conclusion, for this dataset is it not appropaite to apply this distribution algorithm.
Quantiles distribution
Quantiles distribution distributes the data of the dataset in groups of equal size. Its use is recommended when our dataset contains many extreme values (very far from the arithmetic mean).
This is the resulting grid when it is applied the quantiles distribution algorithm to the same dataset as the previous example:
In this case, when creating groups with the same number of data, the interpretetion of data is better than with the simple distribution algorithm.
Repetitions
Repetitions algorithm distributes the data of the dataset according to the absoute frequency of each discrete value. Its use is indicated when it is important to know what values are repeated more or less.
This dataset contains the most polluted cities in Europe for the last 20 years* (each row contains 6 cities, the most polluted cities every 2 months in that year).
This is the resulting grid when it is applied the repetitions algorithm to this dataset:
With this example is easy to see what cities were the most and the least polluted cities for the last 20 years.
*The data shown is not real
When one of these algorithms is being applied, there are two more values of the color rule definition that have to consider:
- Color palette
- Gradient
Color palette
The Color palette defines the list of colors to be applied on the grid. This code validates to pal_code in table wic_jdic_color_palette .
Only available in working dictionary
The available colors palettes are those of the current dictionary. This is not a multidictionary option.Gradient
The Gradient flag determines if consider the palette colors as final values, or use them to create a gradient. It will also determine the number of groups in which the dataset will be divided.
This palette contains the following colors:
Color | Hex |
---|---|
#55ff55 | |
#ff5555 |
In the case that gradient flag is not actived, only the two colors indicated on the palette will be applied, an therefore the number of groups will be 2.
Otherwise, if gradient flag is activated, the system will calculate the number of groups with a mathematical formula.
Imagine that in this case the result is 10. Then, the groups will have the following colors:
Color | Hex |
---|---|
#55ff55 | |
#68ec55 | |
#7bd955 | |
#8ec655 | |
#a1b355 | |
#b3a155 | |
#c68e55 | |
#d97b55 | |
#ec6855 | |
#ff5555 |
By ranges
When the goal is to colorize the dataset in our own way, it is best to use the By rank method.
The Color rule ranges contains the necessary fields to indicate how to manually colorize a grid. Each colorizer range is identified by the unique code of its parent wic_jdic_color_rule_def .
To define the ranges, the following values will be indicated:
- Order (not required)
- Main color
- Secondary color
- Expression
- Label (not required)
Order
Order indicates the order to execute the range expressions. The first ordered expression that is fulfilled will be the one that will be applied to the data. It is not required.
Main color
Main color to be applied to the cell, in case the expression returns true. It shoud contain this types of colors:
- HTML Colors (RED, BLUE, WHITE, etc.)
- Hexadecimal Colors (#FF0000, #54AB19, #000, etc.)
- RGB Colors (rgb(255,255,255), rgba(0, 120, 120, 1), etc.)
Secondary color
Secondary color to be applied to the cell, in case the expression returns true. Corresponds to the text color. It should contain a type of color like the main color.
Expression
The UEL Expression will determine whether apply the current color or not. It must return a boolean value:
- If true, the current color is applied.
- Otherwise, it is expected to applu the color of another item.
- In case of any item for the given palette is applicable, it is not set any color.
In order to give the maximum means for create versatil expressions, the system provides the following variables to the expression evaluator:
Variable | Definition |
---|---|
value | Correspond to the value of the cell the color might be applied. |
totalitems | The number of items available for the current dataset. |
Continuous values | |
max | The maximum value of the dataset. |
min | The minimum value of the dataset. |
avg | The mathematical mean of the dataset. |
med | The median value of the dataset. |
Discrete values | |
repeat_value | Is the number of repetitions of the current value. |
repeat_max | Is the maximum number of repetitions of the dataset. |
repeat_min | Is the minimum number of repetitions of the dataset. |
Label
Label describing the color functional meaning. It will be used in tooltip caption. Its value validates with label_code in wic_jdic_lbldata . It is not required.
If the Show histogram flag is activated and almost a label is applied to a range of the color rule, the label will appear on the tooltip caption.
2.3.2 Table colorizer applications
Applying a colorizer to a SQL table
Once having the necessary color rule definitions to colorize our tables is the time of telling each column what color rule definition will use.
To do this, indicate the color rule definition rule_code in the out_palette field of the SQL table columns.
Only available in working dictionary
The available color rule definitions are those of the current dictionary. This is not a multidictionary option.Applying a colorizer to channels
Once having the necessary color rule definitions to colorize our tables is the time of telling each column what color rule definition will use.
To do this, indicate the color rule definition rule_code in the out_palette field of the SQL table columns.
Only available in working dictionary
The available color rule definitions are those of the current dictionary. This is not a multidictionary option.2.4 Samples
The following section presents a set of samples with the most interesting cases of uses of Axional Studio Table Colorizer
implementations:
2.4.1 Heat map of a CPU usage per hour
Introduction
This sample shows how to implement a defined Table Colorizer
in a SQL Table.
The current sample is based on the following data structure:
As observed, a table with a date and information per hour about the CPU usage of a server contains our dataset.
The following SQL Table shows the content of the table:
After seeing this table, it is apparent that with colors in this table it would be much easier to see when the server is in a critical state of work. That is why it is important to apply a colorizer to the table.
Defining a table colorizer
The color rule definition parametrization for that case consists of:
Column | Value |
---|---|
Code | CPU |
Description | Color rule to colorize the CPU usage of a server |
Consider all columns | true |
Show histogram | true |
Method | Simple distribution |
Palette | cpu_1 |
Gradient | true |
And the color palette assigned to this color rule definition have these colors:
Color | Hexadecimal color |
---|---|
#70b58a | |
#fec444 | |
#fbb050 | |
#f89d5b | |
#f48967 | |
#f17572 |
Applying a colorizer to a SQL table
Once color rule definition is defined, this definition is assigned to the necessary columns of the SQL Table.
Execution
Once color rule definition is defined and assigned to the columns of the SQL Table, the grid will be automatically colorized every time it is generated, and in this case it will be shown as: