CLASS zcl_abapgit_objects_program DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF ty_cua, adm TYPE rsmpe_adm, sta TYPE STANDARD TABLE OF rsmpe_stat WITH DEFAULT KEY, fun TYPE STANDARD TABLE OF rsmpe_funt WITH DEFAULT KEY, men TYPE STANDARD TABLE OF rsmpe_men WITH DEFAULT KEY, mtx TYPE STANDARD TABLE OF rsmpe_mnlt WITH DEFAULT KEY, act TYPE STANDARD TABLE OF rsmpe_act WITH DEFAULT KEY, but TYPE STANDARD TABLE OF rsmpe_but WITH DEFAULT KEY, pfk TYPE STANDARD TABLE OF rsmpe_pfk WITH DEFAULT KEY, set TYPE STANDARD TABLE OF rsmpe_staf WITH DEFAULT KEY, doc TYPE STANDARD TABLE OF rsmpe_atrt WITH DEFAULT KEY, tit TYPE STANDARD TABLE OF rsmpe_titt WITH DEFAULT KEY, biv TYPE STANDARD TABLE OF rsmpe_buts WITH DEFAULT KEY, END OF ty_cua. METHODS serialize_program IMPORTING !io_xml TYPE REF TO zif_abapgit_xml_output OPTIONAL !is_item TYPE zif_abapgit_definitions=>ty_item !io_files TYPE REF TO zcl_abapgit_objects_files !iv_program TYPE syrepid OPTIONAL !iv_extra TYPE clike OPTIONAL RAISING zcx_abapgit_exception. METHODS deserialize_program IMPORTING !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir !it_source TYPE abaptxt255_tab !it_tpool TYPE textpool_table !iv_package TYPE devclass RAISING zcx_abapgit_exception. PROTECTED SECTION. TYPES: ty_spaces_tt TYPE STANDARD TABLE OF i WITH DEFAULT KEY . TYPES: BEGIN OF ty_dynpro, header TYPE rpy_dyhead, containers TYPE dycatt_tab, fields TYPE dyfatc_tab, flow_logic TYPE swydyflow, spaces TYPE ty_spaces_tt, nat_header TYPE d020s, nat_fields TYPE STANDARD TABLE OF d021s WITH DEFAULT KEY, nat_texts TYPE STANDARD TABLE OF d021t WITH DEFAULT KEY, END OF ty_dynpro . TYPES: ty_dynpro_tt TYPE STANDARD TABLE OF ty_dynpro WITH DEFAULT KEY . METHODS strip_generation_comments CHANGING ct_source TYPE STANDARD TABLE. " tab of string or charX METHODS serialize_dynpros IMPORTING !iv_program_name TYPE syrepid RETURNING VALUE(rt_dynpro) TYPE ty_dynpro_tt RAISING zcx_abapgit_exception . METHODS serialize_cua IMPORTING !iv_program_name TYPE syrepid RETURNING VALUE(rs_cua) TYPE ty_cua RAISING zcx_abapgit_exception . METHODS deserialize_dynpros IMPORTING !it_dynpros TYPE ty_dynpro_tt RAISING zcx_abapgit_exception . METHODS deserialize_textpool IMPORTING !iv_program TYPE syrepid !it_tpool TYPE textpool_table !iv_language TYPE sy-langu OPTIONAL !iv_is_include TYPE abap_bool DEFAULT abap_false RAISING zcx_abapgit_exception . METHODS deserialize_cua IMPORTING !iv_program_name TYPE syrepid !is_cua TYPE ty_cua RAISING zcx_abapgit_exception . METHODS is_any_dynpro_locked IMPORTING !iv_program TYPE syrepid RETURNING VALUE(rv_is_any_dynpro_locked) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS is_cua_locked IMPORTING !iv_program TYPE syrepid RETURNING VALUE(rv_is_cua_locked) TYPE abap_bool RAISING zcx_abapgit_exception . METHODS is_text_locked IMPORTING !iv_program TYPE syrepid RETURNING VALUE(rv_is_text_locked) TYPE abap_bool RAISING zcx_abapgit_exception . CLASS-METHODS add_tpool IMPORTING !it_tpool TYPE textpool_table RETURNING VALUE(rt_tpool) TYPE zif_abapgit_definitions=>ty_tpool_tt . CLASS-METHODS read_tpool IMPORTING !it_tpool TYPE zif_abapgit_definitions=>ty_tpool_tt RETURNING VALUE(rt_tpool) TYPE zif_abapgit_definitions=>ty_tpool_tt . PRIVATE SECTION. CONSTANTS: BEGIN OF c_state, active TYPE r3state VALUE 'A', inactive TYPE r3state VALUE 'I', END OF c_state. CONSTANTS c_native_dynpro TYPE c LENGTH 2 VALUE 'IN'. METHODS: uncondense_flow IMPORTING it_flow TYPE swydyflow it_spaces TYPE ty_spaces_tt RETURNING VALUE(rt_flow) TYPE swydyflow. CLASS-METHODS auto_correct_cua_adm IMPORTING is_cua TYPE ty_cua CHANGING cs_adm TYPE rsmpe_adm. METHODS get_program_title IMPORTING !it_tpool TYPE textpool_table RETURNING VALUE(rv_title) TYPE repti . METHODS insert_program IMPORTING !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir !it_source TYPE abaptxt255_tab !iv_title TYPE repti !iv_package TYPE devclass !iv_state TYPE progdir-state DEFAULT c_state-inactive RAISING zcx_abapgit_exception . METHODS update_program IMPORTING !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir !it_source TYPE abaptxt255_tab !iv_title TYPE repti !iv_state TYPE progdir-state DEFAULT c_state-inactive RAISING zcx_abapgit_exception . METHODS is_exit_include IMPORTING !iv_program TYPE syrepid RETURNING VALUE(rv_is_exit_include) TYPE abap_bool. METHODS deserialize_exit_include IMPORTING !is_progdir TYPE zif_abapgit_sap_report=>ty_progdir !it_source TYPE abaptxt255_tab !it_tpool TYPE textpool_table !iv_package TYPE devclass RAISING zcx_abapgit_exception. ENDCLASS. CLASS zcl_abapgit_objects_program IMPLEMENTATION. METHOD add_tpool. FIELD-SYMBOLS: LIKE LINE OF it_tpool, LIKE LINE OF rt_tpool. LOOP AT it_tpool ASSIGNING . APPEND INITIAL LINE TO rt_tpool ASSIGNING . MOVE-CORRESPONDING TO . IF -id = 'S'. -split = -entry. -entry = -entry+8. ENDIF. ENDLOOP. ENDMETHOD. METHOD auto_correct_cua_adm. " issue #1807 automatic correction of CUA interfaces saved incorrectly in the past (ADM was not saved in the XML) CONSTANTS: lc_num_n_space TYPE string VALUE ' 0123456789', lc_num_only TYPE string VALUE '0123456789'. FIELD-SYMBOLS: TYPE rsmpe_pfk, TYPE rsmpe_act, TYPE rsmpe_men. IF cs_adm IS NOT INITIAL AND cs_adm-actcode CO lc_num_n_space AND cs_adm-mencode CO lc_num_n_space AND cs_adm-pfkcode CO lc_num_n_space. "Check performed in form check_adm of include LSMPIF03 RETURN. ENDIF. LOOP AT is_cua-act ASSIGNING . IF -code+6(14) IS INITIAL AND -code(6) CO lc_num_only. cs_adm-actcode = -code. ENDIF. ENDLOOP. LOOP AT is_cua-men ASSIGNING . IF -code+6(14) IS INITIAL AND -code(6) CO lc_num_only. cs_adm-mencode = -code. ENDIF. ENDLOOP. LOOP AT is_cua-pfk ASSIGNING . IF -code+6(14) IS INITIAL AND -code(6) CO lc_num_only. cs_adm-pfkcode = -code. ENDIF. ENDLOOP. ENDMETHOD. METHOD deserialize_cua. DATA: ls_tr_key TYPE trkey, ls_adm TYPE rsmpe_adm. IF lines( is_cua-sta ) = 0 AND lines( is_cua-fun ) = 0 AND lines( is_cua-men ) = 0 AND lines( is_cua-mtx ) = 0 AND lines( is_cua-act ) = 0 AND lines( is_cua-but ) = 0 AND lines( is_cua-pfk ) = 0 AND lines( is_cua-set ) = 0 AND lines( is_cua-doc ) = 0 AND lines( is_cua-tit ) = 0 AND lines( is_cua-biv ) = 0. RETURN. ENDIF. SELECT SINGLE devclass INTO ls_tr_key-devclass FROM tadir WHERE pgmid = 'R3TR' AND object = ms_item-obj_type AND obj_name = ms_item-obj_name. "#EC CI_GENBUFF IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'not found in tadir' ). ENDIF. ls_tr_key-obj_type = ms_item-obj_type. ls_tr_key-obj_name = ms_item-obj_name. ls_tr_key-sub_type = 'CUAD'. ls_tr_key-sub_name = iv_program_name. ls_adm = is_cua-adm. auto_correct_cua_adm( EXPORTING is_cua = is_cua CHANGING cs_adm = ls_adm ). sy-tcode = 'SE41' ##WRITE_OK. " evil hack, workaround to handle fixes in note 2159455 CALL FUNCTION 'RS_CUA_INTERNAL_WRITE' EXPORTING program = iv_program_name language = mv_language tr_key = ls_tr_key adm = ls_adm state = c_state-inactive TABLES sta = is_cua-sta fun = is_cua-fun men = is_cua-men mtx = is_cua-mtx act = is_cua-act but = is_cua-but pfk = is_cua-pfk set = is_cua-set doc = is_cua-doc tit = is_cua-tit biv = is_cua-biv EXCEPTIONS not_found = 1 OTHERS = 2. IF sy-subrc <> 0. * if moving code from SAPlink, see https://github.com/abapGit/abapGit/issues/562 zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_objects_activation=>add( iv_type = 'CUAD' iv_name = iv_program_name ). ENDMETHOD. METHOD deserialize_dynpros. CONSTANTS lc_rpyty_force_off TYPE c LENGTH 1 VALUE '/'. DATA: lv_name TYPE dwinactiv-obj_name, lt_d020s_to_delete TYPE TABLE OF d020s, ls_d020s LIKE LINE OF lt_d020s_to_delete, lt_params TYPE TABLE OF d023s, ls_dynpro LIKE LINE OF it_dynpros. FIELD-SYMBOLS: TYPE rpy_dyfatc. " Delete DYNPROs which are not in the list CALL FUNCTION 'RS_SCREEN_LIST' EXPORTING dynnr = '' progname = ms_item-obj_name TABLES dynpros = lt_d020s_to_delete EXCEPTIONS not_found = 1 OTHERS = 2. IF sy-subrc = 2. zcx_abapgit_exception=>raise_t100( ). ENDIF. SORT lt_d020s_to_delete BY dnum ASCENDING. * ls_dynpro is changed by the function module, a field-symbol will cause * the program to dump since it_dynpros cannot be changed LOOP AT it_dynpros INTO ls_dynpro. READ TABLE lt_d020s_to_delete WITH KEY dnum = ls_dynpro-header-screen TRANSPORTING NO FIELDS BINARY SEARCH. IF sy-subrc = 0. DELETE lt_d020s_to_delete INDEX sy-tabix. ENDIF. " todo: kept for compatibility, remove after grace period #3680 ls_dynpro-flow_logic = uncondense_flow( it_flow = ls_dynpro-flow_logic it_spaces = ls_dynpro-spaces ). IF ls_dynpro-flow_logic IS INITIAL. ls_dynpro-flow_logic = mo_files->read_abap( iv_extra = 'screen_' && ls_dynpro-header-screen ). ENDIF. LOOP AT ls_dynpro-fields ASSIGNING . * if the DDIC element has a PARAMETER_ID and the flag "from_dict" is active * the import will enable the SET-/GET_PARAM flag. In this case: "force off" IF -param_id IS NOT INITIAL AND -from_dict = abap_true. IF -set_param IS INITIAL. -set_param = lc_rpyty_force_off. ENDIF. IF -get_param IS INITIAL. -get_param = lc_rpyty_force_off. ENDIF. ENDIF. * If the previous conditions are met the value 'F' will be taken over * during de-serialization potentially overlapping other fields in the screen, * we set the tag to the correct value 'X' IF -type = 'CHECK' AND -from_dict = abap_true AND -text IS INITIAL AND -modific IS INITIAL. -modific = 'X'. ENDIF. "fix for issue #2747: IF -foreignkey IS INITIAL. -foreignkey = lc_rpyty_force_off. ENDIF. ENDLOOP. IF ls_dynpro-header-type CA c_native_dynpro AND ls_dynpro-nat_header IS NOT INITIAL. DELETE FROM d021t WHERE prog = ls_dynpro-header-program AND dynr = ls_dynpro-header-screen ##SUBRC_OK. INSERT d021t FROM TABLE ls_dynpro-nat_texts ##SUBRC_OK. ls_dynpro-nat_header-dgen = sy-datum. ls_dynpro-nat_header-tgen = sy-uzeit. CALL FUNCTION 'RPY_DYNPRO_INSERT_NATIVE' EXPORTING header = ls_dynpro-nat_header dynprotext = ls_dynpro-header-descript TABLES fieldlist = ls_dynpro-nat_fields flowlogic = ls_dynpro-flow_logic params = lt_params EXCEPTIONS cancelled = 1 already_exists = 2 program_not_exists = 3 not_executed = 4 OTHERS = 5. ELSE. CALL FUNCTION 'RPY_DYNPRO_INSERT' EXPORTING header = ls_dynpro-header suppress_exist_checks = abap_true suppress_generate = ls_dynpro-header-no_execute TABLES containers = ls_dynpro-containers fields_to_containers = ls_dynpro-fields flow_logic = ls_dynpro-flow_logic EXCEPTIONS cancelled = 1 already_exists = 2 program_not_exists = 3 not_executed = 4 missing_required_field = 5 illegal_field_value = 6 field_not_allowed = 7 not_generated = 8 illegal_field_position = 9 OTHERS = 10. ENDIF. IF sy-subrc <> 2 AND sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. CONCATENATE ls_dynpro-header-program ls_dynpro-header-screen INTO lv_name RESPECTING BLANKS. ASSERT NOT lv_name IS INITIAL. zcl_abapgit_objects_activation=>add( iv_type = 'DYNP' iv_name = lv_name ). ENDLOOP. " Delete obsolete screens LOOP AT lt_d020s_to_delete INTO ls_d020s. CALL FUNCTION 'RS_SCRP_DELETE' EXPORTING dynnr = ls_d020s-dnum progname = ms_item-obj_name with_popup = abap_false EXCEPTIONS enqueued_by_user = 1 enqueue_system_failure = 2 not_executed = 3 not_exists = 4 no_modify_permission = 5 popup_canceled = 6. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDLOOP. ENDMETHOD. METHOD deserialize_exit_include. DATA: lv_progname TYPE reposrc-progname, lv_title TYPE rglif-title. " Includes in SAP exit function groups must be processed in active state only " (check in RS_INSERT_INTO_WORKING_AREA) lv_title = get_program_title( it_tpool ). SELECT SINGLE progname FROM reposrc INTO lv_progname WHERE progname = is_progdir-name AND r3state = c_state-active. IF sy-subrc = 0. update_program( is_progdir = is_progdir it_source = it_source iv_title = lv_title iv_state = '' ). ELSE. insert_program( is_progdir = is_progdir it_source = it_source iv_title = lv_title iv_package = iv_package iv_state = '' ). ENDIF. ENDMETHOD. METHOD deserialize_program. DATA: lv_progname TYPE reposrc-progname, lv_title TYPE rglif-title. IF is_exit_include( is_progdir-name ) = abap_true. deserialize_exit_include( is_progdir = is_progdir it_source = it_source it_tpool = it_tpool iv_package = iv_package ). RETURN. ENDIF. zcl_abapgit_factory=>get_cts_api( )->insert_transport_object( iv_object = 'ABAP' iv_obj_name = is_progdir-name iv_package = iv_package iv_language = mv_language ). lv_title = get_program_title( it_tpool ). " Check if program already exists SELECT SINGLE progname FROM reposrc INTO lv_progname WHERE progname = is_progdir-name AND r3state = c_state-active. IF sy-subrc = 0. update_program( is_progdir = is_progdir it_source = it_source iv_title = lv_title ). ELSE. insert_program( is_progdir = is_progdir it_source = it_source iv_title = lv_title iv_package = iv_package ). ENDIF. zcl_abapgit_factory=>get_sap_report( )->update_progdir( is_progdir = is_progdir iv_package = iv_package ). zcl_abapgit_objects_activation=>add( iv_type = 'REPS' iv_name = is_progdir-name ). ENDMETHOD. METHOD deserialize_textpool. DATA lv_language TYPE sy-langu. DATA lv_state TYPE c. DATA lv_delete TYPE abap_bool. IF iv_language IS INITIAL. lv_language = mv_language. ELSE. lv_language = iv_language. ENDIF. IF lv_language = mv_language. lv_state = c_state-inactive. "Textpool in main language needs to be activated ELSE. lv_state = c_state-active. "Translations are always active ENDIF. IF it_tpool IS INITIAL. IF iv_is_include = abap_false OR lv_state = c_state-active. DELETE TEXTPOOL iv_program "Remove initial description from textpool if LANGUAGE lv_language "original program does not have a textpool STATE lv_state. lv_delete = abap_true. ELSE. INSERT TEXTPOOL iv_program "In case of includes: Deletion of textpool in FROM it_tpool "main language cannot be activated because LANGUAGE lv_language "this would activate the deletion of the textpool STATE lv_state. "of the mail program -> insert empty textpool ENDIF. ELSE. INSERT TEXTPOOL iv_program FROM it_tpool LANGUAGE lv_language STATE lv_state. IF sy-subrc <> 0. zcx_abapgit_exception=>raise( 'error from INSERT TEXTPOOL' ). ENDIF. ENDIF. "Textpool in main language needs to be activated (not for FUGS/FUGX) IF lv_state = c_state-inactive AND iv_program NP 'SAPLX*'. zcl_abapgit_objects_activation=>add( iv_type = 'REPT' iv_name = iv_program iv_delete = lv_delete ). ENDIF. ENDMETHOD. METHOD get_program_title. DATA ls_tpool LIKE LINE OF it_tpool. FIELD-SYMBOLS TYPE any. READ TABLE it_tpool INTO ls_tpool WITH KEY id = 'R'. IF sy-subrc = 0. " there is a bug in RPY_PROGRAM_UPDATE, the header line of TTAB is not " cleared, so the title length might be inherited from a different program. ASSIGN ('(SAPLSIFP)TTAB') TO . IF sy-subrc = 0. CLEAR . ENDIF. rv_title = ls_tpool-entry. ENDIF. ENDMETHOD. METHOD insert_program. TRY. CALL FUNCTION 'RPY_PROGRAM_INSERT' EXPORTING development_class = iv_package program_name = is_progdir-name program_type = is_progdir-subc title_string = iv_title save_inactive = iv_state suppress_dialog = abap_true uccheck = is_progdir-uccheck " does not exist on lower releases TABLES source_extended = it_source EXCEPTIONS already_exists = 1 cancelled = 2 name_not_allowed = 3 permission_error = 4 OTHERS = 5 ##FM_SUBRC_OK. CATCH cx_sy_dyn_call_param_not_found. CALL FUNCTION 'RPY_PROGRAM_INSERT' EXPORTING development_class = iv_package program_name = is_progdir-name program_type = is_progdir-subc title_string = iv_title save_inactive = iv_state suppress_dialog = abap_true TABLES source_extended = it_source EXCEPTIONS already_exists = 1 cancelled = 2 name_not_allowed = 3 permission_error = 4 OTHERS = 5 ##FM_SUBRC_OK. ENDTRY. IF sy-subrc = 3. " For cases that standard function does not handle (like FUGR), " we save active and inactive version of source with the given PROGRAM TYPE. " Without the active version, the code will not be visible in case of activation errors. zcl_abapgit_factory=>get_sap_report( )->insert_report( iv_name = is_progdir-name iv_package = iv_package it_source = it_source iv_state = c_state-active iv_version = is_progdir-uccheck iv_program_type = is_progdir-subc ). zcl_abapgit_factory=>get_sap_report( )->insert_report( iv_name = is_progdir-name iv_package = iv_package it_source = it_source iv_state = c_state-inactive iv_version = is_progdir-uccheck iv_program_type = is_progdir-subc ). ELSEIF sy-subrc > 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD is_any_dynpro_locked. DATA: lt_dynpros TYPE ty_dynpro_tt, lv_object TYPE seqg3-garg. FIELD-SYMBOLS: TYPE ty_dynpro. lt_dynpros = serialize_dynpros( iv_program ). LOOP AT lt_dynpros ASSIGNING . lv_object = |{ -header-screen }{ -header-program }|. IF exists_a_lock_entry_for( iv_lock_object = 'ESCRP' iv_argument = lv_object ) = abap_true. rv_is_any_dynpro_locked = abap_true. EXIT. ENDIF. ENDLOOP. ENDMETHOD. METHOD is_cua_locked. DATA: lv_object TYPE eqegraarg. lv_object = |CU{ iv_program }|. OVERLAY lv_object WITH ' '. lv_object = lv_object && '*'. rv_is_cua_locked = exists_a_lock_entry_for( iv_lock_object = 'ESCUAPAINT' iv_argument = lv_object ). ENDMETHOD. METHOD is_exit_include. rv_is_exit_include = boolc( iv_program CP 'LX*' OR iv_program CP 'SAPLX*' OR iv_program+1 CP '/LX*' OR iv_program+1 CP '/SAPLX*' ). ENDMETHOD. METHOD is_text_locked. DATA: lv_object TYPE eqegraarg. lv_object = |*{ iv_program }|. rv_is_text_locked = exists_a_lock_entry_for( iv_lock_object = 'EABAPTEXTE' iv_argument = lv_object ). ENDMETHOD. METHOD read_tpool. FIELD-SYMBOLS: LIKE LINE OF it_tpool, LIKE LINE OF rt_tpool. LOOP AT it_tpool ASSIGNING . APPEND INITIAL LINE TO rt_tpool ASSIGNING . MOVE-CORRESPONDING TO . IF -id = 'S'. CONCATENATE -split -entry INTO -entry RESPECTING BLANKS. ENDIF. ENDLOOP. ENDMETHOD. METHOD serialize_cua. CALL FUNCTION 'RS_CUA_INTERNAL_FETCH' EXPORTING program = iv_program_name language = mv_language state = c_state-active IMPORTING adm = rs_cua-adm TABLES sta = rs_cua-sta fun = rs_cua-fun men = rs_cua-men mtx = rs_cua-mtx act = rs_cua-act but = rs_cua-but pfk = rs_cua-pfk set = rs_cua-set doc = rs_cua-doc tit = rs_cua-tit biv = rs_cua-biv EXCEPTIONS not_found = 1 unknown_version = 2 OTHERS = 3. IF sy-subrc > 1. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDMETHOD. METHOD serialize_dynpros. DATA: ls_header TYPE rpy_dyhead, lt_containers TYPE dycatt_tab, lt_fields_to_containers TYPE dyfatc_tab, lt_flow_logic TYPE swydyflow, lt_d020s TYPE TABLE OF d020s, lt_texts TYPE TABLE OF d021t, lt_fieldlist_int TYPE TABLE OF d021s. "internal format FIELD-SYMBOLS: LIKE LINE OF lt_d020s, TYPE scrpostyle, LIKE LINE OF lt_containers, LIKE LINE OF lt_fields_to_containers, LIKE LINE OF rt_dynpro, LIKE LINE OF lt_fieldlist_int. "#2746: relevant flag values (taken from include MSEUSBIT) CONSTANTS: lc_flg1ddf TYPE x VALUE '20', lc_flg3fku TYPE x VALUE '08', lc_flg3for TYPE x VALUE '04', lc_flg3fdu TYPE x VALUE '02'. CALL FUNCTION 'RS_SCREEN_LIST' EXPORTING dynnr = '' progname = iv_program_name TABLES dynpros = lt_d020s EXCEPTIONS not_found = 1 OTHERS = 2. IF sy-subrc = 2. zcx_abapgit_exception=>raise_t100( ). ENDIF. SORT lt_d020s BY dnum ASCENDING. * loop dynpros and skip generated selection screens LOOP AT lt_d020s ASSIGNING WHERE type <> 'S' AND type <> 'W' AND type <> 'J' AND NOT dnum IS INITIAL. CALL FUNCTION 'RPY_DYNPRO_READ' EXPORTING progname = iv_program_name dynnr = -dnum IMPORTING header = ls_header TABLES containers = lt_containers fields_to_containers = lt_fields_to_containers flow_logic = lt_flow_logic EXCEPTIONS cancelled = 1 not_found = 2 permission_error = 3 OTHERS = 4. IF sy-subrc <> 0. zcx_abapgit_exception=>raise_t100( ). ENDIF. "#2746: we need the dynpro fields in internal format: FREE lt_fieldlist_int. CALL FUNCTION 'RPY_DYNPRO_READ_NATIVE' EXPORTING progname = iv_program_name dynnr = -dnum TABLES fieldlist = lt_fieldlist_int fieldtexts = lt_texts. LOOP AT lt_fields_to_containers ASSIGNING . * output style is a NUMC field, the XML conversion will fail if it contains invalid value * field does not exist in all versions ASSIGN COMPONENT 'OUTPUTSTYLE' OF STRUCTURE TO . IF sy-subrc = 0 AND = ' '. CLEAR . ENDIF. "2746: we apply the same logic as in SAPLWBSCREEN "for setting or unsetting the foreignkey field: UNASSIGN . READ TABLE lt_fieldlist_int ASSIGNING WITH KEY fnam = -name. IF IS ASSIGNED. IF -flg1 O lc_flg1ddf AND -flg3 O lc_flg3for AND -flg3 Z lc_flg3fdu AND -flg3 Z lc_flg3fku. -foreignkey = 'X'. ELSE. CLEAR -foreignkey. ENDIF. ENDIF. IF -from_dict = abap_true AND -modific <> 'F' AND -modific <> 'X'. CLEAR -text. ENDIF. ENDLOOP. LOOP AT lt_containers ASSIGNING . IF -c_resize_v = abap_false. CLEAR -c_line_min. ENDIF. IF -c_resize_h = abap_false. CLEAR -c_coln_min. ENDIF. ENDLOOP. APPEND INITIAL LINE TO rt_dynpro ASSIGNING . -header = ls_header. " Store flow logic as separate ABAP files instead of XML mo_files->add_abap( iv_extra = 'screen_' && ls_header-screen it_abap = lt_flow_logic ). READ TABLE lt_fieldlist_int TRANSPORTING NO FIELDS WITH KEY fill = 'X'. IF ls_header-type CA c_native_dynpro AND sy-subrc = 0. " In particular for dynpros with splitter -nat_header = . CLEAR: -nat_header-dgen, -nat_header-tgen. -nat_fields = lt_fieldlist_int. -nat_texts = lt_texts. ELSE. -containers = lt_containers. -fields = lt_fields_to_containers. ENDIF. ENDLOOP. ENDMETHOD. METHOD serialize_program. DATA: 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, li_report TYPE REF TO zif_abapgit_sap_report, lt_source TYPE TABLE OF abaptxt255, lt_tpool TYPE textpool_table, ls_tpool LIKE LINE OF lt_tpool, li_xml TYPE REF TO zif_abapgit_xml_output. IF iv_program IS INITIAL. lv_program_name = is_item-obj_name. ELSE. lv_program_name = iv_program. ENDIF. zcl_abapgit_language=>set_current_language( mv_language ). CALL FUNCTION 'RPY_PROGRAM_READ' EXPORTING program_name = lv_program_name with_includelist = abap_false with_lowercase = abap_true TABLES source_extended = lt_source textelements = lt_tpool EXCEPTIONS cancelled = 1 not_found = 2 permission_error = 3 OTHERS = 4. IF sy-subrc = 2. zcl_abapgit_language=>restore_login_language( ). RETURN. ELSEIF sy-subrc <> 0. zcl_abapgit_language=>restore_login_language( ). zcx_abapgit_exception=>raise_t100( ). ENDIF. zcl_abapgit_language=>restore_login_language( ). " If inactive version exists, then RPY_PROGRAM_READ does not return the active code li_report = zcl_abapgit_factory=>get_sap_report( ). TRY. " Raises exception if inactive version does not exist ls_progdir = li_report->read_progdir( iv_name = lv_program_name iv_state = c_state-inactive ). " Explicitly request active source code lt_source = li_report->read_report( iv_name = lv_program_name iv_state = c_state-active ). CATCH zcx_abapgit_exception ##NO_HANDLER. ENDTRY. ls_progdir = li_report->read_progdir( iv_name = lv_program_name iv_state = c_state-active ). clear_abap_language_version( CHANGING cv_abap_language_version = ls_progdir-uccheck ). IF io_xml IS BOUND. li_xml = io_xml. ELSE. CREATE OBJECT li_xml TYPE zcl_abapgit_xml_output. ENDIF. li_xml->add( iv_name = 'PROGDIR' ig_data = ls_progdir ). IF ls_progdir-subc = '1' OR ls_progdir-subc = 'M'. lt_dynpros = serialize_dynpros( lv_program_name ). li_xml->add( iv_name = 'DYNPROS' ig_data = lt_dynpros ). ls_cua = serialize_cua( lv_program_name ). IF NOT ls_cua IS INITIAL. li_xml->add( iv_name = 'CUA' ig_data = ls_cua ). ENDIF. ENDIF. READ TABLE lt_tpool WITH KEY id = 'R' INTO ls_tpool. IF sy-subrc = 0 AND ls_tpool-key = '' AND ls_tpool-length = 0. DELETE lt_tpool INDEX sy-tabix. ENDIF. li_xml->add( iv_name = 'TPOOL' ig_data = add_tpool( lt_tpool ) ). IF NOT io_xml IS BOUND. io_files->add_xml( iv_extra = iv_extra ii_xml = li_xml ). ENDIF. strip_generation_comments( CHANGING ct_source = lt_source ). io_files->add_abap( iv_extra = iv_extra it_abap = lt_source ). ENDMETHOD. METHOD strip_generation_comments. FIELD-SYMBOLS TYPE any. " Assuming CHAR (e.g. abaptxt255_tab) or string (FUGR) IF ms_item-obj_type <> 'FUGR'. RETURN. ENDIF. " Case 1: MV FM main prog and TOPs READ TABLE ct_source INDEX 1 ASSIGNING . IF sy-subrc = 0 AND CP '#**regenerated at *'. DELETE ct_source INDEX 1. RETURN. ENDIF. " Case 2: MV FM includes IF lines( ct_source ) < 5. " Generation header length RETURN. ENDIF. READ TABLE ct_source INDEX 1 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#*---*'. RETURN. ENDIF. READ TABLE ct_source INDEX 2 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#**'. RETURN. ENDIF. READ TABLE ct_source INDEX 3 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#**generation date:*'. RETURN. ENDIF. READ TABLE ct_source INDEX 4 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#**generator version:*'. RETURN. ENDIF. READ TABLE ct_source INDEX 5 ASSIGNING . ASSERT sy-subrc = 0. IF NOT CP '#*---*'. RETURN. ENDIF. DELETE ct_source INDEX 4. DELETE ct_source INDEX 3. ENDMETHOD. METHOD uncondense_flow. DATA: lv_spaces LIKE LINE OF it_spaces. FIELD-SYMBOLS: LIKE LINE OF it_flow, LIKE LINE OF rt_flow. LOOP AT it_flow ASSIGNING . APPEND INITIAL LINE TO rt_flow ASSIGNING . -line = -line. READ TABLE it_spaces INDEX sy-tabix INTO lv_spaces. IF sy-subrc = 0. SHIFT -line RIGHT BY lv_spaces PLACES IN CHARACTER MODE. ENDIF. ENDLOOP. ENDMETHOD. METHOD update_program. zcl_abapgit_language=>set_current_language( mv_language ). CALL FUNCTION 'RPY_PROGRAM_UPDATE' EXPORTING program_name = is_progdir-name title_string = iv_title save_inactive = iv_state TABLES source_extended = it_source EXCEPTIONS cancelled = 1 permission_error = 2 not_found = 3 OTHERS = 4. IF sy-subrc <> 0. zcl_abapgit_language=>restore_login_language( ). IF sy-msgid = 'EU' AND sy-msgno = '510'. zcx_abapgit_exception=>raise( 'User is currently editing program' ). ELSEIF sy-msgid = 'EU' AND sy-msgno = '522'. " for generated table maintenance function groups, the author is set to SAP* instead of the user which " generates the function group. This hits some standard checks, pulling new code again sets the author " to the current user which avoids the check IF is_exit_include( is_progdir-name ) = abap_false. zcx_abapgit_exception=>raise( |Delete function group and pull again, { is_progdir-name } (EU522)| ). ENDIF. ELSE. zcx_abapgit_exception=>raise_t100( ). ENDIF. ENDIF. zcl_abapgit_language=>restore_login_language( ). ENDMETHOD. ENDCLASS.