Monday 10 September 2018

How to change the annotations sap:label, sap:heading and sap:quickinfo

Introduction


A customer asked me today how to change the the properties sap:label, sap:heading and sap:quickinfo in an OData service that has been developed using ABAP code based implementation.

Instead of the data which is retrieved by the SAP Gateway framework by default from the underlying data element they wanted to use custom annotations and retrieve the same from other data elements.

Then I got the question how to change these annotations for CDS based OData Services.

<Annotations xmlns="http://docs.oasis-open.org/odata/ns/edm" Target="ZGW_PRODUCT_SRV.Product/Category">

<Annotation String="Label for category" Term="Common.Label"/>

<Annotation String="Heading for category" Term="Common.Heading"/>

<Annotation String="Quickinfo for category" Term="Common.QuickInfo"/>

</Annotations>

These annotations can be interpreted in SAPUI5 as well and if SAP Fiori Elements applications are used these vocabulary based annotions will be used instead of the default values that are set via sap:label, sap:heading and sap:quickinfo.

OData services based on ABAP Code based implementation


Suppose the original OData service would have an entity set ProductSet whose entity type Product is bound to the DDIC structure BAPI_EPM_PRODUCT_HEADER.

The three sandard  sap annotations mentioned above would look like as follows for the property Category.

<Property Name="Category"
...
sap:quickinfo="EPM: Product Category"
sap:label="Category"
sap:heading="Product Category"
...
/>

This is because the property Category is based on the data element SNWD_PRODUCT_CATEGORY.

SAP ABAP Tutorial and Materials, SAP ABAP Guides, SAP ABAP All Certifications, SAP ABAP Study Materials

Solution 1: Use of text elements


A flexible approach is to use text elements as the source for our vocabulary based annotations based on the Common Vocabulary.

The target of the following Annotation is the property Category of the entity type Product.

The above mentioned  annotations are generated if we add the following coding to our DEFINE method of the MPC_EXT class.

  METHOD define.
    DATA: lo_ann_target  TYPE REF TO /iwbep/if_mgw_vocan_ann_target.   " Vocabulary Annotation Target
    DATA: lo_annotation  TYPE REF TO /iwbep/if_mgw_vocan_annotation.   " Vocabulary Annotation
    DATA: lo_simp_value  TYPE REF TO /iwbep/if_mgw_vocan_simple_val.   " Vocabulary Annotation Simple Value
    DATA: lo_reference   TYPE REF TO /iwbep/if_mgw_vocan_reference.    " Vocabulary Annotation

    super->define( ).

    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_COMMON' iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'com.sap.vocabularies.Common.v1' iv_alias = 'Common' ).

    "annotations for entity type "Product" and property "Category"

    lo_ann_target = vocab_anno_model->create_annotations_target( 'Product/Category' ).
    lo_ann_target->set_namespace_qualifier( 'ZGW_PRODUCT_SRV' ).    "change the namespace to the SRV namespace

    "map text 001 to label
    lo_annotation = lo_ann_target->create_annotation( iv_term = 'Common.Label' ).
    lo_simp_value = lo_annotation->create_simple_value( ).
    lo_simp_value->set_string_from_text_element(
              iv_text_element_symbol = '001'
              io_text_element_container_ref = me ).

    "map text 002 to heading
    lo_annotation = lo_ann_target->create_annotation( iv_term = 'Common.Heading' ).
    lo_simp_value = lo_annotation->create_simple_value( ).
    lo_simp_value->set_string_from_text_element(
               iv_text_element_symbol = '002'
               io_text_element_container_ref = me ).

    "map text 003 to quickinfo
    lo_annotation = lo_ann_target->create_annotation( iv_term = 'Common.QuickInfo' ).
    lo_simp_value = lo_annotation->create_simple_value( ).
    lo_simp_value->set_string_from_text_element(
           iv_text_element_symbol = '003'
           io_text_element_container_ref = me ).

  ENDMETHOD.

Please note that we are using the method set_string_from_text_element.

Caution: If you use the  method set_string the annotations will not offer support for multiple languages.

Text elements for a class can be maintained by using transaction SE24. In the edit mode choose the push button Text elements or press F5.

SAP ABAP Tutorial and Materials, SAP ABAP Guides, SAP ABAP All Certifications, SAP ABAP Study Materials

We create three text elements and translate the same to German. You have to make sure to activate your changes first.

SAP ABAP Tutorial and Materials, SAP ABAP Guides, SAP ABAP All Certifications, SAP ABAP Study Materials

After having translated the texts in German (or any other language) we can test the metadata document of our Service.

SAP ABAP Tutorial and Materials, SAP ABAP Guides, SAP ABAP All Certifications, SAP ABAP Study Materials

It turns out that when logging on in German the SAP Gateway client Shows the following response.

<Annotations xmlns="http://docs.oasis-open.org/odata/ns/edm" Target="ZGW_PRODUCT_SRV.Product/Category">

<Annotation String="Label für Kategorie" Term="Common.Label"/>

<Annotation String="Heading für Kategorie" Term="Common.Heading"/>

<Annotation String="Quickinfo für Kategorie" Term="Common.QuickInfo"/>

</Annotations>

Solution 2: Use of data elements


The texts that can be assigned to vocabulary based annotations can also be retrieved from existing data elements.

These might have the Advantage that the field descriptions are already maintained and translated.

In our DEFINE method of the MPC_EXT class we map four field descriptions to the vocabulary based annotations Common.Label, Common.Heading, Commona.QuickInfo and Common.Text.

  METHOD define.
    DATA: lo_ann_target  TYPE REF TO /iwbep/if_mgw_vocan_ann_target.   " Vocabulary Annotation Target
    DATA: lo_annotation  TYPE REF TO /iwbep/if_mgw_vocan_annotation.   " Vocabulary Annotation
    DATA: lo_simp_value  TYPE REF TO /iwbep/if_mgw_vocan_simple_val.   " Vocabulary Annotation Simple Value
    DATA: lo_reference   TYPE REF TO /iwbep/if_mgw_vocan_reference.    " Vocabulary Annotation

    super->define( ).

    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_COMMON' iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'com.sap.vocabularies.Common.v1' iv_alias = 'Common' ).

    "annotations for entity type "Product" and property "Category"

    lo_ann_target = vocab_anno_model->create_annotations_target( 'Product/Category' ).
    lo_ann_target->set_namespace_qualifier( 'ZGW_PRODUCT_SRV' ).    "change the namespace to the SRV namespace

    "map medium description to label
    lo_annotation = lo_ann_target->create_annotation( iv_term = 'Common.Label' ).
    lo_simp_value = lo_annotation->create_simple_value( ).
    lo_simp_value->set_string_from_data_element(
      EXPORTING
        iv_text_type = /iwbep/if_mgw_med_odata_types=>gcs_vocan_text_types-data_element_medium " Vocabulary Annotation text type
        iv_text_id   =   'S_SEATSMAX'                                                               " Vocabulary Annotation text ID
    ).

    "map heading to heading
    lo_annotation = lo_ann_target->create_annotation( iv_term = 'Common.Heading' ).
    lo_simp_value = lo_annotation->create_simple_value( ).
    lo_simp_value->set_string_from_data_element(
        EXPORTING
          iv_text_type = /iwbep/if_mgw_med_odata_types=>gcs_vocan_text_types-data_element_heading " Vocabulary Annotation text type
          iv_text_id   =   'S_SEATSMAX'                                                               " Vocabulary Annotation text ID
      ).

    "map quickinfo to quickinfo
    lo_annotation = lo_ann_target->create_annotation( iv_term = 'Common.QuickInfo' ).
    lo_simp_value = lo_annotation->create_simple_value( ).
    lo_simp_value->set_string_from_data_element(
        EXPORTING
          iv_text_type = /iwbep/if_mgw_med_odata_types=>gcs_vocan_text_types-data_element_quickinfo" Vocabulary Annotation text type
          iv_text_id   =   'S_SEATSMAX'                                                               " Vocabulary Annotation text ID
      ).

    "map long description to Text
    lo_annotation = lo_ann_target->create_annotation( iv_term = 'Common.Text' ).
    lo_simp_value = lo_annotation->create_simple_value( ).
    lo_simp_value->set_string_from_data_element(
        EXPORTING
          iv_text_type = /iwbep/if_mgw_med_odata_types=>gcs_vocan_text_types-data_element_long " Vocabulary Annotation text type
          iv_text_id   =   'S_SEATSMAX'                                                               " Vocabulary Annotation text ID
      ).

*    CATCH /iwbep/cx_mgw_med_exception.

  ENDMETHOD.

The result in the $metadata document looks like:

<Annotations xmlns="http://docs.oasis-open.org/odata/ns/edm" Target="ZGW_PRODUCT_SRV.Product/Category">

<Annotation String="Max. capacity econ." Term="Common.Label"/>

<Annotation String="Capacity in economy class" Term="Common.Heading"/>

<Annotation String="Maximum capacity in economy class" Term="Common.QuickInfo"/>

<Annotation String="Maximum capacity economy class" Term="Common.Text"/>

</Annotations>

Show the result (of Solution 1) in a SAP Fiori Elements App


If we generate a list reporting app to consume our service we will see that column for the product category now uses the value Label for category stored in our text element rather than using the value Category which is stored in sap:label.

<EntityType sap:content-version="1" Name="Product">
<Key>
<PropertyRef Name="ProductId"/>
</Key>
<Property Name="ProductId" sap:label="Product ID" MaxLength="10" Nullable="false" Type="Edm.String"/>
...
<Property Name="Category"  sap:label="Category" MaxLength="40" Nullable="false" Type="Edm.String"/>
<Property Name="Price"     sap:label="Price" Type="Edm.Decimal" Scale="4" Precision="23"/>
...
</EntityType>

