ABAP - CDS Extraktor
How does the CDS extractor work in ABAP and what challenges are there when developing with it? In this article we will look at a few details.
Table of contents
In this article we will look at the extraction of CDS views and hierarchies, which we also use to prepare the CDS information. You will learn something about the extractor as well as the special features of the standard classes.
Introduction
A while ago we published the CDS Field Mapping in the beta phase. This is a list of Core Data Services and tables and their connection via the fields. If you switch to ABAP Cloud, you are faced with the challenge of having to use the new Core Data Services instead of the familiar tables. You can easily find the mapping from the old table to the new CDS views in the Cloudification Repository or on the actual object in your system.
But which field is actually mapped to which field in the Core Data Service and is it really the data you are looking for? This is usually not deducible at a glance, since the mapping runs across several Core Data Services. Therefore, there is little point in having to painstakingly understand each field in detail.
Execution
There are 4 public methods available for executing the extractor. These methods are briefly explained here again:
- GET_MAPPING_IN_JSON_FORMAT - Reading the repository, determining the mapping as a table and converting the data into JSON format.
- GET_MAPPING_AS_TABLE - Reading the repository and determining the mapping as a table
- GET_MAPPING_FROM_CDS - Determining the mapping based on a table and a Core Data Service.
- GET_RELEVANT_OBJS_FROM_REPO - Reading the repository and compiling the open objects for determining the mapping.
The MAIN method always uses the GET_MAPPING_IN_JSON_FORMAT method to determine the data. Not all data is read at once. Known mappings are loaded from the GitHub repository beforehand and only combinations that are not yet mapped are processed. You can use the two ranges LT_R_CDS and LT_R_TABLE to limit the set again if you only want to test different objects.
If you want to execute a combination that has already been mapped or does not exist at all, you can control this using the LS_FIXED structure. Here is an example:
ls_fixed = VALUE #( cds = 'I_CADOCUMENTBPITEMPHYSICAL'
table = 'DFKKOP' ).
Comparison repository
The logic states that in the first step we read the Cloudification repository and read all combinations of tables to Core Data Service. We then read the mapping tool's repository for the data that has already been mapped and add views that have not been released. This gives us a set of objects that still need to be mapped. If all objects have already been mapped, the logic will no longer carry out any determination. You can find the corresponding links to the objects as constants in the class.
CONSTANTS c_url_cloudification_repo TYPE string VALUE `https://raw.githubusercontent.com/SAP/abap-atc-cr-cv-s4hc/main/src/objectReleaseInfoLatest.json`.
CONSTANTS c_url_mappings TYPE string VALUE `https://raw.githubusercontent.com/Xexer/abap-cds-field-mapping/main/mapping/core-data-services.json`.
CONSTANTS c_url_not_released TYPE string VALUE `https://raw.githubusercontent.com/Xexer/abap-cds-field-mapping/main/mapping/not-released-views.json`.
Extraction
In this section we will go a little deeper into data extraction. We will therefore start with the actual method which is called recursively in order to go through the various levels of Core Data Services. At the end the logic gives us a table in this form.
We can then use the table to check whether we can get from the Core Data Service to the database field by reading down the various levels. Once we have found an entry with the table we are looking for, we return the field name (FIND_TABLE_FIELD method). In this example that would be:
- I_CADOCUMENTBPITEMPHYSICAL | CompanyCode -> I_CADOCUMENTBPITEM | COMPANYCODE
- I_CADOCUMENTBPITEM | COMPANYCODE -> DFKKOP | BUKRS
CDS information
Let's now start with the recursive determination of the data. To do this, we use the standard class XCO_CDS to get the information about our object. In the method GET_FIELDS_N_CONTENT_FROM_CDS we want to read the fields and the context.
DATA(lo_cds) = xco_cds=>view( id_cds ).
IF lo_cds->exists( ).
es_content = lo_cds->content( )->get( ).
et_fields = lo_cds->fields->all->get( ).
ENDIF.
To do this, we create a CDS object, check whether it exists and have the fields given to us in the form of objects, as well as the context with further information about the object. The context receives information about the data source, i.e. our next object, and about possible other objects.
If we then look at the Core Data Service, we find the same information about the data source and that an alias was used for the data.
We had started developing the class XCO_CP_CDS back then, as this is also released for ABAP Cloud. However, the class filters out objects without C1 release, which means we can never get to the table because the other views are not released.
Preparation
Unfortunately, the fields are not always simple mappings; in some cases, CDS functions are used, for example to perform a cast or to determine an absolute value.
Currently, we can only access the contents of the fields before the alias via the expression. If we look at the structure, the relevant information would be here to resolve the fields, but we cannot access the attributes because they are set to private.
However, we can have the complete statement returned to us and then put it together so that we can then take it apart ourselves.
DATA(lo_strings) = io_expression->if_xco_text~get_lines( ).
DATA(ld_result) = concat_lines_of( table = lo_strings->value
sep = ` ` ).
We then try to resolve the functions and get to the actual field using the REPLACE_CDS_FUNCTIONS method. To do this, we break down the functions one by one and get a table from the outside in.
We therefore start with the last element and take the data as the field name. At this point it is a simple logic and we do not currently support complex statements with multiple component groups, such as CASE.
ALIAS
Finally, we have to replace the alias in some views; this can consist of the name of the view or use an alias itself. LD_RESULT contains the currently determined field, which still has an ALIAS in its name. In the context of the Core Data Service, you can find the information on ENTITY (the current CDS view) and the ALIAS (alias of the entity) under DATA_SOURCE. Using one of these two pieces of information, we can then resolve the ALIAS on the field.
Source code
This explains the extractor and makes it complete. If you are interested in the source code as a whole, you can find it in our GitHub repository. If you find any errors, we would be happy to receive an issue in the repository. Otherwise, you can also contribute with additional views/tables that may not necessarily have been released by SAP.
Automation
What happens next with the mapping? Basically, you can now use the mapping to learn and use the new entities and fields in your specialist module. We are working on another tool to use the repository to convert SELECT statements. The tool is currently in the ALPHA phase and can only convert very simple statements.
Conclusion
To get all the information about a CDS view and the mapping, a little more effort is required. The advantage of the list is the time you can save by using the information. If you are more interested in how it works, you can look at the source code in the repository.