Introduction
This blog has been inspired by Bruno Esperança and his thought provoking The last runtime buffer you'll ever need? The thing is, I wrote such a thing a few years ago, that's widely used by one of my clients. There's a few areas it could be improved
The Interface
interface zif_lookup
public .
constants c_dateto type fieldname value 'DATETO'. "#EC NOTEXT
methods lookup
exporting
es_data type any
eo_type type ref to cl_abap_structdescr
e_notfound_flag type char1
exceptions
sql_error .
methods set_key_val
importing
i_component type clike
i_value type any .
methods set_val_component
importing
i_component type clike .
methods get_ref2_lookup
returning
value(rp_data) type ref to data
exceptions
sql_error .
methods set_tim_val
importing
i_component type clike optional
i_value type any .
methods set_keyval_range
importing
it_keytab type any table .
methods get_val_struc
returning
value(ro_valstruc) type ref to cl_abap_structdescr .
methods get_notfound_flag
returning
value(r_notfound_flag) type flag .
endinterface.
Buffering in use
Well, the constructor is missing, so just showing you the interface doesn't really help! So, imagine a class with this attribute.
DATA: buffer TYPEREFTO zif_lookup.
Then we have a method in some class that reads materials from the MARC table, with i_matnr, i_werks, exporting e_bwtty and e_mmsta.
IF buffer IS NOT bound.
CREATEOBJECT buffer TYPE zcl_table_lookup EXPORTING
i_table_name = 'MARC'
i_whole_tab = abap_false.
" The data I want to get back
buffer->set_val_component( 'BWTTY' ).
buffer->set_val_component( 'MMSTA' ).
ENDIF.
" The key data
buffer->set_key_val( i_component = 'MATNR' i_value = i_matnr )
buffer->set_key_val( i_component = 'WERKS' i_value = i_werks ).
" Now look it up.
DATA: BEGIN OF looked_up,
bwtty TYPE bwtty_d,
mmsta TYPE mmsta,
END OF looked up.
buffer->lookup( IMPORTING es_data = looked_up ).
e_bwtty = looked_up-bwtty.
e_mmsta = looed_up-mmsta.
What the class ZCL_TABLE_LOOKUP does is take the supplied components through set_val_component and set_key_val, and constructs two hashed tables (using RTTS) with the key components (in this case, MATNR and WERKS) as key. The first contains data looked up, the second contains data looked up and not found.
After the first lookup, you can't change the component fields.
If the i_whole_tab parameter is set, then the whole table will be buffered, rather than doing line by line buffering.
A couple of other implementations
I created a BW style look up, that uses the table look up above, and the same interface. It specialises into two further classes - one for looking up InfoObject master data, the other reading from a DSO.
Their constructors take an InfoObject name / DSO name, convert that to the underlying transparent tables, and instantiates a table lookup instance for this table. Oh - and for InfoObjects there's a flag on the constructor for whether the data is time dependent.
The component setting methods similarly take InfoObject names (instead of field names). The InfoObject names are then converted to field names, and passed to the table lookup instance.
What next?
I bet you want to know the details of the implementation. I will update this blog shortly with that information, but thought I'd give you something to whet your appetites. In any case, it's better this way than supplying the information as comments to Bruno's blog!