diff --git a/.abapgit.xml b/.abapgit.xml index 9bb224b..78de6d4 100644 --- a/.abapgit.xml +++ b/.abapgit.xml @@ -5,6 +5,13 @@ E /src/ FULL + + + SAP_BASIS + 740 + 0002 + + diff --git a/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.abap b/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.abap index 0ac3c0b..c2cf611 100644 --- a/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.abap +++ b/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.abap @@ -5,12 +5,10 @@ CLASS /usi/cl_bal_dc_structure DEFINITION PUBLIC FINAL CREATE PUBLIC. "! Constructor "! "! @parameter i_structure | A Structure + "! @parameter i_title | Text container METHODS constructor - IMPORTING - i_structure TYPE any - i_title TYPE REF TO /usi/if_bal_text_container_c40 OPTIONAL. - - PROTECTED SECTION. + IMPORTING i_structure TYPE any + i_title TYPE REF TO /usi/if_bal_text_container_c40 OPTIONAL. PRIVATE SECTION. TYPES ty_alv_output TYPE STANDARD TABLE OF /usi/bal_fieldname_and_value WITH NON-UNIQUE DEFAULT KEY. @@ -27,11 +25,21 @@ CLASS /usi/cl_bal_dc_structure DEFINITION PUBLIC FINAL CREATE PUBLIC. title TYPE REF TO /usi/if_bal_text_container_c40. METHODS build_alv_output - RAISING - /usi/cx_bal_root. + RAISING /usi/cx_bal_root. -ENDCLASS. + METHODS resolve_structure + IMPORTING i_structure_ref TYPE REF TO data + i_structure_description TYPE REF TO cl_abap_structdescr + i_structure_suffix TYPE string OPTIONAL + RETURNING VALUE(r_result) TYPE ty_alv_output + RAISING /usi/cx_bal_root. + METHODS resolve_elementary_field + IMPORTING i_structure_ref TYPE REF TO data + i_component_name TYPE string + RETURNING VALUE(r_result) TYPE ty_alv_output. + +ENDCLASS. CLASS /usi/cl_bal_dc_structure IMPLEMENTATION. @@ -63,16 +71,14 @@ CLASS /usi/cl_bal_dc_structure IMPLEMENTATION. IF deserialized_data-title_classname IS NOT INITIAL. TRY. CALL METHOD (deserialized_data-title_classname)=>/usi/if_bal_text_container_c40~deserialize - EXPORTING - i_serialized_text_container = deserialized_data-serialized_title - RECEIVING - r_result = title. + EXPORTING i_serialized_text_container = deserialized_data-serialized_title + RECEIVING r_result = title. CATCH cx_sy_dyn_call_error /usi/cx_bal_root INTO DATA(exception). DATA(exception_text) = exception->get_text( ). ASSERT ID /usi/bal_log_writer - FIELDS exception_text - CONDITION exception IS NOT BOUND. + FIELDS exception_text + CONDITION exception IS NOT BOUND. CLEAR title. ENDTRY. @@ -89,8 +95,11 @@ CLASS /usi/cl_bal_dc_structure IMPLEMENTATION. ENDMETHOD. METHOD constructor. - structure = REF #( i_structure ). - title = i_title. + CREATE DATA structure LIKE i_structure. + ASSIGN structure->* TO FIELD-SYMBOL(). + = i_structure. + + title = i_title. ENDMETHOD. METHOD /usi/if_bal_data_container~serialize. @@ -111,9 +120,6 @@ CLASS /usi/cl_bal_dc_structure IMPLEMENTATION. ENDMETHOD. METHOD build_alv_output. - FIELD-SYMBOLS: TYPE any, - TYPE simple. - IF alv_output IS BOUND. RETURN. ENDIF. @@ -122,28 +128,70 @@ CLASS /usi/cl_bal_dc_structure IMPLEMENTATION. DATA(structure_description) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_data_ref( structure ) ). CATCH cx_sy_move_cast_error INTO DATA(type_mismatch). RAISE EXCEPTION TYPE /usi/cx_bal_invalid_input - EXPORTING - textid = /usi/cx_bal_invalid_input=>/usi/cx_bal_invalid_input - previous = type_mismatch. + EXPORTING textid = /usi/cx_bal_invalid_input=>/usi/cx_bal_invalid_input + previous = type_mismatch. ENDTRY. CREATE DATA alv_output. - ASSIGN structure->* TO . - LOOP AT structure_description->get_components( ) - REFERENCE INTO DATA(component) - WHERE type->kind EQ cl_abap_typedescr=>kind_elem. - - ASSIGN COMPONENT component->name OF STRUCTURE TO . - IF sy-subrc NE 0. - CONTINUE. - ENDIF. - - INSERT VALUE #( fieldname = component->name - value = ) - INTO TABLE alv_output->*. + alv_output->* = resolve_structure( i_structure_ref = structure + i_structure_description = structure_description ). + + IF alv_output->* IS INITIAL. + RAISE EXCEPTION TYPE /usi/cx_bal_invalid_input + EXPORTING textid = /usi/cx_bal_invalid_input=>unsupported_structure. + ENDIF. + ENDMETHOD. + + METHOD resolve_structure. + LOOP AT i_structure_description->get_components( ) REFERENCE INTO DATA(component). + CASE component->type->kind. + WHEN cl_abap_typedescr=>kind_elem. + INSERT LINES OF resolve_elementary_field( i_structure_ref = i_structure_ref + i_component_name = |{ component->name }{ i_structure_suffix }| ) + INTO TABLE r_result. + + WHEN cl_abap_typedescr=>kind_struct. + IF component->as_include = abap_true. + INSERT LINES OF resolve_structure( i_structure_ref = i_structure_ref + i_structure_description = CAST #( component->type ) + i_structure_suffix = |{ component->suffix }{ i_structure_suffix }| ) + INTO TABLE r_result. + + ELSE. + ASSIGN i_structure_ref->* TO FIELD-SYMBOL(). + ASSIGN COMPONENT component->name OF STRUCTURE TO FIELD-SYMBOL(). + + TRY. + DATA(structure_description) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_data( + ) ). + CATCH cx_sy_move_cast_error INTO DATA(type_mismatch). + RAISE EXCEPTION TYPE /usi/cx_bal_invalid_input + EXPORTING textid = /usi/cx_bal_invalid_input=>/usi/cx_bal_invalid_input + previous = type_mismatch. + ENDTRY. + + INSERT LINES OF resolve_structure( i_structure_ref = REF #( ) + i_structure_description = structure_description ) + INTO TABLE r_result. + + ENDIF. + ENDCASE. ENDLOOP. ENDMETHOD. + METHOD resolve_elementary_field. + ASSIGN i_structure_ref->* TO FIELD-SYMBOL(). + ASSIGN COMPONENT i_component_name OF STRUCTURE TO FIELD-SYMBOL(). + + IF sy-subrc <> 0. + RETURN. + ENDIF. + + INSERT VALUE #( fieldname = i_component_name + value = ) + INTO TABLE r_result. + ENDMETHOD. + METHOD /usi/if_bal_data_container~get_description. DATA title_text TYPE /usi/if_bal_text_container_c40=>ty_text. @@ -159,23 +207,18 @@ CLASS /usi/cl_bal_dc_structure IMPLEMENTATION. METHOD /usi/if_bal_data_container_rnd~render. CALL FUNCTION 'LVC_FIELDCATALOG_MERGE' - EXPORTING - i_structure_name = '/USI/BAL_FIELDNAME_AND_VALUE' - CHANGING - ct_fieldcat = fieldcat - EXCEPTIONS - OTHERS = 0. + EXPORTING i_structure_name = '/USI/BAL_FIELDNAME_AND_VALUE' + CHANGING ct_fieldcat = fieldcat + EXCEPTIONS OTHERS = 0. build_alv_output( ). DATA(alv_grid) = NEW cl_gui_alv_grid( i_container ). alv_grid->set_table_for_first_display( - EXPORTING - is_layout = VALUE #( cwidth_opt = abap_true - zebra = abap_true ) - it_toolbar_excluding = VALUE #( ( cl_gui_alv_grid=>mc_fc_excl_all ) ) - CHANGING - it_outtab = alv_output->* - it_fieldcatalog = fieldcat ). + EXPORTING is_layout = VALUE #( cwidth_opt = abap_true + zebra = abap_true ) + it_toolbar_excluding = VALUE #( ( cl_gui_alv_grid=>mc_fc_excl_all ) ) + CHANGING it_outtab = alv_output->* + it_fieldcatalog = fieldcat ). ENDMETHOD. ENDCLASS. diff --git a/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.testclasses.abap b/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.testclasses.abap index 7b9f75a..7bdfa84 100644 --- a/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.testclasses.abap +++ b/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.testclasses.abap @@ -8,14 +8,12 @@ CLASS lcl_private_attribute_reader DEFINITION. TYPES ty_alv_output TYPE STANDARD TABLE OF /usi/bal_fieldname_and_value WITH NON-UNIQUE DEFAULT KEY. CLASS-METHODS get_alv_output - IMPORTING - i_cut TYPE REF TO /usi/cl_bal_dc_structure - RETURNING - VALUE(r_result) TYPE ty_alv_output - RAISING - /usi/cx_bal_root. + IMPORTING i_cut TYPE REF TO /usi/cl_bal_dc_structure + RETURNING VALUE(r_result) TYPE ty_alv_output + RAISING /usi/cx_bal_root. ENDCLASS. + CLASS lcl_private_attribute_reader IMPLEMENTATION. METHOD get_alv_output. i_cut->build_alv_output( ). @@ -23,24 +21,38 @@ CLASS lcl_private_attribute_reader IMPLEMENTATION. ENDMETHOD. ENDCLASS. -*--------------------------------------------------------------------* -* Unit test: Serialization -*--------------------------------------------------------------------* + +" --------------------------------------------------------------------- +" Unit test: Serialization +" --------------------------------------------------------------------- CLASS lcl_unit_tests_serialization DEFINITION FINAL FOR TESTING. "#AU Risk_Level Harmless "#AU Duration Short + PRIVATE SECTION. - METHODS test_deserialize_bad_xml FOR TESTING. + METHODS test_deserialize_bad_xml FOR TESTING. + + METHODS test_deserialize_valid_xml FOR TESTING RAISING /usi/cx_bal_root. + + METHODS test_ignores_object_references FOR TESTING RAISING /usi/cx_bal_root. + + METHODS test_throws_on_empty_result FOR TESTING RAISING /usi/cx_bal_root. - METHODS test_deserialize_valid_xml FOR TESTING - RAISING - /usi/cx_bal_root. + METHODS test_resolves_included_struc FOR TESTING RAISING /usi/cx_bal_root. + + METHODS test_resolves_include_w_suffix FOR TESTING RAISING /usi/cx_bal_root. + + METHODS test_resolves_multiple_suffix FOR TESTING RAISING /usi/cx_bal_root. + + METHODS test_resolves_structured_field FOR TESTING RAISING /usi/cx_bal_root. + + METHODS test_resolves_recursively FOR TESTING RAISING /usi/cx_bal_root. + + METHODS test_keeps_deep_struc_values FOR TESTING RAISING /usi/cx_bal_root. - METHODS test_ignores_object_references FOR TESTING - RAISING - /usi/cx_bal_root. ENDCLASS. + CLASS lcl_unit_tests_serialization IMPLEMENTATION. METHOD test_deserialize_bad_xml. TRY. @@ -72,7 +84,10 @@ CLASS lcl_unit_tests_serialization IMPLEMENTATION. ( fieldname = 'STRING' value = input-string ) ). - DATA(cut) = NEW /usi/cl_bal_dc_structure( input ). + DATA(valid_xml) = NEW /usi/cl_bal_dc_structure( input )->/usi/if_bal_data_container~serialize( ). + + DATA(cut) = CAST /usi/cl_bal_dc_structure( + /usi/cl_bal_dc_structure=>/usi/if_bal_data_container~deserialize( valid_xml ) ). DATA(act) = lcl_private_attribute_reader=>get_alv_output( cut ). cl_aunit_assert=>assert_equals( exp = exp @@ -94,18 +109,172 @@ CLASS lcl_unit_tests_serialization IMPLEMENTATION. cl_aunit_assert=>assert_equals( exp = exp act = act ). ENDMETHOD. + + METHOD test_throws_on_empty_result. + DATA: BEGIN OF structure, + to_be_ignored_field TYPE REF TO cl_gui_alv_grid, + END OF structure. + + DATA(cut) = NEW /usi/cl_bal_dc_structure( structure ). + + TRY. + cut->/usi/if_bal_data_container~serialize( ). + cl_aunit_assert=>fail( 'Input contained no relevant fields! Exception expected!' ). + CATCH /usi/cx_bal_root. + RETURN. + ENDTRY. + ENDMETHOD. + + METHOD test_resolves_included_struc. + TYPES: BEGIN OF ty_included_structure, + field_01 TYPE char10, + END OF ty_included_structure. + + TYPES BEGIN OF ty_main_structure. + INCLUDE TYPE ty_included_structure. + TYPES END OF ty_main_structure. + + DATA(given) = VALUE ty_main_structure( field_01 = 'GIVEN' ). + + DATA(exp) = VALUE lcl_private_attribute_reader=>ty_alv_output( ( fieldname = 'FIELD_01' + value = given-field_01 ) ). + + DATA(cut) = NEW /usi/cl_bal_dc_structure( given ). + DATA(act) = lcl_private_attribute_reader=>get_alv_output( cut ). + + cl_aunit_assert=>assert_equals( exp = exp + act = act ). + ENDMETHOD. + + METHOD test_resolves_include_w_suffix. + TYPES: BEGIN OF ty_included_structure, + field_01 TYPE char10, + END OF ty_included_structure. + + TYPES BEGIN OF ty_main_structure. + INCLUDE TYPE ty_included_structure AS included_structure RENAMING WITH SUFFIX _suffix. + TYPES END OF ty_main_structure. + + DATA(given) = VALUE ty_main_structure( field_01_suffix = 'GIVEN' ). + + DATA(exp) = VALUE lcl_private_attribute_reader=>ty_alv_output( ( fieldname = 'FIELD_01_SUFFIX' + value = given-field_01_suffix ) ). + + DATA(cut) = NEW /usi/cl_bal_dc_structure( given ). + DATA(act) = lcl_private_attribute_reader=>get_alv_output( cut ). + + cl_aunit_assert=>assert_equals( exp = exp + act = act ). + ENDMETHOD. + + METHOD test_resolves_multiple_suffix. + TYPES: BEGIN OF ty_structure_on_4th_level, + field_01 TYPE char10, + END OF ty_structure_on_4th_level. + + TYPES BEGIN OF ty_structure_on_3rd_level. + INCLUDE TYPE ty_structure_on_4th_level AS included_structure RENAMING WITH SUFFIX _s4. + TYPES END OF ty_structure_on_3rd_level. + + TYPES BEGIN OF ty_structure_on_2nd_level. + INCLUDE TYPE ty_structure_on_3rd_level AS included_structure RENAMING WITH SUFFIX _s3. + TYPES END OF ty_structure_on_2nd_level. + + TYPES BEGIN OF ty_structure_on_1st_level. + INCLUDE TYPE ty_structure_on_2nd_level AS included_structure RENAMING WITH SUFFIX _s2. + TYPES END OF ty_structure_on_1st_level. + + DATA(given) = VALUE ty_structure_on_1st_level( field_01_s4_s3_s2 = 'GIVEN' ). + + DATA(exp) = VALUE lcl_private_attribute_reader=>ty_alv_output( ( fieldname = 'FIELD_01_S4_S3_S2' + value = given-field_01_s4_s3_s2 ) ). + + DATA(cut) = NEW /usi/cl_bal_dc_structure( given ). + DATA(act) = lcl_private_attribute_reader=>get_alv_output( cut ). + + cl_aunit_assert=>assert_equals( exp = exp + act = act ). + ENDMETHOD. + + METHOD test_resolves_structured_field. + TYPES: BEGIN OF ty_used_structure, + field_01 TYPE char10, + END OF ty_used_structure. + + TYPES: BEGIN OF ty_main_structure, + structured_field TYPE ty_used_structure, + END OF ty_main_structure. + + DATA(given) = VALUE ty_main_structure( structured_field = VALUE #( field_01 = 'GIVEN' ) ). + + DATA(exp) = VALUE lcl_private_attribute_reader=>ty_alv_output( ( fieldname = 'FIELD_01' + value = given-structured_field-field_01 ) ). + + DATA(cut) = NEW /usi/cl_bal_dc_structure( given ). + DATA(act) = lcl_private_attribute_reader=>get_alv_output( cut ). + + cl_aunit_assert=>assert_equals( exp = exp + act = act ). + ENDMETHOD. + + METHOD test_resolves_recursively. + TYPES: BEGIN OF ty_used_structure, + field_01 TYPE char10, + END OF ty_used_structure. + + TYPES: BEGIN OF ty_included_structure, + structured_field TYPE ty_used_structure, + END OF ty_included_structure. + + TYPES BEGIN OF ty_main_structure. + INCLUDE TYPE ty_included_structure. + TYPES END OF ty_main_structure. + + DATA(given) = VALUE ty_main_structure( structured_field = VALUE #( field_01 = 'GIVEN' ) ). + + DATA(exp) = VALUE lcl_private_attribute_reader=>ty_alv_output( ( fieldname = 'FIELD_01' + value = given-structured_field-field_01 ) ). + + DATA(cut) = NEW /usi/cl_bal_dc_structure( given ). + DATA(act) = lcl_private_attribute_reader=>get_alv_output( cut ). + + cl_aunit_assert=>assert_equals( exp = exp + act = act ). + ENDMETHOD. + + METHOD test_keeps_deep_struc_values. + TYPES: BEGIN OF ty_deep_structure, + field_01 TYPE char10, + field_02 TYPE string, + END OF ty_deep_structure. + + DATA(exp) = VALUE lcl_private_attribute_reader=>ty_alv_output( ( fieldname = 'FIELD_01' + value = 'THIS DATA' ) + ( fieldname = 'FIELD_02' + value = 'MUST NOT BE LOST!' ) ). + + DATA(cut) = NEW /usi/cl_bal_dc_structure( VALUE ty_deep_structure( field_01 = 'THIS DATA' + field_02 = 'MUST NOT BE LOST!' ) ). + DATA(act) = lcl_private_attribute_reader=>get_alv_output( cut ). + + cl_aunit_assert=>assert_equals( exp = exp + act = act ). + ENDMETHOD. ENDCLASS. -*--------------------------------------------------------------------* -* Unit test: Cardinality -*--------------------------------------------------------------------* + +" --------------------------------------------------------------------- +" Unit test: Cardinality +" --------------------------------------------------------------------- CLASS lcl_unit_test_cardinality DEFINITION FINAL FOR TESTING. "#AU Risk_Level Harmless "#AU Duration Short + PRIVATE SECTION. METHODS assert_is_single_use FOR TESTING. ENDCLASS. + CLASS lcl_unit_test_cardinality IMPLEMENTATION. METHOD assert_is_single_use. DATA actual_result TYPE abap_bool. @@ -116,16 +285,19 @@ CLASS lcl_unit_test_cardinality IMPLEMENTATION. ENDMETHOD. ENDCLASS. -*--------------------------------------------------------------------* -* Unit test: Classname -*--------------------------------------------------------------------* + +" --------------------------------------------------------------------- +" Unit test: Classname +" --------------------------------------------------------------------- CLASS lcl_unit_test_classname DEFINITION FINAL CREATE PUBLIC FOR TESTING. "#AU Risk_Level Harmless "#AU Duration Short + PRIVATE SECTION. METHODS assert_returns_right_classname FOR TESTING. ENDCLASS. + CLASS lcl_unit_test_classname IMPLEMENTATION. METHOD assert_returns_right_classname. DATA: cut_description TYPE REF TO /usi/cl_bal_aunit_cut_descr_cl, diff --git a/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.xml b/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.xml index a35ebba..005501d 100644 --- a/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.xml +++ b/src/#usi#bal_data_containers/#usi#cl_bal_dc_structure.clas.xml @@ -20,6 +20,19 @@ 18 + + + D + + + I + DES + Struktur + 18 + + + + diff --git a/src/#usi#bal_exceptions/#usi#cx_bal_invalid_input.clas.abap b/src/#usi#bal_exceptions/#usi#cx_bal_invalid_input.clas.abap index 299120e..58a4dce 100644 --- a/src/#usi#bal_exceptions/#usi#cx_bal_invalid_input.clas.abap +++ b/src/#usi#bal_exceptions/#usi#cx_bal_invalid_input.clas.abap @@ -68,6 +68,15 @@ public section. attr3 type scx_attrname value '', attr4 type scx_attrname value '', end of TRANSFORMATION_ERROR . + constants: + begin of UNSUPPORTED_STRUCTURE, + msgid type symsgid value '/USI/BAL', + msgno type symsgno value '050', + attr1 type scx_attrname value '', + attr2 type scx_attrname value '', + attr3 type scx_attrname value '', + attr4 type scx_attrname value '', + end of UNSUPPORTED_STRUCTURE . "!

Constructor

"! diff --git a/src/#usi#bal_exceptions/#usi#cx_bal_invalid_input.clas.xml b/src/#usi#bal_exceptions/#usi#cx_bal_invalid_input.clas.xml index 9ee8250..cf0a8c9 100644 --- a/src/#usi#bal_exceptions/#usi#cx_bal_invalid_input.clas.xml +++ b/src/#usi#bal_exceptions/#usi#cx_bal_invalid_input.clas.xml @@ -16,14 +16,14 @@
- 7A047530010C1EDC97B1F1C0861A1F9C + 005056B49E5B1EDEB2FBBD7B56114E1C E 1 CA==
- 7A047530010C1EDC97B1F1C0861A1F9C + 005056B49E5B1EDEB2FBBD7B56114E1C E 0001 X @@ -38,7 +38,7 @@ LIMU CPUB /USI/CX_BAL_INVALID_INPUT - 7A047530010C1EDC97B1F1C0861A1F9C + 005056B49E5B1EDEB2FBBD7B56114E1C 0001 diff --git a/src/#usi#bal_messages/#usi#bal.msag.xml b/src/#usi#bal_messages/#usi#bal.msag.xml index 27484fb..40832b0 100644 --- a/src/#usi#bal_messages/#usi#bal.msag.xml +++ b/src/#usi#bal_messages/#usi#bal.msag.xml @@ -164,6 +164,12 @@ 040 Transformation error (Check previous exception for details). + + E + /USI/BAL + 050 + Unsupported structure - no field values could be extracted! + D @@ -301,6 +307,16 @@ 030 Nur der Besitzer dieses Logs darf diese Aktion durchführen!
+ + D + 040 + Transformationsfehler ( Siehe vorherige Ausnahme für Details). + + + D + 050 + Nicht unterstützte Struktur - Extraktion von Feldwerten nicht möglich! +