image

In this period I’m involved in many upgrade projects and one of the biggest effort is to adjust ABAP copied from SAPstandard ones that I call CLONEs.

In my experience pure custom ABAPs require few adaptations (obsolete statements, obsolete function modules and so on),modifications are also well managed by modification assistant but rearranging clones is a nightmare! They usually contain a lot of INCLUDEs and call a lot of Function Modules that change so much during the upgrade.

The first step to solve a problem is to know where it is. In this case it means to have a working list of CLONEs.

Sergio Ferrari, colleague of mine and SAP mentor, suggested to me to have a look to the function module ‘RS_COMPARE_WORDS_SIMILAR’;it is very powerful and during a night I developed the report that follows.

We extended it with a lot of other logic andit’s now part of the Techedge X-RAY toolbox that we use to analyze SAP ERP system before upgrades and EhP.

The Simple ABAP Clone Hunter (lite), that I’mgoing to share with the community, tries to match each custom ABAP object witha standard one comparing the report name.

The scope of this report is not to identify univocallya standard one but is to give a rated list of possible matches.

Selection screen:

image

Result:

image

Thanks to Sergio Ferrari for the support

Related weblogs:

And now the code!!!! Code is also available through SAPLink on http://code.google.com/p/abapclonehunter/

Create a new report named ZTXRAY_SIMPLECLONEHUNTER with 2 includes:

ZTXRAY_SIMPLECLONEHUNTER

*&———————————————————————*
*& Report  ZTXRAY_SIMPLECLONEHUNTER
*&
*&———————————————————————*
*&
*&
*&———————————————————————*

INCLUDE ZTXRAY_SIMPLECLONEHUNTERTOP                     .    ” global Data

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
PARAMETERS: p_subc TYPE REPOSRC-SUBC OBLIGATORY DEFAULT 1.
SELECT-OPTIONS: so_name FOR gv_name OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE text-002.
PARAMETERS: p_newdat TYPE c RADIOBUTTON GROUP dsrc,
p_show TYPE c RADIOBUTTON GROUP dsrc DEFAULT ’X’.
SELECTION-SCREEN END OF BLOCK b2.

SELECTION-SCREEN BEGIN OF BLOCK b4 WITH FRAME TITLE text-004.
PARAMETERS: pminrate  TYPE INT4 OBLIGATORY DEFAULT 60.
SELECTION-SCREEN END OF BLOCK b4.

INITIALIZATION.
so_name-sign = ’I’.
so_name-option = ’CP’.
so_name-low = ’*’.
append so_name.

START-OF-SELECTION.

* Find custom and standard objects in the system using filters in the selection screen
PERFORM GET_OBJECTS.

IF NOT p_newdat IS INITIAL.
*  Calculate the rating for all the objects found
PERFORM CALCULATE_RATING.
PERFORM PREPARE_OUTPUT.
PERFORM SAVEDATA.
ELSE.
PERFORM PREPARE_OUTPUT.
ENDIF.

* Display the output
PERFORM DISPLAYDATA.

SELECTION-SCREEN BEGIN OF SCREEN 1001.
SELECTION-SCREEN END OF SCREEN 1001.
CALL SELECTION-SCREEN 1001.

INCLUDE ZTXRAY_SIMPLECLONEHUNTERF01.

ZTXRAY_SIMPLECLONEHUNTERTOP

*&———————————————————————*
*& Include ZTXRAY_SIMPLECLONEHUNTERTOP                              Report ZTXRAY_SIMPLECLONEHUNTER
*&
*&———————————————————————*

REPORT ZTXRAY_SIMPLECLONEHUNTER.

TYPES: BEGIN OF ZTXRAY_OBJECTLIST_S,
SUBC  TYPE SUBC,
FIXPT  TYPE FIXPT,
LDBNAME  TYPE LDBNAM,
NAME  TYPE PROGNAME,
STATE  TYPE R3STATE,
END OF ZTXRAY_OBJECTLIST_S.

