Classes script
New instructions in the Sage X3 script language will enable the development partner to manage classes. They are described as follows:
1. Declare a Reference to an Instance
This is performed by the following instruction:
Local Instance MYINSTANCE Using C_CLASSNAME
This is a “pointer” and its default value is a null pointer defined by the keyword
null
in the language. The Using C_CLASSNAME
option refers to an instance in which the class pointer is defined.
2. Create a Class Instance
The address of the generated class stored in MYINSTANCE
pointer uses the following instruction:
MYINSTANCE=Newinstance C_CLASSNAME AllocGroup Null
The allocation group can be given shared with another instance with the following syntax:
MYINSTANCE=Newinstance C_CLASSNAME AllocGroup OTHER_INSTANCE
When used, grouping of several instances of multiple classes can be managed globally and freed in a single instruction when no longer used.
C_CLASSNAME
has no parameters. The instance will be created and initialized by using the description in the current folder. If the instance must be created by using the context of another folder as the current one, parameters must be added. They are defined in the Notes and complements section.
3. Free Memory Used
To free the memory used by an instance called 'MY_INSTANCE':FreeInstance MY_INSTANCE
To free simultaneously an instance and all the instances having the same allocation group:FreeGroup MY_INSTANCE
4. Access a Property
To access the 'PROP' property of an 'INST' class instance, use the INST.PROP
syntax. This is used either to get the property value in a computation, or to assign a value to it with the `=`` operator.
If the property is a reference to a child class in which a property 'SUBP' exists, the access of a sub-property will be INST.PROP.SUBP
. If you use arrays of references to classes, the same syntax can be used, for example, a property accessed with the following syntax:
SALESORDER.LINE(5).DISCOUNT(3).RATE
This refers to the RATE property in the third element of the DISCOUNT collection for the instance associated to the fifth value of the LINE collection described in a class instance named SALESORDER.
5. Naming Conventions for Properties and Methods
Naming conventions exist for development partners when they create new items in dictionaries including classes, properties, and methods.
- All supervisor codes begin with the letter “A”.
- All generated item codes begin with the letter “W”. A development partner is not allowed to manually create codes in the dictionary using "W" as a first letter.
- All specific and vertical development codes must use the “X”, “Y” or “Z” as the first letter in the code.
- All application codes must begin with the remaining letters: “B” to “V”.
- Do not use the “U” on tables and classes.
- Some internal methods exist in the supervisor layer. Their name starts with an underscore followed by the letter "A". Be aware that these methods may change for any technical reason without notice. They should not be used by application codes. Application internal methods should also start with an underscore followed by a letter between "B" and "V".
6. Global Assignment
When a table stores the data associated with properties defined in a class instance, a global assignment from a class instance to the corresponding properties can be made by the syntaxes:SetInstance [table_abbreviation] With MYINSTANCE
SetInstance MYINSTANCE With [table_abbreviation]
7. Collections and Child Classes
When a single property of a class is a member of a collection, 'PROPERTY(index_value)' is no longer used to access the different values stored in the collection. An intermediate child class array, called 'C_CLASS_COLLECTION', is created to manage the property and the access to the (index_value) instance will be done by MYCLASSINSTANCE.COLLECTION(index_value).PROPERTY
.
For variables declared as arrays out of a class, 'VARNAME(index_value)' is still used and the declaration of this array can be done without any size limit. When this happens, an assignment can be done on VARNAME(index)
, and the memory array storing 'VARNAME' instance will be dynamically enlarged. A new function, maxTab(VARNAME)
, gives the maximum index that has been assigned.
The following example declares a variable collection named 'UNLIMITED_ARRAY' of integers:
Local Integer UNLIMITED_ARRAY(1..)
A child class instance pointer array declared in a main class has the same capabilities: it is managed as an unlimited array, so an assignment on
CHILDINSTANCE(index)
can be done, and maxTab(CHILDINSTANCE)
will also be used.
Note
Make sure that the SetInstance
instruction does not transfer the array found in an [F] table buffers to the class and vice versa. For example, if in the [F:ORD] table we have an array of sales rep codes called REP(0..2) and if REP is the name of the collection, the property in 'MYORD' instance will be MYORD.REP(I).REP
. A SetInstance MYORD With [F:ORD]
will not transfer the REP values from [F:ORD] to MYORD. You will have to add the following lines:
For I=1 to dim([F:REP])
MOYORD.REP(I)= NewInstance C_SALESORDER_REP AllocGroup MYORD
MYORD.REP(I).REP=[F:REP]REP(I-1)
Next I
If you have several values in the same collection, for instance REP, REPNAME, and COMRATE, you will have to perform three assignments:
Local Integer I
# Assignment loop
For I=1 to dim([F:REP])
MOYORD.REP(I)= NewInstance C_SALESORDER_REP AllocGroup MYORD
MYORD.REP(I).REP=[F:REP]REP(I-1)
MYORD.REP(I).REPNAME=[F:REP]REPNAME(I-1)
MYORD.REP(I).COMRATE=[F:REP]COMRATE(I-1)
Next I
When the CRUD code is generated by the supervisor at class validation, the assignment lines for the arrays present in [F] classes are generated.
8. Example of Code
If 'SORDER [SOH]' stores the sales order header, 'SORDERP [SOP]' stores the sales order details, 'SALESORDER' is the class, and 'SORDERLINE' the child class storing the lines, reading a sales order could be done by a program like the following:# Declarations
Local File SORDER [SOH], SORDERP [SOP]
Local Instance MYORDER C_SALESORDER
Local Integer LINE_NUM
# Let’s instantiate the classes and read data in the database
MYORDER=NewInstance C_SALESORDER AllocGroup Null
Read [SOH]SOHNUM = “123456”
SetInstance MYORDER With [SOH]
LINE_NUM=0
For [SOP] Where SOHNUM=”123456”
LINE_NUM+=1
MYORDER.LINES(LINE_NUM)= NewInstance SORDERLINE AllocGroup MYORDER
SetInstance MYORDER.LINES(LINE_NUM) With [SOP]
MYORDER.AORDER=LINE_NUM : # Display order if used with a representation
Next
# The data can now be used and updated. A loop on the lines would be for example done by
For LINE_NUM=1 to maxTab(MYORDER.LINES)
If MYORDER.LINES(LINE_NUM)<>null : # This should always be the case here
…
Endif
Next LINE_NUM
# When everything is finished, let’s free the memory
FreeGroup MYORDER
In most cases, the development partner will not have to write the code because the generation of the CRUD operation on classes is automated when a class is validated. Even complex updates on nested parent, child, grand-child classes are automated. The same program could have been written with the following lines:# Declarations
Local File SORDER [SOH], SORDERP [SOP]
Local Instance MYORDER Using C_SALESORDER
Local Integer RESULT
# Now let’s instantiate the classes
MYORDER=NewInstance C_SALESORDER AllocGroup Null
# Please read the data for me !
RESULT= fmet MYORDER.AREAD("12345")
Notes
Technical implementation of class instantiation
The instantiation of a class automatically calls a constructor method that performs the initialization of some properties in the class.
The default constructor assumes the class is instantiated by using the class definition of the current folder. If a development partner needs to open a class definition located in another folder, it can be done by adding parameters to the Newinstance instruction. It then becomes:
MYINSTANCE=Newinstance =expression_returning_a_character_string , C_CLASSNAME(CTX,UID,LINE,IPA,PPA)
Where:
CTX
is the context associated with the folder where the description is located. If the instance created is a child instance of an instance called 'MYINSTANCE' and already instantiated for the same folder, the parameter value will be 'MYINSTANCE.ACTX'.UID
is a unique ID associated with the instance and is useful when several child instances exist. If NullUuid is sent, a unique ID will be assigned for the instance.LINE
is a line number transmitted to the instance '(property AORDER)'. This is also used when several child instances exist that give a number stored in 'AORDER' property. This property will be used by default when the class content is displayed in a representation (the display order for the lines).IPA
is the parent instance if the class is a child instance.PPA
is the name of the parent instance in the parent class if the class is a child instance.
The following is an example for a sales order header and line instantiation:
# Let's imagine MYACTX is a dedicated context instance
#
Local Instance MYORDER Using C_SALESORDER
Local Integer I,N
# Let's instantiate MYORDER
# MYORDER is the main instance, so no parameter linked to a parent instance has to be defined
#
MYORDER = Newinstance [ORDER], C_SALESORDER(MYACTX,NullUuid,0,Null,"")
# In the next lines, 'N' is somewhere assigned to define the number of line to insert
...
#
# Let's imagine we need to create N lines in a loop : the line property array instance is MYORDER.LINES()
#
For I=1 To N
MYORDER.LINES(I) = Newinstance =MYORDER.ALLOCGRP, C_SALESORDER(MYORDER.ACTX,NullUuid,I,"LINES")
Next I