diff --git a/zsaplink_generic_obj.clas.abap b/zsaplink_generic_obj.clas.abap new file mode 100644 index 000000000..db054c9a3 --- /dev/null +++ b/zsaplink_generic_obj.clas.abap @@ -0,0 +1,358 @@ +* This class is intended to provide generic serialization based on SOBJ-definitions. +* For developers inheriting from this class: BE AWARE: This class will directly insert into +* and delete dynamically from the object's metadata-tables. +* Though this has been tested and is based upon code developed by SAP for a similar purpose, +* this is a risky operation. Please do verify the where-statements generated by the XML-bridge +* for correctness of your dedicated object-type! +* No risk, no fun. +CLASS zsaplink_generic_obj DEFINITION + PUBLIC + INHERITING FROM zsaplink + ABSTRACT + CREATE PUBLIC . + + PUBLIC SECTION. + + METHODS constructor + IMPORTING + !name TYPE string . + + METHODS checkexists + REDEFINITION . + METHODS createixmldocfromobject + REDEFINITION . + METHODS createobjectfromixmldoc + REDEFINITION . + PROTECTED SECTION. + + TYPES: + BEGIN OF ty_s_tlogo_tables, + tabname TYPE ddobjname, + where_clause TYPE string, + data TYPE REF TO data, + END OF ty_s_tlogo_tables . + TYPES: + ty_t_tlogo_tables TYPE SORTED TABLE OF ty_s_tlogo_tables WITH UNIQUE KEY tabname . + + METHODS add_table_metadata + IMPORTING + !io_ixmldocument TYPE REF TO if_ixml_document + !io_root_node TYPE REF TO if_ixml_element . + METHODS serialize_table_content + IMPORTING + !io_ixmldocument TYPE REF TO if_ixml_document + !io_root_node TYPE REF TO if_ixml_element + RAISING + zcx_saplink . + METHODS update_db_table_content + IMPORTING + !i_ixmldocument TYPE REF TO if_ixml_document + RAISING + zcx_saplink . + + METHODS deleteobject + REDEFINITION . + PRIVATE SECTION. + + DATA mo_xml_bridge TYPE REF TO lcl_tlogo_xml_bridge . + CONSTANTS co_xml_metadata TYPE string VALUE 'objMetaData' ##NO_TEXT. + + METHODS get_xml_bridge + RETURNING + VALUE(ro_xml_bridge) TYPE REF TO lcl_tlogo_xml_bridge . + METHODS metadata_to_xml + IMPORTING + !it_metadata TYPE lcl_tlogo_xml_bridge=>tt_obj_metadata + RETURNING + VALUE(ro_metadata_element) TYPE REF TO if_ixml_element . + METHODS xml_to_metadata + IMPORTING + !io_metadata_element TYPE REF TO if_ixml_element + RETURNING + VALUE(rt_metadata) TYPE lcl_tlogo_xml_bridge=>tt_obj_metadata . + METHODS validate_metadata + IMPORTING + !it_metadata TYPE lcl_tlogo_xml_bridge=>tt_obj_metadata + RAISING + zcx_saplink . +ENDCLASS. + + + +CLASS ZSAPLINK_GENERIC_OBJ IMPLEMENTATION. + + + METHOD add_table_metadata. + +* add the table's metdata + DATA(lt_metadata) = get_xml_bridge( )->get_table_metadata( CONV #( me->objname ) ). + +* encapsulate the simple transformation metadata-table-element to have a fixed name + DATA(lo_md_element) = io_ixmldocument->create_element( co_xml_metadata ). + lo_md_element->append_child( me->metadata_to_xml( lt_metadata ) ). + io_root_node->append_child( lo_md_element ). + + ENDMETHOD. + + + METHOD checkexists. + exists = me->get_xml_bridge( )->exists( CONV #( objname ) ). + ENDMETHOD. + + + METHOD constructor. +*/---------------------------------------------------------------------\ +*| This file is part of SAPlink. | +*| | +*| SAPlink is free software; you can redistribute it and/or modify | +*| it under the terms of the GNU General Public License as published | +*| by the Free Software Foundation; either version 2 of the License, | +*| or (at your option) any later version. | +*| | +*| SAPlink is distributed in the hope that it will be useful, | +*| but WITHOUT ANY WARRANTY; without even the implied warranty of | +*| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | +*| GNU General Public License for more details. | +*| | +*| You should have received a copy of the GNU General Public License | +*| along with SAPlink; if not, write to the | +*| Free Software Foundation, Inc., | +*| 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | +*\---------------------------------------------------------------------/ + super->constructor( name = name ). + + ENDMETHOD. + + + METHOD createixmldocfromobject. +* convention by saplink: The root element has to be named with the OBJTYPE, +* the first attribute of the root node denotes the objname + DATA lo_root_node TYPE REF TO if_ixml_element. + ixmldocument = ixml->create_document( ). + + lo_root_node = ixmldocument->create_element( me->getobjecttype( ) ). + lo_root_node->set_attribute( + name = 'objname' " NAME + value = objname + ). + + serialize_table_content( + io_ixmldocument = ixmldocument + io_root_node = lo_root_node ). + + add_table_metadata( + io_ixmldocument = ixmldocument + io_root_node = lo_root_node ). + + ixmldocument->append_child( lo_root_node ). + + ENDMETHOD. + + + METHOD createobjectfromixmldoc. + +* validate the metadata of the underlying DB tables +* As insert/update/delete to a table is being performed, the table structure actually +* defines an interface. The compatibility of this interface has to be validated prior +* to consuming it + DATA(lo_obj_metadata_elem) = ixmldocument->get_elements_by_tag_name( name = co_xml_metadata )->get_item( 0 ). + + IF lo_obj_metadata_elem IS INITIAL. + BREAK-POINT. "this seems to be an old file-format where no consistency between the tables can be checked. +* => proceed only if you know what you're doing and jump over the next statement. + RAISE EXCEPTION TYPE zcx_saplink + EXPORTING + textid = zcx_saplink=>error_message + msg = 'Old (unsupported) format'. + ELSE. + DATA(lt_obj_metadata) = me->xml_to_metadata( CAST #( lo_obj_metadata_elem->get_first_child( ) ) ). + me->validate_metadata( lt_obj_metadata ). + ENDIF. + +* write the content serialized in the XML document into the DB tables + update_db_table_content( ixmldocument ). + + ENDMETHOD. + + + METHOD deleteobject. + "do not do anything - the update of the object implicitly deletes obsolete entries + ASSERT 1 = 1. + + RETURN. + +* there is an opportunity to explicitly purge all tables with the corresponding keys, +* but this is actually not necessary (and quite a critical operation). + get_xml_bridge( )->delete_object( CONV #( objname ) ). + + ENDMETHOD. + + + METHOD get_xml_bridge. + IF mo_xml_bridge IS INITIAL. +* can't be called in the constructor as getObjectType is intended to be polymorphic + mo_xml_bridge = NEW lcl_tlogo_xml_bridge( i_tlogo = CONV #( me->getobjecttype( ) ) ). + ENDIF. + + ro_xml_bridge = mo_xml_bridge. + + ENDMETHOD. + + + METHOD metadata_to_xml. + DATA(lo_document_md) = ixml->create_document( ). + + CALL TRANSFORMATION id + SOURCE metadata = it_metadata + RESULT XML lo_document_md. + + ro_metadata_element = lo_document_md->get_root_element( ). + + ENDMETHOD. + + + METHOD serialize_table_content. + +* read table content to XML + IF get_xml_bridge( )->exists( CONV #( me->objname ) ) = abap_false. + RAISE EXCEPTION TYPE zcx_saplink + EXPORTING + textid = zcx_saplink=>not_found. + ENDIF. + + get_xml_bridge( )->compose_xml( + EXPORTING + i_objnm = CONV #( me->objname ) " Object name in object directory + IMPORTING + e_string_xml = DATA(lv_string_xml) " XML Data + ). + + DATA(lo_xml_bridge_document) = convertstringtoixmldoc( xmlstring = lv_string_xml ). + + io_root_node->append_child( lo_xml_bridge_document->get_root_element( ) ). + + ENDMETHOD. + + + METHOD update_db_table_content. + +* unpack the actual document from the saplink-specific wrapper + DATA(lo_xml_bridge_transport_elem) = i_ixmldocument->get_elements_by_tag_name( name = CONV #( lcl_tlogo_xml_bridge=>p_c_xml_tag_transport ) )->get_item( 0 ). + IF lo_xml_bridge_transport_elem IS INITIAL. + RAISE EXCEPTION TYPE zcx_saplink + EXPORTING + textid = zcx_saplink=>incorrect_file_format + msg = 'No object data found'. + ELSE. + DATA(lo_xml_bridge_document) = cl_ixml=>create( )->create_document( ). + lo_xml_bridge_document->append_child( lo_xml_bridge_transport_elem ). + ENDIF. + +* during existence check, a sanity check is being performed (that not more than one entry in the +* primary table is affected). Thus, issue an existence check without evaluating the result + get_xml_bridge( )->exists( CONV #( me->objname ) ). + + + get_xml_bridge( )->parse_xml( + EXPORTING + i_objnm = CONV #( me->objname ) " Object name in object directory + i_string_xml = convertixmldoctostring( lo_xml_bridge_document ) " String with XML Data + IMPORTING + e_subrc = DATA(lv_subrc_parsing) " Return Value, Return Value After ABAP Statements + ). + IF lv_subrc_parsing IS INITIAL. + + get_xml_bridge( )->save( + IMPORTING + e_subrc = DATA(lv_subrc_save) + ). + + IF lv_subrc_save IS INITIAL. + +* perform after import methods + get_xml_bridge( )->activate( ). + ELSE. + RAISE EXCEPTION TYPE zcx_saplink + EXPORTING + textid = zcx_saplink=>error_message + msg = |An error occurred when saving { objname }. Check Application log Object { cl_rso_repository=>p_c_bal_log_object }|. + ENDIF. + + ELSE. + RAISE EXCEPTION TYPE zcx_saplink + EXPORTING + textid = zcx_saplink=>error_message + msg = 'Object could not be identified in source'. + ENDIF. + + ENDMETHOD. + + + METHOD validate_metadata. +* this method checks whether the metadata of the tables of the transport object +* substantially differ between the object serialized and the current system. +* This is necessary as the DB-table is treated as interface in this tool + +* all the tables which are filled in the source need to exist locally with all fields from +* the source system existing with the same technical datatype locally as well + DEFINE exception_metadata. + RAISE EXCEPTION TYPE zcx_saplink + EXPORTING + textid = zcx_saplink=>error_message + msg = 'Database structure differs. Object cannot be imported.'. + END-OF-DEFINITION. + + LOOP AT it_metadata ASSIGNING FIELD-SYMBOL() WHERE count > 0. "only the relevant tables need to be validated + + DATA lt_dfies TYPE dfies_table. + +* get the DDIC info of the local table structure + CALL FUNCTION 'DDIF_NAMETAB_GET' + EXPORTING + tabname = CONV ddobjname( -db_table ) + TABLES + dfies_tab = lt_dfies + EXCEPTIONS + not_found = 1. + ASSERT sy-subrc = 0. + +* compare the fields-information which is relevant to technical compatibility. + LOOP AT -fields_definition ASSIGNING FIELD-SYMBOL(). + READ TABLE lt_dfies ASSIGNING FIELD-SYMBOL() WITH KEY fieldname = -fieldname. + IF sy-subrc NE 0. + exception_metadata. + ENDIF. + + IF -datatype NE -datatype + OR -inttype NE -inttype. + exception_metadata. + ENDIF. + + IF -leng NE -leng. + "-intlen NE -intlen. Does not have to be the same when transporting between unicode and non-unicode-systems + exception_metadata. + ENDIF. + + IF -decimals NE -decimals. + exception_metadata. + ENDIF. + + ENDLOOP. + + ENDLOOP. + + ENDMETHOD. + + + METHOD xml_to_metadata. + + DATA(lo_document_md) = ixml->create_document( ). + + lo_document_md->append_child( io_metadata_element ). + + CALL TRANSFORMATION id + SOURCE XML lo_document_md + RESULT metadata = rt_metadata . + + ENDMETHOD. +ENDCLASS. \ No newline at end of file diff --git a/zsaplink_generic_obj.clas.locals_def.abap b/zsaplink_generic_obj.clas.locals_def.abap new file mode 100644 index 000000000..3cd716c30 --- /dev/null +++ b/zsaplink_generic_obj.clas.locals_def.abap @@ -0,0 +1,147 @@ +CLASS lcl_rso_tlogo_xml_bridge DEFINITION + CREATE PUBLIC . + +************************************************************************** +* This is slightly modified-copy of CL_RSO_TLOGO_XML_BRIDGE which provides +* features to serialize a logical transport object based on its definition +* in SOBJ. Sadly, the original class hides some information needed in +* private tables. The modification done is to move all this content into +* the protected one. + +*"* public components of class CL_RSO_TLOGO_XML_BRIDGE +*"* do not include other source files here!!! + PUBLIC SECTION. + TYPE-POOLS rs . + INTERFACE if_rso_object_xmic LOAD . + INTERFACE if_rso_repository_xml_const LOAD . + + CONSTANTS p_c_xml_tag_transport TYPE char40 + VALUE 'transport'. "#EC NOTEXT . + + CLASS-METHODS class_constructor . + METHODS activate . + METHODS compose_xml + IMPORTING + !i_objnm TYPE sobj_name + !i_objvers TYPE rsobjvers DEFAULT rs_c_objvers-active + EXPORTING + !e_string_xml TYPE string . + METHODS constructor + IMPORTING + !i_tlogo TYPE rstlogo + EXCEPTIONS + tlogo_doesnt_exist . + METHODS parse_xml + IMPORTING + !i_objnm TYPE sobj_name + !i_string_xml TYPE string + !i_detlevel TYPE bal_s_msg-detlevel DEFAULT '1' + EXPORTING + !e_subrc TYPE sysubrc . + METHODS save + IMPORTING + !i_detlevel TYPE bal_s_msg-detlevel DEFAULT '1' + EXPORTING + !e_subrc TYPE sysubrc . + METHODS get_timestmp_of_data + RETURNING + VALUE(r_timestmp) TYPE rstimestmp . + PROTECTED SECTION. +*"* protected components of class CL_RSO_TLOGO_XML_BRIDGE +*"* do not include other source files here!!! + + METHODS before_export . + " private section. +*"* private components of class CL_RSO_TLOGO_XML_BRIDGE +*"* do not include other source files here!!! + + TYPES: + pt_t_objsl TYPE STANDARD TABLE OF objsl . + TYPES: + pt_ts_objsl TYPE SORTED TABLE OF objsl + WITH UNIQUE KEY objectname objecttype trwcount . + TYPES: + BEGIN OF pt_s_tlogo_tables, + tabname TYPE ddobjname, + where_clause TYPE string, + data TYPE REF TO data, + END OF pt_s_tlogo_tables. . + TYPES: + pt_t_tlogo_tables TYPE STANDARD TABLE OF pt_s_tlogo_tables . + TYPES: + pt_ts_tlogo_tables TYPE SORTED TABLE OF pt_s_tlogo_tables + WITH UNIQUE KEY tabname . + TYPES: + pt_t_objm TYPE STANDARD TABLE OF objm . + TYPES: + pt_ts_objm TYPE SORTED TABLE OF objm + WITH UNIQUE KEY objectname objecttype method . + + CONSTANTS p_c_xml_tag_field TYPE char40 VALUE 'field' . + CONSTANTS p_c_xml_tag_key TYPE char40 VALUE 'key' . + CONSTANTS p_c_xml_tag_row TYPE char40 VALUE 'row' . + CONSTANTS p_c_xml_tag_table TYPE char40 VALUE 'table' . + CLASS-DATA p_r_ixml TYPE REF TO if_ixml . + CLASS-DATA p_r_repository TYPE REF TO cl_rso_repository . + CLASS-DATA p_r_stream_factory TYPE REF TO if_ixml_stream_factory . + DATA p_objnm TYPE sobj_name . + DATA p_s_objh TYPE objh . + DATA p_s_tlogoprop TYPE rstlogoprop . + DATA p_tlogo TYPE rstlogo . + DATA p_ts_objm TYPE pt_ts_objm . + DATA p_ts_objsl TYPE pt_ts_objsl . + DATA p_ts_tlogo_tables TYPE pt_ts_tlogo_tables . + DATA p_timestmp TYPE rstimestmp . + + METHODS read_tlogo_prop . +ENDCLASS. + +CLASS lcl_tlogo_xml_bridge DEFINITION INHERITING FROM lcl_rso_tlogo_xml_bridge + CREATE PUBLIC. + PUBLIC SECTION. + TYPES: BEGIN OF ty_obj_metadata, + db_table TYPE tabname, + count TYPE i, + fields_definition TYPE dfies_table, + END OF ty_obj_metadata, + tt_obj_metadata TYPE SORTED TABLE OF ty_obj_metadata WITH UNIQUE KEY db_table. + + METHODS + exists + IMPORTING + iv_objname TYPE objname + RETURNING VALUE(rv_object_exists) TYPE abap_bool. + + METHODS delete_object + IMPORTING + iv_objname TYPE objname + RETURNING VALUE(rv_deleted) TYPE abap_bool. + + METHODS get_table_metadata + IMPORTING + iv_objname TYPE objname + RETURNING + VALUE(rt_metadata) TYPE lcl_tlogo_xml_bridge=>tt_obj_metadata. + + PROTECTED SECTION. + METHODS + get_where_clause + IMPORTING + iv_tobj_name TYPE sobj_name + iv_objname TYPE objname + RETURNING VALUE(rv_where_on_keys) TYPE string. + + METHODS validate_count_prim_table + IMPORTING + iv_objname TYPE objname + iv_dbcount LIKE sy-dbcnt. + PRIVATE SECTION. + + METHODS timestamp_to_xml + IMPORTING iv_timestamp TYPE timestamp + RETURNING VALUE(rv_string) TYPE string. + + METHODS get_prim_table_objsl + RETURNING + VALUE(rs_objsl) LIKE line of p_ts_objsl. +ENDCLASS. \ No newline at end of file diff --git a/zsaplink_generic_obj.clas.locals_imp.abap b/zsaplink_generic_obj.clas.locals_imp.abap new file mode 100644 index 000000000..d31cf0f75 --- /dev/null +++ b/zsaplink_generic_obj.clas.locals_imp.abap @@ -0,0 +1,887 @@ +CLASS lcl_rso_tlogo_xml_bridge IMPLEMENTATION. + + METHOD activate . + + FIELD-SYMBOLS: TYPE rs_s_tr_prot. + DATA: l_t_tr_prot TYPE rs_t_tr_prot, + l_t_e071 TYPE STANDARD TABLE OF e071, + l_s_e071 TYPE e071, + l_t_e071k TYPE STANDARD TABLE OF e071k. + DATA: l_s_msg TYPE rs_s_msg. + + CHECK NOT p_ts_tlogo_tables IS INITIAL. + +* start the after import method + l_s_e071-pgmid = rs_c_pgmid_r3tr. + l_s_e071-object = p_tlogo. + l_s_e071-obj_name = p_objnm. + INSERT l_s_e071 INTO TABLE l_t_e071. + + CALL FUNCTION 'RS_AFTER_IMPORT' + EXPORTING + i_mode = rs_c_after_import_mode-activate + IMPORTING + e_t_tr_prot = l_t_tr_prot + TABLES + tt_e071 = l_t_e071 + tt_e071k = l_t_e071k. + LOOP AT l_t_tr_prot ASSIGNING . + l_s_msg-msgid = -ag. + l_s_msg-msgno = -msgnr. + l_s_msg-msgv1 = -var1. + l_s_msg-msgv2 = -var2. + l_s_msg-msgv3 = -var3. + l_s_msg-msgv4 = -var4. + CALL METHOD cl_rso_application_log=>if_rso_application_log~add_message_as_structure + EXPORTING + i_s_msg = l_s_msg. + ENDLOOP. + + ENDMETHOD. " + + METHOD before_export . + + FIELD-SYMBOLS: TYPE objm. + DATA: l_t_e071 TYPE STANDARD TABLE OF e071, + l_s_e071 TYPE e071, + l_t_e071k TYPE STANDARD TABLE OF e071k, + l_s_e071k TYPE e071k, + l_client TYPE trclient. + + l_client = sy-mandt. + + l_s_e071-pgmid = rs_c_pgmid_r3tr. + l_s_e071-object = p_tlogo. + l_s_e071-obj_name = p_objnm. + INSERT l_s_e071 INTO TABLE l_t_e071. + + READ TABLE p_ts_objm ASSIGNING + WITH TABLE KEY objectname = p_tlogo objecttype = 'L' method = 'BEFORE_EXP'. + IF sy-subrc = 0. + CALL FUNCTION -methodname + EXPORTING + iv_client = l_client + TABLES + tt_e071 = l_t_e071 + tt_e071k = l_t_e071k. + ENDIF. + + ENDMETHOD. " + + METHOD class_constructor . + +* repository + p_r_repository = cl_rso_repository=>get_repository( ). +* iXML stream factor + p_r_stream_factory = cl_rso_repository=>get_stream_factory( ). +* iXML library + p_r_ixml = cl_ixml=>create( ). + + ENDMETHOD. " + + METHOD compose_xml . + + TYPES: BEGIN OF lt_s_objkey , + num TYPE numc3, + value TYPE char128, + END OF lt_s_objkey, + lt_ts_objkey TYPE SORTED TABLE OF lt_s_objkey +WITH UNIQUE KEY num. + + FIELD-SYMBOLS: TYPE objsl. + FIELD-SYMBOLS: TYPE STANDARD TABLE, + TYPE any. + FIELD-SYMBOLS: TYPE dfies. + FIELD-SYMBOLS: TYPE any. + DATA: l_t_dfies TYPE STANDARD TABLE OF dfies, + l_tabname TYPE ddobjname. + DATA: l_s_data TYPE REF TO data, + l_t_data TYPE REF TO data. + DATA: l_where_stmt TYPE string. + DATA: l_n TYPE i, + l_m TYPE i, + l_k TYPE i, + l_len TYPE i. + DATA: l_s_objkey TYPE lt_s_objkey, + l_ts_objkey TYPE lt_ts_objkey, + l_num TYPE numc3. + DATA: l_value128 TYPE char128. + DATA: l_r_document TYPE REF TO if_ixml_document. + DATA: l_r_element_transport TYPE REF TO if_ixml_element, + l_r_element_table TYPE REF TO if_ixml_element, + l_r_element_row TYPE REF TO if_ixml_element, + l_r_element_key TYPE REF TO if_ixml_element, + l_r_element TYPE REF TO if_ixml_element. + DATA: l_value TYPE string, + l_name TYPE string. + DATA: l_rc TYPE i. + DATA: l_r_ostream TYPE REF TO if_ixml_ostream. + DATA: l_r_renderer TYPE REF TO if_ixml_renderer. + DATA: l_r_encoding TYPE REF TO if_ixml_encoding. + DATA: l_r_cdata TYPE REF TO if_ixml_cdata_section. + DATA: l_flag_asterics TYPE rs_bool. + DATA: l_timestmp TYPE rstimestmp. + + p_objnm = i_objnm. + +* call the before export method + CALL METHOD before_export. + +* create the output stream for the output string + CLEAR e_string_xml. + l_r_ostream = p_r_stream_factory->create_ostream_cstring( string = e_string_xml ). +* create the XML document + l_r_document = p_r_ixml->create_document( ). +* set UTF-8 encoding + l_r_encoding = cl_rso_repository=>get_xml_encoding( + i_byte_order = 0 i_character_set = 'latin1' ). + CALL METHOD l_r_document->set_encoding( + encoding = l_r_encoding ). + +* XML: + l_name = p_c_xml_tag_transport. + CLEAR l_value. + l_r_element_transport = l_r_document->create_element( name = l_name ). + l_rc = l_r_document->append_child( l_r_element_transport ). +* XML: date (for comparison with object, last changed ) + l_name = if_rso_object_xmic=>timestmp. + GET TIME STAMP FIELD l_timestmp. + l_value = cl_rso_repository=>timestamp_to_xml( l_timestmp ). + l_r_element = l_r_document->create_simple_element( + name = l_name value = l_value parent = l_r_element_transport ). + +* parse all tables of this TLOGO object + LOOP AT p_ts_objsl ASSIGNING . + CLEAR l_where_stmt. + +* XML: + l_name = p_c_xml_tag_table. + CLEAR l_value. + l_r_element_table = l_r_document->create_simple_element( + name = l_name + value = l_value + parent = l_r_element_transport ). +* add attribute: name (ID) + l_name = if_rso_repository_xml_const=>id. + l_value = -tobj_name. + l_rc = l_r_element_table->set_attribute( + name = l_name value = l_value ). + +* get the DDIC info of the table structure + l_tabname = -tobj_name. + CALL FUNCTION 'DDIF_NAMETAB_GET' + EXPORTING + tabname = l_tabname + TABLES + dfies_tab = l_t_dfies + EXCEPTIONS + not_found = 1. + IF sy-subrc <> 0. +* message + EXIT. + ENDIF. + +* compose the key (table) + CLEAR l_ts_objkey. + CLEAR l_s_objkey. + l_n = 0. + l_num = 1. + l_k = 0. + l_len = strlen( -tobjkey ). + WHILE l_n <= l_len. + l_s_objkey-num = l_num. +* command + IF -tobjkey+l_n(1) = '/'. + IF NOT l_s_objkey-value IS INITIAL. + INSERT l_s_objkey INTO TABLE l_ts_objkey. + ADD 1 TO l_num. + CLEAR l_s_objkey. + l_s_objkey-num = l_num. + ENDIF. + l_m = l_n + 1. +* '*' means all futher key values + IF -tobjkey+l_m(1) = '*'. + l_s_objkey-value = '*'. + INSERT l_s_objkey INTO TABLE l_ts_objkey. + CLEAR l_s_objkey. + ADD 1 TO l_num. + ADD 1 TO l_n. +* object name + ELSEIF -tobjkey+l_m(1) = '&'. + l_s_objkey-value = i_objnm. +* #CP-SUPPRESS: FP no risc + INSERT l_s_objkey INTO TABLE l_ts_objkey. + CLEAR l_s_objkey. + ADD 1 TO l_num. + ADD 1 TO l_n. +* language + ELSEIF -tobjkey+l_m(1) = 'L'. + l_s_objkey-value = sy-langu. + INSERT l_s_objkey INTO TABLE l_ts_objkey. + CLEAR l_s_objkey. + ADD 1 TO l_num. + ADD 1 TO l_n. + ENDIF. + l_k = 0. +* value + ELSE. + l_s_objkey-value+l_k(1) = -tobjkey+l_n(1). + ADD 1 TO l_k. + ENDIF. + + ADD 1 TO l_n. + ENDWHILE. + IF NOT l_s_objkey-value IS INITIAL. + INSERT l_s_objkey INTO TABLE l_ts_objkey. + ENDIF. + +* compose the where clause + l_flag_asterics = rs_c_false. +* XML: + l_name = p_c_xml_tag_key. + l_r_element_key = l_r_document->create_simple_element( + name = l_name + parent = l_r_element_table ). + l_num = 1. + CLEAR l_where_stmt. +* CONCATENATE '''' i_objvers '''' INTO l_value128. +* CONCATENATE 'OBJVERS' '=' l_value128 INTO l_where_stmt +* SEPARATED BY space. + LOOP AT l_t_dfies ASSIGNING + WHERE NOT keyflag IS INITIAL. +* #CP-SUPPRESS: FP no risc + READ TABLE l_ts_objkey INTO l_s_objkey + WITH TABLE KEY num = l_num. + IF sy-subrc <> 0 + OR -fieldname = 'LANGU'. + CLEAR l_s_objkey. + ADD 1 TO l_num. + CONTINUE. + ENDIF. + IF l_s_objkey-value = '*'. + l_flag_asterics = rs_c_true. + ENDIF. + IF l_flag_asterics = rs_c_true. + CONTINUE. + ENDIF. + IF NOT l_where_stmt IS INITIAL. +* #CP-SUPPRESS: FP no risc + CONCATENATE l_where_stmt 'AND' INTO l_where_stmt + SEPARATED BY space. + ENDIF. +* #CP-SUPPRESS: FP no risc + CONCATENATE '''' l_s_objkey-value '''' INTO l_value128. +* #CP-SUPPRESS: FP no risc + CONCATENATE l_where_stmt -fieldname '=' + l_value128 INTO l_where_stmt SEPARATED BY space. + ADD 1 TO l_num. +* XML: + l_name = -fieldname. + l_r_element = l_r_document->create_simple_element( + name = l_name parent = l_r_element_key ). + l_value = l_s_objkey-value. + l_r_cdata = l_r_document->create_cdata_section( l_value ). + l_rc = l_r_element->append_child( l_r_cdata ). + + ENDLOOP. + +* select from database table using the key + CREATE DATA l_s_data TYPE (-tobj_name). + ASSIGN l_s_data->* TO . + CREATE DATA l_t_data TYPE STANDARD TABLE OF (-tobj_name). + ASSIGN l_t_data->* TO . + +* #CP-SUPPRESS: FP no risc + SELECT * FROM (-tobj_name) INTO TABLE + WHERE (l_where_stmt). + +* write all selected rows + LOOP AT ASSIGNING . +* XML: + l_name = p_c_xml_tag_row. + CLEAR l_value. + l_r_element_row = l_r_document->create_simple_element( + name = l_name + value = l_value + parent = l_r_element_table ). +* write field/value pairs to to XML stream + LOOP AT l_t_dfies ASSIGNING . + ASSIGN COMPONENT -fieldname OF STRUCTURE TO . +* XML: + l_name = p_c_xml_tag_field. + l_r_element = l_r_document->create_simple_element( + name = l_name + parent = l_r_element_row ). + IF NOT IS INITIAL. + l_value = . + l_r_element = l_r_document->create_simple_element( + name = l_name + parent = l_r_element_row ). + l_r_cdata = l_r_document->create_cdata_section( l_value ). + l_rc = l_r_element->append_child( l_r_cdata ). + ENDIF. +* add attribute: fieldname name (ID) + l_name = if_rso_repository_xml_const=>id. + l_value = -fieldname. + l_rc = l_r_element->set_attribute( + name = l_name value = l_value ). + ENDLOOP. + ENDLOOP. + ENDLOOP. + +* render the DOM tree into an XML document + l_r_renderer = p_r_ixml->create_renderer( + ostream = l_r_ostream document = l_r_document ). + l_rc = l_r_renderer->render( ). + + REPLACE 'encoding="sap*"' IN e_string_xml WITH 'encoding="latin1"' . "#EC NOTEXT + + ENDMETHOD. " + + + METHOD constructor . + +* read properties of the TLOGO type + p_tlogo = i_tlogo. + CALL METHOD read_tlogo_prop. + + ENDMETHOD. " + + + METHOD get_timestmp_of_data . + + r_timestmp = p_timestmp. + + ENDMETHOD. " + + + METHOD parse_xml . + + FIELD-SYMBOLS: TYPE STANDARD TABLE, + TYPE any. + FIELD-SYMBOLS: TYPE dfies. + FIELD-SYMBOLS: TYPE any. + + DATA: l_s_tlogo_tables TYPE pt_s_tlogo_tables. + DATA: l_r_child_table TYPE REF TO if_ixml_node, + l_r_child_row TYPE REF TO if_ixml_node, + l_r_child_field TYPE REF TO if_ixml_node, + l_r_child_key TYPE REF TO if_ixml_node. + DATA: l_r_element_transport TYPE REF TO if_ixml_element, + l_r_element_table TYPE REF TO if_ixml_element, + l_r_element_row TYPE REF TO if_ixml_element, + l_r_element_field TYPE REF TO if_ixml_element, + l_r_element_key TYPE REF TO if_ixml_element. + DATA: l_tagname TYPE string. + DATA: l_dummy TYPE c. + DATA: l_t_dfies TYPE STANDARD TABLE OF dfies, + l_th_dfies TYPE HASHED TABLE OF dfies WITH UNIQUE KEY fieldname. + DATA: l_s_data TYPE REF TO data. + DATA: l_name TYPE string, + l_value TYPE string, + l_fieldname TYPE string. + DATA: l_r_ixml TYPE REF TO if_ixml. + DATA: l_r_document TYPE REF TO if_ixml_document. + DATA: l_r_element TYPE REF TO if_ixml_element. + DATA: l_r_renderer TYPE REF TO if_ixml_renderer. + DATA: l_r_encoding TYPE REF TO if_ixml_encoding. + DATA: l_rc TYPE i. + DATA: l_r_istream TYPE REF TO if_ixml_istream. + DATA: l_returncode TYPE sysubrc. + DATA: l_r_parser TYPE REF TO if_ixml_parser. + DATA: l_r_cdata TYPE REF TO if_ixml_cdata_section. + DATA: l_detlevel TYPE bal_s_msg-detlevel. + DATA: l_detlevel2 TYPE bal_s_msg-detlevel. + + CLEAR p_ts_tlogo_tables. + + e_subrc = 0. + + p_objnm = i_objnm. + l_detlevel = i_detlevel + 1. + l_detlevel2 = l_detlevel + 1. + +* create a XML document and parse it +* iXML library + l_r_ixml = cl_ixml=>create( ). +* create an input stream + l_r_istream = p_r_stream_factory->create_istream_cstring( i_string_xml ). + +* create the XML document + l_r_document = l_r_ixml->create_document( ). +* create a parser (used to be once only !!!) + l_r_parser = l_r_ixml->create_parser( stream_factory = p_r_stream_factory + istream = l_r_istream + document = l_r_document ). + +* parse the document + IF l_r_parser->parse( ) NE 0. + IF l_r_parser->num_errors( ) NE 0. + DATA: parseerror TYPE REF TO if_ixml_parse_error, + str TYPE string, + line TYPE i, + column TYPE i, + count TYPE i, + index TYPE i. + count = l_r_parser->num_errors( ). + IF count > 0. + MESSAGE e207(rsoxml) WITH p_objnm p_tlogo count INTO l_dummy. + CALL METHOD cl_rso_application_log=>if_rso_application_log~add_message_level + EXPORTING + i_probclass = if_rso_application_log=>probclass_high + i_detlevel = l_detlevel. + e_subrc = 12. + index = 0. + WHILE index < count. + parseerror = l_r_parser->get_error( index = index ). + line = parseerror->get_line( ). + column = parseerror->get_column( ). + str = parseerror->get_reason( ). + MESSAGE e202(rsoxml) WITH line column str INTO l_dummy. + CALL METHOD cl_rso_application_log=>if_rso_application_log~add_message_level + EXPORTING + i_probclass = if_rso_application_log=>probclass_high + i_detlevel = l_detlevel2. + ADD 1 TO index. + ENDWHILE. + EXIT. + ENDIF. + ENDIF. + ENDIF. + +* parsed OK + CHECK l_returncode = 0. + +* get the root element + l_r_element_transport = l_r_document->get_root_element( ). + +* the TRANSPORT tag was imported +* get the parameters and references + l_r_child_table = l_r_element_transport->get_first_child( ). + WHILE NOT l_r_child_table IS INITIAL. + l_tagname = l_r_child_table->get_name( ). + l_r_element_table ?= l_r_child_table. +* TIMESTAMP + IF l_tagname = if_rso_object_xmic=>timestmp. + p_timestmp = l_r_element_table->get_value( ). +* TABLE tag + ELSEIF l_tagname = p_c_xml_tag_table. + CLEAR l_s_tlogo_tables. +* get the DDIC info of the table structure + l_name = if_rso_repository_xml_const=>id. + l_s_tlogo_tables-tabname = l_r_element_table->get_attribute( name = l_name ). + CALL FUNCTION 'DDIF_NAMETAB_GET' + EXPORTING + tabname = l_s_tlogo_tables-tabname + TABLES + dfies_tab = l_t_dfies + EXCEPTIONS + not_found = 1. + IF sy-subrc <> 0. +* error message + ELSE. + l_th_dfies = l_t_dfies. +* dynamic creation of tables + CREATE DATA l_s_data TYPE (l_s_tlogo_tables-tabname). + ASSIGN l_s_data->* TO . + CREATE DATA l_s_tlogo_tables-data TYPE STANDARD TABLE OF (l_s_tlogo_tables-tabname). + ASSIGN l_s_tlogo_tables-data->* TO . + + CLEAR l_s_tlogo_tables-where_clause. + l_r_child_row = l_r_element_table->get_first_child( ). + WHILE NOT l_r_child_row IS INITIAL. + l_tagname = l_r_child_row->get_name( ). + l_r_element_row ?= l_r_child_row. +* KEY tag + IF l_tagname = p_c_xml_tag_key. + l_r_child_key = l_r_element_row->get_first_child( ). + WHILE NOT l_r_child_key IS INITIAL. + l_tagname = l_r_child_key->get_name( ). + l_r_element_key ?= l_r_child_key. +* fields and values + l_fieldname = l_tagname. + l_value = l_r_element_key->get_value( ). +* modify OBJVERS as R3TRANS does + IF l_fieldname = 'OBJVERS'. + IF l_value = rs_c_objvers-active. + l_value = rs_c_objvers-modified. + ENDIF. + ENDIF. + IF NOT l_s_tlogo_tables-where_clause IS INITIAL. + CONCATENATE l_s_tlogo_tables-where_clause 'AND' + INTO l_s_tlogo_tables-where_clause + SEPARATED BY space. + ENDIF. + CONCATENATE '''' l_value '''' INTO l_value. + CONCATENATE l_s_tlogo_tables-where_clause + l_fieldname '=' l_value + INTO l_s_tlogo_tables-where_clause + SEPARATED BY space. + l_r_child_key = l_r_child_key->get_next( ). + ENDWHILE. +* ROW tag + ELSEIF l_tagname = p_c_xml_tag_row. + CLEAR . + l_r_child_field = l_r_element_row->get_first_child( ). + WHILE NOT l_r_child_field IS INITIAL. + l_tagname = l_r_child_field->get_name( ). + l_r_element_field ?= l_r_child_field. +* FIELD tag + IF l_tagname = p_c_xml_tag_field. + l_name = if_rso_repository_xml_const=>id. + l_fieldname = l_r_element_field->get_attribute( name = l_name ).. + READ TABLE l_th_dfies TRANSPORTING NO FIELDS + WITH TABLE KEY fieldname = l_fieldname. + IF sy-subrc = 0. + ASSIGN COMPONENT l_fieldname OF STRUCTURE TO . + = l_r_element_field->get_value( ). +* modify OBJVERS as R3TRANS does + IF l_fieldname = 'OBJVERS'. + IF = rs_c_objvers-active. + = rs_c_objvers-modified. + ENDIF. + ENDIF. + ENDIF. + ENDIF. + l_r_child_field = l_r_child_field->get_next( ). + ENDWHILE. + INSERT INTO TABLE . + ENDIF. + l_r_child_row = l_r_child_row->get_next( ). + ENDWHILE. + INSERT l_s_tlogo_tables INTO TABLE p_ts_tlogo_tables. + ENDIF. + ENDIF. + l_r_child_table = l_r_child_table->get_next( ). + ENDWHILE. + + ENDMETHOD. " + + + METHOD read_tlogo_prop . + +* get the BW TLOGO properties + CALL METHOD cl_rso_repository=>if_rso_tlogo_properties~get_tlogoprop + EXPORTING + i_tlogo = p_tlogo + IMPORTING + e_s_tlogoprop = p_s_tlogoprop. + +* get the TLOGO properties as stored in transaction SOBJ +* object header (table OBJH) + SELECT SINGLE * FROM objh INTO p_s_objh + WHERE objectname = p_tlogo + AND objecttype = 'L'. +* object tables + SELECT * FROM objsl INTO TABLE p_ts_objsl + WHERE objectname = p_tlogo + AND objecttype = 'L'. +* object methods + SELECT * FROM objm INTO TABLE p_ts_objm + WHERE objectname = p_tlogo + AND objecttype = 'L'. + + ENDMETHOD. " + + + METHOD save . + + FIELD-SYMBOLS: TYPE pt_s_tlogo_tables. + FIELD-SYMBOLS: TYPE STANDARD TABLE. + DATA: l_dummy TYPE c. + + CHECK NOT p_ts_tlogo_tables IS INITIAL. + + e_subrc = 0. + +* insert into TLOGO tables + LOOP AT p_ts_tlogo_tables ASSIGNING . +* delete old records first + IF -where_clause IS INITIAL. + MESSAGE e220(rsoxml) WITH p_objnm p_tlogo INTO l_dummy. + CALL METHOD cl_rso_application_log=>if_rso_application_log~add_message_level + EXPORTING + i_probclass = if_rso_application_log=>probclass_high + i_detlevel = i_detlevel. + e_subrc = 8. + ELSE. +* #CP-SUPPRESS: FP secure coding, no user input + DELETE FROM (-tabname) WHERE (-where_clause). + ENDIF. +* actual insert + ASSIGN -data->* TO . + INSERT (-tabname) FROM TABLE . + IF sy-subrc <> 0. + MESSAGE e221(rsoxml) WITH p_objnm p_tlogo -tabname INTO l_dummy. + CALL METHOD cl_rso_application_log=>if_rso_application_log~add_message_level + EXPORTING + i_probclass = if_rso_application_log=>probclass_high + i_detlevel = i_detlevel. + e_subrc = sy-subrc. + ENDIF. + ENDLOOP. + + ENDMETHOD. " +ENDCLASS. + +CLASS lcl_tlogo_xml_bridge IMPLEMENTATION. + + METHOD exists. +* check whether an object with this name exists in the primary table + DATA(ls_objsl) = get_prim_table_objsl( ). + DATA(lv_where_clause) = me->get_where_clause( + iv_tobj_name = ls_objsl-tobj_name + iv_objname = iv_objname + ). + + SELECT COUNT(*) FROM (ls_objsl-tobj_name) WHERE (lv_where_clause). + + rv_object_exists = boolc( sy-dbcnt > 0 ). + + validate_count_prim_table( iv_dbcount = sy-dbcnt iv_objname = iv_objname ). + + ENDMETHOD. + + METHOD validate_count_prim_table. +* The method shall validate that by accident (bad programming of this class) unwanted +* entries from the object's tables are being modified or deleted. The general assumption +* is that from th key-table, only one entry is affected. +* however, this is not true for some exceptions, where the primary table features a +* compound key (e. g. checkpoint group activation variants, AVAR) + DATA(ls_objsl) = get_prim_table_objsl( ). + DATA(lv_where_clause) = me->get_where_clause( + iv_tobj_name = ls_objsl-tobj_name + iv_objname = iv_objname + ). +* count the key components + DATA lv_count_key_components TYPE i. + DATA lt_dfies TYPE dfies_table. + CALL FUNCTION 'DDIF_NAMETAB_GET' + EXPORTING + tabname = CONV ddobjname( ls_objsl-tobj_name ) + TABLES + dfies_tab = lt_dfies + EXCEPTIONS + not_found = 1. + ASSERT sy-subrc = 0. + + CLEAR lv_count_key_components. + LOOP AT lt_dfies TRANSPORTING NO FIELDS WHERE keyflag = abap_true. + ADD 1 TO lv_count_key_components. + ENDLOOP. + +* if all key-components are covered by the where clause, obviously only one record must be matched by the where-clause + SPLIT lv_where_clause AT | AND | INTO TABLE DATA(lt_where_components). + + IF lines( lt_where_components ) = lv_count_key_components. + ASSERT iv_dbcount <= 1. "Sanity-check: there must not be more than one matching entry in the primary table + ENDIF. + ENDMETHOD. + + METHOD delete_object. + +* first, check existence of the object + IF me->exists( iv_objname = iv_objname ) = abap_true. + LOOP AT p_ts_objsl ASSIGNING FIELD-SYMBOL(). + DATA(lv_where_clause) = me->get_where_clause( + iv_tobj_name = -tobj_name + iv_objname = iv_objname + ). + +* Some sanity checks + ASSERT lv_where_clause IS NOT INITIAL. + + DELETE FROM (-tobj_name) WHERE (lv_where_clause). + + IF -prim_table = abap_true. + DATA(lv_dbcnt) = sy-dbcnt. + validate_count_prim_table( iv_dbcount = lv_dbcnt iv_objname = iv_objname ). + IF lv_dbcnt > 0. + rv_deleted = abap_true. + ENDIF. + ENDIF. + + ENDLOOP. + ENDIF. + ENDMETHOD. + + METHOD get_where_clause. + +* Sadly, the superclass does not provide a reuse-method which generates where-clauses, +* thus the code is copied and refactored (a bit) + + TYPES: BEGIN OF lt_s_objkey , + num TYPE numc3, + value TYPE char128, + END OF lt_s_objkey, + lt_ts_objkey TYPE SORTED TABLE OF lt_s_objkey WITH UNIQUE KEY num. + + READ TABLE p_ts_objsl ASSIGNING FIELD-SYMBOL() WITH KEY tobj_name = iv_tobj_name. + ASSERT sy-subrc = 0. + + DATA: l_t_dfies TYPE dfies_table, + l_n TYPE i, + l_m TYPE i, + l_k TYPE i, + l_len TYPE i, + l_s_objkey TYPE lt_s_objkey, + l_ts_objkey TYPE lt_ts_objkey, + l_num TYPE numc3. + + CALL FUNCTION 'DDIF_NAMETAB_GET' + EXPORTING + tabname = CONV ddobjname( -tobj_name ) + TABLES + dfies_tab = l_t_dfies + EXCEPTIONS + not_found = 1. + ASSERT sy-subrc = 0. + +* compose the key (table) + CLEAR l_ts_objkey. + CLEAR l_s_objkey. + l_n = 0. + l_num = 1. + l_k = 0. + l_len = strlen( -tobjkey ). + WHILE l_n <= l_len. + l_s_objkey-num = l_num. +* command + IF -tobjkey+l_n(1) = '/'. + IF NOT l_s_objkey-value IS INITIAL. + INSERT l_s_objkey INTO TABLE l_ts_objkey. + ADD 1 TO l_num. + CLEAR l_s_objkey. + l_s_objkey-num = l_num. + ENDIF. + l_m = l_n + 1. +* '*' means all futher key values + IF -tobjkey+l_m(1) = '*'. + l_s_objkey-value = '*'. + INSERT l_s_objkey INTO TABLE l_ts_objkey. + CLEAR l_s_objkey. + ADD 1 TO l_num. + ADD 1 TO l_n. +* object name + ELSEIF -tobjkey+l_m(1) = '&'. + l_s_objkey-value = iv_objname. +* #CP-SUPPRESS: FP no risc + INSERT l_s_objkey INTO TABLE l_ts_objkey. + CLEAR l_s_objkey. + ADD 1 TO l_num. + ADD 1 TO l_n. +* language + ELSEIF -tobjkey+l_m(1) = 'L'. + l_s_objkey-value = sy-langu. + INSERT l_s_objkey INTO TABLE l_ts_objkey. + CLEAR l_s_objkey. + ADD 1 TO l_num. + ADD 1 TO l_n. + ENDIF. + l_k = 0. +* value + ELSE. + l_s_objkey-value+l_k(1) = -tobjkey+l_n(1). + ADD 1 TO l_k. + ENDIF. + + ADD 1 TO l_n. + ENDWHILE. + IF NOT l_s_objkey-value IS INITIAL. + INSERT l_s_objkey INTO TABLE l_ts_objkey. + ENDIF. + +* compose the where clause + DATA(l_flag_asterics) = rs_c_false. + l_num = 1. + DATA(l_where_stmt) = ||. + + LOOP AT l_t_dfies ASSIGNING FIELD-SYMBOL() + WHERE NOT keyflag IS INITIAL. +* #CP-SUPPRESS: FP no risc + READ TABLE l_ts_objkey INTO l_s_objkey + WITH TABLE KEY num = l_num. + IF sy-subrc <> 0 + OR -fieldname = 'LANGU'. + CLEAR l_s_objkey. + ADD 1 TO l_num. + CONTINUE. + ENDIF. + IF l_s_objkey-value = '*'. + l_flag_asterics = rs_c_true. + ENDIF. + IF l_flag_asterics = rs_c_true. + CONTINUE. + ENDIF. + IF NOT l_where_stmt IS INITIAL. +* #CP-SUPPRESS: FP no risc + CONCATENATE l_where_stmt 'AND' INTO l_where_stmt + SEPARATED BY space. + ENDIF. +* #CP-SUPPRESS: FP no risc + CONCATENATE '''' l_s_objkey-value '''' INTO DATA(l_value128). +* #CP-SUPPRESS: FP no risc + CONCATENATE l_where_stmt -fieldname '=' + l_value128 INTO l_where_stmt SEPARATED BY space. + ADD 1 TO l_num. + ENDLOOP. + rv_where_on_keys = l_where_stmt. + ENDMETHOD. + + METHOD timestamp_to_xml. + "copy of cl_rso_tlogo=>timestamp_to_xml +* this would be more readable, but must be converted before stored on DB +* additional problem: different time formats (language dependent) +* CONVERT TIME STAMP l_conttimestmp TIME ZONE sy-zonlo +* INTO DATE l_date TIME l_time. +* WRITE: l_date TO l_date_c. +* WRITE: l_time TO l_time_c. +* CONCATENATE l_date_c l_time_c INTO l_value SEPARATED BY ', '. + +* simple, but works + rv_string = iv_timestamp. + + ENDMETHOD. + + + METHOD get_prim_table_objsl. + READ TABLE p_ts_objsl INTO rs_objsl WITH KEY prim_table = abap_true. + IF sy-subrc <> 0. +* Fallback. For some objects, no primary table is explicitly flagged +* The, the one with only one key field shall be chosen + READ TABLE p_ts_objsl INTO rs_objsl WITH KEY tobjkey = '/&'. + ENDIF. + ASSERT rs_objsl IS NOT INITIAL. + ENDMETHOD. + + + METHOD get_table_metadata. + +* parse all tables of this TLOGO object + LOOP AT p_ts_objsl ASSIGNING FIELD-SYMBOL(). + DATA ls_metadata LIKE LINE OF rt_metadata. + ls_metadata-db_table = -tobj_name. + + INSERT ls_metadata INTO TABLE rt_metadata ASSIGNING FIELD-SYMBOL(). + + DATA(lv_where_clause) = me->get_where_clause( + iv_tobj_name = -tobj_name + iv_objname = iv_objname + ). + + SELECT COUNT(*) INTO -count FROM (-tobj_name) WHERE (lv_where_clause). + +* get the DDIC info of the table structure + CALL FUNCTION 'DDIF_NAMETAB_GET' + EXPORTING + tabname = CONV ddobjname( -tobj_name ) + TABLES + dfies_tab = -fields_definition + EXCEPTIONS + not_found = 1. + ASSERT sy-subrc = 0. + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. \ No newline at end of file diff --git a/zsaplink_generic_obj.clas.xml b/zsaplink_generic_obj.clas.xml new file mode 100644 index 000000000..7d5ae1013 --- /dev/null +++ b/zsaplink_generic_obj.clas.xml @@ -0,0 +1,46 @@ + + + + ZSAPLINK_GENERIC_OBJ + 1 + E + Generic adapter for SAPLINK based on sobj + 00000000000000000000000000000000 + 00 + 2 + 1 + 0 + + 00000000 + + 00000000 + + 00000000 + + X + + X + + X + + X + + + + + + + + 00 + + + + + + + 0 + 0 + + + +