abapgit-agent 1.1.6 → 1.3.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.
Files changed (46) hide show
  1. package/.github/workflows/release.yml +3 -1
  2. package/API.md +261 -0
  3. package/CLAUDE.md +384 -0
  4. package/README.md +16 -2
  5. package/RELEASE_NOTES.md +93 -8
  6. package/abap/CLAUDE.md +282 -6
  7. package/abap/copilot-instructions.md +79 -0
  8. package/abap/zcl_abgagt_agent.clas.abap +2 -2
  9. package/abap/zcl_abgagt_cmd_factory.clas.abap +2 -0
  10. package/abap/zcl_abgagt_command_inspect.clas.abap +255 -36
  11. package/abap/zcl_abgagt_command_tree.clas.abap +237 -0
  12. package/abap/zcl_abgagt_command_tree.clas.xml +15 -0
  13. package/abap/zcl_abgagt_command_view.clas.abap +240 -0
  14. package/abap/zcl_abgagt_command_view.clas.xml +15 -0
  15. package/abap/zcl_abgagt_resource_tree.clas.abap +70 -0
  16. package/abap/zcl_abgagt_resource_tree.clas.xml +15 -0
  17. package/abap/zcl_abgagt_resource_view.clas.abap +68 -0
  18. package/abap/zcl_abgagt_resource_view.clas.xml +15 -0
  19. package/abap/zcl_abgagt_rest_handler.clas.abap +2 -0
  20. package/abap/zcl_abgagt_util.clas.abap +2 -2
  21. package/abap/zcl_abgagt_viewer_clas.clas.abap +58 -0
  22. package/abap/zcl_abgagt_viewer_clas.clas.xml +15 -0
  23. package/abap/zcl_abgagt_viewer_ddls.clas.abap +83 -0
  24. package/abap/zcl_abgagt_viewer_ddls.clas.xml +15 -0
  25. package/abap/zcl_abgagt_viewer_dtel.clas.abap +98 -0
  26. package/abap/zcl_abgagt_viewer_dtel.clas.xml +15 -0
  27. package/abap/zcl_abgagt_viewer_factory.clas.abap +41 -0
  28. package/abap/zcl_abgagt_viewer_factory.clas.xml +15 -0
  29. package/abap/zcl_abgagt_viewer_intf.clas.abap +58 -0
  30. package/abap/zcl_abgagt_viewer_intf.clas.xml +15 -0
  31. package/abap/zcl_abgagt_viewer_stru.clas.abap +59 -0
  32. package/abap/zcl_abgagt_viewer_stru.clas.xml +15 -0
  33. package/abap/zcl_abgagt_viewer_tabl.clas.abap +59 -0
  34. package/abap/zcl_abgagt_viewer_tabl.clas.xml +15 -0
  35. package/abap/zcl_abgagt_viewer_ttyp.clas.abap +93 -0
  36. package/abap/zcl_abgagt_viewer_ttyp.clas.xml +15 -0
  37. package/abap/zif_abgagt_command.intf.abap +3 -1
  38. package/abap/zif_abgagt_viewer.intf.abap +12 -0
  39. package/abap/zif_abgagt_viewer.intf.xml +15 -0
  40. package/bin/abapgit-agent +605 -38
  41. package/docs/commands.md +27 -8
  42. package/docs/tree-command.md +303 -0
  43. package/docs/view-command.md +501 -0
  44. package/package.json +1 -1
  45. package/src/abap-client.js +22 -0
  46. package/src/agent.js +27 -0
@@ -6,6 +6,7 @@ CLASS zcl_abgagt_command_inspect DEFINITION PUBLIC FINAL CREATE PUBLIC.
6
6
  PUBLIC SECTION.
7
7
  INTERFACES zif_abgagt_command.
8
8
 
9
+ " Error structure for syntax check results
9
10
  TYPES: BEGIN OF ty_error,
10
11
  line TYPE string,
11
12
  column TYPE string,
