ABAP to the future – my version of the BOPF chapters, part 5 – Properties
8.2.6 Restricting meaningful BO-interaction using properties
In the book “ABAP to the future” (A2tF), this chapter is named slightly different: “Disabling certain commands using validations”. This original title mixes two actually different aspects which should – in my opinion – clearly be separated: Action validations and action properties. As this is a common misunderstanding, I will dedicate this chapter to properties and handle validations in the next one.
As written in the book, it is of interest for a consumer, whether an interaction with some business entity is possible (e. g. whether a button can be pushed or not). Similarly, there is good reason that some attribute should not be visible or displayed only read-only: The interaction, that this attribute can be changed shall not be allowed. This is “disabling in advance to the actual interaction” is particularly relevant for a human consumer. Usually, the business logic which is being executed when deciding about whether a button shall be enabled or not is a subset of the checks which are being executed before the action would be performed. For example, we could enable the button which makes a monster howl at the moon only for monsters with heads. In addition, when trying to howl at the moon, it shall be verified that if the monster is a werewolf, the current time is a full moon. If the user asks a werewolf to howl at other times, an error message shall be created (but no howl). As this werewolf-specific check (“validation” in the BOPF terminology) is quite special, it is better with respect to user experience to explain the impossibility to the user using a message instead of just disabling the button: The user who is not handling werewolves daily would not be able to understand why the button is not enabled. Thus, in BOPF, there are different mechanisms for both aspects: While validations actually verify the requested interaction with or the state of an instance, properties are an additional mechanism to implement business logic which helps to avoid impossible interactions by a human consumer. Consequently, there is an own core-service “retrieve properties” which allows to execute this business logic.
It is crucial to understand that properties will not prevent the consumer (which could also be a report) from performing an interaction which shall not be possible (e. g. changing a read-only or even disabled node attribute). Only validations (which are covered in the next chapter) have got this power. But often, validations and property-determinations share the same logic, so there’s good reason to extract this code in a separate method and use it from the property-determination- as well as from the validation-interface-implementation.
The core-service “retrieve properties” is an optional channel for a user interface in order to request information about limitations of interactions with a BO instance (precisely with the instance of a BO node).
Multiple aspects of the model can be subject to properties (there are some few more than listed below, but they are most likely not relevant for your business and would be really tricky to explain):
- Actions: Whether the action is enabled (usual visualization: Button is active or grayed out)
- Node attributes:
- Enabled
- Read-only
- Mandatory
- Nodes: Delete enabled
- Association: Create enabled
Properties can either be statically modeled (e. g. the hat-size-code shall always be read-only, as it’s being determined from the hat-size) or they can be dynamically determined through a property-determination.
Static definition of properties
There is information in our monster which is for example always calculated. These attributes must never be modified by a consumer, but only by our determination. Thus, we can model these attributes to be statically read-only. At runtime, BOPF will by default validate the modify-command and reject it, if static read-only or disabled attributes would be tried to be changed.
Figure 42 – Static properties: The determined node attributes are read-only final, the alternative-key components are mandatory
Figure 43 – Result of static attribute properties. Mandatoriness is not visualized on the Test-UI though.
Implementation of a property-determination
Based on the fact, whether our monster has got heads, some interaction with a monster is futile. Howling at the moon is not even worth trying and the total of eyes is also of no interest.
A property-determination is a particular configuration of a determination (we’ve been covering that in the previous chapter). As all kinds of determinations, the implementation is an ABAP-class implementing the determination interface /BOBF/IF_FRW_DETERMINATION.
The interface methods CHECK and CHECK_DELTA are or no relevance in this case, as there’s no “change” when retrieving properties, so let’s directly head to the EXECUTE-method.
METHOD /bobf/if_frw_determination~execute.
* Technically, properties are captured at runtime in a technical subnode (which we don’t have to model explicitly).
* A helper class facilitates the handling of this subnode (sadly to be constructed directly)
DATA lo_set_property TYPE REF TO /bobf/cl_lib_h_set_property.
CREATE OBJECT lo_set_property
EXPORTING
is_context = is_ctx ” Determination context
io_modify = io_modify. ” Reference to modify object
DATA lt_root TYPE zmonster_t_root. “The combined table type of the node to be retrieved
io_read->retrieve(
EXPORTING
iv_node = zif_monster_c=>sc_node–root
it_key = it_key
it_requested_attributes = VALUE #( ( zif_monster_c=>sc_node_attribute–root–number_of_heads ) )
IMPORTING
et_data = lt_root ).
LOOP AT lt_root ASSIGNING FIELD-SYMBOL(<ls_root>).
IF <ls_root>-number_of_heads = 0.
* Disable the action to howl at the moon if no head’s available
lo_set_property->set_action_enabled(
EXPORTING
iv_key = <ls_root>-key
iv_action_key = zif_monster_c=>sc_action–root–howl_at_the_moon
iv_value = abap_false ).
* Also, the total number of eyes which we calculate as total eyes of all heads is not relevant in this case,
* let’s disable this attribute (so that a UI knows it can hide it)
lo_set_property->set_attribute_enabled(
EXPORTING
iv_key = <ls_root>-key
iv_attribute_name = zif_monster_c=>sc_node_attribute–root–total_eyes
iv_value = abap_false ).
ENDIF.
ENDLOOP.
ENDMETHOD.
Figure 44 – Result of a property determination: The BOPF Test UI interprets the properties and disables actions as well as attributes.
Figure 45 – You can also make BOBT ignore properties. It’s optional for the consumer to interpret them.
I hope you now got an idea of what properties are and why they should be used in order to determine the potentially meaningful interactions with a node instance. If you’re still in doubt, please do ask!
In the next chapter, we’ll have a look at validations which includes options how to really prevent an interaction.
Re-reading what I wrote some months back I was not too happy with my own quality.
Tried to improve this now, particularly adding screenshots.
Is this valuable to you?
Hi Oliver,
Thank you for spending time and explaining about the Determination and Property Determination. Definitely helped us get through the concepts and working knowledge.
Thanks again.
Regards,
Sujin
Hi Oliver,
I’m continuing with BOPF. And now I have a question about READ ONLY property. I want to make full record READ ONLY, not only certain properties. If I do that with attributes, then I’m in a big trouble if I have a lot of attributes
Would you please help me to find a solution for such situation?
Thank you in advance for your help.
Kind regards,
Katja
Hi Oliver,
I've solved it.
Cheers,
Katja
Dear Katja,
indeed there is not read-only-property for the complete node.
However, you can dynamically determine all node attributes via the BOPF configuration object runtime:
The interface-method provides runtime information including attribute names. You can simply loop at them and apply the property to all of them.
Cheers,
Oliver
P.s.: What was your solution?
Hi Oliver,
I did it in my determinations
lo_set_property->set_node_update_enabled(
EXPORTING
iv_key = .................. " Key of the instance for which the property is to be set
iv_value = abap_false " New value of this property (true/false)
).
I was a bit embarrassed with "enabled" but I played with iv_value. If you use iv_value = abap_false, then node gets read-only status.
Cheers,
Katja
Hi,
Thank you for the explaining the concept.
However, I am not able to implement set_association_create_enabled properly.
I am trying to hide '+' button for one of the associations under root node for some status values of header record.
I passed the association name, key of my header record and iv_key = abap_false.
But the '+' button is still visible, and when I press it, I get a dialog 'No data found'.
Could you please guide me on this?
Thanks,
Prabhat
Prabhat,
Did you ever find a solution? I am facing this same exact issue!!
Thank you Oliver. I have been reading your blogs on BOPF which is informative and interesting to read. After reading your blogs, I am now confident to implement solution using BOPF.
Regards,
Yellappa.