diff --git a/README.md b/README.md index b54d8e04..1e054d3f 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ * Want to help out? see the contribution guidelines [(abap2UI5/contribution)](https://github.com/abap2UI5/abap2UI5/blob/main/CONTRIBUTING.md) #### Apps & Extensions -* Integrate your apps in launchpads and other services [(abap2UI5/ext-service_integration)](https://github.com/abap2UI5/ext-service_integration) -* Try out abap2UI5-tools, a useful collection of tools & apps [(abap2UI5/tools)](https://github.com/abap2UI5/app-tools) +* Integrate your apps in launchpads and other services [(ext-service_integration)](https://github.com/abap2UI5/ext-service_integration) +* Try out abap2UI5-tools, a useful collection of tools & apps [(ext-app_tools)](https://github.com/abap2UI5/app-tools) * Check out other projects using abap2UI5 [(abap2UI5/links)](https://github.com/abap2UI5/abap2UI5-documentation/blob/main/docs/links.md) * And finally: Don't forget to explore the [Samples Repository 🧭](https://github.com/abap2UI5/abap2UI5-samples) diff --git a/abaplint-max_fix.jsonc b/abaplint-max_fix.jsonc new file mode 100644 index 00000000..b076fac9 --- /dev/null +++ b/abaplint-max_fix.jsonc @@ -0,0 +1,258 @@ +{ + "global": { + "files": "/src/**/*.*" + }, + "dependencies": [ + { + "url": "https://github.com/abapedia/steampunk-2305-api", + "folder": "/deps", + "files": "/src/**/*.*" + } + ], + "syntax": { + "version": "v750", + "errorNamespace": "." + }, + "rules": { + "7bit_ascii": true, + "abapdoc": true, + "sql_value_conversion" : true, + "select_single_full_key" : true, + "strict_sql" : true, + "easy_to_find_messages" : true, + "fully_type_itabs" : true, + "align_parameters": true, + "smim_consistency": true, + "allowed_object_naming": true, + "allowed_object_types": true, + "ambiguous_statement": true, + "avoid_use": true, + "begin_end_names": true, + "begin_single_include": true, + "call_transaction_authority_check": true, + "cds_comment_style": true, + "cds_legacy_view": true, + "cds_parser_error": true, + "chain_mainly_declarations": true, + "change_if_to_case": { + "exclude": [], + "severity": "Error", + "skipNames": [] + }, + "check_abstract": true, + "check_comments": true, + "check_ddic": true, + "check_include": true, + "check_subrc": true, + "check_syntax": true, + "check_text_elements": true, + "check_transformation_exists": true, + "class_attribute_names": true, + "classic_exceptions_overlap": true, + "cloud_types": true, + "colon_missing_space": true, + "commented_code": true, + "constant_classes": { + "exclude": [], + "severity": "Error", + "mapping": [] + }, + "constructor_visibility_public": true, + "contains_tab": { + "exclude": [], + "severity": "Error", + "spaces": 1 + }, + "cyclic_oo": true, + "cyclomatic_complexity": { + "exclude": [], + "severity": "Error", + "max": 20 + }, + "dangerous_statement": true, + "db_operation_in_loop": true, + "definitions_top": true, + "description_empty": true, + "double_space": true, + "downport": true, + "empty_line_in_statement": true, + "empty_statement": true, + "empty_structure": { + "loop": true, + "if": true, + "while": true, + "case": true, + "select": true, + "do": true, + "at": true, + "try": true, + "when": true + }, + "exit_or_check": true, + "expand_macros": true, + "exporting": true, + "forbidden_identifier": true, + "forbidden_pseudo_and_pragma": { + "exclude": [], + "severity": "Error", + "pseudo": [], + "pragmas": [], + "ignoreGlobalClassDefinition": true, + "ignoreGlobalInterface": true + }, + "forbidden_void_type": true, + "form_tables_obsolete": true, + "fully_type_constants": { + "checkData": true + }, + "function_module_recommendations": true, + "functional_writing": { + "ignoreExceptions": true + }, + "global_class": true, + "identical_conditions": true, + "identical_contents": true, + "identical_descriptions": true, + "identical_form_names": true, + "if_in_if": true, + "implement_methods": true, + "in_statement_indentation": true, + "indentation": true, + "inline_data_old_versions": true, + "intf_referencing_clas": true, + "keep_single_parameter_on_one_line": true, + "keyword_case": true, + "line_break_multiple_parameters": true, + "line_break_style": true, + "line_length": true, + "line_only_punc": true, + "local_class_naming": true, + "local_testclass_consistency": true, + "local_variable_names": true, + "main_file_contents": true, + "many_parentheses": true, + "max_one_method_parameter_per_line": true, + "max_one_statement": true, + "message_exists": true, + "method_implemented_twice": true, + "method_length": true, + "method_overwrites_builtin": true, + "method_parameter_names": true, + "mix_returning": true, + "modify_only_own_db_tables": { + "reportDynamic": true, + "ownTables": "^[yz]" + }, + "msag_consistency": true, + "names_no_dash": true, + "nesting": { + "depth": 5 + }, + "newline_between_methods": true, + "no_aliases": true, + "no_chained_assignment": true, + "no_external_form_calls": true, + "no_inline_in_optional_branches": true, + "no_public_attributes": true, + "no_yoda_conditions": true, + "nrob_consistency": true, + "object_naming": { + "exclude": [], + "severity": "Error", + "patternKind": "required", + "ignoreNames": [], + "ignorePatterns": [], + "clas": "^Z2UI5_C(L|X)", + "intf": "^Z2UI5_IF", + "prog": "^Z", + "fugr": "^Z", + "tabl": "^Z", + "ttyp": "^Z", + "dtel": "^Z", + "doma": "^Z", + "msag": "^Z", + "tran": "^Z", + "enqu": "^EZ", + "auth": "^Z", + "pinf": "^Z", + "idoc": "^Z", + "xslt": "^Z", + "ssfo": "^Z", + "ssst": "^Z", + "shlp": "^Z" + }, + "obsolete_statement": true, + "omit_parameter_name": true, + "omit_preceding_zeros": true, + "omit_receiving": true, + "parser_702_chaining": true, + "parser_error": true, + "parser_missing_space": true, + "pragma_style": true, + "prefer_corresponding": true, + "prefer_inline": { + "severity": "Warning" + }, + "prefer_is_not": true, + "prefer_raise_exception_new": true, + "prefer_returning_to_exporting": true, + "prefer_xsdbool": true, + "preferred_compare_operator": true, + "prefix_is_current_class": { + "severity": "Warning" + }, + "reduce_string_templates": true, + "release_idoc": true, + "remove_descriptions": { + "exclude": [], + "severity": "Error", + "ignoreExceptions": true, + "ignoreWorkflow": true + }, + "rfc_error_handling": true, + "select_add_order_by": true, + "select_performance": true, + "selection_screen_naming": true, + "sequential_blank": { + "severity": "Warning" + }, + "short_case": true, + "sicf_consistency": true, + "slow_parameter_passing": true, + "space_before_colon": true, + "space_before_dot": true, + "sql_escape_host_variables": true, + "start_at_tab": true, + "static_call_via_instance": { + "allowInTestclassIncludes": true + }, + "superclass_final": true, + "superfluous_value": true, + "sy_modification": true, + "tabl_enhancement_category": true, + "try_without_catch": true, + "type_form_parameters": true, + "types_naming": true, + "uncaught_exception": true, + "unknown_types": true, + "unnecessary_chaining": true, + "unnecessary_pragma": true, + "unnecessary_return": true, + "unreachable_code": true, + "unsecure_fae": true, + "unused_ddic": true, + "unused_methods": true, + "unused_types": true, + "unused_variables": { + "severity": "Error", + "skipNames": ["lv_dummy", "i_mv_editor"] + }, + "use_bool_expression": true, + "use_class_based_exceptions": true, + "use_line_exists": true, + "use_new": true, + "when_others_last": true, + "whitespace_end": true, + "xml_consistency": true + } +} diff --git a/abaplint.jsonc b/abaplint.jsonc index efcd22d6..e45cf55a 100644 --- a/abaplint.jsonc +++ b/abaplint.jsonc @@ -241,13 +241,16 @@ "unnecessary_chaining": true, "unnecessary_pragma": true, "unnecessary_return": true, - "unreachable_code": true, + "unreachable_code": { + "exclude": ["z2ui5_cl_fw_utility.clas.testclasses.abap"] + }, "unsecure_fae": true, "unused_ddic": true, "unused_methods": true, "unused_types": true, "unused_variables": { "severity": "Error", + "exclude": ["z2ui5_cl_fw_utility.clas.testclasses.abap"], "skipNames": ["lv_dummy", "i_mv_editor"] }, "use_bool_expression": true, diff --git a/package-lock.json b/package-lock.json index 73e332cc..f883cb0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,16 +9,16 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@abaplint/cli": "^2.101.6", - "@abaplint/database-sqlite": "^2.7.13", - "@abaplint/runtime": "^2.7.14", - "@abaplint/transpiler-cli": "^2.7.14" + "@abaplint/cli": "^2.102.11", + "@abaplint/database-sqlite": "^2.7.18", + "@abaplint/runtime": "^2.7.55", + "@abaplint/transpiler-cli": "^2.7.55" } }, "node_modules/@abaplint/cli": { - "version": "2.101.6", - "resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.101.6.tgz", - "integrity": "sha512-RFH0Rs3Pe4+8O7Je7Xrye0C+BPhH654WMtdNk+5O5tiJQesKrSPK9rKr8GhTCHpY2V3paYFCHkP8b9DymdxPrw==", + "version": "2.102.11", + "resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.102.11.tgz", + "integrity": "sha512-APdQdrRjN4dUSKkEB1ABm9qijcCa1HWpNFLFGgZgTFVUl2T4PSnTkouJtc6Rad/1A/fB6I0c2lWnOxQV9c3dZA==", "dev": true, "bin": { "abaplint": "abaplint" @@ -31,18 +31,18 @@ } }, "node_modules/@abaplint/database-sqlite": { - "version": "2.7.13", - "resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.7.13.tgz", - "integrity": "sha512-zansX431Tm2u+S84hIG7QrGUlfWGamikLYzp+erniiRbft1BoxWD7WeGaNR7J26MIzlnVpYRHPJUvWi0Z+dLRA==", + "version": "2.7.18", + "resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.7.18.tgz", + "integrity": "sha512-NY1D+39sh9WQV2pmDR0mFM4C0bNI9CTTlbSUhXrUcq8X26rfLjYemGHJ/J/G90W/W9xx6Do4lMzgGep7sMqZ1w==", "dev": true, "dependencies": { "sql.js": "^1.8.0" } }, "node_modules/@abaplint/runtime": { - "version": "2.7.14", - "resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.7.14.tgz", - "integrity": "sha512-ZUN6c4xkKgSoi0RALF8/HvgyYiOiF7ISEQyehz/8jhAq7qbxR9kzcrQzidVnNLlsMTqwVFH3XxsiL2ZWtV0CoQ==", + "version": "2.7.55", + "resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.7.55.tgz", + "integrity": "sha512-bNQ4nexrF2oLQ3d8baj8rSn6s1V19RqimF4sPwBawnUH9jAXb99zxysYFEqMf/R6aTmPUjnPgB9PLnYPPJ6FoA==", "dev": true, "dependencies": { "temporal-polyfill": "^0.1.1" @@ -52,9 +52,9 @@ } }, "node_modules/@abaplint/transpiler-cli": { - "version": "2.7.14", - "resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.7.14.tgz", - "integrity": "sha512-oAXu0K95RfELbqPcF1YJZWMk/ZdmHlkG8osfRfqqdN0LOxvvdZuMC/eVw16el7P6u5TDlqBL+sJq6sxkvxL72w==", + "version": "2.7.55", + "resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.7.55.tgz", + "integrity": "sha512-tgSib6t6TnHsQfmm0a6wLoF0vdpw9nyq24laZMXGNWXADN4442kj5/6NUYo8CJ/0gxqK94P3lQwem0ZkQIZSVA==", "dev": true, "bin": { "abap_transpile": "abap_transpile" @@ -87,33 +87,33 @@ }, "dependencies": { "@abaplint/cli": { - "version": "2.101.6", - "resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.101.6.tgz", - "integrity": "sha512-RFH0Rs3Pe4+8O7Je7Xrye0C+BPhH654WMtdNk+5O5tiJQesKrSPK9rKr8GhTCHpY2V3paYFCHkP8b9DymdxPrw==", + "version": "2.102.11", + "resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.102.11.tgz", + "integrity": "sha512-APdQdrRjN4dUSKkEB1ABm9qijcCa1HWpNFLFGgZgTFVUl2T4PSnTkouJtc6Rad/1A/fB6I0c2lWnOxQV9c3dZA==", "dev": true }, "@abaplint/database-sqlite": { - "version": "2.7.13", - "resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.7.13.tgz", - "integrity": "sha512-zansX431Tm2u+S84hIG7QrGUlfWGamikLYzp+erniiRbft1BoxWD7WeGaNR7J26MIzlnVpYRHPJUvWi0Z+dLRA==", + "version": "2.7.18", + "resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.7.18.tgz", + "integrity": "sha512-NY1D+39sh9WQV2pmDR0mFM4C0bNI9CTTlbSUhXrUcq8X26rfLjYemGHJ/J/G90W/W9xx6Do4lMzgGep7sMqZ1w==", "dev": true, "requires": { "sql.js": "^1.8.0" } }, "@abaplint/runtime": { - "version": "2.7.14", - "resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.7.14.tgz", - "integrity": "sha512-ZUN6c4xkKgSoi0RALF8/HvgyYiOiF7ISEQyehz/8jhAq7qbxR9kzcrQzidVnNLlsMTqwVFH3XxsiL2ZWtV0CoQ==", + "version": "2.7.55", + "resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.7.55.tgz", + "integrity": "sha512-bNQ4nexrF2oLQ3d8baj8rSn6s1V19RqimF4sPwBawnUH9jAXb99zxysYFEqMf/R6aTmPUjnPgB9PLnYPPJ6FoA==", "dev": true, "requires": { "temporal-polyfill": "^0.1.1" } }, "@abaplint/transpiler-cli": { - "version": "2.7.14", - "resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.7.14.tgz", - "integrity": "sha512-oAXu0K95RfELbqPcF1YJZWMk/ZdmHlkG8osfRfqqdN0LOxvvdZuMC/eVw16el7P6u5TDlqBL+sJq6sxkvxL72w==", + "version": "2.7.55", + "resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.7.55.tgz", + "integrity": "sha512-tgSib6t6TnHsQfmm0a6wLoF0vdpw9nyq24laZMXGNWXADN4442kj5/6NUYo8CJ/0gxqK94P3lQwem0ZkQIZSVA==", "dev": true }, "sql.js": { diff --git a/package.json b/package.json index c5643f50..dfb54f0e 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,9 @@ }, "homepage": "https://github.com/abap2UI5/abap2UI5#readme", "devDependencies": { - "@abaplint/cli": "^2.101.6", - "@abaplint/database-sqlite": "^2.7.13", - "@abaplint/runtime": "^2.7.14", - "@abaplint/transpiler-cli": "^2.7.14" + "@abaplint/cli": "^2.102.11", + "@abaplint/database-sqlite": "^2.7.18", + "@abaplint/runtime": "^2.7.55", + "@abaplint/transpiler-cli": "^2.7.55" } } diff --git a/src/00/package.devc.xml b/src/00/package.devc.xml new file mode 100644 index 00000000..b6b25636 --- /dev/null +++ b/src/00/package.devc.xml @@ -0,0 +1,11 @@ + + + + + + abap2UI5 internal + X + + + + diff --git a/src/00/z2ui5_cl_fw_app.clas.abap b/src/00/z2ui5_cl_fw_app.clas.abap new file mode 100644 index 00000000..29b5464a --- /dev/null +++ b/src/00/z2ui5_cl_fw_app.clas.abap @@ -0,0 +1,251 @@ +CLASS z2ui5_cl_fw_app DEFINITION + PUBLIC + FINAL + CREATE PROTECTED. + + PUBLIC SECTION. + + INTERFACES z2ui5_if_app. + + DATA: + BEGIN OF ms_home, + btn_text TYPE string, + btn_event_id TYPE string, + btn_icon TYPE string, + classname TYPE string, + class_value_state TYPE string, + class_value_state_text TYPE string, + class_editable TYPE abap_bool VALUE abap_true, + END OF ms_home. + + CLASS-METHODS factory_start + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_app. + + CLASS-METHODS factory_error + IMPORTING + error TYPE REF TO cx_root + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_app. + + DATA client TYPE REF TO z2ui5_if_client. + DATA mv_check_initialized TYPE abap_bool. + DATA mv_check_demo TYPE abap_bool. + DATA mx_error TYPE REF TO cx_root. + + METHODS z2ui5_on_init. + METHODS z2ui5_on_event. + METHODS view_display_error. + METHODS view_display_start. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. + + + +CLASS Z2UI5_CL_FW_APP IMPLEMENTATION. + + + METHOD factory_error. + + result = NEW #( ). + result->mx_error = error. + + ENDMETHOD. + + + METHOD factory_start. + + result = NEW #( ). + + ENDMETHOD. + + + METHOD view_display_error. + + DATA(lv_url) = shift_left( val = client->get( )-s_config-origin && client->get( )-s_config-pathname + sub = ` ` ). + DATA(lv_url_app) = lv_url && client->get( )-s_config-search. + + DATA(view) = z2ui5_cl_xml_view=>factory( client )->shell( )->illustrated_message( + enableformattedtext = abap_true + illustrationtype = 'sapIllus-ErrorScreen' + title = '500 Internal Server Error' + description = mx_error->get_text( ) + )->additional_content( + )->button( + text = 'Home' + type = 'Emphasized' + press = client->_event_client( action = client->cs_event-location_reload t_arg = VALUE #( ( lv_url ) ) ) + )->button( + text = 'Restart' + press = client->_event_client( action = client->cs_event-location_reload t_arg = VALUE #( ( lv_url_app ) ) ) ). + + client->view_display( view->stringify( ) ). + + ENDMETHOD. + + + METHOD view_display_start. + + DATA(lv_url) = z2ui5_cl_xml_view=>factory( client )->hlp_get_app_url( ms_home-classname ). + + DATA(page) = z2ui5_cl_xml_view=>factory( client )->shell( + )->page( shownavbutton = abap_false ). + + page->header_content( + )->title( `abap2UI5 - Developing UI5 Apps in pure ABAP` + )->toolbar_spacer( + )->link( text = `SCN` + target = `_blank` + href = `https://blogs.sap.com/tag/abap2ui5/` + )->link( text = `Twitter` + target = `_blank` + href = `https://twitter.com/abap2UI5` + )->link( text = `GitHub` + target = `_blank` + href = `https://github.com/abap2ui5/abap2ui5` ). + + DATA(grid) = page->grid( `XL7 L7 M12 S12` + )->content( `layout` ). + DATA(content) = grid->simple_form( title = `Quickstart` + layout = `ResponsiveGridLayout` + editable = `true` + )->content( `form` ). + + content->label( `Step 1` + )->text( `Create a global class in your abap system` + )->label( `Step 2` + )->text( `Add the interface: Z2UI5_IF_APP` + )->label( `Step 3` + )->text( `Define view, implement behaviour` + )->link( text = `(Example)` + target = `_blank` + href = `https://github.com/abap2ui5/ABAP2UI5/blob/main/src/z2ui5_cl_app_hello_world.clas.abap` + )->label( `Step 4` ). + + IF ms_home-class_editable = abap_true. + + content->input( placeholder = `fill in the class name and press 'check'` + editable = z2ui5_cl_fw_utility=>get_json_boolean( ms_home-class_editable ) + value = client->_bind_edit( ms_home-classname ) ). + + ELSE. + content->text( ms_home-classname ). + ENDIF. + + content->button( press = client->_event( ms_home-btn_event_id ) + text = ms_home-btn_text + icon = ms_home-btn_icon + )->label( `Step 5` + )->link( text = `Link to the Application` + target = `_blank` + href = lv_url + enabled = z2ui5_cl_fw_utility=>get_json_boolean( xsdbool( ms_home-class_editable = abap_false ) ) ). + + DATA(form) = grid->simple_form( title = `Samples` + editable = abap_true + layout = 'ResponsiveGridLayout' ). + + IF mv_check_demo = abap_false. + form->message_strip( text = 'Oops! You need to install abap2UI5 demos before continuing...' + type = 'Warning' + )->get( )->_generic( 'link' )->link( text = `(HERE)` + target = '_blank' + href = `https://github.com/oblomov-dev/abap2UI5-demos` ). + ENDIF. + + form->content( `form` )->label( )->button( + text = 'Continue...' + press = client->_event( val = `DEMOS` check_view_destroy = abap_true ) + enabled = xsdbool( mv_check_demo = abap_true ) + )->button( visible = abap_false )->link( text = 'More on GitHub...' + target = '_blank' + href = 'https://github.com/abap2UI5/abap2UI5-documentation/blob/main/docs/links.md' ). + + client->view_display( form->stringify( ) ). + + ENDMETHOD. + + + METHOD z2ui5_if_app~main. + + me->client = client. + + IF mv_check_initialized = abap_false. + mv_check_initialized = abap_true. + z2ui5_on_init( ). + ENDIF. + + z2ui5_on_event( ). + + IF mx_error IS BOUND. + view_display_error( ). + ELSE. + view_display_start( ). + ENDIF. + + ENDMETHOD. + + + METHOD z2ui5_on_event. + + CASE client->get( )-event. + + WHEN `BUTTON_CHANGE`. + ms_home-btn_text = `check`. + ms_home-btn_event_id = `BUTTON_CHECK`. + ms_home-btn_icon = `sap-icon://validate`. + ms_home-class_editable = abap_true. + + WHEN `BUTTON_CHECK`. + TRY. + DATA li_app_test TYPE REF TO z2ui5_if_app. + ms_home-classname = z2ui5_cl_fw_utility=>get_trim_upper( ms_home-classname ). + CREATE OBJECT li_app_test TYPE (ms_home-classname). + + client->message_toast_display( `App is ready to start!` ). + ms_home-btn_text = `edit`. + ms_home-btn_event_id = `BUTTON_CHANGE`. + ms_home-btn_icon = `sap-icon://edit`. + ms_home-class_value_state = `Success`. + ms_home-class_editable = abap_false. + + CATCH cx_root INTO DATA(lx) ##CATCH_ALL. + ms_home-class_value_state_text = lx->get_text( ). + ms_home-class_value_state = `Warning`. + client->message_box_display( text = ms_home-class_value_state_text + type = `error` ). + ENDTRY. + + WHEN `DEMOS`. + + DATA li_app TYPE REF TO z2ui5_if_app. + TRY. + CREATE OBJECT li_app TYPE (`Z2UI5_CL_APP_DEMO_00`). + mv_check_demo = abap_true. + client->nav_app_call( li_app ). + CATCH cx_root. + mv_check_demo = abap_false. + ENDTRY. + + ENDCASE. + + ENDMETHOD. + + + METHOD z2ui5_on_init. + + IF mx_error IS NOT BOUND. + ms_home-btn_text = `check`. + ms_home-btn_event_id = `BUTTON_CHECK`. + ms_home-class_editable = abap_true. + ms_home-btn_icon = `sap-icon://validate`. + ms_home-classname = `z2ui5_cl_app_hello_world`. + ENDIF. + + mv_check_demo = abap_true. + + ENDMETHOD. +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_app.clas.xml b/src/00/z2ui5_cl_fw_app.clas.xml new file mode 100644 index 00000000..4b651084 --- /dev/null +++ b/src/00/z2ui5_cl_fw_app.clas.xml @@ -0,0 +1,16 @@ + + + + + + Z2UI5_CL_FW_APP + E + abap2UI5 - framework app + 1 + X + X + X + + + + diff --git a/src/00/z2ui5_cl_fw_client.clas.abap b/src/00/z2ui5_cl_fw_client.clas.abap new file mode 100644 index 00000000..90044a88 --- /dev/null +++ b/src/00/z2ui5_cl_fw_client.clas.abap @@ -0,0 +1,254 @@ +CLASS z2ui5_cl_fw_client DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + INTERFACES z2ui5_if_client. + + DATA mo_handler TYPE REF TO z2ui5_cl_fw_handler. + + METHODS constructor + IMPORTING + handler TYPE REF TO z2ui5_cl_fw_handler. + +ENDCLASS. + + + +CLASS Z2UI5_CL_FW_CLIENT IMPLEMENTATION. + + + METHOD constructor. + + mo_handler = handler. + + ENDMETHOD. + + + METHOD z2ui5_if_client~cursor_set. + + mo_handler->ms_next-s_set-s_cursor = VALUE #( + id = id + cursorpos = cursorpos + selectionend = selectionend + selectionstart = selectionstart ). + + ENDMETHOD. + + + METHOD z2ui5_if_client~get. + + result = VALUE #( + event = mo_handler->ms_actual-event + check_launchpad_active = mo_handler->ms_actual-check_launchpad_active + t_event_arg = mo_handler->ms_actual-t_event_arg + t_scroll_pos = mo_handler->ms_actual-t_scroll_pos + s_draft = CORRESPONDING #( mo_handler->ms_db ) + check_on_navigated = mo_handler->ms_actual-check_on_navigated + s_config = z2ui5_cl_fw_handler=>ss_config ). + + ENDMETHOD. + + + METHOD z2ui5_if_client~get_app. + result = CAST #( z2ui5_cl_fw_db=>load_app( id )-app ). + ENDMETHOD. + + + METHOD z2ui5_if_client~message_box_display. + + mo_handler->ms_next-s_set-s_msg_box = VALUE #( text = text type = type ). + + ENDMETHOD. + + + METHOD z2ui5_if_client~message_toast_display. + + mo_handler->ms_next-s_set-s_msg_toast = VALUE #( text = text ). + + ENDMETHOD. + + + METHOD z2ui5_if_client~nav_app_call. + mo_handler->ms_next-o_app_call = app. + ENDMETHOD. + + + METHOD z2ui5_if_client~nav_app_leave. + mo_handler->ms_next-o_app_leave = app. + ENDMETHOD. + + + METHOD z2ui5_if_client~nest_view_destroy. + + mo_handler->ms_next-s_set-s_view_nest-check_update_model = abap_true. + + ENDMETHOD. + + + METHOD z2ui5_if_client~nest_view_display. + + mo_handler->ms_next-s_set-s_view_nest-xml = val. + mo_handler->ms_next-s_set-s_view_nest-id = id. + mo_handler->ms_next-s_set-s_view_nest-method_destroy = method_destroy. + mo_handler->ms_next-s_set-s_view_nest-method_insert = method_insert. + + ENDMETHOD. + + + METHOD z2ui5_if_client~nest_view_model_update. + + mo_handler->ms_next-s_set-s_view_nest-check_update_model = abap_true. + + ENDMETHOD. + + + METHOD z2ui5_if_client~popover_destroy. + + mo_handler->ms_next-s_set-s_popover-check_destroy = abap_true. + + ENDMETHOD. + + + METHOD z2ui5_if_client~popover_display. + + mo_handler->ms_next-s_set-s_popover-check_destroy = abap_false. + mo_handler->ms_next-s_set-s_popover-xml = xml. + mo_handler->ms_next-s_set-s_popover-open_by_id = by_id. + + ENDMETHOD. + + + METHOD z2ui5_if_client~popover_model_update. + + mo_handler->ms_next-s_set-s_popover-check_update_model = abap_true. + + ENDMETHOD. + + + METHOD z2ui5_if_client~popup_destroy. + + mo_handler->ms_next-s_set-s_popup-check_destroy = abap_true. + + ENDMETHOD. + + + METHOD z2ui5_if_client~popup_display. + + mo_handler->ms_next-s_set-s_popup-check_destroy = abap_false. + mo_handler->ms_next-s_set-s_popup-xml = val. + + ENDMETHOD. + + + METHOD z2ui5_if_client~popup_model_update. + + mo_handler->ms_next-s_set-s_popup-check_update_model = abap_true. + + ENDMETHOD. + + + METHOD z2ui5_if_client~scroll_position_set. + + mo_handler->ms_next-s_set-t_scroll = val. + + ENDMETHOD. + + + METHOD z2ui5_if_client~timer_set. + + mo_handler->ms_next-s_set-s_timer-interval_ms = interval_ms. + mo_handler->ms_next-s_set-s_timer-event_finished = event_finished. + + ENDMETHOD. + + + METHOD z2ui5_if_client~url_param_set. + + mo_handler->ms_next-s_set-search = val. + mo_handler->ms_actual-s_config-search = val. + + ENDMETHOD. + + + METHOD z2ui5_if_client~view_destroy. + + mo_handler->ms_next-s_set-s_view-check_destroy = abap_true. + + ENDMETHOD. + + + METHOD z2ui5_if_client~view_display. + + mo_handler->ms_next-s_set-s_view-xml = val. + + ENDMETHOD. + + + METHOD z2ui5_if_client~view_model_update. + + mo_handler->ms_next-s_set-s_view-check_update_model = abap_true. + + ENDMETHOD. + + + METHOD z2ui5_if_client~_bind. + + result = mo_handler->_create_binding( value = val + type = z2ui5_cl_fw_handler=>cs_bind_type-one_way ). + + IF path = abap_false. + result = `{` && result && `}`. + ENDIF. + + ENDMETHOD. + + + METHOD z2ui5_if_client~_bind_edit. + + result = mo_handler->_create_binding( value = val + type = z2ui5_cl_fw_handler=>cs_bind_type-two_way ). + + IF path = abap_false. + result = `{` && result && `}`. + ENDIF. + + ENDMETHOD. + + + METHOD z2ui5_if_client~_event. + + result = `onEvent( { 'EVENT' : '` && val && `', 'METHOD' : 'UPDATE' , 'CHECK_VIEW_DESTROY' : ` && z2ui5_cl_fw_utility=>get_json_boolean( check_view_destroy ) && ` }`. + + LOOP AT t_arg REFERENCE INTO DATA(lr_arg). + result = result && `, ` && lr_arg->*. + ENDLOOP. + + result = result && ` )`. + + ENDMETHOD. + + + METHOD z2ui5_if_client~_event_client. + + result = `onEventFrontend( { 'EVENT' : '` && action && `'`. + + IF t_arg IS NOT INITIAL. + result = result && `, 'T_ARG' : [`. + + LOOP AT t_arg REFERENCE INTO DATA(lr_arg). + IF sy-tabix <> 1. + result = result && `,`. + ENDIF. + result = result && `'` && lr_arg->* && `'`. + ENDLOOP. + + result = result && `]`. + ENDIF. + + result = result && `})`. + + ENDMETHOD. +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_client.clas.testclasses.abap b/src/00/z2ui5_cl_fw_client.clas.testclasses.abap new file mode 100644 index 00000000..f183ec51 --- /dev/null +++ b/src/00/z2ui5_cl_fw_client.clas.testclasses.abap @@ -0,0 +1,22 @@ +CLASS ltcl_unit_test DEFINITION FINAL FOR TESTING + DURATION SHORT + RISK LEVEL critical. + + PRIVATE SECTION. + METHODS first_test FOR TESTING RAISING cx_static_check. +ENDCLASS. + + +CLASS ltcl_unit_test IMPLEMENTATION. + + METHOD first_test. + + DATA(lo_handler) = NEW z2ui5_cl_fw_handler( ). + DATA(lo_client) = NEW z2ui5_cl_fw_client( lo_handler ). + + DATA(li_client) = CAST z2ui5_if_client( lo_client ) ##NEEDED. + + + ENDMETHOD. + +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_client.clas.xml b/src/00/z2ui5_cl_fw_client.clas.xml new file mode 100644 index 00000000..809605c4 --- /dev/null +++ b/src/00/z2ui5_cl_fw_client.clas.xml @@ -0,0 +1,17 @@ + + + + + + Z2UI5_CL_FW_CLIENT + E + abap2UI5 - client + 1 + X + X + X + X + + + + diff --git a/src/00/z2ui5_cl_fw_db.clas.abap b/src/00/z2ui5_cl_fw_db.clas.abap new file mode 100644 index 00000000..57d63292 --- /dev/null +++ b/src/00/z2ui5_cl_fw_db.clas.abap @@ -0,0 +1,170 @@ +CLASS z2ui5_cl_fw_db DEFINITION + PUBLIC + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_s_db, + id TYPE string, + id_prev TYPE string, + id_prev_app TYPE string, + id_prev_app_stack TYPE string, + t_attri TYPE z2ui5_cl_fw_utility=>ty_t_attri, + app TYPE REF TO z2ui5_if_app, + END OF ty_s_db. + + CLASS-METHODS create + IMPORTING + id TYPE string + db TYPE ty_s_db. + + CLASS-METHODS load_app + IMPORTING + id TYPE clike + RETURNING + VALUE(result) TYPE ty_s_db. + + CLASS-METHODS read + IMPORTING + id TYPE clike + check_load_app TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(result) TYPE z2ui5_t_draft. + + CLASS-METHODS cleanup. + +ENDCLASS. + + + +CLASS Z2UI5_CL_FW_DB IMPLEMENTATION. + + + METHOD cleanup. + + DATA(lv_time) = z2ui5_cl_fw_utility=>get_timestampl( ). + DATA(lv_four_hours_ago) = cl_abap_tstmp=>subtractsecs( tstmp = lv_time + secs = 60 * 60 * 4 ). + + DELETE FROM z2ui5_t_draft WHERE timestampl < @lv_four_hours_ago. + COMMIT WORK. + + ENDMETHOD. + + + METHOD create. + + TRY. + DATA(lv_xml) = z2ui5_cl_fw_utility=>trans_object_2_xml( REF #( db ) ). + + CATCH cx_xslt_serialization_error INTO DATA(x). + TRY. + + DATA(ls_db) = db. + DATA(lo_app) = CAST object( ls_db-app ). + + IF NOT line_exists( ls_db-t_attri[ check_ref_data = abap_true ] ). + RAISE EXCEPTION x. + ENDIF. + + lo_app = CAST object( ls_db-app ). + LOOP AT ls_db-t_attri REFERENCE INTO DATA(lr_attri) WHERE check_ref_data = abap_true. + + DATA(lv_assign) = 'LO_APP->' && lr_attri->name. + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + ASSIGN (lv_assign) TO . + ASSIGN ->* TO . + + lr_attri->data_rtti = z2ui5_cl_fw_utility=>rtti_get( ). + CLEAR . + CLEAR . + + ENDLOOP. + + lv_xml = z2ui5_cl_fw_utility=>trans_object_2_xml( REF #( ls_db ) ). + + CATCH cx_root INTO DATA(x2). + + RAISE EXCEPTION TYPE z2ui5_cl_fw_error + EXPORTING + val = x->get_text( ) && `

` && x->previous->get_text( ) && `

` && x2->get_text( ). + + ENDTRY. + ENDTRY. + + DATA(ls_draft) = VALUE z2ui5_t_draft( uuid = id + uuid_prev = db-id_prev + uuid_prev_app = db-id_prev_app + uuid_prev_app_stack = db-id_prev_app_stack + uname = z2ui5_cl_fw_utility=>get_user_tech( ) + timestampl = z2ui5_cl_fw_utility=>get_timestampl( ) + data = lv_xml ). + + MODIFY z2ui5_t_draft FROM @ls_draft. + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + COMMIT WORK AND WAIT. + + ENDMETHOD. + + + METHOD load_app. + + DATA(ls_db) = read( id ). + + z2ui5_cl_fw_utility=>trans_xml_2_object( + EXPORTING + xml = ls_db-data + IMPORTING + data = result ). + + LOOP AT result-t_attri TRANSPORTING NO FIELDS WHERE data_rtti <> ``. + DATA(lv_check_rtti) = abap_true. + ENDLOOP. + IF lv_check_rtti = abap_false. + RETURN. + ENDIF. + + DATA(lo_app) = CAST object( result-app ) ##NEEDED. + LOOP AT result-t_attri REFERENCE INTO DATA(lr_attri) WHERE check_ref_data = abap_true. + + FIELD-SYMBOLS TYPE any. + DATA(lv_assign) = 'LO_APP->' && lr_attri->name. + ASSIGN (lv_assign) TO . + + z2ui5_cl_fw_utility=>rtti_set( + EXPORTING + rtti_data = lr_attri->data_rtti + IMPORTING + e_data = ). + + CLEAR lr_attri->data_rtti. + ENDLOOP. + + ENDMETHOD. + + + METHOD read. + + IF check_load_app = abap_true. + + SELECT SINGLE * + FROM z2ui5_t_draft + WHERE uuid = @id + INTO @result. + + ELSE. + + SELECT SINGLE uuid, uuid_prev, uuid_prev_app, uuid_prev_app_stack + FROM z2ui5_t_draft + WHERE uuid = @id + INTO CORRESPONDING FIELDS OF @result. + + ENDIF. + + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + + ENDMETHOD. +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_db.clas.xml b/src/00/z2ui5_cl_fw_db.clas.xml new file mode 100644 index 00000000..f14b3456 --- /dev/null +++ b/src/00/z2ui5_cl_fw_db.clas.xml @@ -0,0 +1,16 @@ + + + + + + Z2UI5_CL_FW_DB + E + abap2UI5 - database + 1 + X + X + X + + + + diff --git a/src/00/z2ui5_cl_fw_error.clas.abap b/src/00/z2ui5_cl_fw_error.clas.abap new file mode 100644 index 00000000..8d92fc76 --- /dev/null +++ b/src/00/z2ui5_cl_fw_error.clas.abap @@ -0,0 +1,62 @@ +CLASS z2ui5_cl_fw_error DEFINITION INHERITING FROM cx_no_check + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + DATA: + BEGIN OF ms_error, + x_root TYPE REF TO cx_root, + uuid TYPE string, + text TYPE string, + END OF ms_error. + + METHODS get_text REDEFINITION. + + METHODS constructor + IMPORTING + val TYPE any OPTIONAL + previous TYPE REF TO cx_root OPTIONAL + PREFERRED PARAMETER val. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. + + + +CLASS z2ui5_cl_fw_error IMPLEMENTATION. + + + METHOD constructor ##ADT_SUPPRESS_GENERATION. + + super->constructor( previous = previous ). + CLEAR textid. + + TRY. + ms_error-x_root ?= val. + CATCH cx_root. + ms_error-text = val. + ENDTRY. + ms_error-uuid = z2ui5_cl_fw_utility=>get_uuid( ). + + ENDMETHOD. + + + METHOD get_text. + + IF ms_error-x_root IS NOT INITIAL. + result = ms_error-x_root->get_text( ). + DATA(error) = abap_true. + ELSEIF ms_error-text IS NOT INITIAL. + result = ms_error-text. + error = abap_true. + ENDIF. + + result = COND #( WHEN error = abap_true AND result IS INITIAL THEN `unknown error` else result ). + + ENDMETHOD. + + +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_error.clas.xml b/src/00/z2ui5_cl_fw_error.clas.xml new file mode 100644 index 00000000..1e8acc35 --- /dev/null +++ b/src/00/z2ui5_cl_fw_error.clas.xml @@ -0,0 +1,17 @@ + + + + + + Z2UI5_CL_FW_ERROR + E + abap2UI5 - error + 40 + 1 + X + X + X + + + + diff --git a/src/00/z2ui5_cl_fw_handler.clas.abap b/src/00/z2ui5_cl_fw_handler.clas.abap new file mode 100644 index 00000000..71022d4b --- /dev/null +++ b/src/00/z2ui5_cl_fw_handler.clas.abap @@ -0,0 +1,563 @@ +CLASS z2ui5_cl_fw_handler DEFINITION + PUBLIC + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + + CONSTANTS: + BEGIN OF cs_bind_type, + one_way TYPE string VALUE 'ONE_WAY', + two_way TYPE string VALUE 'TWO_WAY', + one_time TYPE string VALUE 'ONE_TIME', + END OF cs_bind_type. + + TYPES: + BEGIN OF ty_s_next2, + t_scroll TYPE z2ui5_if_client=>ty_t_name_value, + title TYPE string, + search TYPE string, + BEGIN OF s_view, + xml TYPE string, + check_destroy TYPE abap_bool, + check_update_model TYPE abap_bool, + END OF s_view, + BEGIN OF s_view_nest, + xml TYPE string, + id TYPE string, + method_insert TYPE string, + method_destroy TYPE string, + check_destroy TYPE abap_bool, + check_update_model TYPE abap_bool, + END OF s_view_nest, + BEGIN OF s_popup, + xml TYPE string, + id TYPE string, + check_destroy TYPE abap_bool, + check_update_model TYPE abap_bool, + END OF s_popup, + BEGIN OF s_popover, + xml TYPE string, + id TYPE string, + open_by_id TYPE string, + check_destroy TYPE abap_bool, + check_update_model TYPE abap_bool, + END OF s_popover, + BEGIN OF s_cursor, + id TYPE string, + cursorpos TYPE string, + selectionstart TYPE string, + selectionend TYPE string, + END OF s_cursor, + BEGIN OF s_timer, + interval_ms TYPE string, + event_finished TYPE string, + action_finished TYPE string, + END OF s_timer, + BEGIN OF s_msg_box, + type TYPE string, + text TYPE string, + END OF s_msg_box, + BEGIN OF s_msg_toast, + text TYPE string, + END OF s_msg_toast, + _viewmodel TYPE string, + END OF ty_s_next2. + + TYPES: + BEGIN OF ty_s_next, + o_app_call TYPE REF TO z2ui5_if_app, + o_app_leave TYPE REF TO z2ui5_if_app, + s_set TYPE ty_s_next2, + END OF ty_s_next. + + CLASS-DATA ss_config TYPE z2ui5_if_client=>ty_s_config. + CLASS-DATA so_body TYPE REF TO z2ui5_cl_fw_utility_json. + + DATA ms_db TYPE z2ui5_cl_fw_db=>ty_s_db. + DATA ms_actual TYPE z2ui5_if_client=>ty_s_get. + DATA ms_next TYPE ty_s_next. + + CLASS-METHODS request_begin + IMPORTING + body TYPE string + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_handler. + + METHODS request_end + RETURNING + VALUE(result) TYPE string. + + METHODS _create_binding + IMPORTING + value TYPE data + type TYPE string DEFAULT cs_bind_type-two_way + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS set_app_start + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_handler. + + CLASS-METHODS set_app_client + IMPORTING + id_prev TYPE clike + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_handler. + + METHODS set_app_leave + IMPORTING + check_no_db_save TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_handler. + + METHODS set_app_call + IMPORTING + check_no_db_save TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_handler. + + CLASS-METHODS set_app_system + IMPORTING + VALUE(ix) TYPE REF TO cx_root OPTIONAL + error_text TYPE string OPTIONAL + PREFERRED PARAMETER ix + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_handler. + + CLASS-METHODS model_set_backend + IMPORTING + model TYPE REF TO data + app TYPE REF TO object + t_attri TYPE z2ui5_cl_fw_utility=>ty_t_attri. + + CLASS-METHODS model_set_frontend + IMPORTING + app TYPE REF TO object + t_attri TYPE z2ui5_cl_fw_utility=>ty_t_attri + RETURNING + VALUE(result) TYPE string. + + METHODS app_set_next + IMPORTING + app TYPE REF TO z2ui5_if_app + RETURNING + VALUE(r_result) TYPE REF TO z2ui5_cl_fw_handler. + +ENDCLASS. + + + +CLASS Z2UI5_CL_FW_HANDLER IMPLEMENTATION. + + + METHOD app_set_next. + + app->id = COND #( WHEN app->id IS INITIAL THEN z2ui5_cl_fw_utility=>get_uuid( ) ELSE app->id ). + + r_result = NEW #( ). + r_result->ms_db-app = app. + r_result->ms_db-id = app->id. + r_result->ms_db-id_prev = ms_db-id. + r_result->ms_db-id_prev_app = ms_db-id. + r_result->ms_db-t_attri = z2ui5_cl_fw_utility=>get_t_attri_by_ref( app ). + r_result->ms_actual-check_launchpad_active = ms_actual-check_launchpad_active. + r_result->ms_actual-check_on_navigated = abap_true. + r_result->ms_next-s_set = ms_next-s_set. + + ENDMETHOD. + + + METHOD model_set_backend. + + DATA(lo_app) = CAST object( app ) ##NEEDED. + DATA(lr_model) = CAST data( model ) ##NEEDED. + + LOOP AT t_attri REFERENCE INTO DATA(lr_attri) WHERE bind_type = cs_bind_type-two_way. + TRY. + DATA(lv_type_kind) = lr_attri->type_kind. + + FIELD-SYMBOLS TYPE any. + DATA(lv_name) = `LO_APP->` && lr_attri->name. + ASSIGN (lv_name) TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + + FIELD-SYMBOLS TYPE any. + lv_name = `LR_MODEL->` && replace( val = lr_attri->name + sub = `-` + with = `_` + occ = 0 ). + ASSIGN (lv_name) TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + + IF lr_attri->check_ref_data IS NOT INITIAL. + ASSIGN ->* TO . + TRY. + DATA(lo_tab) = CAST cl_abap_tabledescr( cl_abap_datadescr=>describe_by_data( ) ) ##NEEDED. + lv_type_kind = `h`. + CATCH cx_root. + ENDTRY. + ENDIF. + + CASE lv_type_kind. + + WHEN `h`. + z2ui5_cl_fw_utility=>trans_ref_tab_2_tab( + EXPORTING + ir_tab_from = + IMPORTING + t_result = ). + + WHEN OTHERS. + + ASSIGN ->* TO . + CASE lr_attri->type_kind. + WHEN 'D' OR 'T'. + /ui2/cl_json=>deserialize( + EXPORTING + json = `"` && && `"` + CHANGING + data = ). + WHEN OTHERS. + = . + ENDCASE. + + ENDCASE. + + CATCH cx_root. + ENDTRY. + ENDLOOP. + + ENDMETHOD. + + + METHOD model_set_frontend. + + DATA(lo_app) = CAST object( app ) ##NEEDED. + DATA(lr_view_model) = z2ui5_cl_fw_utility_json=>factory( ). + DATA(lo_update) = lr_view_model->add_attribute_object( ss_config-view_model_edit_name ). + + LOOP AT t_attri REFERENCE INTO DATA(lr_attri) WHERE bind_type <> ``. + + IF lr_attri->bind_type = cs_bind_type-one_time. + lr_view_model->add_attribute( n = lr_attri->name + v = lr_attri->data_stringify + apos_active = abap_false ). + CONTINUE. + ENDIF. + + DATA(lo_actual) = COND #( WHEN lr_attri->bind_type = cs_bind_type-one_way + THEN lr_view_model + ELSE lo_update ). + + FIELD-SYMBOLS TYPE any. + DATA(lv_name) = `LO_APP->` && to_upper( lr_attri->name ). + ASSIGN (lv_name) TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + + CASE lr_attri->type_kind. + + WHEN `h`. + lo_actual->add_attribute( n = lr_attri->name + v = z2ui5_cl_fw_utility=>trans_any_2_json( ) + apos_active = abap_false ). + + WHEN OTHERS. + + CASE lr_attri->type. + + WHEN `ABAP_BOOL` OR `ABAP_BOOLEAN` OR `XSDBOOLEAN`. + + lo_actual->add_attribute( n = lr_attri->name + v = SWITCH #( + WHEN abap_true THEN `true` ELSE `false` ) + apos_active = abap_false ). + + WHEN OTHERS. + + lo_actual->add_attribute( n = lr_attri->name + v = /ui2/cl_json=>serialize( ) + apos_active = abap_false ). + ENDCASE. + ENDCASE. + ENDLOOP. + + result = lr_view_model->stringify( ). + + ENDMETHOD. + + + METHOD request_begin. + + so_body = z2ui5_cl_fw_utility_json=>factory( body ). + + TRY. + DATA(location) = so_body->get_attribute( `OLOCATION` ). + ss_config-body = body. + ss_config-search = location->get_attribute( `SEARCH` )->get_val( ). + ss_config-origin = location->get_attribute( `ORIGIN` )->get_val( ). + ss_config-pathname = location->get_attribute( `PATHNAME` )->get_val( ). + ss_config-version = location->get_attribute( `VERSION` )->get_val( ). + CATCH cx_root. + ENDTRY. + ss_config-view_model_edit_name = `oUpdate`. + + TRY. + DATA(lv_id_prev) = so_body->get_attribute( `ID` )->get_val( ). + result = set_app_client( lv_id_prev ). + result->ms_actual-check_on_navigated = abap_false. + CATCH cx_root. + result = set_app_start( ). + result->ms_actual-check_on_navigated = abap_true. + ENDTRY. + + TRY. + + FIELD-SYMBOLS TYPE any. + ASSIGN ('SO_BODY->MR_ACTUAL') TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + ASSIGN ('->ARGUMENTS') TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + ASSIGN ('->*') TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + + FIELD-SYMBOLS TYPE STANDARD TABLE. + ASSIGN TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + + FIELD-SYMBOLS TYPE any. + LOOP AT ASSIGNING . + + IF sy-tabix = 1. + FIELD-SYMBOLS TYPE any. + ASSIGN ('->EVENT->*') TO . + result->ms_actual-event = . + ELSE. + ASSIGN ->* TO . + INSERT INTO TABLE result->ms_actual-t_event_arg. + ENDIF. + + ENDLOOP. + CATCH cx_root. + ENDTRY. + + TRY. + DATA(lo_scroll) = so_body->get_attribute( `OSCROLL` ). + z2ui5_cl_fw_utility=>trans_ref_tab_2_tab( + EXPORTING + ir_tab_from = lo_scroll->mr_actual + IMPORTING + t_result = result->ms_actual-t_scroll_pos ). + CATCH cx_root. + ENDTRY. + + TRY. + DATA(lo_cursor) = so_body->get_attribute( `OCURSOR` ). + result->ms_actual-s_cursor-id = lo_cursor->get_attribute( `ID` )->get_val( ). + + CATCH cx_root. + ENDTRY. + + IF ss_config-search CS `scenario=LAUNCHPAD`. + result->ms_actual-check_launchpad_active = abap_true. + ENDIF. + + ENDMETHOD. + + + METHOD request_end. + + DATA(lo_resp) = z2ui5_cl_fw_utility_json=>factory( ). + + DATA(lv_viewmodel) = COND #( WHEN ms_next-s_set-_viewmodel IS NOT INITIAL + THEN ms_next-s_set-_viewmodel + ELSE model_set_frontend( app = ms_db-app + t_attri = ms_db-t_attri ) ). + + lo_resp->add_attribute( n = `OVIEWMODEL` + v = lv_viewmodel + apos_active = abap_false ). + lo_resp->add_attribute( n = `PARAMS` + v = z2ui5_cl_fw_utility=>trans_any_2_json( ms_next-s_set ) + apos_active = abap_false ). + lo_resp->add_attribute( n = `ID` + v = ms_db-id ). + + IF ms_next-s_set-search IS INITIAL. + lo_resp->add_attribute( n = `SEARCH` + v = ms_actual-s_config-search ). + ELSE. + lo_resp->add_attribute( n = `SEARCH` + v = ms_next-s_set-search ). + ENDIF. + + result = lo_resp->mo_root->stringify( ). + z2ui5_cl_fw_db=>create( id = ms_db-id + db = ms_db ). + + ENDMETHOD. + + + METHOD set_app_call. + + result = app_set_next( ms_next-o_app_call ). + result->ms_db-id_prev_app_stack = ms_db-id. + + CLEAR ms_next. + IF check_no_db_save = abap_false. + z2ui5_cl_fw_db=>create( id = ms_db-id + db = ms_db ). + ENDIF. + + ENDMETHOD. + + + METHOD set_app_client. + + result = NEW #( ). + result->ms_db = z2ui5_cl_fw_db=>load_app( id_prev ). + result->ms_db-id = z2ui5_cl_fw_utility=>get_uuid( ). + result->ms_db-id_prev = id_prev. + + TRY. + model_set_backend( model = so_body->get_attribute( ss_config-view_model_edit_name )->mr_actual + app = result->ms_db-app + t_attri = result->ms_db-t_attri ). + CATCH cx_root. + ENDTRY. + + ENDMETHOD. + + + METHOD set_app_leave. + + result = app_set_next( ms_next-o_app_leave ). + + TRY. + DATA(ls_draft) = z2ui5_cl_fw_db=>read( id = result->ms_db-id + check_load_app = abap_false ). + result->ms_db-id_prev_app_stack = ls_draft-uuid_prev_app_stack. + CATCH cx_root. + result->ms_db-id_prev_app_stack = ms_db-id_prev_app_stack. + ENDTRY. + + CLEAR ms_next. + IF check_no_db_save = abap_false. + z2ui5_cl_fw_db=>create( id = ms_db-id + db = ms_db ). + ENDIF. + + ENDMETHOD. + + + METHOD set_app_start. + + TRY. + DATA(lv_classname) = to_upper( so_body->get_attribute( 'APP_START' )->get_val( ) ). + lv_classname = shift_left( val = lv_classname + sub = cl_abap_char_utilities=>horizontal_tab ). + lv_classname = shift_right( val = lv_classname + sub = cl_abap_char_utilities=>horizontal_tab ). + CATCH cx_root. + ENDTRY. + + IF lv_classname IS INITIAL. + lv_classname = z2ui5_cl_fw_utility=>url_param_get( val = `app_start` url = ss_config-search ). + ENDIF. + + IF lv_classname IS INITIAL. + result = set_app_system( ). + RETURN. + ENDIF. + + TRY. + result = NEW #( ). + result->ms_db-id = z2ui5_cl_fw_utility=>get_uuid( ). + + lv_classname = z2ui5_cl_fw_utility=>get_trim_upper( lv_classname ). + CREATE OBJECT result->ms_db-app TYPE (lv_classname). + result->ms_db-app->id = result->ms_db-id. + result->ms_db-t_attri = z2ui5_cl_fw_utility=>get_t_attri_by_ref( result->ms_db-app ). + + CATCH cx_root. + result = set_app_system( error_text = `App with name ` && lv_classname && ` not found...` ). + ENDTRY. + + ENDMETHOD. + + + METHOD set_app_system. + + result = NEW #( ). + result->ms_db-id = z2ui5_cl_fw_utility=>get_uuid( ). + + IF ix IS NOT BOUND AND error_text IS NOT INITIAL. + ix = NEW z2ui5_cl_fw_error( val = error_text ). + ENDIF. + + IF ix IS BOUND. + result->ms_next-o_app_call = z2ui5_cl_fw_app=>factory_error( ix ). + result = result->set_app_call( abap_true ). + RETURN. + ENDIF. + + result->ms_db-app = z2ui5_cl_fw_app=>factory_start( ). + result->ms_db-t_attri = z2ui5_cl_fw_utility=>get_t_attri_by_ref( result->ms_db-app ). + result->ms_db-app->id = result->ms_db-id. + + ENDMETHOD. + + + METHOD _create_binding. + + DATA(lo_app) = CAST object( ms_db-app ) ##NEEDED. + + DATA lr_in TYPE REF TO data. + GET REFERENCE OF value INTO lr_in. + + LOOP AT ms_db-t_attri REFERENCE INTO DATA(lr_attri) + WHERE bind_type <> cs_bind_type-one_time. + + FIELD-SYMBOLS TYPE any. + DATA(lv_name) = `LO_APP->` && to_upper( lr_attri->name ). + ASSIGN (lv_name) TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) + v = `Attribute in App with name ` && lv_name && ` not found` ). + DATA lr_ref TYPE REF TO data. + GET REFERENCE OF INTO lr_ref. + + IF lr_attri->check_ref_data IS NOT INITIAL. + FIELD-SYMBOLS TYPE any. + ASSIGN lr_ref->* TO . + lr_ref = CAST data( ). + ENDIF. + + IF lr_in = lr_ref. + IF lr_attri->bind_type IS NOT INITIAL AND lr_attri->bind_type <> type. + z2ui5_cl_fw_utility=>raise( + `

Binding Error - Two different binding types for same attribute used (` && lr_attri->name && `).` ). + ENDIF. + IF strlen( lr_attri->name ) > 30. + z2ui5_cl_fw_utility=>raise( + `

Binding Error - Name of attribute more than 30 characters: ` && lr_attri->name ). + ENDIF. + lr_attri->bind_type = type. + result = COND #( WHEN type = cs_bind_type-two_way THEN `/` && ss_config-view_model_edit_name && `/` ELSE `/` ) && lr_attri->name. + RETURN. + ENDIF. + + ENDLOOP. + + IF type = cs_bind_type-two_way. + z2ui5_cl_fw_utility=>raise( `Binding Error - Two way binding used but no attribute found` ). + ENDIF. + + DATA(lv_id) = z2ui5_cl_fw_utility=>get_uuid( ). + INSERT VALUE #( name = lv_id + data_stringify = z2ui5_cl_fw_utility=>trans_any_2_json( value ) + bind_type = cs_bind_type-one_time ) + INTO TABLE ms_db-t_attri. + result = |/{ lv_id }|. + + ENDMETHOD. +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_handler.clas.testclasses.abap b/src/00/z2ui5_cl_fw_handler.clas.testclasses.abap new file mode 100644 index 00000000..51c3819d --- /dev/null +++ b/src/00/z2ui5_cl_fw_handler.clas.testclasses.abap @@ -0,0 +1,45 @@ +CLASS ltcl_unit_test DEFINITION FINAL FOR TESTING + DURATION SHORT + RISK LEVEL critical. + + PRIVATE SECTION. + METHODS test_req_begin_fw_start FOR TESTING RAISING cx_static_check. + METHODS test_req_begin_app_start FOR TESTING RAISING cx_static_check. + +ENDCLASS. + + +CLASS ltcl_unit_test IMPLEMENTATION. + + METHOD test_req_begin_fw_start. + + DATA(lv_body) = `{"OLOCATION":{"ORIGIN":"https:/url.abap-web.us10.hana.ondemand.com","PATHNAME":"/sap/bc/http/sap/z_http_service_for_ui","SEARCH":"?sap-client=100","VERSION":"com.sap.ui5.dist:sapui5-sdk-dist:1.115.0:war"}}`. + + DATA(lo_handler) = z2ui5_cl_fw_handler=>request_begin( lv_body ). + + IF lo_handler->ms_db-app IS NOT BOUND. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + DATA(lo_app_fw) = CAST z2ui5_cl_fw_app( lo_handler->ms_db-app ) ##NEEDED. + + + ENDMETHOD. + + METHOD test_req_begin_app_start. + + DATA(lv_body) = `{"OLOCATION":{"ORIGIN":"https://url.abap-web.us10.hana.ondemand.com","PATHNAME":"/sap/bc/http/sap/z_http_service_for_ui","SEARCH":"?sap-client=100&app_start=z2ui5_cl_app_hello_world","VERSION":"c` && + `om.sap.ui5.dist:sapui5-sdk-dist:1.115.0:war"}}`. + + DATA(lo_handler) = z2ui5_cl_fw_handler=>request_begin( lv_body ). + + IF lo_handler->ms_db-app IS NOT BOUND. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + DATA(lo_app_fw) = CAST z2ui5_cl_app_hello_world( lo_handler->ms_db-app ) ##NEEDED. + + + ENDMETHOD. + +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_handler.clas.xml b/src/00/z2ui5_cl_fw_handler.clas.xml new file mode 100644 index 00000000..adecc70d --- /dev/null +++ b/src/00/z2ui5_cl_fw_handler.clas.xml @@ -0,0 +1,17 @@ + + + + + + Z2UI5_CL_FW_HANDLER + E + abap2UI5 - handler + 1 + X + X + X + X + + + + diff --git a/src/00/z2ui5_cl_fw_integration_test.clas.abap b/src/00/z2ui5_cl_fw_integration_test.clas.abap new file mode 100644 index 00000000..f8ac9e77 --- /dev/null +++ b/src/00/z2ui5_cl_fw_integration_test.clas.abap @@ -0,0 +1,151 @@ +CLASS z2ui5_cl_fw_integration_test DEFINITION + PUBLIC + FINAL + CREATE PUBLIC. + + PUBLIC SECTION. + INTERFACES z2ui5_if_app. + + DATA product TYPE string. + DATA quantity TYPE string. + DATA check_initialized TYPE abap_bool. + + CLASS-DATA sv_state TYPE string. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. + + + +CLASS Z2UI5_CL_FW_INTEGRATION_TEST IMPLEMENTATION. + + + METHOD z2ui5_if_app~main. + + IF check_initialized = abap_false. + check_initialized = abap_true. + product = 'tomato'. + quantity = '500'. + ENDIF. + + CASE client->get( )-event. + WHEN 'BUTTON_POST'. + client->message_toast_display( |{ product } { quantity } - send to the server| ). + WHEN 'BACK'. + client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ). + ENDCASE. + + IF sv_state = 'TEST_MESSAGE_BOX'. + client->message_box_display( 'test message box' ). + ENDIF. + + IF sv_state = 'TEST_MESSAGE_TOAST'. + client->message_toast_display( 'test message toast' ). + ENDIF. + + CASE sv_state. + + WHEN 'TEST_ONE_WAY'. + client->view_display( z2ui5_cl_xml_view=>factory( client )->shell( + )->page( title = 'abap2UI5 - First Example' + navbuttonpress = client->_event( 'BACK' ) + shownavbutton = abap_true + )->simple_form( title = 'Form Title' + editable = abap_true + )->content( 'form' + )->title( 'Input' + )->label( 'quantity' + )->input( client->_bind( quantity ) + )->label( 'product' + )->input( value = product + enabled = abap_false + )->button( text = 'post' + press = client->_event( 'BUTTON_POST' ) + )->get_root( )->xml_get( ) ). + + WHEN 'TEST_POPUP'. + + client->popup_display( z2ui5_cl_xml_view=>factory( client + )->dialog( title = 'abap2UI5 - First Example' + )->simple_form( title = 'Form Title' + editable = abap_true + )->content( 'form' + )->title( 'Input' + )->label( 'quantity' + )->input( client->_bind_edit( quantity ) + )->label( 'product' + )->input( value = product + enabled = abap_false + )->button( text = 'post' + press = client->_event( 'BUTTON_POST' ) + )->get_root( )->xml_get( ) ). + + WHEN 'TEST_TIMER'. + client->timer_set( event_finished = 'TIMER_FINISHED' + interval_ms = `500` ). + + client->view_display( z2ui5_cl_xml_view=>factory( client )->shell( + )->page( title = 'abap2UI5 - First Example' + navbuttonpress = client->_event( 'BACK' ) + shownavbutton = abap_true + )->simple_form( title = 'Form Title' + editable = abap_true + )->content( 'form' + )->title( 'Input' + )->label( 'quantity' + )->input( client->_bind( quantity ) + )->label( 'product' + )->input( value = product + enabled = abap_false + )->button( text = 'post' + press = client->_event( 'BUTTON_POST' ) + )->get_root( )->xml_get( ) ). + + WHEN OTHERS. + client->view_display( z2ui5_cl_xml_view=>factory( client )->shell( + )->page( title = 'abap2UI5 - First Example' + navbuttonpress = client->_event( 'BACK' ) + shownavbutton = abap_true + )->simple_form( title = 'Form Title' + editable = abap_true + )->content( 'form' + )->title( 'Input' + )->label( 'quantity' + )->input( client->_bind_edit( quantity ) + )->label( 'product' + )->input( value = product + enabled = abap_false + )->button( text = 'post' + press = client->_event( 'BUTTON_POST' ) + )->get_root( )->xml_get( ) ). + + ENDCASE. + + IF sv_state = 'TEST_SCROLL_CURSOR'. + + client->view_display( `test` ). + client->cursor_set( id = 'id_text2' + cursorpos = '5' + selectionstart = '5' + selectionend = '10' ). + + client->scroll_position_set( VALUE #( v = '99999' + ( n = 'id_page' ) + ( n = 'id_text3' ) ) ). + + ENDIF. + + IF sv_state = 'TEST_NAVIGATE'. + DATA(lo_app) = NEW z2ui5_cl_fw_integration_test( ). + sv_state = 'LEAVE_APP'. + client->nav_app_call( lo_app ). + RETURN. + ENDIF. + + IF sv_state = 'LEAVE_APP'. + CLEAR sv_state. + client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app ) ). + ENDIF. + + ENDMETHOD. +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_integration_test.clas.testclasses.abap b/src/00/z2ui5_cl_fw_integration_test.clas.testclasses.abap new file mode 100644 index 00000000..2322d83c --- /dev/null +++ b/src/00/z2ui5_cl_fw_integration_test.clas.testclasses.abap @@ -0,0 +1,362 @@ +CLASS ltcl_unit_02_app_start DEFINITION FINAL FOR TESTING + DURATION SHORT + RISK LEVEL DANGEROUS. + + PUBLIC SECTION. + + + PRIVATE SECTION. + METHODS test_index_html FOR TESTING RAISING cx_static_check. + METHODS test_xml_view FOR TESTING RAISING cx_static_check. + METHODS test_id FOR TESTING RAISING cx_static_check. + METHODS test_xml_popup FOR TESTING RAISING cx_static_check. + METHODS test_bind_one_way FOR TESTING RAISING cx_static_check. + METHODS test_bind_two_way FOR TESTING RAISING cx_static_check. + METHODS test_message_toast FOR TESTING RAISING cx_static_check. + METHODS test_message_box FOR TESTING RAISING cx_static_check. + METHODS test_timer FOR TESTING RAISING cx_static_check. + METHODS test_landing_page FOR TESTING RAISING cx_static_check. + METHODS test_scroll_cursor FOR TESTING RAISING cx_static_check. + METHODS test_navigate FOR TESTING RAISING cx_static_check. + METHODS test_startup_path FOR TESTING RAISING cx_static_check. + +ENDCLASS. + + +CLASS ltcl_unit_02_app_start IMPLEMENTATION. + + METHOD test_xml_view. + + z2ui5_cl_fw_integration_test=>sv_state = ``. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + FIELD-SYMBOLS TYPE any. + UNASSIGN . + DATA(lv_assign) = `PARAMS->S_VIEW->XML->*`. + ASSIGN lo_data->(lv_assign) TO . + = shift_left( ). + IF (9) <> `fail( msg = 'xml view - intital view wrong' + quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_index_html. + + DATA(lv_index_html) = z2ui5_cl_http_handler=>http_get( ). + IF lv_index_html IS INITIAL. + cl_abap_unit_assert=>fail( 'HTTP GET - index html initial' ). + ENDIF. + + ENDMETHOD. + + + METHOD test_id. + + z2ui5_cl_fw_integration_test=>sv_state = ``. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + FIELD-SYMBOLS TYPE any. + UNASSIGN . + DATA(lv_assign) = `ID->*`. + ASSIGN lo_data->(lv_assign) TO . + IF IS INITIAL. + cl_abap_unit_assert=>fail( msg = 'id - initial value is initial' + quit = 5 ). + ENDIF. + ENDMETHOD. + + METHOD test_bind_one_way. + + DATA(lo_test) = NEW z2ui5_cl_fw_integration_test( ) ##NEEDED. + + z2ui5_cl_fw_integration_test=>sv_state = `TEST_ONE_WAY`. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + FIELD-SYMBOLS TYPE any. + UNASSIGN . + DATA(lv_assign) = `OVIEWMODEL->QUANTITY->*`. + ASSIGN lo_data->(lv_assign) TO . + IF <> `500`. + cl_abap_unit_assert=>fail( msg = 'data binding - initial set oUpdate wrong' + quit = 5 ). + ENDIF. + ENDMETHOD. + + METHOD test_bind_two_way. + + z2ui5_cl_fw_integration_test=>sv_state = ``. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + FIELD-SYMBOLS TYPE any. + UNASSIGN . + DATA(lv_assign) = `OVIEWMODEL->OUPDATE->QUANTITY->*`. + ASSIGN lo_data->(lv_assign) TO . + IF <> `500`. + cl_abap_unit_assert=>fail( msg = 'data binding - initial set oUpdate wrong' + quit = 5 ). + ENDIF. + ENDMETHOD. + + METHOD test_message_box. + + z2ui5_cl_fw_integration_test=>sv_state = `TEST_MESSAGE_BOX`. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + FIELD-SYMBOLS TYPE any. + + UNASSIGN . + DATA(lv_assign) = `PARAMS->S_MSG_BOX->TEXT->*`. + ASSIGN lo_data->(lv_assign) TO . + IF <> `test message box`. + cl_abap_unit_assert=>fail( msg = 'message box - text wrong' + quit = 5 ). + ENDIF. + + UNASSIGN . + lv_assign = `PARAMS->S_MSG_BOX->TYPE->*`. + ASSIGN lo_data->(lv_assign) TO . + IF <> `information`. + cl_abap_unit_assert=>fail( msg = 'message box - type wrong' + quit = 5 ). + ENDIF. + ENDMETHOD. + + METHOD test_message_toast. + + z2ui5_cl_fw_integration_test=>sv_state = `TEST_MESSAGE_TOAST`. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + FIELD-SYMBOLS TYPE any. + + UNASSIGN . + DATA(lv_assign) = `PARAMS->S_MSG_TOAST->TEXT->*`. + ASSIGN lo_data->(lv_assign) TO . + IF <> `test message toast`. + cl_abap_unit_assert=>fail( msg = 'message toast - text wrong' + quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_timer. + + z2ui5_cl_fw_integration_test=>sv_state = `TEST_TIMER`. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + FIELD-SYMBOLS TYPE any. + + UNASSIGN . + DATA(lv_assign) = `PARAMS->S_TIMER->EVENT_FINISHED->*`. + ASSIGN lo_data->(lv_assign) TO . + IF <> `TIMER_FINISHED`. + cl_abap_unit_assert=>fail( msg = 'timer - event wrong' + quit = 5 ). + ENDIF. + + UNASSIGN . + lv_assign = `PARAMS->S_TIMER->INTERVAL_MS->*`. + ASSIGN lo_data->(lv_assign) TO . + IF <> `500`. + cl_abap_unit_assert=>fail( msg = 'timer - ms wrong' + quit = 5 ). + ENDIF. + ENDMETHOD. + + METHOD test_xml_popup. + + z2ui5_cl_fw_integration_test=>sv_state = `TEST_POPUP`. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + FIELD-SYMBOLS TYPE any. + UNASSIGN . + DATA(lv_assign) = `PARAMS->S_POPUP->XML->*`. + ASSIGN lo_data->(lv_assign) TO . + = shift_left( ). + IF (9) <> `fail( msg = 'xml popup - intital popup wrong' + quit = 5 ). + ENDIF. + ENDMETHOD. + + METHOD test_landing_page. + + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : ""}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + FIELD-SYMBOLS TYPE any. + UNASSIGN . + DATA(lv_assign) = `PARAMS->S_VIEW->XML->*`. + ASSIGN lo_data->(lv_assign) TO . + = shift_left( ). + IF NS `Step 4`. + cl_abap_unit_assert=>fail( msg = 'landing page - not started when no app' + quit = 5 ). + ENDIF. + ENDMETHOD. + + METHOD test_scroll_cursor. + + z2ui5_cl_fw_integration_test=>sv_state = `TEST_SCROLL_CURSOR`. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + + + + ENDMETHOD. + + METHOD test_startup_path. + + z2ui5_cl_fw_integration_test=>sv_state = `TEST_NAVIGATE`. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + + ENDMETHOD. + + METHOD test_navigate. + + z2ui5_cl_fw_integration_test=>sv_state = `TEST_NAVIGATE`. + DATA(lv_response) = z2ui5_cl_http_handler=>http_post( + `{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ). + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_response + CHANGING data = lo_data ). + + ENDMETHOD. +ENDCLASS. + + +CLASS ltcl_unit_03_app_ajax DEFINITION FINAL FOR TESTING + DURATION LONG + RISK LEVEL DANGEROUS. + + PUBLIC SECTION. + INTERFACES z2ui5_if_app. + + DATA product TYPE string. + DATA quantity TYPE string. + DATA check_initialized TYPE abap_bool. + + CLASS-DATA sv_state TYPE string. + + PRIVATE SECTION. + METHODS test_app_change_value FOR TESTING RAISING cx_static_check. + METHODS test_app_event FOR TESTING RAISING cx_static_check. + METHODS test_app_dump FOR TESTING RAISING cx_static_check. + +ENDCLASS. + + +CLASS ltcl_unit_03_app_ajax IMPLEMENTATION. + + METHOD z2ui5_if_app~main. + IF check_initialized = abap_false. + check_initialized = abap_true. + product = 'tomato'. + quantity = '500'. + + ENDIF. + + CASE client->get( )-event. + WHEN 'BUTTON_POST'. + client->message_toast_display( |{ product } { quantity } - send to the server| ). + WHEN 'BACK'. + client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ). + ENDCASE. + + IF sv_state = 'ERROR'. + z2ui5_cl_fw_utility=>raise( `exception test` ). + ENDIF. + + client->view_display( z2ui5_cl_xml_view=>factory( client )->shell( + )->page( title = 'abap2UI5 - First Example' + navbuttonpress = client->_event( 'BACK' ) + shownavbutton = abap_true + )->simple_form( title = 'Form Title' + editable = abap_true + )->content( 'form' + )->title( 'Input' + )->label( 'quantity' + )->input( client->_bind( quantity ) + )->label( 'product' + )->input( value = product + enabled = abap_false + )->button( text = 'post' + press = client->_event( 'BUTTON_POST' ) + )->get_root( )->xml_get( ) ). + + ENDMETHOD. + + METHOD test_app_change_value. + + + ENDMETHOD. + + METHOD test_app_event. + + + ENDMETHOD. + + METHOD test_app_dump. + + + ENDMETHOD. + +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_integration_test.clas.xml b/src/00/z2ui5_cl_fw_integration_test.clas.xml new file mode 100644 index 00000000..d53c6b72 --- /dev/null +++ b/src/00/z2ui5_cl_fw_integration_test.clas.xml @@ -0,0 +1,17 @@ + + + + + + Z2UI5_CL_FW_INTEGRATION_TEST + E + abap2UI5 - integration test + 1 + X + X + X + X + + + + diff --git a/src/00/z2ui5_cl_fw_utility.clas.abap b/src/00/z2ui5_cl_fw_utility.clas.abap new file mode 100644 index 00000000..b93cd687 --- /dev/null +++ b/src/00/z2ui5_cl_fw_utility.clas.abap @@ -0,0 +1,569 @@ +CLASS z2ui5_cl_fw_utility DEFINITION PUBLIC + CREATE PUBLIC. + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_attri, + name TYPE string, + type_kind TYPE string, + type TYPE string, + bind_type TYPE string, + data_stringify TYPE string, + data_rtti TYPE string, + check_ref_data TYPE abap_bool, + END OF ty_attri. + TYPES ty_t_attri TYPE STANDARD TABLE OF ty_attri WITH EMPTY KEY. + + CLASS-METHODS url_param_get + IMPORTING + val TYPE string + url TYPE string + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS url_param_create_url + IMPORTING + t_params TYPE z2ui5_if_client=>ty_t_name_value + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS url_param_set + IMPORTING + url TYPE string + name TYPE string + value TYPE string + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS get_classname_by_ref + IMPORTING + in TYPE REF TO object + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS raise + IMPORTING + v TYPE clike DEFAULT `CX_SY_SUBRC` + when TYPE abap_bool DEFAULT abap_true + PREFERRED PARAMETER v. + + CLASS-METHODS get_uuid + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS get_user_tech + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS trans_any_2_json + IMPORTING + any TYPE any + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS trans_xml_2_object + IMPORTING + xml TYPE clike + EXPORTING + data TYPE data. + + CLASS-METHODS get_t_attri_by_ref + IMPORTING + io_app TYPE REF TO object + RETURNING + VALUE(result) TYPE ty_t_attri ##NEEDED. + + CLASS-METHODS trans_object_2_xml + IMPORTING + object TYPE data + RETURNING + VALUE(result) TYPE string + RAISING + cx_xslt_serialization_error. + + CLASS-METHODS get_abap_2_json + IMPORTING + val TYPE any + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS check_is_boolean + IMPORTING + val TYPE any + RETURNING + VALUE(result) TYPE abap_bool. + + CLASS-METHODS get_json_boolean + IMPORTING + val TYPE any + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS trans_ref_tab_2_tab + IMPORTING + ir_tab_from TYPE REF TO data + EXPORTING + t_result TYPE STANDARD TABLE. + + CLASS-METHODS get_trim_upper + IMPORTING val TYPE any + RETURNING VALUE(result) TYPE string. + + CLASS-METHODS _get_t_attri_by_struc + IMPORTING + io_app TYPE REF TO object + iv_attri TYPE csequence + RETURNING + VALUE(result) TYPE abap_attrdescr_tab. + + CLASS-METHODS rtti_get + IMPORTING + data TYPE any + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS rtti_set + IMPORTING + rtti_data TYPE string + EXPORTING + e_data TYPE REF TO data. + + CLASS-METHODS get_timestampl + RETURNING + VALUE(result) TYPE timestampl. + + CLASS-METHODS get_replace + IMPORTING + iv_val TYPE clike + iv_begin TYPE clike + iv_end TYPE clike + iv_replace TYPE clike DEFAULT '' + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS get_trim + IMPORTING + val TYPE any + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS get_trim_lower + IMPORTING + val TYPE any + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS url_param_get_tab + IMPORTING + i_val TYPE string + RETURNING + VALUE(rt_params) TYPE z2ui5_if_client=>ty_t_name_value. + + PROTECTED SECTION. + PRIVATE SECTION. + +ENDCLASS. + + + +CLASS z2ui5_cl_fw_utility IMPLEMENTATION. + + + METHOD check_is_boolean. + + TRY. + DATA(lo_ele) = CAST cl_abap_elemdescr( cl_abap_elemdescr=>describe_by_data( val ) ). + CASE lo_ele->get_relative_name( ). + WHEN `ABAP_BOOL` OR `XSDBOOLEAN`. + result = abap_true. + ENDCASE. + CATCH cx_root. + ENDTRY. + + ENDMETHOD. + + + METHOD get_abap_2_json. + + IF check_is_boolean( val ). + result = COND #( WHEN val = abap_true THEN `true` ELSE `false` ). + ELSE. + result = |"{ escape( val = val + format = cl_abap_format=>e_json_string ) }"|. + ENDIF. + + ENDMETHOD. + + + METHOD get_classname_by_ref. + + DATA(lv_classname) = cl_abap_classdescr=>get_class_name( in ). + result = substring_after( val = lv_classname + sub = `\CLASS=` ). + + ENDMETHOD. + + + METHOD get_json_boolean. + + IF check_is_boolean( val ). + result = COND #( WHEN val = abap_true THEN `true` ELSE `false` ). + ELSE. + result = val. + ENDIF. + + ENDMETHOD. + + + METHOD get_replace. + + result = iv_val. + + DATA(lv_1) = substring_before( val = result + sub = iv_begin ). + DATA(lv_2) = substring_after( val = result + sub = iv_end ). + result = COND #( WHEN lv_2 IS NOT INITIAL THEN lv_1 && iv_replace && lv_2 ). + + ENDMETHOD. + + + METHOD get_timestampl. + GET TIME STAMP FIELD result. + ENDMETHOD. + + + METHOD get_trim. + + result = shift_left( shift_right( CONV string( val ) ) ). + result = shift_right( val = result sub = cl_abap_char_utilities=>horizontal_tab ). + result = shift_left( val = result sub = cl_abap_char_utilities=>horizontal_tab ). + result = shift_left( shift_right( CONV string( val ) ) ). + + ENDMETHOD. + + + METHOD get_trim_lower. + + result = to_lower( get_trim( CONV string( val ) ) ). + + ENDMETHOD. + + + METHOD get_trim_upper. + + result = to_upper( get_trim( CONV string( val ) ) ). + + ENDMETHOD. + + + METHOD get_t_attri_by_ref. + + DATA(lt_attri) = CAST cl_abap_classdescr( cl_abap_objectdescr=>describe_by_object_ref( io_app ) )->attributes. + DELETE lt_attri WHERE visibility <> cl_abap_classdescr=>public. + + LOOP AT lt_attri INTO DATA(ls_attri) + WHERE type_kind = cl_abap_classdescr=>typekind_struct2 + OR type_kind = cl_abap_classdescr=>typekind_struct1. + + DELETE lt_attri INDEX sy-tabix. + + INSERT LINES OF _get_t_attri_by_struc( io_app = io_app + iv_attri = ls_attri-name ) INTO TABLE lt_attri. + + ENDLOOP. + + LOOP AT lt_attri INTO ls_attri. + + DATA(ls_attri2) = VALUE ty_attri( ). + ls_attri2 = CORRESPONDING #( ls_attri ). + + + + APPEND ls_attri2 TO result. + ENDLOOP. + + ENDMETHOD. + + + METHOD get_user_tech. + result = sy-uname. + ENDMETHOD. + + + METHOD get_uuid. + + TRY. + DATA uuid TYPE c LENGTH 32. + + TRY. + CALL METHOD (`CL_SYSTEM_UUID`)=>if_system_uuid_static~create_uuid_c32 + RECEIVING + uuid = uuid. + + CATCH cx_sy_dyn_call_illegal_class. + + DATA(lv_fm) = `GUID_CREATE`. + CALL FUNCTION lv_fm + IMPORTING + ev_guid_32 = uuid. + + ENDTRY. + + result = uuid. + + CATCH cx_root. + ASSERT 1 = 0. + ENDTRY. + + ENDMETHOD. + + METHOD raise. + + IF when = abap_true. + RAISE EXCEPTION TYPE z2ui5_cl_fw_error EXPORTING val = v. + ENDIF. + + ENDMETHOD. + + + METHOD rtti_get. + + TRY. + + DATA srtti TYPE REF TO object. + + CALL METHOD ('ZCL_SRTTI_TYPEDESCR')=>('CREATE_BY_DATA_OBJECT') + EXPORTING + data_object = data + RECEIVING + srtti = srtti. + + CALL TRANSFORMATION id SOURCE srtti = srtti dobj = data RESULT XML result. + + CATCH cx_root. + DATA(lv_link) = `https://github.com/sandraros/S-RTTI`. + DATA(lv_text) = `

Please install the open-source project S-RTTI by sandraros and try again: (link)

`. + + RAISE EXCEPTION TYPE z2ui5_cl_fw_error + EXPORTING + val = lv_text. + + ENDTRY. + + ENDMETHOD. + + + METHOD rtti_set. + + TRY. + DATA srtti TYPE REF TO object. + CALL TRANSFORMATION id SOURCE XML rtti_data RESULT srtti = srtti. + + DATA rtti_type TYPE REF TO cl_abap_typedescr. + CALL METHOD srtti->('GET_RTTI') + RECEIVING + rtti = rtti_type. + + DATA lo_datadescr TYPE REF TO cl_abap_datadescr. + lo_datadescr ?= rtti_type. + + CREATE DATA e_data TYPE HANDLE lo_datadescr. + ASSIGN e_data->* TO FIELD-SYMBOL(). + CALL TRANSFORMATION id SOURCE XML rtti_data RESULT dobj = . + + CATCH cx_root. + + DATA(lv_link) = `https://github.com/sandraros/S-RTTI`. + DATA(lv_text) = `

Please install the open-source project S-RTTI by sandraros and try again: (link)

`. + + RAISE EXCEPTION TYPE z2ui5_cl_fw_error + EXPORTING + val = lv_text. + + ENDTRY. + + ENDMETHOD. + + + METHOD trans_any_2_json. + + result = /ui2/cl_json=>serialize( any ). + + ENDMETHOD. + + + METHOD trans_object_2_xml. + + FIELD-SYMBOLS TYPE any. + ASSIGN object->* TO . + raise( when = xsdbool( sy-subrc <> 0 ) ). + + CALL TRANSFORMATION id + SOURCE data = + RESULT XML result + OPTIONS data_refs = `heap-or-create`. + + ENDMETHOD. + + + METHOD trans_ref_tab_2_tab. + + TYPES ty_t_ref TYPE STANDARD TABLE OF REF TO data. + FIELD-SYMBOLS TYPE ty_t_ref. + + ASSIGN ir_tab_from->* TO . + raise( when = xsdbool( sy-subrc <> 0 ) ). + + CLEAR t_result. + + DATA(lo_tab) = CAST cl_abap_tabledescr( cl_abap_datadescr=>describe_by_data( t_result ) ). + DATA(lo_struc) = CAST cl_abap_structdescr( lo_tab->get_table_line_type( ) ). + DATA(lt_components) = lo_struc->get_components( ). + + LOOP AT INTO DATA(lr_from). + + DATA lr_row TYPE REF TO data. + CREATE DATA lr_row TYPE HANDLE lo_struc. + ASSIGN lr_row->* TO FIELD-SYMBOL(). + IF sy-subrc <> 0. + EXIT. + ENDIF. + + ASSIGN lr_from->* TO FIELD-SYMBOL(). + raise( when = xsdbool( sy-subrc <> 0 ) ). + + LOOP AT lt_components INTO DATA(ls_comp). + + FIELD-SYMBOLS TYPE data. + ASSIGN COMPONENT ls_comp-name OF STRUCTURE TO . + IF sy-subrc <> 0. + EXIT. + ENDIF. + + FIELD-SYMBOLS TYPE data. + ASSIGN COMPONENT ls_comp-name OF STRUCTURE TO . + IF sy-subrc <> 0. + EXIT. + ENDIF. + + ASSIGN ->* TO FIELD-SYMBOL(). + IF sy-subrc = 0. + CASE ls_comp-type->kind. + WHEN cl_abap_typedescr=>kind_table. + trans_ref_tab_2_tab( EXPORTING ir_tab_from = + IMPORTING t_result = ). + WHEN OTHERS. + = . + ENDCASE. + ENDIF. + ENDLOOP. + + INSERT INTO TABLE t_result. + ENDLOOP. + + ENDMETHOD. + + + METHOD trans_xml_2_object. + + CALL TRANSFORMATION id + SOURCE XML xml + RESULT data = data. + + ENDMETHOD. + + + METHOD url_param_create_url. + + LOOP AT t_params INTO DATA(ls_param). + result = result && ls_param-n && `=` && ls_param-v && `&`. + ENDLOOP. + result = shift_right( val = result + sub = `&` ). + + ENDMETHOD. + + + METHOD url_param_get. + + DATA(lt_params) = url_param_get_tab( url ). + DATA(lv_val) = get_trim_lower( val ). + result = VALUE #( lt_params[ n = lv_val ]-v OPTIONAL ). + + ENDMETHOD. + + + METHOD url_param_get_tab. + + DATA(lv_search) = replace( val = i_val sub = `%3D` with = '=' occ = 0 ). + lv_search = shift_left( val = lv_search sub = `?` ). + lv_search = get_trim_lower( lv_search ). + + DATA(lv_search2) = substring_after( val = lv_search + sub = `&sap-startup-params=` ). + lv_search = COND #( WHEN lv_search2 IS NOT INITIAL THEN lv_search2 ELSE lv_search ). + + lv_search2 = substring_after( val = get_trim_lower( lv_search ) sub = `?` ). + IF lv_search2 IS NOT INITIAL. + lv_search = lv_search2. + ENDIF. + + SPLIT lv_search AT `&` INTO TABLE DATA(lt_param). + + LOOP AT lt_param REFERENCE INTO DATA(lr_param). + SPLIT lr_param->* AT `=` INTO DATA(lv_name) DATA(lv_value). + INSERT VALUE #( n = get_trim_lower( lv_name ) v = get_trim_lower( lv_value ) ) INTO TABLE rt_params. + ENDLOOP. + + ENDMETHOD. + + + METHOD url_param_set. + + DATA(lt_params) = url_param_get_tab( url ). + + DATA(lv_n) = get_trim_lower( name ). + + LOOP AT lt_params REFERENCE INTO DATA(lr_params) + WHERE n = lv_n. + lr_params->v = get_trim_lower( value ). + ENDLOOP. + IF sy-subrc <> 0. + INSERT VALUE #( n = lv_n v = get_trim_lower( value ) ) INTO TABLE lt_params. + ENDIF. + + result = url_param_create_url( lt_params ). + + ENDMETHOD. + + + METHOD _get_t_attri_by_struc. + + FIELD-SYMBOLS TYPE any. + + DATA(lv_name) = `IO_APP->` && to_upper( iv_attri ). + ASSIGN (lv_name) TO . + raise( when = xsdbool( sy-subrc <> 0 ) ). + + DATA(lo_type) = cl_abap_structdescr=>describe_by_data( ). + DATA(lo_struct) = CAST cl_abap_structdescr( lo_type ). + + LOOP AT lo_struct->get_components( ) REFERENCE INTO DATA(lr_comp). + + DATA(lv_element) = iv_attri && `-` && lr_comp->name. + + IF lr_comp->as_include = abap_true. + INSERT LINES OF _get_t_attri_by_struc( io_app = io_app + iv_attri = lv_element ) INTO TABLE result. + + ELSE. + INSERT VALUE #( name = lv_element + type_kind = lr_comp->type->type_kind ) INTO TABLE result. + ENDIF. + + ENDLOOP. + ENDMETHOD. +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_utility.clas.testclasses.abap b/src/00/z2ui5_cl_fw_utility.clas.testclasses.abap new file mode 100644 index 00000000..7d8b86cb --- /dev/null +++ b/src/00/z2ui5_cl_fw_utility.clas.testclasses.abap @@ -0,0 +1,576 @@ +CLASS ltcl_test_app DEFINITION FINAL FOR TESTING + DURATION SHORT + RISK LEVEL HARMLESS. + + PUBLIC SECTION. + + TYPES: + BEGIN OF ty_row, + title TYPE string, + value TYPE string, + descr TYPE string, + icon TYPE string, + info TYPE string, + selected TYPE abap_bool, + checkbox TYPE abap_bool, + END OF ty_row. + + CONSTANTS sv_status TYPE string VALUE `test` ##NEEDED. + + CLASS-DATA sv_var TYPE string. + CLASS-DATA ss_tab TYPE ty_row. + CLASS-DATA st_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY. + + DATA mv_val TYPE string ##NEEDED. + DATA ms_tab TYPE ty_row ##NEEDED. + DATA mt_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY ##NEEDED. + + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. + +CLASS ltcl_test_app IMPLEMENTATION. +ENDCLASS. + +CLASS ltcl_unit_test_sap_api DEFINITION FINAL FOR TESTING + DURATION SHORT + RISK LEVEL HARMLESS. + + PRIVATE SECTION. + + METHODS check_input + IMPORTING + val TYPE data + RETURNING + VALUE(result) TYPE abap_bool. + + METHODS test_assign FOR TESTING RAISING cx_static_check. + METHODS test_eledescr_rel_name FOR TESTING RAISING cx_static_check. + METHODS test_classdescr FOR TESTING RAISING cx_static_check. + METHODS test_substring_after FOR TESTING RAISING cx_static_check. + METHODS test_substring_before FOR TESTING RAISING cx_static_check. + METHODS test_string_shift FOR TESTING RAISING cx_static_check. + METHODS test_string_replace FOR TESTING RAISING cx_static_check. + METHODS test_raise_error FOR TESTING RAISING cx_static_check. + METHODS test_xsdbool FOR TESTING RAISING cx_static_check. + METHODS test_xsdbool_nested FOR TESTING RAISING cx_static_check. + +ENDCLASS. + +CLASS ltcl_unit_test DEFINITION FINAL FOR TESTING + DURATION MEDIUM + RISK LEVEL HARMLESS. + + PRIVATE SECTION. + + METHODS test_check_is_boolean FOR TESTING RAISING cx_static_check. + METHODS test_get_abap_2_json FOR TESTING RAISING cx_static_check. + METHODS test_create FOR TESTING RAISING cx_static_check. + METHODS test_get_classname_by_ref FOR TESTING RAISING cx_static_check. + METHODS test_get_json_boolean FOR TESTING RAISING cx_static_check. + METHODS test_get_replace FOR TESTING RAISING cx_static_check. + METHODS test_get_timestampl FOR TESTING RAISING cx_static_check. + METHODS test_get_trim_lower FOR TESTING RAISING cx_static_check. + METHODS test_get_trim_upper FOR TESTING RAISING cx_static_check. + METHODS test_attri_by_ref FOR TESTING RAISING cx_static_check. + METHODS test_get_uuid FOR TESTING RAISING cx_static_check. + METHODS test_get_user_tech FOR TESTING RAISING cx_static_check. + METHODS test_raise FOR TESTING RAISING cx_static_check. + METHODS test_any_2_json FOR TESTING RAISING cx_static_check. + METHODS test_any_2_json_02 FOR TESTING RAISING cx_static_check. + METHODS test_trans_ref_tab_2_tab FOR TESTING RAISING cx_static_check. + METHODS test_url_param_create_url FOR TESTING RAISING cx_static_check. + METHODS test_url_param_get FOR TESTING RAISING cx_static_check. + METHODS test_url_param_get_tab FOR TESTING RAISING cx_static_check. + METHODS url_param_set FOR TESTING RAISING cx_static_check. + METHODS test_raise_error_not FOR TESTING RAISING cx_static_check. + METHODS test_raise_error FOR TESTING RAISING cx_static_check. + +ENDCLASS. + +CLASS ltcl_unit_test_sap_api IMPLEMENTATION. + + + METHOD test_assign. + + DATA(lo_app) = NEW ltcl_test_app( ). + + lo_app->mv_val = `ABC`. + FIELD-SYMBOLS TYPE any. + DATA(lv_assign) = `LO_APP->` && 'MV_VAL'. + ASSIGN (lv_assign) TO . + + cl_abap_unit_assert=>assert_equals( + act = + exp = `ABC` ). + + ENDMETHOD. + + + METHOD test_classdescr. + + DATA(lo_app) = NEW ltcl_test_app( ). + + DATA(lt_attri) = CAST cl_abap_classdescr( cl_abap_objectdescr=>describe_by_object_ref( lo_app ) )->attributes. + + DATA(lv_test) = lt_attri[ name = `MS_TAB` ]. + lv_test = lt_attri[ name = `MT_TAB` ]. + lv_test = lt_attri[ name = `MV_VAL` ]. + lv_test = lt_attri[ name = `SS_TAB` ]. + lv_test = lt_attri[ name = `ST_TAB` ]. + lv_test = lt_attri[ name = `SV_STATUS` ]. + lv_test = lt_attri[ name = `SV_VAR` ]. + + ENDMETHOD. + + METHOD test_eledescr_rel_name. + + DATA(lo_ele) = CAST cl_abap_elemdescr( cl_abap_elemdescr=>describe_by_data( abap_true ) ). + + cl_abap_unit_assert=>assert_equals( + act = lo_ele->get_relative_name( ) + exp = `ABAP_BOOL` ). + + ENDMETHOD. + + METHOD test_substring_after. + + cl_abap_unit_assert=>assert_equals( + act = substring_after( val = 'this is a string' sub = 'a' ) + exp = ` string` ). + + ENDMETHOD. + + METHOD test_substring_before. + + cl_abap_unit_assert=>assert_equals( + act = substring_before( val = 'this is a string' sub = 'a' ) + exp = `this is ` ). + + ENDMETHOD. + + METHOD test_string_shift. + + cl_abap_unit_assert=>assert_equals( + act = shift_left( shift_right( val = ` string ` sub = ` ` ) ) + exp = `string` ). + + ENDMETHOD. + + METHOD test_string_replace. + + DATA(lv_search) = replace( val = `one two three` sub = `two` with = 'ABC' occ = 0 ). + + cl_abap_unit_assert=>assert_equals( + act = replace( val = `one two three` sub = `two` with = 'ABC' occ = 0 ) + exp = `one ABC three` ). + + ENDMETHOD. + + METHOD test_raise_error. + + TRY. + RAISE EXCEPTION TYPE z2ui5_cl_fw_error. + cl_abap_unit_assert=>fail( ). + + CATCH z2ui5_cl_fw_error INTO DATA(lx). + cl_abap_unit_assert=>assert_bound( lx ). + ENDTRY. + + ENDMETHOD. + + METHOD test_xsdbool. + + DATA(lv_xsdbool) = xsdbool( 1 = 1 ). + IF lv_xsdbool = abap_false. + cl_abap_unit_assert=>assert_equals( + act = lv_xsdbool + exp = abap_false ). + ENDIF. + + IF xsdbool( 1 = 1 ) = abap_false. + cl_abap_unit_assert=>fail( ). + ENDIF. + + ENDMETHOD. + + METHOD test_xsdbool_nested. + + DATA(lv_xsdbool) = check_input( xsdbool( 1 = 1 ) ). + IF lv_xsdbool = abap_false. + cl_abap_unit_assert=>assert_equals( + act = lv_xsdbool + exp = abap_false ). + ENDIF. + + IF check_input( abap_false ). + cl_abap_unit_assert=>fail( ). + ENDIF. + + IF check_input( xsdbool( 1 = 1 ) ) = abap_false. + cl_abap_unit_assert=>fail( ). + ENDIF. + + IF check_input( xsdbool( 2 = 1 ) ). + cl_abap_unit_assert=>fail( ). + ENDIF. + + ENDMETHOD. + + METHOD check_input. + + result = val. + + ENDMETHOD. + +ENDCLASS. + +CLASS ltcl_unit_test IMPLEMENTATION. + + METHOD test_attri_by_ref. + + "dummy for abaplint check green + ltcl_test_app=>sv_var = ``. + ltcl_test_app=>ss_tab = VALUE #( ). + ltcl_test_app=>st_tab = VALUE #( ). + + DATA(lo_app) = NEW ltcl_test_app( ). + + DATA(lt_attri) = z2ui5_cl_fw_utility=>get_t_attri_by_ref( lo_app ). + + DATA(lt_attri_result) = VALUE z2ui5_cl_fw_utility=>ty_t_attri( + ( name = `MT_TAB` type_kind = `h` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `MV_VAL` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `ST_TAB` type_kind = `h` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `SV_STATUS` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `SV_VAR` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `MS_TAB-TITLE` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `MS_TAB-VALUE` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `MS_TAB-DESCR` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `MS_TAB-ICON` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `MS_TAB-INFO` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `MS_TAB-SELECTED` type_kind = `C` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `MS_TAB-CHECKBOX` type_kind = `C` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `SS_TAB-TITLE` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `SS_TAB-VALUE` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `SS_TAB-DESCR` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `SS_TAB-ICON` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `SS_TAB-INFO` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `SS_TAB-SELECTED` type_kind = `C` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ( name = `SS_TAB-CHECKBOX` type_kind = `C` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' ) + ). + + IF lt_attri_result <> lt_attri. + cl_abap_unit_assert=>fail( msg = 'utility - create t_attri failed' + quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_check_is_boolean. + + DATA(lv_bool) = xsdbool( 1 = 1 ). + cl_abap_unit_assert=>assert_equals( + act = z2ui5_cl_fw_utility=>check_is_boolean( lv_bool ) + exp = abap_true ). + + lv_bool = xsdbool( 1 = 2 ). + cl_abap_unit_assert=>assert_equals( + act = z2ui5_cl_fw_utility=>check_is_boolean( lv_bool ) + exp = abap_true ). + + cl_abap_unit_assert=>assert_equals( + act = z2ui5_cl_fw_utility=>check_is_boolean( abap_true ) + exp = abap_true ). + + cl_abap_unit_assert=>assert_equals( + act = z2ui5_cl_fw_utility=>check_is_boolean( abap_false ) + exp = abap_true ). + + ENDMETHOD. + + METHOD test_create. + + DATA(lo_test) = NEW z2ui5_cl_fw_utility( ) ##NEEDED. + + ENDMETHOD. + + METHOD test_get_abap_2_json. + + DATA(lv_bool) = xsdbool( 1 = 1 ). + cl_abap_unit_assert=>assert_equals( exp = `true` act = z2ui5_cl_fw_utility=>get_abap_2_json( lv_bool ) ). + + lv_bool = xsdbool( 1 = 2 ). + cl_abap_unit_assert=>assert_equals( exp = `false` act = z2ui5_cl_fw_utility=>get_abap_2_json( lv_bool ) ). + + ENDMETHOD. + + METHOD test_get_classname_by_ref. + + DATA(lo_test) = NEW z2ui5_cl_fw_utility( ). + DATA(lv_name) = z2ui5_cl_fw_utility=>get_classname_by_ref( lo_test ). + IF lv_name <> `Z2UI5_CL_FW_UTILITY`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + DATA(lo_test2) = NEW ltcl_test_app( ). + DATA(lv_name2) = z2ui5_cl_fw_utility=>get_classname_by_ref( lo_test2 ). + IF lv_name2 <> `LTCL_TEST_APP`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_get_json_boolean. + + IF `false` <> z2ui5_cl_fw_utility=>get_json_boolean( abap_false ). + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + IF `ABCD` <> z2ui5_cl_fw_utility=>get_json_boolean( `ABCD` ). + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_get_replace. + + DATA(lv_text) = `this is a replace text`. + DATA(lv_result) = z2ui5_cl_fw_utility=>get_replace( + iv_val = lv_text + iv_begin = `is a ` + iv_end = ` te` + iv_replace = 'is a test te' ). + IF lv_result <> `this is a test text`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_get_timestampl. + + DATA(lv_time) = z2ui5_cl_fw_utility=>get_timestampl( ). + DATA(lv_time2) = z2ui5_cl_fw_utility=>get_timestampl( ). + + IF lv_time2 < lv_time. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_get_trim_lower. + + IF z2ui5_cl_fw_utility=>get_trim_lower( ` JsadfHHs ` ) <> `jsadfhhs`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_get_trim_upper. + + IF z2ui5_cl_fw_utility=>get_trim_upper( ` JsadfHHs ` ) <> `JSADFHHS`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_get_uuid. + + DATA(lv_uuid) = z2ui5_cl_fw_utility=>get_uuid( ). + + IF lv_uuid IS INITIAL. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + IF strlen( lv_uuid ) <> 32. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_get_user_tech. + + IF sy-uname <> z2ui5_cl_fw_utility=>get_user_tech( ). + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_raise. + + TRY. + z2ui5_cl_fw_utility=>raise( ). + cl_abap_unit_assert=>fail( quit = 5 ). + CATCH cx_root. + ENDTRY. + + TRY. + z2ui5_cl_fw_utility=>raise( when = xsdbool( 1 = 1 ) ). + cl_abap_unit_assert=>fail( quit = 5 ). + CATCH cx_root. + ENDTRY. + + TRY. + z2ui5_cl_fw_utility=>raise( when = xsdbool( 1 = 3 ) ). + CATCH cx_root. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDTRY. + + ENDMETHOD. + + METHOD test_any_2_json. + + TYPES: + BEGIN OF ty_row, + title TYPE string, + value TYPE string, + selected TYPE abap_bool, + END OF ty_row. + TYPES ty_t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY. + + DATA(lt_tab) = VALUE ty_t_tab( ( title = 'Test' value = 'this is a description' selected = abap_true ) + ( title = 'Test2' value = 'this is a new descr' selected = abap_false ) ). + + + DATA(lv_tab_json) = z2ui5_cl_fw_utility=>trans_any_2_json( lt_tab ). + + DATA(lv_result) = `[{"TITLE":"Test","VALUE":"this is a description","SELECTED":true},{"TITLE":"Test2","VALUE":"this is a new descr","SELECTED":false}]`. + + IF lv_result <> lv_tab_json. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + + METHOD test_any_2_json_02. + + TYPES: + BEGIN OF ty_row, + title TYPE string, + value TYPE string, + selected TYPE abap_bool, + END OF ty_row. + TYPES ty_t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY. + + DATA(lt_tab) = VALUE ty_t_tab( ( title = 'Test' value = 'this is a description' selected = abap_true ) + ( title = 'Test2' value = 'this is a new descr' selected = abap_false ) ). + + DATA(lt_tab2) = VALUE ty_t_tab( ). + DATA(lv_tab) = z2ui5_cl_fw_utility=>trans_any_2_json( lt_tab ). + + /ui2/cl_json=>deserialize( EXPORTING json = lv_tab + CHANGING data = lt_tab2 ). + + IF lt_tab <> lt_tab2. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_trans_ref_tab_2_tab. + + TYPES: + BEGIN OF ty_row, + title TYPE string, + value TYPE string, + selected TYPE abap_bool, + END OF ty_row. + TYPES ty_t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY. + + DATA(lv_result) = `[{"TITLE":"Test","VALUE":"this is a description","SELECTED":true},{"TITLE":"Test2","VALUE":"this is a new descr","SELECTED":false}]`. + + DATA lo_data TYPE REF TO data. + /ui2/cl_json=>deserialize( EXPORTING json = lv_result + CHANGING data = lo_data ). + + DATA(lt_tab2) = VALUE ty_t_tab( ). + z2ui5_cl_fw_utility=>trans_ref_tab_2_tab( + EXPORTING ir_tab_from = lo_data + IMPORTING t_result = lt_tab2 ). + + + DATA(lt_tab) = VALUE ty_t_tab( ( title = 'Test' value = 'this is a description' selected = abap_true ) + ( title = 'Test2' value = 'this is a new descr' selected = abap_false ) ). + + IF lt_tab <> lt_tab2. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_url_param_create_url. + + DATA(lt_param) = z2ui5_cl_fw_utility=>url_param_get_tab( `https://url.com/rvice_for_ui?sap-client=100&app_start=z2ui5_cl_app_hello_world` ). + DATA(lv_url) = z2ui5_cl_fw_utility=>url_param_create_url( lt_param ). + + IF lv_url <> `sap-client=100&app_start=z2ui5_cl_app_hello_world`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_url_param_get. + + DATA(lv_param) = z2ui5_cl_fw_utility=>url_param_get( + val = `app_start` + url = `https://url.com/rvice_for_ui?sap-client=100&app_start=z2ui5_cl_app_hello_world` ). + + IF lv_param <> `z2ui5_cl_app_hello_world`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_url_param_get_tab. + + DATA(lt_param) = z2ui5_cl_fw_utility=>url_param_get_tab( `https://url.com/rvice_for_ui?sap-client=100&app_start=z2ui5_cl_app_hello_world` ). + IF lt_param[ n = `sap-client` ]-v <> `100`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + IF lt_param[ n = `app_start` ]-v <> `z2ui5_cl_app_hello_world`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD url_param_set. + + DATA(lv_param) = z2ui5_cl_fw_utility=>url_param_set( + name = `app_start` + value = `z2ui5_cl_app_hello_world2` + url = `https://url.com/rvice_for_ui?sap-client=100&app_start=z2ui5_cl_app_hello_world` ). + + IF lv_param <> `sap-client=100&app_start=z2ui5_cl_app_hello_world2`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + + METHOD test_raise_error. + + TRY. + z2ui5_cl_fw_utility=>raise( `error occured` ). + cl_abap_unit_assert=>fail( ). + + CATCH z2ui5_cl_fw_error INTO DATA(lx). + +* cl_abap_unit_assert=>assert_equals( +* act = lx->get_text( ) +* exp = `error occured` ). + + ENDTRY. + ENDMETHOD. + + METHOD test_raise_error_not. + + TRY. + z2ui5_cl_fw_utility=>raise( when = xsdbool( 1 = 2 ) ). + + CATCH z2ui5_cl_fw_error INTO DATA(lx). + cl_abap_unit_assert=>fail( quit = 5 ). + ENDTRY. + ENDMETHOD. + +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_utility.clas.xml b/src/00/z2ui5_cl_fw_utility.clas.xml new file mode 100644 index 00000000..a12626fb --- /dev/null +++ b/src/00/z2ui5_cl_fw_utility.clas.xml @@ -0,0 +1,17 @@ + + + + + + Z2UI5_CL_FW_UTILITY + E + abap2UI5 - utility + 1 + X + X + X + X + + + + diff --git a/src/00/z2ui5_cl_fw_utility_json.clas.abap b/src/00/z2ui5_cl_fw_utility_json.clas.abap new file mode 100644 index 00000000..8e805edf --- /dev/null +++ b/src/00/z2ui5_cl_fw_utility_json.clas.abap @@ -0,0 +1,231 @@ +CLASS z2ui5_cl_fw_utility_json DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + DATA mo_root TYPE REF TO z2ui5_cl_fw_utility_json. + DATA mo_parent TYPE REF TO z2ui5_cl_fw_utility_json. + DATA mv_name TYPE string. + DATA mv_value TYPE string. + DATA mt_values TYPE STANDARD TABLE OF REF TO z2ui5_cl_fw_utility_json WITH EMPTY KEY. + DATA mr_actual TYPE REF TO data. + DATA mv_apost_active TYPE abap_bool. + + CLASS-METHODS factory + IMPORTING + iv_json TYPE clike OPTIONAL + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json. + + METHODS constructor. + + METHODS get_attribute + IMPORTING + name TYPE string + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json. + + METHODS get_val + RETURNING + VALUE(result) TYPE string. + + METHODS get_val_ref + RETURNING + VALUE(result) TYPE REF TO data. + + METHODS add_attribute + IMPORTING + n TYPE clike + v TYPE clike + apos_active TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json. + + METHODS add_attribute_object + IMPORTING + name TYPE clike + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json. + + METHODS add_attribute_struc + IMPORTING + val TYPE data + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json. + + METHODS add_attribute_instance + IMPORTING + val TYPE REF TO z2ui5_cl_fw_utility_json + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json. + + METHODS stringify + RETURNING + VALUE(result) TYPE string. + + PROTECTED SECTION. + + CLASS-METHODS new + IMPORTING + io_root TYPE REF TO z2ui5_cl_fw_utility_json + iv_name TYPE simple + RETURNING + VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json. + + PRIVATE SECTION. +ENDCLASS. + + + +CLASS Z2UI5_CL_FW_UTILITY_JSON IMPLEMENTATION. + + + METHOD add_attribute. + + result = new( io_root = mo_root + iv_name = n ). + + result->mv_value = COND #( WHEN apos_active = abap_true + THEN escape( val = v + format = cl_abap_format=>e_json_string ) ELSE v ). + + result->mv_apost_active = apos_active. + result->mo_parent = me. + INSERT result INTO TABLE mt_values. + + ENDMETHOD. + + + METHOD add_attribute_instance. + + val->mo_root = mo_root. + val->mo_parent = me. + INSERT val INTO TABLE mt_values. + result = val. + + ENDMETHOD. + + + METHOD add_attribute_object. + + result = new( io_root = mo_root + iv_name = name ). + INSERT result INTO TABLE mt_values. + result->mo_parent = me. + + ENDMETHOD. + + + METHOD add_attribute_struc. + + FIELD-SYMBOLS TYPE any. + DATA(lo_struc) = CAST cl_abap_structdescr( cl_abap_datadescr=>describe_by_data( val ) ). + DATA(lt_comp) = lo_struc->get_components( ). + + LOOP AT lt_comp REFERENCE INTO DATA(lr_comp). + ASSIGN COMPONENT lr_comp->name OF STRUCTURE val TO . + add_attribute( n = lr_comp->name + v = ). + ENDLOOP. + + result = me. + + ENDMETHOD. + + + METHOD constructor. + mo_root = me. + ENDMETHOD. + + + METHOD factory. + + result = NEW #( ). + result->mo_root = result. + + /ui2/cl_json=>deserialize( + EXPORTING + json = CONV string( iv_json ) + assoc_arrays = abap_true + CHANGING + data = result->mr_actual ). + + ENDMETHOD. + + + METHOD get_attribute. + + z2ui5_cl_fw_utility=>raise( when = xsdbool( mr_actual IS INITIAL ) ). + + result = new( io_root = mo_root + iv_name = name ). + + DATA(lv_name) = 'MR_ACTUAL->' && replace( val = name + sub = `-` + with = `_` + occ = 0 ). + + FIELD-SYMBOLS TYPE any. + ASSIGN (lv_name) TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). + + result->mr_actual = . + result->mo_parent = me. + INSERT result INTO TABLE mt_values. + + ENDMETHOD. + + + METHOD get_val. + + FIELD-SYMBOLS TYPE any. + ASSIGN mr_actual->* TO . + z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) + v = `value of attribute in JSON not found` ). + result = . + + ENDMETHOD. + + + METHOD get_val_ref. + + result = mr_actual. + + ENDMETHOD. + + + METHOD new. + + result = NEW #( ). + result->mo_root = io_root. + result->mv_name = CONV string( iv_name ). + + ENDMETHOD. + + + METHOD stringify. + + LOOP AT mt_values INTO DATA(lo_attri). + + IF sy-tabix > 1. + result = result && `,`. + ENDIF. + + result = |{ result }"{ lo_attri->mv_name }":|. + + IF lo_attri->mt_values IS NOT INITIAL. + result = result && lo_attri->stringify( ). + ELSEIF lo_attri->mv_apost_active = abap_true OR lo_attri->mv_value IS INITIAL. + result = result && `"` && lo_attri->mv_value && `"`. + ELSE. + result = result && lo_attri->mv_value. + ENDIF. + + ENDLOOP. + + result = `{` && result && `}`. + + ENDMETHOD. +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_utility_json.clas.testclasses.abap b/src/00/z2ui5_cl_fw_utility_json.clas.testclasses.abap new file mode 100644 index 00000000..ebf8e4f2 --- /dev/null +++ b/src/00/z2ui5_cl_fw_utility_json.clas.testclasses.abap @@ -0,0 +1,79 @@ +CLASS ltcl_unit_01_json DEFINITION FINAL FOR TESTING + DURATION medium + RISK LEVEL HARMLESS. + + PRIVATE SECTION. + METHODS test_json_attri FOR TESTING RAISING cx_static_check. + METHODS test_json_object FOR TESTING RAISING cx_static_check. + METHODS test_json_struc FOR TESTING RAISING cx_static_check. + METHODS test_create_json FOR TESTING RAISING cx_static_check. + +ENDCLASS. + +CLASS ltcl_unit_01_json IMPLEMENTATION. + + METHOD test_json_attri. + + DATA(lo_tree) = NEW z2ui5_cl_fw_utility_json( ). + lo_tree->add_attribute( n = `AAA` + v = `BBB` ). + + DATA(lv_result) = lo_tree->stringify( ). + IF `{"AAA":"BBB"}` <> lv_result. + cl_abap_unit_assert=>fail( 'json tree - wrong stringify attributes' ). + ENDIF. + + ENDMETHOD. + + METHOD test_json_object. + + DATA(lo_tree) = NEW z2ui5_cl_fw_utility_json( ). + lo_tree->add_attribute_object( `CCC` )->add_attribute( n = `AAA` + v = `BBB` ). + + DATA(lv_result) = lo_tree->stringify( ). + IF `{"CCC":{"AAA":"BBB"}}` <> lv_result. + cl_abap_unit_assert=>fail( 'json tree - wrong stringify object attributes' ). + ENDIF. + + ENDMETHOD. + + METHOD test_json_struc. + + DATA(lo_tree) = NEW z2ui5_cl_fw_utility_json( ). + + TYPES: + BEGIN OF ty_s_test, + comp1 TYPE string, + comp2 TYPE string, + END OF ty_s_test. + + DATA(ls_test) = VALUE ty_s_test( comp1 = `AAA` comp2 = `BBB` ). + lo_tree->add_attribute_object( `CCC` )->add_attribute_struc( ls_test ). + + DATA(lv_result) = lo_tree->stringify( ). + IF `{"CCC":{"COMP1":"AAA","COMP2":"BBB"}}` <> lv_result. + cl_abap_unit_assert=>fail( 'json tree - wrong stringify structure' ). + ENDIF. + + ENDMETHOD. + + METHOD test_create_json. + + DATA(lo_json) = z2ui5_cl_fw_utility_json=>factory( `{"CCC":{"COMP1":"AAA","COMP2":"BBB"}}` ). + + DATA(lo_attri) = lo_json->get_attribute( `CCC` )->get_attribute( `COMP2` ). + + DATA(lr_ref) = lo_attri->get_val_ref( ). + IF lr_ref->* <> `BBB`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + DATA(lv_val) = lo_attri->get_val( ). + IF lv_val <> `BBB`. + cl_abap_unit_assert=>fail( quit = 5 ). + ENDIF. + + ENDMETHOD. + +ENDCLASS. diff --git a/src/00/z2ui5_cl_fw_utility_json.clas.xml b/src/00/z2ui5_cl_fw_utility_json.clas.xml new file mode 100644 index 00000000..b0c1fcc0 --- /dev/null +++ b/src/00/z2ui5_cl_fw_utility_json.clas.xml @@ -0,0 +1,17 @@ + + + + + + Z2UI5_CL_FW_UTILITY_JSON + E + abap2UI5 - utility json + 1 + X + X + X + X + + + + diff --git a/src/z2ui5_t_draft.tabl.xml b/src/00/z2ui5_t_draft.tabl.xml similarity index 100% rename from src/z2ui5_t_draft.tabl.xml rename to src/00/z2ui5_t_draft.tabl.xml diff --git a/src/package.devc.xml b/src/package.devc.xml index 968ac676..f04009f7 100644 --- a/src/package.devc.xml +++ b/src/package.devc.xml @@ -4,6 +4,7 @@ abap2UI5 + X diff --git a/src/z2ui5_cl_app_hello_world.clas.abap b/src/z2ui5_cl_app_hello_world.clas.abap index b73b3461..bc30219f 100644 --- a/src/z2ui5_cl_app_hello_world.clas.abap +++ b/src/z2ui5_cl_app_hello_world.clas.abap @@ -32,7 +32,8 @@ CLASS Z2UI5_CL_APP_HELLO_WORLD IMPLEMENTATION. client->view_display( z2ui5_cl_xml_view=>factory( client )->shell( )->page( title = 'abap2UI5 - z2ui5_cl_app_hello_world' - )->simple_form( title = 'Hello World' editable = abap_true + )->simple_form( title = 'Hello World' + editable = abap_true )->content( ns = `form` )->title( 'Make an input here and send it to the server...' )->label( 'quantity' diff --git a/src/z2ui5_cl_app_hello_world.clas.testclasses.abap b/src/z2ui5_cl_app_hello_world.clas.testclasses.abap new file mode 100644 index 00000000..527a15d1 --- /dev/null +++ b/src/z2ui5_cl_app_hello_world.clas.testclasses.abap @@ -0,0 +1,19 @@ +CLASS ltcl_unit_test DEFINITION FINAL FOR TESTING + DURATION long + RISK LEVEL CRITICAL. + + PRIVATE SECTION. + METHODS first_test FOR TESTING RAISING cx_static_check. + +ENDCLASS. + + +CLASS ltcl_unit_test IMPLEMENTATION. + + METHOD first_test. + + DATA(lo_app) = NEW z2ui5_cl_app_hello_world( ) ##NEEDED. + + ENDMETHOD. + +ENDCLASS. diff --git a/src/z2ui5_cl_app_hello_world.clas.xml b/src/z2ui5_cl_app_hello_world.clas.xml index cae09c60..513914f6 100644 --- a/src/z2ui5_cl_app_hello_world.clas.xml +++ b/src/z2ui5_cl_app_hello_world.clas.xml @@ -10,6 +10,7 @@ X X X + X diff --git a/src/z2ui5_cl_http_handler.clas.abap b/src/z2ui5_cl_http_handler.clas.abap index 5c42d7cf..a3c62068 100644 --- a/src/z2ui5_cl_http_handler.clas.abap +++ b/src/z2ui5_cl_http_handler.clas.abap @@ -4,6 +4,13 @@ CLASS z2ui5_cl_http_handler DEFINITION PUBLIC SECTION. + + CLASS-METHODS http_post + IMPORTING + body TYPE string + RETURNING + VALUE(result) TYPE string. + CLASS-METHODS http_get IMPORTING t_config TYPE z2ui5_if_client=>ty_t_name_value OPTIONAL @@ -13,12 +20,6 @@ CLASS z2ui5_cl_http_handler DEFINITION RETURNING VALUE(r_result) TYPE string. - CLASS-METHODS http_post - IMPORTING - body TYPE string - RETURNING - VALUE(result) TYPE string. - PROTECTED SECTION. PRIVATE SECTION. @@ -31,7 +32,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION. METHOD http_get. - DATA(lt_Config) = t_config. + DATA(lt_config) = t_config. IF lt_config IS INITIAL. lt_config = VALUE #( @@ -49,8 +50,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION. ELSE. lv_sec_policy = content_security_policy. ENDIF. - z2ui5_lcl_fw_db=>cleanup( ). - + z2ui5_cl_fw_db=>cleanup( ). r_result = `` && |\n| && `` && |\n| && @@ -76,360 +76,359 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION. `
` && |\n| && `` && |\n| && `` && |\n|. - r_result = r_result && `` && |\n| && + + r_result = r_result && `` && |\n| && ``. * ` sap.z2ui5.checkLogActive = ` && z2ui5_lcl_utility=>get_json_boolean( check_logging ) && `;` && |\n| && - ENDMETHOD. METHOD http_post. - DATA(lo_handler) = z2ui5_lcl_fw_handler=>request_begin( body ). + DATA(lo_handler) = z2ui5_cl_fw_handler=>request_begin( body ). DO. TRY. ROLLBACK WORK. - CAST z2ui5_if_app( lo_handler->ms_db-o_app )->main( NEW z2ui5_lcl_fw_client( lo_handler ) ). + CAST z2ui5_if_app( lo_handler->ms_db-app )->main( NEW z2ui5_cl_fw_client( lo_handler ) ). ROLLBACK WORK. IF lo_handler->ms_next-o_app_leave IS NOT INITIAL. @@ -445,7 +444,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION. result = lo_handler->request_end( ). CATCH cx_root INTO DATA(x). - lo_handler = z2ui5_lcl_fw_handler=>set_app_system( x ). + lo_handler = z2ui5_cl_fw_handler=>set_app_system( x ). CONTINUE. ENDTRY. diff --git a/src/z2ui5_cl_http_handler.clas.locals_imp.abap b/src/z2ui5_cl_http_handler.clas.locals_imp.abap deleted file mode 100644 index 12612556..00000000 --- a/src/z2ui5_cl_http_handler.clas.locals_imp.abap +++ /dev/null @@ -1,1957 +0,0 @@ -CLASS z2ui5_lcl_utility DEFINITION INHERITING FROM cx_no_check. - - PUBLIC SECTION. - - TYPES: - BEGIN OF ty_attri, - name TYPE string, - type_kind TYPE string, - type TYPE string, - bind_type TYPE string, - data_stringify TYPE string, - data_rtti TYPE string, - check_ref_data TYPE abap_bool, - END OF ty_attri. - TYPES ty_t_attri TYPE STANDARD TABLE OF ty_attri WITH EMPTY KEY. - - DATA: - BEGIN OF ms_error, - x_root TYPE REF TO cx_root, - uuid TYPE string, - text TYPE string, - END OF ms_error. - - METHODS constructor - IMPORTING - val TYPE any OPTIONAL - previous TYPE REF TO cx_root OPTIONAL - PREFERRED PARAMETER val. - - METHODS get_text REDEFINITION. - - CLASS-METHODS get_classname_by_ref - IMPORTING in TYPE REF TO object - RETURNING VALUE(result) TYPE string. - - CLASS-METHODS raise - IMPORTING - v TYPE clike DEFAULT `CX_SY_SUBRC` - when TYPE abap_bool DEFAULT abap_true - PREFERRED PARAMETER v. - - CLASS-METHODS get_uuid - RETURNING VALUE(result) TYPE string. - - CLASS-METHODS get_uuid_session - RETURNING - VALUE(result) TYPE string. - - CLASS-METHODS get_user_tech - RETURNING VALUE(result) TYPE string. - - CLASS-METHODS trans_any_2_json - IMPORTING any TYPE any - RETURNING VALUE(result) TYPE string. - - CLASS-METHODS trans_xml_2_object - IMPORTING xml TYPE clike - EXPORTING data TYPE data. - - CLASS-METHODS get_t_attri_by_ref - IMPORTING io_app TYPE REF TO object - RETURNING VALUE(result) TYPE ty_t_attri ##NEEDED. - - CLASS-METHODS trans_object_2_xml - IMPORTING - object TYPE data - RETURNING - VALUE(result) TYPE string - RAISING cx_xslt_serialization_error. - - CLASS-METHODS get_abap_2_json - IMPORTING val TYPE any - RETURNING VALUE(result) TYPE string. - - CLASS-METHODS check_is_boolean - IMPORTING val TYPE any - RETURNING VALUE(result) TYPE abap_bool. - - CLASS-METHODS get_json_boolean - IMPORTING val TYPE any - RETURNING VALUE(result) TYPE string. - - CLASS-METHODS trans_ref_tab_2_tab - IMPORTING ir_tab_from TYPE REF TO data - EXPORTING t_result TYPE STANDARD TABLE. - - CLASS-METHODS get_trim_upper - IMPORTING val TYPE any - RETURNING VALUE(result) TYPE string. - - CLASS-METHODS _get_t_attri_by_struc - IMPORTING io_app TYPE REF TO object - iv_attri TYPE csequence - RETURNING VALUE(result) TYPE abap_attrdescr_tab. - - CLASS-METHODS rtti_get - IMPORTING - data TYPE any - RETURNING - VALUE(result) TYPE string. - - CLASS-METHODS rtti_set - IMPORTING - rtti_data TYPE string - EXPORTING - e_data TYPE REF TO data. - - CLASS-METHODS get_timestampl - RETURNING - VALUE(result) TYPE timestampl. - - CLASS-METHODS get_param - IMPORTING - val TYPE string - RETURNING - VALUE(r_result) TYPE string. - - PROTECTED SECTION. - CLASS-DATA mv_counter TYPE i. - -ENDCLASS. - -CLASS z2ui5_lcl_utility_tree_json DEFINITION. - - PUBLIC SECTION. - - DATA mo_root TYPE REF TO z2ui5_lcl_utility_tree_json. - DATA mo_parent TYPE REF TO z2ui5_lcl_utility_tree_json. - DATA mv_name TYPE string. - DATA mv_value TYPE string. - DATA mt_values TYPE STANDARD TABLE OF REF TO z2ui5_lcl_utility_tree_json WITH EMPTY KEY. - DATA mv_check_list TYPE abap_bool. - DATA mr_actual TYPE REF TO data. - DATA mv_apost_active TYPE abap_bool. - - CLASS-METHODS new - IMPORTING io_root TYPE REF TO z2ui5_lcl_utility_tree_json - iv_name TYPE simple - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_utility_tree_json. - - CLASS-METHODS factory - IMPORTING iv_json TYPE clike OPTIONAL - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_utility_tree_json. - - METHODS constructor. - - METHODS get_root - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_utility_tree_json. - - METHODS get_attribute - IMPORTING name TYPE string - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_utility_tree_json. - - METHODS get_val - RETURNING VALUE(result) TYPE string. - - METHODS add_attribute - IMPORTING n TYPE clike - v TYPE clike - apos_active TYPE abap_bool DEFAULT abap_true - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_utility_tree_json. - - METHODS add_attribute_object - IMPORTING name TYPE clike - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_utility_tree_json. - - METHODS add_attribute_struc - IMPORTING val TYPE data - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_utility_tree_json. - - METHODS add_attribute_instance - IMPORTING val TYPE REF TO z2ui5_lcl_utility_tree_json - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_utility_tree_json. - - METHODS stringify - RETURNING VALUE(result) TYPE string. - - PROTECTED SECTION. - METHODS wrap_json - IMPORTING iv_text TYPE string - RETURNING VALUE(result) TYPE string. - - METHODS quote_json - IMPORTING iv_text TYPE string - iv_cond TYPE abap_bool - RETURNING VALUE(result) TYPE string. - -ENDCLASS. - - - -CLASS z2ui5_lcl_fw_handler DEFINITION. - - PUBLIC SECTION. - - CONSTANTS: - BEGIN OF cs_bind_type, - one_way TYPE string VALUE 'ONE_WAY', - two_way TYPE string VALUE 'TWO_WAY', - one_time TYPE string VALUE 'ONE_TIME', - END OF cs_bind_type. - - TYPES: - BEGIN OF ty_s_next2, - t_scroll TYPE z2ui5_if_client=>ty_t_name_value, - title TYPE string, - search TYPE string, - BEGIN OF s_view, - xml TYPE string, - check_destroy TYPE abap_bool, - check_update_model TYPE abap_bool, - END OF s_view, - BEGIN OF s_view_nest, - xml TYPE string, - id TYPE string, - method_insert TYPE string, - method_destroy TYPE string, - check_destroy TYPE abap_bool, - check_update_model TYPE abap_bool, - END OF s_view_nest, - BEGIN OF s_popup, - xml TYPE string, - id TYPE string, - check_destroy TYPE abap_bool, - check_update_model TYPE abap_bool, - END OF s_popup, - BEGIN OF s_popover, - xml TYPE string, - id TYPE string, - open_by_id TYPE string, - check_destroy TYPE abap_bool, - check_update_model TYPE abap_bool, - END OF s_popover, - BEGIN OF s_cursor, - id TYPE string, - cursorpos TYPE string, - selectionstart TYPE string, - selectionend TYPE string, - END OF s_cursor, - BEGIN OF s_timer, - interval_ms TYPE string, - event_finished TYPE string, - action_finished TYPE string, - END OF s_timer, - BEGIN OF s_msg_box, - type TYPE string, - text TYPE string, - END OF s_msg_box, - BEGIN OF s_msg_toast, - text TYPE string, - END OF s_msg_toast, - _viewmodel TYPE string, - END OF ty_s_next2. - - TYPES: - BEGIN OF ty_s_db, - id TYPE string, - id_prev TYPE string, - id_prev_app TYPE string, - id_prev_app_stack TYPE string, - t_attri TYPE z2ui5_lcl_utility=>ty_t_attri, - o_app TYPE REF TO z2ui5_if_app, - END OF ty_s_db. - - CLASS-DATA ss_config TYPE z2ui5_if_client=>ty_s_config. - - DATA ms_db TYPE ty_s_db. - - TYPES: - BEGIN OF ty_s_next, - o_app_call TYPE REF TO z2ui5_if_app, - o_app_leave TYPE REF TO z2ui5_if_app, - s_set TYPE ty_s_next2, - END OF ty_s_next. - - DATA ms_actual TYPE z2ui5_if_client=>ty_s_get. - DATA ms_next TYPE ty_s_next. - - CLASS-DATA so_body TYPE REF TO z2ui5_lcl_utility_tree_json. - - CLASS-METHODS request_begin - IMPORTING - body TYPE string - RETURNING - VALUE(result) TYPE REF TO z2ui5_lcl_fw_handler. - - METHODS request_end - RETURNING VALUE(result) TYPE string. - - METHODS _create_binding - IMPORTING value TYPE data - type TYPE string DEFAULT cs_bind_type-two_way - RETURNING VALUE(result) TYPE string. - - CLASS-METHODS set_app_start - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_fw_handler. - - CLASS-METHODS set_app_client - IMPORTING - id_prev TYPE clike - RETURNING - VALUE(result) TYPE REF TO z2ui5_lcl_fw_handler. - - METHODS set_app_leave - IMPORTING - check_no_db_save TYPE abap_bool DEFAULT abap_false - RETURNING - VALUE(result) TYPE REF TO z2ui5_lcl_fw_handler. - - METHODS set_app_call - IMPORTING - check_no_db_save TYPE abap_bool DEFAULT abap_false - RETURNING - VALUE(result) TYPE REF TO z2ui5_lcl_fw_handler. - - CLASS-METHODS set_app_system - IMPORTING VALUE(ix) TYPE REF TO cx_root OPTIONAL - error_text TYPE string OPTIONAL - PREFERRED PARAMETER ix - RETURNING VALUE(result) TYPE REF TO z2ui5_lcl_fw_handler. - - CLASS-METHODS model_set_backend - IMPORTING - model TYPE REF TO data - app TYPE REF TO object - t_attri TYPE z2ui5_lcl_utility=>ty_t_attri. - - CLASS-METHODS model_set_frontend - IMPORTING - app TYPE REF TO object - t_attri TYPE z2ui5_lcl_utility=>ty_t_attri - RETURNING - VALUE(result) TYPE string. - - METHODS app_set_next - IMPORTING - app TYPE REF TO z2ui5_if_app - RETURNING - VALUE(r_result) TYPE REF TO z2ui5_lcl_fw_handler. - -ENDCLASS. - - -CLASS z2ui5_lcl_utility IMPLEMENTATION. - - METHOD get_trim_upper. - result = CONV #( val ). - result = to_upper( shift_left( shift_right( result ) ) ). - ENDMETHOD. - - METHOD constructor. - - super->constructor( previous = previous ). - CLEAR textid. - - TRY. - ms_error-x_root ?= val. - CATCH cx_root ##CATCH_ALL. - ms_error-text = val. - ENDTRY. - - TRY. - ms_error-uuid = get_uuid( ). - CATCH cx_root ##CATCH_ALL. - ENDTRY. - ENDMETHOD. - - METHOD get_abap_2_json. - - IF check_is_boolean( val ). - result = COND #( WHEN val = abap_true THEN `true` ELSE `false` ). - ELSE. - result = |"{ escape( val = val format = cl_abap_format=>e_json_string ) }"|. - ENDIF. - - ENDMETHOD. - - METHOD check_is_boolean. - TRY. - DATA(lo_ele) = CAST cl_abap_elemdescr( cl_abap_elemdescr=>describe_by_data( val ) ). - CASE lo_ele->get_relative_name( ). - WHEN `ABAP_BOOL` OR `ABAP_BOOLEAN` OR `XSDBOOLEAN`. - result = abap_true. - ENDCASE. - CATCH cx_root. - ENDTRY. - ENDMETHOD. - - METHOD get_json_boolean. - IF check_is_boolean( val ). - result = COND #( WHEN val = abap_true THEN `true` ELSE `false` ). - ELSE. - result = val. - ENDIF. - ENDMETHOD. - - METHOD get_timestampl. - GET TIME STAMP FIELD result. - ENDMETHOD. - - - METHOD get_user_tech. - result = sy-uname. - ENDMETHOD. - - METHOD get_uuid. - TRY. - - DATA uuid TYPE c LENGTH 32. - - TRY. - CALL METHOD (`CL_SYSTEM_UUID`)=>if_system_uuid_static~create_uuid_c32 - RECEIVING - uuid = uuid. - - CATCH cx_sy_dyn_call_illegal_class. - - DATA(lv_fm) = `GUID_CREATE`. - CALL FUNCTION lv_fm - IMPORTING - ev_guid_32 = uuid. - - ENDTRY. - - result = uuid. - - CATCH cx_root. - ASSERT 1 = 0. - ENDTRY. - ENDMETHOD. - - METHOD get_uuid_session. - - mv_counter = mv_counter + 1. - result = get_trim_upper( mv_counter ). - - ENDMETHOD. - - - METHOD get_t_attri_by_ref. - - DATA(lt_attri) = CAST cl_abap_classdescr( cl_abap_objectdescr=>describe_by_object_ref( io_app ) )->attributes. - - DELETE lt_attri WHERE visibility <> cl_abap_classdescr=>public. - - LOOP AT lt_attri INTO DATA(ls_attri) - WHERE type_kind = cl_abap_classdescr=>typekind_struct2 - OR type_kind = cl_abap_classdescr=>typekind_struct1. - - DELETE lt_attri INDEX sy-tabix. - - INSERT LINES OF _get_t_attri_by_struc( io_app = io_app - iv_attri = ls_attri-name ) INTO TABLE lt_attri. - - ENDLOOP. - - LOOP AT lt_attri INTO ls_attri. - - DATA(ls_attri2) = VALUE ty_attri( ). - ls_attri2 = CORRESPONDING #( ls_attri ). - - FIELD-SYMBOLS TYPE any. - UNASSIGN . - DATA(lv_assign) = `IO_APP->` && ls_attri-name. - ASSIGN (lv_assign) TO . - - DATA(lo_descr) = cl_abap_datadescr=>describe_by_data( ). - TRY. - DATA(lo_refdescr) = CAST cl_abap_refdescr( lo_descr ). - DATA(lo_reftype) = CAST cl_abap_datadescr( lo_refdescr->get_referenced_type( ) ) ##NEEDED. - ls_attri2-check_ref_data = abap_true. - CATCH cx_root. - ENDTRY. - - APPEND ls_attri2 TO result. - ENDLOOP. - - ENDMETHOD. - - METHOD _get_t_attri_by_struc. - - CONSTANTS c_prefix TYPE string VALUE `IO_APP->`. - FIELD-SYMBOLS TYPE any. - - DATA(lv_name) = c_prefix && to_upper( iv_attri ). - ASSIGN (lv_name) TO . - raise( when = xsdbool( sy-subrc <> 0 ) ). - - DATA(lo_type) = cl_abap_structdescr=>describe_by_data( ). - DATA(lo_struct) = CAST cl_abap_structdescr( lo_type ). - - LOOP AT lo_struct->get_components( ) REFERENCE INTO DATA(lr_comp). - - DATA(lv_element) = iv_attri && `-` && lr_comp->name. - - IF lr_comp->as_include = abap_true. - INSERT LINES OF _get_t_attri_by_struc( io_app = io_app - iv_attri = lv_element ) INTO TABLE result. - - ELSE. - INSERT VALUE #( name = lv_element - type_kind = lr_comp->type->type_kind ) INTO TABLE result. - ENDIF. - - ENDLOOP. - ENDMETHOD. - - METHOD trans_any_2_json. - result = /ui2/cl_json=>serialize( any ). - ENDMETHOD. - - METHOD rtti_get. - - TRY. - - DATA srtti TYPE REF TO object. - - CALL METHOD ('ZCL_SRTTI_TYPEDESCR')=>('CREATE_BY_DATA_OBJECT') - EXPORTING - data_object = data - RECEIVING - srtti = srtti. - - CALL TRANSFORMATION id SOURCE srtti = srtti dobj = data RESULT XML result. - - CATCH cx_root. - DATA(lv_link) = `https://github.com/sandraros/S-RTTI`. - DATA(lv_text) = `

Please install the open-source project S-RTTI by sandraros and try again: (link)

`. - - RAISE EXCEPTION TYPE z2ui5_lcl_utility - EXPORTING - val = lv_text. - - ENDTRY. - - ENDMETHOD. - - METHOD rtti_set. - - TRY. - - DATA srtti TYPE REF TO object. - CALL TRANSFORMATION id SOURCE XML rtti_data RESULT srtti = srtti. - - DATA rtti_type TYPE REF TO cl_abap_typedescr. - CALL METHOD srtti->('GET_RTTI') - RECEIVING - rtti = rtti_type. - - DATA lo_datadescr TYPE REF TO cl_abap_datadescr. - lo_datadescr ?= rtti_type. - - CREATE DATA e_data TYPE HANDLE lo_datadescr. - ASSIGN e_data->* TO FIELD-SYMBOL(). - CALL TRANSFORMATION id SOURCE XML rtti_data RESULT dobj = . - - CATCH cx_root. - DATA(lv_link) = `https://github.com/sandraros/S-RTTI`. - DATA(lv_text) = `

Please install the open-source project S-RTTI by sandraros and try again: (link)

`. - - RAISE EXCEPTION TYPE z2ui5_lcl_utility - EXPORTING - val = lv_text. - - ENDTRY. - - ENDMETHOD. - - METHOD get_classname_by_ref. - DATA(lv_classname) = cl_abap_classdescr=>get_class_name( in ). - result = substring_after( val = lv_classname sub = `\CLASS=` ). - ENDMETHOD. - - METHOD trans_object_2_xml. - - FIELD-SYMBOLS TYPE any. - - ASSIGN object->* TO . - raise( when = xsdbool( sy-subrc <> 0 ) ). - - CALL TRANSFORMATION id - SOURCE data = - RESULT XML result - OPTIONS data_refs = `heap-or-create`. - - ENDMETHOD. - - METHOD trans_ref_tab_2_tab. - TYPES ty_t_ref TYPE STANDARD TABLE OF REF TO data. - - FIELD-SYMBOLS TYPE ty_t_ref. - - ASSIGN ir_tab_from->* TO . - raise( when = xsdbool( sy-subrc <> 0 ) ). - - CLEAR t_result. - - DATA(lo_tab) = CAST cl_abap_tabledescr( cl_abap_datadescr=>describe_by_data( t_result ) ). - DATA(lo_struc) = CAST cl_abap_structdescr( lo_tab->get_table_line_type( ) ). - DATA(lt_components) = lo_struc->get_components( ). - - LOOP AT INTO DATA(lr_from). - - DATA lr_row TYPE REF TO data. - CREATE DATA lr_row LIKE LINE OF t_result. - ASSIGN lr_row->* TO FIELD-SYMBOL(). - - ASSIGN lr_from->* TO FIELD-SYMBOL(). - raise( when = xsdbool( sy-subrc <> 0 ) ). - - LOOP AT lt_components INTO DATA(ls_comp). - - FIELD-SYMBOLS TYPE data. - ASSIGN COMPONENT ls_comp-name OF STRUCTURE TO . - IF sy-subrc <> 0. - EXIT. - ENDIF. - - FIELD-SYMBOLS TYPE data. - ASSIGN COMPONENT ls_comp-name OF STRUCTURE TO . - IF sy-subrc <> 0. - EXIT. - ENDIF. - - ASSIGN ->* TO FIELD-SYMBOL(). - IF sy-subrc = 0. - CASE ls_comp-type->kind. - WHEN cl_abap_typedescr=>kind_table. - trans_ref_tab_2_tab( EXPORTING ir_tab_from = - IMPORTING t_result = ). - WHEN OTHERS. - = . - ENDCASE. - ENDIF. - ENDLOOP. - - INSERT INTO TABLE t_result. - ENDLOOP. - ENDMETHOD. - - METHOD trans_xml_2_object. - CALL TRANSFORMATION id - SOURCE XML xml - RESULT data = data. - ENDMETHOD. - - METHOD get_text. - - IF ms_error-x_root IS NOT INITIAL. - result = ms_error-x_root->get_text( ). - DATA(error) = abap_true. - ELSEIF ms_error-text IS NOT INITIAL. - result = ms_error-text. - error = abap_true. - ENDIF. - - IF error = abap_true AND result IS INITIAL. - result = `unknown error`. - ENDIF. - ENDMETHOD. - - METHOD raise. - IF when = abap_false. - RETURN. - ENDIF. - RAISE EXCEPTION TYPE z2ui5_lcl_utility EXPORTING val = v. - ENDMETHOD. - - METHOD get_param. - - DATA(lt_params) = VALUE z2ui5_if_client=>ty_t_name_value( ). - DATA(lv_search) = z2ui5_lcl_fw_handler=>so_body->get_attribute( `OLOCATION` )->get_attribute( `SEARCH` )->get_val( ). - - SPLIT lv_search AT `&sap-startup-params=` INTO DATA(lv_search1) DATA(lv_search2). - IF lv_search2 IS NOT INITIAL. - lv_search = lv_search2. - REPLACE `%3D` IN lv_search WITH `=`. - REPLACE `%26` IN lv_search WITH `&`. - REPLACE `%2509` IN lv_search WITH ``. - ELSE. - lv_search = lv_search1. - ENDIF. - - lv_search = get_trim_upper( lv_search ). - SHIFT lv_search LEFT DELETING LEADING `?`. - - SPLIT lv_search AT `&` INTO TABLE DATA(lt_param). - - LOOP AT lt_param REFERENCE INTO DATA(lr_param). - - SPLIT lr_param->* AT `=` INTO DATA(lv_name) DATA(lv_value). - - INSERT VALUE #( n = lv_name v = lv_value ) INTO TABLE lt_params. - ENDLOOP. - - DATA(lv_val) = get_trim_upper( val ). - r_result = VALUE #( lt_params[ n = lv_val ]-v OPTIONAL ). - - ENDMETHOD. - -ENDCLASS. - - - -CLASS z2ui5_lcl_utility_tree_json IMPLEMENTATION. - - METHOD add_attribute. - - DATA(lo_attri) = new( io_root = mo_root iv_name = n ). - - IF apos_active = abap_false. - lo_attri->mv_value = v. - ELSE. - lo_attri->mv_value = escape( val = v format = cl_abap_format=>e_json_string ). - ENDIF. - lo_attri->mv_apost_active = apos_active. - lo_attri->mo_parent = me. - - INSERT lo_attri INTO TABLE mt_values. - result = me. - - ENDMETHOD. - - METHOD add_attribute_instance. - - val->mo_root = mo_root. - val->mo_parent = me. - INSERT val INTO TABLE mt_values. - result = val. - - ENDMETHOD. - - METHOD add_attribute_struc. - - FIELD-SYMBOLS TYPE any. - - DATA(lo_struc) = CAST cl_abap_structdescr( cl_abap_datadescr=>describe_by_data( val ) ). - DATA(lt_comp) = lo_struc->get_components( ). - - LOOP AT lt_comp REFERENCE INTO DATA(lr_comp). - ASSIGN COMPONENT lr_comp->name OF STRUCTURE val TO . - add_attribute( n = lr_comp->name v = ). - ENDLOOP. - - result = me. - - ENDMETHOD. - - METHOD add_attribute_object. - - DATA(lo_attri) = new( io_root = mo_root iv_name = name ). - mt_values = VALUE #( BASE mt_values ( lo_attri ) ). - lo_attri->mo_parent = me. - result = lo_attri. - - ENDMETHOD. - - METHOD constructor. - mo_root = me. - ENDMETHOD. - - METHOD factory. - - result = NEW #( ). - result->mo_root = result. - - - /ui2/cl_json=>deserialize( EXPORTING json = CONV string( iv_json ) - assoc_arrays = abap_true - CHANGING data = result->mr_actual ). - - ENDMETHOD. - - METHOD new. - - result = NEW #( ). - result->mo_root = io_root. - result->mv_name = CONV string( iv_name ). - - ENDMETHOD. - - METHOD get_attribute. - - z2ui5_lcl_utility=>raise( when = xsdbool( mr_actual IS INITIAL ) ). - DATA(lo_attri) = new( io_root = mo_root iv_name = name ). - - FIELD-SYMBOLS TYPE any. - DATA(lv_name) = 'MR_ACTUAL->' && replace( val = name sub = `-` with = `_` occ = 0 ). - ASSIGN (lv_name) TO . - z2ui5_lcl_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ). - - lo_attri->mr_actual = . - lo_attri->mo_parent = me. - - INSERT lo_attri INTO TABLE mt_values. - result = lo_attri. - - ENDMETHOD. - - METHOD get_val. - - FIELD-SYMBOLS TYPE any. - ASSIGN mr_actual->* TO . - z2ui5_lcl_utility=>raise( when = xsdbool( sy-subrc <> 0 ) v = `Value of Attribute in JSON not found` ). - - result = . - - ENDMETHOD. - - METHOD get_root. - result = mo_root. - ENDMETHOD. - - METHOD wrap_json. - result = SWITCH #( mv_check_list - WHEN abap_true THEN |[ { iv_text }]| ELSE `{` && iv_text && `}` ). - ENDMETHOD. - - METHOD quote_json. - result = SWITCH #( iv_cond - WHEN abap_true THEN `"` && iv_text && `"` ELSE iv_text ). - ENDMETHOD. - - METHOD stringify. - LOOP AT mt_values INTO DATA(lo_attri). - - IF sy-tabix > 1. - result = result && |,|. - ENDIF. - - IF mv_check_list = abap_false. - result = |{ result }"{ lo_attri->mv_name }":|. - ENDIF. - - IF lo_attri->mt_values IS NOT INITIAL. - result = result && lo_attri->stringify( ). - ELSE. - result = result && - quote_json( iv_cond = xsdbool( lo_attri->mv_apost_active = abap_true OR lo_attri->mv_value IS INITIAL ) - iv_text = lo_attri->mv_value ). - ENDIF. - - ENDLOOP. - - result = wrap_json( result ). - ENDMETHOD. -ENDCLASS. - -CLASS z2ui5_lcl_fw_db DEFINITION. - - PUBLIC SECTION. - - CLASS-METHODS create - IMPORTING - id TYPE string - db TYPE z2ui5_lcl_fw_handler=>ty_s_db. - - CLASS-METHODS load_app - IMPORTING id TYPE clike - RETURNING VALUE(result) TYPE z2ui5_lcl_fw_handler=>ty_s_db. - - CLASS-METHODS read - IMPORTING id TYPE clike - check_load_app TYPE abap_bool DEFAULT abap_true - RETURNING VALUE(result) TYPE z2ui5_t_draft. - - CLASS-METHODS cleanup. - -ENDCLASS. - - -CLASS z2ui5_lcl_fw_app DEFINITION. - - PUBLIC SECTION. - - INTERFACES z2ui5_if_app. - - DATA: - BEGIN OF ms_error, - x_error TYPE REF TO cx_root, - END OF ms_error. - - DATA: - BEGIN OF ms_home, - btn_text TYPE string, - btn_event_id TYPE string, - btn_icon TYPE string, - classname TYPE string, - class_value_state TYPE string, - class_value_state_text TYPE string, - class_editable TYPE abap_bool VALUE abap_true, - END OF ms_home. - - CLASS-METHODS factory_error - IMPORTING - error TYPE REF TO cx_root - RETURNING - VALUE(result) TYPE REF TO z2ui5_lcl_fw_app. - - DATA mv_is_initialized TYPE abap_bool. - - DATA client TYPE REF TO z2ui5_if_client. - - METHODS z2ui5_on_init. - METHODS z2ui5_on_event. - METHODS view_display_error. - METHODS view_display_start. - - PRIVATE SECTION. - DATA lv_check_demo TYPE abap_bool. - -ENDCLASS. - - -CLASS z2ui5_lcl_fw_app IMPLEMENTATION. - - METHOD z2ui5_if_app~main. - - me->client = client. - - IF mv_is_initialized = abap_false. - mv_is_initialized = abap_true. - z2ui5_on_init( ). - ENDIF. - - z2ui5_on_event( ). - - IF ms_error-x_error IS BOUND. - view_display_error( ). - ELSE. - view_display_start( ). - ENDIF. - - ENDMETHOD. - - METHOD factory_error. - - result = NEW #( ). - result->ms_error-x_error = error. - - ENDMETHOD. - - METHOD z2ui5_on_init. - - IF ms_error-x_error IS NOT BOUND. - ms_home-btn_text = `check`. - ms_home-btn_event_id = `BUTTON_CHECK`. - ms_home-class_editable = abap_true. - ms_home-btn_icon = `sap-icon://validate`. - ms_home-classname = `z2ui5_cl_app_hello_world`. - ENDIF. - - lv_check_demo = abap_true. - - ENDMETHOD. - - METHOD z2ui5_on_event. - - CASE client->get( )-event. - - WHEN `BUTTON_CHANGE`. - ms_home-btn_text = `check`. - ms_home-btn_event_id = `BUTTON_CHECK`. - ms_home-btn_icon = `sap-icon://validate`. - ms_home-class_editable = abap_true. - - WHEN `BUTTON_CHECK`. - TRY. - DATA li_app_test TYPE REF TO z2ui5_if_app. - ms_home-classname = z2ui5_lcl_utility=>get_trim_upper( ms_home-classname ). - CREATE OBJECT li_app_test TYPE (ms_home-classname). - - client->message_toast_display( `App is ready to start!` ). - ms_home-btn_text = `edit`. - ms_home-btn_event_id = `BUTTON_CHANGE`. - ms_home-btn_icon = `sap-icon://edit`. - ms_home-class_value_state = `Success`. - ms_home-class_editable = abap_false. - - CATCH cx_root INTO DATA(lx) ##CATCH_ALL. - ms_home-class_value_state_text = lx->get_text( ). - ms_home-class_value_state = `Warning`. - client->message_box_display( text = ms_home-class_value_state_text type = `error` ). - ENDTRY. - - WHEN `DEMOS`. - - DATA li_app TYPE REF TO z2ui5_if_app. - TRY. - CREATE OBJECT li_app TYPE (`Z2UI5_CL_APP_DEMO_00`). - lv_check_demo = abap_true. - client->nav_app_call( li_app ). - CATCH cx_root. - lv_check_demo = abap_false. - ENDTRY. - - ENDCASE. - - ENDMETHOD. - - - METHOD view_display_error. - - WHILE ms_error-x_error->previous IS BOUND. - ms_error-x_error = ms_error-x_error->previous. - ENDWHILE. - - DATA(lv_txt) = ms_error-x_error->get_text( ). - DATA(lv_descr) = escape( val = lv_txt format = cl_abap_format=>e_xml_attr ). - - DATA(ls_get) = client->get( ). - DATA(lv_url) = ls_get-s_config-origin && ls_get-s_config-pathname. - SHIFT lv_url LEFT DELETING LEADING ` `. - DATA(lv_url_app) = lv_url && ls_get-s_config-search. - lv_url = escape( val = lv_url format = cl_abap_format=>e_xml_attr ). - lv_url_app = escape( val = lv_url_app format = cl_abap_format=>e_xml_attr ). - - DATA(lv_xml) = ` ` && |\n| && - ` ` && - `