├── .abapgit.xml ├── LICENSE ├── README.md ├── _config.yml ├── docs └── img │ └── retrieve_keys.JPG └── src ├── package.devc.xml ├── zabapfire_cl_firebase.clas.abap ├── zabapfire_cl_firebase.clas.xml ├── zabapfire_cl_firebase_auth.clas.abap ├── zabapfire_cl_firebase_auth.clas.xml ├── zabapfire_cl_firebase_db.clas.abap ├── zabapfire_cl_firebase_db.clas.xml ├── zabapfire_cl_http_util.clas.abap ├── zabapfire_cl_http_util.clas.xml ├── zabapfire_cl_json_deserializer.clas.abap ├── zabapfire_cl_json_deserializer.clas.xml ├── zabapfire_cl_json_node.clas.abap ├── zabapfire_cl_json_node.clas.xml ├── zabapfire_cl_json_serializer.clas.abap ├── zabapfire_cl_json_serializer.clas.xml ├── zabapfire_demo.prog.abap ├── zabapfire_demo.prog.xml ├── zabapfire_msg.msag.xml ├── zcx_abapfire_firebase.clas.abap ├── zcx_abapfire_firebase.clas.xml ├── zcx_abapfire_json.clas.abap └── zcx_abapfire_json.clas.xml /.abapgit.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | E 6 | /src/ 7 | PREFIX 8 | 9 | /.gitignore 10 | /LICENSE 11 | /README.md 12 | /package.json 13 | /.travis.yml 14 | /_config.yml 15 | /docs/img/retrieve_keys.JPG 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 inquaero 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Tested SAP release: ABAP 740 SP9](https://img.shields.io/badge/ABAP-740%20SP9-green.svg?style=flat) 2 | 3 | # ABAPFire # 4 | ABAP Firebase REST API Helper Library 5 | 6 | ## Installation ## 7 | 8 | ### Clone it using abapGit ## 9 | 10 | Install [abapGit](http://larshp.github.io/abapGit/guide-install.html), then clone the repository in a package (e.g. $ABAPFIRE). 11 | 12 | ### Install Google certificate ### 13 | 14 | Install Root CA from [Google Internet Authority G2](https://pki.google.com/) using transaction STRUST in SSL identity ANONYMOUS. 15 | 16 | ## Usage ## 17 | 18 | Program [ZABAPFIRE_DEMO](src/zabapfire_demo.prog.abap) provides usage examples. 19 | 20 | ### Initialize the Application ### 21 | 22 | To initialize the library, just pass to it your firebase configuration: 23 | 24 | ```abap 25 | DATA: 26 | firebase TYPE REF TO zabapfire_cl_firebase, 27 | ls_config TYPE zabapfire_cl_firebase=>ty_firebase_config. 28 | 29 | ls_config-apikey = '[your apikey]'. 30 | ls_config-authdomain = '[your authdomain]'. 31 | ls_config-databaseurl = '[your databaseurl]'. 32 | ls_config-messagingsenderid = '[your messagingsenderid]'. 33 | ls_config-projectid = '[your projectid]'. 34 | ls_config-storagebucket = '[your storagebucket]'. 35 | 36 | firebase = zabapfire_cl_firebase=>initialize_app( ls_config ). 37 | ``` 38 | 39 | ### User Authentication ### 40 | 41 | The library support only email and password authentication: 42 | 43 | ```abap 44 | TRY. 45 | firebase->auth->authenticate_with_email( 46 | EXPORTING 47 | email = p_email 48 | password = p_pass ). 49 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 50 | WRITE lcx_firebase->get_text( ). 51 | 52 | ENDTRY. 53 | ``` 54 | 55 | ### Retrieve firebase data ### 56 | 57 | ```abap 58 | TRY. 59 | ls_parameters-order_by = 'carrid'. 60 | ls_parameters-equal_to = 'AC'. 61 | firebase->db->get( 62 | EXPORTING 63 | path = p_path 64 | parameters = ls_parameters 65 | IMPORTING 66 | child = lt_abap ). 67 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 68 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 69 | DISPLAY LIKE 'E'. 70 | EXIT. 71 | ENDTRY. 72 | 73 | ``` 74 | 75 | If your target ABAP structure contains a column with name $KEY, firebase generated unique keys are saved in this column: 76 | 77 | ```abap 78 | TYPES: 79 | BEGIN OF ty_abap, 80 | $key TYPE string. 81 | INCLUDE STRUCTURE sflight. 82 | TYPES: 83 | END OF ty_abap 84 | ``` 85 | ![retrieve firebase keys](/docs/img/retrieve_keys.JPG) 86 | 87 | For data retrieving, following query parameters are supported: 88 | * **shallow**: Limit the depth of the data returned. If the data at the location is a JSON primitive (string, number, or boolean) its value will simply be returned. If the data snapshot at the location is a JSON object, the values for each key will be truncated to true. 89 | * **orderBy**: Set a sequence order that can be used to filter the data in combination with startAt endAt and equalTo parameters. 90 | * **startAt**: Set an arbitrary starting point. 91 | * **endAt**: Set an arbitrary ending point. 92 | * **equalTo**: Filter on specific value. 93 | * **limitToFirst**: Set a maximum number of children for which to receive data. 94 | * **limitToLast**: Set a maximum number of children for which to receive data in reverse order. 95 | 96 | Refer to official [firebase documentation](https://firebase.google.com/docs/database/rest/retrieve-data) for more info. 97 | 98 | ### Save data to firebase ### 99 | 100 | #### Set #### 101 | 102 | Writes data to firebase Database location. 103 | This will overwrite any data at this location and all child locations. 104 | 105 | ```abap 106 | SELECT * FROM sflight 107 | INTO CORRESPONDING FIELDS OF TABLE lt_abap. 108 | TRY. 109 | firebase->db->set( 110 | EXPORTING 111 | path = p_path 112 | child = lt_abap ). 113 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 114 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 115 | DISPLAY LIKE 'E'. 116 | EXIT. 117 | ENDTRY. 118 | ``` 119 | 120 | #### Update #### 121 | 122 | As opposed to the set( ) method, update( ) can be use to selectively update only the referenced properties at the current location (instead of replacing all the child properties at the current location). 123 | 124 | 125 | ```abap 126 | TRY. 127 | firebase->db->update( 128 | EXPORTING 129 | path = p_path 130 | child = lt_abap ). 131 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 132 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 133 | DISPLAY LIKE 'E'. 134 | EXIT. 135 | ENDTRY. 136 | ``` 137 | 138 | #### Push #### 139 | 140 | Generates a new child location using a unique key and return the generated unique key. 141 | 142 | ```abap 143 | TRY. 144 | LOOP AT lt_abap ASSIGNING . 145 | -$key = firebase->db->push( 146 | EXPORTING 147 | path = p_path 148 | child = ). 149 | ENDLOOP. 150 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 151 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 152 | DISPLAY LIKE 'E'. 153 | EXIT. 154 | ENDTRY. 155 | ``` 156 | 157 | #### Remove #### 158 | 159 | Removes the data at this firebase Database location. 160 | 161 | ```abap 162 | TRY. 163 | firebase->db->remove( 164 | EXPORTING 165 | path = p_path ). 166 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 167 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 168 | DISPLAY LIKE 'E'. 169 | EXIT. 170 | ENDTRY. 171 | ``` 172 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /docs/img/retrieve_keys.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alborghetti/ABAPFire/667866effd77c13ce1d2a151bd916a79671cc36e/docs/img/retrieve_keys.JPG -------------------------------------------------------------------------------- /src/package.devc.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ABAPFire 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/zabapfire_cl_firebase.clas.abap: -------------------------------------------------------------------------------- 1 | class ZABAPFIRE_CL_FIREBASE definition 2 | public 3 | final 4 | create private . 5 | 6 | public section. 7 | 8 | types: 9 | BEGIN OF ty_firebase_config, 10 | apikey TYPE string, 11 | authdomain TYPE string, 12 | databaseurl TYPE string, 13 | projectid TYPE string, 14 | storagebucket TYPE string, 15 | messagingsenderid TYPE string, 16 | END OF ty_firebase_config . 17 | 18 | data DB type ref to ZABAPFIRE_CL_FIREBASE_DB . 19 | data AUTH type ref to ZABAPFIRE_CL_FIREBASE_AUTH . 20 | 21 | class-methods INITIALIZE_APP 22 | importing 23 | !CONFIG type TY_FIREBASE_CONFIG 24 | !PROXY type STRING optional 25 | !PROXY_PORT type STRING optional 26 | returning 27 | value(RREF_FIREBASE) type ref to ZABAPFIRE_CL_FIREBASE 28 | raising 29 | ZCX_ABAPFIRE_FIREBASE . 30 | methods GET_CONFIG 31 | returning 32 | value(RS_CONFIG) type TY_FIREBASE_CONFIG . 33 | methods GET_CLIENT 34 | returning 35 | value(RREF_HTTP_CLIENT) type ref to IF_HTTP_CLIENT . 36 | methods GET_PROXY_CONF 37 | exporting 38 | !PROXY type STRING 39 | !PROXY_PORT type STRING . 40 | protected section. 41 | private section. 42 | 43 | class-data SREF_FIREBASE type ref to ZABAPFIRE_CL_FIREBASE . 44 | data MV_PROXY type STRING . 45 | data MV_PROXY_PORT type STRING . 46 | data MS_CONFIG type TY_FIREBASE_CONFIG . 47 | data MREF_HTTP_CLIENT type ref to IF_HTTP_CLIENT . 48 | 49 | methods CONSTRUCTOR 50 | importing 51 | !CONFIG type TY_FIREBASE_CONFIG optional 52 | !PROXY type STRING 53 | !PROXY_PORT type STRING 54 | raising 55 | ZCX_ABAPFIRE_FIREBASE . 56 | ENDCLASS. 57 | 58 | 59 | 60 | CLASS ZABAPFIRE_CL_FIREBASE IMPLEMENTATION. 61 | 62 | 63 | METHOD constructor. 64 | DATA lv_url TYPE string. 65 | mv_proxy = proxy. 66 | mv_proxy_port = proxy_port. 67 | * Create API Url 68 | ASSERT CONDITION NOT config-projectid IS INITIAL. 69 | ms_config = config. 70 | lv_url = ms_config-databaseurl. 71 | * Create HTTP Client 72 | CALL METHOD cl_http_client=>create_by_url 73 | EXPORTING 74 | url = lv_url 75 | proxy_host = mv_proxy 76 | proxy_service = mv_proxy_port 77 | ssl_id = 'ANONYM' 78 | IMPORTING 79 | client = mref_http_client 80 | EXCEPTIONS 81 | argument_not_found = 1 82 | plugin_not_active = 2 83 | internal_error = 3 84 | OTHERS = 4. 85 | IF sy-subrc <> 0. 86 | zcx_abapfire_firebase=>raise( 87 | 'HTTP Connection fails' ). "#EC NOTEXT 88 | ENDIF. 89 | 90 | * Create DB Helper 91 | db = zabapfire_cl_firebase_db=>create( me ). 92 | * Create authentication Helper 93 | auth = zabapfire_cl_firebase_auth=>create( me ). 94 | 95 | ENDMETHOD. 96 | 97 | 98 | METHOD get_client. 99 | 100 | rref_http_client = mref_http_client. 101 | 102 | ENDMETHOD. 103 | 104 | 105 | METHOD get_config. 106 | 107 | rs_config = ms_config. 108 | 109 | ENDMETHOD. 110 | 111 | 112 | METHOD get_proxy_conf. 113 | 114 | proxy = mv_proxy. 115 | proxy_port = mv_proxy_port. 116 | 117 | ENDMETHOD. 118 | 119 | 120 | METHOD initialize_app. 121 | 122 | IF sref_firebase IS INITIAL. 123 | CREATE OBJECT sref_firebase 124 | EXPORTING 125 | config = config 126 | proxy = proxy 127 | proxy_port = proxy_port. 128 | 129 | ENDIF. 130 | 131 | rref_firebase = sref_firebase. 132 | 133 | ENDMETHOD. 134 | ENDCLASS. 135 | -------------------------------------------------------------------------------- /src/zabapfire_cl_firebase.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPFIRE_CL_FIREBASE 7 | 1 8 | E 9 | ABAP Firebase REST API Helper 10 | 1 11 | X 12 | X 13 | X 14 | X 15 | 16 | 17 | 18 | ZABAPFIRE_CL_FIREBASE 19 | AUTH 20 | E 21 | ABAP Firebase Authentication Helper 22 | 23 | 24 | ZABAPFIRE_CL_FIREBASE 25 | CONSTRUCTOR 26 | E 27 | Constructor 28 | 29 | 30 | ZABAPFIRE_CL_FIREBASE 31 | DB 32 | E 33 | ABAP Firebase DB Helper 34 | 35 | 36 | ZABAPFIRE_CL_FIREBASE 37 | GET_CLIENT 38 | E 39 | Get HTTP Client 40 | 41 | 42 | ZABAPFIRE_CL_FIREBASE 43 | GET_CONFIG 44 | E 45 | Get application config 46 | 47 | 48 | ZABAPFIRE_CL_FIREBASE 49 | INITIALIZE_APP 50 | E 51 | Initialize Application 52 | 53 | 54 | ZABAPFIRE_CL_FIREBASE 55 | MREF_HTTP_CLIENT 56 | E 57 | HTTP Client 58 | 59 | 60 | ZABAPFIRE_CL_FIREBASE 61 | MV_PROXY 62 | E 63 | Proxy 64 | 65 | 66 | ZABAPFIRE_CL_FIREBASE 67 | MV_PROXY_PORT 68 | E 69 | Proxy Port 70 | 71 | 72 | ZABAPFIRE_CL_FIREBASE 73 | SREF_FIREBASE 74 | E 75 | ABAP Firebase REST API Helper 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/zabapfire_cl_firebase_auth.clas.abap: -------------------------------------------------------------------------------- 1 | class ZABAPFIRE_CL_FIREBASE_AUTH definition 2 | public 3 | final 4 | create private . 5 | 6 | public section. 7 | 8 | types: 9 | BEGIN OF ty_firebase_config, 10 | apikey TYPE string, 11 | authdomain TYPE string, 12 | databaseurl TYPE string, 13 | projectid TYPE string, 14 | storagebucket TYPE string, 15 | messagingsenderid TYPE string, 16 | END OF ty_firebase_config . 17 | 18 | class-methods CREATE 19 | importing 20 | !APPLICATION type ref to ZABAPFIRE_CL_FIREBASE 21 | returning 22 | value(AUTH) type ref to ZABAPFIRE_CL_FIREBASE_AUTH . 23 | methods AUTHENTICATE_WITH_EMAIL 24 | importing 25 | !EMAIL type STRING 26 | !PASSWORD type STRING 27 | raising 28 | ZCX_ABAPFIRE_FIREBASE . 29 | methods GET_TOKEN 30 | returning 31 | value(IDTOKEN) type STRING . 32 | PROTECTED SECTION. 33 | PRIVATE SECTION. 34 | 35 | CONSTANTS cv_url TYPE string VALUE 36 | 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key='. 37 | "#EC NOTEXT 38 | CLASS-DATA sref_auth TYPE REF TO zabapfire_cl_firebase_auth . 39 | DATA application TYPE REF TO zabapfire_cl_firebase . 40 | DATA mv_email TYPE string . "#EC NEEDED 41 | DATA mv_password TYPE string . "#EC NEEDED 42 | DATA mv_id_token TYPE string . 43 | DATA mv_refresh_token TYPE string . "#EC NEEDED 44 | 45 | METHODS constructor 46 | IMPORTING 47 | !application TYPE REF TO zabapfire_cl_firebase . 48 | ENDCLASS. 49 | 50 | 51 | 52 | CLASS ZABAPFIRE_CL_FIREBASE_AUTH IMPLEMENTATION. 53 | 54 | 55 | METHOD authenticate_with_email. 56 | 57 | TYPES: 58 | BEGIN OF lty_payload, 59 | email TYPE string, 60 | password TYPE string, 61 | return_secure_token TYPE abap_bool, 62 | END OF lty_payload, 63 | BEGIN OF lty_response_payload, 64 | kind TYPE string, 65 | local_id TYPE string, 66 | email TYPE string, 67 | display_name TYPE string, 68 | id_token TYPE string, 69 | registered TYPE boolean, 70 | refresh_token TYPE string, 71 | expires_in TYPE string, 72 | END OF lty_response_payload. 73 | 74 | DATA: lv_config 75 | TYPE zabapfire_cl_firebase=>ty_firebase_config, 76 | lv_proxy TYPE string, 77 | lv_proxy_port TYPE string, 78 | lv_http_client TYPE REF TO if_http_client, 79 | lv_body TYPE string, 80 | lv_url TYPE string, 81 | ls_payload TYPE lty_payload, 82 | lref_json_serializer 83 | TYPE REF TO zabapfire_cl_json_serializer, 84 | lv_response_data TYPE string, 85 | lref_json_deserializer 86 | TYPE REF TO zabapfire_cl_json_deserializer, 87 | ls_response_abap TYPE lty_response_payload, 88 | lv_http_status TYPE i, 89 | lcx_json TYPE REF TO zcx_abapfire_json. 90 | 91 | IF email IS INITIAL OR password IS INITIAL. 92 | zcx_abapfire_firebase=>raise( 93 | 'Incorrect authentication parameters (email, password)' 94 | ). "#EC NOTEXT 95 | ELSE. 96 | mv_email = email. 97 | mv_password = password. 98 | ENDIF. 99 | 100 | * Get ApyKey from application configuration 101 | lv_config = application->get_config( ). 102 | CALL METHOD application->get_proxy_conf 103 | IMPORTING 104 | proxy = lv_proxy 105 | proxy_port = lv_proxy_port. 106 | IF lv_config-apikey IS INITIAL. 107 | zcx_abapfire_firebase=>raise( 108 | 'Wrong firebase configuration: APIKEY' ). "#EC NOTEXT 109 | ELSE. 110 | CONCATENATE cv_url lv_config-apikey 111 | INTO lv_url. 112 | ENDIF. 113 | 114 | * Create HTTP Client 115 | CALL METHOD cl_http_client=>create_by_url 116 | EXPORTING 117 | url = lv_url 118 | proxy_host = lv_proxy 119 | proxy_service = lv_proxy_port 120 | ssl_id = 'ANONYM' "#EC NOTEXT 121 | IMPORTING 122 | client = lv_http_client 123 | EXCEPTIONS 124 | argument_not_found = 1 125 | plugin_not_active = 2 126 | internal_error = 3 127 | OTHERS = 4. 128 | 129 | * Get authorization token - begin 130 | lv_http_client->request->set_method( 'POST' ). "#EC NOTEXT 131 | lv_http_client->request->set_content_type( 'application/json' ). 132 | "#EC NOTEXT 133 | 134 | * Build request payload 135 | ls_payload-email = email. 136 | ls_payload-password = password. 137 | ls_payload-return_secure_token = abap_true. 138 | TRY. 139 | CREATE OBJECT lref_json_serializer. 140 | lv_body = lref_json_serializer->serialize( ls_payload ). 141 | CATCH zcx_abapfire_json INTO lcx_json. 142 | zcx_abapfire_firebase=>raise( lcx_json->get_text( ) ). 143 | ENDTRY. 144 | 145 | lv_http_client->request->set_cdata( lv_body ). 146 | 147 | * Send request 148 | CALL METHOD lv_http_client->send 149 | EXCEPTIONS 150 | http_communication_failure = 1 151 | http_invalid_state = 2 152 | http_processing_failed = 3 153 | http_invalid_timeout = 4 154 | OTHERS = 5. 155 | IF sy-subrc NE 0. 156 | zcx_abapfire_firebase=>raise( 157 | 'HTTP Connection fails' ). "#EC NOTEXT 158 | ENDIF. 159 | 160 | * Get response 161 | CALL METHOD lv_http_client->receive 162 | EXCEPTIONS 163 | http_communication_failure = 1 164 | http_invalid_state = 2 165 | http_processing_failed = 3. 166 | IF sy-subrc <> 0. 167 | zcx_abapfire_firebase=>raise( 168 | 'HTTP Connection fails' ). "#EC NOTEXT 169 | ENDIF. 170 | 171 | lv_response_data = lv_http_client->response->get_cdata( ). 172 | REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline 173 | IN lv_response_data WITH ''. 174 | 175 | * Check response code 176 | lv_http_client->response->get_status( 177 | IMPORTING 178 | code = lv_http_status ). 179 | 180 | CASE lv_http_status. 181 | WHEN 302. 182 | zcx_abapfire_firebase=>raise( 183 | 'HTTP redirect, check URL' ). "#EC NOTEXT 184 | WHEN 401. 185 | zcx_abapfire_firebase=>raise( 186 | 'HTTP 401, unauthorized' ). "#EC NOTEXT 187 | WHEN 403. 188 | zcx_abapfire_firebase=>raise( 189 | 'HTTP 403, forbidden' ). "#EC NOTEXT 190 | WHEN 404. 191 | zcx_abapfire_firebase=>raise( 192 | 'HTTP 404, not found' ). "#EC NOTEXT 193 | WHEN 415. 194 | zcx_abapfire_firebase=>raise( 195 | 'HTTP 415, unsupported media type' ). "#EC NOTEXT 196 | WHEN 400. 197 | zcx_abapfire_firebase=>raise( 198 | zabapfire_cl_http_util=>get_http_error_msg( 199 | EXPORTING 200 | code = lv_http_status 201 | api = 'google' "#EC NOTEXT 202 | payload = lv_response_data ) 203 | ). 204 | 205 | ENDCASE. 206 | 207 | * Deserialize JSON Payload 208 | TRY. 209 | CREATE OBJECT lref_json_deserializer. 210 | CALL METHOD lref_json_deserializer->deserialize 211 | EXPORTING 212 | json = lv_response_data 213 | IMPORTING 214 | abap = ls_response_abap. 215 | CATCH zcx_abapfire_json INTO lcx_json. 216 | zcx_abapfire_firebase=>raise( lcx_json->get_text( ) ). 217 | ENDTRY. 218 | 219 | * Store token 220 | mv_id_token = ls_response_abap-id_token. 221 | mv_refresh_token = ls_response_abap-refresh_token. 222 | 223 | lv_http_client->close( ). 224 | 225 | ENDMETHOD. 226 | 227 | 228 | METHOD constructor. 229 | 230 | me->application = application. 231 | 232 | ENDMETHOD. 233 | 234 | 235 | METHOD create. 236 | 237 | IF sref_auth IS INITIAL. 238 | CREATE OBJECT sref_auth 239 | EXPORTING 240 | application = application. 241 | 242 | ENDIF. 243 | 244 | auth = sref_auth. 245 | 246 | ENDMETHOD. 247 | 248 | 249 | METHOD get_token. 250 | 251 | idtoken = mv_id_token. 252 | 253 | ENDMETHOD. 254 | ENDCLASS. 255 | -------------------------------------------------------------------------------- /src/zabapfire_cl_firebase_auth.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPFIRE_CL_FIREBASE_AUTH 7 | 1 8 | E 9 | ABAP Firebase Authentication Helper 10 | 1 11 | X 12 | X 13 | X 14 | X 15 | 16 | 17 | 18 | ZABAPFIRE_CL_FIREBASE_AUTH 19 | APPLICATION 20 | E 21 | ABAP Firebase REST API Helper 22 | 23 | 24 | ZABAPFIRE_CL_FIREBASE_AUTH 25 | CREATE 26 | E 27 | Create 28 | 29 | 30 | ZABAPFIRE_CL_FIREBASE_AUTH 31 | MV_EMAIL 32 | E 33 | Authentication mail 34 | 35 | 36 | ZABAPFIRE_CL_FIREBASE_AUTH 37 | MV_PASSWORD 38 | E 39 | Authentication password 40 | 41 | 42 | ZABAPFIRE_CL_FIREBASE_AUTH 43 | SREF_AUTH 44 | E 45 | ABAP Firebase Authentication Helper 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/zabapfire_cl_firebase_db.clas.abap: -------------------------------------------------------------------------------- 1 | class ZABAPFIRE_CL_FIREBASE_DB definition 2 | public 3 | final 4 | create private . 5 | 6 | public section. 7 | 8 | types: 9 | BEGIN OF ty_get_parameters, 10 | shallow TYPE abap_bool, 11 | order_by TYPE string, 12 | start_at TYPE string, 13 | end_at TYPE string, 14 | limit_to_first TYPE string, 15 | limit_to_last TYPE string, 16 | equal_to TYPE string, 17 | END OF ty_get_parameters . 18 | types: 19 | BEGIN OF ty_firebase_config, 20 | apikey TYPE string, 21 | authdomain TYPE string, 22 | databaseurl TYPE string, 23 | projectid TYPE string, 24 | storagebucket TYPE string, 25 | messagingsenderid TYPE string, 26 | END OF ty_firebase_config . 27 | 28 | class-methods CREATE 29 | importing 30 | !APPLICATION type ref to ZABAPFIRE_CL_FIREBASE 31 | returning 32 | value(RREF_DB) type ref to ZABAPFIRE_CL_FIREBASE_DB . 33 | methods GET 34 | importing 35 | !PATH type STRING 36 | !PARAMETERS type TY_GET_PARAMETERS optional 37 | exporting 38 | value(CHILD) type ANY 39 | raising 40 | ZCX_ABAPFIRE_FIREBASE . 41 | methods REMOVE 42 | importing 43 | !PATH type STRING 44 | raising 45 | ZCX_ABAPFIRE_FIREBASE . 46 | methods PUSH 47 | importing 48 | !PATH type STRING 49 | !CHILD type ANY 50 | returning 51 | value(KEY) type STRING 52 | raising 53 | ZCX_ABAPFIRE_FIREBASE . 54 | methods SET 55 | importing 56 | !PATH type STRING 57 | !CHILD type ANY 58 | raising 59 | ZCX_ABAPFIRE_FIREBASE . 60 | methods UPDATE 61 | importing 62 | !PATH type STRING 63 | !CHILD type ANY 64 | raising 65 | ZCX_ABAPFIRE_FIREBASE . 66 | PROTECTED SECTION. 67 | 68 | private section. 69 | 70 | class-data SREF_DB type ref to ZABAPFIRE_CL_FIREBASE_DB . 71 | data APPLICATION type ref to ZABAPFIRE_CL_FIREBASE . 72 | 73 | methods CONSTRUCTOR 74 | importing 75 | !APPLICATION type ref to ZABAPFIRE_CL_FIREBASE . 76 | methods ADD_PARAMETERS 77 | importing 78 | !PARAMETERS type ANY 79 | changing 80 | !URI type STRING 81 | !QUERY_DELIMITER type CHAR1 82 | raising 83 | ZCX_ABAPFIRE_FIREBASE . 84 | ENDCLASS. 85 | 86 | 87 | 88 | CLASS ZABAPFIRE_CL_FIREBASE_DB IMPLEMENTATION. 89 | 90 | 91 | METHOD add_parameters. 92 | 93 | DATA: 94 | l_abap_type TYPE REF TO cl_abap_typedescr, 95 | l_abap_stru TYPE REF TO cl_abap_structdescr, 96 | lt_components TYPE cl_abap_structdescr=>component_table, 97 | l_component TYPE cl_abap_structdescr=>component, 98 | l_parameter TYPE string, 99 | l_parameter_value TYPE string. 100 | FIELD-SYMBOLS: 101 | TYPE any. 102 | 103 | l_abap_type = cl_abap_typedescr=>describe_by_data( parameters ). 104 | IF l_abap_type->kind = cl_abap_typedescr=>kind_struct. 105 | l_abap_stru ?= cl_abap_typedescr=>describe_by_data( parameters ). 106 | lt_components = l_abap_stru->get_components( ). 107 | LOOP AT lt_components INTO l_component. 108 | ASSIGN COMPONENT l_component-name OF STRUCTURE parameters 109 | TO . 110 | IF sy-subrc NE 0. 111 | zcx_abapfire_firebase=>raise( 112 | 'Wrong URI parameters' ). "#EC NOTEXT 113 | ENDIF. 114 | CHECK NOT IS INITIAL. 115 | l_parameter = 116 | zabapfire_cl_http_util=>abap_lcc( l_component-name ). 117 | l_parameter_value = 118 | zabapfire_cl_http_util=>serialize_value( ). 119 | CONCATENATE 120 | uri 121 | query_delimiter 122 | l_parameter 123 | '=' 124 | l_parameter_value 125 | INTO uri. 126 | query_delimiter = '&'. "#EC NOTEXT 127 | ENDLOOP. 128 | ELSE. 129 | zcx_abapfire_firebase=>raise( 130 | 'Wrong URI parameters' ). "#EC NOTEXT 131 | ENDIF. 132 | 133 | ENDMETHOD. 134 | 135 | 136 | METHOD constructor. 137 | 138 | me->application = application. 139 | 140 | ENDMETHOD. 141 | 142 | 143 | METHOD create. 144 | 145 | IF sref_db IS INITIAL. 146 | CREATE OBJECT sref_db 147 | EXPORTING 148 | application = application. 149 | 150 | ENDIF. 151 | 152 | rref_db = sref_db. 153 | 154 | ENDMETHOD. 155 | 156 | 157 | METHOD get. 158 | 159 | DATA: 160 | lv_uri TYPE string, 161 | lv_idtoken TYPE string, 162 | lv_response_data TYPE string, 163 | lv_http_status TYPE i, 164 | lref_json_deserializer TYPE REF TO 165 | zabapfire_cl_json_deserializer, 166 | l_query_delimiter TYPE c LENGTH 1 VALUE '?', 167 | lcx_json TYPE REF TO zcx_abapfire_json. 168 | 169 | ASSERT CONDITION NOT path IS INITIAL. 170 | 171 | application->get_client( )->request->set_method( 'GET' ). 172 | application->get_client( )->request->set_content_type( 173 | 'application/json' ). 174 | 175 | CONCATENATE path '.json' INTO lv_uri. 176 | 177 | * Set parameters 178 | add_parameters( 179 | EXPORTING 180 | parameters = parameters 181 | CHANGING 182 | uri = lv_uri 183 | query_delimiter = l_query_delimiter ). 184 | 185 | * Get authentication token 186 | lv_idtoken = application->auth->get_token( ). 187 | 188 | IF NOT lv_idtoken IS INITIAL. 189 | CONCATENATE lv_uri l_query_delimiter 'auth=' lv_idtoken 190 | INTO lv_uri. 191 | ENDIF. 192 | 193 | * Set URI 194 | cl_http_utility=>set_request_uri( 195 | EXPORTING 196 | request = application->get_client( )->request 197 | uri = lv_uri 198 | ). 199 | 200 | * Send request 201 | application->get_client( )->send( 202 | EXCEPTIONS 203 | http_communication_failure = 1 204 | http_invalid_state = 2 205 | http_processing_failed = 3 206 | http_invalid_timeout = 4 207 | OTHERS = 5 208 | ). 209 | IF sy-subrc NE 0. 210 | zcx_abapfire_firebase=>raise( 211 | 'HTTP Connection fails' ). "#EC NOTEXT 212 | ENDIF. 213 | 214 | * Get response 215 | application->get_client( )->receive( 216 | EXCEPTIONS 217 | http_communication_failure = 1 218 | http_invalid_state = 2 219 | http_processing_failed = 3 220 | ). 221 | IF sy-subrc <> 0. 222 | zcx_abapfire_firebase=>raise( 223 | 'HTTP Connection fails' ). "#EC NOTEXT 224 | ENDIF. 225 | 226 | lv_response_data = 227 | application->get_client( )->response->get_cdata( ). 228 | REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline 229 | IN lv_response_data WITH ''. 230 | 231 | * Check response code 232 | application->get_client( )->response->get_status( 233 | IMPORTING 234 | code = lv_http_status ). 235 | 236 | CASE lv_http_status. 237 | WHEN 302. 238 | zcx_abapfire_firebase=>raise( 'HTTP redirect, check URL' ). 239 | "#EC NOTEXT 240 | WHEN 401. 241 | zcx_abapfire_firebase=>raise( 'HTTP 401, unauthorized' ). 242 | "#EC NOTEXT 243 | WHEN 403. 244 | zcx_abapfire_firebase=>raise( 'HTTP 403, forbidden' ). 245 | "#EC NOTEXT 246 | WHEN 404. 247 | zcx_abapfire_firebase=>raise( 'HTTP 404, not found' ). 248 | "#EC NOTEXT 249 | WHEN 415. 250 | zcx_abapfire_firebase=>raise( 251 | 'HTTP 415, unsupported media type' ). "#EC NOTEXT 252 | 253 | WHEN 400. 254 | zcx_abapfire_firebase=>raise( 255 | zabapfire_cl_http_util=>get_http_error_msg( 256 | EXPORTING 257 | code = lv_http_status 258 | api = 'firebase' 259 | payload = lv_response_data ) 260 | ). 261 | 262 | ENDCASE. 263 | 264 | * Deserialize JSON Payload 265 | TRY. 266 | CREATE OBJECT lref_json_deserializer. 267 | CALL METHOD lref_json_deserializer->deserialize 268 | EXPORTING 269 | json = lv_response_data 270 | IMPORTING 271 | abap = child. 272 | CATCH zcx_abapfire_json INTO lcx_json. 273 | zcx_abapfire_firebase=>raise( lcx_json->get_text( ) ). 274 | ENDTRY. 275 | 276 | ENDMETHOD. 277 | 278 | 279 | METHOD push. 280 | 281 | DATA: 282 | BEGIN OF ls_key, 283 | name TYPE string, 284 | END OF ls_key, 285 | lv_uri TYPE string, 286 | lv_idtoken TYPE string, 287 | lv_body TYPE string, 288 | lv_response_data TYPE string, 289 | lv_http_status TYPE i, 290 | lref_json_serializer TYPE REF TO zabapfire_cl_json_serializer, 291 | lref_json_deserializer TYPE REF TO 292 | zabapfire_cl_json_deserializer, 293 | l_query_delimiter TYPE c LENGTH 1 VALUE '?', 294 | lcx_json TYPE REF TO zcx_abapfire_json. 295 | 296 | ASSERT CONDITION NOT path IS INITIAL. 297 | 298 | application->get_client( )->request->set_method( 'POST' ). 299 | application->get_client( )->request->set_content_type( 300 | 'application/json' ). 301 | 302 | CONCATENATE path '.json' INTO lv_uri. 303 | 304 | * Get authentication token 305 | lv_idtoken = application->auth->get_token( ). 306 | 307 | IF NOT lv_idtoken IS INITIAL. 308 | CONCATENATE lv_uri l_query_delimiter 'auth=' lv_idtoken 309 | INTO lv_uri. 310 | ENDIF. 311 | 312 | * Set URI 313 | cl_http_utility=>set_request_uri( 314 | EXPORTING 315 | request = application->get_client( )->request 316 | uri = lv_uri 317 | ). 318 | 319 | * Set request body 320 | TRY. 321 | CREATE OBJECT lref_json_serializer. 322 | lv_body = lref_json_serializer->serialize( child ). 323 | CATCH zcx_abapfire_json INTO lcx_json. 324 | zcx_abapfire_firebase=>raise( lcx_json->get_text( ) ). 325 | ENDTRY. 326 | 327 | application->get_client( )->request->set_cdata( lv_body ). 328 | 329 | * Send request 330 | application->get_client( )->send( 331 | EXCEPTIONS 332 | http_communication_failure = 1 333 | http_invalid_state = 2 334 | http_processing_failed = 3 335 | http_invalid_timeout = 4 336 | OTHERS = 5 337 | ). 338 | IF sy-subrc NE 0. 339 | zcx_abapfire_firebase=>raise( 340 | 'HTTP Connection fails' ). "#EC NOTEXT 341 | ENDIF. 342 | 343 | * Get response 344 | application->get_client( )->receive( 345 | EXCEPTIONS 346 | http_communication_failure = 1 347 | http_invalid_state = 2 348 | http_processing_failed = 3 349 | ). 350 | IF sy-subrc <> 0. 351 | zcx_abapfire_firebase=>raise( 352 | 'HTTP Connection fails' ). "#EC NOTEXT 353 | ENDIF. 354 | 355 | * Get response data 356 | lv_response_data = 357 | application->get_client( )->response->get_cdata( ). 358 | REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline 359 | IN lv_response_data WITH ''. 360 | 361 | * Check response code 362 | application->get_client( )->response->get_status( 363 | IMPORTING 364 | code = lv_http_status ). 365 | 366 | CASE lv_http_status. 367 | WHEN 302. 368 | zcx_abapfire_firebase=>raise( 'HTTP redirect, check URL' ). 369 | "#EC NOTEXT 370 | WHEN 401. 371 | zcx_abapfire_firebase=>raise( 'HTTP 401, unauthorized' ). 372 | "#EC NOTEXT 373 | WHEN 403. 374 | zcx_abapfire_firebase=>raise( 'HTTP 403, forbidden' ). 375 | "#EC NOTEXT 376 | WHEN 404. 377 | zcx_abapfire_firebase=>raise( 'HTTP 404, not found' ). 378 | "#EC NOTEXT 379 | WHEN 415. 380 | zcx_abapfire_firebase=>raise( 381 | 'HTTP 415, unsupported media type' ). "#EC NOTEXT 382 | 383 | WHEN 400. 384 | zcx_abapfire_firebase=>raise( 385 | zabapfire_cl_http_util=>get_http_error_msg( 386 | EXPORTING 387 | code = lv_http_status 388 | api = 'firebase' 389 | payload = lv_response_data ) 390 | ). 391 | 392 | ENDCASE. 393 | 394 | * Deserialize JSON Payload 395 | TRY. 396 | CREATE OBJECT lref_json_deserializer. 397 | CALL METHOD lref_json_deserializer->deserialize 398 | EXPORTING 399 | json = lv_response_data 400 | IMPORTING 401 | abap = ls_key. 402 | CATCH zcx_abapfire_json INTO lcx_json. 403 | zcx_abapfire_firebase=>raise( lcx_json->get_text( ) ). 404 | ENDTRY. 405 | 406 | key = ls_key-name. 407 | 408 | ENDMETHOD. 409 | 410 | 411 | METHOD REMOVE. 412 | 413 | DATA: 414 | lv_uri TYPE string, 415 | lv_idtoken TYPE string, 416 | lv_body TYPE string, 417 | lv_response_data TYPE string, 418 | lv_http_status TYPE i, 419 | lref_json_serializer TYPE REF TO zabapfire_cl_json_serializer, 420 | l_query_delimiter TYPE c LENGTH 1 VALUE '?', 421 | lcx_json TYPE REF TO zcx_abapfire_json. 422 | 423 | ASSERT CONDITION NOT path IS INITIAL. 424 | 425 | application->get_client( )->request->set_method( 'DELETE' ). 426 | 427 | CONCATENATE path '.json' INTO lv_uri. 428 | 429 | * Get authentication token 430 | lv_idtoken = application->auth->get_token( ). 431 | 432 | IF NOT lv_idtoken IS INITIAL. 433 | CONCATENATE lv_uri l_query_delimiter 'auth=' lv_idtoken 434 | INTO lv_uri. 435 | ENDIF. 436 | 437 | * Set URI 438 | cl_http_utility=>set_request_uri( 439 | EXPORTING 440 | request = application->get_client( )->request 441 | uri = lv_uri 442 | ). 443 | 444 | * Send request 445 | application->get_client( )->send( 446 | EXCEPTIONS 447 | http_communication_failure = 1 448 | http_invalid_state = 2 449 | http_processing_failed = 3 450 | http_invalid_timeout = 4 451 | OTHERS = 5 452 | ). 453 | IF sy-subrc NE 0. 454 | zcx_abapfire_firebase=>raise( 455 | 'HTTP Connection fails' ). "#EC NOTEXT 456 | ENDIF. 457 | 458 | * Get response 459 | application->get_client( )->receive( 460 | EXCEPTIONS 461 | http_communication_failure = 1 462 | http_invalid_state = 2 463 | http_processing_failed = 3 464 | ). 465 | IF sy-subrc <> 0. 466 | zcx_abapfire_firebase=>raise( 467 | 'HTTP Connection fails' ). "#EC NOTEXT 468 | ENDIF. 469 | 470 | * Check response code 471 | application->get_client( )->response->get_status( 472 | IMPORTING 473 | code = lv_http_status ). 474 | 475 | CASE lv_http_status. 476 | WHEN 302. 477 | zcx_abapfire_firebase=>raise( 'HTTP redirect, check URL' ). 478 | "#EC NOTEXT 479 | WHEN 401. 480 | zcx_abapfire_firebase=>raise( 'HTTP 401, unauthorized' ). 481 | "#EC NOTEXT 482 | WHEN 403. 483 | zcx_abapfire_firebase=>raise( 'HTTP 403, forbidden' ). 484 | "#EC NOTEXT 485 | WHEN 404. 486 | zcx_abapfire_firebase=>raise( 'HTTP 404, not found' ). 487 | "#EC NOTEXT 488 | WHEN 415. 489 | zcx_abapfire_firebase=>raise( 490 | 'HTTP 415, unsupported media type' ). "#EC NOTEXT 491 | 492 | WHEN 400. 493 | lv_response_data = 494 | application->get_client( )->response->get_cdata( ). 495 | REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline 496 | IN lv_response_data WITH ''. 497 | zcx_abapfire_firebase=>raise( 498 | zabapfire_cl_http_util=>get_http_error_msg( 499 | EXPORTING 500 | code = lv_http_status 501 | api = 'firebase' 502 | payload = lv_response_data ) 503 | ). 504 | 505 | ENDCASE. 506 | 507 | ENDMETHOD. 508 | 509 | 510 | METHOD set. 511 | 512 | DATA: 513 | lv_uri TYPE string, 514 | lv_idtoken TYPE string, 515 | lv_body TYPE string, 516 | lv_response_data TYPE string, 517 | lv_http_status TYPE i, 518 | lref_json_serializer TYPE REF TO zabapfire_cl_json_serializer, 519 | l_query_delimiter TYPE c LENGTH 1 VALUE '?', 520 | lcx_json TYPE REF TO zcx_abapfire_json. 521 | 522 | ASSERT CONDITION NOT path IS INITIAL. 523 | 524 | application->get_client( )->request->set_method( 'PUT' ). 525 | application->get_client( )->request->set_content_type( 526 | 'application/json' ). 527 | 528 | CONCATENATE path '.json' INTO lv_uri. 529 | 530 | * Get authentication token 531 | lv_idtoken = application->auth->get_token( ). 532 | 533 | IF NOT lv_idtoken IS INITIAL. 534 | CONCATENATE lv_uri l_query_delimiter 'auth=' lv_idtoken 535 | INTO lv_uri. 536 | ENDIF. 537 | 538 | * Set URI 539 | cl_http_utility=>set_request_uri( 540 | EXPORTING 541 | request = application->get_client( )->request 542 | uri = lv_uri 543 | ). 544 | 545 | * Set request body 546 | TRY. 547 | CREATE OBJECT lref_json_serializer. 548 | lv_body = lref_json_serializer->serialize( child ). 549 | CATCH zcx_abapfire_json INTO lcx_json. 550 | zcx_abapfire_firebase=>raise( lcx_json->get_text( ) ). 551 | ENDTRY. 552 | 553 | application->get_client( )->request->set_cdata( lv_body ). 554 | 555 | * Send request 556 | application->get_client( )->send( 557 | EXCEPTIONS 558 | http_communication_failure = 1 559 | http_invalid_state = 2 560 | http_processing_failed = 3 561 | http_invalid_timeout = 4 562 | OTHERS = 5 563 | ). 564 | IF sy-subrc NE 0. 565 | zcx_abapfire_firebase=>raise( 566 | 'HTTP Connection fails' ). "#EC NOTEXT 567 | ENDIF. 568 | 569 | * Get response 570 | application->get_client( )->receive( 571 | EXCEPTIONS 572 | http_communication_failure = 1 573 | http_invalid_state = 2 574 | http_processing_failed = 3 575 | ). 576 | IF sy-subrc <> 0. 577 | zcx_abapfire_firebase=>raise( 578 | 'HTTP Connection fails' ). "#EC NOTEXT 579 | ENDIF. 580 | 581 | * Check response code 582 | application->get_client( )->response->get_status( 583 | IMPORTING 584 | code = lv_http_status ). 585 | 586 | CASE lv_http_status. 587 | WHEN 302. 588 | zcx_abapfire_firebase=>raise( 'HTTP redirect, check URL' ). 589 | "#EC NOTEXT 590 | WHEN 401. 591 | zcx_abapfire_firebase=>raise( 'HTTP 401, unauthorized' ). 592 | "#EC NOTEXT 593 | WHEN 403. 594 | zcx_abapfire_firebase=>raise( 'HTTP 403, forbidden' ). 595 | "#EC NOTEXT 596 | WHEN 404. 597 | zcx_abapfire_firebase=>raise( 'HTTP 404, not found' ). 598 | "#EC NOTEXT 599 | WHEN 415. 600 | zcx_abapfire_firebase=>raise( 601 | 'HTTP 415, unsupported media type' ). "#EC NOTEXT 602 | 603 | WHEN 400. 604 | lv_response_data = 605 | application->get_client( )->response->get_cdata( ). 606 | REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline 607 | IN lv_response_data WITH ''. 608 | zcx_abapfire_firebase=>raise( 609 | zabapfire_cl_http_util=>get_http_error_msg( 610 | EXPORTING 611 | code = lv_http_status 612 | api = 'firebase' 613 | payload = lv_response_data ) 614 | ). 615 | 616 | ENDCASE. 617 | 618 | ENDMETHOD. 619 | 620 | 621 | METHOD update. 622 | 623 | DATA: 624 | lv_uri TYPE string, 625 | lv_idtoken TYPE string, 626 | lv_body TYPE string, 627 | lv_response_data TYPE string, 628 | lv_http_status TYPE i, 629 | lref_json_serializer TYPE REF TO zabapfire_cl_json_serializer, 630 | l_query_delimiter TYPE c LENGTH 1 VALUE '?', 631 | lcx_json TYPE REF TO zcx_abapfire_json. 632 | 633 | ASSERT CONDITION NOT path IS INITIAL. 634 | 635 | application->get_client( )->request->set_method( 'PATCH' ). 636 | application->get_client( )->request->set_content_type( 637 | 'application/json' ). 638 | 639 | CONCATENATE path '.json' INTO lv_uri. 640 | 641 | * Get authentication token 642 | lv_idtoken = application->auth->get_token( ). 643 | 644 | IF NOT lv_idtoken IS INITIAL. 645 | CONCATENATE lv_uri l_query_delimiter 'auth=' lv_idtoken 646 | INTO lv_uri. 647 | ENDIF. 648 | 649 | * Set URI 650 | cl_http_utility=>set_request_uri( 651 | EXPORTING 652 | request = application->get_client( )->request 653 | uri = lv_uri 654 | ). 655 | 656 | * Set request body 657 | TRY. 658 | CREATE OBJECT lref_json_serializer. 659 | lv_body = lref_json_serializer->serialize( child ). 660 | CATCH zcx_abapfire_json INTO lcx_json. 661 | zcx_abapfire_firebase=>raise( lcx_json->get_text( ) ). 662 | ENDTRY. 663 | 664 | application->get_client( )->request->set_cdata( lv_body ). 665 | 666 | * Send request 667 | application->get_client( )->send( 668 | EXCEPTIONS 669 | http_communication_failure = 1 670 | http_invalid_state = 2 671 | http_processing_failed = 3 672 | http_invalid_timeout = 4 673 | OTHERS = 5 674 | ). 675 | IF sy-subrc NE 0. 676 | zcx_abapfire_firebase=>raise( 677 | 'HTTP Connection fails' ). "#EC NOTEXT 678 | ENDIF. 679 | 680 | * Get response 681 | application->get_client( )->receive( 682 | EXCEPTIONS 683 | http_communication_failure = 1 684 | http_invalid_state = 2 685 | http_processing_failed = 3 686 | ). 687 | IF sy-subrc <> 0. 688 | zcx_abapfire_firebase=>raise( 689 | 'HTTP Connection fails' ). "#EC NOTEXT 690 | ENDIF. 691 | 692 | * Check response code 693 | application->get_client( )->response->get_status( 694 | IMPORTING 695 | code = lv_http_status ). 696 | 697 | CASE lv_http_status. 698 | WHEN 302. 699 | zcx_abapfire_firebase=>raise( 'HTTP redirect, check URL' ). 700 | "#EC NOTEXT 701 | WHEN 401. 702 | zcx_abapfire_firebase=>raise( 'HTTP 401, unauthorized' ). 703 | "#EC NOTEXT 704 | WHEN 403. 705 | zcx_abapfire_firebase=>raise( 'HTTP 403, forbidden' ). 706 | "#EC NOTEXT 707 | WHEN 404. 708 | zcx_abapfire_firebase=>raise( 'HTTP 404, not found' ). 709 | "#EC NOTEXT 710 | WHEN 415. 711 | zcx_abapfire_firebase=>raise( 712 | 'HTTP 415, unsupported media type' ). "#EC NOTEXT 713 | 714 | WHEN 400. 715 | lv_response_data = 716 | application->get_client( )->response->get_cdata( ). 717 | REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline 718 | IN lv_response_data WITH ''. 719 | zcx_abapfire_firebase=>raise( 720 | zabapfire_cl_http_util=>get_http_error_msg( 721 | EXPORTING 722 | code = lv_http_status 723 | api = 'firebase' 724 | payload = lv_response_data ) 725 | ). 726 | 727 | ENDCASE. 728 | 729 | ENDMETHOD. 730 | ENDCLASS. 731 | -------------------------------------------------------------------------------- /src/zabapfire_cl_firebase_db.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPFIRE_CL_FIREBASE_DB 7 | 1 8 | E 9 | ABAP Firebase DB Helper 10 | 1 11 | X 12 | X 13 | X 14 | X 15 | 16 | 17 | 18 | ZABAPFIRE_CL_FIREBASE_DB 19 | APPLICATION 20 | E 21 | ABAP Firebase REST API Helper 22 | 23 | 24 | ZABAPFIRE_CL_FIREBASE_DB 25 | CREATE 26 | E 27 | Create 28 | 29 | 30 | ZABAPFIRE_CL_FIREBASE_DB 31 | SREF_DB 32 | E 33 | ABAP Firebase REST API Helper 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/zabapfire_cl_http_util.clas.abap: -------------------------------------------------------------------------------- 1 | class ZABAPFIRE_CL_HTTP_UTIL definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | 8 | class-methods GET_HTTP_ERROR_MSG 9 | importing 10 | !CODE type I 11 | !PAYLOAD type STRING 12 | !API type STRING 13 | returning 14 | value(RV_MSG) type STRING 15 | raising 16 | ZCX_ABAPFIRE_FIREBASE . 17 | class-methods ABAP_LCC 18 | importing 19 | !IN type STRING 20 | returning 21 | value(OUT) type STRING . 22 | class-methods LCC_ABAP 23 | importing 24 | !IN type STRING 25 | returning 26 | value(OUT) type STRING . 27 | class-methods DESERIALIZE_VALUE 28 | importing 29 | !JSON_VALUE type STRING 30 | !JSON_TYPE type STRING 31 | exporting 32 | value(ABAP_VALUE) type ANY . 33 | class-methods SERIALIZE_VALUE 34 | importing 35 | !ABAP_VALUE type ANY 36 | returning 37 | value(JSON_VALUE) type STRING . 38 | PROTECTED SECTION. 39 | private section. 40 | 41 | constants C_BOOL_TYPES type STRING value `\TYPE-POOL=ABAP\TYPE=ABAP_BOOL\TYPE=BOOLEAN\TYPE=BOOLE_D\TYPE=XFELD` ##NO_TEXT. 42 | 43 | class-methods XSTRING_TO_STRING 44 | importing 45 | !IN type ANY 46 | returning 47 | value(OUT) type STRING . 48 | class-methods STRING_TO_XSTRING 49 | importing 50 | !IN type STRING 51 | changing 52 | !OUT type ANY . 53 | ENDCLASS. 54 | 55 | 56 | 57 | CLASS ZABAPFIRE_CL_HTTP_UTIL IMPLEMENTATION. 58 | 59 | 60 | METHOD ABAP_LCC. 61 | 62 | DATA: tokens TYPE TABLE OF char128. 63 | 64 | FIELD-SYMBOLS: 65 | TYPE any. 66 | 67 | CHECK NOT in IS INITIAL. 68 | 69 | out = in. 70 | TRANSLATE out TO LOWER CASE. 71 | 72 | SPLIT out AT `_` INTO TABLE tokens. 73 | LOOP AT tokens ASSIGNING FROM 2. 74 | TRANSLATE (1) TO UPPER CASE. 75 | ENDLOOP. 76 | 77 | CONCATENATE LINES OF tokens INTO out. 78 | 79 | ENDMETHOD. 80 | 81 | 82 | METHOD DESERIALIZE_VALUE. 83 | DATA: l_elem_descr TYPE REF TO cl_abap_elemdescr, 84 | l_string TYPE string, 85 | l_year TYPE n LENGTH 4, 86 | l_month TYPE n LENGTH 2, 87 | l_day TYPE n LENGTH 2, 88 | l_hour TYPE n LENGTH 2, 89 | l_minute TYPE n LENGTH 2, 90 | l_second TYPE n LENGTH 2, 91 | l_decimals TYPE n LENGTH 7, 92 | tk LIKE l_elem_descr->type_kind. 93 | 94 | DEFINE escape_string. 95 | REPLACE ALL OCCURRENCES OF `\"` IN &1 WITH `"`. 96 | REPLACE ALL OCCURRENCES OF `\\` IN &1 WITH `\`. 97 | END-OF-DEFINITION. 98 | 99 | l_elem_descr ?= cl_abap_typedescr=>describe_by_data( abap_value ). 100 | tk = l_elem_descr->type_kind. 101 | 102 | CASE json_type. 103 | WHEN 'string'. 104 | l_string = json_value. 105 | escape_string l_string. 106 | CASE tk. 107 | WHEN cl_abap_typedescr=>typekind_xstring OR 108 | cl_abap_typedescr=>typekind_hex. 109 | string_to_xstring( EXPORTING in = l_string CHANGING out = abap_value ). 110 | WHEN cl_abap_typedescr=>typekind_date. 111 | FIND FIRST OCCURRENCE OF REGEX '(\d{4})-(\d{2})-(\d{2})' IN json_value 112 | SUBMATCHES l_year l_month l_day. 113 | IF sy-subrc EQ 0. 114 | CONCATENATE l_year l_month l_day INTO abap_value. 115 | ENDIF. 116 | WHEN cl_abap_typedescr=>typekind_time. 117 | FIND FIRST OCCURRENCE OF REGEX '(\d{2}):(\d{2}):(\d{2})' IN json_value 118 | SUBMATCHES l_hour l_minute l_second. 119 | IF sy-subrc EQ 0. 120 | CONCATENATE l_hour l_minute l_second INTO abap_value. 121 | ENDIF. 122 | WHEN cl_abap_typedescr=>typekind_packed. 123 | FIND FIRST OCCURRENCE OF REGEX 124 | '(\d{4})-?(\d{2})-?(\d{2})T(\d{2}):?(\d{2}):?(\d{2})(?:[\.,](\d{0,7}))?Z?' 125 | "#EC NOTEXT 126 | IN json_value 127 | SUBMATCHES l_year l_month l_day l_hour l_minute l_second l_decimals. 128 | IF sy-subrc EQ 0. 129 | CONCATENATE l_year l_month l_day 130 | l_hour l_minute l_second '.' l_decimals INTO l_string. 131 | abap_value = l_string. 132 | ENDIF. 133 | WHEN OTHERS. 134 | abap_value = l_string. 135 | ENDCASE. 136 | WHEN 'boolean'. 137 | CASE json_value. 138 | WHEN 'true'. 139 | abap_value = abap_true. 140 | WHEN 'false' OR 'null'. "TODO Manage 3 values boolean 141 | abap_value = abap_false. 142 | ENDCASE. 143 | WHEN 'number'. 144 | abap_value = json_value. 145 | ENDCASE. 146 | 147 | ENDMETHOD. 148 | 149 | 150 | METHOD get_http_error_msg. 151 | 152 | TYPES: 153 | BEGIN OF ty_error_array, 154 | domain TYPE string, 155 | reason TYPE string, 156 | message TYPE string, 157 | END OF ty_error_array, 158 | BEGIN OF ty_error_google, 159 | errors TYPE STANDARD TABLE OF ty_error_array 160 | WITH DEFAULT KEY, 161 | code TYPE i, 162 | message TYPE string, 163 | END OF ty_error_google, 164 | BEGIN OF ty_response_google, 165 | error TYPE ty_error_google, 166 | END OF ty_response_google, 167 | BEGIN OF ty_response_firebase, 168 | error TYPE string, 169 | END OF ty_response_firebase. 170 | 171 | DATA: 172 | lref_json_deserializer TYPE REF TO zabapfire_cl_json_deserializer, 173 | ls_error_google TYPE ty_response_google, 174 | ls_error_firebase TYPE ty_response_firebase, 175 | lv_code TYPE n LENGTH 4, 176 | lcx_exception TYPE REF TO zcx_abapfire_json. 177 | 178 | FIELD-SYMBOLS: 179 | TYPE any, 180 | TYPE any. 181 | 182 | lv_code = code. 183 | 184 | CASE api. 185 | WHEN 'google'. 186 | ASSIGN ls_error_google TO . 187 | WHEN 'firebase'. 188 | ASSIGN ls_error_firebase TO . 189 | WHEN OTHERS. 190 | CONCATENATE 'HTTP ERROR:' lv_code INTO rv_msg SEPARATED BY space. 191 | RETURN. 192 | ENDCASE. 193 | 194 | TRY. 195 | CREATE OBJECT lref_json_deserializer. 196 | CALL METHOD lref_json_deserializer->deserialize 197 | EXPORTING 198 | json = payload 199 | IMPORTING 200 | abap = . 201 | CATCH zcx_abapfire_json INTO lcx_exception. 202 | zcx_abapfire_firebase=>raise( lcx_exception->get_text( ) ). 203 | ENDTRY. 204 | 205 | CASE api. 206 | WHEN 'google'. "#EC NOTEXT 207 | ASSIGN COMPONENT 'message' 208 | OF STRUCTURE ls_error_google-error 209 | TO . "#EC NOTEXT 210 | WHEN 'firebase'. "#EC NOTEXT 211 | ASSIGN ls_error_firebase-error TO . 212 | ENDCASE. 213 | 214 | IF IS ASSIGNED. 215 | CONCATENATE 'HTTP ERROR:' lv_code 216 | INTO rv_msg SEPARATED BY space. 217 | ENDIF. 218 | 219 | ENDMETHOD. 220 | 221 | 222 | METHOD lcc_abap. 223 | 224 | CHECK NOT in IS INITIAL. 225 | 226 | out = in. 227 | REPLACE ALL OCCURRENCES OF REGEX `([a-z])([A-Z])` 228 | IN out WITH `$1_$2`. "#EC NOTEXT 229 | TRANSLATE out TO UPPER CASE. 230 | 231 | ENDMETHOD. 232 | 233 | 234 | METHOD SERIALIZE_VALUE. 235 | DATA: l_elem_descr TYPE REF TO cl_abap_elemdescr, 236 | tk LIKE l_elem_descr->type_kind, 237 | an LIKE l_elem_descr->absolute_name, 238 | ol LIKE l_elem_descr->output_length. 239 | 240 | DEFINE escape_string. 241 | REPLACE ALL OCCURRENCES OF `\` IN &1 WITH `\\`. 242 | REPLACE ALL OCCURRENCES OF `"` IN &1 WITH `\"`. 243 | END-OF-DEFINITION. 244 | 245 | l_elem_descr ?= cl_abap_typedescr=>describe_by_data( abap_value ). 246 | tk = l_elem_descr->type_kind. 247 | an = l_elem_descr->absolute_name. 248 | ol = l_elem_descr->output_length. 249 | 250 | CASE tk. 251 | WHEN cl_abap_typedescr=>typekind_float OR 252 | cl_abap_typedescr=>typekind_int OR 253 | cl_abap_typedescr=>typekind_int1 OR 254 | cl_abap_typedescr=>typekind_int2 OR 255 | cl_abap_typedescr=>typekind_packed OR 256 | `8`. "typekind_int8 -> '8' only from 7.40. 257 | IF tk EQ cl_abap_typedescr=>typekind_packed AND 258 | an CP `\TYPE=TIMESTAMP*`. 259 | IF abap_value IS INITIAL. 260 | json_value = `""`. 261 | ELSE. 262 | MOVE abap_value TO json_value. 263 | IF an EQ `\TYPE=TIMESTAMP`. 264 | CONCATENATE `"` json_value(4) 265 | `-` json_value+4(2) 266 | `-` json_value+6(2) 267 | `T` json_value+8(2) 268 | `:` json_value+10(2) 269 | `:` json_value+12(2) 270 | `.0000000Z"` INTO json_value. 271 | ELSEIF an EQ `\TYPE=TIMESTAMPL`. 272 | CONCATENATE `"` json_value(4) 273 | `-` json_value+4(2) 274 | `-` json_value+6(2) 275 | `T` json_value+8(2) 276 | `:` json_value+10(2) 277 | `:` json_value+12(2) 278 | `.` json_value+15(7) `Z"` INTO json_value. 279 | ENDIF. 280 | ENDIF. 281 | ELSEIF abap_value IS INITIAL. 282 | json_value = `0`. 283 | ELSE. 284 | MOVE abap_value TO json_value. 285 | IF abap_value LT 0. 286 | IF tk <> cl_abap_typedescr=>typekind_float. "float: sign is already at the beginning 287 | SHIFT json_value RIGHT CIRCULAR. 288 | ENDIF. 289 | ELSE. 290 | CONDENSE json_value. 291 | ENDIF. 292 | ENDIF. 293 | WHEN cl_abap_typedescr=>typekind_num. 294 | IF abap_value IS INITIAL. 295 | json_value = `0`. 296 | ELSE. 297 | MOVE abap_value TO json_value. 298 | SHIFT json_value LEFT DELETING LEADING ` 0`. 299 | ENDIF. 300 | WHEN cl_abap_typedescr=>typekind_string OR 301 | cl_abap_typedescr=>typekind_csequence OR 302 | cl_abap_typedescr=>typekind_clike. 303 | IF abap_value IS INITIAL. 304 | json_value = `""`. 305 | ELSE. 306 | MOVE abap_value TO json_value. 307 | escape_string json_value. 308 | CONCATENATE `"` json_value `"` INTO json_value. 309 | ENDIF. 310 | WHEN cl_abap_typedescr=>typekind_xstring OR 311 | cl_abap_typedescr=>typekind_hex. 312 | IF abap_value IS INITIAL. 313 | json_value = `""`. 314 | ELSE. 315 | json_value = xstring_to_string( abap_value ). 316 | escape_string json_value. 317 | CONCATENATE `"` json_value `"` INTO json_value. 318 | ENDIF. 319 | WHEN cl_abap_typedescr=>typekind_char. 320 | IF ol EQ 1 AND c_bool_types CS an. 321 | IF abap_value EQ abap_true. 322 | json_value = `true`. "#EC NOTEXT 323 | ELSE. 324 | json_value = `false`. "#EC NOTEXT 325 | ENDIF. 326 | ELSE. 327 | MOVE abap_value TO json_value. 328 | escape_string json_value. 329 | CONCATENATE `"` json_value `"` INTO json_value. 330 | ENDIF. 331 | WHEN cl_abap_typedescr=>typekind_date. 332 | MOVE abap_value TO json_value. 333 | CONCATENATE `"` json_value(4) 334 | `-` json_value+4(2) 335 | `-` json_value+6(2) 336 | `T00:00:00.0000000Z"` INTO json_value. 337 | WHEN cl_abap_typedescr=>typekind_time. 338 | MOVE abap_value TO json_value. 339 | CONCATENATE `"` json_value(2) 340 | `:` json_value+2(2) 341 | `:` json_value+4(2) `"` INTO json_value. 342 | WHEN OTHERS. 343 | IF abap_value IS INITIAL. 344 | json_value = `null`. "#EC NOTEXT 345 | ELSE. 346 | MOVE abap_value TO json_value. 347 | ENDIF. 348 | ENDCASE. 349 | 350 | ENDMETHOD. 351 | 352 | 353 | METHOD STRING_TO_XSTRING. 354 | 355 | DATA: l_xstring TYPE xstring. 356 | 357 | CALL FUNCTION 'SSFC_BASE64_DECODE' 358 | EXPORTING 359 | b64data = in 360 | IMPORTING 361 | bindata = l_xstring 362 | EXCEPTIONS 363 | OTHERS = 1. 364 | 365 | IF sy-subrc IS INITIAL. 366 | MOVE l_xstring TO out. 367 | ELSE. 368 | MOVE in TO out. 369 | ENDIF. 370 | 371 | ENDMETHOD. 372 | 373 | 374 | METHOD XSTRING_TO_STRING. 375 | 376 | DATA: l_xstring TYPE xstring. 377 | 378 | l_xstring = in. 379 | 380 | CALL FUNCTION 'SSFC_BASE64_ENCODE' 381 | EXPORTING 382 | bindata = l_xstring 383 | IMPORTING 384 | b64data = out 385 | EXCEPTIONS 386 | OTHERS = 1. 387 | 388 | IF sy-subrc IS NOT INITIAL. 389 | MOVE in TO out. 390 | ENDIF. 391 | 392 | ENDMETHOD. 393 | ENDCLASS. 394 | -------------------------------------------------------------------------------- /src/zabapfire_cl_http_util.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPFIRE_CL_HTTP_UTIL 7 | 1 8 | E 9 | HTTP Utilities 10 | 2 11 | 1 12 | X 13 | X 14 | X 15 | X 16 | 17 | 18 | 19 | ZABAPFIRE_CL_HTTP_UTIL 20 | ABAP_LCC 21 | E 22 | From ABAP to LowerCamelCase 23 | 24 | 25 | ZABAPFIRE_CL_HTTP_UTIL 26 | C_BOOL_TYPES 27 | E 28 | Boolean types 29 | 30 | 31 | ZABAPFIRE_CL_HTTP_UTIL 32 | LCC_ABAP 33 | E 34 | From lowerCamelCase to ABAP 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/zabapfire_cl_json_deserializer.clas.abap: -------------------------------------------------------------------------------- 1 | CLASS zabapfire_cl_json_deserializer DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | 6 | PUBLIC SECTION. 7 | 8 | METHODS deserialize 9 | IMPORTING 10 | !json TYPE string 11 | EXPORTING 12 | !abap TYPE any 13 | RAISING 14 | zcx_abapfire_json . 15 | PROTECTED SECTION. 16 | *"* protected components of class CL_TREX_JSON_DESERIALIZER 17 | *"* do not include other source files here!!! 18 | private section. 19 | 20 | types TY_NODE type ref to ZABAPFIRE_CL_JSON_NODE . 21 | 22 | data MV_NAME type STRING . 23 | data: 24 | mt_nodes_stack TYPE TABLE OF ty_node . 25 | data JSON_HIERARCHY type ref to ZABAPFIRE_CL_JSON_NODE . 26 | 27 | *"* private components of class CL_TREX_JSON_DESERIALIZER 28 | *"* do not include other source files here!!! 29 | methods DESERIALIZE_NODE 30 | importing 31 | !JSON type STRING 32 | changing 33 | !OFFSET type I default 0 34 | raising 35 | ZCX_ABAPFIRE_JSON . 36 | methods DESERIALIZE_OBJECT 37 | importing 38 | !JSON type STRING 39 | changing 40 | !OFFSET type I default 0 41 | raising 42 | ZCX_ABAPFIRE_JSON . 43 | methods DESERIALIZE_ARRAY 44 | importing 45 | !JSON type STRING 46 | changing 47 | !OFFSET type I default 0 48 | raising 49 | ZCX_ABAPFIRE_JSON . 50 | methods DESERIALIZE_KEY 51 | importing 52 | !JSON type STRING 53 | changing 54 | !OFFSET type I default 0 55 | raising 56 | ZCX_ABAPFIRE_JSON . 57 | methods SET_NODE_LEVEL 58 | importing 59 | !ADD type ABAP_BOOL optional 60 | !REMOVE type ABAP_BOOL optional 61 | !ARRAY type ABAP_BOOL optional 62 | !VALUE type STRING optional 63 | !TYPE type STRING optional 64 | raising 65 | ZCX_ABAPFIRE_JSON . 66 | methods RECURSE 67 | importing 68 | !NODE type ref to ZABAPFIRE_CL_JSON_NODE 69 | changing 70 | !COMP type ANY 71 | raising 72 | ZCX_ABAPFIRE_JSON . 73 | ENDCLASS. 74 | 75 | 76 | 77 | CLASS ZABAPFIRE_CL_JSON_DESERIALIZER IMPLEMENTATION. 78 | 79 | 80 | METHOD deserialize. 81 | 82 | deserialize_node( 83 | EXPORTING 84 | json = json ). 85 | 86 | recurse( 87 | EXPORTING 88 | node = json_hierarchy 89 | CHANGING 90 | comp = abap ). 91 | 92 | ENDMETHOD. 93 | 94 | 95 | METHOD deserialize_array. 96 | DATA: 97 | l_done TYPE abap_bool. 98 | 99 | ADD 1 TO offset . "skip [ 100 | 101 | * Add object node to nodes stack 102 | set_node_level( 103 | EXPORTING 104 | add = abap_true 105 | array = abap_true ). 106 | 107 | 108 | WHILE l_done = abap_false . 109 | deserialize_node( 110 | EXPORTING 111 | json = json 112 | CHANGING 113 | offset = offset ) . 114 | 115 | FIND REGEX ',|\]' IN SECTION OFFSET offset OF json MATCH OFFSET offset . 116 | IF sy-subrc <> 0 . 117 | zcx_abapfire_json=>raise( 'Invalid JSON' ). "#EC NOTEXT 118 | ENDIF . 119 | IF json+offset(1) = ']' . 120 | l_done = abap_true . 121 | set_node_level( 122 | EXPORTING 123 | remove = abap_true ). 124 | ENDIF . 125 | ADD 1 TO offset . 126 | ENDWHILE . 127 | 128 | ENDMETHOD. 129 | 130 | 131 | METHOD deserialize_key. 132 | 133 | DATA: 134 | l_len TYPE i, 135 | l_string TYPE string, 136 | l_number TYPE string, 137 | l_boolean TYPE string, 138 | l_value TYPE string, 139 | l_type TYPE string. 140 | 141 | FIND REGEX 142 | '"((?:\\"|(?!").)*)"|(-{1}\d+|\d+)|(true|false|null)' 143 | IN SECTION OFFSET offset OF json 144 | MATCH OFFSET offset MATCH LENGTH l_len 145 | SUBMATCHES l_string l_number l_boolean. 146 | IF sy-subrc <> 0 . 147 | zcx_abapfire_json=>raise( 'Invalid JSON' ). "#EC NOTEXT 148 | ENDIF . 149 | 150 | CASE json+offset(1) . 151 | WHEN '"' . 152 | l_type = 'string'. "#EC NOTEXT 153 | l_value = l_string. 154 | ADD l_len TO offset . 155 | WHEN 't' OR 'f' OR 'n'. 156 | l_type = 'boolean'. "#EC NOTEXT 157 | l_value = l_boolean. 158 | WHEN OTHERS . "0-9 or negative numbers 159 | l_type = 'number'. "#EC NOTEXT 160 | l_value = l_number. 161 | ENDCASE . 162 | 163 | set_node_level( 164 | EXPORTING 165 | value = l_value 166 | type = l_type 167 | add = abap_true ). 168 | CLEAR mv_name. 169 | * key nodes do not have children 170 | set_node_level( 171 | EXPORTING 172 | remove = abap_true ). 173 | 174 | ENDMETHOD. 175 | 176 | 177 | METHOD deserialize_node. 178 | 179 | FIND REGEX 180 | '\{|\[|"((?:\\"|(?!").)*)"|(-{1}\d+|\d+)|(true|false)|\}|\]' 181 | " (\{) --> capturing group 1 { 182 | " (\[) --> capturing group 2 [ 183 | " (["]((?:\\"|(?!").)*)") --> capturing group 3 strings 184 | " (-{1}\d+|\d+) --> capturing group 4 numbers 185 | " (true|false) --> capturing group 5 booleans 186 | 187 | IN SECTION OFFSET offset OF json 188 | MATCH OFFSET offset. 189 | 190 | IF sy-subrc <> 0 . 191 | zcx_abapfire_json=>raise( 'Invalid JSON' ). "#EC NOTEXT 192 | ENDIF . 193 | 194 | CASE json+offset(1) . 195 | WHEN '{' . 196 | deserialize_object( 197 | EXPORTING 198 | json = json 199 | CHANGING 200 | offset = offset ). 201 | WHEN '[' . 202 | deserialize_array( 203 | EXPORTING 204 | json = json 205 | CHANGING 206 | offset = offset ). 207 | WHEN '}' OR ']'. 208 | "Ignore it, while cycle on object or array will be closed 209 | WHEN OTHERS. 210 | deserialize_key( 211 | EXPORTING 212 | json = json 213 | CHANGING 214 | offset = offset ). 215 | ENDCASE . 216 | 217 | ENDMETHOD. 218 | 219 | 220 | METHOD deserialize_object. 221 | DATA: 222 | l_done TYPE abap_bool, 223 | l_len TYPE i. 224 | 225 | ADD 1 TO offset . "skip { 226 | 227 | * Add object node to nodes stack 228 | set_node_level( 229 | EXPORTING 230 | add = abap_true ). 231 | 232 | * handle each component 233 | WHILE l_done = abap_false . 234 | "find next key ("key":) 235 | FIND REGEX '"((?:\\"|(?!").)*)"\s*:' 236 | IN SECTION OFFSET offset OF json 237 | MATCH OFFSET offset MATCH LENGTH l_len 238 | SUBMATCHES mv_name. 239 | IF sy-subrc = 0 . 240 | ADD l_len TO offset. 241 | * remove " from l_name 242 | REPLACE ALL OCCURRENCES OF '"' IN mv_name WITH ''. 243 | * deserialize current component 244 | deserialize_node( 245 | EXPORTING 246 | json = json 247 | CHANGING 248 | offset = offset ). 249 | ENDIF . 250 | FIND REGEX ',|\}' 251 | IN SECTION OFFSET offset OF json 252 | MATCH OFFSET offset . 253 | IF sy-subrc <> 0 . 254 | zcx_abapfire_json=>raise( 'Invalid JSON' ). "#EC NOTEXT 255 | ENDIF . 256 | IF json+offset(1) = '}' . 257 | l_done = abap_true . 258 | set_node_level( 259 | EXPORTING 260 | remove = abap_true ). 261 | ENDIF . 262 | ADD 1 TO offset . 263 | ENDWHILE . 264 | 265 | ENDMETHOD. 266 | 267 | 268 | METHOD recurse. 269 | 270 | DATA: 271 | l_children TYPE zabapfire_cl_json_node=>ty_nodes, 272 | l_node TYPE REF TO zabapfire_cl_json_node, 273 | l_abap_type TYPE REF TO cl_abap_typedescr, 274 | l_name TYPE string, 275 | l_data TYPE REF TO data. 276 | FIELD-SYMBOLS: 277 | TYPE ANY TABLE, 278 | TYPE any, 279 | TYPE any. 280 | 281 | 282 | * Iterate on JSON Hierarchy and fill ABAP type 283 | l_abap_type = cl_abap_typedescr=>describe_by_data( comp ). 284 | IF l_abap_type->kind = cl_abap_typedescr=>kind_table. 285 | * JSON Hierarchy children are table rows 286 | ASSIGN comp TO . 287 | CREATE DATA l_data LIKE LINE OF . 288 | ASSIGN l_data->* TO . 289 | l_children = node->get_children( ). 290 | LOOP AT l_children INTO l_node. 291 | CLEAR . 292 | recurse( 293 | EXPORTING 294 | node = l_node 295 | CHANGING 296 | comp = ). 297 | INSERT INTO TABLE . 298 | ENDLOOP. 299 | ELSEIF l_abap_type->kind = cl_abap_typedescr=>kind_struct. 300 | * JSON Hierarchy children are structure fields 301 | ASSIGN comp TO . 302 | l_children = node->get_children( ). 303 | LOOP AT l_children INTO l_node. 304 | l_name = 305 | zabapfire_cl_http_util=>lcc_abap( l_node->get_name( ) ). 306 | ASSIGN COMPONENT l_name OF STRUCTURE TO . 307 | IF sy-subrc NE 0. 308 | zcx_abapfire_json=>raise( 'Invalid ABAP Target' ). "#EC NOTEXT 309 | ENDIF. 310 | recurse( 311 | EXPORTING 312 | node = l_node 313 | CHANGING 314 | comp = ). 315 | ENDLOOP. 316 | * Check if we have to return object key 317 | ASSIGN COMPONENT '$KEY' OF STRUCTURE TO . "#EX NOTEXT 318 | IF sy-subrc EQ 0. 319 | = node->get_name( ). 320 | ENDIF. 321 | ELSE. 322 | * JSON Hierarchy children are key values 323 | TRY. 324 | zabapfire_cl_http_util=>deserialize_value( 325 | EXPORTING 326 | json_value = node->get_value( ) 327 | json_type = node->get_type( ) 328 | IMPORTING 329 | abap_value = comp ). 330 | CATCH cx_sy_conversion_error. 331 | zcx_abapfire_json=>raise( 'Invalid ABAP Target' ). "#EC NOTEXT 332 | ENDTRY. 333 | ENDIF. 334 | 335 | ENDMETHOD. 336 | 337 | 338 | METHOD set_node_level. 339 | 340 | DATA: 341 | l_len TYPE i, 342 | l_parent TYPE REF TO zabapfire_cl_json_node, 343 | l_node TYPE REF TO zabapfire_cl_json_node. 344 | 345 | DESCRIBE TABLE mt_nodes_stack LINES l_len. 346 | 347 | IF remove = abap_true. 348 | * Remove last node 349 | IF l_len > 0. 350 | READ TABLE mt_nodes_stack INTO json_hierarchy 351 | INDEX l_len. 352 | DELETE mt_nodes_stack INDEX l_len. 353 | ENDIF. 354 | ENDIF. 355 | 356 | IF add = abap_true. 357 | * Add new node 358 | CREATE OBJECT l_node 359 | EXPORTING 360 | name = mv_name 361 | array = array 362 | value = value 363 | type = type. 364 | * Check if a parent node exists 365 | READ TABLE mt_nodes_stack INTO l_parent 366 | INDEX l_len. 367 | IF l_len > 0. 368 | IF NOT l_parent IS INITIAL. 369 | l_parent->add_child( l_node ). 370 | ENDIF. 371 | ENDIF. 372 | CLEAR mv_name. 373 | APPEND l_node TO mt_nodes_stack. 374 | ENDIF. 375 | 376 | ENDMETHOD. 377 | ENDCLASS. 378 | -------------------------------------------------------------------------------- /src/zabapfire_cl_json_deserializer.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPFIRE_CL_JSON_DESERIALIZER 7 | 1 8 | E 9 | Deserialize JSON to ABAP data 10 | 2 11 | 1 12 | X 13 | X 14 | X 15 | X 16 | 17 | 18 | 19 | ZABAPFIRE_CL_JSON_DESERIALIZER 20 | JSON_HIERARCHY 21 | E 22 | JSON Node 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/zabapfire_cl_json_node.clas.abap: -------------------------------------------------------------------------------- 1 | class ZABAPFIRE_CL_JSON_NODE definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | 8 | types TY_NODE type ref to ZABAPFIRE_CL_JSON_NODE . 9 | types: 10 | ty_nodes TYPE SORTED TABLE OF ty_node 11 | WITH UNIQUE DEFAULT KEY . 12 | 13 | methods CONSTRUCTOR 14 | importing 15 | !NAME type STRING optional 16 | !VALUE type STRING optional 17 | !TYPE type STRING optional 18 | !ARRAY type ABAP_BOOL optional 19 | raising 20 | ZCX_ABAPFIRE_JSON . 21 | methods SET_VALUE 22 | importing 23 | !VALUE type STRING . 24 | methods GET_NAME 25 | returning 26 | value(NAME) type STRING . 27 | methods GET_VALUE 28 | returning 29 | value(VALUE) type STRING . 30 | methods GET_TYPE 31 | returning 32 | value(TYPE) type STRING . 33 | methods ADD_CHILD 34 | importing 35 | !CHILD type ref to ZABAPFIRE_CL_JSON_NODE . 36 | methods GET_CHILDREN 37 | returning 38 | value(CHILDREN) type TY_NODES . 39 | methods IS_ARRAY 40 | returning 41 | value(TRUE) type ABAP_BOOL . 42 | protected section. 43 | private section. 44 | 45 | data MV_NAME type STRING . 46 | data MV_VALUE type STRING . 47 | data MV_ARRAY type ABAP_BOOL . 48 | data MV_TYPE type STRING . 49 | data MT_CHILDREN type TY_NODES . 50 | ENDCLASS. 51 | 52 | 53 | 54 | CLASS ZABAPFIRE_CL_JSON_NODE IMPLEMENTATION. 55 | 56 | 57 | METHOD add_child. 58 | 59 | INSERT child INTO TABLE mt_children. 60 | 61 | ENDMETHOD. 62 | 63 | 64 | METHOD constructor. 65 | 66 | mv_name = name. 67 | mv_value = value. 68 | mv_array = array. 69 | mv_type = type. 70 | 71 | ENDMETHOD. 72 | 73 | 74 | METHOD get_children. 75 | 76 | children = mt_children. 77 | 78 | ENDMETHOD. 79 | 80 | 81 | METHOD get_name. 82 | 83 | name = mv_name. 84 | 85 | ENDMETHOD. 86 | 87 | 88 | METHOD get_type. 89 | 90 | type = mv_type. 91 | 92 | ENDMETHOD. 93 | 94 | 95 | METHOD get_value. 96 | 97 | value = mv_value. 98 | 99 | ENDMETHOD. 100 | 101 | 102 | METHOD is_array. 103 | 104 | true = mv_array. 105 | 106 | ENDMETHOD. 107 | 108 | 109 | METHOD set_value. 110 | 111 | mv_value = value. 112 | 113 | ENDMETHOD. 114 | ENDCLASS. 115 | -------------------------------------------------------------------------------- /src/zabapfire_cl_json_node.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPFIRE_CL_JSON_NODE 7 | 1 8 | E 9 | JSON Node 10 | 2 11 | 1 12 | X 13 | X 14 | X 15 | X 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/zabapfire_cl_json_serializer.clas.abap: -------------------------------------------------------------------------------- 1 | class ZABAPFIRE_CL_JSON_SERIALIZER definition 2 | public 3 | final 4 | create public . 5 | 6 | public section. 7 | 8 | *"* public components of class CL_TREX_JSON_SERIALIZER 9 | *"* do not include other source files here!!! 10 | class-methods CLASS_CONSTRUCTOR . 11 | methods SERIALIZE 12 | importing 13 | !ABAP type ANY 14 | returning 15 | value(JSON) type STRING 16 | raising 17 | ZCX_ABAPFIRE_JSON . 18 | protected section. 19 | *"* protected components of class ZL_ASXML_TO_JSON 20 | *"* do not include other source files here!!! 21 | private section. 22 | 23 | class-data C_COLON type STRING . 24 | class-data C_COMMA type STRING . 25 | data: 26 | mt_lines TYPE TABLE OF string . 27 | data JSON_HIERARCHY type ref to ZABAPFIRE_CL_JSON_NODE . 28 | 29 | methods RECURSE 30 | importing 31 | !COMP type DATA 32 | !NAME type STRING optional 33 | changing 34 | !NODE type ref to ZABAPFIRE_CL_JSON_NODE optional 35 | raising 36 | ZCX_ABAPFIRE_JSON . 37 | methods WRITE_JSON 38 | changing 39 | !JSON type STRING 40 | raising 41 | ZCX_ABAPFIRE_JSON . 42 | methods RECURSE_JSON 43 | importing 44 | !NODE type ref to ZABAPFIRE_CL_JSON_NODE 45 | raising 46 | ZCX_ABAPFIRE_JSON . 47 | ENDCLASS. 48 | 49 | 50 | 51 | CLASS ZABAPFIRE_CL_JSON_SERIALIZER IMPLEMENTATION. 52 | 53 | 54 | method CLASS_CONSTRUCTOR. 55 | 56 | cl_abap_string_utilities=>c2str_preserving_blanks( 57 | exporting source = ': ' 58 | importing dest = c_colon ) . 59 | cl_abap_string_utilities=>c2str_preserving_blanks( 60 | exporting source = ', ' 61 | importing dest = c_comma ) . 62 | 63 | endmethod. 64 | 65 | 66 | METHOD recurse. 67 | 68 | DATA: 69 | l_node TYPE REF TO zabapfire_cl_json_node, 70 | l_abap_type TYPE REF TO cl_abap_typedescr, 71 | l_abap_stru TYPE REF TO cl_abap_structdescr, 72 | l_component TYPE abap_compdescr, 73 | l_rec TYPE REF TO data, 74 | l_name TYPE string. 75 | FIELD-SYMBOLS: 76 | TYPE ANY TABLE, 77 | TYPE any, 78 | TYPE any. 79 | 80 | l_abap_type = cl_abap_typedescr=>describe_by_data( comp ). 81 | 82 | * Create current node 83 | CHECK NOT name CA '$#[]/'. "In case ABAP strucutre contains a $KEY 84 | 85 | IF NOT name IS INITIAL. 86 | l_name = zabapfire_cl_http_util=>abap_lcc( name ). 87 | CONCATENATE '"' l_name '"' INTO l_name. 88 | ENDIF. 89 | IF l_abap_type->kind = cl_abap_typedescr=>kind_table. 90 | CREATE OBJECT l_node 91 | EXPORTING 92 | name = l_name 93 | array = abap_true. 94 | ELSE. 95 | CREATE OBJECT l_node 96 | EXPORTING 97 | name = l_name. 98 | ENDIF. 99 | * Add node to father if it exists 100 | IF node IS BOUND. 101 | node->add_child( l_node ). 102 | ENDIF. 103 | * Set first node of hierarchy 104 | IF NOT json_hierarchy IS BOUND. 105 | json_hierarchy = l_node. 106 | ENDIF. 107 | 108 | * Iterate on ABAP and build JSON Hierarchy 109 | IF l_abap_type->kind = cl_abap_typedescr=>kind_table. 110 | * ABAP Table 111 | ASSIGN comp TO . 112 | CREATE DATA l_rec LIKE LINE OF . 113 | ASSIGN l_rec->* TO . 114 | LOOP AT INTO . 115 | recurse( 116 | EXPORTING 117 | comp = 118 | CHANGING 119 | node = l_node ). 120 | ENDLOOP. 121 | ELSEIF l_abap_type->kind = cl_abap_typedescr=>kind_struct. 122 | * ABAP Structure 123 | l_abap_stru ?= cl_abap_typedescr=>describe_by_data( comp ). 124 | LOOP AT l_abap_stru->components INTO l_component. 125 | l_name = l_component-name. 126 | ASSIGN COMPONENT l_name OF STRUCTURE comp TO . 127 | recurse( 128 | EXPORTING 129 | comp = 130 | name = l_name 131 | CHANGING 132 | node = l_node ). 133 | ENDLOOP. 134 | ELSE. 135 | l_node->set_value( 136 | zabapfire_cl_http_util=>serialize_value( comp ) 137 | ). 138 | ENDIF. 139 | 140 | ENDMETHOD. 141 | 142 | 143 | METHOD recurse_json. 144 | 145 | DATA: 146 | l_children TYPE zabapfire_cl_json_node=>ty_nodes, 147 | l_node TYPE REF TO zabapfire_cl_json_node, 148 | l_len TYPE i, 149 | l_index TYPE i, 150 | l_name TYPE string, 151 | l_value TYPE string. 152 | 153 | l_children = node->get_children( ). 154 | l_name = node->get_name( ). 155 | l_value = node->get_value( ). 156 | 157 | l_len = lines( l_children ). 158 | 159 | IF NOT l_name IS INITIAL. 160 | APPEND l_name TO mt_lines. 161 | APPEND c_colon TO mt_lines. 162 | ENDIF. 163 | 164 | IF node->is_array( ) = abap_true. 165 | * Array 166 | APPEND '[' TO mt_lines. 167 | LOOP AT l_children INTO l_node. 168 | ADD 1 TO l_index . 169 | recurse_json( l_node ). 170 | IF l_index < l_len . 171 | APPEND c_comma TO mt_lines. 172 | ENDIF . 173 | ENDLOOP. 174 | APPEND ']' TO mt_lines . 175 | ELSEIF l_len > 0. 176 | * Object 177 | APPEND '{' TO mt_lines. 178 | LOOP AT l_children INTO l_node. 179 | ADD 1 TO l_index . 180 | recurse_json( l_node ). 181 | IF l_index < l_len . 182 | APPEND c_comma TO mt_lines. 183 | ENDIF . 184 | ENDLOOP. 185 | APPEND '}' TO mt_lines . 186 | ELSE. 187 | * Scalar value 188 | APPEND l_value TO mt_lines. 189 | ENDIF. 190 | 191 | ENDMETHOD. 192 | 193 | 194 | METHOD serialize. 195 | 196 | recurse( 197 | EXPORTING comp = abap ) . 198 | 199 | write_json( 200 | CHANGING 201 | json = json ). 202 | 203 | ENDMETHOD. 204 | 205 | 206 | METHOD write_json. 207 | 208 | recurse_json( json_hierarchy ). 209 | 210 | CONCATENATE LINES OF mt_lines INTO json . 211 | 212 | ENDMETHOD. 213 | ENDCLASS. 214 | -------------------------------------------------------------------------------- /src/zabapfire_cl_json_serializer.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPFIRE_CL_JSON_SERIALIZER 7 | 1 8 | E 9 | Serialize ABAP data into JSON format 10 | 2 11 | 1 12 | X 13 | X 14 | X 15 | X 16 | 17 | 18 | 19 | ZABAPFIRE_CL_JSON_SERIALIZER 20 | CLASS_CONSTRUCTOR 21 | E 22 | CLASS_CONSTRUCTOR 23 | 24 | 25 | ZABAPFIRE_CL_JSON_SERIALIZER 26 | JSON_HIERARCHY 27 | E 28 | JSON Node 29 | 30 | 31 | ZABAPFIRE_CL_JSON_SERIALIZER 32 | RECURSE_JSON 33 | E 34 | todo 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/zabapfire_demo.prog.abap: -------------------------------------------------------------------------------- 1 | *&---------------------------------------------------------------------* 2 | *& Report zabapfire_demo 3 | *&---------------------------------------------------------------------* 4 | *& 5 | *&---------------------------------------------------------------------* 6 | REPORT zabapfire_demo. 7 | TYPE-POOLS : slis. 8 | DATA: 9 | firebase TYPE REF TO zabapfire_cl_firebase, 10 | lcx_firebase TYPE REF TO zcx_abapfire_firebase, 11 | ls_config TYPE zabapfire_cl_firebase=>ty_firebase_config. 12 | 13 | PARAMETERS: 14 | p_email TYPE string LOWER CASE, 15 | p_pass TYPE string LOWER CASE, 16 | p_path TYPE string LOWER CASE DEFAULT '/flights' OBLIGATORY, 17 | p_get TYPE char1 RADIOBUTTON GROUP rb1 DEFAULT 'X', 18 | p_set TYPE char1 RADIOBUTTON GROUP rb1, 19 | p_push TYPE char1 RADIOBUTTON GROUP rb1, 20 | p_del TYPE char1 RADIOBUTTON GROUP rb1. 21 | 22 | AT SELECTION-SCREEN OUTPUT. 23 | 24 | LOOP AT SCREEN. 25 | IF screen-name = 'P_PASS'. 26 | screen-invisible = '1'. 27 | MODIFY SCREEN. 28 | ENDIF. 29 | ENDLOOP. 30 | 31 | START-OF-SELECTION. 32 | 33 | ********************************************************************** 34 | * Initialize App 35 | ********************************************************************** 36 | ls_config-apikey = '[your_apikey]'. 37 | ls_config-authdomain = '[your_authdomain]'. 38 | ls_config-databaseurl = '[your_databaseurl]'. 39 | ls_config-messagingsenderid = '[your_messagingsenderid]'. 40 | ls_config-projectid = '[your_projectid]'. 41 | ls_config-storagebucket = '[your_storagebucket]'. 42 | 43 | TRY. 44 | firebase = zabapfire_cl_firebase=>initialize_app( ls_config ). 45 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 46 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 47 | DISPLAY LIKE 'E'. 48 | EXIT. 49 | ENDTRY. 50 | 51 | ********************************************************************** 52 | * Authenticate 53 | ********************************************************************** 54 | TRY. 55 | firebase->auth->authenticate_with_email( 56 | EXPORTING 57 | email = p_email 58 | password = p_pass ). 59 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 60 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 61 | DISPLAY LIKE 'E'. 62 | EXIT. 63 | ENDTRY. 64 | 65 | ********************************************************************** 66 | * Get data 67 | ********************************************************************** 68 | TYPES: 69 | BEGIN OF ty_abap, 70 | $key TYPE string, 71 | carrid TYPE s_carr_id, 72 | connid TYPE s_conn_id, 73 | fldate TYPE s_date, 74 | planetype TYPE s_planetye, 75 | deptime TYPE s_dep_time, 76 | cityfrom TYPE s_from_cit, 77 | airpfrom TYPE s_fromairp, 78 | cityto TYPE s_to_city, 79 | airpto TYPE s_toairp, 80 | carrname TYPE s_carrname, 81 | END OF ty_abap. 82 | DATA: 83 | ls_parameters TYPE zabapfire_cl_firebase_db=>ty_get_parameters, 84 | lt_abap TYPE TABLE OF ty_abap, 85 | ls_fc TYPE slis_fieldcat_alv, 86 | lt_fc TYPE slis_t_fieldcat_alv. 87 | 88 | FIELD-SYMBOLS: 89 | TYPE ty_abap. 90 | 91 | IF p_get = abap_true. 92 | TRY. 93 | ls_parameters-order_by = 'carrid'. 94 | ls_parameters-equal_to = 'AC'. 95 | firebase->db->get( 96 | EXPORTING 97 | path = p_path 98 | parameters = ls_parameters 99 | IMPORTING 100 | child = lt_abap ). 101 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 102 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 103 | DISPLAY LIKE 'E'. 104 | EXIT. 105 | ENDTRY. 106 | ELSEIF p_del = abap_true. 107 | TRY. 108 | firebase->db->remove( 109 | EXPORTING 110 | path = p_path ). 111 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 112 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 113 | DISPLAY LIKE 'E'. 114 | EXIT. 115 | ENDTRY. 116 | ELSE. 117 | SELECT 118 | sflight~carrid AS carrid 119 | sflight~connid AS connid 120 | sflight~fldate AS fldate 121 | sflight~planetype AS planetype 122 | spfli~deptime AS deptime 123 | spfli~cityfrom AS cityfrom 124 | spfli~airpfrom AS airpfrom 125 | spfli~cityto AS cityto 126 | spfli~airpto AS airpto 127 | scarr~carrname AS carrname 128 | FROM sflight 129 | INNER JOIN spfli ON spfli~carrid = sflight~carrid AND 130 | spfli~connid = sflight~connid 131 | INNER JOIN scarr ON scarr~carrid = sflight~carrid 132 | INTO CORRESPONDING FIELDS OF TABLE lt_abap. 133 | 134 | IF p_set = abap_true. 135 | TRY. 136 | firebase->db->set( 137 | EXPORTING 138 | path = p_path 139 | child = lt_abap ). 140 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 141 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 142 | DISPLAY LIKE 'E'. 143 | EXIT. 144 | ENDTRY. 145 | ELSE. 146 | TRY. 147 | LOOP AT lt_abap ASSIGNING . 148 | -$key = firebase->db->push( 149 | EXPORTING 150 | path = p_path 151 | child = ). 152 | ENDLOOP. 153 | CATCH zcx_abapfire_firebase INTO lcx_firebase. 154 | MESSAGE i000(zabapfire_msg) WITH lcx_firebase->get_text( ) 155 | DISPLAY LIKE 'E'. 156 | EXIT. 157 | ENDTRY. 158 | ENDIF. 159 | ENDIF. 160 | 161 | ls_fc-fieldname = '$KEY'. 162 | ls_fc-seltext_m = 'Firebase key'. 163 | ls_fc-lowercase = abap_true. 164 | APPEND ls_fc TO lt_fc. CLEAR ls_fc. 165 | ls_fc-fieldname = 'CARRID'. 166 | ls_fc-seltext_m = 'Carrier Id'. 167 | APPEND ls_fc TO lt_fc. 168 | ls_fc-fieldname = 'CONNID'. 169 | ls_fc-seltext_m = 'Connection Id'. 170 | APPEND ls_fc TO lt_fc. 171 | 172 | CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY' 173 | EXPORTING 174 | it_fieldcat = lt_fc 175 | TABLES 176 | t_outtab = lt_abap 177 | EXCEPTIONS 178 | program_error = 1 179 | OTHERS = 2. 180 | -------------------------------------------------------------------------------- /src/zabapfire_demo.prog.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPFIRE_DEMO 7 | A 8 | X 9 | S 10 | 1 11 | X 12 | D$S 13 | X 14 | 15 | 16 | 17 | R 18 | ABAP Fire Demo Program 19 | 22 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/zabapfire_msg.msag.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZABAPFIRE_MSG 7 | E 8 | ABAPFire messages 9 | 10 | 11 | 12 | E 13 | ZABAPFIRE_MSG 14 | 000 15 | & 16 | 17 | 18 | E 19 | ZABAPFIRE_MSG 20 | 001 21 | && 22 | 23 | 24 | E 25 | ZABAPFIRE_MSG 26 | 002 27 | &&& 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/zcx_abapfire_firebase.clas.abap: -------------------------------------------------------------------------------- 1 | class ZCX_ABAPFIRE_FIREBASE definition 2 | public 3 | inheriting from CX_STATIC_CHECK 4 | final 5 | create public . 6 | 7 | public section. 8 | 9 | interfaces IF_T100_MESSAGE . 10 | 11 | data RAISE_ATTR1 type STRING . 12 | 13 | methods CONSTRUCTOR 14 | importing 15 | !TEXTID like IF_T100_MESSAGE=>T100KEY optional 16 | !PREVIOUS like PREVIOUS optional 17 | !RAISE_ATTR1 type STRING optional . 18 | class-methods RAISE 19 | importing 20 | !IV_TEXT type CLIKE 21 | raising 22 | ZCX_ABAPFIRE_FIREBASE . 23 | PROTECTED SECTION. 24 | PRIVATE SECTION. 25 | ENDCLASS. 26 | 27 | 28 | 29 | CLASS ZCX_ABAPFIRE_FIREBASE IMPLEMENTATION. 30 | 31 | 32 | method CONSTRUCTOR. 33 | CALL METHOD SUPER->CONSTRUCTOR 34 | EXPORTING 35 | PREVIOUS = PREVIOUS 36 | . 37 | me->RAISE_ATTR1 = RAISE_ATTR1 . 38 | clear me->textid. 39 | if textid is initial. 40 | IF_T100_MESSAGE~T100KEY = IF_T100_MESSAGE=>DEFAULT_TEXTID. 41 | else. 42 | IF_T100_MESSAGE~T100KEY = TEXTID. 43 | endif. 44 | endmethod. 45 | 46 | 47 | METHOD raise. 48 | 49 | DATA: BEGIN OF lv_msg, 50 | msgid TYPE symsgid VALUE 'ZABAPFIRE_MSG', 51 | msgno TYPE symsgno VALUE '000', 52 | attr1 TYPE scx_attrname VALUE 'RAISE_ATTR1', 53 | attr2 TYPE scx_attrname VALUE '', 54 | attr3 TYPE scx_attrname VALUE '', 55 | attr4 TYPE scx_attrname VALUE '', 56 | END OF lv_msg . 57 | 58 | RAISE EXCEPTION TYPE zcx_abapfire_firebase 59 | EXPORTING 60 | textid = lv_msg 61 | raise_attr1 = iv_text. 62 | 63 | ENDMETHOD. 64 | ENDCLASS. 65 | -------------------------------------------------------------------------------- /src/zcx_abapfire_firebase.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCX_ABAPFIRE_FIREBASE 7 | 1 8 | E 9 | Exceptions 10 | 40 11 | 2 12 | 1 13 | X 14 | X 15 | X 16 | X 17 | 18 | 19 | 20 | ZCX_ABAPFIRE_FIREBASE 21 | CONSTRUCTOR 22 | E 23 | CONSTRUCTOR 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/zcx_abapfire_json.clas.abap: -------------------------------------------------------------------------------- 1 | class ZCX_ABAPFIRE_JSON definition 2 | public 3 | inheriting from CX_STATIC_CHECK 4 | final 5 | create public . 6 | 7 | public section. 8 | 9 | interfaces IF_T100_MESSAGE . 10 | 11 | data RAISE_ATTR1 type STRING . 12 | 13 | methods CONSTRUCTOR 14 | importing 15 | !TEXTID like IF_T100_MESSAGE=>T100KEY optional 16 | !PREVIOUS like PREVIOUS optional 17 | !RAISE_ATTR1 type STRING optional . 18 | class-methods RAISE 19 | importing 20 | !IV_TEXT type CLIKE 21 | raising 22 | ZCX_ABAPFIRE_JSON . 23 | PROTECTED SECTION. 24 | PRIVATE SECTION. 25 | ENDCLASS. 26 | 27 | 28 | 29 | CLASS ZCX_ABAPFIRE_JSON IMPLEMENTATION. 30 | 31 | 32 | method CONSTRUCTOR ##ADT_SUPPRESS_GENERATION. 33 | CALL METHOD SUPER->CONSTRUCTOR 34 | EXPORTING 35 | PREVIOUS = PREVIOUS 36 | . 37 | me->RAISE_ATTR1 = RAISE_ATTR1 . 38 | clear me->textid. 39 | if textid is initial. 40 | IF_T100_MESSAGE~T100KEY = IF_T100_MESSAGE=>DEFAULT_TEXTID. 41 | else. 42 | IF_T100_MESSAGE~T100KEY = TEXTID. 43 | endif. 44 | endmethod. 45 | 46 | 47 | METHOD raise. 48 | 49 | DATA: BEGIN OF lv_msg, 50 | msgid TYPE symsgid VALUE 'ZABAPFIRE_MSG', 51 | msgno TYPE symsgno VALUE '000', 52 | attr1 TYPE scx_attrname VALUE 'RAISE_ATTR1', 53 | attr2 TYPE scx_attrname VALUE '', 54 | attr3 TYPE scx_attrname VALUE '', 55 | attr4 TYPE scx_attrname VALUE '', 56 | END OF lv_msg . 57 | 58 | RAISE EXCEPTION TYPE zcx_abapfire_json 59 | EXPORTING 60 | textid = lv_msg 61 | raise_attr1 = iv_text. 62 | 63 | ENDMETHOD. 64 | ENDCLASS. 65 | -------------------------------------------------------------------------------- /src/zcx_abapfire_json.clas.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | ZCX_ABAPFIRE_JSON 7 | 1 8 | E 9 | Exceptions 10 | 40 11 | 2 12 | 1 13 | X 14 | X 15 | X 16 | X 17 | 18 | 19 | 20 | ZCX_ABAPFIRE_JSON 21 | CONSTRUCTOR 22 | E 23 | CONSTRUCTOR 24 | 25 | 26 | 27 | 28 | 29 | --------------------------------------------------------------------------------