The heading of the other columns (here: Price and Product ID) are using the text provided by the annotation sap:label instead.

SAP ABAP Tutorial and Materials, SAP ABAP Guides, SAP ABAP All Certifications, SAP ABAP Study Materials

Show the result in a SAP Fiori Master Detail App


As an example how to consume vocabulary based annotations in a SAPUI5 app I have generated a SAP Fiori application based on the Master Detail template.

When you add the following code in your Detail.view.xml of your Master Detail App.

<ObjectHeader
id="objectHeader"
title="{Name}"
number="{
path: 'Price',
formatter: '.formatter.currencyValue'
}"
numberUnit="{CurrencyCode}">
        <attributes>
    <ObjectAttribute text="{Category}" />
    <ObjectAttribute text="{Category/##com.sap.vocabularies.Common.v1.Label/String}" />
    <ObjectAttribute text="{Category/##com.sap.vocabularies.Common.v1.Heading/String}" />
<ObjectAttribute text="{Category/##com.sap.vocabularies.Common.v1.QuickInfo/String}" />
</attributes>
<!-- <ObjectAttribute text="{Category/#@sap:label}" /> -->
</ObjectHeader>

The resulting Screen looks like follows:

SAP ABAP Tutorial and Materials, SAP ABAP Guides, SAP ABAP All Certifications, SAP ABAP Study Materials

This means that you are able to change the default values for sap:label, sap:heading and sap:quickinfo if needed.

OData services based on CDS views


If an OData Service is based on CDS views the recommended way to pubish it as an OData Service is to use the Service Builder and the Reference Data Source Approach if there is the need to add functionality which is not supported by CDS views yet. 

Also for CDS view based OData services the annotations sap:label, sap:heading and sap:quickinfo are taken from the data elements of the underlying data base tables.  Reason is that only this way it is ensured that classic UI’s based used via SAPGUI show the same descriptions.

Since you cannot change the texts of data elements delivered by SAP you have to use the annoations @EndUserText.

@EndUserText.label: '<text>'
@EndUserText.quickInfo: '<text>'

This way it is however only possible to set Customer specific values for sap:label and sap:quickinfo. 

Suppose we have an CDS view that uses the following annotations.

define view Z_C_Product
  as select from snwd_pd as Product
{
      //Product
  key client,
  key product_id,
      category,

      
      @EndUserText: {
        label: 'MyLabel' ,
        quickInfo: 'MyQuickInfo'
      }
      Product.product_id as ProductId
}

If you have maintained the DDL source Code using English as your logon language the annoations for the property ProductId would look like follows:

<Property sap:label="MyLabel" Name="ProductId" 
sap:quickinfo="MyQuickInfo" sap:display-format="UpperCase" 
MaxLength="10" Type="Edm.String"/>

But if you would log on in a different language such as German you would only get an empty string for the annotation sap:label.

<Property Name="ProductId" sap:label="" 
sap:display-format="UpperCase" 
MaxLength="10" Type="Edm.String"/>

In order to achieve multi language support you have to use transaction SE63.

1. Start transaction SE63
2. From the menu choose Translation –> ABAP Objects –> Short Texts or choose Ctrl+F2

3.In the Object Type Selection (Object Groups) dialogue expand the entry A5 User Interface Texts and choose the entry DDLS CDS Views.

SAP ABAP Tutorial and Materials, SAP ABAP Guides, SAP ABAP All Certifications, SAP ABAP Study Materials

4. Enter the name of your CDS view in the field Object Name.
5. Choose the language in which you have maintained your CDS DDL source as the Source Language.
6. Choose your desired Target Language.
7. Press Edit and translate your Texts.

SAP ABAP Tutorial and Materials, SAP ABAP Guides, SAP ABAP All Certifications, SAP ABAP Study Materials

SAP ABAP Tutorial and Materials, SAP ABAP Guides, SAP ABAP All Certifications, SAP ABAP Study Materials

Now the property would show the following metadata when logging on in German

<Property Name="ProductId" sap:quickinfo="MeinQuicInfoGerman" 
sap:label="MeinLabel (German)" sap:display-format="UpperCase" 
MaxLength="10" Type="Edm.String"/>

3 comments:

  1. Thanks for sharing the useful information. In this Machine Learning blogs links very useful to me to upgrade my knowledge. below link is also very interesting about Machine Learning.
    sap abap training in vijayawada

    ReplyDelete
  2. I went through your blog. This is really worth in learning something very useful. Delphi Computech has also helped many SAP Aspirants for the last 18 years. If anyone is interested in SAP Finance and Controlling (FICO) Course, click below.
    SAP FICO Training in Pune

    ReplyDelete
  3. Nice blog. Livewire Technologies providing transparent and consistent communication with all stakeholders to build a long and mutually beneficial association.

    ReplyDelete