CLASS zcl_abapgit_object_type DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

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

  PROTECTED SECTION.
  PRIVATE SECTION.
    CONSTANTS: c_prefix TYPE c LENGTH 3 VALUE '%_C'.

    METHODS read
      EXPORTING ev_ddtext TYPE ddtypet-ddtext
                et_source TYPE abaptxt255_tab
      RAISING   zcx_abapgit_exception.

    METHODS create
      IMPORTING iv_ddtext   TYPE ddtypet-ddtext
                it_source   TYPE abaptxt255_tab
                iv_devclass TYPE devclass
      RAISING   zcx_abapgit_exception.

ENDCLASS.

CLASS zcl_abapgit_object_type IMPLEMENTATION.

  METHOD create.

    DATA: lv_progname  TYPE reposrc-progname,
          lv_typegroup TYPE rsedd0-typegroup.

    lv_typegroup = ms_item-obj_name.

    CALL FUNCTION 'RS_DD_TYGR_INSERT_SOURCES'
      EXPORTING
        typegroupname        = lv_typegroup
        ddtext               = iv_ddtext
        corrnum              = ''
        devclass             = iv_devclass
      TABLES
        source               = it_source
      EXCEPTIONS
        already_exists       = 1
        not_executed         = 2
        permission_failure   = 3
        object_not_specified = 4
        illegal_name         = 5
        OTHERS               = 6.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

    CONCATENATE c_prefix lv_typegroup INTO lv_progname.
    UPDATE progdir SET uccheck = abap_true
      WHERE name = lv_progname.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error setting uccheck' ).
    ENDIF.

  ENDMETHOD.

  METHOD read.

    DATA: lv_typdname  TYPE rsedd0-typegroup,
          lt_psmodisrc TYPE TABLE OF smodisrc,
          lt_psmodilog TYPE TABLE OF smodilog,
          lt_ptrdir    TYPE TABLE OF trdir.

    SELECT SINGLE ddtext FROM ddtypet
      INTO ev_ddtext
      WHERE typegroup  = ms_item-obj_name
        AND ddlanguage = mv_language.

    lv_typdname = ms_item-obj_name.

    " Active version
    CALL FUNCTION 'TYPD_GET_OBJECT'
      EXPORTING
        typdname          = lv_typdname
      TABLES
        psmodisrc         = lt_psmodisrc
        psmodilog         = lt_psmodilog
        psource           = et_source
        ptrdir            = lt_ptrdir
      EXCEPTIONS
        version_not_found = 1
        reps_not_exist    = 2
        OTHERS            = 3.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |No active version found for { ms_item-obj_type } { ms_item-obj_name }| ).
    ENDIF.

  ENDMETHOD.

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

  METHOD zif_abapgit_object~delete.

    IF zif_abapgit_object~exists( ) = abap_false.
      RETURN.
    ENDIF.

    delete_ddic( 'G' ).

  ENDMETHOD.

  METHOD zif_abapgit_object~deserialize.

    DATA: lv_ddtext    TYPE ddtypet-ddtext,
          lt_source    TYPE abaptxt255_tab,
          lv_progname  TYPE reposrc-progname,
          lv_typegroup TYPE rsedd0-typegroup.

    lv_typegroup = ms_item-obj_name.

    io_xml->read( EXPORTING iv_name = 'DDTEXT'
                  CHANGING cg_data = lv_ddtext ).

    lt_source = mo_files->read_abap( ).

    IF zif_abapgit_object~exists( ) = abap_false.
      create( iv_ddtext   = lv_ddtext
              it_source   = lt_source
              iv_devclass = iv_package ).
    ELSE.
      CONCATENATE c_prefix lv_typegroup INTO lv_progname.
      INSERT REPORT lv_progname FROM lt_source STATE 'I'.
    ENDIF.

    zcl_abapgit_objects_activation=>add_item( ms_item ).

  ENDMETHOD.

  METHOD zif_abapgit_object~exists.

    DATA: lv_progname TYPE progname,
          lv_state    TYPE r3state.

    lv_progname = |%_C{ ms_item-obj_name }|.
    SELECT SINGLE state
      FROM progdir
      INTO lv_state
      WHERE name = lv_progname.
    IF lv_state IS NOT INITIAL.
      rv_bool = abap_true.
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_object~get_comparator.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_object~get_deserialize_steps.
    APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps.
  ENDMETHOD.

  METHOD zif_abapgit_object~get_metadata.
    rs_metadata = get_metadata( ).
  ENDMETHOD.

  METHOD zif_abapgit_object~is_active.
    rv_active = is_active( ).
  ENDMETHOD.

  METHOD zif_abapgit_object~is_locked.
    rv_is_locked = abap_false.
  ENDMETHOD.

  METHOD zif_abapgit_object~jump.
    " Covered by ZCL_ABAPGIT_OBJECT=>JUMP
  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA: lv_ddtext TYPE ddtypet-ddtext,
          lt_source TYPE abaptxt255_tab.

    read( IMPORTING ev_ddtext = lv_ddtext
                    et_source = lt_source ).

    io_xml->add( iv_name = 'DDTEXT'
                 ig_data = lv_ddtext ).

    mo_files->add_abap( lt_source ).

  ENDMETHOD.
ENDCLASS.


CLASS zcl_abapgit_popups DEFINITION
  PUBLIC
  FINAL
  CREATE PRIVATE
  GLOBAL FRIENDS zcl_abapgit_ui_factory .

  PUBLIC SECTION.

    INTERFACES zif_abapgit_popups .

  PROTECTED SECTION.
  PRIVATE SECTION.
    CONSTANTS c_default_column TYPE abap_componentdescr-name VALUE `DEFAULT_COLUMN` ##NO_TEXT.

    TYPES:
      ty_lt_fields TYPE STANDARD TABLE OF sval WITH DEFAULT KEY .

    CONSTANTS c_fieldname_selected TYPE abap_componentdescr-name VALUE `SELECTED` ##NO_TEXT.
    CONSTANTS c_answer_cancel      TYPE c LENGTH 1 VALUE 'A' ##NO_TEXT.

    DATA mo_select_list_popup TYPE REF TO cl_salv_table .
    DATA mr_table TYPE REF TO data .
    DATA mv_cancel TYPE abap_bool VALUE abap_false.
    DATA mo_table_descr TYPE REF TO cl_abap_tabledescr .

    METHODS add_field
      IMPORTING
        !iv_tabname    TYPE sval-tabname
        !iv_fieldname  TYPE sval-fieldname
        !iv_fieldtext  TYPE sval-fieldtext
        !iv_value      TYPE clike DEFAULT ''
        !iv_field_attr TYPE sval-field_attr DEFAULT ''
        !iv_obligatory TYPE spo_obl OPTIONAL
      CHANGING
        !ct_fields     TYPE zif_abapgit_popups=>ty_sval_tt .
    METHODS create_new_table
      IMPORTING
        !it_list TYPE STANDARD TABLE .
    METHODS get_selected_rows
      EXPORTING
        !et_list TYPE INDEX TABLE .
    METHODS on_select_list_link_click
        FOR EVENT link_click OF cl_salv_events_table
      IMPORTING
        !row
        !column .
    METHODS on_select_list_function_click
        FOR EVENT added_function OF cl_salv_events_table
      IMPORTING
        !e_salv_function .
    METHODS on_double_click
        FOR EVENT double_click OF cl_salv_events_table
      IMPORTING
        !row
        !column .
    METHODS _popup_3_get_values
      IMPORTING
        !iv_popup_title    TYPE string
        !iv_no_value_check TYPE abap_bool DEFAULT abap_false
      EXPORTING
        !ev_value_1        TYPE spo_value
        !ev_value_2        TYPE spo_value
        !ev_value_3        TYPE spo_value
      CHANGING
        !ct_fields         TYPE ty_lt_fields
      RAISING
        zcx_abapgit_exception .
ENDCLASS.

CLASS zcl_abapgit_popups IMPLEMENTATION.

  METHOD add_field.

    FIELD-SYMBOLS: <ls_field> LIKE LINE OF ct_fields.

    APPEND INITIAL LINE TO ct_fields ASSIGNING <ls_field>.
    <ls_field>-tabname    = iv_tabname.
    <ls_field>-fieldname  = iv_fieldname.
    <ls_field>-fieldtext  = iv_fieldtext.
    <ls_field>-value      = iv_value.
    <ls_field>-field_attr = iv_field_attr.
    <ls_field>-field_obl  = iv_obligatory.

  ENDMETHOD.

  METHOD create_new_table.

    " create and populate a table on the fly derived from
    " it_data with a select column

    DATA: lr_struct        TYPE REF TO data,
          lt_components    TYPE cl_abap_structdescr=>component_table,
          lo_data_descr    TYPE REF TO cl_abap_datadescr,
          lo_elem_descr    TYPE REF TO cl_abap_elemdescr,
          lo_struct_descr  TYPE REF TO cl_abap_structdescr,
          lo_struct_descr2 TYPE REF TO cl_abap_structdescr.

    FIELD-SYMBOLS: <lt_table>     TYPE STANDARD TABLE,
                   <ls_component> TYPE abap_componentdescr,
                   <lg_line>      TYPE data,
                   <lg_data>      TYPE any,
                   <lg_value>     TYPE any.

    mo_table_descr ?= cl_abap_tabledescr=>describe_by_data( it_list ).
    lo_data_descr = mo_table_descr->get_table_line_type( ).

    CASE lo_data_descr->kind.
      WHEN cl_abap_elemdescr=>kind_elem.
        lo_elem_descr ?= mo_table_descr->get_table_line_type( ).
        INSERT INITIAL LINE INTO lt_components ASSIGNING <ls_component> INDEX 1.
        <ls_component>-name = c_default_column.
        <ls_component>-type = lo_elem_descr.

      WHEN cl_abap_elemdescr=>kind_struct.
        lo_struct_descr ?= mo_table_descr->get_table_line_type( ).
        lt_components = lo_struct_descr->get_components( ).

    ENDCASE.

    IF lt_components IS INITIAL.
      RETURN.
    ENDIF.

    INSERT INITIAL LINE INTO lt_components ASSIGNING <ls_component> INDEX 1.
    <ls_component>-name = c_fieldname_selected.
    <ls_component>-type ?= cl_abap_datadescr=>describe_by_name( 'FLAG' ).

    lo_struct_descr2 = cl_abap_structdescr=>create( lt_components ).
    mo_table_descr = cl_abap_tabledescr=>create( lo_struct_descr2 ).

    CREATE DATA mr_table TYPE HANDLE mo_table_descr.
    ASSIGN mr_table->* TO <lt_table>.
    ASSERT sy-subrc = 0.

    CREATE DATA lr_struct TYPE HANDLE lo_struct_descr2.
    ASSIGN lr_struct->* TO <lg_line>.
    ASSERT sy-subrc = 0.

    LOOP AT it_list ASSIGNING <lg_data>.
      CLEAR <lg_line>.
      CASE lo_data_descr->kind.
        WHEN cl_abap_elemdescr=>kind_elem.
          ASSIGN COMPONENT c_default_column OF STRUCTURE <lg_data> TO <lg_value>.
          ASSERT <lg_value> IS ASSIGNED.
          <lg_line> = <lg_value>.

        WHEN OTHERS.
          MOVE-CORRESPONDING <lg_data> TO <lg_line>.

      ENDCASE.
      INSERT <lg_line> INTO TABLE <lt_table>.
    ENDLOOP.

  ENDMETHOD.

  METHOD get_selected_rows.

    DATA: lv_condition TYPE string,
          lr_exporting TYPE REF TO data.

    FIELD-SYMBOLS: <lg_exporting>    TYPE any,
                   <lt_table>        TYPE STANDARD TABLE,
                   <lg_line>         TYPE any,
                   <lg_value>        TYPE any,
                   <lv_selected>     TYPE abap_bool,
                   <lv_selected_row> TYPE LINE OF salv_t_row.

    DATA: lo_data_descr    TYPE REF TO cl_abap_datadescr,
          lo_selections    TYPE REF TO cl_salv_selections,
          lt_selected_rows TYPE salv_t_row.

    ASSIGN mr_table->* TO <lt_table>.
    ASSERT sy-subrc = 0.

    lo_selections = mo_select_list_popup->get_selections( ).

    IF lo_selections->get_selection_mode( ) = if_salv_c_selection_mode=>single.

      lt_selected_rows = lo_selections->get_selected_rows( ).

      LOOP AT lt_selected_rows ASSIGNING <lv_selected_row>.

        READ TABLE <lt_table>
          ASSIGNING <lg_line>
          INDEX <lv_selected_row>.
        CHECK <lg_line> IS ASSIGNED.

        ASSIGN COMPONENT c_fieldname_selected
           OF STRUCTURE <lg_line>
           TO <lv_selected>.
        CHECK <lv_selected> IS ASSIGNED.

        <lv_selected> = abap_true.

      ENDLOOP.

    ENDIF.

    lv_condition = |{ c_fieldname_selected } = ABAP_TRUE|.

    CREATE DATA lr_exporting LIKE LINE OF et_list.
    ASSIGN lr_exporting->* TO <lg_exporting>.

    mo_table_descr ?= cl_abap_tabledescr=>describe_by_data( et_list ).
    lo_data_descr = mo_table_descr->get_table_line_type( ).

    LOOP AT <lt_table> ASSIGNING <lg_line> WHERE (lv_condition).
      CLEAR <lg_exporting>.

      CASE lo_data_descr->kind.
        WHEN cl_abap_elemdescr=>kind_elem.
          ASSIGN COMPONENT c_default_column OF STRUCTURE <lg_line> TO <lg_value>.
          ASSERT <lg_value> IS ASSIGNED.
          <lg_exporting> = <lg_value>.

        WHEN OTHERS.
          MOVE-CORRESPONDING <lg_line> TO <lg_exporting>.

      ENDCASE.
      APPEND <lg_exporting> TO et_list.
    ENDLOOP.

  ENDMETHOD.

  METHOD on_double_click.

    DATA: lo_selections    TYPE REF TO cl_salv_selections.

    lo_selections = mo_select_list_popup->get_selections( ).

    IF lo_selections->get_selection_mode( ) = if_salv_c_selection_mode=>single.
      mo_select_list_popup->close_screen( ).
    ENDIF.

  ENDMETHOD.

  METHOD on_select_list_function_click.

    FIELD-SYMBOLS: <lt_table>    TYPE STANDARD TABLE,
                   <lg_line>     TYPE any,
                   <lv_selected> TYPE abap_bool.

    ASSIGN mr_table->* TO <lt_table>.
    ASSERT sy-subrc = 0.

    CASE e_salv_function.
      WHEN 'O.K.'.
        mv_cancel = abap_false.
        mo_select_list_popup->close_screen( ).

      WHEN 'ABR'.
        "Canceled: clear list to overwrite nothing
        CLEAR <lt_table>.
        mv_cancel = abap_true.
        mo_select_list_popup->close_screen( ).

      WHEN 'SALL'.
        LOOP AT <lt_table> ASSIGNING <lg_line>.

          ASSIGN COMPONENT c_fieldname_selected
                 OF STRUCTURE <lg_line>
                 TO <lv_selected>.
          ASSERT sy-subrc = 0.

          <lv_selected> = abap_true.

        ENDLOOP.

        mo_select_list_popup->refresh( ).

      WHEN 'DSEL'.
        LOOP AT <lt_table> ASSIGNING <lg_line>.

          ASSIGN COMPONENT c_fieldname_selected
                 OF STRUCTURE <lg_line>
                 TO <lv_selected>.
          ASSERT sy-subrc = 0.

          <lv_selected> = abap_false.

        ENDLOOP.

        mo_select_list_popup->refresh( ).

      WHEN OTHERS.
        CLEAR <lt_table>.
        mo_select_list_popup->close_screen( ).
    ENDCASE.

  ENDMETHOD.

  METHOD on_select_list_link_click.

    FIELD-SYMBOLS: <lt_table>    TYPE STANDARD TABLE,
                   <lg_line>     TYPE any,
                   <lv_selected> TYPE abap_bool.

    ASSIGN mr_table->* TO <lt_table>.
    ASSERT sy-subrc = 0.

    READ TABLE <lt_table> ASSIGNING <lg_line> INDEX row.
    IF sy-subrc = 0.

      ASSIGN COMPONENT c_fieldname_selected
             OF STRUCTURE <lg_line>
             TO <lv_selected>.
      ASSERT sy-subrc = 0.

      IF <lv_selected> = abap_true.
        <lv_selected> = abap_false.
      ELSE.
        <lv_selected> = abap_true.
      ENDIF.

    ENDIF.

    mo_select_list_popup->refresh( ).

  ENDMETHOD.

  METHOD zif_abapgit_popups~branch_list_popup.

    DATA: lo_branches    TYPE REF TO zcl_abapgit_git_branch_list,
          lt_branches    TYPE zif_abapgit_definitions=>ty_git_branch_list_tt,
          lv_answer      TYPE c LENGTH 1,
          lv_default     TYPE i,
          lv_head_suffix TYPE string,
          lv_head_symref TYPE string,
          lv_text        TYPE string,
          lt_selection   TYPE TABLE OF spopli.

    FIELD-SYMBOLS: <ls_sel>    LIKE LINE OF lt_selection,
                   <ls_branch> LIKE LINE OF lt_branches.

    lo_branches    = zcl_abapgit_git_transport=>branches( iv_url ).
    lt_branches    = lo_branches->get_branches_only( ).
    lv_head_suffix = | ({ zif_abapgit_definitions=>c_head_name })|.
    lv_head_symref = lo_branches->get_head_symref( ).

    IF iv_hide_branch IS NOT INITIAL.
      DELETE lt_branches WHERE name = iv_hide_branch.
    ENDIF.

    IF iv_hide_head IS NOT INITIAL.
      DELETE lt_branches WHERE name    = zif_abapgit_definitions=>c_head_name
                            OR is_head = abap_true.
    ENDIF.

    IF lt_branches IS INITIAL.
      IF iv_hide_head IS NOT INITIAL.
        lv_text = 'main'.
      ENDIF.
      IF iv_hide_branch IS NOT INITIAL AND iv_hide_branch <> zif_abapgit_definitions=>c_git_branch-main.
        IF lv_text IS INITIAL.
          lv_text = iv_hide_branch && ' is'.
        ELSE.
          CONCATENATE lv_text 'and' iv_hide_branch 'are' INTO lv_text SEPARATED BY space.
        ENDIF.
      ELSE.
        lv_text = lv_text && ' is'.
      ENDIF.
      IF lv_text IS NOT INITIAL.
        zcx_abapgit_exception=>raise( 'No branches available to select (' && lv_text && ' hidden)' ).
      ELSE.
        zcx_abapgit_exception=>raise( 'No branches are available to select' ).
      ENDIF.
    ENDIF.

    LOOP AT lt_branches ASSIGNING <ls_branch>.

      CHECK <ls_branch>-name IS NOT INITIAL. " To ensure some below ifs

      IF <ls_branch>-is_head = abap_true.

        IF <ls_branch>-name = zif_abapgit_definitions=>c_head_name. " HEAD
          IF <ls_branch>-name <> lv_head_symref AND lv_head_symref IS NOT INITIAL.
            " HEAD but other HEAD symref exists - ignore
            CONTINUE.
          ELSE.
            INSERT INITIAL LINE INTO lt_selection INDEX 1 ASSIGNING <ls_sel>.
            <ls_sel>-varoption = <ls_branch>-name.
          ENDIF.
        ELSE.
          INSERT INITIAL LINE INTO lt_selection INDEX 1 ASSIGNING <ls_sel>.
          <ls_sel>-varoption = <ls_branch>-display_name && lv_head_suffix.
        ENDIF.

        IF lv_default > 0. " Shift down default if set
          lv_default = lv_default + 1.
        ENDIF.
      ELSE.
        APPEND INITIAL LINE TO lt_selection ASSIGNING <ls_sel>.
        <ls_sel>-varoption = <ls_branch>-display_name.
      ENDIF.

      IF <ls_branch>-name = iv_default_branch.
        IF <ls_branch>-is_head = abap_true.
          lv_default = 1.
        ELSE.
          lv_default = sy-tabix.
        ENDIF.
      ENDIF.

    ENDLOOP.

    IF iv_show_new_option = abap_true.
      APPEND INITIAL LINE TO lt_selection ASSIGNING <ls_sel>.
      <ls_sel>-varoption = zif_abapgit_popups=>c_new_branch_label.
    ENDIF.

    CALL FUNCTION 'POPUP_TO_DECIDE_LIST'
      EXPORTING
        textline1  = 'Select branch'
        titel      = 'Select branch'
        start_col  = 30
        start_row  = 5
        cursorline = lv_default
      IMPORTING
        answer     = lv_answer
      TABLES
        t_spopli   = lt_selection
      EXCEPTIONS
        OTHERS     = 1.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'Error from POPUP_TO_DECIDE_LIST' ).
    ENDIF.

    IF lv_answer = c_answer_cancel.
      RETURN.
    ENDIF.

    READ TABLE lt_selection ASSIGNING <ls_sel> WITH KEY selflag = abap_true.
    ASSERT sy-subrc = 0.

    IF iv_show_new_option = abap_true AND <ls_sel>-varoption = zif_abapgit_popups=>c_new_branch_label.
      rs_branch-name = zif_abapgit_popups=>c_new_branch_label.
    ELSE.
      REPLACE FIRST OCCURRENCE OF lv_head_suffix IN <ls_sel>-varoption WITH ''.
      READ TABLE lt_branches WITH KEY display_name = <ls_sel>-varoption ASSIGNING <ls_branch>.
      IF sy-subrc <> 0.
* branch name longer than 65 characters
        LOOP AT lt_branches ASSIGNING <ls_branch> WHERE display_name CS <ls_sel>-varoption.
          EXIT. " current loop
        ENDLOOP.
      ENDIF.
      ASSERT <ls_branch> IS ASSIGNED.
      rs_branch = lo_branches->find_by_name( <ls_branch>-name ).
      lv_text = |Branch switched from { zcl_abapgit_git_branch_list=>get_display_name( iv_default_branch ) } to {
        zcl_abapgit_git_branch_list=>get_display_name( rs_branch-name ) } |.
      MESSAGE lv_text TYPE 'S'.
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_popups~branch_popup_callback.

    DATA: lv_url          TYPE string,
          ls_package_data TYPE scompkdtln,
          ls_branch       TYPE zif_abapgit_definitions=>ty_git_branch,
          lv_create       TYPE abap_bool,
          lv_text         TYPE string.

    FIELD-SYMBOLS: <ls_furl>     LIKE LINE OF ct_fields,
                   <ls_fbranch>  LIKE LINE OF ct_fields,
                   <ls_fpackage> LIKE LINE OF ct_fields.

    CLEAR cs_error.

    IF iv_code = 'COD1'.
      cv_show_popup = abap_true.

      READ TABLE ct_fields ASSIGNING <ls_furl> WITH KEY tabname = 'ABAPTXT255'.
      IF sy-subrc <> 0 OR <ls_furl>-value IS INITIAL.
        MESSAGE 'Fill URL' TYPE 'S' DISPLAY LIKE 'E'.
        RETURN.
      ENDIF.
      lv_url = <ls_furl>-value.

      ls_branch = zif_abapgit_popups~branch_list_popup( lv_url ).
      IF ls_branch IS INITIAL.
        RETURN.
      ENDIF.

      READ TABLE ct_fields ASSIGNING <ls_fbranch> WITH KEY tabname = 'TEXTL'.
      ASSERT sy-subrc = 0.
      <ls_fbranch>-value = ls_branch-name.

    ELSEIF iv_code = 'COD2'.
      cv_show_popup = abap_true.

      READ TABLE ct_fields ASSIGNING <ls_fpackage> WITH KEY fieldname = 'DEVCLASS'.
      ASSERT sy-subrc = 0.
      ls_package_data-devclass = <ls_fpackage>-value.

      IF zcl_abapgit_factory=>get_sap_package( ls_package_data-devclass )->exists( ) = abap_true.
        lv_text = |Package { ls_package_data-devclass } already exists|.
        MESSAGE lv_text TYPE 'I' DISPLAY LIKE 'E'.
        RETURN.
      ENDIF.

      zif_abapgit_popups~popup_to_create_package(
        IMPORTING
          es_package_data = ls_package_data
          ev_create       = lv_create ).
      IF lv_create = abap_false.
        RETURN.
      ENDIF.

      zcl_abapgit_factory=>get_sap_package( ls_package_data-devclass )->create( ls_package_data ).
      COMMIT WORK.

      <ls_fpackage>-value = ls_package_data-devclass.
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_popups~choose_pr_popup.

    DATA lv_answer    TYPE c LENGTH 1.
    DATA lt_selection TYPE TABLE OF spopli.
    FIELD-SYMBOLS <ls_sel>  LIKE LINE OF lt_selection.
    FIELD-SYMBOLS <ls_pull> LIKE LINE OF it_pulls.

    IF lines( it_pulls ) = 0.
      zcx_abapgit_exception=>raise( 'No pull requests to select from' ).
    ENDIF.

    LOOP AT it_pulls ASSIGNING <ls_pull>.
      APPEND INITIAL LINE TO lt_selection ASSIGNING <ls_sel>.
      <ls_sel>-varoption = |{ <ls_pull>-number } - { <ls_pull>-title } @{ <ls_pull>-user }|.
    ENDLOOP.

    CALL FUNCTION 'POPUP_TO_DECIDE_LIST'
      EXPORTING
        textline1 = 'Select pull request'
        titel     = 'Select pull request'
        start_col = 30
        start_row = 5
      IMPORTING
        answer    = lv_answer
      TABLES
        t_spopli  = lt_selection
      EXCEPTIONS
        OTHERS    = 1.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'Error from POPUP_TO_DECIDE_LIST' ).
    ENDIF.

    IF lv_answer = c_answer_cancel.
      RETURN.
    ENDIF.

    READ TABLE lt_selection ASSIGNING <ls_sel> WITH KEY selflag = abap_true.
    ASSERT sy-subrc = 0.

    READ TABLE it_pulls INTO rs_pull INDEX sy-tabix.
    ASSERT sy-subrc = 0.

  ENDMETHOD.

  METHOD zif_abapgit_popups~create_branch_popup.

    DATA: lt_fields TYPE TABLE OF sval.
    DATA: lv_name   TYPE spo_value.

    CLEAR: ev_name, ev_cancel.

    add_field( EXPORTING iv_tabname   = 'TEXTL'
                         iv_fieldname = 'LINE'
                         iv_fieldtext = 'Name'
                         iv_value     = 'new-branch-name'
               CHANGING  ct_fields    = lt_fields ).

    TRY.

        _popup_3_get_values(
          EXPORTING iv_popup_title = |Create branch from {
            zcl_abapgit_git_branch_list=>get_display_name( iv_source_branch_name ) }|
          IMPORTING ev_value_1     = lv_name
          CHANGING  ct_fields      = lt_fields ).

        ev_name = zcl_abapgit_git_branch_list=>complete_heads_branch_name(
              zcl_abapgit_git_branch_list=>normalize_branch_name( lv_name ) ).

      CATCH zcx_abapgit_cancel.
        ev_cancel = abap_true.
    ENDTRY.

  ENDMETHOD.

  METHOD zif_abapgit_popups~popup_folder_logic.

    DATA: lt_fields       TYPE TABLE OF sval.
    DATA: lv_folder_logic TYPE spo_value.

    CLEAR: rv_folder_logic.

    add_field( EXPORTING iv_tabname   = 'TDEVC'
                         iv_fieldname = 'INTSYS'
                         iv_fieldtext = 'Folder logic'
                         iv_value     = 'PREFIX'
               CHANGING  ct_fields    = lt_fields ).

    TRY.

        _popup_3_get_values( EXPORTING iv_popup_title    = 'Export package'
                                       iv_no_value_check = abap_true
                             IMPORTING ev_value_1        = lv_folder_logic
                             CHANGING  ct_fields         = lt_fields ).

        rv_folder_logic = to_upper( lv_folder_logic ).

      CATCH zcx_abapgit_cancel.
    ENDTRY.

  ENDMETHOD.

  METHOD zif_abapgit_popups~popup_search_help.

    DATA lt_ret TYPE TABLE OF ddshretval.
    DATA ls_ret LIKE LINE OF lt_ret.
    DATA lv_tabname TYPE dfies-tabname.
    DATA lv_fieldname TYPE dfies-fieldname.

    SPLIT iv_tab_field AT '-' INTO lv_tabname lv_fieldname.
    lv_tabname = to_upper( lv_tabname ).
    lv_fieldname = to_upper( lv_fieldname ).

    CALL FUNCTION 'F4IF_FIELD_VALUE_REQUEST'
      EXPORTING
        tabname    = lv_tabname
        fieldname  = lv_fieldname
      TABLES
        return_tab = lt_ret
      EXCEPTIONS
        OTHERS     = 5.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( |F4IF_FIELD_VALUE_REQUEST error [{ iv_tab_field }]| ).
    ENDIF.

    IF lines( lt_ret ) > 0.
      READ TABLE lt_ret WITH KEY fieldname = lv_fieldname INTO ls_ret.
      IF sy-subrc = 0.
        rv_value = ls_ret-fieldval.
      ELSE.
        READ TABLE lt_ret INDEX 1 INTO ls_ret.
        ASSERT sy-subrc = 0.
        rv_value = ls_ret-fieldval.
      ENDIF.
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_popups~popup_to_confirm.

    CALL FUNCTION 'POPUP_TO_CONFIRM'
      EXPORTING
        titlebar              = iv_titlebar
        text_question         = iv_text_question
        text_button_1         = iv_text_button_1
        icon_button_1         = iv_icon_button_1
        text_button_2         = iv_text_button_2
        icon_button_2         = iv_icon_button_2
        default_button        = iv_default_button
        display_cancel_button = iv_display_cancel_button
      IMPORTING
        answer                = rv_answer
      EXCEPTIONS
        text_not_found        = 1
        OTHERS                = 2.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'error from POPUP_TO_CONFIRM' ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_popups~popup_to_create_package.
    CALL FUNCTION 'FUNCTION_EXISTS'
      EXPORTING
        funcname           = 'PB_POPUP_PACKAGE_CREATE'
      EXCEPTIONS
        function_not_exist = 1
        OTHERS             = 2.
    IF sy-subrc = 1.
* looks like the function module used does not exist on all
* versions since 702, so show an error
      zcx_abapgit_exception=>raise( 'Your system does not support automatic creation of packages.' &&
        'Please, create the package manually.' ).
    ENDIF.

    CALL FUNCTION 'PB_POPUP_PACKAGE_CREATE'
      CHANGING
        p_object_data    = es_package_data
      EXCEPTIONS
        action_cancelled = 1.
    ev_create = boolc( sy-subrc = 0 ).
  ENDMETHOD.

  METHOD zif_abapgit_popups~popup_to_create_transp_branch.
    DATA: lt_fields             TYPE TABLE OF sval,
          lv_transports_as_text TYPE string,
          lv_desc_as_text       TYPE string,
          ls_transport_header   LIKE LINE OF it_transport_headers.
    DATA: lv_branch_name        TYPE spo_value.
    DATA: lv_commit_text        TYPE spo_value.

    CLEAR: rs_transport_branch-branch_name, rs_transport_branch-commit_text.

    " If we only have one transport selected set branch name to Transport
    " name and commit description to transport description.
    IF lines( it_transport_headers ) = 1.
      READ TABLE it_transport_headers INDEX 1 INTO ls_transport_header.
      lv_transports_as_text = ls_transport_header-trkorr.
      SELECT SINGLE as4text FROM e07t INTO lv_desc_as_text  WHERE
        trkorr = ls_transport_header-trkorr AND
        langu = sy-langu.
    ELSE.   " Else set branch name and commit message to 'Transport(s)_TRXXXXXX_TRXXXXX'
      lv_transports_as_text = 'Transport(s)'.
      LOOP AT it_transport_headers INTO ls_transport_header.
        CONCATENATE lv_transports_as_text '_' ls_transport_header-trkorr INTO lv_transports_as_text.
      ENDLOOP.
      lv_desc_as_text = lv_transports_as_text.

    ENDIF.
    add_field( EXPORTING iv_tabname   = 'TEXTL'
                         iv_fieldname = 'LINE'
                         iv_fieldtext = 'Branch name'
                         iv_value     = lv_transports_as_text
               CHANGING ct_fields     = lt_fields ).

    add_field( EXPORTING iv_tabname   = 'ABAPTXT255'
                         iv_fieldname = 'LINE'
                         iv_fieldtext = 'Commit text'
                         iv_value     = lv_desc_as_text
               CHANGING ct_fields     = lt_fields ).

    _popup_3_get_values( EXPORTING iv_popup_title    = 'Transport to new Branch'
                         IMPORTING ev_value_1        = lv_branch_name
                                   ev_value_2        = lv_commit_text
                         CHANGING  ct_fields         = lt_fields ).

    rs_transport_branch-branch_name = lv_branch_name.
    rs_transport_branch-commit_text = lv_commit_text.

  ENDMETHOD.

  METHOD zif_abapgit_popups~popup_to_select_from_list.

    DATA: lv_pfstatus     TYPE sypfkey,
          lo_events       TYPE REF TO cl_salv_events_table,
          lo_columns      TYPE REF TO cl_salv_columns_table,
          lt_columns      TYPE salv_t_column_ref,
          ls_column       TYPE salv_s_column_ref,
          lo_column       TYPE REF TO cl_salv_column_list,
          lo_table_header TYPE REF TO cl_salv_form_text.

    FIELD-SYMBOLS: <lt_table>             TYPE STANDARD TABLE,
                   <ls_column_to_display> TYPE zif_abapgit_definitions=>ty_alv_column.

    CLEAR: et_list.

    create_new_table( it_list ).

    ASSIGN mr_table->* TO <lt_table>.
    ASSERT sy-subrc = 0.

    TRY.
        cl_salv_table=>factory( IMPORTING r_salv_table = mo_select_list_popup
                                CHANGING  t_table = <lt_table> ).

        CASE iv_selection_mode.
          WHEN if_salv_c_selection_mode=>single.
            lv_pfstatus = '110'.

          WHEN OTHERS.
            lv_pfstatus = '102'.

        ENDCASE.

        mo_select_list_popup->set_screen_status( pfstatus = lv_pfstatus
                                                 report = 'SAPMSVIM' ).

        mo_select_list_popup->set_screen_popup( start_column = iv_start_column
                                                end_column   = iv_end_column
                                                start_line   = iv_start_line
                                                end_line     = iv_end_line ).

        lo_events = mo_select_list_popup->get_event( ).

        SET HANDLER on_select_list_link_click FOR lo_events.
        SET HANDLER on_select_list_function_click FOR lo_events.
        SET HANDLER on_double_click FOR lo_events.

        IF iv_title CN ' _0'.
          mo_select_list_popup->get_display_settings( )->set_list_header( iv_title ).
        ENDIF.

        IF iv_header_text CN ' _0'.
          CREATE OBJECT lo_table_header
            EXPORTING
              text = iv_header_text.
          mo_select_list_popup->set_top_of_list( lo_table_header ).
        ENDIF.

        mo_select_list_popup->get_display_settings( )->set_striped_pattern( iv_striped_pattern ).
        mo_select_list_popup->get_selections( )->set_selection_mode( iv_selection_mode ).

        lo_columns = mo_select_list_popup->get_columns( ).
        lt_columns = lo_columns->get( ).
        lo_columns->set_optimize( iv_optimize_col_width ).

        LOOP AT lt_columns INTO ls_column.

          lo_column ?= ls_column-r_column.

          IF    iv_selection_mode    = if_salv_c_selection_mode=>multiple
            AND ls_column-columnname = c_fieldname_selected.
            lo_column->set_cell_type( if_salv_c_cell_type=>checkbox_hotspot ).
            lo_column->set_output_length( 20 ).
            lo_column->set_short_text( |{ iv_select_column_text }| ).
            lo_column->set_medium_text( |{ iv_select_column_text }| ).
            lo_column->set_long_text( |{ iv_select_column_text }| ).
            CONTINUE.
          ENDIF.

          READ TABLE it_columns_to_display
            ASSIGNING <ls_column_to_display>
            WITH KEY name = ls_column-columnname.

          CASE sy-subrc.
            WHEN 0.
              IF <ls_column_to_display>-text CN ' _0'.
                lo_column->set_short_text( |{ <ls_column_to_display>-text }| ).
                lo_column->set_medium_text( |{ <ls_column_to_display>-text }| ).
                lo_column->set_long_text( |{ <ls_column_to_display>-text }| ).
              ENDIF.

              IF <ls_column_to_display>-length > 0.
                lo_column->set_output_length( <ls_column_to_display>-length ).
              ENDIF.

              IF <ls_column_to_display>-show_icon = abap_true.
                lo_column->set_icon( abap_true ).
              ENDIF.

            WHEN OTHERS.
              " Hide column
              lo_column->set_technical( abap_true ).

          ENDCASE.

        ENDLOOP.

        mo_select_list_popup->display( ).

      CATCH cx_salv_msg.
        zcx_abapgit_exception=>raise( 'Error from POPUP_TO_SELECT_FROM_LIST' ).
    ENDTRY.

    IF mv_cancel = abap_true.
      mv_cancel = abap_false.
      RAISE EXCEPTION TYPE zcx_abapgit_cancel.
    ENDIF.

    get_selected_rows( IMPORTING et_list = et_list ).

    CLEAR: mo_select_list_popup,
           mr_table,
           mo_table_descr.

  ENDMETHOD.

  METHOD zif_abapgit_popups~popup_to_select_transports.

* todo, method to be renamed, it only returns one transport

    DATA: lv_trkorr TYPE e070-trkorr,
          ls_trkorr LIKE LINE OF rt_trkorr.

    CALL FUNCTION 'TR_F4_REQUESTS'
      IMPORTING
        ev_selected_request = lv_trkorr.

    IF NOT lv_trkorr IS INITIAL.
      ls_trkorr-trkorr = lv_trkorr.
      APPEND ls_trkorr TO rt_trkorr.
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_popups~popup_transport_request.

    DATA: lt_e071  TYPE STANDARD TABLE OF e071,
          lt_e071k TYPE STANDARD TABLE OF e071k.

    CALL FUNCTION 'TRINT_ORDER_CHOICE'
      EXPORTING
        wi_order_type          = is_transport_type-request
        wi_task_type           = is_transport_type-task
      IMPORTING
        we_order               = rv_transport
      TABLES
        wt_e071                = lt_e071
        wt_e071k               = lt_e071k
      EXCEPTIONS
        no_correction_selected = 1
        display_mode           = 2
        object_append_error    = 3
        recursive_call         = 4
        wrong_order_type       = 5
        OTHERS                 = 6.

    IF sy-subrc = 1.
      RAISE EXCEPTION TYPE zcx_abapgit_cancel.
    ELSEIF sy-subrc > 1.
      zcx_abapgit_exception=>raise_t100( ).
    ENDIF.

  ENDMETHOD.

  METHOD _popup_3_get_values.

    DATA lv_answer TYPE c LENGTH 1.
    FIELD-SYMBOLS: <ls_field> TYPE sval.

    CALL FUNCTION 'POPUP_GET_VALUES'
      EXPORTING
        no_value_check = iv_no_value_check
        popup_title    = iv_popup_title
      IMPORTING
        returncode     = lv_answer
      TABLES
        fields         = ct_fields
      EXCEPTIONS
        OTHERS         = 1.
    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise( 'Error from POPUP_GET_VALUES' ).
    ENDIF.

    IF lv_answer = c_answer_cancel.
      RAISE EXCEPTION TYPE zcx_abapgit_cancel.
    ENDIF.

    IF ev_value_1 IS SUPPLIED.
      READ TABLE ct_fields INDEX 1 ASSIGNING <ls_field>.
      ASSERT sy-subrc = 0.
      ev_value_1 = <ls_field>-value.
    ENDIF.

    IF ev_value_2 IS SUPPLIED.
      READ TABLE ct_fields INDEX 2 ASSIGNING <ls_field>.
      ASSERT sy-subrc = 0.
      ev_value_2 = <ls_field>-value.
    ENDIF.

    IF ev_value_3 IS SUPPLIED.
      READ TABLE ct_fields INDEX 3 ASSIGNING <ls_field>.
      ASSERT sy-subrc = 0.
      ev_value_3 = <ls_field>-value.
    ENDIF.

  ENDMETHOD.
ENDCLASS.


*&---------------------------------------------------------------------*
*& Report  ZDEMO_EXCEL46
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zdemo_excel46.

CONSTANTS:
  gc_ws_title_validation TYPE zexcel_sheet_title VALUE 'Validation'.

DATA:
  lo_excel             TYPE REF TO zcl_excel,
  lo_worksheet         TYPE REF TO zcl_excel_worksheet,
  lo_range             TYPE REF TO zcl_excel_range,
  lv_validation_string TYPE string,
  lo_data_validation   TYPE REF TO zcl_excel_data_validation,
  lv_row               TYPE zexcel_cell_row.

CONSTANTS:
  gc_save_file_name TYPE string VALUE '46_ValidationWarning.xlsx'.

INCLUDE zdemo_excel_outputopt_incl.

START-OF-SELECTION.

*** Sheet Validation

* Creates active sheet
  CREATE OBJECT lo_excel.

* Get active sheet
  lo_worksheet = lo_excel->get_active_worksheet( ).

* Set sheet name "Validation"
  lo_worksheet->set_title( gc_ws_title_validation ).

* short validations can be entered as string (<254Char)
  lv_validation_string = '"New York, Rio, Tokyo"'.

* create validation object
  lo_data_validation = lo_worksheet->add_new_data_validation( ).

* create new validation from validation string
  lo_data_validation->type           = zcl_excel_data_validation=>c_type_list.
  lo_data_validation->formula1       = lv_validation_string.
  lo_data_validation->cell_row       = 2.
  lo_data_validation->cell_row_to    = 4.
  lo_data_validation->cell_column    = 'A'.
  lo_data_validation->cell_column_to = 'A'.
  lo_data_validation->allowblank     = 'X'.
  lo_data_validation->showdropdown   = 'X'.
  lo_data_validation->prompttitle    = 'Value list available'.
  lo_data_validation->prompt         = 'Please select a value from the value list'.
  lo_data_validation->errorstyle     = zcl_excel_data_validation=>c_style_warning.
  lo_data_validation->errortitle     = 'Warning'.
  lo_data_validation->error          = 'This value does not exist in current value list.'.

* add some fields with validation
  lv_row = 2.
  WHILE lv_row <= 4.
    lo_worksheet->set_cell( ip_row = lv_row ip_column = 'A' ip_value = 'Select' ).
    lv_row = lv_row + 1.
  ENDWHILE.

*** Create output
  lcl_output=>output( lo_excel ).


INTERFACE zif_abapgit_repo
  PUBLIC .

  DATA ms_data TYPE zif_abapgit_persistence=>ty_repo READ-ONLY.

  METHODS get_key
    RETURNING
      VALUE(rv_key) TYPE zif_abapgit_persistence=>ty_value .
  METHODS get_name
    RETURNING
      VALUE(rv_name) TYPE string
    RAISING
      zcx_abapgit_exception .
  METHODS is_offline
    RETURNING
      VALUE(rv_offline) TYPE abap_bool .
  METHODS get_package
    RETURNING
      VALUE(rv_package) TYPE zif_abapgit_persistence=>ty_repo-package .
  METHODS get_local_settings
    RETURNING
      VALUE(rs_settings) TYPE zif_abapgit_persistence=>ty_repo-local_settings .

  METHODS get_files_local
    IMPORTING
      !ii_log         TYPE REF TO zif_abapgit_log OPTIONAL
      !ii_obj_filter  TYPE REF TO zif_abapgit_object_filter OPTIONAL
    RETURNING
      VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt
    RAISING
      zcx_abapgit_exception .
  METHODS get_files_remote
    IMPORTING
      !ii_obj_filter   TYPE REF TO zif_abapgit_object_filter OPTIONAL
      !iv_ignore_files TYPE abap_bool DEFAULT abap_false
        PREFERRED PARAMETER ii_obj_filter
    RETURNING
      VALUE(rt_files)  TYPE zif_abapgit_definitions=>ty_files_tt
    RAISING
      zcx_abapgit_exception .
  METHODS refresh
    IMPORTING
      !iv_drop_cache TYPE abap_bool DEFAULT abap_false
      !iv_drop_log   TYPE abap_bool DEFAULT abap_true
        PREFERRED PARAMETER iv_drop_cache
    RAISING
      zcx_abapgit_exception .
  METHODS get_dot_abapgit
    RETURNING
      VALUE(ro_dot_abapgit) TYPE REF TO zcl_abapgit_dot_abapgit .
  METHODS set_dot_abapgit
    IMPORTING
      !io_dot_abapgit TYPE REF TO zcl_abapgit_dot_abapgit
    RAISING
      zcx_abapgit_exception .
  METHODS deserialize
    IMPORTING
      !is_checks TYPE zif_abapgit_definitions=>ty_deserialize_checks
      !ii_log    TYPE REF TO zif_abapgit_log
    RAISING
      zcx_abapgit_exception .
  METHODS deserialize_checks
    RETURNING
      VALUE(rs_checks) TYPE zif_abapgit_definitions=>ty_deserialize_checks
    RAISING
      zcx_abapgit_exception .

  METHODS checksums
    RETURNING
      VALUE(ri_checksums) TYPE REF TO zif_abapgit_repo_checksums
    RAISING
      zcx_abapgit_exception .

ENDINTERFACE.


CLASS zcl_abapgit_object_susc DEFINITION PUBLIC INHERITING FROM zcl_abapgit_objects_super FINAL.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_object.
    ALIASES mo_files FOR zif_abapgit_object~mo_files.
  PROTECTED SECTION.

    CONSTANTS transobjecttype_class TYPE c LENGTH 1 VALUE 'C' ##NO_TEXT.

    METHODS has_authorization
      IMPORTING
        !iv_class    TYPE tobc-oclss
        !iv_activity TYPE activ_auth
      RAISING
        zcx_abapgit_exception .
    METHODS is_used
      IMPORTING
        !iv_auth_object_class TYPE tobc-oclss
      RAISING
        zcx_abapgit_exception .
  PRIVATE SECTION.

    METHODS delete_class
      IMPORTING
        !iv_auth_object_class TYPE tobc-oclss .
    METHODS put_delete_to_transport
      RAISING
        zcx_abapgit_exception .
ENDCLASS.

CLASS zcl_abapgit_object_susc IMPLEMENTATION.

  METHOD delete_class.

    DELETE FROM tobc  WHERE oclss = iv_auth_object_class.
    DELETE FROM tobct WHERE oclss = iv_auth_object_class.

  ENDMETHOD.

  METHOD has_authorization.

    AUTHORITY-CHECK OBJECT 'S_DEVELOP'
           ID 'DEVCLASS' DUMMY
           ID 'OBJTYPE' FIELD 'SUSC'
           ID 'OBJNAME' FIELD iv_class
           ID 'P_GROUP' DUMMY
           ID 'ACTVT'   FIELD iv_activity.

    IF sy-subrc <> 0.
      zcx_abapgit_exception=>raise_t100( iv_msgid = '01'
                                         iv_msgno = '467' ).
    ENDIF.

  ENDMETHOD.

  METHOD is_used.

    DATA: lv_used_auth_object_class TYPE tobc-oclss.

    SELECT SINGLE oclss
      FROM tobj
      INTO lv_used_auth_object_class
      WHERE oclss = iv_auth_object_class ##WARN_OK.
    IF sy-subrc = 0.
      zcx_abapgit_exception=>raise_t100( iv_msgid = '01'
                                         iv_msgno = '212'
                                         iv_msgv1 = |{ iv_auth_object_class }| ).
    ENDIF.

  ENDMETHOD.

  METHOD put_delete_to_transport.

    DATA: lv_tr_object_name TYPE e071-obj_name,
          lv_tr_return      TYPE char1,
          ls_package_info   TYPE tdevc,
          lv_tadir_object   TYPE tadir-object,
          lv_tadir_obj_name TYPE tadir-obj_name.

    lv_tr_object_name = ms_item-obj_name.

    CALL FUNCTION 'SUSR_COMMEDITCHECK'
      EXPORTING
        objectname       = lv_tr_object_name
        transobjecttype  = transobjecttype_class
      IMPORTING
        return_from_korr = lv_tr_return.

    IF lv_tr_return <> 'M'.
      zcx_abapgit_exception=>raise( |error in SUSC delete at SUSR_COMMEDITCHECK| ).
    ENDIF.

    CALL FUNCTION 'TR_DEVCLASS_GET'
      EXPORTING
        iv_devclass = ms_item-devclass
      IMPORTING
        es_tdevc    = ls_package_info
      EXCEPTIONS
        OTHERS      = 1.
    IF sy-subrc = 0 AND ls_package_info-korrflag IS INITIAL.
      lv_tadir_object   = ms_item-obj_type.
      lv_tadir_obj_name = lv_tr_object_name.
      CALL FUNCTION 'TR_TADIR_INTERFACE'
        EXPORTING
          wi_delete_tadir_entry = abap_true
          wi_test_modus         = space
          wi_tadir_pgmid        = 'R3TR'
          wi_tadir_object       = lv_tadir_object
          wi_tadir_obj_name     = lv_tadir_obj_name
        EXCEPTIONS
          OTHERS                = 0.
    ENDIF.

  ENDMETHOD.

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

  METHOD zif_abapgit_object~delete.

    CONSTANTS lc_activity_delete_06 TYPE activ_auth VALUE '06'.

    DATA: lv_auth_object_class TYPE tobc-oclss.

    lv_auth_object_class = ms_item-obj_name.

    TRY.
        IF zif_abapgit_object~exists( ) = abap_false.
          RETURN.
        ENDIF.
      CATCH zcx_abapgit_exception.
        RETURN.
    ENDTRY.

    has_authorization( iv_class    = lv_auth_object_class
                       iv_activity = lc_activity_delete_06 ).

    is_used( lv_auth_object_class ).

    delete_class( lv_auth_object_class ).

    put_delete_to_transport( ).

  ENDMETHOD.

  METHOD zif_abapgit_object~deserialize.
* see function group SUSA

    DATA: ls_tobc       TYPE tobc,
          lv_objectname TYPE e071-obj_name,
          ls_tobct      TYPE tobct.

    io_xml->read( EXPORTING iv_name = 'TOBC'
                  CHANGING cg_data = ls_tobc ).
    io_xml->read( EXPORTING iv_name = 'TOBCT'
                  CHANGING cg_data = ls_tobct ).

    tadir_insert( iv_package ).

    lv_objectname = ms_item-obj_name.
    CALL FUNCTION 'SUSR_COMMEDITCHECK'
      EXPORTING
        objectname      = lv_objectname
        transobjecttype = transobjecttype_class.

    INSERT tobc FROM ls_tobc.                             "#EC CI_SUBRC
* ignore sy-subrc as all fields are key fields

    MODIFY tobct FROM ls_tobct.                           "#EC CI_SUBRC
    ASSERT sy-subrc = 0.

  ENDMETHOD.

  METHOD zif_abapgit_object~exists.

    DATA: lv_oclss TYPE tobc-oclss.

    SELECT SINGLE oclss FROM tobc INTO lv_oclss
      WHERE oclss = ms_item-obj_name.
    rv_bool = boolc( sy-subrc = 0 ).

  ENDMETHOD.

  METHOD zif_abapgit_object~get_comparator.
    RETURN.
  ENDMETHOD.

  METHOD zif_abapgit_object~get_deserialize_steps.
    APPEND zif_abapgit_object=>gc_step_id-abap TO rt_steps.
  ENDMETHOD.

  METHOD zif_abapgit_object~get_metadata.
    rs_metadata = get_metadata( ).
    rs_metadata-delete_tadir = abap_true.
  ENDMETHOD.

  METHOD zif_abapgit_object~is_active.
    rv_active = is_active( ).
  ENDMETHOD.

  METHOD zif_abapgit_object~is_locked.
    rv_is_locked = abap_false.
  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    DATA: lv_objclass TYPE tobc-oclss.

    lv_objclass = ms_item-obj_name.
    CALL FUNCTION 'SUSR_SHOW_OBJECT_CLASS'
      EXPORTING
        objclass = lv_objclass.

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA: ls_tobc  TYPE tobc,
          ls_tobct TYPE tobct.

    SELECT SINGLE * FROM tobc INTO ls_tobc
      WHERE oclss = ms_item-obj_name.
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    SELECT SINGLE * FROM tobct INTO ls_tobct
      WHERE oclss = ms_item-obj_name
      AND langu = mv_language.

    io_xml->add( iv_name = 'TOBC'
                 ig_data = ls_tobc ).
    io_xml->add( iv_name = 'TOBCT'
                 ig_data = ls_tobct ).

  ENDMETHOD.
ENDCLASS.


CLASS zcl_aoc_check_63 DEFINITION
  PUBLIC
  INHERITING FROM zcl_aoc_super_root
  CREATE PUBLIC .

  PUBLIC SECTION.

    METHODS constructor .

    METHODS run
        REDEFINITION .
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS ZCL_AOC_CHECK_63 IMPLEMENTATION.

  METHOD constructor.

    super->constructor( ).

    version        = '001'.
    position       = '063'.

    has_documentation = abap_true.
    has_attributes = abap_true.
    attributes_ok  = abap_true.

    add_obj_type( 'CLAS' ).
    add_obj_type( 'INTF' ).

    insert_scimessage(
        iv_code = '003'
        iv_text = '&1'(m01) ).

  ENDMETHOD.

  METHOD run.

* abapOpenChecks
*
* MIT License

    DATA: lo_instance TYPE REF TO object,
          lr_data     TYPE REF TO data.

    FIELD-SYMBOLS: <lt_log>  TYPE STANDARD TABLE,
                   <lv_type> TYPE string,
                   <lv_text> TYPE string,
                   <lg_log>  TYPE any.

    IF object_type <> 'CLAS' AND object_type <> 'INTF'.
      RETURN.
    ENDIF.

    TRY.
        CREATE DATA lr_data TYPE ('CL_SEDI_ABAP_DOC_LOGGER=>TY_LOG_TAB').
        ASSIGN lr_data->* TO <lt_log>.
      CATCH cx_root ##CATCH_ALL.
        RETURN.
    ENDTRY.

    CALL METHOD ('CL_SEDI_ABAP_DOC_READ_ELEMINFO')=>('CREATE_INSTANCE')
      RECEIVING
        result = lo_instance.

    CASE object_type.
      WHEN 'INTF'.
        CALL METHOD lo_instance->('READ_EI_GLOBAL_INTERFACE')
          EXPORTING
            interface_name = object_name
          IMPORTING
            read_log       = <lt_log>.
      WHEN 'CLAS'.
        CALL METHOD lo_instance->('READ_EI_GLOBAL_CLASS')
          EXPORTING
            class_name = object_name
          IMPORTING
            read_log   = <lt_log>.
      WHEN OTHERS.
        ASSERT 0 = 1.
    ENDCASE.

    LOOP AT <lt_log> ASSIGNING <lg_log>.
      ASSIGN COMPONENT 'TYPE' OF STRUCTURE <lg_log> TO <lv_type>.
      ASSERT sy-subrc = 0.
      IF <lv_type> = 'E'.
        ASSIGN COMPONENT 'TEXT' OF STRUCTURE <lg_log> TO <lv_text>.
        ASSERT sy-subrc = 0.

        IF <lv_text> CP 'active version cannot be read*'.
          CONTINUE.
        ENDIF.

        inform( p_sub_obj_type = object_type
                p_sub_obj_name = object_name
                p_kind         = mv_errty
                p_test         = myname
                p_code         = '001'
                p_param_1      = <lv_text> ).
      ENDIF.
    ENDLOOP.

  ENDMETHOD.
ENDCLASS.


"! abapGit general error
CLASS zcx_abapgit_exception DEFINITION
  PUBLIC
  INHERITING FROM cx_static_check
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES if_t100_message .

    CONSTANTS:
      BEGIN OF c_section_text,
        cause           TYPE string VALUE `Cause`,
        system_response TYPE string VALUE `System response`,
        what_to_do      TYPE string VALUE `Procedure`,
        sys_admin       TYPE string VALUE `System administration`,
      END OF c_section_text .
    CONSTANTS:
      BEGIN OF c_section_token,
        cause           TYPE string VALUE `&CAUSE&`,
        system_response TYPE string VALUE `&SYSTEM_RESPONSE&`,
        what_to_do      TYPE string VALUE `&WHAT_TO_DO&`,
        sys_admin       TYPE string VALUE `&SYS_ADMIN&`,
      END OF c_section_token .
    DATA msgv1 TYPE symsgv READ-ONLY .
    DATA msgv2 TYPE symsgv READ-ONLY .
    DATA msgv3 TYPE symsgv READ-ONLY .
    DATA msgv4 TYPE symsgv READ-ONLY .
    DATA mt_callstack TYPE abap_callstack READ-ONLY .
    DATA mi_log TYPE REF TO zif_abapgit_log READ-ONLY.

    "! Raise exception with text
    "! @parameter iv_text | Text
    "! @parameter ix_previous | Previous exception
    "! @raising zcx_abapgit_exception | Exception
    CLASS-METHODS raise
      IMPORTING
        !iv_text     TYPE clike
        !ix_previous TYPE REF TO cx_root OPTIONAL
        !ii_log      TYPE REF TO zif_abapgit_log OPTIONAL
      RAISING
        zcx_abapgit_exception .
    "! Raise exception with T100 message
    "! <p>
    "! Will default to sy-msg* variables. These need to be set right before calling this method.
    "! </p>
    "! @parameter iv_msgid | Message ID
    "! @parameter iv_msgno | Message number
    "! @parameter iv_msgv1 | Message variable 1
    "! @parameter iv_msgv2 | Message variable 2
    "! @parameter iv_msgv3 | Message variable 3
    "! @parameter iv_msgv4 | Message variable 4
    "! @raising zcx_abapgit_exception | Exception
    CLASS-METHODS raise_t100
      IMPORTING
        VALUE(iv_msgid) TYPE symsgid DEFAULT sy-msgid
        VALUE(iv_msgno) TYPE symsgno DEFAULT sy-msgno
        VALUE(iv_msgv1) TYPE symsgv DEFAULT sy-msgv1
        VALUE(iv_msgv2) TYPE symsgv DEFAULT sy-msgv2
        VALUE(iv_msgv3) TYPE symsgv DEFAULT sy-msgv3
        VALUE(iv_msgv4) TYPE symsgv DEFAULT sy-msgv4
        !ii_log         TYPE REF TO zif_abapgit_log OPTIONAL
        !ix_previous    TYPE REF TO cx_root OPTIONAL
      RAISING
        zcx_abapgit_exception .
    CLASS-METHODS raise_with_text
      IMPORTING
        !ix_previous TYPE REF TO cx_root
      RAISING
        zcx_abapgit_exception .
    METHODS constructor
      IMPORTING
        !textid   LIKE if_t100_message=>t100key OPTIONAL
        !previous LIKE previous OPTIONAL
        !ii_log   TYPE REF TO zif_abapgit_log OPTIONAL
        !msgv1    TYPE symsgv OPTIONAL
        !msgv2    TYPE symsgv OPTIONAL
        !msgv3    TYPE symsgv OPTIONAL
        !msgv4    TYPE symsgv OPTIONAL .

    METHODS get_source_position
        REDEFINITION .
    METHODS if_message~get_longtext
        REDEFINITION .
  PROTECTED SECTION.
  PRIVATE SECTION.

    CONSTANTS c_generic_error_msg TYPE string VALUE `An error occured (ZCX_ABAPGIT_EXCEPTION)` ##NO_TEXT.

    CLASS-METHODS split_text_to_symsg
      IMPORTING
        !iv_text      TYPE string
      RETURNING
        VALUE(rs_msg) TYPE symsg .
    METHODS save_callstack .
    METHODS itf_to_string
      IMPORTING
        !it_itf          TYPE tline_tab
      RETURNING
        VALUE(rv_result) TYPE string .
    METHODS get_t100_longtext_itf
      RETURNING
        VALUE(rt_itf) TYPE tline_tab .
    METHODS remove_empty_section
      IMPORTING
        !iv_tabix_from TYPE i
        !iv_tabix_to   TYPE i
      CHANGING
        !ct_itf        TYPE tline_tab .
    METHODS replace_section_head_with_text
      CHANGING
        !cs_itf TYPE tline .
ENDCLASS.

CLASS ZCX_ABAPGIT_EXCEPTION IMPLEMENTATION.

  METHOD constructor ##ADT_SUPPRESS_GENERATION.

    super->constructor( previous = previous ).

    me->msgv1 = msgv1.
    me->msgv2 = msgv2.
    me->msgv3 = msgv3.
    me->msgv4 = msgv4.
    me->mi_log = ii_log.

    CLEAR me->textid.
    IF textid IS INITIAL.
      if_t100_message~t100key = if_t100_message=>default_textid.
    ELSE.
      if_t100_message~t100key = textid.
    ENDIF.

    save_callstack( ).

  ENDMETHOD.

  METHOD get_source_position.

    FIELD-SYMBOLS: <ls_callstack> TYPE abap_callstack_line.

    READ TABLE mt_callstack ASSIGNING <ls_callstack>
                            INDEX 1.
    IF sy-subrc = 0.
      program_name = <ls_callstack>-mainprogram.
      include_name = <ls_callstack>-include.
      source_line  = <ls_callstack>-line.
    ELSE.
      super->get_source_position(
        IMPORTING
          program_name = program_name
          include_name = include_name
          source_line  = source_line   ).
    ENDIF.

  ENDMETHOD.

  METHOD get_t100_longtext_itf.

    DATA: lv_docu_key TYPE doku_obj.

    FIELD-SYMBOLS <lv_msgv> TYPE any.

    lv_docu_key = if_t100_message~t100key-msgid && if_t100_message~t100key-msgno.

    CALL FUNCTION 'DOCU_GET'
      EXPORTING
        id     = 'NA'
        langu  = sy-langu
        object = lv_docu_key
        typ    = 'E'
      TABLES
        line   = rt_itf
      EXCEPTIONS
        OTHERS = 1.

    IF sy-subrc = 0.
      ASSIGN me->(if_t100_message~t100key-attr1) TO <lv_msgv>.
      IF sy-subrc = 0.
        REPLACE ALL OCCURRENCES OF '&V1&' IN TABLE rt_itf WITH <lv_msgv>.
      ENDIF.
      ASSIGN me->(if_t100_message~t100key-attr2) TO <lv_msgv>.
      IF sy-subrc = 0.
        REPLACE ALL OCCURRENCES OF '&V2&' IN TABLE rt_itf WITH <lv_msgv>.
      ENDIF.
      ASSIGN me->(if_t100_message~t100key-attr3) TO <lv_msgv>.
      IF sy-subrc = 0.
        REPLACE ALL OCCURRENCES OF '&V3&' IN TABLE rt_itf WITH <lv_msgv>.
      ENDIF.
      ASSIGN me->(if_t100_message~t100key-attr4) TO <lv_msgv>.
      IF sy-subrc = 0.
        REPLACE ALL OCCURRENCES OF '&V4&' IN TABLE rt_itf WITH <lv_msgv>.
      ENDIF.
    ENDIF.

  ENDMETHOD.

  METHOD if_message~get_longtext.

    result = super->get_longtext( ).

    IF if_t100_message~t100key IS NOT INITIAL.

      result = itf_to_string( get_t100_longtext_itf( ) ).

    ENDIF.

  ENDMETHOD.

  METHOD itf_to_string.

    CONSTANTS: lc_format_section TYPE string VALUE 'U1'.

    DATA:
      lt_stream      TYPE TABLE OF tdline,
      lt_string      TYPE TABLE OF string,
      lv_string      LIKE LINE OF lt_string,
      lt_itf         TYPE tline_tab,
      lv_has_content TYPE abap_bool,
      lv_tabix_from  TYPE syst-tabix,
      lv_tabix_to    TYPE syst-tabix.

    FIELD-SYMBOLS: <ls_itf_section>      TYPE tline,
                   <ls_itf_section_item> TYPE tline.

    lt_itf = it_itf.

    " You should remember that we replace the U1 format because
    " that preserves the section header of longtexts.
    LOOP AT lt_itf ASSIGNING <ls_itf_section>
                   WHERE tdformat = lc_format_section.

      CLEAR:
        lv_has_content,
        lv_tabix_to.

      lv_tabix_from = sy-tabix.

      LOOP AT lt_itf ASSIGNING <ls_itf_section_item>
                     FROM sy-tabix + 1.

        IF <ls_itf_section_item>-tdformat = lc_format_section.
          lv_tabix_to = sy-tabix.
          EXIT.
        ELSEIF <ls_itf_section_item>-tdline IS NOT INITIAL.
          lv_has_content = abap_true.
        ENDIF.

      ENDLOOP.

      IF lv_has_content = abap_false.
        remove_empty_section(
          EXPORTING
            iv_tabix_from = lv_tabix_from
            iv_tabix_to   = lv_tabix_to
          CHANGING
            ct_itf        = lt_itf ).
        CONTINUE.
      ENDIF.

      replace_section_head_with_text( CHANGING cs_itf = <ls_itf_section> ).

    ENDLOOP.

    CALL FUNCTION 'CONVERT_ITF_TO_STREAM_TEXT'
      EXPORTING
        lf           = 'X'
      IMPORTING
        stream_lines = lt_string
      TABLES
        itf_text     = lt_itf
        text_stream  = lt_stream.

    LOOP AT lt_string INTO lv_string.
      IF sy-tabix = 1.
        rv_result = lv_string.
      ELSE.
        CONCATENATE rv_result lv_string
                    INTO rv_result
                    SEPARATED BY cl_abap_char_utilities=>newline.
      ENDIF.

    ENDLOOP.

  ENDMETHOD.

  METHOD raise.

    DATA lv_text TYPE string.

    IF iv_text IS INITIAL.
      lv_text = c_generic_error_msg.
    ELSE.
      lv_text = iv_text.
    ENDIF.

    split_text_to_symsg( lv_text ).

    raise_t100(
      ii_log      = ii_log
      ix_previous = ix_previous ).

  ENDMETHOD.

  METHOD raise_t100.
    DATA: ls_t100_key TYPE scx_t100key.

    ls_t100_key-msgid = iv_msgid.
    ls_t100_key-msgno = iv_msgno.
    ls_t100_key-attr1 = 'MSGV1'.
    ls_t100_key-attr2 = 'MSGV2'.
    ls_t100_key-attr3 = 'MSGV3'.
    ls_t100_key-attr4 = 'MSGV4'.

    IF iv_msgid IS INITIAL.
      CLEAR ls_t100_key.
    ENDIF.

    RAISE EXCEPTION TYPE zcx_abapgit_exception
      EXPORTING
        textid   = ls_t100_key
        ii_log   = ii_log
        msgv1    = iv_msgv1
        msgv2    = iv_msgv2
        msgv3    = iv_msgv3
        msgv4    = iv_msgv4
        previous = ix_previous.
  ENDMETHOD.

  METHOD raise_with_text.
    raise(
      iv_text = ix_previous->get_text( )
      ix_previous = ix_previous ).
  ENDMETHOD.

  METHOD remove_empty_section.
    IF iv_tabix_to BETWEEN iv_tabix_from AND lines( ct_itf ).
      DELETE ct_itf FROM iv_tabix_from TO iv_tabix_to.
    ELSE.
      DELETE ct_itf FROM iv_tabix_from.
    ENDIF.
  ENDMETHOD.

  METHOD replace_section_head_with_text.

    CASE cs_itf-tdline.
      WHEN c_section_token-cause.
        cs_itf-tdline = c_section_text-cause.
      WHEN c_section_token-system_response.
        cs_itf-tdline = c_section_text-system_response.
      WHEN c_section_token-what_to_do.
        cs_itf-tdline = c_section_text-what_to_do.
      WHEN c_section_token-sys_admin.
        cs_itf-tdline = c_section_text-sys_admin.
    ENDCASE.

  ENDMETHOD.

  METHOD save_callstack.

    FIELD-SYMBOLS: <ls_callstack> TYPE abap_callstack_line.

    CALL FUNCTION 'SYSTEM_CALLSTACK'
      IMPORTING
        callstack = mt_callstack.

    " You should remember that the first lines are from zcx_abapgit_exception
    " and are removed so that highest level in the callstack is the position where
    " the exception is raised.
    "
    " For the merged report it's hard to do that, because zcx_abapgit_exception
    " isn't visible in the callstack. Therefore we have to check the Events.
    LOOP AT mt_callstack ASSIGNING <ls_callstack>.

      IF <ls_callstack>-mainprogram CP |ZCX_ABAPGIT_EXCEPTION*| " full
      OR <ls_callstack>-blockname = `SAVE_CALLSTACK` " merged
      OR <ls_callstack>-blockname = `CONSTRUCTOR` " merged
      OR <ls_callstack>-blockname CP `RAISE*`. "merged
        DELETE TABLE mt_callstack FROM <ls_callstack>.
      ELSE.
        EXIT.
      ENDIF.

    ENDLOOP.

  ENDMETHOD.

  METHOD split_text_to_symsg.

    CONSTANTS:
      lc_length_of_msgv           TYPE i VALUE 50,
      lc_offset_of_last_character TYPE i VALUE 49.

    DATA:
      lv_text    TYPE c LENGTH 200,
      lv_rest    TYPE c LENGTH 200,
      ls_msg     TYPE symsg,
      lv_msg_var TYPE c LENGTH lc_length_of_msgv,
      lv_index   TYPE sy-index.

    lv_text = iv_text.

    DO 4 TIMES.

      lv_index = sy-index.

      CALL FUNCTION 'TEXT_SPLIT'
        EXPORTING
          length = lc_length_of_msgv
          text   = lv_text
        IMPORTING
          line   = lv_msg_var
          rest   = lv_rest.

      IF lv_msg_var+lc_offset_of_last_character(1) = space OR
         lv_text+lc_length_of_msgv(1) = space.
        " keep the space at the beginning of the rest
        " because otherwise it's lost
        lv_rest = | { lv_rest }|.
      ENDIF.

      lv_text = lv_rest.

      CASE lv_index.
        WHEN 1.
          ls_msg-msgv1 = lv_msg_var.
        WHEN 2.
          ls_msg-msgv2 = lv_msg_var.
        WHEN 3.
          ls_msg-msgv3 = lv_msg_var.
        WHEN 4.
          ls_msg-msgv4 = lv_msg_var.
      ENDCASE.

    ENDDO.

    " Set syst using generic error message
    MESSAGE e001(00) WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4 INTO sy-lisel.

    rs_msg = ls_msg.

  ENDMETHOD.
ENDCLASS.


INTERFACE zif_abapgit_services_git PUBLIC.

  TYPES:
    BEGIN OF ty_commit_fields,
      repo_key        TYPE zif_abapgit_persistence=>ty_repo-key,
      committer_name  TYPE string,
      committer_email TYPE string,
      author_name     TYPE string,
      author_email    TYPE string,
      comment         TYPE string,
      body            TYPE string,
    END OF ty_commit_fields.

ENDINTERFACE.


INTERFACE zif_abapgit_auth PUBLIC.

  TYPES: ty_authorization TYPE string.

  CONSTANTS: BEGIN OF c_authorization,
               uninstall             TYPE ty_authorization VALUE 'UNINSTALL',
               create_repo           TYPE ty_authorization VALUE 'CREATE_REPO',
               transport_to_branch   TYPE ty_authorization VALUE 'TRANSPORT_TO_BRANCH',
               update_local_checksum TYPE ty_authorization VALUE 'UPDATE_LOCAL_CHECKSUM',
             END OF c_authorization.

  METHODS:
    is_allowed
      IMPORTING iv_authorization  TYPE ty_authorization
                iv_param          TYPE string OPTIONAL
      RETURNING VALUE(rv_allowed) TYPE abap_bool.

ENDINTERFACE.


CLASS zcl_aoc_check_07 DEFINITION
  PUBLIC
  INHERITING FROM zcl_aoc_super
  CREATE PUBLIC.

  PUBLIC SECTION.
    METHODS constructor.

    METHODS check
        REDEFINITION.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_aoc_check_07 IMPLEMENTATION.

  METHOD check.

* abapOpenChecks
*
* MIT License

    DATA: lv_position TYPE i,
          lv_token    LIKE sy-tabix,
          lv_include  TYPE sobj_name.

    FIELD-SYMBOLS: <ls_token>     LIKE LINE OF io_scan->tokens,
                   <ls_token1>    LIKE LINE OF io_scan->tokens,
                   <ls_token2>    LIKE LINE OF io_scan->tokens,
                   <ls_token3>    LIKE LINE OF io_scan->tokens,
                   <ls_statement> LIKE LINE OF io_scan->statements.

    LOOP AT io_scan->statements ASSIGNING <ls_statement>
        WHERE type = io_scan->gc_statement-standard
        OR type = io_scan->gc_statement-method_direct.

      lv_position = sy-tabix.

      lv_token = <ls_statement>-from.
      READ TABLE io_scan->tokens ASSIGNING <ls_token1> INDEX lv_token.
      IF sy-subrc <> 0.
        CONTINUE. " current loop
      ENDIF.
      lv_token = lv_token + 1.
      READ TABLE io_scan->tokens ASSIGNING <ls_token2> INDEX lv_token.
      IF sy-subrc <> 0.
        CONTINUE. " current loop
      ENDIF.
      lv_token = lv_token + 1.
      READ TABLE io_scan->tokens ASSIGNING <ls_token3> INDEX lv_token.
      IF sy-subrc <> 0.
        CONTINUE. " current loop
      ENDIF.

      IF <ls_token3>-str CP '*>(*'
          OR <ls_token3>-str CP '*)=>*'
          OR <ls_token3>-str CP '*)->*'
          OR <ls_token3>-str CP '(*'
          OR <ls_token3>-str = 'OF'.
* allow dynamic calls and OLE interaction
        CONTINUE.
      ENDIF.

      LOOP AT io_scan->tokens ASSIGNING <ls_token>
          FROM <ls_statement>-from TO <ls_statement>-to
          WHERE str = 'RECEIVING'
          AND type = io_scan->gc_token-identifier.

        IF <ls_token1>-str = 'CALL' OR <ls_token2>-str = 'BADI'.
          EXIT.
        ENDIF.

* allow if old style exceptions are part of method
        LOOP AT io_scan->tokens TRANSPORTING NO FIELDS
            FROM <ls_statement>-from TO <ls_statement>-to
            WHERE str = 'EXCEPTIONS'
            AND type = io_scan->gc_token-identifier.
          EXIT.
        ENDLOOP.
        IF sy-subrc = 0.
          EXIT. " current loop
        ENDIF.

        lv_include = io_scan->get_include( <ls_statement>-level ).
        inform( p_sub_obj_name = lv_include
                p_position     = lv_position
                p_line         = <ls_token>-row
                p_kind         = mv_errty
                p_test         = myname
                p_code         = '002' ).
      ENDLOOP.

      IF <ls_token1>-str <> 'CALL' OR <ls_token2>-str <> 'METHOD'.
        CONTINUE. " current loop
      ENDIF.

      lv_include = io_scan->get_include( <ls_statement>-level ).
      inform( p_sub_obj_name = lv_include
              p_position     = lv_position
              p_line         = <ls_token1>-row
              p_kind         = mv_errty
              p_test         = myname
              p_code         = '001' ).

    ENDLOOP.

  ENDMETHOD.

  METHOD constructor.

    super->constructor( ).

    version        = '001'.
    position       = '007'.

    has_attributes = abap_true.
    attributes_ok  = abap_true.

    enable_rfc( ).
    enable_checksum( ).

    insert_scimessage(
        iv_code = '001'
        iv_text = 'Use functional writing style'(m01) ).
    insert_scimessage(
        iv_code = '002'
        iv_text = 'Use functional writing style instead of RECEIVING'(m02) ).

  ENDMETHOD.
ENDCLASS.


CLASS zcl_aoc_check_18 DEFINITION
  PUBLIC
  INHERITING FROM zcl_aoc_super
  CREATE PUBLIC.

  PUBLIC SECTION.
    METHODS constructor.

    METHODS check
        REDEFINITION.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_aoc_check_18 IMPLEMENTATION.

  METHOD check.

* abapOpenChecks
*
* MIT License

    DATA: lv_include TYPE program,
          lv_found   TYPE abap_bool.

    FIELD-SYMBOLS: <ls_structure> LIKE LINE OF io_scan->structures,
                   <ls_token>     LIKE LINE OF io_scan->tokens,
                   <ls_statement> LIKE LINE OF io_scan->statements.

    LOOP AT io_scan->structures ASSIGNING <ls_structure>
        WHERE type = io_scan->gc_structure-condition.

      lv_found = abap_false.

      LOOP AT io_scan->statements ASSIGNING <ls_statement>
          FROM <ls_structure>-stmnt_from TO <ls_structure>-stmnt_to.

        READ TABLE io_scan->tokens ASSIGNING <ls_token> INDEX <ls_statement>-from.
        IF sy-subrc <> 0 OR <ls_token>-type = io_scan->gc_token-comment.
          CONTINUE.
        ENDIF.

        CASE <ls_token>-str.
          WHEN 'WHEN' OR 'ELSEIF' OR 'ELSE'.
            CONTINUE.
          WHEN OTHERS.
            lv_found = abap_true.
            EXIT.
        ENDCASE.
      ENDLOOP.

      IF lv_found = abap_false.
        READ TABLE io_scan->statements ASSIGNING <ls_statement> INDEX <ls_structure>-stmnt_from.
        CHECK sy-subrc = 0.
        READ TABLE io_scan->tokens ASSIGNING <ls_token> INDEX <ls_statement>-from.
        CHECK sy-subrc = 0.

        lv_include = io_scan->get_include( <ls_statement>-level ).

        inform( p_sub_obj_name = lv_include
                p_position     = <ls_structure>-stmnt_from
                p_line         = <ls_token>-row
                p_kind         = mv_errty
                p_test         = myname
                p_code         = '001' ).
      ENDIF.

    ENDLOOP.

  ENDMETHOD.

  METHOD constructor.

    super->constructor( ).

    version        = '001'.
    position       = '018'.

    has_attributes = abap_true.
    attributes_ok  = abap_true.

    enable_rfc( ).
    enable_checksum( ).

    insert_scimessage(
        iv_code = '001'
        iv_text = 'Empty branch'(m01) ).

  ENDMETHOD.
ENDCLASS.


INTERFACE zif_abapgit_data_config
  PUBLIC .

  TYPES:
    ty_data_type TYPE c LENGTH 4 .
  TYPES:
    BEGIN OF ty_config,
      type  TYPE ty_data_type,
      name  TYPE tadir-obj_name,
      where TYPE string_table,
    END OF ty_config .
  TYPES:
    ty_config_tt TYPE SORTED TABLE OF ty_config WITH UNIQUE KEY type name .

  CONSTANTS c_default_path TYPE string VALUE '/data/' ##NO_TEXT.
  CONSTANTS c_default_format TYPE string VALUE 'json' ##NO_TEXT.
  CONSTANTS c_config TYPE string VALUE 'conf' ##NO_TEXT.
  CONSTANTS:
    BEGIN OF c_data_type,
      tabu TYPE ty_data_type VALUE 'TABU',
      vdat TYPE ty_data_type VALUE 'VDAT',
      cdat TYPE ty_data_type VALUE 'CDAT',
      tdat TYPE ty_data_type VALUE 'TDAT',
    END OF c_data_type .

  METHODS add_config
    IMPORTING
      !is_config TYPE ty_config
    RAISING
      zcx_abapgit_exception .
  METHODS from_json
    IMPORTING
      !it_files TYPE zif_abapgit_definitions=>ty_files_tt
    RAISING
      zcx_abapgit_exception .
  METHODS get_configs
    RETURNING
      VALUE(rt_configs) TYPE ty_config_tt .
  METHODS remove_config
    IMPORTING
      !is_config TYPE ty_config
    RAISING
      zcx_abapgit_exception .
  METHODS to_json
    RETURNING
      VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_tt
    RAISING
      zcx_abapgit_exception .
  METHODS update_config
    IMPORTING
      !is_config TYPE ty_config
    RAISING
      zcx_abapgit_exception .
ENDINTERFACE.


CLASS zcl_excel_style DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

*"* public components of class ZCL_EXCEL_STYLE
*"* do not include other source files here!!!
  PUBLIC SECTION.

    DATA font TYPE REF TO zcl_excel_style_font .
    DATA fill TYPE REF TO zcl_excel_style_fill .
    DATA borders TYPE REF TO zcl_excel_style_borders .
    DATA alignment TYPE REF TO zcl_excel_style_alignment .
    DATA number_format TYPE REF TO zcl_excel_style_number_format .
    DATA protection TYPE REF TO zcl_excel_style_protection .

    METHODS constructor
      IMPORTING
        !ip_guid TYPE zexcel_cell_style OPTIONAL .
    METHODS get_guid
      RETURNING
        VALUE(ep_guid) TYPE zexcel_cell_style .
*"* protected components of class ZABAP_EXCEL_STYLE
*"* do not include other source files here!!!
  PROTECTED SECTION.
*"* private components of class ZCL_EXCEL_STYLE
*"* do not include other source files here!!!
  PRIVATE SECTION.

    DATA guid TYPE zexcel_cell_style .
ENDCLASS.

CLASS zcl_excel_style IMPLEMENTATION.

  METHOD constructor.

    CREATE OBJECT font.
    CREATE OBJECT fill.
    CREATE OBJECT borders.
    CREATE OBJECT alignment.
    CREATE OBJECT number_format.
    CREATE OBJECT protection.

    IF ip_guid IS NOT INITIAL.
      me->guid = ip_guid.
    ELSE.
      me->guid = zcl_excel_obsolete_func_wrap=>guid_create( ).
    ENDIF.

  ENDMETHOD.

  METHOD get_guid.

    ep_guid = me->guid.
  ENDMETHOD.
ENDCLASS.


*----------------------------------------------------------------------*
*       CLASS lcl_Test DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS ltcl_test DEFINITION FOR TESTING
  DURATION SHORT
  RISK LEVEL HARMLESS
  FINAL.

  PRIVATE SECTION.
* ================

    DATA: mt_code   TYPE string_table,
          ms_result TYPE scirest_ad,
          mo_check  TYPE REF TO zcl_aoc_check_28.

    METHODS:
      setup,
      export_import FOR TESTING,
      test001_01 FOR TESTING,
      test001_02 FOR TESTING,
      test001_03 FOR TESTING,
      test001_04 FOR TESTING,
      test001_05 FOR TESTING,
      test001_06 FOR TESTING,
      test001_07 FOR TESTING,
      test001_08 FOR TESTING,
      test001_09 FOR TESTING,
      test001_10 FOR TESTING.

ENDCLASS.       "lcl_Test

*----------------------------------------------------------------------*
*       CLASS lcl_Test IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS ltcl_test IMPLEMENTATION.
* ==============================

  DEFINE _code.
    APPEND &1 TO mt_code.
  END-OF-DEFINITION.

  METHOD setup.
    CREATE OBJECT mo_check.
    zcl_aoc_unit_test=>set_check( mo_check ).
  ENDMETHOD.                    "setup

  METHOD export_import.
    zcl_aoc_unit_test=>export_import( mo_check ).
  ENDMETHOD.

  METHOD test001_01.
* ===========

    _code 'lv_foo = lv_bar .'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '001'
                                        act = ms_result-code ).

  ENDMETHOD.                    "test1

  METHOD test001_02.
* ===========

    _code 'lv_foo = lv_bar.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result ).

  ENDMETHOD.                    "test2

  METHOD test001_03.
* ===========

    _code '.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result ).

  ENDMETHOD.

  METHOD test001_04.
* ===========

    _code 'DATA: lv_foo TYPE i ,'.
    _code '      lv_bar TYPE i.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '001'
                                        act = ms_result-code ).

  ENDMETHOD.

  METHOD test001_05.
* ===========

    _code '* comment'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result ).

  ENDMETHOD.

  METHOD test001_06.
* ===========

    _code 'DEFINE _code.'.
    _code '  append &1 to mt_code.'.
    _code 'END-OF-DEFINITION.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result ).

  ENDMETHOD.

  METHOD test001_07.
* ===========

    _code 'super->constructor( ).'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result ).

  ENDMETHOD.

  METHOD test001_08.
* ===========

    _code 'TRY.'.
    _code '  CATCH cx_root ##CATCH_ALL.'.
    _code 'ENDTRY.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result ).

  ENDMETHOD.

  METHOD test001_09.
* ===========

    _code 'lv_foo = lv_bar    .'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '001'
                                        act = ms_result-code ).

  ENDMETHOD.

  METHOD test001_10.
* ===========

    _code 'CONSTANTS:'.
    _code '  lc_begin TYPE string VALUE ''* <SIGNATURE>-------------------'''.
    _code '  & ''----------------------------------+''.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result ).

  ENDMETHOD.

ENDCLASS.       "lcl_Test


CLASS ltcl_diff DEFINITION FOR TESTING
  DURATION SHORT
  RISK LEVEL HARMLESS.

  PRIVATE SECTION.
    DATA: mt_new      TYPE TABLE OF string,
          mt_old      TYPE TABLE OF string,
          mt_expected TYPE zif_abapgit_definitions=>ty_diffs_tt.

    METHODS:
      add_new IMPORTING iv_new TYPE string,
      add_old IMPORTING iv_old TYPE string,
      add_expected IMPORTING iv_new_num TYPE zif_abapgit_definitions=>ty_diff-new_num
                             iv_new     TYPE zif_abapgit_definitions=>ty_diff-new
                             iv_result  TYPE zif_abapgit_definitions=>ty_diff-result
                             iv_old_num TYPE zif_abapgit_definitions=>ty_diff-old_num
                             iv_old     TYPE zif_abapgit_definitions=>ty_diff-old
                             iv_beacon  TYPE zif_abapgit_definitions=>ty_diff-beacon
                               DEFAULT zcl_abapgit_diff=>co_starting_beacon.

    METHODS: setup.

    METHODS: test
      IMPORTING
        !iv_ignore_indentation TYPE abap_bool DEFAULT abap_false
        !iv_ignore_comments    TYPE abap_bool DEFAULT abap_false
        !iv_ignore_case        TYPE abap_bool DEFAULT abap_false.

    METHODS:
      diff01 FOR TESTING,
      diff02 FOR TESTING,
      diff03 FOR TESTING,
      diff04 FOR TESTING,
      diff05 FOR TESTING,
      diff06 FOR TESTING,
      diff07 FOR TESTING,
      diff08 FOR TESTING,
      diff09 FOR TESTING,
      diff10 FOR TESTING,
      diff11 FOR TESTING,
      diff12 FOR TESTING,
      diff13 FOR TESTING.

ENDCLASS.

CLASS ltcl_diff IMPLEMENTATION.

  METHOD add_new.
    DATA lv_new LIKE LINE OF mt_new.

    lv_new = iv_new.
    APPEND lv_new TO mt_new.
  ENDMETHOD.

  METHOD add_old.
    DATA lv_old LIKE LINE OF mt_old.

    lv_old = iv_old.
    APPEND lv_old TO mt_old.
  ENDMETHOD.

  METHOD add_expected.
    DATA ls_expected LIKE LINE OF mt_expected.

    ls_expected-new_num = iv_new_num.
    ls_expected-new     = iv_new.
    ls_expected-result  = iv_result.
    ls_expected-old_num = iv_old_num.
    ls_expected-old     = iv_old.
    ls_expected-beacon  = iv_beacon.
    APPEND ls_expected TO mt_expected.
  ENDMETHOD.

  METHOD setup.
    CLEAR mt_new.
    CLEAR mt_old.
    CLEAR mt_expected.
  ENDMETHOD.

  METHOD test.

    DATA: lv_new  TYPE string,
          lv_xnew TYPE xstring,
          lv_old  TYPE string,
          lv_xold TYPE xstring,
          lo_diff TYPE REF TO zcl_abapgit_diff,
          lt_diff TYPE zif_abapgit_definitions=>ty_diffs_tt.

    FIELD-SYMBOLS: <ls_diff> LIKE LINE OF lt_diff.

    CONCATENATE LINES OF mt_new INTO lv_new SEPARATED BY zif_abapgit_definitions=>c_newline.
    CONCATENATE LINES OF mt_old INTO lv_old SEPARATED BY zif_abapgit_definitions=>c_newline.

    lv_xnew = zcl_abapgit_convert=>string_to_xstring_utf8( lv_new ).
    lv_xold = zcl_abapgit_convert=>string_to_xstring_utf8( lv_old ).

    CREATE OBJECT lo_diff
      EXPORTING
        iv_new                = lv_xnew
        iv_old                = lv_xold
        iv_ignore_indentation = iv_ignore_indentation
        iv_ignore_comments    = iv_ignore_comments
        iv_ignore_case        = iv_ignore_case.

    lt_diff = lo_diff->get( ).

    LOOP AT lt_diff ASSIGNING <ls_diff>.
      CLEAR <ls_diff>-short.
    ENDLOOP.

    cl_abap_unit_assert=>assert_equals( act = lt_diff
                                        exp = mt_expected ).

  ENDMETHOD.

  METHOD diff01.

    "insert
    add_new( iv_new = 'A' ).

    add_expected( iv_new_num = '    1'
                  iv_new     = 'A'
                  iv_result  = zif_abapgit_definitions=>c_diff-insert
                  iv_old_num = ''
                  iv_old     = '' ).
    test( ).

  ENDMETHOD.

  METHOD diff02.

    " identical
    add_new( iv_new = 'A' ).
    add_old( iv_old = 'A' ).

    add_expected( iv_new_num = '    1'
                  iv_new     = 'A'
                  iv_result  = ''
                  iv_old_num = '    1'
                  iv_old     = 'A' ).
    test( ).

  ENDMETHOD.

  METHOD diff03.

    " delete
    add_old( iv_old = 'A' ).

    add_expected( iv_new_num = ''
                  iv_new     = ''
                  iv_result  = zif_abapgit_definitions=>c_diff-delete
                  iv_old_num = '    1'
                  iv_old     = 'A' ).
    test( ).

  ENDMETHOD.

  METHOD diff04.

    " update
    add_new( iv_new = 'A+' ).

    add_old( iv_old = 'A' ).

    add_expected( iv_new_num = '    1'
                  iv_new     = 'A+'
                  iv_result  = zif_abapgit_definitions=>c_diff-update
                  iv_old_num = '    1'
                  iv_old     = 'A' ).
    test( ).

  ENDMETHOD.

  METHOD diff05.

    " identical
    add_new( iv_new = 'A' ).
    add_new( iv_new = 'B' ).

    add_old( iv_old = 'A' ).
    add_old( iv_old = 'B' ).

    add_expected( iv_new_num = '    1'
                  iv_new     = 'A'
                  iv_result  = ''
                  iv_old_num = '    1'
                  iv_old     = 'A' ).
    add_expected( iv_new_num = '    2'
                  iv_new     = 'B'
                  iv_result  = ''
                  iv_old_num = '    2'
                  iv_old     = 'B' ).
    test( ).

  ENDMETHOD.

  METHOD diff06.

    " mixed
    add_new( iv_new = 'A' ).
    add_new( iv_new = 'B' ).
    add_new( iv_new = 'inserted' ).
    add_new( iv_new = 'C' ).
    add_new( iv_new = 'D update' ).

    add_old( iv_old = 'A' ).
    add_old( iv_old = 'B' ).
    add_old( iv_old = 'C' ).
    add_old( iv_old = 'D' ).

    add_expected( iv_new_num = '    1'
                  iv_new     = 'A'
                  iv_result  = ''
                  iv_old_num = '    1'
                  iv_old     = 'A' ).
    add_expected( iv_new_num = '    2'
                  iv_new     = 'B'
                  iv_result  = ''
                  iv_old_num = '    2'
                  iv_old     = 'B' ).
    add_expected( iv_new_num = '    3'
                  iv_new     = 'inserted'
                  iv_result  = zif_abapgit_definitions=>c_diff-insert
                  iv_old_num = ''
                  iv_old     = '' ).
    add_expected( iv_new_num = '    4'
                  iv_new     = 'C'
                  iv_result  = ''
                  iv_old_num = '    3'
                  iv_old     = 'C' ).
    add_expected( iv_new_num = '    5'
                  iv_new     = 'D update'
                  iv_result  = zif_abapgit_definitions=>c_diff-update
                  iv_old_num = '    4'
                  iv_old     = 'D' ).

    test( ).

  ENDMETHOD.

  METHOD diff07.

    " ignore indentation
    add_new( iv_new = 'A' ).
    add_new( iv_new = ' B' ). " changed indent
    add_new( iv_new = 'C' ).
    add_new( iv_new = '    D' ). " changed indent

    add_old( iv_old = 'A' ).
    add_old( iv_old = 'B' ).
    add_old( iv_old = 'C' ).
    add_old( iv_old = 'D' ).

    add_expected( iv_new_num = '    1'
                  iv_new     = 'A'
                  iv_result  = ''
                  iv_old_num = '    1'
                  iv_old     = 'A' ).
    add_expected( iv_new_num = '    2'
                  iv_new     = ' B'
                  iv_result  = '' " no diff!
                  iv_old_num = '    2'
                  iv_old     = 'B' ).
    add_expected( iv_new_num = '    3'
                  iv_new     = 'C'
                  iv_result  = ''
                  iv_old_num = '    3'
                  iv_old     = 'C' ).
    add_expected( iv_new_num = '    4'
                  iv_new     = '    D'
                  iv_result  = '' " no diff!
                  iv_old_num = '    4'
                  iv_old     = 'D' ).

    test( iv_ignore_indentation = abap_true ).

  ENDMETHOD.

  METHOD diff08.

    " ignore comments
    add_new( iv_new = 'A' ).
    add_new( iv_new = '* X' ). " changed comment
    add_new( iv_new = 'C' ).
    add_new( iv_new = 'D " new' ). " changed comment

    add_old( iv_old = 'A' ).
    add_old( iv_old = '* B' ).
    add_old( iv_old = 'C' ).
    add_old( iv_old = 'D " old' ).

    add_expected( iv_new_num = '    1'
                  iv_new     = 'A'
                  iv_result  = ''
                  iv_old_num = '    1'
                  iv_old     = 'A' ).
    add_expected( iv_new_num = '    2'
                  iv_new     = '* X'
                  iv_result  = '' " no diff!
                  iv_old_num = '    2'
                  iv_old     = '* B' ).
    add_expected( iv_new_num = '    3'
                  iv_new     = 'C'
                  iv_result  = ''
                  iv_old_num = '    3'
                  iv_old     = 'C' ).
    add_expected( iv_new_num = '    4'
                  iv_new     = 'D " new'
                  iv_result  = '' " no diff!
                  iv_old_num = '    4'
                  iv_old     = 'D " old' ).

    test( iv_ignore_comments = abap_true ).

  ENDMETHOD.

  METHOD diff09.

    " ignore case
    add_new( iv_new = 'A' ).
    add_new( iv_new = 'b' ). " changed case
    add_new( iv_new = 'c' ).
    add_new( iv_new = 'D' ). " changed case

    add_old( iv_old = 'A' ).
    add_old( iv_old = 'B' ).
    add_old( iv_old = 'c' ).
    add_old( iv_old = 'd' ).

    add_expected( iv_new_num = '    1'
                  iv_new     = 'A'
                  iv_result  = ''
                  iv_old_num = '    1'
                  iv_old     = 'A' ).
    add_expected( iv_new_num = '    2'
                  iv_new     = 'b'
                  iv_result  = '' " no diff!
                  iv_old_num = '    2'
                  iv_old     = 'B' ).
    add_expected( iv_new_num = '    3'
                  iv_new     = 'c'
                  iv_result  = ''
                  iv_old_num = '    3'
                  iv_old     = 'c' ).
    add_expected( iv_new_num = '    4'
                  iv_new     = 'D'
                  iv_result  = '' " no diff!
                  iv_old_num = '    4'
                  iv_old     = 'd' ).

    test( iv_ignore_case = abap_true ).

  ENDMETHOD.

  METHOD diff10.

    " ignore case should NOT ignore changed literals
    add_new( iv_new = `WRITE 'TEST'` ).

    add_old( iv_old = `WRITE 'test'` ).

    add_expected( iv_new_num = '    1'
                  iv_new     = `WRITE 'TEST'`
                  iv_result  = 'U'
                  iv_old_num = '    1'
                  iv_old     = `WRITE 'test'` ).

    test( iv_ignore_case = abap_true ).

  ENDMETHOD.

  METHOD diff11.

    " ignore case should ignore changed keywords, variables, types
    add_new( iv_new = `write 'test'` ).
    add_new( iv_new = `DATA FOO TYPE I.` ).

    add_old( iv_old = `WRITE 'test'` ).
    add_old( iv_old = `DATA foo TYPE i.` ).

    add_expected( iv_new_num = '    1'
                  iv_new     = `write 'test'`
                  iv_result  = '' " no diff!
                  iv_old_num = '    1'
                  iv_old     = `WRITE 'test'` ).
    add_expected( iv_new_num = '    2'
                  iv_new     = `DATA FOO TYPE I.`
                  iv_result  = '' " no diff!
                  iv_old_num = '    2'
                  iv_old     = `DATA foo TYPE i.` ).

    test( iv_ignore_case = abap_true ).

  ENDMETHOD.

  METHOD diff12.

    " adjusted diffs for insert (workaround for kernel issue)
    add_new( iv_new = `REPORT zprog_diff.` ).
    add_new( iv_new = `*` ).
    add_new( iv_new = `FORM t_1.` ).
    add_new( iv_new = `ENDFORM.` ).
    add_new( iv_new = `FORM t_2.` ).
    add_new( iv_new = `ENDFORM.` ).

    add_old( iv_old = `REPORT zprog_diff.` ).
    add_old( iv_old = `FORM t_1.` ).
    add_old( iv_old = `ENDFORM.` ).

    add_expected( iv_new_num = '    1'
                  iv_new     = `REPORT zprog_diff.`
                  iv_result  = '' " no diff!
                  iv_old_num = '    1'
                  iv_old     = `REPORT zprog_diff.`
                  iv_beacon  = 1 ).
    add_expected( iv_new_num = '    2'
                  iv_new     = `*`
                  iv_result  = 'I'
                  iv_old_num = '     '
                  iv_old     = ``
                  iv_beacon  = 1 ).
    add_expected( iv_new_num = '    3'
                  iv_new     = `FORM t_1.`
                  iv_result  = '' " no diff!
                  iv_old_num = '    2'
                  iv_old     = `FORM t_1.`
                  iv_beacon  = 2 ).
    add_expected( iv_new_num = '    4'
                  iv_new     = `ENDFORM.`
                  iv_result  = '' " no diff!
                  iv_old_num = '    3'
                  iv_old     = `ENDFORM.`
                  iv_beacon  = 2 ).
    add_expected( iv_new_num = '    5'
                  iv_new     = `FORM t_2.`
                  iv_result  = 'I'
                  iv_old_num = '     '
                  iv_old     = ``
                  iv_beacon  = 3 ).
    add_expected( iv_new_num = '    6'
                  iv_new     = `ENDFORM.`
                  iv_result  = 'I'
                  iv_old_num = '     '
                  iv_old     = ``
                  iv_beacon  = 3 ).

    test( ).

  ENDMETHOD.

  METHOD diff13.

    " adjusted diffs for delete (workaround for kernel issue)
    add_old( iv_old = `REPORT zprog_diff.` ).
    add_old( iv_old = `*` ).
    add_old( iv_old = `FORM t_1.` ).
    add_old( iv_old = `ENDFORM.` ).
    add_old( iv_old = `FORM t_2.` ).
    add_old( iv_old = `ENDFORM.` ).

    add_new( iv_new = `REPORT zprog_diff.` ).
    add_new( iv_new = `FORM t_1.` ).
    add_new( iv_new = `ENDFORM.` ).

    add_expected( iv_old_num = '    1'
                  iv_old     = `REPORT zprog_diff.`
                  iv_result  = '' " no diff!
                  iv_new_num = '    1'
                  iv_new     = `REPORT zprog_diff.`
                  iv_beacon  = 1 ).
    add_expected( iv_old_num = '    2'
                  iv_old     = `*`
                  iv_result  = 'D'
                  iv_new_num = '     '
                  iv_new     = ``
                  iv_beacon  = 1 ).
    add_expected( iv_old_num = '    3'
                  iv_old     = `FORM t_1.`
                  iv_result  = '' " no diff!
                  iv_new_num = '    2'
                  iv_new     = `FORM t_1.`
                  iv_beacon  = 2 ).
    add_expected( iv_old_num = '    4'
                  iv_old     = `ENDFORM.`
                  iv_result  = '' " no diff!
                  iv_new_num = '    3'
                  iv_new     = `ENDFORM.`
                  iv_beacon  = 2 ).
    add_expected( iv_old_num = '    5'
                  iv_old     = `FORM t_2.`
                  iv_result  = 'D'
                  iv_new_num = '     '
                  iv_new     = ``
                  iv_beacon  = 2 ).
    add_expected( iv_old_num = '    6'
                  iv_old     = `ENDFORM.`
                  iv_result  = 'D'
                  iv_new_num = '     '
                  iv_new     = ``
                  iv_beacon  = 2 ).

    test( ).

  ENDMETHOD.

ENDCLASS.


*----------------------------------------------------------------------*
*       CLASS lcl_Test DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS ltcl_test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.

  PRIVATE SECTION.
* ================

    DATA: mt_code   TYPE string_table,
          ms_result TYPE scirest_ad,
          mo_check  TYPE REF TO zcl_aoc_check_62.

    METHODS:
      setup,
      export_import FOR TESTING,
      test001_01 FOR TESTING,
      test001_02 FOR TESTING,
      test001_03 FOR TESTING,
      test001_04 FOR TESTING,
      test001_05 FOR TESTING,
      test002_01 FOR TESTING,
      test002_02 FOR TESTING,
      test002_03 FOR TESTING,
      test003_01 FOR TESTING,
      test003_02 FOR TESTING,
      test003_03 FOR TESTING.

ENDCLASS.       "lcl_Test

*----------------------------------------------------------------------*
*       CLASS lcl_Test IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS ltcl_test IMPLEMENTATION.
* ==============================

  DEFINE _code.
    APPEND &1 TO mt_code.
  END-OF-DEFINITION.

  METHOD setup.
    CREATE OBJECT mo_check.
    zcl_aoc_unit_test=>set_check( mo_check ).
  ENDMETHOD.                    "setup

  METHOD export_import.
    zcl_aoc_unit_test=>export_import( mo_check ).
  ENDMETHOD.

  METHOD test001_01.
* ===========

    _code 'LOOP AT lt_tab ASSIGNING <fs> WHERE foo = ''ABC''.'.
    _code '  DELETE lt_tab FROM <fs>.'.
    _code 'ENDLOOP.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '001'
                                        act = ms_result-code ).

  ENDMETHOD.                    "test1

  METHOD test001_02.
* ===========

    _code 'DELETE lt_tab WHERE foo = ''ABC''.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result-code ).

  ENDMETHOD.

  METHOD test001_03.
* ===========

    _code 'LOOP AT lt_tab INTO bar WHERE foo = ''ABC''.'.
    _code '  DELETE lt_tab FROM bar.'.
    _code 'ENDLOOP.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '001'
                                        act = ms_result-code ).

  ENDMETHOD.                    "test1

  METHOD test001_04.
* ===========

    _code 'LOOP AT lt_tab INTO DATA(bar) WHERE foo = ''ABC''.'.
    _code '  DELETE lt_tab FROM bar.'.
    _code 'ENDLOOP.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '001'
                                        act = ms_result-code ).

  ENDMETHOD.

  METHOD test001_05.
* ===========

    _code 'LOOP AT lt_tab ASSIGNING FIELD-SYMBOL(<bar>) WHERE foo = ''ABC''.'.
    _code '  DELETE lt_tab FROM <bar>.'.
    _code 'ENDLOOP.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '001'
                                        act = ms_result-code ).

  ENDMETHOD.

  METHOD test002_01.

    _code 'LOOP AT lt_tab.'.
    _code '  CONTINUE.'.
    _code 'ENDLOOP.'.
    _code 'WRITE hello.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '002'
                                        act = ms_result-code ).

  ENDMETHOD.

  METHOD test002_02.

    _code 'LOOP AT lt_tab.'.
    _code 'ENDLOOP.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result-code ).

  ENDMETHOD.

  METHOD test002_03.

    _code 'WRITE hello.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result-code ).

  ENDMETHOD.

  METHOD test003_01.

    _code 'IF lt_table IS NOT INITIAL.'.
    _code 'LOOP AT lt_table INTO ls_data.'.
    _code 'ENDLOOP.'.
    _code 'ENDIF.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '003'
                                        act = ms_result-code ).

  ENDMETHOD.

  METHOD test003_02.

    _code 'IF lines( lt_messages ) > 0.'.
    _code 'LOOP AT lt_messages INTO ls_message WHERE foo = ''A''.'.
    _code 'ENDLOOP.'.
    _code 'ENDIF.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_equals( exp = '003'
                                        act = ms_result-code ).

  ENDMETHOD.

  METHOD test003_03.

    _code 'LOOP AT lt_table INTO ls_data.'.
    _code 'ENDLOOP.'.

    ms_result = zcl_aoc_unit_test=>check( mt_code ).

    cl_abap_unit_assert=>assert_initial( ms_result-code ).

  ENDMETHOD.

ENDCLASS.