CLASS zini_cl_config_files DEFINITION FINAL.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*--[ Clase que se encarga de leer textos estandar via SO10
*--[ Y tratarlos como ficheros de configuracion estilo LINUX
*--[ Es un inicio
*--[
*--[ Para transportar los textos, bastara crear una entrada via SE09
*--[ En la orden con los siguientes datos:
*--[
*--[ R3TR TEXT TEXT,[AQUI_VA_EL_OBJETO],ST,S
*--[
*--[ O ejecutar el programa RSTXTRAN
*--[
PUBLIC SECTION.
CONSTANTS: c_version TYPE string VALUE 'v01.03' ##no_text ##NEEDED,
*--[ 01.01 - 20241220 + Creacion de la utilidad
*--[ 01.02 - 20241230 + Se anyade el editor de inicializacion desde F8
*--[ 01.03 - 20250107 + Anyadido sample config
*--[ + Seccion tecnica separada
c_error_no_ini_found TYPE sysubrc VALUE 1,
c_error_save_text TYPE sysubrc VALUE 2,
c_error_params TYPE sysubrc VALUE 3,
c_error_var_no_found TYPE sysubrc VALUE 4,
c_error_crear_init TYPE sysubrc VALUE 5,
c_TAG TYPE char4 VALUE 'ZINI' ##no_text,
c_spras TYPE spras VALUE 'S' ##no_text,
c_id TYPE tdid VALUE 'ST' ##no_text,
c_object TYPE tdobject VALUE 'TEXT' ##no_text.
TYPES: BEGIN OF ty_valor,
var TYPE char20,
var_u TYPE char20,
pos TYPE numc3,
val TYPE c LENGTH 112,
END OF ty_valor,
TY_valores TYPE STANDARD TABLE OF ty_valor WITH NON-UNIQUE DEFAULT KEY.
DATA: G_subrc TYPE sysubrc.
METHODS:
constructor IMPORTING p_ini_name TYPE string
p_config_data TYPE string OPTIONAL, "Inicializa y Lee
edit, " Editor de configuracion
set IMPORTING i_config TYPE string, " Inicializa el fichero de configuracion
get_data IMPORTING p_VAR TYPE string OPTIONAL " Recupera una variable del fichero
p_VAR_U TYPE string OPTIONAL
p_POS TYPE string OPTIONAL
CHANGING E_data TYPE any,
get_script RETURNING VALUE(R_script) TYPE string_t,
get_data_R IMPORTING p_VAR TYPE string OPTIONAL " Recupera una variable RANGO del fichero
p_VAR_U TYPE string OPTIONAL
p_POS TYPE string OPTIONAL
CHANGING E_data TYPE table,
get_DATA_all RETURNING VALUE(t_val) TYPE TY_valores. "Devuelve la tabla de valores entera!
PRIVATE SECTION.
CONSTANTS:
c_FORM TYPE tdform VALUE 'SYSTEM' ##no_text,
c_include TYPE char20 VALUE 'INCLUDE' ##no_text,
c_title TYPE char20 VALUE 'Config Script:' ##no_text,
c_begin_of TYPE char24 VALUE '#-->BEGIN OF CONFIG FILE' ##no_text,
c_end_of TYPE char24 VALUE '#<--END OF CONFIG FILE' ##no_text.
TYPES: BEGIN OF ty_ini,
ini_name TYPE string,
ini_data TYPE STANDARD TABLE OF string WITH NON-UNIQUE DEFAULT KEY,
INI_lines TYPE STANDARD TABLE OF tline WITH NON-UNIQUE DEFAULT KEY,
tab_head TYPE tlinet,
tab_tail TYPE tlinet,
ini_header TYPE thead,
END OF ty_ini.
DATA: t_data TYPE ty_ini,
t_valores TYPE STANDARD TABLE OF ty_Valor.
METHODS:
get_data_where IMPORTING p_VAR TYPE string OPTIONAL " <-- Se encarga de preparar la busqueda
p_VAR_U TYPE string OPTIONAL
p_POS TYPE string OPTIONAL
RETURNING VALUE(R_where) TYPE string,
save, " Graba un configuracion
get, " Lee la configuracion
get_ini RETURNING VALUE(t_ini) TYPE tlinet,
sanitize. " Purifica el fichero de configuracion
ENDCLASS.
CLASS zini_cl_config_files IMPLEMENTATION.
METHOD get_script.
DATA: ss TYPE string,
cm(1023).
LOOP AT t_data-ini_data INTO DATA(l_s).
AT FIRST.
APPEND |DATA(my_ini) = NEW zini_cl_config_files( p_ini_name = '{ t_data-ini_name }'| TO r_script ##no_text.
APPEND | p_config_data = CONV string( | TO r_script ##no_text.
ENDAT.
ss = |cl_abap_char_utilities=>cr_lf && '{ l_s }| ##no_text.
IF strlen( ss ) < 100.
cm = ss. " Chapuza para posicionarse
cm+100(4) = |' &&|.
ss = cm.
ELSE.
ss = |{ ss }' &&|.
ENDIF.
APPEND ss TO r_Script.
AT LAST.
APPEND |cl_abap_char_utilities=>cr_lf ) ).| TO r_script ##no_text.
ENDAT.
ENDLOOP.
ENDMETHOD.
METHOD get_data_all.
t_val = T_valores.
ENDMETHOD.
METHOD get_data_where.
CLEAR r_where.
IF p_var IS INITIAL AND p_var_u IS INITIAL.
g_subrc = c_error_params.
EXIT.
ENDIF.
IF p_VAR IS NOT INITIAL. R_where = 'VAR = p_var' ##no_text. ENDIF.
IF p_var_u IS NOT INITIAL. IF R_where IS INITIAL. R_where = 'VAR_U = p_var_u' ##no_text. ELSE. R_where = |{ R_where } and VAR_U = p_var_u| ##no_text. ENDIF. ENDIF.
IF p_pos IS NOT INITIAL. R_where = |{ R_where } and POS = P_POS| ##no_text. ENDIF.
ENDMETHOD.
METHOD get_data.
CLEAR e_data.
DATA(l_where) = CONV string( get_data_where( EXPORTING p_var = p_var p_var_u = p_var_u p_pos = p_pos ) ).
IF l_where IS INITIAL.
g_subrc = c_error_params.
ELSE.
LOOP AT t_valores INTO DATA(ax) WHERE (l_where).
E_data = ax-val.
EXIT.
ENDLOOP.
IF sy-subrc NE 0.
g_subrc = c_error_var_no_found.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD get_data_R.
*--[ Ejemplo de como se puede pasar una tabla interna desde la configuracion
FREE e_data.
DATA(l_where) = CONV string( get_data_where( EXPORTING p_var = p_var p_var_u = p_var_u p_pos = p_pos ) ).
IF l_where IS INITIAL.
g_subrc = c_error_params.
EXIT.
ENDIF.
*--[ Creamos la WA
DATA lin TYPE REF TO data.
CREATE DATA lin LIKE LINE OF E_data.
ASSIGN lin->* TO FIELD-SYMBOL(<bX>).
LOOP AT t_valores INTO DATA(ax) WHERE (l_where).
ASSIGN ('<BX>-SIGN') TO FIELD-SYMBOL(<a1>).
ASSIGN ('<BX>-OPTION') TO FIELD-SYMBOL(<a2>).
ASSIGN ('<BX>-LOW') TO FIELD-SYMBOL(<a3>).
ASSIGN ('<BX>-HIGH') TO FIELD-SYMBOL(<a4>).
*--[ Intenamos evitar problemas de formato
SPLIT ax-val AT ' ' INTO DATA(l_a) DATA(l_b) DATA(l_c) DATA(l_d).
<a1> = l_a. <a2> = l_b. <a3> = l_c. <a4> = l_d.
APPEND INITIAL LINE TO e_data ASSIGNING FIELD-SYMBOL(<cx>).
MOVE-CORRESPONDING <bx> TO <cx>.
ENDLOOP.
IF sy-subrc NE 0.
g_subrc = c_error_var_no_found.
ENDIF.
ENDMETHOD.
METHOD sanitize.
CHECK lines( t_data-ini_data ) > 0.
DATA(t_tmp) = T_data-ini_data[].
REFRESH t_valores.
LOOP AT t_tmp ASSIGNING FIELD-SYMBOL(<ax>).
<ax> = shift_left( <ax> ).
*--[ Eliminamos comentarios y bloques
IF <ax> CP '##*' OR <ax> CP ';*' OR <ax> IS INITIAL OR <ax> CP '[*'.
DELETE t_tmp INDEX sy-tabix.
CONTINUE.
ELSE.
*--[ Borramos los comentarios en medio del codigo
DATA(l_pos) = find( val = <ax> sub = '#' ).
IF l_pos > 0.
<ax> = substring( val = <ax> off = 0 len = l_pos ).
ENDIF.
SPLIT <ax> AT ' ' INTO DATA(l_valor_dir) "<-- Variable
DATA(l_valor_data). "<-- Contenido de la variable
l_valor_data = shift_left( l_valor_data ).
if to_upper( l_valor_data ) cp 'SY-*' or to_upper( l_valor_data ) cp 'SYST-*'.
assign (l_valor_data) to FIELD-SYMBOL(<al>).
if sy-subrc eq 0.
l_valor_data = <al>.
endif.
endif.
IF to_upper( l_valor_dir ) = c_include AND l_valor_data IS NOT INITIAL.
DATA(l_new) = NEW zini_cl_config_files( l_valor_data ).
IF l_new->g_subrc IS INITIAL.
APPEND LINES OF l_new->get_DATA_all( ) TO t_valores.
ENDIF.
ELSE.
t_valores = VALUE #( BASE t_valores ( var = l_valor_dir
var_u = to_upper( l_valor_dir )
pos = 0
val = l_valor_data ) ).
ENDIF.
ENDIF.
ENDLOOP.
LOOP AT t_valores INTO DATA(l_val) GROUP BY l_val-var_u.
DATA(l_index) = CONV numc3( 0 ).
*--[ Esto esta pensado para multiples valores, por ejemplo, pseudo tablas
LOOP AT t_valores ASSIGNING FIELD-SYMBOL(<bx>) WHERE var_u = l_val-var_u.
<bx>-pos = l_index = l_index + 1.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
METHOD get.
CLEAR T_data-ini_header.
CALL FUNCTION 'READ_TEXT'
EXPORTING
id = c_id
language = c_spras
name = CONV tdobname( T_data-ini_name )
object = c_object
IMPORTING
header = T_data-ini_header
TABLES
lines = T_data-ini_lines
EXCEPTIONS
id = 1
language = 2
name = 3
not_found = 4
object = 5
reference_check = 6
wrong_access_to_archive = 7
OTHERS = 8.
IF sy-subrc <> 0.
g_subrc = c_error_no_ini_found.
*--[ Posiblemente se tenga que crear uno nuevo
T_data-ini_header = VALUE #( tdobject = c_object
tdname = CONV tdobname( T_data-ini_name )
tdid = c_id
tdspras = c_spras
tdtitle = |{ c_title } { T_data-ini_name }| ##no_text
tdform = c_form
tdmacode2 = c_TAG
tdlinesize = 132
).
T_data-ini_lines = get_ini( ).
ENDIF.
LOOP AT T_data-ini_lines INTO DATA(ax).
AT FIRST. REFRESH: T_data-ini_data, T_data-tab_head, t_data-tab_TAIL. ENDAT.
IF ax-tdline CP |#{ c_begin_of }*|. APPEND ax TO t_data-tab_head. CONTINUE. ENDIF.
IF ax-tdline CP |#{ c_end_of }*|. APPEND ax TO t_data-tab_TAIL. CONTINUE. ENDIF.
T_data-ini_data = VALUE #( BASE T_data-ini_data ( CONV string( ax-tdline ) ) ).
ENDLOOP.
sanitize( ).
ENDMETHOD.
METHOD get_ini.
REFRESH t_ini.
t_ini = VALUE #( BASE t_ini tdformat = '*'
( tdline = |{ c_begin_of } { sy-datum } { sy-uzeit } { sy-uname }| )
( tdline = '# This is a sample config file ') ##no_text
( tdline = '# Use # or ; at first column for comment lines' ) ##no_text
( tdline = '' ) ##no_text
( tdline = '# Use this format to assign values ​​to variables' ) ##no_text
( tdline = 'PARAMETER VALUE' ) ##no_text
( tdline = '' ) ##no_text
( tdline = '#Sections and subsections are allowed, but they') ##no_text
( tdline = '#are more for aesthetics of the configuration.' ) ##no_text
( tdline = '[Seccion_001]' ) ##no_text
( tdline = '' ) ##no_text
( tdline = '# Use this format for tables-ranges' ) ##no_text
( tdline = 'MY_DATUM I GE 20250101 # This is a comment' ) ##no_text
( tdline = 'MY_DATUM I LE 20250101 # and this too' ) ##no_text
( tdline = '' ) ##no_text
( tdline = |# For further information, view { sy-repid }| ) ##no_text
).
ENDMETHOD.
METHOD set.
CLEAR g_subrc.
CHECK i_config IS NOT INITIAL. "<-- No Config No SAVE
CALL FUNCTION 'DELETE_TEXT'
EXPORTING
id = c_id
language = c_spras
name = CONV tdobname( T_data-ini_name )
object = c_object
savemode_direct = abap_true
EXCEPTIONS
not_found = 1
OTHERS = 2.
IF sy-subrc NE 0. CLEAR sy-subrc. ENDIF.
REFRESH: t_data-ini_data, t_data-INI_lines.
CLEAR T_data-ini_header .
SPLIT i_config AT cl_abap_char_utilities=>cr_lf INTO TABLE t_data-ini_data.
* LOOP AT p_data INTO DATA(l_data).
* t_data-ini_data = VALUE #( BASE t_data-ini_data ( l_data ) ).
* ENDLOOP.
T_data-ini_header = VALUE #( tdobject = c_object
tdname = CONV tdobname( T_data-ini_name )
tdid = c_id
tdspras = c_spras
tdtitle = T_data-ini_name
tdform = c_form
tdlinesize = 132
).
save( ).
IF g_subrc IS INITIAL.
get( ).
ELSE.
g_subrc = c_error_crear_init.
ENDIF.
ENDMETHOD.
METHOD save.
IF lines( t_data-ini_data ) > 0.
LOOP AT T_data-ini_data INTO DATA(ax).
AT FIRST. REFRESH T_data-ini_lines. APPEND LINES OF t_data-tab_head TO t_data-ini_lines. ENDAT.
T_data-ini_lines = VALUE #( BASE T_data-ini_lines ( tdformat = '*' tdline = CONV string( ax ) ) ).
AT LAST.
APPEND LINES OF t_data-tab_tail TO t_data-ini_lines.
T_data-ini_lines = VALUE #( BASE T_data-ini_lines ( tdformat = '*' tdline = |{ c_end_of } { sy-datum } { sy-uzeit } { sy-uname }| ) ).
CALL FUNCTION 'CONVERT_STREAM_TO_ITF_TEXT'
EXPORTING
lf = abap_true
language = c_spras
iv_lw = 132
TABLES
text_stream = T_data-ini_data
itf_text = T_data-ini_lines.
T_data-ini_header-tdmacode2 = c_TAG .
IF T_data-ini_header-tdtitle = T_data-ini_header-tdname.
T_data-ini_header-tdtitle = |{ c_title } { T_data-ini_header-tdname }|.
ENDIF.
CALL FUNCTION 'SAVE_TEXT'
EXPORTING
header = T_data-ini_header
savemode_direct = abap_true
TABLES
lines = T_data-ini_lines
EXCEPTIONS
id = 1
language = 2
name = 3
object = 4
OTHERS = 5.
IF sy-subrc NE 0.
MESSAGE s398(00) WITH 'Error al grabar configuracion' T_data-ini_header-tdname '' '' DISPLAY LIKE 'E' ##no_text.
ENDIF.
ENDAT.
ENDLOOP.
ELSE.
sy-subrc = 4.
ENDIF.
CHECK sy-subrc <> 0.
g_subrc = c_error_save_text.
ENDMETHOD.
METHOD edit.
CALL FUNCTION 'TERM_CONTROL_EDIT'
EXPORTING
titel = T_data-ini_header-tdtitle
langu = c_spras
TABLES
textlines = T_data-ini_data
EXCEPTIONS
user_cancelled = 1
OTHERS = 2.
check sy-subrc EQ 0.
if lines( T_data-ini_data ) = 0.
append '# There is nothing to see here.' to T_data-ini_data.
append '# Please disperse.' to T_data-ini_data.
endif.
save( ).
ENDMETHOD.
METHOD constructor.
T_data-ini_name = p_ini_name.
get( ).
IF g_subrc = c_error_no_ini_found AND p_config_data IS NOT INITIAL.
set( p_config_data ).
ENDIF.
ENDMETHOD.
ENDCLASS.