Skip to Content
Author's profile photo David Halitsky

Abstraction & Inheritance in WD-ABAP Clones of CL_WDR_ALL_IN_ONE_UTIL/UIELEM: What’s a lazy wannabe to do?

In a couple of previous posts, I mentioned how one can use the WD-ABAP component WDR_TEST_UI_ELEMENTS to create one’s own tutorials for many different view models.

But since I am in general a lazy wanna-be who has never had the courage to write any piece of code from scratch, I started looking yesterday at the WDR_TEST_UI_ELEMENTS component in order to learn two more general techniques – how to fire a tree view from a selected link in a tray, and how to fire a detail view from a selected tree element.

And in the process of learning the answers to these two questions, I found out that in order to use what I’d learned “for real”, I needed to make a decision on abstraction/inheritance that I really didn’t trust myself to make.  So the purpose of this post is to ask the SDN community for its opinions on this basic question of abstraction/inheritance. I apologize for the long preamble to this question that appears below, but in order to understand the question, you really have to understand exactly how WDR_TEST_UI_ELEMENTS draws on the methods and attributes of the two classes CL_WDR_ALL_IN_ONE_UTIL and CL_WDR_ALL_IN_ONE_UIELEM.

method create_aggregatee.

  • add it to the hierarchy tree

  • => create the sub node and add an element to it

  lr_hier_tree_context_node = m_hier_tree_context_element->get_child_node( ‘UI_ELEMENT_HIER_REC’ ).

  lr_hier_tree_context_element = lr_hier_tree_context_node->create_element( ).

  lr_hier_tree_context_node->bind_element( new_item = lr_hier_tree_context_element set_initial_elements = abap_false ).

  lr_hier_tree_context_element->set_attribute( name = ‘EXPANDED’     value = abap_false ).

  lr_hier_tree_context_element->set_attribute( name = ‘HAS_CHILDREN’ value = abap_false ).

  lr_hier_tree_context_element->set_attribute( name = ‘TEXT’         value = i_aggregatee-display_name ).

  concatenate ‘/sap/public/bc/webdynpro/viewdesigner/icons/’ i_aggregatee-display_name ‘.gif’ into icon.

  lr_hier_tree_context_element->set_attribute( name = ‘ICON’         value = icon ).


OK – so now we know what old-timers would call the “flow of control” that builds the aggregation tree on the right hand side of the Main view, given the selection of any link in a tray on the left-hand side of the view.

But where is the data itself coming from – the data itself that is used in the methods create_aggregations and create_aggregatee? And how do these methods get the data?

The answer is in the wdDoInit method of the Main view of WDR_TEST_UI_ELEMENTS itself:

method wdDoInit .

  • implicit available data objects

  •   wd_Context type ref to if_wd_context_node.

  •   wd_This    type ref to if_Main.

  • create an instance of the handler class

  create object wd_this->m_handler.


Since m_handler has been declared in the attributes of the Main view to be of type cl_wdr_all_in_one_util, this create statement must take us to the constructor method of this class:

method constructor.

  • initialize the meta data

  cl_wdr_all_in_one_uielem=>init_meta_data( ).


And lo and behold, this constructor method transfers flow of control to the init_meta_data method of cl_wdr_all_in_one_uielem (NOTE! NOT cl_wdr_all_in_one_util), which is where the actual data is created and stored in itabs that will persist sufficiently long to be accessed in the create_aggregations and create_aggregatee methods of cl_wdr_all_in_one_util:

method init_meta_data.

  • get all libraries

  select * from wdy_ui_library into table mt_ui_library

          order by primary key.

  • get all view elements – below we will build the final list

  select * from wdy_ui_elem_def into table mt_ui_elem_def_all.


(Note that the itabs mt_ui_elem_def_all and mt_ui_library are TYPED in the attributes declaration of cl_wdr_all_in_one_uielem.)


So now that we have learned exactly how the WD-ABAP component WDR_TEST_UI_ELEMENTS populates the aggregation tree on the right from a selection on the left, we have learned a general way to fire any tree from any link within a tray of any set of trays: we get the back-end data we need in the constructor method of a class like cl_wdr_all_in_one_uielem, and display this back-end data using methods like create_aggregration and create_aggregatee in a class like cl_wdr_all_in_one_utils. For the sake of discussion, call these zcl_back_end_data and zcl_displayed_data,

But – we have now reached the point of this post: how generic and abstact should our class zcl_back_end_data be?

Remember – the code itself is sufficiently general to permit any tree to be built from data in two custom tables that are the equivalent of the wdy_ui_library and wdy_ui_elem_def tables declared in the attributes section of cl_wdr_all_in_one_uielem.

So, do we want:

1) one zcl_back_end_data class with different selects that fire based on a parm passed in during the init of a particular view;


2) one zcl_back_end_data class that leaves it to subclasses to say which selects fire against which tables?


3) multiple zcl_back_end_data class’s that each get data from appropriate tables?

I would very much, therefore, appreciate any input from knowledgeable SDN folk about which of the alternatives (1-3) they would choose. I am sure there are many who deal/have dealt with this kind of question on a daily basis and can render good advice, and I’m hoping their answers will all pretty much say – “it all depends” (because that’s the kind of answers you learn the most from.)

So, thanks for any time anyone can afford to spend thinking about the above question and putting their thoughts into a reply.

PS: if you drill-down from the onactionon_select_view_elem of the Main view of WDR_TEST_UI_ELEMENTS, you’ll learn exactly how the detail view is fired from selection of a tree node in the aggregation tree on the right, but you’ll also again see that you again wind up in methods of CL_WDR_ALL_IN_ONE_UTIL that rely on back-end data gathered via cl_wdr_all_in_one_uielem=>init_meta_data( ).

Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member
      At a very broad level, I consider most appropriate solution would be option 2.

      Option 1: needs to be updated every time a new type of selection is required

      Option 3: no re-use as each class will be implementing its own functionality

      If your classes are structured in a parent-child relationship, the base class should expose common functionality which can then be extended by subclasses. Using narrow-casting, you can utilize polymorphism which is considered to be a clean, future-proof solution.

      Having said that, if you class is FINAL by nature, then you might have to resort to other options.

      My 2 cents.


      Author's profile photo David Halitsky
      David Halitsky
      Thanks, SK.  That's what I was thinking, so I tend to agree. 

      There are essentially three kinds of tree-like control structures that organize SAP back-end data:

      1) those that are created as ReportSets in SETNODE/SETLEAF by SAP and customers;

      2) those that are implicit in the structures of logical databases created by SAP and customers;

      3) those that are embedded (somewhat obscurely) in the basic organization of SAP data, e.g. the kind of search tree that takes you from a project to a sub-tree of WBS elements to a sub-tree of networks and finally to a trivial sub-tree of activities, or the kind of search tree that takes you from CSKS to COEP to COBK to xKOPF/xSEG, etc.

      So I could imagine a class:


      with three different subclasses


      and then one more level of subclasses under this to handle the specifics of different instantiations of these three classes.

      Anyway, thanks again for taking the time to advise.

      Author's profile photo David Halitsky
      David Halitsky

      In the flow of control overview in my original post, I left out a critical step: the create_settings method invoked by the create method of cl_wdr_all_in_one_ui_elem.  In case you're ever wondering how the right-hand side of the view knows what the left-hand side is doing, here's how the metadata item "runtime_class" is used to create the