` && 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)