Preamble and disclaimer
Creating own implementation for some problem, which was already solved is before, often referred as "inventing a bicycle". I did invent a couple too
🙂 This post, and maybe a couple of following posts, describe several of my open-source "bicycles". I "invented" them because in the time I was searching for such functionalities that I didn't find them. I'm suspect these functionalities do exist already and you can point that out in comments, if you know a better and more standard solution. Yet my "bicycles" were "invented" with the convenience in mind and with an attempt to make clean and universal tools. So I sincerely hope someone will find them useful. If I'm missing an obvious solution - welcome to comment
🙂 KR. Alexander.
String map
Many other languages have an integrated concept of dictionary - a primitive to store key/value associations. E.g. dict in python, Map (or regular objects) in java script. Even C++ has a very standard template of a Map (though not integrated into the language).
Java script
const map = new Map();
map.set('A', 1);
map.get('A'); // => 1
Python
mydict = {}
mydict["A"] = 1
mydict["A"] # => 1
I didn't find similarly convenient and widely used primitive in ABAP. Yes, the new 7.4 syntax allows constructs like
mytab[ key= 'xyz' ]-value which is almost the same ... but this mechanism is missing in older ABAP stacks. And even modern ABAP still misses some convenience features like listing the keys and easy conversion between structure types. The syntax may also be a bit excessive. Therefore, I created my own implementation. Below are a couple of examples of usage which should be self explainable.
There are many applications of such a primitive. I'm using it to manage http queries and headers which are a good example of key-value sets. I'm sure you may find own applications in your context.
The code is open-sourced and published under MIT license here:
https://github.com/sbcgua/abap-string-map. Can be installed using
abapGit.
Functionality and Examples
The class (
zcl_abap_string_map) implements `
get`, `
set`, `
has`, `
size`, `
is_empty`, `
delete` functions
data lo_map type ref to zcl_abap_string_map.
lo_map = zcl_abap_string_map=>create( ). " or create object ...
lo_map->set(
iv_key = 'hello'
iv_val = 'world' ).
some_var = lo_map->get( 'hello' ). " => 'world'
lo_map->has( 'hello' ). " => abap_true
lo_map->is_empty( ). " => abap_false
lo_map->size( ). " => 1
lo_map->delete( 'hello' ). " deletes 'hello' item
lo_map->clear( ). " deletes all items
`
set()` allows chaining
lo_map->set(
iv_key = 'A'
iv_val = '1' )->set(
iv_key = 'B'
iv_val = '2' ).
The class implements `
keys`, `
values` methods
data lt_all_keys type string_table.
data lt_all_vals type string_table.
lt_all_keys = lo_map->keys( ). " => ( 'hello' )
lt_all_vals = lo_map->values( ). " => ( 'world' )
implements `
to_struc`, `
from_struc` to interchange with abap structures
data:
begin of ls_struc,
a type string,
b type abap_bool,
c type i,
end of ls_struc.
lo_map->from_struc( ls_struc ). " Converts abap structure to string map
lo_map->to_struc( changing cs_container = ls_struc ). " Converts map to abap structure
" If you have more data entries in the map than fields in the target structure
" use strict( false ) - this skips entries which do not have a matching field
lo_map->strict( abap_false )->to_struc( changing cs_container = ls_struc ).
It implements `
from_entries` - this copies entries from a provided param.
Importantly, the method accepts
any table but the shape of the record
must conform to `
zcl_abap_string_map=>ty_entry`, namely it
must have 2 string attributes for key and value respectively (see the code of `
from_entries` for clarification)
types:
begin of ty_my_key_value,
key type string,
value type string,
end of ty_my_key_value.
data lt_entries type table of ty_my_key_value.
lt_entries = value #(
( key = 'hello' value = 'world' )
( key = 'and' value = 'another' )
).
lo_map->from_entries( lt_entries ).
You may set the map immutable (read only). Guards `
set`, `
delete`, `
clear`, `
from_*` methods.
lo_map->set(
iv_key = 'A'
iv_val = '1' )->freeze( ).
lo_map->set(
iv_key = 'A'
iv_val = '2' ). " raises cx_no_check
`
create` also supports immediate initiation from another instance of string map, a structure (same as running `
from_struc` after) or a table (same as running `
from_entries` after)
lo_copy = zcl_abap_string_map=>create( lo_map ).
lo_copy = zcl_abap_string_map=>create( ls_struc ). " see examples above
lo_copy = zcl_abap_string_map=>create( lt_entries ). " see examples above
For more examples see
unit tests code.
I hope you find this useful or at least interesting
🙂
Regards, Alexander