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

com.sap.cds.adapter.odata.v4.metadata.cds.CdsServiceEdmEntityContainer Maven / Gradle / Ivy

There is a newer version: 3.6.0
Show newest version
/**************************************************************************
 * (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 **************************************************************************/
package com.sap.cds.adapter.odata.v4.metadata.cds;

import static com.sap.cds.adapter.odata.v4.metadata.cds.CdsServiceEdmUtils.fqn;
import static com.sap.cds.adapter.odata.v4.metadata.cds.CdsServiceEdmUtils.isIncludedEntitySetAssociation;
import static com.sap.cds.adapter.odata.v4.metadata.cds.CdsServiceEdmUtils.isParameterized;
import static com.sap.cds.adapter.odata.v4.metadata.cds.CdsServiceEdmUtils.name;
import static com.sap.cds.adapter.odata.v4.metadata.cds.CdsServiceEdmUtils.target;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.olingo.commons.api.edm.provider.CsdlActionImport;
import org.apache.olingo.commons.api.edm.provider.CsdlBindingTarget;
import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
import org.apache.olingo.commons.api.edm.provider.CsdlEntitySet;
import org.apache.olingo.commons.api.edm.provider.CsdlFunctionImport;
import org.apache.olingo.commons.api.edm.provider.CsdlNamed;
import org.apache.olingo.commons.api.edm.provider.CsdlNavigationPropertyBinding;
import org.apache.olingo.commons.api.edm.provider.CsdlSingleton;

import com.sap.cds.adapter.odata.v4.utils.mapper.EdmxFlavourMapper;
import com.sap.cds.reflect.CdsAction;
import com.sap.cds.reflect.CdsDefinition;
import com.sap.cds.reflect.CdsEntity;
import com.sap.cds.reflect.CdsFunction;
import com.sap.cds.reflect.CdsKind;
import com.sap.cds.reflect.CdsService;
import com.sap.cds.services.utils.model.CdsAnnotations;

class CdsServiceEdmEntityContainer extends CsdlEntityContainer {

	static final String ENTITY_CONTAINER_NAME = "EntityContainer";

	private final EdmxFlavourMapper edmxFlavourMapper;
	private final Map entityLookup = new HashMap<>();
	private final Map actionLookup = new HashMap<>();
	private final Map functionLookup = new HashMap<>();
	private final Map cached = new HashMap<>();

	CdsServiceEdmEntityContainer(CdsService service, EdmxFlavourMapper edmxFlavourMapper) {
		this.edmxFlavourMapper = edmxFlavourMapper;
		service.entities()
			.filter(CdsServiceEdmUtils::isIncludedEntitySet)
			.forEach(e -> entityLookup.put(name(e), e));
		service.actions().forEach(a -> actionLookup.put(name(a), a));
		service.functions().forEach(f -> functionLookup.put(name(f), f));

		setName(ENTITY_CONTAINER_NAME);
		setEntitySets(null);
		setSingletons(null);
		setActionImports(null);
		setFunctionImports(null);
	}

	@Override
	public CsdlEntitySet getEntitySet(String name) {
		CdsEntity entity = entityLookup.get(name);
		if (entity != null && !CdsAnnotations.SINGLETON.isTrue(entity)) {
			return (CsdlEntitySet) buildBindingTarget(entity);
		}
		return null;
	}

	@Override
	public List getEntitySets() {
		return entityLookup.values().stream().filter(e -> !CdsAnnotations.SINGLETON.isTrue(e))
				.map(e -> (CsdlEntitySet) buildBindingTarget(e)).toList();
	}

	@Override
	public CsdlSingleton getSingleton(String name) {
		CdsEntity entity = entityLookup.get(name);
		if (entity != null && CdsAnnotations.SINGLETON.isTrue(entity)) {
			return (CsdlSingleton) buildBindingTarget(entity);
		}
		return null;
	}

	@Override
	public List getSingletons() {
		return entityLookup.values().stream().filter(CdsAnnotations.SINGLETON::isTrue)
				.map(e -> (CsdlSingleton) buildBindingTarget(e)).toList();
	}

	private CsdlBindingTarget buildBindingTarget(CdsEntity entity) {
		return (CsdlBindingTarget) cached.computeIfAbsent(entity, e -> {
			boolean isParameterized = isParameterized(entity);
			CsdlBindingTarget bindingTarget;
			if (CdsAnnotations.SINGLETON.isTrue(entity)) {
				bindingTarget = new CsdlSingleton();
			} else {
				bindingTarget = new CsdlEntitySet();
			}
			bindingTarget.setName(name(entity));
			bindingTarget.setType(fqn(entity) + (isParameterized ? "Parameters" : ""));

			edmxFlavourMapper.createMappings(entity).filter(m -> isIncludedEntitySetAssociation(m.getTargetElement())).forEach(assoc -> {
				CsdlNavigationPropertyBinding binding = new CsdlNavigationPropertyBinding();
				binding.setPath((isParameterized ? "Set/" : "") + assoc.getEdmxName());
				binding.setTarget(name(target(entity, assoc.getTargetElement())));
				bindingTarget.getNavigationPropertyBindings().add(binding);
			});

			if (isParameterized) {
				CsdlNavigationPropertyBinding parametersBinding = new CsdlNavigationPropertyBinding();
				parametersBinding.setPath("Set/Parameters");
				parametersBinding.setTarget(name(entity));
				bindingTarget.getNavigationPropertyBindings().add(parametersBinding);
			}
			return bindingTarget;
		});
	}

	@Override
	public CsdlActionImport getActionImport(String name) {
		CdsAction action = actionLookup.get(name);
		if (action != null) {
			return buildActionImport(action);
		}
		return null;
	}

	@Override
	public List getActionImports(String name) {
		return List.of(getActionImport(name));
	}

	@Override
	public List getActionImports() {
		return actionLookup.values().stream().map(this::buildActionImport).toList();
	}

	private CsdlActionImport buildActionImport(CdsAction action) {
		return (CsdlActionImport) cached.computeIfAbsent(action, a -> {
			CsdlActionImport actionImport = new CsdlActionImport();
			actionImport.setAction(fqn(action));
			actionImport.setName(name(action));
			action.returnType().filter(r -> r.getKind() == CdsKind.ENTITY)
					.map(r -> name(r)).ifPresent(actionImport::setEntitySet);
			return actionImport;
		});
	}

	@Override
	public CsdlFunctionImport getFunctionImport(String name) {
		CdsFunction function = functionLookup.get(name);
		if (function != null) {
			return buildFunctionImport(function);
		}
		return null;
	}

	@Override
	public List getFunctionImports(String name) {
		return List.of(getFunctionImport(name));
	}

	@Override
	public List getFunctionImports() {
		return functionLookup.values().stream().map(this::buildFunctionImport).toList();
	}

	private CsdlFunctionImport buildFunctionImport(CdsFunction function) {
		return (CsdlFunctionImport) cached.computeIfAbsent(function, f -> {
			CsdlFunctionImport functionImport = new CsdlFunctionImport();
			functionImport.setFunction(fqn(function));
			functionImport.setName(name(function));
			if (function.getReturnType().getKind() == CdsKind.ENTITY) {
				functionImport.setEntitySet(name(function.getReturnType()));
			}
			return functionImport;
		});
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy