abapgit-agent 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,386 @@
1
+ *"*"use source
2
+ *"*"Local Interface:
3
+ *"**********************************************************************
4
+ CLASS zcl_abgagt_command_preview DEFINITION PUBLIC FINAL CREATE PUBLIC.
5
+
6
+ PUBLIC SECTION.
7
+ INTERFACES zif_abgagt_command.
8
+
9
+ " Parameter types matching CLI request
10
+ TYPES: BEGIN OF ty_preview_params,
11
+ objects TYPE string_table,
12
+ type TYPE string,
13
+ limit TYPE i,
14
+ where TYPE string,
15
+ columns TYPE string_table,
16
+ END OF ty_preview_params.
17
+
18
+ " Field metadata
19
+ TYPES: BEGIN OF ty_field,
20
+ field TYPE string,
21
+ type TYPE string,
22
+ length TYPE int4,
23
+ decimals TYPE int4,
24
+ END OF ty_field.
25
+
26
+ TYPES ty_fields TYPE STANDARD TABLE OF ty_field WITH DEFAULT KEY.
27
+
28
+ " Row data (dynamic)
29
+ TYPES: BEGIN OF ty_row_data,
30
+ row_index TYPE i,
31
+ data TYPE REF TO data,
32
+ END OF ty_row_data.
33
+
34
+ " Table/CVS view data result
35
+ TYPES: BEGIN OF ty_preview_object,
36
+ name TYPE string,
37
+ type TYPE string,
38
+ type_text TYPE string,
39
+ row_count TYPE i,
40
+ total_rows TYPE i,
41
+ rows TYPE string, " JSON string of rows
42
+ fields TYPE ty_fields,
43
+ columns_displayed TYPE i,
44
+ columns_hidden TYPE string_table,
45
+ error TYPE string,
46
+ END OF ty_preview_object.
47
+
48
+ TYPES ty_preview_objects TYPE STANDARD TABLE OF ty_preview_object WITH DEFAULT KEY.
49
+
50
+ TYPES: BEGIN OF ty_summary,
51
+ total_objects TYPE i,
52
+ total_rows TYPE i,
53
+ END OF ty_summary.
54
+
55
+ TYPES: BEGIN OF ty_preview_result,
56
+ success TYPE abap_bool,
57
+ command TYPE string,
58
+ message TYPE string,
59
+ objects TYPE ty_preview_objects,
60
+ summary TYPE ty_summary,
61
+ error TYPE string,
62
+ END OF ty_preview_result.
63
+
64
+ " Method declarations
65
+ METHODS get_table_data
66
+ IMPORTING
67
+ iv_name TYPE string
68
+ iv_type TYPE string
69
+ iv_limit TYPE i
70
+ iv_where TYPE string
71
+ it_columns TYPE string_table
72
+ RETURNING
73
+ VALUE(rs_result) TYPE ty_preview_object.
74
+
75
+ METHODS detect_object_type
76
+ IMPORTING
77
+ iv_name TYPE string
78
+ RETURNING
79
+ VALUE(rv_type) TYPE string.
80
+
81
+ METHODS fetch_table_data
82
+ IMPORTING
83
+ iv_tabname TYPE string
84
+ iv_limit TYPE i
85
+ iv_where TYPE string
86
+ it_columns TYPE string_table
87
+ CHANGING
88
+ cs_result TYPE ty_preview_object.
89
+
90
+ METHODS get_field_metadata
91
+ IMPORTING
92
+ it_components TYPE abap_component_tab
93
+ RETURNING
94
+ VALUE(rt_fields) TYPE ty_fields.
95
+
96
+ METHODS get_field_metadata_for_columns
97
+ IMPORTING
98
+ it_components TYPE abap_component_tab
99
+ it_columns TYPE string_table
100
+ RETURNING
101
+ VALUE(rt_fields) TYPE ty_fields.
102
+
103
+ ENDCLASS.
104
+
105
+ CLASS zcl_abgagt_command_preview IMPLEMENTATION.
106
+
107
+ METHOD zif_abgagt_command~get_name.
108
+ rv_name = zif_abgagt_command=>gc_preview.
109
+ ENDMETHOD.
110
+
111
+ METHOD zif_abgagt_command~execute.
112
+ " Parse parameters
113
+ DATA: ls_params TYPE ty_preview_params,
114
+ ls_result TYPE ty_preview_result.
115
+
116
+ ls_result-command = zif_abgagt_command=>gc_preview.
117
+
118
+ IF is_param IS SUPPLIED.
119
+ ls_params = CORRESPONDING #( is_param ).
120
+ ENDIF.
121
+
122
+ IF ls_params-objects IS INITIAL.
123
+ ls_result-success = abap_false.
124
+ ls_result-error = 'Objects parameter is required'.
125
+ rv_result = /ui2/cl_json=>serialize( data = ls_result ).
126
+ RETURN.
127
+ ENDIF.
128
+
129
+ " Process each object
130
+ DATA lt_objects TYPE ty_preview_objects.
131
+ DATA lv_object TYPE string.
132
+ DATA lv_total_rows TYPE i.
133
+
134
+ LOOP AT ls_params-objects INTO lv_object.
135
+ DATA(ls_obj) = get_table_data(
136
+ iv_name = lv_object
137
+ iv_type = ls_params-type
138
+ iv_limit = ls_params-limit
139
+ iv_where = ls_params-where
140
+ it_columns = ls_params-columns ).
141
+
142
+ APPEND ls_obj TO lt_objects.
143
+ lv_total_rows = lv_total_rows + ls_obj-row_count.
144
+ ENDLOOP.
145
+
146
+ " Build result
147
+ ls_result-success = abap_true.
148
+ ls_result-message = 'Retrieved data'.
149
+ ls_result-objects = lt_objects.
150
+
151
+ " Build summary
152
+ DATA ls_summary TYPE ty_summary.
153
+ ls_summary-total_objects = lines( lt_objects ).
154
+ ls_summary-total_rows = lv_total_rows.
155
+
156
+ " We need to serialize with summary inline
157
+ DATA: BEGIN OF ls_final,
158
+ success TYPE abap_bool,
159
+ command TYPE string,
160
+ message TYPE string,
161
+ objects TYPE ty_preview_objects,
162
+ summary TYPE ty_summary,
163
+ error TYPE string,
164
+ END OF ls_final.
165
+
166
+ ls_final = CORRESPONDING #( ls_result ).
167
+ ls_final-summary = ls_summary.
168
+
169
+ rv_result = /ui2/cl_json=>serialize( data = ls_final ).
170
+ ENDMETHOD.
171
+
172
+ METHOD get_table_data.
173
+ DATA: ls_result TYPE ty_preview_object,
174
+ lv_tabname TYPE string,
175
+ lv_type TYPE string.
176
+
177
+ ls_result-name = iv_name.
178
+ lv_tabname = to_upper( iv_name ).
179
+ lv_type = to_upper( iv_type ).
180
+
181
+ IF lv_tabname IS INITIAL.
182
+ lv_tabname = iv_name.
183
+ ENDIF.
184
+ IF lv_type IS INITIAL.
185
+ lv_type = iv_type.
186
+ ENDIF.
187
+
188
+ " Auto-detect type if not specified
189
+ IF lv_type IS INITIAL.
190
+ lv_type = detect_object_type( lv_tabname ).
191
+ ENDIF.
192
+
193
+ ls_result-type = lv_type.
194
+
195
+ CASE lv_type.
196
+ WHEN 'TABL' OR 'DDLS' OR ''.
197
+ ls_result-type_text = COND #( WHEN lv_type = 'DDLS' THEN 'CDS View' ELSE 'Table' ).
198
+
199
+ " Get table metadata and data
200
+ fetch_table_data(
201
+ EXPORTING
202
+ iv_tabname = lv_tabname
203
+ iv_limit = iv_limit
204
+ iv_where = iv_where
205
+ it_columns = it_columns
206
+ CHANGING
207
+ cs_result = ls_result ).
208
+
209
+ IF ls_result-error IS NOT INITIAL.
210
+ ls_result-type_text = lv_type.
211
+ ENDIF.
212
+
213
+ WHEN OTHERS.
214
+ ls_result-type_text = lv_type.
215
+ ls_result-row_count = 0.
216
+ ENDCASE.
217
+
218
+ rs_result = ls_result.
219
+ ENDMETHOD.
220
+
221
+ METHOD detect_object_type.
222
+ DATA lv_name TYPE string.
223
+ lv_name = to_upper( iv_name ).
224
+
225
+ " Check if table or CDS view exists in TADIR
226
+ SELECT SINGLE object FROM tadir
227
+ INTO rv_type
228
+ WHERE obj_name = lv_name
229
+ AND object IN ('TABL', 'DDLS').
230
+
231
+ IF sy-subrc <> 0.
232
+ " Default to table if not found in TADIR
233
+ rv_type = 'TABL'.
234
+ ENDIF.
235
+ ENDMETHOD.
236
+
237
+ METHOD fetch_table_data.
238
+ DATA: lv_error TYPE string,
239
+ lr_data TYPE REF TO data,
240
+ lo_tabdescr TYPE REF TO cl_abap_tabledescr,
241
+ lo_strucdescr TYPE REF TO cl_abap_structdescr,
242
+ lt_components TYPE abap_component_tab,
243
+ lv_field_list TYPE string,
244
+ lv_limit TYPE i.
245
+
246
+ FIELD-SYMBOLS <lt_data> TYPE STANDARD TABLE.
247
+
248
+ lv_limit = iv_limit.
249
+ IF lv_limit <= 0.
250
+ lv_limit = 10.
251
+ ENDIF.
252
+
253
+ " Check if table/view exists in DD02L
254
+ DATA lv_tabname_check TYPE dd02l-tabname.
255
+ SELECT SINGLE tabname FROM dd02l
256
+ INTO lv_tabname_check
257
+ WHERE tabname = iv_tabname
258
+ AND as4local = 'A'
259
+ AND tabclass IN ('TRANSP', 'VIEW').
260
+
261
+ IF sy-subrc <> 0.
262
+ cs_result-error = |Table or view not found: { iv_tabname }|.
263
+ cs_result-row_count = 0.
264
+ RETURN.
265
+ ENDIF.
266
+
267
+ TRY.
268
+ " Get structure descriptor first (describe_by_name returns struct descr for table lines)
269
+ lo_strucdescr ?= cl_abap_structdescr=>describe_by_name( iv_tabname ).
270
+ " Create table descriptor from structure
271
+ lo_tabdescr = cl_abap_tabledescr=>create( lo_strucdescr ).
272
+ lt_components = lo_strucdescr->get_components( ).
273
+
274
+ " Handle column selection
275
+ DATA lt_cols TYPE string_table.
276
+ lt_cols = it_columns.
277
+
278
+ IF lt_cols IS NOT INITIAL.
279
+ " Build field list from specified columns
280
+ LOOP AT lt_components INTO DATA(ls_comp).
281
+ READ TABLE lt_cols WITH KEY table_line = ls_comp-name TRANSPORTING NO FIELDS.
282
+ IF sy-subrc = 0.
283
+ IF lv_field_list IS INITIAL.
284
+ lv_field_list = ls_comp-name.
285
+ ELSE.
286
+ lv_field_list = lv_field_list && ',' && ls_comp-name.
287
+ ENDIF.
288
+ ELSE.
289
+ " Track hidden columns
290
+ APPEND ls_comp-name TO cs_result-columns_hidden.
291
+ ENDIF.
292
+ ENDLOOP.
293
+ ELSE.
294
+ " All columns
295
+ LOOP AT lt_components INTO ls_comp.
296
+ IF lv_field_list IS INITIAL.
297
+ lv_field_list = ls_comp-name.
298
+ ELSE.
299
+ lv_field_list = lv_field_list && ',' && ls_comp-name.
300
+ ENDIF.
301
+ ENDLOOP.
302
+ ENDIF.
303
+
304
+ " Create data reference for the internal table
305
+ CREATE DATA lr_data TYPE HANDLE lo_tabdescr.
306
+ ASSIGN lr_data->* TO <lt_data>.
307
+
308
+ " Use SELECT * - dynamic field list has parser issues
309
+ " Column filtering will be done in the response
310
+ IF iv_where IS INITIAL.
311
+ SELECT * FROM (iv_tabname)
312
+ INTO TABLE <lt_data>
313
+ UP TO lv_limit ROWS.
314
+ ELSE.
315
+ SELECT * FROM (iv_tabname)
316
+ INTO TABLE <lt_data>
317
+ UP TO lv_limit ROWS
318
+ WHERE (iv_where).
319
+ ENDIF.
320
+
321
+ " Get row count
322
+ cs_result-row_count = lines( <lt_data> ).
323
+ cs_result-total_rows = cs_result-row_count.
324
+
325
+ " Get field metadata for selected columns only
326
+ cs_result-fields = get_field_metadata_for_columns(
327
+ it_components = lt_components
328
+ it_columns = lt_cols ).
329
+
330
+ " Serialize data to JSON
331
+ cs_result-rows = /ui2/cl_json=>serialize( data = <lt_data> ).
332
+
333
+ " Set column info
334
+ cs_result-columns_displayed = lines( cs_result-fields ).
335
+
336
+ CATCH cx_root INTO DATA(lx_error).
337
+ lv_error = lx_error->get_text( ).
338
+ cs_result-error = lv_error.
339
+ cs_result-row_count = 0.
340
+ ENDTRY.
341
+ ENDMETHOD.
342
+
343
+ METHOD get_field_metadata.
344
+ DATA ls_field TYPE ty_field.
345
+
346
+ LOOP AT it_components ASSIGNING FIELD-SYMBOL(<comp>).
347
+ ls_field-field = <comp>-name.
348
+
349
+ " Get type info from the component
350
+ IF <comp>-type IS BOUND.
351
+ DATA(lo_type) = <comp>-type.
352
+ ls_field-type = lo_type->type_kind.
353
+ ls_field-length = lo_type->length.
354
+ ls_field-decimals = lo_type->decimals.
355
+ ENDIF.
356
+
357
+ APPEND ls_field TO rt_fields.
358
+ ENDLOOP.
359
+ ENDMETHOD.
360
+
361
+ METHOD get_field_metadata_for_columns.
362
+ DATA ls_field TYPE ty_field.
363
+
364
+ " If no columns specified, return all
365
+ IF it_columns IS INITIAL.
366
+ rt_fields = get_field_metadata( it_components ).
367
+ RETURN.
368
+ ENDIF.
369
+
370
+ " Filter to selected columns only
371
+ LOOP AT it_components ASSIGNING FIELD-SYMBOL(<comp>).
372
+ READ TABLE it_columns WITH KEY table_line = <comp>-name TRANSPORTING NO FIELDS.
373
+ IF sy-subrc = 0.
374
+ ls_field-field = <comp>-name.
375
+ IF <comp>-type IS BOUND.
376
+ DATA(lo_type) = <comp>-type.
377
+ ls_field-type = lo_type->type_kind.
378
+ ls_field-length = lo_type->length.
379
+ ls_field-decimals = lo_type->decimals.
380
+ ENDIF.
381
+ APPEND ls_field TO rt_fields.
382
+ ENDIF.
383
+ ENDLOOP.
384
+ ENDMETHOD.
385
+
386
+ ENDCLASS.
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
3
+ <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
4
+ <asx:values>
5
+ <VSEOCLASS>
6
+ <CLSNAME>ZCL_ABGAGT_COMMAND_PREVIEW</CLSNAME>
7
+ <LANGU>E</LANGU>
8
+ <DESCRIPT>PREVIEW command - preview table/CDS view data</DESCRIPT>
9
+ <EXPOSURE>2</EXPOSURE>
10
+ <STATE>1</STATE>
11
+ <UNICODE>X</UNICODE>
12
+ </VSEOCLASS>
13
+ </asx:values>
14
+ </asx:abap>
15
+ </abapGit>
@@ -0,0 +1,67 @@
1
+ *"*"use source
2
+ *"*"Local Interface:
3
+ *"**********************************************************************
4
+ CLASS zcl_abgagt_resource_preview DEFINITION PUBLIC FINAL
5
+ INHERITING FROM cl_rest_resource
6
+ CREATE PUBLIC.
7
+
8
+ PUBLIC SECTION.
9
+ METHODS if_rest_resource~post REDEFINITION.
10
+
11
+ ENDCLASS.
12
+
13
+ CLASS zcl_abgagt_resource_preview IMPLEMENTATION.
14
+
15
+ METHOD if_rest_resource~post.
16
+ DATA lv_json TYPE string.
17
+ lv_json = mo_request->get_entity( )->get_string_data( ).
18
+
19
+ " Parse JSON using /ui2/cl_json
20
+ DATA: BEGIN OF ls_request,
21
+ objects TYPE string_table,
22
+ type TYPE string,
23
+ limit TYPE i,
24
+ where TYPE string,
25
+ columns TYPE string_table,
26
+ END OF ls_request.
27
+
28
+ /ui2/cl_json=>deserialize(
29
+ EXPORTING
30
+ json = lv_json
31
+ CHANGING
32
+ data = ls_request ).
33
+
34
+ DATA lv_json_resp TYPE string.
35
+
36
+ IF ls_request-objects IS INITIAL.
37
+ lv_json_resp = '{"success":false,"command":"PREVIEW","error":"Objects parameter is required"}'.
38
+ DATA(lo_entity) = mo_response->create_entity( ).
39
+ lo_entity->set_content_type( iv_media_type = if_rest_media_type=>gc_appl_json ).
40
+ lo_entity->set_string_data( lv_json_resp ).
41
+ mo_response->set_status( cl_rest_status_code=>gc_client_error_bad_request ).
42
+ RETURN.
43
+ ENDIF.
44
+
45
+ " Get command from factory
46
+ DATA(lo_factory) = zcl_abgagt_cmd_factory=>get_instance( ).
47
+ DATA(lo_command) = lo_factory->get_command( zif_abgagt_command=>gc_preview ).
48
+
49
+ IF lo_command IS NOT BOUND.
50
+ lv_json_resp = '{"success":false,"command":"PREVIEW","error":"PREVIEW command not found"}'.
51
+ lo_entity = mo_response->create_entity( ).
52
+ lo_entity->set_content_type( iv_media_type = if_rest_media_type=>gc_appl_json ).
53
+ lo_entity->set_string_data( lv_json_resp ).
54
+ mo_response->set_status( cl_rest_status_code=>gc_client_error_bad_request ).
55
+ RETURN.
56
+ ENDIF.
57
+
58
+ " Execute command - pass request as generic parameter
59
+ DATA(lv_result) = lo_command->execute( is_param = ls_request ).
60
+
61
+ lo_entity = mo_response->create_entity( ).
62
+ lo_entity->set_content_type( iv_media_type = if_rest_media_type=>gc_appl_json ).
63
+ lo_entity->set_string_data( lv_result ).
64
+ mo_response->set_status( cl_rest_status_code=>gc_success_ok ).
65
+ ENDMETHOD.
66
+
67
+ ENDCLASS.
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
3
+ <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
4
+ <asx:values>
5
+ <VSEOCLASS>
6
+ <CLSNAME>ZCL_ABGAGT_RESOURCE_PREVIEW</CLSNAME>
7
+ <LANGU>E</LANGU>
8
+ <DESCRIPT>PREVIEW command REST resource handler</DESCRIPT>
9
+ <EXPOSURE>2</EXPOSURE>
10
+ <STATE>1</STATE>
11
+ <UNICODE>X</UNICODE>
12
+ </VSEOCLASS>
13
+ </asx:values>
14
+ </asx:abap>
15
+ </abapGit>
@@ -24,6 +24,7 @@ CLASS zcl_abgagt_rest_handler IMPLEMENTATION.
24
24
  lo_router->attach( iv_template = '/import' iv_handler_class = 'ZCL_ABGAGT_RESOURCE_IMPORT' ).
25
25
  lo_router->attach( iv_template = '/tree' iv_handler_class = 'ZCL_ABGAGT_RESOURCE_TREE' ).
26
26
  lo_router->attach( iv_template = '/view' iv_handler_class = 'ZCL_ABGAGT_RESOURCE_VIEW' ).
27
+ lo_router->attach( iv_template = '/preview' iv_handler_class = 'ZCL_ABGAGT_RESOURCE_PREVIEW' ).
27
28
 
28
29
  ro_root_handler = lo_router.
29
30
  ENDMETHOD.
@@ -9,7 +9,8 @@ INTERFACE zif_abgagt_command PUBLIC.
9
9
  gc_create TYPE string VALUE 'CREATE',
10
10
  gc_import TYPE string VALUE 'IMPORT',
11
11
  gc_tree TYPE string VALUE 'TREE',
12
- gc_view TYPE string VALUE 'VIEW'.
12
+ gc_view TYPE string VALUE 'VIEW',
13
+ gc_preview TYPE string VALUE 'PREVIEW'.
13
14
 
14
15
  " Get command name
15
16
  METHODS get_name