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

com.sap.cloud.sdk.odatav2.connectivity.impl.BatchRequestImpl Maven / Gradle / Ivy

package com.sap.cloud.sdk.odatav2.connectivity.impl;

import static com.sap.cloud.sdk.odatav2.connectivity.internal.ODataConnectivityUtil.withSeparator;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.olingo.odata2.api.batch.BatchException;
import org.apache.olingo.odata2.api.client.batch.BatchChangeSet;
import org.apache.olingo.odata2.api.client.batch.BatchChangeSetPart;
import org.apache.olingo.odata2.api.client.batch.BatchPart;
import org.apache.olingo.odata2.api.client.batch.BatchQueryPart;
import org.apache.olingo.odata2.api.client.batch.BatchSingleResponse;
import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
import org.apache.olingo.odata2.api.edm.Edm;
import org.apache.olingo.odata2.api.edm.EdmEntitySet;
import org.apache.olingo.odata2.api.edm.EdmEntityType;
import org.apache.olingo.odata2.api.edm.EdmException;
import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
import org.apache.olingo.odata2.api.edm.EdmProperty;
import org.apache.olingo.odata2.api.edm.EdmSimpleType;
import org.apache.olingo.odata2.api.ep.EntityProvider;
import org.apache.olingo.odata2.api.ep.EntityProviderException;
import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
import org.apache.olingo.odata2.api.processor.ODataResponse;
import org.apache.olingo.odata2.client.api.ODataClient;
import org.apache.olingo.odata2.client.api.ep.DeserializerProperties;
import org.apache.olingo.odata2.client.api.ep.Entity;
import org.apache.olingo.odata2.client.api.ep.EntitySerializerProperties;
import org.apache.olingo.odata2.client.api.ep.EntityStream;
import org.slf4j.Logger;

import com.sap.cloud.sdk.cloudplatform.cache.CacheKey;
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor;
import com.sap.cloud.sdk.cloudplatform.connectivity.WithDestinationName;
import com.sap.cloud.sdk.cloudplatform.logging.CloudLoggerFactory;
import com.sap.cloud.sdk.odatav2.connectivity.ErrorResultHandler;
import com.sap.cloud.sdk.odatav2.connectivity.ODataCreateRequest;
import com.sap.cloud.sdk.odatav2.connectivity.ODataCreateResult;
import com.sap.cloud.sdk.odatav2.connectivity.ODataDeleteRequest;
import com.sap.cloud.sdk.odatav2.connectivity.ODataDeleteResult;
import com.sap.cloud.sdk.odatav2.connectivity.ODataException;
import com.sap.cloud.sdk.odatav2.connectivity.ODataExceptionType;
import com.sap.cloud.sdk.odatav2.connectivity.ODataQuery;
import com.sap.cloud.sdk.odatav2.connectivity.ODataUpdateResult;
import com.sap.cloud.sdk.odatav2.connectivity.UpdateMethod;
import com.sap.cloud.sdk.odatav2.connectivity.batch.BatchRequest;
import com.sap.cloud.sdk.odatav2.connectivity.batch.BatchResult;
import com.sap.cloud.sdk.odatav2.connectivity.batch.BatchResultPart;
import com.sap.cloud.sdk.odatav2.connectivity.batch.ChangeSetResultPart;
import com.sap.cloud.sdk.odatav2.connectivity.internal.EdmWithCSRF;
import com.sap.cloud.sdk.odatav2.connectivity.internal.ODataConnectivityUtil;

import lombok.NonNull;

public class BatchRequestImpl implements BatchRequest {

	private static final Logger logger = CloudLoggerFactory.getLogger(BatchRequestImpl.class);
	private Edm edm = null;
	private ErrorResultHandler errorHandler;
	Map headers;
	private Map destinationRelevantHeaders;
	private Boolean cacheMetadata;
	private URL metadataFilePath;
	private CacheKey cacheKey;
	private Boolean isCacheRefresh;
	private static final String APPLICATION_JSON = "application/json";
	private List batch;
	private List requests = new ArrayList();;
	private String servicePath;
	private static final String BOUNDARY = "batch_123";
	private static final String DOLLAR_BATCH = "/$batch";
	private static final String multipart = "multipart/mixed;boundary=";
	private static final String CRLF = "\r\n";
	private static final String UTF_8 = "UTF-8";
	@NonNull
	private HttpClient httpClient = new DefaultHttpClient();
	private int reqCounter;
	private int resCounter;
	public static final String SEPARATOR_PATH = "/";
	private EdmEntitySet lastEntityMetadata;

	public BatchRequestImpl(ErrorResultHandler errorHandler, Map destinationRelevantHeaders,
			Boolean cacheMetadata, URL metadataFilePath, CacheKey cacheKey, Map headers,
			Boolean isCacheRefresh, List batch, String servicePath) {
		super();
		this.errorHandler = errorHandler;
		this.headers = headers;
		this.destinationRelevantHeaders = destinationRelevantHeaders;
		this.cacheMetadata = cacheMetadata;
		this.metadataFilePath = metadataFilePath;
		this.cacheKey = cacheKey;
		this.isCacheRefresh = isCacheRefresh;
		this.batch = batch;
		this.servicePath = servicePath;
	}

	public BatchRequestImpl(List batch, String servicePath) {
		super();
		this.batch = batch;
		this.servicePath = servicePath;
	}

	protected HttpClient getHttpClient(String destinationName) {
		return HttpClientAccessor.getHttpClient(destinationName);
	}

	public BatchResult handleExecute(HttpClient httpClient, String destinationName) throws ODataException {

		// Create httpClient for the batch request
		this.httpClient = destinationName == null ? httpClient : getHttpClient(destinationName);

		// 1. Fetch the edm first for processing the request and response later
		EdmWithCSRF edmWithCsrf = fetchEdm(destinationName);
		edm = edmWithCsrf.getEdm();

		// ===============REQUEST PROCESSING=============================
		// 2. Iterate Over the requests to form Olingo specific requests
		List batchRequests = new ArrayList<>();
		for (Object batchReq : this.batch) {

			if (batchReq instanceof ChangeSetRequestImpl) {

				BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
				ChangeSetRequestImpl c = (ChangeSetRequestImpl) batchReq;
				ArrayList reqList = c.getRequests();
				Iterator> reqs = reqList.iterator();
				Map changeSetHeaders = new HashMap<>();
				changeSetHeaders.put(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_JSON_VERBOSE);
				changeSetHeaders.put(HttpHeaders.ACCEPT, HttpContentType.APPLICATION_JSON_VERBOSE);
				while (reqs.hasNext()) {
					Iterator request = null;
					ArrayList next = reqs.next();
					if (next != null) {
						request = next.iterator();
					} else {
						break;
					}
					while (request.hasNext()) {
						Object changeSetReqRequest = request.next();
						requests.add(changeSetReqRequest);
						if (changeSetReqRequest instanceof ODataCreateRequest) {
							changeSet.add(createRequest((ODataCreateRequest) changeSetReqRequest, changeSetHeaders));
						} else if (changeSetReqRequest instanceof ChangeSetUpdateRequest) {
							changeSet
									.add(updateRequest((ChangeSetUpdateRequest) changeSetReqRequest, changeSetHeaders));
						} else if (changeSetReqRequest instanceof ODataDeleteRequest) {
							changeSet.add(deleteRequest((ODataDeleteRequest) changeSetReqRequest, changeSetHeaders));
						} else {
							throw new ODataException(ODataExceptionType.ODATA_OPERATION_EXECUTION_FAILED,
									"Invalid Request : " + changeSetReqRequest);
						}
					}
				}
				if (changeSet.getChangeSetParts() != null && !changeSet.getChangeSetParts().isEmpty()) {
					batchRequests.add(changeSet);
				}
			} else if (batchReq instanceof ODataQuery) {
				ODataQueryImpl odataQuery = (ODataQueryImpl) batchReq;
				requests.add(odataQuery);
				batchRequests.add(getRequest(odataQuery));
			} else {
				throw new ODataException(ODataExceptionType.ODATA_OPERATION_EXECUTION_FAILED,
						"Invalid Request : " + batchReq);
			}
		}
		// 3. Forming a valid Batch Request Payload
		InputStream body = EntityProvider.writeBatchRequest(batchRequests, BOUNDARY);
		String bodyAsString = inputStreamToStringCRLFLineBreaks(body);
		logger.info(bodyAsString);

		// 4. Executing Request
		URI uri = URI.create(this.servicePath + DOLLAR_BATCH);
		final HttpPost post = new HttpPost(uri);
		HttpResponse batchResponse = executeBatch(bodyAsString, this.httpClient, edmWithCsrf.getCsrfToken(), post);

		// 5.=======================RESPONSE PROCESSING=======================
		if (batchResponse == null || batchResponse.getEntity() == null) {
			throw new ODataException(ODataExceptionType.BATCH_EXCEPTION, "Null response received from endpoint");
		} else if (batchResponse != null && batchResponse.getStatusLine() != null
				&& batchResponse.getStatusLine().getStatusCode() >= 400) {
			StringBuilder msg = new StringBuilder();
			for (Header headers : batchResponse.getAllHeaders()) {
				msg.append(headers.getName() + ":" + headers.getValue() + ", ");
			}
			ODataException ex = new ODataException(ODataExceptionType.BATCH_EXCEPTION, msg.toString());
			ex.setCode(Integer.toString(batchResponse.getStatusLine().getStatusCode()));
			ex.setMessage(batchResponse.getStatusLine().toString());
			throw ex;
		}
		InputStream responseBody;
		try {
			responseBody = batchResponse.getEntity().getContent();
		} catch (UnsupportedOperationException | IOException e1) {
			logger.error(e1.getMessage());
			HttpClientUtils.closeQuietly(batchResponse);
			throw new ODataException(ODataExceptionType.BATCH_EXCEPTION, e1.getMessage(), e1);
		}
		String content = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue();
		List batchResponsePartList = new ArrayList<>();
		try {
			List responses = EntityProvider.parseBatchResponse(responseBody, content);
			reqCounter = 0;
			resCounter = 0;
			for (BatchPart request : batchRequests) {
				createBatchResult(request, responses, batchResponsePartList);
			}
		} catch (BatchException e) {
			logger.error(e.getMessage());
			throw new ODataException(ODataExceptionType.RESPONSE_DESERIALIZATION_FAILED, e.getMessage(), e);
		} finally {
			ODataConnectivityUtil.closeQuietly(batchResponse, post);
			try {
				responseBody.close();
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
		return new BatchResultImpl(batchResponsePartList);
	}

	private BatchPart getRequest(ODataQueryImpl odataQuery) throws ODataException {

		StringBuilder keysUrl = new StringBuilder(odataQuery.getEntity());
		if (odataQuery.getKeys() != null) {
			EdmEntityType entityType = getEntityType(edm, keysUrl.toString());
			keysUrl.append("(");
			keysUrl.append(convertKeyValuesToString(odataQuery.getKeys(), entityType));
			keysUrl.append(")");
		}
		if (odataQuery.getNavigations().size() > 0) {

			String withSeperator = withSeparator(SEPARATOR_PATH, odataQuery.getEntity(), null);
			try {
				withSeperator =  odataQuery.addNavigations("");
				keysUrl.append(withSeperator);
			} catch (Exception exc) {
				logger.error(exc.getMessage());
			}
		}

		String systemQuery;
		try {
			systemQuery = odataQuery.getoDataQueryResolver().getQuery(null);
			if (systemQuery != null) {
				systemQuery = URLEncoder.encode(systemQuery, "UTF-8");
				keysUrl.append("?");
				keysUrl.append(systemQuery);
			}
		} catch (EdmException | UnsupportedEncodingException e) {
			throw new ODataException(ODataExceptionType.METADATA_FETCH_FAILED, "Metadata fetch failed!", e);
		}

		Map batchHeaders = new HashMap<>();
		batchHeaders.put(HttpHeaders.ACCEPT, HttpContentType.APPLICATION_JSON_VERBOSE);
		batchHeaders.putAll(odataQuery.getHeaders());
		return BatchQueryPart.method(ODataHttpMethod.GET.name()).uri(keysUrl.toString()).headers(batchHeaders).build();
	}

	private BatchChangeSetPart deleteRequest(ODataDeleteRequest request, Map changeSetHeaders)
			throws ODataException {
		ODataDeleteRequestImpl dr = (ODataDeleteRequestImpl) request;
		EdmEntityType entityType = getEntityType(edm, dr.getEntitySetName());
		changeSetHeaders.putAll(dr.getHeaders());
		String keysUrl = "(" + convertKeyValuesToString(dr.getKeys(), entityType) + ")";
		return BatchChangeSetPart.method(ODataHttpMethod.DELETE.name())
				.uri(dr.getServiceName() + "/" + dr.getEntitySetName() + keysUrl).headers(changeSetHeaders).build();
	}

	private BatchChangeSetPart updateRequest(ChangeSetUpdateRequest request, Map changeSetHeaders)
			throws ODataException {
		ODataUpdateRequestImpl ur = (ODataUpdateRequestImpl) request.getRequest();
		UpdateMethod method = request.getMethod();
		String entitySetName = ur.getEntitySetName();
		EdmEntitySet eSet = null;
		Entity entity = null;
		EdmEntitySet targetEtySet = null;
		EdmEntityType entityType = null;
		try {
			eSet = edm.getDefaultEntityContainer().getEntitySet(entitySetName);
			if (eSet == null)
				throw new ODataException(ODataExceptionType.INVALID_ENTITY_NAME,
						"No entity with name " + entitySetName + " in the OData service", null);
			entityType = eSet.getEntityType();
			entity = ODataConnectivityUtil.addPropertiesToEntity(ur.getBody(), entityType);
		} catch (EdmException e) {
			throw new ODataException(ODataExceptionType.METADATA_PARSING_FAILED, "Error while parsing the metadata.",
					e);
		}
		String entityString = getPayloadAsString(eSet, entity, targetEtySet);
		String keysUrl;
		keysUrl = "(" + convertKeyValuesToString(ur.getKeys(), entityType) + ")";
		changeSetHeaders.putAll(ur.getHeaders());
		return BatchChangeSetPart.method(method.name()).uri(ur.getServiceName() + "/" + ur.getEntitySetName() + keysUrl)
				// .contentId("2")
				.body(entityString).headers(changeSetHeaders).build();
	}

	private BatchChangeSetPart createRequest(ODataCreateRequest request, Map changeSetHeaders)
			throws ODataException {

		ODataCreateRequestImpl cr = (ODataCreateRequestImpl) request;
		String entitySetName = cr.getEntitySet();
		String navigationName = cr.getNavigationProperty();
		EdmEntitySet eSet = null;
		Entity entity = null;
		EdmEntitySet targetEtySet = null;
		EdmEntityType entityType = null;
		try {
			eSet = edm.getDefaultEntityContainer().getEntitySet(entitySetName);
			if (eSet == null)
				throw new ODataException(ODataExceptionType.INVALID_ENTITY_NAME,
						"No entity with name " + entitySetName + " in the OData service", null);
			entityType = eSet.getEntityType();
			boolean isNavigationFlow = navigationName == null ? false : true;
			;
			EdmNavigationProperty navigationProperty = null;
			if (isNavigationFlow)
				navigationProperty = cr.getNavigationProperty(eSet);
			EdmEntityType childEntityType = null;
			if (navigationProperty != null) {
				// Find Target Type and Set for Navigation
				childEntityType = getTargetEntityType(edm, eSet, navigationProperty);
				// Must have association set
				targetEtySet = cr.getTargetEntitySet(edm, eSet, navigationProperty);
			}
			if (childEntityType != null) {
				// for Create via Navigation
				entity = ODataConnectivityUtil.addPropertiesToEntity(cr.getBody(), childEntityType);
			} else
				// for Simple Create
				entity = ODataConnectivityUtil.addPropertiesToEntity(cr.getBody(), entityType);

		} catch (EdmException e) {
			throw new ODataException(ODataExceptionType.METADATA_PARSING_FAILED, "Error while parsing the metadata.",
					e);
		}

		String entityString = getPayloadAsString(eSet, entity, targetEtySet);
		String completeUrl = cr.getServiceName() + "/" + entitySetName;
		try {
			completeUrl = cr.handleNavigation(completeUrl, entityType);
		} catch (EdmException e) {
			logger.error(e.getMessage());
			throw new ODataException(ODataExceptionType.METADATA_PARSING_FAILED, "Error while parsing the metadata.",
					e);
		}
		changeSetHeaders.putAll(cr.getHeaders());
		return BatchChangeSetPart.method(ODataHttpMethod.POST.name()).uri(completeUrl)
				// .contentId("2")
				.body(entityString).headers(changeSetHeaders).build();
	}

	private String getPayloadAsString(EdmEntitySet eSet, Entity entity, EdmEntitySet targetEtySet)
			throws ODataException {
		entity.setWriteProperties(EntitySerializerProperties.serviceRoot(URI.create(servicePath)).build());
		ODataResponse response;
		try {
			// Target EntitySet via navigation vs directEntityset
			eSet = (targetEtySet != null) ? targetEtySet : eSet;
			response = ODataClient.newInstance().createSerializer(APPLICATION_JSON).writeEntry(eSet, entity);
		} catch (EntityProviderException e) {
			throw new ODataException(ODataExceptionType.INPUT_DATA_SERIALIZATION_FAILED,
					"Error during serialization of input payload. " + e.getMessage(), e);
		}

		InputStream inputStream = ODataConnectivityUtil.getObjectStream(response.getEntity());
		String entityString = null;
		if (inputStream != null) {
			entityString = inputStreamToStringCRLFLineBreaks(inputStream);
			try {
				inputStream.close();
			} catch (IOException e) {
				logger.error("Error while closing the inputstream", e);
			}
		}
		return entityString;
	}

	private EdmWithCSRF fetchEdm(String destinationName) throws ODataException {
		EdmWithCSRF edmWithCSRF = null;
		try {
			cacheMetadata = cacheMetadata == null ? false : cacheMetadata;
			isCacheRefresh = isCacheRefresh == null ? false : isCacheRefresh;
			edmWithCSRF = ODataConnectivityUtil.readMetadataWithCSRF(servicePath, httpClient, headers, errorHandler,
					cacheMetadata, metadataFilePath, cacheKey, isCacheRefresh);
		} catch (IOException e) {
			throw new ODataException(ODataExceptionType.METADATA_FETCH_FAILED, "Metadata fetch failed!", e);
		}
		if (edmWithCSRF == null || edmWithCSRF.getEdm() == null) {
			throw new ODataException(ODataExceptionType.METADATA_FETCH_FAILED, "Metadata fetch failed!", null);
		}
		return edmWithCSRF;
	}

	private String convertKeyValuesToString(Map keys, EdmEntityType entityType) throws ODataException {

		String keyPredicateString = "";
		for (Entry e : keys.entrySet()) {
			if (!keyPredicateString.isEmpty())
				keyPredicateString += ',';
			String key = e.getKey();
			Object value = e.getValue();
			EdmProperty prop;
			String convertedValue = new String();
			try {
				prop = (EdmProperty) entityType.getProperty(key);

				EdmSimpleType type = (EdmSimpleType) (prop.getType());
				convertedValue = type.toUriLiteral(type.valueToString(value, EdmLiteralKind.DEFAULT, prop.getFacets()));
			} catch (EdmException exp) {
				throw new ODataException(ODataExceptionType.METADATA_PARSING_FAILED,
						"Error while parsing the metadata.", exp);
			}
			keyPredicateString += key + '=' + convertedValue;
		}
		return keyPredicateString;
	}

	private EdmEntityType getEntityType(Edm edm, String entitySetName) throws ODataException {
		EdmEntitySet entitySet;
		try {
			entitySet = edm.getDefaultEntityContainer().getEntitySet(entitySetName);
			if (entitySet == null)
				throw new ODataException(ODataExceptionType.INVALID_ENTITY_NAME,
						"No entity with name " + entitySetName + " in the OData service", null);
			return edm.getDefaultEntityContainer().getEntitySet(entitySetName).getEntityType();
		} catch (EdmException e) {
			throw new ODataException(ODataExceptionType.METADATA_PARSING_FAILED, "Error while parsing the metadata.",
					e);
		}
	}

	private EdmEntityType getTargetEntityType(Edm edm, EdmEntitySet srcEtySet, EdmNavigationProperty navigationProp)
			throws EdmException {

		if (navigationProp == null)
			return null;
		else {
			// Look for Target Entity Type based on Navigation Property
			String toRole = navigationProp.getToRole();
			return navigationProp.getRelationship().getEnd(toRole).getEntityType();

		}

	}

	private void createBatchResult(BatchPart request, List responses,
			List batchResponsePartList) throws ODataException {
		BatchSingleResponse response = responses.get(resCounter);
		if (request instanceof BatchQueryPart) {
			int status = Integer.parseInt(response.getStatusCode());
			BatchResultPart batchResultPart = null;
			if (status >= 400) {
				batchResultPart = new BatchResultPartWrapper(fetchHeaders(response), status,
						new ODataException(ODataExceptionType.BATCH_EXCEPTION, response.getBody()));
			} else {
				try {
					if(requests.get(reqCounter) instanceof ODataQuery)
					lastEntityMetadata = ((ODataQueryImpl) requests.get(reqCounter)).updateNavigationType(edm);
					
					batchResultPart = new BatchQueryResultImpl(response.getBody(), fetchHeaders(response), status,
							lastEntityMetadata);
				} catch (EdmException e) {
					logger.error(e.getMessage());
				}
			}
			batchResponsePartList.add(batchResultPart);
			resCounter++;
			reqCounter++;
		} else if (request instanceof BatchChangeSet) {
			ChangeSetResultPart changeSetResultPart = null;
			List changeSetResultParts = new ArrayList<>();
			BatchResultPart changeSetResult = new ChangeSetResultImpl(changeSetResultParts);
			List changeSetParts = ((BatchChangeSet) request).getChangeSetParts();
			int status = 0;
			for (BatchChangeSetPart changeSetPart : changeSetParts) {
				response = responses.get(resCounter);
				status = Integer.valueOf(response.getStatusCode());
				Map> headers = fetchHeaders(response);
				if (status < 400) {
					if (changeSetPart instanceof BatchChangeSetPart) {
						if (ODataHttpMethod.POST.name().equals(changeSetPart.getMethod())) {
							changeSetResultPart = new ODataCreateResult(fetchResponseData(response).getProperties(),
									headers, status);
						} else if (ODataHttpMethod.PUT.name().equals(changeSetPart.getMethod())
								|| ODataHttpMethod.PATCH.name().equals(changeSetPart.getMethod())
								|| ODataHttpMethod.MERGE.name().equals(changeSetPart.getMethod())) {
							changeSetResultPart = new ODataUpdateResult(headers, status);
						} else if (ODataHttpMethod.DELETE.name().equals(changeSetPart.getMethod())) {
							changeSetResultPart = new ODataDeleteResult(headers, status);
						} else {
							throw new ODataException(ODataExceptionType.ODATA_OPERATION_EXECUTION_FAILED,
									"Invalid Request : " + changeSetPart);
						}
						changeSetResultParts.add(changeSetResultPart);
						resCounter++;
						reqCounter++;
					}
				} else {
					changeSetResult = new BatchResultPartWrapper(fetchHeaders(response), status,
							new ODataException(ODataExceptionType.BATCH_EXCEPTION, response.getBody()));
					resCounter++;
					reqCounter = reqCounter + changeSetParts.size();
					break;
				}
			}
			batchResponsePartList.add(changeSetResult);
		} else {
			throw new ODataException(ODataExceptionType.ODATA_OPERATION_EXECUTION_FAILED,
					"Invalid Request : " + request);
		}
	}

	private ODataEntry fetchResponseData(BatchSingleResponse batchSingleResponse) throws ODataException {
		EntityStream entityStream = new EntityStream();
		InputStream stream = new ByteArrayInputStream(batchSingleResponse.getBody().getBytes(StandardCharsets.UTF_8));
		entityStream.setContent(stream);
		entityStream.setReadProperties(DeserializerProperties.init().build());
		ODataCreateRequestImpl req = ((ODataCreateRequestImpl) requests.get(reqCounter));
		String entitysetName = req.getEntitySet();
		EdmEntitySet entitySet;
		try {
			entitySet = edm.getDefaultEntityContainer().getEntitySet(entitysetName);
			EdmNavigationProperty navProperty = null;
			if (req.getNavigationProperty() != null)
				navProperty = req.getNavigationProperty(entitySet);
			if (navProperty != null) {
				entitySet = req.getTargetEntitySet(edm, entitySet, navProperty);
			}
			return ODataClient.newInstance().createDeserializer(APPLICATION_JSON).readEntry(entitySet, entityStream);
		} catch (EdmException | EntityProviderException e) {
			throw new ODataException(ODataExceptionType.RESPONSE_DESERIALIZATION_FAILED, e.getMessage(), e);
		}
	}

	private Map> fetchHeaders(BatchSingleResponse response) {
		Map> headers = new HashMap<>();
		Map headerMap = response.getHeaders();
		if (headerMap != null) {
			for (Entry header : headerMap.entrySet()) {
				List headerValueList = new ArrayList<>();
				headerValueList.addAll(Arrays.asList(header.getValue()));
				headers.put(header.getKey(), (headerValueList.isEmpty()) ? null : headerValueList);
			}
		}
		return headers;
	}

	@Override
	public BatchResult execute(String destinationName) throws ODataException {
		return handleExecute(null, destinationName);
	}

	private HttpResponse executeBatch(final String body, HttpClient httpClient, String csrf, HttpPost post)
			throws ODataException {
		return execute(new StringEntity(body, UTF_8), httpClient, csrf, post);
	}

	private HttpResponse execute(final HttpEntity entity, HttpClient httpClient, String csrf, HttpPost post)
			throws ODataException {
		HttpResponse httpResponse = null;
		// Set CSRF Token Header.
		post.setHeader(ODataConnectivityUtil.CSRF_HEADER, csrf);
		// Set Content-Type header
		post.setHeader(HttpHeaders.CONTENT_TYPE, multipart + BOUNDARY);
		post.setEntity(entity);
		try {
			httpResponse = httpClient.execute(post);
		} catch (IOException e) {
			ODataConnectivityUtil.closeQuietly(httpResponse, post);
			throw new ODataException(ODataExceptionType.BATCH_EXCEPTION, "IOException", e);
		}
		return httpResponse;
	}

	public static String inputStreamToStringCRLFLineBreaks(final InputStream in) throws ODataException {
		final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in, Charset.forName("UTF-8")));
		final StringBuilder stringBuilder = new StringBuilder();
		String line = null;

		try {
			while ((line = bufferedReader.readLine()) != null) {
				stringBuilder.append(line);
				stringBuilder.append(CRLF);
			}
		} catch (IOException e) {
			logger.error(e.getMessage());
			throw new ODataException(ODataExceptionType.BATCH_EXCEPTION, "Error while parsing the Body.", e);
		} finally {
			try {
				bufferedReader.close();
			} catch (IOException e) {
				logger.error("Error while clossing the buffer.", e);
			}
		}
		return stringBuilder.toString();
	}

	@Override
	public BatchResult execute(WithDestinationName withDestinationName) throws ODataException {
		return execute(withDestinationName.getDestinationName());
	}

	@Override
	public BatchResult execute(HttpClient providedClient) throws ODataException {
		this.httpClient = providedClient;
		return handleExecute(providedClient, null);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy