-{
- private ETagSubmissionStrategy eTagSubmissionStrategy = ETagSubmissionStrategy.SUBMIT_ETAG_FROM_ENTITY;
-
- /**
- * Instantiates this fluent helper using the given service path and entity collection to send the requests.
- *
- * @param servicePath
- * The service path to direct the requests to.
- * @param entityCollection
- * The entity collection to direct the requests to.
- */
- public FluentHelperDelete( @Nonnull final String servicePath, @Nonnull final String entityCollection )
- {
- super(servicePath, entityCollection);
- }
-
- /**
- * The entity object to be deleted by calling the {@link #executeRequest(Destination)} method.
- *
- * @return The entity to be deleted.
- */
- @Nonnull
- protected abstract EntityT getEntity();
-
- @SuppressWarnings( "unchecked" )
- @Override
- @Nonnull
- protected Class extends EntityT> getEntityClass()
- {
- return (Class extends EntityT>) getEntity().getClass();
- }
-
- /**
- * The delete request will ignore any version identifier present on the entity and not send an `If-Match` header.
- *
- * Warning: This might lead to a response from the remote system that the `If-Match` header is missing.
- *
- * It depends on the implementation of the remote system whether the `If-Match` header is expected.
- *
- * @return The same request builder that will not send the `If-Match` header in the update request
- */
- @Nonnull
- public FluentHelperT disableVersionIdentifier()
- {
- eTagSubmissionStrategy = ETagSubmissionStrategy.SUBMIT_NO_ETAG;
- return getThis();
- }
-
- /**
- * The delete request will ignore any version identifier present on the entity and delete the entity, regardless of
- * any changes on the remote entity.
- *
- * Warning: Be careful with this option, as this might overwrite any changes made to the remote
- * representation of this object.
- *
- * @return The same request builder that will ignore the version identifier of the entity to update
- */
- @Nonnull
- public FluentHelperT matchAnyVersionIdentifier()
- {
- eTagSubmissionStrategy = ETagSubmissionStrategy.SUBMIT_ANY_MATCH_ETAG;
- return getThis();
- }
-
- @Override
- @Nonnull
- public ModificationResponse executeRequest( @Nonnull final Destination destination )
- {
- final HttpClient httpClient = getHttpClient(destination);
-
- final ODataRequestResultGeneric result = toRequest().execute(httpClient);
-
- return ModificationResponse.of(result, getEntity(), destination);
- }
-
- @Override
- @Nonnull
- public ODataRequestDelete toRequest()
- {
- final EntityT entity = getEntity();
- final String versionIdentifier =
- eTagSubmissionStrategy.getHeaderFromVersionIdentifier(entity.getVersionIdentifier());
-
- final ODataRequestDelete request =
- new ODataRequestDelete(
- getServicePath(),
- getEntityCollection(),
- ODataEntityKey.of(entity.getKey(), ODataProtocol.V2),
- versionIdentifier,
- ODataProtocol.V2);
-
- return super.addHeadersAndCustomParameters(request);
- }
-
- @Nonnull
- private String getEntityCollection()
- {
- return Option.of(entityCollection).getOrElse(() -> getEntity().getEntityCollection());
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperExecutable.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperExecutable.java
deleted file mode 100644
index 5d7e2a7864..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperExecutable.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.HttpClient;
-
-import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
-import com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException;
-import com.sap.cloud.sdk.cloudplatform.connectivity.exception.HttpClientInstantiationException;
-import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataException;
-
-/**
- * Representation of any OData V2 request that can be executed.
- *
- * @param
- * The type of the result entity, if any.
- */
-public interface FluentHelperExecutable
-{
- /**
- * Executes this request.
- *
- * @param destination
- * The target system this request should be issued against.
- * @return A response according to the query criteria.
- *
- * @throws DestinationAccessException
- * If there is an issue accessing the
- * {@link com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination}.
- * @throws HttpClientInstantiationException
- * If there is an issue creating the {@link HttpClient}.
- * @throws ODataException
- * If the OData request execution failed.
- */
- @Nullable
- ResultT executeRequest( @Nonnull final Destination destination );
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperFactory.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperFactory.java
deleted file mode 100644
index e88436afed..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperFactory.java
+++ /dev/null
@@ -1,280 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.classic.methods.HttpPost;
-import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
-
-import lombok.AccessLevel;
-import lombok.RequiredArgsConstructor;
-
-/**
- * Utility class to conveniently create fluent helper instances.
- */
-@RequiredArgsConstructor( access = AccessLevel.PRIVATE )
-class FluentHelperFactory
-{
- @Nonnull
- private final String servicePath;
-
- static FluentHelperFactory withServicePath( @Nonnull final String servicePath )
- {
- return new FluentHelperFactory(servicePath);
- }
-
- <
- FluentHelperT extends FluentHelperByKey, EntityT extends VdmEntity>, SelectableT>
- FluentHelperByKey
- readByKey(
- @Nonnull final Class entityClass,
- @Nonnull final String entityCollection,
- @Nonnull final Map key )
- {
- return new FluentHelperByKey<>(servicePath, entityCollection)
- {
- @Nonnull
- @Override
- protected Map getKey()
- {
- return key;
- }
-
- @Nonnull
- @Override
- protected Class getEntityClass()
- {
- return entityClass;
- }
- };
- }
-
- <
- FluentHelperT extends FluentHelperRead, EntityT extends VdmEntity>, SelectableT>
- FluentHelperRead
- read( @Nonnull final Class entityClass, @Nonnull final String entityCollection )
- {
- return new FluentHelperRead<>(servicePath, entityCollection)
- {
- @Nonnull
- @Override
- protected Class getEntityClass()
- {
- return entityClass;
- }
- };
- }
-
- <
- FluentHelperT extends FluentHelperCreate, EntityT extends VdmEntity>>
- FluentHelperCreate
- create( @Nonnull final String entityCollection, @Nonnull final EntityT entity )
- {
- return new FluentHelperCreate<>(servicePath, entityCollection)
- {
- @Nonnull
- @Override
- protected EntityT getEntity()
- {
- return entity;
- }
-
- @SuppressWarnings( "unchecked" )
- @Nonnull
- @Override
- protected Class getEntityClass()
- {
- return (Class) entity.getClass();
- }
- };
- }
-
- <
- FluentHelperT extends FluentHelperCreate, EntityT extends VdmEntity>>
- FluentHelperCreate
- create( @Nonnull final EntityT entity )
- {
- return create(entity.getEntityCollection(), entity);
- }
-
- <
- FluentHelperT extends FluentHelperDelete, EntityT extends VdmEntity>>
- FluentHelperDelete
- delete( @Nonnull final String entityCollection, @Nonnull final EntityT entity )
- {
- return new FluentHelperDelete<>(servicePath, entityCollection)
- {
- @Nonnull
- @Override
- protected EntityT getEntity()
- {
- return entity;
- }
-
- @SuppressWarnings( "unchecked" )
- @Nonnull
- @Override
- protected Class getEntityClass()
- {
- return (Class) entity.getClass();
- }
- };
- }
-
- <
- FluentHelperT extends FluentHelperDelete, EntityT extends VdmEntity>>
- FluentHelperDelete
- delete( @Nonnull final EntityT entity )
- {
- return delete(entity.getEntityCollection(), entity);
- }
-
- <
- FluentHelperT extends FluentHelperUpdate, EntityT extends VdmEntity>>
- FluentHelperUpdate
- update( @Nonnull final String entityCollection, @Nonnull final EntityT entity )
- {
- return new FluentHelperUpdate<>(servicePath, entityCollection)
- {
- @Nonnull
- @Override
- protected EntityT getEntity()
- {
- return entity;
- }
-
- @SuppressWarnings( "unchecked" )
- @Nonnull
- @Override
- protected Class getEntityClass()
- {
- return (Class) entity.getClass();
- }
- };
- }
-
- <
- FluentHelperT extends FluentHelperUpdate, EntityT extends VdmEntity>>
- FluentHelperUpdate
- update( @Nonnull final EntityT entity )
- {
- return update(entity.getEntityCollection(), entity);
- }
-
- <
- FluentHelperT extends FluentHelperFunction, ObjectT, ResultT>
- FluentHelperFunction
- function(
- @Nonnull final Map parameters,
- @Nonnull final String functionName,
- @Nonnull final Class objectClass,
- @Nonnull final Function requestHandler,
- @Nonnull final BiFunction, Destination, ResultT> executeHandler )
- {
- return new FluentHelperFunction<>(servicePath)
- {
- @Nonnull
- @Override
- protected Map getParameters()
- {
- return parameters;
- }
-
- @Nonnull
- @Override
- protected String getFunctionName()
- {
- return functionName;
- }
-
- @Nonnull
- @Override
- protected HttpUriRequest createRequest( @Nonnull final URI uri )
- {
- return requestHandler.apply(uri);
- }
-
- @Nonnull
- @Override
- protected Class extends ObjectT> getEntityClass()
- {
- return objectClass;
- }
-
- @Nullable
- @Override
- public ResultT executeRequest( @Nonnull final Destination destination )
- {
- return executeHandler.apply(this, destination);
- }
-
- /**
- * {@inheritDoc} The special treatment for SAP S/4 HANA OData v2 responses is considered.
- */
- @Override
- @Nullable
- protected JsonElement refineJsonResponse( @Nullable JsonElement jsonElement )
- {
- if( jsonElement instanceof JsonObject && ((JsonObject) jsonElement).has(getFunctionName()) ) {
- jsonElement = ((JsonObject) jsonElement).get(getFunctionName());
- }
- return super.refineJsonResponse(jsonElement);
- }
- };
- }
-
- <
- FluentHelperT extends FluentHelperFunction, ObjectT>
- FluentHelperFunction
- functionSinglePost(
- @Nonnull final Map parameters,
- @Nonnull final String functionName,
- @Nonnull final Class objectClass )
- {
- return function(parameters, functionName, objectClass, HttpPost::new, FluentHelperFunction::executeSingle);
- }
-
- <
- FluentHelperT extends FluentHelperFunction, ObjectT>
- FluentHelperFunction
- functionSingleGet(
- @Nonnull final Map parameters,
- @Nonnull final String functionName,
- @Nonnull final Class objectClass )
- {
- return function(parameters, functionName, objectClass, HttpGet::new, FluentHelperFunction::executeSingle);
- }
-
- <
- FluentHelperT extends FluentHelperFunction>, ObjectT>
- FluentHelperFunction>
- functionMultiplePost(
- @Nonnull final Map parameters,
- @Nonnull final String functionName,
- @Nonnull final Class objectClass )
- {
- return function(parameters, functionName, objectClass, HttpPost::new, FluentHelperFunction::executeMultiple);
- }
-
- <
- FluentHelperT extends FluentHelperFunction>, ObjectT>
- FluentHelperFunction>
- functionMultipleGet(
- @Nonnull final Map parameters,
- @Nonnull final String functionName,
- @Nonnull final Class objectClass )
- {
- return function(parameters, functionName, objectClass, HttpGet::new, FluentHelperFunction::executeMultiple);
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperFunction.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperFunction.java
deleted file mode 100644
index fe7704127b..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperFunction.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.classic.methods.HttpPost;
-import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
-
-import com.google.gson.JsonElement;
-import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
-import com.sap.cloud.sdk.datamodel.odata.client.ODataProtocol;
-import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataException;
-import com.sap.cloud.sdk.datamodel.odata.client.expression.ODataResourcePath;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataFunctionParameters;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestAction;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestFunction;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestGeneric;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestResultGeneric;
-
-import io.vavr.Lazy;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * Representation of any OData function import as a fluent interface for further configuring the request and
- * {@link #executeRequest(Destination) executing} it.
- *
- * @param
- * The fluent helper type.
- * @param
- * The type of the object this OData request operates on, if any.
- * @param
- * The type of the result entity, if any.
- */
-@Slf4j
-public abstract class FluentHelperFunction
- extends
- FluentHelperBasic
-{
- /**
- * Upper-case HTTP method derived from {@link #createRequest(URI)} method.
- */
- @SuppressWarnings( "this-escape" )
- private final Lazy httpMethod = Lazy.of(() -> createRequest(URI.create("")).getMethod().toUpperCase());
-
- /**
- * Instantiates this fluent helper using the given service path to send the requests.
- *
- * @param servicePath
- * The service path to direct the requests to.
- */
- public FluentHelperFunction( @Nonnull final String servicePath )
- {
- super(servicePath, null);
- }
-
- /**
- * Getter for the map of parameters to be used in the function call.
- *
- * The map maps the ODataName of a parameter to the corresponding unserialized value.
- *
- * Only literal values are allowed as value. No complex or entity objects.
- *
- * @return A map containing the parameter for the function call.
- */
- @Nonnull
- protected abstract Map getParameters();
-
- /**
- * The exact name of the function to be called on the OData Endpoint.
- *
- * @return The function name on the endpoint.
- */
- @Nonnull
- protected abstract String getFunctionName();
-
- /**
- * Creates a request for this function based on the given {@code URI}.
- *
- * Examples for such requests are {@code HttpGet} and {@code HttpPost}.
- *
- * @param uri
- * The {@code URI} the request should target.
- * @return The instantiated request.
- */
- @Nonnull
- protected abstract HttpUriRequest createRequest( @Nonnull final URI uri );
-
- /**
- * {@inheritDoc}
- *
- * The function import arguments are encoded as HTTP query expressions.
- */
- @Nonnull
- @Override
- public ODataRequestGeneric toRequest()
- {
- final ODataRequestGeneric functionImportRequest = instantiateRequest();
- return super.addHeadersAndCustomParameters(functionImportRequest);
- }
-
- @Nonnull
- private ODataRequestGeneric instantiateRequest()
- {
- final String servicePath = getServicePath();
- final ODataResourcePath resourcePath = ODataResourcePath.of(getFunctionName());
-
- // get and encode function import parameters as query expressions
- final String encodedQuery = ODataFunctionParameters.of(getParameters(), ODataProtocol.V2).toEncodedString();
-
- switch( httpMethod.get() ) {
- case HttpGet.METHOD_NAME:
- return new ODataRequestFunction(servicePath, resourcePath, encodedQuery, ODataProtocol.V2);
- case HttpPost.METHOD_NAME:
- return new ODataRequestAction(servicePath, resourcePath, null, encodedQuery, ODataProtocol.V2);
- default:
- throw new IllegalStateException("Unexpected HTTP request method for function import: " + httpMethod);
- }
- }
-
- /**
- * Default implementation for the case that this function returns a single type.
- *
- * This method can be used in subclasses to implement the {@link #executeRequest(Destination)} method.
- *
- * @param destination
- * The destination to run the function against.
- *
- * @return The single object returned by the function call. Returns {@code null} if the function did not return a
- * result.
- *
- * @throws ODataException
- * If the execution of the function failed.
- */
- @SuppressWarnings( "checkstyle:IllegalCatch" )
- @Nullable
- protected ObjectT executeSingle( @Nonnull final Destination destination )
- throws ODataException
- {
- final ODataRequestResultGeneric result = executeInternal(destination);
- final Class extends ObjectT> resultType = getEntityClass();
-
- if( resultType.equals(Void.class) ) {
- return null;
- }
-
- final ObjectT resultObject = result.as(resultType, this::refineJsonResponse);
-
- if( resultObject instanceof VdmEntity ) {
- final VdmEntity> entity = (VdmEntity>) resultObject;
-
- // use version identifier from header if present
- result.getVersionIdentifierFromHeader().peek(entity::setVersionIdentifier);
-
- entity.attachToService(getServicePath(), destination);
- }
- return resultObject;
- }
-
- /**
- * Default implementation for the case that this function returns a collection of entries.
- *
- * This method can be used in subclasses to implement the {@link #executeRequest(Destination)} method.
- *
- * @param destination
- * The destination to run the function against.
- *
- * @return A list of the objects returned by the function call. Returns an empty list if the function did not return
- * a result.
- *
- * @throws ODataException
- * If the execution of the function failed.
- */
- @Nonnull
- @SuppressWarnings( "unchecked" )
- protected List executeMultiple( @Nonnull final Destination destination )
- throws ODataException
- {
- final ODataRequestResultGeneric result = executeInternal(destination);
-
- final List resultObjectList = (List) result.asList(getEntityClass());
-
- if( !resultObjectList.isEmpty() && resultObjectList.get(0) instanceof VdmEntity ) {
- resultObjectList.forEach(entity -> ((VdmEntity>) entity).attachToService(getServicePath(), destination));
- }
- return resultObjectList;
- }
-
- @Nonnull
- private ODataRequestResultGeneric executeInternal( final Destination destination )
- throws ODataException
- {
- final ODataRequestGeneric functionImportRequest = toRequest();
- return (ODataRequestResultGeneric) functionImportRequest.execute(getHttpClient(destination));
- }
-
- /**
- * Transform the JSON element from the response to extract a result entity. By default this method returns the
- * original object.
- *
- * @param jsonElement
- * The optional response JSON element
- * @return The refined JSON element
- */
- @Nullable
- protected JsonElement refineJsonResponse( @Nullable final JsonElement jsonElement )
- {
- return jsonElement;
- }
-
- /**
- * Activates CSRF token retrieval for this OData request.
- *
- * @return The same fluent helper that will now fetch a CSRF token.
- * @deprecated CSRF token handling is now performed automatically by the underlying HTTP client. This method is a
- * no-op retained only for source compatibility. It is scheduled for removal.
- */
- @Deprecated
- @Nonnull
- public FluentHelperT withCsrfToken()
- {
- return getThis();
- }
-
- /**
- * Deactivates the CSRF token retrieval for this OData request. This is useful if the server does not support or
- * require CSRF tokens as part of the request.
- *
- * @return The same builder
- */
- @Nonnull
- public FluentHelperT withoutCsrfToken()
- {
- setSkipCsrfTokenRetrieval();
- return getThis();
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperModification.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperModification.java
deleted file mode 100644
index bf4dac79a1..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperModification.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-/**
- * Representation of an OData modification request (Create, Update, Delete) as a fluent interface for further
- * configuring the request and {@link #executeRequest(Destination) executing} it.
- *
- * @param
- * The fluent helper type.
- * @param
- * The type of the entity this OData request operates on, if any.
- */
-public abstract class FluentHelperModification>
- extends
- FluentHelperBasic>
-{
- /**
- * Instantiates this fluent helper using the given service path to send the requests.
- *
- * @param servicePath
- * The service path to direct the requests to.
- * @param entityCollection
- * The entity collection to direct the requests to.
- */
- public FluentHelperModification( @Nonnull final String servicePath, @Nullable final String entityCollection )
- {
- super(servicePath, entityCollection);
- }
-
- /**
- * Deactivates the CSRF token retrieval for this OData request. This is useful if the server does not support or
- * require CSRF tokens as part of the request.
- *
- * @return The same builder
- */
- @Nonnull
- public FluentHelperT withoutCsrfToken()
- {
- setSkipCsrfTokenRetrieval();
- return getThis();
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperRead.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperRead.java
deleted file mode 100644
index 7e3e67b10f..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperRead.java
+++ /dev/null
@@ -1,297 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.HttpClient;
-
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Streams;
-import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
-import com.sap.cloud.sdk.datamodel.odata.client.ODataProtocol;
-import com.sap.cloud.sdk.datamodel.odata.client.query.StructuredQuery;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestCount;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestRead;
-
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * Representation of an OData query as a fluent interface for further configuring the request and
- * {@link #executeRequest(Destination) executing} it.
- *
- * @param
- * The fluent helper type.
- * @param
- * The type of the result entity.
- * @param
- * The type of the {@link EntityField class that represents fields of the entity}.
- */
-@Slf4j
-public abstract class FluentHelperRead, SelectableT>
- extends
- FluentHelperBasic>
-{
-
- private final StructuredQuery delegateQuery;
-
- /**
- * Instantiates this fluent helper using the given service path and entity collection to send the requests.
- *
- * @param servicePath
- * The service path to direct the requests to.
- *
- * @param entityCollection
- * The entity collection to direct the requests to.
- */
- public FluentHelperRead( @Nonnull final String servicePath, @Nonnull final String entityCollection )
- {
- super(servicePath, entityCollection);
-
- delegateQuery = StructuredQuery.onEntity(entityCollection, ODataProtocol.V2);
- }
-
- @Override
- @Nonnull
- public ODataRequestRead toRequest()
- {
- final String queryString = delegateQuery.getEncodedQueryString();
- final ODataRequestRead request =
- new ODataRequestRead(getServicePath(), entityCollection, queryString, ODataProtocol.V2);
- return super.addHeadersAndCustomParameters(request);
- }
-
- @Override
- @Nonnull
- public FluentHelperT withQueryParameter( @Nonnull final String key, @Nullable final String value )
- {
- return super.withQueryParameter(key, value);
- }
-
- /**
- * Query modifier to limit which field values of the entity get fetched and populated, and to specify which
- * navigation properties to expand. If this method is never called, then all fields will be fetched and populated,
- * and no navigation properties expanded. But if this method is called at least once, then only the specified fields
- * will be fetched and populated. Calling this multiple times will combine the set(s) of fields and expansions of
- * each call.
- *
- * @param fields
- * Fields to select and/or navigation properties to expand.
- * @return The same fluent helper with this query modifier applied.
- */
- @SuppressWarnings( "unchecked" )
- @Nonnull
- public FluentHelperT select( @Nonnull final SelectableT... fields )
- {
- final Iterable> selectableFields = (Iterable>) Arrays.asList(fields);
- return super.select(selectableFields, delegateQuery::select, delegateQuery::select);
- }
-
- /**
- * Query modifier to sort the set of returned entities by one or more fields. If this method is called more than
- * once, then the result entity set will be sorted by each field in the order that the methods were called.
- *
- * @param field
- * Field to sort by.
- * @param order
- * Sorting direction to use (ascending or descending).
- *
- * @return The same fluent helper with this query modifier applied.
- */
- @Nonnull
- public FluentHelperT orderBy( @Nonnull final EntityField field, @Nonnull final Order order )
- {
- final com.sap.cloud.sdk.datamodel.odata.client.query.Order clientTypeOrder =
- com.sap.cloud.sdk.datamodel.odata.client.query.Order.valueOf(order.toString());
- delegateQuery.orderBy(field.getFieldName(), clientTypeOrder);
-
- return getThis();
- }
-
- /**
- * Query modifier to limit the number of entities returned. If this method is never called, then the result entity
- * list will not be limited in size. If this method is called multiple times, then only the value of the last call
- * will be used.
- *
- * @param top
- * Number of entities to limit the result set to.
- * @return The same fluent helper with this query modifier applied.
- */
- @Nonnull
- public FluentHelperT top( @Nonnull final Number top )
- {
- delegateQuery.top(top);
- return getThis();
- }
-
- /**
- * Query modifier to not return the first N entities of the result set. If this method is never called, then the
- * full list will be returned from the first entity. If this method is called multiple times, then only the value of
- * the last call will be used.
- *
- * @param skip
- * Number of entities to skip by.
- * @return The same fluent helper with this query modifier applied.
- */
- @Nonnull
- public FluentHelperT skip( @Nonnull final Number skip )
- {
- delegateQuery.skip(skip);
- return getThis();
- }
-
- @Override
- @Nonnull
- public List executeRequest( @Nonnull final Destination destination )
- throws com.sap.cloud.sdk.datamodel.odata.client.exception.ODataException
- {
- final Iterable> iterablePages = iteratingPages().executeRequest(destination);
- final Iterable iterableItems = Iterables.concat(Objects.requireNonNull(iterablePages));
- return Lists.newArrayList(iterableItems);
- }
-
- /**
- * Manually explore the individual pages from the lazy-loading entity result-set. The returning object allows for
- * performant consumption of all data through server-driven pagination.
- *
- * @return An instance of {@link FluentHelperExecutable} that allows for lazy iteration through the result-set
- * pages.
- */
- @Nonnull
- public FluentHelperExecutable>> iteratingPages()
- {
- return this::executeInternal;
- }
-
- /**
- * Manually explore the individual entities from the lazy-loading entity result-set. The returning iterable allows
- * for performant consumption of all data through server-driven pagination.
- *
- * @return An instance of {@link FluentHelperExecutable} that allows for lazy iteration through the result-set
- * pages.
- */
- @Nonnull
- public FluentHelperExecutable> iteratingEntities()
- {
- // concat applies lazy evaluation so individual pages will still be loaded lazily
- return destination -> Iterables.concat(executeInternal(destination));
- }
-
- /**
- * Manually explore the individual entities from the lazy-loading entity result-set. The returning Stream allows for
- * performant consumption of all data through server-driven pagination.
- *
- * @return An instance of {@link FluentHelperExecutable} that allows for lazy iteration through the result-set
- * pages.
- */
- @Nonnull
- public FluentHelperExecutable> streamingEntities()
- {
- // concat applies lazy evaluation so individual pages will still be loaded lazily
- return destination -> Streams.stream(Iterables.concat(executeInternal(destination)));
- }
-
- @Nonnull
- private Iterable> executeInternal( @Nonnull final Destination destination )
- throws com.sap.cloud.sdk.datamodel.odata.client.exception.ODataException
- {
- final HttpClient httpClient = getHttpClient(destination);
- final Iterable> result = toRequest().execute(httpClient).iteratePages(getEntityClass());
-
- // Refine lazy iterable to attach destination properties to individual entities in the page lists.
- //noinspection StaticPseudoFunctionalStyleMethod,ConstantConditions
- return Iterables
- .transform(
- result,
- list -> list
- .stream()
- .peek(entity -> entity.attachToService(getServicePath(), destination)) // enable lazy loading for navigation properties on entity
- .collect(Collectors.toList()));
- }
-
- /**
- * Query modifier to restrict the set of returned entities based on the values of one or more fields. If this method
- * is never called, then all accessible entities will be fetched. Calling this multiple times will combine the
- * filters into one that is the intersection of all filters (filter1 AND filter2 AND ... filterN).
- *
- * @param expression
- * Fluent helper that represents a field value expression. To create this, start with an
- * {@link com.sap.cloud.sdk.datamodel.odata.helper.EntityField EntityField} constant in your respective
- * entity type for the desired entity field. Then call one of the comparison operators and provide a
- * comparison value. Optionally the resulting fluent helper can be chained with other expression fluent
- * helpers.
- *
- * @return The same fluent helper with this query modifier applied.
- */
- @Nonnull
- public FluentHelperT filter( @Nonnull final ExpressionFluentHelper expression )
- {
- delegateQuery.filter(expression.getDelegateExpressionWithoutOuterParentheses());
- return getThis();
- }
-
- /**
- * Query modifier to return only the number of tuples that match the criteria specified in the query. The actual
- * tuples are not returned. May be used with all other query modifiers. Any call to top is overloaded with top(0).
- * Any call to skip is ignored.
- *
- * @return The number of tuples that match the criteria specified in the query.
- */
- @Nonnull
- public FluentHelperCount count()
- {
- final StructuredQuery prunedQuery = StructuredQuery.onEntity(entityCollection, ODataProtocol.V2);
-
- delegateQuery.getFilters().forEach(prunedQuery::filter);
- delegateQuery.getCustomParameters().forEach(prunedQuery::withCustomParameter);
-
- final ODataRequestCount requestCount =
- new ODataRequestCount(
- getServicePath(),
- entityCollection,
- prunedQuery.getEncodedQueryString(),
- ODataProtocol.V2);
-
- final ODataRequestCount requestCountUpdated = addHeadersAndCustomParameters(requestCount);
-
- return new FluentHelperCount(requestCountUpdated);
- }
-
- /**
- * Set the preferred page size of the OData response. A result-set may be split into multiple pages, each including
- * a subset of the entities matching the query.
- *
- * Note: The OData service might ignore the preferred page size setting and may not use pagination
- * at all.
- *
- * @param size
- * The preferred page size
- * @return This request object with the added parameter.
- */
- @Nonnull
- public FluentHelperT withPreferredPageSize( final int size )
- {
- return withHeader("Prefer", "odata.maxpagesize=" + size);
- }
-
- /**
- * Activates CSRF token retrieval for this OData request.
- *
- * @return The same fluent helper that will now fetch a CSRF token.
- * @deprecated CSRF token handling is now performed automatically by the underlying HTTP client. This method is a
- * no-op retained only for source compatibility, as read requests never require a CSRF token. It is
- * scheduled for removal.
- */
- @Deprecated
- @Nonnull
- public FluentHelperT withCsrfToken()
- {
- return getThis();
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperUpdate.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperUpdate.java
deleted file mode 100644
index f676b33ec9..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/FluentHelperUpdate.java
+++ /dev/null
@@ -1,292 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import javax.annotation.Nonnull;
-
-import org.apache.hc.client5.http.classic.HttpClient;
-
-import com.google.common.annotations.Beta;
-import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
-import com.sap.cloud.sdk.datamodel.odata.client.ODataProtocol;
-import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataSerializationException;
-import com.sap.cloud.sdk.datamodel.odata.client.expression.FieldReference;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ETagSubmissionStrategy;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataEntityKey;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestResultGeneric;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestUpdate;
-import com.sap.cloud.sdk.datamodel.odata.client.request.UpdateStrategy;
-
-import io.vavr.control.Option;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * Representation of an OData update request as a fluent interface for further configuring the request and
- * {@link #executeRequest(Destination) executing} it.
- *
- * @param
- * The fluent helper type.
- * @param
- * The type of the entity to update.
- */
-@Slf4j
-public abstract class FluentHelperUpdate>
- extends
- FluentHelperModification
-{
- private final Collection> includedFields = new HashSet<>();
- private final Collection> excludedFields = new HashSet<>();
- private UpdateStrategy updateStrategy = UpdateStrategy.MODIFY_WITH_PATCH;
- private ETagSubmissionStrategy eTagSubmissionStrategy = ETagSubmissionStrategy.SUBMIT_ETAG_FROM_ENTITY;
-
- /**
- * Instantiates this fluent helper using the given service path to send the requests.
- *
- * @param servicePath
- * The service path to direct the requests to.
- * @param entityCollection
- * The entity collection to direct the requests to.
- */
- public FluentHelperUpdate( @Nonnull final String servicePath, @Nonnull final String entityCollection )
- {
- super(servicePath, entityCollection);
- }
-
- /**
- * The entity object to be updated by calling the {@link #executeRequest(Destination)} method.
- *
- * @return The entity to be updated.
- */
- protected abstract EntityT getEntity();
-
- @SuppressWarnings( "unchecked" )
- @Nonnull
- @Override
- protected Class extends EntityT> getEntityClass()
- {
- return (Class extends EntityT>) getEntity().getClass();
- }
-
- /**
- * The update request will ignore any version identifier present on the entity and not send an `If-Match` header.
- *
- * Warning: This might lead to a response from the remote system that the `If-Match` header is missing.
- *
- * It depends on the implementation of the remote system whether the `If-Match` header is expected.
- *
- * @return The same request builder that will not send the `If-Match` header in the update request
- */
- @Nonnull
- public FluentHelperT disableVersionIdentifier()
- {
- eTagSubmissionStrategy = ETagSubmissionStrategy.SUBMIT_NO_ETAG;
- return getThis();
- }
-
- /**
- * The update request will ignore any version identifier present on the entity and update the entity, regardless of
- * any changes on the remote entity.
- *
- * Warning: Be careful with this option, as this might overwrite any changes made to the remote
- * representation of this object.
- *
- * @return The same request builder that will ignore the version identifier of the entity to update
- */
- @Nonnull
- public FluentHelperT matchAnyVersionIdentifier()
- {
- eTagSubmissionStrategy = ETagSubmissionStrategy.SUBMIT_ANY_MATCH_ETAG;
- return getThis();
- }
-
- @Override
- @Nonnull
- public ModificationResponse executeRequest( @Nonnull final Destination destination )
- {
- final HttpClient httpClient = getHttpClient(destination);
-
- final ODataRequestResultGeneric result = toRequest().execute(httpClient);
-
- return ModificationResponse.of(result, getEntity(), destination);
- }
-
- @Override
- @Nonnull
- public ODataRequestUpdate toRequest()
- {
- final EntityT entity = getEntity();
- final String serializedEntity = getSerializedEntity();
- final String versionIdentifier =
- eTagSubmissionStrategy.getHeaderFromVersionIdentifier(entity.getVersionIdentifier());
-
- final ODataRequestUpdate request =
- new ODataRequestUpdate(
- getServicePath(),
- getEntityCollection(),
- ODataEntityKey.of(entity.getKey(), ODataProtocol.V2),
- serializedEntity,
- updateStrategy,
- versionIdentifier,
- ODataProtocol.V2);
-
- return super.addHeadersAndCustomParameters(request);
- }
-
- @Nonnull
- private String getSerializedEntity()
- {
- final EntityT entity = getEntity();
- try {
- final List fieldsToExcludeUpdate =
- excludedFields
- .stream()
- .map(EntitySelectable::getFieldName)
- .map(FieldReference::of)
- .collect(Collectors.toList());
-
- final List fieldsToIncludeInUpdate =
- includedFields
- .stream()
- .map(EntitySelectable::getFieldName)
- .map(FieldReference::of)
- .collect(Collectors.toList());
-
- switch( updateStrategy ) {
- case REPLACE_WITH_PUT:
- return ODataEntitySerializer.serializeEntityForUpdatePut(entity, fieldsToExcludeUpdate);
- case MODIFY_WITH_PATCH:
- return ODataEntitySerializer.serializeEntityForUpdatePatchShallow(entity, fieldsToIncludeInUpdate);
- case MODIFY_WITH_PATCH_RECURSIVE_DELTA:
- return ODataEntitySerializer
- .serializeEntityForUpdatePatchRecursiveDelta(entity, fieldsToIncludeInUpdate);
- case MODIFY_WITH_PATCH_RECURSIVE_FULL:
- return ODataEntitySerializer
- .serializeEntityForUpdatePatchRecursiveFull(entity, fieldsToIncludeInUpdate);
- default:
- throw new IllegalStateException("Unexpected update strategy:" + updateStrategy);
- }
- }
- catch( final Exception e ) {
- final String msg =
- String
- .format(
- "Failed to serialize OData Update HTTP request entity for type %s with strategy %s",
- getEntityClass().getSimpleName(),
- updateStrategy);
-
- final ODataRequestUpdate request =
- new ODataRequestUpdate(
- getServicePath(),
- entity.getEntityCollection(),
- ODataEntityKey.of(entity.getKey(), ODataProtocol.V2),
- "",
- updateStrategy,
- eTagSubmissionStrategy.getHeaderFromVersionIdentifier(entity.getVersionIdentifier()),
- ODataProtocol.V2);
- throw new ODataSerializationException(request, entity, msg, e);
- }
- }
-
- /**
- * Allows to explicitly specify entity fields that shall be sent in an update request regardless if the values of
- * these fields have been changed. This is helpful in case the API requires to send certain fields in any case in an
- * update request.
- *
- * @param fields
- * The fields to be included in the update execution.
- * @return The same fluent helper which will include the specified fields in an update request.
- */
- @Nonnull
- @SafeVarargs
- @SuppressWarnings( "varargs" )
- public final FluentHelperT includingFields( @Nonnull final EntitySelectable... fields )
- {
- includedFields.addAll(Arrays.asList(fields));
- return getThis();
- }
-
- /**
- * Allows to explicitly specify entity fields that should not be sent in an update request. This is helpful in case,
- * some services require no read only fields to be sent for update requests. These fields are only excluded in a PUT
- * request, they are not considered in a PATCH request.
- *
- * @param fields
- * The fields to be excluded in the update execution.
- * @return The same fluent helper which will exclude the specified fields in an update request.
- */
- @Nonnull
- @SafeVarargs
- @SuppressWarnings( "varargs" )
- public final FluentHelperT excludingFields( @Nonnull final EntitySelectable... fields )
- {
- excludedFields.addAll(Arrays.asList(fields));
- return getThis();
- }
-
- @Nonnull
- private String getEntityCollection()
- {
- return Option.of(entityCollection).getOrElse(() -> getEntity().getEntityCollection());
- }
-
- /**
- * Allows to control that the request to update the entity is sent with the HTTP method PUT and its payload contains
- * all fields of the entity, regardless which of them have been changed.
- *
- * @return The same fluent helper which will replace the entity in the remote system
- */
- @Nonnull
- public final FluentHelperT replacingEntity()
- {
- updateStrategy = UpdateStrategy.REPLACE_WITH_PUT;
- return getThis();
- }
-
- /**
- * Allows to control that the request to update the entity is sent with the HTTP method PATCH and its payload
- * contains the changed fields only.
- *
- * @return The same fluent helper which will modify the entity in the remote system.
- */
- @Nonnull
- public final FluentHelperT modifyingEntity()
- {
- updateStrategy = UpdateStrategy.MODIFY_WITH_PATCH;
- return getThis();
- }
-
- /**
- * Allows to control that the request to update the entity is sent with the HTTP method PATCH and its payload
- * contains the changed fields only, with different strategies for handling nested fields.
- *
- * @param strategy
- * The strategy to use for the PATCH update.
- * @return The same fluent helper which will modify the entity in the remote system.
- * @throws IllegalArgumentException
- * If an unknown ModifyPatchStrategy is provided.
- * @since 5.16.0
- */
- @Beta
- @Nonnull
- public final FluentHelperT modifyingEntity( @Nonnull final ModifyPatchStrategy strategy )
- {
- switch( strategy ) {
- case SHALLOW:
- return modifyingEntity();
- case RECURSIVE_DELTA:
- updateStrategy = UpdateStrategy.MODIFY_WITH_PATCH_RECURSIVE_DELTA;
- break;
- case RECURSIVE_FULL:
- updateStrategy = UpdateStrategy.MODIFY_WITH_PATCH_RECURSIVE_FULL;
- break;
- default:
- throw new IllegalArgumentException("Unknown ModifyPatchStrategy: " + strategy);
- }
- return getThis();
- }
-
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/ModificationResponse.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/ModificationResponse.java
deleted file mode 100644
index 227c5baa8d..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/ModificationResponse.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import com.google.common.annotations.Beta;
-import com.google.gson.Gson;
-import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestResultGeneric;
-
-import io.vavr.control.Option;
-import io.vavr.control.Try;
-import lombok.AccessLevel;
-import lombok.EqualsAndHashCode;
-import lombok.RequiredArgsConstructor;
-import lombok.ToString;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * Generic OData service response wrapper for data modification requests.
- *
- * @param
- * The generic entity type.
- */
-@EqualsAndHashCode
-@ToString
-@RequiredArgsConstructor( staticName = "of", onConstructor = @__( { @Beta } ), access = AccessLevel.PUBLIC )
-@Slf4j
-public final class ModificationResponse>
-{
- private static final Gson GSON = new Gson();
-
- @Nullable
- private EntityT modifiedEntity;
-
- @Nonnull
- private Option responseEntity = Option.none();
-
- @Nonnull
- private final ODataRequestResultGeneric result;
-
- @Nonnull
- private final EntityT originalRequestEntity;
-
- @Nonnull
- private final Destination destination;
-
- /**
- * Get an updated version of the entity. If the service responded with an entity it is returned here. If the service
- * didn't respond with an entity but send an @{code ETag} header, the entity is updated and returned. Otherwise a
- * copy of the original, unmodified entity is returned.
- *
- * @return The modified entity.
- */
- @Nonnull
- public synchronized EntityT getModifiedEntity()
- {
- if( modifiedEntity == null ) {
- evaluateResponse();
- }
- return modifiedEntity;
- }
-
- /**
- * Get the optional response entity parsed from the HTTP content.
- *
- * @return The parsed entity or none.
- */
- @Nonnull
- public synchronized Option getResponseEntity()
- {
- // We synchronize the full method here because Fortify does not like double checked locking:
- // https://vulncat.fortify.com/en/detail?id=desc.structural.java.code_correctness_double_checked_locking
- if( modifiedEntity == null ) {
- evaluateResponse();
- }
- return responseEntity;
- }
-
- @SuppressWarnings( "unchecked" )
- private void evaluateResponse()
- {
- responseEntity = parseEntityFromResponse();
-
- // create a copy before modifying the version identifier to not change existing objects
- final EntityT entityToModify = responseEntity.getOrElse(originalRequestEntity);
-
- // clone entity
- modifiedEntity = GSON.fromJson(GSON.toJson(entityToModify), (Class) originalRequestEntity.getClass());
-
- modifiedEntity.attachToService(result.getODataRequest().getServicePath(), destination);
-
- modifiedEntity.setVersionIdentifier(getUpdatedVersionIdentifier().getOrNull());
- }
-
- /**
- * Access the original entity used to make the request.
- *
- * @return The original entity object used to perform an OData request.
- */
- @Nonnull
- public EntityT getRequestEntity()
- {
- return originalRequestEntity;
- }
-
- /**
- * Get the response status code.
- *
- * @return The integer representation of the HTTP status code.
- */
- public int getResponseStatusCode()
- {
- return result.getHttpResponse().getCode();
- }
-
- /**
- * Get the response headers.
- *
- * @return The headers of the HTTP status code.
- */
- @Nonnull
- public Map> getResponseHeaders()
- {
- return result.getAllHeaderValues();
- }
-
- /**
- * Get the version identifier present in the response headers, the identifier of the original entity or none, if
- * neither exist.
- *
- * @return An up to date version identifier or none.
- */
- @Nonnull
- public Option getUpdatedVersionIdentifier()
- {
- return result
- .getVersionIdentifierFromHeader()
- .orElse(() -> getResponseEntity().flatMap(entity -> entity.getVersionIdentifier()));
- }
-
- @Nonnull
- @SuppressWarnings( "unchecked" )
- private Option parseEntityFromResponse()
- {
- return Try
- .of(() -> result.as((Class) originalRequestEntity.getClass()))
- .onFailure(e -> log.debug("Failed to parse entity from HTTP response.", e))
- .toOption()
- .peek(entity -> result.getVersionIdentifierFromHeader().peek(entity::setVersionIdentifier));
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/ModifyPatchStrategy.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/ModifyPatchStrategy.java
deleted file mode 100644
index e934c50324..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/ModifyPatchStrategy.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import com.google.common.annotations.Beta;
-
-/**
- * Strategy to determine how a patch operation should be applied to an entity.
- *
- * @since 5.16.0
- */
-@Beta
-public enum ModifyPatchStrategy
-{
- /** Only the top level fields can be patched */
- SHALLOW,
-
- /** All top level and nested fields can be patched, resulting in JSON containing only the changed fields */
- RECURSIVE_DELTA,
-
- /**
- * All top level and nested fields can be patched, resulting in JSON containing the full value of complex object.
- */
- RECURSIVE_FULL
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/ODataEntitySerializer.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/ODataEntitySerializer.java
deleted file mode 100644
index 3898351d0d..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/ODataEntitySerializer.java
+++ /dev/null
@@ -1,321 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.function.BiConsumer;
-import java.util.function.BiPredicate;
-import java.util.function.Predicate;
-import java.util.stream.StreamSupport;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.sap.cloud.sdk.datamodel.odata.adapter.ODataNumberSerializer;
-import com.sap.cloud.sdk.datamodel.odata.client.expression.FieldReference;
-
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-final class ODataEntitySerializer
-{
- private static final Gson GSON;
- private static final Gson GSON_SERIALIZING_NULLS;
-
- static {
- final ODataNumberSerializer numberSerializer = new ODataNumberSerializer();
- final GsonBuilder builder =
- new GsonBuilder()
- .registerTypeAdapter(Long.class, numberSerializer)
- .registerTypeAdapter(Double.class, numberSerializer)
- .registerTypeAdapter(Float.class, numberSerializer)
- .registerTypeAdapter(BigDecimal.class, numberSerializer);
- // CXSDK currently serializes Edm.SByte as plain number so the client also does it for consistency.
- // .registerTypeAdapter(Byte.class, numberSerializer)
-
- GSON = builder.create();
- GSON_SERIALIZING_NULLS = builder.serializeNulls().create();
- }
-
- /**
- * Serializes an entity for update request (PUT). Allowing null values. Removing potential "versionIdentifier"
- * fields.
- *
- * @param entity
- * The OData V2 entity reference.
- * @param excludedFields
- * Collection of fields to be excluded in the update (PUT) request.
- * @return The serialized JSON string for entity update request.
- */
- @Nonnull
- static String serializeEntityForUpdatePut(
- @Nonnull final VdmEntity> entity,
- @Nullable final Collection excludedFields )
- {
- final JsonObject jsonObject = GSON_SERIALIZING_NULLS.toJsonTree(entity).getAsJsonObject();
-
- removeVersionIdentifier(jsonObject);
-
- // find field names to be removed from PUT request
- if( excludedFields != null ) {
- excludedFields.stream().map(FieldReference::getFieldName).forEach(jsonObject::remove);
- }
-
- return GSON_SERIALIZING_NULLS.toJson(jsonObject);
- }
-
- /**
- * Serializes an entity for create request. Ignoring empty collections and null values.
- *
- * @param entity
- * The OData V2 entity reference.
- * @return The serialized JSON string for entity create request.
- */
- @Nonnull
- static String serializeEntityForCreate( @Nonnull final VdmEntity> entity )
- {
- // When using builder pattern, all 1:n navigation properties will be initialized with `new ArrayList()` instead of expected `null`
- final JsonObject jsonObject = GSON.toJsonTree(entity).getAsJsonObject();
-
- removeEmptyArrays(jsonObject);
-
- return GSON.toJson(jsonObject);
- }
-
- /**
- * Serializes an entity for update request (PATCH). Allowing null values.
- *
- * @param entity
- * The OData V2 entity reference.
- * @param includedFields
- * Collection of fields to be included in the update (PATCH) request.
- * @return The serialized JSON string for entity update request.
- */
- @Nonnull
- static String serializeEntityForUpdatePatchShallow(
- @Nonnull final VdmEntity> entity,
- @Nonnull final Collection includedFields )
- {
- final JsonObject fullEntity = GSON_SERIALIZING_NULLS.toJsonTree(entity).getAsJsonObject();
-
- // find field names to be patched
- final Set fieldNamesToPatch = new HashSet<>(entity.getChangedFields().keySet());
- includedFields.stream().map(FieldReference::getFieldName).forEach(fieldNamesToPatch::add);
- log.debug("The following fields are marked for updates: {}.", fieldNamesToPatch);
-
- final JsonObject partialEntity = new JsonObject();
-
- fieldNamesToPatch.forEach(key -> partialEntity.add(key, fullEntity.get(key)));
-
- return GSON_SERIALIZING_NULLS.toJson(partialEntity);
- }
-
- /**
- * Serializes an entity for update request (PATCH) including changes in nested properties. Allowing null values.
- * Resulting JSON contains the full value of complex fields for changing any nested field.
- *
- * @param entity
- * The OData V2 entity reference.
- * @param includedFields
- * Collection of fields to be included in the update (PATCH) request.
- * @return The serialized JSON string for entity update request.
- */
- @Nonnull
- static String serializeEntityForUpdatePatchRecursiveFull(
- @Nonnull final VdmEntity> entity,
- @Nonnull final Collection includedFields )
- {
- final JsonObject fullEntityJson = GSON_SERIALIZING_NULLS.toJsonTree(entity).getAsJsonObject();
- final JsonObject patchObject = new JsonObject();
-
- final Set changedFieldNames = new HashSet<>(entity.getChangedFields().keySet());
- includedFields.stream().map(FieldReference::getFieldName).forEach(changedFieldNames::add);
- changedFieldNames.forEach(key -> patchObject.add(key, fullEntityJson.get(key)));
-
- entity
- .toMapOfFields()
- .entrySet()
- .stream()
- .filter(entry -> !patchObject.has(entry.getKey()))
- .filter(entry -> containsNestedChangedFields(entry.getValue()))
- .forEach(entry -> patchObject.add(entry.getKey(), fullEntityJson.get(entry.getKey())));
-
- log.debug("The following object is serialized for update : {}.", patchObject);
-
- return GSON_SERIALIZING_NULLS.toJson(patchObject);
- }
-
- /**
- * Checks if the given complex object contains any changed fields in its nested fields.
- *
- * @param obj
- * the complex object to check
- * @return true if the complex object contains any changed fields, false otherwise
- */
- private static boolean containsNestedChangedFields( final Object obj )
- {
- if( obj instanceof VdmComplex> vdmComplex ) {
- if( !vdmComplex.getChangedFields().isEmpty() ) {
- return true;
- }
- for( final Object complexField : vdmComplex.toMapOfFields().values() ) {
- if( containsNestedChangedFields(complexField) ) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Serializes an entity for update request (PATCH) including changes in nested properties. Allowing null values.
- * Resulting JSON contains only the changed fields (including nested changes).
- *
- * @param entity
- * The OData V2 entity reference.
- * @param includedFields
- * Collection of fields to be included in the update (PATCH) request.
- * @return The serialized JSON string for entity update request.
- */
- @Nonnull
- static String serializeEntityForUpdatePatchRecursiveDelta(
- @Nonnull final VdmEntity> entity,
- @Nonnull final Collection includedFields )
- {
- final JsonObject fullEntityJson = GSON_SERIALIZING_NULLS.toJsonTree(entity).getAsJsonObject();
- final JsonObject patchObject = new JsonObject();
-
- // Recursively build patch object from changed fields
- final JsonObject tempPatchObject = createPatchObjectRecursiveDelta(entity, fullEntityJson);
-
- // Add included fields (from the root only)
- includedFields
- .stream()
- .map(FieldReference::getFieldName)
- .forEach(key -> patchObject.add(key, fullEntityJson.get(key)));
-
- // Merge all fields from the tempPatchObject if not already present
- tempPatchObject
- .entrySet()
- .stream()
- .filter(entry -> !patchObject.has(entry.getKey()))
- .forEach(entry -> patchObject.add(entry.getKey(), entry.getValue()));
-
- log.debug("The following delta object is serialized for update : {}.", patchObject);
-
- return GSON_SERIALIZING_NULLS.toJson(patchObject);
- }
-
- /**
- * Recursively builds a patch object for a VdmObject by including only changed fields. Complex fields are traversed
- * recursively.
- *
- * @param vdmObject
- * the VdmObject (entity or complex) to build the patch from
- * @param jsonObject
- * the full JSON representation of this object
- * @return a JsonObject that contains only changed fields (including nested changes)
- */
- @Nonnull
- private static
- JsonObject
- createPatchObjectRecursiveDelta( @Nonnull final VdmObject> vdmObject, @Nonnull final JsonObject jsonObject )
- {
- final JsonObject patch = new JsonObject();
-
- // Process all complex fields and recursively build patch for the complex field
- vdmObject.toMapOfFields().forEach(( fieldName, val ) -> {
- if( val instanceof VdmComplex> complexField ) {
- final var childJsonObject = jsonObject.getAsJsonObject(fieldName);
- final var childJsonObjectDelta = createPatchObjectRecursiveDelta(complexField, childJsonObject);
- if( !childJsonObjectDelta.isEmpty() ) {
- patch.add(fieldName, childJsonObjectDelta);
- }
- }
- });
-
- // Add explicitly changed fields
- vdmObject.getChangedFields().keySet().forEach(key -> patch.add(key, jsonObject.get(key)));
-
- return patch;
- }
-
- private static void removeVersionIdentifier( @Nonnull final JsonObject jsonObject )
- {
- log.debug("Removing redundant \"versionIdentifier\" recursively from JSON object: {}", jsonObject);
-
- final Predicate isNullOrString =
- obj -> obj.isJsonNull() || obj.isJsonPrimitive() && obj.getAsJsonPrimitive().isString();
-
- traverseJsonObject(
- jsonObject,
- ( element, name ) -> "versionIdentifier".equals(name) && isNullOrString.test(element),
- JsonObject::remove);
-
- log.debug("JSON object after removing redundant \"versionIdentifier\": {}", jsonObject);
- }
-
- private static void removeEmptyArrays( @Nonnull final JsonObject jsonObject )
- {
- log.debug("Removing empty arrays recursively from JSON object: {}", jsonObject);
-
- traverseJsonObject(
- jsonObject,
- ( element, name ) -> element.isJsonArray() && element.getAsJsonArray().size() == 0,
- JsonObject::remove);
-
- log.debug("JSON object after removing empty arrays: {}", jsonObject);
- }
-
- /**
- * Traverse the JSON object tree to apply an action on filtered items.
- *
- * @param jsonObject
- * The current JSON object to check properties for.
- * @param filter
- * The filter as lambda (predicate) for property value and property key.
- * @param action
- * The action as lambda (consumer) for parent object and filtered property key.
- */
- private static void traverseJsonObject(
- @Nonnull final JsonObject jsonObject,
- @Nonnull final BiPredicate filter,
- @Nonnull final BiConsumer action )
- {
- final List filteredChildKeys = new ArrayList<>();
-
- jsonObject.entrySet().forEach(entry -> {
- if( entry.getValue().isJsonObject() ) {
- // Apply this logic recursively for all nested objects
- traverseJsonObject(entry.getValue().getAsJsonObject(), filter, action);
- } else if( filter.test(entry.getValue(), entry.getKey()) ) {
- // Collect key names for children that tested against the provided filter predicate
- filteredChildKeys.add(entry.getKey());
- } else if( entry.getValue().isJsonArray() ) {
- // Apply this logic recursively for lists of nested objects
- final JsonArray jsonArray = entry.getValue().getAsJsonArray();
- StreamSupport
- .stream(jsonArray.spliterator(), false)
- .filter(JsonElement::isJsonObject)
- .map(JsonElement::getAsJsonObject)
- .forEach(o -> traverseJsonObject(o, filter, action));
- }
- });
-
- log
- .trace(
- "Applying the provided action on parent element {} for the following child items: {}",
- jsonObject,
- filteredChildKeys);
-
- filteredChildKeys.forEach(affectedChildKey -> action.accept(jsonObject, affectedChildKey));
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/OneToOneLink.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/OneToOneLink.java
deleted file mode 100644
index bd5f9b329a..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/OneToOneLink.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import javax.annotation.Nonnull;
-
-/**
- * Interface designed to be implemented by {@link EntityLink} class in order to provide a filter function.
- *
- * @param
- * The entity where the link starts.
- * @param
- * The entity where the link ends (i.e. the related entity).
- */
-public interface OneToOneLink
-{
- /**
- * Add filter to a one-to-one navigation property relationship.
- *
- * @param filterExpression
- * The filter expression to use for resolving the navigation property
- * @return The fluent helper to continue constructing a filter expression.
- */
- @Nonnull
- ExpressionFluentHelper filter( @Nonnull final ExpressionFluentHelper filterExpression );
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/Order.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/Order.java
deleted file mode 100644
index 7ecf43a135..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/Order.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-/**
- * Used with orderBy methods in entity fluent helper objects to set the sorting order of field values.
- */
-public enum Order
-{
- /**
- * Sort field values in ascending order.
- */
- ASC,
-
- /**
- * Sort field values in descending order.
- */
- DESC
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/SingleValuedFluentHelperFunction.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/SingleValuedFluentHelperFunction.java
deleted file mode 100644
index efa3f3c914..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/SingleValuedFluentHelperFunction.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import javax.annotation.Nonnull;
-
-/**
- * Representation of any OData function import as a fluent class for further configuring the request and
- * {@link #executeRequest(Destination) executing} it. This is specifically for functions that return either a single
- * primitive value or entity value
- *
- * @param
- * The fluent helper type.
- * @param
- * The type of the object this OData request operates on, if any.
- * @param
- * The type of the result entity, if any.
- */
-public abstract class SingleValuedFluentHelperFunction
- extends
- FluentHelperFunction
-{
-
- /**
- * Instantiates this fluent helper using the given service path to send the requests.
- *
- * @param servicePath
- * The service path to direct the requests to.
- */
- public SingleValuedFluentHelperFunction( @Nonnull final String servicePath )
- {
- super(servicePath);
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmComplex.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmComplex.java
deleted file mode 100644
index 74297e4257..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmComplex.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import lombok.EqualsAndHashCode;
-
-/**
- * Complex type in the virtual data model.
- *
- * @param
- * Object type of the complex type.
- */
-@EqualsAndHashCode( callSuper = true, doNotUseGetters = true )
-public abstract class VdmComplex extends VdmObject
-{
-
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmEntity.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmEntity.java
deleted file mode 100644
index 7da047d602..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmEntity.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.HttpClient;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.collect.Iterables;
-import com.google.gson.annotations.SerializedName;
-import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
-import com.sap.cloud.sdk.datamodel.odata.client.ODataApacheHttpClient5Accessor;
-import com.sap.cloud.sdk.datamodel.odata.client.ODataProtocol;
-import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataRequestException;
-import com.sap.cloud.sdk.datamodel.odata.client.expression.ODataResourcePath;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataEntityKey;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestRead;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestResultGeneric;
-
-import io.vavr.control.Option;
-import lombok.AccessLevel;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * Represents a {@link VdmObject} which is an entity. Entities may have a version identifier.
- *
- * @param
- * The specific entity data type.
- */
-@EqualsAndHashCode( callSuper = true, doNotUseGetters = true )
-public abstract class VdmEntity extends VdmObject
-{
- @SerializedName( "versionIdentifier" )
- @JsonProperty( "versionIdentifier" )
- @Nullable
- private String versionIdentifier = null;
-
- /**
- * The service path only used for the fetch commands of this entity.
- *
- * Note: Use with caution, as this can easily break the fetch call on this entity. See the interface of the
- * corresponding service for the default service path.
- */
- @Getter( AccessLevel.PROTECTED )
- @Setter( AccessLevel.PROTECTED )
- @JsonIgnore
- @EqualsAndHashCode.Exclude
- private transient String servicePathForFetch;
-
- /**
- * Convenience field for reusing the same destination with multiple queries (e.g. fetching associated entities).
- */
- @Getter( AccessLevel.PROTECTED )
- @Setter( AccessLevel.PROTECTED )
- @JsonIgnore
- @EqualsAndHashCode.Exclude
- private transient Destination destinationForFetch;
-
- /**
- * Getter for the version identifier of this entity.
- *
- * This identifier can be used to compare this entity with a remote one. As not the whole entity has to be sent this
- * reduces the request overhead.
- *
- * Actual use cases can be checking whether this entity is still current with regards to the remote entity, and
- * ensuring that a update/delete operation is done on the expected version of the remote entity.
- *
- * @return The optional version identifier.
- */
- @Nonnull
- public Option getVersionIdentifier()
- {
- return Option.of(versionIdentifier);
- }
-
- /**
- * Setter for the version identifier of this entity.
- *
- * This identifier can be used to compare this entity with a remote one. As not the whole entity has to be sent this
- * reduces the request overhead.
- *
- * Actual use cases can be checking whether this entity is still current with regards to the remote entity, and
- * ensuring that a update/delete operation is done on the expected version of the remote entity.
- *
- * @param versionIdentifier
- * The version identifier of this entity.
- */
- public void setVersionIdentifier( @Nullable final String versionIdentifier )
- {
- this.versionIdentifier = versionIdentifier;
- }
-
- /**
- * Used by fluent helpers and navigation property methods to construct OData queries.
- *
- * @return EDMX name of the entity collection identifier.
- */
- @Nonnull
- protected abstract String getEntityCollection();
-
- /**
- * Used by fluent helpers and navigation property methods to construct OData queries.
- *
- * @return Default context path to the OData service. In other words, everything in between the
- * {@code protocol://hostname:port} and the OData resource name (entity set, {@code $metadata}, etc.)
- */
- @Nullable
- protected String getDefaultServicePath()
- {
- return null;
- }
-
- /**
- * Sets the service path and destination for the fetch commands of this entity.
- *
- * Also applies to any associated entities (navigation properties) that were previously fetched.
- *
- * Note: Use with caution, as this can easily break the fetch calls on this entity. See the interface of the
- * corresponding service for the default service path.
- *
- * @param servicePath
- * Optional parameter. New service path to apply to this entity and any associated entities that were
- * previously fetched. If a null value is provided and the service path has never been set, then the
- * service path will be set to the default defined in the corresponding service interface.
- * @param destination
- * New destination to apply to this entity and any associated entities that were previously fetched.
- */
- protected void attachToService( @Nullable final String servicePath, @Nonnull final Destination destination )
- {
- if( servicePath != null ) {
- servicePathForFetch = servicePath;
- } else if( servicePathForFetch == null ) {
- servicePathForFetch = getDefaultServicePath();
- }
-
- destinationForFetch = destination;
-
- toMapOfNavigationProperties().values().forEach(navProperty -> {
- if( navProperty instanceof Iterable ) {
- final Iterable> navPropertyList = (Iterable>) navProperty;
- final boolean itemTypeIsEntity = Iterables.getFirst(navPropertyList, null) instanceof VdmEntity;
-
- if( itemTypeIsEntity ) {
- for( final Object childEntity : navPropertyList ) {
- final VdmEntity> vdmEntity = (VdmEntity>) childEntity;
- vdmEntity.attachToService(servicePathForFetch, destinationForFetch);
- }
- }
- } else if( navProperty instanceof VdmEntity ) {
- final VdmEntity> vdmEntity = (VdmEntity>) navProperty;
- vdmEntity.attachToService(servicePathForFetch, destinationForFetch);
- }
- });
- }
-
- /**
- * Helper method to lazily resolve a field value from current entity.
- *
- * @param fieldName
- * The field name to lookup.
- * @param fieldType
- * The field type to cast the value to.
- * @param
- * The generic type parameter.
- * @return A list of requested values.
- */
- @Nonnull
- protected > List fetchFieldAsList(
- @Nonnull final String fieldName,
- @Nonnull final Class fieldType )
- {
- final Destination destination = getDestinationForFetch();
- final ODataRequestResultGeneric response = fetchField(fieldName, destination);
- final List entityList = response.asList(fieldType);
- for( final T entity : entityList ) {
- entity.attachToService(getServicePathForFetch(), destination);
- }
- return entityList;
- }
-
- /**
- * Helper method to lazily resolve a field value from current entity.
- *
- * @param fieldName
- * The field name to lookup.
- * @param fieldType
- * The field type to cast the value to.
- * @param
- * The generic type parameter.
- * @return The requested values.
- */
- @Nonnull
- protected > T fetchFieldAsSingle(
- @Nonnull final String fieldName,
- @Nonnull final Class fieldType )
- {
- final Destination destination = getDestinationForFetch();
- final ODataRequestResultGeneric response = fetchField(fieldName, destination);
- final T entity = response.as(fieldType);
- entity.attachToService(getServicePathForFetch(), destination);
- return entity;
- }
-
- @Nonnull
- private ODataRequestResultGeneric fetchField( final String fieldName, final Destination destination )
- {
- final ODataEntityKey entityKey = ODataEntityKey.of(getKey(), ODataProtocol.V2);
- final ODataResourcePath path = ODataResourcePath.of(getEntityCollection(), entityKey).addSegment(fieldName);
- final ODataRequestRead request = new ODataRequestRead(getServicePathForFetch(), path, null, ODataProtocol.V2);
- if( destination == null ) {
- throw new ODataRequestException(
- request,
- "Failed to fetch related objects from field name "
- + fieldName
- + ": The entity was created locally without an assigned HttpDestination. This method is applicable only on entities which were retrieved or created using the OData VDM.",
- null);
- }
- final HttpClient httpClient = ODataApacheHttpClient5Accessor.getHttpClient(destination);
- return request.execute(httpClient);
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmEntityUtil.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmEntityUtil.java
deleted file mode 100644
index 08d6c65692..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmEntityUtil.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.lang.reflect.InvocationTargetException;
-
-import javax.annotation.Nonnull;
-
-import com.sap.cloud.sdk.cloudplatform.exception.ShouldNotHappenException;
-
-import lombok.RequiredArgsConstructor;
-
-/**
- * Utility class to manage OData entity deserialization.
- *
- * @param
- * Entity type to create new instances from.
- */
-@RequiredArgsConstructor
-public final class VdmEntityUtil>
-{
- private final Class entityClass;
-
- @Nonnull
- EntityT newInstance()
- {
- try {
- return entityClass.getDeclaredConstructor().newInstance();
- }
- catch( final
- InstantiationException
- | IllegalAccessException
- | NoSuchMethodException
- | InvocationTargetException e ) {
- throw new ShouldNotHappenException(
- "Failed to instantiate object of type " + entityClass.getSimpleName(),
- e);
- }
- }
-
- /**
- * Helper method to resolve the expected entity type for the provided fluent helper instance. For internal use.
- *
- * @param fluentHelper
- * The fluent helper instance to resolve the entity type for.
- * @param
- * The generic entity type.
- * @return The entity type.
- */
- @SuppressWarnings( "unchecked" )
- @Nonnull
- public static Class getEntityClass( @Nonnull final FluentHelperBasic, ?, ?> fluentHelper )
- {
- return (Class) fluentHelper.getEntityClass();
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmMediaEntity.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmMediaEntity.java
deleted file mode 100644
index b4977c17be..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmMediaEntity.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.annotation.Nonnull;
-
-import org.apache.hc.client5.http.classic.HttpClient;
-import org.apache.hc.core5.http.HttpEntity;
-
-import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
-import com.sap.cloud.sdk.datamodel.odata.client.ODataApacheHttpClient5Accessor;
-import com.sap.cloud.sdk.datamodel.odata.client.ODataProtocol;
-import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataException;
-import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataRequestException;
-import com.sap.cloud.sdk.datamodel.odata.client.exception.ODataResponseException;
-import com.sap.cloud.sdk.datamodel.odata.client.expression.ODataResourcePath;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataEntityKey;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestReadByKey;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestResultGeneric;
-
-import lombok.EqualsAndHashCode;
-
-/**
- * Represents a media entity which exposes additional data under a {@code $value} endpoint.
- *
- * @param
- * The specific entity type.
- */
-@EqualsAndHashCode( callSuper = true, doNotUseGetters = true )
-public abstract class VdmMediaEntity extends VdmEntity
-{
- /**
- * Get the binary data stream (file) from this media entity. Perform this operation after retrieving the
- * entity object from the OData service.
- *
- * Alternatively, you can use this method to only retrieve the media resource without requesting the entity
- * data. Build this entity via its {@code .builder()} and use {@link #attachToService(String, Destination)} to
- * declare a service path and destination to request the media resource from. You can obtain the service path from
- * the {@code #DEFAULT_SERVICE_PATH}, e.g.
- * {@code BusinessPartnerServiceBusinessPartnerService.DEFAULT_SERVICE_PATH}
- *
- * Please ensure this stream is closed after usage. The below example achieves this using
- * try-with-resources:
- *
- *
- * try( InputStream content = entity.fetchMediaStream() ) {
- * // do something with the content here
- * }
- *
- *
- * @return File content as an {@link InputStream}.
- * @throws ODataException
- * if the request could not be sent or the OData service responded with an error.
- */
- @Nonnull
- public InputStream fetchMediaStream()
- throws ODataException
- {
- final ODataResourcePath resource =
- ODataResourcePath
- .of(getEntityCollection(), ODataEntityKey.of(getKey(), ODataProtocol.V2))
- .addSegment("$value");
-
- final ODataRequestReadByKey request =
- new ODataRequestReadByKey(getServicePathForFetch(), resource, null, ODataProtocol.V2);
-
- final Destination destination = getDestinationForFetch();
- if( destination == null ) {
- throw new ODataRequestException(
- request,
- "Failed to fetch media stream.",
- new IllegalStateException(
- "Unable to execute OData query. The entity was created locally without an assigned HttpDestination. This method is applicable only on entities which were retrieved or created using the OData VDM."));
- }
- final HttpClient httpClient = ODataApacheHttpClient5Accessor.getHttpClient(destination);
- final ODataRequestResultGeneric result = request.execute(httpClient);
- @SuppressWarnings( "PMD.CloseResource" ) // entity is intentionally not closed here because its content stream is returned to the caller
- final HttpEntity entity = result.getHttpResponse().getEntity();
- if( entity == null ) {
- throw new ODataResponseException(
- request,
- result.getHttpResponse(),
- "Failed to read the input stream of the OData response: Response didn't contain any payload.",
- null);
- }
- try {
- return entity.getContent();
- }
- catch( final IOException | UnsupportedOperationException e ) {
- throw new ODataResponseException(
- request,
- result.getHttpResponse(),
- "Failed to read the input stream of the OData response.",
- e);
- }
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmObject.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmObject.java
deleted file mode 100644
index 48549f0e40..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/VdmObject.java
+++ /dev/null
@@ -1,373 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper;
-
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import com.fasterxml.jackson.annotation.JsonAnyGetter;
-import com.fasterxml.jackson.annotation.JsonAnySetter;
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.sap.cloud.sdk.s4hana.datamodel.odata.exception.NoSuchEntityFieldException;
-import com.sap.cloud.sdk.typeconverter.TypeConverter;
-
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-/**
- * Superclass of all entities which contains common elements such as a generic representation of custom fields.
- *
- * @param
- * The type of the implementing object.
- */
-@ToString( doNotUseGetters = true )
-@EqualsAndHashCode( doNotUseGetters = true )
-@JsonAutoDetect(
- fieldVisibility = JsonAutoDetect.Visibility.ANY,
- getterVisibility = JsonAutoDetect.Visibility.NONE,
- isGetterVisibility = JsonAutoDetect.Visibility.NONE,
- setterVisibility = JsonAutoDetect.Visibility.NONE,
- creatorVisibility = JsonAutoDetect.Visibility.NONE )
-public abstract class VdmObject
-{
- @JsonIgnore
- private final transient Map customFields = new LinkedHashMap<>();
-
- /**
- * A mapping of the OData field name to the original value.
- *
- * This should be updated via {@link #rememberChangedField(String, Object)} on every set call of a property.
- */
- @JsonIgnore
- @Nonnull
- protected final transient Map changedOriginalFields = new HashMap<>();
-
- /**
- * Returns the names of all custom fields of this object.
- *
- * @return The names of the custom fields of this object.
- */
- @Nonnull
- public Set getCustomFieldNames()
- {
- return customFields.keySet();
- }
-
- /**
- * Returns all custom field names and values of this object.
- *
- * @return All names & values of custom fields as a map.
- */
- @JsonAnyGetter
- @Nonnull
- public Map getCustomFields()
- {
- return customFields;
- }
-
- /**
- * Sets the value of a single custom field.
- *
- * @param customFieldName
- * Name of the custom field.
- * @param value
- * Value of the custom field.
- */
- @JsonAnySetter
- public void setCustomField( @Nonnull final String customFieldName, @Nullable final Object value )
- {
- rememberChangedField(customFieldName, customFields.get(customFieldName));
- customFields.put(customFieldName, value);
- }
-
- /**
- * Sets the value of a single custom field. If the EntityField passed as parameter holds a TypeConverter, the value
- * will be converted before it's stored.
- *
- * @param customField
- * Name of the custom field, represented as an EntityField object.
- * @param value
- * Value of the custom field.
- * @param
- * The type of the custom field to set.
- */
- public void setCustomField(
- @Nonnull final EntityField customField,
- @Nullable final FieldT value )
- {
- if( customField.getTypeConverter() != null ) {
- setCustomField(customField.getFieldName(), customField.getTypeConverter().toDomain(value).get());
- } else {
- setCustomField(customField.getFieldName(), value);
- }
- }
-
- /**
- * Checks whether this object contains a custom field with the given name.
- *
- * @param customFieldName
- * Name of the custom field to check for
- *
- * @return {@code true} if this entity has a custom field with the given name, {@code false} otherwise.
- */
- public boolean hasCustomField( @Nonnull final String customFieldName )
- {
- return customFields.containsKey(customFieldName);
- }
-
- /**
- * Checks whether this object contains a value for the given custom field.
- *
- * @param customField
- * Custom field to check for, represented as an {@code EntityField} object.
- *
- * @return {@code true} if this object has a custom field with the name of the given field, {@code false} otherwise.
- */
- public boolean hasCustomField( @Nonnull final EntityField customField )
- {
- return hasCustomField(customField.getFieldName());
- }
-
- /**
- * This method allows for retrieval of custom fields that are added to the underlying OData services.
- *
- * @param customFieldName
- * Name of the field returned by the underlying OData service.
- * @param
- * The type of the returned field.
- *
- * @return The value of the custom field. Actual type will depend on the type configured in the underlying OData
- * service.
- *
- * @throws NoSuchEntityFieldException
- * if no field with the given name could be found.
- */
- @SuppressWarnings( "unchecked" )
- @Nullable
- public FieldT getCustomField( @Nonnull final String customFieldName )
- throws NoSuchEntityFieldException
- {
- if( !hasCustomField(customFieldName) ) {
- throw new NoSuchEntityFieldException("Object has no field with name '" + customFieldName + "'.");
- }
- return (FieldT) customFields.get(customFieldName);
- }
-
- @SuppressWarnings( "unchecked" )
- @Nullable
- private FieldT getCustomField(
- @Nonnull final String customFieldName,
- @Nonnull final TypeConverter typeConverter )
- throws NoSuchEntityFieldException
- {
- if( !hasCustomField(customFieldName) ) {
- throw new NoSuchEntityFieldException("Object has no field with name '" + customFieldName + "'.");
- }
- return typeConverter.fromDomain((T) customFields.get(customFieldName)).get();
- }
-
- /**
- * This method allows for retrieval of custom fields that are added to the underlying OData services. If the
- * EntityField passed as parameter holds a TypeConverter, the value will be converted before it's returned.
- *
- * @param customField
- * Field returned by the underlying OData service.
- * @param
- * The type of the returned field.
- *
- * @return The value of the custom field. Actual type will depend on the type configured in the underlying OData
- * service.
- *
- * @throws NoSuchEntityFieldException
- * if no field with the given name could be found.
- */
- @Nullable
- public FieldT getCustomField( @Nonnull final EntityField customField )
- throws NoSuchEntityFieldException
- {
- if( customField.getTypeConverter() != null ) {
- return getCustomField(customField.getFieldName(), customField.getTypeConverter());
- } else {
- return getCustomField(customField.getFieldName());
- }
- }
-
- /**
- * Returns the class of this object.
- *
- * @return The class of this object.
- */
- @Nonnull
- public abstract Class getType();
-
- /**
- * Returns the compound key of this object.
- *
- * @return The compound key of this object.
- */
- @Nonnull
- protected Map getKey()
- {
- return new HashMap<>();
- }
-
- /**
- * Sets the values of all custom fields contained in the given {@code values}.
- *
- * Afterwards, marks all fields as unchanged.
- *
- *
- * @param values
- * The map of custom fields to set.
- */
- protected void fromMap( final Map values )
- {
- for( final Map.Entry entry : values.entrySet() ) {
- setCustomField(entry.getKey(), entry.getValue());
- }
-
- resetChangedFields();
- }
-
- /**
- * Returns a map of all custom fields contained in this object.
- *
- * @return A map of all custom fields contained in this object.
- */
- @Nonnull
- protected Map toMapOfCustomFields()
- {
- return Maps.newHashMap(getCustomFields());
- }
-
- /**
- * Returns a set of all custom field names contained in this object.
- *
- * @return A set of all custom field names contained in this object.
- */
- @Nonnull
- protected Set getSetOfCustomFields()
- {
- return Sets.newHashSet(getCustomFields().keySet());
- }
-
- /**
- * Returns a map of all fields contained in this object.
- *
- * @return A map of all fields contained in this object.
- */
- @Nonnull
- protected Map toMapOfFields()
- {
- return new HashMap<>();
- }
-
- /**
- * Returns a set of all field names contained in this object.
- *
- * @return A set of all field names contained in this object.
- */
- @Nonnull
- protected Set getSetOfFields()
- {
- return Sets.newHashSet(toMapOfFields().keySet());
- }
-
- /**
- * Returns a map of all navigation properties contained in this object.
- *
- * @return A map of all navigation properties contained in this object.
- */
- @Nonnull
- protected Map toMapOfNavigationProperties()
- {
- return new HashMap<>();
- }
-
- /**
- * Returns a set of all navigation property names contained in this object.
- *
- * @return A set of all navigation property names contained in this object.
- */
- @Nonnull
- protected Set getSetOfNavigationProperties()
- {
- return Sets.newHashSet(toMapOfNavigationProperties().keySet());
- }
-
- /**
- * Returns a map of all fields, navigation properties, and custom fields contained in this object.
- *
- * @return A map of all fields, navigation properties, and custom fields contained in this object.
- */
- @Nonnull
- protected Map toMap()
- {
- final Map values = new HashMap<>();
-
- values.putAll(toMapOfFields());
- values.putAll(toMapOfNavigationProperties());
- values.putAll(toMapOfCustomFields());
-
- return values;
- }
-
- /**
- * Returns map of all fields which have been changed on this entity along with their updated values.
- *
- * @return Map containing all changed fields with their current value.
- */
- @Nonnull
- public Map getChangedFields()
- {
- final Map changedFields = new HashMap<>();
-
- final Map currentFields = toMapOfFields();
- currentFields.putAll(getCustomFields());
-
- for( final Map.Entry changedOriginalField : changedOriginalFields.entrySet() ) {
- final Object originalValue = changedOriginalField.getValue();
- final Object currentValue = currentFields.get(changedOriginalField.getKey());
-
- if( originalValue != null && !originalValue.equals(currentValue)
- || originalValue == null && currentValue != null ) {
-
- changedFields.put(changedOriginalField.getKey(), currentValue);
- }
- }
-
- return changedFields;
- }
-
- /**
- * Remembers the original value of a changed field.
- *
- * @param fieldName
- * The name of the field that is changed.
- * @param valueBeforeChange
- * The original value before the change.
- */
- protected void rememberChangedField( @Nonnull final String fieldName, @Nullable final Object valueBeforeChange )
- {
- if( !changedOriginalFields.containsKey(fieldName) ) {
- changedOriginalFields.put(fieldName, valueBeforeChange);
- }
- }
-
- /**
- * Resets the map of all fields which have been changed on this entity.
- *
- * After calling this method, no field is considered changed, until you change the value of fields on this entity
- * afterwards.
- */
- public void resetChangedFields()
- {
- changedOriginalFields.clear();
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/batch/BatchChangeSetFluentHelperBasic.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/batch/BatchChangeSetFluentHelperBasic.java
deleted file mode 100644
index d19638cc57..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/batch/BatchChangeSetFluentHelperBasic.java
+++ /dev/null
@@ -1,216 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper.batch;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestAction;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestBatch;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestCreate;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestDelete;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestGeneric;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestUpdate;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperCreate;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperDelete;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperFunction;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperUpdate;
-import com.sap.cloud.sdk.datamodel.odata.helper.VdmEntity;
-
-import lombok.RequiredArgsConstructor;
-
-/**
- * Representation of any changeset in a OData batch request as a fluent interface.
- *
- * @param
- * The fluent helper type of the associated OData batch request.
- * @param
- * The current type of the implementing fluent helper instance.
- */
-@RequiredArgsConstructor
-public abstract class BatchChangeSetFluentHelperBasic, ThisT>
- implements
- FluentHelperBatchEndChangeSet
-{
- private final FluentHelperBatchT typedBatchFluentHelper;
- private final BatchFluentHelperBasic, ?> basicBatchFluentHelper;
-
- private final List operations = new ArrayList<>();
-
- /**
- * Method to safely return the current fluent helper instance upon public method calls.
- *
- * @return The current fluent helper instance.
- */
- @Nonnull
- protected abstract ThisT getThis();
-
- /**
- * Add a delete operation to the current changeset request.
- *
- * @param serviceMethod
- * The method of a delete fluent helper from the given service class.
- * @param entity
- * The entity instance to be deleted.
- * @param
- * The entity type to guarantee type safety.
- * @return The current fluent helper instance.
- */
- @Nonnull
- protected > ThisT addRequestDelete(
- final Function> serviceMethod,
- final EntityT entity )
- {
- final FluentHelperDelete, EntityT> delete = serviceMethod.apply(entity);
- return addRequest(delete);
- }
-
- /**
- * Adds a delete operation to the current changeset request.
- *
- * @param deleteRequest
- * The {@link FluentHelperDelete} that represents the delete operation.
- * @return The current fluent helper instance.
- */
- @Nonnull
- protected ThisT addRequest( @Nonnull final FluentHelperDelete, ?> deleteRequest )
- {
- final ODataRequestDelete request = deleteRequest.toRequest();
- basicBatchFluentHelper.requestMapping.put(deleteRequest, request);
-
- final BatchRequestChangeSetOperation operation =
- new BatchRequestChangeSetOperation(( changeSet ) -> changeSet.addDelete(request), deleteRequest);
-
- operations.add(operation);
- return getThis();
- }
-
- /**
- * Add a create operation to the current changeset request.
- *
- * @param serviceMethod
- * The method of a create fluent helper from the given service class.
- * @param entity
- * The entity instance to be created.
- * @param
- * The entity type to guarantee type safety.
- * @return The current fluent helper instance.
- */
- @Nonnull
- protected > ThisT addRequestCreate(
- final Function> serviceMethod,
- final EntityT entity )
- {
- final FluentHelperCreate, EntityT> create = serviceMethod.apply(entity);
- return addRequest(create);
- }
-
- /**
- * Adds a create operation to the current changeset request.
- *
- * @param createRequest
- * The {@link FluentHelperCreate} that represents the create operation.
- * @return The current fluent helper instance.
- */
- @Nonnull
- protected ThisT addRequest( @Nonnull final FluentHelperCreate, ?> createRequest )
- {
- final ODataRequestCreate request = createRequest.toRequest();
- basicBatchFluentHelper.requestMapping.put(createRequest, request);
-
- final BatchRequestChangeSetOperation operation =
- new BatchRequestChangeSetOperation(( changeSet ) -> changeSet.addCreate(request), createRequest);
-
- operations.add(operation);
- return getThis();
- }
-
- /**
- * Add an update operation to the current changeset request.
- *
- * @param serviceMethod
- * The method of an update fluent helper from the given service class.
- * @param entity
- * The entity instance to be updated.
- * @param
- * The entity type to guarantee type safety.
- * @return The current fluent helper instance.
- */
- @Nonnull
- protected > ThisT addRequestUpdate(
- final Function> serviceMethod,
- final EntityT entity )
- {
- final FluentHelperUpdate, EntityT> update = serviceMethod.apply(entity);
- return addRequest(update);
- }
-
- /**
- * Adds an update operation to the current changeset request.
- *
- * @param updateRequest
- * The {@link FluentHelperUpdate} that represents the update operation.
- * @return The current fluent helper instance.
- */
- @Nonnull
- protected ThisT addRequest( @Nonnull final FluentHelperUpdate, ?> updateRequest )
- {
- final ODataRequestUpdate request = updateRequest.toRequest();
- basicBatchFluentHelper.requestMapping.put(updateRequest, request);
-
- final BatchRequestChangeSetOperation operation =
- new BatchRequestChangeSetOperation(( changeSet ) -> changeSet.addUpdate(request), updateRequest);
-
- operations.add(operation);
- return getThis();
- }
-
- @Nonnull
- @Override
- public FluentHelperBatchT endChangeSet()
- {
- final BatchRequestChangeSet changeSet = new BatchRequestChangeSet(operations);
- basicBatchFluentHelper.addChangeSet(changeSet);
- return typedBatchFluentHelper;
- }
-
- /**
- * Adds a function import call to the currently opened changeset. Only use {@code executeRequest} to issue the batch
- * request.
- *
- * @param functionImport
- * The {@link FluentHelperFunction} that represents the function import call
- * @return The same fluent helper
- * @throws IllegalStateException
- * If the batch request contains a function import call within a change set which uses the HTTP GET
- * method.
- */
- @Nonnull
- public ThisT addFunctionImport( @Nonnull final FluentHelperFunction, ?, ?> functionImport )
- {
- final ODataRequestGeneric request = functionImport.toRequest();
- basicBatchFluentHelper.requestMapping.put(functionImport, request);
-
- final Consumer changesetConsumer;
-
- if( request instanceof ODataRequestAction ) {
- changesetConsumer = changeset -> changeset.addAction((ODataRequestAction) request);
- } else {
- throw new IllegalStateException(
- "Request for function imports in batch change sets must be "
- + ODataRequestAction.class.getSimpleName()
- + ", but was "
- + request.getClass().getSimpleName()
- + ". Only function imports using HTTP POST are allowed.");
- }
-
- final BatchRequestChangeSetOperation operation =
- new BatchRequestChangeSetOperation(changesetConsumer, functionImport);
-
- operations.add(operation);
-
- return getThis();
- }
-}
diff --git a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/batch/BatchFluentHelperBasic.java b/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/batch/BatchFluentHelperBasic.java
deleted file mode 100644
index e3fc705f30..0000000000
--- a/datamodel/odata-core-apache-httpclient5/src/main/java/com/sap/cloud/sdk/datamodel/odata/helper/batch/BatchFluentHelperBasic.java
+++ /dev/null
@@ -1,219 +0,0 @@
-package com.sap.cloud.sdk.datamodel.odata.helper.batch;
-
-import java.util.ArrayList;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.function.Supplier;
-
-import javax.annotation.Nonnull;
-
-import org.apache.hc.client5.http.classic.HttpClient;
-
-import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
-import com.sap.cloud.sdk.datamodel.odata.client.ODataApacheHttpClient5Accessor;
-import com.sap.cloud.sdk.datamodel.odata.client.ODataProtocol;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestAction;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestBatch;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestFunction;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestGeneric;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestRead;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestReadByKey;
-import com.sap.cloud.sdk.datamodel.odata.client.request.ODataRequestResultMultipartGeneric;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperBasic;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperByKey;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperCreate;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperDelete;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperFunction;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperModification;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperRead;
-import com.sap.cloud.sdk.datamodel.odata.helper.FluentHelperUpdate;
-
-import lombok.AccessLevel;
-import lombok.Getter;
-
-/**
- * Representation of any OData batch request as a fluent interface for managing changesets and
- * {@link #executeRequest(Destination) executing} them in a single query.
- *
- * @param
- * The fluent helper type.
- * @param
- * The type of the changesets being managed in this OData batch request.
- */
-public abstract class BatchFluentHelperBasic, FluentHelperBatchChangeSetT extends FluentHelperBatchEndChangeSet>
- implements
- FluentHelperServiceBatch
-{
- @Getter( AccessLevel.PACKAGE )
- private final List requestParts = new ArrayList<>();
- final Map, Integer> requestMappingLegacy = new IdentityHashMap<>();
- @Getter( AccessLevel.PACKAGE )
- final Map