Skip to content

Lesson 5 — CDS Associations & Path Expressions ​

In Lesson 4, you combined related data with explicit joins:

text
/DMO/CONNECTION
   ├─ INNER JOIN Carrier
   ├─ INNER JOIN Origin Airport
   └─ INNER JOIN Destination Airport
            ↓
        Route model

That solved an immediate problem: combine several sources into one result.

The relationships themselves are useful beyond one fixed result:

text
Connection → Carrier
Connection → Origin Airport
Connection → Destination Airport

ABAP CDS provides associations to model those relationships explicitly and make them reusable.

In this lesson, you will build:

text
/DMO/CONNECTION
      ↓
ZI_ROUTE_ASSOC_###
      ├── _Carrier ─────────────► /DMO/I_CARRIER
      ├── _OriginAirport ───────► /DMO/I_AIRPORT
      └── _DestinationAirport ──► /DMO/I_AIRPORT

You will use path expressions to retrieve target fields, expose the associations themselves, and follow those associations directly in ADT Data Preview.


Lesson information ​

DurationAbout 120–150 minutes
EnvironmentSAP BTP ABAP Trial
Development toolEclipse with ABAP Development Tools (ADT)
PrerequisitesLesson 1, Lesson 2, Lesson 3, and Lesson 4
Primary source/DMO/CONNECTION
Association targets/DMO/I_CARRIER, /DMO/I_AIRPORT
CDS entityZI_ROUTE_ASSOC_###
ReaderZCL_ROUTE_ASSOC_READER_###
RunnerZCL_CDS_L05_###

Learning objectives ​

After completing this lesson, you should be able to:

  • explain what a CDS association represents;
  • distinguish an explicit join from an association;
  • explain that associations are directional;
  • define a CDS association;
  • identify its source and target;
  • choose a meaningful association alias;
  • explain [0..1], [1..1], [0..*], and [1..*];
  • choose cardinality based on the real relationship;
  • write an association ON condition;
  • use $projection;
  • explain why a to-one association should normally match the complete target key;
  • use CDS path expressions;
  • explain what happens when a path target field is used;
  • expose an association in the element list;
  • follow an exposed association in ADT Data Preview;
  • distinguish a scalar path field from an exposed relationship;
  • query scalar association-derived fields in SQL Console;
  • consume the CDS model through a Reader;
  • explain how associations prepare the model for RAP and service navigation.

Before you start ​

Replace ### with your student/group suffix.

Example:

text
ZI_ROUTE_ASSOC_###         → ZI_ROUTE_ASSOC_017
ZCL_ROUTE_ASSOC_READER_### → ZCL_ROUTE_ASSOC_READER_017
ZCL_CDS_L05_###            → ZCL_CDS_L05_017

