CLASS zcl_abapgit_gui_page_sett_repo DEFINITION
  PUBLIC
  INHERITING FROM zcl_abapgit_gui_component
  FINAL
  CREATE PRIVATE .

  PUBLIC SECTION.

    INTERFACES zif_abapgit_gui_event_handler .
    INTERFACES zif_abapgit_gui_renderable .

    CLASS-METHODS create
      IMPORTING
        !io_repo       TYPE REF TO zcl_abapgit_repo
      RETURNING
        VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable
      RAISING
        zcx_abapgit_exception .
    METHODS constructor
      IMPORTING
        !io_repo TYPE REF TO zcl_abapgit_repo
      RAISING
        zcx_abapgit_exception .

  PROTECTED SECTION.
  PRIVATE SECTION.

    CONSTANTS:
      BEGIN OF c_id,
        dot             TYPE string VALUE 'dot',
        main_language   TYPE string VALUE 'main_language',
        i18n_langs      TYPE string VALUE 'i18n_langs',
        starting_folder TYPE string VALUE 'starting_folder',
        folder_logic    TYPE string VALUE 'folder_logic',
        ignore          TYPE string VALUE 'ignore',
        requirements    TYPE string VALUE 'requirements',
      END OF c_id .
    CONSTANTS:
      BEGIN OF c_event,
        save TYPE string VALUE 'save',
      END OF c_event .
    CONSTANTS c_empty_rows TYPE i VALUE 2 ##NO_TEXT.

    DATA mo_form TYPE REF TO zcl_abapgit_html_form .
    DATA mo_form_data TYPE REF TO zcl_abapgit_string_map .
    DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils .
    DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map .

    DATA mo_repo TYPE REF TO zcl_abapgit_repo .
    DATA mv_requirements_count TYPE i .

    METHODS validate_form
      IMPORTING
        !io_form_data            TYPE REF TO zcl_abapgit_string_map
      RETURNING
        VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map
      RAISING
        zcx_abapgit_exception .
    METHODS get_form_schema
      RETURNING
        VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form
      RAISING
        zcx_abapgit_exception .
    METHODS read_settings
      RAISING
        zcx_abapgit_exception .
    METHODS save_settings
      RAISING
        zcx_abapgit_exception .
ENDCLASS.

CLASS zcl_abapgit_gui_page_sett_repo IMPLEMENTATION.

  METHOD constructor.

    super->constructor( ).
    CREATE OBJECT mo_validation_log.
    CREATE OBJECT mo_form_data.
    mo_repo = io_repo.
    mo_form = get_form_schema( ).
    mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ).

    read_settings( ).

  ENDMETHOD.

  METHOD create.

    DATA lo_component TYPE REF TO zcl_abapgit_gui_page_sett_repo.

    CREATE OBJECT lo_component
      EXPORTING
        io_repo = io_repo.

    ri_page = zcl_abapgit_gui_page_hoc=>create(
      iv_page_title      = 'Repository Settings'
      io_page_menu       = zcl_abapgit_gui_chunk_lib=>settings_repo_toolbar(
                             iv_key = io_repo->get_key( )
                             iv_act = zif_abapgit_definitions=>c_action-repo_settings )
      ii_child_component = lo_component ).

  ENDMETHOD.

  METHOD get_form_schema.

    ro_form = zcl_abapgit_html_form=>create(
                iv_form_id   = 'repo-settings-form'
                iv_help_page = '' ).

    ro_form->start_group(
      iv_name        = c_id-dot
      iv_label       = 'Repository Settings (.abapgit.xml)'
      iv_hint        = 'Settings stored in root folder in .abapgit.xml file'
    )->text(
      iv_name        = c_id-main_language
      iv_label       = 'Main Language'
      iv_hint        = 'Main language of repository (cannot be changed)'
      iv_readonly    = abap_true
    )->text(
      iv_name        = c_id-i18n_langs
      iv_label       = 'Serialize Translations (experimental LXE approach)'
      iv_hint        = 'Comma-separate 2-letter ISO language codes e.g. "DE,ES,..." - should not include main language'
    )->radio(
      iv_name        = c_id-folder_logic
      iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_label       = 'Folder Logic'
      iv_hint        = 'Define how package folders are named in repository'
    )->option(
      iv_label       = 'Prefix'
      iv_value       = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
    )->option(
      iv_label       = 'Full'
      iv_value       = zif_abapgit_dot_abapgit=>c_folder_logic-full
    )->text(
      iv_name        = c_id-starting_folder
      iv_label       = 'Starting Folder'
      iv_hint        = 'Root folder that defines where serialization starts'
    )->textarea(
      iv_name        = c_id-ignore
      iv_label       = 'Ignore Files'
      iv_hint        = 'List of files in starting folder that shall not be serialized'
    )->table(
      iv_name        = c_id-requirements
      iv_label       = 'Requirements'
      iv_hint        = 'List of software components with minimum release and patch'
    )->column(
      iv_label       = 'Software Component'
      iv_width       = '40%'
    )->column(
      iv_label       = 'Minimum Release'
      iv_width       = '30%'
    )->column(
      iv_label       = 'Minimum Patch'
      iv_width       = '30%'
    )->command(
      iv_label       = 'Save Settings'
      iv_cmd_type    = zif_abapgit_html_form=>c_cmd_type-input_main
      iv_action      = c_event-save
    )->command(
      iv_label       = 'Back'
      iv_action      = zif_abapgit_definitions=>c_action-go_back ).

  ENDMETHOD.

  METHOD read_settings.

    DATA:
      lo_dot          TYPE REF TO zcl_abapgit_dot_abapgit,
      ls_dot          TYPE zif_abapgit_dot_abapgit=>ty_dot_abapgit,
      lv_main_lang    TYPE spras,
      lv_language     TYPE t002t-sptxt,
      lv_ignore       TYPE string,
      ls_requirements LIKE LINE OF ls_dot-requirements,
      lv_row          TYPE i,
      lv_val          TYPE string.

    FIELD-SYMBOLS:
      <lv_ignore> TYPE string.

    " Get settings from DB
    lo_dot = mo_repo->get_dot_abapgit( ).
    ls_dot = lo_dot->get_data( ).
    lv_main_lang = lo_dot->get_main_language( ).

    " Repository Settings
    SELECT SINGLE sptxt INTO lv_language FROM t002t
      WHERE spras = sy-langu AND sprsl = lv_main_lang.
    IF sy-subrc <> 0.
      lv_language = 'Unknown language; Check your .abapgit.xml file'.
    ENDIF.

    mo_form_data->set(
      iv_key = c_id-main_language
      iv_val = |{ lv_main_lang } ({ lv_language })| ).
    mo_form_data->set(
      iv_key = c_id-i18n_langs
      iv_val = zcl_abapgit_lxe_texts=>convert_table_to_lang_string( lo_dot->get_i18n_languages( ) ) ).
    mo_form_data->set(
      iv_key = c_id-folder_logic
      iv_val = ls_dot-folder_logic ).
    mo_form_data->set(
      iv_key = c_id-starting_folder
      iv_val = ls_dot-starting_folder ).

    LOOP AT ls_dot-ignore ASSIGNING <lv_ignore>.
      lv_ignore = lv_ignore && <lv_ignore> && zif_abapgit_definitions=>c_newline.
    ENDLOOP.
    IF sy-subrc <> 0.
      lv_ignore = zif_abapgit_definitions=>c_newline.
    ENDIF.

    mo_form_data->set(
      iv_key = c_id-ignore
      iv_val = lv_ignore ).

    LOOP AT ls_dot-requirements INTO ls_requirements.
      lv_row = lv_row + 1.
      DO 3 TIMES.
        CASE sy-index.
          WHEN 1.
            lv_val = ls_requirements-component.
          WHEN 2.
            lv_val = ls_requirements-min_release.
          WHEN 3.
            lv_val = ls_requirements-min_patch.
        ENDCASE.
        mo_form_data->set(
          iv_key = |{ c_id-requirements }-{ lv_row }-{ sy-index }|
          iv_val = lv_val ).
      ENDDO.
    ENDLOOP.

    DO c_empty_rows TIMES.
      lv_row = lv_row + 1.
      DO 3 TIMES.
        mo_form_data->set(
          iv_key = |{ c_id-requirements }-{ lv_row }-{ sy-index }|
          iv_val = '' ).
      ENDDO.
    ENDDO.

    mv_requirements_count = lv_row.

    mo_form_data->set(
      iv_key = |{ c_id-requirements }-{ zif_abapgit_html_form=>c_rows }|
      iv_val = |{ mv_requirements_count }| ).

    " Set for is_dirty check
    mo_form_util->set_data( mo_form_data ).

  ENDMETHOD.

  METHOD save_settings.

    DATA:
      lo_dot          TYPE REF TO zcl_abapgit_dot_abapgit,
      lv_ignore       TYPE string,
      lt_ignore       TYPE STANDARD TABLE OF string WITH DEFAULT KEY,
      ls_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement,
      lt_requirements TYPE zif_abapgit_dot_abapgit=>ty_requirement_tt.

    lo_dot = mo_repo->get_dot_abapgit( ).

    lo_dot->set_folder_logic( mo_form_data->get( c_id-folder_logic ) ).
    lo_dot->set_starting_folder( mo_form_data->get( c_id-starting_folder ) ).

    lo_dot->set_i18n_languages(
      zcl_abapgit_lxe_texts=>convert_lang_string_to_table(
        iv_langs              = mo_form_data->get( c_id-i18n_langs )
        iv_skip_main_language = lo_dot->get_main_language( ) ) ).

    " Remove all ignores
    lt_ignore = lo_dot->get_data( )-ignore.
    LOOP AT lt_ignore INTO lv_ignore.
      lo_dot->remove_ignore( iv_path = ''
                             iv_filename = lv_ignore ).
    ENDLOOP.

    " Add newly entered ignores
    lt_ignore = zcl_abapgit_convert=>split_string( mo_form_data->get( c_id-ignore ) ).
    LOOP AT lt_ignore INTO lv_ignore WHERE table_line IS NOT INITIAL.
      lo_dot->add_ignore( iv_path = ''
                          iv_filename = lv_ignore ).
    ENDLOOP.

    " Requirements
    DO mv_requirements_count TIMES.
      ls_requirements-component   = to_upper( mo_form_data->get( |{ c_id-requirements }-{ sy-index }-1| ) ).
      ls_requirements-min_release = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-2| ).
      ls_requirements-min_patch   = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-3| ).
      APPEND ls_requirements TO lt_requirements.
    ENDDO.

    SORT lt_requirements BY component min_release min_patch.
    DELETE lt_requirements WHERE component IS INITIAL.
    DELETE ADJACENT DUPLICATES FROM lt_requirements COMPARING ALL FIELDS.

    lo_dot->set_requirements( lt_requirements ).

    mo_repo->set_dot_abapgit( lo_dot ).
    mo_repo->refresh( ).

    COMMIT WORK AND WAIT.

    MESSAGE 'Settings succesfully saved' TYPE 'S'.

    read_settings( ).

  ENDMETHOD.

  METHOD validate_form.

    DATA:
      lv_folder      TYPE string,
      lv_len         TYPE i,
      lv_component   TYPE zif_abapgit_dot_abapgit=>ty_requirement-component,
      lv_min_release TYPE zif_abapgit_dot_abapgit=>ty_requirement-min_release,
      lv_min_patch   TYPE zif_abapgit_dot_abapgit=>ty_requirement-min_patch.

    ro_validation_log = mo_form_util->validate( io_form_data ).

    lv_folder = io_form_data->get( c_id-starting_folder ).
    lv_len = strlen( lv_folder ) - 1.
    IF lv_len > 0 AND lv_folder(1) <> '/'.
      ro_validation_log->set(
        iv_key = c_id-starting_folder
        iv_val = |The folder must begin with /| ).
    ELSEIF lv_len > 0 AND lv_folder+lv_len(1) <> '/'.
      ro_validation_log->set(
        iv_key = c_id-starting_folder
        iv_val = |The folder must end with /| ).
    ELSEIF lv_folder CA '\'.
      ro_validation_log->set(
        iv_key = c_id-starting_folder
        iv_val = |Use / instead of \\| ).
    ENDIF.

    DO mv_requirements_count TIMES.
      lv_component   = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-1| ).
      lv_min_release = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-2| ).
      lv_min_patch   = mo_form_data->get( |{ c_id-requirements }-{ sy-index }-3| ).

      IF lv_component IS INITIAL AND ( lv_min_release IS NOT INITIAL OR lv_min_patch IS NOT INITIAL ).
        ro_validation_log->set(
          iv_key = c_id-requirements
          iv_val = |If you enter a release or patch, you must also enter a software component| ).
      ELSEIF lv_component IS NOT INITIAL AND lv_min_release IS INITIAL.
        ro_validation_log->set(
          iv_key = c_id-requirements
          iv_val = |If you enter a software component, you must also enter a minumum release| ).
      ENDIF.
    ENDDO.

  ENDMETHOD.

  METHOD zif_abapgit_gui_event_handler~on_event.

    mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ).

    CASE ii_event->mv_action.
      WHEN zif_abapgit_definitions=>c_action-go_back.
        rs_handled-state = mo_form_util->exit( mo_form_data ).

      WHEN c_event-save.
        " Validate all form entries
        mo_validation_log = validate_form( mo_form_data ).

        IF mo_validation_log->is_empty( ) = abap_true.
          save_settings( ).
        ENDIF.

        rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render.

    ENDCASE.

  ENDMETHOD.

  METHOD zif_abapgit_gui_renderable~render.

    gui_services( )->register_event_handler( me ).

    IF mo_form_util->is_empty( mo_form_data ) = abap_true.
      read_settings( ).
    ENDIF.

    CREATE OBJECT ri_html TYPE zcl_abapgit_html.

    ri_html->add( `<div class="repo">` ).

    ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top(
                    io_repo               = mo_repo
                    iv_show_commit        = abap_false
                    iv_interactive_branch = abap_true ) ).

    ri_html->add( mo_form->render(
      io_values         = mo_form_data
      io_validation_log = mo_validation_log ) ).

    ri_html->add( `</div>` ).

  ENDMETHOD.
ENDCLASS.


CLASS y_exemption_of_class DEFINITION PUBLIC CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES y_if_exemption_of_object.
    ALIASES is_exempted FOR y_if_exemption_of_object~is_exempted.

  PRIVATE SECTION.
    CLASS-DATA class_header_data TYPE seoclassdf.

    CLASS-METHODS is_srv_maint_ui_generate RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_odata_generate RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_ecatt_odata_test_generate RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_fin_infotype_generate RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_extensibility_generate RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_shma_generate RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_proxy_generate RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_sadl_generate RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_exit_class RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_exception_class RETURNING VALUE(result) TYPE abap_bool.
    CLASS-METHODS is_bcp_application RETURNING VALUE(result) TYPE abap_bool.

ENDCLASS.

CLASS y_exemption_of_class IMPLEMENTATION.

  METHOD y_if_exemption_of_object~is_exempted.
    result = abap_true.

    SELECT SINGLE *
    FROM seoclassdf
    INTO @class_header_data
    WHERE clsname = @object_name
    AND version = 1.

    IF sy-subrc = 0.
      result = xsdbool( is_srv_maint_ui_generate( ) = abap_true OR
                        is_odata_generate( ) = abap_true OR
                        is_ecatt_odata_test_generate( ) = abap_true OR
                        is_fin_infotype_generate(  ) = abap_true OR
                        is_extensibility_generate(  ) = abap_true OR
                        is_shma_generate(  ) = abap_true OR
                        is_proxy_generate(  ) = abap_true OR
                        is_sadl_generate(  ) = abap_true OR
                        is_exit_class(  ) = abap_true OR
                        is_exception_class(  ) = abap_true OR
                        is_bcp_application( ) = abap_true ).
    ENDIF.
  ENDMETHOD.

  METHOD is_bcp_application.
    DATA it_bsp_classes TYPE STANDARD TABLE OF seoclsname.

    it_bsp_classes = VALUE #( ( 'CL_BSP_WD_COMPONENT_CONTROLLER' )
                              ( 'CL_BSP_WD_CONTEXT' )
                              ( 'CL_BSP_WD_CONTEXT_NODE' )
                              ( 'CL_BSP_WD_WINDOW' )
                              ( 'CL_BSP_WD_CUSTOM_CONTROLLER' )
                              ( 'CL_BSP_WD_VIEW_CONTROLLER' )
                              ( 'CL_BSP_WD_ADVSEARCH_CONTROLLER' )
                              ( 'CL_BSP_WD_CONTEXT_NODE_ASP' ) ).

    SELECT SINGLE refclsname FROM seometarel
      WHERE clsname = @class_header_data-clsname AND refclsname IS NOT NULL
      INTO @DATA(inherited_by).
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    "Multi Inheritance
    DO.
      LOOP AT it_bsp_classes TRANSPORTING NO FIELDS WHERE table_line = inherited_by.
        result = abap_true.
        RETURN.
      ENDLOOP.

      SELECT SINGLE refclsname FROM seometarel
        WHERE clsname = @inherited_by AND refclsname IS NOT NULL
        INTO @inherited_by.
      IF sy-subrc = 4.
        RETURN.
      ENDIF.
    ENDDO.
  ENDMETHOD.

  METHOD is_ecatt_odata_test_generate.
    SELECT SINGLE @abap_true
    FROM seoclassdf
    INTO @result
    WHERE clsname = @class_header_data-clsname
    AND author = 'eCATTClassGe'.
  ENDMETHOD.

  METHOD is_exception_class.
    CONSTANTS exception_clase_type LIKE class_header_data-category VALUE '40'.
    IF class_header_data-category = exception_clase_type.
      result = abap_true.
    ENDIF.
  ENDMETHOD.

  METHOD is_exit_class.
    CONSTANTS exit_class_type LIKE class_header_data-category VALUE '01'.
    IF class_header_data-category = exit_class_type.
      result = abap_true.
    ENDIF.
  ENDMETHOD.

  METHOD is_extensibility_generate.
    DATA: lt_interfaces TYPE seor_implementing_keys.
    DATA: lv_seoclskey TYPE  seoclskey.

    lv_seoclskey = class_header_data-clsname.

    CALL FUNCTION 'SEO_CLASS_ALL_IMPLEMENTG_GET'
      EXPORTING
        clskey       = lv_seoclskey
      IMPORTING
        set          = lt_interfaces
      EXCEPTIONS
        not_existing = 1
        is_interface = 2
        model_only   = 3
        OTHERS       = 4.
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    LOOP AT lt_interfaces TRANSPORTING NO FIELDS
      WHERE refclsname = 'IF_CFD_ODATA_MPC_FLX' OR refclsname = 'IF_CFD_ODATA_DPC_FLX'.
      result = abap_true.
      RETURN.
    ENDLOOP.
  ENDMETHOD.

  METHOD is_fin_infotype_generate.
    SELECT SINGLE @abap_true
    FROM t777ditclass
    INTO @result
    WHERE idclass = @class_header_data-clsname
    OR cont_db = @class_header_data-clsname
    OR bl_class = @class_header_data-clsname.
  ENDMETHOD.

  METHOD is_odata_generate.
    SELECT SINGLE @abap_true
    FROM /iwbep/i_sbd_ga
    INTO @result
    WHERE ( gen_art_type = 'DPCB' OR gen_art_type = 'MPCB' )
    AND trobj_type = 'CLAS'
    AND trobj_name = @class_header_data-clsname. "#EC CI_NOFIELD
  ENDMETHOD.

  METHOD is_proxy_generate.
    result = xsdbool( class_header_data-clsproxy = abap_true ).
  ENDMETHOD.

  METHOD is_sadl_generate.
    SELECT SINGLE @abap_true
    FROM seoclasstx
    INTO @result
    WHERE clsname = @class_header_data-clsname
    AND descript = 'Generated by SADL Generation Toolkit' ##NO_TEXT.
  ENDMETHOD.

  METHOD is_shma_generate.
    SELECT SINGLE @abap_true
    FROM tadir
    INTO @result
    WHERE pgmid = 'R3TR'
    AND object = 'SHMA'
    AND obj_name = @class_header_data-clsname.
  ENDMETHOD.

  METHOD is_srv_maint_ui_generate.
    DATA: lt_interfaces TYPE seor_implementing_keys.
    DATA: lv_seoclskey TYPE seoclskey.
    lv_seoclskey = class_header_data-clsname.

    CALL FUNCTION 'SEO_CLASS_ALL_IMPLEMENTG_GET'
      EXPORTING
        clskey       = lv_seoclskey
      IMPORTING
        set          = lt_interfaces
      EXCEPTIONS
        not_existing = 1
        is_interface = 2
        model_only   = 3
        OTHERS       = 4.
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.
    LOOP AT lt_interfaces TRANSPORTING NO FIELDS
      WHERE refclsname = '/FTI/IF_FTI_MODEL' OR refclsname = '/FTI/IF_NATIVE_SQL_GENERATOR'.
      result = abap_true.
      RETURN.
    ENDLOOP.
  ENDMETHOD.

ENDCLASS.


CLASS ltcl_abapgit_tadir_mock DEFINITION FOR TESTING.

  PUBLIC SECTION.
    INTERFACES: zif_abapgit_tadir.

ENDCLASS.

CLASS ltcl_no_dependency_injection DEFINITION FOR TESTING
                              RISK LEVEL HARMLESS
                              DURATION SHORT.

  PRIVATE SECTION.
    METHODS:
      no_injection FOR TESTING RAISING cx_static_check.

ENDCLASS.

CLASS ltcl_simple_dependency_inject DEFINITION FOR TESTING
                                  RISK LEVEL HARMLESS
                                  DURATION SHORT.

  PRIVATE SECTION.
    METHODS:
      setup,
      simple_injection FOR TESTING RAISING cx_static_check.

ENDCLASS.

CLASS ltcl_abapgit_tadir_mock IMPLEMENTATION.

  METHOD zif_abapgit_tadir~get_object_package.

  ENDMETHOD.

  METHOD zif_abapgit_tadir~read.

  ENDMETHOD.

  METHOD zif_abapgit_tadir~read_single.

  ENDMETHOD.

ENDCLASS.

CLASS ltcl_no_dependency_injection IMPLEMENTATION.

  METHOD no_injection.

    DATA: li_tadir       TYPE REF TO zif_abapgit_tadir,
          lo_class_descr TYPE REF TO cl_abap_classdescr.

    li_tadir = zcl_abapgit_factory=>get_tadir( ).

    lo_class_descr ?= cl_abap_classdescr=>describe_by_object_ref( li_tadir ).

    cl_abap_unit_assert=>assert_equals(
      exp = '\CLASS=ZCL_ABAPGIT_TADIR'
      act = lo_class_descr->absolute_name ).

  ENDMETHOD.

ENDCLASS.

CLASS ltcl_simple_dependency_inject IMPLEMENTATION.

  METHOD setup.

    DATA: lo_tadir_mock  TYPE REF TO ltcl_abapgit_tadir_mock.

    CREATE OBJECT lo_tadir_mock.

    zcl_abapgit_injector=>set_tadir( lo_tadir_mock ).

  ENDMETHOD.

  METHOD simple_injection.

    DATA: li_tadir       TYPE REF TO zif_abapgit_tadir,
          lo_class_descr TYPE REF TO cl_abap_classdescr.

    li_tadir = zcl_abapgit_factory=>get_tadir( ).

    lo_class_descr ?= cl_abap_classdescr=>describe_by_object_ref( li_tadir ).

    cl_abap_unit_assert=>assert_equals(
      exp = '\CLASS-POOL=ZCL_ABAPGIT_INJECTOR\CLASS=LTCL_ABAPGIT_TADIR_MOCK'
      act = lo_class_descr->absolute_name ).

  ENDMETHOD.

ENDCLASS.


INTERFACE zif_abapgit_dot_abapgit PUBLIC.

  TYPES:
    BEGIN OF ty_requirement,
      component   TYPE tdevc-dlvunit,
      min_release TYPE saprelease,
      min_patch   TYPE sappatchlv,
    END OF ty_requirement .
  TYPES:
    ty_requirement_tt TYPE STANDARD TABLE OF ty_requirement WITH DEFAULT KEY .

  TYPES:
    BEGIN OF ty_dot_abapgit,
      master_language              TYPE spras,
      i18n_languages               TYPE zif_abapgit_definitions=>ty_languages,
      starting_folder              TYPE string,
      folder_logic                 TYPE string,
      ignore                       TYPE STANDARD TABLE OF string WITH DEFAULT KEY,
      requirements                 TYPE ty_requirement_tt,
    END OF ty_dot_abapgit .

  CONSTANTS:
    BEGIN OF c_folder_logic,
      prefix TYPE string VALUE 'PREFIX',
      full   TYPE string VALUE 'FULL',
    END OF c_folder_logic .

ENDINTERFACE.


CLASS zcl_abapgit_gui_page_addonline DEFINITION
  PUBLIC
  INHERITING FROM zcl_abapgit_gui_component
  FINAL
  CREATE PRIVATE.

  PUBLIC SECTION.

    INTERFACES zif_abapgit_gui_event_handler.
    INTERFACES zif_abapgit_gui_renderable.

    CLASS-METHODS create
      RETURNING
        VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable
      RAISING
        zcx_abapgit_exception.

    METHODS constructor
      RAISING
        zcx_abapgit_exception.

  PROTECTED SECTION.
  PRIVATE SECTION.

    CONSTANTS:
      BEGIN OF c_id,
        url                TYPE string VALUE 'url',
        package            TYPE string VALUE 'package',
        branch_name        TYPE string VALUE 'branch_name',
        display_name       TYPE string VALUE 'display_name',
        folder_logic       TYPE string VALUE 'folder_logic',
        ignore_subpackages TYPE string VALUE 'ignore_subpackages',
        main_lang_only     TYPE string VALUE 'main_lang_only',
      END OF c_id.

    CONSTANTS:
      BEGIN OF c_event,
        go_back         TYPE string VALUE 'go-back',
        choose_package  TYPE string VALUE 'choose-package',
        create_package  TYPE string VALUE 'create-package',
        choose_branch   TYPE string VALUE 'choose-branch',
        add_online_repo TYPE string VALUE 'add-repo-online',
      END OF c_event.

    DATA mo_form TYPE REF TO zcl_abapgit_html_form .
    DATA mo_form_data TYPE REF TO zcl_abapgit_string_map .
    DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils.
    DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map .

    METHODS validate_form
      IMPORTING
        io_form_data             TYPE REF TO zcl_abapgit_string_map
      RETURNING
        VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map
      RAISING
        zcx_abapgit_exception.

    METHODS get_form_schema
      RETURNING
        VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form.
ENDCLASS.

CLASS zcl_abapgit_gui_page_addonline IMPLEMENTATION.

  METHOD constructor.
    super->constructor( ).
    CREATE OBJECT mo_validation_log.
    CREATE OBJECT mo_form_data.
    mo_form = get_form_schema( ).
    mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ).
  ENDMETHOD.

  METHOD create.

    DATA lo_component TYPE REF TO zcl_abapgit_gui_page_addonline.

    CREATE OBJECT lo_component.

    ri_page = zcl_abapgit_gui_page_hoc=>create(
      iv_page_title      = 'New Online Repository'
      ii_child_component = lo_component ).

  ENDMETHOD.

  METHOD get_form_schema.

    ro_form = zcl_abapgit_html_form=>create(
                iv_form_id   = 'add-repo-online-form'
                iv_help_page = '' ).

    ro_form->text(
      iv_name        = c_id-url
      iv_required    = abap_true
      iv_condense    = abap_true
      iv_label       = 'Git Repository URL'
      iv_hint        = 'HTTPS address of the repository'
      iv_placeholder = ''
    )->text(
      iv_name        = c_id-package
      iv_side_action = c_event-choose_package
      iv_required    = abap_true
      iv_upper_case  = abap_true
      iv_label       = 'Package'
      iv_hint        = 'SAP package for repository (should be a dedicated one)'
      iv_placeholder = 'Z... / $...'
    )->text(
      iv_name        = c_id-branch_name
      iv_side_action = c_event-choose_branch
      iv_label       = 'Branch'
      iv_hint        = 'Switch to a specific branch (default: autodetect)'
      iv_placeholder = 'Autodetect default branch'
    )->radio(
      iv_name        = c_id-folder_logic
      iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_label       = 'Folder Logic'
      iv_hint        = 'Define how package folders are named in repository'
    )->option(
      iv_label       = 'Prefix'
      iv_value       = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
    )->option(
      iv_label       = 'Full'
      iv_value       = zif_abapgit_dot_abapgit=>c_folder_logic-full
    )->option(
      iv_label       = 'Mixed'
      iv_value       = zif_abapgit_dot_abapgit=>c_folder_logic-mixed
    )->text(
      iv_name        = c_id-display_name
      iv_label       = 'Display Name'
      iv_hint        = 'Name to show instead of original repository name (optional)'
    )->checkbox(
      iv_name        = c_id-ignore_subpackages
      iv_label       = 'Ignore Subpackages'
      iv_hint        = 'Synchronize root package only'
    )->checkbox(
      iv_name        = c_id-main_lang_only
      iv_label       = 'Serialize Main Language Only'
      iv_hint        = 'Ignore translations, serialize just main language'
    )->command(
      iv_label       = 'Create Online Repo'
      iv_cmd_type    = zif_abapgit_html_form=>c_cmd_type-input_main
      iv_action      = c_event-add_online_repo
    )->command(
      iv_label       = 'Create Package'
      iv_action      = c_event-create_package
    )->command(
      iv_label       = 'Back'
      iv_action      = c_event-go_back ).

  ENDMETHOD.

  METHOD validate_form.

    DATA lx_err TYPE REF TO zcx_abapgit_exception.

    ro_validation_log = mo_form_util->validate( io_form_data ).

    IF io_form_data->get( c_id-url ) IS NOT INITIAL.
      TRY.
          zcl_abapgit_repo_srv=>get_instance( )->validate_url( io_form_data->get( c_id-url ) ).
        CATCH zcx_abapgit_exception INTO lx_err.
          ro_validation_log->set(
            iv_key = c_id-url
            iv_val = lx_err->get_text( ) ).
      ENDTRY.
    ENDIF.

    IF io_form_data->get( c_id-package ) IS NOT INITIAL.
      TRY.
          zcl_abapgit_repo_srv=>get_instance( )->validate_package(
            iv_package    = |{ io_form_data->get( c_id-package ) }|
            iv_ign_subpkg = |{ io_form_data->get( c_id-ignore_subpackages ) }| ).
        CATCH zcx_abapgit_exception INTO lx_err.
          ro_validation_log->set(
            iv_key = c_id-package
            iv_val = lx_err->get_text( ) ).
      ENDTRY.
    ENDIF.

    IF io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-prefix
        AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-full
        AND io_form_data->get( c_id-folder_logic ) <> zif_abapgit_dot_abapgit=>c_folder_logic-mixed.
      ro_validation_log->set(
        iv_key = c_id-folder_logic
        iv_val = |Invalid folder logic { io_form_data->get( c_id-folder_logic ) }| ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_gui_event_handler~on_event.

    DATA: ls_repo_params     TYPE zif_abapgit_services_repo=>ty_repo_params,
          lo_new_online_repo TYPE REF TO zcl_abapgit_repo_online.

    mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ).

    CASE ii_event->mv_action.
      WHEN c_event-go_back.
        rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back.

      WHEN c_event-create_package.

        mo_form_data->set(
          iv_key = c_id-package
          iv_val = zcl_abapgit_services_basis=>create_package(
            iv_prefill_package = |{ mo_form_data->get( c_id-package ) }| ) ).
        IF mo_form_data->get( c_id-package ) IS NOT INITIAL.
          mo_validation_log = validate_form( mo_form_data ).
          rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render.
        ELSE.
          rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act.
        ENDIF.

      WHEN c_event-choose_package.

        mo_form_data->set(
          iv_key = c_id-package
          iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ).
        IF mo_form_data->get( c_id-package ) IS NOT INITIAL.
          mo_validation_log = validate_form( mo_form_data ).
          rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render.
        ELSE.
          rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act.
        ENDIF.

      WHEN c_event-choose_branch.

        mo_validation_log = validate_form( mo_form_data ).
        IF mo_validation_log->has( c_id-url ) = abap_true.
          mo_validation_log->set(
            iv_key = c_id-branch_name
            iv_val = 'Check URL issues' ).
          rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. " Display errors
          RETURN.
        ENDIF.
        mo_form_data->set(
          iv_key = c_id-branch_name
          iv_val = zcl_abapgit_ui_factory=>get_popups( )->branch_list_popup( mo_form_data->get( c_id-url ) )-name ).

        IF mo_form_data->get( c_id-branch_name ) IS INITIAL.
          rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act.
        ELSE.
          mo_form_data->set(
            iv_key = c_id-branch_name
            iv_val = replace( " strip technical
              val = mo_form_data->get( c_id-branch_name )
              sub = zif_abapgit_definitions=>c_git_branch-heads_prefix
              with = '' ) ).
          rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render.
        ENDIF.

      WHEN c_event-add_online_repo.

        mo_validation_log = validate_form( mo_form_data ).

        IF mo_validation_log->is_empty( ) = abap_true.
          mo_form_data->to_abap( CHANGING cs_container = ls_repo_params ).
          lo_new_online_repo = zcl_abapgit_services_repo=>new_online( ls_repo_params ).
          CREATE OBJECT rs_handled-page TYPE zcl_abapgit_gui_page_repo_view
            EXPORTING
              iv_key = lo_new_online_repo->get_key( ).
          rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page_replacing.
        ELSE.
          rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. " Display errors
        ENDIF.

    ENDCASE.

  ENDMETHOD.

  METHOD zif_abapgit_gui_renderable~render.

    gui_services( )->register_event_handler( me ).

    CREATE OBJECT ri_html TYPE zcl_abapgit_html.

    ri_html->add( mo_form->render(
      io_values         = mo_form_data
      io_validation_log = mo_validation_log ) ).

  ENDMETHOD.
ENDCLASS.


CLASS lcl_stack IMPLEMENTATION.

  METHOD push.
    APPEND iv_string TO mt_data.
  ENDMETHOD.

  METHOD concatenate.
    rv_string = concat_lines_of( mt_data ) && iv_string.
  ENDMETHOD.

  METHOD set.
    clear( ).
    push( iv_string ).
  ENDMETHOD.

  METHOD clear.
    CLEAR mt_data.
  ENDMETHOD.

  METHOD pop.
    IF lines( mt_data ) > 0.
      DELETE mt_data INDEX lines( mt_data ).
    ENDIF.
  ENDMETHOD.

ENDCLASS.


CLASS zcl_aoc_check_13 DEFINITION
  PUBLIC
  INHERITING FROM zcl_aoc_super
  CREATE PUBLIC .

  PUBLIC SECTION.

    METHODS constructor .

    METHODS check
        REDEFINITION .
    METHODS get_attributes
        REDEFINITION .
    METHODS if_ci_test~query_attributes
        REDEFINITION .
    METHODS put_attributes
        REDEFINITION .
  PROTECTED SECTION.

    DATA mv_lines TYPE linestotal .
  PRIVATE SECTION.
ENDCLASS.

CLASS ZCL_AOC_CHECK_13 IMPLEMENTATION.

  METHOD check.

* abapOpenChecks
*
* MIT License

    DATA: lt_code TYPE string_table,
          lv_seq  TYPE i,
          lv_line TYPE token_row.

    FIELD-SYMBOLS: <ls_level> LIKE LINE OF io_scan->levels,
                   <lv_code>  LIKE LINE OF lt_code.

    LOOP AT io_scan->levels ASSIGNING <ls_level> WHERE type = io_scan->gc_level-program.
      lt_code = get_source( <ls_level> ).

      LOOP AT lt_code ASSIGNING <lv_code>.
        lv_line = sy-tabix.

        IF strlen( <lv_code> ) = 0.
          lv_seq = lv_seq + 1.
        ELSE.
          lv_seq = 0.
        ENDIF.

        IF lv_seq >= mv_lines.
          inform( p_sub_obj_name = <ls_level>-name
                  p_line         = lv_line
                  p_kind         = mv_errty
                  p_test         = myname
                  p_code         = '001' ).
* only report one error per include
          EXIT. " current loop
        ENDIF.
      ENDLOOP.
    ENDLOOP.

  ENDMETHOD.

  METHOD constructor.

    super->constructor( ).

    version  = '001'.
    position = '013'.

    has_attributes = abap_true.
    attributes_ok  = abap_true.

    mv_lines = 4.

    enable_rfc( ).

    insert_scimessage(
        iv_code = '001'
        iv_text = 'Sequential blank lines'(m01) ).

  ENDMETHOD.

  METHOD get_attributes.

    EXPORT mv_errty = mv_errty mv_maxlength = mv_lines TO DATA BUFFER p_attributes.

  ENDMETHOD.

  METHOD if_ci_test~query_attributes.

    zzaoc_top.

    zzaoc_fill_att mv_errty 'Error Type' ''.                "#EC NOTEXT
    zzaoc_fill_att mv_lines 'Lines' ''.                     "#EC NOTEXT

    zzaoc_popup.

  ENDMETHOD.

  METHOD put_attributes.

    IMPORT
      mv_errty = mv_errty
      mv_maxlength = mv_lines
      FROM DATA BUFFER p_attributes.                 "#EC CI_USE_WANTED
    ASSERT sy-subrc = 0.

  ENDMETHOD.
ENDCLASS.


CLASS zcl_abapgit_object_fdt0 DEFINITION
  PUBLIC
  INHERITING FROM zcl_abapgit_objects_super
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES zif_abapgit_object .
  PROTECTED SECTION.

  PRIVATE SECTION.

    METHODS check_is_local
      RETURNING
        VALUE(rv_is_local) TYPE abap_bool .
    METHODS get_application_id
      RETURNING
        VALUE(rv_application_id) TYPE fdt_admn_0000s-application_id .
    METHODS before_xml_deserialize
      IMPORTING
        !iv_package  TYPE devclass
      EXPORTING
        !ev_create   TYPE abap_bool
        !ev_is_local TYPE abap_bool
      CHANGING
        !co_dom_tree TYPE REF TO if_ixml_document
      RAISING
        zcx_abapgit_exception .
    METHODS filter_xml_serialize
      CHANGING
        !co_ixml_element TYPE REF TO if_ixml_element
      RAISING
        zcx_abapgit_exception .
    METHODS set_field
      IMPORTING
        !iv_name         TYPE string
        !iv_value        TYPE string DEFAULT ''
      CHANGING
        !co_ixml_element TYPE REF TO if_ixml_element
      RAISING
        zcx_abapgit_exception .
ENDCLASS.

CLASS zcl_abapgit_object_fdt0 IMPLEMENTATION.

  METHOD before_xml_deserialize.

    DATA lv_application_id TYPE fdt_admn_0000s-application_id.
    DATA lv_timestamp TYPE timestamp.
    DATA lv_transport TYPE string.
    DATA lv_dlvunit TYPE tdevc-dlvunit.
    DATA lo_node_local TYPE REF TO if_ixml_element.
    DATA lo_node_package TYPE REF TO if_ixml_element.
    DATA lo_node_id TYPE REF TO if_ixml_element.
    DATA lo_xml_element TYPE REF TO if_ixml_element.
    DATA lv_count TYPE i.

    lo_node_local = co_dom_tree->find_from_name( name      = 'Local'
                                                 namespace = 'FDTNS' ).

    IF lo_node_local IS BOUND.
      ev_is_local = lo_node_local->get_value( ).
    ENDIF.

    lo_node_package = co_dom_tree->find_from_name(
      name      = 'DevelopmentPackage'
      namespace = 'FDTNS' ).
    IF lo_node_package IS BOUND.
      lo_node_package->set_value( value = |{ iv_package }| ).
    ENDIF.

    lo_node_id = co_dom_tree->find_from_name(
      name      = 'ApplicationId'
      namespace = 'FDTNS' ).
    IF lo_node_id IS BOUND.
      lv_application_id = lo_node_id->get_value( ).
      SELECT COUNT( * ) FROM fdt_admn_0000s INTO lv_count
        WHERE object_type = 'AP'
        AND id = lv_application_id
        AND deleted = ''.
      ev_create = boolc( lv_count = 0 ).
    ENDIF.

    " Fill in user/time/system-specific fields
    GET TIME STAMP FIELD lv_timestamp.
    lv_transport = |${ sy-sysid }0000000000000001|.

    lo_xml_element = co_dom_tree->get_root_element( ).

    IF ev_create = abap_true.
      set_field(
        EXPORTING
          iv_name         = 'CreationUser'
          iv_value        = |{ sy-uname }|
        CHANGING
          co_ixml_element = lo_xml_element ).

      set_field(
        EXPORTING
          iv_name         = 'CreationTimestamp'
          iv_value        = |{ lv_timestamp }|
        CHANGING
          co_ixml_element = lo_xml_element ).
    ENDIF.

    set_field(
      EXPORTING
        iv_name         = 'ChangeUser'
        iv_value        = |{ sy-uname }|
      CHANGING
        co_ixml_element = lo_xml_element ).

    set_field(
      EXPORTING
        iv_name         = 'ChangeTimestamp'
        iv_value        = |{ lv_timestamp }|
      CHANGING
        co_ixml_element = lo_xml_element ).

    set_field(
      EXPORTING
        iv_name         = 'User'
        iv_value        = |{ sy-uname }|
      CHANGING
        co_ixml_element = lo_xml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Timestamp'
        iv_value        = |{ lv_timestamp }|
      CHANGING
        co_ixml_element = lo_xml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trrequest'
        iv_value        = lv_transport
      CHANGING
        co_ixml_element = lo_xml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trversion'
        iv_value        = '000001'
      CHANGING
        co_ixml_element = lo_xml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trtimestamp'
        iv_value        = |{ lv_timestamp }|
      CHANGING
        co_ixml_element = lo_xml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trsysid'
        iv_value        = |{ sy-sysid }|
      CHANGING
        co_ixml_element = lo_xml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trclient'
        iv_value        = |{ sy-mandt }|
      CHANGING
        co_ixml_element = lo_xml_element ).

    set_field(
      EXPORTING
        iv_name         = 'OversId'
        iv_value        = |{ lv_application_id }|
      CHANGING
        co_ixml_element = lo_xml_element ).

    SELECT SINGLE dlvunit FROM tdevc INTO lv_dlvunit WHERE devclass = iv_package.
    IF sy-subrc = 0.
      set_field(
        EXPORTING
          iv_name         = 'SoftwareComponent'
          iv_value        = |{ lv_dlvunit }|
        CHANGING
          co_ixml_element = lo_xml_element ).
    ENDIF.

    lo_xml_element->set_attribute(
      name  = 'Client'
      value = |{ sy-mandt }| ).
    lo_xml_element->set_attribute(
      name  = 'Date'
      value = |{ sy-datum }| ).
    lo_xml_element->set_attribute(
      name  = 'SAPRelease'
      value = |{ sy-saprl }| ).
    lo_xml_element->set_attribute(
      name  = 'Server'
      value = |{ sy-host }| ).
    lo_xml_element->set_attribute(
      name  = 'SourceExportReqID'
      value = lv_transport ).
    lo_xml_element->set_attribute(
      name  = 'SystemID'
      value = |{ sy-sysid }| ).
    lo_xml_element->set_attribute(
      name  = 'Time'
      value = |{ sy-uzeit }| ).
    lo_xml_element->set_attribute(
      name  = 'User'
      value = |{ sy-uname }| ).

  ENDMETHOD.

  METHOD check_is_local.

    SELECT SINGLE local_object FROM fdt_admn_0000s INTO rv_is_local
      WHERE object_type = 'AP'
      AND name = ms_item-obj_name.

  ENDMETHOD.

  METHOD filter_xml_serialize.

    DATA lo_components_node TYPE REF TO if_ixml_element.

    lo_components_node = co_ixml_element->find_from_name( name      = 'ComponentReleases'
                                                          namespace = 'FDTNS' ).
    IF lo_components_node IS BOUND.
      co_ixml_element->remove_child( old_child = lo_components_node ).
    ENDIF.

    " Clear user/time/system-specific fields
    set_field(
      EXPORTING
        iv_name         = 'CreationUser'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'CreationTimestamp'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'ChangeUser'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'ChangeTimestamp'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'User'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Timestamp'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trrequest'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trversion'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trtimestamp'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trsysid'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'Trclient'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'OversId'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'SoftwareComponent'
      CHANGING
        co_ixml_element = co_ixml_element ).

    set_field(
      EXPORTING
        iv_name         = 'DevelopmentPackage'
      CHANGING
        co_ixml_element = co_ixml_element ).

    " Clear attributes of root  node
    co_ixml_element->set_attribute(
      name  = 'Client'
      value = '' ).
    co_ixml_element->set_attribute(
      name  = 'Date'
      value = '' ).
    co_ixml_element->set_attribute(
      name  = 'SAPRelease'
      value = '' ).
    co_ixml_element->set_attribute(
      name  = 'Server'
      value = '' ).
    co_ixml_element->set_attribute(
      name  = 'SourceExportReqID'
      value = '' ).
    co_ixml_element->set_attribute(
      name  = 'SystemID'
      value = '' ).
    co_ixml_element->set_attribute(
      name  = 'Time'
      value = '' ).
    co_ixml_element->set_attribute(
      name  = 'User'
      value = '' ).

  ENDMETHOD.

  METHOD get_application_id.

    SELECT SINGLE application_id FROM fdt_admn_0000s INTO rv_application_id
      WHERE object_type = 'AP'
      AND name = ms_item-obj_name.

  ENDMETHOD.

  METHOD set_field.

    DATA:
      lo_node_collection TYPE REF TO if_ixml_node_collection,
      lo_node            TYPE REF TO if_ixml_node,
      lv_index           TYPE i.

    lo_node_collection = co_ixml_element->get_elements_by_tag_name(
      namespace = 'FDTNS'
      name      = iv_name ).

    lv_index = 0.
    WHILE lv_index < lo_node_collection->get_length( ).
      lo_node = lo_node_collection->get_item( lv_index ).
      lo_node->set_value( iv_value ).
      lv_index = lv_index + 1.
    ENDWHILE.

  ENDMETHOD.

  METHOD zif_abapgit_object~changed_by.

    DATA lv_ch_user TYPE fdt_admn_0000s-ch_user.

    SELECT SINGLE ch_user FROM fdt_admn_0000s INTO lv_ch_user
      WHERE object_type = 'AP'
      AND name = ms_item-obj_name.

    rv_user = lv_ch_user.

  ENDMETHOD.

  METHOD zif_abapgit_object~delete.

    DATA lv_is_local TYPE abap_bool.
    DATA lt_application_id TYPE TABLE OF fdt_admn_0000s-application_id.
    DATA ls_object_category_sel TYPE if_fdt_query=>s_object_category_sel.
    DATA lv_failure TYPE abap_bool.
    DATA lx_fdt_input TYPE REF TO cx_fdt_input.

    lv_is_local = check_is_local( ).

    SELECT application_id FROM fdt_admn_0000s INTO TABLE lt_application_id
      WHERE object_type = 'AP'
      AND name = ms_item-obj_name.

    ls_object_category_sel-system_objects = 'X'.

    TRY.
        IF lv_is_local = abap_true.

          cl_fdt_delete_handling=>mark_for_delete_via_job(
            EXPORTING
              is_object_category_sel     = ls_object_category_sel
              ita_application_id         = lt_application_id
              iv_background              = abap_true
              iv_local_option            = '1'
              iv_appl_transported_option = '2'
              iv_obj_transported_option  = '2'
            IMPORTING
              ev_failure                 = lv_failure ).
          IF lv_failure IS INITIAL.
            cl_fdt_delete_handling=>delete_logical_via_job(
              EXPORTING
                is_object_category_sel     = ls_object_category_sel
                ita_application_id         = lt_application_id
                iv_retention_time          = 0
                iv_background              = abap_true
                iv_local_option            = '1'
                iv_appl_transported_option = '2'
                iv_obj_transported_option  = '2'
              IMPORTING
                ev_failure                 = lv_failure ).
            IF lv_failure IS INITIAL.
              cl_fdt_delete_handling=>delete_physical_via_job(
                EXPORTING
                  is_object_category_sel     = ls_object_category_sel
                  ita_application_id         = lt_application_id
                  iv_retention_time          = 0
                  iv_background              = abap_true
                  iv_local_option            = '1'
                  iv_appl_transported_option = '2'
                IMPORTING
                  ev_failure                 = lv_failure ).
            ENDIF.
          ENDIF.

        ELSE.

          cl_fdt_delete_handling=>mark_for_delete_via_job(
            EXPORTING
              is_object_category_sel     = ls_object_category_sel
              ita_application_id         = lt_application_id
              iv_background              = abap_true
              iv_local_option            = '2'
              iv_appl_transported_option = '1'
              iv_obj_transported_option  = '1'
            IMPORTING
              ev_failure                 = lv_failure ).
          IF lv_failure IS INITIAL.
            cl_fdt_delete_handling=>delete_logical_via_job(
              EXPORTING
                is_object_category_sel     = ls_object_category_sel
                ita_application_id         = lt_application_id
                iv_retention_time          = 0
                iv_background              = abap_true
                iv_local_option            = '2'
                iv_appl_transported_option = '1'
                iv_obj_transported_option  = '1'
              IMPORTING
                ev_failure                 = lv_failure ).
            IF lv_failure IS INITIAL.
              cl_fdt_delete_handling=>delete_physical_via_job(
                EXPORTING
                  is_object_category_sel     = ls_object_category_sel
                  ita_application_id         = lt_application_id
                  iv_retention_time          = 0
                  iv_background              = abap_true
                  iv_local_option            = '2'
                  iv_appl_transported_option = '1'
                IMPORTING
                  ev_failure                 = lv_failure ).
            ENDIF.
          ENDIF.

        ENDIF.

        IF lv_failure = abap_true.
          zcx_abapgit_exception=>raise( |Error deleting { ms_item-obj_type } { ms_item-obj_name }| ).
        ENDIF.

      CATCH cx_fdt_input INTO lx_fdt_input.
        zcx_abapgit_exception=>raise_with_text( lx_fdt_input ).
    ENDTRY.

  ENDMETHOD.

  METHOD zif_abapgit_object~deserialize.

    DATA lo_dexc TYPE REF TO if_fdt_data_exchange.
    DATA lx_fdt_input TYPE REF TO cx_fdt_input.
    DATA lo_dom_tree TYPE REF TO if_ixml_document.
    DATA lv_is_local TYPE abap_bool.
    DATA lt_message TYPE if_fdt_types=>t_message.
    DATA lv_create TYPE abap_bool.

    FIELD-SYMBOLS <ls_message> TYPE if_fdt_types=>s_message.

    lo_dom_tree = io_xml->get_raw( ).

    before_xml_deserialize(
      EXPORTING
        iv_package  = iv_package
      IMPORTING
        ev_create   = lv_create
        ev_is_local = lv_is_local
      CHANGING
        co_dom_tree = lo_dom_tree ).

    lo_dexc = cl_fdt_factory=>if_fdt_factory~get_instance( )->get_data_exchange( ).

    TRY.

        IF lv_is_local = abap_true. "Local Object

          lo_dexc->import_xml(
            EXPORTING
              io_dom_tree = lo_dom_tree
              iv_create   = lv_create
              iv_activate = abap_true
              iv_simulate = abap_false
            IMPORTING
              et_message  = lt_message ).

        ELSE. "Transportable Object

          lo_dexc->import_xml(
            EXPORTING
              io_dom_tree            = lo_dom_tree
              iv_create              = lv_create
              iv_activate            = abap_true
              iv_simulate            = abap_false
              iv_workbench_trrequest = iv_transport
            IMPORTING
              et_message             = lt_message ).

        ENDIF.

        LOOP AT lt_message ASSIGNING <ls_message>.
          ii_log->add(
            iv_msg  = <ls_message>-text
            iv_type = <ls_message>-msgty ).
        ENDLOOP.

      CATCH cx_fdt_input INTO lx_fdt_input.
        zcx_abapgit_exception=>raise_with_text( lx_fdt_input ).
    ENDTRY.

  ENDMETHOD.

  METHOD zif_abapgit_object~exists.

    DATA lv_count TYPE i.

    SELECT COUNT( * ) FROM fdt_admn_0000s INTO lv_count
      WHERE object_type = 'AP'
      AND name = ms_item-obj_name
      AND deleted = ''.

    rv_bool = boolc( lv_count > 0 ).

  ENDMETHOD.

  METHOD zif_abapgit_object~get_comparator.

    DATA lo_local_version_output TYPE REF TO zcl_abapgit_xml_output.
    DATA lo_local_version_input  TYPE REF TO zcl_abapgit_xml_input.

    CREATE OBJECT lo_local_version_output.
    zif_abapgit_object~serialize( lo_local_version_output ).

    CREATE OBJECT lo_local_version_input
      EXPORTING
        iv_xml = lo_local_version_output->zif_abapgit_xml_output~render( ).

    CREATE OBJECT ri_comparator TYPE zcl_abapgit_object_tabl_compar
      EXPORTING
        ii_local = lo_local_version_input.

  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.

    DATA lv_application_id TYPE fdt_admn_0000s-application_id.
    DATA lx_fdt_input TYPE REF TO cx_fdt_input.
    DATA lo_instance TYPE REF TO if_fdt_admin_data.
    DATA lt_version TYPE if_fdt_admin_data=>ts_version.
    DATA lv_index TYPE sy-tabix.

    FIELD-SYMBOLS <ls_version> LIKE LINE OF lt_version.

    lv_application_id = get_application_id( ).

    TRY.
        cl_fdt_factory=>get_instance_generic(
          EXPORTING
            iv_id       = lv_application_id
          IMPORTING
            eo_instance = lo_instance ).

      CATCH cx_fdt_input INTO lx_fdt_input.
        zcx_abapgit_exception=>raise_with_text( lx_fdt_input ).
    ENDTRY.

    lo_instance->get_versions( IMPORTING ets_version = lt_version ).
    lv_index = lines( lt_version ).
    READ TABLE lt_version ASSIGNING <ls_version> INDEX lv_index.

    rv_active = boolc( <ls_version>-state = 'A' ).

  ENDMETHOD.

  METHOD zif_abapgit_object~is_locked.

    DATA lv_application_id TYPE string.

    lv_application_id = get_application_id( ).

    rv_is_locked = exists_a_lock_entry_for(
      iv_lock_object = 'FDT_ENQUEUE_ID'
      iv_argument    = |$ST{ lv_application_id }| ).

  ENDMETHOD.

  METHOD zif_abapgit_object~jump.

    DATA lv_application_id TYPE fdt_admn_0000s-application_id.
    DATA lx_root TYPE REF TO cx_root.
    DATA lo_fdt_wd TYPE REF TO if_fdt_wd_factory.

    lv_application_id = get_application_id( ).

    IF lv_application_id IS NOT INITIAL.
      TRY.
          lo_fdt_wd = cl_fdt_wd_factory=>if_fdt_wd_factory~get_instance( ).
          lo_fdt_wd->get_ui_execution( )->execute_workbench( iv_id = lv_application_id ).
        CATCH cx_root INTO lx_root.
          zcx_abapgit_exception=>raise_with_text( lx_root ).
      ENDTRY.
    ELSE.
      zcx_abapgit_exception=>raise( 'Could not open BRF+ Workbench' ).
    ENDIF.

  ENDMETHOD.

  METHOD zif_abapgit_object~serialize.

    DATA lo_dexc TYPE REF TO if_fdt_data_exchange.
    DATA lv_application_id TYPE fdt_admn_0000s-application_id.
    DATA lx_fdt_input TYPE REF TO cx_fdt_input.
    DATA lv_xml_fdt0_application TYPE string.
    DATA lo_xml_document TYPE REF TO if_ixml_document.
    DATA lo_xml_element TYPE REF TO if_ixml_element.

    lv_application_id = get_application_id( ).

    lo_dexc = cl_fdt_factory=>if_fdt_factory~get_instance( )->get_data_exchange( ).

    TRY.
        lo_dexc->export_xml_application(
          EXPORTING
            iv_application_id = lv_application_id
            iv_schema         = if_fdt_data_exchange=>gc_xml_schema_type_external
            iv_xml_version    = if_fdt_data_exchange=>gc_xml_version
          IMPORTING
            ev_string         = lv_xml_fdt0_application ).

        lo_xml_document = cl_ixml_80_20=>parse_to_document( stream_string = lv_xml_fdt0_application ).
        lo_xml_element = lo_xml_document->get_root_element( ).

        filter_xml_serialize( CHANGING co_ixml_element = lo_xml_element ).

        io_xml->set_raw( lo_xml_element ).

      CATCH cx_fdt_input INTO lx_fdt_input.
        zcx_abapgit_exception=>raise_with_text( lx_fdt_input ).
    ENDTRY.

  ENDMETHOD.
ENDCLASS.


*"* use this source file for your ABAP unit test classes
CLASS ltcl_apack_manifest_reader DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
  PRIVATE SECTION.
    METHODS:
      setup RAISING cx_static_check,
      manifest_descriptor FOR TESTING RAISING cx_static_check,
      verify_own_descriptor IMPORTING is_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor.

    DATA: mo_manifest_reader TYPE REF TO zcl_abapgit_apack_reader.
ENDCLASS.

CLASS ltcl_apack_manifest_reader IMPLEMENTATION.

  METHOD manifest_descriptor.
    verify_own_descriptor( mo_manifest_reader->get_manifest_descriptor( ) ).
  ENDMETHOD.

  METHOD setup.
    DATA: ls_apack_manifest_descriptor TYPE zif_abapgit_apack_definitions=>ty_descriptor.

    ls_apack_manifest_descriptor-group_id = ''.
    ls_apack_manifest_descriptor-artifact_id = 'abapGit'.
    ls_apack_manifest_descriptor-version = '1.42'.
    ls_apack_manifest_descriptor-git_url = ''.

    mo_manifest_reader = zcl_abapgit_apack_reader=>create_instance( '$TMP' ).
    mo_manifest_reader->set_manifest_descriptor( ls_apack_manifest_descriptor ).

  ENDMETHOD.

  METHOD verify_own_descriptor.
    cl_abap_unit_assert=>assert_not_initial( is_manifest_descriptor ).
    cl_abap_unit_assert=>assert_equals( exp = ''
                                        act = is_manifest_descriptor-group_id ).
    cl_abap_unit_assert=>assert_equals( exp = 'abapGit'
                                        act = is_manifest_descriptor-artifact_id ).
    cl_abap_unit_assert=>assert_equals( exp = '1.42'
                                        act = is_manifest_descriptor-version ).
    " Repository type is added automatically by serializer later
    cl_abap_unit_assert=>assert_initial( is_manifest_descriptor-repository_type ).
    cl_abap_unit_assert=>assert_equals( exp = ''
                                        act = is_manifest_descriptor-git_url ).
    cl_abap_unit_assert=>assert_initial( is_manifest_descriptor-dependencies ).
  ENDMETHOD.

ENDCLASS.


CLASS lcl_http_response DEFINITION FINAL.
  PUBLIC SECTION.

    INTERFACES zif_abapgit_http_response.

    CLASS-METHODS create
      IMPORTING
        ii_client          TYPE REF TO if_http_client
      RETURNING
        VALUE(ri_response) TYPE REF TO zif_abapgit_http_response.

  PRIVATE SECTION.
    DATA mi_client TYPE REF TO if_http_client.
    DATA mi_response TYPE REF TO if_http_response.
ENDCLASS.

CLASS lcl_http_response IMPLEMENTATION.

  METHOD create.
    DATA lo_response TYPE REF TO lcl_http_response.
    CREATE OBJECT lo_response.
    lo_response->mi_client   = ii_client.
    lo_response->mi_response = ii_client->response.
    ri_response ?= lo_response.
  ENDMETHOD.

  METHOD zif_abapgit_http_response~close.
    mi_client->close( ).
  ENDMETHOD.

  METHOD zif_abapgit_http_response~is_ok.
    DATA lv_code TYPE i.
    lv_code = zif_abapgit_http_response~code( ).
    rv_yes = boolc( lv_code >= 200 AND lv_code < 300 ).
  ENDMETHOD.

  METHOD zif_abapgit_http_response~data.
    rv_data = mi_response->get_data( ).
  ENDMETHOD.

  METHOD zif_abapgit_http_response~cdata.
    rv_data = mi_response->get_cdata( ).
  ENDMETHOD.

  METHOD zif_abapgit_http_response~code.
    DATA lv_msg TYPE string ##NEEDED.
    mi_response->get_status(
      IMPORTING
        reason = lv_msg " for debug
        code   = rv_code ).
  ENDMETHOD.

  METHOD zif_abapgit_http_response~json.

    ri_json = zcl_abapgit_ajson=>parse( zif_abapgit_http_response~cdata( ) ).

  ENDMETHOD.

  METHOD zif_abapgit_http_response~error.
    rv_message = mi_response->get_cdata( ).
  ENDMETHOD.

  METHOD zif_abapgit_http_response~headers.

    DATA lt_headers TYPE tihttpnvp.
    FIELD-SYMBOLS <ls_h> LIKE LINE OF lt_headers.

    CREATE OBJECT ro_headers.

    mi_response->get_header_fields( CHANGING fields = lt_headers ).
    LOOP AT lt_headers ASSIGNING <ls_h>.
      ro_headers->set(
        iv_key = <ls_h>-name
        iv_val = <ls_h>-value ).
    ENDLOOP.

  ENDMETHOD.

ENDCLASS.


CLASS zcl_abapgit_ajson_mapping DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    CLASS-METHODS create_camel_case
      IMPORTING
        it_mapping_fields   TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL
        iv_first_json_upper TYPE abap_bool DEFAULT abap_true
      RETURNING
        VALUE(ri_mapping)   TYPE REF TO zif_abapgit_ajson_mapping.

    CLASS-METHODS create_upper_case
      IMPORTING
        it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL
      RETURNING
        VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping.

    CLASS-METHODS create_lower_case
      IMPORTING
        it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL
      RETURNING
        VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping.

    CLASS-METHODS create_field_mapping
      IMPORTING
        it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields
      RETURNING
        VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping.

  PROTECTED SECTION.

  PRIVATE SECTION.

ENDCLASS.

CLASS zcl_abapgit_ajson_mapping IMPLEMENTATION.

  METHOD create_camel_case.

    CREATE OBJECT ri_mapping TYPE lcl_mapping_camel
      EXPORTING
        it_mapping_fields   = it_mapping_fields
        iv_first_json_upper = iv_first_json_upper.

  ENDMETHOD.

  METHOD create_field_mapping.

    CREATE OBJECT ri_mapping TYPE lcl_mapping_fields
      EXPORTING
        it_mapping_fields = it_mapping_fields.

  ENDMETHOD.

  METHOD create_lower_case.

    CREATE OBJECT ri_mapping TYPE lcl_mapping_to_lower
      EXPORTING
        it_mapping_fields = it_mapping_fields.

  ENDMETHOD.

  METHOD create_upper_case.

    CREATE OBJECT ri_mapping TYPE lcl_mapping_to_upper
      EXPORTING
        it_mapping_fields = it_mapping_fields.

  ENDMETHOD.
ENDCLASS.


CLASS zcl_aoc_super_root DEFINITION
  PUBLIC
  INHERITING FROM cl_ci_test_root
  ABSTRACT
  CREATE PUBLIC .

  PUBLIC SECTION.
    TYPE-POOLS zzaoc .

    METHODS constructor .

    METHODS get_attributes
        REDEFINITION .
    METHODS if_ci_test~display_documentation
        REDEFINITION .
    METHODS if_ci_test~query_attributes
        REDEFINITION .
    METHODS put_attributes
        REDEFINITION .
  PROTECTED SECTION.

    TYPES:
      ty_scimessage_text TYPE c LENGTH 255 .

    DATA mv_errty TYPE sci_errty .

    METHODS enable_rfc .
    METHODS set_kind .
    CLASS-METHODS get_destination
      RETURNING
        VALUE(rv_result) TYPE rfcdest .
    METHODS insert_scimessage
      IMPORTING
        !iv_code TYPE scimessage-code
        !iv_text TYPE ty_scimessage_text
        !iv_pcom TYPE scimessage-pcom OPTIONAL .
  PRIVATE SECTION.
ENDCLASS.

CLASS ZCL_AOC_SUPER_ROOT IMPLEMENTATION.

  METHOD constructor.
    super->constructor( ).

    "get description of check class
    SELECT SINGLE descript FROM seoclasstx INTO description
      WHERE clsname = myname
      AND langu   = sy-langu.
    IF sy-subrc <> 0.
      SELECT SINGLE descript FROM seoclasstx INTO description
        WHERE clsname = myname.           "#EC CI_NOORDER "#EC CI_SUBRC
    ENDIF.

    category = 'ZCL_AOC_CATEGORY'.
    mv_errty = 'E'.

  ENDMETHOD.

  METHOD enable_rfc.
* RFC enable the check, new feature for central ATC on 7.51

    FIELD-SYMBOLS: <lv_rfc> TYPE abap_bool.

    ASSIGN ('REMOTE_RFC_ENABLED') TO <lv_rfc>.
    IF sy-subrc = 0.
      <lv_rfc> = abap_true.
    ENDIF.

  ENDMETHOD.

  METHOD get_attributes.

    EXPORT mv_errty = mv_errty TO DATA BUFFER p_attributes.

  ENDMETHOD.

  METHOD get_destination.

    "get destination of calling system (RFC enabled checks only)
    "class, method and variable may not valid in 7.02 systems -> dynamic calls
    CONSTANTS lc_classname TYPE seoclsname VALUE 'CL_ABAP_SOURCE_ID'.
    CONSTANTS lc_methodname TYPE seocpdname VALUE 'GET_DESTINATION'.

    FIELD-SYMBOLS: <lv_srcid> TYPE sysuuid_x.

    ASSIGN ('SRCID') TO <lv_srcid>.

    IF NOT <lv_srcid> IS ASSIGNED.
      rv_result = |NONE|.
      RETURN.
    ENDIF.

    IF <lv_srcid> IS INITIAL.
      rv_result = |NONE|.
      RETURN.
    ENDIF.

    TRY.
        CALL METHOD (lc_classname)=>(lc_methodname)
          EXPORTING
            p_srcid       = <lv_srcid>
          RECEIVING
            p_destination = rv_result
          EXCEPTIONS
            not_found     = 1.

        IF sy-subrc <> 0.
          rv_result = |NONE|.
        ENDIF.

      CATCH cx_sy_dyn_call_illegal_class
            cx_sy_dyn_call_illegal_method.
        rv_result = |NONE|.
    ENDTRY.

  ENDMETHOD.

  METHOD if_ci_test~display_documentation.

    DATA: lv_url TYPE string VALUE '' ##NO_TEXT,
          lv_len TYPE i.

    lv_len = strlen( myname ) - 2.

    CONCATENATE lv_url myname+lv_len(2) INTO lv_url.

    cl_gui_frontend_services=>execute(
      EXPORTING
        document               = lv_url
      EXCEPTIONS
        cntl_error             = 1
        error_no_gui           = 2
        bad_parameter          = 3
        file_not_found         = 4
        path_not_found         = 5
        file_extension_unknown = 6
        error_execute_failed   = 7
        synchronous_failed     = 8
        not_supported_by_gui   = 9
        OTHERS                 = 10 ).                    "#EC CI_SUBRC

  ENDMETHOD.

  METHOD if_ci_test~query_attributes.

    zzaoc_top.

    zzaoc_fill_att mv_errty 'Error Type' ''.                "#EC NOTEXT

    zzaoc_popup.

  ENDMETHOD.

  METHOD insert_scimessage.
* Insert entry into table scimessages, this table is used to determine the message text for a finding.
    DATA ls_scimessage LIKE LINE OF scimessages.

    ls_scimessage-test = myname.
    ls_scimessage-code = iv_code.
    ls_scimessage-kind = mv_errty.
    ls_scimessage-text = iv_text.
    ls_scimessage-pcom = iv_pcom.

    INSERT ls_scimessage INTO TABLE scimessages.

  ENDMETHOD.

  METHOD put_attributes.

    IMPORT
      mv_errty = mv_errty
      FROM DATA BUFFER p_attributes.                 "#EC CI_USE_WANTED
    ASSERT sy-subrc = 0.

    set_kind( ).

  ENDMETHOD.

  METHOD set_kind.

    FIELD-SYMBOLS: <ls_message> LIKE LINE OF scimessages.

    LOOP AT scimessages ASSIGNING <ls_message>.
      <ls_message>-kind = mv_errty.
    ENDLOOP.

  ENDMETHOD.
ENDCLASS.


CLASS zcl_abapgit_gui_page_ex_pckage DEFINITION
  PUBLIC
  INHERITING FROM zcl_abapgit_gui_component
  FINAL
  CREATE PRIVATE.

  PUBLIC SECTION.
    INTERFACES zif_abapgit_gui_event_handler.
    INTERFACES zif_abapgit_gui_renderable.

    CLASS-METHODS create
      RETURNING
        VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable
      RAISING
        zcx_abapgit_exception.
    METHODS constructor
      RAISING
        zcx_abapgit_exception.

  PROTECTED SECTION.
  PRIVATE SECTION.
    CONSTANTS:
      BEGIN OF c_id,
        package        TYPE string VALUE 'package',
        folder_logic   TYPE string VALUE 'folder_logic',
        main_lang_only TYPE string VALUE 'main_lang_only',
      END OF c_id.

    CONSTANTS:
      BEGIN OF c_event,
        go_back        TYPE string VALUE 'go-back',
        export_package TYPE string VALUE 'export-package',
        choose_package TYPE string VALUE 'choose-object-type',
      END OF c_event.

    DATA mo_form TYPE REF TO zcl_abapgit_html_form.
    DATA mo_form_data TYPE REF TO zcl_abapgit_string_map.
    DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map.
    DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils.

    METHODS get_form_schema
      RETURNING
        VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form.

    METHODS export_package
      RAISING
        zcx_abapgit_exception.
ENDCLASS.

CLASS zcl_abapgit_gui_page_ex_pckage IMPLEMENTATION.

  METHOD constructor.
    super->constructor( ).
    CREATE OBJECT mo_validation_log.
    CREATE OBJECT mo_form_data.
    mo_form = get_form_schema( ).
    mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ).
  ENDMETHOD.

  METHOD create.
    DATA lo_component TYPE REF TO zcl_abapgit_gui_page_ex_pckage.
    CREATE OBJECT lo_component.

    ri_page = zcl_abapgit_gui_page_hoc=>create(
      iv_page_title      = 'Export Package to ZIP'
      ii_child_component = lo_component ).
  ENDMETHOD.

  METHOD get_form_schema.
    ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'export-package-to-files' ).

    ro_form->text(
      iv_name          = c_id-package
      iv_label         = 'Package'
      iv_required      = abap_true
      iv_upper_case    = abap_true
      iv_side_action   = c_event-choose_package
    )->radio(
      iv_name          = c_id-folder_logic
      iv_label         = 'Folder Logic'
      iv_default_value = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
      iv_hint          = 'Define how package folders are named in repository'
    )->option(
      iv_label         = 'Prefix'
      iv_value         = zif_abapgit_dot_abapgit=>c_folder_logic-prefix
    )->option(
      iv_label         = 'Full'
      iv_value         = zif_abapgit_dot_abapgit=>c_folder_logic-full
    )->checkbox(
      iv_name          = c_id-main_lang_only
      iv_label         = 'Serialize Main Language Only'
      iv_hint          = 'Ignore translations, serialize just main language'
    )->command(
      iv_label         = 'Export Package to ZIP'
      iv_action        = c_event-export_package
      iv_cmd_type      = zif_abapgit_html_form=>c_cmd_type-input_main
    )->command(
      iv_label         = 'Back'
      iv_action        = c_event-go_back ).
  ENDMETHOD.

  METHOD zif_abapgit_gui_renderable~render.
    gui_services( )->register_event_handler( me ).

    CREATE OBJECT ri_html TYPE zcl_abapgit_html.

    ri_html->add( mo_form->render(
      io_values         = mo_form_data
      io_validation_log = mo_validation_log ) ).
  ENDMETHOD.

  METHOD zif_abapgit_gui_event_handler~on_event.
    mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ).

    CASE ii_event->mv_action.
      WHEN c_event-go_back.

        rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back.

      WHEN c_event-export_package.

        mo_validation_log = mo_form_util->validate( mo_form_data ).
        IF mo_validation_log->is_empty( ) = abap_false.
          rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render.
        ELSE.
          export_package( ).
          MESSAGE 'Package successfully exported' TYPE 'S'.
          rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back.
        ENDIF.

      WHEN c_event-choose_package.

        mo_form_data->set(
          iv_key = c_id-package
          iv_val = zcl_abapgit_ui_factory=>get_popups( )->popup_search_help( 'TDEVC-DEVCLASS' ) ).

        IF mo_form_data->get( c_id-package ) IS NOT INITIAL.
          rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render.
        ELSE.
          rs_handled-state = zcl_abapgit_gui=>c_event_state-no_more_act.
        ENDIF.
    ENDCASE.
  ENDMETHOD.

  METHOD export_package.
    DATA lv_package TYPE devclass.
    DATA lv_folder_logic TYPE string.
    DATA lv_main_lang_only TYPE abap_bool.

    lv_package        = mo_form_data->get( c_id-package ).
    lv_folder_logic   = mo_form_data->get( c_id-folder_logic ).
    lv_main_lang_only = mo_form_data->get( c_id-main_lang_only ).

    zcl_abapgit_zip=>export_package(
        iv_package        = lv_package
        iv_folder_logic   = lv_folder_logic
        iv_main_lang_only = lv_main_lang_only ).
  ENDMETHOD.
ENDCLASS.


*&---------------------------------------------------------------------*
*&  Include           ZABAPGIT_FORMS
*&---------------------------------------------------------------------*

FORM run.

  DATA: lx_exception TYPE REF TO zcx_abapgit_exception.

  TRY.
      zcl_abapgit_migrations=>run( ).
      PERFORM open_gui.
    CATCH zcx_abapgit_exception INTO lx_exception.
      MESSAGE lx_exception TYPE 'E'.
  ENDTRY.

ENDFORM.                    "run

FORM open_gui RAISING zcx_abapgit_exception.

  IF sy-batch = abap_true.
    zcl_abapgit_background=>run( ).
  ELSE.

    zcl_abapgit_services_abapgit=>prepare_gui_startup( ).
    zcl_abapgit_ui_factory=>get_gui( )->go_home( ).
    CALL SELECTION-SCREEN 1001. " trigger screen

  ENDIF.

ENDFORM.

FORM branch_popup TABLES   tt_fields TYPE zif_abapgit_popups=>ty_sval_tt
                  USING    pv_code TYPE clike
                  CHANGING cs_error TYPE svale
                           cv_show_popup TYPE c
                  RAISING zcx_abapgit_exception ##CALLED ##NEEDED.
* called dynamically from function module POPUP_GET_VALUES_USER_BUTTONS

  DATA: lx_error  TYPE REF TO zcx_abapgit_exception,
        li_popups TYPE REF TO zif_abapgit_popups.

  TRY.
      li_popups = zcl_abapgit_ui_factory=>get_popups( ).
      li_popups->branch_popup_callback(
        EXPORTING
          iv_code       = pv_code
        CHANGING
          ct_fields     = tt_fields[]
          cs_error      = cs_error
          cv_show_popup = cv_show_popup ).

    CATCH zcx_abapgit_exception INTO lx_error.
      MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

ENDFORM.                    "branch_popup

FORM output.

  DATA: lx_error TYPE REF TO zcx_abapgit_exception,
        lt_ucomm TYPE TABLE OF sy-ucomm.

  PERFORM set_pf_status IN PROGRAM rsdbrunt IF FOUND.

  APPEND 'CRET' TO lt_ucomm.  "Button Execute
  APPEND 'SPOS' TO lt_ucomm.  "Button Save

  CALL FUNCTION 'RS_SET_SELSCREEN_STATUS'
    EXPORTING
      p_status  = sy-pfkey
    TABLES
      p_exclude = lt_ucomm.

  TRY.
      zcl_abapgit_ui_factory=>get_gui( )->set_focus( ).
    CATCH zcx_abapgit_exception INTO lx_error.
      MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

ENDFORM.

FORM exit.

  DATA lx_error TYPE REF TO zcx_abapgit_exception.

  " The exit logic should only be applied for our 'main' selection screen 1001.
  " All other selection-screens are called as popups and shouldn't influence
  " the gui navigation as it would lead to inpredictable behaviour like dumps.
  IF sy-dynnr <> 1001.
    RETURN.
  ENDIF.

  TRY.
      CASE sy-ucomm.
        WHEN 'CBAC' OR 'CCAN'.  "Back & Escape
          IF zcl_abapgit_ui_factory=>get_gui( )->back( ) = abap_true. " end of stack
            zcl_abapgit_ui_factory=>get_gui( )->free( ). " Graceful shutdown
          ELSE.
            LEAVE TO SCREEN 1001.
          ENDIF.
      ENDCASE.
    CATCH zcx_abapgit_exception INTO lx_error.
      MESSAGE lx_error TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

ENDFORM.

FORM password_popup
      USING
        pv_repo_url TYPE string
      CHANGING
        cv_user     TYPE string
        cv_pass     TYPE string.

  lcl_password_dialog=>popup(
    EXPORTING
      iv_repo_url     = pv_repo_url
    CHANGING
      cv_user         = cv_user
      cv_pass         = cv_pass ).

ENDFORM.

FORM remove_toolbar USING pv_dynnr TYPE sy-dynnr.

  DATA: ls_header               TYPE rpy_dyhead,
        lt_containers           TYPE dycatt_tab,
        lt_fields_to_containers TYPE dyfatc_tab,
        lt_flow_logic           TYPE swydyflow.

  CALL FUNCTION 'RPY_DYNPRO_READ'
    EXPORTING
      progname             = sy-cprog
      dynnr                = pv_dynnr
    IMPORTING
      header               = ls_header
    TABLES
      containers           = lt_containers
      fields_to_containers = lt_fields_to_containers
      flow_logic           = lt_flow_logic
    EXCEPTIONS
      cancelled            = 1
      not_found            = 2
      permission_error     = 3
      OTHERS               = 4.
  IF sy-subrc IS NOT INITIAL.
    RETURN. " Ignore errors, just exit
  ENDIF.

  IF ls_header-no_toolbar = abap_true.
    RETURN. " No change required
  ENDIF.

  ls_header-no_toolbar = abap_true.

  CALL FUNCTION 'RPY_DYNPRO_INSERT'
    EXPORTING
      header                 = ls_header
      suppress_exist_checks  = abap_true
    TABLES
      containers             = lt_containers
      fields_to_containers   = lt_fields_to_containers
      flow_logic             = lt_flow_logic
    EXCEPTIONS
      cancelled              = 1
      already_exists         = 2
      program_not_exists     = 3
      not_executed           = 4
      missing_required_field = 5
      illegal_field_value    = 6
      field_not_allowed      = 7
      not_generated          = 8
      illegal_field_position = 9
      OTHERS                 = 10.
  IF sy-subrc <> 2 AND sy-subrc <> 0.
    RETURN. " Ignore errors, just exit
  ENDIF.

ENDFORM.


CLASS zcl_excel_sheet_setup DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
*"* public components of class ZCL_EXCEL_SHEET_SETUP
*"* do not include other source files here!!!
    TYPE-POOLS abap .

    DATA black_and_white TYPE flag .
    DATA cell_comments TYPE stringval .
    DATA copies TYPE int2 .
    CONSTANTS c_break_column TYPE zexcel_break VALUE 2.     "#EC NOTEXT
    CONSTANTS c_break_none TYPE zexcel_break VALUE 0.       "#EC NOTEXT
    CONSTANTS c_break_row TYPE zexcel_break VALUE 1.        "#EC NOTEXT
    CONSTANTS c_cc_as_displayed TYPE string VALUE 'asDisplayed'. "#EC NOTEXT
    CONSTANTS c_cc_at_end TYPE string VALUE 'atEnd'.        "#EC NOTEXT
    CONSTANTS c_cc_none TYPE string VALUE 'none'.           "#EC NOTEXT
    CONSTANTS c_ord_downthenover TYPE string VALUE 'downThenOver'. "#EC NOTEXT
    CONSTANTS c_ord_overthendown TYPE string VALUE 'overThenDown'. "#EC NOTEXT
    CONSTANTS c_orientation_default TYPE zexcel_sheet_orienatation VALUE 'default'. "#EC NOTEXT
    CONSTANTS c_orientation_landscape TYPE zexcel_sheet_orienatation VALUE 'landscape'. "#EC NOTEXT
    CONSTANTS c_orientation_portrait TYPE zexcel_sheet_orienatation VALUE 'portrait'. "#EC NOTEXT
    CONSTANTS c_papersize_6_3_4_envelope TYPE zexcel_sheet_paper_size VALUE 38. "#EC NOTEXT
    CONSTANTS c_papersize_a2_paper TYPE zexcel_sheet_paper_size VALUE 64. "#EC NOTEXT
    CONSTANTS c_papersize_a3 TYPE zexcel_sheet_paper_size VALUE 8. "#EC NOTEXT
    CONSTANTS c_papersize_a3_extra_paper TYPE zexcel_sheet_paper_size VALUE 61. "#EC NOTEXT
    CONSTANTS c_papersize_a3_extra_tv_paper TYPE zexcel_sheet_paper_size VALUE 66. "#EC NOTEXT
    CONSTANTS c_papersize_a3_tv_paper TYPE zexcel_sheet_paper_size VALUE 65. "#EC NOTEXT
    CONSTANTS c_papersize_a4 TYPE zexcel_sheet_paper_size VALUE 9. "#EC NOTEXT
    CONSTANTS c_papersize_a4_extra_paper TYPE zexcel_sheet_paper_size VALUE 51. "#EC NOTEXT
    CONSTANTS c_papersize_a4_plus_paper TYPE zexcel_sheet_paper_size VALUE 58. "#EC NOTEXT
    CONSTANTS c_papersize_a4_small TYPE zexcel_sheet_paper_size VALUE 10. "#EC NOTEXT
    CONSTANTS c_papersize_a4_tv_paper TYPE zexcel_sheet_paper_size VALUE 53. "#EC NOTEXT
    CONSTANTS c_papersize_a5 TYPE zexcel_sheet_paper_size VALUE 11. "#EC NOTEXT
    CONSTANTS c_papersize_a5_extra_paper TYPE zexcel_sheet_paper_size VALUE 62. "#EC NOTEXT
    CONSTANTS c_papersize_a5_tv_paper TYPE zexcel_sheet_paper_size VALUE 59. "#EC NOTEXT
    CONSTANTS c_papersize_b4 TYPE zexcel_sheet_paper_size VALUE 12. "#EC NOTEXT
    CONSTANTS c_papersize_b4_envelope TYPE zexcel_sheet_paper_size VALUE 33. "#EC NOTEXT
    CONSTANTS c_papersize_b5 TYPE zexcel_sheet_paper_size VALUE 13. "#EC NOTEXT
    CONSTANTS c_papersize_b5_envelope TYPE zexcel_sheet_paper_size VALUE 34. "#EC NOTEXT
    CONSTANTS c_papersize_b6_envelope TYPE zexcel_sheet_paper_size VALUE 35. "#EC NOTEXT
    CONSTANTS c_papersize_c TYPE zexcel_sheet_paper_size VALUE 24. "#EC NOTEXT
    CONSTANTS c_papersize_c3_envelope TYPE zexcel_sheet_paper_size VALUE 29. "#EC NOTEXT
    CONSTANTS c_papersize_c4_envelope TYPE zexcel_sheet_paper_size VALUE 30. "#EC NOTEXT
    CONSTANTS c_papersize_c5_envelope TYPE zexcel_sheet_paper_size VALUE 28. "#EC NOTEXT
    CONSTANTS c_papersize_c65_envelope TYPE zexcel_sheet_paper_size VALUE 32. "#EC NOTEXT
    CONSTANTS c_papersize_c6_envelope TYPE zexcel_sheet_paper_size VALUE 31. "#EC NOTEXT
    CONSTANTS c_papersize_d TYPE zexcel_sheet_paper_size VALUE 25. "#EC NOTEXT
    CONSTANTS c_papersize_de_leg_fanfold TYPE zexcel_sheet_paper_size VALUE 41. "#EC NOTEXT
    CONSTANTS c_papersize_de_std_fanfold TYPE zexcel_sheet_paper_size VALUE 40. "#EC NOTEXT
    CONSTANTS c_papersize_dl_envelope TYPE zexcel_sheet_paper_size VALUE 27. "#EC NOTEXT
    CONSTANTS c_papersize_e TYPE zexcel_sheet_paper_size VALUE 26. "#EC NOTEXT
    CONSTANTS c_papersize_executive TYPE zexcel_sheet_paper_size VALUE 7. "#EC NOTEXT
    CONSTANTS c_papersize_folio TYPE zexcel_sheet_paper_size VALUE 14. "#EC NOTEXT
    CONSTANTS c_papersize_invite_envelope TYPE zexcel_sheet_paper_size VALUE 47. "#EC NOTEXT
    CONSTANTS c_papersize_iso_b4 TYPE zexcel_sheet_paper_size VALUE 42. "#EC NOTEXT
    CONSTANTS c_papersize_iso_b5_extra_paper TYPE zexcel_sheet_paper_size VALUE 63. "#EC NOTEXT
    CONSTANTS c_papersize_italy_envelope TYPE zexcel_sheet_paper_size VALUE 36. "#EC NOTEXT
    CONSTANTS c_papersize_jis_b5_tv_paper TYPE zexcel_sheet_paper_size VALUE 60. "#EC NOTEXT
    CONSTANTS c_papersize_jpn_dbl_postcard TYPE zexcel_sheet_paper_size VALUE 43. "#EC NOTEXT
    CONSTANTS c_papersize_ledger TYPE zexcel_sheet_paper_size VALUE 4. "#EC NOTEXT
    CONSTANTS c_papersize_legal TYPE zexcel_sheet_paper_size VALUE 5. "#EC NOTEXT
    CONSTANTS c_papersize_legal_extra_paper TYPE zexcel_sheet_paper_size VALUE 49. "#EC NOTEXT
    CONSTANTS c_papersize_letter TYPE zexcel_sheet_paper_size VALUE 1. "#EC NOTEXT
    CONSTANTS c_papersize_letter_extra_paper TYPE zexcel_sheet_paper_size VALUE 48. "#EC NOTEXT
    CONSTANTS c_papersize_letter_extv_paper TYPE zexcel_sheet_paper_size VALUE 54. "#EC NOTEXT
    CONSTANTS c_papersize_letter_plus_paper TYPE zexcel_sheet_paper_size VALUE 57. "#EC NOTEXT
    CONSTANTS c_papersize_letter_small TYPE zexcel_sheet_paper_size VALUE 2. "#EC NOTEXT
    CONSTANTS c_papersize_letter_tv_paper TYPE zexcel_sheet_paper_size VALUE 52. "#EC NOTEXT
    CONSTANTS c_papersize_monarch_envelope TYPE zexcel_sheet_paper_size VALUE 37. "#EC NOTEXT
    CONSTANTS c_papersize_no10_envelope TYPE zexcel_sheet_paper_size VALUE 20. "#EC NOTEXT
    CONSTANTS c_papersize_no11_envelope TYPE zexcel_sheet_paper_size VALUE 21. "#EC NOTEXT
    CONSTANTS c_papersize_no12_envelope TYPE zexcel_sheet_paper_size VALUE 22. "#EC NOTEXT
    CONSTANTS c_papersize_no14_envelope TYPE zexcel_sheet_paper_size VALUE 23. "#EC NOTEXT
    CONSTANTS c_papersize_no9_envelope TYPE zexcel_sheet_paper_size VALUE 19. "#EC NOTEXT
    CONSTANTS c_papersize_note TYPE zexcel_sheet_paper_size VALUE 18. "#EC NOTEXT
    CONSTANTS c_papersize_quarto TYPE zexcel_sheet_paper_size VALUE 15. "#EC NOTEXT
    CONSTANTS c_papersize_standard_1 TYPE zexcel_sheet_paper_size VALUE 16. "#EC NOTEXT
    CONSTANTS c_papersize_standard_2 TYPE zexcel_sheet_paper_size VALUE 17. "#EC NOTEXT
    CONSTANTS c_papersize_standard_paper_1 TYPE zexcel_sheet_paper_size VALUE 44. "#EC NOTEXT
    CONSTANTS c_papersize_standard_paper_2 TYPE zexcel_sheet_paper_size VALUE 45. "#EC NOTEXT
    CONSTANTS c_papersize_standard_paper_3 TYPE zexcel_sheet_paper_size VALUE 46. "#EC NOTEXT
    CONSTANTS c_papersize_statement TYPE zexcel_sheet_paper_size VALUE 6. "#EC NOTEXT
    CONSTANTS c_papersize_supera_a4_paper TYPE zexcel_sheet_paper_size VALUE 55. "#EC NOTEXT
    CONSTANTS c_papersize_superb_a3_paper TYPE zexcel_sheet_paper_size VALUE 56. "#EC NOTEXT
    CONSTANTS c_papersize_tabloid TYPE zexcel_sheet_paper_size VALUE 3. "#EC NOTEXT
    CONSTANTS c_papersize_tabl_extra_paper TYPE zexcel_sheet_paper_size VALUE 50. "#EC NOTEXT
    CONSTANTS c_papersize_us_std_fanfold TYPE zexcel_sheet_paper_size VALUE 39. "#EC NOTEXT
    CONSTANTS c_pe_blank TYPE string VALUE 'blank'.         "#EC NOTEXT
    CONSTANTS c_pe_dash TYPE string VALUE 'dash'.           "#EC NOTEXT
    CONSTANTS c_pe_displayed TYPE string VALUE 'displayed'. "#EC NOTEXT
    CONSTANTS c_pe_na TYPE string VALUE 'NA'.               "#EC NOTEXT
    DATA diff_oddeven_headerfooter TYPE flag .
    DATA draft TYPE flag .
    DATA errors TYPE stringval .
    DATA even_footer TYPE zexcel_s_worksheet_head_foot .
    DATA even_header TYPE zexcel_s_worksheet_head_foot .
    DATA first_page_number TYPE int2 .
    DATA fit_to_height TYPE int2 .
    DATA fit_to_page TYPE flag .
    DATA fit_to_width TYPE int2 .
    DATA horizontal_centered TYPE flag .
    DATA horizontal_dpi TYPE int2 .
    DATA margin_bottom TYPE zexcel_dec_8_2 .
    DATA margin_footer TYPE zexcel_dec_8_2 .
    DATA margin_header TYPE zexcel_dec_8_2 .
    DATA margin_left TYPE zexcel_dec_8_2 .
    DATA margin_right TYPE zexcel_dec_8_2 .
    DATA margin_top TYPE zexcel_dec_8_2 .
    DATA odd_footer TYPE zexcel_s_worksheet_head_foot .
    DATA odd_header TYPE zexcel_s_worksheet_head_foot .
    DATA orientation TYPE zexcel_sheet_orienatation .
    DATA page_order TYPE string .
    DATA paper_height TYPE string .
    DATA paper_size TYPE int2 .
    DATA paper_width TYPE string .
    DATA scale TYPE int2 .
    DATA use_first_page_num TYPE flag .
    DATA use_printer_defaults TYPE flag .
    DATA vertical_centered TYPE flag .
    DATA vertical_dpi TYPE int2 .

    METHODS constructor .
    METHODS set_page_margins
      IMPORTING
        !ip_bottom TYPE float OPTIONAL
        !ip_footer TYPE float OPTIONAL
        !ip_header TYPE float OPTIONAL
        !ip_left   TYPE float OPTIONAL
        !ip_right  TYPE float OPTIONAL
        !ip_top    TYPE float OPTIONAL
        !ip_unit   TYPE csequence DEFAULT 'in' .
    METHODS set_header_footer
      IMPORTING
        !ip_odd_header  TYPE zexcel_s_worksheet_head_foot OPTIONAL
        !ip_odd_footer  TYPE zexcel_s_worksheet_head_foot OPTIONAL
        !ip_even_header TYPE zexcel_s_worksheet_head_foot OPTIONAL
        !ip_even_footer TYPE zexcel_s_worksheet_head_foot OPTIONAL .
    METHODS get_header_footer_string
      EXPORTING
        !ep_odd_header  TYPE string
        !ep_odd_footer  TYPE string
        !ep_even_header TYPE string
        !ep_even_footer TYPE string .
    METHODS get_header_footer
      EXPORTING
        !ep_odd_header  TYPE zexcel_s_worksheet_head_foot
        !ep_odd_footer  TYPE zexcel_s_worksheet_head_foot
        !ep_even_header TYPE zexcel_s_worksheet_head_foot
        !ep_even_footer TYPE zexcel_s_worksheet_head_foot .
  PROTECTED SECTION.

*"* protected components of class ZCL_EXCEL_SHEET_SETUP
*"* do not include other source files here!!!
    METHODS process_header_footer
      IMPORTING
        !ip_header                 TYPE zexcel_s_worksheet_head_foot
        !ip_side                   TYPE string
      RETURNING
        VALUE(rv_processed_string) TYPE string .
  PRIVATE SECTION.
*"* private components of class ZCL_EXCEL_SHEET_SETUP
*"* do not include other source files here!!!
ENDCLASS.

CLASS zcl_excel_sheet_setup IMPLEMENTATION.

  METHOD constructor.
    orientation = me->c_orientation_default.

* default margins
    margin_bottom = '0.75'.
    margin_footer = '0.3'.
    margin_header = '0.3'.
    margin_left   = '0.7'.
    margin_right  = '0.7'.
    margin_top    = '0.75'.

* clear page settings
    CLEAR: black_and_white,
           cell_comments,
           copies,
           draft,
           errors,
           first_page_number,
           fit_to_page,
           fit_to_height,
           fit_to_width,
           horizontal_dpi,
           orientation,
           page_order,
           paper_height,
           paper_size,
           paper_width,
           scale,
           use_first_page_num,
           use_printer_defaults,
           vertical_dpi.
  ENDMETHOD.

  METHOD get_header_footer.

* Only Basic font/text formatting possible:
* Bold (yes / no), Font Type, Font Size
*
* usefull placeholders, which can be used in header/footer value strings
* '&P' - page number
* '&N' - total number of pages
* '&D' - Date
* '&T' - Time
* '&F' - File Name
* '&Z' - Path
* '&A' - Sheet name
* new line via class constant CL_ABAP_CHAR_UTILITIES=>newline
*
* Example Value String 'page &P of &N'
*
* DO NOT USE &L , &C or &R which automatically created as position markers

    ep_odd_header = me->odd_header.
    ep_odd_footer = me->odd_footer.
    ep_even_header = me->even_header.
    ep_even_footer = me->even_footer.

  ENDMETHOD.

  METHOD get_header_footer_string.
* ----------------------------------------------------------------------
    DATA:   lc_marker_left(2)   TYPE c VALUE '&L'
          , lc_marker_right(2)  TYPE c VALUE '&R'
          , lc_marker_center(2) TYPE c VALUE '&C'
          , lv_value            TYPE string
          .
* ----------------------------------------------------------------------
    IF ep_odd_header IS SUPPLIED.

      IF me->odd_header-left_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'LEFT' ).
        CONCATENATE lc_marker_left lv_value INTO ep_odd_header.
      ENDIF.

      IF me->odd_header-center_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'CENTER' ).
        CONCATENATE ep_odd_header lc_marker_center lv_value INTO ep_odd_header.
      ENDIF.

      IF me->odd_header-right_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'RIGHT' ).
        CONCATENATE ep_odd_header lc_marker_right lv_value INTO ep_odd_header.
      ENDIF.

      IF me->odd_header-left_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_left lv_value INTO ep_odd_header.
      ENDIF.
      IF me->odd_header-center_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_center lv_value INTO ep_odd_header.
      ENDIF.
      IF me->odd_header-right_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_right lv_value INTO ep_odd_header.
      ENDIF.

    ENDIF.
* ----------------------------------------------------------------------
    IF ep_odd_footer IS SUPPLIED.

      IF me->odd_footer-left_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'LEFT' ).
        CONCATENATE lc_marker_left lv_value INTO ep_odd_footer.
      ENDIF.

      IF me->odd_footer-center_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'CENTER' ).
        CONCATENATE ep_odd_footer lc_marker_center lv_value INTO ep_odd_footer.
      ENDIF.

      IF me->odd_footer-right_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'RIGHT' ).
        CONCATENATE ep_odd_footer lc_marker_right lv_value INTO ep_odd_footer.
      ENDIF.

      IF me->odd_footer-left_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_left lv_value INTO ep_odd_footer.
      ENDIF.
      IF me->odd_footer-center_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_center lv_value INTO ep_odd_footer.
      ENDIF.
      IF me->odd_footer-right_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_right lv_value INTO ep_odd_footer.
      ENDIF.

    ENDIF.
* ----------------------------------------------------------------------
    IF ep_even_header IS SUPPLIED.

      IF me->even_header-left_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'LEFT' ).
        CONCATENATE lc_marker_left lv_value INTO ep_even_header.
      ENDIF.

      IF me->even_header-center_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'CENTER' ).
        CONCATENATE ep_even_header lc_marker_center lv_value INTO ep_even_header.
      ENDIF.

      IF me->even_header-right_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'RIGHT' ).
        CONCATENATE ep_even_header lc_marker_right lv_value INTO ep_even_header.
      ENDIF.

      IF me->even_header-left_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_left lv_value INTO ep_even_header.
      ENDIF.
      IF me->even_header-center_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_center lv_value INTO ep_even_header.
      ENDIF.
      IF me->even_header-right_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_right lv_value INTO ep_even_header.
      ENDIF.

    ENDIF.
* ----------------------------------------------------------------------
    IF ep_even_footer IS SUPPLIED.

      IF me->even_footer-left_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'LEFT' ).
        CONCATENATE lc_marker_left lv_value INTO ep_even_footer.
      ENDIF.

      IF me->even_footer-center_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'CENTER' ).
        CONCATENATE ep_even_footer lc_marker_center lv_value INTO ep_even_footer.
      ENDIF.

      IF me->even_footer-right_value IS NOT INITIAL.
        lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'RIGHT' ).
        CONCATENATE ep_even_footer lc_marker_right lv_value INTO ep_even_footer.
      ENDIF.

      IF me->even_footer-left_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_left lv_value INTO ep_even_footer.
      ENDIF.
      IF me->even_footer-center_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_center lv_value INTO ep_even_footer.
      ENDIF.
      IF me->even_footer-right_image IS NOT INITIAL.
        lv_value = '&G'.
        CONCATENATE ep_odd_header lc_marker_right lv_value INTO ep_even_footer.
      ENDIF.

    ENDIF.
* ----------------------------------------------------------------------
  ENDMETHOD.

  METHOD process_header_footer.

* ----------------------------------------------------------------------
* Only Basic font/text formatting possible:
* Bold (yes / no), Font Type, Font Size

    DATA:   lv_fname(12) TYPE c
          , lv_string    TYPE string
          .

    FIELD-SYMBOLS:   <lv_value> TYPE string
                   , <ls_font>  TYPE zexcel_s_style_font
                   .

* ----------------------------------------------------------------------
    CONCATENATE ip_side '_VALUE' INTO lv_fname.
    ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <lv_value>.

    CONCATENATE ip_side '_FONT' INTO lv_fname.
    ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <ls_font>.

    IF <ls_font> IS ASSIGNED AND <lv_value> IS ASSIGNED.

      IF <lv_value> = '&G'. "image header
        rv_processed_string = <lv_value>.
      ELSE.

        IF <ls_font>-name IS NOT INITIAL.
          CONCATENATE '&"' <ls_font>-name ',' INTO rv_processed_string.
        ELSE.
          rv_processed_string = '&"-,'.
        ENDIF.

        IF <ls_font>-bold = abap_true.
          CONCATENATE rv_processed_string 'Bold"' INTO rv_processed_string.
        ELSE.
          CONCATENATE rv_processed_string 'Standard"' INTO rv_processed_string.
        ENDIF.

        IF <ls_font>-size IS NOT INITIAL.
          lv_string = <ls_font>-size.
          CONCATENATE rv_processed_string '&' lv_string INTO rv_processed_string.
          CONDENSE rv_processed_string NO-GAPS.
        ENDIF.

        CONCATENATE rv_processed_string <lv_value> INTO rv_processed_string.
      ENDIF.
    ENDIF.
* ----------------------------------------------------------------------

  ENDMETHOD.

  METHOD set_header_footer.

* Only Basic font/text formatting possible:
* Bold (yes / no), Font Type, Font Size
*
* usefull placeholders, which can be used in header/footer value strings
* '&P' - page number
* '&N' - total number of pages
* '&D' - Date
* '&T' - Time
* '&F' - File Name
* '&Z' - Path
* '&A' - Sheet name
* new line via class constant CL_ABAP_CHAR_UTILITIES=>newline
*
* Example Value String 'page &P of &N'
*
* DO NOT USE &L , &C or &R which automatically created as position markers

    me->odd_header = ip_odd_header.
    me->odd_footer = ip_odd_footer.
    me->even_header = ip_even_header.
    me->even_footer = ip_even_footer.

    IF me->even_header IS NOT INITIAL OR me->even_footer IS NOT INITIAL.
      me->diff_oddeven_headerfooter = abap_true.
    ENDIF.

  ENDMETHOD.

  METHOD set_page_margins.
    DATA: lv_coef TYPE f,
          lv_unit TYPE string.

    lv_unit = ip_unit.
    TRANSLATE lv_unit TO UPPER CASE.

    CASE lv_unit.
      WHEN 'IN'. lv_coef = 1.
      WHEN 'CM'. lv_coef = '0.393700787'.
      WHEN 'MM'. lv_coef = '0.0393700787'.
    ENDCASE.

    IF ip_bottom IS SUPPLIED. margin_bottom = lv_coef * ip_bottom. ENDIF.
    IF ip_footer IS SUPPLIED. margin_footer = lv_coef * ip_footer. ENDIF.
    IF ip_header IS SUPPLIED. margin_header = lv_coef * ip_header. ENDIF.
    IF ip_left IS SUPPLIED.   margin_left   = lv_coef * ip_left. ENDIF.
    IF ip_right IS SUPPLIED.  margin_right  = lv_coef * ip_right. ENDIF.
    IF ip_top IS SUPPLIED.    margin_top    = lv_coef * ip_top. ENDIF.

  ENDMETHOD.
ENDCLASS.