custom expression types and action types · 2019. 11. 12. · custom expression types and action...

111
CUSTOM EXPRESSION TYPES AND ACTION TYPES A STEP-BY-STEP GUIDE WITH EXAMPLE 1 Custom Expression Types and Action Types A Step-by-Step Guide with Example CUSTOMER Document Version: 1.0 - 15 October 2013 SAP NetWeaver Business Decision Service Management and SAP NetWeaver Business Rule Framework plus © 2013 SAP AG or an SAP affiliate company. All rights reserved.

Upload: others

Post on 13-Aug-2021

28 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

1

Custom Expression Types and Action Types A Step-by-Step Guide with Example

CUSTOMER

Document Version: 1.0 - 15 October 2013

SAP NetWeaver Business Decision Service Management and

SAP NetWeaver Business Rule Framework plus

© 2013 SAP AG or an SAP affiliate company. All rights reserved.

Page 2: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

2

About The Authors

Christian Auth is a senior developer in the SAP NetWeaver Business Rule Framework plus project.

He joined SAP in 2002. Before his assignment in BRFplus, he worked in various development groups in SAP Business ByDesign.

Michael Baer is a senior developer in the SAP NetWeaver Business Rule Framework plus project.

Michael joined SAP in 2008. In BRFplus, he has been working on various back-end topics.

Piyush Deora is a senior developer in SAP Netweaver Business Rule Framework plus project.

Piyush joined SAP in 2008. He has been working on various user interface and third party integration topics.

Hanno Holzheuser is a knowledge architect, currently supporting the SAP Netweaver Business Rule Framework plus team.

Hanno joined SAP in 1990 and has worked for many units in SAP NetWeaver, SAP Business Suite, and SAP Cloud managing KM teams and projects.

Marco Wuest is a senior developer in the BRFplus team. Having mainly worked on UI topics, he created the architecture of the UI layer and implemented the UI infrastructure.

Marco joined SAP in 2003. He previously worked in the Records and Case Management project.

Carsten Ziegler is the chief product owner of SAP NetWeaver Decision Service Management and SAP NetWeaver Business Rule Framework plus.

He joined SAP in 2000. Since then he has been working in various projects as a developer, development architect, project lead and product owner.

2013-07-29

Page 3: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

3

Table of Contents

1 Introduction ........................................................................................................................................... 6

1.1 Overview ................................................................................................................................................. 6

1.2 Expression Types and Action Types ...................................................................................................... 6

2 Specification/Design .......................................................................................................................... 10

3 Database Layout ................................................................................................................................. 12

4 Transport Objects ............................................................................................................................... 17

5 Interface Creation ............................................................................................................................... 21

6 Class Creation ..................................................................................................................................... 26

7 New Methods ....................................................................................................................................... 30

7.1 LOAD_BUFFER_DB ............................................................................................................................. 30

7.2 LOAD_BUFFER .................................................................................................................................... 32

7.3 SET_BUFFER ....................................................................................................................................... 33

7.4 SAVE_BUFFER_DB ............................................................................................................................. 33

7.5 Method in Action Type or Expression Type Specific Interfaces ........................................................... 34

7.5.1 IF_FDT_ACTN_EMAIL=>GET_BODY ............................................................................................ 34

7.5.2 IF_FDT_ACTN_EMAIL=>GET_RECIPIENTS ................................................................................. 35

7.5.3 IF_FDT_ACTN_EMAIL=>GET_PARAMETERS ............................................................................. 35

7.5.4 IF_FDT_ACTN_EMAIL=>GET_SUBJECT ...................................................................................... 35

7.5.5 IF_FDT_ACTN_EMAIL=>SET_BODY ............................................................................................ 35

7.5.6 IF_FDT_ACTN_EMAIL=>SET_RECIPIENTS ................................................................................. 36

7.5.7 IF_FDT_ACTN_EMAIL=>SET_PARAMETERS .............................................................................. 36

7.5.8 IF_FDT_ACTN_EMAIL=>SET_SUBJECT ...................................................................................... 37

8 Redefined Methods ............................................................................................................................. 39

8.1 Class CL_FDT_MAINTENANCE .......................................................................................................... 39

8.1.1 DELETE_FROM_DB ....................................................................................................................... 39

8.1.2 CHECK ............................................................................................................................................ 39

8.1.3 COPY ............................................................................................................................................... 39

8.1.4 RESTORE_BUFFER ....................................................................................................................... 40

8.1.5 SAVE_WITH_VERSION .................................................................................................................. 40

8.1.6 TRANSPORT ................................................................................................................................... 41

8.1.7 GET_CHANGE_DETAILS ............................................................................................................... 42

8.2 Interface IF_FDT_EXPRESSION ......................................................................................................... 43

8.2.1 GET_USED_EXPRESSIONS.......................................................................................................... 44

8.2.2 GET_DSM_AVAILABILITY .............................................................................................................. 45

8.2.3 GET_CONTEXT_DATA_OBJECTS ................................................................................................ 45

8.3 Interface IF_FDT_ADMIN_DATA ......................................................................................................... 46

8.3.1 TO_STRING .................................................................................................................................... 46

8.4 Interface IF_FDT_DATA_EXCHANGE_INTERNAL ............................................................................. 47

9 Check Methods ................................................................................................................................... 48

Page 4: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

4

10 Process Methods ................................................................................................................................ 50

11 Methods for Code Generation ........................................................................................................... 54

11.1 IS_GENERATING ............................................................................................................................ 54

11.2 GENERATE_PROCESS ................................................................................................................. 54

11.2.1 IF_FDT_DATA_OBJECT->GENERATE_CREATE_DATA_REF .................................................... 55

11.2.2 IF_FDT_DATA_OBJECT=>GENERATE_CONVERT_TO .............................................................. 55

11.2.3 CL_FDT_EXPR_SERVICES=> GENERATE_MOVE_FROM_EXTERNAL ................................... 56

11.2.4 CL_FDT_EXPR_SERVICES=> GENERATE_MOVE_TO_EXTERNAL ......................................... 57

11.2.5 CL_FDT_EXPR_SERVICES=> GENERATE_GET_CONTEXT_NAME ......................................... 58

11.2.6 CL_FDT_EXPR_SERVICES=> GEN_GET_NEXT_VARIABLE_NAME ......................................... 58

11.2.7 CL_FDT_EXPR_SERVICES=> GEN_GET_NAME_FOR_GENERATION .................................... 59

11.2.8 CL_FDT_EXPR_SERVICES=> GEN_GENERATE_TRACE .......................................................... 59

11.2.9 CL_FDT_EXPR_SERVICES=>GENERATE_RANGE_PROCESS ................................................ 60

11.2.10 CL_FDT_EXPR_SERVICES=> GENERATE_SIMPLE_VALUE_PROCESS ................................. 60

11.2.11 CL_FDT_EXPRESSION=>GENERATE_GET_VALUE .................................................................. 61

11.2.12 CL_FDT_EXPRESSION=> GENERATE_TRACE_SUB_EXPRESSION ....................................... 62

11.3 Tips for Generation .......................................................................................................................... 63

11.4 Tools for supporting the generation development and maintenance .............................................. 63

12 Methods for Lean Trace Display ....................................................................................................... 64

12.1 CHANGE_TRACE_NODE ............................................................................................................... 64

12.2 CREATE_TRACE_CHILD_NODES ................................................................................................ 65

13 Data Exchange .................................................................................................................................... 67

13.1 EXPORT_XML ................................................................................................................................. 67

13.2 IMPORT_XML ................................................................................................................................. 68

13.3 Implementation for User Defined Expression Types ....................................................................... 70

13.3.1 GET_DTD ........................................................................................................................................ 70

13.3.2 GET_ELEMENT_DOMAIN_LIST .................................................................................................... 75

13.3.3 GET_VERSION_CHANGE_LIST .................................................................................................... 76

13.3.4 MODIFY_XML_VERSION_CHANGES ........................................................................................... 76

14 Creation of the Action Type or Expression Type as an Object in BRFplus ................................. 78

15 Testing the Action Type or Expression Type .................................................................................. 80

16 Creation of the User Interface ........................................................................................................... 81

16.1 Overview about the Components of the User Interface .................................................................. 81

16.2 Web Dynpro Component ................................................................................................................. 82

16.2.1 Implementation of the BRFplus WD Interfaces ............................................................................... 82

16.2.2 Definition of the Context .................................................................................................................. 82

16.2.3 Exception Handling in the UI ........................................................................................................... 83

16.2.4 Implementation of Interface FDT_IWD_OBJECT/FDT_IWD_COMPONENT ................................. 85

16.3 Model Class ..................................................................................................................................... 90

16.3.1 Implementation of Model Class ....................................................................................................... 90

16.3.2 Detecting if the object has changed ................................................................................................ 96

Page 5: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

5

16.3.3 Reference ........................................................................................................................................ 96

16.4 UI Class ........................................................................................................................................... 98

16.4.1 HAS_WD_ABAP_UI ........................................................................................................................ 99

16.4.2 GET_WD_ABAP_MODEL_CLASS ................................................................................................. 99

16.4.3 GET_WD_ABAP_COMPONENT .................................................................................................... 99

16.4.4 GET_WD_ABAP_VERSION .......................................................................................................... 100

16.5 Reuse Components and Service in the UI Layer .......................................................................... 100

16.5.1 Creating a new BRFplus Object .................................................................................................... 100

16.5.2 Selecting an Existing BRFplus Object ........................................................................................... 102

16.5.3 Navigating to Other BRFplus Objects ............................................................................................ 104

16.5.4 Object Menu .................................................................................................................................. 104

16.5.5 Other Services ............................................................................................................................... 108

16.6 Testing ........................................................................................................................................... 108

17 Related Content ................................................................................................................................ 110

Page 6: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

6

1 Introduction

1.1 Overview

Purpose

This guide applies to SAP NetWeaver Decision Service Management (any release) or SAP NetWeaver Business Rule Framework plus (BRFplus) shipped with SAP NetWeaver 7.0 Enhancement Package 3 or SAP NetWeaver 7.3 Enhancement Package 1 or higher. This is a technical document for developers and consultants who seek to enhance the capabilities of BRFplus.

Abstract

The guide uses an example of an action type for sending an email to illustrate how to create a custom action type or expression type. The example covers all aspects such as specification/design, database table creation, code generation, and user interface. After reading this guide, you should be able to create custom action types and expression types.

Caution

SAP delivers the content of this guide on the SAP Community Network (SCN) for use with SAP NetWeaver Decision Service Management or Business Rule Framework plus.

SAP does not provide support for customers using this content to develop their own action types and expression types; all risk is assumed by the customer. SAP is not liable for consequences of or damages resulting from the customer’s use of the information contained in this document.

1.2 Expression Types and Action Types

Expression Types

Expression types define the computational power of BRFplus. Each expression type is a self-contained computational unit with a well-defined logic. In general, it uses input (context data objects or nested expressions) to calculate, determine, or derive output (result). Expression types define the ABAP object class and the ABAP object interface, as well as the user interface for expressions. An expression is considered an instance of an expression type behaving in accordance with to the expression type's logic.

Expressions form the building blocks of rules in BRFplus. An expression is assigned to a function; whenever the function is processed, the expression and its nested expressions are evaluated. Expressions can be used in rulesets. Rulesets contain rules that subscribe to function processing (publish-subscribe). When functions are processed, registered rules/expressions are evaluated and actions are performed.

Page 7: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

7

Action Types

Action types define the interactive part of BRFplus. They are a special expression types with no output (except of the ID of the action performed). However, they have side effects. Instead of the output they perform the action defined in the logic of the action type. Each action type can have an arbitrary number of follow up actions to define an action chain. Similar to expressions, actions can use nested expressions and context data as input. Usually, action types are more application-dependent than expression types; therefore only a few action types are provided in the standard. Corresponding to the available expression types, additional action types can be created.

Class and Interface Hierarchy

The following diagram illustrates the class and interface hierarchy used for action types and expression types.

It shows that action type classes are sub classes of the generic action type class CL_FDT_ACTION. Same as with expression types that are sub classes to the generic expression type class CL_FDT_EXPRESSION.

Finally, action types are a special category of expression types. This becomes obvious in the class and interface diagram as CL_FDT_ACTION inherits from CL_FDT_EXPRESSION same as IF_FDT_ACTION includes IF_FDT_EXPRESSION. CL_FDT_MAINTENANCE with its interfaces IF_FDT_TRANSACTION and IF_FDT_ADMIN_DATA ensures that all action types and expression types provide a consistent and unique set of methods and attributes.

Page 8: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

8

Page 9: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

9

Need for Custom Expression Types and Action Types

Although BRFplus provides a set of action types and expression types such as Decision Table, Formula, Message Log, there are good reasons to develop your own action types or expression types.

User interface simplification Generic BRFplus action types and expression types may provide too many features making the UI more complex in specific use cases.

Compound action types and expression types You can combine several expression types or action types into one compound type that enables better UI usability and integration.

Functionality not (yet) available BRFplus action types and expression types do not provide special features that may be needed in the customer situation. Usually, this is true for action types because actions are usually more dependent on the specific environment.

Building Blocks of an Expression and Action Type Creation

The process of creating expression types and action types comprises the following steps:

Specification/Design

Database Layout

Transport Objects

Interface Creation

Class Creation

New Methods

Redefined Methods

Check Methods

Process Methods

Methods for Code Generation

Methods for Lean Trace Display

Data Exchange

Creation of the Action Type or Expression Type as an Object in BRFplus

Testing the Action Type or Expression Type

Creation of the User Interface

Differences between action types and expression types are illustrated in the text.

Note

Look at the code and the database tables of BRFplus standard action types and expression types.

Action type classes implement IF_FDT_ACTION, while expression type classes implement IF_FDT_EXPRESSION.

Page 10: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

10

2 Specification/Design The first step is to define the capabilities of the new action type or expression type. What is it supposed to do? How should the user interface look like? What parameters should be dynamic? This question is important for the database layout. Dynamic parameters enable you to reference an expression or context data object that returns the value to be used. In this case the action type or expression type may be more complex to use and develop.

The example custom action type in this document is the email action type. With this action type, it is possible to create email actions. An email is an action that sends an email. It includes the following input fields:

Recipient(s)

Subject

Body

Recipient parameters

Message parameters

A user interface may look like this:

&1& is a placeholder for a dynamic value. An expression or context data object may be nested to enrich the message with a value from the rules processing.

Page 11: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

11

Note

The configuration of an application server and prerequisites for sending emails are described in SAP Note 455140.

Page 12: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

12

3 Database Layout You must create database tables in order to save the attributes of the action type or expression type. The database tables follow strict conventions to benefit automatically from features BRFplus provides, such as transport or version management. Look at the tables starting with FDT_ACTN for action types or FDT_EXPR for expression types to see the database tables of the BRFplus standard action types and expression types.

Procedure

1. A good example for our email action type is database table, FDT_ACTN_1010:

Structure FDT_INC_C_KEY_0002 is used for the key. This is a generic key structure used by all customizing and local action and expression tables. It includes the object ID and a version field. You can use it for the new email action table. When there is no additional key needed, create a structure for the attributes and include it in the new table. It is a good idea to use the same abbreviation in the include and in the table name, such as ACTN_1010 in the previous example. If additional key fields are needed, a new include for these key fields is created and added to the table.

2. An example is database table, FDT_ACTN_1110:

Also note that the Group field is used. This group information is not used currently but may be used in the future. You maintain it as illustrated in the example.

3. Our new include, FDT_INC_ACTN_6000_DATA, for the attributes:

Page 13: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

13

4. Our new database table, FDT_ACTN_6000:

Page 14: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

14

5. For your tables, use another name, but not FDT_EXPR* or FDT_ACTN* which is reserved for objects in the BRFplus standard.

Define it as a customizing table. BRFplus supports customizing objects with customizing database tables and other objects.

Object Category

Database Table Delivery Class

Database Table Name

Customizing C – Customizing Ending with a number required (Example: FDT_ACTN_6000)

System S – System Ending with a number + S required (Example: FDT_ACTN_6000S)

Master Data A – Application Ending with a number + A required (Example: FDT_ACTN_6000A)

BCF S – System Ending with a number + T required (Example: FDT_ACTN_6000T)

Note

The naming conventions for database tables as given in the previous table are mandatory and must be observed. Some internal mechanisms of BRFplus rely on this naming convention. Any deviations from the given naming convention results in errors, and the custom expression type cannot be integrated into the BRFplus framework.

Create a table for each object category with BCF being optional.

Page 15: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

15

6. BCF stands for Business Content Framework. This is a tool for shipping content in SAP Business ByDesign. If you have not heard of BCF so far or had to work with it, you probably do not need to create a table for this object category.

Since customizing and master data are client-dependent, you must include the client in the key. For the other object categories, create client independent-tables. You replace the key include FDT_INC_C_KEY_0002 with FDT_INC_KEY_0002:

The following configuration applies to the system table FDT_ACTN_6000S:

Data class: APPL2

Size category: 0

Buffering activated

Buffering type: Single Records Buffering

Number of key fields: 0

Page 16: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

16

The following configuration applies to the system table, FDT_ACTN_6000A:

Data class: APPL0

Size category: 3

Buffering not allowed

Buffering type: None of the options is selected

Number of key fields: 0

Technical settings from BRFplus tables should be analyzed when creating custom action types and expression types, especially with respect to buffering configuration.

Page 17: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

17

4 Transport Objects Customizing, system and BCF table content can be transported. Therefore you need to assign the database table to transport objects. For the BRFplus standard tables, the following standard transport objects are used:

If you defined tables for your custom action type or expression type, you must create new transport objects and assign them to the customer action type or expression type definition.

An entry for BCF is optional – it applies only to Business Content Framework.

You can use transaction SOBJ to see the definition of the standard BRFplus transport objects and all database tables assigned to it.

Note

There are three standard transport objects. Click Position… and enter FDT to find the BRFplus

standard transport objects. Double-click on the name of a transport object to see how it is defined. Select the line and click Piece List to see all tables assigned to the transport object.

Object Category Transport Object

Customizing FDT0000

System FDT0001

BCF (optional) FDT0002

Page 18: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

18

Guidelines

You must define your custom transport objects in a similar way as the standard transport objects with the help of transaction SOBJ. The following guidelines apply to the definition of your custom transport objects.

You only can reuse standard transport objects in custom action types or expression types when the new action type or expression type is a redefinition of an existing action type or expression type and does not include new tables.

Page 19: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

19

Assign only the new tables for your custom action type or expression type to your transport objects. You must not assign tables shipped by the BRFplus tool to your transport objects.

Use only one transport object per action type or expression type.

Like the standard transport objects, the new custom transport objects need to be type T.

The definition of a primary table in SOBJ is not mandatory for your custom transport objects. So the setting of the primary table can be performed as follows:

If there is a database table that contains one entry for each ID stored in your set of tables, this table should be marked as the primary table. However, this is for information purposes only. The information is not needed within the transport environment.

Such a table will exist, when you use your transport object for one expression type or action type. Assume you have a header and an item table for this expression type; the header table should be the primary table.

If there is no such table, you do not need to define a primary table.

The standard BRFplus “before export” and “after import” methods must be used in the custom transport objects.

For C tables: AFTER_IMP FDT_AFTER_IMPORT_C Cross Object = X BEFORE_EXP FDT_BEFORE_EXPORT_C Cross Object = X ZDMPRELOCK FDT_PRELOCK Cross Object = ‘ ‘

For S and T tables: AFTER_IMP FDT_AFTER_IMPORT Cross Object = X BEFORE_EXP FDT_BEFORE_EXPORT Cross Object = X ZDMPRELOCK FDT_PRELOCK Cross Object = X

The ZDMPRELOCK method is new since release SAP_BASIS 7.40.

Starting with release SAP_BASIS 7.40 you also need to apply the following settings in the AIM Details section, which can be reached from the method definition area in transaction SOBJ.

Define the corresponding BRFplus transport object as “Reference to Other AIM”.

Page 20: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

20

You assign the transport objects that have been defined in transaction SOBJ to the new action type and expression type under Transport Objects using transaction BRFplus.

Page 21: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

21

5 Interface Creation You must create an ABAP objects interface for the specific attributes of the action type or expression type.

Action type interfaces need to include IF_FDT_ACTION.

Expression type interfaces need to include IF_FDT_EXPRESSION.

The inclusion of these interfaces will introduce many methods to the new action type or expression type. In the example of the email action the prefix IF_FDT_ACTN is used, which should not be used for custom action types. Instead you must use a special customer namespace (for example, /CUS/IF_FDT_ACTN*) or the local namespace (for example, ZIF_FDT_ACTN*).

Note

Look at the comprehensive interfaces IF_FDT_ACTION and IF_FDT_EXPRESSION to find examples from other action types and expression types.

Procedure

1. Include a forward declaration for IF_FDT_TYPES.

IF_FDT_TYPES contains many type definitions you can reuse in your types, signature, and code.

2. On the Interfaces tab, insert IF_FDT_ACTION.

In case of an expression type interface, insert IF_FDT_EXPRESSION.

Page 22: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

22

3. We recommend you to create some types in the interface. These types are found easily and are decoupled from the database.

TYPES:

BEGIN OF s_parameter,

POSITION TYPE n LENGTH 1,

parameter_id TYPE if_fdt_types=>id,

END OF s_parameter .

TYPES:

ts_parameter TYPE SORTED TABLE OF s_parameter WITH UNIQUE KEY position .

TYPES BODY TYPE FDT_ACTN_6000-BODY .

TYPES SUBJECT TYPE FDT_ACTN_6000-SUBJECT .

TYPES RECIPIENT TYPE FDT_ACTN_6000-RECIPIENTS .

TYPES:

t_recipient TYPE STANDARD TABLE OF recipient WITH NON-UNIQUE KEY table_line .

4. Create SET and GET methods for the expression type or action type specific attributes. You may need to create additional methods in accordance with the action type or expression type involved.

Page 23: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

23

5. To support versioning of the message properties (look at the database layout), you need to offer an optional timestamp as an importing parameter for the GET methods.

If an attribute should be returned it may be returned for the last (current) version. This is the case when no timestamp is supplied. It may be returned for a specific version when a timestamp is supplied. Then the correct version for the timestamp will be determined and is used for the database read. The timestamp may not find a version. In this case a CX_FDT_INPUT exception should be returned.

Interface section of the GET methods for the Email action type:

METHODS get_body

IMPORTING

!iv_timestamp TYPE if_fdt_types=>timestamp OPTIONAL

RETURNING

value(rv_body) TYPE body

RAISING

cx_fdt_input .

METHODS get_parameters

IMPORTING

!iv_timestamp TYPE if_fdt_types=>timestamp OPTIONAL

EXPORTING

!ets_message_parameter TYPE ts_parameter

!ets_recipient_parameter TYPE ts_parameter

RAISING

cx_fdt_input .

METHODS get_recipients

IMPORTING

!iv_timestamp TYPE if_fdt_types=>timestamp OPTIONAL

RETURNING

value(rt_recipient) TYPE t_recipient

RAISING

cx_fdt_input .

METHODS get_subject

Page 24: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

24

IMPORTING

!iv_timestamp TYPE if_fdt_types=>timestamp OPTIONAL

RETURNING

value(rv_subject) TYPE subject

RAISING

cx_fdt_input .

Interface section of the SET methods for the Email action type:

METHODS set_body

IMPORTING

!iv_body TYPE body

RAISING

cx_fdt_input .

METHODS set_parameters

IMPORTING

!its_message_parameter TYPE ts_parameter OPTIONAL

!its_recipient_parameter TYPE ts_parameter OPTIONAL

PREFERRED PARAMETER its_recipient_parameter

RAISING

cx_fdt_input .

METHODS set_recipients

IMPORTING

!it_recipient TYPE t_recipient

RAISING

cx_fdt_input .

METHODS set_subject

IMPORTING

!iv_subject TYPE subject

RAISING

cx_fdt_input .

Note

In the code examples, the following naming conventions are used.

o R = Returning o E = Exporting o I = Importing o RT = Returning table o RS = Returning structure o IF = Interface o CL = Class

6. Create several aliases (that will be used in the following code or even by generic BRFplus methods).

Page 25: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

25

Interface Component Alias

IF_FDT_ADMIN_DATA~MV_CUSTOMIZING_OBJECT MV_CUSTOMIZING_OBJECT

IF_FDT_ADMIN_DATA~MV_ID MV_ID

IF_FDT_ADMIN_DATA~MV_LOCAL_OBJECT MV_LOCAL_OBJECT

IF_FDT_ADMIN_DATA~MV_MASTERDATA_OBJECT MV_MASTERDATA_OBJECT

IF_FDT_ADMIN_DATA~MV_OBJECT_TYPE MV_OBJECT_TYPE

IF_FDT_ADMIN_DATA~MV_SYSTEM_OBJECT MV_SYSTEM_OBJECT

IF_FDT_EXPRESSION~MV_ACTION MV_ACTION

IF_FDT_EXPRESSION~MV_EXPRESSION_TYPE_ID MV_EXPRESSION_TYPE_ID

IF_FDT_EXPRESSION~MV_RULE MV_RULE

In the example of the email action type, you do not need any attributes at this point. For other action type or expression types, attributes may be used.

Page 26: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

26

6 Class Creation You must create an ABAP objects class for the action type or expression type.

Action type classes need to inherit from CL_FDT_ACTION.

Expression type classes need to inherit from CL_FDT_EXPRESSION.

Inheritance ensures that many features do not need to be implemented manually. In the example of the email action, the prefix, CL_FDT_ACTN, must not be used for custom action types. Instead a special customer namespace (for example, /CUS/CL_FDT_ACTN*) or the local namespace (for example, ZCL_FDT_ACTN*) should be used.

Note

Look at the classes inheriting from CL_FDT_ACTION and CL_FDT_EXPRESSION to find examples from other action types and expression types.

All macros used in the sample code can be copied.

FDT_INCL_CHANGE_HISTORY_MACRO

FDT_INCL_MESSAGE_MACROS

FDT_INCL_TRACE_MACROS

The includes must not be used directly, but macros have to be copied.

Procedure

1. Include a forward declaration for IF_FDT_TYPES. IF_FDT_TYPES contains many type definitions you can reuse in your types, signature and code.

Page 27: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

27

You include the corresponding interface to the interface list.

2. Define friendship to CL_FDT_FACTORY.

In combination with a non-public instantiation, this ensures only CL_FDT_FACTORY can create an instance.

3. Create a private type S_BUFFER.

This type is used at many places in the class. It should contain all attributes of the specific action type or expression type. The email action type S_BUFFER is defined as follows:

INTERFACE if_fdt_actn_email LOAD .

TYPES:

BEGIN OF s_buffer,

t_recipient TYPE if_fdt_actn_email=>t_recipient,

subject TYPE if_fdt_actn_email=>subject,

body TYPE if_fdt_actn_email=>body,

ts_message_parameter TYPE if_fdt_actn_email=>ts_parameter,

ts_rec_parameter TYPE if_fdt_actn_email=>ts_parameter,

END OF s_buffer.

Note

You may need to add a forward declaration to the interface as shown in the example. You can do this in the section for forward declarations in the class properties.

Page 28: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

28

Some methods and attributes need to be provided to follow a specific implementation pattern that makes use of many concepts in BRFplus. Big parts of the code for the implementation can be copied and are provided with the following pages of this document.

4. Create the following methods (private section):

METHODS load_buffer

IMPORTING

!iv_timestamp TYPE if_fdt_types=>timestamp OPTIONAL

!iv_version TYPE if_fdt_types=>version OPTIONAL

PREFERRED PARAMETER iv_version

RETURNING

value(rs_buffer) TYPE s_buffer

RAISING

cx_fdt_input .

METHODS load_buffer_db

IMPORTING

!iv_version TYPE if_fdt_types=>version OPTIONAL

RETURNING

value(rs_buffer) TYPE s_buffer .

METHODS save_buffer_db .

METHODS set_buffer

IMPORTING

!is_buffer TYPE s_buffer .

Note

You can define a preferred parameter in the section directly or you navigate to the parameter on the method tab. Place your cursor on the parameter to be switched to preferred. Then press the detail view button and check the preferred field in the upcoming dialog.

5. Define the following attributes:

Attribute Level Visibility Associated Type

Initial Value

MS_BUFFER Instance Attribute

Private Type

S_BUFFER

MV_MS_BUFFER_LOADED Instance Attribute

Private Type

ABAP_BOOL

MS_BUFFER_DB Instance Attribute

Private Type

S_BUFFER

MV_MS_BUFFER_DB_LOADED Instance Attribute

Private Type

ABAP_BOOL

GC_ACTN_6000 Constant Private Type

TABNAME FDT_ACTN_6000

In the last entry (GC_ACTN_6000), the constant (FDT_ACTN_6000) must be replaced by the specific database table name of the action type or expression type. Other action types and expression types have more constants defined. For each database table, a constant is necessary. It is important to use the customizing table name (not system or master data) for the constant value.

Page 29: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

29

Note

When you look at the standard action types and expression types, you find constants for the database tables in the class. You can find which tables belong to a specific action type or expression type.

6. Create a public alias for the object ID:

Interface Component Alias Visible

IF_FDT_ADMIN_DATA~MV_ID MV_ID Public

7. Define your required macros in the macro section of the class:

INCLUDE: fdt_incl_message_macros,

fdt_incl_trace_macros,

fdt_incl_change_history_macro.

These macros will be used in many methods of nearly all action and expression types. These includes are currently not in the package interface. Therefore, you may need to copy the macros that are needed by you directly into the macro section of your class.

Page 30: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

30

7 New Methods This chapter deals with the implementation of the new methods you created. All the methods follow specific patterns that have been applied to all action types and expression types provided in the BRFplus standard. We strongly recommend you to follow these patterns; by doing so, you automatically benefit from many features. Also, it can help when you compare your code with existing and similar classes.

7.1 LOAD_BUFFER_DB The purpose of the method is to load the object data from the database into the object buffer (returning parameter RS_BUFFER). Not all data are loaded; only the data for the specified version (IV_VERSION) or the latest version, which is the working version. The method makes use of a helper object (IF_FDT_PERSISTENCE) that is responsible for reading data

Of the correction object ID

In the correct version

In the correct database table

All of the above works when the patterns are applied. The method supports a buffering mechanism so it may return data from the database buffer (MS_BUFFER_DB). For newly created action and expression types it is good practice to copy the method from an existing class and adjust with the correct data structure and constants for database table names.

No data from other tables for texts, documentation, name have to be read. They will be read by super classes. In this class, the focus is on the application or expression type specific attributes. That is true for this method and for all methods of the class.

For the email action type, create the following code:

DATA: lo_persistence TYPE REF TO if_fdt_persistence,

lv_version TYPE if_fdt_types=>version,

ls_actn_6000 TYPE fdt_actn_6000s,

ls_parameter TYPE if_fdt_actn_email=>s_parameter,

lv_last_db_version TYPE if_fdt_types=>version.

DEFINE db_to_buffer_format.

if &1 is not initial.

ls_parameter-position = &2.

ls_parameter-parameter_id = &1.

insert ls_parameter into table &3.

clear ls_parameter.

endif.

END-OF-DEFINITION.

For each database table from which you wish to read data, you create a variable. When the data are flat, create a structure. When data are deep, create a table. For the latter case, look at other classes to reference the pattern.

lo_persistence = get_persistence( ).

lo_persistence->get_versions(

IMPORTING ev_last_db_version = lv_last_db_version ).

Page 31: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

31

IF mv_ms_buffer_db_loaded EQ abap_true AND

( iv_version IS NOT SUPPLIED OR

iv_version EQ lv_last_db_version ).

* shortcut: we do not read the data again that is already in the buffer

rs_buffer = ms_buffer_db.

RETURN. ">>>

ENDIF.

IF iv_version IS SUPPLIED.

lv_version = iv_version.

ELSE.

lv_version = lv_last_db_version.

ENDIF.

This part deals with initialization and buffer management. It can be copied without any modification.

* FDT_ACTN_6000

lo_persistence->read_single( EXPORTING iv_version = lv_version

iv_tabname = gc_actn_6000

IMPORTING es_value = ls_actn_6000 ).

SPLIT ls_actn_6000-recipients AT space INTO TABLE rs_buffer-t_recipient.

rs_buffer-subject = ls_actn_6000-subject.

rs_buffer-body = ls_actn_6000-body.

"Add position and format it and add to buffer.

db_to_buffer_format ls_actn_6000-rec_param_1 1 rs_buffer-ts_rec_parameter.

db_to_buffer_format ls_actn_6000-rec_param_2 2 rs_buffer-ts_rec_parameter.

db_to_buffer_format ls_actn_6000-rec_param_3 3 rs_buffer-ts_rec_parameter.

db_to_buffer_format ls_actn_6000-rec_param_4 4 rs_buffer-ts_rec_parameter.

db_to_buffer_format ls_actn_6000-msg_param_1 1 rs_buffer-ts_message_parameter.

db_to_buffer_format ls_actn_6000-msg_param_2 2 rs_buffer-ts_message_parameter.

db_to_buffer_format ls_actn_6000-msg_param_3 3 rs_buffer-ts_message_parameter.

db_to_buffer_format ls_actn_6000-msg_param_4 4 rs_buffer-ts_message_parameter.

db_to_buffer_format ls_actn_6000-msg_param_5 5 rs_buffer-ts_message_parameter.

db_to_buffer_format ls_actn_6000-msg_param_6 6 rs_buffer-ts_message_parameter.

db_to_buffer_format ls_actn_6000-msg_param_7 7 rs_buffer-ts_message_parameter.

db_to_buffer_format ls_actn_6000-msg_param_8 8 rs_buffer-ts_message_parameter.

In this part we perform a read of a single record from our database table. Use the constant we have created for the database table. LO_PERSISTENCE will ensure the right database table is used for reading (customizing, system) and the select is done with the correction version and identifier. When the data has been read, it is moved into our buffer structure. In the example, a conversion of the recipients list from the database format to buffer format is done. This part depends on the specific attributes of the action or expression type. Many action and expression types read data from more than one class. Some set default values in case there is no value in DB.

* fill the buffer if appropriate

IF mv_ms_buffer_db_loaded EQ abap_false AND

( iv_version IS NOT SUPPLIED OR iv_version EQ lv_last_db_version ).

ms_buffer_db = rs_buffer.

mv_ms_buffer_db_loaded = abap_true.

ENDIF.

The rest of the method can be overtaken without any change. This part finalizes the buffer management.

Page 32: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

32

7.2 LOAD_BUFFER The purpose of this method is to return the correct buffer information in accordance with the version or timestamp provided. Data may be returned from:

The object buffer MS_BUFFER

The database buffer (see LOAD_BUFFER_DB) or

The database (see LOAD_BUFFER_DB)

The code of the method is always the same. There is no action type or expression type specific aspect.

For the email action type, copy the following code:

DATA: lts_version TYPE if_fdt_admin_data=>ts_version,

ls_message TYPE if_fdt_types=>s_message,

lt_message TYPE if_fdt_types=>t_message,

lv_version TYPE if_fdt_types=>version,

lv_no_version TYPE abap_bool,

lv_ctext TYPE c LENGTH 20,

lv_i TYPE i.

FIELD-SYMBOLS <ls_version> TYPE if_fdt_admin_data=>s_version.

ASSERT NOT ( iv_timestamp IS SUPPLIED AND iv_version IS SUPPLIED ). ">>>

IF iv_timestamp IS NOT SUPPLIED AND iv_version IS NOT SUPPLIED.

* when we have the last version we can read from the buffer

IF mv_ms_buffer_loaded EQ abap_false.

* load the buffer with the last version

ms_buffer = load_buffer_db( ).

mv_ms_buffer_loaded = abap_true.

ENDIF.

rs_buffer = ms_buffer.

RETURN. ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

ELSEIF iv_timestamp IS SUPPLIED. "get the right version for the tmstmp

if_fdt_admin_data~get_active_version(

EXPORTING iv_timestamp = iv_timestamp

IMPORTING ev_version = lv_version

ev_no_version = lv_no_version ).

IF lv_no_version EQ abap_true.

WRITE iv_timestamp TO lv_ctext. "Convert to external format

DATA: lv_name TYPE if_fdt_types=>name.

DATA: lv_str_name TYPE string.

cl_fdt_services=>get_texts_for_id( EXPORTING iv_id = mv_id

IMPORTING ev_name = lv_name ).

lv_str_name = lv_name.

MESSAGE x006(fdt_core) WITH lv_str_name lv_ctext INTO ls_message-text.

message_exception ls_message lt_message cx_fdt_input.

ENDIF.

ELSEIF iv_version IS SUPPLIED. "use this version

lv_version = iv_version.

ENDIF.

* do we have a valid version now?

if_fdt_admin_data~get_versions( IMPORTING ets_version = lts_version ).

READ TABLE lts_version ASSIGNING <ls_version>

WITH TABLE KEY version = lv_version.

IF sy-subrc NE 0.

MESSAGE x002(fdt_core) WITH iv_version INTO ls_message-text.

message_exception ls_message lt_message cx_fdt_input.

Page 33: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

33

ENDIF.

lv_i = lines( lts_version ).

READ TABLE lts_version INDEX lv_i ASSIGNING <ls_version>.

IF <ls_version>-version EQ lv_version.

* when we have the last version we can read from the buffer

IF mv_ms_buffer_loaded EQ abap_false.

* load the buffer with the last version

ms_buffer = load_buffer_db( ).

mv_ms_buffer_loaded = abap_true.

ENDIF.

rs_buffer = ms_buffer.

ELSE.

* requested version has to be loaded from DB

rs_buffer = load_buffer_db( lv_version ).

ENDIF.

7.3 SET_BUFFER The purpose of the method is to copy data to the object buffer.

For our example, copy the code:

ms_buffer = is_buffer.

7.4 SAVE_BUFFER_DB The purpose of the method is to write data to the database. It corresponds to LOAD_BUFFER_DB and follows similar ideas by using interface IF_FDT_PERSISTENCE to ensure writing data

For the correct identifier

In the correction version

To the correct database table

The best approach for this method is to simply copy from a good example and adjust in accordance with the specific attributes of the action type or expression type.

For the email action type, create the following code:

DATA: lo_persistence TYPE REF TO if_fdt_persistence,

ls_actn_6000 TYPE fdt_actn_6000s,

ls_parameter TYPE if_fdt_actn_email=>s_parameter.

For each database table a structure or an internal table needs to be created. Internal tables are needed in case of additional key fields; there may be many entries in the database for one identifier version combination. Look at other classes and patterns applied if you need an internal table. IF_FDT_PERSISTENCE offers additional features to divide the data into lines written into the database and lines that need to be deleted from database.

lo_persistence = get_persistence( ).

This line is following the standard pattern:

* FDT_ACTN_6000

ls_actn_6000-body = ms_buffer-body.

Page 34: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

34

ls_actn_6000-subject = ms_buffer-subject.

LOOP AT ms_buffer-ts_message_parameter INTO ls_parameter.

CASE ls_parameter-position.

WHEN 1.

ls_actn_6000-msg_param_1 = ls_parameter-parameter_id.

WHEN 2.

ls_actn_6000-msg_param_2 = ls_parameter-parameter_id.

WHEN 3.

ls_actn_6000-msg_param_3 = ls_parameter-parameter_id.

WHEN 4.

ls_actn_6000-msg_param_4 = ls_parameter-parameter_id.

WHEN 5.

ls_actn_6000-msg_param_5 = ls_parameter-parameter_id.

WHEN 6.

ls_actn_6000-msg_param_6 = ls_parameter-parameter_id.

WHEN 7.

ls_actn_6000-msg_param_7 = ls_parameter-parameter_id.

WHEN 8.

ls_actn_6000-msg_param_8 = ls_parameter-parameter_id.

ENDCASE.

ENDLOOP.

LOOP AT ms_buffer-ts_rec_parameter INTO ls_parameter.

CASE ls_parameter-position.

WHEN 1.

ls_actn_6000-rec_param_1 = ls_parameter-parameter_id.

WHEN 2.

ls_actn_6000-rec_param_2 = ls_parameter-parameter_id.

WHEN 3.

ls_actn_6000-rec_param_3 = ls_parameter-parameter_id.

WHEN 4.

ls_actn_6000-rec_param_4 = ls_parameter-parameter_id.

ENDCASE.

ENDLOOP.

CONCATENATE LINES OF ms_buffer-t_recipient INTO ls_actn_6000-recipients

SEPARATED BY space.

lo_persistence->write_single( iv_tabname = gc_actn_6000

is_value = ls_actn_6000 ).

This part deals with data conversion from buffer to database structure. Subsequently, data are written into the database.

ms_buffer_db = ms_buffer.

mv_ms_buffer_loaded = abap_true.

mv_ms_buffer_db_loaded = abap_true.

The remainder follows a generic pattern and you can copy it without modification.

7.5 Method in Action Type or Expression Type Specific Interfaces

The following methods are specific to the action type or expression type. The implementation is explained with reference to the new email action type.

7.5.1 IF_FDT_ACTN_EMAIL=>GET_BODY

This is a simple GET method for the email body. All GET methods follow the same pattern.

Page 35: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

35

1. The correct buffer data are loaded.

2. The data are returned.

DATA ls_buffer TYPE s_buffer.

IF iv_timestamp IS SUPPLIED.

ls_buffer = load_buffer( iv_timestamp = iv_timestamp ).

ELSE.

ls_buffer = load_buffer( ).

ENDIF.

rv_body = ls_buffer-body.

7.5.2 IF_FDT_ACTN_EMAIL=>GET_RECIPIENTS

DATA ls_buffer TYPE s_buffer.

IF iv_timestamp IS SUPPLIED.

ls_buffer = load_buffer( iv_timestamp = iv_timestamp ).

ELSE.

ls_buffer = load_buffer( ).

ENDIF.

rt_recipient = ls_buffer-t_recipient.

7.5.3 IF_FDT_ACTN_EMAIL=>GET_PARAMETERS

DATA ls_buffer TYPE s_buffer.

IF iv_timestamp IS SUPPLIED.

ls_buffer = load_buffer( iv_timestamp = iv_timestamp ).

ELSE.

ls_buffer = load_buffer( ).

ENDIF.

ets_message_parameter = ls_buffer-ts_message_parameter.

ets_recipient_parameter = ls_buffer-ts_rec_parameter.

7.5.4 IF_FDT_ACTN_EMAIL=>GET_SUBJECT

DATA ls_buffer TYPE s_buffer.

IF iv_timestamp IS SUPPLIED.

ls_buffer = load_buffer( iv_timestamp = iv_timestamp ).

ELSE.

ls_buffer = load_buffer( ).

ENDIF.

rv_subject = ls_buffer-subject.

7.5.5 IF_FDT_ACTN_EMAIL=>SET_BODY

This is a simple SET method for the email body. All SET methods follow the same pattern.

1. The current buffer values are read.

Page 36: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

36

2. The value is checked and changed in the buffer.

3. Method NOTIFY_CHANGE is called.

The call of notify_change is very important since several generic features provided by super

classes depend on the information that changes occurred.

DATA: ls_buffer TYPE s_buffer.

ls_buffer = load_buffer( ).

CHECK ls_buffer-body NE iv_body. ">>>

ls_buffer-body = iv_body.

set_buffer( ls_buffer ).

notify_change( ).

7.5.6 IF_FDT_ACTN_EMAIL=>SET_RECIPIENTS

DATA: ls_buffer TYPE s_buffer,

lt_recipient LIKE it_recipient.

ls_buffer = load_buffer( ).

CHECK ls_buffer-t_recipient NE it_recipient. ">>>

* remove empty lines

lt_recipient = it_recipient.

DELETE lt_recipient WHERE table_line IS INITIAL.

ls_buffer-t_recipient = lt_recipient.

set_buffer( ls_buffer ).

notify_change( ).

7.5.7 IF_FDT_ACTN_EMAIL=>SET_PARAMETERS

DATA: ls_buffer TYPE s_buffer,

ls_parameter TYPE if_fdt_actn_email=>s_parameter,

lts_parameter TYPE if_fdt_actn_email=>ts_parameter,

ls_msg TYPE if_fdt_types=>s_message,

lt_msg TYPE if_fdt_types=>t_message,

lv_unknown TYPE abap_bool.

ls_buffer = load_buffer( ).

CHECK ( its_message_parameter IS SUPPLIED AND

its_message_parameter NE ls_buffer-ts_message_parameter ) OR

( its_recipient_parameter IS SUPPLIED AND

its_recipient_parameter NE ls_buffer-ts_rec_parameter ).

" check for the allowed number of paramters.

IF lines( its_message_parameter ) > 8.

MESSAGE e316(fdt_expressions) INTO ls_msg-text.

message_exception ls_msg lt_msg cx_fdt_input.

ELSEIF lines( its_recipient_parameter ) > 4.

MESSAGE e317(fdt_expressions) INTO ls_msg-text.

message_exception ls_msg lt_msg cx_fdt_input.

ENDIF.

IF its_message_parameter IS SUPPLIED.

LOOP AT its_message_parameter INTO ls_parameter.

* ls_parameter-position = sy-tabix.

* INSERT ls_parameter INTO TABLE lts_parameter.

Page 37: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

37

" check for valid ID

IF ls_parameter-parameter_id IS NOT INITIAL.

cl_fdt_admin_data=>check_id( EXPORTING iv_id = ls_parameter-parameter_id

IMPORTING ev_id_unknown = lv_unknown ).

IF lv_unknown EQ abap_true.

get_name ls_parameter-parameter_id ls_msg-msgv1.

MESSAGE e320(fdt_expressions) WITH ls_parameter-parameter_id ls_parameter-

position INTO ls_msg-text.

append_message ls_msg lt_msg.

ENDIF.

ENDIF.

ENDLOOP.

ls_buffer-ts_message_parameter = its_message_parameter.

ENDIF.

CLEAR lts_parameter.

IF its_recipient_parameter IS SUPPLIED.

LOOP AT its_recipient_parameter INTO ls_parameter.

ls_parameter-position = sy-tabix.

INSERT ls_parameter INTO TABLE lts_parameter.

" check for valid ID

IF ls_parameter-parameter_id IS NOT INITIAL.

cl_fdt_admin_data=>check_id( EXPORTING iv_id = ls_parameter-parameter_id

IMPORTING ev_id_unknown = lv_unknown ).

IF lv_unknown EQ abap_true.

get_name ls_parameter-parameter_id ls_msg-msgv1.

MESSAGE e320(fdt_expressions) WITH ls_parameter-parameter_id ls_parameter-

position INTO ls_msg-text.

append_message ls_msg lt_msg.

ENDIF.

ENDIF.

ENDLOOP.

ls_buffer-ts_rec_parameter = lts_parameter.

ENDIF.

set_buffer( ls_buffer ).

notify_change( ).

7.5.8 IF_FDT_ACTN_EMAIL=>SET_SUBJECT

DATA: ls_buffer TYPE s_buffer.

ls_buffer = load_buffer( ).

CHECK ls_buffer-subject NE iv_subject. ">>>

ls_buffer-subject = iv_subject.

set_buffer( ls_buffer ).

notify_change( ).

Page 38: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

38

Note o SET methods allow also invalid data. Checking data validity takes

place during activation; before activation, invalid data go into the buffer and DB, which gives freedom when building the content.

o Return an exception (CX_FDT_INPUT) when an input is wrong, such as an ID that is neither an expression nor a data object. Use method GET_ID_INFORMATION in class CL_FDT_FACTORY to check.

o There are some methods that are specific to the custom action and expression. These are not described in detail; if you are in doubt, check the system.

Page 39: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

39

8 Redefined Methods This chapter deals with the mandatory redefinition of methods.

8.1 Class CL_FDT_MAINTENANCE 8.1.1 DELETE_FROM_DB

The purpose of this method is to delete an object (identifier with data) from the database. The implementation follows a simple pattern that can be copied. Services from CL_FDT_PERSISTENCE are used.

Our example contains the following code:

DATA lo_persistence TYPE REF TO if_fdt_persistence.

ASSERT iv_transport_request IS NOT SUPPLIED. ">>>not supported anymore

super->delete_from_db( ).

lo_persistence = get_persistence( ).

lo_persistence->delete( iv_tabname = gc_actn_6000 ).

You only need to use the constant with the database name from which the data are to be deleted. Class inheritance ensures data from other tables are deleted by super classes.

8.1.2 CHECK

The purpose of this method is to check the object. It is discussed in chapter 9 Check Methods.

8.1.3 COPY

This method copies the buffer of the class. This involves only the attributes added by the class, not the attributes copied by the super class. The method follows a pattern used by all action types and expression types in the BRFplus standard.

In our example, the following code is created:

DATA: lo_email TYPE REF TO cl_fdt_actn_email,

ls_buffer TYPE s_buffer.

FIELD-SYMBOLS: <ls_parameter> TYPE if_fdt_actn_email=>s_parameter.

Adapt the class name to create a copy with the correct type:

lo_email ?= super->copy( iv_deep = iv_deep

iv_application_id = iv_application_id ).

IV_DEEP enables creation of a deep copy. When the action or expression uses other objects such as expressions, action, data objects, which are nearly always the case, those objects will be copied in case the

deep flag is set to ABAP_TRUE. In detail, the deep object management works as follows:

Used unnamed objects are copied always

Used named objects in the same application are copied only when IV_DEEP = ABAP_TRUE

Page 40: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

40

Used named objects in other applications are not copied

Any deep operation stops at the application border

When another application is provided (IV_APPLICATION_ID), the copied objects are created in this application (with reference to this application).

* copy the attributes of this class

ls_buffer = load_buffer( ).

LOOP AT ls_buffer-ts_message_parameter ASSIGNING <ls_parameter>.

<ls_parameter>-parameter_id = copy_on_request(

iv_id = <ls_parameter>-parameter_id

iv_deep = iv_deep

iv_application_id = iv_application_id ).

ENDLOOP.

LOOP AT ls_buffer-ts_rec_parameter ASSIGNING <ls_parameter>.

<ls_parameter>-parameter_id = copy_on_request(

iv_id = <ls_parameter>-parameter_id

iv_deep = iv_deep

iv_application_id = iv_application_id ).

ENDLOOP.

lo_email->set_buffer( ls_buffer ).

ro_copy ?= lo_email.

Using the COPY_ON_REQUEST method, you ensure each object is copied once.

Example

There is an object A using objects B and C. Object B uses object C, too.

Now we copy A to A*. This results in A passing the copy to B and C which results in copies B* and C*.

However, B also passes the copy to C, which must not result in another copy of C (C**) but in C*. COPY_ON_REQUEST detects that C was already copied to C* and returns C* instead of creating another copy.

8.1.4 RESTORE_BUFFER

This method rolls back the object buffer to the database buffer. The method follows a generic pattern and can be copied without any changes.

super->restore_buffer( iv_buffer_db ).

IF iv_buffer_db EQ abap_true.

CLEAR ms_buffer_db.

mv_ms_buffer_db_loaded = abap_false.

ms_buffer_db = load_buffer_db( ).

ENDIF.

CLEAR ms_buffer.

mv_ms_buffer_loaded = abap_false.

ms_buffer = load_buffer( ).

8.1.5 SAVE_WITH_VERSION

The purpose of the method is to distribute the save information in the layers of the inheritance hierarchy. The method follows a generic pattern and can be copied without any changes.

Page 41: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

41

IF iv_transport_request IS SUPPLIED.

super->save_with_version( iv_version = iv_version

iv_last_db_version = iv_last_db_version

iv_transport_request = iv_transport_request ).

ELSE.

super->save_with_version( iv_version = iv_version

iv_last_db_version = iv_last_db_version ).

ENDIF.

* we only need to save the data of this class when there is a change in

* the attributes or when the version needs to be changed

CHECK iv_version NE iv_last_db_version OR ms_buffer NE ms_buffer_db.

save_buffer_db( ).

8.1.6 TRANSPORT

This method writes an object to a transport request. The implementation follows a simple pattern that you can copy. Services from IF_FDT_PERSISTENCE are used.

Our example contains the following code:

DATA lo_persistence TYPE REF TO if_fdt_persistence.

super->transport( iv_transport_request = iv_transport_request ).

lo_persistence = get_persistence( ).

lo_persistence->transport( iv_transport_request = iv_transport_request

iv_tabname = gc_actn_6000 ).

You only need to use our constant with the database name from which the data is to be transported. Class inheritance ensures data from other tables are written to transport by super classes.

Note

The following is important with regard to the TRANSPORT method:

You must not create transport piece list entries manually for the table entries of self-implemented expression types.

o You can use report FDT_TRANS to record existing instances or applications on a transport.

o If the expression types were designed correctly, the tables created for these expression types should take part in automated change recording which is done via the folllowing interface methods: - IF_FDT_TRANSACTION-SAVE

(saving and recording of changes) - IF_FDT_TRANSACTION-TRANSPORT

(creating new piece lists for instances)

Caution

Please review your implementation of the TRANSPORT method before you start transporting your content.

We recommend that you first use of a transport copies to a test system to ensure your expression types are implemented so they can be transported without problems. This will avoid the possibility of broken data being transported to the whole system landscape.

Page 42: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

42

8.1.7 GET_CHANGE_DETAILS

This method returns information on changes for two given versions or timestamps. Some of the changes are processing relevant (for example, changed email subject) and some are not processing relevant (for example, changed action text).

Method Parameters

Parameter Type Purpose

IV_1ST_VRS_TMSTMP Importing The first timestamp for the comparison. If initial, it implies the second timestamp, which has been supplied, is the first version of the object.

IV_2ND_VRS_TMSTMP Importing The second timestamp for the comparison. Together, the first and second timestamps define the time range within which user wants to locate the changes performed on the object.

IV_SUB_OBJ_1ST_VRS_TMSTMP Importing The first timestamp for the comparison of the sub- object changes. If initial, it implies the second timestamp, which has been supplied, is the first version of the sub-object.

IV_SUB_OBJ_2ND_VRS_TMSTMP Importing The second timestamp for the comparison of the sub- object changes. Together the first and second timestamps define the range between which the changes in the sub-objects has to be analyzed. The changes are retrieved for the second timestamp of the parent object.

IV_COMPARE_ONLY_SUB_OBJECT Importing A Boolean parameter, when ABAP_TRUE passed, only the sub objects are compared; when ABAP_FALSE is passed, the main object and sub- objects are compared.

IV_SUPERIOR_ID Importing ID of the object referencing the called object.

IV_DETAILED Importing This parameter defines whether all detail information should be added or if summary of changes is required

ETS_PROCESSING_CHANGE Exporting This parameter contains the details of processing changes for the called object and sub objects (IV_COMPARE_ONLY_SUB_OBJECT= ABAP_FALSE).

ETS_NON_PROCESSING_CHANGE Exporting This parameter contains the details of non-processing changes for the called object and sub objects (IV_COMPARE_ONLY_SUB_OBJECT= ABAP_FALSE).

CTS_CHANGE_TIMESLICE Changing This parameter carries the time slices of the object that has been covered. In case of a recursive loop, the changes on the time slices already covered are not analyzed.

CTS_CHANGE_SUMMARY Changing This parameter carries the change summary of the objects that have been covered. While analyzing the sub-objects, this parameter must be passed.

Page 43: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

43

The code in class CL_FDT_ACTN_EMAIL will help you understand how the method should work. You can copy and adapt code from there.

Note

You can create an application with versioning switched on by default to test the method for your custom type and how it works in combination with nested objects.

8.2 Interface IF_FDT_EXPRESSION You must implement the following methods:

PROCESS

GENERATE_PROCESS

IS_GENERATING

A successful check is required to activate an object. The result of the method is a list of information, warnings, or error messages.

This method is implemented to reuse the specific check methods that are used in the SET methods. Detailed checks are performed such as validation of the email addresses supplied or UUIDs used. In this example, the code of the check method is as follows:

DATA: ls_msg TYPE if_fdt_types=>s_message,

lt_msg TYPE if_fdt_types=>t_message,

lt_recipient TYPE if_fdt_actn_email=>t_recipient,

lv_body TYPE if_fdt_actn_email=>body,

lv_subject TYPE if_fdt_actn_email=>subject,

lts_rec_param TYPE if_fdt_actn_email=>ts_parameter,

ls_rec_param TYPE if_fdt_actn_email=>s_parameter,

lts_msg_param TYPE if_fdt_actn_email=>ts_parameter,

ls_msg_param TYPE if_fdt_actn_email=>s_parameter.

rt_message = super->check( iv_activation_check ).

* IV_ACTIVATION_CHECK set to true means that the active version of used

* objects has to be included into the check.

* IV_ACTIVATION_CHECK set to false means that the latest version of used

* objects has to be included into the check.

lt_recipient = if_fdt_actn_email~get_recipients( ).

lv_subject = if_fdt_actn_email~get_subject( ).

lv_body = if_fdt_actn_email~get_body( ).

if_fdt_actn_email~get_parameters( IMPORTING ets_message_parameter = lts_msg_param

ets_recipient_parameter = lts_rec_param ).

* No initial parameter ids in the param tables

LOOP AT lts_msg_param INTO ls_msg_param WHERE parameter_id IS INITIAL.

MESSAGE e321(fdt_expressions) WITH 'message body'(005) ls_msg_param-

position INTO ls_msg-text. append_message ls_msg rt_message.

ENDLOOP.

LOOP AT lts_rec_param INTO ls_rec_param WHERE parameter_id IS INITIAL.

MESSAGE e321(fdt_expressions) WITH 'recipients'(006) ls_rec_param-

position INTO ls_msg-text. append_message ls_msg rt_message.

ENDLOOP.

Page 44: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

44

* body and subject both must not be initial.

IF lv_body IS INITIAL AND lv_subject IS INITIAL.

MESSAGE e311(fdt_expressions) INTO ls_msg-text. append_message ls_msg rt_message.

ENDIF.

lt_msg = CHECK_RECIPIENTS( it_recipient = lt_recipient

its_parameter = lts_rec_param

iv_activation_check = abap_true ).

INSERT LINES OF lt_msg INTO TABLE rt_message.

lt_msg = CHECK_PARAMETERS( iv_subject = lv_subject

iv_body = lv_body

its_rec_param = lts_rec_param

its_msg_param = lts_msg_param

iv_activation_check = abap_true ).

INSERT LINES OF lt_msg INTO TABLE rt_message.

See class CL_FDT_ACTN_EMAIL for the check methods:

CHECK_RECIPIENTS

CHECK_PARAMETERS

8.2.1 GET_USED_EXPRESSIONS

The purpose of this method is to return all UUIDs of expressions which are used by this object. In the example of the Email action only the parameters hold UUIDs, which could be data objects or expressions. So you get those UUIDs and check them for expressions.

DATA: lv_obj_type TYPE if_fdt_types=>object_type,

lts_msg_parameter TYPE if_fdt_actn_email=>ts_parameter,

lts_rec_parameter TYPE if_fdt_actn_email=>ts_parameter,

ls_parameter TYPE if_fdt_actn_email=>s_parameter.

IF iv_timestamp IS SUPPLIED.

rts_expression_id = super-

>if_fdt_expression~get_used_expressions( iv_timestamp = iv_timestamp ).

ELSE.

rts_expression_id = super->if_fdt_expression~get_used_expressions( ).

ENDIF.

* ------------------------------------------------------

IF iv_timestamp IS SUPPLIED.

if_fdt_actn_email~get_parameters(

EXPORTING iv_timestamp = iv_timestamp

IMPORTING ets_message_parameter = lts_msg_parameter

ets_recipient_parameter = lts_rec_parameter ).

ELSE.

if_fdt_actn_email~get_parameters(

IMPORTING ets_message_parameter = lts_msg_parameter

ets_recipient_parameter = lts_rec_parameter ).

ENDIF.

LOOP AT lts_msg_parameter INTO ls_parameter WHERE parameter_id IS NOT INITIAL.

CLEAR lv_obj_type.

cl_fdt_admin_data=>check_id( EXPORTING iv_id = ls_parameter-parameter_id

IMPORTING ev_object_type = lv_obj_type ).

Page 45: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

45

IF lv_obj_type EQ if_fdt_constants=>gc_object_type_expression.

INSERT ls_parameter-parameter_id INTO TABLE rts_expression_id.

ENDIF.

ENDLOOP.

LOOP AT lts_rec_parameter INTO ls_parameter WHERE parameter_id IS NOT INITIAL.

CLEAR lv_obj_type.

cl_fdt_factory=>get_id_information(

EXPORTING iv_id = ls_parameter-parameter_id

IMPORTING ev_object_type = lv_obj_type ).

IF lv_obj_type EQ if_fdt_constants=>gc_object_type_expression.

INSERT ls_parameter-parameter_id INTO TABLE rts_expression_id.

ENDIF.

ENDLOOP.

8.2.2 GET_DSM_AVAILABILITY

The purpose of this method is to define the release from which you want to start supporting your own expression type or action types. Specify the start release you want in the returning parameter.

When you want your defined expression type or action type to be available from SAP_BASIS 7.02, enter 702

in the field for the returning parameter. All managed systems with an SAP NetWeaver release equal to or greater than 7.02 will support your expression type.

METHOD if_fdt_expression~get_dsm_availability.

rv_start_release = 702.

ENDMETHOD.

Caution

For your defined expression type or action types, you need a working implementation for the generation mode with no switch to interpretation mode.

You define a start release, and all higher releases must support your expression types or action types. You cannot define gaps for releases that do not support your defined expression types or action types.

As owner of your defined expression types or action types you are responsible for ensuring that the generated code works correctly in the managed system and does not contain syntax errors.

Note

Relevant for SAP NetWeaver Decision Service Management only.

You must retrieve metadata such as database tables from the managed system, not your local system.

Review CL_FDT_TYPEDESCR to implement the retrieval of metadata. Focus on the uses of the class and sub-classes in the standard expression types and action types such as CL_FDT_ACTN_MESSAGE_LOG.

8.2.3 GET_CONTEXT_DATA_OBJECTS

The purpose of this method is to return all UUIDs of data objects which are used by this object. In the example of the email action, only the parameters hold UUIDs, which could be data objects or expressions.

Page 46: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

46

DATA: lv_obj_type TYPE if_fdt_types=>object_type,

lts_msg_parameter TYPE if_fdt_actn_email=>ts_parameter,

lts_rec_parameter TYPE if_fdt_actn_email=>ts_parameter,

ls_parameter TYPE if_fdt_actn_email=>s_parameter.

IF iv_timestamp IS SUPPLIED.

rts_object_id = super->if_fdt_expression~get_context_data_objects(

iv_timestamp = iv_timestamp

iv_deep = iv_deep

iv_used = iv_used ).

ELSE.

rts_object_id = super->if_fdt_expression~get_context_data_objects(

iv_deep = iv_deep

iv_used = iv_used ).

ENDIF.

* ------------------------------------------------------

CHECK iv_used = abap_true.

IF iv_timestamp IS SUPPLIED.

if_fdt_actn_email~get_parameters(

EXPORTING iv_timestamp = iv_timestamp

IMPORTING ets_message_parameter = lts_msg_parameter

ets_recipient_parameter = lts_rec_parameter ).

ELSE.

if_fdt_actn_email~get_parameters(

IMPORTING ets_message_parameter = lts_msg_parameter

ets_recipient_parameter = lts_rec_parameter ).

ENDIF.

LOOP AT lts_msg_parameter INTO ls_parameter.

CHECK ls_parameter-parameter_id IS NOT INITIAL.

CLEAR lv_obj_type.

cl_fdt_admin_data=>check_id( EXPORTING iv_id = ls_parameter-parameter_id

IMPORTING ev_object_type = lv_obj_type ).

IF lv_obj_type EQ if_fdt_constants=>gc_object_type_data_object.

INSERT ls_parameter-parameter_id INTO TABLE rts_object_id.

ENDIF.

ENDLOOP.

LOOP AT lts_rec_parameter INTO ls_parameter.

CHECK ls_parameter-parameter_id IS NOT INITIAL.

CLEAR lv_obj_type.

cl_fdt_admin_data=>check_id( EXPORTING iv_id = ls_parameter-parameter_id

IMPORTING ev_object_type = lv_obj_type ).

IF lv_obj_type EQ if_fdt_constants=>gc_object_type_data_object.

INSERT ls_parameter-parameter_id INTO TABLE rts_object_id.

ENDIF.

ENDLOOP.

8.3 Interface IF_FDT_ADMIN_DATA 8.3.1 TO_STRING

This method returns a string that describes the object. The result of the TO_STRING method should give you a basic idea about what the object is. This method is needed for unnamed objects. When a name is available, it appears, but this does not apply to the TO_STRING output.

The result of TO_STRING for a constant expression with a value returns the value of the constant.

The result of TO_STRING for a case expression gives you a basic idea about the results for different test parameter values.

There are two modes for the TO_STRING (see constants IF_FDT_CONSTANTS => GC_TO_STRING*).

Page 47: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

47

Mode Description

Brief The result is a brief representation of the object. It does not return additional details such as the name of the object. This is the default mode.

Complete The result of the method is the complete description of the object with details such as object name.

If there is no valid information provided, you can return a default string such as “Action Type ...”. Review and debug the code in other action types and expression types for examples.

Add the following piece of code at the end of the method to truncate the string to the maximum length.

CONDENSE rv_string.

* Truncate the description string length to the max

* length allowed if applicable.

IF iv_max_length LE strlen( rv_string ).

truncate_string( EXPORTING iv_max_length = iv_max_length

CHANGING cv_string = rv_string ).

ENDIF.

8.4 Interface IF_FDT_DATA_EXCHANGE_INTERNAL

You need to implement two methods:

EXPORT_XML

IMPORT_XML

Page 48: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

48

9 Check Methods

CHECK

This method is called to check the object. A successful check is required to activate an object. The result of the method is a list of information, warnings, or error messages.

It is important to understand the meaning of the importing parameter IV_ACTIVATION_CHECK. When set to ABAP_TRUE the check has to be performed as an activation check; the active versions of the referenced objects must be included within the check, (for example, a case expression that has a result data object). The result data object may be numeric in its active version and Boolean in its inactive version, which is the latest state of the object. To activate the result data object used, it must be Boolean, or an error message is returned.

Usually, this method is implemented to reuse the specific check methods used in the SET methods. Detailed checks are performed such as validation of the email addresses supplied or UUIDs used. In this example, the code of the check method looks as follows:

DATA: ls_msg TYPE if_fdt_types=>s_message,

lt_msg TYPE if_fdt_types=>t_message,

lt_recipient TYPE if_fdt_actn_email=>t_recipient,

lv_body TYPE if_fdt_actn_email=>body,

lv_subject TYPE if_fdt_actn_email=>subject,

lts_rec_param TYPE if_fdt_actn_email=>ts_parameter,

ls_rec_param TYPE if_fdt_actn_email=>s_parameter,

lts_msg_param TYPE if_fdt_actn_email=>ts_parameter,

ls_msg_param TYPE if_fdt_actn_email=>s_parameter.

rt_message = super->check( iv_activation_check ).

* IV_ACTIVATION_CHECK set to true means that the active version of used

* objects has to be included into the check.

* IV_ACTIVATION_CHECK set to false means that the latest version of used

* objects has to be included into the check.

lt_recipient = if_fdt_actn_email~get_recipients( ).

lv_subject = if_fdt_actn_email~get_subject( ).

lv_body = if_fdt_actn_email~get_body( ).

if_fdt_actn_email~get_parameters( IMPORTING ets_message_parameter = lts_msg_param

ets_recipient_parameter = lts_rec_param ).

* No initial parameter ids in the param tables

LOOP AT lts_msg_param INTO ls_msg_param WHERE parameter_id IS INITIAL.

MESSAGE e321(fdt_expressions) WITH 'message body'(005) ls_msg_param-

position INTO ls_msg-text.

append_message ls_msg rt_message.

ENDLOOP.

LOOP AT lts_rec_param INTO ls_rec_param WHERE parameter_id IS INITIAL.

MESSAGE e321(fdt_expressions) WITH 'recipients'(006) ls_rec_param-

position INTO ls_msg-text.

append_message ls_msg rt_message.

ENDLOOP.

* body and subject both must not be initial.

IF lv_body IS INITIAL AND lv_subject IS INITIAL.

MESSAGE e311(fdt_expressions) INTO ls_msg-text.

append_message ls_msg rt_message.

ENDIF.

Page 49: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

49

lt_msg = CHECK_RECIPIENTS( it_recipient = lt_recipient

its_parameter = lts_rec_param

iv_activation_check = abap_true ).

INSERT LINES OF lt_msg INTO TABLE rt_message.

lt_msg = CHECK_PARAMETERS( iv_subject = lv_subject

iv_body = lv_body

its_rec_param = lts_rec_param

its_msg_param = lts_msg_param

iv_activation_check = abap_true ).

INSERT LINES OF lt_msg INTO TABLE rt_message.

See class CL_FDT_ACTN_EMAIL for the check methods:

CHECK_RECIPIENTS

CHECK_PARAMETERS

Page 50: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

50

10 Process Methods

PROCESS

This method is the heart of the expression type since it defines its expressiveness, that is, what you can do with it as an end user.

In BRFplus we have two different modes for processing a service:

1. Interpretation

Interpretation mode is used for test purposes or when generation mode is not available. It is slower than generation mode, but it works in all cases without preparation.

2. Generation

Generation mode is a performance-optimized way to process the service. A class is generated that represents the service. The generation can take time, but this can be done beforehand and the processing is not affected.

The method IF_FDT_EXPRESSION~PROCESS has to be redefined to enable the processing. The following table describes all parameters available for processing.

Parameter Description

IO_CONTEXT Context object

IV_TIMESTAMP Processing timestamp for the definitions to take

IO_PROCESSOR Processor instance to resolve nested objects

IO_TRACE Technical trace object

RO_RESULT Result object

CX_FDT Exception handling

In this method, the definitions of the object for the supplied timestamp (IV_TIMESTAMP) use the given context (IO_CONTEXT) to produce a result (RO_RESULT). When a trace is requested (IO_TRACE) execution steps have to be logged in the trace. When the object uses other objects (for example, use of variables in an email body), those objects can be processes with help of the processor (IO_PRCESSOR).

The PROCESS method in the action type email consists of several steps.

DATA: lo_message TYPE REF TO cl_bcs_message,

lx_bcs TYPE REF TO cx_bcs,

lr_data TYPE REF TO data,

lv_id TYPE if_fdt_types=>id,

ls_buffer TYPE s_buffer,

lv_value TYPE string,

lv_main_doc TYPE string,

lv_param TYPE string,

lt_message TYPE if_fdt_types=>t_message,

ls_message TYPE if_fdt_types=>s_message,

ls_parameter TYPE if_fdt_actn_email=>s_parameter,

lv_rec_trace TYPE string,

lo_do_type TYPE if_fdt_types=>data_object_type,

lo_typedescr TYPE REF TO cl_abap_typedescr.

DATA: lv_msg_1 TYPE string,

lv_msg_2 TYPE string,

Page 51: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

51

lv_msg_3 TYPE string,

lv_msg_4 TYPE string.

FIELD-SYMBOLS: <lv_string> TYPE string,

<lv_value> TYPE any,

<la_data> TYPE any,

<lt_data> TYPE ANY TABLE,

<ls_recipient> TYPE LINE OF s_buffer-t_recipient.

First the definitions have to be loaded for the provided timestamp.

ls_buffer = load_buffer( iv_timestamp = iv_timestamp ).

With help of method GET_VALUE, you can resolve UUIDs used in the definitions of the object. The email action type, for example, may use variable returned by other expressions or contained in the context.

LOOP AT ls_buffer-ts_message_parameter INTO ls_parameter.

CONCATENATE '&' ls_parameter-position INTO lv_param.

get_value( EXPORTING iv_id = ls_parameter-parameter_id

io_context = io_context

iv_timestamp = iv_timestamp

io_processor = io_processor

IMPORTING er_value = lr_data ).

ASSIGN lr_data->* TO <la_data>.

lv_value = get_string_from_data( <la_data> ).

REPLACE ALL OCCURRENCES OF lv_param IN ls_buffer-subject WITH lv_value.

REPLACE ALL OCCURRENCES OF lv_param IN ls_buffer-body WITH lv_value.

ENDLOOP.

REPLACE ALL OCCURRENCES OF '\&&' IN ls_buffer-subject WITH '&&'.

REPLACE ALL OCCURRENCES OF '\&&' IN ls_buffer-body WITH '&&'.

Now everything is ready to send the email.

TRY.

CREATE OBJECT lo_message.

lo_message->set_subject( ls_buffer-subject ).

lv_main_doc = ls_buffer-body.

lo_message->set_main_doc( lv_main_doc ).

LOOP AT ls_buffer-t_recipient ASSIGNING <ls_recipient>.

lo_message->add_recipient( <ls_recipient> ).

IF lv_rec_trace IS NOT INITIAL .

CONCATENATE lv_rec_trace <ls_recipient> INTO lv_rec_trace SEPARATED BY ';'.

ELSE.

MOVE <ls_recipient> TO lv_rec_trace.

ENDIF.

ENDLOOP.

LOOP AT ls_buffer-ts_rec_parameter INTO ls_parameter.

get_value( EXPORTING iv_id = ls_parameter-parameter_id

io_context = io_context

iv_timestamp = iv_timestamp

io_processor = io_processor

IMPORTING er_value = lr_data ).

cl_fdt_expression=>get_type( EXPORTING iv_id = ls_parameter-parameter_id

IMPORTING ev_data_object_type = lo_do_type ).

IF lo_do_type EQ if_fdt_constants=>gc_data_object_type_element.

ASSIGN lr_data->* TO <la_data>.

lv_value = get_string_from_data( <la_data> ).

lt_message = check_recipients( iv_recipient = lv_value ).

IF cl_fdt_services=>contains_eax_message( lt_message ) EQ abap_false.

Page 52: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

52

lo_message->add_recipient( lv_value ).

IF lv_rec_trace IS NOT INITIAL .

CONCATENATE lv_rec_trace lv_value INTO lv_rec_trace SEPARATED BY ';'.

ELSE.

MOVE lv_value TO lv_rec_trace.

ENDIF.

ELSE.

write_trace_info_1 '222' lv_value lv_id.

ENDIF.

CLEAR lt_message.

ELSE.

ASSIGN lr_data->* TO <lt_data>.

LOOP AT <lt_data> ASSIGNING <lv_value>.

lo_typedescr = cl_abap_typedescr=>describe_by_data( <lv_value> ).

IF lo_typedescr->kind EQ cl_abap_typedescr=>kind_struct.

ASSIGN COMPONENT 1 OF STRUCTURE <lv_value> TO <lv_string>.

ELSEIF lo_typedescr->kind EQ cl_abap_typedescr=>kind_elem.

ASSIGN <lv_value> TO <lv_string>.

ENDIF.

lt_message = check_recipients( iv_recipient = <lv_string> ).

IF cl_fdt_services=>contains_eax_message( lt_message ) EQ abap_false.

lo_message->add_recipient( <lv_string> ).

ELSE.

write_trace_info_1 '222' <lv_string> lv_id.

ENDIF.

CLEAR lt_message.

ENDLOOP.

ENDIF.

ENDLOOP.

"lo_message->set_update_task( abap_true ).

IF cl_fdt_function_gen_process=>gv_action_in_update_task EQ abap_true.

lo_message->set_update_task( abap_true ).

ENDIF.

lo_message->send( ).

" Record Trace with the detail of recipient. <PD>

split_recipient_string(

EXPORTING iv_string = lv_rec_trace

IMPORTING ev_msg_1 = lv_msg_1

ev_msg_2 = lv_msg_2

ev_msg_3 = lv_msg_3

ev_msg_4 = lv_msg_4 ).

write_trace_info_4 '221' lv_msg_1 space lv_msg_2 space lv_msg_3 space

lv_msg_4 space.

In case of an exception, convert it into exception type CX_FDT_PROCESSING.

CATCH cx_bcs INTO lx_bcs.

MESSAGE e315(fdt_expressions) INTO ls_message-text.

append_message ls_message lt_message.

RAISE EXCEPTION TYPE cx_fdt_processing

EXPORTING

previous = lx_bcs

mt_message = lt_message.

ENDTRY.

Finally, write the result and process the follow up actions. Actions write their UUIDs as a result. In this case you can copy the following lines. Expressions write values defined with data objects. You may check the

Page 53: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

53

processing methods of expression type classes such as CL_FDT_CASE or CL_FDT_RANGE to learn more about this.

ro_result = create_and_set_result( iv_timestamp = iv_timestamp ).

process_followup_actions( io_context = io_context

iv_timestamp = iv_timestamp

io_processor = io_processor

io_result = ro_result ).

Page 54: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

54

11 Methods for Code Generation

11.1 IS_GENERATING For every expression type the method IF_FDT_EXPRESSION~IS_GENERATING has to be implemented.

If the expression type supports generation, the implementation looks as follows:

rv_generating = abap_false.

11.2 GENERATE_PROCESS The generation of an expression (method IF_FDT_EXPRESSION~GENERATE_PROCESS) is only

performed if the method IF_FDT_EXPRESSION~IS_GENERATING returns abap_true. To implement the

generation of an expression, the environment of code generation of BRFplus functions must be understood.

The coding is generated for a complete function. The coding for the complete function [all the used expressions (except the function call expression) and the assigned rulesets] is included in one generated class. In a specific time period, where the function and all used objects (including rulesets) did not change, two generated classes may exist. One class is for processing without lean trace and one with lean trace. The generation occurs when the function is processed and no generation is available for the requested timestamp and lean trace usage. (The generation can be started via tool report).

The generation of a function is started by the BRFplus function object. Each BRFplus object is responsible for the generation of its own functionality. An object using other objects delegates the generation of the respective sub-object. During generation of an expression, it is not determined if the coding is included into the surrounding coding of the parent object or if it will be placed in its own method. Therefore, the generation of each object has to follow some rules so that each code piece can coexist with other code pieces in one method. The coding for an entire function is composed by combining the coding snippets for each used expression into one class (usually into one method). In this case, you must ensure that the variable names for helper variables are unique for the complete generated method. To ensure this, the following technique must be used:

To ensure a unique variable name for each generated data, the declaration method CL_FDT_EXPR_SERVICES=>GEN_GET_NEXT_VARIABLE_NAME is called. This method uses the input string to find a variable name, which is derived from the name and is unique in the generated class (if the string was not used before the string is returned, a number is added which makes the string unique). If the ID of the object is passed for which the helper variable is used, a check is made to determine whether the object is a constant expression. If it is, a check runs to see if a variable for the constant was declared before; if it was, this variable name is returned. Variables for constant expressions are defined as class constants.

At some places a generation manager object is needed. When the method IF_FDT_EXPRESSION~GENERATE_PROCESS of your expression is called an instance of the generation manager is present as an importing parameter and you pass it to the desired parameter list.

If you want to use the lean trace feature your generated coding needs to support this. Respective IF statements in your coding are necessary to distinguish between the coding generated for processing with or without the lean trace feature. The generation infrastructure ensures basic information is added to the trace (such as result) without any expression type or action type specific code. We recommend avoiding trace-specific code in custom action types and expression types.

Page 55: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

55

Code Generation Techniques

Several techniques exist to generate the coding:

1. You can concatenate each line from strings and variable content and append the line into the coding table.

2. You can use a generation template and manipulate it with your own generation tool to obtain the required coding.

3. A tool called code-composer can be used. In BRFplus, there are few places where the code composer is used. You will see more usages of it in older releases (SAP NW 701 and lower).

Recommendation

We recommend using the first technique. This is the one used in the current BRFplus code generation.

We discourage using the code composer (CL_CMP_COMPOSER) based on performance.

The following methods from the BRFplus standard can be used during code generation.

11.2.1 IF_FDT_DATA_OBJECT->GENERATE_CREATE_DATA_REF

This method creates a data statement for a BRFplus data object. It can be used with data objects of type element, structure or table.

Explanation of the parameters:

Parameter Description

IV_VARIABLE_NAME Data object name used in generated coding

IV_TIMESTAMP Generation timestamp

IO_GENERATION_MNGR Generation manager instance

ET_SOURCE_CODE Generated coding

Code Example

Data definition for mail body

lo_mail_body_do->generate_create_data_ref(

EXPORTING iv_variable_name = lv_mail_body_name

iv_timestamp = lv_timestamp

io_generation_mngr = io_generation_mngr

IMPORTING et_source_code = lt_data_def_code ).

APPEND LINES OF lt_data_def_code TO et_source_code.

11.2.2 IF_FDT_DATA_OBJECT=>GENERATE_CONVERT_TO

Page 56: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

56

This method generates coding to convert the data from one data object to another data object. It can be used with data objects of type element, structure, or table.

Explanation of the parameters:

Parameter Description

IV_VARIABLE_NAME_SOURCE Source data object name used in generated coding

IO_TARGET_DATA_OBJECT Target data object instance

IV_VARIABLE_NAME_TARGET Target data object name used in generated coding

IV_TIMESTAMP Generation timestamp

IO_GENERATION_MNGR Generation manager instance

ET_SOURCE_CODE Generated coding

Code Example

Conversion from temporary result to result:

lo_tmp_result_do->generate_convert_to(

EXPORTING iv_variable_name_source = lv_tmp_result_name

io_target_data_object = lo_result_do

iv_variable_name_target = lv_result_do_name

iv_timestamp = lv_timestamp

io_generation_mngr = io_generation_mngr

IMPORTING et_source_code = lt_conv_code ).

APPEND LINES OF lt_conv_code TO et_source_code.

11.2.3 CL_FDT_EXPR_SERVICES=> GENERATE_MOVE_FROM_EXTERNAL

This method generates the coding to move data from an external format (for example, DDIC) to BRFplus format. The external format can be BRFplus.

Explanation of the parameters:

Parameter Description

IV_DOBJ_ID BRFplus data object ID

IV_SOURCE_NAME Source data object name used in generated coding

IV_TARGET_NAME Target data object name used in generated coding

IV_TIMESTAMP Generation timestamp

IV_USE_DOBJ_NAME_S Use source data object name (optional)

IV_USE_DOBJ_NAME_T Use target data object name (optional)

IV_SOURCE_DDIC_NAME Source DDIC name (optional)

ITS_ID_NAME ID name mapping (optional)

ET_SOURCE_CODE Generated coding

Page 57: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

57

Code Example

Move from data of an exporting parameter after a static method call:

Cl_fdt_expr_services=>generate_move_from_external(

EXPORTING iv_dobj_id = lv_dobj_id

iv_source_name = iv_source_do_name

iv_target_name = iv_target_do_name

iv_timestamp = lv_timestamp

IMPORTING et_source_code = lt_move_code ).

APPEND LINES OF lt_move_code TO et_source_code.

11.2.4 CL_FDT_EXPR_SERVICES=> GENERATE_MOVE_TO_EXTERNAL

This method generates the coding to move data from BRFplus to an external format. The external format can be BRFplus.

Explanation of the parameters:

Parameter Description

IV_DOBJ_ID BRFplus data object ID

IV_SOURCE_NAME Source data object name used in generated coding

IV_TARGET_NAME Target data object name used in generated coding

IV_TIMESTAMP Generation timestamp

IV_TARGET_DDIC_NAME Target DDIC name (optional)

IV_USE_DOBJ_NAME Use source data object name (optional)

IV_USE_DNAME_IN_TGT Use target data object name (optional)

ITS_ID_NAME ID name mapping (optional)

ET_SOURCE_CODE Generated coding

Code Example

Move from data of an importing parameter after a static method call:

Cl_fdt_expr_services=>generate_move_to_external(

EXPORTING iv_dobj_id = lv_dobj_id

iv_source_name = iv_source_do_name

iv_target_name = iv_target_do_name

iv_timestamp = lv_timestamp

IMPORTING et_source_code = lt_move_code ).

APPEND LINES OF lt_move_code TO et_source_code.

Page 58: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

58

11.2.5 CL_FDT_EXPR_SERVICES=> GENERATE_GET_CONTEXT_NAME

This method returns the variable name for a context object.

Explanation of the parameters:

Parameter Description

IV_ID BRFplus data object ID (should be present in the context )

EV_NAME Data object name

EV_UNKNOWN True: Context object is not known

Code Example

Get the context name for a recipient:

Cl_fdt_expr_services=>generate_get_context_name(

EXPORTING iv_id = lv_recipient_id

IMPORTING ev_name = lv_recipient_name

ev_unknown = lv_unknown ).

11.2.6 CL_FDT_EXPR_SERVICES=> GEN_GET_NEXT_VARIABLE_NAME

This method returns a unique name for a variable.

Explanation of the parameters:

Parameter Description

IV_DESIRED_NAME Desired variable name

RV_EFFECTIVE_NAME Actual created variable name

Code Example

Get the variable name for the email body and create the data declaration:

lv_body_name =

Cl_fdt_expr_services=>generate_get_context_name(iv_desired_name = ‘lv_body’ ).

lv_line = ` DATA ` && lv_body_name && ` TYPE string.`.

append lv_line to et_source_code.

Page 59: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

59

11.2.7 CL_FDT_EXPR_SERVICES=> GEN_GET_NAME_FOR_GENERATION

This method returns the common name for timestamp / trace object used in generation.

Explanation of the parameters:

Parameter Description

IV_SYMBOLIC_NAME Name of the particular object

Trace: GC_ATTR_NAME_TRACE_OBJ

Timestamp: GC_TIMESTAMP_PARA_NAME

RV_GENERATION _NAME Common name used in generation

Code Example

Get the trace object name to clear its work area:

lv_trace_name = Cl_fdt_expr_services=>gen_get_Name_for_generation

(iv_symbolic_name = ‘GC_ATTR_NAME_TRACE_OBJ’ ).

lv_line = ` CLEAR ` && lv_trace_name && `->ms_record-value.

append lv_line to et_source_code.

11.2.8 CL_FDT_EXPR_SERVICES=> GEN_GENERATE_TRACE

This method returns if the generation takes place with lean trace or without.

Explanation of the parameter:

Parameter Description

EV_GENERATE_TRACE TRUE: Generation with lean trace object

Code Example

Ensure generation occurs with the tracing option; clear the record work area:

Cl_fdt_expr_services=>gen_generate_trace(

IMPORTING ev_generate_trace = lv_trace_used )

IF lv_trace_used EQ ABAP_TRUE.

lv_trace_name = Cl_fdt_expr_services=>gen_get_Name_for_generation

(iv_symbolic_name = ‘GC_ATTR_NAME_TRACE_OBJ’ ).

lv_line = ` CLEAR ` && lv_trace_name && `->ms_record-value.

append lv_line to et_source_code.

ENDIF.

Page 60: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

60

11.2.9 CL_FDT_EXPR_SERVICES=>GENERATE_RANGE_PROCESS

This method generates the coding for a used implicit range.

Explanation of the parameters:

Parameter Description

IV_FUNCTION_ID Function ID

IV_EXPRESSION_ID Calling expression ID

IV_VARIABLE_NAME Variable name for the range result (optional)

IV_CREATE_VARIABLE Create a data declaration for the result

IV_TIMESTAMP Generation timestamp

IV_TEST_PARAMETER Test parameter ID

ITS_RANGE Range table

IV_CASE_SENSITIVITY TRUE: Generate case sensitive (optional)

IV_IS_SV_RANGE TRUE: Range is a simple value range (optional)

ET_SOURCE_CODE Generated source code

EV_DEEP_TRACED TRUE: Deep tracing took place

CTS_USED_CONTEXT_ID Table of used context IDs

Code Example

Implicit range for a condition inside an expression:

cl_fdt_expr_services=>generate_range_process(

EXPORTING iv_function_id = iv_function_id

iv_expression_id = mv_id

iv_variable_name = lv_cond_ok

iv_create_variable = abap_false

iv_timestamp = lv_timestamp

iv_test_parameter = <ls_cond>-s_param_range-parameter_id

its_range = <ls_cond>-s_param_range-ts_range

iv_is_sv_range = abap_true

IMPORTING et_source_code = lt_condition_code

CHANGING cts_used_context_id = cts_used_context_id ).

APPEND LINES OF lt_condition_code TO et_source_code.

11.2.10 CL_FDT_EXPR_SERVICES=> GENERATE_SIMPLE_VALUE_PROCESS

This method generates the coding for a direct value usage inside the expression.

Page 61: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

61

Explanation of the parameters:

Parameter Description

IV_VARIABLE_NAME Variable name where the direct value should be stored

IV_CREATE_VARIABLE Create a data declaration for the storage of the direct value (optional)

IS_VALUE Value

IV_TIMESTAMP Generation timestamp

ET_SOURCE_CODE Generated source code

EV_DIRECT_RESULT_NAME Generated class constant name

Code Example

Direct value for a default result inside an expression:

cl_fdt_expr_services=>generate_simple_value_process(

EXPORTING iv_variable_name = lv_def_res_name

iv_create_variable = abap_false

is_value = s_default_result_value

iv_timestamp = lv_timestamp

IMPORTING et_source_code = lt_def_res_code ). APPEND LINES OF lt_def_res_code TO et_source_code.

11.2.11 CL_FDT_EXPRESSION=>GENERATE_GET_VALUE

This method generates the coding for any subexpression or data object used in the expression.

Explanation of the parameters:

Parameter Description

IV_FUNCTION_ID Function ID

IV_ID (Sub)expression or data object ID

IV_VARIABLE_NAME Variable name of result from subexpression OR variable name for the data object

IV_CREATE_VARIABLE Create a data declaration for the result or the data object

IV_TIMESTAMP Generation timestamp

IO_GENERATION_MNGR Generation manager instance

IV_CALLING_EXPR_ID Expression ID (from the calling expression)

IV_TARGET_DO_ID Target data object (optional, triggers a convert_to)

IV_TARGET_ELEMENT_TYPE Target data object element type (optional)

ET_SOURCE_CODE Generated source code

EV_DIRECT_RESULT_NAME Generated class constant name

EV_DEEP_TRACED TRUE: Expression was deep traced

EV_CONTEXT_OR_CONST TRUE: IV_ID belongs to a constant or to a context ID

Page 62: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

62

CTS_USED_CONTEXT_ID Table of used context IDs

Code Example

Generate parameter code for an email parameter:

generate_get_value( EXPORTING iv_function_id = lv_function_id

iv_id = <ls_para>-parameter_id

iv_variable_name = lv_parm_var_name

iv_create_variable = abap_true

iv_timestamp = lv_timestamp

io_generation_mngr = io_generation_mngr

iv_calling_expr_id = mv_id

IMPORTING et_source_code = lt_parm_code

ev_direct_result_name = lv_direct_parm_name

CHANGING cts_used_context_id = cts_used_context_id ). APPEND LINES OF lt_parm_code TO et_source_code.

11.2.12 CL_FDT_EXPRESSION=> GENERATE_TRACE_SUB_EXPRESSION

This method generates the coding for tracing any subexpressions.

Explanation of the parameters:

Parameter Description

IV_POSITION Trace position

IV_POSITION_NAME Trace position name (optional)

IV_RESULT_NAME Name of result variable

IV_ID Subexpression ID

IV_PARENT_ID Expression ID

IV_WITH_VALUE TRUE: Export trace value to data buffer (optional)

IV_SKIP_TRUE TRUE: Skip all subexpressions with Boolean result, that evaluate to true during runtime (optional)

IV_SKIP_FALSE TRUE: Skip all subexpressions with Boolean result, that evaluate to false during runtime (optional)

IV_IS_SV_RANGE TRUE: Range is a simple value range (optional)

ET_SOURCE_CODE Generated source code

Code Example

Generate trace coding for an embedded procedure call:

IF io_generation_mngr->mv_trace_generation EQ abap_true.

lv_position = <Create a new unique name for this position. For already existing

position names check the attributes of class CL_FDT_TRACE>.

Page 63: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

63

generate_trace_sub_expression(

EXPORTING iv_position_name = lv_trace_position

iv_result_name = lv_result_name

iv_id = <ID of the Procedure Call Expression>

iv_parent_id = mv_id

iv_with_value = abap_true

IMPORTING et_source_code = lt_trace_code ).

APPEND LINES OF lt_trace_code TO et_source_code.

ev_deep_traced = abap_true.

ENDIF.

Note: lv_result_name is the variable, which stores during code generation the name of the variable, which contains in the generated code the result of the Procedure Call.

For more examples, check out the usages of CL_FDT_EXPRESSION=>GENERATE_TRACE_SUB_EXPRESSION in your system.

11.3 Tips for Generation

Recommendation

The names of variables you define need to be unique in the coding. Use method CL_FDT_EXPR_SERVICES=>GEN_GET_NEXT_VARIABLE_NAME to get the final variable name.

Your expression might be called in a loop. Therefore the variables you declared might have a value in the second loop passing. Clear variable if they are not set to a value.

If your expression allows calling other expressions or data objects, ensure the types of the data objects fit the data types you expect or convert the data object to the type you require. (Use method IF_FDT_DATA_OBJECT->GENERATE_CONVERT_TO.)

For reusable methods, see CL_FDT_SERVICES or CL_FDT_EXPR_SERVICES.

Additionally, you can look up package interfaces FDT and FDT_EXTENDED to access all released functionality.

11.4 Tools for supporting the generation development and maintenance

During implementation of this functionality it might be helpful to start the generation directly. You can do this using the report FDT_GENERATION_TOOL. Please check its documentation.

Page 64: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

64

12 Methods for Lean Trace Display

In CL_FDT_EXPRESSION=> GENERATE_TRACE_SUB_EXPRESSION, you created lean trace records for subexpressions used by your expression type. In Testing the Action Type or Expression Type, you will learn about testing your expression and how to save the lean trace. This chapter deals with some methods you can use to manipulate the appearance of your lean trace records in the BRFplus Workbench. You do not have to implement these methods. If you don’t, the lean trace records will be displayed in a standardized way as nodes of an expandible tree by the lean trace Web Dynpro component, FDT_WD_LEAN_TRACE. This component is included in the Show Trace functionality of the function in the BRFplus Workbench or in the Lean Trace Tool. However, if you want to display the lean trace nodes in a specific order or in a structured way, or if you want to extend the description for a particular node, you may create the following:

CHANGE_TRACE_NODE

CREATE_TRACE_CHILD_NODES

12.1 CHANGE_TRACE_NODE This method changes the name of the trace node after its default is set. The interface of the method must contain the following parameters:

Parameter Type Typing Method

Associated Type Description

IO_LEAN_TRACE_HELPER

Importing TYPE REF TO CL_FDT_WD_LEAN_ TRACE_HELPER

Reference to a Lean Trace Helper class

IV_TIMESTAMP Importing TYPE IF_FDT_TYPES=> TIMESTAMP

The execution timestamp of the trace IS_RECORD

IS_RECORD Importing TYPE IF_FDT_LEAN_TRACE=>S_RECORD

One particular record from the trace

CS_NODE Changing TYPE FDTS_WD_TRACE_ MODEL

The UI node created from IS_RECORD

An example for the implementation follows.

Note

You should only change the name of the trace node.

All other fields may be overwritten by the standard methods.

Code Example

METHOD CHANGE_TRACE_NODE.

DATA: lv_name TYPE string.

FIELD-SYMBOLS: <lv_bool> TYPE abap_bool.

Page 65: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

65

TRY.

“Change the name of the node

IF cs_node-value_valueref IS BOUND.

ASSIGN cs_node-value_valueref->* TO <lv_bool>.

IF <lv_bool> = abap_true.

MESSAGE i316(fdt_wd_tools) WITH cs_node-name INTO lv_name.

ELSE.

MESSAGE i317(fdt_wd_tools) WITH cs_node-name INTO lv_name.

ENDIF.

cs_node-name = lv_name.

ENDIF.

CATCH cx_sy_assign_error.

"Keep the node name as it is.

ENDTRY.

ENDMETHOD.

12.2 CREATE_TRACE_CHILD_NODES This method arranges the records traced within your expression in a certain manner. The interface of the method must contain the following parameters:

Parameter Type Typing Method

Associated Type Description

IO_LEAN_TRACE_ HELPER

Importing TYPE REF TO

CL_FDT_WD_LEAN_ TRACE_HELPER

Reference to a Lean Trace Helper class

IS_PARENT_NODE Importing TYPE FDTS_WD_TRACE_ MODEL

Parent node for the child nodes in the UI

ET_NODE Exporting TYPE CL_FDT_WD_LEAN_ TRACE_MODEL=> TS_TRACE_VALUE

Child nodes

CTS_RECORD Changing TYPE IF_FDT_LEAN_TRACE=>TS_RECORD

Records belonging to the parent node

The following example illustrates how to sort nodes and extend their default names.

Note

To create a node, use IO_LEAN_TRACE_HELPER->create_node(…). It contains all relevant fields by default.

To nest nodes, create a node and use it as parent node of another node.

To create nodes without a reference to a record, use the CREATE_NODE( ..) method. To do so, use the IV_NAME attribute instead of IS_RECORD.

Delete all records you have treated in this method from CTS_RECORD.

Code Example

METHOD CREATE_TRACE_CHILD_NODES.

Page 66: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

66

DATA: ls_node TYPE fdts_wd_trace_model,

lt_record TYPE STANDARD TABLE OF if_fdt_lean_trace=>s_record,

lr_record TYPE REF TO if_fdt_lean_trace=>s_record,

lv_name TYPE string,

lv_poscode TYPE string,

lv_token_number TYPE string.

* Operands may not be sorted

LOOP AT cts_record REFERENCE INTO lr_record WHERE

position CS cl_fdt_trace=>gc_poscode_token.

APPEND lr_record->* TO lt_record.

ENDLOOP.

SORT lt_record BY position.

“Sort the table of records in a particular way

* Create nodes and enrich their names

LOOP AT lt_record REFERENCE INTO lr_record.

CLEAR: ls_node.

“Invoke the standard method for node creation

IO_LEAN_TRACE_HELPER->create_node( EXPORTING is_parent_node = is_parent_node

is_record = lr_record->*

IMPORTING es_node = ls_node ).

“Extend the default node name

SPLIT lr_record->position AT gc_separator INTO lv_poscode lv_token_number.

MESSAGE i325(fdt_wd_tools) WITH lv_token_number ls_node-name INTO lv_name.

ls_node-name = lv_name.

APPEND ls_node TO et_node.

“Append new node to exporting table of nodes

DELETE TABLE cts_record FROM lr_record->*.

“Delete the records you have already dealt with

ENDLOOP.

ENDMETHOD.

Page 67: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

67

13 Data Exchange This section explains the methods and the procedure to allow user defined expression types to participate in FDT XML Export / Import for the custom action email.

13.1 EXPORT_XML This method exports the objects in XML format, reads the value from the database using GET methods, and sets it in the XML.

DATA: lv_body TYPE if_fdt_actn_email=>body, lt_recpt TYPE if_fdt_actn_email=>t_recipient,

lv_subject TYPE if_fdt_actn_email=>subject,

lts_msg_parameter TYPE if_fdt_actn_email=>ts_parameter,

lts_rec_parameter TYPE if_fdt_actn_email=>ts_parameter.

super->if_fdt_data_exchange_internal~export_xml( iv_timestamp = iv_timestamp

io_parent = io_parent ).

* Add the Email Recipient Information to xml document.

lt_recpt = if_fdt_actn_email~get_recipients( iv_timestamp ).

convert_abap_to_xml(

io_parent = io_parent

iv_name = 'RECIPIENTS'

iv_namespace_prefix = if_fdt_data_exchange=>gc_xml_namespace_prefix

ia_abap = lt_recpt ).

* Add the Email Body Information to xml document.

lv_body = if_fdt_actn_email~get_body( iv_timestamp ).

convert_abap_to_xml(

io_parent = io_parent

iv_name = 'BODY'

iv_namespace_prefix = if_fdt_data_exchange=>gc_xml_namespace_prefix

ia_abap = lv_body ).

* … and so on for the rest

ENDMETHOD.

There might be elements inside your buffer that are optional. For example, in the case expression, the user can put a simple value as test parameter or an ID that could be a constant. Therefore, within the buffer there will be the simple test value or the ID field filled, but not both. Both XML elements are optional.

In this case, you should put an, “IF… is initial”, statement around the method CONVERT_ABAP_TO_XML.

You will see how to define optional XML elements within your DTD (Implementation of method GET_DTD).

Recommendation

You can shrink the lines of code needed for this method if you make use of a macro such as the following:

DEFINE export_xml.

convert_abap_to_xml( io_parent = io_parent

iv_name = &1

iv_namespace_prefix = gc_my_namespace_prefix

ia_abap = &2 ).

END-OF-DEFINITION.

Page 68: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

68

This might be useful when you have many objects inside your buffer. You would only have to use the following:

export_xml: 'RECIPIENTS' ls_buffer-t_recipient,

'BODY' ls_buffer-body,

'SUBJECT' ls_buffer-subject,

...

You should use your own namespace for the XML elements, as this will prevent possible errors due to

double definition. It is useful to define a global constant (see gc_my_namespace in the previous coding) that

contains your namespace prefix. You can choose whatever you want for a namespace prefix, (for example,

CUST_EXTY1). You have to pass this namespace with exporting parameter es_namespace:

es_namespace-prefix = gc_my_namespace_prefix.

es_namespace-uri = if_fdt_data_exchange=>gc_xml_namespace_uri.

For the namespace URI, you can use the default BRFplus namespace URI.

13.2 IMPORT_XML This method reads the XML file and imports the objects from XML. It reads the value from XML and sets the database using SET methods. After you set one XML object to ABAP, you must raise the event

if_fdt_data_exchange_internal~object_id_as_attribute with the corresponding ID as export

parameter iv_id. You don’t have to do this, when importing objects without an ID (for example, a simple

value of type cl_fdt_expr_sv=>s_value).

DATA: lv_no_element TYPE abap_bool,

ls_msg_parameter TYPE if_fdt_actn_email=>s_parameter,

ls_rec_parameter TYPE if_fdt_actn_email=>s_parameter,

ls_buffer TYPE s_buffer.

super->if_fdt_data_exchange_internal~import_xml( io_parent ).

* Import the Email Body from XML

convert_xml_to_abap( EXPORTING io_parent = io_parent

iv_name = 'BODY'

iv_namespace_prefix = gc_my_namespace_prefix

IMPORTING ea_abap = ls_buffer-body

ev_no_element = lv_no_element ).

IF lv_no_element EQ abap_true.

ls_msg-msgv1 = cx_fdt=>get_object_description( mv_id ).

* Message: No &1 supplied for &2

MESSAGE x302(fdt_core) WITH 'BODY' ls_msg-msgv1 INTO ls_msg-text.

message_exception ls_msg lt_msg cx_fdt_input.

ENDIF.

* Import the Email Recipients from XML

convert_xml_to_abap( EXPORTING io_parent = io_parent

iv_name = 'RECIPIENTS'

iv_namespace_prefix = gc_my_namespace_prefix

IMPORTING ea_abap = ls_buffer-t_recipient

ev_no_element = lv_no_element ).

IF lv_no_element EQ abap_true.

ls_msg-msgv1 = cx_fdt=>get_object_description( mv_id ).

* Message: No &1 supplied for &2

MESSAGE x302(fdt_core) WITH 'RECIPIENTS' ls_msg-msgv1 INTO ls_msg-text.

message_exception ls_msg lt_msg cx_fdt_input.

Page 69: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

69

ENDIF.

* Import the Email Subject from XML

convert_xml_to_abap( EXPORTING io_parent = io_parent

iv_name = 'SUBJECT'

iv_namespace_prefix = gc_my_namespace_prefix

IMPORTING ea_abap = ls_buffer-subject

ev_no_element = lv_no_element ).

IF lv_no_element EQ abap_true.

ls_msg-msgv1 = cx_fdt=>get_object_description( mv_id ).

* Message: No &1 supplied for &2

MESSAGE x302(fdt_core) WITH 'SUBJECT' ls_msg-msgv1 INTO ls_msg-text.

message_exception ls_msg lt_msg cx_fdt_input.

ENDIF.

* Set the paramters

convert_xml_to_abap( EXPORTING io_parent = io_parent

iv_name = 'MESSAGE_PARAMETERS'

iv_namespace_prefix = gc_my_namespace_prefix

IMPORTING ea_abap = ls_buffer-ts_message_parameter

ev_no_element = lv_no_element ).

IF lv_no_element EQ abap_true.

ls_msg-msgv1 = cx_fdt=>get_object_description( mv_id ).

* Message: No &1 supplied for &2

MESSAGE x302(fdt_core) WITH 'MESSAGE_PARAMETERS' ls_msg-msgv1 INTO ls_msg-text.

message_exception ls_msg lt_msg cx_fdt_input.

ENDIF.

convert_xml_to_abap( EXPORTING io_parent = io_parent

iv_name = 'RECIPIENT_PARAMETERS'

iv_namespace_prefix = gc_my_namespace_prefix

IMPORTING ea_abap = ls_buffer-ts_rec_parameter

ev_no_element = lv_no_element ).

IF lv_no_element EQ abap_true.

ls_msg-msgv1 = cx_fdt=>get_object_description( mv_id ).

* Message: No &1 supplied for &2

MESSAGE x302(fdt_core) WITH 'RECIPIENT_PARAMETERS' ls_msg-msgv1 INTO ls_msg-text.

message_exception ls_msg lt_msg cx_fdt_input.

ENDIF.

* Import the IDs first.

LOOP AT ls_buffer-ts_message_parameter INTO ls_msg_parameter.

RAISE EVENT if_fdt_data_exchange_internal~object_id_as_attribute

EXPORTING iv_id = ls_msg_parameter-parameter_id.

ENDLOOP.

LOOP AT ls_buffer-ts_rec_parameter INTO ls_rec_parameter.

RAISE EVENT if_fdt_data_exchange_internal~object_id_as_attribute

EXPORTING iv_id = ls_rec_parameter-parameter_id.

ENDLOOP.

set_buffer( is_buffer = ls_buffer ).

notify_change( ).

ENDMETHOD.

You could make use of an appropriate macro here as well.

As shown in the previous code, you should implement corresponding exception handling after each element in case a mandatory XML element is not supplied within the XML.

Therefore, you can retrieve the parameter EV_NO_ELEMENT, which indicates the status of the element in

the XML ( abap_false ) or ( abap_true ).

You do not need this error handling in case of optional XML elements because their occurrence inside the XML is not mandatory.

Page 70: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

70

13.3 Implementation for User Defined Expression Types

This section enables user-defined expression types to participate in FDT XML export / import for the custom action email.

To participate in XML export / import, you need to create another class that implements the interface IF_FDT_DATA_EXCHANGE_EXTERNAL.

The following sections explain the methods in the interface that need to be re-defined.

13.3.1 GET_DTD

Since the implementation of method GET_DTD requires a deeper understanding of how a DTD has to be built, this chapter focuses on another example in which the different elements of DTD are detailed.

The purpose of this method is to define DTD for User Defined Expressions used for validating the XML during import. For BRFplus internal expression types and action types, the DTD is defined in the XSLT transformation, FDT_APPEND_INTERNAL_DTD. It might be useful to look at this transformation while developing method GET_DTD of your own expression type. You can see a simple expression type (CASE ) is defined. This might help you understand how to build the DTD for your expression type. The tricky part for a custom expression type is that you cannot update the BRFplus internal XSLT transformation to work with your expression type. You must create the DTD definition manually with coding. This task is completed by method GET_DTD.

Your expression type has two parameters with IDs, PARAMETER1 and “PARAMETER2; one simple value

(type CL_FDT_EXPR_SV=>S_VALUE) called SIMPLE_VALUE, and one table with multiple lines called

DEMO_TABLE. (The line type of this table is not important since it should be defined the same way as, for example, the structure SIMPLE_VALUE is defined). Concerning the BRFplus default XSLT transformation, you can figure out that the DTD has been defined as follows:

<!ELEMENT CUST_EXTY1:PARAMETER1 (#PCDATA)>

<!ELEMENT CUST_EXTY1:PARAMETER2 (#PCDATA)>

<!ELEMENT CUST_EXTY1:SIMPLE_VALUE (CUST_EXTY1:ELEMENT_TYPE?, CUST_EXTY1:VALUE?,

CUST_EXTY1:SUPPLEMENT?,

CUST_EXTY1:NONE_AP?)>

<!ELEMENT CUST_EXTY1:DEMO_TABLE (CUST_EXTY1:ITEM| CUST_EXTY1:item)*>

You can see how the structure of your XML is defined.

In the XML, there will be one XML element called PARAMETER1, which has its ID embedded. It has no deeper structure. Therefore the embedded data inside this XML element is defined as #PCDATA.

The same applies to PARAMETER2.

The simple value is different because the SIMPLE_VALUE XML element consists of several other XML elements since its type is CL_FDT_EXPR_SV=>S_VALUE.

These are as follows:

o ELEMENT_TYPE

o VALUE

o SUPPLEMENT

o NONE_AP

Page 71: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

71

The interrogation symbol (?) indicates that this element is optional in the XML. All sub-elements are separated by a comma, which simply means they occur in sequence.

The DEMO_TABLE is different since it has the same element embedded multiple times (in this case, ITEM). The structure of the ITEM XML element could be defined again, for example:

<!ELEMENT CUST_EXTY1:ITEM (CUST_EXTY1:ELEMENT_TYPE?, CUST_EXTY1:VALUE?,

CUST_EXTY1:SUPPLEMENT?, CUST_EXTY1:NONE_AP?)>

<!ELEMENT CUST_EXTY1:item (CUST_EXTY1:ELEMENT_TYPE?, CUST_EXTY1:VALUE?,

CUST_EXTY1:SUPPLEMENT?, CUST_EXTY1:NONE_AP?)>

You would have modeled a DTD for a table, DEMO_TABLE, with line type simple value. Remember that your elements consist of sub-elements that you must define.

<!ELEMENT CUST_EXTY1:ELEMENT_TYPE (#PCDATA)>

<!ELEMENT CUST_EXTY1:VALUE (#PCDATA)>

<!ELEMENT CUST_EXTY1:SUPPLEMENT (#PCDATA)>

<!ELEMENT CUST_EXTY1:NONE_AP (#PCDATA)>

If you compare the sub-XML elements of DEMO_TABLE to the ones in SIMPLE_VALUE, you will notice that they are not separated by a comma but by a |. The separator sign defines the grouping of the sub-elements, whereas the | defines a choice and the comma defines a sequence. Within the XML, the iterating sub-XML-element of DEMO_TABLE could be ITEM (upper case) or item (lower case).

The occurrence sign differs as well from SIMPLE_VALUE since it is a “*” meaning the element (either ITEM or item) can occur never, once, or multiple times inside XML element DEMO_TABLE.

As previously mentioned, you must create this definition manually with ABAP/4 code.

Method GET_DTD supplies two important objects in order to define the DTD, namely:

IO_CONTENT_PARTICLE Type ref to IF_IXML_CONTENT_PARTICLE

IO_DOC_TYPE Type ref to IF_IXML_DOCUMENT_TYPE

If you are looking at the structure of an element inside the transformation, it can be defined as embedded particles.

The outer particle is:

<!ELEMENT CUST_EXTY1:PARAMETER1

. . . >

It can be split into a left particle (the red one) and a right element description (the blue one). Initially, we will focus on the left particle.

The underlined elements of this particle are split into a prefix and a name. You can create this particle with the following code:

Page 72: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

72

DATA: lo_outer_cp TYPE REF TO if_ixml_content_particle.

lo_outer_cp = io_doc_type->create_content_particle( name = 'PARAMETER1'

prefix = cl_fdt_actn_email=>gc_my_namespace_prefix

grouping = if_ixml_content_particle=>co_sequence

occurrence = if_ixml_content_particle=>co_one ).

Recommendation

We use namespace to avoid ambiguity and also if you define the same element twice in XSLT,

then the complete validation fails. To avoid ambiguity, we recommend using customer-specific namespace.

.

The grouping and occurrence parameters will be explained later. For this first particle they should always be

co_sequence and co_one. After having created this particle, you have to add it as content to the main particle which you get as an import parameter:

io_content_particle->add_content_particle( content_particle = lo_outer_cp ).

This is all you have to do for the left particle. For the right particle, you have to create an element description object. You can do this with the following code:

DATA: lo_element_descr TYPE REF TO if_ixml_element_decl.

* Define the content of each XML element used

lo_element_descr = io_doc_type->create_element_decl(

name = 'PARAMETER1'

prefix = cl_fdt_actn_email=>gc_my_namespace_prefix ).

lo_element_descr->set_content_spec( content_spec

= if_ixml_element_decl=>co_mixed ).

lo_element_descr->set_grouping( grouping

= if_ixml_content_particle=>co_sequence ).

lo_element_descr->set_occurrence( occurs

= if_ixml_content_particle=>co_one ).

You must pass the correct name and prefix corresponding to your left particle.

First, you create the content for this object. The main particle embedded as element description is the surrounding brackets.

<!ELEMENT CUST_EXTY1:PARAMETER1 (#PCDATA)>

To achieve this, you have to create an empty particle and add it as content to the element description object.

DATA: lo_cp_brackets TYPE REF TO if_ixml_content_particle.

* -> create anonymous content (brackets-)particle: (...)

lo_cp_brackets = io_doc_type->create_content_particle(

name = ''

Page 73: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

73

grouping = if_ixml_content_particle=>co_sequence

occurrence = if_ixml_content_particle=>co_one ).

Now you can create the content particle that is embedded inside the brackets-particle for PARAMETER1.

DATA: lo_cp_element TYPE REF TO if_ixml_content_particle.

lo_cp_element = io_doc_type->create_content_particle(

name = '#PCDATA'

grouping = if_ixml_content_particle=>co_sequence

occurrence = if_ixml_content_particle=>co_one ).

Note

If you do not pass a “prefix” parameter the particle is created with its name (in this example, #PCDATA).

Now add LO_CP_ELEMENT as content to LO_CP_BRACKETS, which will be added as content to LO_ELEMENT_DESCR.

lo_cp_brackets->add_content_particle( content_particle = lo_cp_element ).

lo_element_descr->add_content_particle( content_particle = lo_cp_brackets ).

Now that you are finished with the element description (with #PCDATA embedded), you can proceed to add the element description as child to the IO_CONTENT_PARTICLE.

io_doc_type->append_child( new_child = lo_element_descr ).

If you look at the SIMPLE_VALUE, you must add not only one particle (#PCDATA) to the brackets-particle but actually four other particles. You have to set the grouping signs and occurrence signs appropriately.

For the XML element SIMPLE_VALUE, the coding is as follows:

lo_outer_cp = io_doc_type->create_content_particle(

name = 'SIMPLE_VALUE’

prefix = cl_fdt_actn_email=>gc_my_namespace_prefix

grouping = if_ixml_content_particle=>co_sequence

occurrence = if_ixml_content_particle=>co_one ).

io_content_particle->add_content_particle( content_particle = lo_outer_cp ).

lo_element_descr = io_doc_type->create_element_decl(

name = 'SIMPLE_VALUE'

prefix = cl_fdt_actn_email=>gc_my_namespace_prefix ).

lo_element_descr-

>set_content_spec( content_spec = if_ixml_element_decl=>co_mixed ).

lo_element_descr-

>set_grouping( grouping = if_ixml_content_particle=>co_sequence ).

lo_element_descr-

>set_occurrence( occurs = if_ixml_content_particle=>co_one ).

* -> create anonymous content (brackets-)particle: (...)

lo_cp_brackets = io_doc_type->create_content_particle(

Page 74: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

74

name = ''

grouping = if_ixml_content_particle=>co_sequence

occurrence = if_ixml_content_particle=>co_one ).

lo_cp_element = io_doc_type->create_content_particle(

name = 'ELEMENT_TYPE'

prefix = cl_fdt_actn_email=>gc_my_namespace_prefix

grouping = if_ixml_content_particle=>co_sequence

occurrence = if_ixml_content_particle=>co_zero_or_one ).

lo_cp_brackets->add_content_particle( content_particle = lo_cp_element ).

lo_cp_element = io_doc_type->create_content_particle(

name = 'VALUE'

prefix = cl_fdt_actn_email=>gc_my_namespace_prefix

grouping = if_ixml_content_particle=>co_sequence

occurrence = if_ixml_content_particle=>co_zero_or_one ).

lo_cp_brackets->add_content_particle( content_particle = lo_cp_element ).

lo_cp_element = io_doc_type->create_content_particle(

name = 'SUPPLEMENT'

prefix = cl_fdt_actn_email=>gc_my_namespace_prefix

grouping = if_ixml_content_particle=>co_sequence

occurrence = if_ixml_content_particle=>co_zero_or_one ).

lo_cp_brackets->add_content_particle( content_particle = lo_cp_element ).

lo_cp_element = io_doc_type->create_content_particle(

name = 'NONE_AP'

prefix = cl_fdt_actn_email=>gc_my_namespace_prefix

grouping = if_ixml_content_particle=>co_sequence

occurrence = if_ixml_content_particle=>co_zero_or_one ).

lo_cp_brackets->add_content_particle( content_particle = lo_cp_element ).

lo_element_descr->add_content_particle( content_particle = lo_cp_brackets ).

io_doc_type->append_child( new_child = lo_element_descr ).

After defining the structure of the SIMPLE_VALUE XML element, you then define the sub-elements. As this is done the same way as with the definition of PARAMETER1 (element description, #PCDATA) the appropriate coding is not covered here.

Recommendation

The order of defining the XML-elements is relevant and you must adhere to the same sequence they are exported via method EXPORT_XML.

The following tables show the outcome of each constant used for grouping and occurrence:

Page 75: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

75

Grouping

Constant Result if_ixml_content_particle=>co_sequence Appended separator for this particle is a

comma (CUST_EXTY1:ELEMENT_TYPE?, )

if_ixml_content_particle=>co_choice Appended separator for this particle is a | (CUST_EXTY1:ITEM| CUST_EXTY1:item )

Occurrence

Constant Result if_ixml_content_particle=>co_one The corresponding XML element occurs

only once in the XML (#PCDATA nothing is appended)

if_ixml_content_particle=>co_one_or_more The corresponding XML element occurs one or multiple times in the XML (CUST_EXTY1:ELEMENT_TYPE+,)

if_ixml_content_particle=>co_zero_or_more The corresponding XML element occurs zero or multiple times in the XML ( (CUST_EXTY1:ITEM| CUST_EXTY1:item)* here the occurrence is set in the bracket particle)

if_ixml_content_particle=>co_zero_or_one The corresponding XML element occurs zero or once (optional XML element) in the XML (CUST_EXTY1:ELEMENT_TYPE?,)

13.3.2 GET_ELEMENT_DOMAIN_LIST

This method defines the domain list of an element. This method must be redefined when the element is bound to DDIC; the value help can read from the domain values.

METHOD if_fdt_data_exchange_external~get_element_domain_list.

DATA: ls_element_domain TYPE if_fdt_data_exchange_external=>s_element_domain,

lt_element_domain TYPE if_fdt_data_exchange_external=>t_element_domain.

Define the DDIC element to which the element ACTIVITY is bounded

ls_element_domain-node_name = 'ABC:RECIPIENT'.

ls_element_domain-type = 'if_fdt_actn_email=>t_recipient'.

INSERT ls_element_domain INTO TABLE et_element_domain_list.

ls_element_domain-node_name = 'ABC:BODY'.

ls_element_domain-type = 'if_fdt_actn_email=>body'.

INSERT ls_element_domain INTO TABLE et_element_domain_list.

ls_element_domain-node_name = 'ABC:SUBJECT'.

ls_element_domain-type = 'if_fdt_actn_email=>subject'.

INSERT ls_element_domain INTO TABLE et_element_domain_list.

ENDMETHOD.

The output parameter for this method is ET_ELEMENT_DOMAIN_LIST. The method lists the domain or type

of user defined XML element.

Page 76: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

76

13.3.3 GET_VERSION_CHANGE_LIST

This method maintains the changes in different XML versions. The name and structure of XML elements can change in different versions, which may prevent the import of older versions. This method allows you to track the changes in different versions, and know which XML version to use.

We need to define this method for any changes and add values to ET_VERSION_CHANGE. During runtime, we call this method to determine the objects for which the modification needs to be made, and if not defined then the modification is skipped.

For example, if the changes were made for expression type email, we need to add for that version.

METHOD if_fdt_data_exchange_external~get_version_change_list.

DATA: ls_version_change TYPE if_fdt_data_exchange_external=>s_xml_version_change,

ls_message TYPE if_fdt_types=>s_message.

ls_version_change-xml_version = '1.07'. " This should be FDT XML Version

ls_message-msgty = 'I'.

ls_message-text = 'Version 1.07 has Recipient, Body and Subject

of Action Email added '.

INSERT ls_message INTO TABLE ls_version_change-messages.

INSERT ls_version_change INTO TABLE et_version_change.

ENDMETHOD.

The output parameter for this method is ET_VERSION_DOMAIN_LIST. The method lists the domain or type

of user defined XML element.

13.3.4 MODIFY_XML_VERSION_CHANGES

This method transforms one version to another, where the version is updated (1.06 to 1.07) or downgraded (1.07 to 1.06).

This method allows you to adhere to the XML downgrade and upgrade from different releases. For example, if your previous release has Element-Recipient that was changed to Recipient(s), you need to delete the old element and insert new one (recipients) so the DTD is validated correctly. The value of the new element is defaulted; vice versa for downgrade.

In our example, if the Recipient changes from a single value to a multiple value, then the changes would be as follows:

METHOD if_fdt_data_exchange_external~modify_xml_version_changes.

DATA: lo_ixml TYPE REF TO if_ixml,

lo_document TYPE REF TO if_ixml_document,

lo_node TYPE REF TO if_ixml_node,

lo_ref_element TYPE REF TO if_ixml_element,

lo_new_element TYPE REF TO if_ixml_element,

lo_element TYPE REF TO if_ixml_element,

lv_value TYPE string,

ls_value TYPE if_fdt_actn_email=>recipient,

lt_value TYPE if_fdt_actn_email=>t_recipient.

lo_ixml = cl_ixml=>create( ).

lo_document = lo_ixml->create_document( ).

IF iv_from_version LT iv_to_version.

* Case of Version Upgradation

* For Version 1.06 -> 1.07 upgradation.

IF iv_from_version EQ '1.01'

Page 77: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

77

AND iv_to_version EQ '1.02'.

lo_element = io_parent->find_from_name( name = 'RECIPIENTS'

namespace = 'ABC' ).

lt_value = lo_element->get_value( ).

* Perform user defined logic which might be required during transformation

LOOP AT lt_value INTO ls_value.

lv_value = la_value-recipient.

RETURN.

ENDLOOP.

CALL METHOD cl_fdt_maintenance=>convert_abap_to_xml

EXPORTING

iv_name = 'RECIPIENT'

ia_abap = lv_value

iv_namespace_prefix = 'ABC'

IMPORTING

eo_element = lo_new_element.

io_parent->replace_child( new_child = lo_new_element

old_child = lo_element ).

ENDIF.

ELSEIF iv_from_version GT iv_to_version.

* For Version 1.02 -> 1.01 downgradation.

IF iv_from_version EQ '1.02' AND

iv_to_version EQ '1.01'.

CALL METHOD cl_fdt_maintenance=>convert_xml_to_abap

EXPORTING

io_parent = io_parent

iv_name = 'RECIPIENT'

iv_namespace_prefix = 'ABC'

IMPORTING

ea_abap = lv_value.

* Perform user defined logic which might be required during transformation

CALL METHOD cl_fdt_maintenance=>convert_abap_to_xml

EXPORTING

iv_name = 'RECIPIENTS'

ia_abap = lt_value

iv_namespace_prefix = 'ABC'

IMPORTING

eo_element = lo_new_element.

io_parent->append_child( lo_new_element ).

io_parent->remove_child( lo_element ).

ENDIF.

ENDMETHOD.

The input parameters for this method are as follows:

IO_PARENT Provides a table of the object IDs for export

IV_FROM_VERSION Lower boundary BRFplus XML version in version change

IV_TO_VERSION Upper boundary BRFplus XML version in version change

The output parameter is as follows:

ET_MESSAGE

Provides a list of failure and success messages

Page 78: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

78

14 Creation of the Action Type or Expression Type as an Object in BRFplus

When the development of the class and the interface is completed, the new action type or expression type needs to be created as a BRFplus object in the BRFplus workbench. You can do this from the context menu in the repository tree on the application in which you want to create it.

FDT_SYSTEM is the application for all action types and expression types in the BRFplus standard.

Procedure

1. Create your own transportable application (like FDT_SYSTEM).

2. Create your own action types and expression types.

3. Change the Access Level to Global so the action type or expression type can be used by objects from other applications.

4. Enter class and application name and make it an action.

Page 79: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

79

5. Set the transport objects and create some meaningful texts.

For more information, see chapter ‎4 Transport Objects.

6. For email action type, you can add a constant to IF_FDT_ACTN_EMAIL with the ID of the type (see general data section).

Note

For most action types and expression types you can find constants in IF_FDT_CONSTANTS.

Transaction FDT_RESERVED gives an overview of UUIDs included into the BRFplus shipment and reserved UUIDs.

You cannot and you do not have to change those objects.

Page 80: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

80

15 Testing the Action Type or Expression Type

Having a test report or even a unit test is a good idea. One is created for our example email action type and used to debug the new development.

REPORT fdt_demo_report_actn_email.

DATA: lo_factory TYPE REF TO if_fdt_factory,

lo_email TYPE REF TO if_fdt_actn_email,

lo_function TYPE REF TO if_fdt_function,

lt_message TYPE if_fdt_types=>t_message,

lo_result TYPE REF TO if_fdt_result,

lr_data TYPE REF TO data,

lv_body TYPE if_fdt_actn_email=>body,

lv_recipient TYPE if_fdt_actn_email=>recipient,

lt_recipient TYPE if_fdt_actn_email=>t_recipient,

lv_subject TYPE if_fdt_actn_email=>subject,

lo_trace TYPE REF TO if_fdt_trace,

lo_lean_trace TYPE REF TO if_fdt_lean_trace.

lo_factory = cl_fdt_factory=>if_fdt_factory~get_instance(

if_fdt_constants=>gc_application_tmp ).

* create the email action

lo_email ?= lo_factory->get_expression(

iv_expression_type_id = if_fdt_actn_email=>gc_exty_email ).

lo_email->if_fdt_transaction~enqueue( ).

lo_email->if_fdt_admin_data~set_name( 'DEMO_ACTN_MESSAGE_LOG' ).

* the email action specific attributes

lv_recipient = '[email protected]'.

APPEND lv_recipient TO lt_recipient.

lo_email->set_recipients( lt_recipient ).

lv_subject = 'This is a test of an email action'.

lo_email->set_subject( lv_subject ).

lv_body = 'This is the first test report. When you can see you email it works.'.

lo_email->set_body( lv_body ).

* make the email action the top expression (most simple test)

lo_function ?= lo_factory->get_function( ).

lo_function->if_fdt_transaction~enqueue( ).

lo_function->if_fdt_admin_data~set_name( cl_fdt_services=>get_unique_name( ) ).

lo_function->set_expression( lo_email->mv_id ).

* activate and save function + email action

lo_function->if_fdt_transaction~activate( EXPORTING iv_deep = abap_true

IMPORTING et_message = lt_message ).

IF lt_message IS NOT INITIAL.

BREAK-POINT.

RETURN. ">>>

ENDIF.

lo_function->if_fdt_transaction~save( iv_deep = abap_true ).

lo_function->if_fdt_transaction~dequeue( iv_deep = abap_true ).

lo_function->process( EXPORTING iv_trace_mode = if_fdt_constants=>gc_trace_mode_lean

IMPORTING eo_result = lo_result

eo_trace = lo_trace ).

lo_lean_trace ?= lo_trace.

lo_lean_trace->save( ).

Page 81: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

81

16 Creation of the User Interface

Prerequisites

To create your own user interfaces for expression types and action types you have a basic understanding about Web Dynpro (WD) ABAP. Tutorials and videos about WD ABAP are available in SCN.

16.1 Overview about the Components of the User Interface

The following table provides an overview of the components of the user interface for custom action types and expression types. They are discussed in more detail in subsequent chapters.

Component Description Web Dynpro Component

The WD component visualizes and controls (react on user actions) the UI. It is the Controller and View of the well-known MVC pattern. The WD component is designed to display the detail part of the expression type/action. The general and toolbar sections are provided by the BRFplus UI framework. The lifecycle and transactional functionalities arehandled by this framework.

The WD component implements two WD interfaces that control the lifecycle of the component.

Model Class

The model class is the connector between the UI and the backend. It represents the model entity of the MVC pattern. It is a standard ABAP OO-class that inherits from CL_FDT_WD_MAINTENANCE_MODEL and retrieves and updates the data that are maintained in the UI. The data are stored in model nodes, which are technically structured WD context nodes. The model class stores the translatable text elements used in dynamic UI screens.

UI Class

The UI OO class determines the model class and the WD component for an expression type/action (Registry). It ensures that customer expression types/actions are protected against future enhancements of the BRFplus UI framework through versioning.

Services

The UI Infrastructure provides various services you use in your UI. One major service is the query component that enables the user to select BRFplus objects. You need this component if your expression type/object refers to other BRFplus objects.

Page 82: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

82

16.2 Web Dynpro Component

Note

Since the shipped WD component for the email action type creates UI parts during runtime (dynamically), the component is not discussed, but those parts relevant to understand the framework. Some features are discussed without referring to the implementation of the email action type to make this tutorial easier to understand.

16.2.1 Implementation of the BRFplus WD Interfaces

The WD component has to reimplement the following WD interfaces in the component definition:

FDT_IWD_COMPONENT

FDT_IWD_OBJECT

FDT_IWD_OBJECT_EXTENDED

FDT_IWD_QUERY

The methods, which have to be implemented, are discussed in detail later.

16.2.2 Definition of the Context

The context of the WD component consists of the model context nodes (root node MODEL) and the node UI_ADJUSTMENT, which is provided by the interface FDT_IWD_OBJECT.

Page 83: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

83

Model Nodes

Model nodes are actually data containers filled in the model class by accessing the backend.

There is a root node, MODEL, under which all model nodes are stored. You have to create this root node for each of your action or expression type WD components.

Each model node (RECIPIENTS) is bound to a DDIC structure (check the FDTS_WD_ACTN_EMAIL_RECP_MODEL and FDTS_WD_ACTN_EMAIL_MSG_MODEL structures to get an idea), which defines its attributes. The cardinality of the node determines if the data are a collection (table) or a flat structure. The model nodes should be defined semantically. That means the attributes that belong together should be part of one model node. Usually those attributes are displayed together in a WD view.

UI Adjustment Node

The UI_ADJUSTMENT node is provided by the UI framework. The attributes read_only and enabled must be bound to the corresponding attributes of the UI elements. This has the advantage that these UI elements are set to read-only or disabled if the user is not allowed to maintain the content. This is the case, when the object is visualized in display mode.

The readOnly attribute of the recipient input field in the WD view is bound to the read_only attribute of the UI_ADJUSTMENT node.

16.2.3 Exception Handling in the UI

In the WD environment, we cannot use CX_FDT (and its subclasses) because the UI layer in BRF has an exception hierarchy, which cannot be used in method signatures (unchecked exceptions) due to history reasons. There is an exception class hierarchy for the WD UI. Its root class is CX_FDT_WD. If you have to propagate a backend exception (CX_FDT and subclasses), you have to convert the backend exception to CX_FDT_WD_BACKEND.

Method CL_FDT_WD_SERVICE=>CONVERT_BACKEND_EXCEPTION does the conversion.

If you call a method that can raise CX_FDT (and its subclasses) ensure you either report the exception to the user or propagate it correctly.

Page 84: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

84

IF_FDT_WD_MODEL~INIT (Model Class)

DATA: lx_fdt TYPE REF TO cx_fdt.

***************************************************************************************

TRY.

*call super

super->if_fdt_wd_model~init( io_context_node = io_context_node

io_controller = io_controller ).

*get action message application log

mo_actn_msg_log ?= mo_factory->get_expression( iv_id = mv_id ).

CATCH cx_fdt INTO lx_fdt.

cl_fdt_wd_service=>convert_backend_exception( lx_fdt ).

ENDTRY.

Now you may catch this exception in the WD component for example and react on it.

Reacting on Exceptions

You have to catch all possible exceptions properly. Depending on the exceptions, you can do one of the following:

Try to react by providing a workaround

Example: If the user cannot edit an object because it is locked you can try to display it.

Within the WD component, do not catch exceptions if they are part of the signature in an interface method.

Example: All maintenance UI WD components are implementing the interface FDT_IWD_OBJECT. These methods have the exception cx_fdt_wd in its signature and are handled by the object manager.

In the majority of cases, you probably cannot react and want to display the exception (error text) to the user. This can be accomplished by calling the method CL_FDT_WD_SERVICE=>REPORT_EXCEPTION.

It provides two parameters:

o IX_EXCEPTION for reporting backend exceptions

o IX_WD_EXCEPTION for UI exceptions

Method in a WD caller, calling a method in the model class and handling exception properly.

TRY.

wd_this->mo_model->refresh_model( ). “->may raise cx_fdt_wd

CATCH cx_fdt_wd_backend INTO lx_fdt_backend.

lo_msg_manager = wd_this->wd_get_api( )->get_message_manager( ).

cl_fdt_wd_service=>report_exception( io_message_manager = lo_msg_manager

ix_wd_exception = lx_fdt_backend ).

ENDTRY.

Page 85: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

85

16.2.4 Implementation of Interface FDT_IWD_OBJECT/FDT_IWD_COMPONENT

The following methods make use of additional attributes and methods seen in the Attributes tab from the COMPONENTCONTROLLER for the WD component FDT_WD_ACTN_EMAIL.

INIT

This method is called by the framework, after the WD component is created.

METHOD INIT .

wd_this->mo_model = io_model.

wd_this->mo_state = io_state.

wd_this->mv_id = iv_id.

wd_this->mo_model->init( io_context_node = wd_context

io_controller = wd_this->wd_get_api( ) ).

wd_this->mo_model_cl ?= io_model.

wd_this->gc_usage_type_message = 'USAGE_MESSAGE_VAR'.

wd_this->gc_usage_type_rec = 'USAGE_REC_VAR'.

DATA: lo_context_node TYPE REF TO if_wd_context_node,

ls_rec TYPE wd_this->element_recipients,

lv_string TYPE string.

lo_context_node = wd_context->path_get_node( path = `MODEL.RECIPIENTS` ).

lo_context_node->get_static_attributes( IMPORTING static_attributes = ls_rec ).

ls_rec-rec_1_req = abap_true.

ls_rec-rec_1_name = wd_this->mo_model-

>if_wd_component_assistance~get_text( key = '001' ).

ls_rec-rec_2_req = abap_true.

ls_rec-rec_2_name = wd_this->mo_model-

>if_wd_component_assistance~get_text( key = '001' ).

ls_rec-rec_3_req = abap_true.

ls_rec-rec_3_name = wd_this->mo_model-

>if_wd_component_assistance~get_text( key = '001' ).

ls_rec-rec_4_req = abap_true.

ls_rec-rec_4_name = wd_this->mo_model-

>if_wd_component_assistance~get_text( key = '001' ).

lo_context_node->bind_structure( EXPORTING new_item = ls_rec ).

ENDMETHOD.

Page 86: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

86

It provides the following parameters:

Parameter Type Purpose

IV_ID Importing ID of the object

IO_MODEL Importing The instance of the model (described later in this document)

IO_STATE Importing The instance of the state representation (described later in this document)

CX_FDT_WD Exception Initialization failed

You should set those parameters into attributes of your component controller.

DISPLAY

The purpose of this method is to notify that the object should be displayed.

METHOD DISPLAY .

wd_this->mo_model->get_model( ).

wd_this->create_toolbar( ).

ENDMETHOD.

Usually, you call the GET_MODEL( ) of your model to get the model from the backend. This method retrieves the data from the backend and provides it by supplying the corresponding model nodes.

Sometimes, you do not want to retrieve the complete data from the backend initially but only if the data needs to be visualized. For example, if you have different tabs in your view. Therefore, instead of calling GET_MODEL( ), you can call GET_MODEL_BY_NODE by providing the name of a model node. In this case, only the provided node is filled with data from the backend.

This method can throw CX_FDT_WD.

EDIT

This method notifies that the object should be edited. Do not enqueue the object since this is done by the UI framework.

METHOD edit .

wd_this->mo_model->get_model( ).

wd_this->create_toolbar( ).

ENDMETHOD.

Please check the previous section concerning the model access.

This method can throw CX_FDT_WD.

SAVE

This method notifies that the object should be saved/synchronized in a consistent state to the backend. The UI component/model must not call the save method in the backend. This is done by the framework, if necessary.

Page 87: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

87

METHOD save .

wd_this->mo_model->refresh_model( ).

ENDMETHOD.

Usually, you call the refresh_model( ) of your model, which synchronizes the UI with the backend.

This method can throw CX_FDT_WD.

SET_CONFIGURATION

After the creation of your WD component, this method is called by the framework and provides the configuration handle (IO_CONFIGURATION). You must store this parameter into an attribute (convention: mo_configuration) of your component controller. The configuration represents the user configuration and technical settings (for example if a toolbar button should be displayed). The configuration handle (IO_CONFIGURATION) is a mandatory parameter for every service method.

wd_this->MO_CONFIGURATION = io_configuration.

VIEW

The view (MAIN_VIEW) contains the layout of the action Email UI. The UI ADJUSTMENT and MODEL nodes are bound from the component controller.

Page 88: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

88

As usual in WD you define your UI elements here and bind the content properties of it to context nodes. The content of the data is provided by the model nodes. For example, you bind the Recipients input field to the

context attribute Model.Recipients.Recipients (same applies to Subject, Message, and Parameters).

You also bind the attributes of the UIAdjustment node to the proper properties (enabled, read_only) of the elements in your view.

Window OBJECT IVIEW

The WD component has a view MAIN_VIEW, which contains the layout for the UI, as discussed. To display the view include it in the window OBJECT_IVIEW, which is an interface view of FDT_IWD_OBJECT.

Only views that are embedded in the window OBJECT_IVIEW are displayed.

REGISTER_TOOLBAR

This event registers a toolbar in the „DETAIL‟ tray.

The toolbar can consist of max 8 toolbar buttons.

Mandatory fields are the name of the action („action‟) and the text of the button („text‟).

Look at IF_FDT_WD_TYPES=>S_TOOLBAR for further fields.

When you press the button on the toolbar you are notified via the method, HDL_ACTION.

If you raise the event again, the toolbar is rebuilt from scratch.

The following method is an example how to populate buttons in the toolbar. You call this method in the display and edit methods of the Componentcontroller.

METHOD create_toolbar_.

DATA: ls_toolbar TYPE if_fdt_wd_types=>s_toolbar,

lt_toolbar TYPE if_fdt_wd_types=>t_toolbar.

ls_toolbar-action = “My_Action”

ls_toolbar-text = “My Test Action”

APPEND ls_toolbar TO lt_toolbar.

"register toolbar

wd_this->fire_register_toolbar_evt( it_toolbar = lt_toolbar ).

Page 89: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

89

If the user presses a button, the method HDL_ACTION is called by the framework. This gives you the chance to handle the action.

METHOD hdl_action .

IF iv_action = My_Action”.

“Do something here

ENDIF.

ENDMETHOD.

Wizard UI

Optionally, you have the possibility to provide a simplified UI for your action or expression type, which is used when the object is created.

An example is the random expression type, which provides the following screen during creation:

You can provide such a wizard UI for your expression or action type by implementing the followings steps:

1. Create a view for the wizard UI. The view should be simple, small and easy to use. You should reuse the existing model nodes, which are already available for your main view. It must not have any links, since it is not possible to navigate to other objects within this view.

2. Nest the view in the interface view WIZARD_IVIEW, which is available.

3. Implement the method IS_SUPPORTING_WIZARD_MODE in your component controller and set:

rv_supports_wizard_mode = abap_true

4. Implement the method MAINTAIN_IN_WIZARD of your component controller. This method is called by the framework, before the create popup is displayed.

You can fill model nodes via your model class if you want to set default values.

Page 90: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

90

When the user has acknowledged the creation of the object, you are notified via the SAVE method. As in the standard view, synchronize your UI with the backend by calling the refresh_model( ).

The method CREATE of your WD component is called by the framework if the user creates a new instance of the object (Create Popup). You use this method to preconfigure your component and to decide dynamically if you provide a wizard UI or not (implementation of IS_SUPPORTING_WIZARD_MODE).

Note

It does not make sense to provide a wizard UI for every expression type or action type, especially for more complex expression types such as the decision table.

Be aware that it is not possible to navigate from a wizard UI to other BRFplus objects.

Therefore, do not use links within this view.

16.3 Model Class Each WD component has an assigned model class with the main task of filling and retrieving the data of the model nodes of the WD component. The framework automatically tracks the user who has changed data in the UI.

The GET_MODEL… methods read data from the backend and provide it as (model) context nodes for the WD component.

The SET_MODEL… methods read data from the (model) context nodes and update the backend accordingly. Each model class must inherit from CL_FDT_WD_MAINTENANCE_MODEL.

Note

You should read data from the API in the GET_MODEL_BY_NODE method and fill the model nodes accordingly. Change the content of model nodes in the WD component only if the user changes data. Otherwise, the tracking of the state of your component will be erroneous.

16.3.1 Implementation of Model Class

The model class for custom action email is CL_FDT_WD_ACTN_EMAIL_MODEL and is inherited from CL_FDT_WD_MAINTENANCE_MODEL.

The redefinition of the following methods is required.

Page 91: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

91

IF_FDT_WD_MODEL~INIT

This method initializes the model and is called during the initialization of the component.

METHOD if_fdt_wd_model~init.

DATA lx_fdt TYPE REF TO cx_fdt.

" calling init of superclass

super->if_fdt_wd_model~init( (1)

io_context_node = io_context_node

io_controller = io_controller ).

TRY.

me->mo_actn_email ?= me->mo_factory->get_expression( iv_id = mv_id ). (2)

CATCH cx_fdt INTO lx_fdt.

cl_fdt_wd_service=>convert_backend_exception( ix_fdt = lx_fdt ). (3)

ENDTRY.

ENDMETHOD.

A call is made to INIT( ) of super class that is CL_FDT_WD_MAINTENANCE_MODEL to initialize the framework (1).

In the next step (2), the reference to the backend is saved in member variable mo_actn_email, which is received from the factory. You get the instance of the corresponding backend class.

Very important is the exception handling in the UI layer. You must always convert backend exceptions (3) with the service call

cl_fdt_wd_service=>convert_backend_exception( ix_fdt = lx_fdt ).

This means, every time you call methods of the backend API, which can potentially raise an exception, you

have to put it in a TRY…CATCH block with the mentioned service call.

The INIT() can throw CX_FTD_WD.

PUBLISH_MODEL_NODES

The purpose of this method is to publish the model nodes which are defined in the WD component controller under the model root node.

METHOD if_fdt_wd_model~publish_model_nodes.

DATA: ls_model_node TYPE if_fdt_wd_types=>s_model_node.

* node recipients

ls_model_node-name = gc_model_node_recipients. (1)

ls_model_node-read_only = abap_false.

INSERT ls_model_node INTO TABLE rt_model_node. (2)

* node subject & Body

ls_model_node-name = gc_model_node_message.

ls_model_node-read_only = abap_false.

INSERT ls_model_node INTO TABLE rt_model_node.

ENDMETHOD.

Page 92: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

92

For every model node you create a constant (1) in the model class by using the name of the model name as its value.

You publish those model nodes in this method. For each model node, you create an entry in table rt_model_node (2). You specify if the model is only read-only; the user cannot change the data. Since this is not true for this component, the read_only flag is set to abap_false.

Sometimes there is the need to add a non-data attribute to your model node. This is true if you use the model for binding against a WD table since WD does not provide the possibility to bind two data sources for content and metadata (for example, design of a row) of the table. To mark an attribute as meta-data and not to consider it for checking if the object has changed, you can model the table ‘attributes’ accordingly, which is part of the structure of the returning parameter rt_model_node.

For example, to exclude the CELL VARIANT attribute from a check to determine if the object was changed,

you would implement the following:

ls_attribute-name = 'CELL_VARIANT'.

ls_attribute-exclude_from_dirty_check = abap_true.

INSERT ls_attribute INTO TABLE lt_attributes.

ls_model_node-attributes = lt_attributes.

GET_MODEL_BY_NODE

This method retrieves the model from the backend and fills the proper model node. We discuss only the recipient model node to simplify this tutorial.

METHOD get_model_by_node.

DATA: lo_model_node TYPE REF TO if_wd_context_node,

lx_fdt TYPE REF TO cx_fdt,

lt_recipients TYPE if_fdt_actn_email=>t_recipient,

lts_rec_param TYPE if_fdt_actn_email=>ts_parameter,

ls_rec_param TYPE if_fdt_actn_email=>s_parameter,

ls_recipients_model TYPE fdts_wd_actn_email_recp_model,

ls_icon TYPE cl_fdt_wd_icons=>s_icon,

lv_body TYPE string,

lv_subject TYPE string,

lv_text TYPE string,

ls_message_model TYPE fdts_wd_actn_email_msg_model.

TRY.

lo_model_node = me->if_fdt_wd_model~get_model_node_by_name( iv_model_node_name ).

(1)

CASE iv_model_node_name.

WHEN gc_model_node_recipients. (2)

IF mv_timestamp IS NOT INITIAL.

lt_recipients = mo_actn_email->get_recipients( mv_timestamp ).

(3)

mo_actn_email->get_parameters(

EXPORTING iv_timestamp = mv_timestamp

IMPORTING ets_recipient_parameter = lts_rec_param ).

ELSE.

lt_recipients = mo_actn_email->get_recipients( ).

mo_actn_email->get_parameters(

IMPORTING ets_recipient_parameter = lts_rec_param ).

ENDIF.

lo_model_node->get_static_attributes(

IMPORTING static_attributes = ls_recipients_model ).

LOOP AT lts_rec_param INTO ls_rec_param.

Page 93: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

93

IF ls_rec_param-parameter_id IS NOT INITIAL.

IF mv_timestamp IS NOT INITIAL.

lv_text = cl_fdt_wd_service=>get_display_name(

iv_id = ls_rec_param-parameter_id

iv_timestamp = mv_timestamp

io_configuration = mo_configuration

iv_bound_object_id = mv_id ).

ELSE.

lv_text = cl_fdt_wd_service=>get_display_name(

iv_id = ls_rec_param-parameter_id

io_configuration = mo_configuration

iv_bound_object_id = mv_id ).

ENDIF.

ELSE.

lv_text = text-001.

ENDIF.

CASE ls_rec_param-position.

WHEN 1.

ls_recipients_model-rec_1 = ls_rec_param-parameter_id.

ls_recipients_model-rec_1_name = lv_text.

ls_recipients_model-rec_1_req = abap_true.

IF ls_rec_param-parameter_id IS NOT INITIAL.

CLEAR ls_icon.

ls_icon = cl_fdt_wd_icons=>get_icon(

iv_id = ls_rec_param-parameter_id

io_configuration = mo_configuration

iv_timestamp = mv_timestamp

iv_bound_object_id = mv_id ).

ls_recipients_model-rec_1_icon = ls_icon-icon_source.

ls_recipients_model-rec_1_tooltip = ls_icon-tooltip.

ELSE.

ls_recipients_model-rec_1_tooltip = lv_text.

ENDIF.

WHEN 2.

ls_recipients_model-rec_2 = ls_rec_param-parameter_id.

ls_recipients_model-rec_2_name = lv_text.

ls_recipients_model-rec_2_req = abap_true.

IF ls_rec_param-parameter_id IS NOT INITIAL.

CLEAR ls_icon.

ls_icon = cl_fdt_wd_icons=>get_icon(

iv_id = ls_rec_param-parameter_id

io_configuration = mo_configuration

iv_timestamp = mv_timestamp

iv_bound_object_id = mv_id ).

ls_recipients_model-rec_2_icon = ls_icon-icon_source.

ls_recipients_model-rec_2_tooltip = ls_icon-tooltip..

ELSE.

ls_recipients_model-rec_2_tooltip = lv_text.

ENDIF.

WHEN 3.

ls_recipients_model-rec_3 = ls_rec_param-parameter_id.

ls_recipients_model-rec_3_name = lv_text.

ls_recipients_model-rec_3_req = abap_true.

IF ls_rec_param-parameter_id IS NOT INITIAL.

CLEAR ls_icon.

ls_icon = cl_fdt_wd_icons=>get_icon(

iv_id = ls_rec_param-parameter_id

io_configuration = mo_configuration

iv_timestamp = mv_timestamp

iv_bound_object_id = mv_id ).

ls_recipients_model-rec_3_icon = ls_icon-icon_source.

ls_recipients_model-rec_3_tooltip = ls_icon-tooltip.

ELSE.

ls_recipients_model-rec_3_tooltip = lv_text.

ENDIF.

Page 94: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

94

WHEN 4.

ls_recipients_model-rec_4 = ls_rec_param-parameter_id.

ls_recipients_model-rec_4_name = lv_text.

ls_recipients_model-rec_4_req = abap_true.

IF ls_rec_param-parameter_id IS NOT INITIAL.

CLEAR ls_icon.

ls_icon = cl_fdt_wd_icons=>get_icon(

iv_id = ls_rec_param-parameter_id

io_configuration = mo_configuration

iv_timestamp = mv_timestamp

iv_bound_object_id = mv_id ).

ls_recipients_model-rec_4_icon = ls_icon-icon_source.

ls_recipients_model-rec_4_tooltip = ls_icon-tooltip.

ELSE.

ls_recipients_model-rec_4_tooltip = lv_text.

ENDIF.

ENDCASE.

ENDLOOP.

CONCATENATE LINES OF lt_recipients INTO ls_recipients_model-

recipients SEPARATED BY '; '. (4)

lo_model_node->bind_structure( new_item = ls_recipients_model

(5)

set_initial_elements = iv_initialize_elements ).

...

ENDCASE.

CATCH cx_fdt INTO lx_fdt.

cl_fdt_wd_service=>convert_backend_exception( ix_fdt = lx_fdt ).

ENDTRY.

ENDMETHOD.

Initially, the instance of the model node is retrieved by calling get_model_node_by_name( ) (1).

For each model node (2) which is provided by the importing parameter iv_model_node_name, we fill the

data accordingly. If you have several model nodes in your component, it makes sense to spread the implementation into several private methods of your model class, which are called by this method.

When you call the GET methods of the backend-API (mo_actn_email->get_recipients) you must

check if the UI should display an older version: if mv_timestamp is not initial, you have to supply this

timestamp for the backend call (3).

The recipient table (lt_recipients) provided by the backend is then prepared for displaying. Therefore,

the recipients are split into a string (lv_recipients_model) (4) and bound to the structure

ls_recipients_model of the structure node ls_recipients.

Then, the structure is bound to the model node (5). If you have a table (context node with cardinality > 1) you

must use the method bind_table instead. Be aware of the optional parameter iv_initialze_elements,

which you should assign to set_initial_elements when calling the BIND… methods of the WD context

node.

Finally, the exceptions of the backend are converted into the cx_fdt_wd_backend exception of the UI

layer.

Note

The protected method SET_MODEL_BY_NODE of CL_FDT_WD_MODEL has to be re-implemented and not the interface IF_FDT_WD_MODEL method.

Page 95: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

95

SET_MODEL_BY_NODE

The purpose of this method is to set the model node to the backend for the respective node. This means the backend is updated.

METHOD set_model_by_node.

DATA: lo_nd_model TYPE REF TO if_wd_context_node,

ls_message_model TYPE fdts_wd_actn_email_msg_model,

ls_parameter TYPE if_fdt_actn_email=>s_parameter,

lts_parameter TYPE if_fdt_actn_email=>ts_parameter,

lt_recipients TYPE if_fdt_actn_email=>t_recipient,

lt_recipients_final TYPE if_fdt_actn_email=>t_recipient,

ls_recipients LIKE LINE OF lt_recipients,

lt_recipients_model TYPE STANDARD TABLE OF fdts_wd_actn_email_recp_model,

ls_recipients_model TYPE fdts_wd_actn_email_recp_model,

ls_bs_model TYPE fdts_wd_actn_email_bs_model,

lx_fdt TYPE REF TO cx_fdt,

lv_recipients_model TYPE string,

lt_plc_hldr TYPE match_result_tab,

lo_query TYPE REF TO if_fdt_query,

lt_ids TYPE REF TO if_fdt_types=>t_object_id,

lt_token TYPE cl_fdt_actn_email=>ts_token,

ls_token TYPE cl_fdt_actn_email=>s_token,

lv_body TYPE string,

lv_message TYPE string.

DATA: result_tab TYPE match_result_tab,

ls_result_tab TYPE match_result.

TRY.

lo_nd_model = me->if_fdt_wd_model~get_model_node_by_name( iv_model_node_name ).

(1)

WHEN gc_model_node_recipients.

(2)

" getting element of node

lo_nd_model-

>get_static_attributes( IMPORTING static_attributes = ls_recipients_model ). (3)

lv_recipients_model = ls_recipients_model-recipients.

SPLIT lv_recipients_model AT ';' INTO TABLE lt_recipients.

LOOP AT lt_recipients INTO ls_recipients.

CONDENSE ls_recipients.

INSERT ls_recipients INTO TABLE lt_recipients_final.

ENDLOOP.

mo_actn_email->set_recipients( lt_recipients_final ).

IF ls_recipients_model-rec_1_req EQ abap_true AND ls_recipients_model-

rec_1 IS NOT INITIAL.

ls_parameter-position = 1.

ls_parameter-parameter_id = ls_recipients_model-rec_1.

INSERT ls_parameter INTO TABLE lts_parameter.

ENDIF.

IF ls_recipients_model-rec_2_req EQ abap_true AND ls_recipients_model-

rec_2 IS NOT INITIAL..

ls_parameter-position = 2.

ls_parameter-parameter_id = ls_recipients_model-rec_2.

INSERT ls_parameter INTO TABLE lts_parameter.

ENDIF.

IF ls_recipients_model-rec_3_req EQ abap_true AND ls_recipients_model-

rec_3 IS NOT INITIAL..

Page 96: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

96

ls_parameter-position = 3.

ls_parameter-parameter_id = ls_recipients_model-rec_3.

INSERT ls_parameter INTO TABLE lts_parameter.

ENDIF.

IF ls_recipients_model-rec_4_req EQ abap_true AND ls_recipients_model-

rec_4 IS NOT INITIAL..

ls_parameter-position = 4.

ls_parameter-parameter_id = ls_recipients_model-rec_4.

INSERT ls_parameter INTO TABLE lts_parameter.

ENDIF.

mo_actn_email->set_parameters( EXPORTING its_recipient_parameter = lts_parameter ).

(4)

ENDCASE.

CATCH cx_fdt INTO lx_fdt.

cl_fdt_wd_service=>convert_backend_exception( ix_fdt = lx_fdt ).

ENDTRY.

ENDMETHOD.

To set the model to the API you need a variable (ls_recipients_model) which refers to the same DDIC-

type as your model node in the Web Dynpro component.

Initially, the reference for the model node is retrieved (1).

Afterwards, you have to check which model node (iv_model_node_name) shall be updated (2).

Then, the data are retrieved from the (model) context node (3).

Finally, the backend is updated (4).

16.3.2 Detecting if the object has changed

In the majority of cases, you do not have to take care about the dirty state of the maintained object, if the current maintained object is changed.

The BRFplus UI framework provides this check as an automatic service by tracking the state of your model nodes. However, this service is not available when there is the need to use a recursive node (displaying hierarchical data in a tree).

In this case, you are responsible to detect if the user has changed the tree (and its content). To do this with the minor effort, apply the following pattern:

Implementation of IF_FDT_WD_MODEL~PUBLISH_MODEL_NODE: Set the field

ls_model_node-exclude_from_dirty_check = abap_true for the model node of the tree

representation (hierarchy) to exclude this model from the ‘dirty check’.

Use a separate model node for the content (attributes) of the node tree. It has the advantage that you do not have to check, if the user has changed these node attributes. Of course, when the user chooses ‘SAVE’ or switches to another node in the tree you must update the model

(set_model_by_node…).

When the user creates or deletes a node, this action calls proper methods in you model class. These methods (CREATE_NODE) change the tree and have to inform the framework by calling the method

if_fdt_wd_model~set_model_changed( ) to indicate that the model has changed.

16.3.3 Reference

The following table provides an overview about the methods of the model class.

The interface IF_FDT_WD_MODEL consists of the following methods. You can call these methods in your WD component:

Page 97: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

97

Method Description IF_WD_COMPONENT_ASSISTANCE~GET_TEXT

If you have defined text symbols in your model class, you can access them with the help of this method.

PUBLISH_MODEL_NODES Redefine this method.

Publish all the model nodes you have defined in your WD

component. Set the read_only flag = abap_true, if the

user cannot change the data of the node. When you have a recursive context node please set the field ‘exclude_from_dirty_check’ = abap_true.

Detecting if the object has changed.

There is also a hash table available (attributes component in the rt_model_node table) that enables you to exclude certain attributes of your node(s) for the dirty state check. This means that if the values of these attributes have changed, the object (=>your WD component) is not considered as unchanged. Do not misapply this option to mix the model with non-model parameters.

INIT Redefine this method. Call this method during initialization of your WD component. Do any necessary initialization here. Do not forget to call the super method.

(super->if_fdt_wd_model~init(io_context_node = io_context_node io_controller =

io_controller)

This method can throw CX_FDT_WD_BACKEND.

GET_MODEL This method gets the whole model for the WD component and calls GET_MODEL_BY_NODE for each model node.

This method can throw CX_FDT_WD_BACKEND.

SET_MODEL This method updates the backend from the WD component and calls SET_MODEL_BY_NODE for each changeable model node.

Optional: you can provide an action which describes the changes (insert, update) if you need such semantics in your implementation.

This method can throw CX_FDT_WD_BACKEND.

GET_MODEL_BY_NODE This method retrieves your model from the backend and fills the proper model node. You can provide a WD context node and/or a WD context element if you need to query the data from the backend. A use case for these query elements would be for instance: you have a tree, the user adds a new node, and you want to re-read the corresponding sub-tree to reflect the changes on the UI.

Do not redefine this method but instead use the protected method GET_MODEL_BY_NODE.

This method can throw CX_FDT_WD_BACKEND.

Page 98: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

98

SET_MODEL_BY_NODE This method sets/updates your model to the backend for the node. Do not redefine this method but instead use the protected method SET_MODEL_BY_NODE. You can provide an action which describes the changes (insert, update). The action is not evaluated by the framework; you can use it in your implementation.

This method can throw CX_FDT_WD_BACKEND.

IS_MODEL_CHANGED This method returns true, if the model has changed.

GET_MODEL_NODE_BY_NAME Retrieves the reference to a model node.

REFRESH_MODEL This method refreshes the model; the UI and backend are synchronized. Technically, SET_MODEL (optional: SET_MODEL_BY_NODE) is called first and then GET_MODEL (optional GET_MODEL_BY_NODE).

This method is useful if the user has changed some data on the UI and you want to call the API to update further fields (texts, descriptions).

This method can throw CX_FDT_WD_BACKEND.

SET_MODEL_CHANGED This method sets the model as changed.

The following protected methods are available:

Method Description SET_NOT_FOUND_TEXT_KEY Do not use this method.

It is inherited from the WD Assistance Class, which is the super class of our model class.

GET_MODEL_BY_NODE Redefine this method:

Implement the functionality to retrieve the model from the API in this method.

This method can throw CX_FDT_WD_BACKEND.

SET_MODEL_BY_NODE Redefine this method:

Implement the functionality to set the model to the API.

This method can throw CX_FDT_WD_BACKEND.

You are provided with the following:

UUID (mv_id)

Timestamp (mv_timestamp)

Instance of the factory (mo_factory)

Current state (mo_state) of the object

16.4 UI Class The purpose of this OO class is to determine the characteristics of the expression / action type regarding its UI. It determines the model class, the WD Component, and the implemented version of the UI framework/infrastructure. The UI class is an attribute of the expression /action type and can be set via the UI.

Page 99: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

99

The necessary reimplementation of the methods of interface IF_FDT_UI_DEFINITION is described in the following sections.

16.4.1 HAS_WD_ABAP_UI

The purpose of this method is to determine if an expression type or an action type has a WD ABAP UI. The method returns a Boolean variable stating the support for WD ABAP UI.

METHOD if_fdt_ui_definition~has_wd_abap_ui.

rv_has_wd_ui = abap_true.

ENDMETHOD.

There is an active WD ABAP UI for custom action email, thus the parameter is set to abap_true.

16.4.2 GET_WD_ABAP_MODEL_CLASS

In this method, the model class for an expression type or action type UI is determined.

METHOD if_fdt_ui_definition~get_wd_abap_model_class.

rv_model_class = 'CL_FDT_WD_ACTN_EMAIL_MODEL'.

ENDMETHOD.

The parameter returns the active model class for the custom action email.

16.4.3 GET_WD_ABAP_COMPONENT

By using this method, the WD ABAP component can be determined.

Page 100: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

100

METHOD if_fdt_ui_definition~get_wd_abap_component.

rv_wd_component = 'FDT_WD_ACTN_EMAIL'.

ENDMETHOD.

The parameter returns the active WD component for the custom action email.

16.4.4 GET_WD_ABAP_VERSION

This method determines the implemented version of the BRFplus UI framework.

METHOD if_fdt_ui_definition~get_wd_abap_version.

rv_version = ‘1.01’.

ENDMETHOD.

By versioning the UI components, it ensures that customer expression type or action types are protected against future enhancements of this BRFplus UI framework. When your system is updated to a newer release and you do not have the chance or do not want to immediately adapt your components, you should return the version, which was available during development. The current version number is the value of the constant IF_FDT_UI_DEFINITION=>GC_WD_ABAP_VERSION.

It is not recommended to return IF_FDT_UI_DEFINITION=>GC_WD_ABAP_VERSION because then you would be forced to immediately react on every framework change. Instead, you should return the value of the constant (1.01) to ensure your coding runs in subsequent SAP NetWeaver releases without adaptation of your expression type.

Note

If you return IF_FDT_UI_DEFINITION=>GC_WD_ABAP_VERSION, you adapt your WD component if the system is upgraded to a newer SAP NetWeaver release. Since the adaptation is not always immediately possible, you are strongly encouraged to return the current version as a value and not the constant. You can make use of new framework features by adapting your coding and then return a higher version.

The change history is documented in the interface documentation of IF_FDT_UI_DEFINITION.

Note

The versioning is independent of an SAP NetWeaver release. An update of an SAP NetWeaver release may not result in an update of the UI framework when there are no incompatible changes.

16.5 Reuse Components and Service in the UI Layer

16.5.1 Creating a new BRFplus Object

If you want to create a new BRFplus object within your expression UI, you can do this by implementing the following steps:

Page 101: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

101

The WD interface FDT_IWD_OBJECT, which is implemented by your WD component, provides two events for creating new objects:

CREATE_OBJECT_SIMPLE

CREATE_OBJECT_EXPERT

CREATE_OBJECT_SIMPLE is easier to use and CREATE_OBJECT_EXPERT provides more options with respect of controlling if the user can use reusable objects.

After the event is fired, the standard creation dialog is displayed. If the user actually creates an object, your component is informed by calling the method ADD_USAGE, which is also part of the interface FDT_IWD_OBJECT. You are provided with the ID of the newly created object and can update your model accordingly.

Example

You have an attribute ‘MY_ATTRIBUTE’ in your expression type, which can be bound to another expression.

Therefore, you create a method ‘CREATE_MY_ATTRIBUTE’ in one of your WD controllers, which is called by a UI action.

DATA: ls_object_type TYPE if_fdt_wd_types=>s_object_type_extended.

ls_object_type-type = if_fdt_constants=>gc_object_type_expression. (1)

wd_comp_controller->fire_create_object_simple_evt( (2)

is_object_type = ls_object_type

The possible object types that can be created by the user are narrowed by expressions (1) and then the event is triggered (2).

When the expression is created, you are notified by the call of the ADD_USAGE method in the component controller:

METHOD add_usage .

wd_this->mo_model->set_element_attribute( (1)

iv_model_node_name = CL_FDT_WD_MY_MODEL=>GC_MY_MODEL_NODE_NAME

iv_attribute_name = MyAttributeName

iv_value = iv_id ).

wd_this->mo_model->refresh_model( wd_this->wdctx_properties ). (2)

The incoming parameter IV_ID represents the ID of the created object. If the attribute is part of a flat model structure you can easily update the model by calling (1), providing the name of the model node and the name of the attribute. You use standard WD means to update the attribute in your WD context (model) node. This is needed if your context node has cardinality > 1 (table).

After the attribute is set, the model is refreshed (2). This means, the API setter and getter are called via your model class. This ensures that dependent attributes are also updated in the UI.

Note

When you have more than one parameter created by the user, you must memorize which parameter is created before raising the event. In the ADD_USAGE method, you can use this variable to differentiate between those parameters.

Page 102: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

102

16.5.2 Selecting an Existing BRFplus Object

If you want to bind a parameter against an existing BRFplus object within your action / expression UI, you can use the UI query.

The WD interface FDT_IWD_QUERY provides various methods to query for a specific BRFplus object. After calling one of those methods, a query dialog is displayed from which the user can choose an object. If the user has actually chosen an object, your component is notified and the ID of the object is provided.

Example

You have an attribute MY_ATTRIBUTE in your expression type, which is bindable to another expression.

To access the query, you must add the component (interface) FDT_IWD_QUERY to your component.

To trigger the query by a user action, create a method, SELECT_MY_ATTRIBUTE, in one of your WD controllers:

DATA: lo_comp_factory TYPE REF TO if_fdt_wd_component_factory.

IF wd_this->wd_cpuse_query( )->has_active_component( ) IS INITIAL. (1)

lo_comp_factory ?= cl_fdt_wd_factory=>if_fdt_wd_factory~get_instance( ).

lo_comp_factory->create_query_component(

io_usage = wd_this->wd_cpuse_query( )

io_configuration = wd_this->mo_configuration ).

ENDIF.

TRY.

lo_admin_data = cl_fdt_wd_service=>get_admin_data( wd_comp_controller->mv_id )(2)

lv_application_id = lo_admin_data->get_application( ).

wd_comp_controller->get_query( )->object_query(

io_calling_object = lo_admin_data

is_object_type = ls_object_type

iv_application_id = lv_application_id

iv_initial_search = abap_true

iv_type_fixed = abap_true

iv_multiple_selection = abap_false

).

CATCH cx_fdt_input INTO lx_fdt_input.

cl_fdt_wd_service=>report_exception(

io_message_manager = wd_this->wd_get_api( )->get_message_manager( )

ix_exception = lx_fdt_input ).

ENDTRY.

Page 103: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

103

(1) If the query is not already instantiated, this is done via the factory. Ensure that you supply the configuration handle (if_fdt_wd_configuration).

(2) The admin data instance of the current object is retrieved and the query is called.

The standard object query consists of the following parameters:

Parameter Type Description

IO_CALLING_PARAMETER Importing Mandatory:

Admin Data Reference of current displayed object (expression).

IS_OBJECT_TYPE Importing Object types, which are considered.

IV_APPLICATION_ID Importing Query can be limited to an application.

IV_INITIAL_SEARCH Importing If ABAP_TRUE, hit list is immediately displayed.

IV_TYPE_FIXED Importing User cannot change object type in the search dialog.

IV_MULTIPLE_SELECTION Importing If ABAP_TRUE, user can select multiple objects from hit list.

Note

IO_CALLING_PARAMETER is optional in the signatures of query methods. This will change in the future. Therefore, make sure that you always provide IO_CALLING_PARAMETER.

To receive the selected object(s), implement an event handler.

The query interface FDT_IWD_QUERY provides the event OBJECTS_SELECTED, which you can implement in an event handler HDL_OBJECTS_SELECTED.

DATA: lt_object TYPE fdtt_wd_object,

lx_fdt_wd TYPE REF TO cx_fdt_wd.

FIELD-SYMBOLS: <ls_object> TYPE fdts_wd_object.

**********************************************************************

READ TABLE mt_objects INDEX 1 ASSIGNING <ls_object>. (1)

wd_comp_controller->mo_model->set_element_attribute(

iv_model_node_name = wd_comp_controller->wdctx_properties (2)

iv_attribute_name = 'EXPRESSION_ID'

iv_value = <ls_object>-id

).

wd_comp_controller->mo_model->refresh_model( wd_comp_controller->wdctx_properties ). (3)

The selected objects are available in the importing table mt_objects (1) of the event.

The selected expression is set to the model node by the convenience method set_element_attribute.

The call of refresh_model (3) refreshes the view.

Page 104: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

104

Note

When you have more than one parameter that can be selected by the user, memorize which parameter is created before raising the event. In the event handler, you can then use this variable to differentiate between those parameters.

The previous example presents the usage of the OBJECT_QUERY method from the class CL_FDT_WD_QUERY_MODEL. This method controls the execution of the object query. In addition to this method, the CL_FDT_WD_QUERY_MODEL class has other useful methods for querying objects.

Object Description

ELEMENT_QUERY Retrieves elements from the query.

CONTEXT_QUERY Retrieves context elements.

ADVANCED_QUERY Retrieves BRFplus objects by specifying a list of object types in the IT_OBJECT_TYPES table and restricting them, based on the result type of expressions.

16.5.3 Navigating to Other BRFplus Objects

You can navigate to other objects within your UI. For example, you can create a link to another expression that is bound to an attribute of your expression type.

To navigate to another object, simply raise the event NAVIGATE_TO_OBJECT and provide the ID of the object. The event is available in the component controller of your component (implemented in interface FDT_IWD_OBJECT).

16.5.4 Object Menu

To enable the user to bind a BRFplus object to a parameter, use a link menu by which the user is able to choose an existing object or to create a new object. The scope of this service is for use within an expression type UI.

Page 105: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

105

The interface IF_FDT_WD_OBJECT_MENU implements the service to render the menu for binding objects. It includes the system objects (Standard). Further, it displays either the context data objects (render_menu_default) or the last accessed objects (render_menu). The number of these ‘quick accessible’ objects is limited. For accessing elements of a structure, the user must use the ‘select’ functionality (standard query).

Additionally, the standard menu items such as Select, Create and Remove are displayed. This interface allows you to customize the menu. Due to WD restriction, this menu has to be created before the user clicks on it.

Demo Component

The WD component FDT_WD_DEMO_OBJECT_MENU provides an example how to use the object menu service.

Rendering the Menu

To render the menu, implement the following steps (name of attributes/methods are proposals):

1. Create a menu for the link (UI element, but without any menu items!).

2. Create an attribute MO_OBJECT_MENU (public access) type ref to IF_FDT_WD_OBJECT_MENU (preferable in the ‘Custom/Action’ controller, public access).

3. Create an attribute MV_REFRESH_OBJECT_MENU, type boole_d (public access) in the component controller.

4. Implement a method ‘BUILD_OBJECT_MENU’ in a controller (it is preferable to do this in the Component / Action controller). Call this method from the wdmodifyview method in your view, if this method is called for the first time or if mv_refresh_object_menu = abap_true. You have to set mv_refresh_object_menu to true if the menu has to be refreshed (the user has selected another object, thus the menu must be updated).

5. Call the constructor by supplying the admin data of the maintained object and the UI configuration (should be available as mo_configuration in your WD comp controller).

Implementation of Method BUILD_OBJECT_MENU

The service interface IF_FDT_WD_OBJECT_MENU provides the following methods to render the menu:

RENDER_DEFAULT_MENU

This method renders a default menu, which includes accessing the context and the selection/creation of an expression.

Use this menu if you want to bind a context parameter or an expression to an attribute of your expression type. In most cases you use this method.

RENDER_MENU

This method renders a menu according to the supplied object_type (is_object_type).

It provides a Select <Object Type>, Create <Object Type>, and a number of last accessed objects, which fits to the object type.

These methods contain the following parameters:

Page 106: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

106

Parameter Type Description

IO_VIEW Importing View handle (provided in WDDOMODIFYVIEW).

IV_MENU_ID Importing ID of the (link) menu (UI element).

IV_ACTION_HANDLER Importing Action (in the view) which handles the object menu actions. You only need to define one action for all menu items.

IS_OBJECT_TYPE Importing Only RENDER_MENU: Defines the object type, which can be selected.

IV_ACTION_MODE Importing Only RENDER_MENU_DEFAULT: If true only actions will be considered for binding (instead of expressions).

IS_CONFIGURATION Importing Customizes the menu. For example, you can define the maximum items for the quick selection items. See type section in IF_FDT_WD_OBJECT_MENU. (Optional)

IV_BOUND_OBJECT_ID Importing Object which is currently bound to the parameter... initial is possible. If no object is bound, the delete menu item is not visible. (Optional)

IV_BIND_ENABLED_PATH Importing Path of enabled attribute (for enabling/disabling the menu items). This is normally UI_ADJUSTMENT.ENABLED; the context node supplied by FDT_IWD_OBJECT. (Optional)

Implementation Example for Method BUILD_OBJECT_MENU

DATA:

lo_configuration TYPE REF TO if_fdt_wd_configuration,

lo_factory TYPE REF TO if_fdt_wd_service_factory,

lo_node TYPE REF TO if_wd_context_node,

lo_node_mode TYPE REF TO if_wd_context_node,

lv_bound_object_id TYPE if_fdt_types=>id,

ls_object_type TYPE if_fdt_wd_types=>s_object_type_extended,

lt_element_type TYPE if_fdt_wd_object_menu=>t_element_type,

lo_caller TYPE REF TO if_fdt_admin_data,

lx_fdt_wd TYPE REF TO cx_fdt_wd.

*************************************************************************

TRY.

*create an instance of the object menu if this is the first call

IF wd_this->mo_object_menu IS NOT BOUND.

lo_factory ?= cl_fdt_wd_factory=>if_fdt_wd_factory~get_instance( ).

lo_caller = cl_fdt_wd_service=>get_admin_data( wd_this->mv_id ).

wd_this->mo_object_menu = lo_factory-

>get_object_menu( io_configuration = wd_this->mo_configuration

io_caller = lo_caller ).

ENDIF.

*you could call the set_filter... methods to filter out the available objects

*wd_this_mo_object_menu->set_filter...

*finally render the menu

wd_this->mo_object_menu->render_menu_default(

io_view = io_view

iv_action_handler = 'OBJECT_MENU_HANDLER'

* iv_bind_enabled_path = 'UI_ADJUSTMENT.ENABLED'

iv_menu_id = 'OBJECT_MENU' ).

CATCH cx_fdt_wd INTO lx_fdt_wd.

cl_fdt_wd_service=>report_exception( io_message_manager =

Page 107: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

107

wd_this->wd_get_api( )->get_message_manager( )

ix_wd_exception = lx_fdt_wd ).

ENDTRY.

You can add additional menu items but you must implement the action handler yourself.

If you want to change the text of a rendered menu, you can get the instance of the menu item by calling the method, GET_MENU_ITEM_BY_ID.

Filter for Data Object + Element Types

The methods SET_FILTER_DATA_OBJECT_TYPES, SET_FILTER_ELEMENT_TYPES, and SET_FILTER_OBJECTS provide the possibility to limit the display of instances to certain element / data object types. Use these filters if the result data object has to be a Boolean type.

Note

Be aware that the filter affects only the quick list (context data objects/history) and system objects.

If you call the query component according to the user action, you have to apply the corresponding filter for the query. The same is true if a new object is created.

Menu Actions

Create an action in the view to react on menu actions. This action must have the same name as the one you assigned by calling the RENDER…. methods.

Call the method GET_ACTION_PARAMETER to retrieve the parameters for the action to detect if the user wants to create/select/remove an object – or if the user has already selected an instance:

DATA: ls_action_parameter TYPE if_fdt_wd_object_menu=>s_action_parameter.

***************************************************************************

*retrieve the action parameter to do followup actions.

ls_action_parameter = wd_comp_controller->mo_object_menu-

>get_action_parameter( wdevent ).

*create/remove/select etc. an object regarding the action, which was triggered by the use

r

CASE ls_action_parameter-action.

*user wants to create a new object (via event CREATE_OBJECT)

WHEN if_fdt_wd_object_menu=>gc_action_param_create.

*user wants to select a context object via the UI context query (via FDT_IWD_QUERY-

>CONTEXT_QUERY)

WHEN if_fdt_wd_object_menu=>gc_action_param_context_query.

*user wants to select an expression via the standard query via methods of FDT_IWD_QUERY

WHEN if_fdt_wd_object_menu=>gc_action_param_query.

*user wants to remove the current bounded object (delete the attribute of your model node

)

WHEN if_fdt_wd_object_menu=>gc_action_param_remove.

*user has selected an instance...

*...the instance is provided in ls_action_parameter-object_id

*...the selected object type is provided in ls_action_parameter-object_type

WHEN if_fdt_wd_object_menu=>gc_action_param_obj_selected.

ENDCASE.

Page 108: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

108

Note

If the user assigns another object, you must refresh the object menu.

If you follow the described pattern, set the member variable mv_refresh_object_menu =

abap_true.

16.5.5 Other Services

IF_FDT_WD_STATE

An instance of this interface is available in the model class (mo_state) and in your WD component

(provided as a parameter in the INIT method).

It represents the state of the currently displayed object (e.g. is displayed, is unsaved, etc.) and is especially helpful if you want to develop more complex UIs, within which the layout is created dynamically. Look at the available methods.

CL_FDT_WD_SERVICE

This service class provides methods to assist you in developing your own UIs. See the following methods:

GET_DISPLAY_NAME

You should use this method to retrieve the display name for an object since the user can decide if he wants to see the name or the text for an object via the configuration. By providing the ID of the object and the configuration handle you retrieve the display name.

GET_ADMIN_DATA

Returns the admin data instance, by providing its ID and the configuration handle.

REPORT_EXCEPTION

Reports a BRFplus exception as user message(s) by providing the exception instance and the WD message handler.

REPORT_MESSAGES

Reports BRFplus messages as user messages by providing the messages and the WD message handler.

CONVERT_BACKEND_EXCEPTION

Every time you call a method in the backend, which can throw an exception, you must catch it and convert it to the CX_FDT_WD_BACKEND exception by using this method.

16.6 Testing If you implemented the UI components correctly, the expression type or action type should be available in the create dialog. To speed up the testing process during development, you can display your UI without the need to navigate to it. The prerequisite for the following shortcut is that there is an existing expression (instance) for your expression type available.

To display any object in BRFplus, you can simply add the URL parameter ID to the URL.

Example:

http://myServer:50000/sap/bc/webdynpro/sap/fdt_wd_workbench?sap-language=EN&sap-client=000&ID=00132120A5A802DB87A5A05EEFFC987B

Page 109: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

109

Recommendation

We recommend setting a breakpoint in the constructor method of CX_FDT. This is a good idea because all of the BRFplus exception classes inherit from CX_FDT, so whenever an error occurs, chances are high that you can catch it there.

Also, when catching exceptions in your code, use the MT_MESSAGE variable that is known to all exception class instances. In most of the cases, this variable contains information on the current exception that you will find helpful in understanding and solving the issue.

Page 110: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE

110

17 Related Content Wikipedia, Business Rules:

http://en.wikipedia.org/wiki/Business_rules

Wikipedia, Business Rule Management System: http://en.wikipedia.org/wiki/Business_Rule_Management_System

SCN, SAP NetWeaver Decision Service Management: http://scn.sap.com/docs/DOC-29158

SCN, Business Rule Framework plus: http://scn.sap.com/docs/DOC-8824

SCN, Business Rules Management http://scn.sap.com/community/brm

Page 111: Custom Expression Types and Action Types · 2019. 11. 12. · CUSTOM EXPRESSION TYPES AND ACTION TYPES – A STEP-BY-STEP GUIDE WITH EXAMPLE 2 About The Authors Christian Auth is

© 2014 SAP AG. All rights reserved.

SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP

BusinessObjects Explorer, StreamWork, SAP HANA, and other SAP

products and services mentioned herein as well as their respective

logos are trademarks or registered trademarks of SAP AG in Germany

and other countries.

Business Objects and the Business Objects logo, BusinessObjects,

Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius, and

other Business Objects products and services mentioned herein as

well as their respective logos are trademarks or registered trademarks

of Business Objects Software Ltd. Business Objects is an SAP

company.

Sybase and Adaptive Server, iAnywhere, Sybase 365, SQL

Anywhere, and other Sybase products and services mentioned herein

as well as their respective logos are trademarks or registered

trademarks of Sybase Inc. Sybase is an SAP company.

Crossgate, m@gic EDDY, B2B 360°, and B2B 360° Services are

registered trademarks of Crossgate AG in Germany and other

countries. Crossgate is an SAP company.

All other product and service names mentioned are the trademarks of

their respective companies. Data contained in this document serves

informational purposes only. National product specifications may vary.

These materials are subject to change without notice. These materials

are provided by SAP AG and its affiliated companies ("SAP Group")

for informational purposes only, without representation or warranty of

any kind, and SAP Group shall not be liable for errors or omissions

with respect to the materials. The only warranties for SAP Group

products and services are those that are set forth in the express

warranty statements accompanying such products and services, if

any. Nothing herein should be construed as constituting an additional

warranty.

www.sap.com