From 89090b5c00b469f305e71eeaec042b691e1a455a Mon Sep 17 00:00:00 2001 From: Albert Mink Date: Thu, 30 Jun 2022 16:06:55 +0200 Subject: [PATCH] [AFF] Allow object handler to serialize JSON via experimental feature (#5660) * [AFF] Object handler for INTF * Add JSON handler * hard coded language * adopt to abapLint rules * wip: abaplint * wip: abapLint * adjust to naming conventions * AJSON filtering abapLanguageVersion for serializat * SELECT 7.02; UPPER * abapLint params * filter/remove the empty arrays * reset obj handler to origin/main * add experimental feature to enable AFF serializati * typos, indentation and more * move code to local clas * Update src/objects/zcl_abapgit_object_intf.clas.abap Co-authored-by: Lars Hvam Co-authored-by: Lars Hvam --- .../aff/zcl_abapgit_json_handler.clas.abap | 89 +++++++++++++++++++ ..._abapgit_json_handler.clas.locals_imp.abap | 47 ++++++++++ .../aff/zcl_abapgit_json_handler.clas.xml | 16 ++++ .../zif_abapgit_aff_type_mapping.intf.abap | 11 +++ .../aff/zif_abapgit_aff_type_mapping.intf.xml | 15 ++++ src/objects/zcl_abapgit_object_intf.clas.abap | 24 +++-- ...l_abapgit_object_intf.clas.locals_imp.abap | 59 ++++++++++++ 7 files changed, 253 insertions(+), 8 deletions(-) create mode 100644 src/objects/aff/zcl_abapgit_json_handler.clas.abap create mode 100644 src/objects/aff/zcl_abapgit_json_handler.clas.locals_imp.abap create mode 100644 src/objects/aff/zcl_abapgit_json_handler.clas.xml create mode 100644 src/objects/aff/zif_abapgit_aff_type_mapping.intf.abap create mode 100644 src/objects/aff/zif_abapgit_aff_type_mapping.intf.xml create mode 100644 src/objects/zcl_abapgit_object_intf.clas.locals_imp.abap diff --git a/src/objects/aff/zcl_abapgit_json_handler.clas.abap b/src/objects/aff/zcl_abapgit_json_handler.clas.abap new file mode 100644 index 000000000..b308386f5 --- /dev/null +++ b/src/objects/aff/zcl_abapgit_json_handler.clas.abap @@ -0,0 +1,89 @@ +CLASS zcl_abapgit_json_handler DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + "! Serializes data to xstring. Type of data is specified in the + "! implementing class. + "! + "! @parameter iv_data | data to be serialized + "! @parameter rv_result | serialized data + METHODS serialize + IMPORTING iv_data TYPE data + RETURNING VALUE(rv_result) TYPE xstring + RAISING cx_static_check. + + "! Deserializes xstring into data. The type of data is specified in + "! the implementing class + "! + "! @parameter iv_content | xstring to be deserialized + "! @parameter ev_data | data of the xstring + METHODS deserialize + IMPORTING iv_content TYPE xstring + EXPORTING ev_data TYPE data + RAISING cx_static_check. + PROTECTED SECTION. + + PRIVATE SECTION. + + +ENDCLASS. + + + +CLASS zcl_abapgit_json_handler IMPLEMENTATION. + + + METHOD deserialize. + DATA lv_json TYPE string. + DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. + DATA lo_mapping TYPE REF TO zif_abapgit_ajson_mapping. + + CLEAR ev_data. + + lv_json = zcl_abapgit_convert=>xstring_to_string_utf8( iv_content ). + lo_mapping = zcl_abapgit_ajson_mapping=>create_camel_case( ). + + lo_ajson = zcl_abapgit_ajson=>parse( iv_json = lv_json + ii_custom_mapping = lo_mapping ). + + lo_ajson->zif_abapgit_ajson~to_abap( IMPORTING ev_container = ev_data ). + + ENDMETHOD. + + + METHOD serialize. + DATA lt_st_source TYPE abap_trans_srcbind_tab. + DATA lo_mapping TYPE REF TO lcl_mapping. + DATA lv_json TYPE string. + DATA lo_ajson TYPE REF TO zcl_abapgit_ajson. + DATA lo_ajson_filtered TYPE REF TO zcl_abapgit_ajson. + DATA lo_aff_filter TYPE REF TO zif_abapgit_ajson_filter. + + FIELD-SYMBOLS: LIKE LINE OF lt_st_source. + + APPEND INITIAL LINE TO lt_st_source ASSIGNING . + GET REFERENCE OF iv_data INTO -value. + CREATE OBJECT lo_mapping. + + lo_ajson = zcl_abapgit_ajson=>create_empty( lo_mapping ). + + lo_ajson->keep_item_order( ). + lo_ajson->set( + iv_path = '/' + iv_val = iv_data ). + + CREATE OBJECT lo_aff_filter TYPE lcl_aff_filter. + lo_ajson_filtered = zcl_abapgit_ajson=>create_from( + ii_source_json = lo_ajson + ii_filter = zcl_abapgit_ajson_filter_lib=>create_empty_filter( ) ). + lo_ajson_filtered->keep_item_order( ). + + lv_json = lo_ajson_filtered->stringify( 2 ). + + rv_result = zcl_abapgit_convert=>string_to_xstring_utf8( lv_json ). + + ENDMETHOD. +ENDCLASS. diff --git a/src/objects/aff/zcl_abapgit_json_handler.clas.locals_imp.abap b/src/objects/aff/zcl_abapgit_json_handler.clas.locals_imp.abap new file mode 100644 index 000000000..6a31a5b00 --- /dev/null +++ b/src/objects/aff/zcl_abapgit_json_handler.clas.locals_imp.abap @@ -0,0 +1,47 @@ +*"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations +CLASS lcl_mapping DEFINITION. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. +ENDCLASS. + +CLASS lcl_mapping IMPLEMENTATION. + METHOD zif_abapgit_ajson_mapping~to_abap. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + TYPES ty_token TYPE c LENGTH 255. + DATA lt_tokens TYPE STANDARD TABLE OF ty_token. + FIELD-SYMBOLS LIKE LINE OF lt_tokens. + + rv_result = iv_name. + + SPLIT rv_result AT `_` INTO TABLE lt_tokens. + LOOP AT lt_tokens ASSIGNING FROM 2. + TRANSLATE (1) TO UPPER CASE. + ENDLOOP. + CONCATENATE LINES OF lt_tokens INTO rv_result. + + ENDMETHOD. +ENDCLASS. + + +CLASS lcl_aff_filter DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_filter. + PRIVATE SECTION. + DATA mt_skip_paths TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line. +ENDCLASS. + +CLASS lcl_aff_filter IMPLEMENTATION. + + METHOD zif_abapgit_ajson_filter~keep_node. + DATA lv_path TYPE string. + lv_path = is_node-path && is_node-name. + + rv_keep = boolc( NOT ( lv_path = `/header/abapLanguageVersion` AND is_node-value = 'X' ) ). + ENDMETHOD. + + +ENDCLASS. diff --git a/src/objects/aff/zcl_abapgit_json_handler.clas.xml b/src/objects/aff/zcl_abapgit_json_handler.clas.xml new file mode 100644 index 000000000..b28014e14 --- /dev/null +++ b/src/objects/aff/zcl_abapgit_json_handler.clas.xml @@ -0,0 +1,16 @@ + + + + + + ZCL_ABAPGIT_JSON_HANDLER + E + abapGit - The object handler for JSON parsing + 1 + X + X + X + + + + diff --git a/src/objects/aff/zif_abapgit_aff_type_mapping.intf.abap b/src/objects/aff/zif_abapgit_aff_type_mapping.intf.abap new file mode 100644 index 000000000..b55b29601 --- /dev/null +++ b/src/objects/aff/zif_abapgit_aff_type_mapping.intf.abap @@ -0,0 +1,11 @@ +INTERFACE zif_abapgit_aff_type_mapping + PUBLIC . + METHODS: + "! Converts to AFF specific meta data + "! + "! @parameter iv_data | (meta-)data of the object + "! @parameter es_data | aff data of the object, e.g. zif_abapgit_aff_intf_v1=>ty_main + to_aff + IMPORTING iv_data TYPE data + EXPORTING es_data TYPE data. +ENDINTERFACE. diff --git a/src/objects/aff/zif_abapgit_aff_type_mapping.intf.xml b/src/objects/aff/zif_abapgit_aff_type_mapping.intf.xml new file mode 100644 index 000000000..3390b3b66 --- /dev/null +++ b/src/objects/aff/zif_abapgit_aff_type_mapping.intf.xml @@ -0,0 +1,15 @@ + + + + + + ZIF_ABAPGIT_AFF_TYPE_MAPPING + E + abapgit - the mapping to ABAP file format types + 2 + 1 + X + + + + diff --git a/src/objects/zcl_abapgit_object_intf.clas.abap b/src/objects/zcl_abapgit_object_intf.clas.abap index ebdf60fe6..897def591 100644 --- a/src/objects/zcl_abapgit_object_intf.clas.abap +++ b/src/objects/zcl_abapgit_object_intf.clas.abap @@ -290,6 +290,7 @@ CLASS zcl_abapgit_object_intf IMPLEMENTATION. DATA: ls_intf TYPE ty_intf, ls_clskey TYPE seoclskey, + lv_serialized_data TYPE xstring, lt_langu_additional TYPE zif_abapgit_lang_definitions=>ty_langus. ls_clskey-clsname = ms_item-obj_name. @@ -324,14 +325,21 @@ CLASS zcl_abapgit_object_intf IMPLEMENTATION. iv_clsname = ls_clskey-clsname ). " HERE: switch with feature flag for XML or JSON file format - io_xml->add( iv_name = 'VSEOINTERF' - ig_data = ls_intf-vseointerf ). - io_xml->add( iv_name = 'DESCRIPTIONS' - ig_data = ls_intf-description ). - io_xml->add( iv_name = 'LINES' - ig_data = ls_intf-docu-lines ). - io_xml->add( iv_name = 'I18N_LINES' - ig_data = ls_intf-docu-i18n_lines ). + IF zcl_abapgit_persist_factory=>get_settings( )->read( )->get_experimental_features( ) = abap_true. + lv_serialized_data = lcl_aff_serialize_metadata=>serialize( ls_intf ). + zif_abapgit_object~mo_files->add_raw( iv_ext = 'json' + iv_data = lv_serialized_data ). + + ELSE. + io_xml->add( iv_name = 'VSEOINTERF' + ig_data = ls_intf-vseointerf ). + io_xml->add( iv_name = 'DESCRIPTIONS' + ig_data = ls_intf-description ). + io_xml->add( iv_name = 'LINES' + ig_data = ls_intf-docu-lines ). + io_xml->add( iv_name = 'I18N_LINES' + ig_data = ls_intf-docu-i18n_lines ). + ENDIF. ENDMETHOD. diff --git a/src/objects/zcl_abapgit_object_intf.clas.locals_imp.abap b/src/objects/zcl_abapgit_object_intf.clas.locals_imp.abap new file mode 100644 index 000000000..5b9868059 --- /dev/null +++ b/src/objects/zcl_abapgit_object_intf.clas.locals_imp.abap @@ -0,0 +1,59 @@ +*"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations +CLASS lcl_aff_type_mapping DEFINITION. + PUBLIC SECTION. + INTERFACES zif_abapgit_aff_type_mapping. +ENDCLASS. + +CLASS lcl_aff_type_mapping IMPLEMENTATION. + + METHOD zif_abapgit_aff_type_mapping~to_aff. + DATA: + ls_data_abapgit TYPE zcl_abapgit_object_intf=>ty_intf, + ls_data_aff TYPE zif_abapgit_aff_intf_v1=>ty_main. + + ls_data_abapgit = iv_data. + + " todo: to convert the data + ls_data_aff-format_version = '42'. + + es_data = ls_data_aff. + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_aff_serialize_metadata DEFINITION. + PUBLIC SECTION. + + CLASS-METHODS serialize + IMPORTING is_intf TYPE data + RETURNING VALUE(rv_result) TYPE xstring + RAISING zcx_abapgit_exception. +ENDCLASS. + +CLASS lcl_aff_serialize_metadata IMPLEMENTATION. + + METHOD serialize. + DATA: + ls_data_abapgit TYPE zcl_abapgit_object_intf=>ty_intf, + ls_data_aff TYPE zif_abapgit_aff_intf_v1=>ty_main, + lx_exception TYPE REF TO cx_root, + lo_ajson TYPE REF TO zcl_abapgit_json_handler, + lo_aff_mapper TYPE REF TO zif_abapgit_aff_type_mapping. + + ls_data_abapgit = is_intf. + + CREATE OBJECT lo_aff_mapper TYPE lcl_aff_type_mapping. + lo_aff_mapper->to_aff( EXPORTING iv_data = ls_data_abapgit + IMPORTING es_data = ls_data_aff ). + CREATE OBJECT lo_ajson. + TRY. + rv_result = lo_ajson->serialize( ls_data_aff ). + CATCH cx_root INTO lx_exception. + zcx_abapgit_exception=>raise_with_text( lx_exception ). + ENDTRY. + + ENDMETHOD. + +ENDCLASS.