From 52b83dcde7a12f8264514281618046898b298112 Mon Sep 17 00:00:00 2001 From: Lars Hvam Date: Tue, 10 Sep 2024 07:57:27 +0200 Subject: [PATCH] basic FUGS serialization --- src/objects/zcl_abapgit_object_fugs.clas.abap | 650 ++++++++++++++++++ src/objects/zcl_abapgit_object_fugs.clas.xml | 16 + 2 files changed, 666 insertions(+) create mode 100644 src/objects/zcl_abapgit_object_fugs.clas.abap create mode 100644 src/objects/zcl_abapgit_object_fugs.clas.xml diff --git a/src/objects/zcl_abapgit_object_fugs.clas.abap b/src/objects/zcl_abapgit_object_fugs.clas.abap new file mode 100644 index 000000000..f482dca55 --- /dev/null +++ b/src/objects/zcl_abapgit_object_fugs.clas.abap @@ -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: 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 . + TRANSLATE 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: LIKE LINE OF rt_includes, + 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 . + DELETE TABLE rt_includes FROM -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 . + " skip autogenerated includes from Table Maintenance Generator + IF CP 'LSVIM*'. + DELETE rt_includes INDEX sy-tabix. + CONTINUE. + ENDIF. + READ TABLE lt_tadir_includes WITH KEY table_line = TRANSPORTING NO FIELDS. + IF sy-subrc = 0. + DELETE rt_includes. + CONTINUE. + ENDIF. + IF strlen( ) = 33 AND +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_tabix = sy-tabix. + +* make sure the include exists + READ TABLE lt_reposrc INTO ls_reposrc + WITH KEY progname = 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( ) = 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: LIKE LINE OF lt_functab, + TYPE LINE OF ty_function-documentation. + + lt_functab = functions( ). + + LOOP AT lt_functab ASSIGNING . +* fm RPY_FUNCTIONMODULE_READ does not support source code +* lines longer than 72 characters + CLEAR ls_function. + MOVE-CORRESPONDING TO ls_function. + + CLEAR lt_new_source. + CLEAR lt_source. + + CALL FUNCTION 'RPY_FUNCTIONMODULE_READ_NEW' + EXPORTING + functionname = -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 . + CLEAR -index. + ENDLOOP. + + SELECT SINGLE exten3 INTO ls_function-exception_classes FROM enlfdir + WHERE funcname = -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 = -funcname + it_abap = lt_new_source ). + ELSE. + strip_generation_comments( CHANGING ct_source = lt_source ). + mo_files->add_abap( + iv_extra = -funcname + it_abap = lt_source ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + + + METHOD serialize_function_docs. + + FIELD-SYMBOLS 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 . + zcl_abapgit_factory=>get_longtexts( )->serialize( + iv_longtext_name = |LONGTEXTS_{ -funcname }| + iv_longtext_id = c_longtext_id_func + iv_object_name = -funcname + io_i18n_params = mo_i18n_params + ii_xml = ii_xml ). + zcl_abapgit_factory=>get_longtexts( )->serialize( + iv_longtext_name = |LONGTEXTS_{ -funcname }___EXC| + iv_longtext_id = c_longtext_id_func_exc + iv_object_name = -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: LIKE LINE OF lt_includes. + + + lt_includes = includes( ). + + LOOP AT lt_includes ASSIGNING . + +* 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 = + iv_extra = ). + + ENDLOOP. + + ENDMETHOD. + + + METHOD serialize_texts. + DATA: lt_tpool_i18n TYPE ty_tpools_i18n, + lt_tpool TYPE textpool_table. + + FIELD-SYMBOLS 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 . + READ TEXTPOOL iv_prog_name + LANGUAGE -language + INTO lt_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. diff --git a/src/objects/zcl_abapgit_object_fugs.clas.xml b/src/objects/zcl_abapgit_object_fugs.clas.xml new file mode 100644 index 000000000..7e5bc4b12 --- /dev/null +++ b/src/objects/zcl_abapgit_object_fugs.clas.xml @@ -0,0 +1,16 @@ + + + + + + ZCL_ABAPGIT_OBJECT_FUGS + E + abapGit - FUGS + 1 + X + X + X + + + +