Hello,

i would like to give a simple example how to use Runtime Type Services (RTTS) for components of a flat structure and assign the components of the structure to field symbols. This is often required if you get a structure into a method by a parameter that its type is data though you don’t know the runtime type and therfore you have to work with field symbols.

Let us start with a simple example without looping over all structure components.

This is the sample code of a simple test report to get the concept:


* Data Declaration
DATA: go_obj       TYPE REF TO zcl_test_am01,
       gv_value     TYPE string,
       lv_comp_name TYPE string,
       ls_bseg      TYPE bseg.
* Create Object
CREATE OBJECT go_obj.
* Check if Object is available
IF NOT go_obj IS BOUND.
   WRITE 'No Instance created'.
ENDIF.
* Assign a Text to the BSEG Structure Field SGTEXT
ls_bseg-sgtxt = 'This is the value we would like to get'.
* Define the Component Name we would like to get Data from
lv_comp_name = 'SGTXT'.
* Call get_component_value
gv_value = go_obj->get_component_value(
     is_struc      = ls_bseg
     iv_comp_name  = lv_comp_name       ).
* Display component value on screen
write: 'Val1: ', gv_value.

Basicly all this report does is the following:

1) Create Instance of Class zcl_test_am01

2) Assign a text to the ls_bseg structure

3) Set lv_comp_name with ‘SGTXT’ => The component name we would like to get the value from.

4) Call of get_component_value of the class zcl_test_am01.

5) Write gv_value

So the interesting part is now, what does the method get_component_value:

Method Interface:

IS_STRUC TYPE DATA Structure Reference

IV_COMP_NAME TYPE STRING Component Name

value( EV_COMP_VALUE ) TYPE STRING Component Value


METHOD get_component_value.
* Field Symbol Definition
     FIELD-SYMBOLS <fs_struc_component> TYPE any.
* Assignment of Component Name of imported structure to fieldsymbol
     ASSIGN COMPONENT iv_comp_name OF STRUCTURE is_struc TO <fs_struc_component>.
* Check if field symbol is assigned ! Important - If you don't check with if is assigned you might get a
GWA_NOT_ASSIGNED Shortdump
     IF <fs_struc_component> IS ASSIGNED.
* Set ev_comp_value     
       ev_comp_value = <fs_struc_component>.
     ELSE.
* Exception Handling     
* eg. raise exception
     ENDIF.
ENDMETHOD.

This method also does not very much:

1) Declaration of Field Symbol <fs_struc_component> – Not type of bseg-sgtxt!

2) Assign Componentn (Dynamic Component Name) of Structure is_struc (type data) to fieldsymbol

3) Check if fieldsymbol is assigned if it is assigned ev_comp_value gets the value of <fs_struc_component>

This short example basicly shows how to get a structure component in a dynamic way. As we now, that we passed ls_bseg in the method and that the component SGTXT exists, there was no need to check if  structure component.

Now let’s have a look at this:

We assume, that we do not now, what structure is passed into our method. Therfore we first check what components are present on the structure and check if the imported component name is present. For this, we can use the abap runtime type services. A good document for this can be found here – if its moved google with this: “Runtime Type Services (RTTS) ABAP”. We would have to check the typekind of the structure (flat = typekind u = TYPEKIND_STRUCT1).

So lets check see the extende test report code:


* Data Declaration
DATA: go_obj       TYPE REF TO zcl_test_am01,
       gv_value     TYPE string,
       lv_comp_name TYPE string,
       ls_bseg      TYPE bseg.
* Create Object
CREATE OBJECT go_obj.
* Check if Object is available
IF NOT go_obj IS BOUND.
   WRITE 'No Instance created'.
ENDIF.
* Assign a Text to the BSEG Structure Field SGTEXT
ls_bseg-sgtxt = 'This is the value we would like to get'.
* Define the Component Name we would like to get Data from
lv_comp_name = 'SGTXT'.
* Call get_component_value
gv_value = go_obj->get_component_value(
     is_struc      = ls_bseg
     iv_comp_name  = lv_comp_name       ).
* Display component value on screen
write: 'Val1: ', gv_value.
* Part 2
clear gv_value.
gv_value = go_obj->get_component_value_gen(
   EXPORTING
     is_struc     = ls_bseg
     iv_comp_name = lv_comp_name            ).
write: /'Val2:', gv_value.

Only *Part 2 is relevant

Again ls_bseg and lv_comp_name are given into the method get_component_value_gen. The code in the method has a few changes:


METHOD get_component_value_gen.
* Field Symbol Definition
     FIELD-SYMBOLS <fs_struc_component> TYPE any.
* Data Declarations
     DATA: lo_struc_type_desc TYPE REF TO cl_abap_structdescr,
           ls_component       TYPE abap_compdescr.
     lo_struc_type_desc ?= cl_abap_structdescr=>describe_by_data( p_data = is_struc ).
     IF lo_struc_type_desc->type_kind NE lo_struc_type_desc->typekind_struct1.
       WRITE: /'IS_STRUC Parameter is not a flat structure ', lo_struc_type_desc->absolute_name.
     ENDIF.
* Components are present in the following instance attribute
     READ TABLE lo_struc_type_desc->components INTO ls_component WITH KEY name = iv_comp_name.
     IF sy-subrc <> 0.
       WRITE: /'Component ', iv_comp_name, ' not present in structure ', lo_struc_type_desc->absolute_name.
     ENDIF.
     ASSIGN COMPONENT ls_component-name OF STRUCTURE is_struc TO <fs_struc_component>.
* Check if field symbol is assigned ! Important - If you don't check with if is assigned you might get a
GWA_NOT_ASSIGNED Shortdump
     IF <fs_struc_component> IS ASSIGNED.
* Set ev_comp_value
       rv_value = <fs_struc_component>.
     ELSE.
* Exception Handling
* eg. raise exception
       WRITE 'Error due to <fs> assign statment'.
     ENDIF.
ENDMETHOD.

The following changed:


lo_struc_type_desc ?= cl_abap_structdescr=>describe_by_data( p_data = is_struc ).

With this statement we use the RTTS to get a description of our structure. With this we are checking, that the structure is flat (if you want e.g a more generic approach you would need to call your method in a recursive way again if eg. it was a deep structure).


IF lo_struc_type_desc->type_kind NE lo_struc_type_desc->typekind_struct1.
       WRITE: /'IS_STRUC Parameter is not a flat structure ', lo_struc_type_desc->absolute_name.
ENDIF.

The rest of the method stays the same.

With this approach it will be quite simple to implement methods that eg. loop over all components of a structure and to check some conditions and so on. Futher you can reuse such a generic method to use it broadly in your developments like kind of a service/utility class.

I hope you liked this document & that there are some tipps for you within it. Thanks for bookmarking or rating the document. I aprreciate all feedback & comments of you.

I wish you a nice day.

Regards,

Michael

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply