*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_OBJECT_SHI3
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_object_shi3 DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_object_shi3 DEFINITION INHERITING FROM lcl_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES lif_object.
    ALIASES mo_files FOR lif_object~mo_files.

    METHODS constructor
      IMPORTING
        is_item     TYPE ty_item
        iv_language TYPE spras.

  PRIVATE SECTION.

    TYPES: BEGIN OF ty_id_map,
             old TYPE ttree-id,
             new TYPE ttree-id,
           END OF ty_id_map.
    TYPES  tt_id_map TYPE STANDARD TABLE OF ty_id_map.
    TYPES  ts_id_map TYPE SORTED TABLE OF ty_id_map WITH UNIQUE KEY old.

    DATA: mv_tree_id TYPE ttree-id,
          mt_map     TYPE ts_id_map. " SORTED !

    METHODS jump_se43
      RAISING lcx_exception.

    METHODS strip_stamps
      CHANGING cs_head  TYPE ttree
               ct_nodes TYPE hier_iface_t.

    METHODS regenerate_ids
      CHANGING ct_nodes TYPE hier_iface_t
               ct_refs  TYPE hier_ref_t
               ct_texts TYPE hier_texts_t
      RAISING  lcx_exception.

    METHODS replace_id
      IMPORTING iv_id            TYPE clike
      RETURNING VALUE(rv_new_id) TYPE ttree-id
      RAISING   lcx_exception.

ENDCLASS.                    "lcl_object_shi3 DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_object_shi3 IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_object_shi3 IMPLEMENTATION.

  METHOD lif_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.  "lif_object~has_changed_since

  METHOD lif_object~changed_by.
    rv_user = c_user_unknown. " todo
  ENDMETHOD.

  METHOD constructor.
    super->constructor( is_item = is_item iv_language = iv_language ).
    mv_tree_id = ms_item-obj_name.
  ENDMETHOD.                    "constructor

  METHOD lif_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.                    "lif_object~get_metadata

  METHOD jump_se43.

    DATA: lt_bdcdata TYPE TABLE OF bdcdata.

    FIELD-SYMBOLS: <ls_bdcdata> LIKE LINE OF lt_bdcdata.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-program  = 'SAPLBMEN'.
    <ls_bdcdata>-dynpro   = '0200'.
    <ls_bdcdata>-dynbegin = abap_true.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'BDC_OKCODE'.
    <ls_bdcdata>-fval = '=SHOW'.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'BMENUNAME-ID'.
    <ls_bdcdata>-fval = ms_item-obj_name.

    CALL FUNCTION 'ABAP4_CALL_TRANSACTION'
      STARTING NEW TASK 'GIT'
      EXPORTING
        tcode                 = 'SE43'
        mode_val              = 'E'
      TABLES
        using_tab             = lt_bdcdata
      EXCEPTIONS
        system_failure        = 1
        communication_failure = 2
        resource_failure      = 3
        OTHERS                = 4.

    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from ABAP4_CALL_TRANSACTION, SHI3' ).
    ENDIF.

  ENDMETHOD.                    "jump_se43

  METHOD lif_object~jump.
    jump_se43( ).
  ENDMETHOD.                    "jump

  METHOD lif_object~exists.

    DATA: ls_msg    TYPE hier_mess,
          ls_header TYPE ttree,
          ls_tadir  TYPE tadir.

    CALL FUNCTION 'STREE_STRUCTURE_EXIST'
      EXPORTING
        structure_id         = mv_tree_id
        do_not_read_devclass = ''
      IMPORTING
        message              = ls_msg
        structure_header     = ls_header
        structure_tadir      = ls_tadir.

    rv_bool = boolc( ls_header-id IS NOT INITIAL ).

  ENDMETHOD.                    "lif_object~exists

  METHOD lif_object~delete.

    CALL FUNCTION 'BMENU_DELETE_TREE'
      EXPORTING
        tree_id            = mv_tree_id
      EXCEPTIONS
        trees_do_not_exist = 1
        no_authority       = 2
        canceled           = 3
        OTHERS             = 4.

    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from BMENU_DELETE_TREE, SHI3' ).
    ENDIF.

  ENDMETHOD.                    "delete

  METHOD lif_object~serialize.

    DATA: ls_msg    TYPE hier_mess,
          ls_head   TYPE ttree,
          lt_titles TYPE TABLE OF ttreet,
          lt_nodes  TYPE TABLE OF hier_iface,
          lt_texts  TYPE TABLE OF hier_texts,
          lt_refs   TYPE TABLE OF hier_ref.

    CALL FUNCTION 'STREE_STRUCTURE_READ'
      EXPORTING
        structure_id     = mv_tree_id
      IMPORTING
        message          = ls_msg
        structure_header = ls_head
      TABLES
        description      = lt_titles.

    CALL FUNCTION 'STREE_HIERARCHY_READ'
      EXPORTING
        structure_id       = mv_tree_id
        read_also_texts    = 'X'
        all_languages      = 'X'
      IMPORTING
        message            = ls_msg
      TABLES
        list_of_nodes      = lt_nodes
        list_of_references = lt_refs
        list_of_texts      = lt_texts.

    strip_stamps( CHANGING cs_head  = ls_head
                           ct_nodes = lt_nodes ).

    io_xml->add( iv_name = 'TREE_HEAD'
                 ig_data = ls_head ).
    io_xml->add( iv_name = 'TREE_TITLES'
                 ig_data = lt_titles ).
    io_xml->add( iv_name = 'TREE_NODES'
                 ig_data = lt_nodes ).
    io_xml->add( iv_name = 'TREE_REFS'
                 ig_data = lt_refs ).
    io_xml->add( iv_name = 'TREE_TEXTS'
                 ig_data = lt_texts ).

  ENDMETHOD.                    "serialize

  METHOD strip_stamps.

    FIELD-SYMBOLS <ls_node> LIKE LINE OF ct_nodes.

    CLEAR: cs_head-luser, cs_head-ldate, cs_head-ltime.
    CLEAR: cs_head-fuser, cs_head-fdate, cs_head-ftime.
    CLEAR: cs_head-responsibl.

    LOOP AT ct_nodes ASSIGNING <ls_node>.
      CLEAR: <ls_node>-luser, <ls_node>-ldate, <ls_node>-ltime.
      CLEAR: <ls_node>-fuser, <ls_node>-fdate, <ls_node>-ftime.
    ENDLOOP.

  ENDMETHOD.                    "strip_stamps

  METHOD regenerate_ids.

    DATA: ls_uid TYPE sys_uid,
          lt_map TYPE tt_id_map.

    FIELD-SYMBOLS: <ls_node> LIKE LINE OF ct_nodes,
                   <ls_ref>  LIKE LINE OF ct_refs,
                   <ls_text> LIKE LINE OF ct_texts,
                   <ls_map>  LIKE LINE OF mt_map.

    "Build map
    LOOP AT ct_nodes ASSIGNING <ls_node>.
      APPEND INITIAL LINE TO lt_map ASSIGNING <ls_map>.
      IF <ls_node>-parent_id IS INITIAL.
        <ls_map>-old = <ls_node>-node_id.
        <ls_map>-new = <ls_node>-node_id. "Root node
      ELSE.
        CALL FUNCTION 'STREE_GET_UNIQUE_ID'
          IMPORTING
            unique_id = ls_uid.

        <ls_map>-old = <ls_node>-node_id.
        <ls_map>-new = ls_uid-id.
      ENDIF.
      <ls_node>-node_id = <ls_map>-new. "Replace id
    ENDLOOP.

    mt_map = lt_map. "Sort

    LOOP AT ct_nodes ASSIGNING <ls_node>.
      <ls_node>-parent_id  = replace_id( <ls_node>-parent_id ).
      <ls_node>-brother_id = replace_id( <ls_node>-brother_id ).
    ENDLOOP.

    LOOP AT ct_refs ASSIGNING <ls_ref>.
      <ls_ref>-node_id = replace_id( <ls_ref>-node_id ).
    ENDLOOP.

    LOOP AT ct_texts ASSIGNING <ls_text>.
      <ls_text>-node_id = replace_id( <ls_text>-node_id ).
    ENDLOOP.

  ENDMETHOD.                    "regenerate_ids

  METHOD replace_id.

    DATA ls_map LIKE LINE OF mt_map.

    IF iv_id IS INITIAL.
      RETURN. "No substitution for empty values
    ENDIF.

    READ TABLE mt_map WITH TABLE KEY old = iv_id INTO ls_map.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'Cannot replace id, SHI3' ).
    ENDIF.

    rv_new_id = ls_map-new.

  ENDMETHOD.                    "replace_id

  METHOD lif_object~deserialize.

    DATA: ls_msg    TYPE hier_mess,
          ls_head   TYPE ttree,
          lt_titles TYPE TABLE OF ttreet,
          lt_nodes  TYPE TABLE OF hier_iface,
          lt_texts  TYPE TABLE OF hier_texts,
          lt_refs   TYPE TABLE OF hier_ref.

    io_xml->read( EXPORTING iv_name = 'TREE_HEAD'
                  CHANGING  cg_data = ls_head ).
    io_xml->read( EXPORTING iv_name = 'TREE_TITLES'
                  CHANGING  cg_data = lt_titles ).
    io_xml->read( EXPORTING iv_name = 'TREE_NODES'
                  CHANGING  cg_data = lt_nodes ).
    io_xml->read( EXPORTING iv_name = 'TREE_REFS'
                  CHANGING  cg_data = lt_refs ).
    io_xml->read( EXPORTING iv_name = 'TREE_TEXTS'
                  CHANGING  cg_data = lt_texts ).

    regenerate_ids( CHANGING ct_nodes = lt_nodes
                             ct_refs  = lt_refs
                             ct_texts = lt_texts ).

    IF lif_object~exists( ) = abap_true.
      lif_object~delete( ).
    ENDIF.

    CALL FUNCTION 'STREE_HIERARCHY_SAVE'
      EXPORTING
        structure_id             = mv_tree_id
        structure_type           = 'BMENU'
        structure_description    = space
        structure_masterlanguage = mv_language
        structure_responsible    = sy-uname
        development_class        = iv_package
      IMPORTING
        message                  = ls_msg
      TABLES
        list_of_nodes            = lt_nodes
        list_of_references       = lt_refs
        list_of_texts            = lt_texts
        structure_descriptions   = lt_titles
      EXCEPTIONS
        no_nodes_given           = 1
        OTHERS                   = 2.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'Error from STREE_HIERARCHY_SAVE, SHI3' ).
    ENDIF.

  ENDMETHOD.                    "deserialize

  METHOD lif_object~compare_to_remote_version.
    CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result.
  ENDMETHOD.

ENDCLASS.                    "lcl_object_shi3 IMPLEMENTATION

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_OBJECT_SHI3
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_object_shi3 DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_object_shi3 DEFINITION INHERITING FROM lcl_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES lif_object.
    ALIASES mo_files FOR lif_object~mo_files.

    METHODS constructor
      IMPORTING
        is_item     TYPE ty_item
        iv_language TYPE spras.

  PRIVATE SECTION.

    TYPES: BEGIN OF ty_id_map,
             old TYPE ttree-id,
             new TYPE ttree-id,
           END OF ty_id_map.
    TYPES  tt_id_map TYPE STANDARD TABLE OF ty_id_map.
    TYPES  ts_id_map TYPE SORTED TABLE OF ty_id_map WITH UNIQUE KEY old.

    DATA: mv_tree_id TYPE ttree-id,
          mt_map     TYPE ts_id_map. " SORTED !

    METHODS jump_se43
      RAISING lcx_exception.

    METHODS clear_fields
      CHANGING cs_head  TYPE ttree
               ct_nodes TYPE hier_iface_t.

*    METHODS regenerate_ids
*      CHANGING ct_nodes TYPE hier_iface_t
*               ct_refs  TYPE hier_ref_t
*               ct_texts TYPE hier_texts_t
*      RAISING  lcx_exception.
*
*    METHODS replace_id
*      IMPORTING iv_id            TYPE clike
*      RETURNING VALUE(rv_new_id) TYPE ttree-id
*      RAISING   lcx_exception.

ENDCLASS.                    "lcl_object_shi3 DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_object_shi3 IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_object_shi3 IMPLEMENTATION.

  METHOD lif_object~has_changed_since.
    rv_changed = abap_true.
  ENDMETHOD.  "lif_object~has_changed_since

  METHOD lif_object~changed_by.

    DATA: ls_head TYPE ttree.

    CALL FUNCTION 'STREE_STRUCTURE_READ'
      EXPORTING
        structure_id     = mv_tree_id
      IMPORTING
        structure_header = ls_head.

    rv_user = ls_head-luser.

  ENDMETHOD.

  METHOD constructor.
    super->constructor( is_item = is_item iv_language = iv_language ).
    mv_tree_id = ms_item-obj_name.
  ENDMETHOD.                    "constructor

  METHOD lif_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.                    "lif_object~get_metadata

  METHOD jump_se43.

    DATA: lt_bdcdata TYPE TABLE OF bdcdata.

    FIELD-SYMBOLS: <ls_bdcdata> LIKE LINE OF lt_bdcdata.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-program  = 'SAPLBMEN'.
    <ls_bdcdata>-dynpro   = '0200'.
    <ls_bdcdata>-dynbegin = abap_true.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'BDC_OKCODE'.
    <ls_bdcdata>-fval = '=SHOW'.

    APPEND INITIAL LINE TO lt_bdcdata ASSIGNING <ls_bdcdata>.
    <ls_bdcdata>-fnam = 'BMENUNAME-ID'.
    <ls_bdcdata>-fval = ms_item-obj_name.

    CALL FUNCTION 'ABAP4_CALL_TRANSACTION'
      STARTING NEW TASK 'GIT'
      EXPORTING
        tcode                 = 'SE43'
        mode_val              = 'E'
      TABLES
        using_tab             = lt_bdcdata
      EXCEPTIONS
        system_failure        = 1
        communication_failure = 2
        resource_failure      = 3
        OTHERS                = 4.

    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from ABAP4_CALL_TRANSACTION, SHI3' ).
    ENDIF.

  ENDMETHOD.                    "jump_se43

  METHOD lif_object~jump.
    jump_se43( ).
  ENDMETHOD.                    "jump

  METHOD lif_object~exists.

    DATA: ls_msg    TYPE hier_mess,
          ls_header TYPE ttree,
          ls_tadir  TYPE tadir.

    CALL FUNCTION 'STREE_STRUCTURE_EXIST'
      EXPORTING
        structure_id         = mv_tree_id
        do_not_read_devclass = ''
      IMPORTING
        message              = ls_msg
        structure_header     = ls_header
        structure_tadir      = ls_tadir.

    rv_bool = boolc( ls_header-id IS NOT INITIAL ).

  ENDMETHOD.                    "lif_object~exists

  METHOD lif_object~delete.

    CALL FUNCTION 'BMENU_DELETE_TREE'
      EXPORTING
        tree_id            = mv_tree_id
      EXCEPTIONS
        trees_do_not_exist = 1
        no_authority       = 2
        canceled           = 3
        OTHERS             = 4.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from BMENU_DELETE_TREE, SHI3' ).
    ENDIF.

  ENDMETHOD.                    "delete

  METHOD lif_object~serialize.

    DATA: ls_msg    TYPE hier_mess,
          ls_head   TYPE ttree,
          lt_titles TYPE TABLE OF ttreet,
          lt_nodes  TYPE TABLE OF hier_iface,
          lt_texts  TYPE TABLE OF hier_texts,
          lt_refs   TYPE TABLE OF hier_ref.

    CALL FUNCTION 'STREE_STRUCTURE_READ'
      EXPORTING
        structure_id     = mv_tree_id
      IMPORTING
        message          = ls_msg
        structure_header = ls_head
      TABLES
        description      = lt_titles.

    CALL FUNCTION 'STREE_HIERARCHY_READ'
      EXPORTING
        structure_id       = mv_tree_id
        read_also_texts    = 'X'
        all_languages      = 'X'
      IMPORTING
        message            = ls_msg
      TABLES
        list_of_nodes      = lt_nodes
        list_of_references = lt_refs
        list_of_texts      = lt_texts.

    clear_fields( CHANGING cs_head  = ls_head
                           ct_nodes = lt_nodes ).

    io_xml->add( iv_name = 'TREE_HEAD'
                 ig_data = ls_head ).
    io_xml->add( iv_name = 'TREE_TITLES'
                 ig_data = lt_titles ).
    io_xml->add( iv_name = 'TREE_NODES'
                 ig_data = lt_nodes ).
    io_xml->add( iv_name = 'TREE_REFS'
                 ig_data = lt_refs ).
    io_xml->add( iv_name = 'TREE_TEXTS'
                 ig_data = lt_texts ).

  ENDMETHOD.                    "serialize

  METHOD clear_fields.

    FIELD-SYMBOLS <ls_node> LIKE LINE OF ct_nodes.

    CLEAR: cs_head-luser, cs_head-ldate, cs_head-ltime.
    CLEAR: cs_head-fuser, cs_head-fdate, cs_head-ftime.
    CLEAR: cs_head-frelease, cs_head-lrelease.
    CLEAR: cs_head-responsibl.

    LOOP AT ct_nodes ASSIGNING <ls_node>.
      CLEAR: <ls_node>-luser, <ls_node>-ldate, <ls_node>-ltime.
      CLEAR: <ls_node>-fuser, <ls_node>-fdate, <ls_node>-ftime.
      CLEAR: <ls_node>-frelease, <ls_node>-lrelease.
    ENDLOOP.

  ENDMETHOD.                    "strip_stamps

*  METHOD regenerate_ids.
*
*    DATA: ls_uid TYPE sys_uid,
*          lt_map TYPE tt_id_map.
*
*    FIELD-SYMBOLS: <ls_node> LIKE LINE OF ct_nodes,
*                   <ls_ref>  LIKE LINE OF ct_refs,
*                   <ls_text> LIKE LINE OF ct_texts,
*                   <ls_map>  LIKE LINE OF mt_map.
*
*    "Build map
*    LOOP AT ct_nodes ASSIGNING <ls_node>.
*      APPEND INITIAL LINE TO lt_map ASSIGNING <ls_map>.
*      IF <ls_node>-parent_id IS INITIAL.
*        <ls_map>-old = <ls_node>-node_id.
*        <ls_map>-new = <ls_node>-node_id. "Root node
*      ELSE.
*        CALL FUNCTION 'STREE_GET_UNIQUE_ID'
*          IMPORTING
*            unique_id = ls_uid.
*
*        <ls_map>-old = <ls_node>-node_id.
*        <ls_map>-new = ls_uid-id.
*      ENDIF.
*      <ls_node>-node_id = <ls_map>-new. "Replace id
*    ENDLOOP.
*
*    mt_map = lt_map. "Sort
*
*    LOOP AT ct_nodes ASSIGNING <ls_node>.
*      <ls_node>-parent_id  = replace_id( <ls_node>-parent_id ).
*      <ls_node>-brother_id = replace_id( <ls_node>-brother_id ).
*    ENDLOOP.
*
*    LOOP AT ct_refs ASSIGNING <ls_ref>.
*      <ls_ref>-node_id = replace_id( <ls_ref>-node_id ).
*    ENDLOOP.
*
*    LOOP AT ct_texts ASSIGNING <ls_text>.
*      <ls_text>-node_id = replace_id( <ls_text>-node_id ).
*    ENDLOOP.
*
*  ENDMETHOD.                    "regenerate_ids
*
*  METHOD replace_id.
*
*    DATA ls_map LIKE LINE OF mt_map.
*
*    IF iv_id IS INITIAL.
*      RETURN. "No substitution for empty values
*    ENDIF.
*
*    READ TABLE mt_map WITH TABLE KEY old = iv_id INTO ls_map.
*    IF sy-subrc <> 0.
*      lcx_exception=>raise( 'Cannot replace id, SHI3' ).
*    ENDIF.
*
*    rv_new_id = ls_map-new.
*
*  ENDMETHOD.                    "replace_id

  METHOD lif_object~deserialize.

    DATA: ls_msg    TYPE hier_mess,
          ls_head   TYPE ttree,
          lt_titles TYPE TABLE OF ttreet,
          lt_nodes  TYPE TABLE OF hier_iface,
          lt_texts  TYPE TABLE OF hier_texts,
          lt_refs   TYPE TABLE OF hier_ref.

    io_xml->read( EXPORTING iv_name = 'TREE_HEAD'
                  CHANGING  cg_data = ls_head ).
    io_xml->read( EXPORTING iv_name = 'TREE_TITLES'
                  CHANGING  cg_data = lt_titles ).
    io_xml->read( EXPORTING iv_name = 'TREE_NODES'
                  CHANGING  cg_data = lt_nodes ).
    io_xml->read( EXPORTING iv_name = 'TREE_REFS'
                  CHANGING  cg_data = lt_refs ).
    io_xml->read( EXPORTING iv_name = 'TREE_TEXTS'
                  CHANGING  cg_data = lt_texts ).

*    regenerate_ids( CHANGING ct_nodes = lt_nodes
*                             ct_refs  = lt_refs
*                             ct_texts = lt_texts ).

    IF lif_object~exists( ) = abap_true.
      lif_object~delete( ).
    ENDIF.

    CALL FUNCTION 'STREE_HIERARCHY_SAVE'
      EXPORTING
        structure_id             = mv_tree_id
        structure_type           = 'BMENU'
        structure_description    = space
        structure_masterlanguage = mv_language
        structure_responsible    = sy-uname
        development_class        = iv_package
      IMPORTING
        message                  = ls_msg
      TABLES
        list_of_nodes            = lt_nodes
        list_of_references       = lt_refs
        list_of_texts            = lt_texts
        structure_descriptions   = lt_titles
      EXCEPTIONS
        no_nodes_given           = 1
        OTHERS                   = 2.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'Error from STREE_HIERARCHY_SAVE, SHI3' ).
    ENDIF.

  ENDMETHOD.                    "deserialize

  METHOD lif_object~compare_to_remote_version.
    CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result.
  ENDMETHOD.

ENDCLASS.                    "lcl_object_shi3 IMPLEMENTATION

fix SHI3 diffs #483

fix SHI3 diffs #483


*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_SAP_PACKAGE
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_package DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_sap_package DEFINITION FINAL.

  PUBLIC SECTION.
    TYPES: ty_devclass_tt TYPE STANDARD TABLE OF devclass WITH DEFAULT KEY.

    CLASS-METHODS:
      check
        IMPORTING io_log     TYPE REF TO lcl_log
                  it_results TYPE ty_results_tt
                  iv_start   TYPE string
                  iv_top     TYPE devclass,
      list_subpackages IMPORTING iv_package     TYPE devclass
                       RETURNING VALUE(rt_list) TYPE ty_devclass_tt,
      list_superpackages IMPORTING iv_package     TYPE devclass
                         RETURNING VALUE(rt_list) TYPE ty_devclass_tt,
      create_local
        IMPORTING iv_package TYPE devclass
        RAISING   lcx_exception,
      create
        IMPORTING is_package        TYPE scompkdtln
        RETURNING VALUE(ri_package) TYPE REF TO if_package
        RAISING   lcx_exception,
      create_child
        IMPORTING iv_parent TYPE devclass
                  iv_child  TYPE devclass
        RAISING   lcx_exception,
      exists
        IMPORTING iv_package     TYPE devclass
        RETURNING VALUE(rv_bool) TYPE abap_bool.

  PRIVATE SECTION.
    CLASS-METHODS:
      class_to_path
        IMPORTING
          iv_top         TYPE devclass
          iv_start       TYPE string
          iv_package     TYPE devclass
        RETURNING
          VALUE(rv_path) TYPE string.

ENDCLASS.                    "lcl_package DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_package IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_sap_package IMPLEMENTATION.

  METHOD class_to_path.

    DATA: lv_len      TYPE i,
          lv_path     TYPE string,
          lv_parentcl TYPE tdevc-parentcl.

    IF iv_top = iv_package.
      rv_path = iv_start.
    ELSE.
      SELECT SINGLE parentcl FROM tdevc INTO lv_parentcl
        WHERE devclass = iv_package.      "#EC CI_SUBRC "#EC CI_GENBUFF
      ASSERT sy-subrc = 0.

      IF lv_parentcl IS INITIAL.
        rv_path = 'error' ##no_text.
      ELSE.
        lv_len = strlen( lv_parentcl ).
        lv_path = iv_package+lv_len.
        IF strlen( lv_path ) = 0.
          RETURN. " prevent dump
        ENDIF.
        IF lv_path(1) = '_'.
          lv_path = lv_path+1.
        ENDIF.
        TRANSLATE lv_path TO LOWER CASE.
        CONCATENATE lv_path '/' INTO lv_path.

        rv_path = class_to_path( iv_top     = iv_top
                                 iv_start   = iv_start
                                 iv_package = lv_parentcl ).

        CONCATENATE rv_path lv_path INTO rv_path.

      ENDIF.

    ENDIF.

  ENDMETHOD.                    "class_to_path

  METHOD check.

    DATA: lv_path     TYPE string,
          ls_item     TYPE ty_item,
          ls_file     TYPE ty_file_signature,
          lt_res_sort LIKE it_results,
          lt_item_idx LIKE it_results.

    FIELD-SYMBOLS: <ls_res1> LIKE LINE OF it_results,
                   <ls_res2> LIKE LINE OF it_results.

    IF io_log IS INITIAL.
      RETURN.
    ENDIF.

    " Collect object indexe
    lt_res_sort = it_results.
    SORT lt_res_sort BY obj_type ASCENDING obj_name ASCENDING.

    LOOP AT it_results ASSIGNING <ls_res1> WHERE NOT obj_type IS INITIAL.
      IF NOT ( <ls_res1>-obj_type = ls_item-obj_type AND <ls_res1>-obj_name = ls_item-obj_name ).
        APPEND INITIAL LINE TO lt_item_idx ASSIGNING <ls_res2>.
        <ls_res2>-obj_type = <ls_res1>-obj_type.
        <ls_res2>-obj_name = <ls_res1>-obj_name.
        <ls_res2>-path     = <ls_res1>-path.
        MOVE-CORRESPONDING <ls_res1> TO ls_item.
      ENDIF.
    ENDLOOP.

    " Check files for one object is in the same folder

    LOOP AT it_results ASSIGNING <ls_res1> WHERE NOT obj_type IS INITIAL.
      READ TABLE lt_item_idx ASSIGNING <ls_res2>
        WITH KEY obj_type = <ls_res1>-obj_type obj_name = <ls_res1>-obj_name
        BINARY SEARCH. " Sorted above

      IF sy-subrc <> 0 OR <ls_res1>-path <> <ls_res2>-path. " All paths are same
        io_log->add( iv_msgv1 = 'Files for object'
                     iv_msgv2 = <ls_res1>-obj_type
                     iv_msgv3 = <ls_res1>-obj_name
                     iv_msgv4 = 'are not placed in the same folder'
                     iv_rc    = '1' ) ##no_text.
      ENDIF.
    ENDLOOP.

    " Check that objects are created in package corresponding to folder
    LOOP AT it_results ASSIGNING <ls_res1>
        WHERE NOT package IS INITIAL AND NOT path IS INITIAL.
      lv_path = class_to_path( iv_top     = iv_top
                               iv_start   = iv_start
                               iv_package = <ls_res1>-package ).
      IF lv_path <> <ls_res1>-path.
        io_log->add( iv_msgv1 = 'Package and path does not match for object,'
                     iv_msgv2 = <ls_res1>-obj_type
                     iv_msgv3 = <ls_res1>-obj_name
                     iv_rc    = '2' ) ##no_text.
      ENDIF.
    ENDLOOP.

    " Check for multiple files with same filename
    SORT lt_res_sort BY filename ASCENDING.

    LOOP AT lt_res_sort ASSIGNING <ls_res1>.
      IF <ls_res1>-filename IS NOT INITIAL AND <ls_res1>-filename = ls_file-filename.
        io_log->add( iv_msgv1 = 'Multiple files with same filename,'
                     iv_msgv2 = <ls_res1>-filename
                     iv_rc    = '3' ) ##no_text.
      ENDIF.

      IF <ls_res1>-filename IS INITIAL.
        io_log->add( iv_msgv1 = 'Filename is empty for object'
                     iv_msgv2 = <ls_res1>-obj_type
                     iv_msgv3 = <ls_res1>-obj_name
                     iv_rc    = '4' ) ##no_text.
      ENDIF.

      MOVE-CORRESPONDING <ls_res1> TO ls_file.
    ENDLOOP.

  ENDMETHOD.                    "check

  METHOD exists.

    cl_package_factory=>load_package(
      EXPORTING
        i_package_name             = iv_package
      EXCEPTIONS
        object_not_existing        = 1
        unexpected_error           = 2
        intern_err                 = 3
        no_access                  = 4
        object_locked_and_modified = 5 ).
    rv_bool = boolc( sy-subrc <> 1 ).

  ENDMETHOD.

  METHOD create_child.

    DATA: li_parent TYPE REF TO if_package,
          ls_child  TYPE scompkdtln.

    cl_package_factory=>load_package(
      EXPORTING
        i_package_name             = iv_parent
      IMPORTING
        e_package                  = li_parent
      EXCEPTIONS
        object_not_existing        = 1
        unexpected_error           = 2
        intern_err                 = 3
        no_access                  = 4
        object_locked_and_modified = 5 ).
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error reading parent package' ).
    ENDIF.

    ls_child-devclass  = iv_child.
    ls_child-ctext     = iv_child.
    ls_child-parentcl  = iv_parent.
    ls_child-component = li_parent->transport_layer.
    ls_child-as4user   = sy-uname.

    create( ls_child ).

  ENDMETHOD.

  METHOD create.

    DATA: lv_err     TYPE string,
          ls_package LIKE is_package.

    ASSERT NOT is_package-devclass IS INITIAL.

    cl_package_factory=>load_package(
      EXPORTING
        i_package_name             = is_package-devclass
      EXCEPTIONS
        object_not_existing        = 1
        unexpected_error           = 2
        intern_err                 = 3
        no_access                  = 4
        object_locked_and_modified = 5 ).
    IF sy-subrc = 0.
      RETURN. "Package already exists. We assume this is fine
    ENDIF.

    ls_package = is_package.

    cl_package_factory=>create_new_package(
      EXPORTING
        i_reuse_deleted_object     = abap_true
*        i_suppress_dialog          = abap_true " does not exist in 730
      IMPORTING
        e_package                  = ri_package
      CHANGING
        c_package_data             = ls_package
      EXCEPTIONS
        object_already_existing    = 1
        object_just_created        = 2
        not_authorized             = 3
        wrong_name_prefix          = 4
        undefined_name             = 5
        reserved_local_name        = 6
        invalid_package_name       = 7
        short_text_missing         = 8
        software_component_invalid = 9
        layer_invalid              = 10
        author_not_existing        = 11
        component_not_existing     = 12
        component_missing          = 13
        prefix_in_use              = 14
        unexpected_error           = 15
        intern_err                 = 16
        no_access                  = 17
*        invalid_translation_depth  = 18
*        wrong_mainpack_value       = 19
*        superpackage_invalid       = 20
*        error_in_cts_checks        = 21
        OTHERS                     = 18 ).
    IF sy-subrc <> 0.
      lcx_exception=>raise( |Package { is_package-devclass } could not be created| ).
    ENDIF.

    ri_package->save(
*      EXPORTING
*        i_suppress_dialog     = abap_true    " Controls whether popups can be transmitted
      EXCEPTIONS
        object_invalid        = 1
        object_not_changeable = 2
        cancelled_in_corr     = 3
        permission_failure    = 4
        unexpected_error      = 5
        intern_err            = 6
        OTHERS                = 7 ).
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_err.
      lcx_exception=>raise( lv_err ).
    ENDIF.

    ri_package->set_changeable( abap_false ).

  ENDMETHOD.

  METHOD list_superpackages.

    DATA: lt_list     LIKE rt_list,
          lv_parent   TYPE tdevc-parentcl,
          lv_devclass LIKE LINE OF rt_list.

    APPEND iv_package TO rt_list.

    SELECT SINGLE parentcl INTO lv_parent
      FROM tdevc WHERE devclass = iv_package.           "#EC CI_GENBUFF

    IF NOT lv_parent IS INITIAL.
      APPEND lv_parent TO rt_list.
      lt_list = list_superpackages( lv_devclass ).
      APPEND LINES OF lt_list TO rt_list.
    ENDIF.

  ENDMETHOD.

  METHOD list_subpackages.

    DATA: lt_list     LIKE rt_list,
          lv_devclass LIKE LINE OF rt_list.

    SELECT devclass INTO TABLE rt_list
      FROM tdevc WHERE parentcl = iv_package.           "#EC CI_GENBUFF

* note the recursion, since packages are added to the list
    LOOP AT rt_list INTO lv_devclass.
      lt_list = list_subpackages( lv_devclass ).
      APPEND LINES OF lt_list TO rt_list.
    ENDLOOP.

  ENDMETHOD.

  METHOD create_local.

    DATA: ls_package TYPE scompkdtln.

    ls_package-devclass  = iv_package.
    ls_package-ctext     = iv_package.
    ls_package-parentcl  = '$TMP'.
    ls_package-component = 'LOCAL'.
    ls_package-as4user   = sy-uname.

    create( ls_package ).

  ENDMETHOD.                    "create

ENDCLASS.                    "lcl_package IMPLEMENTATION

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_SAP_PACKAGE
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_package DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_sap_package DEFINITION FINAL.

  PUBLIC SECTION.
    TYPES: ty_devclass_tt TYPE STANDARD TABLE OF devclass WITH DEFAULT KEY.

    CLASS-METHODS:
      check
        IMPORTING io_log     TYPE REF TO lcl_log
                  it_results TYPE ty_results_tt
                  iv_start   TYPE string
                  iv_top     TYPE devclass,
      list_subpackages IMPORTING iv_package     TYPE devclass
                       RETURNING VALUE(rt_list) TYPE ty_devclass_tt,
      list_superpackages IMPORTING iv_package     TYPE devclass
                         RETURNING VALUE(rt_list) TYPE ty_devclass_tt,
      create_local
        IMPORTING iv_package TYPE devclass
        RAISING   lcx_exception,
      create
        IMPORTING is_package        TYPE scompkdtln
        RETURNING VALUE(ri_package) TYPE REF TO if_package
        RAISING   lcx_exception,
      create_child
        IMPORTING iv_parent TYPE devclass
                  iv_child  TYPE devclass
        RAISING   lcx_exception,
      exists
        IMPORTING iv_package     TYPE devclass
        RETURNING VALUE(rv_bool) TYPE abap_bool.

  PRIVATE SECTION.
    CLASS-METHODS:
      class_to_path
        IMPORTING
          iv_top         TYPE devclass
          iv_start       TYPE string
          iv_package     TYPE devclass
        RETURNING
          VALUE(rv_path) TYPE string.

ENDCLASS.                    "lcl_package DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_package IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_sap_package IMPLEMENTATION.

  METHOD class_to_path.

    DATA: lv_len      TYPE i,
          lv_path     TYPE string,
          lv_parentcl TYPE tdevc-parentcl.

    IF iv_top = iv_package.
      rv_path = iv_start.
    ELSE.
      SELECT SINGLE parentcl FROM tdevc INTO lv_parentcl
        WHERE devclass = iv_package.      "#EC CI_SUBRC "#EC CI_GENBUFF
      ASSERT sy-subrc = 0.

      IF lv_parentcl IS INITIAL.
        rv_path = 'error' ##no_text.
      ELSE.
        lv_len = strlen( lv_parentcl ).
        lv_path = iv_package+lv_len.
        IF strlen( lv_path ) = 0.
          RETURN. " prevent dump
        ENDIF.
        IF lv_path(1) = '_'.
          lv_path = lv_path+1.
        ENDIF.
        TRANSLATE lv_path TO LOWER CASE.
        CONCATENATE lv_path '/' INTO lv_path.

        rv_path = class_to_path( iv_top     = iv_top
                                 iv_start   = iv_start
                                 iv_package = lv_parentcl ).

        CONCATENATE rv_path lv_path INTO rv_path.

      ENDIF.

    ENDIF.

  ENDMETHOD.                    "class_to_path

  METHOD check.

    DATA: lv_path     TYPE string,
          ls_item     TYPE ty_item,
          ls_file     TYPE ty_file_signature,
          lt_res_sort LIKE it_results,
          lt_item_idx LIKE it_results.

    FIELD-SYMBOLS: <ls_res1> LIKE LINE OF it_results,
                   <ls_res2> LIKE LINE OF it_results.

    IF io_log IS INITIAL.
      RETURN.
    ENDIF.

    " Collect object indexe
    lt_res_sort = it_results.
    SORT lt_res_sort BY obj_type ASCENDING obj_name ASCENDING.

    LOOP AT it_results ASSIGNING <ls_res1> WHERE NOT obj_type IS INITIAL.
      IF NOT ( <ls_res1>-obj_type = ls_item-obj_type AND <ls_res1>-obj_name = ls_item-obj_name ).
        APPEND INITIAL LINE TO lt_item_idx ASSIGNING <ls_res2>.
        <ls_res2>-obj_type = <ls_res1>-obj_type.
        <ls_res2>-obj_name = <ls_res1>-obj_name.
        <ls_res2>-path     = <ls_res1>-path.
        MOVE-CORRESPONDING <ls_res1> TO ls_item.
      ENDIF.
    ENDLOOP.

    " Check files for one object is in the same folder

    LOOP AT it_results ASSIGNING <ls_res1> WHERE NOT obj_type IS INITIAL.
      READ TABLE lt_item_idx ASSIGNING <ls_res2>
        WITH KEY obj_type = <ls_res1>-obj_type obj_name = <ls_res1>-obj_name
        BINARY SEARCH. " Sorted above

      IF sy-subrc <> 0 OR <ls_res1>-path <> <ls_res2>-path. " All paths are same
        io_log->add( iv_msgv1 = 'Files for object'
                     iv_msgv2 = <ls_res1>-obj_type
                     iv_msgv3 = <ls_res1>-obj_name
                     iv_msgv4 = 'are not placed in the same folder'
                     iv_rc    = '1' ) ##no_text.
      ENDIF.
    ENDLOOP.

    " Check that objects are created in package corresponding to folder
    LOOP AT it_results ASSIGNING <ls_res1>
        WHERE NOT package IS INITIAL AND NOT path IS INITIAL.
      lv_path = class_to_path( iv_top     = iv_top
                               iv_start   = iv_start
                               iv_package = <ls_res1>-package ).
      IF lv_path <> <ls_res1>-path.
        io_log->add( iv_msgv1 = 'Package and path does not match for object,'
                     iv_msgv2 = <ls_res1>-obj_type
                     iv_msgv3 = <ls_res1>-obj_name
                     iv_rc    = '2' ) ##no_text.
      ENDIF.
    ENDLOOP.

    " Check for multiple files with same filename
    SORT lt_res_sort BY filename ASCENDING.

    LOOP AT lt_res_sort ASSIGNING <ls_res1>.
      IF <ls_res1>-filename IS NOT INITIAL AND <ls_res1>-filename = ls_file-filename.
        io_log->add( iv_msgv1 = 'Multiple files with same filename,'
                     iv_msgv2 = <ls_res1>-filename
                     iv_rc    = '3' ) ##no_text.
      ENDIF.

      IF <ls_res1>-filename IS INITIAL.
        io_log->add( iv_msgv1 = 'Filename is empty for object'
                     iv_msgv2 = <ls_res1>-obj_type
                     iv_msgv3 = <ls_res1>-obj_name
                     iv_rc    = '4' ) ##no_text.
      ENDIF.

      MOVE-CORRESPONDING <ls_res1> TO ls_file.
    ENDLOOP.

  ENDMETHOD.                    "check

  METHOD exists.

    cl_package_factory=>load_package(
      EXPORTING
        i_package_name             = iv_package
      EXCEPTIONS
        object_not_existing        = 1
        unexpected_error           = 2
        intern_err                 = 3
        no_access                  = 4
        object_locked_and_modified = 5 ).
    rv_bool = boolc( sy-subrc <> 1 ).

  ENDMETHOD.

  METHOD create_child.

    DATA: li_parent TYPE REF TO if_package,
          ls_child  TYPE scompkdtln.

    cl_package_factory=>load_package(
      EXPORTING
        i_package_name             = iv_parent
      IMPORTING
        e_package                  = li_parent
      EXCEPTIONS
        object_not_existing        = 1
        unexpected_error           = 2
        intern_err                 = 3
        no_access                  = 4
        object_locked_and_modified = 5 ).
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error reading parent package' ).
    ENDIF.

    ls_child-devclass  = iv_child.
    ls_child-dlvunit   = li_parent->software_component.
    ls_child-ctext     = iv_child.
    ls_child-parentcl  = iv_parent.
    ls_child-pdevclass = li_parent->transport_layer.
    ls_child-as4user   = sy-uname.

    create( ls_child ).

  ENDMETHOD.

  METHOD create.

    DATA: lv_err     TYPE string,
          ls_package LIKE is_package.

    ASSERT NOT is_package-devclass IS INITIAL.

    cl_package_factory=>load_package(
      EXPORTING
        i_package_name             = is_package-devclass
      EXCEPTIONS
        object_not_existing        = 1
        unexpected_error           = 2
        intern_err                 = 3
        no_access                  = 4
        object_locked_and_modified = 5 ).
    IF sy-subrc = 0.
      RETURN. "Package already exists. We assume this is fine
    ENDIF.

    ls_package = is_package.

    " Set software component to 'HOME' if none is set at this point.
    " Otherwise SOFTWARE_COMPONENT_INVALID will be raised.
    IF ls_package-dlvunit IS INITIAL.
      ls_package-dlvunit = 'HOME'.
    ENDIF.

    cl_package_factory=>create_new_package(
      EXPORTING
        i_reuse_deleted_object     = abap_true
*        i_suppress_dialog          = abap_true " does not exist in 730
      IMPORTING
        e_package                  = ri_package
      CHANGING
        c_package_data             = ls_package
      EXCEPTIONS
        object_already_existing    = 1
        object_just_created        = 2
        not_authorized             = 3
        wrong_name_prefix          = 4
        undefined_name             = 5
        reserved_local_name        = 6
        invalid_package_name       = 7
        short_text_missing         = 8
        software_component_invalid = 9
        layer_invalid              = 10
        author_not_existing        = 11
        component_not_existing     = 12
        component_missing          = 13
        prefix_in_use              = 14
        unexpected_error           = 15
        intern_err                 = 16
        no_access                  = 17
*        invalid_translation_depth  = 18
*        wrong_mainpack_value       = 19
*        superpackage_invalid       = 20
*        error_in_cts_checks        = 21
        OTHERS                     = 18 ).
    IF sy-subrc <> 0.
      lcx_exception=>raise( |Package { is_package-devclass } could not be created| ).
    ENDIF.

    ri_package->save(
*      EXPORTING
*        i_suppress_dialog     = abap_true    " Controls whether popups can be transmitted
      EXCEPTIONS
        object_invalid        = 1
        object_not_changeable = 2
        cancelled_in_corr     = 3
        permission_failure    = 4
        unexpected_error      = 5
        intern_err            = 6
        OTHERS                = 7 ).
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO lv_err.
      lcx_exception=>raise( lv_err ).
    ENDIF.

    ri_package->set_changeable( abap_false ).

  ENDMETHOD.

  METHOD list_superpackages.

    DATA: lt_list     LIKE rt_list,
          lv_parent   TYPE tdevc-parentcl,
          lv_devclass LIKE LINE OF rt_list.

    APPEND iv_package TO rt_list.

    SELECT SINGLE parentcl INTO lv_parent
      FROM tdevc WHERE devclass = iv_package.           "#EC CI_GENBUFF

    IF NOT lv_parent IS INITIAL.
      APPEND lv_parent TO rt_list.
      lt_list = list_superpackages( lv_devclass ).
      APPEND LINES OF lt_list TO rt_list.
    ENDIF.

  ENDMETHOD.

  METHOD list_subpackages.

    DATA: lt_list     LIKE rt_list,
          lv_devclass LIKE LINE OF rt_list.

    SELECT devclass INTO TABLE rt_list
      FROM tdevc WHERE parentcl = iv_package.           "#EC CI_GENBUFF

* note the recursion, since packages are added to the list
    LOOP AT rt_list INTO lv_devclass.
      lt_list = list_subpackages( lv_devclass ).
      APPEND LINES OF lt_list TO rt_list.
    ENDLOOP.

  ENDMETHOD.

  METHOD create_local.

    DATA: ls_package TYPE scompkdtln.

    ls_package-devclass  = iv_package.
    ls_package-ctext     = iv_package.
    ls_package-parentcl  = '$TMP'.
    ls_package-dlvunit   = 'LOCAL'.
    ls_package-as4user   = sy-uname.

    create( ls_package ).

  ENDMETHOD.                    "create

ENDCLASS.                    "lcl_package IMPLEMENTATION

Fix missing software component for subpackages


*&---------------------------------------------------------------------*
*&  Include  zabapgit_requirements
*&---------------------------------------------------------------------*

"! Helper class for checking requirements / dependencies
CLASS lcl_requirement_helper DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES:
      BEGIN OF gty_status,
        met               TYPE abap_bool,
        component         TYPE dlvunit,
        description       TYPE text80,
        installed_release TYPE saprelease,
        installed_patch   TYPE sappatchlv,
        required_release  TYPE saprelease,
        required_patch    TYPE sappatchlv,
      END OF gty_status,
      gty_status_tab TYPE STANDARD TABLE OF gty_status WITH DEFAULT KEY.
    CLASS-METHODS:
      "! Check if the given requirements are met with user interaction
      "! <p>
      "! Shows a popup if requested and asks the user if he wants to continue if there are unmet
      "! requirements. If not an exception is raised.
      "! </p>
      "! @parameter it_requirements | The requirements to check
      "! @parameter iv_show_popup | Show popup with requirements
      "! @raising lcx_exception | Cancelled by user or internal error
      check_requirements IMPORTING it_requirements TYPE lcl_dot_abapgit=>ty_requirement_tab
                                   iv_show_popup   TYPE abap_bool DEFAULT abap_true
                         RAISING   lcx_exception,
      "! Get a table with information about each requirement
      "! @parameter it_requirements | Requirements
      "! @parameter rt_status | Result
      "! @raising lcx_exception | Internal error
      get_requirement_met_status IMPORTING it_requirements  TYPE lcl_dot_abapgit=>ty_requirement_tab
                                 RETURNING VALUE(rt_status) TYPE gty_status_tab
                                 RAISING   lcx_exception.
  PROTECTED SECTION.
  PRIVATE SECTION.
    CLASS-METHODS:
      show_requirement_popup IMPORTING it_requirements TYPE gty_status_tab
                             RAISING   lcx_exception,
      version_greater_or_equal IMPORTING is_status      TYPE gty_status
                               RETURNING VALUE(rv_true) TYPE abap_bool.
ENDCLASS.

