* ,----, * ,/ .`| ,----, ,----.. ,--. * ,` .' : ,---, .' .`| / / \ ,--.'| ,---,. * ; ; /,--.' | .' .' ; / . : ,--,: : | ,' .' | * .'___,/ ,' | | : ,---, ' .'. / ;. \,`--.'`| ' :,---.' | * | : | : : : | : ./. ; / ` ;| : : | || | .' * ; |.'; ; : | |,--. ,---. ; | .' / ; | ; \ ; |: | \ | :: : |-, * `----' | | | : ' | / \ `---' / ; | : | ; | '| : ' '; |: | ;/| * ' : ; | | /' : / / | / ; / . | ' ' ' :' ' ;. ;| : .' * | | ' ' : | | |. ' / | ; / /--, ' ; \; / || | | \ || | |-, * ' : | | | ' | :' ; /| / / / .`| \ \ ', / ' : | ; .'' : ;/| * ; |.' | : :_:,'' | / | ./__; : ; : / | | '`--' | | \ * '---' | | ,' | : | | : .' \ \ .' ' : | | : .' * `--'' \ \ / ; | .' `---` ; |.' | | ,' * `----' `---' '---' `----' * Home of custom build re-usable components * "! Welcome to the ZONE documentation tool for re-usable components. Feel free to add your "! own groups with classes, reports, function modules and tables directly into the source coding of "! include ZONE_SCRIPT of this report. "! REPORT zone. DATA gv_okcode TYPE sy-ucomm. DATA gt_documentheader TYPE STANDARD TABLE OF char255. DATA: BEGIN OF gs_images, logo TYPE c LENGTH 170, background TYPE c LENGTH 170, END OF gs_images. CLASS lcl_event_receiver DEFINITION. PUBLIC SECTION. CLASS-METHODS handle_sapevent FOR EVENT sapevent OF cl_gui_html_viewer IMPORTING getdata query_table. ENDCLASS. CLASS lcl_document_groups DEFINITION DEFERRED. CLASS lcl_component_documentor DEFINITION. PUBLIC SECTION. CONSTANTS: co_undetermined TYPE c LENGTH 20 VALUE '~???~', co_field_error TYPE c LENGTH 25 VALUE '(no description)'. TYPES: BEGIN OF gty_docline, linenr TYPE i, content TYPE string, END OF gty_docline. TYPES: gty_doclines TYPE SORTED TABLE OF gty_docline WITH UNIQUE KEY linenr. TYPES: BEGIN OF gty_parameter, linenr TYPE i, parameter TYPE string, pardecltyp TYPE seopardecl, "0=importing, 1=exporting, 2= changing, 3= returning, 9=exception datatype TYPE string, optional TYPE boolean, END OF gty_parameter. TYPES: gty_parameters TYPE SORTED TABLE OF gty_parameter WITH UNIQUE KEY linenr. TYPES: BEGIN OF gty_class_details, author TYPE vseoclass-author, createdon TYPE vseoclass-createdon, changedby TYPE vseoclass-changedby, changedon TYPE vseoclass-changedon, superclass TYPE seoclsname, interfaces TYPE string, linecount TYPE int4, methods TYPE int4, redefinitions TYPE int4, filter_on_methods TYPE boolean, message TYPE string, END OF gty_class_details. TYPES: BEGIN OF gty_report_details, cnam TYPE trdir-cnam, cdat TYPE trdir-cdat, unam TYPE trdir-unam, udat TYPE trdir-udat, includes TYPE SORTED TABLE OF char80 WITH UNIQUE KEY table_line, linecount TYPE sy-dbcnt, END OF gty_report_details. TYPES: BEGIN OF gty_function_details, author TYPE tadir-author, created_on TYPE tadir-created_on, area TYPE enlfdir-area, linecount TYPE sy-dbcnt, hitcount TYPE sy-dbcnt, END OF gty_function_details. TYPES: BEGIN OF gty_table_details, created_by TYPE e070-as4user, created_on TYPE e070-as4date, changed_by TYPE dd02l-as4user, changed_on TYPE dd02l-as4date, maintenance TYPE boolean, dd03l TYPE SORTED TABLE OF dd03l WITH UNIQUE KEY position fieldname, END OF gty_table_details. TYPES: BEGIN OF gty_component, component_type TYPE string, component_name TYPE string, description TYPE string, abapdoc TYPE gty_doclines, attvalue TYPE string, parameters TYPE gty_parameters, read_only TYPE boolean, method_hitcount TYPE sy-dbcnt, class TYPE gty_class_details, report TYPE gty_report_details, function TYPE gty_function_details, table TYPE gty_table_details, devclass TYPE tadir-devclass, devclass_text TYPE tdevct-ctext, redefinition TYPE boolean, END OF gty_component. TYPES: BEGIN OF gty_user, user TYPE sy-uname, fullname TYPE bapiaddr3-fullname, END OF gty_user. TYPES: BEGIN OF ty_devclass, devclass TYPE tdevc-devclass, parentcl TYPE tdevc-parentcl, ctext_E TYPE tdevct-ctext, ctext_N TYPE tdevct-ctext, relevant TYPE boolean, objectcounter TYPE int2, tadircounter TYPE int2, END OF ty_devclass. CLASS-DATA gt_devclass TYPE SORTED TABLE OF ty_devclass WITH UNIQUE KEY devclass WITH UNIQUE SORTED KEY via_parents COMPONENTS parentcl devclass. DATA gt_abap TYPE STANDARD TABLE OF string. DATA gt_components TYPE STANDARD TABLE OF gty_component. CLASS-DATA gt_users TYPE SORTED TABLE OF gty_user WITH UNIQUE KEY user. METHODS constructor IMPORTING iv_only_methods TYPE string iv_type TYPE string iv_name TYPE string iv_abapdoc TYPE string. CLASS-METHODS get_zone_version RETURNING VALUE(rv_version_str) TYPE string. CLASS-METHODS get_username IMPORTING iv_user TYPE sy-uname RETURNING VALUE(rv_fullname) TYPE bapiaddr3-fullname. CLASS-METHODS get_sap_description IMPORTING fieldreference TYPE any language TYPE sy-langu DEFAULT sy-langu RETURNING VALUE(description) TYPE text80. CLASS-METHODS read_developmentclasses. PRIVATE SECTION. METHODS complex_definitions IMPORTING component_type TYPE string start_tabix TYPE sy-tabix. METHODS string_to_abapdoc IMPORTING iv_string TYPE string RETURNING VALUE(rt_abapdoc) TYPE gty_doclines. METHODS read_class IMPORTING iv_classname TYPE seoclsname iv_only_methods TYPE string iv_abapdoc TYPE string. METHODS read_report IMPORTING iv_report TYPE sy-repid iv_abapdoc TYPE string. METHODS read_table IMPORTING iv_table TYPE string iv_abapdoc TYPE string. METHODS read_function IMPORTING iv_function TYPE string iv_abapdoc TYPE string. ENDCLASS. CLASS lcl_document_groups DEFINITION. PUBLIC SECTION. TYPES: BEGIN OF gty_link, label TYPE string, link TYPE string, END OF gty_link. TYPES: BEGIN OF gty_review, date TYPE d, uname TYPE sy-uname, username TYPE string, rating TYPE n LENGTH 1, "0 to 5 stars summary TYPE string, remarks TYPE string, END OF gty_review. TYPES: BEGIN OF gty_playlistentry, object_type TYPE string, object_name TYPE string, tagwords TYPE string, only_methods TYPE string, "Comma delimited list of method names that should be presented abapdoc TYPE string, links TYPE SORTED TABLE OF gty_link WITH UNIQUE KEY label link, reviews TYPE SORTED TABLE OF gty_review WITH UNIQUE KEY date uname, END OF gty_playlistentry. TYPES gty_playlist TYPE STANDARD TABLE OF gty_playlistentry. TYPES: BEGIN OF gty_group_object, id TYPE sy-tabix, object_type TYPE string, object_name TYPE string, components TYPE REF TO lcl_component_documentor, links TYPE SORTED TABLE OF gty_link WITH UNIQUE KEY label link, tagwords TYPE string, reviews TYPE SORTED TABLE OF gty_review WITH UNIQUE KEY date uname, created TYPE d, changed TYPE d, END OF gty_group_object. TYPES: BEGIN OF gty_group, description TYPE string, summary TYPE string, objects TYPE SORTED TABLE OF gty_group_object WITH UNIQUE KEY id, created TYPE d, changed TYPE d, END OF gty_group. TYPES: BEGIN OF gty_content, label TYPE string, value TYPE string, username TYPE sy-uname, datevalue TYPE d, END OF gty_content. TYPES: gty_content_tt TYPE STANDARD TABLE OF gty_content. "SVG image repository DATA gt_svg_class TYPE STANDARD TABLE OF char255. DATA gt_svg_report TYPE STANDARD TABLE OF char255. DATA gt_svg_function TYPE STANDARD TABLE OF char255. DATA gt_svg_table TYPE STANDARD TABLE OF char255. DATA gv_svg_mini_icon TYPE char255. DATA gv_svg_mini_icon2 TYPE char255. DATA gt_svg_exporting TYPE STANDARD TABLE OF char255. DATA gt_svg_importing TYPE STANDARD TABLE OF char255. DATA gt_svg_changing TYPE STANDARD TABLE OF char255. DATA gt_svg_returning TYPE STANDARD TABLE OF char255. DATA gt_svg_parameter TYPE STANDARD TABLE OF char255. DATA gt_svg_selectoption TYPE STANDARD TABLE OF char255. DATA gt_svg_exception TYPE STANDARD TABLE OF char255. DATA gt_svg_screw TYPE STANDARD TABLE OF char255. DATA gt_svg_star_empty TYPE STANDARD TABLE OF char255. DATA gt_svg_star TYPE STANDARD TABLE OF char255. DATA gt_svg_lapse TYPE STANDARD TABLE OF char255. DATA go_html_control TYPE REF TO cl_gui_html_viewer. DATA go_container TYPE REF TO cl_gui_custom_container. DATA gt_myevents TYPE cntl_simple_events. DATA go_event_receiver TYPE REF TO lcl_event_receiver. DATA gt_html TYPE STANDARD TABLE OF char255. DATA gv_url TYPE c LENGTH 200. DATA: BEGIN OF gs_counters, groups TYPE i, objects TYPE i, classes TYPE i, methods TYPE i, classmethods TYPE i, tables TYPE i, reports TYPE i, functions TYPE i, END OF gs_counters. CLASS-DATA gt_groups TYPE STANDARD TABLE OF gty_group. CLASS-DATA gv_id TYPE sy-tabix. CLASS-METHODS set_group IMPORTING iv_description TYPE string iv_summary TYPE string DEFAULT '' it_playlist TYPE gty_playlist. METHODS string_to_html IMPORTING iv_string TYPE string. METHODS set_html_style. METHODS set_svg_images. METHODS set_age_color IMPORTING iv_date TYPE d RETURNING VALUE(rv_color) TYPE char10. METHODS harvest_counters. METHODS harvest_developmentclasses. METHODS print_developmentclass IMPORTING iv_level TYPE int2 iv_devclass TYPE lcl_component_documentor=>ty_devclass. METHODS harvest_dates. METHODS set_abapdoc IMPORTING it_abapdoc TYPE lcl_component_documentor=>gty_doclines. METHODS set_group_header IMPORTING iv_groupnr TYPE sy-tabix is_group TYPE gty_group. CLASS-METHODS get_date_summary IMPORTING iv_date TYPE d RETURNING VALUE(rv_result) TYPE string. METHODS set_all_tagwords IMPORTING is_group TYPE gty_group. METHODS set_tagwords IMPORTING iv_tagwords TYPE string. METHODS set_parameter_svg IMPORTING iv_parameter_type TYPE any. METHODS set_links IMPORTING is_object TYPE gty_group_object. METHODS set_reviews IMPORTING is_object TYPE gty_group_object. METHODS set_object_header IMPORTING is_object TYPE gty_group_object. METHODS set_group_detail IMPORTING iv_created_by TYPE sy-uname iv_created_on TYPE sy-datum it_content TYPE gty_content_tt. METHODS filter_focus IMPORTING iv_devclass TYPE devclass. METHODS zone_reporter. PRIVATE SECTION. METHODS mini_dot_as_svg IMPORTING iv_object_type TYPE string iv_medium TYPE boolean DEFAULT abap_false RETURNING VALUE(rv_colored_dot) TYPE char255. ENDCLASS. CLASS lcl_event_receiver IMPLEMENTATION. METHOD handle_sapevent. DATA lv_devclass TYPE devclass. SPLIT getdata AT '=' INTO TABLE DATA(lt_tokens). lv_devclass = COND #( WHEN lines( lt_tokens ) = 2 THEN lt_tokens[ 2 ] ELSE '' ). "Execute a refresh SUBMIT zone WITH pa_devcl = lv_devclass. ENDMETHOD. ENDCLASS. CLASS lcl_component_documentor IMPLEMENTATION. METHOD constructor. CASE iv_type. WHEN 'CLASS'. read_class( iv_classname = |{ iv_name }| iv_only_methods = iv_only_methods iv_abapdoc = iv_abapdoc ). WHEN 'REPORT'. read_report( iv_report = |{ iv_name }| iv_abapdoc = iv_abapdoc ). WHEN 'TABLE'. read_table( iv_table = |{ iv_name }| iv_abapdoc = iv_abapdoc ). WHEN 'FUNCTION'. read_function( iv_function = |{ iv_name }| iv_abapdoc = iv_abapdoc ). ENDCASE. ENDMETHOD. METHOD complex_definitions. DATA lv_finish_tabix TYPE sy-tabix. DATA lt_cleanabap TYPE STANDARD TABLE OF string. DATA lv_cleanabapline TYPE string. DATA lv_structurevariabele TYPE string. DATA lt_abapdoc TYPE gty_doclines. DATA lv_component_type TYPE string. DATA lv_value TYPE string. FIELD-SYMBOLS TYPE gty_component. lv_component_type = to_upper( component_type ). REPLACE ':' IN lv_component_type WITH ''. "Focus on the coding between : and . - first find the . (dot) LOOP AT gt_abap FROM start_tabix INTO DATA(lv_abapline). DATA(lv_loop_tabix) = sy-tabix. SHIFT lv_abapline LEFT DELETING LEADING space. "Opening line: remove the component_type IF lv_loop_tabix = start_tabix. SHIFT lv_abapline LEFT BY strlen( component_type ) PLACES. ENDIF. CONDENSE lv_abapline. " ABAP doc comments IF strlen( lv_abapline ) > 3 AND lv_abapline(2) = '"!'. APPEND lv_abapline TO lt_cleanabap. CONTINUE. ENDIF. SPLIT lv_abapline AT '"' INTO lv_abapline DATA(lv_comments). "Strip comments lv_cleanabapline = |{ lv_cleanabapline } { lv_abapline }|. IF lv_cleanabapline CA '.,'. SHIFT lv_cleanabapline LEFT DELETING LEADING space. "Cut out the TYPE definition SPLIT lv_cleanabapline AT space INTO TABLE DATA(lt_tokens). IF lines( lt_tokens ) > 2. IF to_upper( lt_tokens[ 2 ] ) = 'TYPE'. "TYPE REF TO IF to_upper( lt_tokens[ 3 ] ) = 'REF'. DELETE lt_tokens FROM 2 TO 5. ELSE. DELETE lt_tokens FROM 2 TO 3. ENDIF. ELSEIF to_upper( lt_tokens[ 2 ] ) = 'FOR' OR to_upper( lt_tokens[ 2 ] ) = 'LIKE'. DELETE lt_tokens FROM 2 TO 3. ENDIF. ENDIF. CLEAR lv_cleanabapline. LOOP AT lt_tokens INTO DATA(lv_token). CONCATENATE lv_cleanabapline lv_token INTO lv_cleanabapline SEPARATED BY space. ENDLOOP. SHIFT lv_cleanabapline LEFT DELETING LEADING space. REPLACE ',' IN lv_cleanabapline WITH ''. APPEND lv_cleanabapline TO lt_cleanabap. CLEAR lv_cleanabapline. ENDIF. IF lv_abapline CS '.'. lv_finish_tabix = sy-tabix. EXIT. ENDIF. ENDLOOP. LOOP AT lt_cleanabap INTO lv_cleanabapline. IF strlen( lv_cleanabapline ) > 2 AND lv_cleanabapline(2) = '"!'. INSERT VALUE gty_docline( linenr = lines( lt_abapdoc ) content = lv_cleanabapline+2 ) INTO TABLE lt_abapdoc. CONTINUE. ENDIF. SPLIT lv_cleanabapline AT space INTO TABLE lt_tokens. CASE lv_component_type. WHEN 'SELECT-OPTIONS' OR 'PARAMETERS'. WHEN OTHERS. IF to_upper( lt_tokens[ 1 ] ) = 'BEGIN'. lv_structurevariabele = |{ to_upper( lt_tokens[ 3 ] ) }|. APPEND VALUE gty_component( component_type = lv_component_type component_name = lv_structurevariabele ) TO gt_components ASSIGNING . APPEND LINES OF lt_abapdoc TO -abapdoc. CLEAR lt_abapdoc. * lv_structurevariabele = '    '. CLEAR lv_structurevariabele. CONTINUE. ENDIF. IF to_upper( lt_tokens[ 1 ] ) = 'END'. CLEAR lv_structurevariabele. CONTINUE. ENDIF. ENDCASE. lv_value = COND #( WHEN ( lines( lt_tokens ) >= 3 ) AND ( to_upper( lt_tokens[ 2 ] ) = 'VALUE' ) THEN lt_tokens[ 3 ] ELSE '' ). APPEND VALUE gty_component( component_type = lv_component_type component_name = |{ lv_structurevariabele }{ to_upper( lt_tokens[ 1 ] ) }| attvalue = lv_value ) TO gt_components ASSIGNING . APPEND LINES OF lt_abapdoc TO -abapdoc. CLEAR lt_abapdoc. ENDLOOP. IF lv_finish_tabix > 0. "Structure too complex if no end line available lv_finish_tabix = lv_finish_tabix + start_tabix. "Clean up the block of coding that was interpreted - to ensure the regular processing remains LOOP AT gt_abap FROM start_tabix TO lv_finish_tabix ASSIGNING FIELD-SYMBOL(). CLEAR . ENDLOOP. ENDIF. ENDMETHOD. METHOD string_to_abapdoc. DATA lt_string_components TYPE STANDARD TABLE OF swastrtab. CHECK strlen( iv_string ) > 0. CALL FUNCTION 'SWA_STRING_SPLIT' EXPORTING input_string = iv_string max_component_length = 70 TABLES string_components = lt_string_components. LOOP AT lt_string_components INTO DATA(ls_string_component). APPEND VALUE #( linenr = lines( rt_abapdoc ) content = ls_string_component-str ) TO rt_abapdoc. ENDLOOP. ENDMETHOD. METHOD get_zone_version. SELECT SINGLE unam, udat FROM trdir INTO @DATA(ls_trdir) WHERE name = 'ZONE_SCRIPT'. IF ls_trdir-udat = sy-datum. rv_version_str = |Last zone_script update today by { get_username( ls_trdir-unam ) } ({ ls_trdir-unam })|. ELSE. rv_version_str = |Last zone_script update on { ls_trdir-udat DATE = USER } ({ lcl_document_groups=>get_date_summary( iv_date = ls_trdir-udat ) }) | && | by { get_username( ls_trdir-unam ) } ({ ls_trdir-unam })|. ENDIF. rv_version_str = |{ rv_version_str } (click to refresh)|. ENDMETHOD. METHOD get_username. DATA ls_address TYPE bapiaddr3. DATA lt_return TYPE STANDARD TABLE OF bapiret2. READ TABLE gt_users WITH KEY user = iv_user INTO DATA(ls_user). IF sy-subrc <> 0. CALL FUNCTION 'BAPI_USER_GET_DETAIL' EXPORTING username = iv_user IMPORTING address = ls_address TABLES return = lt_return. ls_user = VALUE #( user = iv_user fullname = ls_address-fullname ). INSERT ls_user INTO TABLE gt_users. ENDIF. rv_fullname = ls_user-fullname. ENDMETHOD. METHOD get_sap_description. DATA: lv_tabname TYPE c LENGTH 20, lv_fieldname TYPE c LENGTH 25, lv_description TYPE dd03t-ddtext, lv_rollname TYPE dd03l-rollname. * Fetch SAP description if possible: CLEAR lv_description. IF NOT fieldreference IS INITIAL. lv_description = co_undetermined. SPLIT fieldreference AT '-' INTO lv_tabname lv_fieldname. IF NOT lv_fieldname IS INITIAL. SELECT ddtext FROM dd03t INTO lv_description UP TO 1 ROWS WHERE tabname = lv_tabname AND fieldname = lv_fieldname AND as4local = 'A' AND ddlanguage = language. ENDSELECT. IF sy-subrc <> 0 OR lv_description IS INITIAL. SELECT rollname FROM dd03l INTO lv_rollname UP TO 1 ROWS WHERE tabname = lv_tabname AND fieldname = lv_fieldname AND as4local = 'A' AND as4vers = 0000. ENDSELECT. IF sy-subrc = 0. SELECT SINGLE scrtext_l FROM dd04t INTO @DATA(lv_scrtext_l) WHERE rollname = @lv_rollname AND ddlanguage = @language AND as4local = 'A' AND as4vers = 0000. IF sy-subrc = 0. lv_description = lv_scrtext_l. ELSE. lv_description = co_field_error. ENDIF. ENDIF. ENDIF. ELSE. * Structure name ? SELECT ddtext FROM dd02t INTO lv_description UP TO 1 ROWS WHERE tabname = lv_tabname AND as4local = 'A' AND ddlanguage = language. ENDSELECT. IF sy-subrc = 0. CONCATENATE 'Structure' lv_description INTO lv_description SEPARATED BY space. ENDIF. ENDIF. ENDIF. description = lv_description. REPLACE ALL OCCURRENCES OF '"' IN description WITH '#'. ENDMETHOD. METHOD read_class. DATA lv_classname TYPE seoclskey. DATA lt_abapdoc TYPE gty_doclines. DATA lo_cls TYPE REF TO if_oo_class_incl_naming. DATA lv_moving_component_type TYPE string. DATA lt_only_methods TYPE SORTED TABLE OF string WITH UNIQUE KEY table_line. DATA lv_lines TYPE sy-index. DATA lv_helper TYPE c LENGTH 100. FIELD-SYMBOLS TYPE gty_component. IF NOT iv_abapdoc IS INITIAL. APPEND LINES OF string_to_abapdoc( iv_abapdoc ) TO lt_abapdoc. ENDIF. IF NOT iv_only_methods IS INITIAL. SPLIT to_upper( iv_only_methods ) AT ',' INTO TABLE DATA(lt_tokens). LOOP AT lt_tokens INTO DATA(lv_token). CONDENSE lv_token NO-GAPS. READ TABLE lt_only_methods WITH KEY table_line = lv_token TRANSPORTING NO FIELDS. IF sy-subrc <> 0. INSERT lv_token INTO TABLE lt_only_methods. ENDIF. ENDLOOP. ENDIF. "Class interrogation - is this a valid class ? Gather details: TRY. DATA(lo_oo_class) = cl_oo_class=>get_instance( clsname = iv_classname ). DATA(lo_oo_class2) = NEW cl_oo_class( clsname = iv_classname ). lv_classname = iv_classname. * Source for this technique: report dsmy_class_output CALL METHOD cl_oo_include_naming=>get_instance_by_cifkey EXPORTING cifkey = lv_classname RECEIVING cifref = DATA(lo_cif) EXCEPTIONS OTHERS = 1. lo_cls ?= lo_cif. READ REPORT lo_cls->main_source INTO gt_abap. IF sy-subrc <> 0. DATA(lv_message) = 'Inaccurate line count - main source unavailable'. ENDIF. lv_lines = lines( gt_abap ). READ REPORT lo_cls->public_section INTO gt_abap. "Translate the public section of the class to a list of constants and methods LOOP AT gt_abap INTO DATA(lv_abapline). DATA(lv_loop_tabix) = sy-tabix. SHIFT lv_abapline LEFT DELETING LEADING space. DATA(lv_abaplineupper) = to_upper( lv_abapline ). SPLIT lv_abaplineupper AT '.' INTO lv_abaplineupper DATA(lv_dummy). SPLIT lv_abaplineupper AT space INTO TABLE DATA(lt_abapline_tokens). "Abap DOC comments are for a statement that follows the comments. To ensure comments "are not added to a statement by accident, some checks are applied: IF strlen( lv_abapline ) = 0. CLEAR lt_abapdoc. ELSEIF strlen( lv_abapline ) > 3 AND lv_abapline(2) <> '"!' AND NOT lv_dummy IS INITIAL. CLEAR lt_abapdoc. ENDIF. " ABAP doc comments IF strlen( lv_abapline ) > 3 AND lv_abapline(2) = '"!'. INSERT VALUE gty_docline( linenr = lines( lt_abapdoc ) content = lv_abapline+2 ) INTO TABLE lt_abapdoc. ELSEIF ( lines( lt_abapline_tokens ) >= 1 ) AND ( ( strlen( lv_abaplineupper ) >= 10 AND lv_abaplineupper(10) = 'CONSTANTS:' ) OR ( strlen( lv_abaplineupper ) >= 5 AND lv_abaplineupper(5) = 'DATA:' ) OR ( strlen( lv_abaplineupper ) >= 11 AND lv_abaplineupper(11) = 'CLASS-DATA:' ) ). "Constants and attribute definitions with : are catered for differently. Multiple coding lines are "interpreted and required information is extracted. The extractor can clear gt_abap lines complex_definitions( component_type = lt_abapline_tokens[ 1 ] start_tabix = lv_loop_tabix ). "Attribute definitions (DATA and CLASS-DATA) ELSEIF ( lines( lt_abapline_tokens ) > 1 ) AND NOT lv_moving_component_type IS INITIAL. READ TABLE lo_oo_class->attributes INTO DATA(ls_attribute_details) WITH KEY clsname = lv_classname cmpname = lt_abapline_tokens[ 1 ]. IF sy-subrc = 0. APPEND VALUE gty_component( component_type = lv_moving_component_type component_name = ls_attribute_details-cmpname attvalue = ls_attribute_details-attvalue read_only = ls_attribute_details-attrdonly ) TO gt_components ASSIGNING . APPEND LINES OF lt_abapdoc TO -abapdoc. ENDIF. CLEAR lt_abapdoc. ELSEIF ( lines( lt_abapline_tokens ) > 1 ) AND ( ( strlen( lv_abaplineupper ) > 9 AND lv_abaplineupper(9) = 'CONSTANTS' ) OR ( strlen( lv_abaplineupper ) > 4 AND lv_abaplineupper(4) = 'DATA' ) OR ( strlen( lv_abaplineupper ) > 10 AND lv_abaplineupper(10) = 'CLASS-DATA' ) ). READ TABLE lo_oo_class->attributes INTO ls_attribute_details WITH KEY clsname = lv_classname cmpname = lt_abapline_tokens[ 2 ]. IF sy-subrc = 0. APPEND VALUE gty_component( component_type = lt_abapline_tokens[ 1 ] component_name = ls_attribute_details-cmpname attvalue = ls_attribute_details-attvalue read_only = ls_attribute_details-attrdonly ) TO gt_components ASSIGNING . APPEND LINES OF lt_abapdoc TO -abapdoc. ENDIF. CLEAR lt_abapdoc. "CLASS METHOD definition as well as METHOD definition ELSEIF ( strlen( lv_abaplineupper ) > 12 AND lv_abaplineupper(12) = 'CLASS-METHOD' ) OR ( strlen( lv_abaplineupper ) > 6 AND lv_abaplineupper(6) = 'METHOD' ). READ TABLE lo_oo_class->methods INTO DATA(ls_method_details) WITH KEY clsname = lv_classname cmpname = lt_abapline_tokens[ 2 ]. IF sy-subrc = 0. IF lines( lt_only_methods ) > 0. READ TABLE lt_only_methods WITH KEY table_line = to_upper( lt_abapline_tokens[ 2 ] ) TRANSPORTING NO FIELDS. IF sy-subrc <> 0. CLEAR lt_abapdoc. CONTINUE. ENDIF. ENDIF. APPEND VALUE gty_component( component_type = lt_abapline_tokens[ 1 ] component_name = ls_method_details-cmpname ) TO gt_components ASSIGNING . APPEND LINES OF lt_abapdoc TO -abapdoc. "Determine method hitcount (number of times it is called) DATA(lv_reference) = |{ iv_classname }\\ME:{ -component_name }|. SELECT COUNT(*) FROM wbcrossgt INTO @-method_hitcount WHERE otype = 'ME' AND name = @lv_reference. "Add method parameters - in sequence of type DO 4 TIMES. LOOP AT lo_oo_class->method_parameters INTO DATA(ls_method_parameter_details) WHERE clsname = ls_method_details-clsname AND cmpname = ls_method_details-cmpname AND pardecltyp = ( sy-index - 1 ). INSERT VALUE gty_parameter( linenr = lines( -parameters ) parameter = ls_method_parameter_details-sconame pardecltyp = ls_method_parameter_details-pardecltyp datatype = ls_method_parameter_details-type optional = ls_method_parameter_details-paroptionl ) INTO TABLE -parameters. ENDLOOP. ENDDO. "Exceptions LOOP AT lo_oo_class->method_exceptions INTO DATA(ls_method_exception_details) WHERE clsname = ls_method_details-clsname AND cmpname = ls_method_details-cmpname. INSERT VALUE gty_parameter( linenr = lines( -parameters ) parameter = ls_method_exception_details-sconame pardecltyp = 9 ) INTO TABLE -parameters. ENDLOOP. ELSE. "Method is a redefinition READ TABLE lo_oo_class2->redefinitions INTO DATA(ls_refefinition_details) WITH KEY clsname = lv_classname mtdname = lt_abapline_tokens[ 2 ]. IF sy-subrc = 0. IF lines( lt_only_methods ) > 0. READ TABLE lt_only_methods WITH KEY table_line = to_upper( lt_abapline_tokens[ 2 ] ) TRANSPORTING NO FIELDS. IF sy-subrc <> 0. CLEAR lt_abapdoc. CONTINUE. ENDIF. ENDIF. APPEND VALUE gty_component( component_type = lt_abapline_tokens[ 1 ] component_name = ls_refefinition_details-mtdname parameters = value #( ( linenr = 1 parameter = '?' pardecltyp = '2' ) ) redefinition = abap_true ) TO gt_components ASSIGNING . APPEND LINES OF lt_abapdoc TO -abapdoc. "Determine method hitcount (number of times it is called) lv_reference = |{ iv_classname }\\ME:{ -component_name }|. SELECT COUNT(*) FROM wbcrossgt INTO @-method_hitcount WHERE otype = 'ME' AND name = @lv_reference. ENDIF. ENDIF. CLEAR lt_abapdoc. "CLASS definition ELSEIF strlen( lv_abaplineupper ) > 5 AND lv_abaplineupper(5) = 'CLASS'. IF lt_abapline_tokens[ 1 ] = 'CLASS' AND lt_abapline_tokens[ 3 ] = 'DEFINITION'. DATA lv_clsname TYPE vseoclass-clsname. lv_clsname = lv_classname. APPEND VALUE gty_component( component_type = lt_abapline_tokens[ 1 ] component_name = lv_classname class-superclass = lo_oo_class2->superclass class-methods = lines( lo_oo_class->methods ) class-redefinitions = lines( lo_oo_class2->redefinitions ) ) TO gt_components ASSIGNING . LOOP AT lo_oo_class2->implementings INTO DATA(ls_implementing). IF -class-interfaces IS INITIAL. -class-interfaces = ls_implementing-refclsname. ELSE. -class-interfaces = |{ -class-interfaces }, { ls_implementing-refclsname }|. ENDIF. ENDLOOP. -class-filter_on_methods = COND #( WHEN iv_only_methods IS INITIAL THEN abap_false ELSE abap_true ). SELECT SINGLE descript, author, createdon, changedby, changedon FROM vseoclass INTO ( @-description, @-class-author, @-class-createdon, @-class-changedby, @-class-changedon ) WHERE clsname = @lv_clsname. -class-linecount = lv_lines. -class-message = lv_message. "Some effort to find an accurate last changed date (and user) - based on STMS lv_helper = |{ lv_clsname }%|. SELECT h~as4date, h~as4user FROM e070 AS h INNER JOIN e071 AS o ON o~trkorr = h~trkorr UP TO 1 ROWS INTO @DATA(ls_stms) WHERE ( o~obj_name = @lv_clsname AND o~object IN ( 'CLAS', 'CLSD', 'CPUB' ) ) OR ( o~obj_name LIKE @lv_helper AND o~object IN ( 'METH' ) ) ORDER BY h~as4date DESCENDING, h~as4time DESCENDING. ENDSELECT. IF sy-subrc = 0. -class-changedby = ls_stms-as4user. -class-changedon = ls_stms-as4date. ENDIF. APPEND LINES OF lt_abapdoc TO -abapdoc. SELECT SINGLE devclass FROM tadir INTO @-devclass WHERE pgmid = 'R3TR' AND object = 'CLAS' AND obj_name = @-component_name. IF sy-subrc = 0. SELECT SINGLE ctext FROM tdevct INTO @-devclass_text WHERE devclass = @-devclass AND spras = @sy-langu. IF sy-subrc <> 0. SELECT SINGLE ctext FROM tdevct INTO @-devclass_text WHERE devclass = @-devclass AND spras <> @sy-langu. ENDIF. ENDIF. ENDIF. CLEAR lt_abapdoc. ENDIF. ENDLOOP. CATCH cx_class_not_existent. "skipped: not a class ENDTRY. ENDMETHOD. METHOD read_report. DATA lt_abapdoc TYPE gty_doclines. DATA lt_includes TYPE STANDARD TABLE OF char80. DATA lv_REPORT_tagged TYPE boolean. DATA lt_abap TYPE STANDARD TABLE OF string. DATA lt_RSEL_INFO TYPE STANDARD TABLE OF rsel_info. FIELD-SYMBOLS TYPE gty_component. IF NOT iv_abapdoc IS INITIAL. APPEND LINES OF string_to_abapdoc( iv_abapdoc ) TO lt_abapdoc. ENDIF. READ REPORT iv_report INTO gt_abap. "The report logic is interpreted for it's ABAPdoc comments LOOP AT gt_abap INTO DATA(lv_abapline). DATA(lv_loop_tabix) = sy-tabix. SHIFT lv_abapline LEFT DELETING LEADING space. DATA(lv_abaplineupper) = to_upper( lv_abapline ). SPLIT lv_abaplineupper AT '.' INTO lv_abaplineupper DATA(lv_dummy). SPLIT lv_abaplineupper AT space INTO TABLE DATA(lt_abapline_tokens). DELETE lt_abapline_tokens WHERE table_line = ''. " ABAP doc comments IF strlen( lv_abaplineupper ) > 3 AND lv_abaplineupper(2) = '"!'. INSERT VALUE gty_docline( linenr = lines( lt_abapdoc ) content = lv_abapline+3 ) INTO TABLE lt_abapdoc. " Report definitie ELSEIF ( strlen( lv_abaplineupper ) > 6 AND lv_abaplineupper(6) = 'REPORT' ) AND lv_REPORT_tagged = abap_false. lv_REPORT_tagged = abap_true. APPEND VALUE gty_component( component_type = lt_abapline_tokens[ 1 ] component_name = lt_abapline_tokens[ 2 ] report-linecount = lines( gt_abap ) ) TO gt_components ASSIGNING . SELECT SINGLE cnam, cdat, unam, udat FROM trdir INTO (@-report-cnam, @-report-cdat, @-report-unam, @-report-udat) WHERE name = @-component_name. SELECT SINGLE text FROM trdirt INTO @-description WHERE name = @-component_name AND sprsl = @sy-langu. IF sy-subrc <> 0. SELECT text FROM trdirt INTO @-description WHERE name = @-component_name. ENDSELECT. ENDIF. SELECT SINGLE devclass FROM tadir INTO @-devclass WHERE pgmid = 'R3TR' AND object = 'PROG' AND obj_name = @-component_name. IF sy-subrc = 0. SELECT SINGLE ctext FROM tdevct INTO @-devclass_text WHERE devclass = @-devclass AND spras = @sy-langu. IF sy-subrc <> 0. SELECT SINGLE ctext FROM tdevct INTO @-devclass_text WHERE devclass = @-devclass AND spras <> @sy-langu. ENDIF. ENDIF. CALL FUNCTION 'GET_INCLUDETAB' EXPORTING progname = -component_name TABLES incltab = lt_includes. "Update the program line counter with include lines LOOP AT lt_includes INTO DATA(lv_include). READ REPORT lv_include INTO lt_abap. -report-linecount = -report-linecount + lines( lt_abap ). ENDLOOP. INSERT LINES OF lt_includes INTO TABLE -report-includes. CALL FUNCTION 'RS_SELECTIONS_DESCRIPTION_RFC' EXPORTING report = iv_report default_values = ' ' TABLES field_info = lt_RSEL_INFO EXCEPTIONS OTHERS = 0. LOOP AT lt_RSEL_INFO INTO DATA(ls_RSEL_INFO). APPEND VALUE gty_parameter( linenr = lines( -parameters ) pardecltyp = COND #( WHEN ls_RSEL_INFO-kind = 'P' THEN '6' ELSE '7' ) parameter = ls_RSEL_INFO-name ) TO -parameters. ENDLOOP. APPEND LINES OF lt_abapdoc TO -abapdoc. CLEAR lt_abapdoc. ENDIF. ENDLOOP. ENDMETHOD. METHOD read_table. DATA lt_abapdoc TYPE gty_doclines. IF NOT iv_abapdoc IS INITIAL. APPEND LINES OF string_to_abapdoc( iv_abapdoc ) TO lt_abapdoc. ENDIF. SELECT SINGLE ddtext FROM dd02t INTO @DATA(ls_description) WHERE tabname = @iv_table. CHECK sy-subrc = 0. APPEND VALUE gty_component( component_type = 'TABLE' description = ls_description component_name = |{ iv_table }| ) TO gt_components ASSIGNING FIELD-SYMBOL(). SELECT SINGLE as4user, as4date, mainflag FROM dd02l INTO @DATA(ls_dd02l) WHERE tabname = @iv_table AND as4local = 'A' AND as4vers = 0000. IF sy-subrc = 0. -table-changed_on = ls_dd02l-as4date. -table-changed_by = ls_dd02l-as4user. -table-maintenance = ls_dd02l-mainflag. ENDIF. SELECT SINGLE devclass FROM tadir INTO @-devclass WHERE pgmid = 'R3TR' AND object = 'TABL' AND obj_name = @-component_name. IF sy-subrc = 0. SELECT SINGLE ctext FROM tdevct INTO @-devclass_text WHERE devclass = @-devclass AND spras = @sy-langu. IF sy-subrc <> 0. SELECT SINGLE ctext FROM tdevct INTO @-devclass_text WHERE devclass = @-devclass AND spras <> @sy-langu. ENDIF. SELECT e070~as4user, e070~as4date FROM e071 INNER JOIN e070 ON e070~trkorr = e071~trkorr WHERE e071~pgmid = 'R3TR' AND e071~object = 'TABL' AND e071~obj_name = @-component_name ORDER BY e071~trkorr INTO @DATA(ls_e070) . "Fetch the creation date from transports -table-created_on = ls_e070-as4date. -table-created_by = ls_e070-as4user. EXIT. ENDSELECT. ENDIF. SELECT * FROM dd03l INTO TABLE @-table-dd03l WHERE tabname = @iv_table AND as4local = 'A' AND as4vers = 0000. -abapdoc = lt_abapdoc. ENDMETHOD. METHOD read_function. DATA lt_abapdoc TYPE gty_doclines. DATA lt_abap TYPE STANDARD TABLE OF string. DATA lv_include TYPE char40. IF NOT iv_abapdoc IS INITIAL. APPEND LINES OF string_to_abapdoc( iv_abapdoc ) TO lt_abapdoc. ENDIF. SELECT SINGLE enlfdir~area, tadir~author, tadir~devclass, tadir~created_on, tfdir~pname, tfdir~include FROM enlfdir INNER JOIN tadir ON tadir~obj_name = enlfdir~area AND tadir~pgmid = 'R3TR' AND tadir~object = 'FUGR' INNER JOIN tfdir ON tfdir~funcname = enlfdir~funcname INTO @DATA(ls_function_data) WHERE enlfdir~funcname = @iv_function. * APPEND VALUE gty_component( component_type = 'FUNCTION' component_name = |{ iv_function }| devclass = ls_function_data-devclass function-author = ls_function_data-author function-created_on = ls_function_data-created_on function-area = ls_function_data-area ) TO gt_components ASSIGNING FIELD-SYMBOL(). SELECT stext FROM tftit INTO @-description WHERE funcname = @iv_function. EXIT. ENDSELECT. "Hitcounter SELECT COUNT(*) INTO @-function-hitcount FROM cross WHERE type = 'F' AND name = @iv_function. SELECT SINGLE ctext FROM tdevct INTO @-devclass_text WHERE devclass = @-devclass AND spras = @sy-langu. IF sy-subrc <> 0. SELECT SINGLE ctext FROM tdevct INTO @-devclass_text WHERE devclass = @-devclass AND spras <> @sy-langu. ENDIF. lv_include = |{ ls_function_data-pname+3 }U{ ls_function_data-include }|. READ REPORT lv_include INTO lt_abap. -function-linecount = lines( lt_abap ). -abapdoc = lt_abapdoc. SELECT parameter, paramtype FROM fupararef INTO TABLE @DATA(lt_FUPARAREF) WHERE funcname = @iv_function AND r3state = 'A'. "Importing LOOP AT lt_FUPARAREF INTO DATA(ls_FUPARAREF) WHERE paramtype = 'I'. INSERT VALUE gty_parameter( linenr = lines( -parameters ) pardecltyp = '0' parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters. ENDLOOP. "Changing LOOP AT lt_FUPARAREF INTO ls_FUPARAREF WHERE paramtype = 'C'. INSERT VALUE gty_parameter( linenr = lines( -parameters ) pardecltyp = '2' parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters. ENDLOOP. "Exporting LOOP AT lt_FUPARAREF INTO ls_FUPARAREF WHERE paramtype = 'E'. INSERT VALUE gty_parameter( linenr = lines( -parameters ) pardecltyp = '1' parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters. ENDLOOP. "Tables LOOP AT lt_FUPARAREF INTO ls_FUPARAREF WHERE paramtype = 'T'. INSERT VALUE gty_parameter( linenr = lines( -parameters ) pardecltyp = '2' parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters. ENDLOOP. "Exceptions LOOP AT lt_FUPARAREF INTO ls_FUPARAREF WHERE paramtype = 'X'. INSERT VALUE gty_parameter( linenr = lines( -parameters ) pardecltyp = '9' parameter = ls_FUPARAREF-parameter ) INTO TABLE -parameters. ENDLOOP. ENDMETHOD. METHOD read_developmentclasses. DATA lr_devclass TYPE RANGE OF tdevc-devclass. DATA lr_objectnames type range of tadir-obj_name. lr_devclass = VALUE #( ( sign = 'I' option = 'CP' low = '$*' ) ( sign = 'I' option = 'CP' low = 'Z*' ) ( sign = 'I' option = 'CP' low = 'Y*' ) ). SELECT tdevc~devclass, tdevc~parentcl, tdevct_E~ctext, tdevct_N~ctext FROM tdevc LEFT OUTER JOIN tdevct AS tdevct_E ON tdevc~devclass = tdevct_E~devclass AND tdevct_E~spras = 'E' LEFT OUTER JOIN tdevct AS tdevct_N ON tdevc~devclass = tdevct_N~devclass AND tdevct_N~spras = 'N' INTO TABLE @gt_devclass WHERE tdevc~devclass IN @lr_devclass. lr_objectnames = VALUE #( ( sign = 'I' option = 'CP' low = 'Y*' ) ( sign = 'I' option = 'CP' low = 'Z*' ) ). select distinct devclass, count( * ) as counter from tadir into table @data(lt_tadircounts) WHERE obj_name in @lr_objectnames and devclass IN @lr_devclass group by devclass. loop at gt_devclass assigning field-symbol(). read table lt_tadircounts with key devclass = -devclass into data(ls_tadircount). if sy-subrc = 0. -tadircounter = ls_tadircount-counter. endif. endloop. ENDMETHOD. ENDCLASS. CLASS lcl_document_groups IMPLEMENTATION. METHOD set_group. DATA lv_space_counter TYPE n LENGTH 3. FIELD-SYMBOLS TYPE gty_group. FIELD-SYMBOLS TYPE gty_group_object. INSERT VALUE gty_group( ) INTO TABLE gt_groups ASSIGNING . -description = iv_description. -summary = iv_summary. LOOP AT it_playlist INTO DATA(ls_playlist). IF ls_playlist-object_type = 'SPACE'. lv_space_counter = lv_space_counter + 1. ls_playlist-object_name = lv_space_counter. ENDIF. READ TABLE -objects WITH KEY object_type = ls_playlist-object_type object_name = ls_playlist-object_name ASSIGNING . IF sy-subrc <> 0. INSERT VALUE gty_group_object( id = lines( -objects ) object_type = ls_playlist-object_type object_name = ls_playlist-object_name links = ls_playlist-links tagwords = ls_playlist-tagwords reviews = ls_playlist-reviews ) INTO TABLE -objects ASSIGNING . ENDIF. -components = NEW lcl_component_documentor( iv_only_methods = ls_playlist-only_methods iv_abapdoc = ls_playlist-abapdoc iv_name = ls_playlist-object_name iv_type = ls_playlist-object_type ). ENDLOOP. ENDMETHOD. METHOD string_to_html. DATA lt_string_components TYPE STANDARD TABLE OF swastrtab. CHECK strlen( iv_string ) > 0. CALL FUNCTION 'SWA_STRING_SPLIT' EXPORTING input_string = iv_string max_component_length = 70 TABLES string_components = lt_string_components. LOOP AT lt_string_components INTO DATA(ls_string_component). APPEND ls_string_component-str TO gt_html. ENDLOOP. ENDMETHOD. METHOD set_html_style. gt_html = VALUE #( ( 'The Zone - inspiration for developers') ( '') ( '' ) ). ENDMETHOD. METHOD set_svg_images. gt_svg_class = VALUE #( ( ' ' ) ( ' ' ) ( ' Class ' ) ). gt_svg_report = VALUE #( ( ' ' ) ( ' ' ) ( ' Report ' ) ). gt_svg_function = VALUE #( ( ' ' ) ( ' ' ) ( ' Function ' ) ). gt_svg_table = VALUE #( ( ' ' ) ( ' ' ) ( ' Table ' ) ). gv_svg_mini_icon = '' && 'TEXT '. gv_svg_mini_icon2 = '' && 'TEXT '. * https://www.svgrepo.com/collection/solar-line-duotone-icons/19 gt_svg_exporting = VALUE #( ( '
' ) ( '' ) ( '
' ) ). gt_svg_importing = VALUE #( ( '
' ) ( '' ) ( '
' ) ). gt_svg_changing = VALUE #( ( '
' ) ( '' ) ( '' ) ( '
' ) ). gt_svg_returning = VALUE #( ( '
' ) ( '' ) ( '' ) ( '
' ) ). gt_svg_parameter = VALUE #( ( '
' ) ( '' ) ( '
' ) ). gt_svg_selectoption = VALUE #( ( '
' ) ( '' ) ( '' ) ( '
' ) ). gt_svg_exception = VALUE #( ( '
' ) ( '' ) ( '' ) ( '' ) ( '
' ) ). gt_svg_screw = VALUE #( ( '' ) ( '' ) ( '' ) ). gt_svg_star = VALUE #( ( ' ' ) ( ' ' ) ). gt_svg_star_empty = VALUE #( ( ' ' ) ( ' ' ) ). gt_svg_lapse = VALUE #( ( ' ' ) ( ' ' ) ( 'm1 ' ) ( ' ' ) ( 'm2 ' ) ( ' ' ) ). ENDMETHOD. METHOD set_age_color. "The age-color grading is derived from the age in days against fibonacci numbers TYPES: BEGIN OF lty_colors, days TYPE int2, color TYPE c LENGTH 8, END OF lty_colors. rv_color = '#000000'. CHECK NOT iv_date IS INITIAL. DATA lt_colorcodes TYPE SORTED TABLE OF lty_colors WITH UNIQUE KEY days. lt_colorcodes = VALUE #( ( days = 0 color = '#00ff00' ) ( days = 2 color = '#e6e6ff' ) ( days = 3 color = '#ccccff' ) ( days = 5 color = '#b3b3ff' ) ( days = 8 color = '#9999ff' ) ( days = 13 color = '#8080ff' ) ( days = 21 color = '#6666ff' ) ( days = 34 color = '#4d4dff' ) ( days = 55 color = '#3333ff' ) ( days = 89 color = '#1a1aff' ) ( days = 144 color = '#1a1aff' ) ( days = 233 color = '#0000ff' ) ( days = 377 color = '#0000e6' ) ( days = 610 color = '#0000cc' ) ( days = 987 color = '#0000b3' ) ( days = 1697 color = '#000099' ) ( days = 2584 color = '#000080' ) ( days = 32000 color = '#000000' ) ). DATA(lv_age_in_days) = sy-datum - iv_date. LOOP AT lt_colorcodes INTO DATA(ls_colorcode) WHERE days <= lv_age_in_days. rv_color = ls_colorcode-color. ENDLOOP. ENDMETHOD. METHOD harvest_counters. CLEAR gs_counters. LOOP AT gt_groups INTO DATA(ls_group). gs_counters-groups = gs_counters-groups + 1. LOOP AT ls_group-objects INTO DATA(ls_object) WHERE object_type <> 'SPACE'. gs_counters-objects = gs_counters-objects + 1. LOOP AT ls_object-components->gt_components INTO DATA(ls_component). CASE ls_component-component_type. WHEN 'CLASS'. gs_counters-classes = gs_counters-classes + 1. WHEN 'METHODS'. gs_counters-methods = gs_counters-methods + 1. WHEN 'CLASS-METHODS'. gs_counters-classmethods = gs_counters-classmethods + 1. WHEN 'TABLE'. gs_counters-tables = gs_counters-tables + 1. WHEN 'REPORT'. gs_counters-reports = gs_counters-reports + 1. WHEN 'FUNCTION'. gs_counters-functions = gs_counters-functions + 1. ENDCASE. ENDLOOP. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD harvest_developmentclasses. DATA lv_focus_devclass TYPE devclass. LOOP AT gt_groups INTO DATA(ls_group). gs_counters-groups = gs_counters-groups + 1. LOOP AT ls_group-objects INTO DATA(ls_object). gs_counters-objects = gs_counters-objects + 1. LOOP AT ls_object-components->gt_components INTO DATA(ls_component). READ TABLE lcl_component_documentor=>gt_devclass ASSIGNING FIELD-SYMBOL() WITH KEY devclass = ls_component-devclass. IF sy-subrc = 0. -objectcounter = -objectcounter + 1. ENDIF. ENDLOOP. ENDLOOP. ENDLOOP. "Determine relevance: everything with a counter and their parents LOOP AT lcl_component_documentor=>gt_devclass ASSIGNING WHERE objectcounter > 0. -relevant = abap_true. "Find all parents lv_focus_devclass = -parentcl. DO 20 TIMES. IF lv_focus_devclass IS INITIAL. EXIT. ENDIF. READ TABLE lcl_component_documentor=>gt_devclass ASSIGNING FIELD-SYMBOL() WITH KEY devclass = lv_focus_devclass. IF sy-subrc = 0. -relevant = abap_true. lv_focus_devclass = -parentcl. ELSE. CLEAR lv_focus_devclass. ENDIF. ENDDO. ENDLOOP. DELETE lcl_component_documentor=>gt_devclass WHERE relevant = abap_false. ENDMETHOD. METHOD print_developmentclass. "Recursive calls DATA lv_description TYPE string. IF iv_devclass-objectcounter = 0. APPEND || TO gt_html. "No click-link functionality ELSE. APPEND || TO gt_html. ENDIF. APPEND |{ iv_devclass-devclass }| TO gt_html. lv_description = COND #( WHEN iv_devclass-ctext_N <> '' THEN iv_devclass-ctext_N ELSE iv_devclass-ctext_E ). APPEND |{ lv_description }| TO gt_html. if iv_devclass-objectcounter = 0. APPEND || TO gt_html. ELSE. APPEND |{ iv_devclass-objectcounter } objects| TO gt_html. APPEND |.. of { iv_devclass-tadircounter } objects| TO gt_html. endif. APPEND || TO gt_html. LOOP AT lcl_component_documentor=>gt_devclass INTO DATA(ls_devclass) USING KEY via_parents WHERE parentcl = iv_devclass-devclass. print_developmentclass( EXPORTING iv_level = ( iv_level + 1 ) iv_devclass = ls_devclass ). ENDLOOP. ENDMETHOD. METHOD harvest_dates. "The components on the group have a CREATED and CHANGED date, which needs to be set with information derived from the components. LOOP AT gt_groups ASSIGNING FIELD-SYMBOL(). -created = sy-datum. * -changed = '19690308'. LOOP AT -objects ASSIGNING FIELD-SYMBOL(). -created = sy-datum. * -changed = '19690308'. LOOP AT -components->gt_components INTO DATA(ls_component). CASE ls_component-component_type. WHEN 'CLASS'. -created = COND #( WHEN ls_component-class-createdon < -created THEN ls_component-class-createdon ELSE -created ). -changed = COND #( WHEN ls_component-class-changedon > -changed THEN ls_component-class-changedon ELSE -changed ). WHEN 'REPORT'. -created = COND #( WHEN ls_component-report-cdat < -created THEN ls_component-report-cdat ELSE -created ). -changed = COND #( WHEN ls_component-report-udat > -changed THEN ls_component-report-udat ELSE -changed ). WHEN 'FUNCTION'. -created = COND #( WHEN ls_component-function-created_on < -created THEN ls_component-function-created_on ELSE -created ). -changed = COND #( WHEN ls_component-function-created_on > -changed THEN ls_component-function-created_on ELSE -changed ). WHEN 'TABLE'. -created = COND #( WHEN ls_component-table-created_on < -created THEN ls_component-table-created_on ELSE -created ). -changed = COND #( WHEN ls_component-table-changed_on > -changed THEN ls_component-table-changed_on ELSE -changed ). ENDCASE. ENDLOOP. IF NOT -created IS INITIAL. -created = COND #( WHEN -created < -created THEN -created ELSE -created ). ENDIF. IF NOT -changed IS INITIAL. -changed = COND #( WHEN -changed > -changed THEN -changed ELSE -changed ). ENDIF. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD set_abapdoc. CHECK lines( it_abapdoc ) > 0. APPEND '
' TO gt_html. LOOP AT it_abapdoc INTO DATA(ls_abapdocline). "@parameter and @exception are ABAPdoc elements that require a bit of special attention REPLACE '@parameter' IN ls_abapdocline-content WITH '

Parameter'. REPLACE '@exception' IN ls_abapdocline-content WITH '

Exception'. REPLACE '|' IN ls_abapdocline-content WITH ''. APPEND |{ ls_abapdocline-content }| TO gt_html. ENDLOOP. APPEND '

' TO gt_html. ENDMETHOD. METHOD mini_dot_as_svg. DATA lv_color TYPE c LENGTH 20. DATA lv_text TYPE c LENGTH 3. IF iv_medium = abap_false. rv_colored_dot = gv_svg_mini_icon. ELSE. rv_colored_dot = gv_svg_mini_icon2. "Just a little bigger ENDIF. CASE iv_object_type. WHEN 'CLASS'. lv_color = 'blue'. lv_text = 'Cla'. WHEN 'TABLE'. lv_color = 'orange'. lv_text = 'Tab'. WHEN 'REPORT'. lv_color = 'purple'. lv_text = 'Rep'. WHEN 'FUNCTION'. lv_color = 'red'. lv_text = 'Fun'. WHEN OTHERS. lv_color = 'black'. lv_text = '?'. ENDCASE. REPLACE 'BLACK' IN rv_colored_dot WITH lv_color. REPLACE 'TEXT' IN rv_colored_dot WITH lv_text. ENDMETHOD. METHOD set_group_header. DATA lv_colored_dot TYPE char255. DATA lt_svg_lapse TYPE STANDARD TABLE OF char255. APPEND |
| TO gt_html. APPEND |

{ iv_groupnr }.
| TO gt_html. APPEND || TO gt_html. APPEND |
| TO gt_html. LOOP AT is_group-objects INTO DATA(ls_object) WHERE object_type <> 'SPACE'. APPEND mini_dot_as_svg( ls_object-object_type ) TO gt_html. ENDLOOP. APPEND || TO gt_html. "Compose an SVG image with a bit of data on it - the create/last change icons lt_svg_lapse[] = gt_svg_lapse[]. LOOP AT lt_svg_lapse ASSIGNING FIELD-SYMBOL(). REPLACE 'm1' IN WITH get_date_summary( is_group-created ). REPLACE 'col1' IN WITH set_age_color( is_group-created ). IF is_group-changed = sy-datum. REPLACE 'm2' IN WITH 'Today'. ELSE. REPLACE 'm2' IN WITH get_date_summary( is_group-changed ). ENDIF. REPLACE 'col2' IN WITH set_age_color( is_group-changed ). APPEND TO gt_html. ENDLOOP. APPEND |
| TO gt_html. APPEND |

{ is_group-description }

| TO gt_html. APPEND |
| TO gt_html. IF NOT is_group-summary IS INITIAL. APPEND |

{ is_group-summary }| TO gt_html. ENDIF. set_all_tagwords( is_group = is_group ). APPEND |


| TO gt_html. ENDMETHOD. METHOD get_date_summary. DATA lv_components TYPE n VALUE 0. IF iv_date IS INITIAL. rv_result = '.'. EXIT. ENDIF. "Number of days into year, week and day DATA(lv_days_total) = sy-datum - iv_date. CLEAR rv_result. DATA(lv_div) = lv_days_total DIV 365. IF ( lv_div > 0 ). rv_result = |{ lv_div }j|. lv_days_total = lv_days_total - ( lv_div * 365 ). lv_components = lv_components + 1. ENDIF. lv_div = lv_days_total DIV 7. IF ( lv_div > 0 ). rv_result = |{ rv_result }{ lv_div }w|. lv_days_total = lv_days_total - ( lv_div * 7 ). lv_components = lv_components + 1. ELSEIF lv_components > 0. RETURN. ENDIF. CHECK lv_components < 2. IF ( lv_days_total > 0 ). rv_result = |{ rv_result }{ lv_days_total }d|. lv_components = lv_components + 1. ELSEIF lv_components > 0. RETURN. ENDIF. ENDMETHOD. METHOD set_all_tagwords. DATA lv_all_tagwords TYPE string. DATA lt_all_tagwords TYPE STANDARD TABLE OF string. CLEAR lv_all_tagwords. CLEAR lt_all_tagwords. LOOP AT is_group-objects INTO DATA(ls_object) WHERE tagwords <> ''. lv_all_tagwords = |{ lv_all_tagwords } { ls_object-tagwords }|. ENDLOOP. CONDENSE lv_all_tagwords. APPEND |

| TO gt_html. IF NOT lv_all_tagwords IS INITIAL. SPLIT lv_all_tagwords AT space INTO TABLE lt_all_tagwords. SORT lt_all_tagwords. DELETE ADJACENT DUPLICATES FROM lt_all_tagwords. lv_all_tagwords = 'Tagwords '. LOOP AT lt_all_tagwords INTO DATA(lv_tagword). lv_all_tagwords = |{ lv_all_tagwords } \| { lv_tagword }|. IF strlen( lv_all_tagwords ) > 150. APPEND lv_all_tagwords TO gt_html. CLEAR lv_all_tagwords. ENDIF. ENDLOOP. APPEND |{ lv_all_tagwords }| TO gt_html. ENDIF. APPEND '' TO gt_html. ENDMETHOD. METHOD set_tagwords. IF iv_tagwords IS INITIAL. APPEND | | TO gt_html. ELSE. APPEND |
TAGWORDS| TO gt_html. SPLIT iv_tagwords AT space INTO TABLE DATA(lt_tokens). SORT lt_tokens. LOOP AT lt_tokens INTO DATA(lv_token). APPEND |{ lv_token }
| TO gt_html. ENDLOOP. APPEND |
| TO gt_html. ENDIF. ENDMETHOD. METHOD set_parameter_svg. CASE iv_parameter_type. WHEN 0. APPEND LINES OF gt_svg_exporting TO gt_html. WHEN 1. APPEND LINES OF gt_svg_importing TO gt_html. WHEN 2. APPEND LINES OF gt_svg_changing TO gt_html. WHEN 3. APPEND LINES OF gt_svg_returning TO gt_html. WHEN 6. APPEND LINES OF gt_svg_parameter TO gt_html. WHEN 7. APPEND LINES OF gt_svg_selectoption TO gt_html. WHEN 9. APPEND LINES OF gt_svg_exception TO gt_html. ENDCASE. ENDMETHOD. METHOD set_links. CHECK lines( is_object-links ) > 0. APPEND '

External links

' TO gt_html. LOOP AT is_object-links INTO DATA(ls_link). APPEND |

{ ls_link-label }| TO gt_html. ENDLOOP. APPEND '

 ' TO gt_html. ENDMETHOD. METHOD set_reviews. CHECK lines( is_object-reviews ) > 0. APPEND '

Reviews

' TO gt_html. LOOP AT is_object-reviews INTO DATA(ls_review). APPEND |
| TO gt_html. APPEND |

| TO gt_html. " style="margin-left:90px;" DO 5 TIMES. IF sy-index <= ls_review-rating. APPEND LINES OF gt_svg_star TO gt_html. ELSE. APPEND LINES OF gt_svg_star_empty TO gt_html. ENDIF. ENDDO. APPEND |{ ls_review-summary }
| TO gt_html. string_to_html( ls_review-remarks ). APPEND |
{ ls_review-date DATE = USER } \| { ls_review-uname }| TO gt_html. APPEND | { lcl_component_documentor=>get_username( ls_review-uname ) } { ls_review-username } | TO gt_html. APPEND '

' TO gt_html. ENDLOOP. ENDMETHOD. METHOD set_object_header. DATA lt_svg_lapse TYPE STANDARD TABLE OF char255. DATA lv_review_date TYPE d. DATA lv_review_text TYPE string. gv_id = gv_id + 1. APPEND |
| TO gt_html. APPEND |
| TO gt_html. CASE is_object-object_type. WHEN 'CLASS'. APPEND LINES OF gt_svg_class TO gt_html. WHEN 'REPORT'. APPEND LINES OF gt_svg_report TO gt_html. WHEN 'TABLE'. APPEND LINES OF gt_svg_table TO gt_html. WHEN 'FUNCTION'. APPEND LINES OF gt_svg_function TO gt_html. ENDCASE. APPEND || TO gt_html. CLEAR: lv_review_text, lv_review_date. IF lines( is_object-reviews ) > 0. LOOP AT is_object-reviews INTO DATA(ls_review). IF ls_review-date > lv_review_date. lv_review_date = ls_review-date. ENDIF. ENDLOOP. lv_review_text = |{ lines( is_object-reviews ) } reviews - { get_date_summary( ls_review-date ) }|. ENDIF. APPEND |

{ is_object-object_name }

| TO gt_html. IF NOT lv_review_text IS INITIAL. APPEND LINES OF gt_svg_star TO gt_html. ENDIF. APPEND |
| TO gt_html. READ TABLE is_object-components->gt_components INTO DATA(ls_main_component) WITH KEY component_type = is_object-object_type component_name = is_object-object_name. IF sy-subrc = 0. APPEND |{ ls_main_component-description }| TO gt_html. set_abapdoc( ls_main_component-abapdoc ). APPEND |
| TO gt_html. "Compose an SVG image with a bit of data on it - the create/last change icons lt_svg_lapse[] = gt_svg_lapse[]. LOOP AT lt_svg_lapse ASSIGNING FIELD-SYMBOL(). REPLACE 'm1' IN WITH get_date_summary( is_object-created ). REPLACE 'col1' IN WITH set_age_color( is_object-created ). IF is_object-changed = sy-datum. REPLACE 'm2' IN WITH 'Today'. ELSE. REPLACE 'm2' IN WITH get_date_summary( is_object-changed ). ENDIF. REPLACE 'col2' IN WITH set_age_color( is_object-changed ). APPEND TO gt_html. ENDLOOP. set_tagwords( is_object-tagwords ). ELSE. APPEND |

Sorry ! { is_object-object_type CASE = LOWER } not found

| TO gt_html. ENDIF. APPEND |
| TO gt_html. APPEND |
' TO gt_html. * ==================================================================================================== WHEN 'REPORT'. * ==================================================================================================== READ TABLE ls_object-components->gt_components INTO ls_component WITH KEY component_type = ls_object-object_type component_name = ls_object-object_name. DATA lt_group_detail_content TYPE gty_content_tt. DATA lv_count_text TYPE string. lv_count_text = COND #( WHEN lines( ls_component-report-includes ) = 0 THEN '' ELSE ' (with includes)' ). lt_group_detail_content = VALUE #( ( label = 'Last changed by' username = ls_component-report-unam datevalue = ls_component-report-udat ) ( label = 'Lines of Abap coding' value = |{ ls_component-report-linecount } { lv_count_text }| ) ( label = 'Development class' value = |{ ls_component-devclass } { ls_component-devclass_text }| ) ). LOOP AT ls_component-report-includes INTO DATA(lv_include). APPEND VALUE #( label = 'Include' value = lv_include ) TO lt_group_detail_content. ENDLOOP. SELECT SINGLE tstct~tcode, tstct~ttext FROM tstc INNER JOIN tstct ON tstct~tcode = tstc~tcode INTO (@DATA(lv_tcode), @DATA(lv_ttext)) WHERE pgmna = @ls_object-object_name AND tstct~sprsl = @sy-langu. IF sy-subrc <> 0. SELECT SINGLE tstct~tcode, tstct~ttext FROM tstc INNER JOIN tstct ON tstct~tcode = tstc~tcode INTO (@lv_tcode, @lv_ttext) WHERE pgmna = @ls_object-object_name AND tstct~sprsl = 'E'. ENDIF. IF sy-subrc = 0. APPEND VALUE #( label = 'Transaction' value = |{ lv_tcode } { lv_ttext }| ) TO lt_group_detail_content. ENDIF. set_group_detail( iv_created_by = ls_component-report-cnam iv_created_on = ls_component-report-cdat it_content = lt_group_detail_content ). set_reviews( ls_object ). set_links( ls_object ). APPEND |
PARAMETERS| TO gt_html. READ TABLE ls_object-components->gt_components INTO ls_component INDEX 1. LOOP AT ls_component-parameters INTO ls_parameter. IF sy-tabix > 8. APPEND || TO gt_html. EXIT. ENDIF. APPEND || TO gt_html. ENDLOOP. IF sy-subrc <> 0. APPEND '' TO gt_html. ENDIF. APPEND '
{ lines( ls_component-parameters ) - 8 } more ...
| TO gt_html. set_parameter_svg( ls_parameter-pardecltyp ). APPEND |{ ls_parameter-parameter }
' TO gt_html. APPEND '' TO gt_html. * ==================================================================================================== WHEN 'TABLE'. * ==================================================================================================== READ TABLE ls_object-components->gt_components INTO ls_component WITH KEY component_type = ls_object-object_type component_name = ls_object-object_name. set_group_detail( iv_created_by = ls_component-table-created_by iv_created_on = ls_component-table-created_on it_content = VALUE #( ( label = 'Last changed by' username = ls_component-table-changed_by datevalue = ls_component-table-changed_on ) ( label = 'Has table maintenance' value = |{ COND #( WHEN ls_component-table-maintenance = abap_true THEN 'Yes' ELSE 'No' ) }| ) ( label = 'Development class' value = |{ ls_component-devclass } { ls_component-devclass_text }| ) ) ). set_reviews( ls_object ). set_links( ls_object ). APPEND '

Definition

' TO gt_html. APPEND '' TO gt_html. DATA lv_fields TYPE string. DATA lv_fieldname TYPE string. DATA lv_html_line TYPE string. DATA lv_description TYPE string. DATA lv_type TYPE char40. CLEAR lv_fields. LOOP AT ls_component-table-dd03l INTO DATA(ls_dd03l) WHERE fieldname(5) <> '.INCL'. * Field description and type definition: lv_fieldname = |{ ls_object-object_name }-{ ls_dd03l-fieldname }|. lv_description = lcl_component_documentor=>get_sap_description( fieldreference = lv_fieldname ). WRITE: ls_dd03l-leng TO lv_type NO-ZERO LEFT-JUSTIFIED. SHIFT lv_type RIGHT BY 1 PLACES. lv_type(1) = ls_dd03l-inttype. lv_type = |{ lv_type }|. CONDENSE lv_type NO-GAPS. * Field (or key field) lv_html_line = COND #( WHEN ls_dd03l-keyflag = abap_true THEN |{ ls_dd03l-fieldname }| ELSE |{ ls_dd03l-fieldname }| ). APPEND || TO gt_html. lv_fields = lv_fields + 1. IF lv_fields > 50. APPEND || TO gt_html. EXIT. ENDIF. ENDLOOP. APPEND '
FieldnameTypeDescription
{ lv_html_line }{ lv_type }{ lv_description }
Only 50 fields listed
' TO gt_html. * ==================================================================================================== WHEN 'FUNCTION'. * ==================================================================================================== READ TABLE ls_object-components->gt_components INTO ls_component WITH KEY component_type = ls_object-object_type component_name = ls_object-object_name. set_group_detail( iv_created_by = ls_component-function-author iv_created_on = ls_component-function-created_on it_content = VALUE #( ( label = 'Area' value = ls_component-function-area ) ( label = 'Where-used: used from' value = |{ ls_component-function-hitcount } locations| ) ( label = 'Lines of Abap coding' value = ls_component-function-linecount ) ( label = 'Development class' value = |{ ls_component-devclass } { ls_component-devclass_text }| ) ) ). set_reviews( ls_object ). set_links( ls_object ). APPEND |
PARAMETERS| TO gt_html. LOOP AT ls_component-parameters INTO ls_parameter. APPEND '| TO gt_html. ENDLOOP. IF sy-subrc <> 0. APPEND '' TO gt_html. ENDIF. APPEND '
' TO gt_html. set_parameter_svg( ls_parameter-pardecltyp ). APPEND |{ ls_parameter-parameter }
' TO gt_html. APPEND '' TO gt_html. * ==================================================================================================== WHEN 'SPACE'. * ==================================================================================================== "A bit of space on the overview APPEND '


' TO gt_html. ENDCASE. ENDLOOP. APPEND '


' TO gt_html. ENDLOOP. APPEND |


{ sy-datum DATE = USER } on SAP { sy-sysid } report/transaction { sy-repid }
| TO gt_html. APPEND '' TO gt_html. ENDMETHOD. ENDCLASS. PARAMETERS pa_devcl TYPE devclass NO-DISPLAY. START-OF-SELECTION. CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR' EXPORTING percentage = 0 text = 'Starting up and gathering information...'. DATA(go_documentation) = NEW lcl_document_groups( ). * ==================================================================================================== INCLUDE zone_script. * ==================================================================================================== "Apply development class filter - when applicable go_documentation->filter_focus( pa_devcl ). "Fetch the development class hierarchy - custom classes only lcl_component_documentor=>read_developmentclasses( ). go_documentation->zone_reporter( ). CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR' EXPORTING percentage = 0 text = 'Enjoy...'. CALL SCREEN 900. MODULE status_0900 OUTPUT. SET PF-STATUS 'MAIN'. SET TITLEBAR '001'. IF go_documentation->go_container IS INITIAL. CREATE OBJECT go_documentation->go_container EXPORTING container_name = 'CUSTOM_CONTROL' EXCEPTIONS OTHERS = 4. CREATE OBJECT go_documentation->go_html_control EXPORTING parent = go_documentation->go_container. "To enable response from the HTML document go_documentation->gt_myevents = VALUE #( ( eventid = go_documentation->go_html_control->m_id_sapevent appl_event = 'x' ) ). CALL METHOD go_documentation->go_html_control->set_registered_events EXPORTING events = go_documentation->gt_myevents. CREATE OBJECT go_documentation->go_event_receiver. SET HANDLER go_documentation->go_event_receiver->handle_sapevent FOR go_documentation->go_html_control. "Load the html control with the (already prepared) html/javascript content go_documentation->go_html_control->load_data( IMPORTING assigned_url = go_documentation->gv_url CHANGING data_table = go_documentation->gt_html ). ENDIF. go_documentation->go_html_control->show_url( EXPORTING url = go_documentation->gv_url ). ENDMODULE. MODULE user_command_0900 INPUT. CASE gv_okcode. WHEN 'BACK' OR 'LEAVE'. LEAVE PROGRAM. WHEN 'DOWNLOAD'. DATA lv_returncode TYPE sy-subrc. cl_gui_frontend_services=>clipboard_export( IMPORTING data = go_documentation->gt_html CHANGING rc = lv_returncode EXCEPTIONS OTHERS = 4 ). IF sy-subrc = 0 AND lv_returncode = 0. MESSAGE 'Full HTML content placed on clipboard' TYPE 'S'. ENDIF. ENDCASE. ENDMODULE.