class ZCL_BC_TABLE_INTROSPECTOR definition
public
final
create private .
public section.
*"* public components of class ZCL_BC_TABLE_INTROSPECTOR
*"* do not include other source files here!!!
types:
ty_delimiter type c length 1 .
type-pools ABAP .
class-methods FACTORY_USING_SQL
importing
value(IM_DBTAB) type CSEQUENCE
value(IM_COLUMNS) type CSEQUENCE optional
value(IM_WHERE_CLAUSE) type CSEQUENCE optional
value(IM_MAX_ROWS) type I optional
value(IM_DELIMITER) type TY_DELIMITER default ','
value(IM_USE_HEADER_RECORD) type ABAP_BOOL default ABAP_TRUE
value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL default ABAP_TRUE
value(IM_POINT_HEADER_TO_DDIC) type ABAP_BOOL default ABAP_TRUE
value(IM_ENCLOSE_STRINGS) type ABAP_BOOL default ABAP_FALSE
value(IM_FORMAT_TIME) type ABAP_BOOL default ABAP_TRUE
value(IM_FORMAT_DATE) type ABAP_BOOL default ABAP_TRUE
exporting
!EX_TABLE_INTROSPECTOR type ref to ZCL_BC_TABLE_INTROSPECTOR
raising
ZCX_BC_TABLE_INTROSPECTOR .
class-methods FACTORY_USING_TABLE
importing
value(IM_TABLE) type ANY TABLE
value(IM_COLUMNS) type CSEQUENCE optional
value(IM_DELIMITER) type TY_DELIMITER default ','
value(IM_USE_HEADER_RECORD) type ABAP_BOOL default ABAP_TRUE
value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL default ABAP_TRUE
value(IM_POINT_HEADER_TO_DDIC) type ABAP_BOOL default ABAP_TRUE
value(IM_ENCLOSE_STRINGS) type ABAP_BOOL default ABAP_FALSE
value(IM_FORMAT_TIME) type ABAP_BOOL default ABAP_TRUE
value(IM_FORMAT_DATE) type ABAP_BOOL default ABAP_TRUE
exporting
!EX_TABLE_INTROSPECTOR type ref to ZCL_BC_TABLE_INTROSPECTOR
raising
ZCX_BC_TABLE_INTROSPECTOR .
methods GET_ALV_RENDITION
exporting
!EX_SALV_TABLE type ref to CL_SALV_TABLE
raising
ZCX_BC_TABLE_INTROSPECTOR .
methods GET_SOLI_RENDITION
importing
!IM_TRUNCATE_LINES type ABAP_BOOL default ABAP_TRUE
exporting
!EX_SOLI type SOLI_TAB
raising
ZCX_BC_TABLE_INTROSPECTOR .
methods GET_SOLIX_RENDITION
exporting
!EX_SOLIX type SOLIX_TAB
raising
ZCX_BC_TABLE_INTROSPECTOR .
methods GET_FILE_RENDITION
exporting
!EX_OUTPUT_TABLE type STRING_TABLE
raising
ZCX_BC_TABLE_INTROSPECTOR .
protected section.
*"* protected components of class ZCL_BC_TABLE_INTROSPECTOR
*"* do not include other source files here!!!
private section.
*"* private components of class ZCL_BC_TABLE_INTROSPECTOR
*"* do not include other source files here!!!
type-pools ABAP .
data USE_HEADER_RECORD type ABAP_BOOL .
data USE_COLUMN_ALIGNMENT type ABAP_BOOL .
data HEADER_DATA_REF type ref to DATA .
data TABLE_DATA_REF type ref to DATA .
data RAW_TABLE_DATA_REF type ref to DATA .
methods CONSTRUCTOR
importing
!IM_USE_HEADER_RECORD type ABAP_BOOL
!IM_USE_COLUMN_ALIGNMENT type ABAP_BOOL
!IM_HEADER_DATA_REF type ref to DATA
!IM_TABLE_DATA_REF type ref to DATA
!IM_RAW_TABLE_DATA_REF type ref to DATA .
class-methods GET_INTERNAL_TABLE_METADATA
importing
value(IM_TABLE) type ANY TABLE
value(IM_COLUMNS) type CSEQUENCE optional
exporting
!EX_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR
raising
ZCX_BC_TABLE_INTROSPECTOR .
class-methods GET_TABLE_METADATA
importing
value(IM_DBTAB) type CSEQUENCE
value(IM_COLUMNS) type CSEQUENCE
exporting
!EX_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR
raising
ZCX_BC_TABLE_INTROSPECTOR .
class CL_ABAP_STRUCTDESCR definition load .
class-methods RECURSIVE_FILTER_COLUMNS
importing
value(IM_COLUMNS) type CSEQUENCE
value(IM_COMPONENTS) type CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE
exporting
!EX_COMPONENTS type CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE
raising
ZCX_BC_TABLE_INTROSPECTOR .
class-methods POPULATE_HEADER
importing
value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL
value(IM_POINT_HEADER_TO_DDIC) type ABAP_BOOL
value(IM_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR
exporting
!EX_STRUCT_REF type ref to DATA
raising
ZCX_BC_TABLE_INTROSPECTOR .
class-methods EXECUTE_SQL
importing
value(IM_DBTAB) type CSEQUENCE
value(IM_WHERE_CLAUSE) type CSEQUENCE
value(IM_MAX_ROWS) type I
value(IM_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR
exporting
!EX_TABLE_REF type ref to DATA
raising
ZCX_BC_TABLE_INTROSPECTOR .
class-methods POPULATE_TABLE
importing
!IM_TABLE type ANY TABLE
!IM_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR
exporting
!EX_TABLE_REF type ref to DATA
raising
ZCX_BC_TABLE_INTROSPECTOR .
class-methods BUILD_FORMATTED_COMPONENTS
importing
value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL
value(IM_ENCLOSE_STRINGS) type ABAP_BOOL
value(IM_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR
exporting
!EX_FORMATTED_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR
!EX_FORMATTED_TABLE_DESCR type ref to CL_ABAP_STRUCTDESCR
raising
ZCX_BC_TABLE_INTROSPECTOR .
class-methods POPULATE_FORMATTED_HEADER
importing
value(IM_DELIMITER) type TY_DELIMITER optional
value(IM_ENCLOSE_STRINGS) type ABAP_BOOL
value(IM_FORMATTED_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR
value(IM_STRUCT_REF) type ref to DATA
exporting
!EX_FORMATTED_STRUCT_REF type ref to DATA
raising
ZCX_BC_TABLE_INTROSPECTOR .
class-methods POPULATE_FORMATTED_TABLE
importing
value(IM_DELIMITER) type TY_DELIMITER optional
value(IM_ENCLOSE_STRINGS) type ABAP_BOOL
value(IM_FORMAT_TIME) type ABAP_BOOL optional
value(IM_FORMAT_DATE) type ABAP_BOOL optional
value(IM_FORMATTED_TABLE_DESCR) type ref to CL_ABAP_STRUCTDESCR
value(IM_TABLE_REF) type ref to DATA
exporting
!EX_FORMATTED_TABLE_REF type ref to DATA
raising
ZCX_BC_TABLE_INTROSPECTOR .
class-methods NORMALIZE_LINE_FORMAT
importing
value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL
value(IM_DATA) type ANY
exporting
!EX_TABLE type STRING_TABLE
raising
ZCX_BC_TABLE_INTROSPECTOR .
ENDCLASS.
CLASS ZCL_BC_TABLE_INTROSPECTOR IMPLEMENTATION.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>BUILD_FORMATTED_COMPONENTS
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL
* | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL
* | [--->] IM_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [<---] EX_FORMATTED_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [<---] EX_FORMATTED_TABLE_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method BUILD_FORMATTED_COMPONENTS.
*-- object references
data: lo_elem_objectdescr type ref to cl_abap_objectdescr,
lo_struct_objectdescr type ref to cl_abap_objectdescr,
lo_elemdescr type ref to cl_abap_elemdescr,
lo_header_struct_descr type ref to cl_abap_structdescr,
lo_table_struct_descr type ref to cl_abap_structdescr,
lo_root_exc type ref to cx_root.
*-- internal table defintion
data: lt_components type cl_abap_structdescr=>component_table,
lt_hdr_components_interleaved type cl_abap_structdescr=>component_table,
lt_rec_components_interleaved type cl_abap_structdescr=>component_table,
lt_inner_components type cl_abap_structdescr=>component_table,
lt_hdr_components_temp type cl_abap_structdescr=>component_table,
lt_rec_components_temp type cl_abap_structdescr=>component_table.
*-- structure defintion
data: ls_component type abap_componentdescr,
ls_component_temp type abap_componentdescr.
*-- local variables
data: lv_output_length type i,
lv_delimiter_name type char5,
lv_counter type n length 4,
lv_error_msg type string.
lt_components = im_struct_descr->get_components( ).
*-- loop thru all components and convert to flat, character-based, delimited collection suitable for output in flat file
loop at lt_components into ls_component.
try.
*-- create new character-based component based on length of ddic description (for header)
clear: ls_component_temp.
lo_elemdescr ?= ls_component-type.
if im_use_column_alignment eq abap_true.
*-- account for string elements which have no defined length
if lo_elemdescr->output_length eq 0.
ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 255 ).
else.
lv_output_length = lo_elemdescr->output_length.
if im_enclose_strings eq abap_true and
( lo_elemdescr->type_kind eq cl_abap_typedescr=>typekind_char or
lo_elemdescr->type_kind eq cl_abap_typedescr=>typekind_string ).
add 2 to lv_output_length.
endif.
ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = lv_output_length ).
endif.
else.
ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 40 ).
endif.
ls_component_temp-name = ls_component-name.
append ls_component_temp to lt_hdr_components_interleaved.
*-- cast to cl_abap_elemdescr, retrieve output length, and create new character-based component based on this length (for record)
clear: ls_component_temp.
lo_elemdescr ?= ls_component-type.
if lo_elemdescr->output_length eq 0.
ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 255 ).
else.
lv_output_length = lo_elemdescr->output_length.
if im_enclose_strings eq abap_true and
( lo_elemdescr->type_kind eq cl_abap_typedescr=>typekind_char or
lo_elemdescr->type_kind eq cl_abap_typedescr=>typekind_string ).
add 2 to lv_output_length.
endif.
ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = lv_output_length ).
endif.
ls_component_temp-name = ls_component-name.
append ls_component_temp to lt_rec_components_interleaved.
*-- create dynamically named delimiter component
clear: ls_component_temp.
add 1 to lv_counter.
concatenate 'd' lv_counter into lv_delimiter_name.
ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 1 ).
ls_component_temp-name = lv_delimiter_name.
append ls_component_temp to lt_hdr_components_interleaved.
append ls_component_temp to lt_rec_components_interleaved.
catch cx_sy_move_cast_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
endloop.
try.
lo_header_struct_descr =
cl_abap_structdescr=>create( lt_hdr_components_interleaved ).
lo_table_struct_descr =
cl_abap_structdescr=>create( lt_rec_components_interleaved ).
catch cx_sy_struct_creation
cx_sy_table_creation into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
*-- return new delimited component structure
ex_formatted_struct_descr = lo_header_struct_descr.
ex_formatted_table_descr = lo_table_struct_descr.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_BC_TABLE_INTROSPECTOR->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_USE_HEADER_RECORD TYPE ABAP_BOOL
* | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL
* | [--->] IM_HEADER_DATA_REF TYPE REF TO DATA
* | [--->] IM_TABLE_DATA_REF TYPE REF TO DATA
* | [--->] IM_RAW_TABLE_DATA_REF TYPE REF TO DATA
* +--------------------------------------------------------------------------------------
method constructor.
use_header_record = im_use_header_record.
use_column_alignment = im_use_column_alignment.
header_data_ref = im_header_data_ref.
table_data_ref = im_table_data_ref.
raw_table_data_ref = im_raw_table_data_ref.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>EXECUTE_SQL
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_DBTAB TYPE CSEQUENCE
* | [--->] IM_WHERE_CLAUSE TYPE CSEQUENCE
* | [--->] IM_MAX_ROWS TYPE I
* | [--->] IM_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [<---] EX_TABLE_REF TYPE REF TO DATA
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method execute_sql.
*-- object references
data: lo_table_descr type ref to cl_abap_tabledescr,
lo_root_exc type ref to cx_root.
*-- local variables
data: lv_structdata_ref type ref to data,
lv_error_msg type string,
lv_error_msg_temp type string.
*-- field symbols
field-symbols: type standard table,
type any.
try.
lo_table_descr = cl_abap_tabledescr=>create( im_struct_descr ).
create data ex_table_ref type handle lo_table_descr.
assign ex_table_ref->* to .
create data lv_structdata_ref type handle im_struct_descr.
assign lv_structdata_ref->* to .
catch cx_sy_create_data_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
if im_max_rows lt 0.
lv_error_msg = 'With "UP TO n ROWS", specify only positive values'.
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endif.
try.
select *
from (im_dbtab)
into corresponding fields of table
up to im_max_rows rows
where (im_where_clause).
catch cx_sy_sql_error into lo_root_exc.
clear: lv_error_msg_temp.
lv_error_msg = 'Error in SQL execution'.
lv_error_msg_temp = lo_root_exc->get_text( ).
if lv_error_msg_temp is not initial.
concatenate lv_error_msg ': ' lv_error_msg_temp into lv_error_msg respecting blanks.
endif.
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_BC_TABLE_INTROSPECTOR=>FACTORY_USING_SQL
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_DBTAB TYPE CSEQUENCE
* | [--->] IM_COLUMNS TYPE CSEQUENCE(optional)
* | [--->] IM_WHERE_CLAUSE TYPE CSEQUENCE(optional)
* | [--->] IM_MAX_ROWS TYPE I(optional)
* | [--->] IM_DELIMITER TYPE TY_DELIMITER (default =',')
* | [--->] IM_USE_HEADER_RECORD TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [--->] IM_POINT_HEADER_TO_DDIC TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [--->] IM_FORMAT_TIME TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [--->] IM_FORMAT_DATE TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [<---] EX_TABLE_INTROSPECTOR TYPE REF TO ZCL_BC_TABLE_INTROSPECTOR
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method factory_using_sql.
*-- object references
data: lo_struct_descr type ref to cl_abap_structdescr,
lo_formatted_struct_descr type ref to cl_abap_structdescr,
lo_formatted_table_descr type ref to cl_abap_structdescr,
lo_table_ref type ref to data,
lo_formatted_table_ref type ref to data,
lo_struct_ref type ref to data,
lo_formatted_struct_ref type ref to data.
*-- local variables
data: lv_folder type string,
lv_file type string,
lv_use_header type abap_bool,
lv_use_column_alignment type abap_bool,
lv_use_tstamp type abap_bool,
lv_use_server type abap_bool.
*-- get flattened components according to columns
call method get_table_metadata(
exporting
im_dbtab = im_dbtab
im_columns = im_columns
importing
ex_struct_descr = lo_struct_descr ).
*-- populate header structure
call method populate_header(
exporting
im_use_column_alignment = im_use_column_alignment
im_point_header_to_ddic = im_point_header_to_ddic
im_struct_descr = lo_struct_descr
importing
ex_struct_ref = lo_struct_ref ).
*-- execute SQL query and populate table structure
call method execute_sql(
exporting
im_dbtab = im_dbtab
im_where_clause = im_where_clause
im_max_rows = im_max_rows
im_struct_descr = lo_struct_descr
importing
ex_table_ref = lo_table_ref ).
*-- create new header and table structures with delimiters inserted
call method build_formatted_components(
exporting
im_use_column_alignment = im_use_column_alignment
im_enclose_strings = im_enclose_strings
im_struct_descr = lo_struct_descr
importing
ex_formatted_struct_descr = lo_formatted_struct_descr
ex_formatted_table_descr = lo_formatted_table_descr ).
*-- populate formatted header
call method populate_formatted_header(
exporting
im_delimiter = im_delimiter
im_enclose_strings = im_enclose_strings
im_formatted_struct_descr = lo_formatted_struct_descr
im_struct_ref = lo_struct_ref
importing
ex_formatted_struct_ref = lo_formatted_struct_ref ).
*-- populate formatted table
call method populate_formatted_table(
exporting
im_delimiter = im_delimiter
im_enclose_strings = im_enclose_strings
im_format_time = im_format_time
im_format_date = im_format_date
im_formatted_table_descr = lo_formatted_table_descr
im_table_ref = lo_table_ref
importing
ex_formatted_table_ref = lo_formatted_table_ref ).
*-- finally we instantiate the class
create object ex_table_introspector
exporting
im_use_header_record = im_use_header_record
im_use_column_alignment = im_use_column_alignment
im_header_data_ref = lo_formatted_struct_ref
im_table_data_ref = lo_formatted_table_ref
im_raw_table_data_ref = lo_table_ref.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_BC_TABLE_INTROSPECTOR=>FACTORY_USING_TABLE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_TABLE TYPE ANY TABLE
* | [--->] IM_COLUMNS TYPE CSEQUENCE(optional)
* | [--->] IM_DELIMITER TYPE TY_DELIMITER (default =',')
* | [--->] IM_USE_HEADER_RECORD TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [--->] IM_POINT_HEADER_TO_DDIC TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [--->] IM_FORMAT_TIME TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [--->] IM_FORMAT_DATE TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [<---] EX_TABLE_INTROSPECTOR TYPE REF TO ZCL_BC_TABLE_INTROSPECTOR
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method factory_using_table.
*-- object references
data: lo_struct_descr type ref to cl_abap_structdescr,
lo_formatted_struct_descr type ref to cl_abap_structdescr,
lo_formatted_table_descr type ref to cl_abap_structdescr,
lo_table_ref type ref to data,
lo_formatted_table_ref type ref to data,
lo_struct_ref type ref to data,
lo_formatted_struct_ref type ref to data,
lo_root_exc type ref to cx_root.
*-- local variables
data: lv_folder type string,
lv_file type string,
lv_use_header type abap_bool,
lv_use_column_alignment type abap_bool,
lv_use_tstamp type abap_bool,
lv_use_server type abap_bool,
lv_error_msg type string.
*-- get flattened components according to columns
call method get_internal_table_metadata(
exporting
im_table = im_table
im_columns = im_columns
importing
ex_struct_descr = lo_struct_descr ).
*-- populate header structure
call method populate_header(
exporting
im_use_column_alignment = im_use_column_alignment
im_point_header_to_ddic = im_point_header_to_ddic
im_struct_descr = lo_struct_descr
importing
ex_struct_ref = lo_struct_ref ).
*-- populate table structure
call method populate_table(
exporting
im_table = im_table
im_struct_descr = lo_struct_descr
importing
ex_table_ref = lo_table_ref ).
*-- create new header and table structures with delimiters interleaved
call method build_formatted_components(
exporting
im_use_column_alignment = im_use_column_alignment
im_enclose_strings = im_enclose_strings
im_struct_descr = lo_struct_descr
importing
ex_formatted_struct_descr = lo_formatted_struct_descr
ex_formatted_table_descr = lo_formatted_table_descr ).
*-- populate formatted header
call method populate_formatted_header(
exporting
im_delimiter = im_delimiter
im_enclose_strings = im_enclose_strings
im_formatted_struct_descr = lo_formatted_struct_descr
im_struct_ref = lo_struct_ref
importing
ex_formatted_struct_ref = lo_formatted_struct_ref ).
*-- populate formatted table
call method populate_formatted_table(
exporting
im_delimiter = im_delimiter
im_enclose_strings = im_enclose_strings
im_format_time = im_format_time
im_format_date = im_format_date
im_formatted_table_descr = lo_formatted_table_descr
im_table_ref = lo_table_ref
importing
ex_formatted_table_ref = lo_formatted_table_ref ).
*-- finally we instantiate the class
create object ex_table_introspector
exporting
im_use_header_record = im_use_header_record
im_use_column_alignment = im_use_column_alignment
im_header_data_ref = lo_formatted_struct_ref
im_table_data_ref = lo_formatted_table_ref
im_raw_table_data_ref = lo_table_ref.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_ALV_RENDITION
* +-------------------------------------------------------------------------------------------------+
* | [<---] EX_SALV_TABLE TYPE REF TO CL_SALV_TABLE
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method get_alv_rendition.
*-- object references
data: lo_root_exc type ref to cx_root.
*-- local variables
data: lv_error_msg type string.
*-- field symbols
field-symbols: type standard table.
if raw_table_data_ref is not bound.
lv_error_msg = 'No table data found - make sure you have instantiated the class first.'.
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endif.
try.
assign raw_table_data_ref->* to .
cl_salv_table=>factory(
importing r_salv_table = ex_salv_table
changing t_table = ).
catch cx_salv_msg into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_FILE_RENDITION
* +-------------------------------------------------------------------------------------------------+
* | [<---] EX_OUTPUT_TABLE TYPE STRING_TABLE
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method get_file_rendition.
*-- internal table defintion
data: lt_header_table type string_table,
lt_body_table type string_table,
lt_output_table type string_table.
*-- local variables
data: lv_error_msg type string.
*-- field symbols
field-symbols: type any,
type standard table.
if table_data_ref is not bound.
lv_error_msg = 'No table data found - make sure you have instantiated the class first.'.
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endif.
assign header_data_ref->* to .
assign table_data_ref->* to .
*-- normalize header and body
call method normalize_line_format
exporting
im_use_column_alignment = use_column_alignment
im_data =
importing
ex_table = lt_header_table.
call method normalize_line_format
exporting
im_use_column_alignment = use_column_alignment
im_data =
importing
ex_table = lt_body_table.
if use_header_record eq abap_true.
append lines of lt_header_table to lt_output_table.
endif.
append lines of lt_body_table to lt_output_table.
ex_output_table[] = lt_output_table[].
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>GET_INTERNAL_TABLE_METADATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_TABLE TYPE ANY TABLE
* | [--->] IM_COLUMNS TYPE CSEQUENCE(optional)
* | [<---] EX_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method get_internal_table_metadata.
*-- object references
data: lo_struct_descr type ref to cl_abap_structdescr,
lo_table_descr type ref to cl_abap_tabledescr,
lo_root_exc type ref to cx_root.
*-- internal table defintion
data: lt_components type cl_abap_structdescr=>component_table,
lt_components_filtered type cl_abap_structdescr=>component_table.
*-- structure defintion
data: ls_components_filtered like line of lt_components_filtered.
*-- local variables
data: lv_error_msg type string.
try.
lo_table_descr ?= cl_abap_tabledescr=>describe_by_data( im_table ).
lo_struct_descr ?= lo_table_descr->get_table_line_type( ).
catch cx_sy_move_cast_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
lt_components = lo_struct_descr->get_components( ).
*-- recursive call - as side effect, components are flattened
call method recursive_filter_columns(
exporting
im_columns = im_columns
im_components = lt_components
importing
ex_components = lt_components_filtered ).
if lt_components_filtered[] is initial.
lv_error_msg = 'No columns found according to search criteria'.
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endif.
try.
lo_struct_descr =
cl_abap_structdescr=>create( lt_components_filtered ).
catch cx_sy_struct_creation
cx_sy_table_creation into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
ex_struct_descr = lo_struct_descr.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_SOLIX_RENDITION
* +-------------------------------------------------------------------------------------------------+
* | [<---] EX_SOLIX TYPE SOLIX_TAB
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method get_solix_rendition.
*-- object references
data: lo_root_exc type ref to cx_bcs.
*-- internal table defintion
data: lt_solix type solix_tab,
lt_output_table type string_table.
*-- structure defintion
data: ls_output_table like line of lt_output_table.
*-- local variables
data: lv_string type string,
lv_error_msg type string.
if table_data_ref is not bound.
lv_error_msg = 'No table data found - make sure you have instantiated the class first.'.
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endif.
call method me->get_file_rendition
importing
ex_output_table = lt_output_table.
loop at lt_output_table into ls_output_table.
concatenate
lv_string
ls_output_table
cl_abap_char_utilities=>cr_lf
into lv_string respecting blanks.
endloop.
try.
cl_bcs_convert=>string_to_solix(
exporting
iv_string = lv_string
importing
et_solix = lt_solix ).
catch cx_bcs into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
ex_solix[] = lt_solix[].
endmethod.
* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_SOLI_RENDITION
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_TRUNCATE_LINES TYPE ABAP_BOOL (default =ABAP_TRUE)
* | [<---] EX_SOLI TYPE SOLI_TAB
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method get_soli_rendition.
*-- object references
data: lo_root_exc type ref to cx_bcs.
*-- internal table defintion
data: lt_soli type soli_tab,
lt_soli_temp type soli_tab,
lt_output_table type string_table.
*-- structure defintion
data: ls_soli type soli,
ls_output_table like line of lt_output_table.
*-- local variables
data: lv_string type string,
lv_max_len type i,
lv_str_len type i,
lv_error_msg type string.
if table_data_ref is not bound.
lv_error_msg = 'No table data found - make sure you have instantiated the class first.'.
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endif.
call method me->get_file_rendition
importing
ex_output_table = lt_output_table.
describe field ls_soli-line length lv_max_len in character mode.
loop at lt_output_table into ls_output_table.
if im_truncate_lines eq abap_true.
lv_str_len = strlen( ls_output_table ).
if lv_str_len gt lv_max_len.
lv_str_len = lv_max_len.
endif.
ls_soli-line = ls_output_table(lv_str_len).
append ls_soli to lt_soli.
else.
try.
cl_bcs_convert=>string_to_soli(
exporting
iv_string = ls_output_table
receiving
et_soli = lt_soli_temp ).
append lines of lt_soli_temp to lt_soli.
catch cx_bcs into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
endif.
endloop.
ex_soli[] = lt_soli[].
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>GET_TABLE_METADATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_DBTAB TYPE CSEQUENCE
* | [--->] IM_COLUMNS TYPE CSEQUENCE
* | [<---] EX_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method get_table_metadata.
*-- object references
data: lo_type_descr type ref to cl_abap_typedescr,
lo_elemdescr type ref to cl_abap_elemdescr,
lo_struct_descr type ref to cl_abap_structdescr,
lo_root_exc type ref to cx_root.
*-- internal table defintion
data: lt_components type cl_abap_structdescr=>component_table,
lt_components_filtered type cl_abap_structdescr=>component_table.
*-- structure defintion
data: ls_components_filtered like line of lt_components_filtered,
ls_dfies type dfies.
*-- local variables
data: lv_error_msg type string.
cl_abap_typedescr=>describe_by_name(
exporting p_name = im_dbtab
receiving p_descr_ref = lo_type_descr
exceptions type_not_found = 4 ).
if sy-subrc = 4.
if im_dbtab is initial.
lv_error_msg = 'No table specified'.
else.
concatenate 'Table ' im_dbtab ' not found' into lv_error_msg respecting blanks.
condense lv_error_msg.
endif.
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endif.
try.
lo_struct_descr ?= lo_type_descr.
catch cx_sy_move_cast_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
lt_components = lo_struct_descr->get_components( ).
*-- recursive call - as side effect, components are flattened
call method recursive_filter_columns(
exporting
im_columns = im_columns
im_components = lt_components
importing
ex_components = lt_components_filtered ).
if lt_components_filtered[] is initial.
lv_error_msg = 'No columns found according to search criteria'.
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endif.
try.
lo_struct_descr =
cl_abap_structdescr=>create( lt_components_filtered ).
catch cx_sy_struct_creation
cx_sy_table_creation into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
ex_struct_descr = lo_struct_descr.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>NORMALIZE_LINE_FORMAT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL
* | [--->] IM_DATA TYPE ANY
* | [<---] EX_TABLE TYPE STRING_TABLE
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method normalize_line_format.
*-- object references
data: lo_struct_ref type ref to data,
lo_table_ref type ref to data,
lo_struct_objectdescr type ref to cl_abap_objectdescr,
lo_table_objectdescr type ref to cl_abap_objectdescr,
lo_type_descr type ref to cl_abap_typedescr.
*-- local variables
data: lv_len type i,
lv_mod_result type i,
lv_counter type i,
lv_line type string.
*-- field symbols
field-symbols: type any,
type standard table,
type any,
type any.
cl_abap_typedescr=>describe_by_data(
exporting p_data = im_data
receiving p_descr_ref = lo_type_descr ).
lo_struct_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_structdescr' ).
lo_table_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_tabledescr' ).
if lo_struct_objectdescr->applies_to( lo_type_descr ) eq 'X'.
*-- process structure
create data lo_struct_ref like im_data.
assign lo_struct_ref->* to .
= im_data.
lv_counter = 0.
lv_line = ''.
if im_use_column_alignment eq abap_false.
*-- build up line with condensed fields
do.
add 1 to lv_counter.
assign component lv_counter of structure to .
if sy-subrc is not initial.
exit.
endif.
shift right deleting trailing space.
shift left deleting leading space.
*-- add field to line
lv_len = strlen( ).
if lv_len ge 1.
concatenate lv_line (lv_len) into lv_line respecting blanks.
endif.
enddo.
else.
lv_len = strlen( ).
lv_line = (lv_len).
endif.
append lv_line to ex_table.
elseif lo_table_objectdescr->applies_to( lo_type_descr ) eq 'X'.
*-- process table
create data lo_table_ref like im_data.
assign lo_table_ref->* to .
= im_data.
loop at assigning . " cast to address fields symbol. w/out using offset/length
lv_counter = 0.
lv_line = ''.
if im_use_column_alignment eq abap_false.
*-- build up line with condensed fields
do.
add 1 to lv_counter.
assign component lv_counter of structure to .
if sy-subrc is not initial.
exit.
endif.
shift right deleting trailing space.
shift left deleting leading space.
lv_len = strlen( ).
if lv_len ge 1.
concatenate lv_line (lv_len) into lv_line respecting blanks.
endif.
enddo.
else.
lv_len = strlen( ).
lv_line = (lv_len).
endif.
append lv_line to ex_table.
endloop.
endif.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_FORMATTED_HEADER
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_DELIMITER TYPE TY_DELIMITER(optional)
* | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL
* | [--->] IM_FORMATTED_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [--->] IM_STRUCT_REF TYPE REF TO DATA
* | [<---] EX_FORMATTED_STRUCT_REF TYPE REF TO DATA
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method populate_formatted_header.
*-- object references
data: lo_elemdescr type ref to cl_abap_elemdescr,
lo_root_exc type ref to cx_root.
*-- local variables
data: lv_counter type i value 0,
lv_mod_result type i,
lv_string_length type i,
lv_output_length type i,
lv_repetitions type string,
lv_regex type string,
lv_error_msg type string.
*-- field symbols
field-symbols: type any,
type any,
type any.
try.
create data ex_formatted_struct_ref type handle im_formatted_struct_descr.
assign ex_formatted_struct_ref->* to . " point to results for later export
catch cx_sy_create_data_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
*-- move data to , and inject delimiters
assign im_struct_ref->* to .
move-corresponding to .
*-- iterate thru each component of interleaved structure
lv_counter = 0.
do.
add 1 to lv_counter.
assign component lv_counter of structure to .
if sy-subrc is not initial.
exit.
endif.
lv_mod_result = lv_counter mod 2.
*-- populate field
if lv_mod_result ne 0.
shift right deleting trailing space.
shift left deleting leading space.
*-- header fields are always treated as a string
if im_enclose_strings eq abap_true.
*-- build regular expression to correctly insert quotes
lo_elemdescr ?= cl_abap_elemdescr=>describe_by_data( ).
lv_output_length = lo_elemdescr->output_length - 2.
lv_string_length = strlen( ).
if lv_output_length lt lv_string_length.
lv_repetitions = lv_output_length.
else.
lv_repetitions = lv_string_length.
endif.
condense lv_repetitions.
concatenate '(^.{' lv_repetitions '})(.*$)' into lv_regex.
*-- interpolate quotes in field
replace regex lv_regex in with '"$1"'.
endif.
else.
*-- populate delimiter
= im_delimiter.
endif.
enddo.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_FORMATTED_TABLE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_DELIMITER TYPE TY_DELIMITER(optional)
* | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL
* | [--->] IM_FORMAT_TIME TYPE ABAP_BOOL(optional)
* | [--->] IM_FORMAT_DATE TYPE ABAP_BOOL(optional)
* | [--->] IM_FORMATTED_TABLE_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [--->] IM_TABLE_REF TYPE REF TO DATA
* | [<---] EX_FORMATTED_TABLE_REF TYPE REF TO DATA
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method populate_formatted_table.
*-- object references
data: lo_struct_descr type ref to cl_abap_structdescr,
lo_table_descr type ref to cl_abap_tabledescr,
lo_structdescr_interleaved type ref to cl_abap_structdescr,
lo_tabledescr_interleaved type ref to cl_abap_tabledescr,
lo_table_line_ref type ref to data,
lo_table_interleaved_ref type ref to data,
lo_root_exc type ref to cx_root.
*-- local variables
data: lv_error_msg type string,
lv_counter type i value 0,
lv_typekind type abap_typekind,
lv_mod_result type i,
lv_date_internal type sydatum,
lv_date_external type string,
lv_time_internal type syuzeit,
lv_time_external type string.
*-- field symbols
field-symbols: type standard table,
type standard table,
type any,
type any,
like line of cl_abap_structdescr=>components,
type any,
type any.
*-- create new (empty) table based on previously built interleaved components
try.
lo_tabledescr_interleaved =
cl_abap_tabledescr=>create( im_formatted_table_descr ).
catch cx_sy_struct_creation
cx_sy_table_creation into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
try.
create data ex_formatted_table_ref type handle lo_tabledescr_interleaved.
assign ex_formatted_table_ref->* to . " point to results for later export
catch cx_sy_create_data_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
try.
*-- create table work area
assign im_table_ref->* to .
create data lo_table_line_ref like line of .
assign lo_table_line_ref->* to .
*-- create interleaved table work area
create data lo_table_interleaved_ref like line of .
assign lo_table_interleaved_ref->* to .
catch cx_sy_create_data_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
*-- move data to , and inject delimiters
loop at into .
*-- iterate thru each component of interleaved structure
lv_counter = 0.
loop at im_formatted_table_descr->components assigning .
add 1 to lv_counter.
assign component -name of structure to .
lv_mod_result = lv_counter mod 2.
*-- populate field
if lv_mod_result ne 0.
*-- lookup original field to get type kind
assign component -name of structure to .
lv_typekind = cl_abap_elemdescr=>get_data_type_kind( ).
= .
*-- apply formatting to field
check is not initial.
case lv_typekind.
when cl_abap_typedescr=>typekind_time.
if im_format_time eq abap_true.
lv_time_internal = .
try.
call method cl_abap_timefm=>conv_time_int_to_ext
exporting
time_int = lv_time_internal
importing
time_ext = lv_time_external.
= lv_time_external.
catch cx_parameter_invalid_range.
clear .
endtry.
endif.
when cl_abap_typedescr=>typekind_date.
if im_format_date eq abap_true.
lv_date_internal = .
try.
call method cl_abap_datfm=>conv_date_int_to_ext
exporting
im_datint = lv_date_internal
importing
ex_datext = lv_date_external.
= lv_date_external.
catch cx_abap_datfm_format_unknown.
clear .
endtry.
endif.
when cl_abap_typedescr=>typekind_string
or cl_abap_typedescr=>typekind_char.
if im_enclose_strings eq abap_true.
replace all occurrences of '"' in with ''''.
concatenate '"' '"' into .
else.
*-- remove delimiter when not escaped with quotes
replace all occurrences of im_delimiter in with ` `.
endif.
when cl_abap_typedescr=>typekind_num
or cl_abap_typedescr=>typekind_packed
or cl_abap_typedescr=>typekind_int
or cl_abap_typedescr=>typekind_float.
call function 'CLOI_PUT_SIGN_IN_FRONT'
changing
value = .
endcase.
shift right deleting trailing space.
shift left deleting leading space.
else.
*-- populate delimiter
= im_delimiter.
endif.
endloop.
append to .
endloop.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_HEADER
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL
* | [--->] IM_POINT_HEADER_TO_DDIC TYPE ABAP_BOOL
* | [--->] IM_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [<---] EX_STRUCT_REF TYPE REF TO DATA
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method populate_header.
*-- object references
data: lo_elemdescr type ref to cl_abap_elemdescr,
lo_struct_descr type ref to cl_abap_structdescr,
lo_root_exc type ref to cx_root.
*-- internal table defintion
data: lt_components type cl_abap_structdescr=>component_table,
lt_hdr_components type cl_abap_structdescr=>component_table.
*-- structure defintion
data: ls_component type abap_componentdescr,
ls_hdr_component type abap_componentdescr,
ls_component_temp type abap_componentdescr,
ls_dfies type dfies.
*-- local variables
data: lv_normalized_name type c length 255,
lv_error_msg type string.
*-- field symbols
field-symbols: type any,
type any.
*-- call get_components to populate components from structure
lt_components = im_struct_descr->get_components( ).
loop at lt_components into ls_component.
*-- create new structure based on structure passed thru
try.
clear: ls_component_temp.
lo_elemdescr ?= ls_component-type.
if im_use_column_alignment eq abap_true.
*-- account for string elements which have no defined length
if lo_elemdescr->output_length eq 0.
ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 255 ).
else.
ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = lo_elemdescr->output_length ).
endif.
else.
ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 40 ).
endif.
ls_component_temp-name = ls_component-name.
append ls_component_temp to lt_hdr_components.
catch cx_sy_move_cast_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
endloop.
*-- get structure description from newly created component table
try.
lo_struct_descr =
cl_abap_structdescr=>create( lt_hdr_components ).
catch cx_sy_struct_creation into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
*-- now populate each field from previous ddic lookup
try.
create data ex_struct_ref type handle lo_struct_descr.
assign ex_struct_ref->* to .
catch cx_sy_create_data_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
loop at lt_hdr_components into ls_hdr_component.
assign component ls_hdr_component-name of structure to .
*-- lookup original component and read element description
read table lt_components with key name = ls_hdr_component-name into ls_component.
lo_elemdescr ?= ls_component-type.
*-- retrieve ddic description where relevant
if im_point_header_to_ddic eq abap_false.
lv_normalized_name = ls_hdr_component-name.
translate lv_normalized_name to lower case.
else.
*-- if ddic element, retrieve field label
if lo_elemdescr->is_ddic_type( ) eq abap_true.
ls_dfies = lo_elemdescr->get_ddic_field( ).
lv_normalized_name = ls_dfies-scrtext_l.
else.
*-- if not ddic element, set field label to pretty printed name of element
lv_normalized_name = ls_hdr_component-name.
replace all occurrences of '_' in lv_normalized_name with ` `.
translate lv_normalized_name to lower case.
translate lv_normalized_name+0(1) to upper case.
endif.
endif.
= lv_normalized_name.
endloop.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_TABLE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_TABLE TYPE ANY TABLE
* | [--->] IM_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR
* | [<---] EX_TABLE_REF TYPE REF TO DATA
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method populate_table.
*-- object references
data: lo_src_table_descr type ref to cl_abap_tabledescr,
lo_src_table_ref type ref to data,
lo_src_struct_descr type ref to cl_abap_structdescr,
lo_src_struct_ref type ref to data,
lo_dst_table_ref type ref to data,
lo_dst_struct_ref type ref to data,
lo_table_descr type ref to cl_abap_tabledescr,
lo_root_exc type ref to cx_root.
*-- local variables
data: lv_error_msg type string.
*-- field symbols
field-symbols: type standard table,
type any,
type standard table,
type any.
*-- prepare source table structures
try.
lo_src_table_descr ?= cl_abap_tabledescr=>describe_by_data( im_table ).
lo_src_struct_descr ?= lo_src_table_descr->get_table_line_type( ).
catch cx_sy_move_cast_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
create data lo_src_table_ref type handle lo_src_table_descr.
assign lo_src_table_ref->* to .
create data lo_src_struct_ref type handle lo_src_struct_descr.
assign lo_src_struct_ref->* to .
= im_table.
*-- prepare destination table structures (descriptions passed represent destination)
lo_table_descr = cl_abap_tabledescr=>create( im_struct_descr ).
create data lo_dst_table_ref type handle lo_table_descr.
assign lo_dst_table_ref->* to .
create data lo_dst_struct_ref type handle im_struct_descr.
assign lo_dst_struct_ref->* to .
*-- copy data between tables
loop at into .
move-corresponding to .
append to .
endloop.
ex_table_ref = lo_dst_table_ref.
endmethod.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>RECURSIVE_FILTER_COLUMNS
* +-------------------------------------------------------------------------------------------------+
* | [--->] IM_COLUMNS TYPE CSEQUENCE
* | [--->] IM_COMPONENTS TYPE CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE
* | [<---] EX_COMPONENTS TYPE CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE
* | [!CX!] ZCX_BC_TABLE_INTROSPECTOR
* +--------------------------------------------------------------------------------------
method recursive_filter_columns.
*-- object references
data: lo_elem_objectdescr type ref to cl_abap_objectdescr,
lo_struct_objectdescr type ref to cl_abap_objectdescr,
lo_structdescr type ref to cl_abap_structdescr,
lo_root_exc type ref to cx_root.
*-- internal table defintion
data: lt_components type cl_abap_structdescr=>component_table,
lt_components_filtered type cl_abap_structdescr=>component_table,
lt_inner_components type cl_abap_structdescr=>component_table,
lt_components_temp type cl_abap_structdescr=>component_table.
*-- structure defintion
data: ls_component type abap_componentdescr,
ls_component_temp type abap_componentdescr.
*-- local variables
data: lv_error_msg type string.
lt_components[] = im_components[].
*-- loop thru all components and convert to flat, filtered collection
loop at lt_components into ls_component.
*-- set up descriptors to test what subclass of cl_abap_typedescr is being processed (ABAP lacks instance of operator)
lo_elem_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_elemdescr' ).
lo_struct_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_structdescr' ).
*-- iterate thru each component: if component is an element, process directly; if component is a structure, process recursively
if lo_elem_objectdescr->applies_to( ls_component-type ) eq 'X'.
*-- skip MANDT column here
if ls_component-name eq 'MANDT'.
continue.
endif.
*-- adjust component collection based on selected columns (* or space defaults to all columns)
clear: ls_component_temp.
if im_columns ns '*' and im_columns is not initial.
move ls_component to ls_component_temp.
concatenate '\b' ls_component_temp-name '\b'
into ls_component_temp-name.
find regex ls_component_temp-name in im_columns ignoring case.
if sy-subrc <> 0.
"remove all occurrences
replace all occurrences of regex ls_component_temp-name in im_columns with ''.
continue.
endif.
endif.
append ls_component to lt_components_filtered.
elseif lo_struct_objectdescr->applies_to( ls_component-type ) eq 'X'.
try.
*-- cast to cl_abap_structdescr, get each component related to the structure, and process
lo_structdescr ?= ls_component-type.
catch cx_sy_move_cast_error into lo_root_exc.
lv_error_msg = lo_root_exc->get_text( ).
raise exception type zcx_bc_table_introspector
exporting
error_text = lv_error_msg.
endtry.
lt_inner_components = lo_structdescr->get_components( ).
*-- recursive call
call method recursive_filter_columns(
exporting
im_columns = im_columns
im_components = lt_inner_components
importing
ex_components = lt_components_temp ).
append lines of lt_components_temp to lt_components_filtered.
endif.
endloop.
*-- return new flat filtered component structure
ex_components[] = lt_components_filtered[].
endmethod.
ENDCLASS.