CLASS lcl_requirement_helper IMPLEMENTATION.
  METHOD check_requirements.
    DATA: lt_met_status TYPE gty_status_tab,
          lv_answer     TYPE c LENGTH 1.

    lt_met_status = get_requirement_met_status( it_requirements ).

    IF iv_show_popup = abap_true.
      show_requirement_popup( lt_met_status ).
    ENDIF.

    LOOP AT lt_met_status TRANSPORTING NO FIELDS WHERE met = abap_false.
      EXIT.
    ENDLOOP.

    IF sy-subrc = 0.
      CALL FUNCTION 'POPUP_TO_CONFIRM'
        EXPORTING
          text_question = 'The project has unmet requirements. Install anyways?'
        IMPORTING
          answer        = lv_answer.
      IF lv_answer <> '1'.
        lcx_exception=>raise( 'Cancelling because of unmet requirements.' ).
      ENDIF.
    ENDIF.
  ENDMETHOD.

  METHOD get_requirement_met_status.
    DATA: lt_installed TYPE STANDARD TABLE OF cvers_sdu.
    FIELD-SYMBOLS: <ls_requirement>    TYPE lcl_dot_abapgit=>ty_requirement,
                   <ls_status>         TYPE gty_status,
                   <ls_installed_comp> TYPE cvers_sdu.

    CALL FUNCTION 'DELIVERY_GET_INSTALLED_COMPS'
      TABLES
        tt_comptab       = lt_installed
      EXCEPTIONS
        no_release_found = 1
        OTHERS           = 2.
    IF sy-subrc <> 0.
      lcx_exception=>raise( |Error from DELIVERY_GET_INSTALLED_COMPS { sy-subrc }| ) ##NO_TEXT.
    ENDIF.

    LOOP AT it_requirements ASSIGNING <ls_requirement>.
      APPEND INITIAL LINE TO rt_status ASSIGNING <ls_status>.
      <ls_status>-component = <ls_requirement>-component.
      <ls_status>-required_release = <ls_requirement>-min_release.
      <ls_status>-required_patch = <ls_requirement>-min_patch.

      READ TABLE lt_installed WITH KEY component = <ls_requirement>-component
                              ASSIGNING <ls_installed_comp>.
      IF sy-subrc = 0.
        <ls_status>-installed_release = <ls_installed_comp>-release.
        <ls_status>-installed_patch = <ls_installed_comp>-extrelease.
        <ls_status>-description = <ls_installed_comp>-desc_text.

        <ls_status>-met = version_greater_or_equal( <ls_status> ).
      ENDIF.

      UNASSIGN <ls_installed_comp>.
    ENDLOOP.
  ENDMETHOD.

  METHOD version_greater_or_equal.
    DATA: lv_number TYPE numc4.

    TRY.
        MOVE EXACT: is_status-installed_release TO lv_number,
                    is_status-installed_patch   TO lv_number,
                    is_status-required_release  TO lv_number,
                    is_status-required_patch    TO lv_number.
      CATCH cx_sy_conversion_error.
        " Cannot compare by number, assume requirement not fullfilled (user can force install
        " anyways if this was an error)
        rv_true = abap_false.
        RETURN.
    ENDTRY.

    " Check if versions are comparable by number
    IF is_status-installed_release > is_status-required_release
       OR ( is_status-installed_release = is_status-required_release
            AND ( is_status-required_patch IS INITIAL OR
                  is_status-installed_patch >= is_status-required_patch ) ).

      rv_true = abap_true.
    ENDIF.
  ENDMETHOD.

  METHOD show_requirement_popup.
    CONSTANTS: lc_color_column_name TYPE lvc_fname VALUE 'COLOR'.
    DATA: lo_alv              TYPE REF TO cl_salv_table,
          lo_column           TYPE REF TO cl_salv_column,
          lr_colored_table    TYPE REF TO data,
          lo_tab_descr        TYPE REF TO cl_abap_tabledescr,
          lo_struct_descr     TYPE REF TO cl_abap_structdescr,
          lo_enh_struct_descr TYPE REF TO cl_abap_structdescr,
          lo_enh_tab_descr    TYPE REF TO cl_abap_tabledescr,
          lt_comps            TYPE cl_abap_structdescr=>component_table,
          lt_color_neg        TYPE lvc_t_scol,
          lt_color_pos        TYPE lvc_t_scol,
          ls_color            TYPE lvc_s_scol,
          lx_ex               TYPE REF TO cx_root.
    FIELD-SYMBOLS: <ls_comp>    TYPE abap_componentdescr,
                   <lt_pointer> TYPE STANDARD TABLE,
                   <lg_line>    TYPE data,
                   <lt_color>   TYPE lvc_t_scol,
                   <lv_met>     TYPE abap_bool.

    ls_color-color-col = col_negative.
    APPEND ls_color TO lt_color_neg.

    ls_color-color-col = col_positive.
    APPEND ls_color TO lt_color_pos.

    CLEAR ls_color.

    lo_tab_descr ?= cl_abap_typedescr=>describe_by_data( it_requirements ).
    lo_struct_descr ?= lo_tab_descr->get_table_line_type( ).
    lt_comps = lo_struct_descr->get_components( ).
    APPEND INITIAL LINE TO lt_comps ASSIGNING <ls_comp>.
    <ls_comp>-name = lc_color_column_name.
    <ls_comp>-type ?= cl_abap_typedescr=>describe_by_name( 'LVC_T_SCOL' ).
    lo_enh_struct_descr = cl_abap_structdescr=>get( lt_comps ).
    lo_enh_tab_descr = cl_abap_tabledescr=>get( lo_enh_struct_descr ).

    CREATE DATA lr_colored_table TYPE HANDLE lo_enh_tab_descr.
    ASSERT lr_colored_table IS BOUND.
    ASSIGN lr_colored_table->* TO <lt_pointer>.
    ASSERT <lt_pointer> IS ASSIGNED.

    MOVE-CORRESPONDING it_requirements TO <lt_pointer>.

    LOOP AT <lt_pointer> ASSIGNING <lg_line>.
      ASSIGN COMPONENT 'MET' OF STRUCTURE <lg_line> TO <lv_met>.
      ASSERT <lv_met> IS ASSIGNED.
      ASSIGN COMPONENT lc_color_column_name OF STRUCTURE <lg_line> TO <lt_color>.
      ASSERT <lt_color> IS ASSIGNED.
      IF <lv_met> = abap_false.
        <lt_color> = lt_color_neg.
      ELSE.
        <lt_color> = lt_color_pos.
      ENDIF.
      UNASSIGN: <lt_color>, <lv_met>.
    ENDLOOP.
    UNASSIGN <lg_line>.

    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table   = lo_alv
          CHANGING
            t_table        = <lt_pointer>
        ).

        lo_alv->get_columns(:
          )->get_column( 'MET' )->set_short_text( 'Met' ),
          )->set_color_column( lc_color_column_name ),
          )->set_optimize( ),
        ).

        lo_column = lo_alv->get_columns( )->get_column( 'REQUIRED_RELEASE' ).
        lo_column->set_fixed_header_text( 'S').
        lo_column->set_short_text( 'Req. Rel.' ).

        lo_column = lo_alv->get_columns( )->get_column( 'REQUIRED_PATCH' ).
        lo_column->set_fixed_header_text( 'S').
        lo_column->set_short_text( 'Req. SP L.' ).

        lo_alv->set_screen_popup( start_column = 30
                                  end_column   = 100
                                  start_line   = 10
                                  end_line     = 20 ).
        lo_alv->get_display_settings( )->set_list_header( 'Requirements' ).
        lo_alv->display( ).

      CATCH cx_salv_msg cx_salv_not_found cx_salv_data_error INTO lx_ex.
        RAISE EXCEPTION TYPE lcx_exception
          EXPORTING
            iv_text     = lx_ex->get_text( )
            ix_previous = lx_ex.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

*&---------------------------------------------------------------------*
*&  Include  zabapgit_requirements
*&---------------------------------------------------------------------*

"! Helper class for checking requirements / dependencies
CLASS lcl_requirement_helper DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES:
      BEGIN OF gty_status,
        met               TYPE abap_bool,
        component         TYPE dlvunit,
        description       TYPE text80,
        installed_release TYPE saprelease,
        installed_patch   TYPE sappatchlv,
        required_release  TYPE saprelease,
        required_patch    TYPE sappatchlv,
      END OF gty_status,
      gty_status_tab TYPE STANDARD TABLE OF gty_status WITH DEFAULT KEY.
    CLASS-METHODS:
      "! Check if the given requirements are met with user interaction
      "! <p>
      "! Shows a popup if requested and asks the user if he wants to continue if there are unmet
      "! requirements. If not an exception is raised.
      "! </p>
      "! @parameter it_requirements | The requirements to check
      "! @parameter iv_show_popup | Show popup with requirements
      "! @raising lcx_exception | Cancelled by user or internal error
      check_requirements IMPORTING it_requirements TYPE lcl_dot_abapgit=>ty_requirement_tab
                                   iv_show_popup   TYPE abap_bool DEFAULT abap_true
                         RAISING   lcx_exception,
      "! Get a table with information about each requirement
      "! @parameter it_requirements | Requirements
      "! @parameter rt_status | Result
      "! @raising lcx_exception | Internal error
      get_requirement_met_status IMPORTING it_requirements  TYPE lcl_dot_abapgit=>ty_requirement_tab
                                 RETURNING VALUE(rt_status) TYPE gty_status_tab
                                 RAISING   lcx_exception.
  PROTECTED SECTION.
  PRIVATE SECTION.
    CLASS-METHODS:
      show_requirement_popup IMPORTING it_requirements TYPE gty_status_tab
                             RAISING   lcx_exception,
      version_greater_or_equal IMPORTING is_status      TYPE gty_status
                               RETURNING VALUE(rv_true) TYPE abap_bool.
ENDCLASS.

CLASS lcl_requirement_helper IMPLEMENTATION.
  METHOD check_requirements.
    DATA: lt_met_status TYPE gty_status_tab,
          lv_answer     TYPE c LENGTH 1.

    lt_met_status = get_requirement_met_status( it_requirements ).

    IF iv_show_popup = abap_true.
      show_requirement_popup( lt_met_status ).
    ENDIF.

    LOOP AT lt_met_status TRANSPORTING NO FIELDS WHERE met = abap_false.
      EXIT.
    ENDLOOP.

    IF sy-subrc = 0.
      CALL FUNCTION 'POPUP_TO_CONFIRM'
        EXPORTING
          text_question = 'The project has unmet requirements. Install anyways?'
        IMPORTING
          answer        = lv_answer.
      IF lv_answer <> '1'.
        lcx_exception=>raise( 'Cancelling because of unmet requirements.' ).
      ENDIF.
    ENDIF.
  ENDMETHOD.

  METHOD get_requirement_met_status.
    DATA: lt_installed TYPE STANDARD TABLE OF cvers_sdu.
    FIELD-SYMBOLS: <ls_requirement>    TYPE lcl_dot_abapgit=>ty_requirement,
                   <ls_status>         TYPE gty_status,
                   <ls_installed_comp> TYPE cvers_sdu.

    CALL FUNCTION 'DELIVERY_GET_INSTALLED_COMPS'
      TABLES
        tt_comptab       = lt_installed
      EXCEPTIONS
        no_release_found = 1
        OTHERS           = 2.
    IF sy-subrc <> 0.
      lcx_exception=>raise( |Error from DELIVERY_GET_INSTALLED_COMPS { sy-subrc }| ) ##NO_TEXT.
    ENDIF.

    LOOP AT it_requirements ASSIGNING <ls_requirement>.
      APPEND INITIAL LINE TO rt_status ASSIGNING <ls_status>.
      <ls_status>-component = <ls_requirement>-component.
      <ls_status>-required_release = <ls_requirement>-min_release.
      <ls_status>-required_patch = <ls_requirement>-min_patch.

      READ TABLE lt_installed WITH KEY component = <ls_requirement>-component
                              ASSIGNING <ls_installed_comp>.
      IF sy-subrc = 0.
        <ls_status>-installed_release = <ls_installed_comp>-release.
        <ls_status>-installed_patch = <ls_installed_comp>-extrelease.
        <ls_status>-description = <ls_installed_comp>-desc_text.

        <ls_status>-met = version_greater_or_equal( <ls_status> ).
      ENDIF.

      UNASSIGN <ls_installed_comp>.
    ENDLOOP.
  ENDMETHOD.

  METHOD version_greater_or_equal.
    DATA: lv_number TYPE numc4.

    TRY.
        MOVE EXACT: is_status-installed_release TO lv_number,
                    is_status-installed_patch   TO lv_number,
                    is_status-required_release  TO lv_number,
                    is_status-required_patch    TO lv_number.
      CATCH cx_sy_conversion_error.
        " Cannot compare by number, assume requirement not fullfilled (user can force install
        " anyways if this was an error)
        rv_true = abap_false.
        RETURN.
    ENDTRY.

    " Check if versions are comparable by number
    IF is_status-installed_release > is_status-required_release
       OR ( is_status-installed_release = is_status-required_release
            AND ( is_status-required_patch IS INITIAL OR
                  is_status-installed_patch >= is_status-required_patch ) ).

      rv_true = abap_true.
    ENDIF.
  ENDMETHOD.

  METHOD show_requirement_popup.
    TYPES: BEGIN OF lty_color_line,
             color TYPE lvc_t_scol.
        INCLUDE TYPE gty_status.
    TYPES: END OF lty_color_line,
    lty_color_tab TYPE STANDARD TABLE OF lty_color_line WITH DEFAULT KEY.
    DATA: lo_alv         TYPE REF TO cl_salv_table,
          lo_column      TYPE REF TO cl_salv_column,
          lt_color_table TYPE lty_color_tab,
          lt_color_neg   TYPE lvc_t_scol,
          lt_color_pos   TYPE lvc_t_scol,
          ls_color       TYPE lvc_s_scol,
          lx_ex          TYPE REF TO cx_root.
    FIELD-SYMBOLS: <ls_line> TYPE lty_color_line.

    ls_color-color-col = col_negative.
    APPEND ls_color TO lt_color_neg.

    ls_color-color-col = col_positive.
    APPEND ls_color TO lt_color_pos.

    CLEAR ls_color.

    MOVE-CORRESPONDING it_requirements TO lt_color_table.

    LOOP AT lt_color_table ASSIGNING <ls_line>.
      IF <ls_line>-met = abap_false.
        <ls_line>-color = lt_color_neg.
      ELSE.
        <ls_line>-color = lt_color_pos.
      ENDIF.
    ENDLOOP.
    UNASSIGN <ls_line>.

    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table   = lo_alv
          CHANGING
            t_table        = lt_color_table
        ).

        lo_alv->get_columns(:
          )->get_column( 'MET' )->set_short_text( 'Met' ),
          )->set_color_column( 'COLOR' ),
          )->set_optimize( ),
        ).

        lo_column = lo_alv->get_columns( )->get_column( 'REQUIRED_RELEASE' ).
        lo_column->set_fixed_header_text( 'S').
        lo_column->set_short_text( 'Req. Rel.' ).

        lo_column = lo_alv->get_columns( )->get_column( 'REQUIRED_PATCH' ).
        lo_column->set_fixed_header_text( 'S').
        lo_column->set_short_text( 'Req. SP L.' ).

        lo_alv->set_screen_popup( start_column = 30
                                  end_column   = 100
                                  start_line   = 10
                                  end_line     = 20 ).
        lo_alv->get_display_settings( )->set_list_header( 'Requirements' ).
        lo_alv->display( ).

      CATCH cx_salv_msg cx_salv_not_found cx_salv_data_error INTO lx_ex.
        RAISE EXCEPTION TYPE lcx_exception
          EXPORTING
            iv_text     = lx_ex->get_text( )
            ix_previous = lx_ex.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

Remove unnecessary dynamic typing

Remove unnecessary dynamic typing


*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_REPO
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_repo DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_repo DEFINITION ABSTRACT FRIENDS lcl_repo_srv.

  PUBLIC SECTION.
    METHODS:
      constructor
        IMPORTING is_data TYPE lcl_persistence_repo=>ty_repo,
      get_key
        RETURNING VALUE(rv_key) TYPE lcl_persistence_db=>ty_value,
      get_name
        RETURNING VALUE(rv_name) TYPE string
        RAISING   lcx_exception,
      get_files_local
        IMPORTING io_log          TYPE REF TO lcl_log OPTIONAL
        RETURNING VALUE(rt_files) TYPE ty_files_item_tt
        RAISING   lcx_exception,
      get_local_checksums
        RETURNING VALUE(rt_checksums) TYPE lcl_persistence_repo=>ty_local_checksum_tt,
      get_local_checksums_per_file
        RETURNING VALUE(rt_checksums) TYPE ty_file_signatures_tt,
      get_files_remote
        RETURNING VALUE(rt_files) TYPE ty_files_tt
        RAISING   lcx_exception,
      get_package
        RETURNING VALUE(rv_package) TYPE lcl_persistence_repo=>ty_repo-package,
      get_master_language
        RETURNING VALUE(rv_language) TYPE spras,
      is_write_protected
        RETURNING VALUE(rv_yes) TYPE sap_bool,
      delete
        RAISING lcx_exception,
      get_dot_abapgit
        RETURNING VALUE(ro_dot_abapgit) TYPE REF TO lcl_dot_abapgit,
      deserialize
        RAISING lcx_exception,
      refresh
        IMPORTING iv_drop_cache TYPE abap_bool DEFAULT abap_false
        RAISING lcx_exception,
      refresh_local, " For testing purposes, maybe removed later
      update_local_checksums
        IMPORTING it_files            TYPE ty_file_signatures_tt
        RAISING   lcx_exception,
      rebuild_local_checksums
        RAISING   lcx_exception,
      is_offline
        RETURNING VALUE(rv_offline) TYPE abap_bool
        RAISING   lcx_exception.

  PROTECTED SECTION.

    DATA: mt_local              TYPE ty_files_item_tt,
          mt_remote             TYPE ty_files_tt,
          mo_dot_abapgit        TYPE REF TO lcl_dot_abapgit,
          mv_do_local_refresh   TYPE abap_bool,
          mv_last_serialization TYPE timestamp,
          ms_data               TYPE lcl_persistence_repo=>ty_repo.

    METHODS:
      find_dot_abapgit
        RAISING lcx_exception,
      set
        IMPORTING iv_sha1        TYPE ty_sha1 OPTIONAL
                  it_checksums   TYPE lcl_persistence_repo=>ty_local_checksum_tt OPTIONAL
                  iv_url         TYPE lcl_persistence_repo=>ty_repo-url OPTIONAL
                  iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name OPTIONAL
                  iv_head_branch TYPE lcl_persistence_repo=>ty_repo-head_branch OPTIONAL
                  iv_offline     TYPE lcl_persistence_repo=>ty_repo-offline OPTIONAL
        RAISING   lcx_exception.

ENDCLASS.                    "lcl_repo DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_repo_online DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_repo_online DEFINITION INHERITING FROM lcl_repo FINAL.

  PUBLIC SECTION.
    METHODS:
      refresh REDEFINITION,
      constructor
        IMPORTING is_data TYPE lcl_persistence_repo=>ty_repo
        RAISING   lcx_exception,
      get_url
        RETURNING VALUE(rv_url) TYPE lcl_persistence_repo=>ty_repo-url,
      get_branch_name
        RETURNING VALUE(rv_name) TYPE lcl_persistence_repo=>ty_repo-branch_name,
      get_head_branch_name
        RETURNING VALUE(rv_name) TYPE lcl_persistence_repo=>ty_repo-head_branch,
      get_branches
        RETURNING VALUE(ro_branches) TYPE REF TO lcl_git_branch_list
        RAISING   lcx_exception,
      set_url
        IMPORTING iv_url TYPE lcl_persistence_repo=>ty_repo-url
        RAISING   lcx_exception,
      set_branch_name
        IMPORTING iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name
        RAISING   lcx_exception,
      set_new_remote
        IMPORTING iv_url TYPE lcl_persistence_repo=>ty_repo-url
                  iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name
        RAISING   lcx_exception,
      get_sha1_local
        RETURNING VALUE(rv_sha1) TYPE lcl_persistence_repo=>ty_repo-sha1,
      get_sha1_remote
        RETURNING VALUE(rv_sha1) TYPE lcl_persistence_repo=>ty_repo-sha1
        RAISING   lcx_exception,
      get_files_remote REDEFINITION,
      get_objects
        RETURNING VALUE(rt_objects) TYPE ty_objects_tt
        RAISING   lcx_exception,
      deserialize REDEFINITION,
      status
        IMPORTING io_log            TYPE REF TO lcl_log OPTIONAL
        RETURNING VALUE(rt_results) TYPE ty_results_tt
        RAISING   lcx_exception,
      reset_status,
      rebuild_local_checksums REDEFINITION,
      push
        IMPORTING is_comment TYPE ty_comment
                  io_stage   TYPE REF TO lcl_stage
        RAISING   lcx_exception.

  PRIVATE SECTION.
    DATA:
      mt_objects     TYPE ty_objects_tt,
      mv_branch      TYPE ty_sha1,
      mv_initialized TYPE abap_bool,
      mo_branches    TYPE REF TO lcl_git_branch_list,
      mt_status      TYPE ty_results_tt.

    METHODS:
      handle_stage_ignore
        IMPORTING io_stage TYPE REF TO lcl_stage
        RAISING   lcx_exception,
      initialize
        RAISING lcx_exception,
      actualize_head_branch
        RAISING lcx_exception.

ENDCLASS.                    "lcl_repo_online DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_repo_offline DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_repo_offline DEFINITION INHERITING FROM lcl_repo FINAL.

  PUBLIC SECTION.
    METHODS:
      set_files_remote
        IMPORTING it_files TYPE ty_files_tt
        RAISING   lcx_exception.

ENDCLASS.                    "lcl_repo_offline DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_repo_srv DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_repo_srv DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app.

  PUBLIC SECTION.

    TYPES: ty_repo_tt TYPE STANDARD TABLE OF REF TO lcl_repo WITH DEFAULT KEY.

    METHODS list
      RETURNING VALUE(rt_list) TYPE ty_repo_tt
      RAISING   lcx_exception.

    METHODS refresh
      RAISING lcx_exception.

    METHODS new_online
      IMPORTING iv_url         TYPE string
                iv_branch_name TYPE string
                iv_package     TYPE devclass
      RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo_online
      RAISING   lcx_exception.

    METHODS new_offline
      IMPORTING iv_url         TYPE string
                iv_package     TYPE devclass
      RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo_offline
      RAISING   lcx_exception.

    METHODS delete
      IMPORTING io_repo TYPE REF TO lcl_repo
      RAISING   lcx_exception.

    METHODS get
      IMPORTING iv_key         TYPE lcl_persistence_db=>ty_value
      RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo
      RAISING   lcx_exception.

    METHODS is_repo_installed
      IMPORTING iv_url              TYPE string
                iv_target_package   TYPE devclass OPTIONAL
      RETURNING VALUE(rv_installed) TYPE abap_bool
      RAISING   lcx_exception.

    METHODS switch_repo_type
      IMPORTING iv_key     TYPE lcl_persistence_db=>ty_value
                iv_offline TYPE abap_bool
      RAISING   lcx_exception.

  PRIVATE SECTION.

    METHODS constructor.

    DATA: mv_init        TYPE abap_bool VALUE abap_false,
          mo_persistence TYPE REF TO lcl_persistence_repo,
          mt_list        TYPE ty_repo_tt.

    METHODS add
      IMPORTING io_repo TYPE REF TO lcl_repo
      RAISING   lcx_exception.

    METHODS validate_package
      IMPORTING iv_package TYPE devclass
      RAISING   lcx_exception.

ENDCLASS.                    "lcl_repo_srv DEFINITION

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_REPO
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_repo DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_repo DEFINITION ABSTRACT FRIENDS lcl_repo_srv.

  PUBLIC SECTION.
    METHODS:
      constructor
        IMPORTING is_data TYPE lcl_persistence_repo=>ty_repo,
      get_key
        RETURNING VALUE(rv_key) TYPE lcl_persistence_db=>ty_value,
      get_name
        RETURNING VALUE(rv_name) TYPE string
        RAISING   lcx_exception,
      get_files_local
        IMPORTING io_log          TYPE REF TO lcl_log OPTIONAL
                  it_filter       TYPE scts_tadir OPTIONAL
        RETURNING VALUE(rt_files) TYPE ty_files_item_tt
        RAISING   lcx_exception,
      get_local_checksums
        RETURNING VALUE(rt_checksums) TYPE lcl_persistence_repo=>ty_local_checksum_tt,
      get_local_checksums_per_file
        RETURNING VALUE(rt_checksums) TYPE ty_file_signatures_tt,
      get_files_remote
        RETURNING VALUE(rt_files) TYPE ty_files_tt
        RAISING   lcx_exception,
      get_package
        RETURNING VALUE(rv_package) TYPE lcl_persistence_repo=>ty_repo-package,
      get_master_language
        RETURNING VALUE(rv_language) TYPE spras,
      is_write_protected
        RETURNING VALUE(rv_yes) TYPE sap_bool,
      delete
        RAISING lcx_exception,
      get_dot_abapgit
        RETURNING VALUE(ro_dot_abapgit) TYPE REF TO lcl_dot_abapgit,
      deserialize
        RAISING lcx_exception,
      refresh
        IMPORTING iv_drop_cache TYPE abap_bool DEFAULT abap_false
        RAISING lcx_exception,
      refresh_local, " For testing purposes, maybe removed later
      update_local_checksums
        IMPORTING it_files            TYPE ty_file_signatures_tt
        RAISING   lcx_exception,
      rebuild_local_checksums
        RAISING   lcx_exception,
      is_offline
        RETURNING VALUE(rv_offline) TYPE abap_bool
        RAISING   lcx_exception.

  PROTECTED SECTION.

    DATA: mt_local              TYPE ty_files_item_tt,
          mt_remote             TYPE ty_files_tt,
          mo_dot_abapgit        TYPE REF TO lcl_dot_abapgit,
          mv_do_local_refresh   TYPE abap_bool,
          mv_last_serialization TYPE timestamp,
          ms_data               TYPE lcl_persistence_repo=>ty_repo.

    METHODS:
      find_dot_abapgit
        RAISING lcx_exception,
      set
        IMPORTING iv_sha1        TYPE ty_sha1 OPTIONAL
                  it_checksums   TYPE lcl_persistence_repo=>ty_local_checksum_tt OPTIONAL
                  iv_url         TYPE lcl_persistence_repo=>ty_repo-url OPTIONAL
                  iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name OPTIONAL
                  iv_head_branch TYPE lcl_persistence_repo=>ty_repo-head_branch OPTIONAL
                  iv_offline     TYPE lcl_persistence_repo=>ty_repo-offline OPTIONAL
        RAISING   lcx_exception.

