add code line attribute for leading spaces #2011 (#2014)

* add code line attribute for leading spaces

Use attribute abapgit-leadig-spaces to store leading spaces of coding lines at serialization. This is used in deserialization to restoreformatting after XML normalization.

* add attribute also for global types and forms

* fix code formatting
This commit is contained in:
Domi Bigl 2018-10-26 07:11:38 +02:00 committed by Lars Hvam
parent 088f465c13
commit 1c396d9f19

View File

@ -5,192 +5,28 @@ CLASS zcl_abapgit_object_ssfo DEFINITION PUBLIC INHERITING FROM zcl_abapgit_obje
ALIASES mo_files FOR zif_abapgit_object~mo_files.
PRIVATE SECTION.
METHODS: fix_ids IMPORTING ii_xml_doc TYPE REF TO if_ixml_document.
CLASS-DATA: range_node_codes TYPE stty_sr_string_range.
CONSTANTS: attrib_abapgit_leadig_spaces TYPE string VALUE 'abapgit-leadig-spaces' ##NO_TEXT.
METHODS fix_ids IMPORTING ii_xml_doc TYPE REF TO if_ixml_document.
METHODS set_attribute_leading_spaces IMPORTING i_name TYPE string
i_node TYPE REF TO if_ixml_node
CHANGING c_within_code_section TYPE abap_bool.
METHODS handle_attrib_leading_spaces IMPORTING i_name TYPE string
i_node TYPE REF TO if_ixml_node
CHANGING c_within_code_section TYPE abap_bool.
METHODS get_range_node_codes RETURNING VALUE(e_range_node_codes) TYPE stty_sr_string_range.
METHODS code_item_section_handling IMPORTING i_name TYPE string
i_node TYPE REF TO if_ixml_node
EXPORTING e_code_item_element TYPE REF TO if_ixml_element
CHANGING c_within_code_section TYPE abap_bool
RAISING zcx_abapgit_exception.
ENDCLASS.
CLASS zcl_abapgit_object_ssfo IMPLEMENTATION.
METHOD zif_abapgit_object~has_changed_since.
rv_changed = abap_true.
ENDMETHOD.
METHOD zif_abapgit_object~changed_by.
SELECT SINGLE lastuser FROM stxfadm INTO rv_user
WHERE formname = ms_item-obj_name.
IF sy-subrc <> 0.
rv_user = c_user_unknown.
ENDIF.
ENDMETHOD.
METHOD zif_abapgit_object~get_metadata.
rs_metadata = get_metadata( ).
rs_metadata-delete_tadir = abap_true.
ENDMETHOD.
METHOD zif_abapgit_object~exists.
DATA: lv_formname TYPE stxfadm-formname.
SELECT SINGLE formname FROM stxfadm INTO lv_formname
WHERE formname = ms_item-obj_name.
rv_bool = boolc( sy-subrc = 0 ).
ENDMETHOD.
METHOD zif_abapgit_object~jump.
DATA: lt_bdcdata TYPE TABLE OF bdcdata,
lv_formtype TYPE stxfadm-formtype.
FIELD-SYMBOLS: <ls_bdcdata> LIKE LINE OF lt_bdcdata.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-program = 'SAPMSSFO'.
<ls_bdcdata>-dynpro = '0100'.
<ls_bdcdata>-dynbegin = abap_true.
SELECT SINGLE formtype FROM stxfadm INTO lv_formtype
WHERE formname = ms_item-obj_name.
IF lv_formtype = cssf_formtype_text.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'RB_TX'.
<ls_bdcdata>-fval = abap_true.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'BDC_OKCODE'.
<ls_bdcdata>-fval = '=RB'.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-program = 'SAPMSSFO'.
<ls_bdcdata>-dynpro = '0100'.
<ls_bdcdata>-dynbegin = abap_true.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'SSFSCREEN-TNAME'.
<ls_bdcdata>-fval = ms_item-obj_name.
ELSE.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'SSFSCREEN-FNAME'.
<ls_bdcdata>-fval = ms_item-obj_name.
ENDIF.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'BDC_OKCODE'.
<ls_bdcdata>-fval = '=DISPLAY'.
CALL FUNCTION 'ABAP4_CALL_TRANSACTION'
STARTING NEW TASK 'GIT'
EXPORTING
tcode = 'SMARTFORMS'
mode_val = 'E'
TABLES
using_tab = lt_bdcdata
EXCEPTIONS
system_failure = 1
communication_failure = 2
resource_failure = 3
OTHERS = 4
##fm_subrc_ok. "#EC CI_SUBRC
ENDMETHOD.
METHOD zif_abapgit_object~delete.
DATA: lv_formname TYPE tdsfname.
lv_formname = ms_item-obj_name.
CALL FUNCTION 'FB_DELETE_FORM'
EXPORTING
i_formname = lv_formname
i_with_dialog = abap_false
i_with_confirm_dialog = abap_false
EXCEPTIONS
no_name = 1
no_form = 2
form_locked = 3
no_access_permission = 4
illegal_language = 5
illegal_formtype = 6
OTHERS = 7.
IF sy-subrc <> 0 AND sy-subrc <> 2.
zcx_abapgit_exception=>raise( 'Error from FB_DELETE_FORM' ).
ENDIF.
ENDMETHOD.
METHOD zif_abapgit_object~serialize.
* see function module FB_DOWNLOAD_FORM
DATA: lo_sf TYPE REF TO cl_ssf_fb_smart_form,
lv_name TYPE string,
li_node TYPE REF TO if_ixml_node,
li_element TYPE REF TO if_ixml_element,
li_iterator TYPE REF TO if_ixml_node_iterator,
lv_formname TYPE tdsfname,
li_ixml TYPE REF TO if_ixml,
li_xml_doc TYPE REF TO if_ixml_document.
li_ixml = cl_ixml=>create( ).
li_xml_doc = li_ixml->create_document( ).
CREATE OBJECT lo_sf.
lv_formname = ms_item-obj_name. " convert type
TRY.
lo_sf->load( im_formname = lv_formname
im_language = '' ).
CATCH cx_ssf_fb.
* the smartform is not present in system, or other error occured
RETURN.
ENDTRY.
lo_sf->xml_download( EXPORTING parent = li_xml_doc
CHANGING document = li_xml_doc ).
li_iterator = li_xml_doc->create_iterator( ).
li_node = li_iterator->get_next( ).
WHILE NOT li_node IS INITIAL.
lv_name = li_node->get_name( ).
IF lv_name = 'DEVCLASS'
OR lv_name = 'LASTDATE'
OR lv_name = 'LASTTIME'.
li_node->set_value( '' ).
ENDIF.
IF lv_name = 'FIRSTUSER'
OR lv_name = 'LASTUSER'.
li_node->set_value( 'DUMMY' ).
ENDIF.
li_node = li_iterator->get_next( ).
ENDWHILE.
fix_ids( li_xml_doc ).
li_element = li_xml_doc->get_root_element( ).
li_element->set_attribute(
name = 'sf'
namespace = 'xmlns'
value = 'urn:sap-com:SmartForms:2000:internal-structure' ). "#EC NOTEXT
li_element->set_attribute(
name = 'xmlns'
value = 'urn:sap-com:sdixml-ifr:2000' ). "#EC NOTEXT
io_xml->set_raw( li_xml_doc->get_root_element( ) ).
ENDMETHOD.
METHOD fix_ids.
" makes sure ID and IDREF values are the same values for each serialization run
@ -263,6 +99,123 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION.
ENDMETHOD.
METHOD handle_attrib_leading_spaces.
DATA element TYPE REF TO if_ixml_element.
DATA leading_spaces TYPE string.
DATA coding_line TYPE string.
TRY.
code_item_section_handling( EXPORTING i_name = i_name
i_node = i_node
IMPORTING e_code_item_element = element
CHANGING c_within_code_section = c_within_code_section ).
leading_spaces = element->get_attribute_ns( name = zcl_abapgit_object_ssfo=>attrib_abapgit_leadig_spaces ).
coding_line = element->get_value( ).
SHIFT coding_line RIGHT BY leading_spaces PLACES.
element->set_value( coding_line ).
CATCH zcx_abapgit_exception ##no_handler.
ENDTRY.
ENDMETHOD.
METHOD set_attribute_leading_spaces.
DATA: element TYPE REF TO if_ixml_element.
DATA: code_line TYPE string.
DATA: offset TYPE i.
TRY.
code_item_section_handling( EXPORTING i_name = i_name
i_node = i_node
IMPORTING e_code_item_element = element
CHANGING c_within_code_section = c_within_code_section ).
code_line = i_node->get_value( ).
"find 1st non space char
FIND FIRST OCCURRENCE OF REGEX '\S' IN code_line MATCH OFFSET offset.
IF sy-subrc = 0 AND offset > 0.
TRY.
element ?= i_node.
element->set_attribute( name = zcl_abapgit_object_ssfo=>attrib_abapgit_leadig_spaces
value = |{ offset }| ).
CATCH cx_sy_move_cast_error ##no_handler.
ENDTRY.
ENDIF.
CATCH zcx_abapgit_exception ##no_handler.
ENDTRY.
ENDMETHOD.
METHOD code_item_section_handling.
CONSTANTS: node_item TYPE string VALUE 'item' ##NO_TEXT.
CONSTANTS: node_text TYPE string VALUE '#text' ##NO_TEXT.
IF i_name IN get_range_node_codes( ).
c_within_code_section = abap_true.
ENDIF.
IF c_within_code_section = abap_true.
IF i_name = node_item.
TRY.
e_code_item_element ?= i_node.
RETURN.
CATCH cx_sy_move_cast_error ##no_handler.
ENDTRY.
ELSEIF i_name NOT IN get_range_node_codes( ) AND
i_name <> node_text.
c_within_code_section = abap_false.
ENDIF.
ENDIF.
RAISE EXCEPTION TYPE zcx_abapgit_exception.
ENDMETHOD.
METHOD zif_abapgit_object~changed_by.
SELECT SINGLE lastuser FROM stxfadm INTO rv_user
WHERE formname = ms_item-obj_name.
IF sy-subrc <> 0.
rv_user = c_user_unknown.
ENDIF.
ENDMETHOD.
METHOD zif_abapgit_object~compare_to_remote_version.
CREATE OBJECT ro_comparison_result TYPE zcl_abapgit_comparison_null.
ENDMETHOD.
METHOD zif_abapgit_object~delete.
DATA: lv_formname TYPE tdsfname.
lv_formname = ms_item-obj_name.
CALL FUNCTION 'FB_DELETE_FORM'
EXPORTING
i_formname = lv_formname
i_with_dialog = abap_false
i_with_confirm_dialog = abap_false
EXCEPTIONS
no_form = 1
OTHERS = 2.
IF sy-subrc <> 0 AND sy-subrc <> 1.
zcx_abapgit_exception=>raise( 'Error from FB_DELETE_FORM' ).
ENDIF.
ENDMETHOD.
METHOD zif_abapgit_object~deserialize.
* see function module FB_UPLOAD_FORM
@ -274,7 +227,7 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION.
lo_res TYPE REF TO cl_ssf_fb_smart_form,
lx_error TYPE REF TO cx_ssf_fb,
lv_text TYPE string.
DATA: within_code_section TYPE abap_bool.
CREATE OBJECT lo_sf.
@ -292,8 +245,13 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION.
sy-uzeit(2) && ':' && sy-uzeit+2(2) && ':' && sy-uzeit+4(2) ).
WHEN 'FIRSTUSER' OR 'LASTUSER'.
li_node->set_value( sy-uname && '' ).
ENDCASE.
handle_attrib_leading_spaces( EXPORTING i_name = lv_name
i_node = li_node
CHANGING c_within_code_section = within_code_section ).
li_node = li_iterator->get_next( ).
ENDWHILE.
@ -325,10 +283,29 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION.
ENDMETHOD.
METHOD zif_abapgit_object~compare_to_remote_version.
CREATE OBJECT ro_comparison_result TYPE zcl_abapgit_comparison_null.
METHOD zif_abapgit_object~exists.
DATA: lv_formname TYPE stxfadm-formname.
SELECT SINGLE formname FROM stxfadm INTO lv_formname
WHERE formname = ms_item-obj_name.
rv_bool = boolc( sy-subrc = 0 ).
ENDMETHOD.
METHOD zif_abapgit_object~get_metadata.
rs_metadata = get_metadata( ).
rs_metadata-delete_tadir = abap_true.
ENDMETHOD.
METHOD zif_abapgit_object~has_changed_since.
rv_changed = abap_true.
ENDMETHOD.
METHOD zif_abapgit_object~is_locked.
rv_is_locked = exists_a_lock_entry_for( iv_lock_object = 'E_SMFORM'
@ -336,4 +313,152 @@ CLASS zcl_abapgit_object_ssfo IMPLEMENTATION.
ENDMETHOD.
METHOD zif_abapgit_object~jump.
DATA: lt_bdcdata TYPE TABLE OF bdcdata,
lv_formtype TYPE stxfadm-formtype.
FIELD-SYMBOLS: <ls_bdcdata> LIKE LINE OF lt_bdcdata.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-program = 'SAPMSSFO'.
<ls_bdcdata>-dynpro = '0100'.
<ls_bdcdata>-dynbegin = abap_true.
SELECT SINGLE formtype FROM stxfadm INTO lv_formtype
WHERE formname = ms_item-obj_name.
IF lv_formtype = cssf_formtype_text.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'RB_TX'.
<ls_bdcdata>-fval = abap_true.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'BDC_OKCODE'.
<ls_bdcdata>-fval = '=RB'.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-program = 'SAPMSSFO'.
<ls_bdcdata>-dynpro = '0100'.
<ls_bdcdata>-dynbegin = abap_true.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'SSFSCREEN-TNAME'.
<ls_bdcdata>-fval = ms_item-obj_name.
ELSE.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'SSFSCREEN-FNAME'.
<ls_bdcdata>-fval = ms_item-obj_name.
ENDIF.
APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
<ls_bdcdata>-fnam = 'BDC_OKCODE'.
<ls_bdcdata>-fval = '=DISPLAY'.
CALL FUNCTION 'ABAP4_CALL_TRANSACTION'
STARTING NEW TASK 'GIT'
EXPORTING
tcode = 'SMARTFORMS'
mode_val = 'E'
TABLES
using_tab = lt_bdcdata
EXCEPTIONS
OTHERS = 1
##fm_subrc_ok. "#EC CI_SUBRC
ENDMETHOD.
METHOD zif_abapgit_object~serialize.
* see function module FB_DOWNLOAD_FORM
DATA: lo_sf TYPE REF TO cl_ssf_fb_smart_form,
lv_name TYPE string,
li_node TYPE REF TO if_ixml_node,
li_element TYPE REF TO if_ixml_element,
li_iterator TYPE REF TO if_ixml_node_iterator,
lv_formname TYPE tdsfname,
li_ixml TYPE REF TO if_ixml,
li_xml_doc TYPE REF TO if_ixml_document.
DATA: within_code_section TYPE abap_bool.
li_ixml = cl_ixml=>create( ).
li_xml_doc = li_ixml->create_document( ).
CREATE OBJECT lo_sf.
lv_formname = ms_item-obj_name. " convert type
TRY.
lo_sf->load( im_formname = lv_formname
im_language = '' ).
CATCH cx_ssf_fb.
* the smartform is not present in system, or other error occured
RETURN.
ENDTRY.
lo_sf->xml_download( EXPORTING parent = li_xml_doc
CHANGING document = li_xml_doc ).
li_iterator = li_xml_doc->create_iterator( ).
li_node = li_iterator->get_next( ).
WHILE NOT li_node IS INITIAL.
lv_name = li_node->get_name( ).
IF lv_name = 'DEVCLASS'
OR lv_name = 'LASTDATE'
OR lv_name = 'LASTTIME'.
li_node->set_value( '' ).
ENDIF.
IF lv_name = 'FIRSTUSER'
OR lv_name = 'LASTUSER'.
li_node->set_value( 'DUMMY' ).
ENDIF.
set_attribute_leading_spaces( EXPORTING i_name = lv_name
i_node = li_node
CHANGING c_within_code_section = within_code_section ).
li_node = li_iterator->get_next( ).
ENDWHILE.
fix_ids( li_xml_doc ).
li_element = li_xml_doc->get_root_element( ).
li_element->set_attribute(
name = 'sf'
namespace = 'xmlns'
value = 'urn:sap-com:SmartForms:2000:internal-structure' ). "#EC NOTEXT
li_element->set_attribute(
name = 'xmlns'
value = 'urn:sap-com:sdixml-ifr:2000' ). "#EC NOTEXT
io_xml->set_raw( li_xml_doc->get_root_element( ) ).
ENDMETHOD.
METHOD get_range_node_codes.
DATA: range_node_code TYPE sstr_sr_string_range.
IF me->range_node_codes IS INITIAL.
range_node_code-sign = 'I'.
range_node_code-option = 'EQ'.
range_node_code-low = 'CODE'.
INSERT range_node_code INTO TABLE me->range_node_codes.
range_node_code-low = 'GTYPES'.
INSERT range_node_code INTO TABLE me->range_node_codes.
range_node_code-low = 'GCODING'.
INSERT range_node_code INTO TABLE me->range_node_codes.
range_node_code-low = 'FCODING'.
INSERT range_node_code INTO TABLE me->range_node_codes.
ENDIF.
e_range_node_codes = me->range_node_codes.
ENDMETHOD.
ENDCLASS.