@@ -15,21 +16,49 @@ CLASS zcl_abgagt_command_inspect DEFINITION PUBLIC FINAL CREATE PUBLIC.
15
16
 
16
17
  TYPES ty_errors TYPE STANDARD TABLE OF ty_error WITH NON-UNIQUE DEFAULT KEY.
17
18
 
19
+ " Generic warning structure (for DDLS and other objects)
20
+ TYPES: BEGIN OF ty_warning,
21
+ type TYPE string,
22
+ line TYPE string,
23
+ column TYPE string,
24
+ severity TYPE string,
25
+ message TYPE string,
26
+ object_type TYPE string,
27
+ object_name TYPE string,
28
+ END OF ty_warning.
29
+
30
+ TYPES ty_warnings TYPE STANDARD TABLE OF ty_warning WITH NON-UNIQUE DEFAULT KEY.
31
+
32
+ " Result for each individual object
18
33
  TYPES: BEGIN OF ty_inspect_result,
34
+ object_type TYPE string,
35
+ object_name TYPE string,
19
36
  success TYPE abap_bool,
20
37
  error_count TYPE i,
21
38
  errors TYPE ty_errors,
39
+ warnings TYPE ty_warnings,
22
40
  END OF ty_inspect_result.
23
41
 
42
+ " Table to hold results for multiple objects
43
+ TYPES ty_inspect_results TYPE STANDARD TABLE OF ty_inspect_result WITH NON-UNIQUE DEFAULT KEY.
44
+
24
45
  TYPES: BEGIN OF ty_inspect_params,
25
46
  files TYPE string_table,
26
47
  END OF ty_inspect_params.
27
48
 
28
49
  TYPES ty_object_keys TYPE TABLE OF scir_objs WITH NON-UNIQUE DEFAULT KEY.
29
50
 
51
+ " Type for DDLS object names
52
+ TYPES ty_ddls_names TYPE STANDARD TABLE OF tadir-obj_name WITH NON-UNIQUE DEFAULT KEY.
53
+
30
54
  METHODS run_syntax_check
31
55
  IMPORTING it_objects TYPE ty_object_keys
32
- RETURNING VALUE(rs_result) TYPE ty_inspect_result.
56
+ RETURNING VALUE(rt_results) TYPE ty_inspect_results.
57
+
58
+ " Validate DDLS (CDS views)
59
+ METHODS validate_ddls
60
+ IMPORTING it_ddls_names TYPE ty_ddls_names
61
+ RETURNING VALUE(rt_results) TYPE ty_inspect_results.
33
62
 
34
63
  ENDCLASS.
35
64
 
@@ -45,9 +74,11 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
45
74
  lv_obj_type TYPE string,
46
75
  lv_obj_name TYPE string,
47
76
  lo_util TYPE REF TO zcl_abgagt_util,
48
- ls_result TYPE ty_inspect_result,
77
+ lt_results TYPE ty_inspect_results,
49
78
  lt_objects TYPE ty_object_keys,
50
- ls_obj TYPE scir_objs.
79
+ lt_ddls_names TYPE ty_ddls_names,
80
+ ls_obj TYPE scir_objs,
81
+ ls_result TYPE ty_inspect_result.
51
82
 
52
83
  " Parse parameters from is_param
53
84
  IF is_param IS SUPPLIED.
@@ -57,7 +88,10 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
57
88
  IF ls_params-files IS INITIAL.
58
89
  ls_result-success = abap_false.
59
90
  ls_result-error_count = 1.
60
- rv_result = /ui2/cl_json=>serialize( data = ls_result ).
91
+ ls_result-object_name = 'N/A'.
92
+ ls_result-object_type = 'N/A'.
93
+ APPEND ls_result TO lt_results.
94
+ rv_result = /ui2/cl_json=>serialize( data = lt_results ).
61
95
  RETURN.
62
96
  ENDIF.
63
97
 
@@ -72,24 +106,191 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
72
106
  ev_obj_name = lv_obj_name ).
73
107
 
74
108
  IF lv_obj_type IS NOT INITIAL AND lv_obj_name IS NOT INITIAL.
75
- CLEAR ls_obj.
76
- ls_obj-objtype = lv_obj_type.
77
- ls_obj-objname = lv_obj_name.
78
- APPEND ls_obj TO lt_objects.
109
+ " Separate DDLS from other objects
110
+ IF lv_obj_type = 'DDLS'.
111
+ APPEND lv_obj_name TO lt_ddls_names.
112
+ ELSE.
113
+ CLEAR ls_obj.
114
+ ls_obj-objtype = lv_obj_type.
115
+ ls_obj-objname = lv_obj_name.
116
+ APPEND ls_obj TO lt_objects.
117
+ ENDIF.
79
118
  ENDIF.
80
119
  ENDLOOP.
81
120
 
82
- IF lt_objects IS INITIAL.
121
+ " Run syntax check for non-DDLS objects
122
+ IF lt_objects IS NOT INITIAL.
123
+ DATA(lt_sci_results) = run_syntax_check( lt_objects ).
124
+ INSERT LINES OF lt_sci_results INTO TABLE lt_results.
125
+ ENDIF.
126
+
127
+ " Run DDLS validation
128
+ IF lt_ddls_names IS NOT INITIAL.
129
+ DATA(lt_ddls_results) = validate_ddls( lt_ddls_names ).
130
+ INSERT LINES OF lt_ddls_results INTO TABLE lt_results.
131
+ ENDIF.
132
+
133
+ " If no valid objects found
134
+ IF lt_objects IS INITIAL AND lt_ddls_names IS INITIAL.
83
135
  ls_result-success = abap_false.
84
136
  ls_result-error_count = 1.
85
- rv_result = /ui2/cl_json=>serialize( data = ls_result ).
86
- RETURN.
137
+ ls_result-object_name = 'N/A'.
138
+ ls_result-object_type = 'N/A'.
139
+ APPEND ls_result TO lt_results.
87
140
  ENDIF.
88
141
 
89
- " Run syntax check for all objects together
90
- ls_result = run_syntax_check( lt_objects ).
142
+ rv_result = /ui2/cl_json=>serialize( data = lt_results ).
143
+ ENDMETHOD.
91
144
 
