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

com.sap.cloud.sdk.service.prov.v4.util.ODataServiceUtility Maven / Gradle / Ivy

There is a newer version: 1.40.11
Show newest version
/*******************************************************************************
 * (c) 201X SAP SE or an SAP affiliate company. All rights reserved.
 ******************************************************************************/
package com.sap.cloud.sdk.service.prov.v4.util;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import org.apache.olingo.commons.api.Constants;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.data.Link;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.ValueType;
import org.apache.olingo.commons.api.edm.EdmElement;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
import org.apache.olingo.commons.api.edm.EdmNavigationPropertyBinding;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataLibraryException;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceNavigation;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.core.ODataExceptionHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.sap.cloud.sdk.service.prov.api.EntityData;
import com.sap.cloud.sdk.service.prov.api.Message;
import com.sap.cloud.sdk.service.prov.api.Severity;
import com.sap.cloud.sdk.service.prov.api.request.GenericRequest;
import com.sap.cloud.sdk.service.prov.api.request.MessageContainerImpl;
import com.sap.cloud.sdk.service.prov.api.request.QueryRequest;
import com.sap.cloud.sdk.service.prov.api.request.ReadRequest;
import com.sap.cloud.sdk.service.prov.api.request.impl.SQLGenerator;
import com.sap.cloud.sdk.service.prov.api.request.impl.SQLType;
import com.sap.cloud.sdk.service.prov.api.response.ErrorResponse;
import com.sap.cloud.sdk.service.prov.api.response.impl.ErrorResponseImpl;
import com.sap.cloud.sdk.service.prov.api.response.impl.QueryResponseImpl;
import com.sap.cloud.sdk.service.prov.api.response.impl.ReadResponseImpl;
import com.sap.cloud.sdk.service.prov.api.statistics.SAPStatistics;
import com.sap.cloud.sdk.service.prov.v4.request.impl.CDSV4SQLGenerator;
import com.sap.cloud.sdk.service.prov.v4.rt.core.exception.MessageContainerException;
import com.sap.cloud.sdk.service.prov.v4.rt.core.util.OperationType;

public class ODataServiceUtility { 
	private static Logger log = LoggerFactory.getLogger(ODataServiceUtility.class);
	private static final String CODE = "code";
	private static final String MESSAGE = "message";
	private static final String TARGET = "target";
	private static final String DETAILS = "details";
	private static final String DEFAULT_CHARSET = "utf-8";
	
	public Map populateKeys(EdmEntitySet targetEdmEntitySet, Entity sourceEntity) {
		Map keys = new HashMap<>();
		List keyPredicateNames = targetEdmEntitySet.getEntityType().getKeyPredicateNames();
		for (String name: keyPredicateNames) {
			Object value = sourceEntity.getProperty(name).getValue();
			logDebug(log,"Populating key "+name+" value "+value+" from source entity.");
			keys.put(name, value);
		}
		return keys;
	}	
	
	public static Entity getResponseEntity(EntityData respEntityData, Object pojoData, Map data,
			EdmEntityType requestEntity) {
		Entity responseEntity = null;
		if (data != null) {
			responseEntity = MapToOData
					.convertMapToEntity(data, requestEntity);
		} else if (respEntityData != null) {
			responseEntity = EntityDataToOData
					.convertEntityDataToEntity(respEntityData);
		} else if (pojoData != null) {
			responseEntity = EntityDataToOData.convertPojoDataToEntity(
					pojoData, requestEntity);
		}
		return responseEntity;
	}
	
	public List getAllNavigationPropForExpand(UriInfo uriInfo){
		EdmNavigationProperty edmNavigationProperty = null;
		List edmNavigationPropertyList = new ArrayList<>();
		List expandItems = uriInfo.getExpandOption().getExpandItems();
		List resourcePaths = uriInfo.getUriResourceParts();
		UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0);
		EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();
		
