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)
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.
* 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
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
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 ) )
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
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.