Search

Model Reflection API

The Model Reflection API is a set of interfaces, which provide the ability to introspect a CDS model and retrieve details on the services, types, entities, and their elements that are defined by the model. The interface CdsModel represents the complete CDS model of the CAP application and is the starting point for the introspection.

Usage of the API

When using the API you will often have to get detail information for a component of the model. As a general concept, the API offers three methods to access the detail components:

CDS model
entity Books {
  title  : localized String(111);
  ...
}
CDS reflect
CdsModel model = ...

// get by name
CdsEntity book = model.getEntity("my.bookshop.Books");

// find by name
Optional<CdsElement> title = book.findElement("title");
title.ifPresent(e ->

  // stream
  e.annotations().map(CdsAnnotation::getName).forEach(System.out::println)
);

Get by name

The get methods allow to access a detail component by name assuming that it exists.

Get an entity by its qualified name

CdsEntity book = model.getEntity("my.bookshop.Books");

If there is no entity with name “my.bookshop.Books”, an exception is thrown.

Find by name

To avoid an exception, use the find methods, which return an Optional:

Optional<CdsEntity> book = model.findEntity("my.bookshop.Books");
book.ifPresent(b -> ...);

Streams

The Reflection API uses Java 8 Streams, which make it easy to filter definitions and elements by specific properties:

Filter nonabstract services
Stream<CdsService> services = model.services()
    .filter(s -> !s.isAbstract());
List<CdsService> serviceList = services.collect(Collectors.toList());
Filter entities by namespace
Stream<CdsEntity> entities = model.entities()
    .filter(byNamespace("my.bookshop"));
Filter entity elements with @title annotation
CdsEntity order = model.getEntity("my.bookshop.Orders");
Stream<CdsElement> elements = order.elements()
    .filter(byAnnotation("title"));

Get and inspect an element of an entity

CDS model
entity Books {
  title  : localized String(111);
  ...
}
CDS reflect
CdsElement title = book.getElement("title");

boolean key = title.isKey();      // false
CdsType type = title.getType();   // CdsSimpleType

if (type.isSimple()) {   // true
  CdsSimpleType simple = type.as(CdsSimpleType.class);

  String typeName = simple.getQualifiedName();  // "cds.String"
  CdsBaseType baseType = simple.getType();      // CdsBaseType.STRING
  Class<?> javaType = simple.getJavaType();     // String.class
  Boolean localized = simple.get("localized");  // true
  Integer length = simple.get("length");        // 111
}

Examples

Get and inspect an association element of an entity

CDS model
entity Books {
  author : Association to Authors;
  ...
}
entity Authors {
  key ID : Integer;
  ...
}
CDS reflect
CdsElement authorElement = book.getAssociation("author");
CdsAssociationType toAuthor = authorElement.getType();

CdsEntity author = toAuthor.getTarget(); // Entity: my.bookshop.Authors
boolean association = toAuthor.isAssociation();   // true
boolean composition = toAuthor.isComposition();   // false

Cardinality cardinality = toAuthor.getCardinality();
String sourceMax = cardinality.getSourceMax();    // "*"
String targetMin = cardinality.getTargetMin();    // "0"
String targetMax = cardinality.getTargetMax();    // "1"

Stream<CdsElement> keys = toAuthor.keys();  // Stream: [ ID ]
Optional<CqnExpression> onCondition = toAuthor.onCondition(); // empty

Find an annotation by name and get its value

CDS model
entity Orders {
  OrderNo  : String @title:'Order Number';
  ...
}
CDS reflect
CdsEntity order = model.getEntity("my.bookshop.Orders");
CdsElement orderNo = order.getElement("OrderNo");

Optional<CdsAnnotation<String>> annotation = orderNo
        .findAnnotation("title");
String title = annotation.map(CdsAnnotation::getValue)
        .orElse(orderNo.getName());   // "Order Number"