		if(expandItems.get(0).isStar()){  // for * all the navigationProperties should be added
			List bindings = edmEntitySet.getNavigationPropertyBindings();
			// we know that there are navigation bindings however normally in this case a check if navigation bindings exists is done
			if(!bindings.isEmpty()) {
				getAllNavigationsList(bindings,edmEntitySet,edmNavigationPropertyList);
			}
		}else{
			for(ExpandItem expandItem1 : expandItems ){
				List uriResources = expandItem1.getResourcePath().getUriResourceParts();
				for(UriResource uriResource : uriResources ){
					if(uriResource instanceof UriResourceNavigation) {
						edmNavigationProperty = ((UriResourceNavigation) uriResource).getProperty();
						edmNavigationPropertyList.add(edmNavigationProperty);
					}
				}
			}
		}
		return edmNavigationPropertyList;
	}
	
	
	private void getAllNavigationsList(List bindings, EdmEntitySet edmEntitySet, List edmNavigationPropertyList) {
		EdmNavigationProperty edmNavigationProperty = null;
		for (EdmNavigationPropertyBinding binding : bindings){
			// loop through the bindings to get the different navigation property
			EdmElement property = edmEntitySet.getEntityType().getProperty(binding.getPath());
			// we don't need to handle error cases, as it is done in the Olingo library
			if(property instanceof EdmNavigationProperty) {
				edmNavigationProperty = (EdmNavigationProperty) property;
			}
			edmNavigationPropertyList.add(edmNavigationProperty);
		}
	
		
	}

	public EntityCollection bindEntitySet(EdmEntitySet entitySet,List> data) {
		String key = null;
		List keyPropRefList = entitySet.getEntityType().getKeyPropertyRefs();
		for(EdmKeyPropertyRef keyRef:keyPropRefList) {
			key = keyRef.getName();//Currently supporting only one key per entityset
		}
		EntityCollection entityCollection = new EntityCollection();
		addPropertiesToEntityCollection(entityCollection,data,key,entitySet);
		addEntityTypeToEntityCollection(entityCollection,entitySet);
		return entityCollection;
	}
	
	public EntityCollection bindEntitySetForPojo(EdmEntitySet entitySet,List data) {
		/*-- Get Hashmap from Pojo --*/
		List> hashMapData = getHashMapFromPojo(data);
		
		String key = null;
		List keyPropRefList = entitySet.getEntityType().getKeyPropertyRefs();
		for(EdmKeyPropertyRef keyRef:keyPropRefList) {
			key = keyRef.getName();//Currently supporting only one key per entityset
		}
		
		EntityCollection entityCollection = new EntityCollection();
		addPropertiesToEntityCollection(entityCollection,hashMapData,key,entitySet);
		addEntityTypeToEntityCollection(entityCollection,entitySet);
		return entityCollection;
	}
	
	public static List> getHashMapFromPojo(List data) {
		ObjectMapper mapper = new ObjectMapper();
		/*-- Ignore Null Values --*/
		mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
		/*-- do not fail on empty beans  --*/
		mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS , false );
		/*-- First: hide all elements in the class ; make property,getter,setter hidden  --*/
		mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
		/*-- Second: now only make the properties discoverable   --*/
		mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
		mapper.setSerializationInclusion(Include.NON_NULL);
		return data.stream().map(pojo -> {
			  @SuppressWarnings("unchecked")
			Map entity = mapper.convertValue(pojo, Map.class);
			  return entity ;
		}).collect(Collectors.toList());
              
	}
	public static  Map getHashMapFromSinglePojo(Object pojoData) {
		ObjectMapper mapper = new ObjectMapper();
		/*-- Ignore Null Values --*/
		mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
		/*-- do not fail on empty beans  --*/
		mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS , false );
		/*-- First: hide all elements in the class ; make property,getter,setter hidden  --*/
		mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
		/*-- Second: now only make the properties discoverable   --*/
		mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
		mapper.setSerializationInclusion(Include.NON_NULL);
		@SuppressWarnings("unchecked")
		Map pojoInMap = mapper.convertValue(pojoData, Map.class); 
		
		return pojoInMap;
	}

	private void addPropertiesToEntityCollection(EntityCollection entityCollection, List> data,
			String key, EdmEntitySet entitySet) {
		for (Map propertyMap : data) {
			Entity entity = new Entity();
			HashMap complexTypes = new HashMap<>();
			for (Map.Entry property : propertyMap.entrySet()) {
				if (property.getValue() instanceof HashMap) {
					complexTypes.put(property.getKey(), property.getValue());
				} else {
					entity.addProperty(createPrimitive(property.getKey(), property.getValue(), entitySet.getEntityType()));
				}
			}
			entity.getProperties().addAll(MapToOData.getComplexProperties(complexTypes));
			entityCollection.getEntities().add(entity);
		}
	}
	
	private Property createPrimitive(final String name, final Object value, EdmEntityType edmEntityType) {
		 
		String edmType = getEdmType(name, edmEntityType) ;
		if(edmType!= null && edmType.equals("Edm.Guid")){
			return new Property(edmType, name, ValueType.PRIMITIVE, UUID.fromString(value.toString())) ;
		}
		else 		
	      return new Property(edmType, name, ValueType.PRIMITIVE, value);
	}
	
	

	private String getEdmType(String propertyName, EdmEntityType entity){
	 		return (entity.getProperty(propertyName) != null ? entity.getProperty(propertyName).getType().toString() : null ); 
	}
	
	private void addEntityTypeToEntityCollection(EntityCollection entityCollection,EdmEntitySet entitySet) {
		for (Entity entity:entityCollection.getEntities()) {
		      entity.setType(entitySet.getEntityType().getFullQualifiedName().getFullQualifiedNameAsString());
		}
	}
	
	
	@SuppressWarnings("unchecked")
	public EntityCollection getEntityCollection(EdmEntitySet edmEntitySet,QueryRequest queryRequest, String serviceName,SAPStatistics timings) throws ODataApplicationException {
		logDebug(log,"getEntityCollection request in custome Processor started...");
		List> data = null;
		EntityCollection entityCollection = null;
		ODataServiceUtility utility = new ODataServiceUtility();
		QueryResponseImpl queryResponse = new QueryResponseImpl();
		try {
			queryResponse = (QueryResponseImpl) ProcessorHelper.invokeOperation(queryRequest, serviceName, OperationType.QUERY,timings);
		} catch (ODataApplicationException e) {
			log.error("Error in fetching the entity ." + edmEntitySet.getName(),e);
			throw e;
		}
		logDebug(log,"Query Response" + queryResponse );
		if (queryResponse.getEntityData()!= null){		
			entityCollection = EntityDataToOData.convertEntityDataListToEntityCollection(queryResponse.getEntityData(), entityCollection);
		}else if (queryResponse.getData()!= null) {
			data = (List>) queryResponse.getData();
			entityCollection = utility.bindEntitySet(edmEntitySet,data);
		}else if(queryResponse.getPojoData()!= null){
			entityCollection = utility.bindEntitySetForPojo(edmEntitySet , queryResponse.getPojoData()) ;
		}
		if (entityCollection == null) {
			//Create an empty collection
			entityCollection = new EntityCollection();
		}
		return entityCollection;
	}
	
	public static ReadResponseImpl getEntity(ReadRequest readRequest,EdmEntitySet edmEntitySet, String serviceName,SAPStatistics timings) throws 
	ODataApplicationException{
		ReadResponseImpl readResponse = (ReadResponseImpl) ProcessorHelper.invokeOperation(readRequest, serviceName,
				OperationType.READ,timings);
		ODataServiceUtility.logDebug(log,"Data fetched from the entity" + edmEntitySet.getName());
		return readResponse;
	}
	
	public EdmEntitySet getNavigatioProp(EdmEntitySet edmEntitySet,EdmType expandEdmEntityType){
		List entitySets = edmEntitySet.getEntityContainer().getEntitySets();
		EdmEntitySet edmEntitySetFornavigation = null;
		for(EdmEntitySet entitySet:entitySets) {
			edmEntitySetFornavigation = entitySet.getEntityType().getFullQualifiedName().equals(expandEdmEntityType.getFullQualifiedName()) ?entitySet : null; 
			if(edmEntitySetFornavigation!=null) break;
		}
		return edmEntitySetFornavigation;
	}
	

	public static void checkUserException(ErrorResponseImpl error,GenericRequest request) throws ODataApplicationException{
		if(error != null){
			Throwable t = error.getCause();
			int statusCode = (error.getStatusCode() <= 0) ? HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode() : error.getStatusCode();
			ErrorResponseImpl errorResponseImpl = (ErrorResponseImpl) error;
			if(errorResponseImpl.getErrorDetails() != null && !errorResponseImpl.getErrorDetails().isEmpty()){
				throw convertErrorResponseToMessageContainerException(error,
						request);
			}
			else{
				if(t != null){
					throw new ODataApplicationException(error.getMessage(), statusCode, request.getLocale(), t , error.getErrorCode());
				}else{
					throw new ODataApplicationException(error.getMessage(), statusCode, request.getLocale(),error.getErrorCode());                          
				}
			}
		}
	}

	
	   private static MessageContainerException convertErrorResponseToMessageContainerException(
   			ErrorResponse errorResponse, GenericRequest currentRequest) {

   		ErrorResponseImpl errorResponseImpl = (ErrorResponseImpl) errorResponse;

   		int statusCode = errorResponseImpl.getStatusCode();
   		Throwable e = errorResponseImpl.getCause();
   		String msg = errorResponseImpl.getMessage();
   		Locale locale = currentRequest.getLocale();
   		String errorCode = errorResponseImpl.getErrorCode();
   		List errorDetails = new ArrayList<>();

   		if (errorResponseImpl.getErrorDetails() != null && !errorResponseImpl.getErrorDetails().isEmpty()) {

   			for (Object o : errorResponseImpl.getErrorDetails()) {
   				if (o instanceof Message) {
   					errorDetails.add((Message) o);
   				} else {
   					List severities = Arrays.asList((Severity[]) o);
   					MessageContainerImpl msgCon = (MessageContainerImpl) currentRequest.getMessageContainer();
   					for (Message m : msgCon.getMessageDetails()) {
   						if (severities.contains(m.getSeverity())) {
   							errorDetails.add(m);
   						}
   					}
   				}
   			}
   		}

   		return new MessageContainerException(msg, locale, statusCode, e,errorCode,
   				errorDetails);
   	}
	   
	public static SQLGenerator getSQLGenerator(SQLType sqlType){
		SQLGenerator sqlGenerator = new CDSV4SQLGenerator();
		if(sqlType == null){
			sqlGenerator = new CDSV4SQLGenerator();			
		}		
		return sqlGenerator;
	}
	
	public static void populateODataErrorResponse(OData oData, Exception exception, ContentType responseFormat, ODataResponse errorResponse) {
		try {
			ODataServerError serverError = null;
			ODataSerializer serializer = oData.createSerializer(responseFormat);
			if (exception instanceof ODataLibraryException) {
				serverError = ODataExceptionHelper.createServerErrorObject((ODataLibraryException)exception, null);
			} else if (exception instanceof ODataApplicationException) {
				serverError = ODataExceptionHelper.createServerErrorObject((ODataApplicationException)exception);
			}
			if (serverError != null) {
				errorResponse.setContent(serializer.error(serverError).getContent());
				errorResponse.setStatusCode(serverError.getStatusCode());
				return;
			}
		} catch (SerializerException e) {
			log.error(e.getMessage());
		}
		errorResponse.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
	}
	
	public Link getLink(String navPropName){
		Link link = new Link();
		link.setTitle(navPropName);
		link.setType(Constants.ENTITY_NAVIGATION_LINK_TYPE);
		link.setRel(Constants.NS_ASSOCIATION_LINK_REL + navPropName);
		return link;
	}
	
	public static void logDebug( Logger logger,String logInfo){
		if (logger.isDebugEnabled()) {
			logger.debug(logInfo);
		}
	}
	
	public static Entity getResponseEntity(Object data, EdmEntityType entityType) {
		if(data instanceof EntityData)
			return getResponseEntity((EntityData) data, null, null, entityType);
		else if(data instanceof Map)
			return getResponseEntity( null, null, (Map) data, entityType);
		else
			return getResponseEntity( null, data, null, entityType);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy