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

com.sap.cds.adapter.odata.v2.processors.ExpandWriteCallback 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.v2.processors;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.olingo.odata2.api.ODataCallback;
import org.apache.olingo.odata2.api.edm.EdmEntitySet;
import org.apache.olingo.odata2.api.edm.EdmException;
import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
import org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent;
import org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent;
import org.apache.olingo.odata2.api.ep.callback.WriteCallbackContext;
import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext;
import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackResult;
import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext;
import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackResult;
import org.apache.olingo.odata2.api.exception.ODataApplicationException;
import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sap.cds.services.ErrorStatuses;
import com.sap.cds.services.utils.ErrorStatusException;

public class ExpandWriteCallback implements OnWriteFeedContent, OnWriteEntryContent {

	private URI baseUri;
	private boolean deferredExpand;
	private final static Logger logger = LoggerFactory.getLogger(ExpandWriteCallback.class);

	public ExpandWriteCallback(URI baseUri, boolean deferredExpand) {
		this.baseUri = baseUri;
		this.deferredExpand = deferredExpand;
	}

	@SuppressWarnings("unchecked")
	@Override
	public WriteEntryCallbackResult retrieveEntryResult(WriteEntryCallbackContext context)
			throws ODataApplicationException {
		WriteEntryCallbackResult result = new WriteEntryCallbackResult();

		Map entry = context.getEntryData();
		EdmNavigationProperty navigationProperty = context.getNavigationProperty();

		Map inlinedEntry;
		try {
			inlinedEntry = (Map) entry.get(navigationProperty.getName());
			result.setEntryData(inlinedEntry); // no null check required
			if(inlinedEntry != null){
				result.setInlineProperties(getInlineEntityProviderProperties(context, inlinedEntry));
			} else {
				result.setInlineProperties(context.getCurrentWriteProperties());
			}
			return result;

		} catch (EdmException e) {
			logger.error(e.getMessage(), e);
			throw new ErrorStatusException(ErrorStatuses.SERVER_ERROR, e);
		}
	}

	private EntityProviderWriteProperties getInlineEntityProviderProperties(WriteCallbackContext context, Map propertyMap) throws EdmException {
		EntityProviderWriteProperties inlineProperties = null;
		EdmNavigationProperty navProperty = context.getNavigationProperty();
		EdmEntitySet sourceEntitySet = context.getSourceEntitySet();
		EdmEntitySet relatedEntitySet = sourceEntitySet.getRelatedEntitySet(navProperty);

		List selectedProperties = new ArrayList(propertyMap.keySet());
		List allNavigationProperties = new ArrayList<>(relatedEntitySet.getEntityType().getNavigationPropertyNames());
		List expandedNavigationProperties = allNavigationProperties;
		if (deferredExpand) {
			// if navigation property is not in $expand - defer loading
			expandedNavigationProperties = allNavigationProperties.stream()
					.filter(e -> selectedProperties.contains(e)).collect(Collectors.toList());
		}

		selectedProperties.removeAll(allNavigationProperties);
		//getExpandSelectTree
		ExpandSelectTreeNode expandSelectTree = null;
		List properties = new ArrayList();
		properties.addAll(relatedEntitySet.getEntityType().getPropertyNames());
		properties.retainAll(propertyMap.keySet());

		// Register callbacks only for selected navigation properties, rest should be deferred.
		// If the callback for navigation property is not registered, Olingo marks it as deferred in the response
		Map callbacks = new HashMap();
		if (expandedNavigationProperties.size() > 0) {
			for (String navigationPropName : expandedNavigationProperties) {
				callbacks.put(navigationPropName, new ExpandWriteCallback(baseUri, deferredExpand));
			}
		}
		expandSelectTree = ExpandSelectTreeNode.entitySet(relatedEntitySet)
				.expandedLinks(allNavigationProperties).build();
		inlineProperties = EntityProviderWriteProperties
				.serviceRoot(baseUri).expandSelectTree(expandSelectTree).callbacks(callbacks).build();

		return inlineProperties;
	}

	@SuppressWarnings("unchecked")
	@Override
	public WriteFeedCallbackResult retrieveFeedResult(WriteFeedCallbackContext context)
			throws ODataApplicationException {
		WriteFeedCallbackResult result = new WriteFeedCallbackResult();

		try{
			Map entry = context.getEntryData();
			EdmNavigationProperty navigationProperty = context.getNavigationProperty();

			List> inlinedFeed = (List>) entry.get(navigationProperty.getName());
			result.setFeedData(inlinedFeed);
			if(inlinedFeed != null && !inlinedFeed.isEmpty()){
				result.setInlineProperties(getInlineEntityProviderProperties(context, inlinedFeed.get(0)));
			} else {
				result.setInlineProperties(context.getCurrentWriteProperties());
			}
			return result;

		}catch(EdmException e){
			logger.error(e.getMessage(), e);
			throw new ErrorStatusException(ErrorStatuses.SERVER_ERROR, e);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy