
com.sap.cds.reflect.impl.CdsModelBuilder Maven / Gradle / Ivy
/*******************************************************************
* © 2020 SAP SE or an SAP affiliate company. All rights reserved. *
*******************************************************************/
package com.sap.cds.reflect.impl;
import static java.util.Collections.emptyList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
import com.sap.cds.reflect.CdsAction;
import com.sap.cds.reflect.CdsAnnotation;
import com.sap.cds.reflect.CdsDefinition;
import com.sap.cds.reflect.CdsDefinitionNotFoundException;
import com.sap.cds.reflect.CdsEntity;
import com.sap.cds.reflect.CdsEvent;
import com.sap.cds.reflect.CdsFunction;
import com.sap.cds.reflect.CdsKind;
import com.sap.cds.reflect.CdsModel;
import com.sap.cds.reflect.CdsService;
import com.sap.cds.reflect.CdsStructuredType;
import com.sap.cds.reflect.CdsType;
import com.sap.cds.reflect.impl.reader.model.CdsConstants;
public class CdsModelBuilder {
private final Map entities = new HashMap<>();
private final Map services = new HashMap<>();
private final Map> actions = new HashMap<>();
private final Map> functions = new HashMap<>();
private final Map events = new HashMap<>();
private final Map> types = new HashMap<>();
private final Map meta = new HashMap<>();
private final Map>> contextAnnotations = new HashMap<>();
private CdsModelBuilder() {
}
public static CdsModelBuilder create() {
return new CdsModelBuilder();
}
public Stream concreteEntities() {
return entities().filter(e -> !e.isAbstract());
}
void addAnnotations(String key, Collection> annotations) {
contextAnnotations.put(key, annotations);
}
public Optional> findType(String qualifiedName) {
CdsTypeBuilder> type = types.get(qualifiedName);
if (type != null) {
return Optional.of(type);
}
return Optional.ofNullable(entities.get(qualifiedName));
}
public Stream entities() {
return entities.values().stream();
}
public Optional findEntity(String qualifiedName) {
return Optional.ofNullable(entities.get(qualifiedName));
}
public CdsEntityBuilder getEntity(String qualifiedName) {
return findEntity(qualifiedName).orElseThrow(notFound(CdsKind.ENTITY, qualifiedName));
}
public Optional> findAspect(String qualifiedName) {
return Optional.ofNullable(types.get(qualifiedName));
}
public CdsTypeBuilder> getAspect(String qualifiedName) {
return findAspect(qualifiedName).orElseThrow(notFound(CdsKind.ASPECT, qualifiedName));
}
public Optional> findAction(String qualifiedName) {
return Optional.ofNullable(actions.get(qualifiedName));
}
public Optional> findFunction(String qualifiedName) {
return Optional.ofNullable(functions.get(qualifiedName));
}
@SuppressWarnings("unchecked")
public T getMeta(String key) {
return (T) meta.get(key);
}
void addType(String key, CdsTypeBuilder> type) {
this.types.put(key, type);
}
void addEntity(CdsEntityBuilder entity) {
addEntity(entity.qualifiedName, entity);
}
void addEntity(String key, CdsEntityBuilder entity) {
this.entities.put(key, entity);
}
void addEvent(CdsEventBuilder event) {
addEvent(event.getQualifiedName(), event);
}
void addEvent(String key, CdsEventBuilder event) {
this.events.put(key, event);
}
public void addService(CdsServiceBuilder service) {
addService(service.getQualifiedName(), service);
}
void addService(String key, CdsServiceBuilder service) {
this.services.put(key, service);
}
void addFunction(CdsOperationBuilder function) {
addFunction(function.getQualifiedName(), function);
}
void addFunction(String key, CdsOperationBuilder function) {
this.functions.put(key, function);
}
void addAction(CdsOperationBuilder action) {
addAction(action.getQualifiedName(), action);
}
void addAction(String key, CdsOperationBuilder action) {
this.actions.put(key, action);
}
void addMeta(String key, Object value) {
this.meta.put(key, value);
}
void addMeta(Map meta) {
this.meta.putAll(meta);
}
private static Supplier notFound(CdsKind kind, String qualifiedName) {
return () -> new CdsDefinitionNotFoundException(kind, qualifiedName);
}
public CdsModel build() {
Map immutableEntities = buildDefinitions(entities);
Map immuteableTypes = buildTypes(types);
Map immutableActions = buildDefinitions(actions);
Map immutableFunctions = buildDefinitions(functions);
return new CdsModelImpl(immutableEntities, services, immutableActions, immutableFunctions, events,
immuteableTypes, meta, contextAnnotations);
}
private static Map buildDefinitions(
Map> builders) {
Map definitions = new HashMap<>();
builders.forEach((n, b) -> {
if (!b.toBeIgnored(b.getQualifiedName())) {
definitions.put(n, b.build());
}
});
return definitions;
}
private static Map buildTypes(Map> builders) {
Map types = new HashMap<>();
builders.forEach((n, b) -> {
if (!b.toBeIgnored(b.getQualifiedName())) {
types.put(n, b.build());
}
});
return types;
}
private static class CdsModelImpl implements CdsModel {
private final Map definitions;
private final Map meta;
private final Map>> contextAnnotations;
private CdsModelImpl(Map entities, Map servicesBuilders,
Map actions, Map functions,
Map eventBuilders, Map types, Map meta,
Map>> contextAnnotations) {
this.definitions = new HashMap<>();
this.definitions.putAll(entities);
this.definitions.putAll(buildServices(servicesBuilders));
this.definitions.putAll(actions);
this.definitions.putAll(functions);
this.definitions.putAll(buildEvents(eventBuilders));
this.definitions.putAll(types);
this.meta = meta;
this.contextAnnotations = contextAnnotations;
}
private Map buildServices(Map services) {
Map immutableServices = new HashMap<>();
services.forEach((name, sb) -> immutableServices.put(name, sb.build(this)));
return immutableServices;
}
private Map buildEvents(Map builders) {
Map definitions = new HashMap<>();
builders.forEach((name, eb) -> definitions.put(name, eb.build(this)));
return definitions;
}
@Override
public Stream> annotations(String namespace) {
return contextAnnotations.getOrDefault(namespace, emptyList()).stream();
}
@Override
public Stream services() {
return streamAs(CdsModelImpl::isService, CdsService.class);
}
@Override
public CdsService getService(String qualifiedName) {
return getAs(qualifiedName, CdsModelImpl::isService, CdsService.class, CdsKind.SERVICE);
}
@Override
public Optional findService(String qualifiedName) {
return findAs(qualifiedName, CdsModelImpl::isService, CdsService.class);
}
@Override
public Stream types() {
return streamAs(CdsModelImpl::isType, CdsType.class);
}
@Override
@SuppressWarnings("unchecked")
public T getType(String qualifiedName) {
return (T) getAs(qualifiedName, CdsModelImpl::isType, CdsType.class, CdsKind.TYPE);
}
@Override
@SuppressWarnings("unchecked")
public Optional findType(String qualifiedName) {
return (Optional) findAs(qualifiedName, CdsModelImpl::isType, CdsType.class);
}
@Override
public Stream entities() {
return streamAs(CdsModelImpl::isEntity, CdsEntity.class);
}
@Override
public CdsEntity getEntity(String qualifiedName) {
return getAs(qualifiedName, CdsModelImpl::isEntity, CdsEntity.class, CdsKind.ENTITY);
}
@Override
public Optional findEntity(String qualifiedName) {
return findAs(qualifiedName, CdsModelImpl::isEntity, CdsEntity.class);
}
@Override
public Optional findAction(String qualifiedName) {
return findAs(qualifiedName, CdsModelImpl::isAction, CdsAction.class);
}
@Override
public Stream actions() {
return streamAs(CdsModelImpl::isAction, CdsAction.class);
}
@Override
public CdsAction getAction(String qualifiedName) {
return getAs(qualifiedName, CdsModelImpl::isAction, CdsAction.class, CdsKind.ACTION);
}
@Override
public Optional findFunction(String qualifiedName) {
return findAs(qualifiedName, CdsModelImpl::isFunction, CdsFunction.class);
}
@Override
public Stream functions() {
return streamAs(CdsModelImpl::isFunction, CdsFunction.class);
}
@Override
public CdsFunction getFunction(String qualifiedName) {
return getAs(qualifiedName, CdsModelImpl::isFunction, CdsFunction.class, CdsKind.FUNCTION);
}
@Override
public Stream events() {
return streamAs(CdsModelImpl::isEvent, CdsEvent.class);
}
@Override
public CdsEvent getEvent(String qualifiedName) {
return getAs(qualifiedName, CdsModelImpl::isEvent, CdsEvent.class, CdsKind.EVENT);
}
@Override
public Optional findEvent(String qualifiedName) {
return findAs(qualifiedName, CdsModelImpl::isEvent, CdsEvent.class);
}
@Override
public Stream structuredTypes() {
return streamAs(CdsModelImpl::isStructuredType, CdsStructuredType.class);
}
@Override
public CdsStructuredType getStructuredType(String qualifiedName) {
return getAs(qualifiedName, CdsModelImpl::isStructuredType, CdsStructuredType.class, CdsKind.TYPE);
}
@Override
public Optional findStructuredType(String qualifiedName) {
return findAs(qualifiedName, CdsModelImpl::isStructuredType, CdsStructuredType.class);
}
@Override
public Stream aspects() {
return streamAs(CdsModelImpl::isAspect, CdsStructuredType.class);
}
@Override
public CdsStructuredType getAspect(String qualifiedName) {
return getAs(qualifiedName, CdsModelImpl::isAspect, CdsStructuredType.class, CdsKind.TYPE);
}
@Override
public Optional findAspect(String qualifiedName) {
return findAs(qualifiedName, CdsModelImpl::isAspect, CdsStructuredType.class);
}
@Override
@SuppressWarnings("unchecked")
public T getMeta(String key) {
return (T) meta.get(key);
}
@Override
public String getVersion() {
return getMeta(CdsConstants.VERSION);
}
private static boolean isService(CdsDefinition def) {
return def.getKind() == CdsKind.SERVICE;
}
private static boolean isEvent(CdsDefinition def) {
return def.getKind() == CdsKind.EVENT;
}
private static boolean isEntity(CdsDefinition def) {
return def.getKind() == CdsKind.ENTITY;
}
private static boolean isAction(CdsDefinition def) {
return def.getKind() == CdsKind.ACTION;
}
private static boolean isFunction(CdsDefinition def) {
return def.getKind() == CdsKind.FUNCTION;
}
private static boolean isType(CdsDefinition def) {
return def.getKind() == CdsKind.TYPE || def.getKind() == CdsKind.ASPECT;
}
private static boolean isAspect(CdsDefinition def) {
return def.getKind() == CdsKind.ASPECT;
}
private static boolean isStructuredType(CdsDefinition def) {
CdsKind kind = def.getKind();
return kind == CdsKind.EVENT || kind == CdsKind.ENTITY || kind == CdsKind.ASPECT
|| (kind == CdsKind.TYPE && ((CdsType) def).isStructured());
}
private T getAs(String qualifiedName, Predicate filter, Class clazz,
CdsKind kind) {
return findAs(qualifiedName, filter, clazz).orElseThrow(notFound(kind, qualifiedName));
}
private Optional findAs(String qualifiedName, Predicate filter,
Class clazz) {
return findDefinition(qualifiedName).filter(filter).map(def -> def.as(clazz));
}
private Stream streamAs(Predicate filter, Class clazz) {
return definitions.values().stream().filter(filter).map(def -> def.as(clazz));
}
private Optional findDefinition(String qualifiedName) {
return definitions.containsKey(qualifiedName) ? Optional.of(definitions.get(qualifiedName))
: Optional.empty();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy