Z Sap BW Note Analyzer

You might also like

Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 178

************************************************************************

* Z_SAP_BW_NOTE_ANALYZER (SAP Note 2383530)


* Provided by Product Management SAP EDW (BW/HANA)
*
* The SAP BW Note Analyzer provides customers a clear and consistent
* process to update a particular component of SAP BW or SAP BW/4HANA
* without implementing support packages or going through SAP Note
* nightmares
*
* (c) SAP SE 2017-18 MFB, SAP Canada Inc.
* Last update: 2018-12-04
************************************************************************

REPORT z_sap_bw_note_analyzer.

TYPE-POOLS: abap, slis, icon, bcwbn.

* Version of this program (Ideally corresponds to the version no in development


system)
CONSTANTS gc_version TYPE n LENGTH 4 VALUE '0119'.

CONSTANTS gc_guide TYPE string


VALUE 'https://help.sap.com/doc/b235b5bd94664d9986f721f049d72cbb/1.0/en-
US/User_Guide_for_SAP_BW_Note_Analyzer.pdf'.

* Versions history (for complete history see SAP Note 1909597)


* 0116: Fixed duplicate entries in result when downloading note in dialog mode
* Fixed status check of implemented SAP Notes
* Changed action icon to "upload" in case UDO program does not exist yet
* 0117: Adedd support for uninstalling add-ons (download/upload software packages)
* Added check for implemented but outdated SAP Notes
* 0118: Minor correction to display correct version of implemented SAP Notes
* Adjust some message texts
* Fixed syntax error and dump in release 70x
* 0119: Improved messages in batch job for SAP Notes download
* Avoid second message in case SAP Note needs to be downloaded
* Improved check of SAP Notes marked as obsolete or outdated
* Added "Number of SAP Notes to be downloaded/implemeted" to summary section
* Enhancement to allow definition of conditions for displaying SAP Notes

CONSTANTS:
gc_unknown TYPE c VALUE '-',
gc_display TYPE c VALUE '+'.

*&---------------------------------------------------------------------*
*& Include STC_NOTE_ANALYZER_DEF
*&---------------------------------------------------------------------*

**********************************************************************
* Global Type Definitions for Note Analyzer
**********************************************************************

* Entities introduced with the report


TYPES gty_scope_id TYPE c LENGTH 60.
TYPES gty_solution TYPE c LENGTH 30.
TYPES gty_tab_notes TYPE STANDARD TABLE OF cwbntnumm WITH NON-UNIQUE KEY
table_line.
TYPES gty_splevel TYPE c LENGTH 2.
TYPES gty_splevel_n TYPE n LENGTH 2.
TYPES gty_purpose TYPE c LENGTH 1.
TYPES gty_tab_rng_scope_id TYPE RANGE OF gty_scope_id.

* Scope definition structure


TYPES: BEGIN OF gty_str_scope_def,
scope_id TYPE gty_scope_id,
description TYPE string,
solution TYPE gty_solution,
doku_ref TYPE string,
END OF gty_str_scope_def.
* Scope is unique key, however defining it here in ABAP might lead to let the
transformation dump => check in ABAP instead
TYPES gty_tab_scope_def TYPE STANDARD TABLE OF gty_str_scope_def WITH NON-UNIQUE
DEFAULT KEY.

*TYPES: BEGIN OF gty_str_sol_def,


* scope_id TYPE gty_scope_id,
* solution TYPE gty_solution,
* END OF gty_str_sol_def.
*TYPES gty_tab_sol_def TYPE STANDARD TABLE OF gty_str_sol_def WITH NON-UNIQUE
DEFAULT KEY.

* Scope checking structure


TYPES: BEGIN OF gty_str_scope_check,
scope_id_uses TYPE gty_scope_id,
scope_id_used TYPE gty_scope_id,
severity TYPE symsgty,
message TYPE c LENGTH 200,
END OF gty_str_scope_check.
TYPES gty_tab_scope_check TYPE STANDARD TABLE OF gty_str_scope_check WITH NON-
UNIQUE DEFAULT KEY.

* Parameter checking structure


TYPES: BEGIN OF gty_str_param_check,
scope_id TYPE gty_scope_id,
param_name TYPE pfeparname,
severity TYPE symsgty,
message TYPE c LENGTH 200,
flg_chk_only TYPE boolean,
option TYPE c LENGTH 2,
value TYPE pfepvalue,
END OF gty_str_param_check.
TYPES: gty_tab_param_check TYPE STANDARD TABLE OF gty_str_param_check WITH NON-
UNIQUE DEFAULT KEY.

* Component checking structure


TYPES: BEGIN OF gty_str_comp_check,
scope_id TYPE gty_scope_id,
severity TYPE symsgty,
message TYPE c LENGTH 200,
swcomponent TYPE dlvunit,
rel_option TYPE c LENGTH 2,
release TYPE saprelease,
splevel TYPE sappatchlv,
END OF gty_str_comp_check.
TYPES gty_tab_comp_check TYPE STANDARD TABLE OF gty_str_comp_check WITH NON-UNIQUE
DEFAULT KEY.

* Note checking structure


TYPES: BEGIN OF gty_str_note_check,
scope_id TYPE gty_scope_id,
number TYPE cwbntnumm,
description TYPE string,
version TYPE n LENGTH 4,
END OF gty_str_note_check.
TYPES: gty_tab_note_check TYPE STANDARD TABLE OF gty_str_note_check WITH NON-UNIQUE
DEFAULT KEY.

* Note validity information


TYPES: BEGIN OF gty_str_note_validity,
number TYPE cwbntnumm,
swcomponent TYPE dlvunit,
release TYPE saprelease,
* splevel TYPE sappatchlv,
* Patch level is defined a char 10, however note analyzer calculates note validity
depending on
* correction instructions, so actually we can work on numc 2 at moment. If you
change this here,
* change the coding for calculation, too.
splevel TYPE gty_splevel,
END OF gty_str_note_validity.
TYPES: gty_tab_note_validity TYPE SORTED TABLE OF gty_str_note_validity WITH NON-
UNIQUE KEY number.

* Note Comment structure


TYPES: BEGIN OF gty_str_note_comment,
number TYPE cwbntnumm,
severity TYPE symsgty,
message TYPE c LENGTH 200,
purpose TYPE gty_purpose,
target_note TYPE cwbntnumm,
END OF gty_str_note_comment.
* TYPES: gty_tab_note_comment TYPE SORTED TABLE OF gty_str_note_comment WITH NON-
UNIQUE KEY number.
TYPES: gty_tab_note_comment TYPE STANDARD TABLE OF gty_str_note_comment WITH NON-
UNIQUE KEY number.

* Solution File
TYPES: BEGIN OF gty_str_file,
scope_def TYPE gty_tab_scope_def,
* sol_def TYPE gty_tab_sol_def,
prep_note_check TYPE gty_tab_note_check,
scope_check TYPE gty_tab_scope_check,
param_check TYPE gty_tab_param_check,
comp_check TYPE gty_tab_comp_check,
note_check TYPE gty_tab_note_check,
note_validity TYPE gty_tab_note_validity,
note_comment TYPE gty_tab_note_comment,
END OF gty_str_file.

**********************************************************************************
* End of global definition for sharing with XML
*********************************************************************************

TYPES: BEGIN OF gty_str_header,


number TYPE cwbntnumm,
xml_id TYPE c LENGTH 20,
xml_version TYPE c LENGTH 15,
END OF gty_str_header.
TYPES: gty_tab_header TYPE STANDARD TABLE OF gty_str_header WITH DEFAULT KEY.

TYPES: BEGIN OF gty_str_release_patch,


release TYPE n LENGTH 3,
version TYPE n LENGTH 5,
patch TYPE n LENGTH 5,
END OF gty_str_release_patch.

TYPES: gty_version TYPE n LENGTH 4.

*----------------------------------------------------------------------*
* CLASS lcl_wb DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_wb DEFINITION.

PUBLIC SECTION.

CLASS-METHODS save_log.

CLASS-METHODS display_log
IMPORTING
i_db_search TYPE xfeld OPTIONAL "search logs on db
i_no_save TYPE xfeld OPTIONAL
i_report TYPE program.

CLASS-METHODS set_context
IMPORTING
i_object TYPE e071-object
i_obj_name TYPE c
i_obj_name2 TYPE c OPTIONAL
i_text TYPE c OPTIONAL
i_no_message TYPE c OPTIONAL
i_langu TYPE sylangu.

CLASS-METHODS language_installed
IMPORTING
i_langu TYPE sylangu
RETURNING
value(r_installed) TYPE xfeld.

CLASS-METHODS log_message.

CLASS-METHODS get_object_text
IMPORTING
i_object TYPE e071-object "e.g. TABD
i_obj_name TYPE c OPTIONAL "for DOCU
RETURNING
value(r_text) TYPE string.

ENDCLASS. "lcl_wb DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_utilities DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_utilities DEFINITION FINAL.

PUBLIC SECTION.
* Constants must match lcl_msg
CONSTANTS:
gc_info TYPE symsgty VALUE 'I',
gc_action_none TYPE symsgty VALUE space.

TYPES:
gty_code TYPE c LENGTH 255,
gty_tab_code TYPE STANDARD TABLE OF gty_code.

CLASS-METHODS open_xml
IMPORTING
iv_title TYPE string OPTIONAL
iv_pattern TYPE string OPTIONAL
EXPORTING
es_str_file TYPE gty_str_file
ev_xml TYPE xstring
ev_filename TYPE string
ev_flg_loaded TYPE abap_bool.

CLASS-METHODS save_xml
IMPORTING
is_file TYPE gty_str_file.

CLASS-METHODS call_browser
IMPORTING
iv_url TYPE csequence.

CLASS-DATA:
gv_fast TYPE abap_bool,
gv_uninstall TYPE abap_bool,
gv_debug TYPE string.

CLASS-METHODS open_abap
IMPORTING
iv_title TYPE string OPTIONAL
iv_pattern TYPE clike OPTIONAL
EXPORTING
et_code TYPE gty_tab_code
ev_filename TYPE string
ev_flg_loaded TYPE abap_bool.

CLASS-METHODS format
IMPORTING
iv_value TYPE clike
RETURNING
value(ev_value) TYPE string.

CLASS-METHODS display_logs.

CLASS-METHODS is_system_modifiable
RETURNING
value(rv_modifiable) TYPE abap_bool.

CLASS-METHODS is_system_test_or_prod
RETURNING
value(rv_test_prod) TYPE abap_bool.

CLASS-METHODS is_snote_allowed
RETURNING
value(rv_snote_allowed) TYPE abap_bool.

CLASS-METHODS is_upgrage_running
RETURNING
value(rv_upgrade_running) TYPE abap_bool.

CLASS-METHODS is_spam_locked
RETURNING
value(rv_spam_locked) TYPE abap_bool.

CLASS-METHODS is_fast
IMPORTING
value(iv_msg_type) TYPE symsgty DEFAULT gc_info
value(iv_action) TYPE symsgty DEFAULT gc_action_none
RETURNING
value(rv_fast) TYPE abap_bool.

CLASS-METHODS is_debug
IMPORTING
value(iv_check) TYPE any
RETURNING
value(rv_debug) TYPE abap_bool.

CLASS-METHODS get_db_release
EXPORTING
es_dbinfo TYPE dbrelinfo
es_hana_release TYPE gty_str_release_patch.

CLASS-METHODS get_spam_release
RETURNING
value(rs_details) TYPE gty_str_release_patch.

CLASS-METHODS get_kernel_release
RETURNING
value(rs_details) TYPE gty_str_release_patch.

ENDCLASS. "lcl_utilities DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_files DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_files DEFINITION FINAL.

PUBLIC SECTION.

TYPES:
gty_file_type TYPE i.

CONSTANTS:
gc_file_type_bw TYPE gty_file_type VALUE 2,
gc_file_type_val TYPE gty_file_type VALUE 8,
gc_file_type_others TYPE gty_file_type VALUE 9.

TYPES:
BEGIN OF gty_str_file_info,
type TYPE gty_file_type,
title TYPE string,
pattern TYPE string,
END OF gty_str_file_info,
BEGIN OF gty_str_store_files,
type TYPE gty_file_type,
filename TYPE string,
file TYPE gty_str_file,
END OF gty_str_store_files,

gty_tab_store_files TYPE SORTED TABLE OF gty_str_store_files


WITH UNIQUE KEY type filename.

DATA mt_file TYPE gty_tab_store_files.

CLASS-METHODS get_instance
RETURNING
value(ro_instance) TYPE REF TO lcl_files.

METHODS is_file_loaded
IMPORTING
iv_file_type TYPE gty_file_type
RETURNING
value(rv_loaded) TYPE abap_bool.

METHODS get_next_file_info
RETURNING
value(rs_file_info) TYPE gty_str_file_info.

METHODS add_file
IMPORTING
iv_filename TYPE string
is_file TYPE gty_str_file.

METHODS get_merged_file
IMPORTING
iv_filter_scope_id TYPE gty_scope_id OPTIONAL
EXPORTING
es_file TYPE gty_str_file.

METHODS get_validation_scope
EXPORTING
et_rng_val_scope TYPE gty_tab_rng_scope_id.

METHODS get_file_count
RETURNING
value(rv_count) TYPE i.

METHODS get_file_count_notes
RETURNING
value(rv_count) TYPE i.

PRIVATE SECTION.

CONSTANTS:
gc_scope_val TYPE gty_scope_id VALUE 'XML_VAL',
gc_solution_bw TYPE gty_solution VALUE 'BW'.

TYPES:
gty_tab_file_info TYPE SORTED TABLE OF gty_str_file_info
WITH UNIQUE KEY type,
gty_tab_scope TYPE STANDARD TABLE OF gty_scope_id.
DATA:
mt_file_info TYPE gty_tab_file_info.

METHODS _merge_file
IMPORTING
is_new_file TYPE gty_str_file
CHANGING
cs_old_file TYPE gty_str_file.

METHODS _filter_file
IMPORTING
iv_filter_scope_id TYPE gty_scope_id
CHANGING
cs_file TYPE gty_str_file.

METHODS _get_required_scope
IMPORTING
iv_sel_scope TYPE gty_scope_id
is_file TYPE gty_str_file
EXPORTING
et_scope TYPE gty_tab_scope.

METHODS _derive_file_type
IMPORTING
is_file TYPE gty_str_file
RETURNING
value(rv_file_type) TYPE gty_file_type.

ENDCLASS. "lcl_files DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_bw_check DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_bw_check DEFINITION FINAL.

PUBLIC SECTION.

CLASS-METHODS get_instance
RETURNING
value(ro_instance) TYPE REF TO lcl_bw_check.

METHODS is_bw_relevant
RETURNING
value(rv_relevant) TYPE abap_bool.

METHODS is_bw_system
RETURNING
value(rv_is) TYPE abap_bool.

METHODS is_connected_system
RETURNING
value(rv_is) TYPE abap_bool.

METHODS toggle_modif_group_visibility
IMPORTING
io_files TYPE REF TO lcl_files
CHANGING
cs_screen TYPE screen.
PRIVATE SECTION.

TYPES:
BEGIN OF ts_modif_visible,
is_relevant TYPE abap_bool,
is_bw_default TYPE abap_bool,
has_src_wo_odp TYPE abap_bool,
has_opd_src TYPE abap_bool,
has_target_wo_odp TYPE abap_bool,
has_target_wo_odp_src TYPE abap_bool,
has_opd_target TYPE abap_bool,
has_opd_target_wo_src TYPE abap_bool,
has_target TYPE abap_bool,
has_dw4core_comp TYPE abap_bool,
has_pi_basis TYPE abap_bool,
END OF ts_modif_visible.

DATA:
mv_has_source TYPE abap_bool,
mv_has_target TYPE abap_bool,
mv_has_odp_source TYPE abap_bool,
mv_has_odp_target TYPE abap_bool,
mv_has_dw4core TYPE abap_bool,
mv_has_pi_basis TYPE abap_bool, "#EC NEEDED
ms_modif_visible TYPE ts_modif_visible. "#EC NEEDED

METHODS has_system_targets
RETURNING
value(rv_has) TYPE abap_bool.

METHODS has_system_sources
RETURNING
value(rv_has) TYPE abap_bool.

METHODS has_odp_targets
RETURNING
value(rv_has) TYPE abap_bool.

METHODS has_odp_sources
RETURNING
value(rv_has) TYPE abap_bool.

METHODS has_pi_basis
RETURNING
value(rv_has) TYPE abap_bool.

METHODS has_dw4_core
RETURNING
value(rv_has) TYPE abap_bool.

ENDCLASS. "lcl_bw_check DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_msg DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_msg DEFINITION FINAL.

PUBLIC SECTION.
TYPES:
gty_action TYPE symsgty,
gty_text_id TYPE c LENGTH 3,
gty_count TYPE n LENGTH 4,
gty_object TYPE c LENGTH 40.

CONSTANTS:
gc_action_none TYPE gty_action VALUE space,
gc_action_auto_impl TYPE gty_action VALUE '1',
gc_action_man_impl TYPE gty_action VALUE '2',
gc_action_msg_sap TYPE gty_action VALUE '3',
gc_action_check_usage TYPE gty_action VALUE '4',
gc_action_load_file TYPE gty_action VALUE '5',
gc_action_delta_file TYPE gty_action VALUE '6',
gc_action_impl_tool TYPE gty_action VALUE '7',
gc_action_impl_issue TYPE gty_action VALUE '8',
gc_action_web_link TYPE gty_action VALUE '9',
gc_action_sp_impl TYPE gty_action VALUE 'A',
gc_action_read_note TYPE gty_action VALUE 'B',
gc_action_download_note TYPE gty_action VALUE 'C',
gc_action_tci_download TYPE gty_action VALUE 'D',
gc_action_tci_upload TYPE gty_action VALUE 'E',
gc_action_icf_activate TYPE gty_action VALUE 'F',
gc_action_note_inactive TYPE gty_action VALUE 'G',
gc_action_note_reset TYPE gty_action VALUE 'H',
gc_action_udo_upload TYPE gty_action VALUE 'I',
gc_action_sw_download TYPE gty_action VALUE 'J',
gc_action_sw_upload TYPE gty_action VALUE 'K',

gc_node_sys_info TYPE i VALUE 200,


gc_node_scope_check TYPE i VALUE 300,
gc_node_param_check TYPE i VALUE 400,
gc_node_comp_check TYPE i VALUE 500,
gc_node_prep_check TYPE i VALUE 600,
gc_node_note_check TYPE i VALUE 700,
gc_node_summary TYPE i VALUE 900,

gc_success TYPE sy-msgty VALUE 'S',


gc_info TYPE sy-msgty VALUE 'I',
gc_warning TYPE sy-msgty VALUE 'W',
gc_error TYPE sy-msgty VALUE 'E',
gc_abort TYPE sy-msgty VALUE 'A',

gc_scope_summary TYPE gty_scope_id VALUE 'SUMMARY',

gc_msg_download TYPE string VALUE 'in system and needs to be


downloaded'.

TYPES:
BEGIN OF gty_str_msg,
sequence TYPE i,
node TYPE i,
scope_id TYPE gty_scope_id,
msg_type TYPE symsgty,
object TYPE gty_object,
text TYPE string,
action TYPE gty_action,
short_text_id TYPE gty_text_id,
long_text_id TYPE gty_text_id,
target_note TYPE string, "cwbntnumm but also other domains
impl_status TYPE cwbprstat,
swcomponent TYPE dlvunit,
release TYPE saprelease,
splevel TYPE sappatchlv,
purpose TYPE gty_purpose,
END OF gty_str_msg,

gty_tab_msg TYPE SORTED TABLE OF gty_str_msg


WITH UNIQUE KEY node sequence.

DATA:
mt_header TYPE gty_tab_header,
mv_version TYPE string.

CLASS-METHODS get_instance
RETURNING
value(ro_instance) TYPE REF TO lcl_msg.

METHODS start_node
IMPORTING
iv_node TYPE i
iv_description TYPE gty_text_id
iv_msg_v1 TYPE clike OPTIONAL.

METHODS end_node
IMPORTING
iv_node TYPE i.

METHODS update_node_status.

METHODS get_msg_text
IMPORTING
iv_object TYPE clike
iv_msg_text TYPE gty_text_id
iv_msg_v1 TYPE clike OPTIONAL
iv_msg_v2 TYPE clike OPTIONAL
iv_msg_v3 TYPE clike OPTIONAL
iv_msg_v4 TYPE clike OPTIONAL
EXPORTING
ev_text TYPE string
ev_short_id TYPE gty_text_id
ev_long_id TYPE gty_text_id.

METHODS find_msg
IMPORTING
is_msg TYPE gty_str_msg
RETURNING
value(rv_sequence) TYPE i.

METHODS delete_msg
IMPORTING
is_msg TYPE gty_str_msg.

METHODS set_msg
IMPORTING
is_msg TYPE gty_str_msg
iv_sequence TYPE i.
METHODS add_msg
IMPORTING
iv_msg_type TYPE symsgty DEFAULT gc_error
iv_scope_id TYPE gty_scope_id
iv_object TYPE clike
iv_action TYPE gty_action
iv_msg_text TYPE gty_text_id OPTIONAL
iv_msg_v1 TYPE clike OPTIONAL
iv_msg_v2 TYPE clike OPTIONAL
iv_msg_v3 TYPE clike OPTIONAL
iv_msg_v4 TYPE clike OPTIONAL
iv_target_note TYPE clike OPTIONAL
iv_text TYPE csequence OPTIONAL
iv_purpose TYPE c OPTIONAL
iv_impl_status TYPE cwbprstat OPTIONAL
iv_swcomponent TYPE dlvunit OPTIONAL
iv_release TYPE saprelease OPTIONAL
iv_splevel TYPE gty_splevel OPTIONAL
RETURNING
value(rv_sequence) TYPE i.

METHODS add_msg_direct
IMPORTING
iv_msg_type TYPE symsgty
iv_scope_id TYPE gty_scope_id
iv_object TYPE clike
iv_action TYPE gty_action
iv_msg_text TYPE csequence
iv_target_note TYPE string OPTIONAL
iv_purpose TYPE c OPTIONAL.

METHODS add_t100_msg
IMPORTING
iv_msg_type TYPE symsgty DEFAULT gc_error
iv_scope_id TYPE gty_scope_id
iv_object TYPE clike
iv_action TYPE gty_action.

METHODS get_msg
EXPORTING
et_msg TYPE gty_tab_msg.

METHODS get_status
IMPORTING
iv_node TYPE i OPTIONAL
RETURNING
value(rv_msg_type) TYPE symsgty.

PRIVATE SECTION.

TYPES:
BEGIN OF gty_str_symsgty,
id TYPE symsgid,
number TYPE symsgno,
type TYPE symsgty,
msgv1 TYPE symsgv,
msgv2 TYPE symsgv,
msgv3 TYPE symsgv,
msgv4 TYPE symsgv,
END OF gty_str_symsgty,

gty_tab_symsgty TYPE SORTED TABLE OF gty_str_symsgty


WITH UNIQUE KEY id number type msgv1 msgv2 msgv3 msgv4,

BEGIN OF gty_node,
node TYPE i,
start TYPE i,
END OF gty_node,

gty_nodes TYPE SORTED TABLE OF gty_node


WITH UNIQUE KEY node.

DATA:
mt_msg TYPE gty_tab_msg,
mt_stored_t100_msg TYPE gty_tab_symsgty,
mv_current_node TYPE i,
mv_start_node_sequence TYPE i,
mt_nodes TYPE gty_nodes,
mv_current_sequence TYPE i,
mv_current_scope TYPE gty_scope_id,
mv_current_object TYPE gty_object,
mv_summary TYPE symsgty.

ENDCLASS. "lcl_msg DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_msg_repository DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_msg_repository DEFINITION FINAL.

PUBLIC SECTION.

CLASS-METHODS get_short_text
IMPORTING
iv_text_id TYPE lcl_msg=>gty_text_id
RETURNING
value(rv_text) TYPE string.

CLASS-METHODS get_long_text
IMPORTING
iv_text_id TYPE lcl_msg=>gty_text_id
RETURNING
value(rv_text) TYPE string.

CLASS-METHODS show_text_in_pop_up
IMPORTING
iv_text_id TYPE lcl_msg=>gty_text_id
iv_msg_type TYPE symsgty.

PRIVATE SECTION.

TYPES:
gty_fixed_text TYPE c LENGTH 60,
gty_tab_string TYPE STANDARD TABLE OF string WITH DEFAULT KEY.

CLASS-METHODS _split_string
IMPORTING
it_string TYPE gty_tab_string
EXPORTING
ev_text TYPE gty_fixed_text
CHANGING
cv_start_index TYPE sytabix.

ENDCLASS. "lcl_msg_repository DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_checks DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_checks DEFINITION FINAL.

PUBLIC SECTION.

TYPES:
tn_t_log_hdr TYPE STANDARD TABLE OF balhdr WITH DEFAULT KEY,
tn_t_bal_msg TYPE STANDARD TABLE OF bal_s_msg WITH DEFAULT KEY,

BEGIN OF tn_s_bal_log_msg,
log_hdr TYPE balhdr,
t_msg TYPE tn_t_bal_msg,
END OF tn_s_bal_log_msg,

tn_t_bal_log_msg TYPE STANDARD TABLE OF tn_s_bal_log_msg WITH DEFAULT KEY,

BEGIN OF tn_s_note_inactive,
numm TYPE cwbntnumm,
versno TYPE cwbntvers,
objtype TYPE trobjtype,
objname TYPE trobj_name,
END OF tn_s_note_inactive,

tn_t_note_inactive TYPE HASHED TABLE OF tn_s_note_inactive WITH UNIQUE


DEFAULT KEY.

CLASS-DATA:
nt_note_inactive TYPE tn_t_note_inactive.

CLASS-METHODS get_instance
IMPORTING
is_file TYPE gty_str_file
RETURNING
value(ro_instance) TYPE REF TO lcl_checks.

METHODS add_info_from_sel_screen
IMPORTING
iv_filter_scope_id TYPE gty_scope_id OPTIONAL
io_bw_check TYPE REF TO lcl_bw_check OPTIONAL.

METHODS reset_msg.

METHODS check_all
IMPORTING
iv_flg_download TYPE abap_bool DEFAULT abap_false
iv_flg_resolve TYPE abap_bool DEFAULT abap_false
RETURNING
value(ro_msg) TYPE REF TO lcl_msg.
METHODS validate_all
IMPORTING
it_rng_val_scope TYPE gty_tab_rng_scope_id
EXPORTING
eo_msg TYPE REF TO lcl_msg
es_delta_file TYPE gty_str_file.

METHODS get_all_notes
EXPORTING
et_notes TYPE gty_tab_notes.

METHODS get_needed_notes
EXPORTING
et_notes TYPE gty_tab_notes.

METHODS is_scope_consistent
EXPORTING
ev_flg_ok TYPE abap_bool
eo_msg TYPE REF TO lcl_msg.

METHODS check_note_again
IMPORTING
is_msg TYPE lcl_msg=>gty_str_msg.

METHODS evaluate_t_bal_msg
IMPORTING
i_t_bal_log_msg TYPE tn_t_bal_log_msg
i_no_of_exec TYPE i
RETURNING
value(rv_msg_type) TYPE symsgty.

METHODS get_bal_log
IMPORTING
i_udo_report TYPE program
RETURNING
value(r_t_bal_log_msg) TYPE tn_t_bal_log_msg.

METHODS split_udo
IMPORTING
i_udo_comment TYPE string
EXPORTING
e_udo_report TYPE program
e_no_of_exec TYPE i
e_release TYPE saprelease.

METHODS split_tci
IMPORTING
i_tci_comment TYPE string
EXPORTING
e_tci_sar TYPE string
e_tci_url TYPE string
e_release TYPE saprelease.

METHODS split_icf
IMPORTING
i_icf_comment TYPE string
EXPORTING
e_icf_name TYPE icfname
e_icf_par TYPE icfparguid
e_icf_path TYPE string
e_icf_text TYPE string
e_release TYPE saprelease.

METHODS check_icf_service
IMPORTING
i_icf_name TYPE icfname
i_icf_par TYPE icfparguid
RETURNING
value(r_icf_status) TYPE abap_bool.

METHODS get_header
RETURNING
value(et_header) TYPE gty_tab_header.

METHODS get_version
RETURNING
value(rv_version) TYPE gty_version.

METHODS check_outdated_notes
IMPORTING
it_notes TYPE gty_tab_notes
EXPORTING
et_changed_notes TYPE bcwbn_note_keys_vs.

METHODS update_outdated_notes
IMPORTING
it_changed_notes TYPE bcwbn_note_keys_vs.

METHODS remove_outdated_note
IMPORTING
iv_note_number TYPE cwbntnumm.

PRIVATE SECTION.

CONSTANTS:
* From include CWBNTCNS
gc_prstat_implemented TYPE cwbprstat VALUE 'E',
gc_prstat_obsolete TYPE cwbprstat VALUE 'O',
gc_prstat_initial TYPE cwbprstat VALUE ' ',
gc_prstat_old_vrs_impl TYPE cwbprstat VALUE 'V',
gc_prstat_incompl_impl TYPE cwbprstat VALUE 'U',
gc_prstat_not_implemented TYPE cwbprstat VALUE 'N',
gc_prstat_no_valid_cinst TYPE cwbprstat VALUE '-',

gc_note_status_new TYPE cwbntstat VALUE 'N', "#EC NEEDED


gc_note_status_finished TYPE cwbntstat VALUE 'A',
gc_note_status_not_relevant TYPE cwbntstat VALUE 'R', "#EC NEEDED
gc_note_status_in_process TYPE cwbntstat VALUE 'I', "#EC NEEDED

* Implementation sttatus - do not change order


gc_implemented_deimplement TYPE i VALUE -2,
gc_implemented_obsolete TYPE i VALUE -1,
gc_implemented_completely TYPE i VALUE 0,
gc_implemented_inactive TYPE i VALUE 1,
gc_implemented_not_valid TYPE i VALUE 2,
gc_implemented_incomplete TYPE i VALUE 4,
gc_implemented_old_vers TYPE i VALUE 5,
gc_implemented_outdated TYPE i VALUE 6,
gc_implemented_not_yet TYPE i VALUE 7,
gc_implemented_error TYPE i VALUE 8,
gc_implemented_unknown TYPE i VALUE 12,

* Additional "software components"


gc_sw_comp_kernel TYPE dlvunit VALUE 'KERNEL',
gc_sw_comp_spam TYPE dlvunit VALUE 'SPAM',
gc_sw_comp_hana TYPE dlvunit VALUE 'HANA',

* From function SCWB_NOTES_RESOLVE_NECESSARY


gc_cwbadm_cs_nt TYPE rfcdest VALUE 'SAPOSS',
gc_cwbadm_cs_nt_new TYPE rfcdest VALUE 'SAPSNOTE'.

TYPE-POOLS: bcwbn.

TYPES:
BEGIN OF gty_str_note_details.
INCLUDE TYPE gty_str_note_check.
TYPES:
flg_manual_activities TYPE abap_bool,
flg_corr_instr_exist TYPE abap_bool,
flg_note_found TYPE abap_bool,
note_status TYPE cwbntstat,
END OF gty_str_note_details,

gty_tab_note_details TYPE STANDARD TABLE OF gty_str_note_details


WITH NON-UNIQUE DEFAULT KEY,

BEGIN OF gty_str_sp_level,
swcomponent TYPE dlvunit,
release TYPE saprelease,
splevel TYPE sappatchlv,
END OF gty_str_sp_level,

gty_tab_sp_level TYPE HASHED TABLE OF gty_str_sp_level


WITH UNIQUE KEY swcomponent release,

gty_tab_add_notes_found TYPE HASHED TABLE OF gty_str_note_details


WITH UNIQUE KEY number.

DATA:
ms_file TYPE gty_str_file,
ms_delta_file TYPE gty_str_file,
mo_msg TYPE REF TO lcl_msg,
mt_cvers TYPE HASHED TABLE OF cvers WITH UNIQUE KEY component,
mv_release TYPE saprelease,
mv_filter_scope_id TYPE gty_scope_id,
mo_bw_check TYPE REF TO lcl_bw_check,
mt_note_validity TYPE gty_tab_note_validity,
mt_changed_notes TYPE bcwbn_note_keys_vs.

METHODS _check_sys_info
IMPORTING
io_bw_check TYPE REF TO lcl_bw_check OPTIONAL
RETURNING
value(rv_ok) TYPE abap_bool.

METHODS _validate_prep_notes
IMPORTING
it_rng_val_scope TYPE gty_tab_rng_scope_id.

METHODS _check_scope
IMPORTING
iv_filter_scope TYPE gty_scope_id OPTIONAL
RETURNING
value(rv_ok) TYPE abap_bool.

METHODS _validate_scope
IMPORTING
it_rng_val_scope TYPE gty_tab_rng_scope_id.

METHODS _validate_scope_id
IMPORTING
iv_scope_id TYPE gty_scope_id
iv_object TYPE clike.

METHODS _check_param.

METHODS _validate_param
IMPORTING
it_rng_val_scope TYPE gty_tab_rng_scope_id.

METHODS _check_components
RETURNING
value(rv_ok) TYPE abap_bool.

METHODS _validate_components
IMPORTING
it_rng_val_scope TYPE gty_tab_rng_scope_id.

METHODS _check_notes
IMPORTING
iv_node TYPE i
iv_description TYPE lcl_msg=>gty_text_id
iv_flg_download TYPE abap_bool DEFAULT abap_false
iv_flg_resolve TYPE abap_bool DEFAULT abap_false
CHANGING
ct_note_check TYPE gty_tab_note_check.

METHODS _check_note
IMPORTING
iv_again TYPE abap_bool DEFAULT abap_false
iv_node TYPE i OPTIONAL
is_note_check TYPE gty_str_note_check.

METHODS _read_inactive_objects.

METHODS _check_summary.

METHODS _get_note_validity
IMPORTING
is_note_check TYPE gty_str_note_check
EXPORTING
es_note_validity TYPE gty_str_note_validity.

METHODS _check_note_single
IMPORTING
iv_again TYPE abap_bool DEFAULT abap_false
is_note_check TYPE gty_str_note_check
is_note_validity TYPE gty_str_note_validity
iv_add_note_text TYPE string OPTIONAL.

METHODS _validate_notes
IMPORTING
it_rng_val_scope TYPE gty_tab_rng_scope_id.

METHODS _check_note_condition
IMPORTING
is_note_check TYPE gty_str_note_check
RETURNING
value(rv_result) TYPE abap_bool.

METHODS _resolve_not_implemented_notes
EXPORTING
et_add_notes TYPE gty_tab_add_notes_found
ev_flg_not_possible TYPE abap_bool
CHANGING
ct_note_check TYPE gty_tab_note_check
ct_note_validity TYPE gty_tab_note_validity.

METHODS _load_not_downloaded_notes
IMPORTING
it_note_check TYPE gty_tab_note_check
it_note_validity TYPE gty_tab_note_validity.

METHODS _load_notes
IMPORTING
it_notes_load TYPE gty_tab_note_check.

METHODS _calculate_max_sp_level
IMPORTING
it_note_validity TYPE gty_tab_note_validity
EXPORTING
et_max_sp_level TYPE gty_tab_sp_level.

METHODS _resolve_notes
IMPORTING
it_note_check TYPE gty_tab_note_check
EXPORTING
et_additional_notes TYPE gty_tab_note_details
et_additional_validity TYPE gty_tab_note_validity
ev_flg_not_possible TYPE abap_bool.

METHODS _check_note_by_validity
IMPORTING
is_note_check TYPE gty_str_note_check
it_note_validity TYPE gty_tab_note_validity
iv_flg_silent TYPE abap_bool DEFAULT abap_false
RETURNING
value(rv_download_needed) TYPE abap_bool.

METHODS _load_cvers.

METHODS _validate_note_check_sngl
IMPORTING
is_note_check TYPE gty_str_note_check
value(iv_note_index) TYPE sytabix "By value, so you can assign
sy- values against it
it_note_validity TYPE gty_tab_note_validity
EXPORTING
ev_flg_not_possible TYPE abap_bool.

METHODS _get_note_detail
IMPORTING
is_note_check TYPE gty_str_note_check
iv_flg_warn_val TYPE abap_bool DEFAULT abap_false
EXPORTING
es_note_check TYPE gty_str_note_details
et_note_validity TYPE gty_tab_note_validity.

METHODS _check_note_is_implemented
IMPORTING
iv_again TYPE abap_bool DEFAULT abap_false
is_note_check TYPE gty_str_note_check
iv_flg_silent TYPE abap_bool DEFAULT abap_false
EXPORTING
ev_is_implemented TYPE sysubrc
ev_status TYPE cwbprstat
ev_versno TYPE cwbntvers.

METHODS _check_note_is_downloaded
IMPORTING
is_note_check TYPE gty_str_note_check
RETURNING
value(rv_is_downloaded) TYPE abap_bool.

METHODS _add_note_comment
IMPORTING
is_note_check TYPE gty_str_note_check
iv_pre_impl TYPE abap_bool DEFAULT abap_false
iv_post_impl TYPE abap_bool DEFAULT abap_false.

METHODS _add_note_comment_special
IMPORTING
is_note_check TYPE gty_str_note_check.

METHODS _validate_note_comment
IMPORTING
is_note_check TYPE gty_str_note_check
it_note_comment TYPE gty_tab_note_comment.

METHODS _compare_sp_level
IMPORTING
iv_scope_id TYPE gty_scope_id
iv_object TYPE clike
iv_act_level TYPE clike
iv_min_level TYPE clike
iv_flg_gt_only TYPE abap_bool DEFAULT abap_false
RETURNING
value(rv_ok) TYPE abap_bool.

METHODS _compare_release
IMPORTING
iv_scope_id TYPE gty_scope_id
iv_object TYPE clike
iv_act_release TYPE clike
iv_chk_release TYPE clike
iv_option TYPE clike
RETURNING
value(rv_ok) TYPE abap_bool.

METHODS _restrict_validity
IMPORTING
it_note_check TYPE gty_tab_note_check OPTIONAL
CHANGING
ct_note_validity TYPE gty_tab_note_validity.

METHODS _show_progress
IMPORTING
value(iv_index) TYPE syindex
value(iv_max) TYPE syindex
value(iv_note_number) TYPE cwbntnumm.

METHODS _derive_patchlevel
IMPORTING
iv_sp_text TYPE string
EXPORTING
ev_patchlevel TYPE gty_splevel_n
ev_flg_failed TYPE abap_bool.

METHODS _does_rfc_connection_exist
RETURNING
value(rv_flg_ok) TYPE abap_bool.

ENDCLASS. "lcl_checks DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_batch DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_batch DEFINITION FINAL.

PUBLIC SECTION.

CONSTANTS:
gc_jobname TYPE tbtcjob-jobname VALUE 'SAP_BW_NOTES_DOWNLOAD'.

CLASS-METHODS call_note_analyzer_in_batch
IMPORTING
it_notes TYPE gty_tab_notes
RETURNING
value(rv_jobcount) TYPE tbtcjob-jobcount.

CLASS-METHODS execute_note_analyzer_in_batch
IMPORTING
it_sel_opt_notes TYPE STANDARD TABLE.

CLASS-METHODS is_batch_job_still_running
RETURNING
value(rv_running) TYPE abap_bool.

CLASS-METHODS get_last_batch_execution
RETURNING
value(rv_run_today) TYPE abap_bool.

PRIVATE SECTION.
TYPES:
gty_tab_param TYPE STANDARD TABLE OF rsparams WITH NON-UNIQUE DEFAULT KEY.

CLASS-DATA:
gv_exec_start TYPE timestamp,
gv_exec_end TYPE timestamp.

CLASS-METHODS _conv_to_param
IMPORTING
it_notes TYPE gty_tab_notes
EXPORTING
et_param TYPE gty_tab_param.

CLASS-METHODS _check_and_repeat_download
IMPORTING
it_notes TYPE scwb_api_t_notenumber.

CLASS-METHODS _commit_and_sync.

ENDCLASS. "lcl_batch DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_alv DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_alv DEFINITION FINAL.

PUBLIC SECTION.

CONSTANTS:
gc_purpose_pcai TYPE gty_purpose VALUE 'P',
gc_purpose_udo TYPE gty_purpose VALUE 'B',
gc_purpose_issue TYPE gty_purpose VALUE 'I',
gc_purpose_other TYPE gty_purpose VALUE 'O',
gc_purpose_udo_before TYPE gty_purpose VALUE 'S',
gc_purpose_udo_after TYPE gty_purpose VALUE 'U',
gc_purpose_tci_down TYPE gty_purpose VALUE 'T',
gc_purpose_tci_up TYPE gty_purpose VALUE 'V',
gc_purpose_sw_down TYPE gty_purpose VALUE 'W',
gc_purpose_sw_up TYPE gty_purpose VALUE 'X',
gc_purpose_icf TYPE gty_purpose VALUE 'F',
gc_purpose_header TYPE gty_purpose VALUE 'H',
gc_purpose_version TYPE gty_purpose VALUE 'A',
gc_purpose_condition TYPE gty_purpose VALUE 'C'.

CLASS-METHODS get_instance
IMPORTING
io_msg TYPE REF TO lcl_msg
RETURNING
value(ro_instance) TYPE REF TO lcl_alv.

METHODS prepare.

METHODS display
IMPORTING
iv_callback_form TYPE slis_formname
RETURNING
value(rs_exit) TYPE slis_exit_by_user.
METHODS display_as_popup
IMPORTING
iv_callback_form TYPE slis_formname
RETURNING
value(rs_exit) TYPE slis_exit_by_user.

METHODS call_back
IMPORTING
value(iv_ucomm) TYPE syucomm
CHANGING
cs_selfield TYPE slis_selfield.

METHODS display_udo_appllog
IMPORTING
i_udo_comment TYPE string.

METHODS display_inactive_objects
IMPORTING
iv_note_number TYPE cwbntnumm.

METHODS set_validation
IMPORTING
i_validation TYPE boolean.

METHODS set_scrollstatus
IMPORTING
is_grid_scroll TYPE lvc_s_scrl.

METHODS get_scrollstatus
EXPORTING
es_grid_scroll TYPE lvc_s_scrl.

PRIVATE SECTION.

CONSTANTS:
gc_sequence TYPE slis_fieldname VALUE 'SEQUENCE',
gc_alv_color TYPE slis_fieldname VALUE 'ALV_COLOR',
gc_icon_ltext TYPE slis_fieldname VALUE 'IC_LTEXT',
gc_icon_action TYPE slis_fieldname VALUE 'IC_ACTION',
gc_node TYPE slis_fieldname VALUE 'NODE',
gc_scope_id TYPE slis_fieldname VALUE 'SCOPE_ID',
gc_object TYPE slis_fieldname VALUE 'OBJECT'.

TYPES:
gty_icon TYPE c LENGTH 64, "Need additional space for tooltip

BEGIN OF gty_str_outtab.
INCLUDE TYPE lcl_msg=>gty_str_msg.
TYPES:
ic_lights TYPE gty_icon,
ic_action TYPE gty_icon,
ic_ltext TYPE gty_icon,
* Line color, reference
*
http://help.sap.com/saphelp_wp/helpdata/de/37/89479e9b8511d4b615006094192fe3/conten
t.htm
alv_color TYPE c LENGTH 4,
END OF gty_str_outtab,
gty_tab_outtab TYPE STANDARD TABLE OF gty_str_outtab WITH DEFAULT KEY.

DATA:
mo_msg TYPE REF TO lcl_msg,
mt_field_cat TYPE slis_t_fieldcat_alv,
ms_layout TYPE slis_layout_alv,
mt_sort_info TYPE slis_t_sortinfo_alv,
mt_outtab TYPE gty_tab_outtab,
mt_excl_func TYPE slis_t_extab,
* mt_event_exit TYPE slis_t_event_exit,
m_validation TYPE boolean,
ms_grid_scroll TYPE lvc_s_scrl.

METHODS _create_field_cat.

METHODS _create_layout.

METHODS _create_sort_info.

METHODS _create_excl_func.

* METHODS _create_exit_func.

METHODS _conv_action_to_icon
IMPORTING
iv_action TYPE lcl_msg=>gty_action
iv_purpose TYPE gty_purpose OPTIONAL
RETURNING
value(rv_icon) TYPE gty_icon.

METHODS _conv_msg_type_to_icon
IMPORTING
iv_msg_type TYPE symsgty
RETURNING
value(rv_icon) TYPE gty_icon.

METHODS _check_protocol_udo_report
IMPORTING
ir_outtab TYPE REF TO gty_str_outtab
CHANGING
cs_selfield TYPE slis_selfield.

METHODS _modify_outtab_action_column. "#EC *

METHODS _check_note_and_refresh_alv
IMPORTING
ir_outtab TYPE REF TO gty_str_outtab
CHANGING
cs_selfield TYPE slis_selfield.

METHODS _execute_udo_report
IMPORTING
ir_outtab TYPE REF TO gty_str_outtab
CHANGING
cs_selfield TYPE slis_selfield.

METHODS _activate_icf_service
IMPORTING
ir_outtab TYPE REF TO gty_str_outtab
CHANGING
cs_selfield TYPE slis_selfield.

ENDCLASS. "lcl_alv DEFINITION

* Declaration for INITIALIZATION


TYPE-POOLS: icon.

TABLES: sscrfields.

* UDO Enhancements
CONSTANTS:
c_bal_object TYPE balobj_d VALUE 'SNOTE',
c_bal_subobj TYPE balsubobj VALUE space,
c_bal_context TYPE tabname VALUE 'ADIR_KEY'.

* Callback Forms
CONSTANTS:
c_callback_alv TYPE slis_formname VALUE 'CALLBACK_ALV',
c_callback_eval TYPE slis_formname VALUE 'CALLBACK_EVAL'.

* Declaration of globals
DATA:
gs_screen TYPE screen,
go_bw_check TYPE REF TO lcl_bw_check,
go_files TYPE REF TO lcl_files,
gs_file TYPE gty_str_file,
gv_filename TYPE string,
gs_new TYPE gty_str_file,
gv_xml TYPE xstring,
go_xml_doc TYPE REF TO cl_xml_document,
gv_flg_batch_still_running TYPE abap_bool,
gv_text_1 TYPE string,
gv_text_2 TYPE string,
gv_text_3 TYPE string,
go_checks TYPE REF TO lcl_checks,
go_result_msg TYPE REF TO lcl_msg,
gs_delta_file TYPE gty_str_file,
gt_notes_to_download TYPE gty_tab_notes,
gt_notes_changed TYPE bcwbn_note_keys_vs,
go_alv TYPE REF TO lcl_alv,
gv_jobcount TYPE tbtcjob-jobcount,
gv_flg_ok TYPE abap_bool,
gs_exit TYPE slis_exit_by_user,
gv_run_today TYPE abap_bool,
gv_answer TYPE c LENGTH 1,
gv_flg_dl_dialog TYPE abap_bool,
gs_file_info TYPE lcl_files=>gty_str_file_info,
gv_flg_bool TYPE abap_bool,
gv_filter_scope_id TYPE gty_scope_id,
gt_rng_val_scope TYPE gty_tab_rng_scope_id,
g_log_handle TYPE balloghndl,
g_errors_occured TYPE abap_bool, "#EC NEEDED
g_master_languages TYPE string,
g_t_skipped_languages TYPE TABLE OF sylangu.

*#screen
*******************************************************************
* Standard Selection Screen (SCREEN 1000)
* SELECTION-SCREEN: FUNCTION KEY 1.

* Needed to transfer the note number to batch execution


* Change name or type here then change in lcl_batch, too.
SELECT-OPTIONS s_notes FOR ('CWBNTNUMM') NO-DISPLAY.

******************************************************************
* SCREEN 500, so we can call it again without loosing the data loaded

SELECTION-SCREEN BEGIN OF SCREEN 500.

* Possible files
SELECTION-SCREEN BEGIN OF BLOCK file WITH FRAME TITLE txt_030.
SELECTION-SCREEN SKIP.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN PUSHBUTTON 2(15) p_load USER-COMMAND load .
SELECTION-SCREEN COMMENT 20(79) txt_122.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN PUSHBUTTON 2(15) p_show USER-COMMAND show.
SELECTION-SCREEN COMMENT 20(60) txt_123.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN PUSHBUTTON 2(15) p_res USER-COMMAND reset.
SELECTION-SCREEN COMMENT 20(60) txt_124.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK file.

* execution options
SELECTION-SCREEN BEGIN OF BLOCK options WITH FRAME TITLE txt_020.
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS p_chk TYPE c DEFAULT 'X' RADIOBUTTON GROUP opt USER-COMMAND opt.
SELECTION-SCREEN COMMENT 5(70) txt_103 FOR FIELD p_chk.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS p_rsolv TYPE c RADIOBUTTON GROUP opt.
SELECTION-SCREEN COMMENT 5(79) txt_102 FOR FIELD p_rsolv.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS p_val TYPE c RADIOBUTTON GROUP opt MODIF ID val.
SELECTION-SCREEN COMMENT 5(70) txt_104 FOR FIELD p_val MODIF ID val.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK options.

* Download options
SELECTION-SCREEN BEGIN OF BLOCK download WITH FRAME TITLE txt_040.
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS p_dl TYPE c AS CHECKBOX DEFAULT '' MODIF ID res.
SELECTION-SCREEN COMMENT 5(70) txt_105 FOR FIELD p_dl MODIF ID res.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN POSITION 5.
PARAMETERS p_async TYPE c DEFAULT 'X' RADIOBUTTON GROUP dl MODIF ID res.
SELECTION-SCREEN COMMENT 10(70) txt_100 FOR FIELD p_async MODIF ID res.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN POSITION 5.
PARAMETERS p_sync TYPE c RADIOBUTTON GROUP dl MODIF ID res.
SELECTION-SCREEN COMMENT 10(70) txt_101 FOR FIELD p_sync MODIF ID res.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK download.

SELECTION-SCREEN BEGIN OF BLOCK header WITH FRAME TITLE txt_u01.


SELECTION-SCREEN SKIP.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN PUSHBUTTON 2(15) p_info USER-COMMAND info.
SELECTION-SCREEN COMMENT 20(40) txt_u02.
SELECTION-SCREEN COMMENT 75(15) txt_u03.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN PUSHBUTTON 2(15) p_logs USER-COMMAND logs.
SELECTION-SCREEN COMMENT 20(40) txt_u04.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK header.

SELECTION-SCREEN END OF SCREEN 500.

INITIALIZATION.

DATA:
gs_text TYPE textpool,
gt_text TYPE TABLE OF textpool,
gt_text2 TYPE TABLE OF textpool.

DEFINE macro_textpool_load.
read textpool sy-repid into gt_text language sy-langu.
gt_text2[] = gt_text[].
END-OF-DEFINITION.

DEFINE macro_textpool_save.
if gt_text[] <> gt_text2[].
insert textpool sy-repid from gt_text language sy-langu.
endif.
END-OF-DEFINITION.

DEFINE macro_textpool.
read table gt_text into gs_text with key id = &1 key = &2.
if sy-subrc = 0.
delete gt_text where id = &1 and key = &2.
endif.
clear gs_text.
gs_text-id = &1.
gs_text-key = &2.
if &1 = 'S'.
gs_text-entry+8 = &3.
else.
gs_text-entry = &3.
endif.
gs_text-length = strlen( gs_text-entry ).
append gs_text to gt_text.
END-OF-DEFINITION.

macro_textpool_load.

macro_textpool 'R' '' 'SAP BW and SAP BW/4HANA Note Analyzer'.

macro_textpool_save.
txt_020 = 'Check options'(020).
txt_030 = 'XML files to load'(030).
txt_040 = 'Download options before check'(040).

txt_100 = 'In background'(100).


txt_101 = 'In dialog'(101).
txt_102 = 'List dependent notes separately (search in SAP Support Portal required
- slow)'(102).
txt_103 = 'Check implementation state against information in XML file'(103).
txt_104 = 'Validate XML file against SAP Service Marketplace'(104).
txt_105 = 'Download needed SAP Notes'(105).
txt_123 = 'Show last loaded XML file'(123).
txt_124 = 'Reset all loaded XML files'(124).

CALL FUNCTION 'ICON_CREATE'


EXPORTING
name = icon_open
add_stdinf = space " 'X': Tooltip ' ': No tooltip
IMPORTING
result = p_load
EXCEPTIONS
icon_not_found = 1
outputfield_too_short = 2.
ASSERT sy-subrc = 0.

CALL FUNCTION 'ICON_CREATE'


EXPORTING
name = icon_display
add_stdinf = space " 'X': Tooltip ' ': No tooltip
IMPORTING
result = p_show
EXCEPTIONS
icon_not_found = 1
outputfield_too_short = 2.
ASSERT sy-subrc = 0.

CALL FUNCTION 'ICON_CREATE'


EXPORTING
name = icon_system_undo
add_stdinf = space " 'X': Tooltip ' ': No tooltip
IMPORTING
result = p_res
EXCEPTIONS
icon_not_found = 1
outputfield_too_short = 2.
ASSERT sy-subrc = 0.

txt_u01 = 'Information'.
txt_u02 = 'User Guide'.
txt_u03 = 'Version &'.
REPLACE '&' WITH gc_version INTO txt_u03.
txt_u04 = 'Logs'.

CALL FUNCTION 'ICON_CREATE'


EXPORTING
name = icon_information
add_stdinf = space
IMPORTING
result = p_info
EXCEPTIONS
icon_not_found = 1
outputfield_too_short = 2.
ASSERT sy-subrc = 0.

CALL FUNCTION 'ICON_CREATE'


EXPORTING
name = icon_history
add_stdinf = space
IMPORTING
result = p_logs
EXCEPTIONS
icon_not_found = 1
outputfield_too_short = 2.
ASSERT sy-subrc = 0.

AT SELECTION-SCREEN OUTPUT.

DATA:
l_text TYPE c LENGTH 60,
l_count TYPE i,
l_char TYPE c LENGTH 10.

IF go_files IS INITIAL.
go_files = lcl_files=>get_instance( ).
l_text = 'No files loaded'.
ELSE.
l_text = '&1 files loaded, &2 SAP Notes'.

l_count = go_files->get_file_count( ).
WRITE l_count TO l_char LEFT-JUSTIFIED.
REPLACE '&1' WITH l_char INTO l_text.
IF l_count = 1.
REPLACE 'files' WITH 'file' INTO l_text.
ENDIF.

l_count = go_files->get_file_count_notes( ).
WRITE l_count TO l_char LEFT-JUSTIFIED.
REPLACE '&2' WITH l_char INTO l_text.
ENDIF.
CONCATENATE '(' l_text ')' INTO l_text.
CONDENSE l_text.

txt_122 = 'Load XML file &'(122).


REPLACE '&' WITH l_text INTO txt_122.

IF go_bw_check IS INITIAL.
go_bw_check = lcl_bw_check=>get_instance( ).
ENDIF.

LOOP AT screen INTO gs_screen.


IF gs_screen-group1 CS 'BW'.
go_bw_check->toggle_modif_group_visibility(
EXPORTING
io_files = go_files
CHANGING
cs_screen = gs_screen
).
ELSEIF gs_screen-group1 = 'VAL'.
* Display check option only if a certain file is loaded
gv_flg_bool = go_files->is_file_loaded( iv_file_type =
lcl_files=>gc_file_type_val ).
IF gv_flg_bool = abap_true.
gs_screen-active = 1.
p_val = abap_true.
CLEAR: p_chk, p_rsolv.
ELSE.
gs_screen-active = 0.
p_val = abap_false.
ENDIF.
ELSE.
CONTINUE.
ENDIF.

MODIFY screen FROM gs_screen.


ENDLOOP.

AT SELECTION-SCREEN.

CASE sscrfields-ucomm.

WHEN 'LOAD'.
gs_file_info = go_files->get_next_file_info( ).

lcl_utilities=>open_xml(
EXPORTING
iv_title = gs_file_info-title
iv_pattern = gs_file_info-pattern
IMPORTING
es_str_file = gs_new
ev_filename = gv_filename
ev_xml = gv_xml
).

IF gs_new IS NOT INITIAL.


go_files->add_file(
EXPORTING
iv_filename = gv_filename
is_file = gs_new
).
ENDIF.

WHEN 'SHOW'.
IF gv_xml IS NOT INITIAL.
CREATE OBJECT go_xml_doc.
go_xml_doc->parse_xstring( stream = gv_xml ).
go_xml_doc->display( ).
ELSE.
gv_text_1 = 'You need to load at least one XML file'(201).
CLEAR gv_text_2.

CALL FUNCTION 'POPUP_TO_INFORM'


EXPORTING
titel = 'Message'
txt1 = gv_text_1
txt2 = gv_text_2.
ENDIF.
WHEN 'RESET'.
CLEAR: gs_file, gv_xml, go_files.

WHEN 'ONLI' "F8


OR 'CRET'. "Return from call selection-screen
gv_flg_ok = abap_false.
* User wants to execute the program
* We need an XML except for batch execution
IF sy-batch IS INITIAL.
* Check if batch is still running
gv_flg_batch_still_running = lcl_batch=>is_batch_job_still_running( ).
IF gv_flg_batch_still_running = abap_true.
gv_text_1 = 'Batch job (&1) downloading SAP Notes running'(202).
REPLACE '&1' IN gv_text_1 WITH lcl_batch=>gc_jobname.
gv_text_2 = 'Please exit this program and wait for the batch job to
finish.'(203).

CALL FUNCTION 'POPUP_TO_INFORM'


EXPORTING
titel = 'SAP Notes download running'(204)
txt1 = gv_text_1
txt2 = gv_text_2.
LEAVE PROGRAM.
ENDIF.

CLEAR gv_filter_scope_id.

go_files->get_merged_file(
EXPORTING
iv_filter_scope_id = gv_filter_scope_id
IMPORTING
es_file = gs_file
).
IF gs_file IS INITIAL.
gv_text_1 = 'You need to load at least one XML file'(201).
CLEAR gv_text_2.

CALL FUNCTION 'POPUP_TO_INFORM'


EXPORTING
titel = 'Message'(206)
txt1 = gv_text_1
txt2 = gv_text_2.

CLEAR sscrfields-ucomm.
ELSE.
* Check if all needed files are loaded
go_checks = lcl_checks=>get_instance( is_file = gs_file ).

go_checks->is_scope_consistent(
IMPORTING
ev_flg_ok = gv_flg_ok
eo_msg = go_result_msg
).
IF gv_flg_ok = abap_false.
CLEAR sscrfields-ucomm.
* Show error using standard message container
go_alv = lcl_alv=>get_instance( io_msg = go_result_msg ).
go_alv->prepare( ).
go_alv->display_as_popup( iv_callback_form = c_callback_alv ).
CLEAR: sscrfields-ucomm, gs_file.
ENDIF.
ENDIF.
ENDIF.

WHEN 'INFO'.
* Show user guide in browser
lcl_utilities=>call_browser( iv_url = gc_guide ).

WHEN 'LOGS'.
* Display logs of previous runs
lcl_utilities=>display_logs( ).

WHEN 'EXPERT'.
* Expert options
IF lcl_utilities=>gv_fast = abap_true.
lcl_utilities=>gv_fast = abap_false.
MESSAGE s398(00) WITH 'Expert mode turned' 'off' '' ''.
ELSE.
lcl_utilities=>gv_fast = abap_true.
MESSAGE s398(00) WITH 'Expert mode turned' 'on' '' ''.
ENDIF.

WHEN OTHERS.
* Debug options
lcl_utilities=>gv_debug = sscrfields-ucomm.

MESSAGE s398(00) WITH 'Debugging set to pattern' lcl_utilities=>gv_debug ''


''.
ENDCASE.

START-OF-SELECTION.

**********************************************************************
* Batch processing

IF sy-batch IS NOT INITIAL.


lcl_batch=>execute_note_analyzer_in_batch( it_sel_opt_notes = s_notes[] ).
LEAVE PROGRAM.
ENDIF.

**********************************************************************
* Dialog Processing

DO.

CLEAR: gs_file, gv_filter_scope_id, gv_flg_ok.

CALL SELECTION-SCREEN 500.

IF gv_flg_ok = abap_false.
* selection screen left without hitting F8 Button
LEAVE PROGRAM.
ENDIF.

IF p_val = abap_true AND sy-langu <> 'E'.


gv_text_1 = 'Execute validation mode in English only'(216).
CLEAR: gv_text_2, gv_text_3.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = 'Information'
txt1 = gv_text_1
txt2 = gv_text_2
txt3 = gv_text_3.
LEAVE PROGRAM.
ENDIF.

IF go_checks IS BOUND.
go_checks->reset_msg( ).
CLEAR: go_result_msg, go_alv.
ELSEIF gs_file IS NOT INITIAL.
go_checks = lcl_checks=>get_instance( is_file = gs_file ).
ENDIF.

go_checks->add_info_from_sel_screen(
EXPORTING
iv_filter_scope_id = gv_filter_scope_id
io_bw_check = go_bw_check
).

* In case this is a BW relevant system and the customer has not loaded the BW file
send a warning
* But no popup in case of XML validation option
gv_flg_bool = go_files->is_file_loaded( iv_file_type =
lcl_files=>gc_file_type_val ).
IF gv_flg_bool = abap_false.
gv_flg_bool = go_bw_check->is_bw_relevant( ).
IF gv_flg_bool = abap_true.
gv_flg_bool = go_files->is_file_loaded( iv_file_type =
lcl_files=>gc_file_type_bw ).
IF gv_flg_bool = abap_false.
CALL FUNCTION 'POPUP_TO_CONFIRM'
EXPORTING
text_question = 'This system is a BW system or connected to a BW
system. Do you want to load the BW XML file'(214)
popup_type = 'ICON_MESSAGE_WARNING'
IMPORTING
answer = gv_answer " Return values: '1', '2', 'A'
EXCEPTIONS
text_not_found = 0.
IF gv_answer = '1' OR gv_answer = 'A'.
* Back to selection screen
CONTINUE.
ENDIF.
ENDIF.
ELSE.
* And the opposite is worth a warning if BW content is loaded
gv_flg_bool = go_files->is_file_loaded( iv_file_type =
lcl_files=>gc_file_type_bw ).
IF gv_flg_bool = abap_true.
CALL FUNCTION 'POPUP_TO_CONFIRM'
EXPORTING
text_question = 'This system is not a BW system or connected to a BW
system. Do you want to check the BW XML file anyway?'(217)
IMPORTING
answer = gv_answer " Return values: '1', '2', 'A'
EXCEPTIONS
text_not_found = 0.
IF gv_answer = '2' OR gv_answer = 'A'.
* Back to selection screen
CONTINUE.
ENDIF.
ENDIF.
ENDIF.
ENDIF.

* Check for or download latest version of implemented SAP Notes option


IF p_dl = abap_false.
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
percentage = 1
text = 'Checking for outdated SAP Notes'.

go_checks->get_all_notes(
IMPORTING
et_notes = gt_notes_to_download
).

go_checks->check_outdated_notes(
EXPORTING
it_notes = gt_notes_to_download
IMPORTING
et_changed_notes = gt_notes_changed
).

go_checks->update_outdated_notes(
EXPORTING
it_changed_notes = gt_notes_changed
).
ENDIF.

* Download required SAP Notes option


IF p_dl = abap_true AND p_async = abap_true.
gv_run_today = lcl_batch=>get_last_batch_execution( ).
IF gv_run_today = abap_true.
CALL FUNCTION 'POPUP_TO_CONFIRM'
EXPORTING
text_question = 'Batch job to load SAP Notes was finished. Do
you want to start another one?'(207)
default_button = '2'
display_cancel_button = space
IMPORTING
answer = gv_answer " Return values: '1', '2', 'A'
EXCEPTIONS
text_not_found = 0.
ELSE.
gv_answer = '1'. "Automatically OK
ENDIF.
IF gv_answer = '1'.
IF p_val = abap_true.
go_checks->get_all_notes(
IMPORTING
et_notes = gt_notes_to_download
).
ELSE.
go_checks->get_needed_notes(
IMPORTING
et_notes = gt_notes_to_download
).
ENDIF.
ENDIF.
IF gt_notes_to_download IS NOT INITIAL.
gv_jobcount =
lcl_batch=>call_note_analyzer_in_batch( gt_notes_to_download ).

gv_text_1 = 'The batch job (Name &1 Count &2 ) has started'(208).
REPLACE '&1' IN gv_text_1 WITH lcl_batch=>gc_jobname.
REPLACE '&2' IN gv_text_1 WITH gv_jobcount.
gv_text_2 = 'Start this program again when the batch job is finished'(209).
gv_text_3 = 'Then you can proceed with the check'(210).
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = 'Note download started'(213)
txt1 = gv_text_1
txt2 = gv_text_2
txt3 = gv_text_3.
LEAVE PROGRAM.
ELSE.
gv_text_1 = 'No SAP Notes need to be downloaded'(211).
CLEAR gv_text_2.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = 'SAP Note download'(212)
txt1 = gv_text_1
txt2 = gv_text_2.
ENDIF.

ELSEIF p_dl = abap_true AND p_sync = abap_true.


gv_flg_dl_dialog = abap_true.
ELSE.
gv_flg_dl_dialog = abap_false.
ENDIF.

* Check option
IF p_chk = abap_true.
go_result_msg = go_checks->check_all(
iv_flg_download = gv_flg_dl_dialog
iv_flg_resolve = abap_false
).
ELSEIF p_rsolv = abap_true.
go_result_msg = go_checks->check_all(
iv_flg_download = gv_flg_dl_dialog
iv_flg_resolve = abap_true
).
ELSEIF p_val = abap_true.
go_files->get_validation_scope(
IMPORTING
et_rng_val_scope = gt_rng_val_scope
).
go_checks->validate_all(
EXPORTING
it_rng_val_scope = gt_rng_val_scope
IMPORTING
eo_msg = go_result_msg
es_delta_file = gs_delta_file
).
ELSE.
* Must not happen
ASSERT 0 = 1.
ENDIF.

*****************************************************************************
* Output

* Prepare output
go_alv = lcl_alv=>get_instance( io_msg = go_result_msg ).
go_alv->set_validation( p_val ).
go_alv->prepare( ).

* Output
gs_exit = go_alv->display( iv_callback_form = c_callback_alv ).

IF gs_exit-cancel = abap_true OR gs_exit-exit = abap_true.


LEAVE PROGRAM.
ENDIF.

ENDDO.

**********************************************************************
* End of program processing blocks
* Implementation of forms and methods following
**********************************************************************
*#forms
FORM callback_eval
USING i_variable TYPE clike
CHANGING e_value TYPE f
e_subrc TYPE any.

STATICS:
st_cvers TYPE HASHED TABLE OF cvers WITH UNIQUE KEY component.

DATA:
l_swcomp TYPE cvers-component,
l_version TYPE string,
ls_cvers TYPE cvers,
ls_dbinfo TYPE dbrelinfo,
ls_hana_release TYPE gty_str_release_patch,
ls_kernel_release TYPE gty_str_release_patch,
ls_spam_release TYPE gty_str_release_patch.

CLEAR: e_value, e_subrc.

IF st_cvers IS INITIAL.
SELECT * FROM cvers INTO TABLE st_cvers.
ENDIF.

TRY.
CASE i_variable.
WHEN 'SAP_BASIS' OR 'SAP_BW' OR 'DW4CORE'.
READ TABLE st_cvers INTO ls_cvers WITH TABLE KEY
component = i_variable.
IF sy-subrc = 0.
e_value = ls_cvers-release.
ENDIF.
WHEN 'SAP_BASIS_SP' OR 'SAP_BW_SP' OR 'DW4CORE_SP'.
l_swcomp = i_variable.
REPLACE '_SP' IN l_swcomp WITH ''.
READ TABLE st_cvers INTO ls_cvers WITH TABLE KEY
component = l_swcomp.
IF sy-subrc = 0.
e_value = ls_cvers-extrelease.
ENDIF.
WHEN 'DATABASE' OR 'DATABASE_PATCH' OR 'DBSL' or 'DBSL_PATCH'.
CALL METHOD lcl_utilities=>get_db_release
IMPORTING
es_dbinfo = ls_dbinfo.
IF i_variable = 'DATABASE'.
FIND FIRST OCCURRENCE OF REGEX '(\d+)\.\d+\.*' IN ls_dbinfo-srvrel
SUBMATCHES l_version.
ELSEIF i_variable = 'DATABASE_PATCH'.
FIND FIRST OCCURRENCE OF REGEX '\d+\.(\d+)\.*' IN ls_dbinfo-srvrel
SUBMATCHES l_version.
ELSEif i_variable = 'DBSL'.
SPLIT ls_dbinfo-dbsl_vers AT '.' INTO l_version sy-lisel.
ELSE.
SPLIT ls_dbinfo-dbsl_vers AT '.' INTO sy-lisel l_version.
ENDIF.
IF sy-subrc = 0.
e_value = l_version.
ENDIF.
WHEN 'HANA' OR 'HANA_REVISION' OR 'HANA_REVISION_PATCH'.
CALL METHOD lcl_utilities=>get_db_release
IMPORTING
es_hana_release = ls_hana_release.
IF i_variable = 'HANA'.
e_value = ls_hana_release-release.
ELSEIF i_variable = 'HANA_REVISION'.
e_value = ls_hana_release-version.
ELSE.
e_value = ls_hana_release-patch.
ENDIF.
WHEN 'SPAM' OR 'SPAM_VERSION'.
ls_spam_release = lcl_utilities=>get_spam_release( ).
IF i_variable = 'SPAM'.
e_value = ls_spam_release-release.
ELSE.
e_value = ls_spam_release-version.
ENDIF.
WHEN 'KERNEL' OR 'KERNEL_PATCH'.
ls_kernel_release = lcl_utilities=>get_kernel_release( ).
IF i_variable = 'KERNEL'.
e_value = ls_kernel_release-release.
ELSE.
e_value = ls_kernel_release-patch.
ENDIF.
WHEN OTHERS.
e_subrc = 4.
ENDCASE.
CATCH cx_root.
e_subrc = 8.
ENDTRY.

ENDFORM. "callback_eval
*&---------------------------------------------------------------------*

FORM callback_alv USING iv_ucomm TYPE syucomm


cs_selfield TYPE slis_selfield. "#EC CALLED

DATA:
ls_grid_scroll TYPE lvc_s_scrl.

CALL FUNCTION 'REUSE_ALV_GRID_LAYOUT_INFO_GET'


IMPORTING
es_grid_scroll = ls_grid_scroll
EXCEPTIONS
no_infos = 1
program_error = 2
OTHERS = 3.
IF sy-subrc <> 0.
* nothing
ENDIF.

go_alv->set_scrollstatus( is_grid_scroll = ls_grid_scroll ).

* This is strange parameterization, but only can changing the using


* parameter is_selfield to trigger something in ALV
go_alv->call_back(
EXPORTING
iv_ucomm = iv_ucomm
CHANGING
cs_selfield = cs_selfield
).

ENDFORM. "callback_alv

*&---------------------------------------------------------------------*

FORM set_pf_status USING rt_extab TYPE slis_t_extab. "#EC CALLED

DATA:
ls_grid_scroll TYPE lvc_s_scrl,
ls_excl TYPE slis_extab.

go_alv->get_scrollstatus(
IMPORTING
es_grid_scroll = ls_grid_scroll
).

CALL FUNCTION 'REUSE_ALV_GRID_LAYOUT_INFO_SET'


EXPORTING
is_grid_scroll = ls_grid_scroll.

ls_excl-fcode = cl_gui_alv_grid=>mc_fc_info.
APPEND ls_excl TO rt_extab.
ls_excl-fcode = cl_gui_alv_grid=>mc_fc_graph.
APPEND ls_excl TO rt_extab.

SET PF-STATUS 'STANDARD' OF PROGRAM 'SAPLKKBL' EXCLUDING rt_extab.

ENDFORM. "set_pf_status

*----------------------------------------------------------------------*
* CLASS lcl_wb IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_wb IMPLEMENTATION.

METHOD get_object_text.

STATICS:
lt_object_text TYPE TABLE OF ko100,
lt_doktypes TYPE TABLE OF dd07v.

DATA:
ls_object_text TYPE ko100,
ls_doktype TYPE dd07v.

IF lt_object_text IS INITIAL.
CALL FUNCTION 'TR_OBJECT_TABLE'
TABLES
wt_object_text = lt_object_text.

SORT lt_object_text BY object.

CALL FUNCTION 'DDIF_DOMA_GET'


EXPORTING
name = 'DOK_ID'
langu = sy-langu
TABLES
dd07v_tab = lt_doktypes
EXCEPTIONS
OTHERS = 0.

SORT lt_doktypes BY domvalue_l.


ENDIF.

IF i_object EQ 'DOCU' AND i_obj_name CP 'FU*'.


"check if name containes two words
SPLIT i_obj_name AT space INTO sy-lisel sy-lisel.
IF sy-lisel IS INITIAL.
r_text = 'Documentation Function Module'. "#EC NOTEXT
ELSE.
r_text = 'Documentation Function Module Parameter'. "#EC NOTEXT
ENDIF.
ELSEIF i_object EQ 'DOCU'.
READ TABLE lt_doktypes INTO ls_doktype BINARY SEARCH
WITH KEY domvalue_l = i_obj_name(2).
IF sy-subrc EQ 0.
CONCATENATE 'Documentation' ls_doktype-ddtext
INTO r_text SEPARATED BY space. "#EC NOTEXT
ELSE.
r_text = 'Documentation'. "#EC NOTEXT
ENDIF.
ELSEIF i_object EQ 'FUNH'.
r_text = 'Function Module Release Status'. "#EC NOTEXT
ELSEIF i_object EQ 'PROC'.
r_text = 'HANA Stored Procedure'. "#EC NOTEXT
ELSEIF i_object EQ 'ALVV'.
r_text = 'ALV Standard Variant'. "#EC NOTEXT
ELSEIF NOT i_object IS INITIAL.
READ TABLE lt_object_text INTO ls_object_text BINARY SEARCH
WITH KEY object = i_object. "ignore PGMID!
IF sy-subrc EQ 0.
r_text = ls_object_text-text.
ENDIF.
ENDIF.

ENDMETHOD. "get_object_text

METHOD log_message.

DATA:
ls_msg TYPE bal_s_msg.

IF sy-msgno IS INITIAL OR sy-msgid IS INITIAL.


MESSAGE i666(01) WITH 'Unknown error' INTO sy-lisel. "#EC *
ENDIF.
MOVE-CORRESPONDING syst TO ls_msg.

CALL FUNCTION 'BAL_LOG_MSG_ADD'


EXPORTING
i_log_handle = g_log_handle
i_s_msg = ls_msg
EXCEPTIONS
OTHERS = 0.

IF ls_msg-msgty = lcl_msg=>gc_error OR ls_msg-msgty = lcl_msg=>gc_abort.


g_errors_occured = abap_true.
ENDIF.

ENDMETHOD. "log_message

METHOD language_installed.

DATA:
l_languages TYPE string.

CLEAR r_installed.

IF i_langu IS INITIAL OR g_master_languages CS i_langu.


r_installed = abap_true.
ELSE.
CALL FUNCTION 'SYSTEM_INSTALLED_LANGUAGES'
IMPORTING
languages = l_languages
EXCEPTIONS
sapgparam_error = 1
OTHERS = 2.
IF sy-subrc NE 0 OR l_languages CS i_langu.
r_installed = abap_true.
ELSE.
COLLECT i_langu INTO g_t_skipped_languages.
ENDIF.
ENDIF.

ENDMETHOD. "language_installed

METHOD set_context.

STATICS:
BEGIN OF lss_key, "save last key
i_object TYPE e071-object,
i_obj_name TYPE adir_key-obj_name,
i_obj_name2 TYPE adir_key-obj_name,
i_text TYPE string,
i_langu TYPE sylangu,
END OF lss_key.

DATA:
ls_msg_defaults TYPE bal_s_mdef,
ls_context TYPE adir_key,
l_text TYPE c LENGTH 70,
l_mode TYPE string,
ls_key LIKE lss_key,
ls_e071 TYPE e071,
ls_tadir TYPE tadir,
ls_tadir_key TYPE tadir.

CHECK NOT lcl_wb=>language_installed( i_langu ) IS INITIAL.

ls_key-i_object = i_object.
ls_key-i_obj_name = i_obj_name.
ls_key-i_obj_name2 = i_obj_name2.
ls_key-i_text = i_text.
ls_key-i_langu = i_langu.
IF ls_key EQ lss_key. "check last key
"avoid double message like "add field to table"
RETURN.
ELSE.
lss_key = ls_key.
ENDIF.

ls_context-object = i_object.
CONCATENATE i_obj_name i_obj_name2 INTO ls_context-obj_name SEPARATED BY space.
ls_msg_defaults-log_handle = g_log_handle.
ls_msg_defaults-context-value = ls_context.
ls_msg_defaults-context-tabname = c_bal_context.

CALL FUNCTION 'BAL_GLB_MSG_DEFAULTS_SET'


EXPORTING
i_s_msg_defaults = ls_msg_defaults
EXCEPTIONS
OTHERS = 0.

IF NOT i_no_message IS INITIAL.


EXIT.
ENDIF.

* Try to check if object exists


IF NOT i_object IS INITIAL AND NOT i_obj_name IS INITIAL.
ls_e071-pgmid = 'R3TR'.
ls_e071-object = i_object.
ls_e071-obj_name = i_obj_name.

CALL FUNCTION 'SCWB_GET_TADIR_REM'


EXPORTING
is_e071 = ls_e071
IMPORTING
es_tadir_key = ls_tadir_key
es_tadir = ls_tadir.
IF ls_tadir_key IS INITIAL.
ls_e071-pgmid = 'LIMU'.
CALL FUNCTION 'SCWB_GET_TADIR_REM'
EXPORTING
is_e071 = ls_e071
IMPORTING
es_tadir_key = ls_tadir_key
es_tadir = ls_tadir.
ENDIF.

IF ls_tadir IS INITIAL.
l_mode = 'Create'. "#EC NOTEXT
ELSE.
l_mode = 'Change'. "#EC NOTEXT
"check if object has been manually modified by customer.
SELECT COUNT( * ) FROM adiraccess
WHERE pgmid EQ ls_tadir-pgmid
AND object EQ ls_tadir-object
AND obj_name EQ ls_tadir-obj_name.
IF sy-dbcnt NE 0.
MESSAGE w666(01) WITH ls_tadir-object ls_tadir-obj_name
'was manually changed before.'
'Please adjust manually afterwards' INTO sy-lisel. "#EC *
CALL METHOD log_message.
ENDIF.
ENDIF.
ENDIF.

IF i_text IS INITIAL.
CALL METHOD get_object_text
EXPORTING
i_object = i_object
i_obj_name = i_obj_name
RECEIVING
r_text = l_text.

CONCATENATE l_mode l_text INTO l_text SEPARATED BY space.


ELSE.
l_text = i_text.
ENDIF.

IF NOT l_text IS INITIAL.


IF NOT i_langu IS INITIAL.
MESSAGE s666(01) WITH l_text '( language' i_langu ')'
INTO l_text. "#EC NOTEXT
ENDIF.
CALL FUNCTION 'BAL_LOG_MSG_ADD_FREE_TEXT'
EXPORTING
i_msgty = lcl_msg=>gc_info
i_text = l_text
EXCEPTIONS
OTHERS = 0.
ENDIF.

ENDMETHOD. "set_context

METHOD save_log.

DATA:
lt_log_handle TYPE bal_t_logh.

APPEND g_log_handle TO lt_log_handle.

CALL FUNCTION 'BAL_DB_SAVE'


EXPORTING
i_t_log_handle = lt_log_handle
EXCEPTIONS
OTHERS = 0.

ENDMETHOD. "save_log

METHOD display_log.

DATA:
lt_log_handle TYPE bal_t_logh,
lt_log_handle_all TYPE bal_t_logh,
ls_profile TYPE bal_s_prof,
l_s_fcat TYPE bal_s_fcat,
lt_dfies TYPE TABLE OF dfies,
ls_dfies TYPE dfies,
lr_filter_client TYPE RANGE OF mandt,
ls_filter_client LIKE LINE OF lr_filter_client,
ls_filter_lfil TYPE bal_s_lfil,
ls_filter TYPE bal_s_extn,
ls_extnumber TYPE bal_s_extn,
lt_log_header_all TYPE balhdr_t,
l_ts_log_header TYPE balhdr_t.

* Reset SNOTE & SCWB mode


CALL FUNCTION 'SCWG_TOOLFLAG_RESET'.
TRY.
CALL METHOD ('CL_CWB_RUNTIME')=>set_finished.
CATCH cx_sy_dyn_call_illegal_class. "#EC NO_HANDLER
* Carry on
ENDTRY.

IF g_log_handle IS INITIAL.
CHECK NOT i_db_search IS INITIAL.

CLEAR: ls_filter_lfil, ls_extnumber.

* Search only log file of this application


ls_filter-sign = 'I'.
ls_filter-option = 'EQ'.
ls_filter-low = c_bal_object.
APPEND ls_filter TO ls_filter_lfil-object.

ls_filter-sign = 'I'.
ls_filter-option = 'EQ'.
ls_filter-low = c_bal_subobj.
APPEND ls_filter TO ls_filter_lfil-subobject.

* Search only log file of this change number


ls_extnumber-low = i_report.
ls_extnumber-sign = 'I'.
ls_extnumber-option = 'EQ'.
APPEND ls_extnumber TO ls_filter_lfil-extnumber.
ls_filter_client-sign = 'I'.
ls_filter_client-option = 'EQ'.
ls_filter_client-low = sy-mandt.
APPEND ls_filter_client TO lr_filter_client.

* Read header
SELECT * FROM balhdr CLIENT SPECIFIED "all clients
INTO TABLE lt_log_header_all
WHERE mandant IN ( SELECT mandt FROM t000 ) "#EC CI_BUFFSUBQ
AND object IN ls_filter_lfil-object
AND subobject IN ls_filter_lfil-subobject
AND extnumber IN ls_filter_lfil-extnumber.

* Look for kog im memory


CALL FUNCTION 'BAL_GLB_SEARCH_LOG'
EXPORTING
i_s_log_filter = ls_filter_lfil
IMPORTING
e_t_log_handle = lt_log_handle_all
EXCEPTIONS
log_not_found = 1
OTHERS = 2.

IF sy-subrc NE 0.
* Not found, look for log on database
FIELD-SYMBOLS <l_s_log_hdr> TYPE any.
LOOP AT lt_log_header_all ASSIGNING <l_s_log_hdr>.

CLEAR: l_ts_log_header,
lt_log_handle.
INSERT <l_s_log_hdr> INTO TABLE l_ts_log_header.

CALL FUNCTION 'BAL_DB_LOAD'


EXPORTING
i_t_log_header = l_ts_log_header
IMPORTING
e_t_log_handle = lt_log_handle
EXCEPTIONS
no_logs_specified = 1
log_not_found = 2
log_already_loaded = 3
OTHERS = 4.
IF sy-subrc <> 0.
CONTINUE.
ENDIF.
INSERT LINES OF lt_log_handle INTO TABLE lt_log_handle_all.
ENDLOOP.
ENDIF.

INSERT g_log_handle INTO TABLE lt_log_handle_all.


ENDIF.

IF 1 = 1.
* Display as grid
CALL FUNCTION 'BAL_DSP_PROFILE_SINGLE_LOG_GET'
IMPORTING
e_s_display_profile = ls_profile
EXCEPTIONS
OTHERS = 0.
ls_profile-show_all = abap_true.
ls_profile-use_grid = abap_true.
ls_profile-tree_ontop = abap_true.
ls_profile-exp_level = 1.
ls_profile-mess_mark = abap_true.
ELSE.
* Display as tree
CALL FUNCTION 'BAL_DSP_PROFILE_DETLEVEL_GET'
IMPORTING
e_s_display_profile = ls_profile
EXCEPTIONS
OTHERS = 0.
ENDIF.

* Add own fields to field cat


CALL FUNCTION 'DDIF_FIELDINFO_GET'
EXPORTING
tabname = c_bal_context
TABLES
dfies_tab = lt_dfies
EXCEPTIONS
not_found = 1
internal_error = 2
OTHERS = 3.
IF sy-subrc NE 0.
MESSAGE a666(01) WITH
'Error in DDIF_FIELDINFO_GET for table:' c_bal_context. "#EC *
ENDIF.

LOOP AT lt_dfies INTO ls_dfies WHERE fieldname EQ 'OBJECT'


OR fieldname EQ 'OBJ_NAME'.
l_s_fcat-ref_table = c_bal_context.
l_s_fcat-ref_field = ls_dfies-fieldname.
l_s_fcat-outputlen = ls_dfies-outputlen + 1.
APPEND l_s_fcat TO ls_profile-mess_fcat.
ENDLOOP.

* Set parameters for saving layout.


ls_profile-disvariant-report = sy-repid.
ls_profile-disvariant-handle = c_bal_subobj.

ls_profile-clbk_ucbf-userexitp = sy-repid.
ls_profile-clbk_ucbf-userexitf = 'BAL_CALLBACK_UCOMM'.

IF g_log_handle IS INITIAL.
ls_profile-title = 'UDO - All Logs'. "#EC *
ELSE.
ls_profile-title = 'UDO - Problem Log'. "#EC *
ls_profile-start_row = 5.
ls_profile-start_col = 5.
ls_profile-end_row = 30.
ls_profile-end_col = 160.
ENDIF.

DATA: ls_statistics TYPE bal_s_scnt.

IF i_no_save IS INITIAL.
CALL METHOD lcl_wb=>save_log.
ls_statistics-msg_cnt_al = 1.
ELSE.
CALL FUNCTION 'BAL_LOG_HDR_READ'
EXPORTING
i_log_handle = g_log_handle
IMPORTING
e_statistics = ls_statistics
EXCEPTIONS
log_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE a666(01) WITH 'Log not found'. "#EC *
ENDIF.
ENDIF.

IF ls_statistics-msg_cnt_al NE 0 AND sy-batch IS INITIAL.


CALL FUNCTION 'BAL_DSP_LOG_DISPLAY'
EXPORTING
i_t_log_handle = lt_log_handle_all
i_s_display_profile = ls_profile
i_amodal = space
EXCEPTIONS
profile_inconsistent = 1
internal_error = 2
no_data_available = 3
no_authority = 4
OTHERS = 5.
IF sy-subrc = 1 OR sy-subrc = 2 OR sy-subrc = 5.
MESSAGE a666(01) WITH 'Log not found'. "#EC *
ELSEIF sy-subrc = 4.
MESSAGE e666(01) WITH 'Not authorization to display log'. "#EC *
ENDIF.
ENDIF.

IF NOT i_no_save IS INITIAL.


CALL FUNCTION 'BAL_LOG_REFRESH'
EXPORTING
i_log_handle = g_log_handle
EXCEPTIONS
log_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE a666(01) WITH 'Log not found'. "#EC *
ENDIF.
"reset context
CALL METHOD set_context(
EXPORTING
i_langu = space
i_object = space
i_obj_name = space
).
ENDIF.

CLEAR g_log_handle.

ENDMETHOD. "display_log

ENDCLASS. "lcl_wb IMPLEMENTATION


*----------------------------------------------------------------------*
* CLASS lcl_utilities IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_utilities IMPLEMENTATION.

METHOD open_xml.

CONSTANTS:
lc_line_size TYPE i VALUE 1000.

DATA:
lt_files TYPE filetable,
lrs_file TYPE REF TO file_table,
lv_rc_file_open TYPE i,
lv_default_filename TYPE string,
lv_file_size TYPE i,
lv_file_content TYPE x LENGTH lc_line_size,
lt_file_content LIKE TABLE OF lv_file_content,
lv_user_action TYPE i,
lx_error TYPE REF TO cx_transformation_error,
lx_deser_error TYPE REF TO cx_xslt_deserialization_error,
lx_root TYPE REF TO cx_root,
lv_msg_text TYPE c LENGTH 300,
lv_msg_1 TYPE string,
lv_msg_2 TYPE string,
lv_title TYPE string.

FIELD-SYMBOLS:
<lv_bin> TYPE x,
<lv_rest> TYPE x.

CLEAR: es_str_file, ev_filename, ev_flg_loaded, ev_xml.

IF iv_pattern IS SUPPLIED.
CONCATENATE iv_pattern '.xml' INTO lv_default_filename.
ELSE.
lv_default_filename = '*.xml'.
ENDIF.
IF iv_title IS SUPPLIED.
lv_title = iv_title.
ELSE.
lv_title = 'XML File'.
ENDIF.

* Return Code, Number of Files or -1 If Error Occurred


CALL METHOD cl_gui_frontend_services=>file_open_dialog
EXPORTING
window_title = lv_title
default_extension = '.xml'
default_filename = lv_default_filename
file_filter = cl_gui_frontend_services=>filetype_xml
multiselection = ' '
CHANGING
file_table = lt_files
rc = lv_rc_file_open
user_action = lv_user_action
EXCEPTIONS
OTHERS = 9.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
RETURN.
ENDIF.
IF lv_user_action = cl_gui_frontend_services=>action_cancel.
RETURN.
ENDIF.

IF lv_rc_file_open EQ 1.
READ TABLE lt_files REFERENCE INTO lrs_file INDEX 1.
ev_filename = lrs_file->filename.

CALL METHOD cl_gui_frontend_services=>gui_upload


EXPORTING
filename = ev_filename
filetype = 'BIN'
codepage = '4110'
IMPORTING
filelength = lv_file_size
CHANGING
data_tab = lt_file_content
EXCEPTIONS
OTHERS = 99.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
RETURN.
ENDIF.
ELSE.
RETURN.
ENDIF.

LOOP AT lt_file_content ASSIGNING <lv_bin>.


CHECK lv_file_size > 0.
IF lv_file_size < lc_line_size.
ASSIGN <lv_bin>(lv_file_size) TO <lv_rest>.
CONCATENATE ev_xml <lv_rest> INTO ev_xml IN BYTE MODE.
ELSE.
CONCATENATE ev_xml <lv_bin> INTO ev_xml IN BYTE MODE.
ENDIF.
lv_file_size = lv_file_size - lc_line_size.
ENDLOOP.

TRY.
CALL TRANSFORMATION id
SOURCE XML ev_xml
RESULT file_struct = es_str_file.

CATCH cx_xslt_deserialization_error INTO lx_deser_error.


* In this case we get the position in the tree and the source of the error
lv_msg_1 = lx_deser_error->tree_position.
IF lx_deser_error->previous IS BOUND.
lx_root = lx_deser_error->previous.
lv_msg_2 = lx_root->get_text( ).
ENDIF.
CONCATENATE 'Deserialization error at tree' lv_msg_1 ':' lv_msg_2
INTO lv_msg_text SEPARATED BY space.
MESSAGE lv_msg_text TYPE lcl_msg=>gc_error.
CATCH cx_transformation_error INTO lx_error.
MESSAGE lx_error TYPE lcl_msg=>gc_error.
ENDTRY.

ev_flg_loaded = abap_true.

ENDMETHOD. "open_xml

METHOD save_xml.

DATA:
lv_string TYPE xstring,
lv_filename TYPE string,
lv_path TYPE string,
lv_fullpath TYPE string,
lv_file TYPE x LENGTH 1000,
lt_file LIKE TABLE OF lv_file,
lv_offs TYPE i,
lv_rest TYPE i,
lv_size TYPE i,
lv_user_action TYPE i.

ASSERT is_file IS NOT INITIAL.

CALL TRANSFORMATION id
SOURCE file_struct = is_file
RESULT XML lv_string.

REFRESH lt_file.
lv_size = xstrlen( lv_string ).
DO.
lv_rest = lv_size - lv_offs.
IF lv_rest < 1000.
lv_file = lv_string+lv_offs(lv_rest).
APPEND lv_file TO lt_file.
EXIT.
ELSE.
lv_file = lv_string+lv_offs(1000).
APPEND lv_file TO lt_file.
lv_offs = lv_offs + 1000.
ENDIF.
ENDDO.

CALL METHOD cl_gui_frontend_services=>file_save_dialog


EXPORTING
window_title = 'XML File'
default_extension = '.xml'
default_file_name = 'Note_Analyzer_Delta.xml'
file_filter = cl_gui_frontend_services=>filetype_xml
prompt_on_overwrite = abap_true
CHANGING
filename = lv_filename
path = lv_path
fullpath = lv_fullpath
user_action = lv_user_action
EXCEPTIONS
OTHERS = 99.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
DISPLAY LIKE lcl_msg=>gc_info.
RETURN.
ENDIF.
IF lv_user_action = cl_gui_frontend_services=>action_cancel.
RETURN.
ENDIF.

CALL METHOD cl_gui_frontend_services=>gui_download


EXPORTING
bin_filesize = lv_size
filename = lv_filename
filetype = 'BIN'
trunc_trailing_blanks = abap_true
write_lf = abap_false
codepage = '4110'
write_bom = abap_true
CHANGING
data_tab = lt_file
EXCEPTIONS
OTHERS = 99.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
DISPLAY LIKE lcl_msg=>gc_info.
RETURN.
ENDIF.

ENDMETHOD. "save_xml

METHOD call_browser.

DATA:
lv_url_c TYPE c LENGTH 500.

CHECK NOT iv_url IS INITIAL.

lv_url_c = iv_url.

CALL FUNCTION 'CALL_BROWSER'


EXPORTING
url = lv_url_c
new_window = abap_true
EXCEPTIONS
frontend_not_supported = 1
frontend_error = 2
prog_not_found = 3
no_batch = 4
unspecified_error = 5.
IF sy-subrc <> 0.
* Message inside
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
DISPLAY LIKE lcl_msg=>gc_info.
ENDIF.

ENDMETHOD. "call_browser

METHOD open_abap.
DATA:
lt_files TYPE filetable,
lrs_file TYPE REF TO file_table,
lv_rc_file_open TYPE i,
lv_default_filename TYPE string,
lv_file_size TYPE i, "#EC NEEDED
lv_user_action TYPE i,
lv_title TYPE string.

CLEAR: ev_filename, ev_flg_loaded, et_code.

IF iv_pattern IS SUPPLIED.
CONCATENATE iv_pattern '.txt' INTO lv_default_filename.
ELSE.
lv_default_filename = '*.txt'.
ENDIF.
IF iv_title IS SUPPLIED.
lv_title = iv_title.
ELSE.
lv_title = 'ABAP File'.
ENDIF.

* Return Code, Number of Files or -1 If Error Occurred


CALL METHOD cl_gui_frontend_services=>file_open_dialog
EXPORTING
window_title = lv_title
default_extension = '.txt'
default_filename = lv_default_filename
file_filter = cl_gui_frontend_services=>filetype_text
multiselection = ' '
CHANGING
file_table = lt_files
rc = lv_rc_file_open
user_action = lv_user_action
EXCEPTIONS
OTHERS = 9.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
DISPLAY LIKE lcl_msg=>gc_info.
RETURN.
ENDIF.
IF lv_user_action = cl_gui_frontend_services=>action_cancel.
RETURN.
ENDIF.

IF lv_rc_file_open EQ 1.
READ TABLE lt_files REFERENCE INTO lrs_file INDEX 1.
ev_filename = lrs_file->filename.

CALL METHOD cl_gui_frontend_services=>gui_upload


EXPORTING
filename = ev_filename
filetype = 'ASC'
codepage = '4110'
IMPORTING
filelength = lv_file_size
CHANGING
data_tab = et_code
EXCEPTIONS
OTHERS = 99.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
DISPLAY LIKE lcl_msg=>gc_info.
RETURN.
ENDIF.
ELSE.
RETURN.
ENDIF.

ev_flg_loaded = abap_true.

ENDMETHOD. "open_abap

METHOD format.

ev_value = iv_value.

IF NOT ev_value CO '0 '.


SHIFT ev_value LEFT DELETING LEADING '0'.
ENDIF.

CONDENSE ev_value.

ENDMETHOD. "format

METHOD display_logs.

TYPES:
BEGIN OF tn_s_logs,
numm TYPE cwbntmsg-numm,
sdate TYPE d,
stime TYPE t,
icon TYPE icon_d,
message TYPE string,
uname TYPE cwbntmsg-uname,
END OF tn_s_logs.

DATA:
lv_timezone TYPE timezone VALUE 'UTC',
ls_cwbntmsg TYPE cwbntmsg,
ls_logs TYPE tn_s_logs,
lt_logs TYPE STANDARD TABLE OF tn_s_logs,
l_s_fcat TYPE slis_fieldcat_alv,
l_t_fcat TYPE slis_t_fieldcat_alv,
l_s_sort TYPE slis_sortinfo_alv,
l_t_sort TYPE slis_t_sortinfo_alv,
l_s_layout TYPE slis_layout_alv.

SELECT * FROM cwbntmsg INTO ls_cwbntmsg


WHERE msgid = '01' AND msgno = '666' AND msgv1 LIKE 'Installation%'.

CLEAR ls_logs.
MOVE-CORRESPONDING ls_cwbntmsg TO ls_logs.
CONCATENATE ls_cwbntmsg-msgv1 ls_cwbntmsg-msgv2 ls_cwbntmsg-msgv3
ls_cwbntmsg-msgv4 INTO ls_logs-message SEPARATED BY space.
CASE ls_cwbntmsg-msgty.
WHEN 'I'.
ls_logs-icon = icon_led_green.
WHEN 'W'.
ls_logs-icon = icon_led_yellow.
WHEN 'E'.
ls_logs-icon = icon_led_red.
ENDCASE.

CONVERT TIME STAMP ls_cwbntmsg-tstamp TIME ZONE lv_timezone


INTO DATE ls_logs-sdate TIME ls_logs-stime.
APPEND ls_logs TO lt_logs.

ENDSELECT.

l_s_layout-colwidth_optimize = abap_true.
l_s_layout-window_titlebar = 'SAP BW Note Analyzer Logs'.

* For every element of select list an entry in field catalog


CLEAR l_s_fcat.
l_s_fcat-col_pos = 1.
l_s_fcat-seltext_l = 'SAP Note'.
l_s_fcat-seltext_m = l_s_fcat-seltext_l.
l_s_fcat-seltext_s = l_s_fcat-seltext_l.
l_s_fcat-fieldname = 'NUMM'.
l_s_fcat-datatype = 'NUMC'.
l_s_fcat-outputlen = '10'.
l_s_fcat-key = abap_true.
APPEND l_s_fcat TO l_t_fcat.
CLEAR l_s_fcat.
l_s_fcat-col_pos = 2.
l_s_fcat-seltext_l = 'Date'.
l_s_fcat-seltext_m = l_s_fcat-seltext_l.
l_s_fcat-seltext_s = l_s_fcat-seltext_l.
l_s_fcat-fieldname = 'SDATE'.
l_s_fcat-datatype = 'DATS'.
l_s_fcat-outputlen = '10'.
APPEND l_s_fcat TO l_t_fcat.
CLEAR l_s_fcat.
l_s_fcat-col_pos = 3.
l_s_fcat-seltext_l = 'Time'.
l_s_fcat-seltext_m = l_s_fcat-seltext_l.
l_s_fcat-seltext_s = l_s_fcat-seltext_l.
l_s_fcat-fieldname = 'STIME'.
l_s_fcat-datatype = 'TIMS'.
l_s_fcat-outputlen = '8'.
APPEND l_s_fcat TO l_t_fcat.
CLEAR l_s_fcat.
l_s_fcat-col_pos = 4.
l_s_fcat-seltext_l = 'Status'.
l_s_fcat-seltext_m = l_s_fcat-seltext_l.
l_s_fcat-seltext_s = l_s_fcat-seltext_l.
l_s_fcat-fieldname = 'ICON'.
l_s_fcat-datatype = 'CHAR'.
l_s_fcat-outputlen = '4'.
l_s_fcat-icon = abap_true.
APPEND l_s_fcat TO l_t_fcat.
CLEAR l_s_fcat.
l_s_fcat-col_pos = 5.
l_s_fcat-seltext_l = 'Message'.
l_s_fcat-seltext_m = l_s_fcat-seltext_l.
l_s_fcat-seltext_s = l_s_fcat-seltext_l.
l_s_fcat-fieldname = 'MESSAGE'.
l_s_fcat-datatype = 'CHAR'.
l_s_fcat-outputlen = '200'.
APPEND l_s_fcat TO l_t_fcat.
CLEAR l_s_fcat.
l_s_fcat-col_pos = 6.
l_s_fcat-seltext_l = 'User'.
l_s_fcat-seltext_m = l_s_fcat-seltext_l.
l_s_fcat-seltext_s = l_s_fcat-seltext_l.
l_s_fcat-fieldname = 'UNAME'.
l_s_fcat-datatype = 'CHAR'.
l_s_fcat-outputlen = '12'.
APPEND l_s_fcat TO l_t_fcat.

* Sort order
CLEAR l_s_sort.
l_s_sort-spos = 1.
l_s_sort-fieldname = 'NUMM'.
APPEND l_s_sort TO l_t_sort.
l_s_sort-spos = 2.
l_s_sort-fieldname = 'SDATE'.
APPEND l_s_sort TO l_t_sort.
l_s_sort-spos = 3.
l_s_sort-fieldname = 'STIME'.
APPEND l_s_sort TO l_t_sort.

CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'


EXPORTING
it_fieldcat = l_t_fcat
it_sort = l_t_sort
is_layout = l_s_layout
TABLES
t_outtab = lt_logs.

ENDMETHOD. "display_logs

METHOD is_system_modifiable.

DATA:
l_systemedit TYPE tadir-edtflag.

CALL FUNCTION 'TR_SYS_PARAMS'


IMPORTING
systemedit = l_systemedit
EXCEPTIONS
no_systemname = 1
no_systemtype = 2
OTHERS = 3.
IF sy-subrc <> 0 OR l_systemedit = 'N'. "not modifiable
rv_modifiable = abap_false.
ELSE.
rv_modifiable = abap_true.
ENDIF.

ENDMETHOD. "is_system_modifiable
METHOD is_system_test_or_prod.

DATA:
l_client_role TYPE cccategory.

CALL FUNCTION 'TR_SYS_PARAMS'


IMPORTING
system_client_role = l_client_role
EXCEPTIONS
no_systemname = 1
no_systemtype = 2
OTHERS = 3.
IF sy-subrc <> 0 OR l_client_role CA 'PTS'. "prod/test/sap reference
rv_test_prod = abap_true.
ELSE.
rv_test_prod = abap_false.
ENDIF.

ENDMETHOD. "is_system_test_or_prod

METHOD is_snote_allowed.

CALL FUNCTION 'OCS_CHECK_RUNNING_UPGRADE_4_NA'


IMPORTING
ev_snote_allowed = rv_snote_allowed.

ENDMETHOD. "is_spam_in_progress

METHOD is_upgrage_running.

CALL FUNCTION 'OCS_CHECK_RUNNING_UPGRADE_4_NA'


IMPORTING
ev_upg_running = rv_upgrade_running.

ENDMETHOD. "is_spam_in_progress

METHOD is_spam_locked.

DATA:
ls_sema TYPE pat10.

CALL FUNCTION 'OCS_QUEUE_SEMAPHORE'


EXPORTING
iv_tool = 'SPAM'
iv_read_only = abap_true
IMPORTING
ev_locked = rv_spam_locked
CHANGING
cs_sema = ls_sema
EXCEPTIONS
foreign_lock = 1
internal_error = 2
OTHERS = 3.
CHECK sy-subrc = 0. "ignore errors

ENDMETHOD. "is_spam_in_progress

METHOD is_fast.
IF gv_fast = abap_true AND iv_msg_type = gc_info AND iv_action =
gc_action_none.
rv_fast = abap_true.
ELSE.
rv_fast = abap_false.
ENDIF.

ENDMETHOD. "is_fast

METHOD is_debug.

IF NOT gv_debug IS INITIAL AND iv_check CS gv_debug.


rv_debug = abap_true.
ELSE.
rv_debug = abap_false.
ENDIF.

ENDMETHOD. "is_debug

METHOD get_db_release.

DATA:
l_release TYPE n LENGTH 3,
l_text_1 TYPE string,
l_text_2 TYPE string,
l_text_3 TYPE string,
l_hana_rel TYPE i,
l_hana_subrel TYPE i.

CLEAR: es_dbinfo, es_hana_release.

CALL FUNCTION 'DB_DBRELINFO'


IMPORTING
dbinfo = es_dbinfo.

IF es_dbinfo-dbsys = 'HDB'.
* First number in version is release, third one is revision level
FIND FIRST OCCURRENCE OF REGEX '(\d+)\.(\d+)\.(\d+)\.(\d*)\.\d*' IN
es_dbinfo-srvrel
SUBMATCHES l_text_1 l_text_2 es_hana_release-version es_hana_release-patch.
IF sy-subrc = 0.
l_hana_rel = l_text_1.
l_hana_subrel = l_text_2.
l_release = 100 * l_hana_rel + l_hana_subrel.
es_hana_release-release = l_release.
IF es_hana_release-patch > 1000. "it s the changelog for old revisions
es_hana_release-patch = 0.
ENDIF.
ENDIF.
ENDIF.

ENDMETHOD. "get_db_release

METHOD get_spam_release.

CONSTANTS:
lc_spam_vers_func TYPE funcname VALUE 'SPAM_VERSION'.

DATA:
lv_spam_vers TYPE n LENGTH 4.

TRY.
CALL FUNCTION lc_spam_vers_func
IMPORTING
version = lv_spam_vers.
* Basis Release for BW system conversion is 700 to 750 only
rs_details-release = sy-saprl. "#EC SAPRL_OK
rs_details-version = lv_spam_vers.
CATCH cx_sy_dyn_call_illegal_func.
ENDTRY.

ENDMETHOD. "get_spam_release

METHOD get_kernel_release.

* Kernel Info retrival copied from FuGrp SHSY Module get_kinfo


TYPES:
BEGIN OF lty_kernel_info,
key TYPE c LENGTH 21,
data TYPE c LENGTH 69,
END OF lty_kernel_info.

DATA:
lt_kernel_info TYPE STANDARD TABLE OF lty_kernel_info,
lr_kernel_info TYPE REF TO lty_kernel_info.

* Kernel Release Information


CALL 'SAPCORE' ID 'ID' FIELD 'VERSION'
ID 'TABLE' FIELD lt_kernel_info. "#EC CI_CCALL

READ TABLE lt_kernel_info REFERENCE INTO lr_kernel_info INDEX 12.


rs_details-release = lr_kernel_info->data.
rs_details-version = 0.

READ TABLE lt_kernel_info REFERENCE INTO lr_kernel_info INDEX 15.


rs_details-patch = lr_kernel_info->data.

ENDMETHOD. "get_kernel_release

ENDCLASS. "lcl_utilities IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_bw_check IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_bw_check IMPLEMENTATION.

METHOD get_instance.

CREATE OBJECT ro_instance.

ro_instance->mv_has_source = ro_instance->has_system_sources( ).
ro_instance->mv_has_target = ro_instance->has_system_targets( ).
ro_instance->mv_has_odp_source = ro_instance->has_odp_sources( ).
ro_instance->mv_has_odp_target = ro_instance->has_odp_targets( ).
ro_instance->mv_has_pi_basis = ro_instance->has_pi_basis( ).
ro_instance->mv_has_dw4core = ro_instance->has_dw4_core( ).

ENDMETHOD. "get_instance
METHOD is_bw_relevant.
* Do not check pi_basis. Otherwise every ERP system needs to load BW XML file
* Only if the customer wants this scope he/she needs to load the BW XML file

IF mv_has_target = abap_true OR mv_has_source = abap_true OR


mv_has_odp_source = abap_true OR mv_has_odp_target = abap_true OR
mv_has_dw4core = abap_true.
rv_relevant = abap_true.
ELSE.
rv_relevant = abap_false.
ENDIF.

ENDMETHOD. "is_bw_relevant

METHOD is_bw_system.

rv_is = mv_has_source.

ENDMETHOD. "is_bw_system

METHOD is_connected_system.

rv_is = mv_has_target.

ENDMETHOD. "is_connected_system

METHOD toggle_modif_group_visibility.

DATA:
lv_flg_val_file_loaded TYPE abap_bool,
lv_flg_bw_file_loaded TYPE abap_bool.

lv_flg_val_file_loaded = io_files->is_file_loaded( iv_file_type =


lcl_files=>gc_file_type_val ).
IF lv_flg_val_file_loaded = abap_true AND cs_screen-group1 CS 'BW'.
* In validation mode we check always the whole file
cs_screen-active = 0.
CLEAR ms_modif_visible.
RETURN.
ENDIF.

lv_flg_bw_file_loaded = io_files->is_file_loaded( iv_file_type =


lcl_files=>gc_file_type_bw ).
IF lv_flg_bw_file_loaded = abap_false AND cs_screen-group1 CS 'BW'.
* Without BW file no BW screen parameters
cs_screen-active = 0.
CLEAR ms_modif_visible.
RETURN.
ENDIF.

ENDMETHOD. "toggle_modif_group_visibility

METHOD has_system_targets.

DATA:
lt_dummy TYPE STANDARD TABLE OF rsslogsys.

SELECT slogsys FROM rsbasidoc UP TO 1 ROWS INTO TABLE lt_dummy


WHERE slogsys IN ( SELECT logsys FROM t000 )
AND srctype NE 'M'. "#EC CI_BUFFSUBQ

IF sy-subrc = 0.
rv_has = abap_true.
ELSE.
rv_has = abap_false.
ENDIF.

ENDMETHOD. "has_system_targets

METHOD has_system_sources.

DATA:
lv_rscc_rsadm_acc TYPE funcname VALUE 'RSCC_RSADM_ACC',
lv_bwmandt TYPE symandt,
lv_myself TYPE logsys,
lt_dummy TYPE STANDARD TABLE OF rsslogsys.

CALL FUNCTION 'FUNCTION_EXISTS'


EXPORTING
funcname = lv_rscc_rsadm_acc
EXCEPTIONS
function_not_exist = 1
OTHERS = 2.
IF sy-subrc <> 0.
rv_has = abap_false.
RETURN.
ENDIF.

CALL FUNCTION lv_rscc_rsadm_acc


EXPORTING
fieldname = 'BWMANDT'
action = 'S'
CHANGING
adminvalue = lv_bwmandt
EXCEPTIONS
info_limit_reached = 1
false_field = 2
no_upd_rsadmins = 3
no_increment = 4
limit_reached = 5
lock_fail = 6
fieldinfo_fail = 7
false_action = 8
OTHERS = 9.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE lcl_msg=>gc_info NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
rv_has = abap_false.
RETURN.
ENDIF.

IF lv_bwmandt IS INITIAL.
rv_has = abap_false.
RETURN.
ENDIF.

SELECT SINGLE logsys FROM t000 INTO lv_myself


WHERE mandt = lv_bwmandt.

SELECT slogsys FROM rsbasidoc INTO TABLE lt_dummy UP TO 1 ROWS


WHERE rlogsys = lv_myself
AND ( srctype = '3' OR srctype = 'D' OR srctype = 'O' ). "#EC CI_BUFFSUBQ
IF sy-subrc = 0.
rv_has = abap_true.
ELSE.
rv_has = abap_false.
ENDIF.

ENDMETHOD. "has_system_sources

METHOD has_odp_sources.

DATA:
lv_rscc_rsadm_acc TYPE funcname VALUE 'RSCC_RSADM_ACC',
lv_bwmandt TYPE symandt,
lv_myself TYPE logsys,
lt_dummy TYPE STANDARD TABLE OF rsslogsys.

CALL FUNCTION 'FUNCTION_EXISTS'


EXPORTING
funcname = lv_rscc_rsadm_acc
EXCEPTIONS
function_not_exist = 1
OTHERS = 2.
IF sy-subrc <> 0.
rv_has = abap_false.
RETURN.
ENDIF.

CALL FUNCTION lv_rscc_rsadm_acc


EXPORTING
fieldname = 'BWMANDT'
action = 'S'
CHANGING
adminvalue = lv_bwmandt
EXCEPTIONS
info_limit_reached = 1
false_field = 2
no_upd_rsadmins = 3
no_increment = 4
limit_reached = 5
lock_fail = 6
fieldinfo_fail = 7
false_action = 8
OTHERS = 9.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE lcl_msg=>gc_info NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
rv_has = abap_false.
RETURN.
ENDIF.

IF lv_bwmandt IS INITIAL.
rv_has = abap_false.
RETURN.
ENDIF.
SELECT SINGLE logsys FROM t000 INTO lv_myself
WHERE mandt = lv_bwmandt.

SELECT slogsys FROM rsbasidoc INTO TABLE lt_dummy UP TO 1 ROWS


WHERE rlogsys = lv_myself AND srctype = 'O'. "#EC CI_BUFFSUBQ
IF sy-subrc = 0.
rv_has = abap_true.
ELSE.
rv_has = abap_false.
ENDIF.

ENDMETHOD. "has_odp_sources

METHOD has_odp_targets.

DATA:
lv_tab_name TYPE ddobjname VALUE 'RODPS_REPL_SUBSC',
lv_gotstate TYPE ddgotstate,
lt_dummy TYPE STANDARD TABLE OF symandt WITH DEFAULT KEY.

CALL FUNCTION 'DDIF_TABL_GET'


EXPORTING
name = lv_tab_name
IMPORTING
gotstate = lv_gotstate " Status in which Reading took Place
EXCEPTIONS
illegal_input = 1.
IF sy-subrc = 0 AND lv_gotstate = 'A'.
SELECT mandt INTO TABLE lt_dummy FROM (lv_tab_name)
CLIENT SPECIFIED UP TO 1 ROWS
WHERE subscriber_type = 'SAP_BW'.
IF sy-subrc = 0.
rv_has = abap_true.
ENDIF.
ENDIF.

ENDMETHOD. "has_odp_targets

METHOD has_pi_basis.

DATA:
lt_dummy TYPE STANDARD TABLE OF dlvunit WITH DEFAULT KEY.

SELECT component INTO TABLE lt_dummy FROM cvers UP TO 1 ROWS


WHERE component LIKE 'PI_BASIS%'.
IF sy-subrc = 0.
rv_has = abap_true.
ELSE.
rv_has = abap_false.
ENDIF.

ENDMETHOD. "has_pi_basis

METHOD has_dw4_core.

DATA:
lt_dummy TYPE STANDARD TABLE OF dlvunit WITH DEFAULT KEY.
SELECT component INTO TABLE lt_dummy FROM cvers UP TO 1 ROWS
WHERE component LIKE 'DW4CORE%'.
IF sy-subrc = 0.
rv_has = abap_true.
ELSE.
rv_has = abap_false.
ENDIF.

ENDMETHOD. "has_dw4_core

ENDCLASS. "lcl_bw_check IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_files IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_files IMPLEMENTATION.

METHOD get_instance.

CREATE OBJECT ro_instance.

ENDMETHOD. "get_instance

METHOD is_file_loaded.

READ TABLE mt_file TRANSPORTING NO FIELDS


WITH KEY type = iv_file_type.
IF sy-subrc = 0.
rv_loaded = abap_true.
ELSE.
rv_loaded = abap_false.
ENDIF.

ENDMETHOD. "is_file_loaded

METHOD get_next_file_info.

DATA:
ls_file_info TYPE gty_str_file_info,
lr_file_info TYPE REF TO gty_str_file_info,
lv_loaded TYPE abap_bool.

IF mt_file_info IS INITIAL.
ls_file_info-type = gc_file_type_bw.
ls_file_info-title = 'Load the BW XML file'(231).
ls_file_info-pattern = '*BW*'.
INSERT ls_file_info INTO TABLE mt_file_info.
ls_file_info-type = gc_file_type_val.
ls_file_info-title = 'Load the another XML file'(232).
ls_file_info-pattern = '*'.
INSERT ls_file_info INTO TABLE mt_file_info.
ENDIF.

lv_loaded = is_file_loaded( iv_file_type = gc_file_type_bw ).


IF lv_loaded = abap_false.
READ TABLE mt_file_info REFERENCE INTO lr_file_info
WITH TABLE KEY type = gc_file_type_bw.
ELSE.
READ TABLE mt_file_info REFERENCE INTO lr_file_info
WITH TABLE KEY type = gc_file_type_val.
ENDIF.

rs_file_info = lr_file_info->*.

ENDMETHOD. "get_next_file_info

METHOD add_file.

DATA:
ls_store_files TYPE gty_str_store_files.

ASSERT is_file IS NOT INITIAL.

ls_store_files-type = _derive_file_type( is_file = is_file ).


ls_store_files-filename = iv_filename.
ls_store_files-file = is_file.
INSERT ls_store_files INTO TABLE mt_file.

ENDMETHOD. "add_file

METHOD get_merged_file.

DATA:
lr_store_file TYPE REF TO gty_str_store_files.

CLEAR es_file.

LOOP AT mt_file REFERENCE INTO lr_store_file.


_merge_file(
EXPORTING
is_new_file = lr_store_file->file
CHANGING
cs_old_file = es_file
).
ENDLOOP.

IF iv_filter_scope_id IS NOT INITIAL.


_filter_file(
EXPORTING
iv_filter_scope_id = iv_filter_scope_id
CHANGING
cs_file = es_file
).
ENDIF.

ENDMETHOD. "get_merged_file

METHOD get_validation_scope.

DATA:
ls_rng_val_scope TYPE LINE OF gty_tab_rng_scope_id,
lr_store_file TYPE REF TO gty_str_store_files,
lr_scope_check TYPE REF TO gty_str_scope_check.

CLEAR et_rng_val_scope.

READ TABLE mt_file REFERENCE INTO lr_store_file


WITH KEY type = gc_file_type_val.
IF sy-subrc <> 0.
RETURN.
ENDIF.

ls_rng_val_scope-sign = 'I'.
ls_rng_val_scope-option = 'EQ'.

LOOP AT lr_store_file->file-scope_check REFERENCE INTO lr_scope_check


WHERE scope_id_uses = gc_scope_val.
ls_rng_val_scope-low = lr_scope_check->scope_id_used.
APPEND ls_rng_val_scope TO et_rng_val_scope.
ENDLOOP.

ENDMETHOD. "get_validation_scope

METHOD get_file_count.

rv_count = lines( mt_file ).

ENDMETHOD. "get_file_count

METHOD get_file_count_notes.

DATA:
lr_store_file TYPE REF TO gty_str_store_files,
lv_count TYPE i.

rv_count = 0.
LOOP AT mt_file REFERENCE INTO lr_store_file.
lv_count = lines( lr_store_file->file-note_check ).
ADD lv_count TO rv_count.
lv_count = lines( lr_store_file->file-prep_note_check ).
ADD lv_count TO rv_count.
ENDLOOP.

ENDMETHOD. "get_file_count_notes

METHOD _merge_file.

FIELD-SYMBOLS:
<lt_any_new> TYPE INDEX TABLE,
<lt_any_old> TYPE INDEX TABLE,
<ls_any> TYPE any.

IF cs_old_file IS INITIAL.
cs_old_file = is_new_file.
RETURN.
ENDIF.

DO.
ASSIGN COMPONENT sy-index OF STRUCTURE cs_old_file TO <lt_any_old>.
IF sy-subrc <> 0.
EXIT.
ENDIF.

ASSIGN COMPONENT sy-index OF STRUCTURE is_new_file TO <lt_any_new>.

LOOP AT <lt_any_new> ASSIGNING <ls_any>.


INSERT <ls_any> INTO TABLE <lt_any_old>.
ENDLOOP.
ENDDO.

ENDMETHOD. "_merge_file

METHOD _filter_file.

DATA:
lt_required_scope TYPE gty_tab_scope.

FIELD-SYMBOLS:
<lt_any> TYPE INDEX TABLE,
<ls_any> TYPE any,
<lv_any> TYPE any.

IF cs_file IS INITIAL.
RETURN.
ENDIF.

_get_required_scope(
EXPORTING
iv_sel_scope = iv_filter_scope_id
is_file = cs_file
IMPORTING
et_scope = lt_required_scope
).

SORT lt_required_scope.

DO.
ASSIGN COMPONENT sy-index OF STRUCTURE cs_file TO <lt_any>.
IF sy-subrc <> 0.
EXIT.
ENDIF.

LOOP AT <lt_any> ASSIGNING <ls_any>.


ASSIGN COMPONENT 'SCOPE_ID' OF STRUCTURE <ls_any> TO <lv_any>.
IF sy-subrc <> 0.
ASSIGN COMPONENT 'SCOPE_ID_USES' OF STRUCTURE <ls_any> TO <lv_any>.
CHECK sy-subrc = 0.
ENDIF.
READ TABLE lt_required_scope TRANSPORTING NO FIELDS
WITH KEY table_line = <lv_any> BINARY SEARCH.
CHECK sy-subrc <> 0.
DELETE <lt_any>.
ENDLOOP.
ENDDO.

ENDMETHOD. "_filter_file

METHOD _get_required_scope.

DATA:
lr_scope_check TYPE REF TO gty_str_scope_check,
lv_scope TYPE gty_scope_id,
lr_scope TYPE REF TO gty_scope_id,
lt_scope_last TYPE gty_tab_scope,
lt_scope_new TYPE gty_tab_scope.
COLLECT iv_sel_scope INTO lt_scope_new.

lt_scope_last = lt_scope_new.

DO.
LOOP AT lt_scope_last REFERENCE INTO lr_scope.
LOOP AT is_file-scope_check REFERENCE INTO lr_scope_check
WHERE scope_id_uses = lr_scope->*.
lv_scope = lr_scope_check->scope_id_used.
COLLECT lv_scope INTO lt_scope_new.
ENDLOOP.
ENDLOOP.

IF lt_scope_new = lt_scope_last.
EXIT.
ELSE.
lt_scope_last = lt_scope_new.
ENDIF.
ENDDO.

et_scope = lt_scope_new.

ENDMETHOD. "_get_required_scope

METHOD _derive_file_type.

READ TABLE is_file-scope_def TRANSPORTING NO FIELDS


WITH KEY solution = gc_solution_bw.
IF sy-subrc = 0.
rv_file_type = gc_file_type_bw.
RETURN.
ENDIF.

READ TABLE is_file-scope_def TRANSPORTING NO FIELDS


WITH KEY scope_id = gc_scope_val.
IF sy-subrc = 0.
rv_file_type = gc_file_type_val.
RETURN.
ENDIF.

* Default
rv_file_type = gc_file_type_others.

ENDMETHOD. "_derive_file_type

ENDCLASS. "lcl_files IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_checks IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_checks IMPLEMENTATION.

METHOD get_instance.

ASSERT is_file IS NOT INITIAL.

CREATE OBJECT ro_instance.

ro_instance->mo_msg = lcl_msg=>get_instance( ).
ro_instance->ms_file = is_file.
CLEAR ro_instance->ms_delta_file.
CLEAR ro_instance->mt_cvers.

ro_instance->mo_msg->mt_header = ro_instance->get_header( ).

ro_instance->mo_msg->mv_version = ro_instance->get_version( ).

ENDMETHOD. "get_instance

METHOD add_info_from_sel_screen.

mv_filter_scope_id = iv_filter_scope_id.
mo_bw_check = io_bw_check.

ENDMETHOD. "add_info_from_sel_screen

METHOD reset_msg.

mo_msg = lcl_msg=>get_instance( ).
CLEAR ms_delta_file.
CLEAR mt_cvers.

mo_msg->mt_header = get_header( ).

mo_msg->mv_version = get_version( ).

ENDMETHOD. "reset_msg

METHOD check_all.

DATA:
lv_ok TYPE abap_bool.

lv_ok = _check_sys_info( io_bw_check = mo_bw_check ).


IF lv_ok = abap_false.
* fatal check
ro_msg = mo_msg.
RETURN.
ENDIF.

lv_ok = _check_scope( iv_filter_scope = mv_filter_scope_id ).


IF lv_ok = abap_false.
* fatal check
ro_msg = mo_msg.
RETURN.
ENDIF.

_check_param( ).

lv_ok = _check_components( ).
IF lv_ok = abap_false.
* fatal check
ro_msg = mo_msg.
RETURN.
ENDIF.

_read_inactive_objects( ).
_check_notes(
EXPORTING
iv_node = mo_msg->gc_node_prep_check
iv_description = '200'
iv_flg_download = iv_flg_download
iv_flg_resolve = iv_flg_resolve
CHANGING
ct_note_check = ms_file-prep_note_check
).

_check_notes(
EXPORTING
iv_node = mo_msg->gc_node_note_check
iv_description = '300'
iv_flg_download = iv_flg_download
iv_flg_resolve = iv_flg_resolve
CHANGING
ct_note_check = ms_file-note_check
).

_check_summary( ).

ro_msg = mo_msg.

ENDMETHOD. "check_all

METHOD validate_all.

CLEAR: eo_msg, es_delta_file.

_validate_scope( it_rng_val_scope ).

_validate_param( it_rng_val_scope ).

_validate_components( it_rng_val_scope ).

_validate_prep_notes( it_rng_val_scope ).

_validate_notes( it_rng_val_scope ).

eo_msg = mo_msg.
es_delta_file = ms_delta_file.

ENDMETHOD. "validate_all

METHOD get_all_notes.

DATA:
lr_note_check TYPE REF TO gty_str_note_check.

CLEAR et_notes.
LOOP AT ms_file-note_check REFERENCE INTO lr_note_check.
APPEND lr_note_check->number TO et_notes.
ENDLOOP.

LOOP AT ms_file-prep_note_check REFERENCE INTO lr_note_check.


APPEND lr_note_check->number TO et_notes.
ENDLOOP.
ENDMETHOD. "get_all_notes

METHOD get_needed_notes.

DATA:
lr_note_check TYPE REF TO gty_str_note_check,
lv_download_needed TYPE abap_bool,
lv_downloaded TYPE abap_bool.

CLEAR et_notes.
LOOP AT ms_file-note_check REFERENCE INTO lr_note_check.
lv_download_needed = _check_note_by_validity(
is_note_check = lr_note_check->*
it_note_validity = ms_file-note_validity
iv_flg_silent = abap_true
).
CHECK lv_download_needed = abap_true.

lv_downloaded = _check_note_is_downloaded( is_note_check = lr_note_check-


>* ).
CHECK lv_downloaded = abap_false.

APPEND lr_note_check->number TO et_notes.


ENDLOOP.

LOOP AT ms_file-prep_note_check REFERENCE INTO lr_note_check.


lv_download_needed = _check_note_by_validity(
is_note_check = lr_note_check->*
it_note_validity = ms_file-note_validity
iv_flg_silent = abap_true
).
CHECK lv_download_needed = abap_true.

lv_downloaded = _check_note_is_downloaded( is_note_check = lr_note_check-


>* ).
CHECK lv_downloaded = abap_false.

APPEND lr_note_check->number TO et_notes.


ENDLOOP.

ENDMETHOD. "get_needed_notes

METHOD is_scope_consistent.

ev_flg_ok = _check_scope( ).
IF ev_flg_ok = abap_true AND ( p_chk = abap_false OR p_dl = abap_true ).
* Check in addition that the ping to SAP works
ev_flg_ok = _does_rfc_connection_exist( ).
ENDIF.
eo_msg = mo_msg.

ENDMETHOD. "is_scope_consistent

METHOD check_note_again.

DATA:
lv_sequence TYPE i,
lv_number TYPE cwbntnumm,
lt_note_check TYPE TABLE OF gty_str_note_check,
lr_note_check TYPE REF TO gty_str_note_check.

* Prep or regular check


IF is_msg-node = lcl_msg=>gc_node_prep_check.
lt_note_check = ms_file-prep_note_check.
ELSEIF is_msg-node = lcl_msg=>gc_node_note_check.
lt_note_check = ms_file-note_check.
ELSE.
RETURN.
ENDIF.

* Find start of sequence for the note


lv_sequence = mo_msg->find_msg( is_msg ).
ASSERT lv_sequence >= 0.

* Delete all messages related to the note


mo_msg->delete_msg( is_msg ).

* Set correct starting point


mo_msg->set_msg(
EXPORTING
is_msg = is_msg
iv_sequence = lv_sequence
).

* Now check note again


lv_number = is_msg-object.

READ TABLE lt_note_check REFERENCE INTO lr_note_check


WITH KEY scope_id = is_msg-scope_id number = lv_number.
ASSERT sy-subrc = 0.

_check_note(
EXPORTING
iv_again = abap_true
iv_node = is_msg-node
is_note_check = lr_note_check->*
).

ENDMETHOD. "check_note

METHOD evaluate_t_bal_msg.

CONSTANTS:
c_update_mode TYPE string VALUE 'Running in Update Mode',
c_no_execution TYPE string VALUE 'Report execution not required anymore.',
c_diff_release TYPE string VALUE 'This report was generated for',
c_manual_adj TYPE string VALUE 'Please adjust manually afterwards',
c_immediate TYPE string VALUE 'only immediately after note
implementation'.

DATA:
l_cnt TYPE i.

FIELD-SYMBOLS: <l_s_bal_log_msg> TYPE tn_s_bal_log_msg, <l_s_msg> TYPE


bal_s_msg.

rv_msg_type = lcl_msg=>gc_warning.
LOOP AT i_t_bal_log_msg ASSIGNING <l_s_bal_log_msg>.
LOOP AT <l_s_bal_log_msg>-t_msg ASSIGNING <l_s_msg>
WHERE msgid = '01' AND msgno = '666'
AND ( msgv1 = c_update_mode
OR msgv3 = c_no_execution
OR msgv4 = c_no_execution ).
EXIT.
ENDLOOP.
IF sy-subrc = 0.
l_cnt = l_cnt + 1.
ENDIF.
ENDLOOP.
IF l_cnt < i_no_of_exec.
" no update of msgty and action -> not executed enough times.
RETURN.
ELSE.
" get most current ballog entry.
LOOP AT i_t_bal_log_msg ASSIGNING <l_s_bal_log_msg>.
LOOP AT <l_s_bal_log_msg>-t_msg ASSIGNING <l_s_msg>
WHERE msgid = '01' AND msgno = '666'
AND ( msgv1 = c_update_mode
OR msgv3 = c_no_execution
OR msgv4 = c_no_execution ).
EXIT.
ENDLOOP.
IF sy-subrc = 0.
rv_msg_type = lcl_msg=>gc_info.

IF <l_s_msg>-msgv1 = c_update_mode.
LOOP AT <l_s_bal_log_msg>-t_msg ASSIGNING <l_s_msg>
WHERE msgv1 NS c_diff_release AND msgv4 NS c_manual_adj
AND msgv4 NS c_immediate.
IF <l_s_msg>-msgty = lcl_msg=>gc_error OR
<l_s_msg>-msgty = lcl_msg=>gc_abort.
rv_msg_type = lcl_msg=>gc_error.
EXIT.
ELSEIF <l_s_msg>-msgty = lcl_msg=>gc_warning.
* Remember: we leave the loop as soon as rv_msg_type got 'E'
* So no further checking on the existing rv_msg_type
rv_msg_type = lcl_msg=>gc_warning.
ENDIF.
ENDLOOP.
ENDIF.

EXIT.
ENDIF.
ENDLOOP.
ENDIF.

ENDMETHOD. "evaluate_t_bal_msg

METHOD get_bal_log.

DATA:
l_s_log_filter TYPE bal_s_lfil,
l_t_log_handle_all TYPE bal_t_logh,
l_t_log_handle TYPE bal_t_logh,
l_ts_log_header TYPE balhdr_t,
l_t_log_header_all TYPE tn_t_log_hdr,
l_ts_log_header_all TYPE balhdr_t,
l_t_msg_handle TYPE bal_t_msgh,
l_s_object TYPE bal_s_obj,
l_s_bal_msg TYPE bal_s_msg,
l_t_bal_msg TYPE STANDARD TABLE OF bal_s_msg,
l_s_msg_handle TYPE balmsghndl,
lr_extnumber TYPE bal_s_extn,
l_s_bal_log_msg TYPE tn_s_bal_log_msg,
l_t_bal_log_msg TYPE tn_t_bal_log_msg.

FIELD-SYMBOLS:
<l_s_log_handle> TYPE balloghndl,
<l_s_log_header> TYPE balhdr,
<l_s_bal_log_msg> TYPE tn_s_bal_log_msg.

l_s_object-sign = 'I'.
l_s_object-option = 'EQ'.
l_s_object-low = 'SNOTE'.
APPEND l_s_object TO l_s_log_filter-object.

l_s_object-sign = 'I'.
l_s_object-option = 'EQ'.
l_s_object-low = ''.
APPEND l_s_object TO l_s_log_filter-subobject.

*-- UDO-Report
lr_extnumber-low = i_udo_report.
lr_extnumber-sign = 'I'.
lr_extnumber-option = 'EQ'.
APPEND lr_extnumber TO l_s_log_filter-extnumber.

*-- read header


CALL FUNCTION 'BAL_DB_SEARCH'
EXPORTING
i_s_log_filter = l_s_log_filter
IMPORTING
e_t_log_header = l_ts_log_header_all
EXCEPTIONS
log_not_found = 1
no_filter_criteria = 2
OTHERS = 3.
IF sy-subrc <> 0.
RETURN.
ENDIF.

l_t_log_header_all = l_ts_log_header_all.
SORT l_t_log_header_all BY aldate DESCENDING altime DESCENDING.
LOOP AT l_t_log_header_all ASSIGNING <l_s_log_header>.
MOVE-CORRESPONDING <l_s_log_header> TO l_s_bal_log_msg-log_hdr.
APPEND l_s_bal_log_msg TO l_t_bal_log_msg.
ENDLOOP.

*--- log im Hauptspeicher suchen


CALL FUNCTION 'BAL_GLB_SEARCH_LOG'
EXPORTING
i_s_log_filter = l_s_log_filter
IMPORTING
e_t_log_handle = l_t_log_handle_all
EXCEPTIONS
log_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
* ignore
ENDIF.

"--- nicht gefunden, oder noch weitere auf der DB -> besser mal schauen
LOOP AT l_t_bal_log_msg ASSIGNING <l_s_bal_log_msg>.
CLEAR: l_ts_log_header, l_t_log_handle.
INSERT <l_s_bal_log_msg>-log_hdr INTO TABLE l_ts_log_header.

*--- Log von der Datenbank holen


CALL FUNCTION 'BAL_DB_LOAD'
EXPORTING
i_t_log_header = l_ts_log_header
IMPORTING
e_t_log_handle = l_t_log_handle
EXCEPTIONS
no_logs_specified = 1
log_not_found = 2
log_already_loaded = 3
OTHERS = 4.
IF sy-subrc <> 0.
CONTINUE.
ENDIF.
INSERT LINES OF l_t_log_handle INTO TABLE l_t_log_handle_all.
ENDLOOP.

*-- Meldungshandles zu den gefundenen Loghandels auslesen


LOOP AT l_t_log_handle_all ASSIGNING <l_s_log_handle>.
CLEAR: l_t_msg_handle, l_t_log_handle.
INSERT <l_s_log_handle> INTO TABLE l_t_log_handle.

CALL FUNCTION 'BAL_GLB_SEARCH_MSG'


EXPORTING
i_t_log_handle = l_t_log_handle
IMPORTING
e_t_msg_handle = l_t_msg_handle
EXCEPTIONS
msg_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
RETURN.
ENDIF.

CLEAR: l_t_bal_msg.
LOOP AT l_t_msg_handle INTO l_s_msg_handle.
CALL FUNCTION 'BAL_LOG_MSG_READ'
EXPORTING
i_s_msg_handle = l_s_msg_handle
IMPORTING
e_s_msg = l_s_bal_msg
EXCEPTIONS
log_not_found = 1
msg_not_found = 2
OTHERS = 3.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
APPEND l_s_bal_msg TO l_t_bal_msg.
ENDLOOP.

READ TABLE l_t_bal_log_msg ASSIGNING <l_s_bal_log_msg>


WITH KEY log_hdr-log_handle = <l_s_log_handle>.
IF sy-subrc = 0.
<l_s_bal_log_msg>-t_msg = l_t_bal_msg.
ENDIF.
ENDLOOP.

r_t_bal_log_msg = l_t_bal_log_msg.

ENDMETHOD. "get_bal_log

METHOD split_udo.

* Format 1:
* <Program>
* - Execute program once before/after implementing SAP Note

* Format 2:
* <Program> [<Number_of_Executions>]
* - Execute program x times before/after implementing SAP Note

* Format 3:
* <Release>: <Program>
* - Execute program before/after implementing SAP Note limited to given release
* - Release can be a fixed number like 701 or a pattern like 73* (optional)

DATA:
l_prog TYPE string,
l_no_of_exec TYPE i,
l_dummy1 TYPE string,
l_dummy2 TYPE string. "#EC NEEDED

l_prog = i_udo_comment.

* UDO is release dependend


IF l_prog CS ':'.
SPLIT l_prog AT ':' INTO e_release l_prog.
SHIFT l_prog LEFT DELETING LEADING space.
ELSE.
e_release = '*'.
ENDIF.

* UOD should be executed multiple times


SPLIT l_prog AT '[' INTO l_prog l_dummy1.
IF NOT l_dummy1 IS INITIAL.
SPLIT l_dummy1 AT ']' INTO l_dummy1 l_dummy2.
ENDIF.
IF l_dummy1 IS INITIAL.
l_no_of_exec = 1.
ELSE.
TRY.
l_no_of_exec = l_dummy1.
CATCH cx_root.
l_no_of_exec = 1.
ENDTRY.
ENDIF.

e_udo_report = l_prog.
e_no_of_exec = l_no_of_exec.

ENDMETHOD. "split_udo

METHOD split_tci.

* Format:
* <Release>: <Package> <URL Key>
* - Provide download link to TCI SAR file or software package limited to given
release
* - Release must be a fixed number like 701 or 730 since TCIs or sotware packages
are release dependent

DATA:
l_tci TYPE string.

l_tci = i_tci_comment.

* TCI or SW package is release dependend


IF l_tci CS ':'.
SPLIT l_tci AT ':' INTO e_release l_tci.
SHIFT l_tci LEFT DELETING LEADING space.
ELSE.
e_release = '*'.
ENDIF.

SPLIT l_tci AT space INTO e_tci_sar e_tci_url.

CONCATENATE 'https://softwaredownloads.sap.com/file/' e_tci_url INTO e_tci_url.

ENDMETHOD. "split_tci

METHOD split_icf.

* Format 1:
* <ICF GUID>
* - Provide link to SICF for activating service

* Format 2:
* <Release>: <ICF GUID>
* - Provide link to SICF for activating service
* - Release can be a fixed number like 701 or a pattern like 73*

DATA:
l_icf TYPE string,
l_s_icf TYPE icfservice,
l_error TYPE abap_bool,
l_hostnumber TYPE i.

l_icf = i_icf_comment.

* ICF is release dependend


IF l_icf CS ':'.
SPLIT l_icf AT ':' INTO e_release l_icf.
SHIFT l_icf LEFT DELETING LEADING space.
ELSE.
e_release = '*'.
ENDIF.

SELECT SINGLE * FROM icfservice INTO l_s_icf


WHERE icfnodguid = l_icf. "#EC *
IF sy-subrc = 0.
* Get ICF service path
PERFORM construct_path_from_host IN PROGRAM rsicftree
USING l_s_icf
CHANGING e_icf_path l_error l_hostnumber.

CONCATENATE e_icf_path l_s_icf-orig_name INTO e_icf_text.

REPLACE '/default_host' WITH '' INTO e_icf_path.


SHIFT e_icf_path LEFT DELETING LEADING space.

e_icf_name = l_s_icf-icf_name.
e_icf_par = l_s_icf-icfparguid.
ENDIF.

ENDMETHOD. "split_icf

METHOD check_icf_service.

SELECT SINGLE icfactive FROM icfservloc INTO r_icf_status


WHERE icf_name = i_icf_name AND icfparguid = i_icf_par.
IF sy-subrc <> 0.
r_icf_status = abap_false.
ENDIF.

ENDMETHOD. "check_icf_service

METHOD get_header.

DATA:
lr_note_comment TYPE REF TO gty_str_note_comment,
ls_header TYPE gty_str_header.

CLEAR et_header.

LOOP AT ms_file-note_comment REFERENCE INTO lr_note_comment


WHERE purpose = lcl_alv=>gc_purpose_header.

CLEAR ls_header.
ls_header-number = lr_note_comment->number.

SPLIT lr_note_comment->message AT space


INTO ls_header-xml_id ls_header-xml_version.

INSERT ls_header INTO TABLE et_header.


ENDLOOP.

ENDMETHOD. "get_header

METHOD get_version.

DATA:
lr_note_comment TYPE REF TO gty_str_note_comment,
lv_version TYPE gty_version.
CLEAR rv_version.

LOOP AT ms_file-note_comment REFERENCE INTO lr_note_comment


WHERE purpose = lcl_alv=>gc_purpose_version.

lv_version = lr_note_comment->message.

IF lv_version > rv_version.


rv_version = lv_version.
ENDIF.
ENDLOOP.

ENDMETHOD. "get_version

METHOD check_outdated_notes.

DATA:
lv_destination TYPE rfcdest,
lt_destinations TYPE TABLE OF rfcdest,
ls_note_keys TYPE cwbntkeylg,
lt_note_keys TYPE bcwbn_note_keys_lg.

FIELD-SYMBOLS:
<lv_destination> TYPE rfcdest.

DATA:
lr_prstatus TYPE RANGE OF cwbntcust-prstatus,
ls_prstatus LIKE LINE OF lr_prstatus,
ls_notes TYPE bcwbn_note,
lt_notes TYPE bcwbn_notes,
ls_select_options TYPE bcwbn_note_select_options.

* Get all implemented SAP Notes


ls_prstatus-option = 'EQ'.
ls_prstatus-sign = 'I'.
ls_prstatus-low = gc_prstat_implemented.
APPEND ls_prstatus TO ls_select_options-prstatus.

CALL FUNCTION 'SCWN_NOTE_SELECT'


EXPORTING
is_note_select_options = ls_select_options
IMPORTING
es_notes = lt_notes
EXCEPTIONS
nothing_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
RETURN.
ENDIF.

* Restrict to SAP Notes included in XML


LOOP AT lt_notes INTO ls_notes.
READ TABLE it_notes TRANSPORTING NO FIELDS
WITH TABLE KEY table_line = ls_notes-key-numm.
IF sy-subrc <> 0.
DELETE lt_notes.
ENDIF.
ENDLOOP.
CHECK NOT lt_notes IS INITIAL.

* Get SAP Note versions in XML


LOOP AT lt_notes INTO ls_notes.
CLEAR ls_note_keys.
ls_note_keys-numm = ls_notes-key-numm.
ls_note_keys-versno = ls_notes-key-versno.
COLLECT ls_note_keys INTO lt_note_keys.
ENDLOOP.

* Fill destination table


SELECT SINGLE rfcdest FROM cwbrfcusr INTO lv_destination WHERE bname = sy-
uname.
IF sy-subrc EQ 0. " override RFC destination for current user
APPEND lv_destination TO lt_destinations.
ELSE.
APPEND gc_cwbadm_cs_nt_new TO lt_destinations.
APPEND gc_cwbadm_cs_nt TO lt_destinations.
ENDIF.

* Check whether the SAP Notes have been changed by SAP (ignore errors)
LOOP AT lt_destinations ASSIGNING <lv_destination>.
CALL FUNCTION 'BHREM_SAPNOTE_CHECK_CHANGED'
DESTINATION <lv_destination>
EXPORTING
iv_implementation_test_only = abap_false
TABLES
it_note_keys = lt_note_keys
* it_note_tstamp = lt_note_tstamp
et_changed_notes = et_changed_notes
EXCEPTIONS
communication_failure = 1
system_failure = 2
OTHERS = 3. "#EC EXISTS
IF sy-subrc = 0. EXIT. ENDIF.
ENDLOOP.

SORT et_changed_notes.

ENDMETHOD. "check_outdated_notes

METHOD update_outdated_notes.

mt_changed_notes = it_changed_notes.

ENDMETHOD. "update_outdated_notes

METHOD remove_outdated_note.

DELETE mt_changed_notes WHERE numm = iv_note_number.

ENDMETHOD. "remove_outdated_note

METHOD _does_rfc_connection_exist.

DATA:
lv_rfc_connection TYPE rfcdes-rfcdest.
rv_flg_ok = abap_true.

lv_rfc_connection = gc_cwbadm_cs_nt_new.

CALL FUNCTION 'SCWB_RFC_PING'


EXPORTING
iv_destination = lv_rfc_connection
iv_timeout = '3.000'
EXCEPTIONS
rfc_error = 1
communication_failure = 2
system_failure = 3
OTHERS = 4.
IF sy-subrc <> 0.
* altenative connection
lv_rfc_connection = gc_cwbadm_cs_nt.
CALL FUNCTION 'SCWB_RFC_PING'
EXPORTING
iv_destination = lv_rfc_connection
iv_timeout = '3.000'
EXCEPTIONS
rfc_error = 1
communication_failure = 2
system_failure = 3
OTHERS = 4.
IF sy-subrc <> 0.
mo_msg->start_node(
iv_node = mo_msg->gc_node_sys_info
iv_description = '700'
).
mo_msg->add_t100_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = 'RFC_TO_SAP'
iv_object = 'PING'
iv_action = lcl_msg=>gc_action_none
).
rv_flg_ok = abap_false.
mo_msg->end_node( mo_msg->gc_node_sys_info ).
ENDIF.
ENDIF.

ENDMETHOD. "_does_rfc_connection_exist
*#info
METHOD _check_sys_info.

CONSTANTS:
lc_system TYPE gty_scope_id VALUE 'System',
lc_kernel TYPE c LENGTH 10 VALUE 'Kernel',
lc_r3trans TYPE c LENGTH 10 VALUE 'R3trans',
lc_cvers TYPE c LENGTH 10 VALUE 'Component',
lc_analyzer TYPE c LENGTH 10 VALUE 'Analyzer',
lc_bw TYPE c LENGTH 10 VALUE 'BW',
lc_db TYPE c LENGTH 10 VALUE 'Database',
lc_spam TYPE c LENGTH 10 VALUE 'SPAM',
lc_global TYPE c LENGTH 10 VALUE 'Global'.

DATA:
lv_system_name TYPE stpa-sysname,
lv_r3trans_source TYPE stpa-timestamp,
lr_cvers TYPE REF TO cvers,
lv_text TYPE string,
ls_kernel_release TYPE gty_str_release_patch,
ls_header TYPE gty_str_header,
lv_timestmp TYPE tzonref-tstamps,
lv_tzone TYPE tzonref-tzone,
lv_date TYPE d,
lv_date_c TYPE c LENGTH 20,
lv_time TYPE t,
lv_time_c TYPE c LENGTH 20,
lv_flg_is TYPE abap_bool,
ls_dbinfo TYPE dbrelinfo,
ls_spam_release TYPE gty_str_release_patch,
lv_splevel TYPE gty_splevel.

rv_ok = abap_true.

mo_msg->start_node(
iv_node = mo_msg->gc_node_sys_info
iv_description = '700'
).

* Installed components
_load_cvers( ).

GET TIME STAMP FIELD lv_timestmp.


lv_tzone = 'UTC'.
CONVERT TIME STAMP lv_timestmp TIME ZONE lv_tzone INTO DATE lv_date TIME
lv_time.
WRITE lv_date TO lv_date_c.
WRITE lv_time TO lv_time_c.

* Note Analyzer was here message


mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_analyzer
iv_action = mo_msg->gc_action_none
iv_msg_text = '704'
iv_msg_v1 = gc_version
iv_msg_v2 = lv_date_c
iv_msg_v3 = lv_time_c
).

* Note Analyzer version check


IF NOT mo_msg->mv_version IS INITIAL AND mo_msg->mv_version > gc_version.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = lc_system
iv_object = lc_analyzer
iv_action = mo_msg->gc_action_none
iv_msg_text = '715'
iv_msg_v1 = gc_version
iv_msg_v2 = mo_msg->mv_version
).
ENDIF.
* XML ID and version
LOOP AT mo_msg->mt_header INTO ls_header.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_analyzer
iv_action = mo_msg->gc_action_none
iv_msg_text = '719'
iv_msg_v1 = ls_header-xml_id
iv_msg_v2 = ls_header-xml_version
).
ENDLOOP.

* SID and host


mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_system
iv_action = mo_msg->gc_action_none
iv_msg_text = '707'
iv_msg_v1 = sy-sysid
iv_msg_v2 = sy-host
).

* Software components
LOOP AT mt_cvers REFERENCE INTO lr_cvers.
CLEAR lv_text.
SELECT SINGLE desc_text FROM cvers_ref INTO lv_text
WHERE component = lr_cvers->component AND langu = sy-langu.
IF sy-subrc <> 0.
lv_text = lr_cvers->component.
ENDIF.

lv_splevel = lr_cvers->extrelease+2(2).

IF lcl_utilities=>is_fast( ) = abap_false OR
lr_cvers->component = 'SAP_BW' OR lr_cvers->component CP 'DW4*' OR
lr_cvers->component CP 'BW4*'.

mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_cvers
iv_action = mo_msg->gc_action_none
iv_msg_text = '703'
iv_msg_v1 = lv_text
iv_swcomponent = lr_cvers->component
iv_release = lr_cvers->release
iv_splevel = lv_splevel
).
ENDIF.
ENDLOOP.

* Kernel Release Information


IF lcl_utilities=>is_fast( ) = abap_false.
ls_kernel_release = lcl_utilities=>get_kernel_release( ).

mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_kernel
iv_action = mo_msg->gc_action_none
iv_msg_text = '701'
iv_msg_v1 = ls_kernel_release-release
iv_msg_v2 = ls_kernel_release-patch
).

* However it turned out, that not the kernel release and patch level is needed
* but R3/Trans
* Func TRINT_TP_INTERFACE with command CONNECT checks R3trans version, too.
* This is returned in form a timestamp in EV_R3TRANS_SOURCE
lv_system_name = sy-sysid.

CALL FUNCTION 'TRINT_TP_INTERFACE'


EXPORTING
iv_tp_command = 'CONNECT'
iv_system_name = lv_system_name
IMPORTING
ev_r3trans_source = lv_r3trans_source
EXCEPTIONS
OTHERS = 9.

IF sy-subrc <> 0.
mo_msg->add_t100_msg(
EXPORTING
iv_scope_id = lc_system
iv_object = lc_r3trans
iv_action = mo_msg->gc_action_none
).
ENDIF.

mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_r3trans
iv_action = mo_msg->gc_action_none
iv_msg_text = '702'
iv_msg_v1 = lv_r3trans_source
).
ENDIF.

* Add DB release information


lcl_utilities=>get_db_release(
IMPORTING
es_dbinfo = ls_dbinfo
).

mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_db
iv_action = mo_msg->gc_action_none
iv_msg_text = '708'
iv_msg_v1 = ls_dbinfo-dbname
iv_msg_v2 = ls_dbinfo-dbsys
iv_msg_v3 = ls_dbinfo-patchlevel
iv_msg_v4 = ls_dbinfo-srvrel
).

* BW Info
IF lcl_utilities=>is_fast( ) = abap_false.
IF io_bw_check IS BOUND.
lv_flg_is = io_bw_check->is_bw_system( ).
IF lv_flg_is = abap_true.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_bw
iv_action = mo_msg->gc_action_none
iv_msg_text = '705'
).
ENDIF.
lv_flg_is = io_bw_check->is_connected_system( ).
IF lv_flg_is = abap_true.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_bw
iv_action = mo_msg->gc_action_none
iv_msg_text = '706'
).
ENDIF.
ENDIF.
ENDIF.

* Global system change option


lv_flg_is = lcl_utilities=>is_system_modifiable( ).
IF lv_flg_is = abap_false.
lv_flg_is = lcl_utilities=>is_system_test_or_prod( ).
IF lv_flg_is = abap_true.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = lc_system
iv_object = lc_global
iv_action = mo_msg->gc_action_none
iv_msg_text = '713'
).
ELSE.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = lc_system
iv_object = lc_global
iv_action = mo_msg->gc_action_none
iv_msg_text = '714'
).
ENDIF.
ENDIF.

* Upgrade status
lv_flg_is = lcl_utilities=>is_upgrage_running( ).
IF lv_flg_is = abap_true.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = lc_system
iv_object = lc_global
iv_action = mo_msg->gc_action_none
iv_msg_text = '716'
).
ENDIF.

* Note assistant status


lv_flg_is = lcl_utilities=>is_snote_allowed( ).
IF lv_flg_is = abap_false.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_abort
iv_scope_id = lc_system
iv_object = lc_global
iv_action = mo_msg->gc_action_none
iv_msg_text = '717'
).
rv_ok = abap_false.
ENDIF.

* SPAM version
ls_spam_release = lcl_utilities=>get_spam_release( ).

mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lc_system
iv_object = lc_spam
iv_action = mo_msg->gc_action_none
iv_msg_text = '709'
iv_msg_v1 = ls_spam_release-release
iv_msg_v2 = ls_spam_release-version
).

* SPAM status
lv_flg_is = lcl_utilities=>is_spam_locked( ).
IF lv_flg_is = abap_true.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_abort
iv_scope_id = lc_system
iv_object = lc_global
iv_action = mo_msg->gc_action_none
iv_msg_text = '718'
).
rv_ok = abap_false.
ENDIF.

mo_msg->end_node( mo_msg->gc_node_sys_info ).
ENDMETHOD. "_check_sys_info

METHOD _validate_prep_notes.

DATA:
lr_prep_check TYPE REF TO gty_str_note_check.

mo_msg->start_node(
iv_node = mo_msg->gc_node_prep_check
iv_description = '200'
).

LOOP AT ms_file-prep_note_check REFERENCE INTO lr_prep_check


WHERE scope_id IN it_rng_val_scope.
_validate_note_check_sngl(
EXPORTING
is_note_check = lr_prep_check->*
iv_note_index = sy-tabix
it_note_validity = ms_file-note_validity
).
ENDLOOP.

mo_msg->end_node( mo_msg->gc_node_prep_check ).

ENDMETHOD. "_validate_prep_notes
*#scope
METHOD _check_scope.

DATA:
lr_scope_check TYPE REF TO gty_str_scope_check,
lr_scope_def TYPE REF TO gty_str_scope_def.

rv_ok = abap_true.

IF ms_file-scope_def IS INITIAL AND ms_file-scope_check IS INITIAL.


RETURN.
ENDIF.

mo_msg->start_node(
iv_node = mo_msg->gc_node_scope_check
iv_description = '500'
).

IF iv_filter_scope IS NOT INITIAL.


mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = iv_filter_scope
iv_object = iv_filter_scope
iv_action = mo_msg->gc_action_none
iv_msg_text = '502'
).
ENDIF.

* Check if XML contains an uninstall scope


LOOP AT ms_file-scope_def REFERENCE INTO lr_scope_def
WHERE scope_id CS 'UNINSTALL'.
EXIT.
ENDLOOP.
IF sy-subrc = 0.
lcl_utilities=>gv_uninstall = abap_true.
ENDIF.

* Check if required scopes are loaded


IF lcl_utilities=>is_fast( ) = abap_false.
LOOP AT ms_file-scope_def REFERENCE INTO lr_scope_def.
IF lr_scope_def->doku_ref IS NOT INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lr_scope_def->scope_id
iv_object = lr_scope_def->scope_id
iv_action = mo_msg->gc_action_web_link
iv_msg_text = '501'
iv_msg_v1 = lr_scope_def->description
iv_msg_v2 = lr_scope_def->solution
iv_target_note = lr_scope_def->doku_ref
).
ELSE.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lr_scope_def->scope_id
iv_object = lr_scope_def->scope_id
iv_action = mo_msg->gc_action_none
iv_msg_text = '501'
iv_msg_v1 = lr_scope_def->description
iv_msg_v2 = lr_scope_def->solution
).
ENDIF.
ENDLOOP.
ENDIF.

LOOP AT ms_file-scope_check REFERENCE INTO lr_scope_check.

READ TABLE ms_file-scope_def TRANSPORTING NO FIELDS


WITH KEY scope_id = lr_scope_check->scope_id_used.

IF sy-subrc <> 0.
mo_msg->add_msg_direct(
EXPORTING
iv_msg_type = lr_scope_check->severity
iv_scope_id = lr_scope_check->scope_id_uses
iv_object = lr_scope_check->scope_id_used
iv_action = mo_msg->gc_action_load_file
iv_msg_text = lr_scope_check->message
).
IF lr_scope_check->severity = lcl_msg=>gc_error.
rv_ok = abap_false.
ENDIF.
ENDIF.

ENDLOOP.

mo_msg->end_node( mo_msg->gc_node_scope_check ).

ENDMETHOD. "_check_scope
METHOD _validate_scope.

DATA:
lr_scope_check TYPE REF TO gty_str_scope_check,
ls_rng_val_scope TYPE LINE OF gty_tab_rng_scope_id.

mo_msg->start_node(
iv_node = mo_msg->gc_node_scope_check
iv_description = '500'
).

LOOP AT it_rng_val_scope INTO ls_rng_val_scope.


mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = 'XML_VAL'
iv_object = ls_rng_val_scope-low
iv_action = lcl_msg=>gc_action_none
iv_msg_text = '812'
).
ENDLOOP.

LOOP AT ms_file-scope_check REFERENCE INTO lr_scope_check


WHERE scope_id_used IN it_rng_val_scope.

IF lr_scope_check->message IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_scope_check->scope_id_uses
iv_object = lr_scope_check->scope_id_uses
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '801'
iv_msg_v1 = lr_scope_check->message
).
CONTINUE.
ENDIF.

IF lr_scope_check->severity IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_scope_check->scope_id_uses
iv_object = lr_scope_check->scope_id_uses
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '801'
iv_msg_v1 = lr_scope_check->severity
).
CONTINUE.
ENDIF.

_validate_scope_id(
EXPORTING
iv_scope_id = lr_scope_check->scope_id_uses
iv_object = lr_scope_check->scope_id_uses
).

_validate_scope_id(
EXPORTING
iv_scope_id = lr_scope_check->scope_id_used
iv_object = lr_scope_check->scope_id_used
).

ENDLOOP.

mo_msg->end_node( mo_msg->gc_node_scope_check ).

ENDMETHOD. "_validate_scope

METHOD _validate_scope_id.

IF iv_scope_id IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = iv_scope_id
iv_object = iv_object
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '801'
iv_msg_v1 = iv_scope_id
).
ENDIF.

READ TABLE ms_file-scope_def TRANSPORTING NO FIELDS


WITH KEY scope_id = iv_scope_id.
IF sy-subrc <> 0.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = iv_scope_id
iv_object = iv_object
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '805'
iv_msg_v1 = iv_scope_id
).
ENDIF.

ENDMETHOD. "_validate_scope_id
*#param
METHOD _check_param.

DATA:
lr_param_check TYPE REF TO gty_str_param_check,
lt_par_sub TYPE STANDARD TABLE OF spfparlist,
lt_par_usub TYPE STANDARD TABLE OF spfparlist,
lr_par TYPE REF TO spfparlist,
lv_value TYPE pfepvalue.

IF ms_file-param_check IS INITIAL.
RETURN.
ENDIF.

mo_msg->start_node(
iv_node = mo_msg->gc_node_param_check
iv_description = '400'
).

SORT ms_file-param_check BY scope_id param_name.


LOOP AT ms_file-param_check REFERENCE INTO lr_param_check.

IF lt_par_sub IS INITIAL.
CALL FUNCTION 'RZL_GET_PROFILE_PAR'
TABLES
par_sub = lt_par_sub
par_usub = lt_par_usub.

SORT lt_par_sub BY parname.


ENDIF.

READ TABLE lt_par_sub REFERENCE INTO lr_par


WITH KEY parname = lr_param_check->param_name
BINARY SEARCH.

IF sy-subrc <> 0.
mo_msg->add_msg_direct(
EXPORTING
iv_msg_type = lr_param_check->severity
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_none
iv_msg_text = lr_param_check->message
).
CONTINUE.
ENDIF.

CHECK lr_param_check->flg_chk_only = abap_false.

* Check instance parameter, if instance parameter has no value take default


parameter
IF lr_par->parvalu IS NOT INITIAL.
lv_value = lr_par->parvalu.
ELSEIF lr_par->parvald IS NOT INITIAL.
lv_value = lr_par->parvald.
ELSE.
CLEAR lv_value.
ENDIF.

mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_none
iv_msg_text = '411'
iv_msg_v1 = lv_value
).

CASE lr_param_check->option.
WHEN 'EQ'.
CHECK lv_value EQ lr_param_check->value.
WHEN 'NE'.
CHECK lv_value NE lr_param_check->value.
WHEN 'LT'.
CHECK lv_value LT lr_param_check->value.
WHEN 'LE'.
CHECK lv_value LE lr_param_check->value.
WHEN 'GE'.
CHECK lv_value GE lr_param_check->value.
WHEN 'GT'.
CHECK lv_value GT lr_param_check->value.
WHEN 'CP'.
CHECK lv_value CP lr_param_check->value.
WHEN 'NP'.
CHECK lv_value NP lr_param_check->value.
WHEN OTHERS.
mo_msg->add_msg(
EXPORTING
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_msg_sap
iv_msg_text = '410'
iv_msg_v1 = lr_param_check->option
).
ENDCASE.

* If we reach this line the check failed


mo_msg->add_msg_direct(
EXPORTING
iv_msg_type = lr_param_check->severity
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = lr_param_check->message
).

ENDLOOP.

mo_msg->end_node( mo_msg->gc_node_param_check ).

ENDMETHOD. "_check_param

METHOD _validate_param.

DATA:
lr_param_check TYPE REF TO gty_str_param_check,
lt_par_sub TYPE STANDARD TABLE OF spfparlist,
lt_par_usub TYPE STANDARD TABLE OF spfparlist.

mo_msg->start_node(
iv_node = mo_msg->gc_node_param_check
iv_description = '400'
).

SORT ms_file-param_check BY scope_id param_name.

LOOP AT ms_file-param_check REFERENCE INTO lr_param_check


WHERE scope_id IN it_rng_val_scope.

_validate_scope_id(
EXPORTING
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
).

IF lr_param_check->param_name IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'PARAM_NAME'
).
CONTINUE.
ENDIF.

IF lr_param_check->message IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'MESSAGE'
).
ENDIF.

IF lr_param_check->severity IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'SEVERITY'
).
ENDIF.

IF lr_param_check->flg_chk_only = abap_false
AND lr_param_check->option IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'OPTION'
).
ENDIF.

IF lr_param_check->flg_chk_only = abap_false
AND lr_param_check->value IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'VALUE'
).
ENDIF.

IF lt_par_sub IS INITIAL.
CALL FUNCTION 'RZL_GET_PROFILE_PAR'
TABLES
par_sub = lt_par_sub
par_usub = lt_par_usub.

SORT lt_par_sub BY parname.


ENDIF.

READ TABLE lt_par_sub TRANSPORTING NO FIELDS


WITH KEY parname = lr_param_check->param_name
BINARY SEARCH.

IF sy-subrc <> 0.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = lr_param_check->scope_id
iv_object = lr_param_check->param_name
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '807'
iv_msg_v1 = lr_param_check->param_name
).
ENDIF.

ENDLOOP.

mo_msg->end_node( mo_msg->gc_node_param_check ).

ENDMETHOD. "_validate_param
*#comp
METHOD _check_components.

DATA:
lr_comp_check TYPE REF TO gty_str_comp_check,
lr_cvers TYPE REF TO cvers,
lv_flg_comp_found TYPE abap_bool,
lv_flg_rel_found TYPE abap_bool,
ls_kernel_release TYPE gty_str_release_patch,
ls_spam_release TYPE gty_str_release_patch,
ls_dbinfo TYPE dbrelinfo,
ls_hana_release TYPE gty_str_release_patch.

* Current strategy is not to abort processing in case of a mismatch


rv_ok = abap_true.

IF ms_file-comp_check IS INITIAL.
RETURN.
ENDIF.

mo_msg->start_node(
iv_node = mo_msg->gc_node_comp_check
iv_description = '100'
).

_load_cvers( ).
LOOP AT ms_file-comp_check REFERENCE INTO lr_comp_check.
CLEAR: lv_flg_rel_found, lv_flg_comp_found.

READ TABLE mt_cvers REFERENCE INTO lr_cvers


WITH TABLE KEY component = lr_comp_check->swcomponent.
IF sy-subrc = 0.
lv_flg_comp_found = _compare_release(
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
iv_act_release = lr_cvers->release
iv_chk_release = lr_comp_check->release
iv_option = lr_comp_check->rel_option
).
IF lv_flg_comp_found = abap_true.
lv_flg_rel_found = _compare_sp_level(
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
iv_act_level = lr_cvers->extrelease
iv_min_level = lr_comp_check->splevel
).
ELSE.
CONTINUE.
ENDIF.
ELSEIF lr_comp_check->swcomponent = gc_sw_comp_kernel.
* Kernel release is not stored in cvers
ls_kernel_release = lcl_utilities=>get_kernel_release( ).

lv_flg_comp_found = _compare_release(
iv_scope_id = lr_comp_check->scope_id
iv_object = gc_sw_comp_kernel
iv_act_release = ls_kernel_release-release
iv_chk_release = lr_comp_check->release
iv_option = lr_comp_check->rel_option
).
IF lv_flg_comp_found = abap_true.
lv_flg_rel_found = _compare_sp_level(
iv_scope_id = lr_comp_check->scope_id
iv_object = gc_sw_comp_kernel
iv_act_level = ls_kernel_release-patch
iv_min_level = lr_comp_check->splevel
).
ELSE.
CONTINUE.
ENDIF.
ELSEIF lr_comp_check->swcomponent = gc_sw_comp_spam.
* SPAM release is not stored in cvers
ls_spam_release = lcl_utilities=>get_spam_release( ).

lv_flg_comp_found = _compare_release(
iv_scope_id = lr_comp_check->scope_id
iv_object = gc_sw_comp_spam
iv_act_release = ls_spam_release-release
iv_chk_release = lr_comp_check->release
iv_option = lr_comp_check->rel_option
).
IF lv_flg_comp_found = abap_true.
lv_flg_rel_found = _compare_sp_level(
iv_scope_id = lr_comp_check->scope_id
iv_object = gc_sw_comp_spam
iv_act_level = ls_spam_release-version
iv_min_level = lr_comp_check->splevel
).
ELSE.
CONTINUE.
ENDIF.
ELSEIF lr_comp_check->swcomponent = gc_sw_comp_hana.
* HANA release is not stored in cvers
lcl_utilities=>get_db_release(
IMPORTING
es_dbinfo = ls_dbinfo
es_hana_release = ls_hana_release
).
CHECK ls_dbinfo-dbsys = 'HDB'. "Mapping version to sp level valid only for
HANA

lv_flg_comp_found = _compare_release(
iv_scope_id = lr_comp_check->scope_id
iv_object = gc_sw_comp_hana
iv_act_release = ls_hana_release-release
iv_chk_release = lr_comp_check->release
iv_option = lr_comp_check->rel_option
).
IF lv_flg_comp_found = abap_true .
lv_flg_rel_found = _compare_sp_level(
iv_scope_id = lr_comp_check->scope_id
iv_object = gc_sw_comp_hana
iv_act_level = ls_hana_release-version
iv_min_level = lr_comp_check->splevel
).
ELSE.
CONTINUE.
ENDIF.
ELSEIF lr_comp_check->release = '000'.
* Component not installed but there's a check entry for it
lv_flg_rel_found = abap_false.
ELSE.
CONTINUE.
ENDIF.

IF lv_flg_rel_found = abap_false.
mo_msg->add_msg_direct(
EXPORTING
iv_msg_type = lr_comp_check->severity
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
iv_action = mo_msg->gc_action_none
iv_msg_text = lr_comp_check->message
).
* Cancel check for severe issues
IF lr_comp_check->severity = lcl_msg=>gc_abort.
rv_ok = abap_false.
ENDIF.
ELSE.
IF lcl_utilities=>is_fast( ) = abap_false.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
iv_action = mo_msg->gc_action_none
iv_msg_text = '503'
).
ENDIF.
ENDIF.

ENDLOOP.

mo_msg->end_node( mo_msg->gc_node_comp_check ).

ENDMETHOD. "_check_components

METHOD _validate_components.

DATA:
lr_comp_check TYPE REF TO gty_str_comp_check.

mo_msg->start_node(
iv_node = mo_msg->gc_node_comp_check
iv_description = '100'
).

SORT ms_file-comp_check BY scope_id swcomponent.

LOOP AT ms_file-comp_check REFERENCE INTO lr_comp_check


WHERE scope_id IN it_rng_val_scope.

_validate_scope_id(
EXPORTING
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
).

IF lr_comp_check->swcomponent IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'SWCOMPONENT'
).
ENDIF.

IF lr_comp_check->release IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'RELEASE'
).
ENDIF.
IF lr_comp_check->splevel IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'SPLEVEL'
).
ENDIF.

IF lr_comp_check->severity IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'SEVERITY'
).
ENDIF.

IF lr_comp_check->message IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = lr_comp_check->scope_id
iv_object = lr_comp_check->swcomponent
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'MESSAGE'
).
ENDIF.

ENDLOOP.

mo_msg->end_node( mo_msg->gc_node_comp_check ).

ENDMETHOD. "_validate_components

METHOD _check_notes.

CONSTANTS:
lc_add_note_text TYPE c LENGTH 13 VALUE 'Prerequisite:'.

DATA:
lr_note_check TYPE REF TO gty_str_note_check,
ls_note_validity TYPE gty_str_note_validity,
lt_add_notes TYPE gty_tab_add_notes_found,
lt_max_sp_level TYPE gty_tab_sp_level,
lr_max_sp_level TYPE REF TO gty_str_sp_level,
lv_add_note_text TYPE string,
lv_max_index TYPE syindex,
lv_flg_not_possible TYPE abap_bool.

IF iv_node = mo_msg->gc_node_prep_check AND ms_file-prep_note_check IS INITIAL.


RETURN.
ELSEIF iv_node = mo_msg->gc_node_note_check AND ms_file-note_check IS INITIAL.
RETURN.
ENDIF.

mo_msg->start_node(
iv_node = iv_node
iv_description = iv_description
).

* Determine validity of all notes


mt_note_validity = ms_file-note_validity.

IF iv_flg_resolve = abap_true.
_resolve_not_implemented_notes(
IMPORTING
et_add_notes = lt_add_notes
ev_flg_not_possible = lv_flg_not_possible
CHANGING
ct_note_check = ct_note_check
ct_note_validity = mt_note_validity
).
IF lv_flg_not_possible = abap_true.
RETURN.
ENDIF.
ELSEIF iv_flg_download = abap_true.
_load_not_downloaded_notes(
EXPORTING
it_note_check = ct_note_check
it_note_validity = mt_note_validity
).
ENDIF.

_restrict_validity(
EXPORTING
it_note_check = ct_note_check
CHANGING
ct_note_validity = mt_note_validity
).

* Determine maximum support package level for all notes


_calculate_max_sp_level(
EXPORTING
it_note_validity = mt_note_validity
IMPORTING
et_max_sp_level = lt_max_sp_level
).

* Add log messages for needed SP instead of notes


IF lt_max_sp_level IS NOT INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_success
iv_scope_id = space
iv_object = space
iv_action = lcl_msg=>gc_action_none
iv_msg_text = '324'
).

LOOP AT lt_max_sp_level REFERENCE INTO lr_max_sp_level.


mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_success
iv_scope_id = space
iv_object = space
iv_action = lcl_msg=>gc_action_none
iv_msg_text = '325'
iv_msg_v1 = lr_max_sp_level->swcomponent
iv_msg_v2 = lr_max_sp_level->release
iv_msg_v3 = lr_max_sp_level->splevel
).
ENDLOOP.
ENDIF.

* Check all notes individually


lv_max_index = lines( ct_note_check ).

LOOP AT ct_note_check REFERENCE INTO lr_note_check.

_show_progress(
EXPORTING
iv_index = sy-tabix
iv_max = lv_max_index
iv_note_number = lr_note_check->number
).

* Is it one of the additional notes found in resolving => Add a remark


READ TABLE lt_add_notes TRANSPORTING NO FIELDS
WITH TABLE KEY number = lr_note_check->number.
IF sy-subrc = 0.
lv_add_note_text = lc_add_note_text.
ELSE.
CLEAR lv_add_note_text.
ENDIF.

* Get SP information from restricted table


_get_note_validity(
EXPORTING
is_note_check = lr_note_check->*
IMPORTING
es_note_validity = ls_note_validity
).

IF ls_note_validity IS INITIAL.
_add_note_comment_special(
EXPORTING
is_note_check = lr_note_check->*
).
CONTINUE.
ENDIF.

* Check note
_check_note_single(
EXPORTING
is_note_check = lr_note_check->*
is_note_validity = ls_note_validity
iv_add_note_text = lv_add_note_text
).
ENDLOOP.

mo_msg->end_node( iv_node ).

ENDMETHOD. "_check_notes

METHOD _check_note.

DATA:
ls_note_validity TYPE gty_str_note_validity,
lt_note_check TYPE gty_tab_note_check.

* Determine validity again for notes of correct node


IF iv_again = abap_true.
mt_note_validity = ms_file-note_validity.

IF iv_node = mo_msg->gc_node_prep_check.
lt_note_check = ms_file-prep_note_check.
ELSE.
lt_note_check = ms_file-note_check.
ENDIF.

_restrict_validity(
EXPORTING
it_note_check = lt_note_check
CHANGING
ct_note_validity = mt_note_validity
).
ENDIF.

* Get SP information from restricted table


_get_note_validity(
EXPORTING
is_note_check = is_note_check
IMPORTING
es_note_validity = ls_note_validity
).

IF ls_note_validity IS INITIAL.
_add_note_comment_special(
EXPORTING
is_note_check = is_note_check
).
RETURN.
ENDIF.

* Check note
_check_note_single(
EXPORTING
iv_again = iv_again
is_note_check = is_note_check
is_note_validity = ls_note_validity
).

ENDMETHOD. "_check_note

METHOD _read_inactive_objects.

CONSTANTS:
c_dwinactiv TYPE tabname VALUE 'DWINACTIV',
c_dwinactiv_a TYPE tabname VALUE 'DWINACTIV_A'.

TYPES:
BEGIN OF ty_str_inactive,
mod_name TYPE smodilog-mod_name,
objtype TYPE trobjtype,
objname TYPE trobj_name,
END OF ty_str_inactive.

DATA:
lv_subrc TYPE sy-subrc,
lv_from TYPE string,
ls_note_inactive TYPE tn_s_note_inactive,
ls_modname TYPE ty_str_inactive,
lt_modname TYPE TABLE OF ty_str_inactive.

CLEAR nt_note_inactive.

CALL FUNCTION 'DB_EXISTS_TABLE'


EXPORTING
tabname = c_dwinactiv_a
IMPORTING
subrc = lv_subrc.
IF lv_subrc = 0.
CONCATENATE c_dwinactiv_a 'AS d LEFT OUTER JOIN smodilog AS s'
'ON d~objtype_tr = s~sub_type AND d~objname_tr = s~sub_name'
INTO lv_from SEPARATED BY space.
SELECT DISTINCT s~mod_name d~objtype_tr d~objname_tr
INTO TABLE lt_modname FROM (lv_from).
ELSE.
CONCATENATE c_dwinactiv 'AS d LEFT OUTER JOIN smodilog AS s'
'ON d~object = s~sub_type AND d~obj_name = s~sub_name'
INTO lv_from SEPARATED BY space.
SELECT DISTINCT s~mod_name d~object d~obj_name
INTO TABLE lt_modname FROM (lv_from).
ENDIF.

LOOP AT lt_modname INTO ls_modname WHERE mod_name <> ''.


CLEAR ls_note_inactive.
ls_note_inactive-numm = ls_modname-mod_name(10).
ls_note_inactive-versno = ls_modname-mod_name+10(4).
ls_note_inactive-objtype = ls_modname-objtype.
ls_note_inactive-objname = ls_modname-objname.
COLLECT ls_note_inactive INTO nt_note_inactive.
ENDLOOP.

ENDMETHOD. "_read_inactive_objects

METHOD _check_summary.

mo_msg->start_node(
iv_node = mo_msg->gc_node_summary
iv_description = '711'
).

* Overall status will be updated when ALV is prepared

mo_msg->end_node( mo_msg->gc_node_summary ).
ENDMETHOD. "_check_summary

METHOD _get_note_validity.

DATA:
lt_validity_tmp TYPE gty_tab_note_validity.

CLEAR es_note_validity.

READ TABLE mt_note_validity INTO es_note_validity


WITH TABLE KEY number = is_note_check-number.
IF sy-subrc <> 0.
READ TABLE ms_file-note_validity TRANSPORTING NO FIELDS
WITH TABLE KEY number = is_note_check-number.
IF sy-subrc = 0.
IF lcl_utilities=>is_fast( ) = abap_false.
* Note validity in content maintained but not valid for this system
mo_msg->add_msg(
EXPORTING
iv_action = lcl_msg=>gc_action_none
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_msg_text = '328'
iv_msg_v1 = is_note_check-version
iv_msg_v2 = is_note_check-description
iv_target_note = is_note_check-number
iv_impl_status = space
).
* Do not try to access the note as it will never be downloaded
RETURN.
ENDIF.
ELSE.
_get_note_detail(
EXPORTING
is_note_check = is_note_check
IMPORTING
et_note_validity = lt_validity_tmp
).

_restrict_validity(
CHANGING
ct_note_validity = lt_validity_tmp
).

READ TABLE lt_validity_tmp INTO es_note_validity


WITH TABLE KEY number = is_note_check-number.
IF sy-subrc <> 0.
* Note is not valid for this release
CLEAR es_note_validity.
ENDIF.
ENDIF.
ENDIF.

ENDMETHOD. "_get_note_validity
*#check
METHOD _check_note_single.
DATA:
lv_implemented TYPE sysubrc,
lv_status TYPE cwbprstat,
lv_version_impl TYPE cwbntvers,
lv_version_requ TYPE cwbntvers,
ls_note_details TYPE gty_str_note_details,
lv_action TYPE lcl_msg=>gty_action,
lv_pre_impl TYPE abap_bool,
lv_post_impl TYPE abap_bool,
lv_msg_type TYPE sy-msgty,
lv_msg_text TYPE lcl_msg=>gty_text_id,
lv_msg_v1 TYPE string,
lv_msg_v2 TYPE string,
lv_msg_v3 TYPE string,
lv_msg_v4 TYPE string.

IF lcl_utilities=>is_debug( is_note_check-number ) = abap_true.


BREAK-POINT. "#EC NOBREAK
ENDIF.

IF _check_note_condition( is_note_check ) = abap_false.


RETURN.
ENDIF.

_check_note_is_implemented(
EXPORTING
iv_again = iv_again
is_note_check = is_note_check
IMPORTING
ev_is_implemented = lv_implemented
ev_status = lv_status
ev_versno = lv_version_impl
).

_get_note_detail(
EXPORTING
is_note_check = is_note_check
IMPORTING
es_note_check = ls_note_details
).

* Determine which version should be implemented


lv_version_requ = is_note_check-version. "XML
IF lv_version_requ < ls_note_details-version. "SNOTE
lv_version_requ = ls_note_details-version.
ENDIF.

* Adjust status based on required version of note


IF lv_implemented BETWEEN gc_implemented_obsolete AND gc_implemented_old_vers
AND lv_version_impl < lv_version_requ.
lv_implemented = gc_implemented_old_vers.
ENDIF.

* Add message about note status


lv_pre_impl = gc_unknown.
lv_post_impl = gc_unknown.

CASE lv_implemented.
WHEN gc_implemented_deimplement. " -2 - deimplement
lv_action = lcl_msg=>gc_action_note_reset.

* &v3& SAP Note obsolete and must be deimplemented: &object& (&v1&) "&v2&"
lv_msg_type = lcl_msg=>gc_error.
lv_msg_text = '335'.
lv_msg_v1 = lv_version_impl.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = iv_add_note_text.

WHEN gc_implemented_obsolete. " -1 - obsolete

lv_action = lcl_msg=>gc_action_none.

* &v3& SAP Note obsolete: &object& (&v1&) "&v2&"


lv_msg_text = '333'.
lv_msg_v1 = lv_version_impl.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = iv_add_note_text.

WHEN gc_implemented_completely. " 0 - implemented

lv_action = lcl_msg=>gc_action_none.

lv_pre_impl = gc_display.
lv_post_impl = gc_display.

* &v3& SAP Note implemented in this system: &object& (&v1&) "&v2&"


lv_msg_type = lcl_msg=>gc_info.
lv_msg_text = '322'.
lv_msg_v1 = lv_version_impl.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = iv_add_note_text.

WHEN gc_implemented_inactive. " 1 - implemented but inactive objects

lv_action = lcl_msg=>gc_action_note_inactive.

lv_pre_impl = abap_true.
lv_post_impl = abap_true.

* &v3& SAP Note implemented but inactive objects exist: &object& (&v1&)
"&v2&"
lv_msg_type = lcl_msg=>gc_warning.
lv_msg_text = '331'.
lv_msg_v1 = lv_version_impl.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = iv_add_note_text.

WHEN gc_implemented_not_valid. " 2 - no valid correction instructions

* Check if validity is given


IF ls_note_details-flg_corr_instr_exist = abap_true AND is_note_validity IS
INITIAL.
lv_action = lcl_msg=>gc_action_none.

* SAP Note not relevant for this system: &object& (&v1&) "&v2&"
lv_msg_type = lcl_msg=>gc_info.
lv_msg_text = '328'.
lv_msg_v1 = lv_version_impl.
lv_msg_v2 = is_note_check-description.
ELSE.
* Check if note is confirmed by user
IF ls_note_details-note_status = gc_note_status_finished.
lv_action = lcl_msg=>gc_action_none.

lv_msg_type = lcl_msg=>gc_info.
ELSE.
lv_action = lcl_msg=>gc_action_read_note.

lv_pre_impl = abap_true.
lv_post_impl = abap_true.

lv_msg_type = lcl_msg=>gc_warning.
ENDIF.

* SAP Note has no valid correction instruction for this system: &object&
(&v1&) "&v2&"
lv_msg_text = '329'.
lv_msg_v1 = lv_version_impl.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = ls_note_details-version.
ENDIF.

WHEN gc_implemented_incomplete. " 4 - incompletely implemented

IF ls_note_details-flg_manual_activities = abap_true.
lv_action = lcl_msg=>gc_action_man_impl.
ELSEIF ls_note_details-flg_corr_instr_exist = abap_true.
lv_action = lcl_msg=>gc_action_auto_impl.
ELSE.
lv_action = lcl_msg=>gc_action_sp_impl.
ENDIF.

lv_pre_impl = abap_true.
lv_post_impl = abap_true.

* &v3& SAP Note inconsistent in this system: &object& (&v1&) "&v2&"


lv_msg_type = lcl_msg=>gc_warning.
lv_msg_text = '327'.
lv_msg_v1 = lv_version_impl.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = iv_add_note_text.

WHEN gc_implemented_old_vers. " 5 - old version implemented

IF ls_note_details-version < is_note_check-version.


lv_action = lcl_msg=>gc_action_download_note.
ELSE.
IF ls_note_details-flg_manual_activities = abap_true.
lv_action = lcl_msg=>gc_action_man_impl.
ELSEIF ls_note_details-flg_corr_instr_exist = abap_true.
lv_action = lcl_msg=>gc_action_auto_impl.
ELSE.
lv_action = lcl_msg=>gc_action_sp_impl.
ENDIF.

lv_pre_impl = abap_true.
lv_post_impl = abap_true.
ENDIF.

* &v4& SAP Note implemented in version &v3& instead of &v1&: &object& "&v2&"
lv_msg_type = lcl_msg=>gc_warning.
lv_msg_text = '326'.
lv_msg_v1 = lv_version_requ.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = lv_version_impl.
lv_msg_v4 = iv_add_note_text.

WHEN gc_implemented_outdated. " 6 - outdated version implemented

lv_action = lcl_msg=>gc_action_download_note.

* &v3& SAP Note is outdated and needs to be downloaded again: &object& (&v1&)
"&v2&"
lv_msg_type = lcl_msg=>gc_warning.
lv_msg_text = '336'.
lv_msg_v1 = lv_version_requ.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = iv_add_note_text.

WHEN gc_implemented_not_yet. " 7 - can be implemented

IF ls_note_details-flg_manual_activities = abap_true.
lv_action = lcl_msg=>gc_action_man_impl.
ELSEIF ls_note_details-flg_corr_instr_exist = abap_true.
lv_action = lcl_msg=>gc_action_auto_impl.
ELSE.
lv_action = lcl_msg=>gc_action_sp_impl.
ENDIF.

lv_pre_impl = abap_true.
lv_post_impl = abap_true.

* &v3& SAP Note needs to be implemented: &object& (&v1&) "&v2&"


lv_msg_type = lcl_msg=>gc_error.
lv_msg_text = '320'.
lv_msg_v1 = lv_version_requ.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = iv_add_note_text.

WHEN gc_implemented_error. " 8 - consistency error

lv_action = lcl_msg=>gc_action_download_note.

* &v3& SAP Note data is inconsistent and needs to be downloaded again:


&object& (&v1&) "&v2&"
lv_msg_type = lcl_msg=>gc_error.
lv_msg_text = '332'.
lv_msg_v1 = lv_version_requ.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = iv_add_note_text.

WHEN OTHERS. "12 - something else... let's download again...

lv_action = lcl_msg=>gc_action_download_note.
* &v3& SAP Note needs to be downloaded and implemented: &object& (&v1&)
"&v2&"
lv_msg_type = lcl_msg=>gc_error.
lv_msg_text = '334'.
lv_msg_v1 = lv_version_requ.
lv_msg_v2 = is_note_check-description.
lv_msg_v3 = iv_add_note_text.

ENDCASE.

* Any comments before message?


IF lv_pre_impl <> gc_unknown.
_add_note_comment(
EXPORTING
is_note_check = is_note_check
iv_pre_impl = lv_pre_impl
).
ENDIF.

IF lcl_utilities=>is_fast( iv_msg_type = lv_msg_type iv_action = lv_action ) =


abap_false.
* Add message
mo_msg->add_msg(
EXPORTING
iv_msg_type = lv_msg_type
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = lv_action
iv_msg_text = lv_msg_text
iv_msg_v1 = lv_msg_v1
iv_msg_v2 = lv_msg_v2
iv_msg_v3 = lv_msg_v3
iv_msg_v4 = lv_msg_v4
iv_target_note = is_note_check-number
iv_impl_status = lv_status
iv_swcomponent = is_note_validity-swcomponent
iv_release = is_note_validity-release
iv_splevel = is_note_validity-splevel
).
ENDIF.

* Any additional comments after message?


IF lv_post_impl <> gc_unknown.
_add_note_comment(
EXPORTING
is_note_check = is_note_check
iv_post_impl = lv_post_impl
).
ENDIF.

ENDMETHOD. "_check_note_single

METHOD _validate_notes.

DATA:
lr_note_check TYPE REF TO gty_str_note_check,
lv_flg_not_possible TYPE abap_bool,
lv_index TYPE syindex,
lv_max_index TYPE syindex.
mo_msg->start_node(
iv_node = mo_msg->gc_node_note_check
iv_description = '300'
).

lv_max_index = lines( ms_file-note_check ).

LOOP AT ms_file-note_check REFERENCE INTO lr_note_check


WHERE scope_id IN it_rng_val_scope.
lv_index = sy-tabix.

_show_progress(
iv_index = lv_index
iv_max = lv_max_index
iv_note_number = lr_note_check->number
).

_validate_note_check_sngl(
EXPORTING
is_note_check = lr_note_check->*
iv_note_index = sy-tabix
it_note_validity = ms_file-note_validity
IMPORTING
ev_flg_not_possible = lv_flg_not_possible
).

IF lv_flg_not_possible = abap_true.
EXIT.
ENDIF.

_validate_note_comment(
EXPORTING
is_note_check = lr_note_check->*
it_note_comment = ms_file-note_comment
).

ENDLOOP.

mo_msg->end_node( mo_msg->gc_node_note_check ).

ENDMETHOD. "_validate_notes

METHOD _check_note_condition.

DATA:
ls_comment TYPE gty_str_note_comment,
lv_result TYPE c LENGTH 30.

rv_result = abap_true.

LOOP AT ms_file-note_comment INTO ls_comment


WHERE number = is_note_check-number AND purpose =
lcl_alv=>gc_purpose_condition.

* Evaluate condition. Result will be "TRUE" or "FALSE"


CALL FUNCTION 'EVAL_FORMULA'
EXPORTING
formula = ls_comment-message
program = sy-repid
routine = c_callback_eval
IMPORTING
value = lv_result
EXCEPTIONS
division_by_zero = 1
exp_error = 2
formula_table_not_valid = 3
invalid_expression = 4
invalid_value = 5
log_error = 6
parameter_error = 7
sqrt_error = 8
units_not_valid = 9
missing_parameter = 10
OTHERS = 11.
IF sy-subrc = 0.
IF lv_result = 'TRUE'.
rv_result = abap_true.
ELSE.
rv_result = abap_false.
EXIT.
ENDIF.
ELSE.
MESSAGE a666(01) WITH 'Invalid condition.' 'Contact SAP Support'.
ENDIF.

ENDLOOP.

ENDMETHOD. "_check_note_condition

METHOD _resolve_not_implemented_notes.

DATA:
lr_note_check TYPE REF TO gty_str_note_check,
lv_implemented TYPE sysubrc,
lt_additional_notes TYPE gty_tab_note_details,
lt_additional_validity TYPE gty_tab_note_validity,
lr_notes TYPE REF TO gty_str_note_details,
ls_note_check TYPE gty_str_note_check,
lt_note_check_tmp TYPE gty_tab_note_check,
lt_note_check_add TYPE gty_tab_note_check,
lt_note_check_resolve TYPE gty_tab_note_check,
lv_index TYPE syindex,
lv_max_index TYPE syindex.

CLEAR et_add_notes.

* We intend to add notes to this table in the loop


lt_note_check_tmp = ct_note_check.
lv_max_index = lines( ct_note_check ).

LOOP AT ct_note_check REFERENCE INTO lr_note_check.


lv_index = sy-tabix.
CLEAR: lt_additional_notes, lt_additional_validity, lt_note_check_add,
lt_note_check_resolve.

_show_progress(
iv_index = lv_index
iv_max = lv_max_index
iv_note_number = lr_note_check->number
).

_check_note_is_implemented(
EXPORTING
is_note_check = lr_note_check->*
IMPORTING
ev_is_implemented = lv_implemented
).

CHECK lv_implemented <> gc_implemented_completely.

APPEND lr_note_check->* TO lt_note_check_resolve.

_resolve_notes(
EXPORTING
it_note_check = lt_note_check_resolve
IMPORTING
et_additional_notes = lt_additional_notes
et_additional_validity = lt_additional_validity
ev_flg_not_possible = ev_flg_not_possible
).
IF ev_flg_not_possible = abap_true.
RETURN.
ENDIF.

_restrict_validity(
CHANGING
ct_note_validity = lt_additional_validity
).
INSERT LINES OF lt_additional_validity INTO TABLE ct_note_validity.

* The prerequisite notes


LOOP AT lt_additional_notes REFERENCE INTO lr_notes.
MOVE-CORRESPONDING lr_notes->* TO ls_note_check.
ls_note_check-scope_id = lr_note_check->scope_id.
* Additional notes gotten from resolving a note which are not yet part of our
file
* As these are prerequisite notes we add them before the current one.
* in note validity table sequence doesn't matter
APPEND ls_note_check TO lt_note_check_add.

INSERT lr_notes->* INTO TABLE et_add_notes.


ENDLOOP.
INSERT LINES OF lt_note_check_add INTO lt_note_check_tmp INDEX lv_index.

ENDLOOP.

ct_note_check = lt_note_check_tmp.

ENDMETHOD. "_resolve_not_implemented_notes

METHOD _load_not_downloaded_notes.

DATA:
lr_note_check TYPE REF TO gty_str_note_check,
lv_download_needed TYPE abap_bool,
lv_downloaded TYPE abap_bool,
lv_max_index TYPE syindex,
lt_note_load TYPE gty_tab_note_check.

LOOP AT it_note_check REFERENCE INTO lr_note_check.


CLEAR: lt_note_load.

_show_progress(
iv_index = sy-index
iv_max = lv_max_index
iv_note_number = lr_note_check->number
).

lv_download_needed = _check_note_by_validity(
is_note_check = lr_note_check->*
it_note_validity = it_note_validity
iv_flg_silent = abap_true
).
CHECK lv_download_needed = abap_true.

lv_downloaded = _check_note_is_downloaded( is_note_check = lr_note_check-


>* ).
CHECK lv_downloaded = abap_false.

APPEND lr_note_check->* TO lt_note_load.


_load_notes( it_notes_load = lt_note_load ).
ENDLOOP.

ENDMETHOD. "_load_not_downloaded_notes

METHOD _load_notes.

DATA:
lr_notes_load TYPE REF TO gty_str_note_check,
ls_note_keys_lg TYPE cwbntkeylg,
lt_note_keys_lg TYPE bcwbn_note_keys_lg.

LOOP AT it_notes_load REFERENCE INTO lr_notes_load.


ls_note_keys_lg-numm = lr_notes_load->number.
ls_note_keys_lg-langu = sy-langu.
APPEND ls_note_keys_lg TO lt_note_keys_lg.
ENDLOOP.

CALL FUNCTION 'SCWN_NOTES_DOWNLOAD'


EXPORTING
it_note_keys_lg = lt_note_keys_lg
iv_classify_notes = abap_true
EXCEPTIONS
error = 1
rfc_error = 2.
IF sy-subrc <> 0.
mo_msg->add_t100_msg(
EXPORTING
iv_scope_id = lr_notes_load->scope_id
iv_object = lr_notes_load->number
iv_action = lcl_msg=>gc_action_none
).
ELSE.
COMMIT WORK.
ENDIF.
ENDMETHOD. "_load_notes

METHOD _calculate_max_sp_level.

DATA:
lr_note_validity TYPE REF TO gty_str_note_validity,
ls_max_sp_level TYPE gty_str_sp_level,
lr_max_sp_level TYPE REF TO gty_str_sp_level,
lt_validity_tmp TYPE gty_tab_note_validity,
lv_flg_gt TYPE abap_bool.

CLEAR et_max_sp_level.

* Calculate max sp level of notes


lt_validity_tmp = it_note_validity.

_restrict_validity(
CHANGING
ct_note_validity = lt_validity_tmp
).

LOOP AT lt_validity_tmp REFERENCE INTO lr_note_validity.


* Ignore notes not shipped in SP (yet)
CHECK lr_note_validity->splevel < 99.
* Calculate max sp level
READ TABLE et_max_sp_level REFERENCE INTO lr_max_sp_level
WITH TABLE KEY swcomponent = lr_note_validity->swcomponent
release = lr_note_validity->release.
IF sy-subrc = 0.
lv_flg_gt = _compare_sp_level(
iv_scope_id = space
iv_object = lr_note_validity->number
iv_act_level = lr_note_validity->splevel
iv_min_level = lr_max_sp_level->splevel
iv_flg_gt_only = abap_true
).
IF lv_flg_gt = abap_true.
lr_max_sp_level->splevel = lr_note_validity->splevel.
ENDIF.
ELSE.
MOVE-CORRESPONDING lr_note_validity->* TO ls_max_sp_level.
INSERT ls_max_sp_level INTO TABLE et_max_sp_level.
ENDIF.
ENDLOOP.

ENDMETHOD. "_calculate_max_sp_level

METHOD _resolve_notes.

DATA:
ls_note_check TYPE gty_str_note_check,
lt_notes TYPE scwb_api_t_notenumber,
lr_notes TYPE REF TO cwbntkeyvs,
ls_notes TYPE cwbntkeyvs,
lt_required_notes TYPE scwb_api_t_notenumber,
lv_rfc_error TYPE bcwbn_bool,
lt_note_validity TYPE gty_tab_note_validity,
ls_note_details TYPE gty_str_note_details.
CLEAR: et_additional_notes, et_additional_validity.

LOOP AT it_note_check INTO ls_note_check.


ls_notes-numm = ls_note_check-number.
ls_notes-versno = ls_note_check-version.
INSERT ls_notes INTO TABLE lt_notes.
ENDLOOP.

TRY.
CALL FUNCTION 'SCWB_NOTES_RESOLVE_NECESSARY'
EXPORTING
it_notes = lt_notes
IMPORTING
et_required_notes = lt_required_notes
ev_rfc_error = lv_rfc_error
EXCEPTIONS
error = 1.

IF sy-subrc <> 0 OR lv_rfc_error = abap_true.


mo_msg->add_t100_msg(
iv_scope_id = ls_note_check-scope_id
iv_object = ls_note_check-number
iv_action = mo_msg->gc_action_none
).
RETURN.
ENDIF.

CATCH cx_sy_dyn_call_illegal_func.
mo_msg->add_msg(
iv_scope_id = ls_note_check-scope_id
iv_object = ls_note_check-number
iv_action = mo_msg->gc_action_none
iv_msg_text = '330'
).
ev_flg_not_possible = abap_true.
RETURN.
ENDTRY.

LOOP AT lt_required_notes REFERENCE INTO lr_notes.

READ TABLE ms_file-note_check TRANSPORTING NO FIELDS


WITH KEY number = lr_notes->numm.
IF sy-subrc = 0.
* Note will be checked according to defined sequence
CONTINUE.
ENDIF.
* New note not part of the file
CLEAR: ls_note_check, lt_note_validity.
ls_note_check-number = lr_notes->numm.
ls_note_check-version = lr_notes->versno.

_get_note_detail(
EXPORTING
is_note_check = ls_note_check
IMPORTING
es_note_check = ls_note_details
et_note_validity = lt_note_validity
).
APPEND ls_note_details TO et_additional_notes.
APPEND LINES OF lt_note_validity TO et_additional_validity.

ENDLOOP.

ENDMETHOD. "_resolve_notes

METHOD _check_note_by_validity.

DATA:
lr_note_validity TYPE REF TO gty_str_note_validity,
lr_cvers TYPE REF TO cvers,
lv_component_found TYPE abap_bool,
lv_release_found TYPE abap_bool,
lv_sp_found TYPE abap_bool.

_load_cvers( ).

LOOP AT it_note_validity REFERENCE INTO lr_note_validity


WHERE number = is_note_check-number.

READ TABLE mt_cvers REFERENCE INTO lr_cvers


WITH TABLE KEY component = lr_note_validity->swcomponent.
IF sy-subrc = 0.
lv_component_found = abap_true.
ELSE.
CONTINUE.
ENDIF.

IF lr_cvers->release = lr_note_validity->release.
lv_release_found = abap_true.

lv_sp_found = _compare_sp_level(
iv_scope_id = is_note_check-scope_id
iv_object = lr_note_validity->number
iv_act_level = lr_cvers->extrelease
iv_min_level = lr_note_validity->splevel
).
IF lv_sp_found = abap_true.
EXIT.
ENDIF.
ENDIF.

ENDLOOP.
IF sy-subrc <> 0.
* No validity maintained => Need to download the note
rv_download_needed = abap_true.
RETURN.
ENDIF.

IF lv_sp_found = abap_true.
IF iv_flg_silent = abap_false.
mo_msg->add_msg(
iv_scope_id = is_note_check-scope_id
iv_msg_type = lcl_msg=>gc_info
iv_object = lr_note_validity->number
iv_action = mo_msg->gc_action_none
iv_msg_text = '311'
iv_msg_v1 = is_note_check-version
iv_msg_v2 = is_note_check-description
).
ENDIF.
rv_download_needed = abap_false.
ELSEIF lv_release_found = abap_true.
* Release validity defined and present in this system, but sp won't match
rv_download_needed = abap_true.
ELSEIF lv_component_found = abap_true.
* Found component but not release: Note is not relevannt
rv_download_needed = abap_false.
ELSE.
* Component not found: Strange as we don't expect this note to be tested on
this system
* But still the note is not relevant without matching component
rv_download_needed = abap_false.
ENDIF.

ENDMETHOD. "_check_note_by_validity

METHOD _load_cvers.

DATA:
lr_cvers TYPE REF TO cvers,
lv_ocs_release TYPE saprelease,
lv_ocs_level TYPE num4,
lv_funcname TYPE funcname VALUE 'OCS_GET_COMPONENT_STATE'.

IF mt_cvers IS INITIAL.
SELECT * FROM cvers INTO CORRESPONDING FIELDS OF TABLE mt_cvers.

TRY.
LOOP AT mt_cvers REFERENCE INTO lr_cvers.
CALL FUNCTION lv_funcname
EXPORTING
iv_component = lr_cvers->component
IMPORTING
ev_comp_rel = lv_ocs_release
ev_comp_level = lv_ocs_level
EXCEPTIONS
unknown_component = 1.
IF sy-subrc <> 0.
CONTINUE.
ELSE.
lr_cvers->release = lv_ocs_release.
lr_cvers->extrelease = lv_ocs_level.
ENDIF.

IF lr_cvers->component = 'SAP_BW' OR lr_cvers->component = 'DW4CORE'.


mv_release = lr_cvers->release.
ENDIF.
ENDLOOP.
CATCH cx_sy_dyn_call_illegal_func cx_sy_dyn_call_illegal_type
cx_sy_dyn_call_param_missing cx_sy_dyn_call_param_not_found. "#EC
NO_HANDLER
* Do nothing, func comes with SPAM update
ENDTRY.
ENDIF.
ENDMETHOD. "_load_cvers

METHOD _validate_note_check_sngl.

DATA:
lt_note_validity TYPE gty_tab_note_validity,
lt_additional_validity TYPE gty_tab_note_validity,
lr_note_validity TYPE REF TO gty_str_note_validity,
lr_new_validity TYPE REF TO gty_str_note_validity,
ls_delta_validity TYPE gty_str_note_validity,
ls_delta_check TYPE gty_str_note_check,
lt_note_resolve TYPE gty_tab_note_check,
lt_additional_notes TYPE gty_tab_note_details,
lr_additional_notes TYPE REF TO gty_str_note_details,
ls_note_details TYPE gty_str_note_details,
lv_flg_add_note_once TYPE abap_bool,
lv_flg_sp_found TYPE abap_bool,
lv_add_note_index TYPE sytabix,
lv_msgv2 TYPE n LENGTH 3,
lv_msgv3 TYPE n LENGTH 3.

_validate_scope_id(
EXPORTING
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
).

IF is_note_check-number IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_msg_sap
iv_msg_text = '800'
iv_msg_v1 = 'NUMBER'
).
ENDIF.

IF is_note_check-version IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_msg_sap
iv_msg_text = '800'
iv_msg_v1 = 'VERSION'
).
ENDIF.

IF is_note_check-description IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_msg_sap
iv_msg_text = '800'
iv_msg_v1 = 'DESCRIPTION'
).
ENDIF.

READ TABLE ms_file-note_validity REFERENCE INTO lr_note_validity


WITH TABLE KEY number = is_note_check-number.

IF sy-subrc <> 0 AND is_note_check-number <> '0001932459'.


mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_msg_sap
iv_msg_text = '802'
).
ENDIF.

* Now check notes against the current version in CSS


APPEND is_note_check TO lt_note_resolve.

_resolve_notes(
EXPORTING
it_note_check = lt_note_resolve
IMPORTING
et_additional_notes = lt_additional_notes
et_additional_validity = lt_additional_validity
ev_flg_not_possible = ev_flg_not_possible
).
IF ev_flg_not_possible = abap_true.
RETURN.
ENDIF.

* Call this after download


_get_note_detail(
EXPORTING
is_note_check = is_note_check
iv_flg_warn_val = abap_true
IMPORTING
es_note_check = ls_note_details
et_note_validity = lt_note_validity
).

* First check the current note


IF ls_note_details-version <> is_note_check-version.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_delta_file
iv_msg_text = '801'
iv_msg_v1 = is_note_check-version
iv_msg_v2 = ls_note_details-version
iv_target_note = is_note_check-number
).
lv_flg_add_note_once = abap_true.
ENDIF.

IF ls_note_details-description <> is_note_check-description.


mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_delta_file
iv_msg_text = '811'
iv_msg_v1 = is_note_check-description
iv_msg_v2 = ls_note_details-description
iv_target_note = is_note_check-number
).
lv_flg_add_note_once = abap_true.
ENDIF.

* Then check current validity


LOOP AT lt_note_validity REFERENCE INTO lr_new_validity
WHERE swcomponent NS 'VIRTUAL' AND swcomponent <> 'HIDDEN' AND swcomponent <>
'S4CORE'.

CLEAR lv_flg_sp_found.
LOOP AT it_note_validity REFERENCE INTO lr_note_validity
WHERE number = lr_new_validity->number.
CHECK lr_note_validity->swcomponent = lr_new_validity->swcomponent.
CHECK lr_note_validity->release = lr_new_validity->release.
CHECK lr_note_validity->splevel = lr_new_validity->splevel.
lv_flg_sp_found = abap_true.
ENDLOOP.

IF lv_flg_sp_found = abap_false.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_delta_file
iv_msg_text = '803'
iv_msg_v1 = lr_new_validity->swcomponent
iv_msg_v2 = lr_new_validity->release
iv_msg_v3 = lr_new_validity->splevel
).

ls_delta_validity-number = lr_new_validity->number.
ls_delta_validity-swcomponent = lr_new_validity->swcomponent.
ls_delta_validity-release = lr_new_validity->release.
ls_delta_validity-splevel = lr_new_validity->splevel.
INSERT ls_delta_validity INTO TABLE ms_delta_file-note_validity.

lv_flg_add_note_once = abap_true.
ENDIF.

ENDLOOP.

IF lv_flg_add_note_once = abap_true.
ls_delta_check-scope_id = is_note_check-scope_id.
ls_delta_check-number = ls_note_details-number.
ls_delta_check-description = ls_note_details-description.
ls_delta_check-version = ls_note_details-version.
INSERT ls_delta_check INTO TABLE ms_delta_file-note_check.
ENDIF.
* Then check if the prerequisite notes are part of the list
LOOP AT lt_additional_notes REFERENCE INTO lr_additional_notes.
READ TABLE ms_file-note_check TRANSPORTING NO FIELDS
WITH KEY number = lr_additional_notes->number.
IF sy-subrc <> 0.
* Note not in the list at all
READ TABLE ms_delta_file-note_check TRANSPORTING NO FIELDS
WITH KEY number = lr_additional_notes->number.
CHECK sy-subrc <> 0.

mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_delta_file
iv_msg_text = '321'
iv_msg_v1 = lr_additional_notes->number
iv_msg_v2 = lr_additional_notes->version
iv_msg_v3 = lr_additional_notes->description
).

ls_delta_check-scope_id = lr_additional_notes->scope_id.
ls_delta_check-number = lr_additional_notes->number.
ls_delta_check-description = lr_additional_notes->description.
ls_delta_check-version = lr_additional_notes->version.
INSERT ls_delta_check INTO TABLE ms_delta_file-note_check.

* Add the validity in addition


LOOP AT lt_additional_validity REFERENCE INTO lr_new_validity
WHERE number = lr_additional_notes->number.

ls_delta_validity-number = lr_new_validity->number.
ls_delta_validity-swcomponent = lr_new_validity->swcomponent.
ls_delta_validity-release = lr_new_validity->release.
ls_delta_validity-splevel = lr_new_validity->splevel.
INSERT ls_delta_validity INTO TABLE ms_delta_file-note_validity.
ENDLOOP.
ELSE.
* Note in the list, but in the correct position?
lv_add_note_index = sy-tabix.

IF lv_add_note_index > iv_note_index.


* i.e. the prerequisite note is in the list later than the current one
lv_msgv2 = iv_note_index.
lv_msgv3 = lv_add_note_index.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_check_usage
iv_msg_text = '810'
iv_msg_v1 = lr_additional_notes->number
iv_msg_v2 = lv_msgv2
iv_msg_v3 = lv_msgv3
).
ENDIF.
ENDIF.
ENDLOOP.

ENDMETHOD. "_validate_note_check_sngl

METHOD _get_note_detail.

DATA:
ls_note TYPE bcwbn_note,
lr_corr_instruction TYPE REF TO bcwbn_corr_instruction,
lt_validity_txt TYPE cwb_validity_txt,
lt_validity_tmp TYPE cwb_validity_txt,
lr_validity_txt TYPE REF TO scwb_s_screen_validity_txt,
lt_patch TYPE STANDARD TABLE OF string,
lr_patch TYPE REF TO string,
lv_index_patch TYPE i,
ls_note_validity TYPE gty_str_note_validity,
lv_patchlevel TYPE gty_splevel_n,
lv_max_level TYPE gty_splevel_n,
lv_flg_failed TYPE abap_bool.

CLEAR: es_note_check, et_note_validity.

ls_note-key-numm = is_note_check-number.
* Do not add version, so we read the latest version

CALL FUNCTION 'SCWB_NOTE_READ'


EXPORTING
iv_read_short_text = abap_true
iv_read_corr_instructions = abap_true
iv_read_customer_attributes = abap_true
CHANGING
cs_note = ls_note
EXCEPTIONS
note_not_found = 1
language_not_found = 2
unreadable_text_format = 3
corr_instruction_not_found = 4
OTHERS = 5.

CASE sy-subrc.
WHEN 0.
* Fine
es_note_check-flg_note_found = abap_true.
es_note_check-number = ls_note-key-numm.
es_note_check-version = ls_note-key-versno.
es_note_check-description = ls_note-stext.
es_note_check-note_status = ls_note-customer_attributes-ntstatus.
IF ls_note-corr_instructions IS NOT INITIAL.
es_note_check-flg_corr_instr_exist = abap_true.
ENDIF.

WHEN 1.
* Not found
es_note_check-flg_note_found = abap_false.
RETURN.

WHEN 2.
* Wrong language but otherwise ok
mo_msg->add_t100_msg(
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_none
).

es_note_check-flg_note_found = abap_true.
es_note_check-number = ls_note-key-numm.
es_note_check-version = ls_note-key-versno.
CLEAR es_note_check-description.
IF ls_note-corr_instructions IS NOT INITIAL.
es_note_check-flg_corr_instr_exist = abap_true.
ENDIF.

WHEN OTHERS.
mo_msg->add_t100_msg(
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_none
).
RETURN.
ENDCASE.

LOOP AT ls_note-corr_instructions REFERENCE INTO lr_corr_instruction.


CLEAR lt_validity_tmp.

CALL FUNCTION 'SCWB_CINST_READ'


EXPORTING
iv_read_header = abap_true
iv_read_validity = abap_true
CHANGING
cs_corr_instruction = lr_corr_instruction->*
EXCEPTIONS
corr_instruction_not_found = 1
deltas_unreadable = 2
unknown_delta_format = 3.
IF sy-subrc <> 0.
mo_msg->add_t100_msg(
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_none
).
CONTINUE.
ENDIF.

IF lr_corr_instruction->manual_activity = abap_true.
es_note_check-flg_manual_activities = abap_true.
ENDIF.

IF et_note_validity IS REQUESTED.
CALL FUNCTION 'SCWB_CINST_VALIDITY_TEXT'
EXPORTING
it_validity = lr_corr_instruction->validity
IMPORTING
et_validity_txt = lt_validity_tmp
EXCEPTIONS
not_found = 1.
IF sy-subrc <> 0.
mo_msg->add_t100_msg(
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = mo_msg->gc_action_none
).
CONTINUE.
ENDIF.
APPEND LINES OF lt_validity_tmp TO lt_validity_txt.
ENDIF.

ENDLOOP.

IF et_note_validity IS REQUESTED.
SORT lt_validity_txt BY paktxt aletxt.

LOOP AT lt_validity_txt REFERENCE INTO lr_validity_txt


WHERE paktxt NS 'VIRTUAL'.

IF lr_validity_txt->validity CS 'All Support Package Levels' OR


lr_validity_txt->validity CS 'Alle Support Package Stände' OR
lr_validity_txt->validity CS 'From' OR
lr_validity_txt->validity CS 'Von' OR
lr_validity_txt->validity CS 'unbekannt' OR
lr_validity_txt->validity CS 'Unknown'. "#EC STRING_OK
lv_patchlevel = 99.
ELSEIF lr_validity_txt->validity CS 'No Support Packages' OR
lr_validity_txt->validity CS 'w/o Support Packages' OR
lr_validity_txt->validity CS 'Ohne Support Packages'.
lv_patchlevel = 1.
ELSE.
SPLIT lr_validity_txt->validity AT ' ' INTO TABLE lt_patch.

lv_index_patch = lines( lt_patch ).

READ TABLE lt_patch REFERENCE INTO lr_patch INDEX lv_index_patch.


CHECK sy-subrc = 0.

_derive_patchlevel(
EXPORTING
iv_sp_text = lr_patch->*
IMPORTING
ev_patchlevel = lv_patchlevel
ev_flg_failed = lv_flg_failed
).
ENDIF.
IF lv_max_level < lv_patchlevel.
lv_max_level = lv_patchlevel.
ENDIF.

AT END OF aletxt. "#EC *

IF lv_flg_failed = abap_true AND iv_flg_warn_val = abap_true.


mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = lcl_msg=>gc_action_none
iv_msg_text = '323'
iv_msg_v1 = lr_validity_txt->paktxt
iv_msg_v2 = lr_validity_txt->aletxt
iv_msg_v3 = lr_validity_txt->validity
).
ENDIF.

ls_note_validity-number = es_note_check-number.
ls_note_validity-swcomponent = lr_validity_txt->paktxt.
ls_note_validity-release = lr_validity_txt->aletxt.
ls_note_validity-splevel = lv_max_level.
SHIFT ls_note_validity-splevel LEFT DELETING LEADING '0'.

INSERT ls_note_validity INTO TABLE et_note_validity.

CLEAR: ls_note_validity, lv_patchlevel, lv_max_level.


ENDAT.

ENDLOOP.

ENDIF.

IF p_val = abap_true.
DATA lr_note_comment TYPE REF TO gty_str_note_comment. "#EC NEEDED

IF es_note_check-flg_manual_activities = abap_true.
LOOP AT ms_file-note_comment REFERENCE INTO lr_note_comment
WHERE number = is_note_check-number.
ENDLOOP.
IF sy-subrc <> 0.
* Check if there's a comment about RSUDO reports
FIND 'UDO' IN TABLE ls_note-text RESPECTING CASE.
IF sy-subrc <> 0.
FIND 'ZNOTE' IN TABLE ls_note-text RESPECTING CASE.
IF sy-subrc <> 0.
FIND 'Z_NOTE' IN TABLE ls_note-text RESPECTING CASE.
ENDIF.
ENDIF.
IF sy-subrc = 0.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = lcl_msg=>gc_action_none
iv_msg_text = '813'
).
ELSE.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_warning
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = lcl_msg=>gc_action_none
iv_msg_text = '814'
).
ENDIF.
ENDIF.
ENDIF.
ENDIF.

ENDMETHOD. "_get_note_detail
*#implemented
METHOD _check_note_is_implemented.

DATA:
lv_subrc TYPE sysubrc,
ls_note TYPE bcwbn_note,
lv_status TYPE patchstat,
lv_count_imp TYPE i,
lv_count_deimp TYPE i,
ls_ocspatntci TYPE ocspatntci,
lt_to_be_implemented TYPE bcwbn_corr_instructions,
lt_to_be_deimplemented TYPE bcwbn_corr_instructions,
lt_already_implemented TYPE bcwbn_corr_instructions.

FIELD-SYMBOLS:
<ls_corr> TYPE bcwbn_corr_instruction.

ev_status = gc_prstat_initial.
ev_is_implemented = gc_implemented_unknown.
ev_versno = '0000'.

ls_note-key-numm = is_note_check-number.

IF iv_again = abap_true.
_read_inactive_objects( ).
ENDIF.

TRY.
CALL FUNCTION 'SCWB_NOTE_IMPL_STATUS'
EXPORTING
iv_update_note = iv_again
iv_silent_mode = abap_true
is_note = ls_note
IMPORTING
ev_status = ev_status
et_to_be_implemented = lt_to_be_implemented
et_to_be_deimplemented = lt_to_be_deimplemented
et_already_implemented = lt_already_implemented
EXCEPTIONS
note_not_found = 1
inconsistent_delivery_data = 2
undefined_component_state = 3
incomplete_note_data = 4
OTHERS = 9.
lv_subrc = sy-subrc.
CATCH cx_sy_dyn_call_parameter_error.
* Parameter iv_silent_mode is not available in some releases
CALL FUNCTION 'SCWB_NOTE_IMPL_STATUS'
EXPORTING
iv_update_note = iv_again
is_note = ls_note
IMPORTING
ev_status = ev_status
et_to_be_implemented = lt_to_be_implemented
et_to_be_deimplemented = lt_to_be_deimplemented
EXCEPTIONS
note_not_found = 1
inconsistent_delivery_data = 2
undefined_component_state = 3
incomplete_note_data = 4
OTHERS = 9.
lv_subrc = sy-subrc.
ENDTRY.

* What version is implemented?


READ TABLE lt_already_implemented ASSIGNING <ls_corr> INDEX 1.
IF sy-subrc = 0.
ev_versno = <ls_corr>-note_key-versno.
ELSE.
CALL FUNCTION 'SCWB_NOTE_READ'
EXPORTING
iv_read_attributes = abap_true
iv_read_sap_status = abap_true
CHANGING
cs_note = ls_note
EXCEPTIONS
note_not_found = 1
language_not_found = 2
unreadable_text_format = 3
corr_instruction_not_found = 4
OTHERS = 5.
IF sy-subrc = 0.
ev_versno = ls_note-key-versno.
ENDIF.
ENDIF.

IF lv_subrc = 0.
* SAP Note found
CASE ev_status.
WHEN gc_prstat_obsolete.
* Already shipped in release or support package
ev_is_implemented = gc_implemented_obsolete.
WHEN gc_prstat_implemented.
* Implemented, but we check for outdates notes
READ TABLE mt_changed_notes TRANSPORTING NO FIELDS
WITH KEY numm = ls_note-key-numm.
IF sy-subrc = 0.
ev_is_implemented = gc_implemented_outdated.
ELSE.
* Implemented, but we check of inactive objects
READ TABLE nt_note_inactive TRANSPORTING NO FIELDS
WITH KEY numm = ls_note-key-numm.
IF sy-subrc = 0.
ev_is_implemented = gc_implemented_inactive.
ELSE.
ev_is_implemented = gc_implemented_completely.
ENDIF.
ENDIF.
WHEN gc_prstat_no_valid_cinst.
* No correction instructions
ev_is_implemented = gc_implemented_not_valid.
WHEN gc_prstat_not_implemented.
* Can be implemented
ev_is_implemented = gc_implemented_not_yet.
WHEN gc_prstat_incompl_impl.
* Implemented incompletely
ev_is_implemented = gc_implemented_incomplete.
WHEN gc_prstat_old_vrs_impl.
* Older version implemented
ev_is_implemented = gc_implemented_old_vers.

DESCRIBE TABLE lt_to_be_implemented LINES lv_count_imp.


DESCRIBE TABLE lt_to_be_deimplemented LINES lv_count_deimp.
IF ( lv_count_deimp > 0 AND lv_count_imp = 0 ).
ev_is_implemented = gc_implemented_deimplement.
ELSE.
READ TABLE lt_to_be_deimplemented ASSIGNING <ls_corr> INDEX 1.
IF sy-subrc = 0.
ev_versno = <ls_corr>-note_key-versno.

IF <ls_corr>-filled-related_note = abap_false.
CALL FUNCTION 'SCWB_CINST_READ'
EXPORTING
iv_read_related_note = abap_true
CHANGING
cs_corr_instruction = <ls_corr>
EXCEPTIONS
corr_instruction_not_found = 1
deltas_unreadable = 2
unknown_delta_format = 3
OTHERS = 4.
IF sy-subrc = 0.
ev_versno = <ls_corr>-note_key-versno.
ENDIF.
ENDIF.
ELSEIF ev_versno < ls_note-key-versno.
ev_versno = ls_note-key-versno.
ENDIF.
ENDIF.
WHEN OTHERS.
* Something is wrong
ev_is_implemented = gc_implemented_error.
ENDCASE.
ELSEIF lv_subrc = 1.
* SAP Note not found... Check if Note is part of TCI
SELECT SINGLE * INTO ls_ocspatntci FROM ocspatntci
WHERE numm = ls_note-key-numm. "#EC *
IF sy-subrc = 0.
* Get status of TCI package
SELECT SINGLE status INTO lv_status FROM pat03
WHERE patch = ls_ocspatntci-patch.
IF sy-subrc = 0 AND lv_status = 'I'.
ev_status = gc_prstat_implemented.
ev_is_implemented = gc_implemented_completely.
ENDIF.
ENDIF.
ELSE.
IF lv_subrc BETWEEN 2 AND 4.
ev_is_implemented = gc_implemented_error.
ENDIF.

* Other cases
IF iv_flg_silent = abap_false.
mo_msg->add_t100_msg(
EXPORTING
iv_scope_id = is_note_check-scope_id
iv_object = is_note_check-number
iv_action = lcl_msg=>gc_action_none
).
ENDIF.
ENDIF.

ENDMETHOD. "_check_note_is_implemented

METHOD _check_note_is_downloaded.

DATA:
ls_note TYPE bcwbn_note,
ls_note_details TYPE gty_str_note_details.

ls_note-key-numm = is_note_check-number.

CALL FUNCTION 'SCWB_NOTE_READ'


EXPORTING
iv_read_short_text = abap_true
CHANGING
cs_note = ls_note
EXCEPTIONS
note_not_found = 1
language_not_found = 9
unreadable_text_format = 9
corr_instruction_not_found = 9.

IF sy-subrc = 0 AND ls_note-incomplete = abap_false.


_get_note_detail(
EXPORTING
is_note_check = is_note_check
IMPORTING
es_note_check = ls_note_details
).

IF ls_note_details-version < is_note_check-version.


rv_is_downloaded = abap_false.
ELSE.
rv_is_downloaded = abap_true.
ENDIF.
ELSE.
rv_is_downloaded = abap_false.
ENDIF.

ENDMETHOD. "_check_note_is_downloaded

METHOD _add_note_comment.

DATA:
lr_note_comment TYPE REF TO gty_str_note_comment,
lv_action TYPE lcl_msg=>gty_action,
l_t_bal_log_msg TYPE tn_t_bal_log_msg,
l_release TYPE saprelease,
l_prog TYPE program,
l_function TYPE funcname,
lv_count TYPE c LENGTH 20,
lv_text TYPE string,
l_no_of_exec TYPE i,
l_tci_sar TYPE string,
l_package TYPE patch,
l_status TYPE patchstat,
l_icf_name TYPE icfname,
l_icf_par TYPE icfparguid,
l_icf_text TYPE string,
l_icf_status TYPE abap_bool,
lv_msg_type TYPE symsgty,
lv_object TYPE lcl_msg=>gty_object,
lv_target TYPE string.

* Process all comments for note


LOOP AT ms_file-note_comment REFERENCE INTO lr_note_comment
WHERE number = is_note_check-number.

CLEAR lv_action.

* Get action and decide if shown before or after message


CASE lr_note_comment->purpose.
WHEN lcl_alv=>gc_purpose_header OR lcl_alv=>gc_purpose_version.
" never show
CONTINUE.
WHEN lcl_alv=>gc_purpose_issue.
" show after
IF iv_post_impl = abap_true.
lv_action = lcl_msg=>gc_action_impl_issue.
ENDIF.
WHEN lcl_alv=>gc_purpose_pcai
OR lcl_alv=>gc_purpose_udo.
" show after
IF iv_post_impl = abap_true.
lv_action = lcl_msg=>gc_action_impl_tool.
ENDIF.
WHEN lcl_alv=>gc_purpose_udo_before.
" show before
IF iv_pre_impl = abap_true OR iv_pre_impl = gc_display.
lv_action = lcl_msg=>gc_action_impl_tool.
ENDIF.
WHEN lcl_alv=>gc_purpose_udo_after.
" show after
IF iv_post_impl = abap_true OR iv_post_impl = gc_display.
lv_action = lcl_msg=>gc_action_impl_tool.
ENDIF.
WHEN lcl_alv=>gc_purpose_tci_down.
" show before
IF iv_pre_impl = abap_true.
lv_action = lcl_msg=>gc_action_tci_download.
ENDIF.
WHEN lcl_alv=>gc_purpose_tci_up.
" show after
IF iv_post_impl = abap_true.
lv_action = lcl_msg=>gc_action_tci_upload.
ENDIF.
WHEN lcl_alv=>gc_purpose_sw_down.
lv_action = lcl_msg=>gc_action_sw_download.
WHEN lcl_alv=>gc_purpose_sw_up.
lv_action = lcl_msg=>gc_action_sw_upload.
WHEN lcl_alv=>gc_purpose_icf.
" show after
IF iv_post_impl = abap_true.
lv_action = lcl_msg=>gc_action_icf_activate.
ENDIF.
WHEN OTHERS.
lv_action = lcl_msg=>gc_action_none.
ENDCASE.

CHECK NOT lv_action IS INITIAL.

* Get note number and message type


lv_object = lcl_utilities=>format( lr_note_comment->number ).
lv_msg_type = lr_note_comment->severity.

* Process special commennts


IF lr_note_comment->purpose = lcl_alv=>gc_purpose_udo_before OR
lr_note_comment->purpose = lcl_alv=>gc_purpose_udo_after.
* === UDO comments ===
lv_target = lr_note_comment->message.

split_udo(
EXPORTING
i_udo_comment = lv_target
IMPORTING
e_udo_report = l_prog
e_no_of_exec = l_no_of_exec
e_release = l_release
).

* Check if UDO is relevant for this release


IF mv_release NP l_release.
CONTINUE.
ENDIF.

lv_text = 'Execute program &1 &2 implementing SAP Note &3'(u01).


REPLACE '&1' WITH l_prog INTO lv_text.
WRITE l_no_of_exec TO lv_count LEFT-JUSTIFIED.
IF lr_note_comment->purpose = lcl_alv=>gc_purpose_udo_before.
IF l_no_of_exec > 1.
CONCATENATE lv_count 'times before'(u02) INTO lv_count SEPARATED BY
space.
ELSE.
lv_count = 'before'(u03).
ENDIF.
ELSEIF lr_note_comment->purpose = lcl_alv=>gc_purpose_udo_after.
IF l_no_of_exec > 1.
CONCATENATE lv_count 'times after'(u04) INTO lv_count SEPARATED BY
space.
ELSE.
lv_count = 'after'(u05).
ENDIF.
ENDIF.
REPLACE '&2' WITH lv_count INTO lv_text.
REPLACE '&3' WITH lv_object INTO lv_text.

IF lcl_utilities=>is_debug( l_prog ) = abap_true.


BREAK-POINT. "#EC NOBREAK
ENDIF.
* Does UDO exist?
SELECT SINGLE name FROM trdir INTO l_prog WHERE name = l_prog.
IF sy-subrc = 0.
* Get UDO logs
l_t_bal_log_msg = get_bal_log(
i_udo_report = l_prog
).

* Evaluate UDO logs


IF lines( l_t_bal_log_msg ) > 0.
lv_msg_type = evaluate_t_bal_msg(
i_t_bal_log_msg = l_t_bal_log_msg
i_no_of_exec = l_no_of_exec
).

IF lv_msg_type = lcl_msg=>gc_info.
IF lcl_utilities=>is_fast( ) = abap_true OR
iv_pre_impl = gc_display OR iv_post_impl = gc_display.
CONTINUE.
ELSE.
lv_action = lcl_msg=>gc_action_none.
ENDIF.
ENDIF.
ENDIF.
ELSEIF l_prog(1) CA 'YZ'.
* Custom UDO -> upload
lv_action = lcl_msg=>gc_action_udo_upload.
ELSE.
* Standard UDO -> nothing since it will be installed with SAP Note
lv_action = lcl_msg=>gc_action_none.
ENDIF.

ELSEIF lr_note_comment->purpose = lcl_alv=>gc_purpose_tci_down


OR lr_note_comment->purpose = lcl_alv=>gc_purpose_tci_up
OR lr_note_comment->purpose = lcl_alv=>gc_purpose_sw_down
OR lr_note_comment->purpose = lcl_alv=>gc_purpose_sw_up.
* === TCI or SW package comments ===
lv_target = lr_note_comment->message.

split_tci(
EXPORTING
i_tci_comment = lv_target
IMPORTING
e_tci_sar = l_tci_sar
e_release = l_release
).

* Check if TCI or SW package is relevant for this release


IF mv_release NP l_release.
CONTINUE.
ENDIF.

IF lcl_utilities=>is_debug( l_tci_sar ) = abap_true.


BREAK-POINT. "#EC NOBREAK
ENDIF.

* Check if TCI is uploaded already


IF sy-saprl >= '730'.
l_package = l_tci_sar.
l_function = 'OCS_API_GET_OCS_PKG_STATUS'.

CALL FUNCTION l_function


EXPORTING
iv_package = l_package
IMPORTING
ev_status = l_status
EXCEPTIONS
package_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
CLEAR l_status.
ENDIF.
ENDIF.

CASE lr_note_comment->purpose.
WHEN lcl_alv=>gc_purpose_tci_down.
CHECK l_status IS INITIAL.
lv_text = 'Download file &1 from SAP Note &2'(u10).
WHEN lcl_alv=>gc_purpose_sw_down.
CHECK l_status IS INITIAL.
lv_text = 'Download file &1 from Software Center'(u11).
WHEN OTHERS.
IF l_status IS INITIAL.
lv_text = 'Upload file &1 to SAP Patch Manager (SPAM)'(u12).
ELSE.
lv_text = 'File &1 already available in SAP Patch Manager
(SPAM)'(u13).
lv_msg_type = lcl_msg=>gc_info.
lv_action = lcl_msg=>gc_action_none.
ENDIF.
ENDCASE.

REPLACE '&1' WITH l_tci_sar INTO lv_text.


REPLACE '&2' WITH lv_object INTO lv_text.

ELSEIF lr_note_comment->purpose = lcl_alv=>gc_purpose_icf.


* === ICF comments ===
lv_target = lr_note_comment->message.

split_icf(
EXPORTING
i_icf_comment = lv_target
IMPORTING
e_icf_name = l_icf_name
e_icf_par = l_icf_par
e_icf_text = l_icf_text
e_release = l_release
).

* Check if ICF is relevant for this release


IF mv_release NP l_release.
CONTINUE.
ENDIF.

lv_text = 'Activate service &1'(u20).


REPLACE '&1' WITH l_icf_text INTO lv_text.

IF lcl_utilities=>is_debug( l_icf_name ) = abap_true.


BREAK-POINT. "#EC NOBREAK
ENDIF.

l_icf_status = check_icf_service(
i_icf_name = l_icf_name
i_icf_par = l_icf_par
).

IF l_icf_status = abap_true.
lv_msg_type = lcl_msg=>gc_info.
lv_action = lcl_msg=>gc_action_none.
ENDIF.

ELSE.
* === Regular comment ===
lv_target = lcl_utilities=>format( lr_note_comment->target_note ).
lv_text = lr_note_comment->message.
ENDIF.

CONDENSE lv_text.

mo_msg->add_msg_direct(
EXPORTING
iv_msg_type = lv_msg_type
iv_scope_id = is_note_check-scope_id
iv_object = lv_object
iv_action = lv_action
iv_msg_text = lv_text
iv_target_note = lv_target
iv_purpose = lr_note_comment->purpose
).

ENDLOOP.

ENDMETHOD. "_add_note_comment

METHOD _add_note_comment_special.

DATA:
lv_show TYPE abap_bool.

* SAP Notes that have software download comments


READ TABLE ms_file-note_comment TRANSPORTING NO FIELDS WITH KEY
number = is_note_check-number
purpose = lcl_alv=>gc_purpose_sw_down.
IF sy-subrc = 0.
lv_show = abap_true.
ENDIF.

* SAP Notes that have no correction instructions


* but we want to show comments anyway
CHECK is_note_check-number = '2415249' AND mv_release CP '75*'
OR is_note_check-number = '2420960' AND mv_release = '740'
OR lv_show = abap_true.

_add_note_comment(
EXPORTING
is_note_check = is_note_check
iv_post_impl = abap_true
).

ENDMETHOD. "_add_note_comment_special

METHOD _validate_note_comment.

DATA:
lr_note_comment TYPE REF TO gty_str_note_comment.

LOOP AT it_note_comment REFERENCE INTO lr_note_comment


WHERE number = is_note_check-number.

IF lr_note_comment->message IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = is_note_check-scope_id
iv_object = lr_note_comment->number
iv_action = lcl_msg=>gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'MESSAGE'
).
ENDIF.

IF lr_note_comment->number IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = is_note_check-scope_id
iv_object = lr_note_comment->number
iv_action = lcl_msg=>gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'NUMBER'
).
ENDIF.

IF lr_note_comment->severity IS INITIAL.
mo_msg->add_msg(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = is_note_check-scope_id
iv_object = lr_note_comment->number
iv_action = lcl_msg=>gc_action_check_usage
iv_msg_text = '800'
iv_msg_v1 = 'SEVERITY'
).
ENDIF.

CASE lr_note_comment->purpose.
WHEN lcl_alv=>gc_purpose_pcai
OR lcl_alv=>gc_purpose_udo
OR lcl_alv=>gc_purpose_issue
OR lcl_alv=>gc_purpose_other
OR lcl_alv=>gc_purpose_udo_before
OR lcl_alv=>gc_purpose_udo_after
OR lcl_alv=>gc_purpose_tci_down
OR lcl_alv=>gc_purpose_tci_up
OR lcl_alv=>gc_purpose_sw_down
OR lcl_alv=>gc_purpose_sw_up
OR lcl_alv=>gc_purpose_icf
OR lcl_alv=>gc_purpose_header
OR lcl_alv=>gc_purpose_version.
* Fine

WHEN OTHERS.
mo_msg->add_msg(
EXPORTING
iv_scope_id = is_note_check-scope_id
iv_object = lr_note_comment->number
iv_action = lcl_msg=>gc_action_check_usage
iv_msg_text = '809'
iv_msg_v1 = lr_note_comment->purpose
).
ENDCASE.

ENDLOOP.

ENDMETHOD. "_validate_note_comment

METHOD _compare_sp_level.

DATA:
lv_sp_level1 TYPE n LENGTH 4,
lv_sp_level2 TYPE n LENGTH 4,
lx_conv_error TYPE REF TO cx_sy_conversion_error,
lv_text TYPE string.

* Unfortunately table CVERS defines the SP level as type c


* but contains values fitting to type n of various length
* so we cannot simply compare 001 and 1
TRY.
lv_sp_level1 = iv_act_level.
lv_sp_level2 = iv_min_level.
CATCH cx_sy_conversion_error INTO lx_conv_error.
lv_text = lx_conv_error->get_text( ).
mo_msg->add_msg_direct(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = iv_scope_id
iv_object = iv_object
iv_action = lcl_msg=>gc_action_msg_sap
iv_msg_text = lv_text
).
ENDTRY.

IF iv_flg_gt_only = abap_false.
IF lv_sp_level1 >= lv_sp_level2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
ELSE.
IF lv_sp_level1 > lv_sp_level2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
ENDIF.
ENDMETHOD. "_compare_sp_level

METHOD _compare_release.

DATA:
lv_release1 TYPE string,
lv_release2 TYPE string,
lx_conv_error TYPE REF TO cx_sy_conversion_error,
lv_text TYPE string.

* Unfortunately table CVERS defines the SP level as type c


* but contains values fitting to type n of various length
* so we cannot simply compare 001 and 1
TRY.
lv_release1 = iv_act_release.
lv_release2 = iv_chk_release.
CATCH cx_sy_conversion_error INTO lx_conv_error.
lv_text = lx_conv_error->get_text( ).
mo_msg->add_msg_direct(
EXPORTING
iv_msg_type = lcl_msg=>gc_error
iv_scope_id = iv_scope_id
iv_object = iv_object
iv_action = lcl_msg=>gc_action_msg_sap
iv_msg_text = lv_text
).
ENDTRY.

CASE iv_option.
WHEN 'EQ'.
IF lv_release1 = lv_release2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
WHEN 'NE'.
IF lv_release1 <> lv_release2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
WHEN 'LT'.
IF lv_release1 < lv_release2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
WHEN 'LE'.
IF lv_release1 <= lv_release2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
WHEN 'GT'.
IF lv_release1 > lv_release2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
WHEN 'GE'.
IF lv_release1 >= lv_release2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
WHEN 'CP'.
IF lv_release1 CP lv_release2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
WHEN 'NP'.
IF lv_release1 NP lv_release2.
rv_ok = abap_true.
ELSE.
rv_ok = abap_false.
ENDIF.
WHEN OTHERS.
mo_msg->add_msg(
iv_scope_id = iv_scope_id
iv_object = iv_object
iv_action = mo_msg->gc_action_msg_sap
iv_msg_text = '410'
iv_msg_v1 = iv_option
).
ENDCASE.

ENDMETHOD. "_compare_release

METHOD _restrict_validity.

DATA:
lr_note_validity TYPE REF TO gty_str_note_validity,
lr_cvers TYPE REF TO cvers,
lv_flg_note_obsolete TYPE abap_bool.

_load_cvers( ).

LOOP AT ct_note_validity REFERENCE INTO lr_note_validity.

IF it_note_check IS SUPPLIED.
READ TABLE it_note_check TRANSPORTING NO FIELDS
WITH KEY number = lr_note_validity->number.
IF sy-subrc <> 0.
DELETE ct_note_validity.
CONTINUE.
ENDIF.
ENDIF.

READ TABLE mt_cvers REFERENCE INTO lr_cvers


WITH TABLE KEY component = lr_note_validity->swcomponent.
IF sy-subrc <> 0.
DELETE ct_note_validity.
CONTINUE.
ENDIF.

IF lr_cvers->release <> lr_note_validity->release.


DELETE ct_note_validity.
CONTINUE.
ENDIF.

lv_flg_note_obsolete = _compare_sp_level(
iv_scope_id = space "Not available here, needed only in case of type
mismatch in comparison
iv_object = lr_note_validity->number
iv_act_level = lr_cvers->extrelease
iv_min_level = lr_note_validity->splevel
).
IF lv_flg_note_obsolete = abap_true.
DELETE ct_note_validity.
CONTINUE.
ENDIF.

ENDLOOP.

ENDMETHOD. "_restrict_validity

METHOD _show_progress.

CONSTANTS:
lc_progress_text TYPE string VALUE 'Checking SAP Note &'.

DATA:
lv_percentage TYPE syindex,
lv_progress_text TYPE string,
lv_number TYPE string.

IF iv_max = 0.
RETURN.
ENDIF.

lv_progress_text = lc_progress_text.
lv_number = lcl_utilities=>format( iv_note_number ).
REPLACE '&' IN lv_progress_text WITH lv_number.
lv_percentage = iv_index * 100 / iv_max.

CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'


EXPORTING
percentage = lv_percentage
text = lv_progress_text.

ENDMETHOD. "_show_progress

METHOD _derive_patchlevel.

* As we derive validity from correction instructions: These mean instruction to


be applied to,
* i.e. with the next patch level there is no need to apply the SP anymore
CONSTANTS:
lc_chars TYPE string VALUE '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.

DATA:
lv_char TYPE c LENGTH 1,
lv_offset TYPE i.

CLEAR ev_flg_failed.
* Older patches are like SAPKB71105 (or SAPKW30B05 or SAPKB46B05)
FIND REGEX '[A-Z]{5}\d{2,3}[A-D]?(\d{2})' IN iv_sp_text SUBMATCHES
ev_patchlevel.
IF sy-subrc = 0.
ADD 1 TO ev_patchlevel.
ELSE.
* Newer patches are like SAPK-75003INSAPBW
FIND REGEX 'SAPK-\d{3}(\d{2})[A-Z]*' IN iv_sp_text SUBMATCHES ev_patchlevel.
IF sy-subrc = 0.
ADD 1 TO ev_patchlevel.
ELSE.
* PI Basis Patches since 701
FIND REGEX '[A-Z]{4}-\d{3}(\d{2})\S+' IN iv_sp_text SUBMATCHES
ev_patchlevel.
IF sy-subrc = 0.
ADD 1 TO ev_patchlevel.
ELSE.
* PI Basis Patches since 2006_1_700
FIND REGEX '[A-Z]{8}(\d{2})' IN iv_sp_text SUBMATCHES ev_patchlevel.
IF sy-subrc = 0.
ADD 1 TO ev_patchlevel.
ELSE.
* PI Basis Patches 2005_1_700
FIND REGEX '[A-Z]{8}\d([A-Z0-9])' IN iv_sp_text SUBMATCHES lv_char.
IF sy-subrc = 0.
* Add 1, i.e. get the successor
FIND FIRST OCCURRENCE OF lv_char IN lc_chars MATCH OFFSET lv_offset.
ADD 1 TO lv_offset.
ev_patchlevel = lv_offset.
ELSE.
* Might be an unknown pattern or simply for all or without support
packages in a different language
* Anyway with patchlevel 1 we err on the safe side
ev_patchlevel = 1.
ev_flg_failed = abap_true.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDIF.

ENDMETHOD. "_derive_patchlevel

ENDCLASS. "lcl_checks IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_msg IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_msg IMPLEMENTATION.

METHOD get_instance.

CREATE OBJECT ro_instance.

ENDMETHOD. "get_instance

METHOD start_node.

mv_current_node = iv_node.
mv_start_node_sequence = add_msg(
iv_msg_type = lcl_msg=>gc_info
iv_scope_id = space
iv_object = space
iv_action = space
iv_msg_text = iv_description
iv_msg_v1 = iv_msg_v1
).

ENDMETHOD. "start_node

METHOD end_node.

DATA:
lv_msg_type TYPE symsgty,
lr_msg TYPE REF TO gty_str_msg.

ASSERT iv_node = mv_current_node.

lv_msg_type = get_status( iv_node = mv_current_node ).

* Insert status at the start of the current node


READ TABLE mt_msg REFERENCE INTO lr_msg
WITH TABLE KEY node = mv_current_node
sequence = mv_start_node_sequence.
ASSERT FIELDS mv_current_node mv_start_node_sequence CONDITION sy-subrc = 0.

lr_msg->msg_type = lv_msg_type.

DATA ls_node TYPE gty_node.


ls_node-node = mv_current_node.
ls_node-start = mv_start_node_sequence.
INSERT ls_node INTO TABLE mt_nodes.

CLEAR: mv_current_node, mv_start_node_sequence.

ENDMETHOD. "end_node

METHOD update_node_status.

DATA:
lr_node TYPE REF TO gty_node,
lv_msg_text TYPE gty_text_id,
lv_msg_type TYPE sy-msgty,
lv_msg_v1 TYPE sy-msgv1,
lv_summary TYPE sy-msgty,
lv_sequence TYPE i,
lr_msg TYPE REF TO gty_str_msg,
lp_msg TYPE bcwbn_msg,
ls_note TYPE bcwbn_note,
ls_header TYPE gty_str_header,
lv_download TYPE n LENGTH 4,
lv_auto_impl TYPE n LENGTH 4,
lv_man_impl TYPE n LENGTH 4.

lv_summary = gc_info.

LOOP AT mt_nodes REFERENCE INTO lr_node.


lv_msg_type = get_status( iv_node = lr_node->node ).

* Update status at the start of the current node


READ TABLE mt_msg REFERENCE INTO lr_msg
WITH TABLE KEY node = lr_node->node
sequence = lr_node->start.
ASSERT FIELDS lr_node->node lr_node->start CONDITION sy-subrc = 0.

IF lr_node->node = gc_node_summary.
lr_msg->msg_type = lv_summary.

IF lv_summary = gc_info.
lv_msg_text = '711'.
ELSE.
lv_msg_text = '712'.
ENDIF.

IF lcl_utilities=>gv_uninstall = abap_true.
lv_msg_v1 = 'Preparation for uninstall'.
ELSE.
lv_msg_v1 = 'Installation'.
ENDIF.

get_msg_text(
EXPORTING
iv_object = gc_scope_summary
iv_msg_text = lv_msg_text
iv_msg_v1 = lv_msg_v1
IMPORTING
ev_text = lr_msg->text
ev_short_id = lr_msg->short_text_id
ev_long_id = lr_msg->long_text_id
).
ELSE.
lr_msg->msg_type = lv_msg_type.

IF lv_msg_type = gc_warning AND lv_summary = gc_info.


lv_summary = gc_warning.
ELSEIF lv_msg_type = gc_error OR lv_msg_type = gc_abort.
lv_summary = gc_error.
ENDIF.
ENDIF.

ENDLOOP.

IF lr_node->node = gc_node_summary.
DELETE mt_msg WHERE node = gc_node_summary AND sequence > lr_node->start.

lv_sequence = lr_node->start + 1.

set_msg( is_msg = lr_msg->* iv_sequence = lv_sequence ).

LOOP AT mt_msg REFERENCE INTO lr_msg.


CASE lr_msg->action.
WHEN gc_action_download_note.
ADD 1 TO lv_download.
WHEN gc_action_auto_impl.
ADD 1 TO lv_auto_impl.
WHEN gc_action_man_impl.
ADD 1 TO lv_man_impl.
ENDCASE.
ENDLOOP.

IF lv_download > 0.
add_msg(
EXPORTING
iv_action = gc_action_none
iv_msg_type = ''
iv_scope_id = ''
iv_object = ''
iv_msg_text = '601'
iv_msg_v1 = lv_download
).
ENDIF.
IF lv_auto_impl > 0.
add_msg(
EXPORTING
iv_action = gc_action_none
iv_msg_type = ''
iv_scope_id = ''
iv_object = ''
iv_msg_text = '602'
iv_msg_v1 = lv_auto_impl
).
ENDIF.
IF lv_man_impl > 0.
add_msg(
EXPORTING
iv_action = gc_action_none
iv_msg_type = ''
iv_scope_id = ''
iv_object = ''
iv_msg_text = '603'
iv_msg_v1 = lv_man_impl
).
ENDIF.

ENDIF.

* Log initial execution and status changes


IF lv_summary <> mv_summary.
LOOP AT mt_header INTO ls_header.
CLEAR ls_note.
ls_note-key-numm = ls_header-number.

CLEAR lp_msg.
lp_msg-msgid = '01'.
lp_msg-msgno = '666'.
lp_msg-msgty = lv_summary.
IF lv_summary = gc_info.
lp_msg-msgv1 = 'Installation completed successfully:'(u40).
ELSE.
lp_msg-msgv1 = 'Installation incomplete:'(u41).
ENDIF.
lp_msg-msgv2 = ls_header-xml_id.
lp_msg-msgv3 = 'Version:'(u42).
lp_msg-msgv4 = ls_header-xml_version.
CALL FUNCTION 'SCWN_LOG_MSG_ADD'
EXPORTING
ip_msg = lp_msg
CHANGING
cs_note = ls_note
EXCEPTIONS
OTHERS = 0.

ENDLOOP.
ENDIF.

mv_summary = lv_summary.

ENDMETHOD. "update_node_status

METHOD get_msg_text.

DATA:
lv_dummy TYPE string.

* Replace variables in text


ev_text = lcl_msg_repository=>get_short_text( iv_msg_text ).

* Improve formatting
REPLACE ALL OCCURRENCES OF '&object&' IN ev_text WITH iv_object.
lv_dummy = lcl_utilities=>format( iv_msg_v1 ).
REPLACE ALL OCCURRENCES OF '&v1&' IN ev_text WITH lv_dummy.
lv_dummy = lcl_utilities=>format( iv_msg_v2 ).
REPLACE ALL OCCURRENCES OF '&v2&' IN ev_text WITH lv_dummy.
lv_dummy = lcl_utilities=>format( iv_msg_v3 ).
REPLACE ALL OCCURRENCES OF '&v3&' IN ev_text WITH lv_dummy.
lv_dummy = lcl_utilities=>format( iv_msg_v4 ).
REPLACE ALL OCCURRENCES OF '&v4&' IN ev_text WITH lv_dummy.

CONDENSE ev_text.
SHIFT ev_text LEFT DELETING LEADING space.

ev_short_id = iv_msg_text.

lv_dummy = lcl_msg_repository=>get_long_text( iv_msg_text ).


IF lv_dummy IS NOT INITIAL.
ev_long_id = iv_msg_text.
ENDIF.

ENDMETHOD. "get_msg_text

METHOD find_msg.

DATA:
lr_msg TYPE REF TO gty_str_msg.

rv_sequence = -1.

LOOP AT mt_msg REFERENCE INTO lr_msg


WHERE node = is_msg-node
AND scope_id = is_msg-scope_id
AND object = is_msg-object.
rv_sequence = lr_msg->sequence.
EXIT.

ENDLOOP.

ENDMETHOD. "find_msg

METHOD delete_msg.

DELETE mt_msg
WHERE node = is_msg-node
AND scope_id = is_msg-scope_id
AND object = is_msg-object.

ENDMETHOD. "delete_msg

METHOD set_msg.

mv_current_node = is_msg-node.
mv_current_scope = is_msg-scope_id.
mv_current_object = is_msg-object.

mv_current_sequence = iv_sequence - 1.

ENDMETHOD. "set_msg

METHOD add_msg.

DATA:
ls_msg TYPE gty_str_msg,
lv_object TYPE string.

lv_object = lcl_utilities=>format( iv_object ).

IF mv_current_scope = iv_scope_id AND mv_current_object = lv_object.


* Same scope and object... baby steps
mv_current_sequence = mv_current_sequence + 1.
ELSE.
* Different scope or object... big steps (round up to next 10)
mv_current_sequence = ( mv_current_sequence + 10 ) DIV 10 * 10.
mv_current_scope = iv_scope_id.
mv_current_object = lv_object.
ENDIF.

ls_msg-node = mv_current_node.
ls_msg-sequence = mv_current_sequence.
ls_msg-scope_id = iv_scope_id.
ls_msg-object = lv_object.
ls_msg-msg_type = iv_msg_type.
ls_msg-action = iv_action.
ls_msg-target_note = lcl_utilities=>format( iv_target_note ).
ls_msg-purpose = iv_purpose.
ls_msg-impl_status = iv_impl_status.
ls_msg-swcomponent = iv_swcomponent.
ls_msg-release = iv_release.
ls_msg-splevel = iv_splevel.

IF iv_text IS SUPPLIED.
ls_msg-text = iv_text.
ELSE.
get_msg_text(
EXPORTING
iv_object = ls_msg-object
iv_msg_text = iv_msg_text
iv_msg_v1 = iv_msg_v1
iv_msg_v2 = iv_msg_v2
iv_msg_v3 = iv_msg_v3
iv_msg_v4 = iv_msg_v4
IMPORTING
ev_text = ls_msg-text
ev_short_id = ls_msg-short_text_id
ev_long_id = ls_msg-long_text_id
).
ENDIF.

rv_sequence = ls_msg-sequence.

INSERT ls_msg INTO TABLE mt_msg.

ENDMETHOD. "add_msg

METHOD add_t100_msg.

DATA:
lv_text TYPE string,
ls_t100_msg TYPE gty_str_symsgty,
lv_action TYPE gty_action,
lv_target TYPE string.

ls_t100_msg-id = sy-msgid.
ls_t100_msg-number = sy-msgno.
ls_t100_msg-type = iv_msg_type.
ls_t100_msg-msgv1 = lcl_utilities=>format( sy-msgv1 ).
ls_t100_msg-msgv2 = lcl_utilities=>format( sy-msgv2 ).
ls_t100_msg-msgv3 = lcl_utilities=>format( sy-msgv3 ).
ls_t100_msg-msgv4 = lcl_utilities=>format( sy-msgv4 ).

READ TABLE mt_stored_t100_msg TRANSPORTING NO FIELDS


WITH TABLE KEY
id = ls_t100_msg-id
number = ls_t100_msg-number
type = ls_t100_msg-type
msgv1 = ls_t100_msg-msgv1
msgv2 = ls_t100_msg-msgv2
msgv3 = ls_t100_msg-msgv3
msgv4 = ls_t100_msg-msgv4.
IF sy-subrc = 0.
* Same message already stored, do not store duplicates
RETURN.
ENDIF.

MESSAGE ID sy-msgid TYPE iv_msg_type NUMBER sy-msgno


WITH ls_t100_msg-msgv1 ls_t100_msg-msgv2
ls_t100_msg-msgv3 ls_t100_msg-msgv4 INTO lv_text.

* Improve certain messages


REPLACE '(version 0000)' IN lv_text WITH ''.
CONDENSE lv_text.
lv_action = iv_action.

IF sy-msgid = 'SCWN' AND ( sy-msgno = '400' OR sy-msgno = '526' ).


CONCATENATE lv_text gc_msg_download INTO lv_text SEPARATED BY space.
lv_action = gc_action_download_note.
lv_target = ls_t100_msg-msgv1.
ENDIF.

* Add message
add_msg_direct(
EXPORTING
iv_scope_id = iv_scope_id
iv_object = iv_object
iv_action = lv_action
iv_msg_type = iv_msg_type
iv_msg_text = lv_text
iv_target_note = lv_target
).

INSERT ls_t100_msg INTO TABLE mt_stored_t100_msg.

ENDMETHOD. "add_t100_msg

METHOD add_msg_direct.

add_msg(
EXPORTING
iv_scope_id = iv_scope_id
iv_object = iv_object
iv_action = iv_action
iv_msg_type = iv_msg_type
iv_text = iv_msg_text
iv_target_note = iv_target_note
iv_purpose = iv_purpose
).

ENDMETHOD. "add_msg_direct

METHOD get_msg.

et_msg = mt_msg.

ENDMETHOD. "get_msg

METHOD get_status.

DATA:
lr_msg TYPE REF TO gty_str_msg,
lv_index TYPE i.

rv_msg_type = lcl_msg=>gc_info.
lv_index = 1.

IF iv_node IS SUPPLIED.

LOOP AT mt_msg REFERENCE INTO lr_msg


WHERE node = iv_node.
IF lv_index > 1.
IF lr_msg->msg_type = lcl_msg=>gc_error OR lr_msg->msg_type =
lcl_msg=>gc_abort.
rv_msg_type = lcl_msg=>gc_error.
EXIT.
ELSEIF lr_msg->msg_type = lcl_msg=>gc_warning.
* Remember: we leave the loop as soon as rv_msg_type got 'E'
* So no further checking on the existing rv_msg_type
rv_msg_type = lcl_msg=>gc_warning.
ENDIF.
ENDIF.
ADD 1 TO lv_index.
ENDLOOP.

ELSE.

LOOP AT mt_msg REFERENCE INTO lr_msg.


IF lv_index > 1.
IF lr_msg->msg_type = lcl_msg=>gc_error OR lr_msg->msg_type =
lcl_msg=>gc_abort.
rv_msg_type = lcl_msg=>gc_error.
EXIT.
ELSEIF lr_msg->msg_type = lcl_msg=>gc_warning.
* Remember: we leave the loop as soon as rv_msg_type got 'E'
* So no further checking on the existing rv_msg_type
rv_msg_type = lcl_msg=>gc_warning.
ENDIF.
ENDIF.
ADD 1 TO lv_index.
ENDLOOP.

ENDIF.

ENDMETHOD. "get_status

ENDCLASS. "lcl_msg IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_batch IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_batch IMPLEMENTATION.

METHOD call_note_analyzer_in_batch.

DATA:
lv_jobcount TYPE tbtcjob-jobcount,
lv_repid TYPE syrepid,
lt_param TYPE gty_tab_param,
lv_msgid TYPE symsgid VALUE 'SCTC_SC'. "To avoid package errors

* This method may only be called in dialog


ASSERT sy-batch IS INITIAL.

CALL FUNCTION 'JOB_OPEN'


EXPORTING
jobname = gc_jobname
IMPORTING
jobcount = lv_jobcount
EXCEPTIONS
cant_create_job = 1
invalid_job_data = 2
jobname_missing = 3.

IF sy-subrc <> 0.
MESSAGE ID lv_msgid TYPE lcl_msg=>gc_error NUMBER '032' WITH gc_jobname sy-
subrc.
RETURN.
ENDIF.

rv_jobcount = lv_jobcount.

lv_repid = sy-repid.

lcl_batch=>_conv_to_param(
EXPORTING
it_notes = it_notes
IMPORTING
et_param = lt_param
).

SUBMIT (lv_repid) WITH SELECTION-TABLE lt_param


VIA JOB gc_jobname NUMBER lv_jobcount
AND RETURN. "#EC CI_SUBMIT.

CALL FUNCTION 'JOB_CLOSE'


EXPORTING
jobcount = lv_jobcount
jobname = gc_jobname
strtimmed = abap_true
EXCEPTIONS
cant_start_immediate = 1
invalid_startdate = 2
jobname_missing = 3
job_close_failed = 4
job_nosteps = 5
job_notex = 6
lock_failed = 7
invalid_target = 8.

IF sy-subrc <> 0.
MESSAGE ID lv_msgid TYPE lcl_msg=>gc_error NUMBER '034' WITH gc_jobname sy-
subrc.
RETURN.
ENDIF.

ENDMETHOD. "call_note_analyzer_in_batch

METHOD execute_note_analyzer_in_batch.

CONSTANTS:
lc_msgv TYPE symsgv VALUE 'SAP Note &1 added to download list',
lc_msgv1 TYPE symsgv VALUE 'Number of SAP Notes to be downloaded: &1',
lc_msgv2 TYPE symsgv VALUE 'Expect approximately &1 minutes runtime'.

DATA:
ls_note_keys_lg TYPE cwbntkeylg,
lt_note_keys_lg TYPE bcwbn_note_keys_lg,
lv_msgv TYPE symsgv,
lt_notes TYPE scwb_api_t_notenumber,
ls_notes TYPE cwbntkeyvs,
lv_rfc_error TYPE bcwbn_bool,
lv_minutes TYPE c LENGTH 3.

FIELD-SYMBOLS:
<lt_sel_opt_notes> TYPE STANDARD TABLE,
<ls_sel_opt_notes> TYPE any,
<lv_value> TYPE any.

* This method may only be called in batch


ASSERT sy-batch IS NOT INITIAL.

ASSIGN it_sel_opt_notes TO <lt_sel_opt_notes>.

LOOP AT <lt_sel_opt_notes> ASSIGNING <ls_sel_opt_notes>.


ASSIGN COMPONENT 'LOW' OF STRUCTURE <ls_sel_opt_notes> TO <lv_value>.
ASSERT FIELDS <ls_sel_opt_notes> CONDITION sy-subrc = 0.

* For one API


ls_notes-numm = <lv_value>.
INSERT ls_notes INTO TABLE lt_notes.
* For the other API
ls_note_keys_lg-numm = <lv_value>.
ls_note_keys_lg-langu = sy-langu.
APPEND ls_note_keys_lg TO lt_note_keys_lg.

lv_msgv = lc_msgv.
REPLACE '&1' IN lv_msgv WITH ls_note_keys_lg-numm.
MESSAGE ID '00' TYPE lcl_msg=>gc_info NUMBER 208 WITH lv_msgv.
ENDLOOP.

* Expectation download of a note at least 1 minute per note


lv_minutes = lines( lt_notes ).
lv_msgv = lc_msgv1.
REPLACE '&1' IN lv_msgv WITH lv_minutes.
MESSAGE ID '00' TYPE lcl_msg=>gc_info NUMBER 208 WITH lv_msgv.

lv_minutes = ( ( lines( lt_notes ) DIV 10 ) + 1 ) * 10.


lv_msgv = lc_msgv2.
REPLACE '&1' IN lv_msgv WITH lv_minutes.
MESSAGE ID '00' TYPE lcl_msg=>gc_info NUMBER 208 WITH lv_msgv.

GET TIME STAMP FIELD gv_exec_start.

TRY.
CALL FUNCTION 'SCWB_NOTES_RESOLVE_NECESSARY'
EXPORTING
it_notes = lt_notes
IMPORTING
ev_rfc_error = lv_rfc_error
EXCEPTIONS
error = 1.

IF sy-subrc <> 0 OR lv_rfc_error = abap_true.


MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

lcl_batch=>_commit_and_sync( ).
lcl_batch=>_check_and_repeat_download( it_notes = lt_notes ).

CATCH cx_sy_dyn_call_illegal_func.
* Resolve API comes by implementing prerequisite notes
* If it is not implemented use the download API
CALL FUNCTION 'SCWN_NOTES_DOWNLOAD'
EXPORTING
it_note_keys_lg = lt_note_keys_lg
iv_classify_notes = abap_true
EXCEPTIONS
error = 1
rfc_error = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDTRY.

ENDMETHOD. "execute_note_analyzer_in_batch

METHOD is_batch_job_still_running.

* From include LBTCHDEF


CONSTANTS:
btc_running TYPE btcstatus VALUE 'R', "#EC NEEDED
btc_ready TYPE btcstatus VALUE 'Y', "#EC NEEDED
btc_scheduled TYPE btcstatus VALUE 'P', "#EC NEEDED
btc_intercepted TYPE btcstatus VALUE btc_scheduled, "#EC NEEDED
btc_released TYPE btcstatus VALUE 'S', "#EC NEEDED
btc_aborted TYPE btcstatus VALUE 'A', "#EC NEEDED
btc_finished TYPE btcstatus VALUE 'F', "#EC NEEDED
btc_put_active TYPE btcstatus VALUE 'Z', "#EC NEEDED
btc_unknown_state TYPE btcstatus VALUE 'X'. "#EC NEEDED

DATA:
lt_joblist TYPE STANDARD TABLE OF bpxminfo,
ls_joblist TYPE bpxminfo,
lr_joblist TYPE REF TO bpxminfo,
ls_jobsel_param_in TYPE btcselect,
lt_select_joblist TYPE STANDARD TABLE OF tbtcjob,
lr_select_joblist TYPE REF TO tbtcjob,
lv_msgid TYPE symsgid VALUE 'SCTC_SC'. "To avoid
package errors

rv_running = abap_false.
ls_jobsel_param_in-jobname = gc_jobname.

CALL FUNCTION 'BP_JOB_SELECT'


EXPORTING
jobselect_dialog = 'N'
jobsel_param_in = ls_jobsel_param_in
TABLES
jobselect_joblist = lt_select_joblist
EXCEPTIONS
invalid_dialog_type = 1
jobname_missing = 2
no_jobs_found = 11 "<----- !!!!!
selection_canceled = 4
username_missing = 5.
CASE sy-subrc.
WHEN 0.
* Carry on
WHEN 11.
rv_running = abap_false.
RETURN.
WHEN OTHERS.
MESSAGE ID lv_msgid TYPE lcl_msg=>gc_error NUMBER '050' WITH sy-subrc
gc_jobname.
RETURN.
ENDCASE.

LOOP AT lt_select_joblist REFERENCE INTO lr_select_joblist.


ls_joblist-jobname = lr_select_joblist->jobname.
ls_joblist-jobcount = lr_select_joblist->jobcount.
APPEND ls_joblist TO lt_joblist.
ENDLOOP.

CALL FUNCTION 'BP_JOBLIST_STATUS_GET'


TABLES
joblist = lt_joblist
EXCEPTIONS
unknown_error = 1.
IF sy-subrc <> 0.
MESSAGE ID lv_msgid TYPE lcl_msg=>gc_error NUMBER '050' WITH sy-subrc space.
RETURN.
ENDIF.

LOOP AT lt_joblist REFERENCE INTO lr_joblist.


ASSERT FIELDS lr_joblist->* CONDITION lr_joblist->status <> 'N'.
CHECK lr_joblist->status = btc_running
OR lr_joblist->status = btc_ready
OR lr_joblist->status = btc_scheduled
OR lr_joblist->status = btc_released.
rv_running = abap_true.
EXIT.
ENDLOOP.

ENDMETHOD. "is_batch_job_still_running

METHOD get_last_batch_execution.

DATA:
ls_jobsel_param_in TYPE btcselect,
lt_select_joblist TYPE STANDARD TABLE OF tbtcjob,
lr_select_joblist TYPE REF TO tbtcjob,
lv_cmp_date TYPE btcxdate,
lv_msgid TYPE symsgid VALUE 'SCTC_SC'. "To avoid
package errors

rv_run_today = abap_false.
ls_jobsel_param_in-jobname = gc_jobname.
lv_cmp_date = sy-datum.

CALL FUNCTION 'BP_JOB_SELECT'


EXPORTING
jobselect_dialog = 'N'
jobsel_param_in = ls_jobsel_param_in
TABLES
jobselect_joblist = lt_select_joblist
EXCEPTIONS
invalid_dialog_type = 1
jobname_missing = 2
no_jobs_found = 11 "<----- !!!!!
selection_canceled = 4
username_missing = 5.
CASE sy-subrc.
WHEN 0.
* Carry on
WHEN 11.
rv_run_today = abap_false.
RETURN.
WHEN OTHERS.
MESSAGE ID lv_msgid TYPE lcl_msg=>gc_error NUMBER '050' WITH sy-subrc
gc_jobname.
RETURN.
ENDCASE.

LOOP AT lt_select_joblist REFERENCE INTO lr_select_joblist.


IF lv_cmp_date <= lr_select_joblist->strtdate.
rv_run_today = abap_true.
ENDIF.
ENDLOOP.

ENDMETHOD. "get_last_batch_execution

METHOD _conv_to_param.

DATA:
lv_notes TYPE cwbntnumm,
ls_param TYPE rsparams.

CLEAR et_param.

ls_param-selname = 'S_NOTES'.
ls_param-kind = 'S'. "select option
ls_param-sign = 'I'.
ls_param-option = 'EQ'.

LOOP AT it_notes INTO lv_notes.


ls_param-low = lv_notes.
APPEND ls_param TO et_param.
ENDLOOP.

ENDMETHOD. "_conv_to_param

METHOD _check_and_repeat_download.

TYPES:
BEGIN OF lty_str_msg,
msgid TYPE symsgid,
msgty TYPE symsgty,
msgno TYPE symsgno,
msgv1 TYPE symsgv,
msgv2 TYPE symsgv,
msgv3 TYPE symsgv,
msgv4 TYPE symsgv,
END OF lty_str_msg,
lty_tab_msg TYPE STANDARD TABLE OF lty_str_msg.

CONSTANTS:
lc_msgv1 TYPE symsgv VALUE 'Number of SAP Notes to be downloaded: &1',
lc_msgv2 TYPE symsgv VALUE 'Expect approximately &1 minutes runtime',
lc_msgv3 TYPE symsgv VALUE 'SAP Note &1 added to download list again'.

DATA:
ls_note_keys_lg TYPE cwbntkeylg,
lt_note_keys_lg TYPE bcwbn_note_keys_lg,
lv_msgv TYPE symsgv,
lv_minutes TYPE c LENGTH 3,
ls_note2 TYPE bcwbn_note,
lr_notes TYPE REF TO cwbntkeyvs,
lt_msg TYPE lty_tab_msg,
lr_msg TYPE REF TO lty_str_msg.

* Resolve notes is something picky on note consistency (ref. to IT/IBC 4258449


2013)
* So check everything is there
CLEAR lt_note_keys_lg.
LOOP AT it_notes REFERENCE INTO lr_notes.
CLEAR ls_note2.
ls_note2-key-numm = lr_notes->numm.
* Do not add version, so we read the latest version

CALL FUNCTION 'SCWB_NOTE_READ'


EXPORTING
iv_read_short_text = abap_true
iv_read_corr_instructions = abap_true
CHANGING
cs_note = ls_note2
EXCEPTIONS
note_not_found = 1
language_not_found = 2
unreadable_text_format = 3
corr_instruction_not_found = 4.

IF sy-subrc <> 0 OR ls_note2-incomplete = abap_true.


* Failure
ls_note_keys_lg-numm = lr_notes->numm.
ls_note_keys_lg-langu = sy-langu.
APPEND ls_note_keys_lg TO lt_note_keys_lg.

lv_msgv = lc_msgv3.
REPLACE '&1' IN lv_msgv WITH ls_note_keys_lg-numm.
MESSAGE ID '00' TYPE lcl_msg=>gc_info NUMBER 208 WITH lv_msgv.
ENDIF.
ENDLOOP.

IF lt_note_keys_lg IS NOT INITIAL.


lv_minutes = lines( lt_note_keys_lg ).
lv_msgv = lc_msgv1.
REPLACE '&1' IN lv_msgv WITH lv_minutes.
MESSAGE ID '00' TYPE lcl_msg=>gc_info NUMBER 208 WITH lv_msgv.

lv_minutes = ( ( lines( lt_note_keys_lg ) DIV 10 ) + 1 ) * 10.


lv_msgv = lc_msgv2.
REPLACE '&1' IN lv_msgv WITH lv_minutes.
MESSAGE ID '00' TYPE lcl_msg=>gc_info NUMBER 208 WITH lv_msgv.

CALL FUNCTION 'SCWN_NOTES_DOWNLOAD'


EXPORTING
it_note_keys_lg = lt_note_keys_lg
iv_classify_notes = abap_true
EXCEPTIONS
error = 1
rfc_error = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDIF.

lcl_batch=>_commit_and_sync( ).

GET TIME STAMP FIELD gv_exec_end.

LOOP AT lt_note_keys_lg INTO ls_note_keys_lg.


CLEAR ls_note2.
ls_note2-key-numm = lr_notes->numm.
* Do not add version, so we read the latest version

CALL FUNCTION 'SCWB_NOTE_READ'


EXPORTING
iv_read_short_text = abap_true
iv_read_corr_instructions = abap_true
CHANGING
cs_note = ls_note2
EXCEPTIONS
note_not_found = 1
language_not_found = 2
unreadable_text_format = 3
corr_instruction_not_found = 4.

IF sy-subrc <> 0 OR ls_note2-incomplete = abap_true.


* Failure
* No point in trying to download again, however try to add messages related
to this note
CLEAR lt_msg.

SELECT DISTINCT msgid msgty msgno msgv1 msgv2 msgv3 msgv4 FROM cwbntmsg
INTO CORRESPONDING FIELDS OF TABLE lt_msg
WHERE numm = lr_notes->numm AND tstamp BETWEEN gv_exec_start AND
gv_exec_end.

LOOP AT lt_msg REFERENCE INTO lr_msg.


MESSAGE ID lr_msg->msgid TYPE lcl_msg=>gc_success NUMBER lr_msg->msgno
WITH lr_msg->msgv1 lr_msg->msgv2 lr_msg->msgv3 lr_msg->msgv4.
ENDLOOP.
ENDIF.
ENDLOOP.

ENDMETHOD. "_check_and_repeat_download

METHOD _commit_and_sync.
COMMIT WORK.

* Tables CWBNTHEAD, CWBNTSTXT etc. are not buffered.


* Table CWBNTCI is buffered (at least in newer releases)
CALL FUNCTION 'SBUF_PARTIAL_RESET'
EXPORTING
tabname = 'CWBNTCI'
EXCEPTIONS
OTHERS = 0.

ENDMETHOD. "_commit_and_sync

ENDCLASS. "lcl_batch IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_alv IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_alv IMPLEMENTATION.

METHOD get_instance.

ASSERT io_msg IS BOUND.


CREATE OBJECT ro_instance.
ro_instance->mo_msg = io_msg.

ENDMETHOD. "get_instance

METHOD prepare.

DATA:
ls_outtab TYPE gty_str_outtab,
lt_msg TYPE lcl_msg=>gty_tab_msg,
lr_msg TYPE REF TO lcl_msg=>gty_str_msg,
lv_last_node TYPE i,
lv_last_object TYPE lcl_msg=>gty_object,
l_prog TYPE program,
l_t_bal_log_msg TYPE lcl_checks=>tn_t_bal_log_msg.

* Update status of all nodes


mo_msg->update_node_status( ).

* Create outtab
mo_msg->get_msg(
IMPORTING
et_msg = lt_msg
).

CLEAR mt_outtab.
LOOP AT lt_msg REFERENCE INTO lr_msg.
CLEAR ls_outtab.
MOVE-CORRESPONDING lr_msg->* TO ls_outtab.

ls_outtab-ic_action = _conv_action_to_icon(
iv_action = lr_msg->action
iv_purpose = lr_msg->purpose
).
ls_outtab-ic_lights = _conv_msg_type_to_icon(
iv_msg_type = lr_msg->msg_type
).

IF lr_msg->long_text_id IS NOT INITIAL.


ls_outtab-ic_ltext = icon_system_help.
REPLACE SECTION OFFSET 3 OF ls_outtab-ic_ltext WITH '\QLong Text@'(a01).
ENDIF.

* If there's an application log for UDO, then show "log" icon


IF lr_msg->purpose = gc_purpose_udo_before OR
lr_msg->purpose = gc_purpose_udo_after.

go_checks->split_udo(
EXPORTING
i_udo_comment = lr_msg->target_note
IMPORTING
e_udo_report = l_prog
).

CLEAR: l_t_bal_log_msg.
l_t_bal_log_msg = go_checks->get_bal_log( i_udo_report = l_prog ).

IF lines( l_t_bal_log_msg ) > 0.


ls_outtab-ic_ltext = icon_protocol.
REPLACE SECTION OFFSET 3 OF ls_outtab-ic_ltext WITH '\QLog UDO-
Report@'(a02).
ENDIF.

ENDIF.

* If there are inactive objects, then show "object" icon


IF lr_msg->action = lcl_msg=>gc_action_note_inactive.
ls_outtab-ic_ltext = icon_object_list.
REPLACE SECTION OFFSET 3 OF ls_outtab-ic_ltext WITH '\QInactive
objects@'(a03).
ENDIF.

* Coloring
* Char 1 = C (This is a color property)
* Char 2 = 3 (Color codes: 1 - 7) (rf. to program SHOWCOLO for demo of values)
* Char 3 = Intensified on/off ( 1 or 0 )
* Char 4 = Inverse display on/off ( 1 or 0 )
IF lv_last_node <> ls_outtab-node.
lv_last_node = ls_outtab-node.
* Color new node
CASE lr_msg->msg_type.
WHEN lcl_msg=>gc_info.
ls_outtab-alv_color = 'C500'. "Positive (green)
WHEN lcl_msg=>gc_warning.
ls_outtab-alv_color = 'C300'. "Total (yellow)
WHEN OTHERS.
ls_outtab-alv_color = 'C600'. "Negative (red)
ENDCASE.
ELSEIF lv_last_object <> ls_outtab-object.
lv_last_object = ls_outtab-object.
* Color first message to object
* Typically only notes have more that one message per object
* and then provide additional information
ls_outtab-alv_color = 'C210'.
ELSE.
ls_outtab-alv_color = 'C200'.
ENDIF.

APPEND ls_outtab TO mt_outtab.


ENDLOOP.

_create_layout( ).
_create_field_cat( ).
_create_sort_info( ).
_create_excl_func( ).
* _create_exit_func( ).

ENDMETHOD. "prepare

METHOD display.

CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'


EXPORTING
i_callback_program = sy-repid
i_callback_pf_status_set = 'SET_PF_STATUS'
i_callback_user_command = iv_callback_form
is_layout = ms_layout
it_fieldcat = mt_field_cat
it_excluding = mt_excl_func
it_sort = mt_sort_info
IMPORTING
es_exit_caused_by_user = rs_exit
TABLES
t_outtab = mt_outtab
EXCEPTIONS
program_error = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

ENDMETHOD. "display

METHOD display_as_popup.

CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'


EXPORTING
i_callback_program = sy-repid
i_callback_user_command = iv_callback_form
is_layout = ms_layout
it_fieldcat = mt_field_cat
it_excluding = mt_excl_func
it_sort = mt_sort_info
i_screen_start_column = 5
i_screen_start_line = 5
i_screen_end_column = 160
i_screen_end_line = 40
IMPORTING
es_exit_caused_by_user = rs_exit
TABLES
t_outtab = mt_outtab
EXCEPTIONS
program_error = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

ENDMETHOD. "display_as_popup
*#action
METHOD call_back.

DATA:
lr_outtab TYPE REF TO gty_str_outtab,
lv_param_name TYPE tpfet-parname,
lv_number TYPE cwbntnumm,
lv_version TYPE cwbntvers,
ls_note TYPE bcwbn_note,
ls_notes TYPE cwbntkeylg,
lt_notes TYPE bcwbn_note_keys_lg,
lv_url TYPE string,
lv_refresh TYPE abap_bool.
CASE iv_ucomm.
WHEN '&NTE'.
READ TABLE mt_outtab REFERENCE INTO lr_outtab INDEX cs_selfield-tabindex.
ASSERT FIELDS cs_selfield CONDITION sy-subrc = 0.

lv_refresh = abap_true.
WHEN '&IC1'. "icon click or double click on field
READ TABLE mt_outtab REFERENCE INTO lr_outtab INDEX cs_selfield-tabindex.
ASSERT FIELDS cs_selfield CONDITION sy-subrc = 0.

IF cs_selfield-fieldname = gc_icon_ltext.
IF lr_outtab->purpose = gc_purpose_udo_before OR
lr_outtab->purpose = gc_purpose_udo_after.

display_udo_appllog( lr_outtab->target_note ).

ELSEIF lr_outtab->action = lcl_msg=>gc_action_note_inactive.

lv_number = lr_outtab->object.

display_inactive_objects( lv_number ).

ELSE.

IF NOT lr_outtab->long_text_id IS INITIAL.


lcl_msg_repository=>show_text_in_pop_up(
iv_text_id = lr_outtab->long_text_id
iv_msg_type = lr_outtab->msg_type
).
ENDIF.

ENDIF.
ELSEIF cs_selfield-fieldname = gc_object
OR cs_selfield-fieldname = gc_icon_action.

CASE lr_outtab->action.
WHEN lcl_msg=>gc_action_impl_tool
OR lcl_msg=>gc_action_udo_upload.

IF lr_outtab->purpose = gc_purpose_udo_before OR
lr_outtab->purpose = gc_purpose_udo_after.
* Run UDO program
_execute_udo_report(
EXPORTING
ir_outtab = lr_outtab
CHANGING
cs_selfield = cs_selfield
).

lv_refresh = abap_true.
ENDIF.

WHEN lcl_msg=>gc_action_auto_impl
OR lcl_msg=>gc_action_man_impl
OR lcl_msg=>gc_action_impl_issue
OR lcl_msg=>gc_action_read_note
OR lcl_msg=>gc_action_note_inactive
OR lcl_msg=>gc_action_none.

* Jump to note browser


IF lr_outtab->object CO ' 0123456789'.
lv_number = lr_outtab->object.

SELECT SINGLE numm versno FROM cwbnthead INTO (lv_number,


lv_version)
WHERE numm = lv_number. "#EC *
IF sy-subrc = 0.
IF lcl_utilities=>is_fast( ) = abap_true AND
( lr_outtab->action = lcl_msg=>gc_action_auto_impl OR
lr_outtab->action = lcl_msg=>gc_action_man_impl ).

CLEAR ls_note.
ls_note-key-numm = lv_number.
ls_note-key-versno = lv_version.

CALL FUNCTION 'SCWB_NOTE_IMPLEMENT'


CHANGING
cs_note = ls_note
EXCEPTIONS
OTHERS = 0.

ELSE.
SUBMIT scwn_note_browser WITH numm = lv_number AND RETURN. "#EC
CI_SUBMIT
ENDIF.

lv_refresh = abap_true.
ENDIF.
ENDIF.

* WHEN lcl_msg=>gc_action_msg_sap.

WHEN lcl_msg=>gc_action_check_usage.

* Display parameter
IF lr_outtab->node = lcl_msg=>gc_node_param_check.
lv_param_name = lr_outtab->object.

CALL FUNCTION 'PFL_SHOW_PARAMETER_DETAILS'


EXPORTING
parameter_name = lv_param_name
EXCEPTIONS
no_para_found = 0.
ENDIF.

WHEN lcl_msg=>gc_action_load_file.

* Need to load another file


* This error is already checked at selection-screen, so we simply leave
the ALV
cs_selfield-exit = abap_true.

WHEN lcl_msg=>gc_action_delta_file.

* Save delta file


lcl_utilities=>save_xml( is_file = gs_delta_file ).

WHEN lcl_msg=>gc_action_web_link.

* Show link in browser


lcl_utilities=>call_browser( iv_url = lr_outtab->target_note ).

WHEN lcl_msg=>gc_action_download_note.

* Download SAP Note


CLEAR: ls_notes, lt_notes.
ls_notes-numm = lr_outtab->target_note.
ls_notes-versno = '9999'.
APPEND ls_notes TO lt_notes.

CALL FUNCTION 'SCWN_NOTES_DOWNLOAD'


EXPORTING
it_note_keys_lg = lt_notes
iv_classify_notes = abap_true
EXCEPTIONS
error = 1
rfc_error = 2
OTHERS = 3.
IF sy-subrc = 0.
lv_refresh = abap_true.

go_checks->remove_outdated_note( ls_notes-numm ).

ELSEIF sy-subrc = 2.
MESSAGE e666(01) WITH 'RFC error when downloading SAP Note'(a10).
ELSE.
MESSAGE e666(01) WITH 'Error downloading SAP Note'(a11) lr_outtab-
>target_note.
ENDIF.

WHEN lcl_msg=>gc_action_tci_download
OR lcl_msg=>gc_action_sw_download.

* Download SAR file for TCI note


go_checks->split_tci(
EXPORTING
i_tci_comment = lr_outtab->target_note
IMPORTING
e_tci_url = lv_url
).

lcl_utilities=>call_browser( iv_url = lv_url ).

WHEN lcl_msg=>gc_action_tci_upload
OR lcl_msg=>gc_action_sw_upload.

* Upload SAR file to SPAM


PERFORM transfer_n_decompress IN PROGRAM sapmspam IF FOUND.

WHEN lcl_msg=>gc_action_icf_activate.

* Activate ICF service


_activate_icf_service(
EXPORTING
ir_outtab = lr_outtab
CHANGING
cs_selfield = cs_selfield
).

lv_refresh = abap_true.
WHEN OTHERS.
* Currently no hotspot target
ENDCASE.
* ELSE.
* Hotspot not supported here
ENDIF.
ENDCASE.

* Update ALV
IF lv_refresh = abap_true AND p_val IS INITIAL.
READ TABLE mt_outtab REFERENCE INTO lr_outtab INDEX cs_selfield-tabindex.
ASSERT FIELDS cs_selfield CONDITION sy-subrc = 0.

_check_note_and_refresh_alv(
EXPORTING
ir_outtab = lr_outtab
CHANGING
cs_selfield = cs_selfield
).
ENDIF.

ENDMETHOD. "call_back

METHOD display_udo_appllog.

DATA:
l_report TYPE program.

go_checks->split_udo(
EXPORTING
i_udo_comment = i_udo_comment
IMPORTING
e_udo_report = l_report
).

lcl_wb=>display_log(
EXPORTING
i_db_search = abap_true
i_report = l_report
).

ENDMETHOD. "display_udo_appllog

METHOD display_inactive_objects.

DATA:
ls_note_inactive TYPE lcl_checks=>tn_s_note_inactive,
lt_note_inactive TYPE SORTED TABLE OF lcl_checks=>tn_s_note_inactive
WITH UNIQUE DEFAULT KEY.

LOOP AT lcl_checks=>nt_note_inactive INTO ls_note_inactive


WHERE numm = iv_note_number.
INSERT ls_note_inactive INTO TABLE lt_note_inactive.
ENDLOOP.

CALL FUNCTION 'RSDU_CALL_ALV_TABLE'


EXPORTING
i_title = 'Inactive Objects'(a12)
i_ta_data = lt_note_inactive.

ENDMETHOD. "display_inactive_objects

METHOD set_validation.
m_validation = i_validation.
ENDMETHOD. "set_validation

METHOD set_scrollstatus.
ms_grid_scroll = is_grid_scroll.
ENDMETHOD. "set_scrollstatus

METHOD get_scrollstatus.
es_grid_scroll = ms_grid_scroll.
ENDMETHOD. "get_scrollstatus

METHOD _create_field_cat.

DATA:
ls_field_cat TYPE slis_fieldcat_alv.

ls_field_cat-fieldname = gc_sequence.
ls_field_cat-col_pos = 1.
ls_field_cat-datatype = 'INT4'.
ls_field_cat-no_out = abap_true.
ls_field_cat-seltext_s = 'Sequence'(b01).
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = gc_node.
ls_field_cat-col_pos = 2.
ls_field_cat-datatype = 'INT4'.
ls_field_cat-no_out = abap_true.
ls_field_cat-seltext_s = 'Node'(b02).
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = gc_scope_id.
ls_field_cat-col_pos = 3.
ls_field_cat-datatype = 'CHAR'.
ls_field_cat-intlen = 60.
ls_field_cat-outputlen = 15.
ls_field_cat-key = abap_true.
ls_field_cat-seltext_s = 'Scope ID'(b03).
ls_field_cat-emphasize = 'C410'.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = gc_object.
ls_field_cat-col_pos = 4.
ls_field_cat-datatype = 'CHAR'.
ls_field_cat-intlen = 30.
ls_field_cat-outputlen = 10.
ls_field_cat-key = abap_true.
ls_field_cat-seltext_s = 'Check'(b04).
ls_field_cat-emphasize = 'C410'.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'MSG_TYPE'.
ls_field_cat-col_pos = 5.
ls_field_cat-rollname = 'SYMSGTY'.
ls_field_cat-no_out = abap_true.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'IC_LIGHTS'.
ls_field_cat-col_pos = 6.
ls_field_cat-datatype = 'CHAR'.
ls_field_cat-intlen = 4.
ls_field_cat-seltext_s = 'Status'(b05).
ls_field_cat-icon = abap_true.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'ACTION'.
ls_field_cat-col_pos = 7.
ls_field_cat-datatype = 'CHAR'.
ls_field_cat-intlen = 1.
ls_field_cat-seltext_s = 'Action Type'(b06).
ls_field_cat-no_out = abap_true.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = gc_icon_action.
ls_field_cat-col_pos = 8.
ls_field_cat-rollname = 'ICON_L2'.
ls_field_cat-seltext_s = 'Action'(b07).
ls_field_cat-icon = abap_true.
ls_field_cat-hotspot = abap_true.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'TEXT'.
ls_field_cat-col_pos = 9.
ls_field_cat-datatype = 'STRG'.
ls_field_cat-outputlen = 160.
ls_field_cat-seltext_s = 'Message'(b08).
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = gc_icon_ltext.
ls_field_cat-col_pos = 10.
ls_field_cat-rollname = 'ICON_L2'.
ls_field_cat-seltext_s = 'More'(b09).
ls_field_cat-icon = abap_true.
ls_field_cat-hotspot = abap_true.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'SHORT_TEXT_ID'.
ls_field_cat-col_pos = 11.
ls_field_cat-datatype = 'CHAR'.
ls_field_cat-intlen = 3.
ls_field_cat-no_out = abap_true.
ls_field_cat-tech = abap_true.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'LONG_TEXT_ID'.
ls_field_cat-col_pos = 12.
ls_field_cat-datatype = 'CHAR'.
ls_field_cat-intlen = 3.
ls_field_cat-no_out = abap_true.
ls_field_cat-tech = abap_true.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'TARGET_NOTE'.
ls_field_cat-col_pos = 13.
ls_field_cat-rollname = 'CWBNTNUMM'.
ls_field_cat-no_out = abap_true.
ls_field_cat-tech = abap_true.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = gc_alv_color.
ls_field_cat-col_pos = 14.
ls_field_cat-datatype = 'CHAR'.
ls_field_cat-intlen = 4.
ls_field_cat-no_out = abap_true.
ls_field_cat-tech = abap_true.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'IMPL_STATUS'.
ls_field_cat-col_pos = 15.
ls_field_cat-datatype = 'CWBPRSTAT'.
ls_field_cat-intlen = 1.
ls_field_cat-outputlen = 40.
ls_field_cat-seltext_s = 'Note State'(b10).
ls_field_cat-no_out = abap_true.
ls_field_cat-tech = abap_false.
ls_field_cat-ddic_outputlen = 40.
ls_field_cat-edit_mask = '==PSTAT'.
APPEND ls_field_cat TO mt_field_cat.
CLEAR ls_field_cat.
ls_field_cat-fieldname = 'SWCOMPONENT'.
ls_field_cat-col_pos = 16.
ls_field_cat-datatype = 'DLVUNIT'.
ls_field_cat-intlen = 30.
ls_field_cat-outputlen = 18.
ls_field_cat-seltext_s = 'SW Component'(b11).
ls_field_cat-no_out = abap_false.
ls_field_cat-tech = abap_false.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'RELEASE'.
ls_field_cat-col_pos = 17.
ls_field_cat-datatype = 'SAPRELEASE'.
ls_field_cat-intlen = 10.
ls_field_cat-seltext_s = 'Release'(b12).
ls_field_cat-no_out = abap_false.
ls_field_cat-tech = abap_false.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'SPLEVEL'.
ls_field_cat-col_pos = 18.
ls_field_cat-datatype = 'SAPPATCHLV'.
ls_field_cat-intlen = 10.
ls_field_cat-outputlen = 12.
ls_field_cat-seltext_s = 'SP Level'(b13).
ls_field_cat-no_out = abap_false.
ls_field_cat-tech = abap_false.
APPEND ls_field_cat TO mt_field_cat.

CLEAR ls_field_cat.
ls_field_cat-fieldname = 'PURPOSE'.
ls_field_cat-col_pos = 19.
ls_field_cat-datatype = 'CHAR'.
ls_field_cat-intlen = 4.
ls_field_cat-seltext_s = 'Purpose'(b14).
ls_field_cat-no_out = abap_true.
ls_field_cat-tech = abap_false.
APPEND ls_field_cat TO mt_field_cat.

ENDMETHOD. "_create_field_cat

METHOD _create_layout.

ms_layout-no_input = abap_true. " only display fields


ms_layout-colwidth_optimize = abap_true.
ms_layout-window_titlebar = 'SAP BW and SAP BW/4HANA Note Analyzer
Results'(b20).
ms_layout-no_sumchoice = abap_true.
ms_layout-info_fieldname = gc_alv_color.
ms_layout-allow_switch_to_list = abap_true.
ms_layout-cell_merge = abap_true.

ENDMETHOD. "_create_layout

METHOD _create_sort_info.
DATA:
ls_sort_info TYPE slis_sortinfo_alv.

ls_sort_info-spos = 1.
ls_sort_info-fieldname = gc_sequence.
APPEND ls_sort_info TO mt_sort_info.

ls_sort_info-spos = 2.
ls_sort_info-fieldname = gc_node.
APPEND ls_sort_info TO mt_sort_info.

ls_sort_info-spos = 3.
ls_sort_info-fieldname = gc_scope_id.
APPEND ls_sort_info TO mt_sort_info.

ls_sort_info-spos = 4.
ls_sort_info-fieldname = gc_object.
APPEND ls_sort_info TO mt_sort_info.

ENDMETHOD. "_create_sort_info

METHOD _create_excl_func.

DATA:
ls_excl TYPE slis_extab.

ls_excl-fcode = cl_gui_alv_grid=>mc_fc_info.
APPEND ls_excl TO mt_excl_func.
ls_excl-fcode = cl_gui_alv_grid=>mc_fc_graph.
APPEND ls_excl TO mt_excl_func.

ENDMETHOD. "_create_excl_func

* METHOD _create_exit_func.
* DATA ls_event_exit TYPE slis_event_exit.
*
* ls_event_exit-ucomm = cl_gui_alv_grid=>mc_fc_info.
* ls_event_exit-before = abap_true.
* APPEND ls_event_exit TO mt_event_exit.
*
* ENDMETHOD.

METHOD _conv_action_to_icon.

CASE iv_action.
WHEN lcl_msg=>gc_action_none.
CLEAR rv_icon.
WHEN lcl_msg=>gc_action_auto_impl.
rv_icon = icon_fast_entry.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QAutomatic implementation@'.
WHEN lcl_msg=>gc_action_man_impl.
rv_icon = icon_tools.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QManual activities necessary@'.
WHEN lcl_msg=>gc_action_msg_sap.
CLEAR rv_icon.
rv_icon = icon_short_message.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QSend a customer messsage to
SAP@'.
WHEN lcl_msg=>gc_action_check_usage.
rv_icon = icon_check.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QCheck the system@'.
WHEN lcl_msg=>gc_action_load_file.
rv_icon = icon_import.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QLoad additional file@'.
WHEN lcl_msg=>gc_action_delta_file.
rv_icon = icon_export.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QSave file with delta@'.
WHEN lcl_msg=>gc_action_impl_tool.
IF iv_purpose = gc_purpose_udo_after.
rv_icon = icon_execute_object.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QAdditional programs required
after note implementation@'.
ELSEIF iv_purpose = gc_purpose_udo_before.
rv_icon = icon_execute_object.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QAdditional programs required
before note implementation@'.
ELSE.
rv_icon = icon_warning.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QAdditional activities
required when note implementation@'.
ENDIF.
WHEN lcl_msg=>gc_action_impl_issue.
rv_icon = icon_failure.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QKnown issues when implementing
the note@'.
WHEN lcl_msg=>gc_action_web_link.
rv_icon = icon_hlp.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QLink to external
documentation@'.
WHEN lcl_msg=>gc_action_sp_impl.
rv_icon = icon_binary_document.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QImplementation by support
package only@'.
WHEN lcl_msg=>gc_action_read_note.
rv_icon = icon_display.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QDisplay SAP Note@'.
WHEN lcl_msg=>gc_action_download_note.
rv_icon = icon_import.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QDownload SAP Note@'.
WHEN lcl_msg=>gc_action_tci_download.
rv_icon = icon_export.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QDownload SAR file for
transport-based correction instructions@'.
WHEN lcl_msg=>gc_action_tci_upload.
rv_icon = icon_import.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QUpload SAR file for transport-
based correction instructions@'.
WHEN lcl_msg=>gc_action_sw_download.
rv_icon = icon_export.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QDownload file from software
center@'.
WHEN lcl_msg=>gc_action_sw_upload.
rv_icon = icon_import.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QUpload file to SAP Patch
Manager@'.
WHEN lcl_msg=>gc_action_icf_activate.
rv_icon = icon_wf_reserve_workitem.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QActivate ICF service@'.
WHEN lcl_msg=>gc_action_note_inactive.
rv_icon = icon_activate.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QDisplay object list and
activate any inactive objects@'.
WHEN lcl_msg=>gc_action_note_reset.
rv_icon = icon_system_undo.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QReset SAP Note@'.
WHEN lcl_msg=>gc_action_udo_upload.
rv_icon = icon_import.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QUpload program required by SAP
Note@'.
WHEN OTHERS.
* Should not happen
rv_icon = icon_message_question.
ENDCASE.

ENDMETHOD. "_conv_action_to_icon

METHOD _conv_msg_type_to_icon.

CASE iv_msg_type.
WHEN lcl_msg=>gc_error OR lcl_msg=>gc_abort.
rv_icon = icon_red_light.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QError@'.
WHEN lcl_msg=>gc_warning.
rv_icon = icon_yellow_light.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QWarning@'.
WHEN lcl_msg=>gc_info.
rv_icon = icon_green_light.
REPLACE SECTION OFFSET 3 OF rv_icon WITH '\QOK@'.
WHEN OTHERS.
rv_icon = icon_light_out.
ENDCASE.

ENDMETHOD. "_conv_msg_type_to_icon

METHOD _check_protocol_udo_report.

DATA:
l_t_bal_log_msg TYPE lcl_checks=>tn_t_bal_log_msg,
l_prog TYPE program,
l_no_of_exec TYPE i.

FIELD-SYMBOLS: <ls_outtab> TYPE gty_str_outtab.

ASSIGN ir_outtab->* TO <ls_outtab>.

go_checks->split_udo(
EXPORTING
i_udo_comment = ir_outtab->target_note
IMPORTING
e_udo_report = l_prog
e_no_of_exec = l_no_of_exec
).

* Get UDO logs


l_t_bal_log_msg = go_checks->get_bal_log(
i_udo_report = l_prog
).
* Evaluate UDO logs
IF lines( l_t_bal_log_msg ) > 0.
<ls_outtab>-msg_type = go_checks->evaluate_t_bal_msg(
i_t_bal_log_msg = l_t_bal_log_msg
i_no_of_exec = l_no_of_exec
).

IF <ls_outtab>-msg_type = lcl_msg=>gc_info.
<ls_outtab>-action = lcl_msg=>gc_action_none.
ENDIF.
ENDIF.

cs_selfield-refresh = abap_true.
go_alv->prepare( ).

ENDMETHOD. "_check_protocol_udo_report

METHOD _execute_udo_report.

DATA:
l_prog TYPE program,
l_function TYPE funcname,
l_title TYPE repti,
l_s_progdir TYPE progdir,
l_answer TYPE c,
l_loaded TYPE abap_bool,
lt_code TYPE lcl_utilities=>gty_tab_code,
l_question TYPE string.

go_checks->split_udo(
EXPORTING
i_udo_comment = ir_outtab->target_note
IMPORTING
e_udo_report = l_prog
).

DO.
SELECT SINGLE * FROM progdir INTO l_s_progdir
WHERE name = l_prog AND state = 'A'.

IF sy-subrc = 0.
IF lcl_utilities=>is_fast( ) = abap_true AND
( l_prog CS 'RS_UDO' OR l_prog CS 'RSUDO' OR l_prog CS 'RS_NOTE' OR
l_prog CS 'ZNOTE' ).
SUBMIT (l_prog) VIA SELECTION-SCREEN
WITH testrun = abap_false
WITH update = abap_true
AND RETURN.
ELSE.
SUBMIT (l_prog) VIA SELECTION-SCREEN AND RETURN.
ENDIF.

_check_protocol_udo_report(
EXPORTING
ir_outtab = ir_outtab
CHANGING
cs_selfield = cs_selfield
).
EXIT.
ENDIF.

IF NOT l_prog(1) CA 'YZ'.


EXIT.
ENDIF.

IF lcl_utilities=>is_fast( ) IS INITIAL.
l_question = 'Program &1 does not exist. Do you want to upload and install
it?'.
REPLACE '&1' WITH l_prog INTO l_question.
CONDENSE l_question.

CALL FUNCTION 'POPUP_TO_CONFIRM'


EXPORTING
titlebar = sy-title
text_question = l_question
text_button_1 = 'Yes'
text_button_2 = 'No'
default_button = '1'
display_cancel_button = 'X'
IMPORTING
answer = l_answer
EXCEPTIONS
text_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0 OR l_answer <> '1'.
EXIT.
ENDIF.
ENDIF.

lcl_utilities=>open_abap(
EXPORTING
iv_title = 'Upload ABAP Program'
iv_pattern = l_prog
IMPORTING
et_code = lt_code
ev_flg_loaded = l_loaded
).

IF l_loaded = abap_false.
EXIT.
ENDIF.

l_title = l_prog.
l_function = 'RPY_PROGRAM_INSERT'.
IF sy-saprl >= '730'.
CALL FUNCTION l_function
EXPORTING
program_name = l_prog
program_type = '1'
title_string = l_title
development_class = '$TMP'
temporary = abap_true
save_inactive = abap_false
suppress_dialog = abap_true
TABLES
source_extended = lt_code
EXCEPTIONS
already_exists = 1
cancelled = 2
name_not_allowed = 3
permission_error = 4
OTHERS = 5.
ELSE.
CALL FUNCTION l_function
EXPORTING
program_name = l_prog
program_type = '1'
title_string = l_title
development_class = '$TMP'
temporary = abap_true
save_inactive = abap_false
TABLES
source_extended = lt_code
EXCEPTIONS
already_exists = 1
cancelled = 2
name_not_allowed = 3
permission_error = 4
OTHERS = 5.
ENDIF.
IF sy-subrc <> 0.
MESSAGE 'Error creating program' TYPE 'E' DISPLAY LIKE 'I'.
EXIT.
ENDIF.

CALL FUNCTION 'TRINT_TADIR_INSERT'


EXPORTING
devclass = '$TMP'
object = 'PROG'
obj_name = l_prog
pgmid = 'R3TR'
EXCEPTIONS
object_exists_global = 1
object_exists_local = 2
OTHERS = 3.
IF sy-subrc <> 0.
MESSAGE 'Error creating entry in TADIR' TYPE 'E' DISPLAY LIKE 'I'.
EXIT.
ENDIF.

* Have to commit or remote compile will lead to hanging session


COMMIT WORK.
ENDDO.

ENDMETHOD. "_execute_udo_report

METHOD _activate_icf_service.

DATA:
l_icf_name TYPE icfname,
l_icf_par TYPE icfparguid,
l_icf_path TYPE string,
l_icf_status TYPE abap_bool.

FIELD-SYMBOLS:
<ls_outtab> TYPE gty_str_outtab.

ASSIGN ir_outtab->* TO <ls_outtab>.

go_checks->split_icf(
EXPORTING
i_icf_comment = ir_outtab->target_note
IMPORTING
e_icf_name = l_icf_name
e_icf_par = l_icf_par
e_icf_path = l_icf_path
).

SUBMIT rsicftree VIA SELECTION-SCREEN AND RETURN


WITH icf_url = l_icf_path
WITH icf_serv = l_icf_name.

l_icf_status = go_checks->check_icf_service(
i_icf_name = l_icf_name
i_icf_par = l_icf_par
).

IF l_icf_status = abap_true.
<ls_outtab>-msg_type = lcl_msg=>gc_info.
<ls_outtab>-action = lcl_msg=>gc_action_none.
ENDIF.

cs_selfield-refresh = abap_true.
go_alv->prepare( ).

ENDMETHOD. "_activate_icf_service

METHOD _modify_outtab_action_column.

* so that the order is kept... only one action item in the ALV can be pressed
DATA:
l_found TYPE boolean.

IF m_validation = abap_true.
RETURN.
ENDIF.

FIELD-SYMBOLS: <l_s_outtab> TYPE gty_str_outtab.


LOOP AT mt_outtab ASSIGNING <l_s_outtab>.
IF l_found = abap_true.
CLEAR: <l_s_outtab>-action,
<l_s_outtab>-ic_action.
ENDIF.
IF NOT <l_s_outtab>-action IS INITIAL.
l_found = abap_true.
ENDIF.
ENDLOOP.

ENDMETHOD. "_modify_outtab_action_column

METHOD _check_note_and_refresh_alv.

DATA:
ls_msg TYPE lcl_msg=>gty_str_msg.
FIELD-SYMBOLS:
<ls_outtab> TYPE gty_str_outtab.

ASSIGN ir_outtab->* TO <ls_outtab>.


MOVE-CORRESPONDING <ls_outtab> TO ls_msg.

go_checks->check_note_again(
EXPORTING
is_msg = ls_msg
).

cs_selfield-refresh = abap_true.
go_alv->prepare( ).

ENDMETHOD. "_check_note_and_refresh_alv

ENDCLASS. "lcl_alv IMPLEMENTATION

*----------------------------------------------------------------------*
* CLASS lcl_msg_repository IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_msg_repository IMPLEMENTATION.

METHOD show_text_in_pop_up.

DATA:
lv_string TYPE string,
lv_text1 TYPE gty_fixed_text,
lv_text2 TYPE gty_fixed_text,
lv_text3 TYPE gty_fixed_text,
lv_text4 TYPE gty_fixed_text,
lv_text5 TYPE gty_fixed_text,
lv_text6 TYPE gty_fixed_text,
lt_result TYPE gty_tab_string,
lv_index TYPE sytabix.

lv_string = lcl_msg_repository=>get_long_text( iv_text_id = iv_text_id ).

SPLIT lv_string AT ' ' INTO TABLE lt_result.

lcl_msg_repository=>_split_string(
EXPORTING
it_string = lt_result
IMPORTING
ev_text = lv_text1
CHANGING
cv_start_index = lv_index
).
lcl_msg_repository=>_split_string(
EXPORTING
it_string = lt_result
IMPORTING
ev_text = lv_text2
CHANGING
cv_start_index = lv_index
).
lcl_msg_repository=>_split_string(
EXPORTING
it_string = lt_result
IMPORTING
ev_text = lv_text3
CHANGING
cv_start_index = lv_index
).
lcl_msg_repository=>_split_string(
EXPORTING
it_string = lt_result
IMPORTING
ev_text = lv_text4
CHANGING
cv_start_index = lv_index
).
lcl_msg_repository=>_split_string(
EXPORTING
it_string = lt_result
IMPORTING
ev_text = lv_text5
CHANGING
cv_start_index = lv_index
).
lcl_msg_repository=>_split_string(
EXPORTING
it_string = lt_result
IMPORTING
ev_text = lv_text6
CHANGING
cv_start_index = lv_index
).

CALL FUNCTION 'POPUP_FOR_INTERACTION'


EXPORTING
headline = 'Message'
text1 = lv_text1
text2 = lv_text2
text3 = lv_text3
text4 = lv_text4
text5 = lv_text5
text6 = lv_text6
ticon = iv_msg_type
button_1 = 'Ok'.

ENDMETHOD. "show_text_in_pop_up

METHOD _split_string.

DATA:
lr_string TYPE REF TO string,
lv_text_save TYPE gty_fixed_text.

CLEAR ev_text.

DO.
* Do not clear cv_index
ADD 1 TO cv_start_index.
READ TABLE it_string REFERENCE INTO lr_string INDEX cv_start_index.
IF sy-subrc <> 0.
EXIT.
ENDIF.

CONCATENATE ev_text lr_string->* INTO ev_text SEPARATED BY ' '.


IF sy-subrc = 0.
* Fits
lv_text_save = ev_text.
ELSE.
* Too long
SUBTRACT 1 FROM cv_start_index.
ev_text = lv_text_save.
EXIT.
ENDIF.
ENDDO.

ENDMETHOD. "_split_string

METHOD get_short_text.

CASE iv_text_id.
WHEN '100'.
rv_text = 'Software Component Checking Phase'.
WHEN '200'.
rv_text = 'Preparation SAP Note Checking Phase'.
WHEN '300'.
rv_text = 'SAP Note Checking Phase'.
WHEN '310'.
rv_text = 'SAP Note requires component &v1&: &object& (&v1&) "&v2&"'.
WHEN '311'.
rv_text = 'SAP Note already implemented with support package: &object&
(&v1&) "&v2&"'.
WHEN '320'.
rv_text = '&v3& SAP Note needs to be implemented: &object& (&v1&) "&v2&"'.
WHEN '321'.
rv_text = 'Prerequisite SAP Note added to the list of SAP Notes: &v1&
(&v2&) "&v3&"'.
WHEN '322'.
rv_text = '&v3& SAP Note implemented in this system: &object& (&v1&)
"&v2&"'.
WHEN '323'.
rv_text = 'SAP Note &object&: validity not recognized (component &v1&;
release &v2&; support package &v3&)'.
WHEN '324'.
rv_text = 'Patch up to the following support packages or implement the SAP
Notes with status RED'.
WHEN '325'.
rv_text = 'Component &v1&; release &v2&; support package level &v3&'.
WHEN '326'.
rv_text = '&v4& SAP Note implemented in version &v3& instead of &v1&:
&object& (&v1&) "&v2&"'.
WHEN '327'.
rv_text = '&v3& SAP Note inconsistent in this system: &object& (&v1&)
"&v2&"'.
WHEN '328'.
rv_text = 'SAP Note not relevant for this system: &object& (&v1&) "&v2&"'.
WHEN '329'.
rv_text = 'SAP Note has no valid correction instruction for this system:
&object& (&v1&) "&v2&"'.
WHEN '330'.
rv_text = 'Function SCWB_NOTES_RESOLVE_NECESSARY is missing'.
WHEN '331'.
rv_text = '&v3& SAP Note implemented but inactive objects exist: &object&
(&v1&) "&v2&"'.
WHEN '332'.
rv_text = '&v3& SAP Note is inconsistent and needs to be downloaded again:
&object& (&v1&) "&v2&"'.
WHEN '333'.
rv_text = '&v3& SAP Note obsolete: &object& (&v1&) "&v2&"'.
WHEN '334'.
rv_text = '&v3& SAP Note needs to be downloaded and implemented: &object&
(&v1&) "&v2&"'.
WHEN '335'.
rv_text = '&v3& SAP Note obsolete and must be deimplemented: &object&
(&v1&) "&v2&"'.
WHEN '336'.
rv_text = '&v3& SAP Note is implemented but outdated and needs to be
downloaded again: &object& (&v1&) "&v2&"'.
WHEN '400'.
rv_text = 'System Profile Parameter Checking Phase'.
WHEN '410'.
rv_text = 'Unsupported option &v1&'.
WHEN '411'.
rv_text = 'Parameter &object& has value &v1&'.
WHEN '500'.
rv_text = 'Scope Checking Phase'.
WHEN '501'.
rv_text = 'Scope "&v1&" loaded'.
WHEN '502'.
rv_text = 'Check restricted to Scope ID &object& and dependent scope IDs'.
WHEN '503'.
rv_text = 'Software component fulfills prerequisites'.
WHEN '601'.
rv_text = 'Number of SAP Notes to be downloaded: &v1&'.
WHEN '602'.
rv_text = 'Number of SAP Notes to be implemented automatically: &v1&'.
WHEN '603'.
rv_text = 'Number of SAP Notes to be implemented with manual activities:
&v1&'.
WHEN '700'.
rv_text = 'System Information'.
WHEN '701'.
rv_text = 'Kernel release &v1& patch level &v2&'.
WHEN '702'.
rv_text = 'R3trans build at &v1&'.
WHEN '703'.
rv_text = 'Installed component "&v1&"'.
WHEN '704'.
rv_text = 'Note Analyzer version &v1& executed on &v2& at &v3&'.
WHEN '705'.
rv_text = 'System is a SAP BW or SAP BW/4HANA system'.
WHEN '706'.
rv_text = 'System is connected to a SAP BW or SAP BW/4HANA system'.
WHEN '707'.
rv_text = 'System ID &v1& Host &v2&'.
WHEN '708'.
rv_text = 'Database name &v1& type &v2& release &v4& DSBL patchlevel &v3&'.
WHEN '709'.
rv_text = 'SAP Patch Manager release &v1& version &v2&'.
WHEN '710'.
rv_text = 'File name: &v2& (type &v2&)'.
WHEN '711'.
rv_text = '&v1& completed successfully'.
WHEN '712'.
rv_text = '&v1& incomplete. Check the yellow and red lights above'.
WHEN '713'.
rv_text = 'System is not modifiable. Apply missing SAP Notes to development
system and transport them'.
WHEN '714'.
rv_text = 'System is not modifiable. Set system change option to
"modifiable" in transaction SE03'.
WHEN '715'.
rv_text = 'Note Analyzer version &v1& is obsolete. Update to version &v2&'.
WHEN '716'.
rv_text = 'Upgrade is running. It''s not recommended to implement any SAP
Notes'.
WHEN '717'.
rv_text = 'Note Assistant is locked. It''s not possible to implement SAP
Notes'.
WHEN '718'.
rv_text = 'SAP Patch Manager is locked. It''s not possible to implement SAP
Notes'.
WHEN '719'.
rv_text = 'Analysis for &v1& version &v2&'.
WHEN '800'.
rv_text = 'Field &v1& is initial'.
WHEN '801'.
rv_text = 'SAP Note &object& check version &v1& differs from validity
version &v2&'.
WHEN '802'.
rv_text = 'SAP Note &object& does not have validity maintained'.
WHEN '803'.
rv_text = 'SAP Note &object& validity missing for component &v1&; release
&v2&; support package &v3&'.
WHEN '804'.
rv_text = 'SAP Note &object& detecting release and patch level failed'.
WHEN '805'.
rv_text = 'Scope id &v1& is not defined but used in scope check'.
WHEN '806'.
rv_text = 'Scope &object& is not defined'.
WHEN '807'.
rv_text = 'Parameter &object& does not exist in this system'.
WHEN '809'.
rv_text = 'Comment for SAP Note &object&; purpose &v1& invalid'.
WHEN '810'.
rv_text = 'SAP Note &object& (position &v2&) has prequisite SAP Note &v1&
(position &v3&) which is in the list after the current one'.
WHEN '811'.
rv_text = 'SAP Note &object& check text &v1& differs from validity text
&v2&'.
WHEN '812'.
rv_text = 'Validation restricted to scope id &object&'.
WHEN '813'.
rv_text = 'Comment for SAP Note &object& missing althought RSUDO mentioned
in manual activity'.
WHEN '814'.
rv_text = 'Manual activity but no comment for SAP Note &object&'.
WHEN OTHERS.
CLEAR rv_text.
ENDCASE.

ENDMETHOD. "get_short_text

METHOD get_long_text.

CASE iv_text_id.
* At most 6 lines with 60 chars each
* Do NOT split words over lines
* _________1_________2_________3_________4_________5_________6
WHEN '100'.
CONCATENATE 'The note analyzer program checks if all required software'
'components exist. If software components or releases are'
'missing, the solution you analyze might not support'
'the software stack of this system.'
INTO rv_text SEPARATED BY space.
WHEN '200'.
CONCATENATE 'The note analyzer program checks which SAP Notes are'
' required to provide a correct analysis and implementation.'
'Implement all required SAP Notes and before you implement'
'SAP Notes of the following SAP Note Checking Phase.'
INTO rv_text SEPARATED BY space.
WHEN '300'.
CONCATENATE 'The note analyzer program checks which SAP Notes are'
'required to run the solution. The program lists which SAP'
'Notes are not implemented and which support packages cover'
'all required SAP Notes in this release.'
INTO rv_text SEPARATED BY space.
WHEN '310'.
CONCATENATE 'This SAP Note requires a software component which does not'
'exist in this system. You got already an error in'
'the component checking phase.'
INTO rv_text SEPARATED BY space.
WHEN '311'.
CONCATENATE 'The content of this SAP Note is already implemented with'
'support package. No further action is needed.'
INTO rv_text SEPARATED BY space.
WHEN '320'.
CONCATENATE 'Implement this SAP Note. The action column indicates if'
'this SAP Note requires manual activities described in the'
'SAP Note. You can jump to the note browser from here.'
'Comments might indicate tools which support manual'
'activites for this SAP Note. Changes in the SAP Notes'
'status are shown after you run the program again.'
INTO rv_text SEPARATED BY space.
WHEN '323'.
CONCATENATE 'The validity of the correction instruction of this SAP Note'
'contains a value which the program cannot represent as a'
'numerical value. The program sets the support package level'
'to 1. Check the SAP Note for the exact value.'
INTO rv_text SEPARATED BY space.
WHEN '326'.
CONCATENATE 'If the implemented version is lower than the version from'
'the XML file, check the SAP Note for further required'
'implementations. Otherwise ignore this message; the SAP'
'Note is more recent than the XML file.'
INTO rv_text SEPARATED BY space.
WHEN '327'.
CONCATENATE 'Check the SAP Note in the note browser for details.'
''
INTO rv_text SEPARATED BY space.
WHEN '329'.
CONCATENATE 'This SAP Note has either no correction instructions for'
'this release or a correction instruction which requires a'
'higher support package level. Read the SAP Note for'
'details.'
INTO rv_text SEPARATED BY space.
WHEN '330'.
CONCATENATE 'This function is needed to check SAP Notes against SAP'
'Marketplace. You need to implement SAP Note 1523687 '
'as a prerequisite. The program terminates the execution.'
INTO rv_text SEPARATED BY space.
WHEN '332'.
CONCATENATE 'The SAP Note data is in some inconsistent state and can'
'not be used for implementing the SAP Note. Typically,'
'this situation is resolved by downloading the SAP Note'
'again. If that does not work, check the SAP Note in'
'transaction SNOTE or create an incident with SAP'
'support for component BC-ABA-NA.'
INTO rv_text SEPARATED BY space.
WHEN '400'.
CONCATENATE 'The note analyzer program checks the system parameters.'
''
INTO rv_text SEPARATED BY space.
WHEN '410'.
CONCATENATE 'This is an error in the XML file.'
'Ignore this message.'
INTO rv_text SEPARATED BY space.
WHEN '500'.
CONCATENATE 'Note analyzer content is divided in scopes. Scopes can be'
'dependent on each other.'
'This phase lists all checked scope IDs.'
INTO rv_text SEPARATED BY space.
WHEN '502'.
CONCATENATE 'You restricted the scope in the selection screen before'
'starting the check.'
'The program derives which other scopes the restricted scope'
'uses and restricts the checking to these scopes.'
INTO rv_text SEPARATED BY space.
WHEN '700'.
CONCATENATE 'The note analyzer program provides information about this'
'system.'
INTO rv_text SEPARATED BY space.
WHEN '711'.
CONCATENATE 'All prerequisites are fulfilled and all SAP Notes have been'
'implemented successfully.'
INTO rv_text SEPARATED BY space.
WHEN '712'.
CONCATENATE 'Either some prerequisites are not fulfilled or some SAP'
'Notes are not completely implemented. Check the warnings'
'and errors and execute the proposed action items.'
INTO rv_text SEPARATED BY space.
WHEN '715'.
CONCATENATE 'The XML file was generated with a new version of the Note'
'Analyzer. Replace this program Z_SAP_BW_NOTE_ANALYZER with'
'the newer version you will find in the same SAP Note that'
'contained the XML file.'
INTO rv_text SEPARATED BY space.
WHEN OTHERS.
CLEAR rv_text.
ENDCASE.

ENDMETHOD. "get_long_text

ENDCLASS. "lcl_msg_repository IMPLEMENTATION

You might also like