Classes script

Declare a Reference to an Instance Create a Class Instance Free Memory Used
Access a Property Naming Conventions for Properties and Methods Global Assignment
Collections and Child Classes Example of Code Notes

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