ENDCLASS.                    "lcl_repo DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_repo_online DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_repo_online DEFINITION INHERITING FROM lcl_repo FINAL.

  PUBLIC SECTION.
    METHODS:
      refresh REDEFINITION,
      constructor
        IMPORTING is_data TYPE lcl_persistence_repo=>ty_repo
        RAISING   lcx_exception,
      get_url
        RETURNING VALUE(rv_url) TYPE lcl_persistence_repo=>ty_repo-url,
      get_branch_name
        RETURNING VALUE(rv_name) TYPE lcl_persistence_repo=>ty_repo-branch_name,
      get_head_branch_name
        RETURNING VALUE(rv_name) TYPE lcl_persistence_repo=>ty_repo-head_branch,
      get_branches
        RETURNING VALUE(ro_branches) TYPE REF TO lcl_git_branch_list
        RAISING   lcx_exception,
      set_url
        IMPORTING iv_url TYPE lcl_persistence_repo=>ty_repo-url
        RAISING   lcx_exception,
      set_branch_name
        IMPORTING iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name
        RAISING   lcx_exception,
      set_new_remote
        IMPORTING iv_url TYPE lcl_persistence_repo=>ty_repo-url
                  iv_branch_name TYPE lcl_persistence_repo=>ty_repo-branch_name
        RAISING   lcx_exception,
      get_sha1_local
        RETURNING VALUE(rv_sha1) TYPE lcl_persistence_repo=>ty_repo-sha1,
      get_sha1_remote
        RETURNING VALUE(rv_sha1) TYPE lcl_persistence_repo=>ty_repo-sha1
        RAISING   lcx_exception,
      get_files_remote REDEFINITION,
      get_objects
        RETURNING VALUE(rt_objects) TYPE ty_objects_tt
        RAISING   lcx_exception,
      deserialize REDEFINITION,
      status
        IMPORTING io_log            TYPE REF TO lcl_log OPTIONAL
        RETURNING VALUE(rt_results) TYPE ty_results_tt
        RAISING   lcx_exception,
      reset_status,
      rebuild_local_checksums REDEFINITION,
      push
        IMPORTING is_comment TYPE ty_comment
                  io_stage   TYPE REF TO lcl_stage
        RAISING   lcx_exception.

  PRIVATE SECTION.
    DATA:
      mt_objects     TYPE ty_objects_tt,
      mv_branch      TYPE ty_sha1,
      mv_initialized TYPE abap_bool,
      mo_branches    TYPE REF TO lcl_git_branch_list,
      mt_status      TYPE ty_results_tt.

    METHODS:
      handle_stage_ignore
        IMPORTING io_stage TYPE REF TO lcl_stage
        RAISING   lcx_exception,
      initialize
        RAISING lcx_exception,
      actualize_head_branch
        RAISING lcx_exception.

ENDCLASS.                    "lcl_repo_online DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_repo_offline DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_repo_offline DEFINITION INHERITING FROM lcl_repo FINAL.

  PUBLIC SECTION.
    METHODS:
      set_files_remote
        IMPORTING it_files TYPE ty_files_tt
        RAISING   lcx_exception.

ENDCLASS.                    "lcl_repo_offline DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_repo_srv DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_repo_srv DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app.

  PUBLIC SECTION.

    TYPES: ty_repo_tt TYPE STANDARD TABLE OF REF TO lcl_repo WITH DEFAULT KEY.

    METHODS list
      RETURNING VALUE(rt_list) TYPE ty_repo_tt
      RAISING   lcx_exception.

    METHODS refresh
      RAISING lcx_exception.

    METHODS new_online
      IMPORTING iv_url         TYPE string
                iv_branch_name TYPE string
                iv_package     TYPE devclass
      RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo_online
      RAISING   lcx_exception.

    METHODS new_offline
      IMPORTING iv_url         TYPE string
                iv_package     TYPE devclass
      RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo_offline
      RAISING   lcx_exception.

    METHODS delete
      IMPORTING io_repo TYPE REF TO lcl_repo
      RAISING   lcx_exception.

    METHODS get
      IMPORTING iv_key         TYPE lcl_persistence_db=>ty_value
      RETURNING VALUE(ro_repo) TYPE REF TO lcl_repo
      RAISING   lcx_exception.

    METHODS is_repo_installed
      IMPORTING iv_url              TYPE string
                iv_target_package   TYPE devclass OPTIONAL
      RETURNING VALUE(rv_installed) TYPE abap_bool
      RAISING   lcx_exception.

    METHODS switch_repo_type
      IMPORTING iv_key     TYPE lcl_persistence_db=>ty_value
                iv_offline TYPE abap_bool
      RAISING   lcx_exception.

  PRIVATE SECTION.

    METHODS constructor.

    DATA: mv_init        TYPE abap_bool VALUE abap_false,
          mo_persistence TYPE REF TO lcl_persistence_repo,
          mt_list        TYPE ty_repo_tt.

    METHODS add
      IMPORTING io_repo TYPE REF TO lcl_repo
      RAISING   lcx_exception.

    METHODS validate_package
      IMPORTING iv_package TYPE devclass
      RAISING   lcx_exception.

ENDCLASS.                    "lcl_repo_srv DEFINITION

Update zabapgit_repo.prog.abap

Update zabapgit_repo.prog.abap


REPORT zabapgit LINE-SIZE 100.

* See http://www.abapgit.org

CONSTANTS: gc_xml_version  TYPE string VALUE 'v1.0.0',      "#EC NOTEXT
           gc_abap_version TYPE string VALUE 'v1.17.16'.    "#EC NOTEXT

********************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 abapGit Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
********************************************************************************

SELECTION-SCREEN BEGIN OF SCREEN 1001.
* dummy for triggering screen
SELECTION-SCREEN END OF SCREEN 1001.

INCLUDE zabapgit_password_dialog. " !!! Contains SELECTION SCREEN

INCLUDE zabapgit_definitions.
INCLUDE zabapgit_exceptions.
INCLUDE zabapgit_zlib.
INCLUDE zabapgit_html.
INCLUDE zabapgit_util.
INCLUDE zabapgit_xml.

INCLUDE zabapgit_app. " Some deferred definitions here
INCLUDE zabapgit_persistence_old.
INCLUDE zabapgit_persistence.
INCLUDE zabapgit_dot_abapgit.
INCLUDE zabapgit_sap_package.

INCLUDE zabapgit_stage.
INCLUDE zabapgit_git_helpers.
INCLUDE zabapgit_repo.
INCLUDE zabapgit_stage_logic.
INCLUDE zabapgit_git.
INCLUDE zabapgit_objects.
INCLUDE zabapgit_tadir.
INCLUDE zabapgit_file_status.
INCLUDE zabapgit_popups.
INCLUDE zabapgit_zip.
INCLUDE zabapgit_objects_impl.

INCLUDE zabapgit_object_serializing. " All serializing classes here

INCLUDE zabapgit_repo_impl.
INCLUDE zabapgit_background.
INCLUDE zabapgit_transport.

INCLUDE zabapgit_services. " All services here
INCLUDE zabapgit_gui_pages. " All GUI pages here
INCLUDE zabapgit_gui_pages_userexit IF FOUND.
INCLUDE zabapgit_gui_router.
INCLUDE zabapgit_gui.

INCLUDE zabapgit_app_impl.
INCLUDE zabapgit_unit_test.
INCLUDE zabapgit_forms.

**********************************************************************
INITIALIZATION.
  lcl_password_dialog=>on_screen_init( ).

START-OF-SELECTION.
  PERFORM run.

* Hide Execute button from screen
AT SELECTION-SCREEN OUTPUT.
  IF sy-dynnr = lcl_password_dialog=>dynnr.
    lcl_password_dialog=>on_screen_output( ).
  ELSE.
    PERFORM output.
  ENDIF.

* SAP back command re-direction
AT SELECTION-SCREEN ON EXIT-COMMAND.
  PERFORM exit.

AT SELECTION-SCREEN.
  IF sy-dynnr = lcl_password_dialog=>dynnr.
    lcl_password_dialog=>on_screen_event( sscrfields-ucomm ).
  ENDIF.

REPORT zabapgit LINE-SIZE 100.

* See http://www.abapgit.org

CONSTANTS: gc_xml_version  TYPE string VALUE 'v1.0.0',      "#EC NOTEXT
           gc_abap_version TYPE string VALUE 'v1.17.17'.    "#EC NOTEXT

********************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 abapGit Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
********************************************************************************

SELECTION-SCREEN BEGIN OF SCREEN 1001.
* dummy for triggering screen
SELECTION-SCREEN END OF SCREEN 1001.

INCLUDE zabapgit_password_dialog. " !!! Contains SELECTION SCREEN

INCLUDE zabapgit_definitions.
INCLUDE zabapgit_exceptions.
INCLUDE zabapgit_zlib.
INCLUDE zabapgit_html.
INCLUDE zabapgit_util.
INCLUDE zabapgit_xml.

INCLUDE zabapgit_app. " Some deferred definitions here
INCLUDE zabapgit_persistence_old.
INCLUDE zabapgit_persistence.
INCLUDE zabapgit_dot_abapgit.
INCLUDE zabapgit_sap_package.

INCLUDE zabapgit_stage.
INCLUDE zabapgit_git_helpers.
INCLUDE zabapgit_repo.
INCLUDE zabapgit_stage_logic.
INCLUDE zabapgit_git.
INCLUDE zabapgit_objects.
INCLUDE zabapgit_tadir.
INCLUDE zabapgit_file_status.
INCLUDE zabapgit_popups.
INCLUDE zabapgit_zip.
INCLUDE zabapgit_objects_impl.

INCLUDE zabapgit_object_serializing. " All serializing classes here

INCLUDE zabapgit_repo_impl.
INCLUDE zabapgit_background.
INCLUDE zabapgit_transport.

INCLUDE zabapgit_services. " All services here
INCLUDE zabapgit_gui_pages. " All GUI pages here
INCLUDE zabapgit_gui_pages_userexit IF FOUND.
INCLUDE zabapgit_gui_router.
INCLUDE zabapgit_gui.

INCLUDE zabapgit_app_impl.
INCLUDE zabapgit_unit_test.
INCLUDE zabapgit_forms.

**********************************************************************
INITIALIZATION.
  lcl_password_dialog=>on_screen_init( ).

START-OF-SELECTION.
  PERFORM run.

* Hide Execute button from screen
AT SELECTION-SCREEN OUTPUT.
  IF sy-dynnr = lcl_password_dialog=>dynnr.
    lcl_password_dialog=>on_screen_output( ).
  ELSE.
    PERFORM output.
  ENDIF.

* SAP back command re-direction
AT SELECTION-SCREEN ON EXIT-COMMAND.
  PERFORM exit.

AT SELECTION-SCREEN.
  IF sy-dynnr = lcl_password_dialog=>dynnr.
    lcl_password_dialog=>on_screen_event( sscrfields-ucomm ).
  ENDIF.

bump version to v1.17.17

bump version to v1.17.17


*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_OBJECT_SHLP
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_object_shlp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_object_shlp DEFINITION INHERITING FROM lcl_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES lif_object.
    ALIASES mo_files FOR lif_object~mo_files.

ENDCLASS.                    "lcl_object_dtel DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_object_dtel IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_object_shlp IMPLEMENTATION.

  METHOD lif_object~has_changed_since.

    DATA: lv_date    TYPE dats,
          lv_time    TYPE tims,
          lv_ts      TYPE timestamp.

    SELECT SINGLE as4date as4time FROM dd30l
      INTO (lv_date, lv_time)
      WHERE shlpname = ms_item-obj_name
      AND as4local = 'A'.

    _object_check_timestamp lv_date lv_time.

  ENDMETHOD.  "lif_object~has_changed_since

  METHOD lif_object~changed_by.

    SELECT SINGLE as4user FROM dd30l INTO rv_user
      WHERE shlpname = ms_item-obj_name
      AND as4local = 'A'.                               "#EC CI_GENBUFF
    IF sy-subrc <> 0.
      rv_user = c_user_unknown.
    ENDIF.

  ENDMETHOD.

  METHOD lif_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.                    "lif_object~get_metadata

  METHOD lif_object~exists.

    DATA: lv_shlpname TYPE dd30l-shlpname.

    SELECT SINGLE shlpname FROM dd30l INTO lv_shlpname
      WHERE shlpname = ms_item-obj_name
      AND as4local = 'A'.                               "#EC CI_GENBUFF
    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.                    "lif_object~exists

  METHOD lif_object~jump.

    jump_se11( iv_radio = 'RSRD1-SHMA'
               iv_field = 'RSRD1-SHMA_VAL' ).

  ENDMETHOD.                    "jump

  METHOD lif_object~delete.

    DATA: lv_objname TYPE rsedd0-ddobjname.

    lv_objname = ms_item-obj_name.

    CALL FUNCTION 'RS_DD_DELETE_OBJ'
      EXPORTING
        no_ask               = abap_true
        objname              = lv_objname
        objtype              = 'H'
      EXCEPTIONS
        not_executed         = 1
        object_not_found     = 2
        object_not_specified = 3
        permission_failure   = 4.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from RS_DD_DELETE_OBJ, SHLP' ).
    ENDIF.

  ENDMETHOD.                    "delete

  METHOD lif_object~serialize.

    DATA: lv_name  TYPE ddobjname,
          ls_dd30v TYPE dd30v,
          lt_dd31v TYPE TABLE OF dd31v,
          lt_dd32p TYPE TABLE OF dd32p,
          lt_dd33v TYPE TABLE OF dd33v.

    lv_name = ms_item-obj_name.

    CALL FUNCTION 'DDIF_SHLP_GET'
      EXPORTING
        name          = lv_name
        state         = 'A'
        langu         = mv_language
      IMPORTING
        dd30v_wa      = ls_dd30v
      TABLES
        dd31v_tab     = lt_dd31v
        dd32p_tab     = lt_dd32p
        dd33v_tab     = lt_dd33v
      EXCEPTIONS
        illegal_input = 1
        OTHERS        = 2.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from DDIF_SHLP_GET' ).
    ENDIF.
    IF ls_dd30v IS INITIAL.
      RETURN. " does not exist in system
    ENDIF.

    CLEAR: ls_dd30v-as4user,
           ls_dd30v-as4date,
           ls_dd30v-as4time.

    io_xml->add( iv_name = 'DD30V'
                 ig_data = ls_dd30v ).
    io_xml->add( ig_data = lt_dd31v
                 iv_name = 'DD31V_TABLE' ).
    io_xml->add( ig_data = lt_dd32p
                 iv_name = 'DD32P_TABLE' ).
    io_xml->add( ig_data = lt_dd33v
                 iv_name = 'DD33V_TABLE' ).

  ENDMETHOD.                    "serialize

  METHOD lif_object~deserialize.

    DATA: lv_name  TYPE ddobjname,
          ls_dd30v TYPE dd30v,
          lt_dd31v TYPE TABLE OF dd31v,
          lt_dd32p TYPE TABLE OF dd32p,
          lt_dd33v TYPE TABLE OF dd33v.

    io_xml->read( EXPORTING iv_name = 'DD30V'
                  CHANGING cg_data = ls_dd30v ).
    io_xml->read( EXPORTING iv_name = 'DD31V_TABLE'
                  CHANGING cg_data = lt_dd31v ).
    io_xml->read( EXPORTING iv_name = 'DD32P_TABLE'
                  CHANGING cg_data = lt_dd32p ).
    io_xml->read( EXPORTING iv_name = 'DD33V_TABLE'
                  CHANGING cg_data = lt_dd33v ).

    corr_insert( iv_package ).

    lv_name = ms_item-obj_name.

    CALL FUNCTION 'DDIF_SHLP_PUT'
      EXPORTING
        name              = lv_name
        dd30v_wa          = ls_dd30v
      TABLES
        dd31v_tab         = lt_dd31v
        dd32p_tab         = lt_dd32p
        dd33v_tab         = lt_dd33v
      EXCEPTIONS
        shlp_not_found    = 1
        name_inconsistent = 2
        shlp_inconsistent = 3
        put_failure       = 4
        put_refused       = 5
        OTHERS            = 6.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from DDIF_SHLP_PUT' ).
    ENDIF.

    lcl_objects_activation=>add_item( ms_item ).

  ENDMETHOD.                    "deserialize

ENDCLASS.                    "lcl_object_shlp IMPLEMENTATION

*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_OBJECT_SHLP
*&---------------------------------------------------------------------*

*----------------------------------------------------------------------*
*       CLASS lcl_object_shlp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_object_shlp DEFINITION INHERITING FROM lcl_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES lif_object.
    ALIASES mo_files FOR lif_object~mo_files.

ENDCLASS.                    "lcl_object_dtel DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_object_dtel IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_object_shlp IMPLEMENTATION.

  METHOD lif_object~has_changed_since.

    DATA: lv_date TYPE dats,
          lv_time TYPE tims,
          lv_ts   TYPE timestamp.

    SELECT SINGLE as4date as4time FROM dd30l
      INTO (lv_date, lv_time)
      WHERE shlpname = ms_item-obj_name
      AND as4local = 'A'.

    _object_check_timestamp lv_date lv_time.

  ENDMETHOD.  "lif_object~has_changed_since

  METHOD lif_object~changed_by.

    SELECT SINGLE as4user FROM dd30l INTO rv_user
      WHERE shlpname = ms_item-obj_name
      AND as4local = 'A'.                               "#EC CI_GENBUFF
    IF sy-subrc <> 0.
      rv_user = c_user_unknown.
    ENDIF.

  ENDMETHOD.

  METHOD lif_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.                    "lif_object~get_metadata

  METHOD lif_object~exists.

    DATA: lv_shlpname TYPE dd30l-shlpname.

    SELECT SINGLE shlpname FROM dd30l INTO lv_shlpname
      WHERE shlpname = ms_item-obj_name
      AND as4local = 'A'.                               "#EC CI_GENBUFF
    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.                    "lif_object~exists

  METHOD lif_object~jump.

    jump_se11( iv_radio = 'RSRD1-SHMA'
               iv_field = 'RSRD1-SHMA_VAL' ).

  ENDMETHOD.                    "jump

  METHOD lif_object~delete.

    DATA: lv_objname TYPE rsedd0-ddobjname.

    lv_objname = ms_item-obj_name.

    CALL FUNCTION 'RS_DD_DELETE_OBJ'
      EXPORTING
        no_ask               = abap_true
        objname              = lv_objname
        objtype              = 'H'
      EXCEPTIONS
        not_executed         = 1
        object_not_found     = 2
        object_not_specified = 3
        permission_failure   = 4.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from RS_DD_DELETE_OBJ, SHLP' ).
    ENDIF.

  ENDMETHOD.                    "delete

  METHOD lif_object~serialize.

    DATA: lv_name  TYPE ddobjname,
          ls_dd30v TYPE dd30v,
          lt_dd31v TYPE TABLE OF dd31v,
          lt_dd32p TYPE TABLE OF dd32p,
          lt_dd33v TYPE TABLE OF dd33v.

    FIELD-SYMBOLS: <ls_dd32p> LIKE LINE OF lt_dd32p.

    lv_name = ms_item-obj_name.

    CALL FUNCTION 'DDIF_SHLP_GET'
      EXPORTING
        name          = lv_name
        state         = 'A'
        langu         = mv_language
      IMPORTING
        dd30v_wa      = ls_dd30v
      TABLES
        dd31v_tab     = lt_dd31v
        dd32p_tab     = lt_dd32p
        dd33v_tab     = lt_dd33v
      EXCEPTIONS
        illegal_input = 1
        OTHERS        = 2.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from DDIF_SHLP_GET' ).
    ENDIF.
    IF ls_dd30v IS INITIAL.
      RETURN. " does not exist in system
    ENDIF.

    CLEAR: ls_dd30v-as4user,
           ls_dd30v-as4date,
           ls_dd30v-as4time.

    LOOP AT lt_dd32p ASSIGNING <ls_dd32p>.
* clear information inherited from domain
      CLEAR: <ls_dd32p>-domname,
        <ls_dd32p>-headlen,
        <ls_dd32p>-scrlen1,
        <ls_dd32p>-scrlen2,
        <ls_dd32p>-datatype,
        <ls_dd32p>-leng,
        <ls_dd32p>-outputlen,
        <ls_dd32p>-decimals,
        <ls_dd32p>-lowercase,
        <ls_dd32p>-signflag,
        <ls_dd32p>-convexit.
    ENDLOOP.

    io_xml->add( iv_name = 'DD30V'
                 ig_data = ls_dd30v ).
    io_xml->add( ig_data = lt_dd31v
                 iv_name = 'DD31V_TABLE' ).
    io_xml->add( ig_data = lt_dd32p
                 iv_name = 'DD32P_TABLE' ).
    io_xml->add( ig_data = lt_dd33v
                 iv_name = 'DD33V_TABLE' ).

  ENDMETHOD.                    "serialize

  METHOD lif_object~deserialize.

    DATA: lv_name  TYPE ddobjname,
          ls_dd30v TYPE dd30v,
          lt_dd31v TYPE TABLE OF dd31v,
          lt_dd32p TYPE TABLE OF dd32p,
          lt_dd33v TYPE TABLE OF dd33v.

    io_xml->read( EXPORTING iv_name = 'DD30V'
                  CHANGING cg_data = ls_dd30v ).
    io_xml->read( EXPORTING iv_name = 'DD31V_TABLE'
                  CHANGING cg_data = lt_dd31v ).
    io_xml->read( EXPORTING iv_name = 'DD32P_TABLE'
                  CHANGING cg_data = lt_dd32p ).
    io_xml->read( EXPORTING iv_name = 'DD33V_TABLE'
                  CHANGING cg_data = lt_dd33v ).

    corr_insert( iv_package ).

    lv_name = ms_item-obj_name.

    CALL FUNCTION 'DDIF_SHLP_PUT'
      EXPORTING
        name              = lv_name
        dd30v_wa          = ls_dd30v
      TABLES
        dd31v_tab         = lt_dd31v
        dd32p_tab         = lt_dd32p
        dd33v_tab         = lt_dd33v
      EXCEPTIONS
        shlp_not_found    = 1
        name_inconsistent = 2
        shlp_inconsistent = 3
        put_failure       = 4
        put_refused       = 5
        OTHERS            = 6.
    IF sy-subrc <> 0.
      lcx_exception=>raise( 'error from DDIF_SHLP_PUT' ).
    ENDIF.

    lcl_objects_activation=>add_item( ms_item ).

  ENDMETHOD.                    "deserialize

ENDCLASS.                    "lcl_object_shlp IMPLEMENTATION

clear info inherited from domain

SHLP: clear info inherited from domain