abapGit/src/objects/zcl_abapgit_objects_program.clas.abap
Marc Bernard 73576ee60e
Improve error messages (#4472)
* Improve error messages

Pass T100 messages to UI/log

* T100 errors

* APACK

* OO

* DEVC

* DRUL

* DTDC

* SRVB

* OBJS

* Program

Co-authored-by: Lars Hvam <larshp@hotmail.com>
2021-02-03 16:31:55 +01:00

967 lines
29 KiB
ABAP

CLASS zcl_abapgit_objects_program DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super.
PUBLIC SECTION.
TYPES: BEGIN OF ty_progdir,
name TYPE progdir-name,
state TYPE progdir-state,
sqlx TYPE progdir-sqlx,
edtx TYPE progdir-edtx,
varcl TYPE progdir-varcl,
dbapl TYPE progdir-dbapl,
dbna TYPE progdir-dbna,
clas TYPE progdir-clas,
type TYPE progdir-type,
occurs TYPE progdir-occurs,
subc TYPE progdir-subc,
appl TYPE progdir-appl,
secu TYPE progdir-secu,
cnam TYPE progdir-cnam,
cdat TYPE progdir-cdat,
unam TYPE progdir-unam,
udat TYPE progdir-udat,
vern TYPE progdir-vern,
levl TYPE progdir-levl,
rstat TYPE progdir-rstat,
rmand TYPE progdir-rmand,
rload TYPE progdir-rload,
fixpt TYPE progdir-fixpt,
sset TYPE progdir-sset,
sdate TYPE progdir-sdate,
stime TYPE progdir-stime,
idate TYPE progdir-idate,
itime TYPE progdir-itime,
ldbname TYPE progdir-ldbname,
uccheck TYPE progdir-uccheck,
END OF ty_progdir.
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 programm OPTIONAL
iv_extra TYPE clike OPTIONAL
RAISING zcx_abapgit_exception.
METHODS read_progdir
IMPORTING iv_program TYPE programm
RETURNING VALUE(rs_progdir) TYPE ty_progdir.
METHODS deserialize_program
IMPORTING is_progdir TYPE 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,
END OF ty_dynpro .
TYPES:
ty_dynpro_tt TYPE STANDARD TABLE OF ty_dynpro WITH DEFAULT KEY .
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_dynpros
IMPORTING
!iv_program_name TYPE programm
RETURNING
VALUE(rt_dynpro) TYPE ty_dynpro_tt
RAISING
zcx_abapgit_exception .
METHODS serialize_cua
IMPORTING
!iv_program_name TYPE programm
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 programm
!it_tpool TYPE textpool_table
!iv_language TYPE langu OPTIONAL
!iv_is_include TYPE abap_bool DEFAULT abap_false
RAISING
zcx_abapgit_exception .
METHODS deserialize_cua
IMPORTING
!iv_program_name TYPE programm
!is_cua TYPE ty_cua
RAISING
zcx_abapgit_exception .
METHODS is_any_dynpro_locked
IMPORTING
!iv_program TYPE programm
RETURNING
VALUE(rv_is_any_dynpro_locked) TYPE abap_bool
RAISING
zcx_abapgit_exception .
METHODS is_cua_locked
IMPORTING
!iv_program TYPE programm
RETURNING
VALUE(rv_is_cua_locked) TYPE abap_bool
RAISING
zcx_abapgit_exception .
METHODS is_text_locked
IMPORTING
!iv_program TYPE programm
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.
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.
ENDCLASS.
CLASS zcl_abapgit_objects_program IMPLEMENTATION.
METHOD add_tpool.
FIELD-SYMBOLS: <ls_tpool_in> LIKE LINE OF it_tpool,
<ls_tpool_out> LIKE LINE OF rt_tpool.
LOOP AT it_tpool ASSIGNING <ls_tpool_in>.
APPEND INITIAL LINE TO rt_tpool ASSIGNING <ls_tpool_out>.
MOVE-CORRESPONDING <ls_tpool_in> TO <ls_tpool_out>.
IF <ls_tpool_out>-id = 'S'.
<ls_tpool_out>-split = <ls_tpool_out>-entry.
<ls_tpool_out>-entry = <ls_tpool_out>-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:
<ls_pfk> TYPE rsmpe_pfk,
<ls_act> TYPE rsmpe_act,
<ls_men> 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 <ls_act>.
IF <ls_act>-code+6(14) IS INITIAL AND <ls_act>-code(6) CO lc_num_only.
cs_adm-actcode = <ls_act>-code.
ENDIF.
ENDLOOP.
LOOP AT is_cua-men ASSIGNING <ls_men>.
IF <ls_men>-code+6(14) IS INITIAL AND <ls_men>-code(6) CO lc_num_only.
cs_adm-mencode = <ls_men>-code.
ENDIF.
ENDLOOP.
LOOP AT is_cua-pfk ASSIGNING <ls_pfk>.
IF <ls_pfk>-code+6(14) IS INITIAL AND <ls_pfk>-code(6) CO lc_num_only.
cs_adm-pfkcode = <ls_pfk>-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 = 'I'
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,
ls_dynpro LIKE LINE OF it_dynpros.
FIELD-SYMBOLS: <ls_field> TYPE rpy_dyfatc.
* 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.
" 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 ).
LOOP AT ls_dynpro-fields ASSIGNING <ls_field>.
* 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 <ls_field>-param_id IS NOT INITIAL
AND <ls_field>-from_dict = abap_true.
IF <ls_field>-set_param IS INITIAL.
<ls_field>-set_param = lc_rpyty_force_off.
ENDIF.
IF <ls_field>-get_param IS INITIAL.
<ls_field>-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 <ls_field>-type = 'CHECK'
AND <ls_field>-from_dict = abap_true
AND <ls_field>-text IS INITIAL
AND <ls_field>-modific IS INITIAL.
<ls_field>-modific = 'X'.
ENDIF.
"fix for issue #2747:
IF <ls_field>-foreignkey IS INITIAL.
<ls_field>-foreignkey = lc_rpyty_force_off.
ENDIF.
ENDLOOP.
CALL FUNCTION 'RPY_DYNPRO_INSERT'
EXPORTING
header = ls_dynpro-header
suppress_exist_checks = abap_true
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.
IF sy-subrc <> 2 AND sy-subrc <> 0.
zcx_abapgit_exception=>raise_t100( ).
ENDIF.
* todo, RPY_DYNPRO_UPDATE?
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.
ENDMETHOD.
METHOD deserialize_program.
DATA: lv_exists TYPE abap_bool,
lv_progname TYPE reposrc-progname,
ls_tpool LIKE LINE OF it_tpool,
lv_title TYPE rglif-title,
ls_progdir_new TYPE progdir.
FIELD-SYMBOLS: <lg_any> TYPE any.
CALL FUNCTION 'RS_CORR_INSERT'
EXPORTING
object = is_progdir-name
object_class = 'ABAP'
devclass = iv_package
master_language = mv_language
mode = 'I'
suppress_dialog = abap_true
EXCEPTIONS
cancelled = 1
permission_failure = 2
unknown_objectclass = 3
OTHERS = 4.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise_t100( ).
ENDIF.
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 <lg_any>.
IF sy-subrc = 0.
CLEAR <lg_any>.
ENDIF.
lv_title = ls_tpool-entry.
ENDIF.
SELECT SINGLE progname FROM reposrc INTO lv_progname
WHERE progname = is_progdir-name
AND r3state = 'A'.
lv_exists = boolc( sy-subrc = 0 ).
IF lv_exists = abap_true.
zcl_abapgit_language=>set_current_language( mv_language ).
CALL FUNCTION 'RPY_PROGRAM_UPDATE'
EXPORTING
program_name = is_progdir-name
title_string = lv_title
save_inactive = 'I'
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
zcx_abapgit_exception=>raise( |Delete function group and pull again, { is_progdir-name } (EU522)| ).
ELSE.
zcx_abapgit_exception=>raise( |PROG { is_progdir-name }, updating error: { sy-msgid } { sy-msgno }| ).
ENDIF.
ENDIF.
zcl_abapgit_language=>restore_login_language( ).
ELSEIF strlen( is_progdir-name ) > 30.
* function module RPY_PROGRAM_INSERT cannot handle function group includes
" special treatment for extensions
" if the program name exceeds 30 characters it is not a usual
" ABAP program but might be some extension, which requires the internal
" addition EXTENSION TYPE, see
" http://help.sap.com/abapdocu_751/en/abapinsert_report_internal.htm#!ABAP_ADDITION_1@1@
" This e.g. occurs in case of transportable Code Inspector variants (ending with ===VC)
INSERT REPORT is_progdir-name
FROM it_source
STATE 'I'
EXTENSION TYPE is_progdir-name+30.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise( 'error from INSERT REPORT .. EXTENSION TYPE' ).
ENDIF.
ELSE.
INSERT REPORT is_progdir-name
FROM it_source
STATE 'I'
PROGRAM TYPE is_progdir-subc.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise( 'error from INSERT REPORT' ).
ENDIF.
ENDIF.
IF NOT it_tpool[] IS INITIAL.
INSERT TEXTPOOL is_progdir-name
FROM it_tpool
LANGUAGE mv_language
STATE 'I'.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise( 'error from INSERT TEXTPOOL' ).
ENDIF.
ENDIF.
CALL FUNCTION 'READ_PROGDIR'
EXPORTING
i_progname = is_progdir-name
i_state = 'I'
IMPORTING
e_progdir = ls_progdir_new
EXCEPTIONS
not_exists = 1
OTHERS = 2.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise( |not found in PROGDIR. Subrc = { sy-subrc }| ).
ENDIF.
* todo, package?
ls_progdir_new-ldbname = is_progdir-ldbname.
ls_progdir_new-dbna = is_progdir-dbna.
ls_progdir_new-dbapl = is_progdir-dbapl.
ls_progdir_new-rload = is_progdir-rload.
ls_progdir_new-fixpt = is_progdir-fixpt.
ls_progdir_new-varcl = is_progdir-varcl.
ls_progdir_new-appl = is_progdir-appl.
ls_progdir_new-rstat = is_progdir-rstat.
ls_progdir_new-sqlx = is_progdir-sqlx.
ls_progdir_new-uccheck = is_progdir-uccheck.
ls_progdir_new-clas = is_progdir-clas.
CALL FUNCTION 'UPDATE_PROGDIR'
EXPORTING
i_progdir = ls_progdir_new
i_progname = ls_progdir_new-name
i_state = ls_progdir_new-state
EXCEPTIONS
not_executed = 1
OTHERS = 2.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise( |PROG, error inserting. Subrc = { sy-subrc }| ).
ENDIF.
SELECT SINGLE * FROM progdir INTO ls_progdir_new
WHERE name = ls_progdir_new-name
AND state = ls_progdir_new-state.
IF sy-subrc = 0 AND is_progdir-varcl = space AND ls_progdir_new-varcl = abap_true.
* function module UPDATE_PROGDIR does not update VARCL
UPDATE progdir SET varcl = is_progdir-varcl
WHERE name = ls_progdir_new-name
AND state = ls_progdir_new-state. "#EC CI_SUBRC
ENDIF.
zcl_abapgit_objects_activation=>add(
iv_type = 'REPS'
iv_name = is_progdir-name ).
ENDMETHOD.
METHOD deserialize_textpool.
DATA lv_language TYPE 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 = 'I'. "Textpool in main language needs to be activated
ELSE.
lv_state = 'A'. "Translations are always active
ENDIF.
IF it_tpool IS INITIAL.
IF iv_is_include = abap_false OR lv_state = 'A'.
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 woul activate the deletion of the textpool
STATE lv_state. "of the mail program -> insert empty textpool
ENDIF.
ELSE.
IF lines( it_tpool ) = 1 AND lv_language = mv_language.
READ TABLE it_tpool WITH KEY id = 'R' TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
RETURN. "No action because description in main language is already there
ENDIF.
ENDIF.
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.
IF lv_state = 'I'. "Textpool in main language needs to be activated
zcl_abapgit_objects_activation=>add(
iv_type = 'REPT'
iv_name = iv_program
iv_delete = lv_delete ).
ENDIF.
ENDMETHOD.
METHOD is_any_dynpro_locked.
DATA: lt_dynpros TYPE ty_dynpro_tt,
lv_object TYPE seqg3-garg.
FIELD-SYMBOLS: <ls_dynpro> TYPE ty_dynpro.
lt_dynpros = serialize_dynpros( iv_program ).
LOOP AT lt_dynpros ASSIGNING <ls_dynpro>.
lv_object = |{ <ls_dynpro>-header-screen }{ <ls_dynpro>-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_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_progdir.
DATA: ls_sapdir TYPE progdir.
CALL FUNCTION 'READ_PROGDIR'
EXPORTING
i_progname = iv_program
i_state = 'A'
IMPORTING
e_progdir = ls_sapdir.
MOVE-CORRESPONDING ls_sapdir TO rs_progdir.
CLEAR: rs_progdir-edtx,
rs_progdir-cnam,
rs_progdir-cdat,
rs_progdir-unam,
rs_progdir-udat,
rs_progdir-levl,
rs_progdir-vern,
rs_progdir-rmand,
rs_progdir-sdate,
rs_progdir-stime,
rs_progdir-idate,
rs_progdir-itime,
rs_progdir-varcl,
rs_progdir-state.
ENDMETHOD.
METHOD read_tpool.
FIELD-SYMBOLS: <ls_tpool_in> LIKE LINE OF it_tpool,
<ls_tpool_out> LIKE LINE OF rt_tpool.
LOOP AT it_tpool ASSIGNING <ls_tpool_in>.
APPEND INITIAL LINE TO rt_tpool ASSIGNING <ls_tpool_out>.
MOVE-CORRESPONDING <ls_tpool_in> TO <ls_tpool_out>.
IF <ls_tpool_out>-id = 'S'.
CONCATENATE <ls_tpool_in>-split <ls_tpool_in>-entry
INTO <ls_tpool_out>-entry
RESPECTING BLANKS.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD serialize_cua.
CALL FUNCTION 'RS_CUA_INTERNAL_FETCH'
EXPORTING
program = iv_program_name
language = mv_language
state = 'A'
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_fieldlist_int TYPE TABLE OF d021s. "internal format
FIELD-SYMBOLS: <ls_d020s> LIKE LINE OF lt_d020s,
<lv_outputstyle> TYPE scrpostyle,
<ls_container> LIKE LINE OF lt_containers,
<ls_field> LIKE LINE OF lt_fields_to_containers,
<ls_dynpro> LIKE LINE OF rt_dynpro,
<ls_field_int> 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 <ls_d020s>
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 = <ls_d020s>-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 = <ls_d020s>-dnum
TABLES
fieldlist = lt_fieldlist_int.
LOOP AT lt_fields_to_containers ASSIGNING <ls_field>.
* 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 <ls_field> TO <lv_outputstyle>.
IF sy-subrc = 0 AND <lv_outputstyle> = ' '.
CLEAR <lv_outputstyle>.
ENDIF.
"2746: we apply the same logic as in SAPLWBSCREEN
"for setting or unsetting the foreignkey field:
UNASSIGN <ls_field_int>.
READ TABLE lt_fieldlist_int ASSIGNING <ls_field_int> WITH KEY fnam = <ls_field>-name.
IF <ls_field_int> IS ASSIGNED.
IF <ls_field_int>-flg1 O lc_flg1ddf AND
<ls_field_int>-flg3 O lc_flg3for AND
<ls_field_int>-flg3 Z lc_flg3fdu AND
<ls_field_int>-flg3 Z lc_flg3fku.
<ls_field>-foreignkey = 'X'.
ELSE.
CLEAR <ls_field>-foreignkey.
ENDIF.
ENDIF.
ENDLOOP.
LOOP AT lt_containers ASSIGNING <ls_container>.
IF <ls_container>-c_resize_v = abap_false.
CLEAR <ls_container>-c_line_min.
ENDIF.
IF <ls_container>-c_resize_h = abap_false.
CLEAR <ls_container>-c_coln_min.
ENDIF.
ENDLOOP.
APPEND INITIAL LINE TO rt_dynpro ASSIGNING <ls_dynpro>.
<ls_dynpro>-header = ls_header.
<ls_dynpro>-containers = lt_containers.
<ls_dynpro>-fields = lt_fields_to_containers.
<ls_dynpro>-flow_logic = lt_flow_logic.
ENDLOOP.
ENDMETHOD.
METHOD serialize_program.
DATA: ls_progdir TYPE ty_progdir,
lv_program_name TYPE programm,
lt_dynpros TYPE ty_dynpro_tt,
ls_cua TYPE ty_cua,
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( ).
ls_progdir = read_progdir( lv_program_name ).
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.
io_files->add_abap( iv_extra = iv_extra
it_abap = lt_source ).
ENDMETHOD.
METHOD uncondense_flow.
DATA: lv_spaces LIKE LINE OF it_spaces.
FIELD-SYMBOLS: <ls_flow> LIKE LINE OF it_flow,
<ls_output> LIKE LINE OF rt_flow.
LOOP AT it_flow ASSIGNING <ls_flow>.
APPEND INITIAL LINE TO rt_flow ASSIGNING <ls_output>.
<ls_output>-line = <ls_flow>-line.
READ TABLE it_spaces INDEX sy-tabix INTO lv_spaces.
IF sy-subrc = 0.
SHIFT <ls_output>-line RIGHT BY lv_spaces PLACES IN CHARACTER MODE.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.