diff --git a/src/objects/aff/zcl_abapgit_aff_registry.clas.abap b/src/objects/aff/zcl_abapgit_aff_registry.clas.abap new file mode 100644 index 000000000..e533a5919 --- /dev/null +++ b/src/objects/aff/zcl_abapgit_aff_registry.clas.abap @@ -0,0 +1,79 @@ +CLASS zcl_abapgit_aff_registry DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_aff_registry. + + METHODS: + constructor + IMPORTING + io_settings TYPE REF TO zcl_abapgit_settings OPTIONAL. + PROTECTED SECTION. + PRIVATE SECTION. + TYPES: + BEGIN OF ty_registry_entry, + obj_type TYPE tadir-object, + experimental TYPE abap_bool, + END OF ty_registry_entry. + + CLASS-DATA: + gt_registry TYPE HASHED TABLE OF ty_registry_entry WITH UNIQUE KEY obj_type. + + DATA: + mo_settings TYPE REF TO zcl_abapgit_settings. + + CLASS-METHODS: + register + IMPORTING + iv_obj_type TYPE tadir-object + iv_experimental TYPE abap_bool DEFAULT abap_false. + +ENDCLASS. + + +CLASS zcl_abapgit_aff_registry IMPLEMENTATION. + + METHOD constructor. + IF io_settings IS SUPPLIED. + mo_settings = io_settings. + ELSE. + mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). + ENDIF. + ENDMETHOD. + + METHOD zif_abapgit_aff_registry~is_supported_object_type. + + DATA ls_registry_entry TYPE ty_registry_entry. + + IF gt_registry IS INITIAL. + register( iv_obj_type = 'CHKC' ). + register( iv_obj_type = 'CHKO' ). + register( iv_obj_type = 'CHKV' ). + register( iv_obj_type = 'EVTB' ). + register( iv_obj_type = 'INTF' + iv_experimental = abap_true ). + register( iv_obj_type = 'SMBC' ). + ENDIF. + + READ TABLE gt_registry WITH TABLE KEY obj_type = iv_obj_type INTO ls_registry_entry. + IF sy-subrc = 0 AND ls_registry_entry-experimental = abap_false. + rv_result = abap_true. + ELSEIF sy-subrc = 0 AND mo_settings->get_experimental_features( ) = abap_true. + rv_result = abap_true. + ELSE. + rv_result = abap_false. + ENDIF. + ENDMETHOD. + + METHOD register. + DATA ls_registry_entry TYPE ty_registry_entry. + + ls_registry_entry-obj_type = iv_obj_type. + ls_registry_entry-experimental = iv_experimental. + INSERT ls_registry_entry INTO TABLE gt_registry. + ENDMETHOD. + +ENDCLASS. diff --git a/src/objects/aff/zcl_abapgit_aff_registry.clas.testclasses.abap b/src/objects/aff/zcl_abapgit_aff_registry.clas.testclasses.abap new file mode 100644 index 000000000..a66fa6b34 --- /dev/null +++ b/src/objects/aff/zcl_abapgit_aff_registry.clas.testclasses.abap @@ -0,0 +1,84 @@ +"! @testing zcl_abapgit_filename_logic +CLASS ltcl_aff_registry DEFINITION FINAL FOR TESTING + DURATION SHORT + RISK LEVEL HARMLESS. + + PRIVATE SECTION. + METHODS: + assert_that + IMPORTING + iv_obj_type TYPE tadir-object + iv_is_supported TYPE abap_bool + iv_experimental TYPE abap_bool DEFAULT abap_false, + clas_not_supported FOR TESTING RAISING cx_static_check, + chkc FOR TESTING RAISING cx_static_check, + chko FOR TESTING RAISING cx_static_check, + chkv FOR TESTING RAISING cx_static_check, + evtb FOR TESTING RAISING cx_static_check, + intf_not_supported FOR TESTING RAISING cx_static_check, + intf_experimental FOR TESTING RAISING cx_static_check, + smbc FOR TESTING RAISING cx_static_check. +ENDCLASS. + + +CLASS ltcl_aff_registry IMPLEMENTATION. + + METHOD assert_that. + DATA: + lo_cut TYPE REF TO zif_abapgit_aff_registry, + lo_settings_stub TYPE REF TO zcl_abapgit_settings, + lv_act TYPE abap_bool. + + + CREATE OBJECT lo_settings_stub. + lo_settings_stub->set_experimental_features( iv_experimental ). + CREATE OBJECT lo_cut TYPE zcl_abapgit_aff_registry + EXPORTING + io_settings = lo_settings_stub. + lv_act = lo_cut->is_supported_object_type( iv_obj_type ). + cl_abap_unit_assert=>assert_equals( exp = iv_is_supported + act = lv_act ). + ENDMETHOD. + + METHOD clas_not_supported. + assert_that( iv_obj_type = 'CLAS' + iv_is_supported = abap_false ). + ENDMETHOD. + + METHOD chkc. + assert_that( iv_obj_type = 'CHKC' + iv_is_supported = abap_true ). + ENDMETHOD. + + METHOD chko. + assert_that( iv_obj_type = 'CHKO' + iv_is_supported = abap_true ). + ENDMETHOD. + + METHOD chkv. + assert_that( iv_obj_type = 'CHKV' + iv_is_supported = abap_true ). + ENDMETHOD. + + METHOD evtb. + assert_that( iv_obj_type = 'EVTB' + iv_is_supported = abap_true ). + ENDMETHOD. + + METHOD intf_not_supported. + assert_that( iv_obj_type = 'INTF' + iv_is_supported = abap_false ). + ENDMETHOD. + + METHOD intf_experimental. + assert_that( iv_obj_type = 'INTF' + iv_is_supported = abap_true + iv_experimental = abap_true ). + ENDMETHOD. + + METHOD smbc. + assert_that( iv_obj_type = 'SMBC' + iv_is_supported = abap_true ). + ENDMETHOD. + +ENDCLASS. diff --git a/src/objects/aff/zcl_abapgit_aff_registry.clas.xml b/src/objects/aff/zcl_abapgit_aff_registry.clas.xml new file mode 100644 index 000000000..1750c5917 --- /dev/null +++ b/src/objects/aff/zcl_abapgit_aff_registry.clas.xml @@ -0,0 +1,17 @@ + + + + + + ZCL_ABAPGIT_AFF_REGISTRY + E + abapGit - Class that tells you whether object type has AFF + 1 + X + X + X + X + + + + diff --git a/src/objects/aff/zcl_abapgit_object_common_aff.clas.abap b/src/objects/aff/zcl_abapgit_object_common_aff.clas.abap index f21c97184..590323cca 100644 --- a/src/objects/aff/zcl_abapgit_object_common_aff.clas.abap +++ b/src/objects/aff/zcl_abapgit_object_common_aff.clas.abap @@ -134,6 +134,8 @@ CLASS zcl_abapgit_object_common_aff IMPLEMENTATION. lr_messages TYPE REF TO data, lv_json_as_xstring TYPE xstring, lx_exception TYPE REF TO cx_root, + lv_file_name TYPE string, + lo_file_name_mapper TYPE REF TO object, lv_name TYPE c LENGTH 120. FIELD-SYMBOLS: TYPE any, @@ -161,11 +163,6 @@ CLASS zcl_abapgit_object_common_aff IMPLEMENTATION. RECEIVING result = lo_object_handler. - CREATE OBJECT lo_object_json_file TYPE ('CL_AFF_FILE') - EXPORTING - name = |{ to_lower( lv_name ) }.{ to_lower( ms_item-obj_type ) }.json| - content = lv_json_as_xstring. - CREATE OBJECT lo_object_aff TYPE ('CL_AFF_OBJ') EXPORTING package = ms_item-devclass @@ -180,12 +177,27 @@ CLASS zcl_abapgit_object_common_aff IMPLEMENTATION. EXPORTING object = . + CALL METHOD ('CL_AFF_FILE_NAME_MAPPER')=>for_json + RECEIVING + result = lo_file_name_mapper. + + CALL METHOD lo_file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') + EXPORTING + object = + RECEIVING + result = lv_file_name. + CREATE OBJECT lo_settings TYPE ('CL_AFF_SETTINGS_DESERIALIZE') EXPORTING version = 'A' language = mv_language user = sy-uname. + CREATE OBJECT lo_object_json_file TYPE ('CL_AFF_FILE') + EXPORTING + name = lv_file_name + content = lv_json_as_xstring. + CREATE DATA lr_intf_aff_file TYPE REF TO ('IF_AFF_FILE'). ASSIGN lr_intf_aff_file->* TO . ?= lo_object_json_file. @@ -356,6 +368,9 @@ CLASS zcl_abapgit_object_common_aff IMPLEMENTATION. lv_json_as_xstring TYPE xstring, lx_exception TYPE REF TO cx_root, lv_name TYPE c LENGTH 120, + lv_file_name TYPE string, + lo_file_name_mapper TYPE REF TO object, + lv_is_deletion TYPE abap_bool VALUE abap_false, lv_dummy TYPE string. FIELD-SYMBOLS: TYPE any, @@ -432,9 +447,19 @@ CLASS zcl_abapgit_object_common_aff IMPLEMENTATION. ENDIF. ENDLOOP. + CALL METHOD ('CL_AFF_FILE_NAME_MAPPER')=>for_json + RECEIVING + result = lo_file_name_mapper. + + CALL METHOD lo_file_name_mapper->('IF_AFF_FILE_NAME_MAPPER~GET_FILE_NAME_FROM_OBJECT') + EXPORTING + object = + RECEIVING + result = lv_file_name. + CALL METHOD lo_files_container->('IF_AFF_FILES_CONTAINER~GET_FILE') EXPORTING - name = |{ to_lower( lv_name ) }.{ to_lower( ms_item-obj_type ) }.json| + name = lv_file_name RECEIVING result = lo_object_json_file. diff --git a/src/objects/aff/zif_abapgit_aff_registry.intf.abap b/src/objects/aff/zif_abapgit_aff_registry.intf.abap new file mode 100644 index 000000000..27b6a4c7f --- /dev/null +++ b/src/objects/aff/zif_abapgit_aff_registry.intf.abap @@ -0,0 +1,13 @@ +INTERFACE zif_abapgit_aff_registry + PUBLIC . + + METHODS: + "! Returns TRUE if the object type is supported by ABAP file formats (AFF) in abapGit.
+ "! Either there is a (standalone AFF capable) object handler, + "! or object handler calls the AFF framework in newer ABAP systems. + is_supported_object_type + IMPORTING + iv_obj_type TYPE tadir-object + RETURNING + VALUE(rv_result) TYPE abap_bool. +ENDINTERFACE. diff --git a/src/objects/aff/zif_abapgit_aff_registry.intf.xml b/src/objects/aff/zif_abapgit_aff_registry.intf.xml new file mode 100644 index 000000000..26c1fa815 --- /dev/null +++ b/src/objects/aff/zif_abapgit_aff_registry.intf.xml @@ -0,0 +1,15 @@ + + + + + + ZIF_ABAPGIT_AFF_REGISTRY + E + abapGit - interface for the aff registry + 2 + 1 + X + + + + diff --git a/src/objects/core/zcl_abapgit_filename_logic.clas.abap b/src/objects/core/zcl_abapgit_filename_logic.clas.abap index 8d90da0fd..f7d77c008 100644 --- a/src/objects/core/zcl_abapgit_filename_logic.clas.abap +++ b/src/objects/core/zcl_abapgit_filename_logic.clas.abap @@ -19,6 +19,7 @@ CLASS zcl_abapgit_filename_logic DEFINITION extension TYPE c LENGTH 4 VALUE 'json', END OF c_json_file. + CLASS-METHODS file_to_object IMPORTING !iv_filename TYPE string @@ -40,6 +41,9 @@ CLASS zcl_abapgit_filename_logic DEFINITION VALUE(rv_filename) TYPE string . PROTECTED SECTION. PRIVATE SECTION. + CLASS-DATA: + go_aff_registry TYPE REF TO zif_abapgit_aff_registry. + ENDCLASS. @@ -51,7 +55,7 @@ CLASS zcl_abapgit_filename_logic IMPLEMENTATION. DATA: lv_name TYPE string, - lv_type TYPE string, + lv_type TYPE trobjtype, lv_ext TYPE string. " Guess object type and name @@ -61,6 +65,12 @@ CLASS zcl_abapgit_filename_logic IMPLEMENTATION. REPLACE ALL OCCURRENCES OF '#' IN lv_name WITH '/'. REPLACE ALL OCCURRENCES OF '#' IN lv_type WITH '/'. REPLACE ALL OCCURRENCES OF '#' IN lv_ext WITH '/'. + " Assume AFF namespace convention + CREATE OBJECT go_aff_registry TYPE zcl_abapgit_aff_registry. + IF go_aff_registry->is_supported_object_type( lv_type ) = abap_true. + REPLACE ALL OCCURRENCES OF '(' IN lv_name WITH '/'. + REPLACE ALL OCCURRENCES OF ')' IN lv_name WITH '/'. + ENDIF. " The counter part to this logic must be maintained in OBJECT_TO_FILE IF lv_type = to_upper( c_package_file-obj_type ). @@ -88,6 +98,8 @@ CLASS zcl_abapgit_filename_logic IMPLEMENTATION. METHOD object_to_file. DATA lv_obj_name TYPE string. + DATA lv_nb_of_slash TYPE string. + lv_obj_name = is_item-obj_name. @@ -121,8 +133,18 @@ CLASS zcl_abapgit_filename_logic IMPLEMENTATION. ENDIF. " handle namespaces - REPLACE ALL OCCURRENCES OF '/' IN rv_filename WITH '#'. - TRANSLATE rv_filename TO LOWER CASE. + CREATE OBJECT go_aff_registry TYPE zcl_abapgit_aff_registry. + IF go_aff_registry->is_supported_object_type( is_item-obj_type ) = abap_true. + FIND ALL OCCURRENCES OF `/` IN rv_filename MATCH COUNT lv_nb_of_slash. + IF lv_nb_of_slash = 2. + REPLACE FIRST OCCURRENCE OF `/` IN rv_filename WITH `(`. + REPLACE `/` IN rv_filename WITH `)`. + ENDIF. + ELSE. + REPLACE ALL OCCURRENCES OF '/' IN rv_filename WITH '#'. + ENDIF. + TRANSLATE rv_filename TO LOWER CASE. ENDMETHOD. + ENDCLASS. diff --git a/src/objects/core/zcl_abapgit_filename_logic.clas.testclasses.abap b/src/objects/core/zcl_abapgit_filename_logic.clas.testclasses.abap index 35ea5633f..ac5396e8b 100644 --- a/src/objects/core/zcl_abapgit_filename_logic.clas.testclasses.abap +++ b/src/objects/core/zcl_abapgit_filename_logic.clas.testclasses.abap @@ -128,7 +128,24 @@ CLASS ltcl_run_checks IMPLEMENTATION. exp = 'ZMIME_<>_?' act = ls_item-obj_name ). - " JSON + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = 'ztest(name).w3mi.data,json' + iv_path = '/src/' + iv_devclass = '$PACK' + io_dot = mo_dot + IMPORTING + es_item = ls_item + ev_is_xml = lv_is_xml ). + + cl_abap_unit_assert=>assert_equals( + exp = 'W3MI' + act = ls_item-obj_type ). + cl_abap_unit_assert=>assert_equals( + exp = 'ZTEST(NAME)' + act = ls_item-obj_name ). + + " AFF file zcl_abapgit_filename_logic=>file_to_object( EXPORTING iv_filename = 'ztest.chko.json' @@ -149,6 +166,28 @@ CLASS ltcl_run_checks IMPLEMENTATION. exp = abap_true act = lv_is_json ). + + " AFF file with namespace + zcl_abapgit_filename_logic=>file_to_object( + EXPORTING + iv_filename = '(abcd)ztest.chko.json' + iv_path = '/src/' + iv_devclass = '$PACK' + io_dot = mo_dot + IMPORTING + es_item = ls_item + ev_is_json = lv_is_json ). + + cl_abap_unit_assert=>assert_equals( + exp = 'CHKO' + act = ls_item-obj_type ). + cl_abap_unit_assert=>assert_equals( + exp = '/ABCD/ZTEST' + act = ls_item-obj_name ). + cl_abap_unit_assert=>assert_equals( + exp = abap_true + act = lv_is_json ). + ENDMETHOD. METHOD object_to_file. @@ -215,6 +254,29 @@ CLASS ltcl_run_checks IMPLEMENTATION. exp = 'zmime_%3c%3e_%3f.w3mi.jpg' act = lv_filename ). + ls_item-obj_type = 'W3MI'. + ls_item-obj_name = 'ZTEST(NAME)'. + + lv_filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ls_item + iv_ext = 'json' ). + + cl_abap_unit_assert=>assert_equals( + exp = 'ztest(name).w3mi.json' + act = lv_filename ). + + " AFF object with namespace + ls_item-obj_type = 'CHKO'. + ls_item-obj_name = '/TEST/ZTEST'. + + lv_filename = zcl_abapgit_filename_logic=>object_to_file( + is_item = ls_item + iv_ext = 'json' ). + + cl_abap_unit_assert=>assert_equals( + exp = '(test)ztest.chko.json' + act = lv_filename ). + ENDMETHOD. METHOD file_to_object_pack. diff --git a/test/abap_transpile.json b/test/abap_transpile.json index 600182d5b..9b185981f 100644 --- a/test/abap_transpile.json +++ b/test/abap_transpile.json @@ -5,6 +5,7 @@ "src/ui/zcl_abapgit_e", "src/zcl_abapgit_e", "zcl_abapgit_adt_link", + "zcl_abapgit_aff_registry", "zcl_abapgit_ajson*", "zcl_abapgit_apack_reader", "zcl_abapgit_auth",