Report program language source code translation to object-oriented language source code which emulates report program language behavior6467079Abstract A computer-implemented method in which report program language is converted to object-oriented source code, such as Java, using the report program language compiler. The object-oriented source code emulates the behaviour of the report program language, such as VARPG. Applications written in RPG are converted to Java and therefore can run on every platform for which a Java virtual machine exists. RPG programmers now have the ability to write internet applications. Java applications and applets can be written in RPG and existing RPG applications can be converted to Java applets. Claims The embodiments of the invention in which an exclusive property or privilege is claimed are defined as follows: Description BACKGROUND OF THE INVENTION
Component class components. Contains all the
methods used for
Instantiated by the constructor for the VARPG performing GUI operations.
application class for NOMAIN and EXE
components. Used for component wide RpgLang
operations, such as indicating what state the This class holds most of the
methods required by the
component is in. pure RPG language. For example,
methods implementing MOVEL would be
in this
GuiComponent class class. All of the methods in this
class are static
Extends Component class. Instantiated when methods. It is used extensively
by the generated Java
initializeComponent is called for Visual source code, especially for
character operations.
RpgNumeric
This class holds almost all of the methods PrinterFile
required to perform operations involving the Extends RpgFile, Contains the
methods and data
Packed, Zoned, Binary, and Unsigned numeric required to support PRINTER
files.
data types, as well as some static methods that
can be called when manipulating float data. A RemoteDiskFile
BigDecimal instance variable contains the value Extends DiskFile. Contains
the methods and data
of the numeric. Two int variables contain the common to host files.
declared number of digits and decimal places for
the VARPG field. LocalFile
Extends DiskFile. Contains the
methods and data
common to local files.
RpgPacked
Extends RpgNumeric class. Contains all the FixedLengthLocalFile
methods specific to dealing with the Packed Extends LocalFile. Contains the
methods and data
Decimal data type. required to support local files
with fixed length
records.
RpgZoned
Extends RpgNumeric class. Contains all the VarLengthLocalFile
methods specific to dealing with the Zoned Extends LocalFile. Contains the
methods and data
Decimal data type. required to support local files
with varying length
records.
RpgBinary
Extends RpgNumeric class. Contains all the RemoteKeyedDiskFile
methods specific to dealing with the Binary data Extends RemoteDiskFile.
Contains the methods and
type. data required to support keyed host
files.
RpgUnsigned RemoteNonKeyedDiskFile
Extends RpgNumeric class. Contains all the Extends RemoteDiskFile. Contains
the methods and
methods specific to dealing with the Unsigned data required to support
non-keyed host files.
data type.
VarLenFld SubfileFile
Contains all the methods required to support the Contains the methods
required to support GUI
Varying Length Character datatype. The length subfiles.
is saved in an instance variable of type int. A
byte array contains the data. The size of the byte RpgRemoteCall
array is equal to the maximum size declared for This class contains the
methods required to perform
the VARPG varying length field. a call to a program on the host,
and also the methods
required to retrieve the host time.
All of the methods
RpgFile in this class are static.
Contains the methods and data common to all
VARPG file types. RpgDataArea
This class contains the data and
methods required to
DiskFile support data areas. It uses the
RpgRemoteCall class
Extends RpgFile. Contains the methods and to call the VARPG program on the
host which
data common to DISK files. actually performs the data area
operations.
RpgDate RpgException and RpgFileException
This class contains all the methods required to These two objects are
constructed when an
support the Date, Time, and Timestamp data exception occurs.
types. All of the methods in this class are static.
RpgEditNumeric
ExceptionHandler This class is used to edit numeric
data for
This class contains all of the methods required to output. All of the
methods in this class are static.
support VARPG-like exception handling.
Mapping of VARPG Datatypes to Java Datatypes VARPG datatypes are converted or mapped to Java datatypes. A byte array was chosen for character data over StringBuffer or char array to ensure the length of the field remains static throughout execution of the program. The use of byte array also maintains the same number of bytes of storage as the equivalent VARPG datatype. Because there is no equivalent Java datatype for numeric types Binary, Packed, Zoned, and Unsigned, these datatypes are represented by runtime classes that are all subclassed from the class RpgNumeric which contains the bulk of the methods to support their RPG behavior. These subclasses ensure that both the whole number portion and the precision of the numeric value fits into the declared size for the field. In VARPG, null capable fields are implemented as a field value and a separate indicator value which indicates if the field should be considered to have a null value at the moment. The Java source code conversion implements a similar design. Null-capable fields are handled as if they were normal fields but are provided with a separate null indicator value. This null indicator is set and used when the field is read or written to a corresponding null capable field in the remote server, preferably an AS/400, file. The null indicator value is available to the application programmer for checking, and setting, just as it is when targeting a Windows object. The mapping of VARPG datatypes to Java datatypes is presented in the following table.
Datatype on
VARPG Datatype D-spec Size Java Datatype
Fixed Character (xA) x*A x byte[]
Varying Character (xA) xA x VarLenFId class
VARYING
Indicator N 1 byte[]
Date, Time, Timestamp D, T, Z Depend byte[]
on format
Binary xB RpgBinary class
Float 4F or 8F float or double
Integer 5I or 10I short or int
Packed xP RpgPacked class
Unsigned 5U or 10U RpgUnsigned class
Zoned xS RpgZoned class
Graphic xG NOT SUPPORTED
*x is the number of characters or digits.
Translation of Operation Codes The vast majority of VARPG operation codes are executed by calling into one of the runtime classes. The methods in the runtime classes have been implemented in such a way that the expected VARPG behavior will occur when the operation is executed. When the VARPG source code calls a non-Java external procedure, such as a C function, the appropriate Java source code is generated for a function call through the Java Native Interface (JNI). The application programmer is responsible for providing the appropriate call target program on the native system side, in accordance with the JNI specifications.
ADD For RpgNumeric types, converted to methods. CALL Method
in RpgRemoteCall
method in RpgNumeric class. For class.
other types, Java + operator BEGSR All user subroutines are
converted to methods. CALLP If to
subprocedure or Java
ADDDUR Method in RpgDate class method, then
a method call. If to a
BITOFF Method in RpgLang class. native
(non-Java) function, then a
ANDxx Java && operator Java Native
Interface call (see
BITON Method in RpgLang class. below).
BEGACT All action subroutines are
CASxx Java logical operator, KLIST As for
Windows (compile
depending on xx. DOUxx Java do-while statement time
operation)
CAT Method in RpgLang class. DOW Java while statement LEAVE Java
break statement
CHAIN Method in the appropriate DOWxx Java while statement LOOKUP
Method in RpgLang
RpgFile class. class
DSPLY Method in GuiComponent
CHECK Method in RpgLang class. class. MOVE Method
in RpgLang or
RpgDate.
Method used depends on
CHECKR Method in RpgLang class. ELSE Java else statement the
datatypes of the source and target
of the
operation.
CLEAR If clearing a record, ENDyy Java end block (})
method in the generated Java class. MOVEA
Method in RpgLang class
If clearing a window, generated ENDACT Java end method (})
method in the Java class which in MOVEL
Method in RpgLang or
turn uses a method in the ENDSR Java end method (}) RpgDate.
Method used depends on
GuiComponent class. If clearing a the
datatypes of the source and target
field, inline Java code, method in EVAL Assignment is done of the
operation.
RpgNumeric class, or method in according to datatype. RPG
RpgDate class. behaviour is preserved, meaning that MULT
For RpgNumeric types,
numerics retain their attributes and method
in RpgNumeric class--For
CLOSE Method in appropriate character fields retain their length. other
types, Java * operator.
RpgFile class.
EXCEPT Except method is MVR For
RpgNumeric types,
CLSWIN Method in GuiComponent generated containing calls to the method in
RpgNumeric class. For
class. output method for each record to be other
types, remainder is calculated
written when the EXCEPT occurs. based on
operands to previous DIV
COMMIT Method in appropriate operation,
which were saved.
RpgFile class. EXSR Java method invocation
OCCUR Java
integer assignment
COMP If a native Java type, inline EXTRCT Method in RpgDate class OPEN
Method in appropriate
code. If numeric, method in RpgFile class
RpgNumeric class. If DTZ, method FEOD Method in appropriate
in RpgDate class. If character, RpgFile class ORxx Java II
operator
method in RpgLang class.
GETATR Method in OTHER Java
default case or final
DEFINE As for Windows (compile GuiComponent class else clause
time operation)
IF Java if statement OUT Method in
RpgDataArea
DELETE Method in appropriate class.
RpgFile class IFxx Java if statement
PARM As for
Windows (compile
DIV For RpgNumeric types, method IN Method in RpgDataArea class time
operation)
In RpgNumericclass. For other
types, Java/operator. ITER Java continue statement PLIST As for
Windows (compile
time
operation)
DO Java do statement KFLD As for Windows (compile
time operation) POST
Appropriate method in
DOU Java do-while statement RpgFile class
SETATR Method in TESTN Method
in RpgLang class.
READ If reading a record, method GuiComponent class
in the appropriate RpgFile class. If TESTZ
Method in RpgNumeric
reading a window, generated method SETGT Appropriate method in class.
in the Java class which in turn uses a RpgFile class.
method in the GuiComponent class. TIME If
local time, method in
SETLL Appropriate method in RpgDate
class. If time from host,
READC Method in SubfileFile RpgFile class. method in
RpgRemoteCall class.
class.
SETOFF Inline Java code UNLOCK Method
in appropriate
READE Method in RpgFile
class.
RemoteKeyedDiskFile class. SETON Inline Java code
UPDATE Method
in appropriate
READP Method in the appropriate SHOWWIN Method in RpgFile
class.
RpgFile class. GuiComponent class
WHEN Java
if/else if/else statement
READPE Method in
RemoteKeyedDiskFile class. SORTA Method in RpgLang class WHENxx Java
if/else if/else
statement
READS Method in SubfileFile SQRT For RpgNumeric types,
class. method in RpgNumeric class. For WRITE If
writing a record, method
other types, method in Java Math in the
appropriate RpgFile class. If
RESET If resetting a record, class. writing a
window, generated method
method in the generated Java class. in the
Java class which in turn uses a
If resetting a window, generated START Method in GuiComponent method in
the GuiComponent class.
method in the Java class which in class
turn uses a method in the XFOOT Inline
Java code in
GuiComponent class. If resetting a STOP Method in GuiComponent
conjunction with any methods used
field, inline Java code, method in class for ADD
RpgNumeric class, or method in
RpgDate class. SUB For RpgNumeric types, XLATE Method
in RpgLang class.
method in RpgNumeric class. For
RETURN Java return statement other types, Java-operator Z-ADD For
RpgNumeric types,
method in
RpgNumeric class. For
ROLBK Method in appropriate SUBDUR Method in RpgDate other types,
Java assignment
RpgFile class. class. operator.
SCAN Method in RpgLang class. SUBST Method in RpgLang class. Z-SUB For
RpgNumeric types,
method in
RpgNumeric class. For
SELECT Java if/else if/else TEST Method in RpgDate class. other types,
Java assignment
statement TESTB Method in RpgLang class. operator.
Translation of Builtin Functions As for operation codes, most of the Builtin functions are evaluated by calling into the runtime classes.
% ABS Depending on the type, class. % STATUS Method in
RpgFile
either a method in RpgNumeric class or in line
Java code,
class or in the Java Math class. % FOUND Inline Java code. depending on if
a file parameter is
present.
% CHAR A non-operation % GETATR Method in
GuiComponent class. % SUBST Method in
RpgLang
% DEC Method in RpgNumeric class.
class % INT Depending on the
datatype of the operand, method % TRIM Method
in RpgLang
% DECH Method in in RpgNumeric or Java Math class.
RpgNumeric class class.
% TRIML Method in
RpgLang
% DECPOS Same as in % INTH Depending on the class.
Windows (compile time function) datatype of the operand, method
in RpgNumeric or Java Math % TRIMR Method in
RpgLang
% EDITC Method in class. class.
RpgEditNumeric class.
% LEN Either a compile-time % UNS Depending on
the
% EDITFLT Method in operation, or the length attribute datatype of
the operand, method in
RpgNumeric class. of a byte array. RpgNumeric or Java
Math class.
% EDITW Method in % OPEN Method in RpgFile % UNSH Depending on
the
RpgEditNumeric class. class. datatype of the
operand, method in
RpgNumeric or Java
Math class.
% EOF -- method in RpgFile % REPLACE Method in
class. RpgLang class. % ELEM Same as in
Windows
(compile-time
function)
% EQUAL Inline Java code % SCAN Method in RpgLang
class. % NULLIND Inline
Java code
% ERROR Inline Java code
% SETATR Method in % SIZE Same as in
Windows
% FLOAT Depending on the GuiComponent class. (compile-time
function).
datatype of the operand, method
in RpgNumeric or Java Math
Implementation of Host (Remote) Files The method of generating Java source code from VARPG code described herein may be implemented on any server, preferably an AS/400. The actual source conversion occurs on a Windows platform, although the invention could be implemented on any platform. The AS/400 Toolbox for Java provides Java class support for AS/400 database file access and AS/400 program calls and so the VARPG runtime classes that support host file operations also use the AS/400 Toolbox for Java support. The AS/400 Toolbox classes have been enhanced to support a full range of RPG file operations. The runtime uses the AS/400 Toolbox classes. The generated Java source code handles field movement between program values and record buffers but still calls VARPG runtime class methods for file operations. Exception Handling When an RPG runtime error occurs, the RPG compiler first checks for an error indicator or error operation code extender. If the error indicator or error operation code extender is present, it is set and the method continues to execute from the next RPG statement. If there is no error indicator or error operation code extender there is a check for the Program Status SubRoutine (*PSSR). If the subroutine is present, then the method will call it and the user will indicate where control should resume in the VARPG code. If neither the error indicator or error operation code extender nor the *PSSR is present, the default exception handler is called. The default exception handler displays an error message in a dialog box and the user will respond to several choices. This behavior must be maintained in the Java application. An implementation with C uses setjmp/longjmp whereas in Java, the try/catch model must be used. Two exception subclasses were designed: a general RPG exception class and a file error specific class. These exceptions occur when errors are detected both in the generated Java source code and in the VARPG runtime classes. Java source code is generated to handle the exceptions according to the presence of error indicator or error operation code extenders, and presence of a *PSSR subroutine (INFSR subroutine for file errors). Generation of Java Source Code from VARPG Source Code The creation of the basic building blocks for the generation of the Java source code from the VARPG source code have been delineated. Now it is time to see how the RPG compiler actually generates the Java source code from RPG source code. In designing the generated source code, the following decision points are maintained: (1) structure of the generated Java source; (2) the VARPG runtime classes; (3) exception handling; (4) datatypes; (5) translation of operation codes; and (6) translation of builtin functions. The Java source code generated from the VARPG source code is based on one of the following models, depending on the type of VARPG project. The italicized lines of code below represents a sample skeleton of the generated Java source code. Recall that VARPG has three components or project types: VISUAL, NOMAIN, and EXE. For a VARPG VISUAL project, a component name is given to the Java public class that will be generated. public class <ComponentName> { The VARPG compiler then generates the Java instance variables, which most likely are private but in some instances could be public. These instance variables are internal variables which preserve the VARPG behaviour in the Java source code and are generated for every application. //Compiler generated instance variables private . . . private . . . All the VARPG global fields are converted to Java instance variables. //All global fields are converted to instance variables private . . . private . . . The VARPG compiler than generates the main method, i.e., the main initialization function. //main method starts the GUI runtime and exits public static final void main( ) The translation then converts the input and output specifications of the VARPG project. In Windows, this stage is usually invisible to the user but with the program herein described the input and output specifications are exposed. //Methods for reading and writing records and windows and //methods for clearing and resetting records and windows private internalMethod1( . . . ) private internalMethod2( . . . ) The action subroutines and user subroutines, that contain calculation specifications, are converted to Java methods. //Action subroutines and user subroutines public actionSubroutine1( . . . ) public actionSubroutine2( . . . ) private subroutine1( . . . ) private subroutine2( . . . ) //Subprocedures private procedure1( . . . ) private procedure2( . . . ) Then, a constructor method for the application class is generated. The constructor instantiates and initializes the global variables. //Constructor public ComponentName( ) The methods required for interfacing with the GUI runtime are generated. These methods are not generated from user logic, i.e., they are not present in the VARPG source code. //Methods required for interfacing with GUI runtime public initializeComponent public queryVersion public componentInitialized public closingComponentObjects public terminatingComponent public processActionSubroutine Last, a method to handle errors is generated. //Methods required for exception handling private handleException( . . . ) } For a VARPG NOMAIN project, the code generation phase does not generate any Java source code for the main method, for running or interfacing with GUI runtime, or for the action and user subroutine calculation specification because a NOMAIN project does not have these functions. Therefore, code generation for a NOMAIN project is simplified. public class <ComponentName> { //Compiler generated instance variables private . . . private . . . //All global fields are converted to instance variables private . . . private . . . //Methods for reading and writing records and windows and //methods for clearing and resetting records and windows private internalMethod1( . . . ) private internalMethod2( . . . ) //Subprocedures. Private if not EXPORTed, public if EXPORTed private/public subprocedure1( . . . ) private/public subprocedure2( . . . ) //Constructor public ComponentName( ) //Methods required for exception handling private handleException( . . . ) } For a VARPG EXE project, the code generation phase does not generate any Java source code for running or interfacing with GUI runtime because an EXE project does not have these functions. Therefore, code generation for a EXE project is also simplified. Note that for both NOMAIN and EXE components, any initialization that is normally performed in the initializeComponent method of VISUAL projects takes place in the constructor. public class <ComponentName> //Compiler generated instance variables private . . . private . . . //All global fields are converted to instance variables private . . . private . . . //Methods for reading and writing records and windows and //methods for clearing and resetting records and windows private internalMethod1( . . . ) private internalMethod2( . . . ) //main method public staticfinal <type> main( . . . ) //Subprocedures. private if not EXPORTed, public if EXPORTed private/public subprocedure1( . . . ) private/public subprocedure2( . . . ) //Constructor public ComponentName( ) //Methods required for exception handling private handleException( . . . ) } For all component types, the compiler generated instance variables which preserve the VARPG behaviour include:
//The indicator array (*1N01 to *1N99, LR)
byte[] indicatorArray[ 100];
//One of the following
Component varpgComponent //NOMAIN and EXE
GuiComponent varpgComponent //GUI components
//For exception handling
ExceptionHandler varpgExceptionHandler;
//For exception handling
int lineNum;
//For interfacing with the VARPG toolbox
RemoteServerTable rstFile
Calling Java Methods It is useful to call Java methods from RPG. In order to do so, the VARPG compiler needs to know the following information: (a) the name of the method; (b) a syntax to specify a class name and a method signature; (3) if the method returns an object, the class of the returned object; (4) whether the method is a static method; and (5) the datatypes of the parameters passed to the method. If the method, moreover, is not a static method, then an object must be instantiated in order to call the method. If the method returns an object, then the compiler must have somewhere to store the returned object. If the method requires an object as a parameter, then there must be some way to create that object. One way to accomplish this is to add to the VARPG language the following: (a) the Object datatype; (b) the CLASS keyword; and an extension of the EXTPROC keyword. Fields that can store objects are declared using the new `O` datatype. When declaring a field of type `O`, `O` must be coded in column 40 of the D-specification, and the class of the object must be provided using the new CLASS keyword. The CLASS keyword accepts two parameters: CLASS (*Java:class name), where *Java identifies the object as a Java object, the class name specifies the class of the object. The class must be a character literal, and the class name must be fully qualified. The class name is case sensitive. To declare a field that will hold an object of type BigDecimal: D bdnum S O CLASS(*JAVA: `java.math.BigDecimal`) To declare a field that will hold an object of type String: D string S O CLASS(*Java: `java.lang.String`) Notice that both class names are fully qualified and that their case exactly matches that of the Java class. Fields of type O cannot be defined as subfields of data structures. It is possible to have arrays of type O fields but type O tables are not allowed because tables have to be preloaded at runtime. Certain keywords cannot be used with the CLASS keyword. The EXTPROC keyword has been extended and is used to specify the name of the method and the class to which it belongs. When prototyping a Java method, the expected format of the EXTPROC keyword is: EXTPROC(*JAVA or *JAVARPG:class name:method name) where *JAVARPG identifies the method as a Java method that was generated using VARPG. *JAVA identifies the method as a Java method that was generated from code originally written in Java, that is, not through VARPG. This distinction is important because methods generated from VARPG will allow certain datatypes to be passed by reference that normally cannot be passed by reference in Java. This allows the same source code to be used when targeting Windows and when generating Java source code. Both the class name and the method name must be a character literal. The class name must be a fully qualified Java class name and the method name must be the name of the method to be called; both are case sensitive. The extended form of the EXTPROC keyword can only be used when calling Java methods and will result in a compiler error if targeting Windows. The datatypes of the parameters and the return value of the method are specified in the same way as they are when prototyping a subprocedure. The only twist on this is that the datatypes actually map to Java datatypes. The compiler maps VARPG datatypes to Java datatypes in the following way:
Java datatype VARPG datatype
boolean indicator (N)
byte[] alpha (A of any length)
int integer (10I)
short integer (5I)
float float (4F)
double float (8F)
any object object (O)
Zoned, Packed, Binary, and Unsigned datatypes do not appear in the table because these datatypes are not available in Java. If a Zoned, Packed, Binary, or Unsigned field is passed as a parameter, the VARPG compiler will do the appropriate conversion, but this will most likely result in truncation and/or loss of precision. If*JAVARPG has been specified as the first parameter of the EXTPROC keyword, meaning that the method being called was generated by VARPG, then Packed, Zoned, Binary, and Unsigned datatypes can be specified as the datatype of parameters and return values. This can only be done for methods generated by VARPG. Methods generated from code originally written in Java do not have the capability to accept or return Packed, Zoned, Binary, and Unsigned fields. When calling a method, the compiler accepts arrays as parameters if the parameter is prototyped using the DIM keyword. Otherwise, only scalar fields, data structures, and tables will be accepted. If the return value of a method is an object, then the class of the object must be provided. This is done by coding the CLASS keyword on the prototype. The class name specified will be that of the object being returned. The class of the method being called is specified using the EXTPROC keyword. If the method being called is a static method, then the STATIC keyword must be specified on the prototype. In Java, some datatypes can only be passed by value. Datatypes that can only be passed by value are: int, short, float, and double. Parameters of these types must have the VALUE keyword specified for them on the prototype. If*JAVARPG has been specified as the first parameter of the EXTPROC keyword, meaning that the method being called was generated by VARPG, then these datatypes can be passed by reference and so the VALUE keyword is not required. Note that objects can only be passed by reference. The VALUE keyword cannot be specified with type `O` Since arrays are seen by Java as objects, parameters mapping to arrays must also be passed by reference. This includes byte arrays. EXAMPLES OF PROTOTYPING JAVA METHODS Example 1 The Java Integer class contains a static method called toString, which accepts an int parameter, and returns a String object.
String Integer.toString (int)
This method would be prototyped as follows:
D tostring PR O EXTPROC(*JAVA:`java.lang.Integer`:
D `toString`)
D CLASS('*JAVA':`java.lang.string`)
D STATIC
D num 10I 0 VALUE
In the above example, the EXTPROC keyword tells the compiler that the method was not generated by VARPG. It also indicates that the method name is `toString`, and that it is found in class `java.lang.Integer. The `O` in column 40 and the CLASS keyword tell the compiler that the method returns an object, and the class of that object is `java.lang.String`. The STATIC keyword tells the compiler that the method is a static method, meaning that an Integer object is not required to call the method. The datatype of the parameter is specified as 10I, which maps to the Java int datatype, and because the parameter is an int, it must be passed by value, and hence the VALUE keyword is specified. Example 2 This method accepts two objects as parameters. `O` is coded in column 40 of the D-specification, and the CLASS keyword specifies the class of each object parameter. The Java Integer class contains a static method called getInteger, which accepts String and Integer objects as parameters, and returns an Integer object. Integer Integer.getInteger(String, Integer) This method would be prototyped as follows:
D getint PR O EXTPROC(*JAVA:`java.lang.Integer`:
D `getInteger`)
D CLASS(`*JAVA`:`java.lang.Integer`)
D STATIC
D string O CLASS(*JAVA:`java.lang.String`)
D num O CLASS(*JAVA:`java.lang.Integer`)
Example 3 The Java Integer class contains a method called shortValue, which returns the short representation of the Integer object used to invoke the method. The STATIC keyword is not specified because the method is not a static method. The method takes no parameters, so none are coded. The return value is specified as 5I, which maps to the Javashort datatype.
short shortValue()
This method would be prototyped as follows:
D shortval PR 5I 0 EXTPROC(*JAVA:`java.lang.Integer`:
D `shortValue`)
Example 4 The Java Integer class contains a method called equals, which accepts an Object as parameter and returns a boolean. The return value is specified as N, which maps to the Java boolean datatype.
boolean equals(Object)
This method would be prototyped as follows:
D equals PR N EXTPROC (*JAVA:'java.lang.Integer':'equals')
D obj O CLASS (*JAVA:'java.lang.Object`)
Creating Objects In order to call a method that is not static, an object is required. The class of the object must be the same as the class containing the method. Objects are instantiated, or created, by calling the class constructor. The class constructor is not a static method, but it does not require an object to call it. The special method name *CONSTRUCTOR is used when prototyping a constructor.
For example: In order to construct a BigDecimal object from a float
value, the constructor expects that a float parameter must be called.
Notice
that the parameter must be passed by value because it maps to the
Java float datatype.
BigDecimal(float) returns a new BigDecimal object
D bdcreate PR O EXTPROC(*JAVA:'java.math.BigDecimal':
D *CONSTRUCTOR)
D CLASS(*JAVA:'java.math.BigDecimal`)
D dnum 4F VALUE
Calling Java Methods Java methods will be called using existing operation codes CALLP when no return value is expected and EVAL when a return value is expected. No new syntax is required. When calling a static method, an object is not required in order to make the call. But when calling a method that is not static, an object is required. The object to be used must be coded as the first parameter in the call. This parameter is not specified on the prototype, but is implied for all methods that are not static. This means that whenever a method that is not static is called, a minimum of one parameter must be specified.
Example: In this example, the goal is to add two BigDecimal values
together. In order to
do this, two BigDecimal objects must be instantiated by calling the
constructor for the
BigDecimal class, fields must be declared to store the BigDecimal
objects, and the add() method
in the BigDecimal class must be called.
D*
D* Prototype the BigDecimal constructor that accepts a String
parameter. It returns a
D* new BigDecimal object.
D*
D bdcreate1 PR O
EXTPROC(*JAVA:'java.math.BigDecimal`:
D *CONSTRUCTOR)
D
CLASS(*JAVA:'java.math.BigDecimal`)
D str O
CLASS(*JAVA:`java.lang.String`)
D*
D* Prototype the BigDecimal constructor that accepts a double
parameter, 8F maps to the
D Java double datatype and so must be passed by VALUE. It
returns a BigDecimal
D object.
D*
D bdcreate2 PR O
EXTPROC(*JAVA:`java.math.BigDecimal`:
D *CONSTRUCTOR)
D
CLASS(*JAVA:'java.math.BigDecimal`)
D double 8F VALUE
D*
D* Define fields to store the BigDecimal objects
D*
D bdnum1 S O
CLASS(*JAVA:`java.math.BigDecimal')
D bdnum2 S O CLASS(*JAVA:'java.math.
BigDecimal')
D*
D* A constructor requiring a String object will have to be
constructed. Prototype the
D* String constructor that accepts a byte array as a parameter.
It returns a String object.
D*
D makestring PR O EXTPROC(*JAVA:'java.lang
String`:.
D *CONSTRUCTOR)
D
CLASS(*JAVA:`java.lang.String`)
D bytes 10A
D*
D* Define a field to store the String object.
D*
D string S O
CLASS(*JAVA:'java.lang.String`)
D*
D* Prototype the BigDecimal add method. It accepts BigDecimal
object as a parameter and
D* returns a BigDecimal object (the sum of the parameter and of
the BigDecimal object used
D* to make the call.
D*
D add PR O
EXTPROC(*JAVA:'java.lang.BigDecimal`:
D `add`)
D
CLASS(*JAVA:`java.math.BigDecimal')
D bd1 O CLASS(*JAVA:`java.math
BigDecimal').
D*
D* Define a field to store the sum.
D*
D sum S O
CLASS(*JAVA:'java.math.BigDecimal')
D double S 8F INZ(1.1)
D fld1 S 10A
Here is the code that does the call:
C MOVEL `mystring" fld110
C*
C* Call the constructor for the String class, to create a String
object from fld1. Because we are
C* calling the constructor, we do not need to pass a String
object as the first parameter.
C*
C EVAL string = makestring(fld1)
C*
C* Call the BigDecimal constructor that accepts a String
parameter, using the String object we
C* just instantiated.
C*
C EVAL bdnum1 = bdcreatel(string)
C*
C* Call the BigDecimal constructor that accepts a double as a
parameter.
C*
C EVAL bdnum2 = bdcreate2(double)
C* Add the two BigDecimal objects together by calling the add
method. The prototype
C* indicates that add accepts one parameter, but because add is
not a static method, we must
C* also pass a BigDecimal object in order to make the call, and
it must be passed as the first
C* parameter. The object bdnum1 is used to make the call, and
bdnum2 is the parameter.
C*
C EVAL sum = add(bdnum1:bdnum2)
C* Sum contains a BigDecimal object with the value bdnum1 +
bdnum2.
To do a TRIM using Java instead of the VARPG %TRIM BIF, the trim( ) method found in the String class may be used. The trim( ) method is not a static method so a String object is needed to call the method.
D*
D* Define a field to store the String object we wish to trim
D*
D str S O
CLASS(*JAVA:'java.lang.String')
D*
D* Prototype the constructor for the String class. The
constructor expects a byte array.
D*
D makestring PR O
EXTPROC(*JAVA:'java.lang.String':
D *CONSTRUCTOR)
D
CLASS(*JAVA:'java.lang.String')
D parm 10A
D*
D* Prototype the String method getBytes which converts a String
to a byte array. We can then
D* store this byte array in an alpha field.
D*
D makealpha PR 10A
EXTPROC(*JAVA:jJava.lang.String':
D getBytes`)
D*
D* Prototype the String method trim. It doesn't take any
parameters, but since it is not a static
D* method, must be called using a String object.
D*
D trimstring PR O
EXTPROC(*JAVA:`java.lang.String`:`trim`)
D fld S 10A INZ(` hello `)
Now do the actual call.
C*
C* Call the String constructor.
C*
C EVAL str = makestring(fld)
C*
C* Trim the string by calling the String trim() method.
C* We will reuse the str field to store the result.
C*
C EVAL str = trimstring(str)
C*
C* Convert the string back to a byte array and store it in fld.
C*
C EVAL fld = makealpha(str)
Static methods are called in the same way, except that an object is not required to make a call. If the makealpha method above was static, the call would look like: C EVAL fld=makealpha( ) CALLP is used when the method does not have a return value The compiler will not attempt to resolve classes at compile time. If a class cannot be located at run time, a run time error will occur. It will indicate that an UnresolvedLinkException object was received from the Java environment. The compiler does not do any type checking of parameters at compile time. If there is a conflict between the prototype and the method being called, an error will be received at run time. It is very important that *JAVARPG be specified as the first parameter of EXTPROC if the method being called has been generated from VARPG. If this is not done, it is likely that one of the above two error situations will occur. Restrictions and Run Time Behaviour Differences When Generating Java Source Code The following VARPG language elements are not supported when generating Java source code:
Keywords: OVERLAY
ALIGN
STATIC on field definitions. STATIC is supported on
Java method prototypes.
EXPROPTS
Operation codes: TAG
GOTO
CABxx
ALLOC
REALLOC
DEALLOC
CALLB
DSPLY (not supported for NOMAIN and EXE only, it
is supported otherwise)
Operation extenders: M
R
Datatypes: Pointer datatype
File types: SPECIAL
File operations: Writing records by relative record number
Language Features: Embedded SQL statements.
In order to generate the Java source code, some changes may be required to the VARPG source. For instance, To/from notation is not allowed when defining data structure subfields. Exceptions to this are when defining subfields of the PSDS and INFDS. In fact, the to/from notation must be used when defining subfields of the PSDS and INFDS in order to allow the compiler to validate the subfield definitions. The definition of subfields in the INFDS and PSDS must match the definitions specified in the VARPG Language Reference. A compile time error will be issued if they do not. There cannot be an unconditional LEAVE or ITER operation as anything other than the last operation in a loop, otherwise the Java compiler issues an error. If there is an unconditional LEAVE or ITER operation in a loop, all operations occurring after it in the loop should be deleted because they will never be executed. When adding and subtracting date/time/timestamp durations, only values between maxint (2 147 483 647) and -maxint (-2 147 483 648) can be used. Because Java does not allow int (10I), short (5I), float (4F),and double (8F) values to be passed by reference, Java code has to be generated by VARPG to retain this functionality for subprocedures being converted to Java. The code generated to accomplish this can cause Java compiler errors when the VARPG source contains subprocedures with multiple return points and receives integer or float parameters passed by reference.
Sample code that may cause Java compile errors:
C IF x = 1
C ...
C RETURN 1
C ELSE
C ...
C RETURN 0
C ENDIF
This code should be changed to:
C IF x = 1
C ...
C RETURN 1
C ELSE
C ...
C ENDIF
C RETURN 0
More Restrictions and runtime behavior differences The characters `*`, `#`, and `@` cannot be contained in Java identifiers. Because of this, all occurrences of `*` `#` and `@` in VARPG names will be changed to `_`. It is possible that this will result in duplicate names. If a COMMIT or ROLBK operation is coded within an application that has no files, a severity 30 message (RNF7833) will be issued. Because of the way that a local *PSSR is converted to Java, it is not possible to call a local *PSSR. Because GOTO is not supported, the only way to leave a local *PSSR and avoid the default handler is to code a RETURN operation. There is no short circuiting of logical expressions so the order in which a compound logical expression is executed is not reliable. Varying length fields are implemented as a class when converting to Java so they are not stored as documented in the VARPG Language Reference. Code that relies on a certain storage format way will not work. Data structure subfields will not be initialized to blanks if there is no initial value provided, but will be initialized to a default value depending on the datatype of the subfield. The default value is 0 for numerics, blanks for character, and *LOVAL for date, time, and timestamp. Varying length fields will have their length set to 0. If a length is specified for a data structure, it must match the total length of the subfields it contains, otherwise the compiler will issue a sev 30 diagnostic message. Subroutines cannot be defined within subprocedures. The only exception is that a *PSSR can be defined within a subprocedure. Any subroutines within subprocedures should be moved outside the subprocedure. If the subroutine accesses local fields within the subprocedure, then either the fields need to be changed to global fields, or the subroutine should be changed to a subprocedure that accepts the local fields as parameters. Unconditional LEAVE statements within DO loops are not supported. A Java compiler error will occur if this situation exists. Since an unconditional LEAVE within a DO loop means that the loop will only ever be executed once, the LEAVE should be removed and the code changed to remove the loop operation codes. Using event attributes in fixed compound conditional statements currently causes Java compile errors. The equivalent freeform expression should be used instead and the code should be changed as follows:
Sample code that may cause Java compile errors:
C %mousex IFEQ x
C %mousey ANDEQ y
C ...
C ENDIF
This code should be changed to:
C IF %mousex = x AND
C %mousey = y
C ...
C ENDIF
An unconditional RETURN operation cannot be coded unless it is the last statement in a user subroutine, action subroutine, or subprocedure; otherwise, the Java compiler may report an error. SELECT statements can cause Java compile errors when they occur in subprocedures or contain RETURN operations and no RETURN is coded within the main body of the subprocedure. In general, a RETURN operation should be coded for all possible code paths of a subprocedure, otherwise the Java compiler may report errors.
Sample code that may cause Java compile errors:
C SELECT
C x WHENEQ y
C RETURN 1
C x WHENEQ z
C RETURN 2
C OTHER
C RETURN 0
C ENDSL
This code should be changed to:
C SELECT
C x WHENEQ y
C RETURN 1
C x WHENEQ z
C RETURN 2
C ENDSL
C RETURN 0
Arrays cannot be passed by value to subprocedures. Because of differences between the Windows and Java environments an application may run differently under Java than it does under Windows. The following areas are affected: The %SCAN builtin function will return an integer result, in Windows, it returns an unsigned result; the truncate numeric build option is unreliable. When an I/O exception occurs, the user will not be given the option to retry the operation. Data structures are not treated as one large character field when the Java application is running which may cause unexpected results. The format of binary, integer, and unsigned datatypes is handled differently for local files, e.g., when reading and writing local files the Java format of having the high order bytes being left most is assumed, whereas when running as a Windows application, they are right most. Exception handling for subprocedures will behave the same as for action subroutines and the default error handler is called if there is no local *PSSR or INFSR and no error indicator or error operation code extender on the operation. If an invalid date, time, or timestamp value is encountered when reading or writing a field to/from a file, the field will be set to the default value (*LOVAL) and no error is reported. Java can only handle a three digit millisecond portion in timestamps. When doing calculations with timestamps that use all six digits of the millisecond portion, i.e., they do not have milliseconds in the form 000xxx, the results might not be as expected. Intermediate results in expressions are not limited to thirty digits. In fact, when running in the VARPG environment, no attention is paid to the precision of intermediate results. Memory cannot be shared between components. If a component is started by another component via START, changes made to passed parameters are not reflected across components. Integer overflow/underflow will not be reported. Float overflow/underflow will be reported as status 9999. If an error occurs while a subprocedure in a NOMAIN or EXE application is being executed, and there is no error indicator or error operation code extender, or *PSSR, then the error will be reported back to the caller and handled by the caller. When running under Windows, the application would terminate. Positioning a host file to Null-Valued Records when ALWNULL(*NO) has been specified results in CPF5035. The following language elements are not supported when running a VARPG applet and will result in Java errors at run time: Printer files, Local files, Calling C functions, external subprocedures, EXEs. NOMAIN and EXE applications cannot be run as applets. Although a specific embodiment of the invention has been described herein in some detail, this has been done solely for the purpose of illustrating the invention in various of its aspects, and it is to be understood that the foregoing description does not limit the scope of the invention. It is contemplated that various substitutions, alterations and/or modifications to the embodiment of the invention disclosed herein, including but not limited to those implementation options specifically noted herein, may be made to the invention without departing from the spirit and scope of the invention as defined in the appended claims.
|
Same subclass Same class Consider this |
||||||||||