DATA: gt_cus_list TYPE SORTED TABLE OF ZTXRAY_OBJECTLIST_S WITH UNIQUE KEY SUBC LDBNAME FIXPT NAME,
gs_cus_list TYPE ZTXRAY_OBJECTLIST_S,
gt_std_list TYPE SORTED TABLE OF ZTXRAY_OBJECTLIST_S WITH UNIQUE KEY SUBC LDBNAME FIXPT NAME,
gs_std_list TYPE ZTXRAY_OBJECTLIST_S.

DATA: gt_clones TYPE SORTED TABLE OF ZTXRAY_CLONE WITH UNIQUE KEY SYSID SUBC OBJ_NAME STD_NAME,
gs_clones TYPE ZTXRAY_CLONE,
gt_save_clones TYPE TABLE OF ZTXRAY_CLONE,
gs_save_clones TYPE ZTXRAY_CLONE.

DATA: gt_alv_clones TYPE TABLE OF ZTXRAY_CLONE,
gs_alv_clones TYPE ZTXRAY_CLONE.

DATA: gv_name TYPE PROGDIR-NAME.

DATA  gr_repn TYPE RANGE OF progdir-name.
DATA  gr_cnam TYPE RANGE OF progdir-cnam.

ZTXRAY_SIMPLECLONEHUNTERF01

*———————————————————————-*
***INCLUDE ZTXRAY_SIMPLECLONEHUNTERF01.
*———————————————————————-*
FORM GET_OBJECTS.

REFRESH: gt_cus_list, gt_std_list.

IF NOT p_newdat IS INITIAL.

PERFORM GET_SO_NAME_CUSTOM USING ’X’.
PERFORM GET_SO_AUTHOR USING ”.

SELECT * INTO CORRESPONDING FIELDS OF TABLE gt_cus_list
FROM PROGDIR
WHERE
name IN so_name AND
name IN gr_repn AND
subc  = p_subc AND
clas  <> ’$TMP’ AND
cnam IN gr_cnam AND
state = ’A’.

PERFORM GET_SO_NAME_CUSTOM USING ”.
PERFORM GET_SO_AUTHOR USING ’X’.

SELECT * INTO CORRESPONDING FIELDS OF TABLE gt_std_list
FROM PROGDIR
WHERE
name IN gr_repn AND
subc  = p_subc AND
clas  <> ’$TMP’ AND
cnam IN gr_cnam AND
state = ’A’.

ELSE.
SELECT * INTO TABLE gt_clones
FROM ZTXRAY_CLONE
WHERE
OBJ_NAME  IN so_name AND
SUBC      = p_subc.
ENDIF.

ENDFORM.                    ”GET_OBJECTS
*&———————————————————————*
*&      Form  CALCULATE_RATING
*&———————————————————————*
*       text
*———————————————————————-*
FORM CALCULATE_RATING .

DATA: lt_mainprograms TYPE TABLE OF D010INC-MASTER,
ls_mainprograms TYPE D010INC-MASTER.

DATA: lt_clones_tmp LIKE gt_clones,
ls_clones_tmp LIKE LINE OF lt_clones_tmp,
lt_clones LIKE gt_clones,
ls_clones LIKE LINE OF lt_clones.

DATA: lv_flag_similar TYPE flag.

CLEAR: gs_cus_list, gs_clones.
REFRESH gt_clones.

LOOP AT gt_cus_list INTO gs_cus_list.

IF gs_cus_list-subc = ’1′ OR
gs_cus_list-subc = ’F' OR
gs_cus_list-subc = ’M’.

PERFORM CHECK_ATTRIBUTES CHANGING lt_clones_tmp.

LOOP AT lt_clones_tmp INTO ls_clones_tmp.

*          Check custom name set rating
PERFORM CHECK_NAME
USING
ls_clones_tmp-obj_name
ls_clones_tmp-std_name
CHANGING
lv_flag_similar
ls_clones_tmp-rating.

