Refactoring: Prioritization/sequence of deserialization (#5198)

This commit is contained in:
Lars Hvam 2022-01-03 10:55:06 +01:00 committed by GitHub
parent 2eaaff7ad9
commit fd401956b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 310 additions and 98 deletions

View File

@ -21,18 +21,23 @@ CLASS zcl_abapgit_file_deserialize DEFINITION
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
!ii_log TYPE REF TO zif_abapgit_log OPTIONAL
RETURNING
VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt.
VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt .
CLASS-METHODS prioritize_deser
IMPORTING
!ii_log TYPE REF TO zif_abapgit_log
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RETURNING
VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt.
VALUE(rt_results) TYPE zif_abapgit_definitions=>ty_results_tt .
CLASS-METHODS map_results_to_items
IMPORTING
!it_results TYPE zif_abapgit_definitions=>ty_results_tt
RETURNING
VALUE(rt_items) TYPE zif_abapgit_definitions=>ty_items_tt .
ENDCLASS.
CLASS zcl_abapgit_file_deserialize IMPLEMENTATION.
CLASS ZCL_ABAPGIT_FILE_DESERIALIZE IMPLEMENTATION.
METHOD filter_files_to_deserialize.
@ -126,108 +131,126 @@ CLASS zcl_abapgit_file_deserialize IMPLEMENTATION.
METHOD get_results.
DATA lt_results TYPE zif_abapgit_definitions=>ty_results_tt.
lt_results = filter_files_to_deserialize(
it_results = zcl_abapgit_file_status=>status( io_repo )
ii_log = ii_log ).
rt_results = prioritize_deser(
filter_files_to_deserialize(
it_results = zcl_abapgit_file_status=>status( io_repo )
ii_log = ii_log ) ).
ii_log = ii_log
it_results = lt_results ).
ENDMETHOD.
METHOD map_results_to_items.
DATA ls_item LIKE LINE OF rt_items.
FIELD-SYMBOLS: <ls_result> TYPE zif_abapgit_definitions=>ty_result.
LOOP AT it_results ASSIGNING <ls_result>.
ls_item-devclass = <ls_result>-package.
ls_item-obj_type = <ls_result>-obj_type.
ls_item-obj_name = <ls_result>-obj_name.
INSERT ls_item INTO TABLE rt_items.
ENDLOOP.
ENDMETHOD.
METHOD prioritize_deser.
* todo, refactor this method #3536
DATA lt_items TYPE zif_abapgit_definitions=>ty_items_tt.
DATA ls_item LIKE LINE OF lt_items.
DATA lt_requires TYPE zif_abapgit_definitions=>ty_items_tt.
DATA ls_require LIKE LINE OF lt_requires.
DATA ls_result LIKE LINE OF it_results.
DATA lo_graph TYPE REF TO zcl_abapgit_item_graph.
FIELD-SYMBOLS: <ls_result> LIKE LINE OF it_results.
lt_items = map_results_to_items( it_results ).
* WEBI has to be handled before SPRX.
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'WEBI'.
APPEND <ls_result> TO rt_results.
CREATE OBJECT lo_graph EXPORTING it_items = lt_items.
LOOP AT lt_items INTO ls_item.
CLEAR lt_requires.
* TODO: BEGIN extract to object handler method in ZIF_ABAPGIT_OBJECT:
* METHODS get_deserialize_order
* IMPORTING
* it_items TYPE ty_items_tt
* RETURNING
* VALUE(rt_requries) TYPE ty_items_tt
CASE ls_item-obj_type.
WHEN 'SPRX'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'WEBI'.
WHEN 'CLAS'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'SPRX'
AND obj_type <> 'XSLT'.
WHEN 'PROG'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'XSLT'.
WHEN 'INTF'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'SPRX'.
WHEN 'TABL'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'SPRX'.
WHEN 'ISRP'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'IASP'.
WHEN 'DCLS'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'DDLS'.
WHEN 'ODSO'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'IOBJ'.
WHEN 'SCP1'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'TOBJ'.
WHEN 'CHAR'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'OTGR'.
WHEN 'PINF'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'CLAS'
AND obj_type <> 'INTF'
AND obj_type <> 'TABL'
AND obj_type <> 'DOMA'
AND obj_type <> 'DTEL'.
WHEN 'DEVC'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'PINF'.
WHEN 'ENHC'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'ENHO'.
WHEN 'ENHO'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'ENSC'.
WHEN 'ENSC'.
lt_requires = lt_items.
DELETE lt_requires WHERE obj_type <> 'ENHS'.
ENDCASE.
* TODO: END extract to object handler method
LOOP AT lt_requires INTO ls_require.
lo_graph->add_edge(
is_from = ls_require
is_to = ls_item ).
ENDLOOP.
ENDLOOP.
* SPRX has to be handled before depended objects CLAS/INFT/TABL etc.
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'SPRX'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* XSLT has to be handled before CLAS/PROG
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'XSLT'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* PROG before internet services, as the services might use the screens
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'PROG'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* ISAP has to be handled before ISRP
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'IASP'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* DDLS has to be handled before DCLS
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'DDLS'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* IOBJ has to be handled before ODSO
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'IOBJ'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* TOBJ has to be handled before SCP1
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'TOBJ'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* OTGR has to be handled before CHAR
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'OTGR'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
LOOP AT it_results ASSIGNING <ls_result>
WHERE obj_type <> 'IASP'
AND obj_type <> 'PROG'
AND obj_type <> 'XSLT'
AND obj_type <> 'PINF'
AND obj_type <> 'DEVC'
AND obj_type <> 'ENHS'
AND obj_type <> 'ENHO'
AND obj_type <> 'ENHC'
AND obj_type <> 'ENSC'
AND obj_type <> 'DDLS'
AND obj_type <> 'SPRX'
AND obj_type <> 'WEBI'
AND obj_type <> 'IOBJ'
AND obj_type <> 'TOBJ'
AND obj_type <> 'OTGR'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* Enhancements might refer to other objects of the repo so create them after
* Order: spots, composite spots, implementations, composite implementations
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'ENHS'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'ENSC'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'ENHO'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'ENHC'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* PINF after everything as it can expose objects
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'PINF'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
* DEVC after PINF, as it can refer for package interface usage
LOOP AT it_results ASSIGNING <ls_result> WHERE obj_type = 'DEVC'.
APPEND <ls_result> TO rt_results.
ENDLOOP.
WHILE lo_graph->has_vertices( ) = abap_true.
ls_item = lo_graph->get_next( ii_log ).
READ TABLE it_results INTO ls_result WITH KEY
obj_name = ls_item-obj_name
obj_type = ls_item-obj_type.
ASSERT sy-subrc = 0.
APPEND ls_result TO rt_results.
ENDWHILE.
ENDMETHOD.
ENDCLASS.

View File

@ -248,6 +248,7 @@ CLASS ltcl_prio_deserialization DEFINITION FINAL FOR TESTING
mo_objects TYPE REF TO zcl_abapgit_file_deserialize,
mt_input TYPE zif_abapgit_definitions=>ty_results_tt,
mt_output TYPE zif_abapgit_definitions=>ty_results_tt,
mv_counter TYPE i,
mv_exp_output_tabix TYPE i.
ENDCLASS.
@ -387,17 +388,24 @@ CLASS ltcl_prio_deserialization IMPLEMENTATION.
METHOD given.
DATA: ls_input LIKE LINE OF mt_input.
DATA ls_input LIKE LINE OF mt_input.
ls_input-obj_type = iv_object_type.
ls_input-obj_name = mv_counter.
INSERT ls_input INTO TABLE mt_input.
mv_counter = mv_counter + 1.
ENDMETHOD.
METHOD when_deser_is_priorized.
mt_output = mo_objects->prioritize_deser( mt_input ).
DATA lo_log TYPE REF TO zcl_abapgit_log.
CREATE OBJECT lo_log.
mt_output = mo_objects->prioritize_deser(
ii_log = lo_log
it_results = mt_input ).
ENDMETHOD.

View File

@ -0,0 +1,104 @@
CLASS zcl_abapgit_item_graph DEFINITION
PUBLIC
CREATE PUBLIC .
PUBLIC SECTION.
METHODS constructor
IMPORTING
!it_items TYPE zif_abapgit_definitions=>ty_items_tt .
METHODS add_edge
IMPORTING
!is_from TYPE zif_abapgit_definitions=>ty_item
!is_to TYPE zif_abapgit_definitions=>ty_item .
METHODS has_vertices
RETURNING
VALUE(rv_bool) TYPE abap_bool .
METHODS get_next
IMPORTING
!ii_log TYPE REF TO zif_abapgit_log
RETURNING
VALUE(rs_item) TYPE zif_abapgit_definitions=>ty_item .
PRIVATE SECTION.
TYPES: BEGIN OF ty_edge,
from TYPE zif_abapgit_definitions=>ty_item,
to TYPE zif_abapgit_definitions=>ty_item,
END OF ty_edge.
DATA mt_vertices TYPE STANDARD TABLE OF zif_abapgit_definitions=>ty_item WITH DEFAULT KEY.
DATA mt_edges TYPE STANDARD TABLE OF ty_edge WITH DEFAULT KEY.
DATA mv_warning TYPE abap_bool.
METHODS remove_vertex IMPORTING iv_index TYPE i.
ENDCLASS.
CLASS ZCL_ABAPGIT_ITEM_GRAPH IMPLEMENTATION.
METHOD add_edge.
DATA ls_edge LIKE LINE OF mt_edges.
ASSERT is_from IS NOT INITIAL.
ASSERT is_to IS NOT INITIAL.
ls_edge-from = is_from.
ls_edge-to = is_to.
APPEND ls_edge TO mt_edges.
ENDMETHOD.
METHOD constructor.
INSERT LINES OF it_items INTO TABLE mt_vertices.
ENDMETHOD.
METHOD get_next.
* find a vertex with no inbound edges, if it does not exist pick anything
DATA ls_vertex LIKE LINE OF mt_vertices.
DATA lv_index TYPE i.
LOOP AT mt_vertices INTO ls_vertex.
lv_index = sy-tabix.
READ TABLE mt_edges WITH KEY
to-obj_type = ls_vertex-obj_type
to-obj_name = ls_vertex-obj_name
TRANSPORTING NO FIELDS.
IF sy-subrc <> 0.
remove_vertex( lv_index ).
rs_item = ls_vertex.
RETURN.
ENDIF.
ENDLOOP.
IF mv_warning = abap_false.
* only issue the warning once per graph
ii_log->add_warning( |Cycle detected in item graph| ).
mv_warning = abap_true.
ENDIF.
READ TABLE mt_vertices INTO rs_item INDEX 1.
ASSERT sy-subrc = 0.
remove_vertex( 1 ).
ENDMETHOD.
METHOD has_vertices.
rv_bool = boolc( lines( mt_vertices ) > 0 ).
ENDMETHOD.
METHOD remove_vertex.
DATA ls_vertex LIKE LINE OF mt_vertices.
READ TABLE mt_vertices INDEX iv_index INTO ls_vertex.
ASSERT sy-subrc = 0.
DELETE mt_vertices INDEX iv_index.
DELETE mt_edges WHERE
from-obj_type = ls_vertex-obj_type AND
from-obj_name = ls_vertex-obj_name.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,60 @@
CLASS ltcl_test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.
PRIVATE SECTION.
METHODS basic FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_test IMPLEMENTATION.
METHOD basic.
DATA lo_graph TYPE REF TO zcl_abapgit_item_graph.
DATA li_log TYPE REF TO zif_abapgit_log.
DATA lt_items TYPE zif_abapgit_definitions=>ty_items_tt.
DATA ls_item1 LIKE LINE OF lt_items.
DATA ls_item2 LIKE LINE OF lt_items.
DATA ls_next LIKE LINE OF lt_items.
CREATE OBJECT li_log TYPE zcl_abapgit_log.
ls_item1-obj_type = 'TYPE'.
ls_item1-obj_type = '1111'.
APPEND ls_item1 TO lt_items.
ls_item2-obj_type = 'TYPE'.
ls_item2-obj_type = '2222'.
APPEND ls_item2 TO lt_items.
CREATE OBJECT lo_graph EXPORTING it_items = lt_items.
lo_graph->add_edge(
is_from = ls_item1
is_to = ls_item2 ).
cl_abap_unit_assert=>assert_equals(
act = lo_graph->has_vertices( )
exp = abap_true ).
ls_next = lo_graph->get_next( li_log ).
cl_abap_unit_assert=>assert_equals(
act = ls_next-obj_name
exp = ls_item1-obj_name ).
cl_abap_unit_assert=>assert_equals(
act = lo_graph->has_vertices( )
exp = abap_true ).
ls_next = lo_graph->get_next( li_log ).
cl_abap_unit_assert=>assert_equals(
act = ls_next-obj_name
exp = ls_item2-obj_name ).
cl_abap_unit_assert=>assert_equals(
act = lo_graph->has_vertices( )
exp = abap_false ).
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_ABAPGIT_ITEM_GRAPH</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abapGit - Item graph</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>