All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cds.reflect.impl.CdsModelBuilder Maven / Gradle / Ivy

There is a newer version: 3.8.0
Show newest version
/*******************************************************************
 * © 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