92
- rv_result = /ui2/cl_json=>serialize( data = ls_result ).
145
+ METHOD validate_ddls.
146
+ " Validate DDLS (CDS views) using CL_DD_DDL_HANDLER_FACTORY
147
+ " First checks inactive version ('M'), falls back to active ('A')
148
+ DATA: lv_ddls_name TYPE ddlname,
149
+ lo_handler TYPE REF TO if_dd_ddl_handler,
150
+ ls_ddlsrcv TYPE ddddlsrcv,
151
+ ls_error TYPE ty_error,
152
+ ls_warning TYPE ty_warning,
153
+ lt_warnings TYPE ddl2ddicwarnings,
154
+ lx_error TYPE REF TO cx_dd_ddl_check,
155
+ lv_found TYPE abap_bool,
156
+ ls_result TYPE ty_inspect_result,
157
+ lv_err_msg TYPE string,
158
+ lv_warn_msg TYPE string.
159
+
160
+ rt_results = VALUE #( ).
161
+
162
+ " Create DDL handler
163
+ lo_handler = cl_dd_ddl_handler_factory=>create( ).
164
+
165
+ " Check each DDLS object
166
+ LOOP AT it_ddls_names INTO lv_ddls_name.
167
+ CLEAR: ls_ddlsrcv, lt_warnings, lv_found, ls_result.
168
+
169
+ ls_result-object_type = 'DDLS'.
170
+ ls_result-object_name = lv_ddls_name.
171
+ ls_result-success = abap_true.
172
+
173
+ " First try to read inactive version (get_state = 'M')
174
+ TRY.
175
+ lo_handler->read(
176
+ EXPORTING
177
+ name = lv_ddls_name
178
+ get_state = 'M'
179
+ IMPORTING
180
+ ddddlsrcv_wa = ls_ddlsrcv ).
181
+
182
+ IF ls_ddlsrcv-source IS NOT INITIAL.
183
+ lv_found = abap_true.
184
+ ENDIF.
185
+
186
+ CATCH cx_dd_ddl_check.
187
+ " Ignore - will try active version
188
+ ENDTRY.
189
+
190
+ " If no inactive version, try active version
191
+ IF lv_found = abap_false.
192
+ TRY.
193
+ lo_handler->read(
194
+ EXPORTING
195
+ name = lv_ddls_name
196
+ get_state = 'A'
197
+ IMPORTING
198
+ ddddlsrcv_wa = ls_ddlsrcv ).
199
+
200
+ IF ls_ddlsrcv-source IS NOT INITIAL.
201
+ lv_found = abap_true.
202
+ ENDIF.
203
+ CATCH cx_dd_ddl_check.
204
+ " Ignore
205
+ ENDTRY.
206
+ ENDIF.
207
+
208
+ " If still not found, report error
209
+ IF lv_found = abap_false.
210
+ ls_error-line = '1'.
211
+ ls_error-column = '1'.
212
+ ls_error-text = |DDLS { lv_ddls_name } not found in repository|.
213
+ APPEND ls_error TO ls_result-errors.
214
+ ls_result-success = abap_false.
215
+ ls_result-error_count = lines( ls_result-errors ).
216
+ APPEND ls_result TO rt_results.
217
+ CONTINUE.
218
+ ENDIF.
219
+
220
+ " Run validation check
221
+ TRY.
222
+ " Get warnings from check method
223
+ lo_handler->check(
224
+ EXPORTING
225
+ name = lv_ddls_name
226
+ IMPORTING
227
+ warnings = lt_warnings
228
+ CHANGING
229
+ ddlsrcv_wa = ls_ddlsrcv ).
230
+
231
+ " Parse warnings from check method
232
+ LOOP AT lt_warnings INTO DATA(ls_warn_from_check).
233
+ CLEAR ls_warning.
234
+ ls_warning-type = ls_warn_from_check-type.
235
+ ls_warning-line = ls_warn_from_check-line.
236
+ ls_warning-column = ls_warn_from_check-column.
237
+ ls_warning-severity = ls_warn_from_check-severity.
238
+ ls_warning-object_type = 'DDLS'.
239
+ ls_warning-object_name = lv_ddls_name.
240
+ " Use MESSAGE statement to get real warning message
241
+ MESSAGE ID ls_warn_from_check-arbgb TYPE 'E' NUMBER ls_warn_from_check-msgnr
242
+ WITH ls_warn_from_check-var1 ls_warn_from_check-var2 ls_warn_from_check-var3 ls_warn_from_check-var4
243
+ INTO lv_warn_msg.
244
+ ls_warning-message = lv_warn_msg.
245
+ APPEND ls_warning TO ls_result-warnings.
246
+ ENDLOOP.
247
+
248
+ " If no errors and no warnings, validation passed
249
+ IF ls_result-warnings IS INITIAL.
250
+ ls_result-success = abap_true.
251
+ ELSE.
252
+ ls_result-success = abap_false.
253
+ ENDIF.
254
+
255
+ CATCH cx_dd_ddl_check INTO lx_error.
256
+ " Validation failed - get error details using get_errors method
257
+ DATA(lt_errors) = lx_error->get_errors( ).
258
+ LOOP AT lt_errors INTO DATA(ls_err).
259
+ CLEAR ls_error.
260
+ ls_error-line = ls_err-line.
261
+ ls_error-column = ls_err-column.
262
+ " Use MESSAGE statement to get real error message
263
+ MESSAGE ID ls_err-arbgb TYPE 'E' NUMBER ls_err-msgnr
264
+ WITH ls_err-var1 ls_err-var2 ls_err-var3 ls_err-var4
265
+ INTO lv_err_msg.
266
+ ls_error-text = lv_err_msg.
267
+ APPEND ls_error TO ls_result-errors.
268
+ ENDLOOP.
269
+
270
+ " Also get warnings if any
271
+ DATA(lt_warn) = lx_error->get_warnings( ).
272
+ LOOP AT lt_warn INTO DATA(ls_warn2).
273
+ CLEAR ls_warning.
274
+ ls_warning-type = ls_warn2-type.
275
+ ls_warning-line = ls_warn2-line.
276
+ ls_warning-column = ls_warn2-column.
277
+ ls_warning-severity = ls_warn2-severity.
278
+ ls_warning-object_type = 'DDLS'.
279
+ ls_warning-object_name = lv_ddls_name.
280
+ " Use MESSAGE statement to get real warning message
281
+ MESSAGE ID ls_warn2-arbgb TYPE 'E' NUMBER ls_warn2-msgnr
282
+ WITH ls_warn2-var1 ls_warn2-var2 ls_warn2-var3 ls_warn2-var4
283
+ INTO lv_warn_msg.
284
+ ls_warning-message = lv_warn_msg.
285
+ APPEND ls_warning TO ls_result-warnings.
286
+ ENDLOOP.
287
+
288
+ ls_result-success = abap_false.
289
+ ENDTRY.
290
+
291
+ ls_result-error_count = lines( ls_result-errors ).
292
+ APPEND ls_result TO rt_results.
293
+ ENDLOOP.
93
294
  ENDMETHOD.
94
295
 
95
296
  METHOD run_syntax_check.
@@ -99,9 +300,11 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
99
300
  lo_inspection TYPE REF TO cl_ci_inspection,
100
301
  lt_list TYPE scit_alvlist,
101
302
  ls_error TYPE ty_error,
102
- lx_error TYPE REF TO cx_root.
303
+ ls_list TYPE scir_alvlist,
304
+ lx_error TYPE REF TO cx_root,
305
+ ls_result TYPE ty_inspect_result.
103
306
 
104
- rs_result-success = abap_true.
307
+ rt_results = VALUE #( ).
105
308
 
106
309
  TRY.
107
310
  " Create unique name for inspection
@@ -145,14 +348,29 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
145
348
  " Get results
146
349
  lo_inspection->plain_list( IMPORTING p_list = lt_list ).
147
350
 
148
- " Parse results - aggregate all errors
149
- LOOP AT lt_list INTO DATA(ls_list).
150
- CLEAR ls_error.
151
- ls_error-line = ls_list-line.
152
- ls_error-column = ls_list-col.
153
- ls_error-text = ls_list-text.
154
- ls_error-word = ls_list-code.
155
- APPEND ls_error TO rs_result-errors.
351
+ " Build result for each object
352
+ LOOP AT it_objects INTO DATA(ls_obj).
353
+ CLEAR ls_result.
354
+ ls_result-object_type = ls_obj-objtype.
355
+ ls_result-object_name = ls_obj-objname.
356
+ ls_result-success = abap_true.
357
+
358
+ " Get errors for this object
359
+ LOOP AT lt_list INTO ls_list WHERE objname = ls_obj-objname.
360
+ CLEAR ls_error.
361
+ ls_error-line = ls_list-line.
362
+ ls_error-column = ls_list-col.
363
+ ls_error-text = ls_list-text.
364
+ ls_error-word = ls_list-code.
365
+ APPEND ls_error TO ls_result-errors.
366
+ ENDLOOP.
367
+
368
+ ls_result-error_count = lines( ls_result-errors ).
369
+ IF ls_result-error_count > 0.
370
+ ls_result-success = abap_false.
371
+ ENDIF.
372
+
373
+ APPEND ls_result TO rt_results.
156
374
  ENDLOOP.
157
375
 
158
376
  " Cleanup
@@ -173,19 +391,20 @@ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
173
391
  exists_in_objs = 5
174
392
  OTHERS = 6 ).
175
393
 
176
- rs_result-error_count = lines( rs_result-errors ).
177
- IF rs_result-error_count > 0.
178
- rs_result-success = abap_false.
179
- ENDIF.
180
-
181
394
  CATCH cx_root INTO lx_error.
182
- rs_result-success = abap_false.
183
- rs_result-error_count = 1.
184
- ls_error-line = '1'.
185
- ls_error-column = '1'.
186
- ls_error-text = lx_error->get_text( ).
187
- ls_error-word = ''.
188
- APPEND ls_error TO rs_result-errors.
395
+ " Return error for all objects
396
+ LOOP AT it_objects INTO ls_obj.
397
+ CLEAR ls_result.
398
+ ls_result-object_type = ls_obj-objtype.
399
+ ls_result-object_name = ls_obj-objname.
400
+ ls_result-success = abap_false.
401
+ ls_error-line = '1'.
402
+ ls_error-column = '1'.
403
+ ls_error-text = lx_error->get_text( ).
404
+ APPEND ls_error TO ls_result-errors.
405
+ ls_result-error_count = 1.
406
+ APPEND ls_result TO rt_results.
407
+ ENDLOOP.
189
408
  ENDTRY.
190
409
  ENDMETHOD.
191
410
 
@@ -0,0 +1,237 @@
1
+ *"*"use source
2
+ *"*"Local Interface:
3
+ *"**********************************************************************
4
+ " TREE command implementation - displays package hierarchy tree
5
+ CLASS zcl_abgagt_command_tree DEFINITION PUBLIC FINAL CREATE PUBLIC.
6
+ PUBLIC SECTION.
7
+ INTERFACES zif_abgagt_command.
8
+
9
+ TYPES: BEGIN OF ty_tree_params,
10
+ package TYPE tdevc-devclass,
11
+ depth TYPE i,
12
+ include_objects TYPE abap_bool,
13
+ END OF ty_tree_params.
14
+
15
+ TYPES: BEGIN OF ty_object_count,
16
+ object TYPE tadir-object,
17
+ count TYPE i,
18
+ END OF ty_object_count.
19
+
20
+ TYPES ty_object_counts TYPE TABLE OF ty_object_count WITH NON-UNIQUE DEFAULT KEY.
21
+
22
+ TYPES: BEGIN OF ty_package_node,
23
+ package TYPE tdevc-devclass,
24
+ parent TYPE tdevc-devclass,
25
+ description TYPE string,
26
+ depth TYPE i,
27
+ object_count TYPE i,
28
+ END OF ty_package_node.
29
+
30
+ TYPES ty_package_nodes TYPE TABLE OF ty_package_node WITH NON-UNIQUE DEFAULT KEY.
31
+
32
+ TYPES: BEGIN OF ty_tree_result,
33
+ success TYPE abap_bool,
34
+ command TYPE string,
35
+ package TYPE tdevc-devclass,
36
+ message TYPE string,
37
+ parent_package TYPE tdevc-devclass,
38
+ nodes TYPE ty_package_nodes,
39
+ total_packages TYPE i,
40
+ total_objects TYPE i,
41
+ objects TYPE ty_object_counts,
42
+ error TYPE string,
43
+ END OF ty_tree_result.
44
+
45
+ METHODS build_tree
46
+ IMPORTING is_params TYPE ty_tree_params
47
+ RETURNING VALUE(rs_result) TYPE ty_tree_result.
48
+
49
+ METHODS get_object_count
50
+ IMPORTING iv_package TYPE tdevc-devclass
51
+ RETURNING VALUE(rv_count) TYPE i.
52
+
53
+ METHODS get_object_counts_by_type
54
+ IMPORTING iv_package TYPE tdevc-devclass
55
+ CHANGING ct_counts TYPE ty_object_counts.
56
+
57
+ METHODS collect_subpackages
58
+ IMPORTING iv_parent TYPE tdevc-devclass
59
+ iv_current_depth TYPE i
60
+ iv_max_depth TYPE i
61
+ iv_include_objects TYPE abap_bool
62
+ CHANGING ct_nodes TYPE ty_package_nodes
63
+ cv_total_objects TYPE i
64
+ ct_types TYPE ty_object_counts.
65
+
66
+ ENDCLASS.
67
+
68
+ CLASS zcl_abgagt_command_tree IMPLEMENTATION.
69
+
70
+ METHOD zif_abgagt_command~get_name.
71
+ rv_name = zif_abgagt_command=>gc_tree.
72
+ ENDMETHOD.
73
+
74
+ METHOD zif_abgagt_command~execute.
75
+ DATA: ls_params TYPE ty_tree_params,
76
+ ls_result TYPE ty_tree_result.
77
+
78
+ ls_result-command = zif_abgagt_command=>gc_tree.
79
+
80
+ IF is_param IS SUPPLIED.
81
+ ls_params = CORRESPONDING #( is_param ).
82
+ ENDIF.
83
+
84
+ IF ls_params-package IS INITIAL.
85
+ ls_result-success = abap_false.
86
+ ls_result-error = 'Package is required'.
87
+ rv_result = /ui2/cl_json=>serialize( data = ls_result ).
88
+ RETURN.
89
+ ENDIF.
90
+
91
+ IF ls_params-depth IS INITIAL OR ls_params-depth <= 0.
92
+ ls_params-depth = 3.
93
+ ENDIF.
94
+
95
+ IF ls_params-depth > 10.
96
+ ls_params-depth = 10.
97
+ ENDIF.
98
+
99
+ ls_result = build_tree( ls_params ).
100
+ rv_result = /ui2/cl_json=>serialize( data = ls_result ).
101
+ ENDMETHOD.
102
+
103
+ METHOD build_tree.
104
+ DATA: lv_package TYPE tdevc-devclass,
105
+ lv_max_depth TYPE i,
106
+ lv_total_objects TYPE i,
107
+ lt_all_types TYPE ty_object_counts,
108
+ lt_nodes TYPE ty_package_nodes,
109
+ ls_package TYPE tdevc.
110
+
111
+ lv_package = is_params-package.
112
+ lv_max_depth = is_params-depth.
113
+
114
+ SELECT SINGLE devclass parentcl FROM tdevc
115
+ INTO ls_package
116
+ WHERE devclass = lv_package.
117
+
118
+ IF sy-subrc <> 0.
119
+ rs_result-success = abap_false.
120
+ rs_result-package = lv_package.
121
+ rs_result-error = |Package { lv_package } does not exist|.
122
+ RETURN.
123
+ ENDIF.
124
+
125
+ rs_result-success = abap_true.
126
+ rs_result-command = 'TREE'.
127
+ rs_result-package = lv_package.
128
+ rs_result-message = 'Tree retrieved successfully'.
129
+ rs_result-parent_package = ls_package-parentcl.
130
+
131
+ " Add root package
132
+ DATA(ls_root) = VALUE ty_package_node(
133
+ package = lv_package
134
+ parent = ls_package-parentcl
135
+ description = lv_package
136
+ depth = 0
137
+ object_count = get_object_count( lv_package ) ).
138
+ APPEND ls_root TO lt_nodes.
139
+
140
+ lv_total_objects = ls_root-object_count.
141
+
142
+ " Get object types for root
143
+ IF is_params-include_objects = abap_true.
144
+ get_object_counts_by_type(
145
+ EXPORTING iv_package = lv_package
146
+ CHANGING ct_counts = rs_result-objects ).
147
+ LOOP AT rs_result-objects INTO DATA(ls_obj).
148
+ APPEND ls_obj TO lt_all_types.
149
+ ENDLOOP.
150
+ ENDIF.
151
+
152
+ " Add all subpackages
153
+ collect_subpackages(
154
+ EXPORTING iv_parent = lv_package
155
+ iv_current_depth = 1
156
+ iv_max_depth = lv_max_depth
157
+ iv_include_objects = is_params-include_objects
158
+ CHANGING ct_nodes = lt_nodes
159
+ cv_total_objects = lv_total_objects
160
+ ct_types = lt_all_types ).
161
+
162
+ rs_result-nodes = lt_nodes.
163
+ rs_result-total_packages = lines( lt_nodes ).
164
+ rs_result-total_objects = lv_total_objects.
165
+ rs_result-objects = lt_all_types.
166
+ ENDMETHOD.
167
+
168
+ METHOD get_object_count.
169
+ DATA lv_count TYPE i.
170
+ SELECT COUNT(*) FROM tadir
171
+ INTO lv_count
172
+ WHERE devclass = iv_package
173
+ AND object NOT IN ('DEVC', 'PACK').
174
+ rv_count = lv_count.
175
+ ENDMETHOD.
176
+
177
+ METHOD get_object_counts_by_type.
178
+ DATA lt_counts TYPE ty_object_counts.
179
+ SELECT object COUNT(*) AS count FROM tadir
180
+ INTO TABLE lt_counts
181
+ WHERE devclass = iv_package
182
+ AND object NOT IN ('DEVC', 'PACK')
183
+ GROUP BY object.
184
+ ct_counts = lt_counts.
185
+ ENDMETHOD.
186
+
187
+ METHOD collect_subpackages.
188
+ DATA: lt_direct_subs TYPE TABLE OF tdevc,
189
+ ls_direct TYPE tdevc.
190
+
191
+ SELECT devclass parentcl FROM tdevc
192
+ INTO TABLE lt_direct_subs
193
+ WHERE parentcl = iv_parent
194
+ ORDER BY devclass.
195
+
196
+ LOOP AT lt_direct_subs INTO ls_direct.
197
+ DATA ls_node TYPE ty_package_node.
198
+ ls_node-package = ls_direct-devclass.
199
+ ls_node-parent = iv_parent.
200
+ ls_node-description = ls_direct-devclass.
201
+ ls_node-depth = iv_current_depth.
202
+ ls_node-object_count = get_object_count( ls_direct-devclass ).
203
+
204
+ APPEND ls_node TO ct_nodes.
205
+ cv_total_objects = cv_total_objects + ls_node-object_count.
206
+
207
+ " Add object types
208
+ IF iv_include_objects = abap_true.
209
+ DATA lt_types TYPE ty_object_counts.
210
+ get_object_counts_by_type(
211
+ EXPORTING iv_package = ls_direct-devclass
212
+ CHANGING ct_counts = lt_types ).
213
+ LOOP AT lt_types INTO DATA(ls_type).
214
+ READ TABLE ct_types WITH KEY object = ls_type-object
215
+ ASSIGNING FIELD-SYMBOL(<ls_existing>).
216
+ IF sy-subrc = 0.
217
+ <ls_existing>-count = <ls_existing>-count + ls_type-count.
218
+ ELSE.
219
+ APPEND ls_type TO ct_types.
220
+ ENDIF.
221
+ ENDLOOP.
222
+ ENDIF.
223
+
224
+ IF iv_current_depth < iv_max_depth.
225
+ collect_subpackages(
226
+ EXPORTING iv_parent = ls_direct-devclass
227
+ iv_current_depth = iv_current_depth + 1
228
+ iv_max_depth = iv_max_depth
229
+ iv_include_objects = iv_include_objects
230
+ CHANGING ct_nodes = ct_nodes
231
+ cv_total_objects = cv_total_objects
232
+ ct_types = ct_types ).
233
+ ENDIF.
234
+ ENDLOOP.
235
+ ENDMETHOD.
236
+
237
+ 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_TREE</CLSNAME>
7
+ <LANGU>E</LANGU>
8
+ <DESCRIPT>Tree Command for ABAP Git Agent</DESCRIPT>
9
+ <EXPOSURE>2</EXPOSURE>
10
+ <STATE>1</STATE>
11
+ <UNICODE>X</UNICODE>
12
+ </VSEOCLASS>
13
+ </asx:values>
14
+ </asx:abap>
15
+ </abapGit>