SFPF, SFPI: Error by import (issue #2353) (#2388)

* SFPF, SFPI: Error by import (issue #2353)

The renumbering of the attributes "id" and "href" is reworked

* Pretty printer of the full class source

* indentation
This commit is contained in:
p-dmitrij 2019-02-13 15:49:35 +03:00 committed by Lars Hvam
parent 4e40705350
commit de4c92fb73

View File

@ -1,13 +1,21 @@
CLASS zcl_abapgit_object_sfpf DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL. CLASS zcl_abapgit_object_sfpf DEFINITION
PUBLIC
INHERITING FROM zcl_abapgit_objects_super
FINAL
CREATE PUBLIC .
PUBLIC SECTION. PUBLIC SECTION.
INTERFACES zif_abapgit_object.
ALIASES mo_files FOR zif_abapgit_object~mo_files.
CLASS-METHODS: INTERFACES zif_abapgit_object .
fix_oref
IMPORTING ii_document TYPE REF TO if_ixml_document.
ALIASES mo_files
FOR zif_abapgit_object~mo_files .
CLASS-METHODS fix_oref
IMPORTING
!ii_document TYPE REF TO if_ixml_document
RAISING
zcx_abapgit_exception .
PROTECTED SECTION. PROTECTED SECTION.
PRIVATE SECTION. PRIVATE SECTION.
METHODS: METHODS:
@ -27,50 +35,70 @@ CLASS ZCL_ABAPGIT_OBJECT_SFPF IMPLEMENTATION.
METHOD fix_oref. METHOD fix_oref.
DATA: li_iterator TYPE REF TO if_ixml_node_iterator, * During serialization of a SFPF / SFPI object the interface hierarchy
lv_new TYPE n LENGTH 3, * is represented by attributes "id" and "href", where the id looks
lv_old TYPE string, * like "o<number>" and href like "#o<number>". Every run of
lt_map TYPE STANDARD TABLE OF string WITH DEFAULT KEY, * serialization generates a new <number> in these attributes, that
li_attr_map TYPE REF TO if_ixml_named_node_map, * leads to differences even by comparing of untouched forms.
li_attr TYPE REF TO if_ixml_node, * The purpose of this method is to renumber the id's consequentially
li_node TYPE REF TO if_ixml_node. * and therefore to avoid fictive differences.
DEFINE _lookup. * NB: As the method iterator->get_next() works quite slowly,
READ TABLE lt_map FROM &1 TRANSPORTING NO FIELDS. * it is better to collect all attributes in a cache table
IF sy-subrc <> 0. * instead of implementing of a nested loop using get_next().
APPEND &1 TO lt_map.
READ TABLE lt_map FROM &1 TRANSPORTING NO FIELDS. DATA:
li_iterator TYPE REF TO if_ixml_node_iterator,
li_elem TYPE REF TO if_ixml_element,
lv_new TYPE string,
lv_old TYPE string,
lv_count TYPE i,
BEGIN OF ls_attr_href,
val TYPE string,
attr TYPE REF TO if_ixml_attribute,
END OF ls_attr_href,
lt_attr_href LIKE SORTED TABLE OF ls_attr_href WITH NON-UNIQUE KEY val.
FIELD-SYMBOLS <ls_attr_href> LIKE LINE OF lt_attr_href.
* Collect all attributes href='#o...' in the cache table
li_iterator = ii_document->create_iterator_filtered(
ii_document->create_filter_and(
filter1 = ii_document->create_filter_node_type( if_ixml_node=>co_node_element )
filter2 = ii_document->create_filter_attribute( 'href' ) ) ).
li_elem ?= li_iterator->get_next( ).
WHILE li_elem IS NOT INITIAL.
ls_attr_href-attr = li_elem->get_attribute_node( 'href' ).
ls_attr_href-val = ls_attr_href-attr->get_value( ).
IF ls_attr_href-val CP '##o*'.
INSERT ls_attr_href INTO TABLE lt_attr_href.
ENDIF. ENDIF.
lv_new = sy-tabix + 100. li_elem ?= li_iterator->get_next( ).
END-OF-DEFINITION. ENDWHILE.
* Renumber id='o...' attributes
li_iterator = ii_document->create_iterator( ). li_iterator = ii_document->create_iterator_filtered(
li_node = li_iterator->get_next( ). ii_document->create_filter_and(
WHILE NOT li_node IS INITIAL. filter1 = ii_document->create_filter_node_type( if_ixml_node=>co_node_element )
li_attr_map = li_node->get_attributes( ). filter2 = ii_document->create_filter_attribute( 'id' ) ) ).
li_elem ?= li_iterator->get_next( ).
IF li_attr_map IS BOUND. WHILE li_elem IS NOT INITIAL.
li_attr = li_attr_map->get_named_item_ns( 'href' ). lv_old = li_elem->get_attribute( 'id' ).
IF li_attr IS BOUND. IF lv_old CP 'o*'.
lv_old = li_attr->get_value( ). lv_count = lv_count + 1.
IF lv_old(2) = '#o'. lv_new = |o{ lv_count }|.
_lookup lv_old+1. * Rewrite id
li_attr->set_value( '#o' && lv_new ). IF li_elem->set_attribute( name = 'id' value = lv_new ) IS NOT INITIAL.
ENDIF. zcx_abapgit_exception=>raise( 'SFPF error, FIX_OREF' ).
ENDIF. ENDIF.
* Update references
li_attr = li_attr_map->get_named_item_ns( 'id' ). LOOP AT lt_attr_href ASSIGNING <ls_attr_href> WHERE val = '#' && lv_old.
IF li_attr IS BOUND. IF <ls_attr_href>-attr->set_value( '#' && lv_new ) IS NOT INITIAL.
lv_old = li_attr->get_value( ). zcx_abapgit_exception=>raise( 'SFPF error, FIX_OREF' ).
IF lv_old(1) = 'o'.
_lookup lv_old.
li_attr->set_value( 'o' && lv_new ).
ENDIF. ENDIF.
ENDIF. ENDLOOP.
ENDIF. ENDIF.
li_elem ?= li_iterator->get_next( ).
li_node = li_iterator->get_next( ).
ENDWHILE. ENDWHILE.
ENDMETHOD. ENDMETHOD.