Downtime Announcement: Please note the SAP Community Wiki will be unavailable due to a system upgrade on Thursday, September 24th between 6 and 7 AM CEST
Skip to end of metadata
Go to start of metadata

List of all pages

Pages at first level

Description: Field Symbol can hold run time object of type any and Runtime Type identification which is part of Runtime Type services can help us to identify the type of objects at runtime, including dictionary types and classes / objects.

Below is the code snippet which will explain you the use of Field symbol at run time and different way to cast the data objects type and the usage of RTTI.

Field symbols can be declared with specific types or can be declared as generic type

Part I:  Generically typed field symbols will have the run time type based on the 'type of data object assigned'.

For e.g if you have following structure defined in your program

Step 1)  

DATA: BEGIN OF spfli_key,
        carrid TYPE s_carr_id,
        connid TYPE s_conn_id,
      END OF spfli_key.
 

Step 2)

and if you want to identify the components of the structure or type of the structure at runtime, then

DATA: descr_ref TYPE REF TO cl_abap_structdescr,
      wa_comp TYPE abap_compdescr.
 

cl_abap_structdescr is the class defined by SAP under RTTI to identify the structure and components of the structure at runtime.

Step 3) 

At some part of your program, you may assign any strucutre to field symbol as below.

spfli_key-carrid = 'AA'.
spfli_key-connid = 800.

ASSIGN spfli_key TO <fs_any>.
 

Step 4)  call the static method of t he class typedescr, and import the field symbol created. Loop throgh the components and identify the name of the component.

descr_ref ?= cl_abap_typedescr=>describe_by_data( <fs_any> ).

WRITE: ' Structure components at run time :' .
SKIP 2.
WRITE: ' Field symbol will hold the data object assigned :' .

LOOP AT  descr_ref->components INTO wa_comp.
  WRITE: wa_comp-name.
ENDLOOP.

UNASSIGN <fs_any>.
 

Part II:  Generically typed field symbols can be casted at runtime by using the keyword, 'CASTING TYPE'. Data object assigned to the field symbol, will be type casted based on the runtime type specified.

Step 1: Follow the steps as before. and cast the field symbol defined as any to  any particular type at runtime, using 'CASTING TYPE' .

ASSIGN obj_spfli TO <fs_any> CASTING TYPE spfli_type.

descr_ref ?= cl_abap_typedescr=>describe_by_data( <fs_any> ).

WRITE: ' Field symbol will read the data object assign as per the casted type :' .
SKIP 2.

LOOP AT  descr_ref->components INTO wa_comp.
  WRITE: wa_comp-name.
ENDLOOP.
 
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*----this program is aimed for converting a character into currency format

DATA: v_dcpfm    TYPE usr01-dcpfm,
      v_amount   TYPE bseg-wrbtr,
      v_char(16) TYPE c.

SELECT SINGLE dcpfm FROM usr01
                    INTO v_dcpfm
                   WHERE bname = sy-uname.
IF v_dcpfm = 'X'.
*-- decimal point is '.' and thousands separator is ','
  TRANSLATE v_char USING ', '.
  CONDENSE v_char NO-GAPS.
  v_amount = v_char.
ELSEIF v_dcpfm = 'Y'.
*-- decimal point is ',' and thousands separator is '.'
  TRANSLATE v_char USING '. '.
  CONDENSE v_char NO-GAPS.
  v_amount = v_char.
ELSE.
*-- decimal point is ',' and thousands separator is space
  CONDENSE v_char NO-GAPS.
  v_amount = v_char.
ENDIF.

we can also use this function module HRCM_STRING_TO_AMOUNT_CONVERT


List of all pages

Pages at first level

*-------------------------------------------------------*
*  report name
*-------------------------------------------------------*

REPORT zchange_of_case .

*-------------------------------------------------------*
*   selection screen parameters
*------------------------------------------------------*

PARAMETERS: P_STR TYPE CHAR100 .

*-------------------------------------------------------*
*      data declarations
*------------------------------------------------------*

DATA: STRING TYPE CHAR100 .

*-------------------------------------------------------*
*    initialization
*------------------------------------------------------*

INITIALIZATION .

P_STR = 'THIS IS THE TEST' .

*-------------------------------------------------------*
*  start of selection
*------------------------------------------------------*

START-OF-SELECTION .

CALL FUNCTION 'STRING_UPPER_LOWER_CASE'
  EXPORTING
    delimiter = ' '
    string1   = P_STR
  IMPORTING
    STRING    = STRING
  EXCEPTIONS
    NOT_VALID = 1
    TOO_LONG  = 2
    TOO_SMALL = 3
    OTHERS    = 4.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.

*------output
	WRITE:/ STRING .

Go to SE37

Enter Name < NN_TEXT_CONVERT_PROPER>

Press Create Button

Enter Import & Export Variables as Type String

Enter Exceptions as      NOT_VALID

                                    TOO_LONG

                                    TOO_SMALL  
Create Source Code as Follows

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
FUNCTION nn_text_convert_proper.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(STRING1)
*"  EXPORTING
*"     REFERENCE(STRING)
*"  EXCEPTIONS
*"      NOT_VALID
*"      TOO_LONG
*"      TOO_SMALL
*"----------------------------------------------------------------------

  DATA  :
        it_txts      TYPE TABLE OF string,  "Tabel for data storing
        wa_txts(100) TYPE c,                "Getting each words
        cp_text      TYPE string,           "Copying text
        nn_text      TYPE string.           "Result text

  cp_text = string1.
  SPLIT cp_text AT space INTO: TABLE it_txts.

  LOOP AT it_txts INTO wa_txts.
    PERFORM  change_case USING wa_txts.
    CONCATENATE nn_text wa_txts INTO nn_text SEPARATED BY space.
  ENDLOOP.
  CONDENSE nn_text.
*
  CASE sy-subrc.
    WHEN 0.
      string = nn_text.
      EXIT.
    WHEN 2.
      RAISE not_valid.
    WHEN 3.
      RAISE too_long.
    WHEN 4.
      RAISE too_small.
  ENDCASE.

ENDFUNCTION.

*in the perform part add code as follows (include lzpropertop)

FUNCTION-POOL zproper.                      "MESSAGE-ID ..

*&---------------------------------------------------------------------*
*&      Form  CHANGE_CASE
*&---------------------------------------------------------------------*
FORM change_case  USING  p_wa_txts.

  DATA : p_dem.

  p_dem = '&'.

  CALL FUNCTION 'STRING_UPPER_LOWER_CASE'
    EXPORTING
      delimiter = p_dem
      string1   = p_wa_txts
    IMPORTING
      string    = p_wa_txts
    EXCEPTIONS
      not_valid = 1
      too_long  = 2
      too_small = 3
      OTHERS    = 4.
ENDFORM.                    " CHANGE_CASE
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*----this is the report for concatenating 2 strings

REPORT  zconcatenate_fm                         .

DATA: string(100) TYPE c.

PARAMETERS: abc(15) TYPE c,
            bbc(15) TYPE c.

CALL FUNCTION 'STRING_CONCATENATE'
  EXPORTING
    string1   = abc
    string2   = bbc
  IMPORTING
    string    = string
  EXCEPTIONS
    too_small = 1
    OTHERS    = 2.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

WRITE:/ string.

*----------------------------------------------------------------*
*  this is the report for concatenating 3 strings
*--------------------------------------------------------------*
REPORT  zconcatenate_fm01   .

DATA: string(50) TYPE c.

PARAMETERS: p_strng1(15) TYPE c,
            p_strng2(15) TYPE c,
            p_strng3(15) TYPE c.

CALL FUNCTION 'STRING_CONCATENATE_3'
  EXPORTING
    string1   = p_strng1
    string2   = p_strng2
    string3   = p_strng3
  IMPORTING
    string    = string
  EXCEPTIONS
    too_small = 1
    OTHERS    = 2.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

WRITE:/ string.

Method 1

PARAMETERS inp(40) DEFAULT 'Habitación' LOWER CASE.

DATA: BEGIN OF uml,
  um1 VALUE 'ó',
  um1_e VALUE 'o',
  um2 VALUE 'ä',
  um2_e VALUE 'a',
  um7 VALUE 'ß',
  um7_e(2) VALUE 'ss',
 END OF uml.

FIELD-SYMBOLS: <h1_string>, <h2_string>.
DATA string TYPE string.
DATA outp(40).
DATA: zaehler TYPE i VALUE 1.

string = inp.

DO.
  ASSIGN COMPONENT zaehler OF STRUCTURE uml TO <h1_string>.
  IF sy-subrc  NE 0.
    EXIT.
  ENDIF.
  zaehler = zaehler + 1.
  ASSIGN COMPONENT zaehler OF STRUCTURE uml TO <h2_string>.
  IF sy-subrc  NE 0.
    MESSAGE e000(yp).
  ENDIF.
  IF string CA <h1_string>.
    sy-subrc = 0.
    WHILE sy-subrc = 0.
      REPLACE <h1_string> WITH <h2_string> INTO string.
    ENDWHILE.
  ENDIF.
  zaehler = zaehler + 1.
ENDDO.

WRITE: inp, / string.
 

Method 2

PARAMETERS inp(40) DEFAULT 'Habitación' LOWER CASE.

DATA: outtext TYPE char40 .

CALL FUNCTION 'SCP_REPLACE_STRANGE_CHARS'
  EXPORTING
    intext  = inp
  IMPORTING
    outtext = outtext.

WRITE:/ outtext.
 

This code explains that how we can find the length of a string using the oops class using Static and instance method.

The  "methods" statement declares or redefines an instance method "get_strlen".

Instance methods are linked to Objects.

To use instance methods,we have to create an object of the class.

By Instance method we can access all components of the own class without using a component selector.

REPORT ztest_prem
     NO STANDARD PAGE HEADING LINE-SIZE 255.

DATA:  string_in  TYPE string,
       len_out TYPE i.

*----------------------------------------------------------------------*
*       CLASS string_op DEFINITION
*----------------------------------------------------------------------*
CLASS string_op DEFINITION.

  PUBLIC SECTION.
    METHODS : get_strlen IMPORTING value(str1) TYPE string
                         EXPORTING value(len1) TYPE i.


    METHODS : constructor.


    CLASS-METHODS : write_len.

**The CLASS-METHODS statement declares a static method.
* With the class component selector (=>), static methods can be used independently of objects.
*By static methods, we can only access the static components of the class or its
*superclasses

ENDCLASS.                    "string_op DEFINITION

DATA :  inst TYPE REF TO string_op.

CREATE OBJECT inst.

string_in = 'Premraj'.

CALL METHOD inst->get_strlen     "Calling of Instance method.
EXPORTING
   str1 = string_in
IMPORTING
   len1 = len_out.

CALL METHOD string_op=>write_len.   "Calling of Staic method.

*----------------------------------------------------------------------*
*       CLASS string_op IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS string_op IMPLEMENTATION.

  METHOD get_strlen.
    len1 = strlen( str1 ).
  ENDMETHOD.                    "get_strlen

  METHOD write_len.
    WRITE : len_out.
  ENDMETHOD.                    "write_len

  METHOD constructor.
    WRITE : 'The length of String is :'.
  ENDMETHOD.                    "constructor

ENDCLASS.                    "string_op IMPLEMENTATION
 

Author: Jay Sadaram
Submitted: 11/07/2008
Description: In a SAP script I had some long text,which I was getting from Read_text function module. I had to split it and show in various lines. When the code was originally developed they were using the FM RKD_WORD_WRAP which splits to 3 lines Only, but my requirement was to have more than 10+ lines. So I developed a logic where with min changes you can adjust the number of characters to split to.. and kind of dynamic approach.

DATA: lv_len TYPE i,
      lv_z1 TYPE i,
      lv_z2 TYPE i,
      lv_z3 TYPE i,
      lv_z4 TYPE i,
      lv_z5 TYPE i,
      lv_z6 TYPE i,
      lv_z7 TYPE i,
      lv_last TYPE i,
      lv_offset(3) TYPE n.

lv_len = strlen( ztext ).
CLEAR: lv_offset.
lv_offset = lv_len / 7 .
lv_z1 = lv_offset.
lv_z2 = lv_z1 + 1.
lv_z3 = lv_z2 + lv_z1 + 1.
lv_z4 = lv_z3 + lv_z1 + 1.
lv_z5 = lv_z4 + lv_z1 + 1.
lv_z6 = lv_z5 + lv_z1 + 1.
lv_z7 = lv_z6 + lv_z1 + 1.
zoutline1 = ztext+0(lv_z1).
zoutline2 = ztext+lv_z2(lv_z1).
zoutline3 = ztext+lv_z3(lv_z1).
zoutline4 = ztext+lv_z4(lv_z1).
zoutline5 = ztext+lv_z5(lv_z1).
zoutline6 = ztext+lv_z6(lv_z1).
CHECK lv_len GT lv_z7.
lv_last = abs( lv_len - lv_z7 ).
zoutline7 = ztext+lv_z7(lv_last).
 

Here is a sample code where datatype 'N' accepts alphabets.

REPORT zconvert.
DATA :
w_date TYPE d , " Variable of type D
w_num(6) TYPE n . " Variable of type N

w_date = 'ABC123' .
MOVE w_date TO w_num .
SKIP 2 .
WRITE :25 w_num .

 In this case datatype 'N' accepts characters.





Factorial Calculation using Macro.

This program calculates the factorials of first 5 numbers using a macro.
Display the output in the following format using another macro.

Factorial of 1 is 1.
Factorial of 2 is 2.
Factorial of 3 is 6.
Factorial of 4 is 24.
Factorial of 5 is 120.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT zmacro.
* Work variables
DATA:
  w_num TYPE i VALUE 1,                " First number
  w_num1 TYPE i VALUE 5,               " Last Number
  w_fact TYPE i VALUE 1.               " Factorial Value
* Definition of Macro to Perform Factorial of first 5 numbers
DEFINE factorial.
  while &1 <= &2.
    &3 = &3 * &1.
    output &1 &3.
    add 1 to &1.
  endwhile.
END-OF-DEFINITION.                     " DEFINITION FACTORIAL
* Definition of Macro to Display the factorial result
DEFINE output.
  write:/ 'Factorial of', &1,'is', &2.
END-OF-DEFINITION.                     " DEFINITION OUTPUT

factorial w_num w_num1 w_fact.

Author: Jatra Riwayanto
Submitted: 06.06.2007

Description:
There is a time that we need to encode our data before we save it to database table.
I try encoded and decoded string data using method IF_HTTP_UTILITY~DECODE_BASE64 and IF_HTTP_UTILITY~ENCODE_BASE64 in class CL_HTTP_UTILITY.

Here the snippet:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
DATA: encoded   TYPE string,
      unencoded TYPE string.

START-OF-SELECTION.

  unencoded = 'This is test value'.
  WRITE: / 'Unencoded string:',  unencoded.

  encoded = cl_http_utility=>if_http_utility~encode_base64( unencoded = unencoded ).
  WRITE: / 'Encoded string:',  encoded.

  CLEAR: unencoded.
  unencoded = cl_http_utility=>if_http_utility~decode_base64( encoded = encoded ).
  WRITE: / 'Unencoded string:',  unencoded.

Result:

Author: JNN
Submitted: April 2nd 2014
Related Links:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT zz_buffer3.


CLASS lcx_buffer_error DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.                    "lcx_buffer_error DEFINITION


CLASS lcx_buffer_key_in_buffer DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.                    "lcx_buffer_key_in_buffer DEFINITION


CLASS lcx_iterator_error DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.


CLASS lcx_buffer_value_not_found DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.                    "lcx_buffer_value_not_found DEFINITION


INTERFACE lif_unit_test.
ENDINTERFACE.


*----------------------------------------------------------------------*
*       CLASS lcl_table_buffer DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_table_buffer DEFINITION CREATE PRIVATE FRIENDS lif_unit_test.


  PUBLIC SECTION.
    TYPES tt_fieldname TYPE STANDARD TABLE OF fieldname.
*   create a table buffer
    CLASS-METHODS factory
      IMPORTING iv_text TYPE csequence      " Unique ID, used for caching
                iv_value TYPE any           " any structure
                iv_key TYPE fieldname       " name of key field in structure
                it_keys TYPE tt_fieldname OPTIONAL  " (or all key fields) - not tested
      RETURNING value(ro_buffer) TYPE REF TO lcl_table_buffer
      RAISING lcx_buffer_error.
    METHODS put                             " put structure value in buffer
      IMPORTING iv_value TYPE any
      RAISING lcx_buffer_key_in_buffer .
    METHODS get                             " get value from buffer according to key
      IMPORTING iv_key TYPE simple
      EXPORTING ev_value TYPE data
      RAISING lcx_buffer_value_not_found.
    METHODS size                            " number of entries in buffer
      RETURNING value(rv_size) TYPE syindex.
    METHODS isempty                         " is the buffer empty?
      RETURNING value(rv_empty) TYPE flag.
    METHODS contains_key                    " is there a value with this key in buffer?
      IMPORTING iv_key TYPE simple
      RETURNING value(rv_idx) TYPE syindex.
    METHODS contains                       " is this value in the buffer ?
      IMPORTING iv_value TYPE data
      RETURNING value(rv_idx) TYPE syindex.
    METHODS delete                         " remove value with key from buffer
      IMPORTING iv_key TYPE simple
      RETURNING value(rv_found) TYPE flag.
    METHODS clear.                          " clear/empty the buffer
    CLASS-METHODS free
      IMPORTING iv_text TYPE csequence OPTIONAL.


  PRIVATE SECTION.
    DATA mv_key TYPE fieldname.
    DATA mr_buffer TYPE REF TO data.
    TYPES: BEGIN OF ts_map,
             name TYPE string,
             buffer TYPE REF TO lcl_table_buffer,
           END OF ts_map.
    CLASS-DATA gt_map TYPE SORTED TABLE OF ts_map
      WITH UNIQUE KEY name.
    METHODS constructor
      IMPORTING it_keys TYPE tt_fieldname
                is_struct TYPE any
      RAISING lcx_buffer_error.
ENDCLASS.


*----------------------------------------------------------------------*
*       CLASS lcl_table_buffer IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_table_buffer IMPLEMENTATION.


  METHOD factory.
    DATA ls_map TYPE ts_map.
    DATA lt_keys TYPE tt_fieldname.
    IF it_keys IS INITIAL.
      APPEND iv_key TO lt_keys.
    ELSE.
      lt_keys = it_keys.
    ENDIF.
    READ TABLE gt_map INTO ls_map
      WITH KEY name = iv_text.
    IF sy-subrc NE 0.
      CREATE OBJECT ls_map-buffer
        EXPORTING it_keys = lt_keys
                  is_struct = iv_value.
      ls_map-name = iv_text.
      INSERT ls_map INTO TABLE gt_map.
    ENDIF.
    ro_buffer = ls_map-buffer.
  ENDMETHOD.                    "create


  METHOD constructor.
    FIELD-SYMBOLS <lv_comp> TYPE any.
    FIELD-SYMBOLS <ls_struct> TYPE any.
    FIELD-SYMBOLS <lv_key> TYPE fieldname.
    super->constructor( ).
    LOOP AT it_keys ASSIGNING <lv_key>.
      AT FIRST.
        mv_key = <lv_key>.
      ENDAT.
      ASSIGN COMPONENT <lv_key> OF STRUCTURE is_struct TO <lv_comp>.
      CHECK sy-subrc NE 0.
      RAISE EXCEPTION TYPE lcx_buffer_error.
    ENDLOOP.
    CREATE DATA mr_buffer LIKE SORTED TABLE OF is_struct
      WITH UNIQUE KEY (it_keys).
  ENDMETHOD.


  METHOD free.
    DATA ls_map TYPE ts_map.
    READ TABLE gt_map INTO ls_map
      WITH KEY name = iv_text.
    IF sy-subrc EQ 0.
      DELETE gt_map INDEX sy-index.
      FREE ls_map-buffer.
    ELSEIF iv_text IS INITIAL.
      CLEAR gt_map.
    ENDIF.
  ENDMETHOD.


  METHOD clear.
    CLEAR mr_buffer.
  ENDMETHOD.


  DEFINE assign_buffer.
    FIELD-SYMBOLS <lt_buffer> TYPE SORTED TABLE.
    ASSIGN mr_buffer->* TO <lt_buffer>.
    CHECK <lt_buffer> IS ASSIGNED.
  END-OF-DEFINITION.


  METHOD size.
    CLEAR rv_size.
    assign_buffer.
    rv_size = lines( <lt_buffer> ).
  ENDMETHOD.                    "size


  METHOD isempty.
    rv_empty = abap_true.
    assign_buffer.
    IF <lt_buffer> IS NOT INITIAL.
      rv_empty = abap_false.
    ENDIF.
  ENDMETHOD.                    "isEmpty


  METHOD contains_key.
*   Search for already buffered value
    CLEAR rv_idx.
    assign_buffer.
    READ TABLE <lt_buffer> TRANSPORTING NO FIELDS
      WITH TABLE KEY (mv_key) = iv_key.
    CHECK sy-subrc EQ 0.
    rv_idx = sy-tabix.
  ENDMETHOD.                    "contains_key


  METHOD contains.
*   Search for already buffered value
    CLEAR rv_idx.
    assign_buffer.
    READ TABLE <lt_buffer> TRANSPORTING NO FIELDS
      FROM iv_value.
    CHECK sy-subrc EQ 0.
    rv_idx = sy-tabix.
  ENDMETHOD.                    "contains

  METHOD get.
    FIELD-SYMBOLS <ls_data> TYPE any.
    assign_buffer.
    READ TABLE <lt_buffer> ASSIGNING <ls_data>
      WITH KEY (mv_key) = iv_key.
    IF sy-subrc NE 0.
*     Value was not found
      RAISE EXCEPTION TYPE lcx_buffer_value_not_found.
    ELSE.
      ev_value = <ls_data>.
    ENDIF.
  ENDMETHOD.                    "GET
  
  METHOD put.
*   Search for already buffered value
    FIELD-SYMBOLS <ls_data> TYPE any.
    assign_buffer.
    READ TABLE <lt_buffer> ASSIGNING <ls_data>
      FROM iv_value.
    IF sy-subrc EQ 0.
*     key was already in the buffer
      RAISE EXCEPTION TYPE lcx_buffer_key_in_buffer.
    ELSE.
*     Value was not found, insert:
      INSERT iv_value INTO TABLE <lt_buffer>.
    ENDIF.
  ENDMETHOD.                    "insert


  METHOD delete.
*   remove existing entry - not tested yet
    FIELD-SYMBOLS <ls_data> TYPE any.
    assign_buffer.
    DELETE TABLE <lt_buffer>
      WITH TABLE KEY (mv_key) = iv_key.
  ENDMETHOD.                    "insert
ENDCLASS.


*----------------------------------------------------------------------*
*       CLASS lcl_test DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_test DEFINITION FOR TESTING
  DURATION MEDIUM RISK LEVEL HARMLESS.
  PUBLIC SECTION.
    INTERFACES lif_unit_test.
  PRIVATE SECTION.
    CONSTANTS c_max_size TYPE i VALUE 1000.
    CONSTANTS c_text_save TYPE char40 VALUE 'SAVE_BUFFER_TEST'.
    DATA mv_sbook_size TYPE i.
    DATA mv_buffer_size TYPE i.
    DATA mt_sbook TYPE STANDARD TABLE OF sbook.
    DATA mv_start TYPE i.
    DATA mv_time TYPE i.
    DATA mi_timer TYPE REF TO IF_ABAP_RUNTIME.


    METHODS setup.
    METHODS without_buffer FOR TESTING.
    METHODS filling_buffer FOR TESTING.
    METHODS select_without_buffer
      RETURNING VALUE(rv_counter) TYPE i.
    METHODS select_with_buffer
      RETURNING VALUE(ro_buffer) TYPE REF TO lcl_table_buffer
      RAISING lcx_buffer_error.
    METHODS from_buffer
      RAISING lcx_buffer_error.
    METHODS start_timer.
    METHODS stop_timer RETURNING VALUE(rv_time) TYPE i.
    METHODS buffer_runtime FOR TESTING.
    METHODS save_buffer FOR TESTING.
    METHODS contains FOR TESTING.
ENDCLASS.                    "lcl_test DEFINITION


*----------------------------------------------------------------------*
*       CLASS lcl_test IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_test IMPLEMENTATION.


  METHOD setup.
    DATA lt_customid TYPE STANDARD TABLE OF sbook-customid.
    SELECT * FROM sbook INTO TABLE mt_sbook
      UP TO c_max_size ROWS.
    SELECT customid FROM sbook
      INTO TABLE lt_customid
      FOR ALL ENTRIES IN mt_sbook
      WHERE carrid = mt_sbook-carrid
        AND connid = mt_sbook-connid
        AND fldate = mt_sbook-fldate
        AND bookid = mt_sbook-bookid.
      mv_buffer_size = lines( lt_customid ).
      mv_sbook_size = lines( mt_sbook ).
      mi_timer = cl_abap_runtime=>create_hr_timer( ).
    ENDMETHOD.                    "query_sbook


    METHOD start_timer.
      mv_start = mi_timer->get_runtime( ).
    ENDMETHOD.


    METHOD stop_timer.
      rv_time = mi_timer->get_runtime( ) - mv_start.
    ENDMETHOD.


    METHOD select_without_buffer.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      CLEAR rv_counter.
      LOOP AT mt_sbook INTO ls_sbook.
        SELECT SINGLE * FROM sbuspart INTO ls_sbuspart
          WHERE buspartnum = ls_sbook-customid.
        ADD 1 TO rv_counter.
      ENDLOOP.
    ENDMETHOD.


    METHOD without_buffer.
      DATA lv_counter TYPE i.
      lv_counter = select_without_buffer( ).
      cl_aunit_assert=>assert_equals( exp = mv_sbook_size
                                      act = lv_counter
                                      msg = 'WITHOUT_BUFFER error' ).
    ENDMETHOD.                    "without_buffer


    METHOD select_with_buffer.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      ro_buffer = lcl_table_buffer=>factory(
        iv_text = 'CUSTOMER_DETAILS'
        iv_value = ls_sbuspart      " structure
        iv_key = 'BUSPARTNUM' ).
      LOOP AT mt_sbook INTO ls_sbook.
        CHECK ro_buffer->contains_key( ls_sbook-customid ) EQ 0.
*       If we haven't saved it yet, get it and save it
        SELECT SINGLE * FROM sbuspart INTO ls_sbuspart
          WHERE buspartnum = ls_sbook-customid.
        ro_buffer->put( ls_sbuspart ).
      ENDLOOP.
    ENDMETHOD.


    METHOD filling_buffer.
      DATA lo_buffer TYPE REF TO lcl_table_buffer.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lv_counter TYPE i.
      TRY.
          lo_buffer = select_with_buffer( ).
          lv_counter = lo_buffer->size( ).
          cl_aunit_assert=>assert_equals( exp = mv_buffer_size
                                          act = lv_counter
                                          msg = 'WITH_BUFFER error' ).
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | WITH_BUFFER { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.                    "with_buffer


    METHOD from_buffer.
      DATA lo_buffer TYPE REF TO lcl_table_buffer.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lv_counter TYPE i.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      lo_buffer = lcl_table_buffer=>factory(
        iv_text = 'CUSTOMER_DETAILS'
        iv_value = ls_sbuspart      " structure
        iv_key = 'BUSPARTNUM' ).
      TRY.
          LOOP AT mt_sbook INTO ls_sbook.
            lo_buffer->get( ls_sbook-customid ).
            ADD 1 to lv_counter.
          ENDLOOP.
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | ITERATOR { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.


    METHOD buffer_runtime.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lv_time_from_buffer TYPE i.
      DATA lv_time_fill_buffer TYPE i.
      DATA lv_time_wo_buffer TYPE i.
      DATA lv_flag TYPE flag.
      start_timer( ).
      select_without_buffer( ).
      lv_time_wo_buffer = stop_timer( ).
      start_timer( ).
      TRY.
          select_with_buffer( ).
          lv_time_fill_buffer = stop_timer( ).
          start_timer( ).
          from_buffer( ).
          lv_time_from_buffer = stop_timer( ).
          IF lv_time_fill_buffer LT lv_time_wo_buffer.
            lv_flag = 'X'.
          ELSE.
            lv_flag = space.
          ENDIF.
          cl_abap_unit_assert=>assert_equals(
            exp = 'X'
            act = lv_flag
            level = if_aunit_constants=>tolerable
            msg = |RUN TIME fill buffer: { lv_time_fill_buffer } w/o buffer: { lv_time_wo_buffer } from buffer: { lv_time_from_buffer } | ).
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | RUN TIME { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.                    "with_buffer


    METHOD contains.
      DATA ls_sbuspart TYPE sbuspart.
      DATA lv_idx TYPE sytabix.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lo_buffer TYPE REF TO lcl_table_buffer.
      TRY.
          ls_sbuspart-buspartnum = '00002075'.
          lo_buffer = lcl_table_buffer=>factory(
            iv_text = c_text_save
            iv_value = ls_sbuspart
            iv_key = 'BUSPARTNUM' ).
          lo_buffer->put( ls_sbuspart ).
          lv_idx = lo_buffer->contains( ls_sbuspart ).
          cl_abap_unit_assert=>assert_equals(
            exp = 1
            act = lv_idx
            msg = 'LCL_TABLE_BUFFER->CONTAINS Error' ).
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | CONTAINS { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.


    METHOD save_buffer.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lo_first TYPE REF TO lcl_table_buffer.
      DATA lo_next TYPE REF TO lcl_table_buffer.
      TRY.
          lo_first = lcl_table_buffer=>factory(
            iv_text = c_text_save
            iv_value = ls_sbuspart
            iv_key = 'BUSPARTNUM' ).
          lo_next = lcl_table_buffer=>factory(
            iv_text = c_text_save
            iv_value = ls_sbuspart
            iv_key = 'BUSPARTNUM' ).
          cl_abap_unit_assert=>assert_equals(
            exp = lo_first
            act = lo_next
            msg = |LCL_TABLE_BUFFER=>FACTORY Cache Error: { c_text_save } | ).
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | SAVE_BUFFER { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.
  ENDCLASS.                    "lcl_test IMPLEMENTATION




  ENDCLASS.                    "lcl_test IMPLEMENTATION

 

An ABAP implementation of an associative array (aka symbol table or map)

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*----------------------------------------------------------------------*
REPORT zz_buffer.


*----------------------------------------------------------------------*
*       CLASS lcx_buffer_error DEFINITION
*----------------------------------------------------------------------*
CLASS lcx_buffer_error DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.                    "lcx_buffer_error DEFINITION
*----------------------------------------------------------------------*
*       CLASS lcx_buffer_key_in_buffer DEFINITION
*----------------------------------------------------------------------*
CLASS lcx_buffer_key_in_buffer DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.                    "lcx_buffer_key_in_buffer DEFINITION
*----------------------------------------------------------------------*
*       CLASS lcx_buffer_value_not_found DEFINITION
*----------------------------------------------------------------------*
CLASS lcx_buffer_value_not_found DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.                    "lcx_buffer_value_not_found DEFINITION


*----------------------------------------------------------------------*
*       INTERFACE lif_entry DEFINITION
*----------------------------------------------------------------------*
INTERFACE lif_entry.
  METHODS find
    IMPORTING iv_key TYPE any
    RETURNING value(rv_found) TYPE flag.
  METHODS get
    EXPORTING value(ev_value) TYPE any.
ENDINTERFACE.                    "lif_entry DEFINITION


*----------------------------------------------------------------------*
*       CLASS lcl_entry DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_entry DEFINITION CREATE PRIVATE.
  PUBLIC SECTION.
    INTERFACES lif_entry.

    CLASS-METHODS factory
      IMPORTING iv_key TYPE any
                iv_value TYPE any
      RETURNING value(ri_entry) TYPE REF TO lif_entry.


  PROTECTED SECTION.
    DATA mr_key   TYPE REF TO data.
    DATA mr_value TYPE REF TO data.
    METHODS constructor
      IMPORTING iv_key TYPE any
                iv_value TYPE any.
ENDCLASS.                    "lcl_entry DEFINITION


*----------------------------------------------------------------------*
*       CLASS lcl_entry IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_entry IMPLEMENTATION.


  METHOD constructor.
    FIELD-SYMBOLS <lv_ref> TYPE any.
    super->constructor( ).
    CREATE DATA mr_key LIKE iv_key.
    ASSIGN mr_key->* TO <lv_ref>.
    <lv_ref> = iv_key.
    CREATE DATA mr_value LIKE iv_value.
    ASSIGN mr_value->* TO <lv_ref>.
    <lv_ref> = iv_value.
  ENDMETHOD.                    "constructor


  METHOD factory.
    CREATE OBJECT ri_entry TYPE lcl_entry
      EXPORTING
        iv_key   = iv_key
        iv_value = iv_value.
  ENDMETHOD.                    "factory


  METHOD lif_entry~find.
    FIELD-SYMBOLS <lv_ref> TYPE any.
    CLEAR rv_found.
    ASSIGN mr_key->* TO <lv_ref>.
    CHECK <lv_ref> EQ iv_key.
    rv_found = abap_true.
  ENDMETHOD.                    "lif_entry~find

  METHOD lif_entry~get.
    FIELD-SYMBOLS <lv_ref> TYPE any.
    ASSIGN mr_value->* TO <lv_ref>.
    ev_value = <lv_ref>.
  ENDMETHOD.                    "get
ENDCLASS.                    "lcl_entry IMPLEMENTATION


*----------------------------------------------------------------------*
*       CLASS lcl_map DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_map DEFINITION CREATE PRIVATE.
  PUBLIC SECTION.
    METHODS insert
      IMPORTING iv_key TYPE any
                iv_value TYPE any
      RAISING lcx_buffer_key_in_buffer .


    METHODS get_size
      RETURNING value(rv_size) TYPE syindex.


    METHODS isempty
      RETURNING value(rv_empty) TYPE flag.


    METHODS contains
      IMPORTING iv_key TYPE any
      RETURNING value(rv_found) TYPE flag.


    METHODS remove
      IMPORTING iv_key TYPE any
      RETURNING value(rv_found) TYPE flag.


    METHODS lookup
      IMPORTING iv_key TYPE any
      EXPORTING ev_value TYPE any
      RAISING lcx_buffer_value_not_found.

    CLASS-METHODS factory
      IMPORTING iv_name TYPE csequence
      RETURNING value(ro_buffer) TYPE REF TO lcl_map
      RAISING lcx_buffer_error.
  PRIVATE SECTION.
    TYPES tt_buffer TYPE STANDARD TABLE OF REF TO lif_entry.

    DATA mt_buffer TYPE tt_buffer.
    DATA mv_name TYPE string.
ENDCLASS.                    "lcl_map DEFINITION

*----------------------------------------------------------------------*
*       CLASS lCL_MAP IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_map IMPLEMENTATION.


  METHOD factory.
    CREATE OBJECT ro_buffer.
    ro_buffer->mv_name = iv_name.
  ENDMETHOD.                    "create


  METHOD get_size.
    rv_size = lines( mt_buffer ).
  ENDMETHOD.                    "get_size


  METHOD isempty.
    IF mt_buffer IS INITIAL.
      rv_empty = abap_true.
    ELSE.
      rv_empty = abap_false.
    ENDIF.
  ENDMETHOD.                    "isEmpty


  METHOD contains.
*   Search for already buffered value
    DATA li_entry TYPE REF TO lif_entry.
    CLEAR rv_found.
    LOOP AT mt_buffer INTO li_entry.
      CHECK li_entry->find( iv_key ) EQ abap_true.
      rv_found = abap_true.
      RETURN.
    ENDLOOP.
  ENDMETHOD.                    "contains


  METHOD lookup.
*   Search for already buffered value
    DATA li_entry TYPE REF TO lif_entry.
    LOOP AT mt_buffer INTO li_entry.
      CHECK li_entry->find( iv_key ) EQ abap_true.
      li_entry->get( IMPORTING ev_value = ev_value ).
      RETURN.
    ENDLOOP.
*   Value was not found
    RAISE EXCEPTION TYPE lcx_buffer_value_not_found.
  ENDMETHOD.                    "GET


  METHOD insert.
*   Search for already buffered value
    DATA li_entry TYPE REF TO lif_entry.
    IF me->contains( iv_key ) EQ abap_true.
*     key was already in the buffer
      RAISE EXCEPTION TYPE lcx_buffer_key_in_buffer.
    ENDIF.
*   Value was not found, insert:
    li_entry = lcl_entry=>factory( iv_key = iv_key
                                   iv_value = iv_value ).
    INSERT li_entry INTO TABLE mt_buffer.
  ENDMETHOD.                    "insert


  METHOD remove.
*   remove existing entry
    DATA li_entry TYPE REF TO lif_entry.
    CLEAR rv_found.
    LOOP AT mt_buffer INTO li_entry.
      CHECK li_entry->find( iv_key ) EQ abap_true.
      rv_found = abap_true.
      DELETE mt_buffer.
      FREE li_entry.
      RETURN.
    ENDLOOP.
  ENDMETHOD.                    

ENDCLASS.                    "lCL_BUFFER IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS lcl_test DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_test DEFINITION FOR TESTING
  DURATION MEDIUM RISK LEVEL HARMLESS.

  PRIVATE SECTION.
    CONSTANTS c_max_size TYPE i VALUE 1000.
    DATA mv_sbook_size TYPE i.
    DATA mv_buffer_size TYPE i.
    DATA mt_sbook TYPE STANDARD TABLE OF sbook.


    METHODS setup.
    METHODS without_buffer FOR TESTING.
    METHODS with_buffer FOR TESTING.
ENDCLASS.                    "lcl_test DEFINITION


*----------------------------------------------------------------------*
*       CLASS lcl_test IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_test IMPLEMENTATION.

  METHOD setup.
    DATA lt_customid TYPE STANDARD TABLE OF sbook-customid.
    SELECT * FROM sbook INTO TABLE mt_sbook
      UP TO c_max_size ROWS.
*    SELECT COUNT( DISTINCT customid ) INTO mv_buffer_size
*      FROM sbook
*      UP TO c_max_size ROWS.
* Ooops! only one row was returned
*    Have to use the convoluted logic below
    SELECT customid FROM sbook
      INTO TABLE lt_customid
      FOR ALL ENTRIES IN mt_sbook
      WHERE carrid = mt_sbook-carrid
        AND connid = mt_sbook-connid
        AND fldate = mt_sbook-fldate
        AND bookid = mt_sbook-bookid.
      mv_buffer_size = lines( lt_customid ).
      mv_sbook_size = lines( mt_sbook ).
    ENDMETHOD.                    "query_sbook

    METHOD without_buffer.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      DATA lv_counter TYPE i.
      LOOP AT mt_sbook INTO ls_sbook.
        SELECT SINGLE * FROM sbuspart INTO ls_sbuspart
          WHERE buspartnum = ls_sbook-customid.
        ADD 1 TO lv_counter.
      ENDLOOP.
      cl_aunit_assert=>assert_equals( exp = mv_sbook_size
                                      act = lv_counter
                                      msg = 'WITHOUT_BUFFER error' ).
    ENDMETHOD.                    "without_buffer

    METHOD with_buffer.
      DATA lo_buffer TYPE REF TO lcl_map.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lv_counter TYPE i.
      DATA lv_text TYPE string.
      TRY.
          LOOP AT mt_sbook INTO ls_sbook.
            AT FIRST.
              lo_buffer = lcl_map=>factory( 'CUSTOMER_DETAILS' ).
            ENDAT.
            CHECK lo_buffer->contains( ls_sbook-customid ) EQ abap_false.
*         If we haven't saved it yet, get it and save it
            SELECT SINGLE * FROM sbuspart INTO ls_sbuspart
              WHERE buspartnum = ls_sbook-customid.
            lo_buffer->insert( iv_key   = ls_sbook-customid
                               iv_value = ls_sbuspart ).
          ENDLOOP.
          lv_counter = lo_buffer->get_size( ).
          cl_aunit_assert=>assert_equals( exp = mv_buffer_size
                                          act = lv_counter
                                          msg = 'WITH_BUFFER error' ).
        CATCH lcx_buffer_error INTO lx_error.
          lv_text = | WITH_BUFFER { lx_error->get_text( ) } |.
          cl_aunit_assert=>fail( msg = lv_text ).
      ENDTRY.
    ENDMETHOD.                    "with_buffer
  ENDCLASS.                    "lcl_test IMPLEMENTATION
REPORT  zceil_floor .
*-----------------------------------------------------------------------------------*
*              selection screen parameters
*----------------------------------------------------------------------------------*
PARAMETERS: p_int  TYPE i ,
            p_int1 TYPE i .
*-----------------------------------------------------------------------------------*
*              data declarations
*----------------------------------------------------------------------------------*
DATA: value  TYPE p DECIMALS 2  ,
      value1  TYPE p DECIMALS 2 ,
      value2  TYPE p DECIMALS 2 .
*-----------------------------------------------------------------------------------*
*              start of selection
*----------------------------------------------------------------------------------*
START-OF-SELECTION.
  value = p_int / p_int1 .
  value1 = ceil( value  ) .
  value2 = floor( value ) .
*----display output
  WRITE:/ 'the actual value is  :           ' ,   value .
  WRITE:/ 'value using the ceil  function : ' , value1 .
  WRITE:/ 'value using the floor function : ' , value2 .
 

Horst Keller's Blog - ABAP news for release 740 SP05

100 lines of test code with a Unit Test that fails.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT YY_CORRESPONDING.
TYPES ts_sat TYPE if_atra_uml_tool=>ty_sat_record.
TYPES:  BEGIN OF ts_call,
          prog TYPE program,
          type TYPE trobjtype,
          inst TYPE satr_de_instance,
          lcl  TYPE program,
          mod  TYPE seocpdname,
        END OF ts_call.
TYPES:
  BEGIN OF ts_trace,
    id        TYPE satr_de_id,
    aus_ebene TYPE satr_de_ebene,
    caller    TYPE ts_call,
    called    TYPE ts_call,
  END OF ts_trace.
INTERFACE lif_unit_test.
ENDINTERFACE.
CLASS lcl_converter DEFINITION FRIENDS lif_unit_test.
  PUBLIC SECTION.
  PRIVATE SECTION.
    METHODS copy_fields
      IMPORTING is_trace      TYPE ts_sat
      RETURNING VALUE(rs_sat) TYPE ts_trace.
    METHODS operator
      IMPORTING is_trace      TYPE ts_sat
      RETURNING VALUE(rs_sat) TYPE ts_trace.
ENDCLASS.
CLASS ltc_converter DEFINITION
  INHERITING FROM cl_aunit_assert FOR TESTING
  RISK LEVEL HARMLESS DURATION SHORT.
  PUBLIC SECTION.
    INTERFACES lif_unit_test.
  PRIVATE SECTION.
    DATA ms_sat TYPE ts_sat.
    DATA mo_convert TYPE REF TO lcl_converter.
    METHODS setup.
    METHODS convert FOR TESTING.
ENDCLASS.
CLASS lcl_converter IMPLEMENTATION.
  METHOD copy_fields.
    MOVE-CORRESPONDING is_trace TO rs_sat.
    rs_sat-caller = VALUE #( prog = is_trace-caller
                             type = is_trace-caller_type
                             inst = is_trace-caller_inst
                             lcl = is_trace-caller_lcl
                             mod = is_trace-caller_mod ).
    rs_sat-called = VALUE #( prog = is_trace-called
                             type = is_trace-called_type
                             inst = is_trace-called_inst
                             lcl = is_trace-called_lcl
                             mod = is_trace-called_mod ).
  ENDMETHOD.
  METHOD operator.
    rs_sat =  CORRESPONDING #( is_trace MAPPING
            ( caller = table_line MAPPING prog = caller
                                          type = caller_type
                                          inst = caller_inst
                                          lcl = caller_lcl
                                          mod = caller_mod  )
            ( called = table_line MAPPING prog = called
                                          type = called_type
                                          inst = called_inst
                                          lcl = called_lcl
                                          mod = called_mod  )   ).
  ENDMETHOD.
ENDCLASS.
CLASS ltc_converter IMPLEMENTATION.
  METHOD setup.
    mo_convert = NEW #( ).
    ms_sat = VALUE #( id = 'm'
                      caller = 'PROGRAM'
                      caller_mod = 'TEST'
                      called_type = 'CLAS'
                      called_inst = 4
                      called_lcl = 'LCL_DEMO' ).
  ENDMETHOD.
  METHOD convert.
    DATA(ls_trace) = mo_convert->copy_fields( ms_sat ).
    DATA(ls_act) = mo_convert->operator( ms_sat ).
    assert_equals(  act = ls_act
                    exp = ls_trace
                    msg = 'CONVERSION Error').
  ENDMETHOD.
ENDCLASS.


  • No labels