ABAP Cloud and /DMO/*

The /DMO/* artifacts used here are SAP Flight Reference Scenario demo/tutorial content.

For productive ABAP Cloud development, consume SAP functionality through APIs released for the applicable cloud-development contract.


1. Revisit the Lesson 4 model ​

Lesson 4 used explicit joins:

abap
inner join /dmo/carrier as Carrier
  on Connection.carrier_id = Carrier.carrier_id

inner join /dmo/airport as OriginAirport
  on Connection.airport_from_id = OriginAirport.airport_id

inner join /dmo/airport as DestinationAirport
  on Connection.airport_to_id = DestinationAirport.airport_id

This says:

For this CDS result, combine these sources now.

Associations let us say something more reusable:

text
A Connection has a Carrier relationship.
A Connection has an Origin Airport relationship.
A Connection has a Destination Airport relationship.

2. What is a CDS association? ​

A CDS association is a named relationship from an association source to an association target.

Conceptually:

text
Connection ── _Carrier ──► Carrier

An association has:

text
target
name/alias
cardinality
ON condition

The ON condition describes how source and target records correspond.

TIP

Think of an association as a named navigation path between data entities.


3. Associations are directional ​

If you define:

text
Connection → Carrier

that does not automatically define:

text
Carrier → Connection

The association belongs to its source entity.

If reverse navigation is needed, it needs its own model relationship.

This becomes important later when RAP models parent/child relationships explicitly.


4. Why this lesson uses CDS targets ​

This lesson targets SAP's demo CDS entities:

text
/DMO/I_CARRIER
/DMO/I_AIRPORT

rather than directly targeting the database tables.

The Flight Reference Scenario exposes:

text
/DMO/I_CARRIER
  AirlineID
  Name
  CurrencyCode

and:

text
/DMO/I_AIRPORT
  AirportID
  Name
  City
  CountryCode

This gives a useful architecture:

text
Your CDS entity
      ↓ association
Reusable target CDS entity
      ↓
Persistence

5. Inspect /DMO/I_CARRIER ​

Press:

text
Ctrl + Shift + A

Search for:

text
/DMO/I_CARRIER

Open its Data Definition.

Identify:

text
AirlineID
Name
CurrencyCode

The target key is:

text
AirlineID

Use Data Preview if useful.


6. Inspect /DMO/I_AIRPORT ​

Open:

text
/DMO/I_AIRPORT

Identify:

text
AirportID
Name
City
CountryCode

The target key is:

text
AirportID

Before writing any association, you should understand the key of its target.


7. Association syntax ​

A basic association looks like:

abap
association [1..1] to /DMO/I_Carrier as _Carrier
  on <condition>

Break it down:

PartMeaning
associationdefine a relationship
[1..1]target cardinality
totarget follows
/DMO/I_Carriertarget CDS entity
_Carrierassociation name
onrelationship condition

8. Association naming ​

This course uses names such as:

text
_Carrier
_OriginAirport
_DestinationAirport

The leading underscore is a common SAP CDS naming style for associations.

The underscore is not a CDS keyword and is not what makes something an association.

Use names that describe the target's role.


9. Cardinality ​

Cardinality describes how many target records are expected for one source record.

Common forms:

CardinalityMeaning
[0..1]zero or one
[1..1]exactly one
[0..*]zero, one, or many
[1..*]one or many

For the demo connection model:

text
one Connection → one Carrier
one Connection → one Origin Airport
one Connection → one Destination Airport

Use:

text
[1..1]

for these relationships.

Cardinality is part of the model

Do not copy [1..1] mechanically.

Cardinality must agree with the real relationship and the ON condition.


10. Create ZI_ROUTE_ASSOC_### ​

Right-click your package:

text
New
  → Other ABAP Repository Object
  → Core Data Services
  → Data Definition

Enter:

text
Name:        ZI_ROUTE_ASSOC_###
Description: Lesson 5 - Route Associations

Choose the course transport if required.

Select a CDS View Entity template.

Confirm:

abap
define view entity

and finish.


11. Start with the Connection fields ​

Enter:

abap
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Route with Associations'

define view entity ZI_Route_Assoc_###
  as select from /dmo/connection as Connection
{
  key Connection.carrier_id       as CarrierId,
  key Connection.connection_id    as ConnectionId,

      Connection.airport_from_id  as OriginAirportId,
      Connection.airport_to_id    as DestinationAirportId,
      Connection.departure_time   as DepartureTime,
      Connection.arrival_time     as ArrivalTime,
      Connection.distance         as Distance,
      Connection.distance_unit    as DistanceUnit
}

Replace ###.

Check:

text
Ctrl + F2

Activate:

text
Ctrl + F3

Preview:

text
F8

12. Add _Carrier ​

Place the association between the data source and the element list:

abap
association [1..1] to /DMO/I_Carrier as _Carrier
  on $projection.CarrierId = _Carrier.AirlineID

Your source section becomes:

abap
define view entity ZI_Route_Assoc_###
  as select from /dmo/connection as Connection

    association [1..1] to /DMO/I_Carrier as _Carrier
      on $projection.CarrierId = _Carrier.AirlineID

{
  ...
}

13. What is $projection? ​

The persistence source provides:

text
Connection.carrier_id

Your CDS entity exposes it as:

text
CarrierId

$projection refers to an element of the current CDS projection:

abap
$projection.CarrierId

So:

abap
on $projection.CarrierId = _Carrier.AirlineID

means:

text
current entity CarrierId
=
associated carrier AirlineID

This keeps the relationship aligned with the current CDS model's element names.


14. Complete target-key reasoning ​

/DMO/I_CARRIER is identified by:

text
AirlineID

The association matches:

text
CarrierId → AirlineID

That is a complete target-key relationship.

For a to-one association, checking the target key is essential.

You will see a composite target key in the practice assignment.


15. Use the association with a path expression ​

Add:

abap
_Carrier.Name as CarrierName,

This path expression contains:

text
_Carrier
  ↓
Name

Read it as:

Navigate through _Carrier and use the target's Name element.

The resulting scalar element in your entity is:

text
CarrierName

16. Activate and preview ​

Run:

text
Ctrl + F2
Ctrl + F3
F8

You should now see:

text
CarrierId
CarrierName

CarrierName is retrieved through the association path.


17. What happens when a path target field is used? ​

The association itself defines the relationship.

When you request a target field:

abap
_Carrier.Name

the relationship must be instantiated to retrieve the target data.

Current CDS behavior uses a left outer join by default for a path target field in a CDS element list.

Conceptually:

text
association declaration
   =
relationship model

path target field
   =
use relationship to retrieve target value

18. Join vs association ​

Lesson 4:

text
Connection
  INNER JOIN Carrier

The join is fixed into the source expression.

Lesson 5:

text
Connection
  association → Carrier

The relationship can then be:

text
used through a path
exposed for navigation
reused by consumers

Associations are still translated into database operations when used. They are a higher-level relationship model, not a replacement for relational execution.


19. Add _OriginAirport ​

Add:

abap
association [1..1] to /DMO/I_Airport as _OriginAirport
  on $projection.OriginAirportId = _OriginAirport.AirportID

The relationship is:

text
OriginAirportId → AirportID

20. Add Origin path fields ​

Add:

abap
_OriginAirport.Name        as OriginAirportName,
_OriginAirport.City        as OriginCity,
_OriginAirport.CountryCode as OriginCountryCode,

Activate and preview.

Verify that the airport ID and descriptive values match.


21. Add _DestinationAirport ​

Add:

abap
association [1..1] to /DMO/I_Airport as _DestinationAirport
  on $projection.DestinationAirportId = _DestinationAirport.AirportID

The same target CDS entity is now used in another role.

Role-based names make the distinction clear:

text
_OriginAirport
_DestinationAirport

22. Add Destination path fields ​

Add:

abap
_DestinationAirport.Name        as DestinationAirportName,
_DestinationAirport.City        as DestinationCity,
_DestinationAirport.CountryCode as DestinationCountryCode,

Activate and preview.


23. Model before association exposure ​

Your entity can now look like:

abap
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Route with Associations'

define view entity ZI_Route_Assoc_###
  as select from /dmo/connection as Connection

    association [1..1] to /DMO/I_Carrier as _Carrier
      on $projection.CarrierId = _Carrier.AirlineID

    association [1..1] to /DMO/I_Airport as _OriginAirport
      on $projection.OriginAirportId = _OriginAirport.AirportID

    association [1..1] to /DMO/I_Airport as _DestinationAirport
      on $projection.DestinationAirportId = _DestinationAirport.AirportID

{
  key Connection.carrier_id       as CarrierId,
  key Connection.connection_id    as ConnectionId,

      _Carrier.Name               as CarrierName,

      Connection.airport_from_id  as OriginAirportId,
      _OriginAirport.Name         as OriginAirportName,
      _OriginAirport.City         as OriginCity,
      _OriginAirport.CountryCode  as OriginCountryCode,

      Connection.airport_to_id    as DestinationAirportId,
      _DestinationAirport.Name        as DestinationAirportName,
      _DestinationAirport.City        as DestinationCity,
      _DestinationAirport.CountryCode as DestinationCountryCode,

      Connection.departure_time   as DepartureTime,
      Connection.arrival_time     as ArrivalTime,
      Connection.distance         as Distance,
      Connection.distance_unit    as DistanceUnit
}

This uses associations internally, but the relationships themselves are not yet exposed.


24. Expose an association ​

Add the association name to the element list:

abap
_Carrier

Do the same for:

abap
_OriginAirport
_DestinationAirport

Near the end of the element list:

abap
      _Carrier,
      _OriginAirport,
      _DestinationAirport

Now the relationships themselves are part of the public CDS model.


25. Final ZI_ROUTE_ASSOC_### ​

abap
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Route with Associations'

define view entity ZI_Route_Assoc_###
  as select from /dmo/connection as Connection

    association [1..1] to /DMO/I_Carrier as _Carrier
      on $projection.CarrierId = _Carrier.AirlineID

    association [1..1] to /DMO/I_Airport as _OriginAirport
      on $projection.OriginAirportId = _OriginAirport.AirportID

    association [1..1] to /DMO/I_Airport as _DestinationAirport
      on $projection.DestinationAirportId = _DestinationAirport.AirportID

{
  key Connection.carrier_id       as CarrierId,
  key Connection.connection_id    as ConnectionId,

      _Carrier.Name               as CarrierName,

      Connection.airport_from_id  as OriginAirportId,
      _OriginAirport.Name         as OriginAirportName,
      _OriginAirport.City         as OriginCity,
      _OriginAirport.CountryCode  as OriginCountryCode,

      Connection.airport_to_id    as DestinationAirportId,
      _DestinationAirport.Name        as DestinationAirportName,
      _DestinationAirport.City        as DestinationCity,
      _DestinationAirport.CountryCode as DestinationCountryCode,

      Connection.departure_time   as DepartureTime,
      Connection.arrival_time     as ArrivalTime,
      Connection.distance         as Distance,
      Connection.distance_unit    as DistanceUnit,

      _Carrier,
      _OriginAirport,
      _DestinationAirport
}

Check and activate:

text
Ctrl + F2
Ctrl + F3

26. Scalar path field vs exposed association ​

Compare:

abap
_Carrier.Name as CarrierName

with:

abap
_Carrier

The first creates a scalar result element:

text
CarrierName

The second exposes the relationship itself.

Think:

text
_Carrier.Name
=
give this entity a CarrierName field

_Carrier
=
make the Carrier relationship navigable

27. Follow an association in Data Preview ​

Open Data Preview:

text
F8

Now use the ADT association-navigation feature.

Step 27.1 ​

Open:

text
Follow Association

from Data Preview.

Depending on ADT layout/version, this can be available from the table context menu or navigation/breadcrumb controls.

Step 27.2 ​

Choose:

text
_Carrier

ADT navigates to the associated target data.

You should see target fields such as:

text
AirlineID
Name
CurrencyCode

Step 27.3 ​

Use the breadcrumb/navigation control to return to:

text
ZI_ROUTE_ASSOC_###

Step 27.4 ​

Follow:

text
_OriginAirport

Inspect:

text
AirportID
Name
City
CountryCode

Step 27.5 ​

Repeat for:

text
_DestinationAirport

TIP

An exposed association is now visible as an actual navigation relationship in the development tooling.


28. Why exposed associations matter ​

Without exposing _Carrier, your entity can still use:

abap
_Carrier.Name

internally.

Exposing:

abap
_Carrier

adds the relationship itself to the entity's public model.

That matters later for:

text
other CDS models
projection layers
service navigation
RAP models

29. Path expressions can be longer ​

Conceptually, path expressions can navigate through more than one association:

text
_Association1._Association2.Field

For example:

text
Booking
  ↓ _Customer
Customer
  ↓ _Country
Country

The exact allowed use depends on cardinality, context, filters, and path-expression rules.

This lesson deliberately uses one association step at a time.


30. To-one vs to-many ​

Our guided associations are to-one:

text
Connection → Carrier
Connection → Origin Airport
Connection → Destination Airport

A different direction can be to-many:

text
Carrier → Connections

One carrier can have several connections.

That could be modeled as:

text
[0..*]

The practice includes this as an optional challenge.


31. Why cardinality matters ​

Do not treat cardinality as a comment.

It influences how CDS understands the relationship and can influence generated SQL/optimization behavior.

Before declaring to-one, ask:

text
Can zero targets exist?
Can multiple targets exist?
Does the ON condition match the target key?

32. Path target join attributes ​

The default CDS path target field uses left outer join semantics.

Current CDS also supports a path attribute such as:

abap
_Carrier[inner].Name

to request inner-join behavior for that path.

Do not change the lesson model to this form.

The important point is to understand that:

text
association cardinality

and:

text
join behavior when a path is used

are related but different concepts.


33. SQL Console ​

Open SQL Console and query:

abap
SELECT FROM zi_route_assoc_###
  FIELDS CarrierId,
         ConnectionId,
         CarrierName,
         OriginAirportId,
         OriginCity,
         DestinationAirportId,
         DestinationCity
  ORDER BY CarrierId,
           ConnectionId

The consumer sees ordinary scalar elements.

It does not repeat the associations or path expressions.


34. Filter a path-derived element ​

Use a country code that exists in your tenant.

Example:

abap
SELECT FROM zi_route_assoc_###
  FIELDS CarrierId,
         ConnectionId,
         CarrierName,
         OriginCity,
         OriginCountryCode,
         DestinationCity,
         DestinationCountryCode
  WHERE OriginCountryCode = 'DE'
  ORDER BY CarrierId,
           ConnectionId

OriginCountryCode was derived through:

text
_OriginAirport.CountryCode

but the SQL consumer uses the exposed scalar name.


35. Create ZCL_ROUTE_ASSOC_READER_### ​

Create a normal ABAP class.

Do not implement:

text
IF_OO_ADT_CLASSRUN

Define:

abap
CLASS zcl_route_assoc_reader_### DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.

    TYPES tt_routes
      TYPE STANDARD TABLE OF zi_route_assoc_###
      WITH EMPTY KEY.

ENDCLASS.

36. Add Reader methods ​

Add:

abap
METHODS get_all
  RETURNING VALUE(routes) TYPE tt_routes.

METHODS get_from_country
  IMPORTING
    country_code TYPE /dmo/airport-country
  RETURNING
    VALUE(routes) TYPE tt_routes.

37. Implement GET_ALL ​

abap
METHOD get_all.

  SELECT FROM zi_route_assoc_###
    FIELDS *
    ORDER BY CarrierId,
             ConnectionId
    INTO TABLE @routes.

ENDMETHOD.

The Reader contains no relationship definition.


38. Implement GET_FROM_COUNTRY ​

abap
METHOD get_from_country.

  SELECT FROM zi_route_assoc_###
    FIELDS *
    WHERE OriginCountryCode = @country_code
    ORDER BY CarrierId,
             ConnectionId
    INTO TABLE @routes.

ENDMETHOD.

A scalar path-derived CDS field can be filtered like any other exposed element.


39. Complete Reader ​

abap
CLASS zcl_route_assoc_reader_### DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.

    TYPES tt_routes
      TYPE STANDARD TABLE OF zi_route_assoc_###
      WITH EMPTY KEY.

    METHODS get_all
      RETURNING VALUE(routes) TYPE tt_routes.

    METHODS get_from_country
      IMPORTING
        country_code TYPE /dmo/airport-country
      RETURNING
        VALUE(routes) TYPE tt_routes.

ENDCLASS.


CLASS zcl_route_assoc_reader_### IMPLEMENTATION.

  METHOD get_all.

    SELECT FROM zi_route_assoc_###
      FIELDS *
      ORDER BY CarrierId,
               ConnectionId
      INTO TABLE @routes.

  ENDMETHOD.


  METHOD get_from_country.

    SELECT FROM zi_route_assoc_###
      FIELDS *
      WHERE OriginCountryCode = @country_code
      ORDER BY CarrierId,
               ConnectionId
      INTO TABLE @routes.

  ENDMETHOD.

ENDCLASS.

Activate it.


40. Create the Runner ​

Create:

text
ZCL_CDS_L05_###

Definition:

abap
CLASS zcl_cds_l05_### DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

ENDCLASS.

41. Consume the Reader ​

abap
CLASS zcl_cds_l05_### IMPLEMENTATION.

  METHOD if_oo_adt_classrun~main.

    DATA(reader) = NEW zcl_route_assoc_reader_###( ).

    DATA(routes) = reader->get_all( ).

    LOOP AT routes INTO DATA(route).

      out->write(
        |{ route-CarrierName }: | &&
        |{ route-OriginCity } -> { route-DestinationCity }|
      ).

    ENDLOOP.

  ENDMETHOD.

ENDCLASS.

Activate and run:

text
F9

42. Test the Reader filter ​

Choose a country code present in Data Preview.

Example:

abap
DATA country_code TYPE /dmo/airport-country VALUE 'DE'.

DATA(routes_from_country) =
  reader->get_from_country(
    country_code = country_code
  ).

out->write( routes_from_country ).

Use a value that exists in your own tenant.


43. Associations are part of CDS, not RAP behavior ​

A normal CDS association models a data relationship.

It is not:

text
a RAP action
a validation
a determination
a service binding

RAP later uses CDS relationships heavily, but the association itself is a CDS modeling concept.


44. Associations vs compositions ​

Later RAP lessons introduce:

text
composition
association to parent

Those are specialized relationship concepts for business-object hierarchies.

This lesson focuses on normal associations:

abap
association ... to ...

45. Common mistakes ​

Using target persistence names ​

Target:

text
/DMO/I_CARRIER

exposes:

text
AirlineID
Name
CurrencyCode

Do not write:

text
carrier_id
currency_code

against the CDS target.


Forgetting $projection ​

The current model alias:

text
CarrierId

is referenced as:

abap
$projection.CarrierId

inside the association condition.


Using the wrong airport relationship ​

Wrong:

abap
_OriginAirport.Name as DestinationAirportName

Correct:

abap
_DestinationAirport.Name as DestinationAirportName

Declaring every relationship [1..1] ​

Choose cardinality based on the real relationship.


Declaring to-one without matching the target key ​

If several target rows can match, the relationship is not really to-one.


Forgetting that path target fields perform data access ​

This:

abap
_Carrier.Name

causes target data to be retrieved.

The association is not merely documentation.


Forgetting to expose the association ​

This:

abap
_Carrier.Name as CarrierName

does not automatically expose the _Carrier relationship.

Add:

abap
_Carrier

if navigation should be public.


Assuming associations are automatically bidirectional ​

They are directional.


46. Knowledge check ​

1. What does an association define? ​

Show answer

A named directional relationship from a CDS source to a target, together with cardinality and an ON condition.

2. What does [1..1] mean? ​

Show answer

Exactly one target record is expected for one source record.

3. What does [0..*] mean? ​

Show answer

Zero, one, or many target records may exist for one source record.

4. What is $projection.CarrierId? ​

Show answer

A reference to the current CDS entity's projected element CarrierId.

5. What does _Carrier.Name mean? ​

Show answer

Navigate the _Carrier association and use the target's Name element.

6. What is the default join behavior of a CDS path target field in the element list? ​

Show answer

Left outer join semantics.

7. What does _Carrier by itself in the element list do? ​

Show answer

It exposes the association so supported consumers can navigate the relationship.

8. Are associations automatically bidirectional? ​

Show answer

No.

9. Why should a to-one association match the complete target key? ​

Show answer

Otherwise several target records may match one source record, contradicting the declared relationship.

10. Why did joins come before associations in this course? ​

Show answer

Joins make row matching, ON conditions, join types, and row multiplication explicit. Associations then add a reusable relationship abstraction over those concepts.


47. Lesson summary ​

You moved from:

text
fixed explicit joins

to:

text
named reusable relationships

You learned:

text
association
source and target
association aliases
cardinality
ON conditions
$projection
path expressions
path target fields
association exposure
Follow Association in ADT
default left outer path behavior
Reader consumption

The final model is:

text
/DMO/CONNECTION
      ↓
ZI_ROUTE_ASSOC_###
      ├── _Carrier [1..1] ───────────► /DMO/I_CARRIER
      ├── _OriginAirport [1..1] ─────► /DMO/I_AIRPORT
      └── _DestinationAirport [1..1] ► /DMO/I_AIRPORT

The central idea is:

A CDS association gives a relationship a name, cardinality, condition, and navigation path so it can be reused instead of existing only as a fixed join.


48. What comes next? ​

Before moving on, complete the Lesson 5 practice assignment to apply associations to booking, customer, carrier, and connection data. Use the Lesson 5 companion for deeper explanations, troubleshooting, and reference implementations.

The model now contains:

text
data
calculations
filters
joins
associations
navigation

Lesson 6 — CDS Semantics & Annotations adds semantic metadata:

text
amount + currency
quantity + unit
text elements
text associations
annotation propagation
business meaning

That prepares the CDS layer for later service consumption.