basic FUGS serialization

This commit is contained in:
Lars Hvam 2024-09-10 07:57:27 +02:00
parent 41619e6e4d
commit 52b83dcde7
2 changed files with 666 additions and 0 deletions

View File

@ -0,0 +1,650 @@
CLASS zcl_abapgit_object_fugs DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_program FINAL.
PUBLIC SECTION.
INTERFACES zif_abapgit_object.
PROTECTED SECTION.
PRIVATE SECTION.
CONSTANTS:
c_longtext_id_prog TYPE dokil-id VALUE 'RE',
c_longtext_id_func TYPE dokil-id VALUE 'FU',
c_longtext_id_func_exc TYPE dokil-id VALUE 'FX'.
TYPES:
ty_rs38l_incl_tt TYPE STANDARD TABLE OF rs38l_incl WITH DEFAULT KEY .
TYPES:
BEGIN OF ty_function,
funcname TYPE rs38l_fnam,
global_flag TYPE rs38l-global,
remote_call TYPE rs38l-remote,
update_task TYPE rs38l-utask,
short_text TYPE tftit-stext,
remote_basxml TYPE rs38l-basxml_enabled,
import TYPE STANDARD TABLE OF rsimp WITH DEFAULT KEY,
changing TYPE STANDARD TABLE OF rscha WITH DEFAULT KEY,
export TYPE STANDARD TABLE OF rsexp WITH DEFAULT KEY,
tables TYPE STANDARD TABLE OF rstbl WITH DEFAULT KEY,
exception TYPE STANDARD TABLE OF rsexc WITH DEFAULT KEY,
documentation TYPE STANDARD TABLE OF rsfdo WITH DEFAULT KEY,
exception_classes TYPE abap_bool,
END OF ty_function .
TYPES:
ty_function_tt TYPE STANDARD TABLE OF ty_function WITH DEFAULT KEY .
TYPES:
ty_sobj_name_tt TYPE STANDARD TABLE OF sobj_name WITH DEFAULT KEY .
TYPES:
BEGIN OF ty_tpool_i18n,
language TYPE langu,
textpool TYPE zif_abapgit_definitions=>ty_tpool_tt,
END OF ty_tpool_i18n .
TYPES:
ty_tpools_i18n TYPE STANDARD TABLE OF ty_tpool_i18n .
DATA mt_includes_cache TYPE ty_sobj_name_tt .
METHODS main_name
RETURNING
VALUE(rv_program) TYPE program
RAISING
zcx_abapgit_exception .
METHODS functions
RETURNING
VALUE(rt_functab) TYPE ty_rs38l_incl_tt
RAISING
zcx_abapgit_exception .
METHODS includes
RETURNING
VALUE(rt_includes) TYPE ty_sobj_name_tt
RAISING
zcx_abapgit_exception .
METHODS serialize_functions
RETURNING
VALUE(rt_functions) TYPE ty_function_tt
RAISING
zcx_abapgit_exception .
METHODS serialize_function_docs
IMPORTING
!iv_prog_name TYPE syrepid
!it_functions TYPE ty_function_tt
!ii_xml TYPE REF TO zif_abapgit_xml_output
RAISING
zcx_abapgit_exception .
METHODS serialize_xml
IMPORTING
!ii_xml TYPE REF TO zif_abapgit_xml_output
RAISING
zcx_abapgit_exception .
METHODS serialize_texts
IMPORTING
!iv_prog_name TYPE syrepid
!ii_xml TYPE REF TO zif_abapgit_xml_output
RAISING
zcx_abapgit_exception .
METHODS serialize_includes
RAISING
zcx_abapgit_exception .
METHODS is_part_of_other_fugr
IMPORTING
!iv_include TYPE sobj_name
RETURNING
VALUE(rv_belongs_to_other_fugr) TYPE abap_bool.
ENDCLASS.
CLASS ZCL_ABAPGIT_OBJECT_FUGS IMPLEMENTATION.
METHOD functions.
DATA: lv_area TYPE rs38l-area.
FIELD-SYMBOLS: <ls_functab> TYPE LINE OF ty_rs38l_incl_tt.
lv_area = ms_item-obj_name.
CALL FUNCTION 'RS_FUNCTION_POOL_CONTENTS'
EXPORTING
function_pool = lv_area
TABLES
functab = rt_functab
EXCEPTIONS
function_pool_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise_t100( ).
ENDIF.
* The result can also contain function which are lowercase.
LOOP AT rt_functab ASSIGNING <ls_functab>.
TRANSLATE <ls_functab> TO UPPER CASE.
ENDLOOP.
SORT rt_functab BY funcname ASCENDING.
DELETE ADJACENT DUPLICATES FROM rt_functab COMPARING funcname.
ENDMETHOD.
METHOD includes.
TYPES: BEGIN OF ty_reposrc,
progname TYPE reposrc-progname,
END OF ty_reposrc.
DATA: lt_reposrc TYPE STANDARD TABLE OF ty_reposrc WITH DEFAULT KEY,
ls_reposrc LIKE LINE OF lt_reposrc,
lv_program TYPE program,
lv_maintviewname LIKE LINE OF rt_includes,
lv_offset_ns TYPE i,
lv_tabix LIKE sy-tabix,
lt_functab TYPE ty_rs38l_incl_tt,
lt_tadir_includes TYPE HASHED TABLE OF objname WITH UNIQUE KEY table_line.
FIELD-SYMBOLS: <lv_include> LIKE LINE OF rt_includes,
<ls_func> LIKE LINE OF lt_functab.
IF lines( mt_includes_cache ) > 0.
rt_includes = mt_includes_cache.
RETURN.
ENDIF.
lv_program = main_name( ).
lt_functab = functions( ).
CALL FUNCTION 'RS_GET_ALL_INCLUDES'
EXPORTING
program = lv_program
TABLES
includetab = rt_includes
EXCEPTIONS
not_existent = 1
no_program = 2
OTHERS = 3.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise( 'Error from RS_GET_ALL_INCLUDES' ).
ENDIF.
LOOP AT lt_functab ASSIGNING <ls_func>.
DELETE TABLE rt_includes FROM <ls_func>-include.
ENDLOOP.
* handle generated maintenance views
IF ms_item-obj_name(1) <> '/'.
"FGroup name does not contain a namespace
lv_maintviewname = |L{ ms_item-obj_name }T00|.
ELSE.
"FGroup name contains a namespace
lv_offset_ns = find( val = ms_item-obj_name+1
sub = '/' ).
lv_offset_ns = lv_offset_ns + 2.
lv_maintviewname = |{ ms_item-obj_name(lv_offset_ns) }L{ ms_item-obj_name+lv_offset_ns }T00|.
ENDIF.
READ TABLE rt_includes WITH KEY table_line = lv_maintviewname TRANSPORTING NO FIELDS.
IF sy-subrc <> 0.
APPEND lv_maintviewname TO rt_includes.
ENDIF.
SORT rt_includes.
IF lines( rt_includes ) > 0.
" check which includes have their own tadir entry
" these includes might reside in a different package or might be shared between multiple function groups
" or other programs and are hence no part of the to serialized FUGS object
" they will be handled as individual objects when serializing their package
" in addition, referenced XTI includes referencing (simple) transformations must be ignored
SELECT obj_name
INTO TABLE lt_tadir_includes
FROM tadir
FOR ALL ENTRIES IN rt_includes
WHERE pgmid = 'R3TR'
AND object = 'PROG'
AND obj_name = rt_includes-table_line.
LOOP AT rt_includes ASSIGNING <lv_include>.
" skip autogenerated includes from Table Maintenance Generator
IF <lv_include> CP 'LSVIM*'.
DELETE rt_includes INDEX sy-tabix.
CONTINUE.
ENDIF.
READ TABLE lt_tadir_includes WITH KEY table_line = <lv_include> TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
DELETE rt_includes.
CONTINUE.
ENDIF.
IF strlen( <lv_include> ) = 33 AND <lv_include>+30(3) = 'XTI'.
"ignore referenced (simple) transformation includes
DELETE rt_includes.
CONTINUE.
ENDIF.
ENDLOOP.
IF lines( rt_includes ) > 0.
SELECT progname FROM reposrc
INTO TABLE lt_reposrc
FOR ALL ENTRIES IN rt_includes
WHERE progname = rt_includes-table_line
AND r3state = 'A'.
ENDIF.
SORT lt_reposrc BY progname ASCENDING.
ENDIF.
LOOP AT rt_includes ASSIGNING <lv_include>.
lv_tabix = sy-tabix.
* make sure the include exists
READ TABLE lt_reposrc INTO ls_reposrc
WITH KEY progname = <lv_include> BINARY SEARCH.
IF sy-subrc <> 0.
DELETE rt_includes INDEX lv_tabix.
CONTINUE.
ENDIF.
"Make sure that the include does not belong to another function group
IF is_part_of_other_fugr( <lv_include> ) = abap_true.
DELETE rt_includes.
ENDIF.
ENDLOOP.
APPEND lv_program TO rt_includes.
SORT rt_includes.
mt_includes_cache = rt_includes.
ENDMETHOD.
METHOD is_part_of_other_fugr.
" make sure that the include belongs to the function group
" like in LSEAPFAP Form TADIR_MAINTENANCE
DATA ls_tadir TYPE tadir.
DATA lv_namespace TYPE rs38l-namespace.
DATA lv_function_group TYPE rs38l-area.
DATA lv_include TYPE rs38l-include.
rv_belongs_to_other_fugr = abap_false.
IF iv_include(1) = 'L' OR iv_include+1 CS '/L'.
lv_include = iv_include.
ls_tadir-object = 'FUGR'.
CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT'
IMPORTING
namespace = lv_namespace
group = lv_function_group
CHANGING
include = lv_include
EXCEPTIONS
OTHERS = 1.
IF lv_function_group(1) = 'X'. " "EXIT"-function-module
ls_tadir-object = 'FUGS'.
ENDIF.
IF sy-subrc = 0.
CONCATENATE lv_namespace lv_function_group INTO ls_tadir-obj_name.
" compare complete tadir key to distinguish between regular and exit function groups
IF ls_tadir-obj_name <> ms_item-obj_name OR ls_tadir-object <> ms_item-obj_type.
rv_belongs_to_other_fugr = abap_true.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD main_name.
DATA: lv_area TYPE rs38l-area,
lv_namespace TYPE rs38l-namespace,
lv_group TYPE rs38l-area.
lv_area = ms_item-obj_name.
CALL FUNCTION 'FUNCTION_INCLUDE_SPLIT'
EXPORTING
complete_area = lv_area
IMPORTING
namespace = lv_namespace
group = lv_group
EXCEPTIONS
include_not_exists = 1
group_not_exists = 2
no_selections = 3
no_function_include = 4
no_function_pool = 5
delimiter_wrong_position = 6
no_customer_function_group = 7
no_customer_function_include = 8
reserved_name_customer = 9
namespace_too_long = 10
area_length_error = 11
OTHERS = 12.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise_t100( ).
ENDIF.
CONCATENATE lv_namespace 'SAPL' lv_group INTO rv_program.
ENDMETHOD.
METHOD serialize_functions.
DATA:
lt_source TYPE TABLE OF rssource,
lt_functab TYPE ty_rs38l_incl_tt,
lt_new_source TYPE rsfb_source,
ls_function LIKE LINE OF rt_functions.
FIELD-SYMBOLS: <ls_func> LIKE LINE OF lt_functab,
<ls_documentation> TYPE LINE OF ty_function-documentation.
lt_functab = functions( ).
LOOP AT lt_functab ASSIGNING <ls_func>.
* fm RPY_FUNCTIONMODULE_READ does not support source code
* lines longer than 72 characters
CLEAR ls_function.
MOVE-CORRESPONDING <ls_func> TO ls_function.
CLEAR lt_new_source.
CLEAR lt_source.
CALL FUNCTION 'RPY_FUNCTIONMODULE_READ_NEW'
EXPORTING
functionname = <ls_func>-funcname
IMPORTING
global_flag = ls_function-global_flag
remote_call = ls_function-remote_call
update_task = ls_function-update_task
short_text = ls_function-short_text
remote_basxml_supported = ls_function-remote_basxml
TABLES
import_parameter = ls_function-import
changing_parameter = ls_function-changing
export_parameter = ls_function-export
tables_parameter = ls_function-tables
exception_list = ls_function-exception
documentation = ls_function-documentation
source = lt_source
CHANGING
new_source = lt_new_source
EXCEPTIONS
error_message = 1
function_not_found = 2
invalid_name = 3
OTHERS = 4.
IF sy-subrc = 2.
CONTINUE.
ELSEIF sy-subrc <> 0.
zcx_abapgit_exception=>raise( 'Error from RPY_FUNCTIONMODULE_READ_NEW' ).
ENDIF.
LOOP AT ls_function-documentation ASSIGNING <ls_documentation>.
CLEAR <ls_documentation>-index.
ENDLOOP.
SELECT SINGLE exten3 INTO ls_function-exception_classes FROM enlfdir
WHERE funcname = <ls_func>-funcname. "#EC CI_SUBRC
APPEND ls_function TO rt_functions.
IF NOT lt_new_source IS INITIAL.
strip_generation_comments( CHANGING ct_source = lt_new_source ).
mo_files->add_abap(
iv_extra = <ls_func>-funcname
it_abap = lt_new_source ).
ELSE.
strip_generation_comments( CHANGING ct_source = lt_source ).
mo_files->add_abap(
iv_extra = <ls_func>-funcname
it_abap = lt_source ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD serialize_function_docs.
FIELD-SYMBOLS <ls_func> LIKE LINE OF it_functions.
zcl_abapgit_factory=>get_longtexts( )->serialize(
iv_longtext_id = c_longtext_id_prog
iv_object_name = iv_prog_name
io_i18n_params = mo_i18n_params
ii_xml = ii_xml ).
LOOP AT it_functions ASSIGNING <ls_func>.
zcl_abapgit_factory=>get_longtexts( )->serialize(
iv_longtext_name = |LONGTEXTS_{ <ls_func>-funcname }|
iv_longtext_id = c_longtext_id_func
iv_object_name = <ls_func>-funcname
io_i18n_params = mo_i18n_params
ii_xml = ii_xml ).
zcl_abapgit_factory=>get_longtexts( )->serialize(
iv_longtext_name = |LONGTEXTS_{ <ls_func>-funcname }___EXC|
iv_longtext_id = c_longtext_id_func_exc
iv_object_name = <ls_func>-funcname
io_i18n_params = mo_i18n_params
ii_xml = ii_xml ).
ENDLOOP.
ENDMETHOD.
METHOD serialize_includes.
DATA: lt_includes TYPE ty_sobj_name_tt.
FIELD-SYMBOLS: <lv_include> LIKE LINE OF lt_includes.
lt_includes = includes( ).
LOOP AT lt_includes ASSIGNING <lv_include>.
* todo, filename is not correct, a include can be used in several programs
serialize_program( is_item = ms_item
io_files = mo_files
iv_program = <lv_include>
iv_extra = <lv_include> ).
ENDLOOP.
ENDMETHOD.
METHOD serialize_texts.
DATA: lt_tpool_i18n TYPE ty_tpools_i18n,
lt_tpool TYPE textpool_table.
FIELD-SYMBOLS <ls_tpool> LIKE LINE OF lt_tpool_i18n.
IF mo_i18n_params->ms_params-main_language_only = abap_true.
RETURN.
ENDIF.
" Table d010tinf stores info. on languages in which program is maintained
" Select all active translations of program texts
" Skip main language - it was already serialized
SELECT DISTINCT language
INTO CORRESPONDING FIELDS OF TABLE lt_tpool_i18n
FROM d010tinf
WHERE r3state = 'A'
AND prog = iv_prog_name
AND language <> mv_language
ORDER BY language ##TOO_MANY_ITAB_FIELDS.
mo_i18n_params->trim_saplang_keyed_table(
EXPORTING
iv_lang_field_name = 'LANGUAGE'
CHANGING
ct_tab = lt_tpool_i18n ).
SORT lt_tpool_i18n BY language ASCENDING.
LOOP AT lt_tpool_i18n ASSIGNING <ls_tpool>.
READ TEXTPOOL iv_prog_name
LANGUAGE <ls_tpool>-language
INTO lt_tpool.
<ls_tpool>-textpool = add_tpool( lt_tpool ).
ENDLOOP.
IF lines( lt_tpool_i18n ) > 0.
ii_xml->add( iv_name = 'I18N_TPOOL'
ig_data = lt_tpool_i18n ).
ENDIF.
ENDMETHOD.
METHOD serialize_xml.
DATA: lt_includes TYPE ty_sobj_name_tt,
lv_areat TYPE tlibt-areat.
SELECT SINGLE areat INTO lv_areat
FROM tlibt
WHERE spras = mv_language
AND area = ms_item-obj_name. "#EC CI_GENBUFF "#EC CI_SUBRC
lt_includes = includes( ).
ii_xml->add( iv_name = 'AREAT'
ig_data = lv_areat ).
ii_xml->add( iv_name = 'INCLUDES'
ig_data = lt_includes ).
ENDMETHOD.
METHOD zif_abapgit_object~changed_by.
rv_user = c_user_unknown.
ENDMETHOD.
METHOD zif_abapgit_object~delete.
ASSERT 1 = 'todo'.
ENDMETHOD.
METHOD zif_abapgit_object~deserialize.
ASSERT 1 = 'todo'.
ENDMETHOD.
METHOD zif_abapgit_object~exists.
DATA lv_pool TYPE tlibg-area.
lv_pool = ms_item-obj_name.
CALL FUNCTION 'RS_FUNCTION_POOL_EXISTS'
EXPORTING
function_pool = lv_pool
EXCEPTIONS
pool_not_exists = 1.
rv_bool = boolc( sy-subrc <> 1 ).
ENDMETHOD.
METHOD zif_abapgit_object~get_comparator.
RETURN.
ENDMETHOD.
METHOD zif_abapgit_object~get_deserialize_order.
RETURN.
ENDMETHOD.
METHOD zif_abapgit_object~get_deserialize_steps.
APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps.
ENDMETHOD.
METHOD zif_abapgit_object~get_metadata.
rs_metadata = get_metadata( ).
ENDMETHOD.
METHOD zif_abapgit_object~is_active.
rv_active = is_active( ).
ENDMETHOD.
METHOD zif_abapgit_object~is_locked.
rv_is_locked = abap_false.
ENDMETHOD.
METHOD zif_abapgit_object~jump.
RETURN.
ENDMETHOD.
METHOD zif_abapgit_object~map_filename_to_object.
RETURN.
ENDMETHOD.
METHOD zif_abapgit_object~map_object_to_filename.
RETURN.
ENDMETHOD.
METHOD zif_abapgit_object~serialize.
* function group SEUF
* function group SIFP
* function group SUNI
DATA: lt_functions TYPE ty_function_tt,
ls_progdir TYPE zif_abapgit_sap_report=>ty_progdir,
lv_program_name TYPE syrepid,
lt_dynpros TYPE ty_dynpro_tt,
ls_cua TYPE ty_cua.
IF zif_abapgit_object~exists( ) = abap_false.
RETURN.
ENDIF.
serialize_xml( io_xml ).
lt_functions = serialize_functions( ).
io_xml->add( iv_name = 'FUNCTIONS'
ig_data = lt_functions ).
serialize_includes( ).
lv_program_name = main_name( ).
ls_progdir = zcl_abapgit_factory=>get_sap_report( )->read_progdir( lv_program_name ).
IF mo_i18n_params->is_lxe_applicable( ) = abap_false.
serialize_texts(
iv_prog_name = lv_program_name
ii_xml = io_xml ).
ENDIF.
IF ls_progdir-subc = 'F'.
lt_dynpros = serialize_dynpros( lv_program_name ).
io_xml->add( iv_name = 'DYNPROS'
ig_data = lt_dynpros ).
ls_cua = serialize_cua( lv_program_name ).
io_xml->add( iv_name = 'CUA'
ig_data = ls_cua ).
ENDIF.
serialize_function_docs( iv_prog_name = lv_program_name
it_functions = lt_functions
ii_xml = io_xml ).
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_ABAPGIT_OBJECT_FUGS</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abapGit - FUGS</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>