This document covers the following topics:
After the Map Converter has been used to create page layouts from map extract files, the last step in the conversion process is adapting the application code to the new user interface. This step can either be performed manually or, with Natural Engineer, partly automatically. In the following, the manual code conversion is described.
First of all, it is necessary to generate HTML code and Natural adapters from the page layouts that have been created by the Map Converter. This is the same procedure as with page layouts that have been created manually with the Layout Painter. Then, the adapters are imported into the Natural development environment.
In this context, we need not consider the application code as a whole, but only the layer that handles the user interface. Often, the user interface handling part of a map-based application is structured in the following way:
DEFINE DATA
Initialization
REPEAT
INPUT [USING MAP
map-name]
Includes client-side validations (processing rules)
Server-side validations
REINPUT
or ESCAPE TOP
DECIDE ON *PF-KEY
Function key handler 1
Processing
REINPUT
or ESCAPE
TOP
Function key handler 2
Processing
REINPUT
or ESCAPE
TOP
Function key handler n
Processing
ESCAPE BOTTOM
...
END-DECIDE
END-REPEAT
Cleanup
END
In practice,
the REPEAT
loop might or might not be there,
and
there might not be a clean DECIDE
structure for
the function key handlers. Instead, checks for the pressed function key might
be spread all over the code.
However, accepting these differences, the above structure should match a large number of applications.
The corresponding part of a Natural for Ajax application looks as follows:
DEFINE DATA
Initialization
REPEAT
PROCESS PAGE USING
adapter-name
Includes client-side validations
Server-side validations
PROCESS PAGE UPDATE FULL
DECIDE ON *PAGE-EVENT
Event handler 1
Processing
PROCESS PAGE UPDATE FULL
or
ESCAPE TOP
Event handler 2
Processing
PROCESS PAGE UPDATE FULL
or
ESCAPE TOP
Event handler n
Processing
ESCAPE BOTTOM
...
END-DECIDE
END-REPEAT
Cleanup
END
The code conversion should achieve the following:
It should be minimal invasive.
It should not duplicate business code.
The converted application should be able to run not only with the new user interface, but also in a terminal session, in a Natural Web I/O Interface session and in batch, if it did so before the code conversion.
In detail, the code conversion needs to deal with the statements and constructs mentioned below.
The DEFINE DATA
statement must be extended because
the data structures exchanged between a program and map are not fully identical
to those exchanged between a program and the corresponding adapter.
The default conversion rules delivered with the Map Converter perform a data type mapping that tries to ensure that the data elements in the map interface are mapped to data elements of the same type and name in the adapter interface.
The Application Designer controls are usually not only bound to business data
elements, but also to additional control fields. Which control fields these are
depends on the way in which the elements of a map are mapped to Application Designer controls
by the Map Converter rules. For instance, a
statusprop
can be assigned to a field, which
results in an additional parameter in the parameter data area of the adapter.
An array on a map can have been converted to a grid control with server-side
scrolling. In this case, the additional data structures needed to control
server-side scrolling need to be added to the DEFINE DATA
statement.
The statusprop
is needed to control
the error status or focus of a FIELD
control dynamically (see example 3 for the
REINPUT
statement below where it is used to replace the MARK
*field-name
clause). The default conversion
rules contain a rule that creates a statusprop
property for each map field that is controlled by a control variable. The
adapter generator creates from this property a corresponding status variable
and a comment line that identifies the status variable as belonging to the
field.
The parameter data area of the map contains:
01 LIB-NAME (A8) 01 LIB-NAME-CV (C)
The parameter data area of the adapter will then contain:
* statusprop= STATUS_LIB-NAME-CV 01 LIB-NAME (A8) 01 STATUS_LIB-NAME-CV (A) DYNAMIC
The variable STATUS_LIB-NAME-CV
is
not yet known to the main program and must be defined there.
The replacement for the INPUT
statement is the
PROCESS PAGE
statement. In its simplest form, the
INPUT
statement just references the map. In this case, it is just
replaced by a PROCESS PAGE
statement with the corresponding
adapter.
Main program before conversion:
INPUT USING MAP 'MMENU'
Main program after conversion:
IF *BROWSER-IO NE 'RICHGUI' INPUT USING MAP 'MMENU' ELSE PROCESS PAGE USING 'AMENU' END-IF
The INPUT
statement can come with a message text that
is displayed in the status bar. There is no direct replacement for this
construction because the PROCESS PAGE
statement (in contrast to
the PROCESS PAGE UPDATE
statement) does not support the SEND
EVENT
clause.
Main program before conversion:
INPUT WITH TEXT MSG01 USING MAP 'MMENU'
Main program after conversion (no message will be displayed):
IF *BROWSER-IO NE 'RICHGUI' INPUT WITH TEXT MSG01 USING MAP 'MMENU' ELSE PROCESS PAGE USING 'AMENU' END-IF
The replacement for the REINPUT
statement is the
PROCESS PAGE UPDATE
statement. In its simplest form, the
REINPUT
statement comes with a message text that is displayed in
the status bar. In the converted code, this is handled by the SEND
EVENT
clause of the PROCESS PAGE UPDATE
statement.
Main program before conversion:
REINPUT [FULL] WITH TEXT MSG01
Main program after conversion:
IF *BROWSER-IO NE 'RICHGUI' REINPUT [FULL] WITH TEXT MSG01 ELSE PROCESS PAGE UPDATE [FULL] AND SEND EVENT 'nat:page.message' WITH PARAMETERS NAME 'type' VALUE 'E' NAME 'short' VALUE MSG01 END-PARAMETERS END-IF
The REINPUT
statement can come with a message number
and replacements. In this case, the message must be created from number and
replacements before it is sent to the status bar with the SEND
EVENT
clause.
This example uses a subprogram GETMSTXT
that builds
the message text from number and replacements.
Main program before conversion:
REINPUT [FULL] WITH TEXT *MSGNR, REPL1, REPL2
Main program after conversion:
IF *BROWSER-IO NE 'RICHGUI' REINPUT [FULL] WITH TEXT *MSGNR, REPL1, REPL2 ELSE CALLNAT 'GETMSTXT' MSTEXT MSGNR REPL1 REPL2 PROCESS PAGE UPDATE [FULL] AND SEND EVENT 'nat:page.message' WITH PARAMETERS NAME 'type' VALUE 'E' NAME 'short' VALUE MSTEXT END-PARAMETERS END-IF
The REINPUT
statement can come with a
MARK
clause in order to put the focus on a field. This case
requires that a statusprop
property is created for
the field during map conversion. The variable bound to the
statusprop
property is then used before the
PROCESS PAGE UPDATE
statement to set the FOCUS
to the
field.
Main program before conversion:
REINPUT [FULL] WITH TEXT MSG01 MARK *LIB-NAME
Main program after conversion:
01 STATUS_LIB-NAME-CV (A) DYNAMIC ... IF *BROWSER-IO NE 'RICHGUI' REINPUT [FULL] WITH TEXT MSG01 MARK *LIB-NAME ELSE STATUS_LIB-NAME-CV := 'FOCUS' PROCESS PAGE UPDATE FULL AND SEND EVENT 'nat:page.message' WITH PARAMETERS NAME 'type' VALUE 'W' NAME 'short' VALUE MSG01 END-PARAMETERS END-IF
The original application might contain checks for the content of
the system variable *PF-KEY
at arbitrary places in
the code. In order to handle function key events correctly in the converted
application, several things need to be achieved:
In response to the function keys, the converted application
must raise events that are named like the possible contents of
*PF-KEY
. This can be achieved by using a page
template such as NATPAGEHOTKEYS_TEMPLATE.xml which
contains the required hot key definitions.
A common local variable must be set up right after the
INPUT
or PROCESS PAGE
statement that contains either
the value *PF-KEY
or
*PAGE-EVENT
, depending on the execution
environment. The name of the variable can be freely chosen. In the example
below, the name XEVENT
is used.
The events nat:page.end
and
nat:browser.end
must be handled in such a way so that the program
terminates. See also Built-in Events and User-defined
Events.
A default event handler must be set up that takes care of the
values of *PAGE-EVENT
that are not expected by the
original application code. These unexpected events are simply replied with a
PROCESS PAGE UPDATE FULL
statement.
01 XEVENT (U) DYNAMIC ... PROCESS PAGE USING ... ... IF *BROWSER-IO = 'RICHGUI' DECIDE FOR FIRST CONDITION WHEN *PAGE-EVENT = 'nat:page.end' STOP WHEN *PAGE-EVENT = MASK ('PF'*) OR = MASK ('PA'*) OR = 'ENTR' OR = 'CLR' XEVENT := *PAGE-EVENT WHEN NONE PROCESS PAGE UPDATE FULL END-DECIDE ELSE XEVENT := *PF-KEY END-IF
All references to *PF-KEY
in the code
must then be replaced by references to XEVENT
.
Natural for Ajax provides two controls (NJX:BUTTONITEMLIST and NJX:BUTTONITEMLISTFIX) that represent a row of buttons. These controls can be used to replace the visual representation of the function keys from the original application. If the page template NATPAGEPFKEYS_TEMPLATE.xml or a similar individually adapted template is used during map conversion, each resulting page will contain a row of function key buttons. The subject of this section is how the converted application can control the labeling and the program-sensitivity of the function keys with only little code changes.
Natural controls the labeling and program-sensitivity of the
function keys in a highly dynamic way. The corresponding application code
(SET KEY
statements) can be distributed across program levels and
can be lexically separated from the corresponding INPUT
statements. Also, the SET KEY
statement has several flavors, some
affecting all keys and others affecting only individual keys. As a result, the
status of the function keys at a given point in time can only be determined at
application runtime.
Therefore, the following approach is chosen: Natural provides the
application programming interface (API) USR4005
that reads the
current function key naming and program-sensitivity at runtime. During code
conversion, a call to this API is inserted after each SET KEY
statement or into each round trip. This call reads the function key status and
passes it to the user interface.
Main program before conversion:
SET KEY ENTR NAMED 'Enter' PF1 NAMED 'F1' PF2 NAMED 'F2' PF3 NAMED 'Modify' PF4 NAMED 'Delete' PF5 NAMED 'F5' PF6 NAMED 'F6' PF7 NAMED 'Create' PF8 NAMED 'Display' PF9 NAMED 'F9' PF10 NAMED 'F10' PF11 NAMED 'F11' PF12 NAMED 'F12' * INPUT USING MAP "KEYS-M" * END
Map before conversion:
*** PF-Keys *** Enter-PF1---PF2---PF3---PF4---PF5---PF6---PF7---PF8---PF9---PF10--PF11--PF12--- Enter F1 F2 Modif Delet F5 F6 Creat Displ F9 F10 F11 F12 |
Main program after conversion:
DEFINE DATA LOCAL 1 PFKEY (1:*) 2 METHOD (A) DYNAMIC 2 NAME (A) DYNAMIC 2 TITLE (A) DYNAMIC 2 VISIBLE (L) 1 METHODS (A4/13) CONST <'ENTR','PF1','PF2','PF3','PF4', 'PF5','PF6','PF7','PF8','PF9','PF10','PF11','PF12'> END-DEFINE * SET KEY ENTR NAMED 'Enter' PF1 NAMED 'F1' PF2 NAMED 'F2' PF3 NAMED 'Modify' PF4 NAMED 'Delete' PF5 NAMED 'F5' PF6 NAMED 'F6' PF7 NAMED 'Create' PF8 NAMED 'Display' PF9 NAMED 'F9' PF10 NAMED 'F10' PF11 NAMED 'F11' PF12 NAMED 'F12' * IF *BROWSER-IO NE "RICHGUI" INPUT USING MAP "KEYS-M" ELSE EXPAND ARRAY PFKEY TO (1:13) METHOD(1:13) := METHODS (*) CALLNAT "GETKEY-N" PFKEY (*) PROCESS PAGE USING "KEYS-A" END-IF * END
Page after conversion:
The structure PFKEY
is generated into the Natural
adapter of the page as the application interface to the BUTTONITEMLISTFIX
control.
The subprogram GETKEY-N
is a convenience wrapper for
the API subprogram USR4005
. It uses USR4005
to
determine the labeling and the program-sensitivity status for a given list of
function keys. Each function key is identified by the *PF-KEY
value it raises. GETKEY-N
returns the function key information in
a data structure suitable for the application interface of the
BUTTONITEMLISTFIX control. The subprogram is delivered in source code with the
Natural for Ajax demos and can be adapted to the needs of the application.
To use grid controls like TEXTGRIDSSS2 and ROWTABLEAREA2, you need
to bind the griddataprop
attribute to an array
structure at level 1. For the example Natural data definitions below the
griddataprop
attribute needs to be bound to the
level1
field.
1 level1 (00001:00005) 2 arrayfield1 (a10) 2 arrayfield2 (a10)
1 level1 2 arrayfield1(a10/00001:00005) 2 arrayfield2(a10/00001:00005)
Natural however, also allows to have a combination of single fields and arrays as shown in the following example:
1 level1 2 field1 (a10) 2 arrayfield1(a10/00001:00005) 2 arrayfield2(a10/00001:00005)
To bind a TEXTGRIDSSS3 or ROWTABLEAREA2 to structures as shown in example 3 you basically have two options:
Change the original Natural data definition structure, which is usually the preferred and recommended way.
Add an extra set of variable definitions to your Natural code like:
1 level1x 2 field1 (a10) 1 level1 2 array1(a10/00001:00005) 2 array2(a10/00001:00005)
You may need to add extra Natural code to transfer the values
to/from the original fields. However, if the Natural source code only
references the variables without level 1 qualifiers (for example, using
reset array1(*)
instead of reset level1.array1(*)
) no
source change is required except for the initial data definitions.
If Option 1 is not possible, the convrulesCVVariables.xml example rules file offers semi-automated support for Option 2. It automatically splits the original structure into two and adds an "x" to the name of the newly created structure for the non-array fields in the adapter and adapter interface as shown in Option 2.
The Natural maps in the application to be converted may contain processing rules. In the sense of a Natural for Ajax application, the processing rules are server-side validations because they are executed on the Natural server side of the application.
In order to extract processing rules from the maps and to turn them into server-side validations in the converted application, the Natural Engineer function "Separate Processing Rules from Maps" can be used.
There is currently no function available that automatically turns processing rules into client-side validations in Application Designer.
If a map displays a system variable (for example,
*DATX
), a specific default conversion rule takes
care that the necessary code for handling the system variable is generated into
the Natural adapter of the resulting page layout.
The map displays the contents of the system variables
*DATX
and *TIMX
. The
contents of these system variables are not modifiable.
The DEFINE DATA
statement of the adapter will then
contain:
LOCAL 01 XDATX (A8) 01 XTIMX (A8)
The body of the adapter will then contain:
XDATX := *DATX XTIMX := *TIMX * PROCESS PAGE ... WITH PARAMETERS ... NAME U'XDATX' VALUE XDATX NAME U'XTIMX' VALUE XTIMX END-PARAMETERS
The main program needs no special adaptation.
The map displays the content of the system variable
*CODEPAGE
. The content of this system variables is
modifiable.
The DEFINE DATA
statement of the adapter will then
contain:
LOCAL 01 XCODEPAGE (A64)
The body of the adapter will then contain:
XCODEPAGE := *CODEPAGE * PROCESS PAGE ... WITH PARAMETERS ... NAME U’XCODEPAGE’ VALUE XCODEPAGE ... END-PARAMETERS * *CODEPAGE := XCODEPAGE
The main program needs no special adaptation.
A similar procedure applies to special characters contained in variable names. These are the following special characters:
+
#
/
@
§
&
$
Note:
The hash (#) can occur only as the first character.
Variables names containing these special characters cannot be
directly bound to Application Designer control attributes. A specific default conversion rule
replaces the names containing these special characters with configurable
replacements. The original field name is generated into the parameter data area
of the Natural adapter and a corresponding mapping is generated into the
PROCESS PAGE
statement of the adapter.
The map displays the variables #FIRST
and #LAST
.
The DEFINE DATA
statement of the adapter will then
contain:
DEFINE DATA PARAMETER 1 #FIRST (A16) 1 #LAST (A20)
The body of the adapter will then contain:
... PROCESS PAGE ... WITH PARAMETERS ... NAME U'HFIRST' VALUE #FIRST NAME U'HLAST' VALUE #LAST ... END-PARAMETERS
The main program needs no special adaptation.