IF lv_flag_similar IS NOT INITIAL AND ls_clones_tmp-rating GE pminrate.
*        Save all the ratings calculated
INSERT ls_clones_tmp INTO TABLE gt_clones.

ENDIF.
ENDLOOP.

ELSE.
** Now these objects are not considered
CONTINUE.
ENDIF.

ENDLOOP.

ENDFORM.                    ”CALCULATE_RATING
*&———————————————————————*
*&      Form  SAVEDATA
*&———————————————————————*
*       text
*———————————————————————-*
FORM SAVEDATA .

* Delete data with the same subc
DELETE FROM ZTXRAY_CLONE WHERE SUBC = p_subc.
COMMIT WORK AND WAIT.

* Store data
INSERT ZTXRAY_CLONE FROM TABLE gt_save_clones.
COMMIT WORK AND WAIT.

ENDFORM.                    ”SAVEDATA
*&———————————————————————*
*&      Form  DISPLAYDATA
*&———————————————————————*
*       text
*———————————————————————-*
FORM DISPLAYDATA .

data:
go_layout     TYPE LVC_S_LAYO,                  ” layout options
lt_sort       TYPE LVC_T_SORT,                  ” sorting options
wa_sort       TYPE LINE OF LVC_T_SORT,          ” sorting options
lt_exclude    TYPE UI_FUNCTIONS,                ” excluded functions
wa_exclude    TYPE UI_FUNC,                     ” excluded functions
lt_fieldcatalog TYPE LVC_T_FCAT,                ” field catalog
wa_fieldcatalog TYPE LINE OF LVC_T_FCAT,        ” field catalog
go_container  TYPE REF TO CL_GUI_CONTAINER,     ” container
go_alv        TYPE REF TO CL_GUI_ALV_GRID,       ” ALV
go_variant    TYPE DISVARIANT.                  ” For parameter IS_VARIANT

TRY.
*======================= VARIANT ===================================*
go_variant-report = sy-repid.
*===================================================================*

*======================= LAYOUT ====================================*
go_layout-ZEBRA      = ’X’.
go_layout-GRID_TITLE = ’Clone hunter’.
*===================================================================*

*========================= SORT ====================================*
wa_sort-DOWN          = ’X’.
wa_sort-FIELDNAME     = ’RATING’.
APPEND wa_sort TO lt_sort.
CLEAR wa_sort.
*===================================================================*

*==================== FIELD CATALOG ================================*

wa_fieldcatalog-FIELDNAME = ’OBJ_NAME’.
wa_fieldcatalog-REF_TABLE = ’ZTXRAY_CLONE’.
wa_fieldcatalog-REF_FIELD = ’OBJ_NAME’.
APPEND wa_fieldcatalog TO lt_fieldcatalog.
CLEAR wa_fieldcatalog.
wa_fieldcatalog-FIELDNAME = ’STD_NAME’.
wa_fieldcatalog-REF_TABLE = ’ZTXRAY_CLONE’.
wa_fieldcatalog-REF_FIELD = ’STD_NAME’.
APPEND wa_fieldcatalog TO lt_fieldcatalog.
CLEAR wa_fieldcatalog.
wa_fieldcatalog-FIELDNAME = ’RATING’.
wa_fieldcatalog-REF_TABLE = ’ZTXRAY_CLONE’.
wa_fieldcatalog-REF_FIELD = ’RATING’.
wa_fieldcatalog-COLTEXT   = text-101.
wa_fieldcatalog-SCRTEXT_L = text-102.
wa_fieldcatalog-SCRTEXT_M = text-103.
wa_fieldcatalog-SCRTEXT_S = text-104.
APPEND wa_fieldcatalog TO lt_fieldcatalog.
CLEAR wa_fieldcatalog.
*===================================================================*
CREATE OBJECT go_alv
EXPORTING
i_parent = cl_gui_container=>screen0.

CREATE OBJECT go_container
EXPORTING
clsid = SPACE.

go_alv->set_graphics_container(
EXPORTING
I_GRAPHICS_CONTAINER = go_container
).

go_alv->set_table_for_first_display(
EXPORTING
IS_LAYOUT            = go_layout
IS_VARIANT           = go_variant
I_SAVE               = ’A’
IT_TOOLBAR_EXCLUDING = lt_exclude
CHANGING
it_outtab        = gt_alv_clones
IT_SORT          = lt_sort
IT_FIELDCATALOG  = lt_fieldcatalog
).

ENDTRY.

ENDFORM.                    ”DISPLAYDATA
*&———————————————————————*
*&      Form  CHECK_NAME
*&———————————————————————*
*       Check two string
*———————————————————————-*
*      –>P_NAME1         custom report name
*      –>P_NAME2         standard report name
*      –>P_FLAG_SIMILAR  if checked name are similar
*      –>P_RATING        rate max value 100
*———————————————————————-*
FORM CHECK_NAME USING p_name1 TYPE PROGNAME
p_name2 TYPE PROGNAME
CHANGING p_flag_similar p_rating.

DATA: lv_name1 LIKE p_name1,
lv_name2 LIKE p_name2.

lv_name1 = p_name1.
lv_name2 = p_name2.

IF  p_subc = ’M' AND p_name1(4) = ’SAPM’.
lv_name1 = p_name1+4.
ENDIF.

IF  p_subc = ’M' AND p_name2(4) = ’SAPM’.
lv_name2 = p_name2+4.
ENDIF.

IF  p_subc = ’F' AND p_name1(4) = ’SAPF’.
lv_name1 = p_name1+4.
ENDIF.

IF  p_subc = ’F' AND p_name2(4) = ’SAPF’.
lv_name2 = p_name2+4.
ENDIF.

CALL FUNCTION ’RS_COMPARE_WORDS_SIMILAR’
EXPORTING
word1         = lv_name1
word2         = lv_name2
IMPORTING
similar       = p_flag_similar
word_distance = p_rating.

p_rating = 100 - p_rating.

ENDFORM.                    ”CHECK_NAME
*&———————————————————————*
*&      Form  CHECK_ATTRIBUTES
*&———————————————————————*
*       text
*———————————————————————-*
*      –>P_T_CLONES table of similar objects
*———————————————————————-*
FORM CHECK_ATTRIBUTES  CHANGING P_T_CLONES LIKE gt_clones.

DATA: ls_clones LIKE LINE OF p_t_clones.

REFRESH: p_t_clones.

LOOP AT gt_std_list INTO gs_std_list WHERE
subc    = gs_cus_list-subc AND
ldbname = gs_cus_list-ldbname AND
fixpt   = gs_cus_list-fixpt.

CLEAR ls_clones.

ls_clones-sysid     = sy-sysid.
ls_clones-subc      = gs_cus_list-subc.
ls_clones-obj_name  = gs_cus_list-name.
ls_clones-std_name  = gs_std_list-name.
APPEND ls_clones TO p_t_clones.
ENDLOOP.

ENDFORM.                    ”CHECK_ATTRIBUTES

*&———————————————————————*
*&      Form  GET_SO_NAME_CUSTOM
*&———————————————————————*
*       text
*———————————————————————-*
*      –>INCLUDE    if checked Custom name are included
*———————————————————————-*
FORM GET_SO_NAME_CUSTOM  USING    INCLUDE_CUSTOM TYPE CHAR1.

DATA: lrl_repn LIKE LINE OF gr_repn,
lv_sign(1) TYPE c VALUE ’I’.

REFRESH gr_repn.

IF INCLUDE_CUSTOM IS INITIAL.
lv_sign = ’E’.
ENDIF.

lrl_repn-sign   = lv_sign.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’Z*’.
APPEND lrl_repn TO gr_repn.
lrl_repn-sign   = lv_sign.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’Y*’.
APPEND lrl_repn TO gr_repn.
lrl_repn-sign   = lv_sign.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’SAPLZ*’.
APPEND lrl_repn TO gr_repn.
lrl_repn-sign   = lv_sign.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’SAPLY*’.
APPEND lrl_repn TO gr_repn.
lrl_repn-sign   = lv_sign.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’SAPMZ*’.
APPEND lrl_repn TO gr_repn.
lrl_repn-sign   = lv_sign.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’SAPMY*’.
APPEND lrl_repn TO gr_repn.

* Always excluded
lrl_repn-sign   = ’E’.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’/*’.
APPEND lrl_repn TO gr_repn.
lrl_repn-sign   = ’E’.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’%*’.
APPEND lrl_repn TO gr_repn.
lrl_repn-sign   = ’E’.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’:*’.
APPEND lrl_repn TO gr_repn.
lrl_repn-sign   = ’E’.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’>*’.
APPEND lrl_repn TO gr_repn.
lrl_repn-sign   = ’E’.
lrl_repn-option = ’CP’.
lrl_repn-low    = ’&*’.
APPEND lrl_repn TO gr_repn.

ENDFORM.                    ”GET_SO_NAME_CUSTOM
*&———————————————————————*
*&      Form  GET_SO_AUTHOR
*&———————————————————————*
*       text
*———————————————————————-*
*      –>SAP_AUTHOR if checked SAP default user are included
*———————————————————————-*
FORM GET_SO_AUTHOR  USING    SAP_AUTHOR TYPE CHAR1.

DATA: lrl_cnam LIKE LINE OF gr_cnam,
lv_sign(1) TYPE c VALUE ’I’.

REFRESH gr_cnam.

IF SAP_AUTHOR IS INITIAL.
lv_sign = ’E’.
ENDIF.

lrl_cnam-sign   = lv_sign.
lrl_cnam-option = ’EQ’.
lrl_cnam-low    = ’SAP’.
APPEND lrl_cnam TO gr_cnam.
lrl_cnam-sign   = lv_sign.
lrl_cnam-option = ’EQ’.
lrl_cnam-low    = ’DDIC’.
APPEND lrl_cnam TO gr_cnam.

ENDFORM.                    ”GET_SO_AUTHOR
*&———————————————————————*
*&      Form  PREPARE_OUTPUT
*&———————————————————————*
*       text
*———————————————————————-*
FORM PREPARE_OUTPUT.

DATA: lv_rated TYPE i.

REFRESH: gt_alv_clones, gt_save_clones.
CLEAR: gs_alv_clones, gs_save_clones.

* Calculate total rating
LOOP AT gt_clones INTO gs_clones WHERE rating GE pminrate.

MOVE-CORRESPONDING gs_clones TO gs_save_clones.
APPEND gs_save_clones TO gt_save_clones.
CLEAR gs_save_clones.

MOVE-CORRESPONDING gs_clones TO gs_alv_clones.
APPEND gs_alv_clones TO gt_alv_clones.
CLEAR gs_alv_clones.

ENDLOOP.

ENDFORM.                    ”PREPARE_OUTPUT


Selection text

Name
Text
Dictionary
PMINRATE Minumum rate
P_NEWDAT Find and store rating
P_SHOW Display stored data
P_SUBC Program type X
SO_NAME Program Name X

Data dictionary objects

Transparent Table ZTXRAY_CLONE

Field
Key Initial
Data element
SUBC X X SUBC
OBJ_NAME X X PROGNAME
STD_NAME X X PROGNAME
RATING X INT4

Related posts:

  1. Galaxy wars with ABAP
  2. SAP obsolete functions (2) – CL_GUI_FRONTEND_SERVICES
  3. SAP obsolete functions (1) – POPUP_TO_CONFIRM