diff --git a/datamodel/openapi/openapi-api-apache-sample/pom.xml b/datamodel/openapi/openapi-api-apache-sample/pom.xml
new file mode 100644
index 000000000..75d7abe55
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/pom.xml
@@ -0,0 +1,216 @@
+
+
+ 4.0.0
+
+ com.sap.cloud.sdk.datamodel
+ openapi-parent
+ 5.26.0-SNAPSHOT
+
+ openapi-api-apache-sample
+ Data Model - OpenAPI Services - Sample API
+ Sample generated API classes of the OpenAPI VDM
+ https://sap.github.io/cloud-sdk/docs/java/getting-started
+
+ SAP SE
+ https://www.sap.com
+
+
+
+ The Apache Software License, Version 2.0
+ https://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+ SAP
+ cloudsdk@sap.com
+ SAP SE
+ https://www.sap.com
+
+
+
+
+ com.sap.cloud.sdk.datamodel
+ openapi-core
+
+
+ com.sap.cloud.sdk.cloudplatform
+ cloudplatform-connectivity
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.wiremock
+ wiremock
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ test
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ test
+
+
+
+
+
+ com.sap.cloud.sdk.datamodel
+ openapi-generator-maven-plugin
+
+ released
+ ${project.basedir}/src/main/java
+ true
+
+
+
+ sample-apache-swagger-v2
+ generate-sources
+
+ generate
+
+
+ ${project.basedir}/src/main/resources/petstore-swagger2.json
+ com.sap.cloud.sdk.datamodel.openapi.apache.petstore.api
+ com.sap.cloud.sdk.datamodel.openapi.apache.petstore.model
+
+ apache-httpclient
+
+
+
+
+ sample-apache-openapi-v3
+
+ generate
+
+ generate-sources
+
+ ${project.basedir}/src/main/resources/sodastore.yaml
+ com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.api
+ com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model
+ File=byte[]
+
+ apache-httpclient
+ create
+ protected
+ true
+ true
+ true
+ true
+
+ true
+ true
+
+
+
+
+
+ net.revelc.code.formatter
+ formatter-maven-plugin
+
+
+
+ format
+
+
+
+
+ false
+
+
+
+ net.revelc.code
+ impsort-maven-plugin
+
+
+
+ sort
+
+
+
+
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+ true
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+ true
+
+
+
+
+
+
+ release
+
+
+ release
+
+
+
+
+
+
+ org.sonatype.central
+ central-publishing-maven-plugin
+
+
+ injected-central-publishing
+
+
+
+
+
+
+
+
+
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/api/DefaultApi.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/api/DefaultApi.java
new file mode 100644
index 000000000..b08117f8d
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/api/DefaultApi.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.petstore.api;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
+import com.sap.cloud.sdk.datamodel.openapi.apache.petstore.model.Pet;
+import com.sap.cloud.sdk.datamodel.openapi.apache.petstore.model.PetInput;
+import com.sap.cloud.sdk.services.openapi.apache.ApiClient;
+import com.sap.cloud.sdk.services.openapi.apache.BaseApi;
+import com.sap.cloud.sdk.services.openapi.apache.OpenApiResponse;
+import com.sap.cloud.sdk.services.openapi.apache.Pair;
+import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException;
+
+/**
+ * Swagger Petstore in version 1.0.0.
+ *
+ * A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
+ */
+public class DefaultApi extends BaseApi
+{
+
+ /**
+ * Instantiates this API class to invoke operations on the Swagger Petstore
+ */
+ public DefaultApi()
+ {
+ }
+
+ /**
+ * Instantiates this API class to invoke operations on the Swagger Petstore.
+ *
+ * @param httpDestination
+ * The destination that API should be used with
+ */
+ public DefaultApi( @Nonnull final Destination httpDestination )
+ {
+ super(httpDestination);
+ }
+
+ /**
+ * Instantiates this API class to invoke operations on the Swagger Petstore based on a given {@link ApiClient}.
+ *
+ * @param apiClient
+ * ApiClient to invoke the API on
+ */
+ public DefaultApi( @Nonnull final ApiClient apiClient )
+ {
+ super(apiClient);
+ }
+
+ /**
+ *
+ *
+ * Creates a new pet in the store. Duplicates are allowed
+ *
+ * 200 - pet response
+ *
+ * 0 - unexpected error
+ *
+ * @param pet
+ * Pet to add to the store
+ * @return Pet
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nonnull
+ public Pet addPet( @Nonnull final PetInput pet )
+ throws OpenApiRequestException
+ {
+
+ // verify the required parameter 'pet' is set
+ if( pet == null ) {
+ throw new OpenApiRequestException("Missing the required parameter 'pet' when calling addPet")
+ .statusCode(400);
+ }
+
+ // create path and map variables
+ final String localVarPath = "/pets";
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/json" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+ final String[] localVarContentTypes = { "application/json" };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference localVarReturnType = new TypeReference()
+ {
+ };
+
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "POST",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ pet,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+
+ /**
+ *
+ *
+ * deletes a single pet based on the ID supplied
+ *
+ * 204 - pet deleted
+ *
+ * 0 - unexpected error
+ *
+ * @param id
+ * ID of pet to delete
+ * @return An OpenApiResponse containing the status code of the HttpResponse.
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nonnull
+ public OpenApiResponse deletePet( @Nonnull final Long id )
+ throws OpenApiRequestException
+ {
+
+ // verify the required parameter 'id' is set
+ if( id == null ) {
+ throw new OpenApiRequestException("Missing the required parameter 'id' when calling deletePet")
+ .statusCode(400);
+ }
+
+ // create path and map variables
+ final String localVarPath =
+ "/pets/{id}".replaceAll("\\{" + "id" + "\\}", ApiClient.escapeString(ApiClient.parameterToString(id)));
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/json" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+ final String[] localVarContentTypes = {
+
+ };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference localVarReturnType = new TypeReference()
+ {
+ };
+
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "DELETE",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ null,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+
+ /**
+ *
+ *
+ * Returns a user based on a single ID, if the user does not have access to the pet
+ *
+ * 200 - pet response
+ *
+ * 0 - unexpected error
+ *
+ * @param id
+ * ID of pet to fetch
+ * @return Pet
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nonnull
+ public Pet findPetById( @Nonnull final Long id )
+ throws OpenApiRequestException
+ {
+
+ // verify the required parameter 'id' is set
+ if( id == null ) {
+ throw new OpenApiRequestException("Missing the required parameter 'id' when calling findPetById")
+ .statusCode(400);
+ }
+
+ // create path and map variables
+ final String localVarPath =
+ "/pets/{id}".replaceAll("\\{" + "id" + "\\}", ApiClient.escapeString(ApiClient.parameterToString(id)));
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/json", "application/xml", "text/xml", "text/html" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+ final String[] localVarContentTypes = {
+
+ };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference localVarReturnType = new TypeReference()
+ {
+ };
+
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "GET",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ null,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+
+ /**
+ *
+ *
+ * Returns all pets from the system that the user has access to
+ *
+ * 200 - pet response
+ *
+ * 0 - unexpected error
+ *
+ * @param tags
+ * (optional) tags to filter by
+ * @param limit
+ * (optional) maximum number of results to return
+ * @return List<Pet>
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nonnull
+ public List findPets( @Nullable final List tags, @Nullable final Integer limit )
+ throws OpenApiRequestException
+ {
+
+ // create path and map variables
+ final String localVarPath = "/pets";
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ localVarCollectionQueryParams.addAll(ApiClient.parameterToPairs("csv", "tags", tags));
+ localVarQueryParams.addAll(ApiClient.parameterToPair("limit", limit));
+
+ final String[] localVarAccepts = { "application/json", "application/xml", "text/xml", "text/html" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+ final String[] localVarContentTypes = {
+
+ };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference> localVarReturnType = new TypeReference>()
+ {
+ };
+
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "GET",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ null,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+
+ /**
+ *
+ *
+ * Returns all pets from the system that the user has access to
+ *
+ * 200 - pet response
+ *
+ * 0 - unexpected error
+ *
+ * @return List<Pet>
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nonnull
+ public List findPets()
+ throws OpenApiRequestException
+ {
+ return findPets(null, null);
+ }
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/model/ErrorModel.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/model/ErrorModel.java
new file mode 100644
index 000000000..046e744f0
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/model/ErrorModel.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * Swagger Petstore
+ * A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.petstore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * ErrorModel
+ */
+// CHECKSTYLE:OFF
+public class ErrorModel
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "code" )
+ private Integer code;
+
+ @JsonProperty( "message" )
+ private String message;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Set the code of this {@link ErrorModel} instance and return the same instance.
+ *
+ * @param code
+ * The code of this {@link ErrorModel}
+ * @return The same instance of this {@link ErrorModel} class
+ */
+ @Nonnull
+ public ErrorModel code( @Nonnull final Integer code )
+ {
+ this.code = code;
+ return this;
+ }
+
+ /**
+ * Get code
+ *
+ * @return code The code of this {@link ErrorModel} instance.
+ */
+ @Nonnull
+ public Integer getCode()
+ {
+ return code;
+ }
+
+ /**
+ * Set the code of this {@link ErrorModel} instance.
+ *
+ * @param code
+ * The code of this {@link ErrorModel}
+ */
+ public void setCode( @Nonnull final Integer code )
+ {
+ this.code = code;
+ }
+
+ /**
+ * Set the message of this {@link ErrorModel} instance and return the same instance.
+ *
+ * @param message
+ * The message of this {@link ErrorModel}
+ * @return The same instance of this {@link ErrorModel} class
+ */
+ @Nonnull
+ public ErrorModel message( @Nonnull final String message )
+ {
+ this.message = message;
+ return this;
+ }
+
+ /**
+ * Get message
+ *
+ * @return message The message of this {@link ErrorModel} instance.
+ */
+ @Nonnull
+ public String getMessage()
+ {
+ return message;
+ }
+
+ /**
+ * Set the message of this {@link ErrorModel} instance.
+ *
+ * @param message
+ * The message of this {@link ErrorModel}
+ */
+ public void setMessage( @Nonnull final String message )
+ {
+ this.message = message;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link ErrorModel}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link ErrorModel} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("ErrorModel has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link ErrorModel} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( code != null )
+ declaredFields.put("code", code);
+ if( message != null )
+ declaredFields.put("message", message);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link ErrorModel} instance. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final ErrorModel errorModel = (ErrorModel) o;
+ return Objects.equals(this.cloudSdkCustomFields, errorModel.cloudSdkCustomFields)
+ && Objects.equals(this.code, errorModel.code)
+ && Objects.equals(this.message, errorModel.message);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(code, message, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class ErrorModel {\n");
+ sb.append(" code: ").append(toIndentedString(code)).append("\n");
+ sb.append(" message: ").append(toIndentedString(message)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/model/Pet.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/model/Pet.java
new file mode 100644
index 000000000..d86916dfb
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/model/Pet.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * Swagger Petstore
+ * A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.petstore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Pet
+ */
+// CHECKSTYLE:OFF
+public class Pet
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "id" )
+ private Long id;
+
+ @JsonProperty( "name" )
+ private String name;
+
+ @JsonProperty( "tag" )
+ private String tag;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Set the id of this {@link Pet} instance and return the same instance.
+ *
+ * @param id
+ * The id of this {@link Pet}
+ * @return The same instance of this {@link Pet} class
+ */
+ @Nonnull
+ public Pet id( @Nonnull final Long id )
+ {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * Get id
+ *
+ * @return id The id of this {@link Pet} instance.
+ */
+ @Nonnull
+ public Long getId()
+ {
+ return id;
+ }
+
+ /**
+ * Set the id of this {@link Pet} instance.
+ *
+ * @param id
+ * The id of this {@link Pet}
+ */
+ public void setId( @Nonnull final Long id )
+ {
+ this.id = id;
+ }
+
+ /**
+ * Set the name of this {@link Pet} instance and return the same instance.
+ *
+ * @param name
+ * The name of this {@link Pet}
+ * @return The same instance of this {@link Pet} class
+ */
+ @Nonnull
+ public Pet name( @Nonnull final String name )
+ {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Get name
+ *
+ * @return name The name of this {@link Pet} instance.
+ */
+ @Nonnull
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Set the name of this {@link Pet} instance.
+ *
+ * @param name
+ * The name of this {@link Pet}
+ */
+ public void setName( @Nonnull final String name )
+ {
+ this.name = name;
+ }
+
+ /**
+ * Set the tag of this {@link Pet} instance and return the same instance.
+ *
+ * @param tag
+ * The tag of this {@link Pet}
+ * @return The same instance of this {@link Pet} class
+ */
+ @Nonnull
+ public Pet tag( @Nullable final String tag )
+ {
+ this.tag = tag;
+ return this;
+ }
+
+ /**
+ * Get tag
+ *
+ * @return tag The tag of this {@link Pet} instance.
+ */
+ @Nonnull
+ public String getTag()
+ {
+ return tag;
+ }
+
+ /**
+ * Set the tag of this {@link Pet} instance.
+ *
+ * @param tag
+ * The tag of this {@link Pet}
+ */
+ public void setTag( @Nullable final String tag )
+ {
+ this.tag = tag;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link Pet}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link Pet} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("Pet has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link Pet} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( id != null )
+ declaredFields.put("id", id);
+ if( name != null )
+ declaredFields.put("name", name);
+ if( tag != null )
+ declaredFields.put("tag", tag);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link Pet} instance. If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final Pet pet = (Pet) o;
+ return Objects.equals(this.cloudSdkCustomFields, pet.cloudSdkCustomFields)
+ && Objects.equals(this.id, pet.id)
+ && Objects.equals(this.name, pet.name)
+ && Objects.equals(this.tag, pet.tag);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(id, name, tag, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class Pet {\n");
+ sb.append(" id: ").append(toIndentedString(id)).append("\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" tag: ").append(toIndentedString(tag)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/model/PetInput.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/model/PetInput.java
new file mode 100644
index 000000000..3d458b782
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/petstore/model/PetInput.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * Swagger Petstore
+ * A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.petstore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * PetInput
+ */
+// CHECKSTYLE:OFF
+public class PetInput
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "id" )
+ private Long id;
+
+ @JsonProperty( "name" )
+ private String name;
+
+ @JsonProperty( "tag" )
+ private String tag;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Set the id of this {@link PetInput} instance and return the same instance.
+ *
+ * @param id
+ * The id of this {@link PetInput}
+ * @return The same instance of this {@link PetInput} class
+ */
+ @Nonnull
+ public PetInput id( @Nonnull final Long id )
+ {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * Get id
+ *
+ * @return id The id of this {@link PetInput} instance.
+ */
+ @Nonnull
+ public Long getId()
+ {
+ return id;
+ }
+
+ /**
+ * Set the id of this {@link PetInput} instance.
+ *
+ * @param id
+ * The id of this {@link PetInput}
+ */
+ public void setId( @Nonnull final Long id )
+ {
+ this.id = id;
+ }
+
+ /**
+ * Set the name of this {@link PetInput} instance and return the same instance.
+ *
+ * @param name
+ * The name of this {@link PetInput}
+ * @return The same instance of this {@link PetInput} class
+ */
+ @Nonnull
+ public PetInput name( @Nonnull final String name )
+ {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Get name
+ *
+ * @return name The name of this {@link PetInput} instance.
+ */
+ @Nonnull
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Set the name of this {@link PetInput} instance.
+ *
+ * @param name
+ * The name of this {@link PetInput}
+ */
+ public void setName( @Nonnull final String name )
+ {
+ this.name = name;
+ }
+
+ /**
+ * Set the tag of this {@link PetInput} instance and return the same instance.
+ *
+ * @param tag
+ * The tag of this {@link PetInput}
+ * @return The same instance of this {@link PetInput} class
+ */
+ @Nonnull
+ public PetInput tag( @Nullable final String tag )
+ {
+ this.tag = tag;
+ return this;
+ }
+
+ /**
+ * Get tag
+ *
+ * @return tag The tag of this {@link PetInput} instance.
+ */
+ @Nonnull
+ public String getTag()
+ {
+ return tag;
+ }
+
+ /**
+ * Set the tag of this {@link PetInput} instance.
+ *
+ * @param tag
+ * The tag of this {@link PetInput}
+ */
+ public void setTag( @Nullable final String tag )
+ {
+ this.tag = tag;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link PetInput}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link PetInput} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("PetInput has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link PetInput} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( id != null )
+ declaredFields.put("id", id);
+ if( name != null )
+ declaredFields.put("name", name);
+ if( tag != null )
+ declaredFields.put("tag", tag);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link PetInput} instance. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final PetInput petInput = (PetInput) o;
+ return Objects.equals(this.cloudSdkCustomFields, petInput.cloudSdkCustomFields)
+ && Objects.equals(this.id, petInput.id)
+ && Objects.equals(this.name, petInput.name)
+ && Objects.equals(this.tag, petInput.tag);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(id, name, tag, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class PetInput {\n");
+ sb.append(" id: ").append(toIndentedString(id)).append("\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" tag: ").append(toIndentedString(tag)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/api/OrdersApi.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/api/OrdersApi.java
new file mode 100644
index 000000000..c6d82a1d8
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/api/OrdersApi.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.api;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+
+import javax.annotation.Nonnull;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.Order;
+import com.sap.cloud.sdk.services.openapi.apache.ApiClient;
+import com.sap.cloud.sdk.services.openapi.apache.BaseApi;
+import com.sap.cloud.sdk.services.openapi.apache.Pair;
+import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException;
+
+/**
+ * SodaStore API in version 1.0.0.
+ *
+ * API for managing soda products and orders in SodaStore.
+ */
+public class OrdersApi extends BaseApi
+{
+
+ /**
+ * Instantiates this API class to invoke operations on the SodaStore API
+ */
+ public OrdersApi()
+ {
+ }
+
+ /**
+ * Instantiates this API class to invoke operations on the SodaStore API.
+ *
+ * @param httpDestination
+ * The destination that API should be used with
+ */
+ public OrdersApi( @Nonnull final Destination httpDestination )
+ {
+ super(httpDestination);
+ }
+
+ /**
+ * Instantiates this API class to invoke operations on the SodaStore API based on a given {@link ApiClient}.
+ *
+ * @param apiClient
+ * ApiClient to invoke the API on
+ */
+ public OrdersApi( @Nonnull final ApiClient apiClient )
+ {
+ super(apiClient);
+ }
+
+ /**
+ *
+ * Create a new order
+ *
+ *
+ * 201 - The created order
+ *
+ * @param order
+ * The order details
+ * @return Order
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nonnull
+ public Order ordersPost( @Nonnull final Order order )
+ throws OpenApiRequestException
+ {
+
+ // verify the required parameter 'order' is set
+ if( order == null ) {
+ throw new OpenApiRequestException("Missing the required parameter 'order' when calling ordersPost")
+ .statusCode(400);
+ }
+
+ // create path and map variables
+ final String localVarPath = "/orders";
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/json" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+ final String[] localVarContentTypes = { "application/json" };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference localVarReturnType = new TypeReference()
+ {
+ };
+
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "POST",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ order,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/api/SodasApi.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/api/SodasApi.java
new file mode 100644
index 000000000..8e3f539f4
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/api/SodasApi.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.api;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.Soda;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.SodaWithId;
+import com.sap.cloud.sdk.services.openapi.apache.ApiClient;
+import com.sap.cloud.sdk.services.openapi.apache.BaseApi;
+import com.sap.cloud.sdk.services.openapi.apache.Pair;
+import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException;
+
+/**
+ * SodaStore API in version 1.0.0.
+ *
+ * API for managing soda products and orders in SodaStore.
+ */
+public class SodasApi extends BaseApi
+{
+
+ /**
+ * Instantiates this API class to invoke operations on the SodaStore API
+ */
+ public SodasApi()
+ {
+ }
+
+ /**
+ * Instantiates this API class to invoke operations on the SodaStore API.
+ *
+ * @param httpDestination
+ * The destination that API should be used with
+ */
+ public SodasApi( @Nonnull final Destination httpDestination )
+ {
+ super(httpDestination);
+ }
+
+ /**
+ * Instantiates this API class to invoke operations on the SodaStore API based on a given {@link ApiClient}.
+ *
+ * @param apiClient
+ * ApiClient to invoke the API on
+ */
+ public SodasApi( @Nonnull final ApiClient apiClient )
+ {
+ super(apiClient);
+ }
+
+ /**
+ *
+ * Download soda product data as binary
+ *
+ *
+ * 200 - Successful response
+ *
+ * 404 - Soda product not found
+ *
+ * @param id
+ * ID of the soda product to download
+ * @return byte[]
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nonnull
+ public byte[] sodasDownloadIdGet( @Nonnull final Long id )
+ throws OpenApiRequestException
+ {
+
+ // verify the required parameter 'id' is set
+ if( id == null ) {
+ throw new OpenApiRequestException("Missing the required parameter 'id' when calling sodasDownloadIdGet")
+ .statusCode(400);
+ }
+
+ // create path and map variables
+ final String localVarPath =
+ "/sodas/download/{id}"
+ .replaceAll("\\{" + "id" + "\\}", ApiClient.escapeString(ApiClient.parameterToString(id)));
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/octet-stream" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+ final String[] localVarContentTypes = {
+
+ };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference localVarReturnType = new TypeReference()
+ {
+ };
+
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "GET",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ null,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+
+ /**
+ *
+ * Get all soda products
+ *
+ *
+ * 200 - A list of soda products
+ *
+ * @return List<SodaWithId>
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nonnull
+ public List sodasGet()
+ throws OpenApiRequestException
+ {
+
+ // create path and map variables
+ final String localVarPath = "/sodas";
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/json" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+ final String[] localVarContentTypes = {
+
+ };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference> localVarReturnType = new TypeReference>()
+ {
+ };
+
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "GET",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ null,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+
+ /**
+ *
+ * Get a specific soda product by ID
+ *
+ *
+ * 200 - The soda product
+ *
+ * 404 - Soda product not found
+ *
+ * @param id
+ * ID of the soda product to retrieve
+ * @return SodaWithId
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nonnull
+ public SodaWithId sodasIdGet( @Nonnull final Long id )
+ throws OpenApiRequestException
+ {
+
+ // verify the required parameter 'id' is set
+ if( id == null ) {
+ throw new OpenApiRequestException("Missing the required parameter 'id' when calling sodasIdGet")
+ .statusCode(400);
+ }
+
+ // create path and map variables
+ final String localVarPath =
+ "/sodas/{id}".replaceAll("\\{" + "id" + "\\}", ApiClient.escapeString(ApiClient.parameterToString(id)));
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/json" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+ final String[] localVarContentTypes = {
+
+ };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference localVarReturnType = new TypeReference()
+ {
+ };
+
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "GET",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ null,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+
+ /**
+ *
+ * Update a specific soda product by ID
+ *
+ *
+ * 200 - The updated soda product
+ *
+ * 204 - Nothing has changed
+ *
+ * 404 - Soda product not found
+ *
+ * @param sodaWithId
+ * The updated soda product
+ * @return Soda
+ * @throws OpenApiRequestException
+ * if an error occurs while attempting to invoke the API
+ */
+ @Nullable
+ public Soda sodasPut( @Nonnull final SodaWithId sodaWithId )
+ throws OpenApiRequestException
+ {
+
+ // verify the required parameter 'sodaWithId' is set
+ if( sodaWithId == null ) {
+ throw new OpenApiRequestException("Missing the required parameter 'sodaWithId' when calling sodasPut")
+ .statusCode(400);
+ }
+
+ // create path and map variables
+ final String localVarPath = "/sodas";
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/json" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+ final String[] localVarContentTypes = { "application/json" };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference localVarReturnType = new TypeReference()
+ {
+ };
+
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "PUT",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ sodaWithId,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/AllOf.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/AllOf.java
new file mode 100644
index 000000000..4314271a4
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/AllOf.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * AllOf
+ */
+// CHECKSTYLE:OFF
+public class AllOf
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "sodaType" )
+ private String sodaType;
+
+ @JsonProperty( "caffeine" )
+ private Boolean caffeine;
+
+ @JsonProperty( "logo" )
+ private ColaLogo logo;
+
+ @JsonProperty( "barCode" )
+ private ColaBarCode barCode;
+
+ @JsonProperty( "color" )
+ private String color;
+
+ @JsonProperty( "flavor" )
+ private FantaFlavor flavor;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for AllOf.
+ */
+ protected AllOf()
+ {
+ }
+
+ /**
+ * Set the sodaType of this {@link AllOf} instance and return the same instance.
+ *
+ * @param sodaType
+ * The sodaType of this {@link AllOf}
+ * @return The same instance of this {@link AllOf} class
+ */
+ @Nonnull
+ public AllOf sodaType( @Nullable final String sodaType )
+ {
+ this.sodaType = sodaType;
+ return this;
+ }
+
+ /**
+ * Get sodaType
+ *
+ * @return sodaType The sodaType of this {@link AllOf} instance.
+ */
+ @Nonnull
+ public String getSodaType()
+ {
+ return sodaType;
+ }
+
+ /**
+ * Set the sodaType of this {@link AllOf} instance.
+ *
+ * @param sodaType
+ * The sodaType of this {@link AllOf}
+ */
+ public void setSodaType( @Nullable final String sodaType )
+ {
+ this.sodaType = sodaType;
+ }
+
+ /**
+ * Set the caffeine of this {@link AllOf} instance and return the same instance.
+ *
+ * @param caffeine
+ * The caffeine of this {@link AllOf}
+ * @return The same instance of this {@link AllOf} class
+ */
+ @Nonnull
+ public AllOf caffeine( @Nullable final Boolean caffeine )
+ {
+ this.caffeine = caffeine;
+ return this;
+ }
+
+ /**
+ * Get caffeine
+ *
+ * @return caffeine The caffeine of this {@link AllOf} instance.
+ */
+ @Nonnull
+ public Boolean isCaffeine()
+ {
+ return caffeine;
+ }
+
+ /**
+ * Set the caffeine of this {@link AllOf} instance.
+ *
+ * @param caffeine
+ * The caffeine of this {@link AllOf}
+ */
+ public void setCaffeine( @Nullable final Boolean caffeine )
+ {
+ this.caffeine = caffeine;
+ }
+
+ /**
+ * Set the logo of this {@link AllOf} instance and return the same instance.
+ *
+ * @param logo
+ * The logo of this {@link AllOf}
+ * @return The same instance of this {@link AllOf} class
+ */
+ @Nonnull
+ public AllOf logo( @Nullable final ColaLogo logo )
+ {
+ this.logo = logo;
+ return this;
+ }
+
+ /**
+ * Get logo
+ *
+ * @return logo The logo of this {@link AllOf} instance.
+ */
+ @Nonnull
+ public ColaLogo getLogo()
+ {
+ return logo;
+ }
+
+ /**
+ * Set the logo of this {@link AllOf} instance.
+ *
+ * @param logo
+ * The logo of this {@link AllOf}
+ */
+ public void setLogo( @Nullable final ColaLogo logo )
+ {
+ this.logo = logo;
+ }
+
+ /**
+ * Set the barCode of this {@link AllOf} instance and return the same instance.
+ *
+ * @param barCode
+ * The barCode of this {@link AllOf}
+ * @return The same instance of this {@link AllOf} class
+ */
+ @Nonnull
+ public AllOf barCode( @Nullable final ColaBarCode barCode )
+ {
+ this.barCode = barCode;
+ return this;
+ }
+
+ /**
+ * Get barCode
+ *
+ * @return barCode The barCode of this {@link AllOf} instance.
+ */
+ @Nonnull
+ public ColaBarCode getBarCode()
+ {
+ return barCode;
+ }
+
+ /**
+ * Set the barCode of this {@link AllOf} instance.
+ *
+ * @param barCode
+ * The barCode of this {@link AllOf}
+ */
+ public void setBarCode( @Nullable final ColaBarCode barCode )
+ {
+ this.barCode = barCode;
+ }
+
+ /**
+ * Set the color of this {@link AllOf} instance and return the same instance.
+ *
+ * @param color
+ * The color of this {@link AllOf}
+ * @return The same instance of this {@link AllOf} class
+ */
+ @Nonnull
+ public AllOf color( @Nullable final String color )
+ {
+ this.color = color;
+ return this;
+ }
+
+ /**
+ * Get color
+ *
+ * @return color The color of this {@link AllOf} instance.
+ */
+ @Nonnull
+ public String getColor()
+ {
+ return color;
+ }
+
+ /**
+ * Set the color of this {@link AllOf} instance.
+ *
+ * @param color
+ * The color of this {@link AllOf}
+ */
+ public void setColor( @Nullable final String color )
+ {
+ this.color = color;
+ }
+
+ /**
+ * Set the flavor of this {@link AllOf} instance and return the same instance.
+ *
+ * @param flavor
+ * The flavor of this {@link AllOf}
+ * @return The same instance of this {@link AllOf} class
+ */
+ @Nonnull
+ public AllOf flavor( @Nullable final FantaFlavor flavor )
+ {
+ this.flavor = flavor;
+ return this;
+ }
+
+ /**
+ * Get flavor
+ *
+ * @return flavor The flavor of this {@link AllOf} instance.
+ */
+ @Nonnull
+ public FantaFlavor getFlavor()
+ {
+ return flavor;
+ }
+
+ /**
+ * Set the flavor of this {@link AllOf} instance.
+ *
+ * @param flavor
+ * The flavor of this {@link AllOf}
+ */
+ public void setFlavor( @Nullable final FantaFlavor flavor )
+ {
+ this.flavor = flavor;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link AllOf}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link AllOf} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("AllOf has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link AllOf} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( sodaType != null )
+ declaredFields.put("sodaType", sodaType);
+ if( caffeine != null )
+ declaredFields.put("caffeine", caffeine);
+ if( logo != null )
+ declaredFields.put("logo", logo);
+ if( barCode != null )
+ declaredFields.put("barCode", barCode);
+ if( color != null )
+ declaredFields.put("color", color);
+ if( flavor != null )
+ declaredFields.put("flavor", flavor);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link AllOf} instance. If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final AllOf allOf = (AllOf) o;
+ return Objects.equals(this.cloudSdkCustomFields, allOf.cloudSdkCustomFields)
+ && Objects.equals(this.sodaType, allOf.sodaType)
+ && Objects.equals(this.caffeine, allOf.caffeine)
+ && Objects.equals(this.logo, allOf.logo)
+ && Objects.equals(this.barCode, allOf.barCode)
+ && Objects.equals(this.color, allOf.color)
+ && Objects.equals(this.flavor, allOf.flavor);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(sodaType, caffeine, logo, barCode, color, flavor, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class AllOf {\n");
+ sb.append(" sodaType: ").append(toIndentedString(sodaType)).append("\n");
+ sb.append(" caffeine: ").append(toIndentedString(caffeine)).append("\n");
+ sb.append(" logo: ").append(toIndentedString(logo)).append("\n");
+ sb.append(" barCode: ").append(toIndentedString(barCode)).append("\n");
+ sb.append(" color: ").append(toIndentedString(color)).append("\n");
+ sb.append(" flavor: ").append(toIndentedString(flavor)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a new {@link AllOf} instance. No arguments are required.
+ */
+ public static AllOf create()
+ {
+ return new AllOf();
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/AnyOf.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/AnyOf.java
new file mode 100644
index 000000000..7a52c6b68
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/AnyOf.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * AnyOf
+ */
+// CHECKSTYLE:OFF
+public class AnyOf
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "sodaType" )
+ private String sodaType;
+
+ @JsonProperty( "caffeine" )
+ private Boolean caffeine;
+
+ @JsonProperty( "logo" )
+ private ColaLogo logo;
+
+ @JsonProperty( "barCode" )
+ private ColaBarCode barCode;
+
+ @JsonProperty( "color" )
+ private String color;
+
+ @JsonProperty( "flavor" )
+ private FantaFlavor flavor;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for AnyOf.
+ */
+ protected AnyOf()
+ {
+ }
+
+ /**
+ * Set the sodaType of this {@link AnyOf} instance and return the same instance.
+ *
+ * @param sodaType
+ * The sodaType of this {@link AnyOf}
+ * @return The same instance of this {@link AnyOf} class
+ */
+ @Nonnull
+ public AnyOf sodaType( @Nullable final String sodaType )
+ {
+ this.sodaType = sodaType;
+ return this;
+ }
+
+ /**
+ * Get sodaType
+ *
+ * @return sodaType The sodaType of this {@link AnyOf} instance.
+ */
+ @Nonnull
+ public String getSodaType()
+ {
+ return sodaType;
+ }
+
+ /**
+ * Set the sodaType of this {@link AnyOf} instance.
+ *
+ * @param sodaType
+ * The sodaType of this {@link AnyOf}
+ */
+ public void setSodaType( @Nullable final String sodaType )
+ {
+ this.sodaType = sodaType;
+ }
+
+ /**
+ * Set the caffeine of this {@link AnyOf} instance and return the same instance.
+ *
+ * @param caffeine
+ * The caffeine of this {@link AnyOf}
+ * @return The same instance of this {@link AnyOf} class
+ */
+ @Nonnull
+ public AnyOf caffeine( @Nullable final Boolean caffeine )
+ {
+ this.caffeine = caffeine;
+ return this;
+ }
+
+ /**
+ * Get caffeine
+ *
+ * @return caffeine The caffeine of this {@link AnyOf} instance.
+ */
+ @Nonnull
+ public Boolean isCaffeine()
+ {
+ return caffeine;
+ }
+
+ /**
+ * Set the caffeine of this {@link AnyOf} instance.
+ *
+ * @param caffeine
+ * The caffeine of this {@link AnyOf}
+ */
+ public void setCaffeine( @Nullable final Boolean caffeine )
+ {
+ this.caffeine = caffeine;
+ }
+
+ /**
+ * Set the logo of this {@link AnyOf} instance and return the same instance.
+ *
+ * @param logo
+ * The logo of this {@link AnyOf}
+ * @return The same instance of this {@link AnyOf} class
+ */
+ @Nonnull
+ public AnyOf logo( @Nullable final ColaLogo logo )
+ {
+ this.logo = logo;
+ return this;
+ }
+
+ /**
+ * Get logo
+ *
+ * @return logo The logo of this {@link AnyOf} instance.
+ */
+ @Nonnull
+ public ColaLogo getLogo()
+ {
+ return logo;
+ }
+
+ /**
+ * Set the logo of this {@link AnyOf} instance.
+ *
+ * @param logo
+ * The logo of this {@link AnyOf}
+ */
+ public void setLogo( @Nullable final ColaLogo logo )
+ {
+ this.logo = logo;
+ }
+
+ /**
+ * Set the barCode of this {@link AnyOf} instance and return the same instance.
+ *
+ * @param barCode
+ * The barCode of this {@link AnyOf}
+ * @return The same instance of this {@link AnyOf} class
+ */
+ @Nonnull
+ public AnyOf barCode( @Nullable final ColaBarCode barCode )
+ {
+ this.barCode = barCode;
+ return this;
+ }
+
+ /**
+ * Get barCode
+ *
+ * @return barCode The barCode of this {@link AnyOf} instance.
+ */
+ @Nonnull
+ public ColaBarCode getBarCode()
+ {
+ return barCode;
+ }
+
+ /**
+ * Set the barCode of this {@link AnyOf} instance.
+ *
+ * @param barCode
+ * The barCode of this {@link AnyOf}
+ */
+ public void setBarCode( @Nullable final ColaBarCode barCode )
+ {
+ this.barCode = barCode;
+ }
+
+ /**
+ * Set the color of this {@link AnyOf} instance and return the same instance.
+ *
+ * @param color
+ * The color of this {@link AnyOf}
+ * @return The same instance of this {@link AnyOf} class
+ */
+ @Nonnull
+ public AnyOf color( @Nullable final String color )
+ {
+ this.color = color;
+ return this;
+ }
+
+ /**
+ * Get color
+ *
+ * @return color The color of this {@link AnyOf} instance.
+ */
+ @Nonnull
+ public String getColor()
+ {
+ return color;
+ }
+
+ /**
+ * Set the color of this {@link AnyOf} instance.
+ *
+ * @param color
+ * The color of this {@link AnyOf}
+ */
+ public void setColor( @Nullable final String color )
+ {
+ this.color = color;
+ }
+
+ /**
+ * Set the flavor of this {@link AnyOf} instance and return the same instance.
+ *
+ * @param flavor
+ * The flavor of this {@link AnyOf}
+ * @return The same instance of this {@link AnyOf} class
+ */
+ @Nonnull
+ public AnyOf flavor( @Nullable final FantaFlavor flavor )
+ {
+ this.flavor = flavor;
+ return this;
+ }
+
+ /**
+ * Get flavor
+ *
+ * @return flavor The flavor of this {@link AnyOf} instance.
+ */
+ @Nonnull
+ public FantaFlavor getFlavor()
+ {
+ return flavor;
+ }
+
+ /**
+ * Set the flavor of this {@link AnyOf} instance.
+ *
+ * @param flavor
+ * The flavor of this {@link AnyOf}
+ */
+ public void setFlavor( @Nullable final FantaFlavor flavor )
+ {
+ this.flavor = flavor;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link AnyOf}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link AnyOf} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("AnyOf has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link AnyOf} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( sodaType != null )
+ declaredFields.put("sodaType", sodaType);
+ if( caffeine != null )
+ declaredFields.put("caffeine", caffeine);
+ if( logo != null )
+ declaredFields.put("logo", logo);
+ if( barCode != null )
+ declaredFields.put("barCode", barCode);
+ if( color != null )
+ declaredFields.put("color", color);
+ if( flavor != null )
+ declaredFields.put("flavor", flavor);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link AnyOf} instance. If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final AnyOf anyOf = (AnyOf) o;
+ return Objects.equals(this.cloudSdkCustomFields, anyOf.cloudSdkCustomFields)
+ && Objects.equals(this.sodaType, anyOf.sodaType)
+ && Objects.equals(this.caffeine, anyOf.caffeine)
+ && Objects.equals(this.logo, anyOf.logo)
+ && Objects.equals(this.barCode, anyOf.barCode)
+ && Objects.equals(this.color, anyOf.color)
+ && Objects.equals(this.flavor, anyOf.flavor);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(sodaType, caffeine, logo, barCode, color, flavor, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class AnyOf {\n");
+ sb.append(" sodaType: ").append(toIndentedString(sodaType)).append("\n");
+ sb.append(" caffeine: ").append(toIndentedString(caffeine)).append("\n");
+ sb.append(" logo: ").append(toIndentedString(logo)).append("\n");
+ sb.append(" barCode: ").append(toIndentedString(barCode)).append("\n");
+ sb.append(" color: ").append(toIndentedString(color)).append("\n");
+ sb.append(" flavor: ").append(toIndentedString(flavor)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a new {@link AnyOf} instance. No arguments are required.
+ */
+ public static AnyOf create()
+ {
+ return new AnyOf();
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Bar.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Bar.java
new file mode 100644
index 000000000..b08fd7d21
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Bar.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Bar
+ */
+// CHECKSTYLE:OFF
+public class Bar implements OneOfWithEnumDiscriminator
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "bar" )
+ private String bar;
+
+ /**
+ * Gets or Sets disc
+ */
+ public enum DiscEnum
+ {
+ /**
+ * The DISC_BAR option of this Bar
+ */
+ DISC_BAR("disc_bar"),
+
+ /**
+ * The UNKNOWN_DEFAULT_OPEN_API option of this Bar
+ */
+ UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api");
+
+ private String value;
+
+ DiscEnum( String value )
+ {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the enum
+ *
+ * @return The enum value
+ */
+ @JsonValue
+ @Nonnull
+ public String getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Get the String value of the enum value.
+ *
+ * @return The enum value as String
+ */
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ return String.valueOf(value);
+ }
+
+ /**
+ * Get the enum value from a String value
+ *
+ * @param value
+ * The String value
+ * @return The enum value of type Bar
+ */
+ @JsonCreator
+ @Nonnull
+ public static DiscEnum fromValue( @Nonnull final String value )
+ {
+ for( DiscEnum b : DiscEnum.values() ) {
+ if( b.value.equals(value) ) {
+ return b;
+ }
+ }
+ return UNKNOWN_DEFAULT_OPEN_API;
+ }
+ }
+
+ @JsonProperty( "disc" )
+ private DiscEnum disc;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for Bar.
+ */
+ protected Bar()
+ {
+ }
+
+ /**
+ * Set the bar of this {@link Bar} instance and return the same instance.
+ *
+ * @param bar
+ * The bar of this {@link Bar}
+ * @return The same instance of this {@link Bar} class
+ */
+ @Nonnull
+ public Bar bar( @Nullable final String bar )
+ {
+ this.bar = bar;
+ return this;
+ }
+
+ /**
+ * Get bar
+ *
+ * @return bar The bar of this {@link Bar} instance.
+ */
+ @Nonnull
+ public String getBar()
+ {
+ return bar;
+ }
+
+ /**
+ * Set the bar of this {@link Bar} instance.
+ *
+ * @param bar
+ * The bar of this {@link Bar}
+ */
+ public void setBar( @Nullable final String bar )
+ {
+ this.bar = bar;
+ }
+
+ /**
+ * Set the disc of this {@link Bar} instance and return the same instance.
+ *
+ * @param disc
+ * The disc of this {@link Bar}
+ * @return The same instance of this {@link Bar} class
+ */
+ @Nonnull
+ public Bar disc( @Nullable final DiscEnum disc )
+ {
+ this.disc = disc;
+ return this;
+ }
+
+ /**
+ * Get disc
+ *
+ * @return disc The disc of this {@link Bar} instance.
+ */
+ @Nonnull
+ public DiscEnum getDisc()
+ {
+ return disc;
+ }
+
+ /**
+ * Set the disc of this {@link Bar} instance.
+ *
+ * @param disc
+ * The disc of this {@link Bar}
+ */
+ public void setDisc( @Nullable final DiscEnum disc )
+ {
+ this.disc = disc;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link Bar}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link Bar} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("Bar has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link Bar} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( bar != null )
+ declaredFields.put("bar", bar);
+ if( disc != null )
+ declaredFields.put("disc", disc);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link Bar} instance. If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final Bar bar = (Bar) o;
+ return Objects.equals(this.cloudSdkCustomFields, bar.cloudSdkCustomFields)
+ && Objects.equals(this.bar, bar.bar)
+ && Objects.equals(this.disc, bar.disc);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(bar, disc, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class Bar {\n");
+ sb.append(" bar: ").append(toIndentedString(bar)).append("\n");
+ sb.append(" disc: ").append(toIndentedString(disc)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a new {@link Bar} instance. No arguments are required.
+ */
+ public static Bar create()
+ {
+ return new Bar();
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Cola.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Cola.java
new file mode 100644
index 000000000..e5065f83b
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Cola.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Cola
+ */
+// CHECKSTYLE:OFF
+public class Cola implements OneOf, OneOfWithDiscriminator, OneOfWithDiscriminatorAndMapping
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "sodaType" )
+ private String sodaType;
+
+ @JsonProperty( "caffeine" )
+ private Boolean caffeine;
+
+ @JsonProperty( "logo" )
+ private ColaLogo logo;
+
+ @JsonProperty( "barCode" )
+ private ColaBarCode barCode;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for Cola.
+ */
+ protected Cola()
+ {
+ }
+
+ /**
+ * Set the sodaType of this {@link Cola} instance and return the same instance.
+ *
+ * @param sodaType
+ * The sodaType of this {@link Cola}
+ * @return The same instance of this {@link Cola} class
+ */
+ @Nonnull
+ public Cola sodaType( @Nullable final String sodaType )
+ {
+ this.sodaType = sodaType;
+ return this;
+ }
+
+ /**
+ * Get sodaType
+ *
+ * @return sodaType The sodaType of this {@link Cola} instance.
+ */
+ @Nonnull
+ public String getSodaType()
+ {
+ return sodaType;
+ }
+
+ /**
+ * Set the sodaType of this {@link Cola} instance.
+ *
+ * @param sodaType
+ * The sodaType of this {@link Cola}
+ */
+ public void setSodaType( @Nullable final String sodaType )
+ {
+ this.sodaType = sodaType;
+ }
+
+ /**
+ * Set the caffeine of this {@link Cola} instance and return the same instance.
+ *
+ * @param caffeine
+ * The caffeine of this {@link Cola}
+ * @return The same instance of this {@link Cola} class
+ */
+ @Nonnull
+ public Cola caffeine( @Nullable final Boolean caffeine )
+ {
+ this.caffeine = caffeine;
+ return this;
+ }
+
+ /**
+ * Get caffeine
+ *
+ * @return caffeine The caffeine of this {@link Cola} instance.
+ */
+ @Nonnull
+ public Boolean isCaffeine()
+ {
+ return caffeine;
+ }
+
+ /**
+ * Set the caffeine of this {@link Cola} instance.
+ *
+ * @param caffeine
+ * The caffeine of this {@link Cola}
+ */
+ public void setCaffeine( @Nullable final Boolean caffeine )
+ {
+ this.caffeine = caffeine;
+ }
+
+ /**
+ * Set the logo of this {@link Cola} instance and return the same instance.
+ *
+ * @param logo
+ * The logo of this {@link Cola}
+ * @return The same instance of this {@link Cola} class
+ */
+ @Nonnull
+ public Cola logo( @Nullable final ColaLogo logo )
+ {
+ this.logo = logo;
+ return this;
+ }
+
+ /**
+ * Get logo
+ *
+ * @return logo The logo of this {@link Cola} instance.
+ */
+ @Nonnull
+ public ColaLogo getLogo()
+ {
+ return logo;
+ }
+
+ /**
+ * Set the logo of this {@link Cola} instance.
+ *
+ * @param logo
+ * The logo of this {@link Cola}
+ */
+ public void setLogo( @Nullable final ColaLogo logo )
+ {
+ this.logo = logo;
+ }
+
+ /**
+ * Set the barCode of this {@link Cola} instance and return the same instance.
+ *
+ * @param barCode
+ * The barCode of this {@link Cola}
+ * @return The same instance of this {@link Cola} class
+ */
+ @Nonnull
+ public Cola barCode( @Nullable final ColaBarCode barCode )
+ {
+ this.barCode = barCode;
+ return this;
+ }
+
+ /**
+ * Get barCode
+ *
+ * @return barCode The barCode of this {@link Cola} instance.
+ */
+ @Nonnull
+ public ColaBarCode getBarCode()
+ {
+ return barCode;
+ }
+
+ /**
+ * Set the barCode of this {@link Cola} instance.
+ *
+ * @param barCode
+ * The barCode of this {@link Cola}
+ */
+ public void setBarCode( @Nullable final ColaBarCode barCode )
+ {
+ this.barCode = barCode;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link Cola}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link Cola} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("Cola has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link Cola} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( sodaType != null )
+ declaredFields.put("sodaType", sodaType);
+ if( caffeine != null )
+ declaredFields.put("caffeine", caffeine);
+ if( logo != null )
+ declaredFields.put("logo", logo);
+ if( barCode != null )
+ declaredFields.put("barCode", barCode);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link Cola} instance. If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final Cola cola = (Cola) o;
+ return Objects.equals(this.cloudSdkCustomFields, cola.cloudSdkCustomFields)
+ && Objects.equals(this.sodaType, cola.sodaType)
+ && Objects.equals(this.caffeine, cola.caffeine)
+ && Objects.equals(this.logo, cola.logo)
+ && Objects.equals(this.barCode, cola.barCode);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(sodaType, caffeine, logo, barCode, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class Cola {\n");
+ sb.append(" sodaType: ").append(toIndentedString(sodaType)).append("\n");
+ sb.append(" caffeine: ").append(toIndentedString(caffeine)).append("\n");
+ sb.append(" logo: ").append(toIndentedString(logo)).append("\n");
+ sb.append(" barCode: ").append(toIndentedString(barCode)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a new {@link Cola} instance. No arguments are required.
+ */
+ public static Cola create()
+ {
+ return new Cola();
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/ColaBarCode.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/ColaBarCode.java
new file mode 100644
index 000000000..1643ab004
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/ColaBarCode.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import javax.annotation.Nonnull;
+
+/**
+ * ColaBarCode
+ */
+public interface ColaBarCode
+{
+ /**
+ * Helper class to create {@code float[] } that implements {@link ColaBarCode}.
+ */
+ record ArrayOfFloats(@com.fasterxml.jackson.annotation.JsonValue @Nonnull float[] values) implements ColaBarCode {}
+
+ /**
+ * Creator to enable deserialization of {@code float[] }.
+ *
+ * @param val
+ * the value to use
+ * @return a new instance of {@link ArrayOfFloats}.
+ */
+ @com.fasterxml.jackson.annotation.JsonCreator
+ @Nonnull
+ static ArrayOfFloats createArrayOfFloats( @Nonnull final float[] val )
+ {
+ return new ArrayOfFloats(val);
+ }
+
+ /**
+ * Helper class to create {@code String } that implements {@link ColaBarCode}.
+ */
+ record InnerString(@com.fasterxml.jackson.annotation.JsonValue @Nonnull String value) implements ColaBarCode {}
+
+ /**
+ * Creator to enable deserialization of {@code String }.
+ *
+ * @param val
+ * the value to use
+ * @return a new instance of {@link InnerString}.
+ */
+ @com.fasterxml.jackson.annotation.JsonCreator
+ @Nonnull
+ static InnerString create( @Nonnull final String val )
+ {
+ return new InnerString(val);
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/ColaLogo.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/ColaLogo.java
new file mode 100644
index 000000000..c757ceca1
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/ColaLogo.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+/**
+ * ColaLogo
+ */
+public interface ColaLogo
+{
+ /**
+ * Helper class to create {@code List> } that implements {@link ColaLogo}.
+ */
+ record ListOfListOfIntegers(@com.fasterxml.jackson.annotation.JsonValue @Nonnull List> values) implements ColaLogo {}
+
+ /**
+ * Creator to enable deserialization of {@code List> }.
+ *
+ * @param val
+ * the value to use
+ * @return a new instance of {@link ListOfListOfIntegers}.
+ */
+ @com.fasterxml.jackson.annotation.JsonCreator
+ @Nonnull
+ static ListOfListOfIntegers createListOfListOfIntegers( @Nonnull final List> val )
+ {
+ return new ListOfListOfIntegers(val);
+ }
+
+ /**
+ * Helper class to create {@code String } that implements {@link ColaLogo}.
+ */
+ record InnerString(@com.fasterxml.jackson.annotation.JsonValue @Nonnull String value) implements ColaLogo {}
+
+ /**
+ * Creator to enable deserialization of {@code String }.
+ *
+ * @param val
+ * the value to use
+ * @return a new instance of {@link InnerString}.
+ */
+ @com.fasterxml.jackson.annotation.JsonCreator
+ @Nonnull
+ static InnerString create( @Nonnull final String val )
+ {
+ return new InnerString(val);
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Fanta.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Fanta.java
new file mode 100644
index 000000000..10ec15000
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Fanta.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Fanta
+ */
+// CHECKSTYLE:OFF
+public class Fanta implements OneOf, OneOfWithDiscriminator, OneOfWithDiscriminatorAndMapping
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "sodaType" )
+ private String sodaType;
+
+ @JsonProperty( "color" )
+ private String color;
+
+ @JsonProperty( "flavor" )
+ private FantaFlavor flavor;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for Fanta.
+ */
+ protected Fanta()
+ {
+ }
+
+ /**
+ * Set the sodaType of this {@link Fanta} instance and return the same instance.
+ *
+ * @param sodaType
+ * The sodaType of this {@link Fanta}
+ * @return The same instance of this {@link Fanta} class
+ */
+ @Nonnull
+ public Fanta sodaType( @Nullable final String sodaType )
+ {
+ this.sodaType = sodaType;
+ return this;
+ }
+
+ /**
+ * Get sodaType
+ *
+ * @return sodaType The sodaType of this {@link Fanta} instance.
+ */
+ @Nonnull
+ public String getSodaType()
+ {
+ return sodaType;
+ }
+
+ /**
+ * Set the sodaType of this {@link Fanta} instance.
+ *
+ * @param sodaType
+ * The sodaType of this {@link Fanta}
+ */
+ public void setSodaType( @Nullable final String sodaType )
+ {
+ this.sodaType = sodaType;
+ }
+
+ /**
+ * Set the color of this {@link Fanta} instance and return the same instance.
+ *
+ * @param color
+ * The color of this {@link Fanta}
+ * @return The same instance of this {@link Fanta} class
+ */
+ @Nonnull
+ public Fanta color( @Nullable final String color )
+ {
+ this.color = color;
+ return this;
+ }
+
+ /**
+ * Get color
+ *
+ * @return color The color of this {@link Fanta} instance.
+ */
+ @Nonnull
+ public String getColor()
+ {
+ return color;
+ }
+
+ /**
+ * Set the color of this {@link Fanta} instance.
+ *
+ * @param color
+ * The color of this {@link Fanta}
+ */
+ public void setColor( @Nullable final String color )
+ {
+ this.color = color;
+ }
+
+ /**
+ * Set the flavor of this {@link Fanta} instance and return the same instance.
+ *
+ * @param flavor
+ * The flavor of this {@link Fanta}
+ * @return The same instance of this {@link Fanta} class
+ */
+ @Nonnull
+ public Fanta flavor( @Nullable final FantaFlavor flavor )
+ {
+ this.flavor = flavor;
+ return this;
+ }
+
+ /**
+ * Get flavor
+ *
+ * @return flavor The flavor of this {@link Fanta} instance.
+ */
+ @Nonnull
+ public FantaFlavor getFlavor()
+ {
+ return flavor;
+ }
+
+ /**
+ * Set the flavor of this {@link Fanta} instance.
+ *
+ * @param flavor
+ * The flavor of this {@link Fanta}
+ */
+ public void setFlavor( @Nullable final FantaFlavor flavor )
+ {
+ this.flavor = flavor;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link Fanta}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link Fanta} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("Fanta has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link Fanta} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( sodaType != null )
+ declaredFields.put("sodaType", sodaType);
+ if( color != null )
+ declaredFields.put("color", color);
+ if( flavor != null )
+ declaredFields.put("flavor", flavor);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link Fanta} instance. If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final Fanta fanta = (Fanta) o;
+ return Objects.equals(this.cloudSdkCustomFields, fanta.cloudSdkCustomFields)
+ && Objects.equals(this.sodaType, fanta.sodaType)
+ && Objects.equals(this.color, fanta.color)
+ && Objects.equals(this.flavor, fanta.flavor);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(sodaType, color, flavor, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class Fanta {\n");
+ sb.append(" sodaType: ").append(toIndentedString(sodaType)).append("\n");
+ sb.append(" color: ").append(toIndentedString(color)).append("\n");
+ sb.append(" flavor: ").append(toIndentedString(flavor)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a new {@link Fanta} instance. No arguments are required.
+ */
+ public static Fanta create()
+ {
+ return new Fanta();
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/FantaFlavor.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/FantaFlavor.java
new file mode 100644
index 000000000..41738c868
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/FantaFlavor.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * FantaFlavor
+ */
+public interface FantaFlavor
+{
+ /**
+ * Helper class to create {@code String } that implements {@link FantaFlavor}.
+ */
+ record InnerString(@com.fasterxml.jackson.annotation.JsonValue @Nonnull String value) implements FantaFlavor {}
+
+ /**
+ * Creator to enable deserialization of {@code String }.
+ *
+ * @param val
+ * the value to use
+ * @return a new instance of {@link InnerString}.
+ */
+ @com.fasterxml.jackson.annotation.JsonCreator
+ @Nonnull
+ static InnerString create( @Nonnull final String val )
+ {
+ return new InnerString(val);
+ }
+
+ /**
+ * Helper class to create {@code Integer } that implements {@link FantaFlavor}.
+ */
+ record InnerInteger(@com.fasterxml.jackson.annotation.JsonValue @Nonnull Integer value) implements FantaFlavor {}
+
+ /**
+ * Creator to enable deserialization of {@code Integer }.
+ *
+ * @param val
+ * the value to use
+ * @return a new instance of {@link InnerInteger}.
+ */
+ @com.fasterxml.jackson.annotation.JsonCreator
+ @Nonnull
+ static InnerInteger create( @Nonnull final Integer val )
+ {
+ return new InnerInteger(val);
+ }
+
+ /**
+ * Helper class to create {@code FlavorType } that implements {@link FantaFlavor}.
+ */
+ record InnerFlavorType(@com.fasterxml.jackson.annotation.JsonValue @Nonnull FlavorType value) implements FantaFlavor {}
+
+ /**
+ * Creator to enable deserialization of {@code FlavorType }.
+ *
+ * @param val
+ * the value to use
+ * @return a new instance of {@link InnerFlavorType}.
+ */
+ @com.fasterxml.jackson.annotation.JsonCreator
+ @Nonnull
+ static InnerFlavorType createInnerFlavorType( @Nonnull final FlavorType val )
+ {
+ return new InnerFlavorType(val);
+ }
+
+ /**
+ * Helper class to create {@code List } that implements {@link FantaFlavor}.
+ */
+ record ListOfFlavorTypes(@com.fasterxml.jackson.annotation.JsonValue @Nonnull List values) implements FantaFlavor {}
+
+ /**
+ * Creator to enable deserialization of {@code List }.
+ *
+ * @param val
+ * the value to use
+ * @return a new instance of {@link ListOfFlavorTypes}.
+ */
+ @com.fasterxml.jackson.annotation.JsonCreator
+ @Nonnull
+ static ListOfFlavorTypes createListOfFlavorTypes( @Nonnull final List val )
+ {
+ return new ListOfFlavorTypes(val);
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/FlavorType.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/FlavorType.java
new file mode 100644
index 000000000..22c389044
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/FlavorType.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * FlavorType
+ */
+// CHECKSTYLE:OFF
+public class FlavorType
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "intensity" )
+ private Integer intensity;
+
+ @JsonProperty( "nuance" )
+ private String nuance;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for FlavorType.
+ */
+ protected FlavorType()
+ {
+ }
+
+ /**
+ * Set the intensity of this {@link FlavorType} instance and return the same instance.
+ *
+ * @param intensity
+ * The intensity of the flavor
+ * @return The same instance of this {@link FlavorType} class
+ */
+ @Nonnull
+ public FlavorType intensity( @Nullable final Integer intensity )
+ {
+ this.intensity = intensity;
+ return this;
+ }
+
+ /**
+ * The intensity of the flavor
+ *
+ * @return intensity The intensity of this {@link FlavorType} instance.
+ */
+ @Nonnull
+ public Integer getIntensity()
+ {
+ return intensity;
+ }
+
+ /**
+ * Set the intensity of this {@link FlavorType} instance.
+ *
+ * @param intensity
+ * The intensity of the flavor
+ */
+ public void setIntensity( @Nullable final Integer intensity )
+ {
+ this.intensity = intensity;
+ }
+
+ /**
+ * Set the nuance of this {@link FlavorType} instance and return the same instance.
+ *
+ * @param nuance
+ * The nuance of the flavor
+ * @return The same instance of this {@link FlavorType} class
+ */
+ @Nonnull
+ public FlavorType nuance( @Nullable final String nuance )
+ {
+ this.nuance = nuance;
+ return this;
+ }
+
+ /**
+ * The nuance of the flavor
+ *
+ * @return nuance The nuance of this {@link FlavorType} instance.
+ */
+ @Nonnull
+ public String getNuance()
+ {
+ return nuance;
+ }
+
+ /**
+ * Set the nuance of this {@link FlavorType} instance.
+ *
+ * @param nuance
+ * The nuance of the flavor
+ */
+ public void setNuance( @Nullable final String nuance )
+ {
+ this.nuance = nuance;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link FlavorType}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link FlavorType} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("FlavorType has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link FlavorType} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( intensity != null )
+ declaredFields.put("intensity", intensity);
+ if( nuance != null )
+ declaredFields.put("nuance", nuance);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link FlavorType} instance. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final FlavorType flavorType = (FlavorType) o;
+ return Objects.equals(this.cloudSdkCustomFields, flavorType.cloudSdkCustomFields)
+ && Objects.equals(this.intensity, flavorType.intensity)
+ && Objects.equals(this.nuance, flavorType.nuance);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(intensity, nuance, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class FlavorType {\n");
+ sb.append(" intensity: ").append(toIndentedString(intensity)).append("\n");
+ sb.append(" nuance: ").append(toIndentedString(nuance)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a new {@link FlavorType} instance. No arguments are required.
+ */
+ public static FlavorType create()
+ {
+ return new FlavorType();
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Foo.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Foo.java
new file mode 100644
index 000000000..1b07e9411
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Foo.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Foo
+ */
+// CHECKSTYLE:OFF
+public class Foo implements OneOfWithEnumDiscriminator
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "foo" )
+ private String foo;
+
+ /**
+ * Gets or Sets disc
+ */
+ public enum DiscEnum
+ {
+ /**
+ * The DISC_FOO option of this Foo
+ */
+ DISC_FOO("disc_foo"),
+
+ /**
+ * The UNKNOWN_DEFAULT_OPEN_API option of this Foo
+ */
+ UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api");
+
+ private String value;
+
+ DiscEnum( String value )
+ {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the enum
+ *
+ * @return The enum value
+ */
+ @JsonValue
+ @Nonnull
+ public String getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Get the String value of the enum value.
+ *
+ * @return The enum value as String
+ */
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ return String.valueOf(value);
+ }
+
+ /**
+ * Get the enum value from a String value
+ *
+ * @param value
+ * The String value
+ * @return The enum value of type Foo
+ */
+ @JsonCreator
+ @Nonnull
+ public static DiscEnum fromValue( @Nonnull final String value )
+ {
+ for( DiscEnum b : DiscEnum.values() ) {
+ if( b.value.equals(value) ) {
+ return b;
+ }
+ }
+ return UNKNOWN_DEFAULT_OPEN_API;
+ }
+ }
+
+ @JsonProperty( "disc" )
+ private DiscEnum disc;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for Foo.
+ */
+ protected Foo()
+ {
+ }
+
+ /**
+ * Set the foo of this {@link Foo} instance and return the same instance.
+ *
+ * @param foo
+ * The foo of this {@link Foo}
+ * @return The same instance of this {@link Foo} class
+ */
+ @Nonnull
+ public Foo foo( @Nullable final String foo )
+ {
+ this.foo = foo;
+ return this;
+ }
+
+ /**
+ * Get foo
+ *
+ * @return foo The foo of this {@link Foo} instance.
+ */
+ @Nonnull
+ public String getFoo()
+ {
+ return foo;
+ }
+
+ /**
+ * Set the foo of this {@link Foo} instance.
+ *
+ * @param foo
+ * The foo of this {@link Foo}
+ */
+ public void setFoo( @Nullable final String foo )
+ {
+ this.foo = foo;
+ }
+
+ /**
+ * Set the disc of this {@link Foo} instance and return the same instance.
+ *
+ * @param disc
+ * The disc of this {@link Foo}
+ * @return The same instance of this {@link Foo} class
+ */
+ @Nonnull
+ public Foo disc( @Nullable final DiscEnum disc )
+ {
+ this.disc = disc;
+ return this;
+ }
+
+ /**
+ * Get disc
+ *
+ * @return disc The disc of this {@link Foo} instance.
+ */
+ @Nonnull
+ public DiscEnum getDisc()
+ {
+ return disc;
+ }
+
+ /**
+ * Set the disc of this {@link Foo} instance.
+ *
+ * @param disc
+ * The disc of this {@link Foo}
+ */
+ public void setDisc( @Nullable final DiscEnum disc )
+ {
+ this.disc = disc;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link Foo}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link Foo} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("Foo has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link Foo} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( foo != null )
+ declaredFields.put("foo", foo);
+ if( disc != null )
+ declaredFields.put("disc", disc);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link Foo} instance. If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final Foo foo = (Foo) o;
+ return Objects.equals(this.cloudSdkCustomFields, foo.cloudSdkCustomFields)
+ && Objects.equals(this.foo, foo.foo)
+ && Objects.equals(this.disc, foo.disc);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(foo, disc, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class Foo {\n");
+ sb.append(" foo: ").append(toIndentedString(foo)).append("\n");
+ sb.append(" disc: ").append(toIndentedString(disc)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a new {@link Foo} instance. No arguments are required.
+ */
+ public static Foo create()
+ {
+ return new Foo();
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOf.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOf.java
new file mode 100644
index 000000000..08460550c
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOf.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+/**
+ * OneOf
+ */
+@JsonTypeInfo( use = JsonTypeInfo.Id.DEDUCTION )
+@JsonSubTypes( { @JsonSubTypes.Type( value = Cola.class ), @JsonSubTypes.Type( value = Fanta.class ), } )
+
+public interface OneOf
+{
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOfWithDiscriminator.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOfWithDiscriminator.java
new file mode 100644
index 000000000..c360e6957
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOfWithDiscriminator.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+/**
+ * OneOfWithDiscriminator
+ */
+@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, property = "sodaType", visible = true )
+@JsonSubTypes( {
+ @JsonSubTypes.Type( value = Cola.class, name = "Cola" ),
+ @JsonSubTypes.Type( value = Fanta.class, name = "Fanta" ), } )
+
+public interface OneOfWithDiscriminator
+{
+ Object getSodaType();
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOfWithDiscriminatorAndMapping.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOfWithDiscriminatorAndMapping.java
new file mode 100644
index 000000000..b5bd9540f
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOfWithDiscriminatorAndMapping.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+/**
+ * OneOfWithDiscriminatorAndMapping
+ */
+@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, property = "sodaType", visible = true )
+@JsonSubTypes( {
+ @JsonSubTypes.Type( value = Cola.class, name = "cool_cola" ),
+ @JsonSubTypes.Type( value = Fanta.class, name = "fancy_fanta" ), } )
+
+public interface OneOfWithDiscriminatorAndMapping
+{
+ Object getSodaType();
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOfWithEnumDiscriminator.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOfWithEnumDiscriminator.java
new file mode 100644
index 000000000..60c6bafc6
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OneOfWithEnumDiscriminator.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+/**
+ * OneOfWithEnumDiscriminator
+ */
+@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, property = "disc", visible = true )
+@JsonSubTypes( {
+ @JsonSubTypes.Type( value = Bar.class, name = "disc_bar" ),
+ @JsonSubTypes.Type( value = Foo.class, name = "disc_foo" ), } )
+
+public interface OneOfWithEnumDiscriminator
+{
+ Object getDisc();
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Order.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Order.java
new file mode 100644
index 000000000..722bfd26a
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Order.java
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Order
+ */
+// CHECKSTYLE:OFF
+public class Order
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "productId" )
+ private Long productId;
+
+ @JsonProperty( "quantity" )
+ private Integer quantity;
+
+ @JsonProperty( "totalPrice" )
+ private Float totalPrice;
+
+ @JsonProperty( "typelessProperty" )
+ private Object typelessProperty = null;
+
+ @JsonProperty( "nullableProperty" )
+ private String nullableProperty;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for Order.
+ */
+ protected Order()
+ {
+ }
+
+ /**
+ * Set the productId of this {@link Order} instance and return the same instance.
+ *
+ * @param productId
+ * The productId of this {@link Order}
+ * @return The same instance of this {@link Order} class
+ */
+ @Nonnull
+ public Order productId( @Nonnull final Long productId )
+ {
+ this.productId = productId;
+ return this;
+ }
+
+ /**
+ * Get productId
+ *
+ * @return productId The productId of this {@link Order} instance.
+ */
+ @Nonnull
+ public Long getProductId()
+ {
+ return productId;
+ }
+
+ /**
+ * Set the productId of this {@link Order} instance.
+ *
+ * @param productId
+ * The productId of this {@link Order}
+ */
+ public void setProductId( @Nonnull final Long productId )
+ {
+ this.productId = productId;
+ }
+
+ /**
+ * Set the quantity of this {@link Order} instance and return the same instance.
+ *
+ * @param quantity
+ * The quantity of this {@link Order}
+ * @return The same instance of this {@link Order} class
+ */
+ @Nonnull
+ public Order quantity( @Nonnull final Integer quantity )
+ {
+ this.quantity = quantity;
+ return this;
+ }
+
+ /**
+ * Get quantity
+ *
+ * @return quantity The quantity of this {@link Order} instance.
+ */
+ @Nonnull
+ public Integer getQuantity()
+ {
+ return quantity;
+ }
+
+ /**
+ * Set the quantity of this {@link Order} instance.
+ *
+ * @param quantity
+ * The quantity of this {@link Order}
+ */
+ public void setQuantity( @Nonnull final Integer quantity )
+ {
+ this.quantity = quantity;
+ }
+
+ /**
+ * Set the totalPrice of this {@link Order} instance and return the same instance.
+ *
+ * @param totalPrice
+ * The totalPrice of this {@link Order}
+ * @return The same instance of this {@link Order} class
+ */
+ @Nonnull
+ public Order totalPrice( @Nullable final Float totalPrice )
+ {
+ this.totalPrice = totalPrice;
+ return this;
+ }
+
+ /**
+ * Get totalPrice
+ *
+ * @return totalPrice The totalPrice of this {@link Order} instance.
+ */
+ @Nonnull
+ public Float getTotalPrice()
+ {
+ return totalPrice;
+ }
+
+ /**
+ * Set the totalPrice of this {@link Order} instance.
+ *
+ * @param totalPrice
+ * The totalPrice of this {@link Order}
+ */
+ public void setTotalPrice( @Nullable final Float totalPrice )
+ {
+ this.totalPrice = totalPrice;
+ }
+
+ /**
+ * Set the typelessProperty of this {@link Order} instance and return the same instance.
+ *
+ * @param typelessProperty
+ * Some typeless property, interpreted by the generator as nullable by default (because typeless)
+ * @return The same instance of this {@link Order} class
+ */
+ @Nonnull
+ public Order typelessProperty( @Nullable final Object typelessProperty )
+ {
+ this.typelessProperty = typelessProperty;
+ return this;
+ }
+
+ /**
+ * Some typeless property, interpreted by the generator as nullable by default (because typeless)
+ *
+ * @return typelessProperty The typelessProperty of this {@link Order} instance.
+ */
+ @Nullable
+ public Object getTypelessProperty()
+ {
+ return typelessProperty;
+ }
+
+ /**
+ * Set the typelessProperty of this {@link Order} instance.
+ *
+ * @param typelessProperty
+ * Some typeless property, interpreted by the generator as nullable by default (because typeless)
+ */
+ public void setTypelessProperty( @Nullable final Object typelessProperty )
+ {
+ this.typelessProperty = typelessProperty;
+ }
+
+ /**
+ * Set the nullableProperty of this {@link Order} instance and return the same instance.
+ *
+ * @param nullableProperty
+ * Some typed property that is deliberately made nullable
+ * @return The same instance of this {@link Order} class
+ */
+ @Nonnull
+ public Order nullableProperty( @Nullable final String nullableProperty )
+ {
+ this.nullableProperty = nullableProperty;
+ return this;
+ }
+
+ /**
+ * Some typed property that is deliberately made nullable
+ *
+ * @return nullableProperty The nullableProperty of this {@link Order} instance.
+ */
+ @Nullable
+ public String getNullableProperty()
+ {
+ return nullableProperty;
+ }
+
+ /**
+ * Set the nullableProperty of this {@link Order} instance.
+ *
+ * @param nullableProperty
+ * Some typed property that is deliberately made nullable
+ */
+ public void setNullableProperty( @Nullable final String nullableProperty )
+ {
+ this.nullableProperty = nullableProperty;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link Order}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link Order} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("Order has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link Order} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( productId != null )
+ declaredFields.put("productId", productId);
+ if( quantity != null )
+ declaredFields.put("quantity", quantity);
+ if( totalPrice != null )
+ declaredFields.put("totalPrice", totalPrice);
+ if( typelessProperty != null )
+ declaredFields.put("typelessProperty", typelessProperty);
+ if( nullableProperty != null )
+ declaredFields.put("nullableProperty", nullableProperty);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link Order} instance. If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final Order order = (Order) o;
+ return Objects.equals(this.cloudSdkCustomFields, order.cloudSdkCustomFields)
+ && Objects.equals(this.productId, order.productId)
+ && Objects.equals(this.quantity, order.quantity)
+ && Objects.equals(this.totalPrice, order.totalPrice)
+ && Objects.equals(this.typelessProperty, order.typelessProperty)
+ && Objects.equals(this.nullableProperty, order.nullableProperty);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(productId, quantity, totalPrice, typelessProperty, nullableProperty, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class Order {\n");
+ sb.append(" productId: ").append(toIndentedString(productId)).append("\n");
+ sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n");
+ sb.append(" totalPrice: ").append(toIndentedString(totalPrice)).append("\n");
+ sb.append(" typelessProperty: ").append(toIndentedString(typelessProperty)).append("\n");
+ sb.append(" nullableProperty: ").append(toIndentedString(nullableProperty)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a type-safe, fluent-api builder object to construct a new {@link Order} instance with all required
+ * arguments.
+ */
+ public static Builder create()
+ {
+ return ( productId ) -> ( quantity ) -> new Order().productId(productId).quantity(quantity);
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder
+ {
+ /**
+ * Set the productId of this {@link Order} instance.
+ *
+ * @param productId
+ * The productId of this {@link Order}
+ * @return The Order builder.
+ */
+ Builder1 productId( @Nonnull final Long productId );
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder1
+ {
+ /**
+ * Set the quantity of this {@link Order} instance.
+ *
+ * @param quantity
+ * The quantity of this {@link Order}
+ * @return The Order instance.
+ */
+ Order quantity( @Nonnull final Integer quantity );
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OrderWithTimestamp.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OrderWithTimestamp.java
new file mode 100644
index 000000000..7a37e6995
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/OrderWithTimestamp.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.time.OffsetDateTime;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * OrderWithTimestamp
+ */
+// CHECKSTYLE:OFF
+public class OrderWithTimestamp
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "productId" )
+ private Long productId;
+
+ @JsonProperty( "quantity" )
+ private Integer quantity;
+
+ @JsonProperty( "totalPrice" )
+ private Float totalPrice;
+
+ @JsonProperty( "typelessProperty" )
+ private Object typelessProperty;
+
+ @JsonProperty( "nullableProperty" )
+ private String nullableProperty;
+
+ @JsonProperty( "timestamp" )
+ private OffsetDateTime timestamp;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for OrderWithTimestamp.
+ */
+ protected OrderWithTimestamp()
+ {
+ }
+
+ /**
+ * Set the productId of this {@link OrderWithTimestamp} instance and return the same instance.
+ *
+ * @param productId
+ * The productId of this {@link OrderWithTimestamp}
+ * @return The same instance of this {@link OrderWithTimestamp} class
+ */
+ @Nonnull
+ public OrderWithTimestamp productId( @Nonnull final Long productId )
+ {
+ this.productId = productId;
+ return this;
+ }
+
+ /**
+ * Get productId
+ *
+ * @return productId The productId of this {@link OrderWithTimestamp} instance.
+ */
+ @Nonnull
+ public Long getProductId()
+ {
+ return productId;
+ }
+
+ /**
+ * Set the productId of this {@link OrderWithTimestamp} instance.
+ *
+ * @param productId
+ * The productId of this {@link OrderWithTimestamp}
+ */
+ public void setProductId( @Nonnull final Long productId )
+ {
+ this.productId = productId;
+ }
+
+ /**
+ * Set the quantity of this {@link OrderWithTimestamp} instance and return the same instance.
+ *
+ * @param quantity
+ * The quantity of this {@link OrderWithTimestamp}
+ * @return The same instance of this {@link OrderWithTimestamp} class
+ */
+ @Nonnull
+ public OrderWithTimestamp quantity( @Nonnull final Integer quantity )
+ {
+ this.quantity = quantity;
+ return this;
+ }
+
+ /**
+ * Get quantity
+ *
+ * @return quantity The quantity of this {@link OrderWithTimestamp} instance.
+ */
+ @Nonnull
+ public Integer getQuantity()
+ {
+ return quantity;
+ }
+
+ /**
+ * Set the quantity of this {@link OrderWithTimestamp} instance.
+ *
+ * @param quantity
+ * The quantity of this {@link OrderWithTimestamp}
+ */
+ public void setQuantity( @Nonnull final Integer quantity )
+ {
+ this.quantity = quantity;
+ }
+
+ /**
+ * Set the totalPrice of this {@link OrderWithTimestamp} instance and return the same instance.
+ *
+ * @param totalPrice
+ * The totalPrice of this {@link OrderWithTimestamp}
+ * @return The same instance of this {@link OrderWithTimestamp} class
+ */
+ @Nonnull
+ public OrderWithTimestamp totalPrice( @Nullable final Float totalPrice )
+ {
+ this.totalPrice = totalPrice;
+ return this;
+ }
+
+ /**
+ * Get totalPrice
+ *
+ * @return totalPrice The totalPrice of this {@link OrderWithTimestamp} instance.
+ */
+ @Nonnull
+ public Float getTotalPrice()
+ {
+ return totalPrice;
+ }
+
+ /**
+ * Set the totalPrice of this {@link OrderWithTimestamp} instance.
+ *
+ * @param totalPrice
+ * The totalPrice of this {@link OrderWithTimestamp}
+ */
+ public void setTotalPrice( @Nullable final Float totalPrice )
+ {
+ this.totalPrice = totalPrice;
+ }
+
+ /**
+ * Set the typelessProperty of this {@link OrderWithTimestamp} instance and return the same instance.
+ *
+ * @param typelessProperty
+ * Some typeless property, interpreted by the generator as nullable by default (because typeless)
+ * @return The same instance of this {@link OrderWithTimestamp} class
+ */
+ @Nonnull
+ public OrderWithTimestamp typelessProperty( @Nullable final Object typelessProperty )
+ {
+ this.typelessProperty = typelessProperty;
+ return this;
+ }
+
+ /**
+ * Some typeless property, interpreted by the generator as nullable by default (because typeless)
+ *
+ * @return typelessProperty The typelessProperty of this {@link OrderWithTimestamp} instance.
+ */
+ @Nullable
+ public Object getTypelessProperty()
+ {
+ return typelessProperty;
+ }
+
+ /**
+ * Set the typelessProperty of this {@link OrderWithTimestamp} instance.
+ *
+ * @param typelessProperty
+ * Some typeless property, interpreted by the generator as nullable by default (because typeless)
+ */
+ public void setTypelessProperty( @Nullable final Object typelessProperty )
+ {
+ this.typelessProperty = typelessProperty;
+ }
+
+ /**
+ * Set the nullableProperty of this {@link OrderWithTimestamp} instance and return the same instance.
+ *
+ * @param nullableProperty
+ * Some typed property that is deliberately made nullable
+ * @return The same instance of this {@link OrderWithTimestamp} class
+ */
+ @Nonnull
+ public OrderWithTimestamp nullableProperty( @Nullable final String nullableProperty )
+ {
+ this.nullableProperty = nullableProperty;
+ return this;
+ }
+
+ /**
+ * Some typed property that is deliberately made nullable
+ *
+ * @return nullableProperty The nullableProperty of this {@link OrderWithTimestamp} instance.
+ */
+ @Nullable
+ public String getNullableProperty()
+ {
+ return nullableProperty;
+ }
+
+ /**
+ * Set the nullableProperty of this {@link OrderWithTimestamp} instance.
+ *
+ * @param nullableProperty
+ * Some typed property that is deliberately made nullable
+ */
+ public void setNullableProperty( @Nullable final String nullableProperty )
+ {
+ this.nullableProperty = nullableProperty;
+ }
+
+ /**
+ * Set the timestamp of this {@link OrderWithTimestamp} instance and return the same instance.
+ *
+ * @param timestamp
+ * The timestamp of this {@link OrderWithTimestamp}
+ * @return The same instance of this {@link OrderWithTimestamp} class
+ */
+ @Nonnull
+ public OrderWithTimestamp timestamp( @Nullable final OffsetDateTime timestamp )
+ {
+ this.timestamp = timestamp;
+ return this;
+ }
+
+ /**
+ * Get timestamp
+ *
+ * @return timestamp The timestamp of this {@link OrderWithTimestamp} instance.
+ */
+ @Nonnull
+ public OffsetDateTime getTimestamp()
+ {
+ return timestamp;
+ }
+
+ /**
+ * Set the timestamp of this {@link OrderWithTimestamp} instance.
+ *
+ * @param timestamp
+ * The timestamp of this {@link OrderWithTimestamp}
+ */
+ public void setTimestamp( @Nullable final OffsetDateTime timestamp )
+ {
+ this.timestamp = timestamp;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link OrderWithTimestamp}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link OrderWithTimestamp} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("OrderWithTimestamp has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link OrderWithTimestamp} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( productId != null )
+ declaredFields.put("productId", productId);
+ if( quantity != null )
+ declaredFields.put("quantity", quantity);
+ if( totalPrice != null )
+ declaredFields.put("totalPrice", totalPrice);
+ if( typelessProperty != null )
+ declaredFields.put("typelessProperty", typelessProperty);
+ if( nullableProperty != null )
+ declaredFields.put("nullableProperty", nullableProperty);
+ if( timestamp != null )
+ declaredFields.put("timestamp", timestamp);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link OrderWithTimestamp} instance. If the map previously contained a
+ * mapping for the key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final OrderWithTimestamp orderWithTimestamp = (OrderWithTimestamp) o;
+ return Objects.equals(this.cloudSdkCustomFields, orderWithTimestamp.cloudSdkCustomFields)
+ && Objects.equals(this.productId, orderWithTimestamp.productId)
+ && Objects.equals(this.quantity, orderWithTimestamp.quantity)
+ && Objects.equals(this.totalPrice, orderWithTimestamp.totalPrice)
+ && Objects.equals(this.typelessProperty, orderWithTimestamp.typelessProperty)
+ && Objects.equals(this.nullableProperty, orderWithTimestamp.nullableProperty)
+ && Objects.equals(this.timestamp, orderWithTimestamp.timestamp);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects
+ .hash(productId, quantity, totalPrice, typelessProperty, nullableProperty, timestamp, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class OrderWithTimestamp {\n");
+ sb.append(" productId: ").append(toIndentedString(productId)).append("\n");
+ sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n");
+ sb.append(" totalPrice: ").append(toIndentedString(totalPrice)).append("\n");
+ sb.append(" typelessProperty: ").append(toIndentedString(typelessProperty)).append("\n");
+ sb.append(" nullableProperty: ").append(toIndentedString(nullableProperty)).append("\n");
+ sb.append(" timestamp: ").append(toIndentedString(timestamp)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a type-safe, fluent-api builder object to construct a new {@link OrderWithTimestamp} instance with all
+ * required arguments.
+ */
+ public static Builder create()
+ {
+ return ( productId ) -> ( quantity ) -> new OrderWithTimestamp().productId(productId).quantity(quantity);
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder
+ {
+ /**
+ * Set the productId of this {@link OrderWithTimestamp} instance.
+ *
+ * @param productId
+ * The productId of this {@link OrderWithTimestamp}
+ * @return The OrderWithTimestamp builder.
+ */
+ Builder1 productId( @Nonnull final Long productId );
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder1
+ {
+ /**
+ * Set the quantity of this {@link OrderWithTimestamp} instance.
+ *
+ * @param quantity
+ * The quantity of this {@link OrderWithTimestamp}
+ * @return The OrderWithTimestamp instance.
+ */
+ OrderWithTimestamp quantity( @Nonnull final Integer quantity );
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Soda.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Soda.java
new file mode 100644
index 000000000..d114bfac9
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/Soda.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Soda
+ */
+// CHECKSTYLE:OFF
+public class Soda
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "name" )
+ private String name;
+
+ @JsonProperty( "brand" )
+ private String brand;
+
+ @JsonProperty( "quantity" )
+ private Integer quantity;
+
+ /**
+ * Gets or Sets packaging
+ */
+ public enum PackagingEnum
+ {
+ /**
+ * The GLASS option of this Soda
+ */
+ GLASS("glass"),
+
+ /**
+ * The CARTON option of this Soda
+ */
+ CARTON("carton"),
+
+ /**
+ * The CAN option of this Soda
+ */
+ CAN("can"),
+
+ /**
+ * The UNKNOWN_DEFAULT_OPEN_API option of this Soda
+ */
+ UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api");
+
+ private String value;
+
+ PackagingEnum( String value )
+ {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the enum
+ *
+ * @return The enum value
+ */
+ @JsonValue
+ @Nonnull
+ public String getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Get the String value of the enum value.
+ *
+ * @return The enum value as String
+ */
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ return String.valueOf(value);
+ }
+
+ /**
+ * Get the enum value from a String value
+ *
+ * @param value
+ * The String value
+ * @return The enum value of type Soda
+ */
+ @JsonCreator
+ @Nonnull
+ public static PackagingEnum fromValue( @Nonnull final String value )
+ {
+ for( PackagingEnum b : PackagingEnum.values() ) {
+ if( b.value.equals(value) ) {
+ return b;
+ }
+ }
+ return UNKNOWN_DEFAULT_OPEN_API;
+ }
+ }
+
+ @JsonProperty( "packaging" )
+ private PackagingEnum packaging;
+
+ @JsonProperty( "price" )
+ private Float price;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for Soda.
+ */
+ protected Soda()
+ {
+ }
+
+ /**
+ * Set the name of this {@link Soda} instance and return the same instance.
+ *
+ * @param name
+ * The name of this {@link Soda}
+ * @return The same instance of this {@link Soda} class
+ */
+ @Nonnull
+ public Soda name( @Nonnull final String name )
+ {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Get name
+ *
+ * @return name The name of this {@link Soda} instance.
+ */
+ @Nonnull
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Set the name of this {@link Soda} instance.
+ *
+ * @param name
+ * The name of this {@link Soda}
+ */
+ public void setName( @Nonnull final String name )
+ {
+ this.name = name;
+ }
+
+ /**
+ * Set the brand of this {@link Soda} instance and return the same instance.
+ *
+ * @param brand
+ * The brand of this {@link Soda}
+ * @return The same instance of this {@link Soda} class
+ */
+ @Nonnull
+ public Soda brand( @Nonnull final String brand )
+ {
+ this.brand = brand;
+ return this;
+ }
+
+ /**
+ * Get brand
+ *
+ * @return brand The brand of this {@link Soda} instance.
+ */
+ @Nonnull
+ public String getBrand()
+ {
+ return brand;
+ }
+
+ /**
+ * Set the brand of this {@link Soda} instance.
+ *
+ * @param brand
+ * The brand of this {@link Soda}
+ */
+ public void setBrand( @Nonnull final String brand )
+ {
+ this.brand = brand;
+ }
+
+ /**
+ * Set the quantity of this {@link Soda} instance and return the same instance.
+ *
+ * @param quantity
+ * The quantity of this {@link Soda}
+ * @return The same instance of this {@link Soda} class
+ */
+ @Nonnull
+ public Soda quantity( @Nonnull final Integer quantity )
+ {
+ this.quantity = quantity;
+ return this;
+ }
+
+ /**
+ * Get quantity
+ *
+ * @return quantity The quantity of this {@link Soda} instance.
+ */
+ @Nonnull
+ public Integer getQuantity()
+ {
+ return quantity;
+ }
+
+ /**
+ * Set the quantity of this {@link Soda} instance.
+ *
+ * @param quantity
+ * The quantity of this {@link Soda}
+ */
+ public void setQuantity( @Nonnull final Integer quantity )
+ {
+ this.quantity = quantity;
+ }
+
+ /**
+ * Set the packaging of this {@link Soda} instance and return the same instance.
+ *
+ * @param packaging
+ * The packaging of this {@link Soda}
+ * @return The same instance of this {@link Soda} class
+ */
+ @Nonnull
+ public Soda packaging( @Nullable final PackagingEnum packaging )
+ {
+ this.packaging = packaging;
+ return this;
+ }
+
+ /**
+ * Get packaging
+ *
+ * @return packaging The packaging of this {@link Soda} instance.
+ */
+ @Nonnull
+ public PackagingEnum getPackaging()
+ {
+ return packaging;
+ }
+
+ /**
+ * Set the packaging of this {@link Soda} instance.
+ *
+ * @param packaging
+ * The packaging of this {@link Soda}
+ */
+ public void setPackaging( @Nullable final PackagingEnum packaging )
+ {
+ this.packaging = packaging;
+ }
+
+ /**
+ * Set the price of this {@link Soda} instance and return the same instance.
+ *
+ * @param price
+ * The price of this {@link Soda}
+ * @return The same instance of this {@link Soda} class
+ */
+ @Nonnull
+ public Soda price( @Nonnull final Float price )
+ {
+ this.price = price;
+ return this;
+ }
+
+ /**
+ * Get price
+ *
+ * @return price The price of this {@link Soda} instance.
+ */
+ @Nonnull
+ public Float getPrice()
+ {
+ return price;
+ }
+
+ /**
+ * Set the price of this {@link Soda} instance.
+ *
+ * @param price
+ * The price of this {@link Soda}
+ */
+ public void setPrice( @Nonnull final Float price )
+ {
+ this.price = price;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link Soda}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link Soda} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("Soda has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link Soda} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( name != null )
+ declaredFields.put("name", name);
+ if( brand != null )
+ declaredFields.put("brand", brand);
+ if( quantity != null )
+ declaredFields.put("quantity", quantity);
+ if( packaging != null )
+ declaredFields.put("packaging", packaging);
+ if( price != null )
+ declaredFields.put("price", price);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link Soda} instance. If the map previously contained a mapping for the
+ * key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final Soda soda = (Soda) o;
+ return Objects.equals(this.cloudSdkCustomFields, soda.cloudSdkCustomFields)
+ && Objects.equals(this.name, soda.name)
+ && Objects.equals(this.brand, soda.brand)
+ && Objects.equals(this.quantity, soda.quantity)
+ && Objects.equals(this.packaging, soda.packaging)
+ && Objects.equals(this.price, soda.price);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(name, brand, quantity, packaging, price, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class Soda {\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" brand: ").append(toIndentedString(brand)).append("\n");
+ sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n");
+ sb.append(" packaging: ").append(toIndentedString(packaging)).append("\n");
+ sb.append(" price: ").append(toIndentedString(price)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a type-safe, fluent-api builder object to construct a new {@link Soda} instance with all required
+ * arguments.
+ */
+ public static Builder create()
+ {
+ return ( name ) -> (
+ brand ) -> ( quantity ) -> ( price ) -> new Soda().name(name).brand(brand).quantity(quantity).price(price);
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder
+ {
+ /**
+ * Set the name of this {@link Soda} instance.
+ *
+ * @param name
+ * The name of this {@link Soda}
+ * @return The Soda builder.
+ */
+ Builder1 name( @Nonnull final String name );
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder1
+ {
+ /**
+ * Set the brand of this {@link Soda} instance.
+ *
+ * @param brand
+ * The brand of this {@link Soda}
+ * @return The Soda builder.
+ */
+ Builder2 brand( @Nonnull final String brand );
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder2
+ {
+ /**
+ * Set the quantity of this {@link Soda} instance.
+ *
+ * @param quantity
+ * The quantity of this {@link Soda}
+ * @return The Soda builder.
+ */
+ Builder3 quantity( @Nonnull final Integer quantity );
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder3
+ {
+ /**
+ * Set the price of this {@link Soda} instance.
+ *
+ * @param price
+ * The price of this {@link Soda}
+ * @return The Soda instance.
+ */
+ Soda price( @Nonnull final Float price );
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/SodaWithId.java b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/SodaWithId.java
new file mode 100644
index 000000000..3bac8d0f2
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/java/com/sap/cloud/sdk/datamodel/openapi/apache/sodastore/model/SodaWithId.java
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved.
+ */
+
+/*
+ * SodaStore API
+ * API for managing soda products and orders in SodaStore.
+ *
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+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.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * SodaWithId
+ */
+// CHECKSTYLE:OFF
+public class SodaWithId
+// CHECKSTYLE:ON
+{
+ @JsonProperty( "name" )
+ private String name;
+
+ @JsonProperty( "brand" )
+ private String brand;
+
+ @JsonProperty( "quantity" )
+ private Integer quantity;
+
+ /**
+ * Gets or Sets packaging
+ */
+ public enum PackagingEnum
+ {
+ /**
+ * The GLASS option of this SodaWithId
+ */
+ GLASS("glass"),
+
+ /**
+ * The CARTON option of this SodaWithId
+ */
+ CARTON("carton"),
+
+ /**
+ * The CAN option of this SodaWithId
+ */
+ CAN("can"),
+
+ /**
+ * The UNKNOWN_DEFAULT_OPEN_API option of this SodaWithId
+ */
+ UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api");
+
+ private String value;
+
+ PackagingEnum( String value )
+ {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the enum
+ *
+ * @return The enum value
+ */
+ @JsonValue
+ @Nonnull
+ public String getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Get the String value of the enum value.
+ *
+ * @return The enum value as String
+ */
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ return String.valueOf(value);
+ }
+
+ /**
+ * Get the enum value from a String value
+ *
+ * @param value
+ * The String value
+ * @return The enum value of type SodaWithId
+ */
+ @JsonCreator
+ @Nonnull
+ public static PackagingEnum fromValue( @Nonnull final String value )
+ {
+ for( PackagingEnum b : PackagingEnum.values() ) {
+ if( b.value.equals(value) ) {
+ return b;
+ }
+ }
+ return UNKNOWN_DEFAULT_OPEN_API;
+ }
+ }
+
+ @JsonProperty( "packaging" )
+ private PackagingEnum packaging;
+
+ @JsonProperty( "price" )
+ private Float price;
+
+ @JsonProperty( "id" )
+ private Long id;
+
+ @JsonAnySetter
+ @JsonAnyGetter
+ private final Map cloudSdkCustomFields = new LinkedHashMap<>();
+
+ /**
+ * Default constructor for SodaWithId.
+ */
+ protected SodaWithId()
+ {
+ }
+
+ /**
+ * Set the name of this {@link SodaWithId} instance and return the same instance.
+ *
+ * @param name
+ * The name of this {@link SodaWithId}
+ * @return The same instance of this {@link SodaWithId} class
+ */
+ @Nonnull
+ public SodaWithId name( @Nonnull final String name )
+ {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Get name
+ *
+ * @return name The name of this {@link SodaWithId} instance.
+ */
+ @Nonnull
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Set the name of this {@link SodaWithId} instance.
+ *
+ * @param name
+ * The name of this {@link SodaWithId}
+ */
+ public void setName( @Nonnull final String name )
+ {
+ this.name = name;
+ }
+
+ /**
+ * Set the brand of this {@link SodaWithId} instance and return the same instance.
+ *
+ * @param brand
+ * The brand of this {@link SodaWithId}
+ * @return The same instance of this {@link SodaWithId} class
+ */
+ @Nonnull
+ public SodaWithId brand( @Nonnull final String brand )
+ {
+ this.brand = brand;
+ return this;
+ }
+
+ /**
+ * Get brand
+ *
+ * @return brand The brand of this {@link SodaWithId} instance.
+ */
+ @Nonnull
+ public String getBrand()
+ {
+ return brand;
+ }
+
+ /**
+ * Set the brand of this {@link SodaWithId} instance.
+ *
+ * @param brand
+ * The brand of this {@link SodaWithId}
+ */
+ public void setBrand( @Nonnull final String brand )
+ {
+ this.brand = brand;
+ }
+
+ /**
+ * Set the quantity of this {@link SodaWithId} instance and return the same instance.
+ *
+ * @param quantity
+ * The quantity of this {@link SodaWithId}
+ * @return The same instance of this {@link SodaWithId} class
+ */
+ @Nonnull
+ public SodaWithId quantity( @Nonnull final Integer quantity )
+ {
+ this.quantity = quantity;
+ return this;
+ }
+
+ /**
+ * Get quantity
+ *
+ * @return quantity The quantity of this {@link SodaWithId} instance.
+ */
+ @Nonnull
+ public Integer getQuantity()
+ {
+ return quantity;
+ }
+
+ /**
+ * Set the quantity of this {@link SodaWithId} instance.
+ *
+ * @param quantity
+ * The quantity of this {@link SodaWithId}
+ */
+ public void setQuantity( @Nonnull final Integer quantity )
+ {
+ this.quantity = quantity;
+ }
+
+ /**
+ * Set the packaging of this {@link SodaWithId} instance and return the same instance.
+ *
+ * @param packaging
+ * The packaging of this {@link SodaWithId}
+ * @return The same instance of this {@link SodaWithId} class
+ */
+ @Nonnull
+ public SodaWithId packaging( @Nullable final PackagingEnum packaging )
+ {
+ this.packaging = packaging;
+ return this;
+ }
+
+ /**
+ * Get packaging
+ *
+ * @return packaging The packaging of this {@link SodaWithId} instance.
+ */
+ @Nonnull
+ public PackagingEnum getPackaging()
+ {
+ return packaging;
+ }
+
+ /**
+ * Set the packaging of this {@link SodaWithId} instance.
+ *
+ * @param packaging
+ * The packaging of this {@link SodaWithId}
+ */
+ public void setPackaging( @Nullable final PackagingEnum packaging )
+ {
+ this.packaging = packaging;
+ }
+
+ /**
+ * Set the price of this {@link SodaWithId} instance and return the same instance.
+ *
+ * @param price
+ * The price of this {@link SodaWithId}
+ * @return The same instance of this {@link SodaWithId} class
+ */
+ @Nonnull
+ public SodaWithId price( @Nonnull final Float price )
+ {
+ this.price = price;
+ return this;
+ }
+
+ /**
+ * Get price
+ *
+ * @return price The price of this {@link SodaWithId} instance.
+ */
+ @Nonnull
+ public Float getPrice()
+ {
+ return price;
+ }
+
+ /**
+ * Set the price of this {@link SodaWithId} instance.
+ *
+ * @param price
+ * The price of this {@link SodaWithId}
+ */
+ public void setPrice( @Nonnull final Float price )
+ {
+ this.price = price;
+ }
+
+ /**
+ * Set the id of this {@link SodaWithId} instance and return the same instance.
+ *
+ * @param id
+ * The id of this {@link SodaWithId}
+ * @return The same instance of this {@link SodaWithId} class
+ */
+ @Nonnull
+ public SodaWithId id( @Nullable final Long id )
+ {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * Get id
+ *
+ * @return id The id of this {@link SodaWithId} instance.
+ */
+ @Nonnull
+ public Long getId()
+ {
+ return id;
+ }
+
+ /**
+ * Set the id of this {@link SodaWithId} instance.
+ *
+ * @param id
+ * The id of this {@link SodaWithId}
+ */
+ public void setId( @Nullable final Long id )
+ {
+ this.id = id;
+ }
+
+ /**
+ * Get the names of the unrecognizable properties of the {@link SodaWithId}.
+ *
+ * @return The set of properties names
+ */
+ @JsonIgnore
+ @Nonnull
+ public Set getCustomFieldNames()
+ {
+ return cloudSdkCustomFields.keySet();
+ }
+
+ /**
+ * Get the value of an unrecognizable property of this {@link SodaWithId} instance.
+ *
+ * @deprecated Use {@link #toMap()} instead.
+ * @param name
+ * The name of the property
+ * @return The value of the property
+ * @throws NoSuchElementException
+ * If no property with the given name could be found.
+ */
+ @Nullable
+ @Deprecated
+ public Object getCustomField( @Nonnull final String name )
+ throws NoSuchElementException
+ {
+ if( !cloudSdkCustomFields.containsKey(name) ) {
+ throw new NoSuchElementException("SodaWithId has no field with name '" + name + "'.");
+ }
+ return cloudSdkCustomFields.get(name);
+ }
+
+ /**
+ * Get the value of all properties of this {@link SodaWithId} instance including unrecognized properties.
+ *
+ * @return The map of all properties
+ */
+ @JsonIgnore
+ @Nonnull
+ public Map toMap()
+ {
+ final Map declaredFields = new LinkedHashMap<>(cloudSdkCustomFields);
+ if( name != null )
+ declaredFields.put("name", name);
+ if( brand != null )
+ declaredFields.put("brand", brand);
+ if( quantity != null )
+ declaredFields.put("quantity", quantity);
+ if( packaging != null )
+ declaredFields.put("packaging", packaging);
+ if( price != null )
+ declaredFields.put("price", price);
+ if( id != null )
+ declaredFields.put("id", id);
+ return declaredFields;
+ }
+
+ /**
+ * Set an unrecognizable property of this {@link SodaWithId} instance. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param customFieldName
+ * The name of the property
+ * @param customFieldValue
+ * The value of the property
+ */
+ @JsonIgnore
+ public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue )
+ {
+ cloudSdkCustomFields.put(customFieldName, customFieldValue);
+ }
+
+ @Override
+ public boolean equals( @Nullable final java.lang.Object o )
+ {
+ if( this == o ) {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+ final SodaWithId sodaWithId = (SodaWithId) o;
+ return Objects.equals(this.cloudSdkCustomFields, sodaWithId.cloudSdkCustomFields)
+ && Objects.equals(this.name, sodaWithId.name)
+ && Objects.equals(this.brand, sodaWithId.brand)
+ && Objects.equals(this.quantity, sodaWithId.quantity)
+ && Objects.equals(this.packaging, sodaWithId.packaging)
+ && Objects.equals(this.price, sodaWithId.price)
+ && Objects.equals(this.id, sodaWithId.id);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(name, brand, quantity, packaging, price, id, cloudSdkCustomFields);
+ }
+
+ @Override
+ @Nonnull
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class SodaWithId {\n");
+ sb.append(" name: ").append(toIndentedString(name)).append("\n");
+ sb.append(" brand: ").append(toIndentedString(brand)).append("\n");
+ sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n");
+ sb.append(" packaging: ").append(toIndentedString(packaging)).append("\n");
+ sb.append(" price: ").append(toIndentedString(price)).append("\n");
+ sb.append(" id: ").append(toIndentedString(id)).append("\n");
+ cloudSdkCustomFields
+ .forEach(( k, v ) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n"));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces (except the first line).
+ */
+ private String toIndentedString( final java.lang.Object o )
+ {
+ if( o == null ) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+
+ /**
+ * Create a type-safe, fluent-api builder object to construct a new {@link SodaWithId} instance with all required
+ * arguments.
+ */
+ public static Builder create()
+ {
+ return ( name ) -> ( brand ) -> (
+ quantity ) -> ( price ) -> new SodaWithId().name(name).brand(brand).quantity(quantity).price(price);
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder
+ {
+ /**
+ * Set the name of this {@link SodaWithId} instance.
+ *
+ * @param name
+ * The name of this {@link SodaWithId}
+ * @return The SodaWithId builder.
+ */
+ Builder1 name( @Nonnull final String name );
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder1
+ {
+ /**
+ * Set the brand of this {@link SodaWithId} instance.
+ *
+ * @param brand
+ * The brand of this {@link SodaWithId}
+ * @return The SodaWithId builder.
+ */
+ Builder2 brand( @Nonnull final String brand );
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder2
+ {
+ /**
+ * Set the quantity of this {@link SodaWithId} instance.
+ *
+ * @param quantity
+ * The quantity of this {@link SodaWithId}
+ * @return The SodaWithId builder.
+ */
+ Builder3 quantity( @Nonnull final Integer quantity );
+ }
+
+ /**
+ * Builder helper class.
+ */
+ public interface Builder3
+ {
+ /**
+ * Set the price of this {@link SodaWithId} instance.
+ *
+ * @param price
+ * The price of this {@link SodaWithId}
+ * @return The SodaWithId instance.
+ */
+ SodaWithId price( @Nonnull final Float price );
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/resources/petstore-swagger2.json b/datamodel/openapi/openapi-api-apache-sample/src/main/resources/petstore-swagger2.json
new file mode 100644
index 000000000..a088d1a1b
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/resources/petstore-swagger2.json
@@ -0,0 +1,227 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "Swagger Petstore",
+ "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "name": "Swagger API Team"
+ },
+ "license": {
+ "name": "MIT"
+ }
+ },
+ "host": "petstore.swagger.io",
+ "basePath": "/api",
+ "schemes": [
+ "http"
+ ],
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "paths": {
+ "/pets": {
+ "get": {
+ "description": "Returns all pets from the system that the user has access to",
+ "operationId": "findPets",
+ "produces": [
+ "application/json",
+ "application/xml",
+ "text/xml",
+ "text/html"
+ ],
+ "parameters": [
+ {
+ "name": "tags",
+ "in": "query",
+ "description": "tags to filter by",
+ "required": false,
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "collectionFormat": "csv"
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "maximum number of results to return",
+ "required": false,
+ "type": "integer",
+ "format": "int32"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "pet response",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Pet"
+ }
+ }
+ },
+ "default": {
+ "description": "unexpected error",
+ "schema": {
+ "$ref": "#/definitions/ErrorModel"
+ }
+ }
+ }
+ },
+ "post": {
+ "description": "Creates a new pet in the store. Duplicates are allowed",
+ "operationId": "addPet",
+ "produces": [
+ "application/json"
+ ],
+ "parameters": [
+ {
+ "name": "pet",
+ "in": "body",
+ "description": "Pet to add to the store",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/PetInput"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "pet response",
+ "schema": {
+ "$ref": "#/definitions/Pet"
+ }
+ },
+ "default": {
+ "description": "unexpected error",
+ "schema": {
+ "$ref": "#/definitions/ErrorModel"
+ }
+ }
+ }
+ }
+ },
+ "/pets/{id}": {
+ "get": {
+ "description": "Returns a user based on a single ID, if the user does not have access to the pet",
+ "operationId": "findPetById",
+ "produces": [
+ "application/json",
+ "application/xml",
+ "text/xml",
+ "text/html"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of pet to fetch",
+ "required": true,
+ "type": "integer",
+ "format": "int64"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "pet response",
+ "schema": {
+ "$ref": "#/definitions/Pet"
+ }
+ },
+ "default": {
+ "description": "unexpected error",
+ "schema": {
+ "$ref": "#/definitions/ErrorModel"
+ }
+ }
+ }
+ },
+ "delete": {
+ "description": "deletes a single pet based on the ID supplied",
+ "operationId": "deletePet",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of pet to delete",
+ "required": true,
+ "type": "integer",
+ "format": "int64"
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "pet deleted"
+ },
+ "default": {
+ "description": "unexpected error",
+ "schema": {
+ "$ref": "#/definitions/ErrorModel"
+ }
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "Pet": {
+ "type": "object",
+ "required": [
+ "id",
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "name": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ }
+ }
+ },
+ "PetInput": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/Pet"
+ },
+ {
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ }
+ ]
+ },
+ "ErrorModel": {
+ "type": "object",
+ "required": [
+ "code",
+ "message"
+ ],
+ "properties": {
+ "code": {
+ "type": "integer",
+ "format": "int32"
+ },
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/main/resources/sodastore.yaml b/datamodel/openapi/openapi-api-apache-sample/src/main/resources/sodastore.yaml
new file mode 100644
index 000000000..bf2b80a7f
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/main/resources/sodastore.yaml
@@ -0,0 +1,307 @@
+openapi: 3.0.3
+info:
+ title: SodaStore API
+ version: 1.0.0
+ description: API for managing soda products and orders in SodaStore.
+tags:
+ - name: Sodas
+ description: Everything about our Sodas
+ - name: user
+ description: Operations about user
+ - name: Orders
+ description: Access to Sodastore orders
+components:
+ securitySchemes:
+ apiKeyAuth:
+ type: apiKey
+ in: header
+ name: X-API-Key
+ bearerAuth:
+ type: http
+ scheme: bearer
+ schemas:
+ Soda:
+ type: object
+ required:
+ - name
+ - brand
+ - quantity
+ - price
+ properties:
+ name:
+ type: string
+ example: Cola
+ brand:
+ type: string
+ example: Coca-Cola
+ quantity:
+ type: integer
+ format: int32
+ example: 100
+ packaging:
+ type: string
+ enum:
+ - glass
+ - carton
+ - can
+ nullable: false
+ price:
+ type: number
+ format: float
+ example: 1.5
+ SodaWithId:
+ allOf:
+ - $ref: '#/components/schemas/Soda'
+ - type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ example: 123
+ Order:
+ type: object
+ additionalProperties: true
+ required:
+ - productId
+ - quantity
+ properties:
+ productId:
+ type: integer
+ format: int64
+ example: 1
+ quantity:
+ type: integer
+ format: int32
+ example: 2
+ totalPrice:
+ type: number
+ format: float
+ example: 3
+ typelessProperty:
+ description: >-
+ Some typeless property, interpreted by the generator as nullable by
+ default (because typeless)
+ nullableProperty:
+ type: string
+ description: Some typed property that is deliberately made nullable
+ nullable: true
+ OrderWithTimestamp:
+ allOf:
+ - $ref: '#/components/schemas/Order'
+ - type: object
+ properties:
+ timestamp:
+ type: string
+ format: date-time
+ OneOfWithDiscriminatorAndMapping:
+ oneOf:
+ - $ref: '#/components/schemas/Cola'
+ - $ref: '#/components/schemas/Fanta'
+ discriminator:
+ propertyName: sodaType
+ mapping:
+ cool_cola: '#/components/schemas/Cola'
+ fancy_fanta: '#/components/schemas/Fanta'
+ OneOfWithDiscriminator:
+ oneOf:
+ - $ref: '#/components/schemas/Cola'
+ - $ref: '#/components/schemas/Fanta'
+ discriminator:
+ propertyName: sodaType
+ OneOfWithEnumDiscriminator:
+ oneOf:
+ - $ref: '#/components/schemas/Foo'
+ - $ref: '#/components/schemas/Bar'
+ discriminator:
+ propertyName: disc
+ mapping:
+ disc_foo: '#/components/schemas/Foo'
+ disc_bar: '#/components/schemas/Bar'
+ Foo:
+ type: object
+ properties:
+ foo:
+ type: string
+ disc:
+ type: string
+ enum:
+ - disc_foo
+ Bar:
+ type: object
+ properties:
+ bar:
+ type: string
+ disc:
+ type: string
+ enum:
+ - disc_bar
+ OneOf:
+ oneOf:
+ - $ref: '#/components/schemas/Cola'
+ - $ref: '#/components/schemas/Fanta'
+ AnyOf:
+ anyOf:
+ - $ref: '#/components/schemas/Cola'
+ - $ref: '#/components/schemas/Fanta'
+ AllOf:
+ allOf:
+ - $ref: '#/components/schemas/Cola'
+ - $ref: '#/components/schemas/Fanta'
+ Cola:
+ type: object
+ properties:
+ sodaType:
+ type: string
+ caffeine:
+ type: boolean
+ logo:
+ oneOf:
+ - type: string
+ - type: array
+ items:
+ type: array
+ items:
+ type: integer
+ format: int32
+ barCode:
+ oneOf:
+ - type: array
+ items:
+ type: number
+ - type: string
+ Fanta:
+ type: object
+ properties:
+ sodaType:
+ type: string
+ color:
+ type: string
+ flavor:
+ oneOf:
+ - type: string
+ - type: integer
+ - type: array
+ items:
+ $ref: '#/components/schemas/FlavorType'
+ - $ref: '#/components/schemas/FlavorType'
+ FlavorType:
+ type: object
+ properties:
+ intensity:
+ type: integer
+ description: The intensity of the flavor
+ nuance:
+ type: string
+ description: The nuance of the flavor
+paths:
+ /sodas:
+ get:
+ summary: Get all soda products
+ tags:
+ - Sodas
+ security:
+ - apiKeyAuth: [ ]
+ responses:
+ '200':
+ description: A list of soda products
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/SodaWithId'
+ put:
+ summary: Update a specific soda product by ID
+ tags:
+ - Sodas
+ security:
+ - apiKeyAuth: [ ]
+ requestBody:
+ description: The updated soda product
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SodaWithId'
+ responses:
+ '200':
+ description: The updated soda product
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Soda'
+ '204':
+ description: Nothing has changed
+ '404':
+ description: Soda product not found
+ /sodas/{id}:
+ get:
+ summary: Get a specific soda product by ID
+ tags:
+ - Sodas
+ security:
+ - apiKeyAuth: [ ]
+ parameters:
+ - name: id
+ in: path
+ description: ID of the soda product to retrieve
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: The soda product
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SodaWithId'
+ '404':
+ description: Soda product not found
+ /sodas/download/{id}:
+ get:
+ summary: Download soda product data as binary
+ tags:
+ - Sodas
+ parameters:
+ - name: id
+ in: path
+ description: ID of the soda product to download
+ required: true
+ schema:
+ type: integer
+ format: int64
+ responses:
+ '200':
+ description: Successful response
+ content:
+ application/octet-stream:
+ schema:
+ type: string
+ format: binary
+ '404':
+ description: Soda product not found
+ /orders:
+ post:
+ summary: Create a new order
+ tags:
+ - Orders
+ security:
+ - apiKeyAuth: [ ]
+ requestBody:
+ description: The order details
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Order'
+ responses:
+ '201':
+ description: The created order
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Order'
+security:
+ - apiKeyAuth: [ ]
+ - bearerAuth: [ ]
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/test/java/com/sap/cloud/sdk/services/openapi/apache/DeserializationTest.java b/datamodel/openapi/openapi-api-apache-sample/src/test/java/com/sap/cloud/sdk/services/openapi/apache/DeserializationTest.java
new file mode 100644
index 000000000..384185717
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/test/java/com/sap/cloud/sdk/services/openapi/apache/DeserializationTest.java
@@ -0,0 +1,143 @@
+package com.sap.cloud.sdk.services.openapi.apache;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.okJson;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import java.util.Map;
+
+import org.assertj.core.api.InstanceOfAssertFactories;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
+import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.api.SodasApi;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.SodaWithId;
+
+@WireMockTest
+class DeserializationTest
+{
+
+ private SodasApi sut;
+ private String responseBody;
+
+ @BeforeEach
+ void setUp( WireMockRuntimeInfo wmRuntimeInfo )
+ {
+ sut = new SodasApi(DefaultHttpDestination.builder(wmRuntimeInfo.getHttpBaseUrl()).build());
+ }
+
+ @Test
+ void testFullResponse()
+ {
+ responseBody = """
+ {
+ "name": "Cola",
+ "brand": "Coca-Cola",
+ "quantity": 100,
+ "packaging" : "new-value",
+ "price": 1.5,
+ "id": 0
+ }
+ """;
+ stub(responseBody);
+
+ final SodaWithId expected =
+ SodaWithId
+ .create()
+ .name("Cola")
+ .brand("Coca-Cola")
+ .quantity(100)
+ .price(1.5f)
+ .id(0L)
+ .packaging(SodaWithId.PackagingEnum.UNKNOWN_DEFAULT_OPEN_API);
+
+ final SodaWithId actual = sut.sodasIdGet(1L);
+
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @Test
+ void testUnexpectedFieldOrder()
+ {
+ responseBody = """
+ {
+ "name": "Cola",
+ "price": 1.5,
+ "id": 0,
+ "brand": "Coca-Cola",
+ "quantity": 100
+ }
+ """;
+ stub(responseBody);
+
+ final SodaWithId expected =
+ SodaWithId.create().name("Cola").brand("Coca-Cola").quantity(100).price(1.5f).id(0L);
+
+ final SodaWithId actual = sut.sodasIdGet(1L);
+
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @Test
+ void testPartialResponse()
+ {
+ responseBody = "{\"name\": \"Cola\"}";
+ stub(responseBody);
+
+ final SodaWithId expected = SodaWithId.create().name("Cola").brand(null).quantity(null).price(null);
+
+ final SodaWithId actual = sut.sodasIdGet(1L);
+
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @Test
+ @SuppressWarnings( "deprecation" )
+ void testUnexpectedAdditionalField()
+ {
+ responseBody = """
+ {
+ "name": "Cola",
+ "unexpectedField": []
+ }
+ """;
+ stub(responseBody);
+
+ final SodaWithId actual = sut.sodasIdGet(1L);
+
+ assertThat(actual.getName()).isEqualTo("Cola");
+ assertThat(actual.toMap())
+ .containsExactlyInAnyOrderEntriesOf(Map.of("name", "Cola", "unexpectedField", List.of()));
+ assertThat(actual.toMap().get("doesNotExist")).isNull();
+ assertThat(actual.getCustomFieldNames()).containsExactly("unexpectedField");
+ assertThat(actual.getCustomField("unexpectedField")).asInstanceOf(InstanceOfAssertFactories.LIST).isEmpty();
+ }
+
+ @Test
+ void testBinaryResponse()
+ {
+ final byte[] binaryData = "binary file content".getBytes();
+ WireMock
+ .stubFor(
+ WireMock
+ .get(WireMock.urlMatching("/sodas/download/\\d+"))
+ .willReturn(
+ WireMock
+ .aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/octet-stream")
+ .withBody(binaryData)));
+ final byte[] result = sut.sodasDownloadIdGet(1L);
+ assertThat(result).isNotNull();
+ assertThat(result).isEqualTo(binaryData);
+ }
+
+ private void stub( String responseBody )
+ {
+ WireMock.stubFor(WireMock.get(WireMock.anyUrl()).willReturn(okJson(responseBody)));
+ }
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/test/java/com/sap/cloud/sdk/services/openapi/apache/OneOfDeserializationTest.java b/datamodel/openapi/openapi-api-apache-sample/src/test/java/com/sap/cloud/sdk/services/openapi/apache/OneOfDeserializationTest.java
new file mode 100644
index 000000000..ed7ea48f5
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/test/java/com/sap/cloud/sdk/services/openapi/apache/OneOfDeserializationTest.java
@@ -0,0 +1,318 @@
+package com.sap.cloud.sdk.services.openapi.apache;
+
+import static com.fasterxml.jackson.annotation.PropertyAccessor.GETTER;
+import static com.fasterxml.jackson.annotation.PropertyAccessor.SETTER;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import javax.annotation.Nonnull;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.AllOf;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.AnyOf;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.Bar;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.Cola;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.ColaBarCode;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.ColaLogo;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.Fanta;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.FantaFlavor;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.FlavorType;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.Foo;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.OneOf;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.OneOfWithDiscriminator;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.OneOfWithDiscriminatorAndMapping;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.OneOfWithEnumDiscriminator;
+
+class OneOfDeserializationTest
+{
+ private static final ObjectMapper objectMapper = newDefaultObjectMapper();
+
+ private static final Cola COLA_OBJECT = Cola.create().caffeine(true).sodaType("Cola");
+ private static final Fanta FANTA_OBJECT =
+ Fanta
+ .create()
+ .color("orange")
+ .sodaType("Fanta")
+ .flavor(new FantaFlavor.InnerFlavorType(FlavorType.create().intensity(3).nuance("wood")));
+ private static final String COLA_JSON = """
+ {
+ "sodaType": "Cola",
+ "caffeine": true,
+ "logo":null,
+ "barCode":null
+ }""";
+ private static final String FANTA_JSON = """
+ {
+ "sodaType": "Fanta",
+ "color": "orange",
+ "flavor": {"intensity":3,"nuance":"wood"}
+ }""";
+ private static final String FANTA_FLAVOR_ARRAY_JSON = """
+ {
+ "sodaType": "Fanta",
+ "color": "orange",
+ "flavor": [
+ {"intensity":3,"nuance":"wood"},
+ {"intensity":5,"nuance":"citrus"}
+ ]
+ }""";
+ private static final String COLA_LOGO_MATRIX_JSON = """
+ {
+ "sodaType": "Cola",
+ "caffeine": true,
+ "logo": [[255, 0, 0], [0, 255, 0], [0, 0, 255]]
+ }""";
+ private static final String UNKNOWN_JSON = """
+ {
+ "sodaType": "Sprite",
+ "someProperty": "someValue"
+ }""";
+
+ private static final String COLA_BARCODE_FLOAT_ARRAY_JSON = """
+ {
+ "sodaType": "Cola",
+ "caffeine": true,
+ "barCode": [1.1, 2.2, 3.3]
+ }""";
+
+ @Test
+ void oneOf()
+ throws JsonProcessingException
+ {
+ var actual = objectMapper.readValue(COLA_JSON, OneOf.class);
+ assertThat(actual)
+ .describedAs("Object should automatically be deserialized as Cola with JSON subtype deduction")
+ .isInstanceOf(Cola.class)
+ .isEqualTo(COLA_OBJECT);
+
+ actual = objectMapper.readValue(FANTA_JSON, OneOf.class);
+ assertThat(actual)
+ .describedAs("Object should automatically be deserialized as Fanta with JSON subtype deduction")
+ .isInstanceOf(Fanta.class)
+ .isEqualTo(FANTA_OBJECT);
+
+ assertThatThrownBy(() -> objectMapper.readValue(UNKNOWN_JSON, OneOf.class))
+ .isInstanceOf(JsonProcessingException.class);
+ }
+
+ @Test
+ void oneOfWithDiscriminator()
+ throws JsonProcessingException
+ {
+ var actual = objectMapper.readValue(COLA_JSON, OneOfWithDiscriminator.class);
+ assertThat(actual)
+ .describedAs(
+ "Object should automatically be deserialized as Cola using the class names as discriminator mapping values")
+ .isInstanceOf(Cola.class)
+ .isEqualTo(COLA_OBJECT);
+
+ actual = objectMapper.readValue(FANTA_JSON, OneOfWithDiscriminator.class);
+ assertThat(actual)
+ .describedAs(
+ "Object should automatically be deserialized as Fanta using the class names as discriminator mapping values")
+ .isInstanceOf(Fanta.class)
+ .isEqualTo(FANTA_OBJECT);
+
+ assertThatThrownBy(() -> objectMapper.readValue(UNKNOWN_JSON, OneOfWithDiscriminator.class))
+ .isInstanceOf(JsonProcessingException.class);
+ }
+
+ @Test
+ void oneOfWithDiscriminatorAndMapping()
+ throws JsonProcessingException
+ {
+ var jsonWithCustomMapping = """
+ {
+ "sodaType": "cool_cola",
+ "caffeine": true
+ }""";
+ var actual = objectMapper.readValue(jsonWithCustomMapping, OneOfWithDiscriminatorAndMapping.class);
+ assertThat(actual)
+ .describedAs(
+ "Object should automatically be deserialized as Cola using the explicit discriminator mapping values")
+ .isInstanceOf(Cola.class)
+ .isEqualTo(Cola.create().caffeine(true).sodaType("cool_cola"));
+
+ jsonWithCustomMapping = """
+ {
+ "sodaType": "fancy_fanta",
+ "color": "orange"
+ }""";
+ actual = objectMapper.readValue(jsonWithCustomMapping, OneOfWithDiscriminatorAndMapping.class);
+ assertThat(actual)
+ .describedAs(
+ "Object should automatically be deserialized as Fanta using the explicit discriminator mapping values")
+ .isInstanceOf(Fanta.class)
+ .isEqualTo(Fanta.create().color("orange").sodaType("fancy_fanta"));
+
+ assertThatThrownBy(() -> objectMapper.readValue(UNKNOWN_JSON, OneOfWithDiscriminatorAndMapping.class))
+ .isInstanceOf(JsonProcessingException.class);
+ }
+
+ static Stream> oneOfStrategiesProvider()
+ {
+ return Stream.of(OneOf.class, OneOfWithDiscriminator.class);
+ }
+
+ @ParameterizedTest( name = "Deserialization with strategy: {0}" )
+ @MethodSource( "oneOfStrategiesProvider" )
+ void oneOfWithNestedArrayOfObjects( Class> strategy )
+ throws JsonProcessingException
+ {
+ var payload = FANTA_FLAVOR_ARRAY_JSON;
+ if( strategy == OneOfWithDiscriminatorAndMapping.class ) {
+ payload.replace("Fanta", "fancy_fanta").replace("Cola", "cool_cola");
+ }
+
+ Object actual = objectMapper.readValue(payload, strategy);
+
+ assertThat(actual)
+ .describedAs("Object should automatically be deserialized as Fanta with JSON subtype deduction")
+ .isInstanceOf(Fanta.class);
+ var fanta = (Fanta) actual;
+ assertThat(fanta.getFlavor())
+ .describedAs("Flavor should be deserialized as wrapper class for a list of FlavorType instances")
+ .isInstanceOf(FantaFlavor.ListOfFlavorTypes.class);
+ var flavorTypes = (FantaFlavor.ListOfFlavorTypes) fanta.getFlavor();
+ assertThat(flavorTypes.values())
+ .describedAs("Flavor should be deserialized as a list of FlavorType instances")
+ .isNotEmpty()
+ .allMatch(FlavorType.class::isInstance);
+
+ actual = objectMapper.readValue(COLA_LOGO_MATRIX_JSON, strategy);
+
+ assertThat(actual)
+ .describedAs("Object should automatically be deserialized as Cola with JSON subtype deduction")
+ .isInstanceOf(Cola.class);
+ var cola = (Cola) actual;
+ assertThat(cola.isCaffeine()).isTrue();
+ assertThat(cola.getLogo()).isInstanceOf(ColaLogo.ListOfListOfIntegers.class);
+ var logo = (ColaLogo.ListOfListOfIntegers) cola.getLogo();
+ assertThat(logo.values())
+ .describedAs("Logo should be deserialized as a list of list of integers")
+ .isInstanceOf(List.class)
+ .containsExactly(List.of(255, 0, 0), List.of(0, 255, 0), List.of(0, 0, 255));
+
+ actual = objectMapper.readValue(COLA_BARCODE_FLOAT_ARRAY_JSON, strategy);
+ assertThat(actual)
+ .describedAs("Object should automatically be deserialized as Cola with JSON subtype deduction")
+ .isInstanceOf(Cola.class);
+ cola = (Cola) actual;
+ assertThat(cola.isCaffeine()).isTrue();
+ assertThat(cola.getBarCode()).isInstanceOf(ColaBarCode.ArrayOfFloats.class);
+ var barCode = (ColaBarCode.ArrayOfFloats) cola.getBarCode();
+ assertThat(barCode.values())
+ .describedAs("BarCode should be deserialized as an array of floats")
+ .isInstanceOf(float[].class)
+ .containsExactly(1.1f, 2.2f, 3.3f);
+ }
+
+ @Test
+ void anyOf()
+ throws JsonProcessingException
+ {
+ AnyOf anyOfCola = objectMapper.readValue(COLA_JSON, AnyOf.class);
+ assertThat(anyOfCola.getSodaType()).isEqualTo("Cola");
+ assertThat(anyOfCola.isCaffeine()).isTrue();
+ assertThat(anyOfCola.getColor()).isNull();
+
+ AnyOf anyOfFanta = objectMapper.readValue(FANTA_JSON, AnyOf.class);
+ assertThat(anyOfFanta.getSodaType()).isEqualTo("Fanta");
+ assertThat(anyOfFanta.getColor()).isEqualTo("orange");
+ assertThat(anyOfFanta.isCaffeine()).isNull();
+
+ AnyOf actual = objectMapper.readValue(FANTA_FLAVOR_ARRAY_JSON, AnyOf.class);
+
+ assertThat(actual.getSodaType()).isEqualTo("Fanta");
+ assertThat(actual.getColor()).isEqualTo("orange");
+ assertThat(actual.getFlavor()).isInstanceOf(FantaFlavor.ListOfFlavorTypes.class);
+ assertThat(((FantaFlavor.ListOfFlavorTypes) actual.getFlavor()).values())
+ .allMatch(FlavorType.class::isInstance);
+ }
+
+ @Test
+ void allOf()
+ throws JsonProcessingException
+ {
+ AllOf allOfCola = objectMapper.readValue(COLA_JSON, AllOf.class);
+ assertThat(allOfCola.getSodaType()).isEqualTo("Cola");
+ assertThat(allOfCola.isCaffeine()).isTrue();
+ assertThat(allOfCola.getColor()).isNull();
+
+ AllOf allOfFanta = objectMapper.readValue(FANTA_JSON, AllOf.class);
+ assertThat(allOfFanta.getSodaType()).isEqualTo("Fanta");
+ assertThat(allOfFanta.getColor()).isEqualTo("orange");
+ assertThat(allOfFanta.isCaffeine()).isNull();
+ }
+
+ @Test
+ void testColaSerialization()
+ throws JsonProcessingException
+ {
+ var expected = objectMapper.readValue(COLA_JSON, JsonNode.class);
+ var actual = objectMapper.valueToTree(COLA_OBJECT);
+
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @Test
+ void testFantaSerialization()
+ throws JsonProcessingException
+ {
+ var expected = objectMapper.readValue(FANTA_JSON, JsonNode.class);
+ var actual = objectMapper.valueToTree(FANTA_OBJECT);
+
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @Test
+ void testDeserializationWithEnumDiscriminator()
+ throws JsonProcessingException
+ {
+ var json = """
+ {
+ "foo": "asdf",
+ "disc": "disc_foo"
+ }""";
+ assertThat(objectMapper.readValue(json, OneOfWithEnumDiscriminator.class))
+ .isInstanceOf(Foo.class)
+ .isEqualTo(Foo.create().foo("asdf").disc(Foo.DiscEnum.DISC_FOO));
+ json = """
+ {
+ "bar": "asdf",
+ "disc": "disc_bar"
+ }""";
+ assertThat(objectMapper.readValue(json, OneOfWithEnumDiscriminator.class))
+ .isInstanceOf(Bar.class)
+ .isEqualTo(Bar.create().bar("asdf").disc(Bar.DiscEnum.DISC_BAR));
+
+ assertThatThrownBy(() -> objectMapper.readValue("{ \"type\": \"unknown\" }", OneOfWithEnumDiscriminator.class))
+ .isInstanceOf(JsonProcessingException.class);
+ }
+
+ /**
+ * Taken from {@link com.sap.cloud.sdk.services.openapi.apiclient.ApiClient}
+ */
+ @Nonnull
+ private static ObjectMapper newDefaultObjectMapper()
+ {
+ return JsonMapper
+ .builder()
+ .addModule(new JavaTimeModule())
+ .visibility(GETTER, JsonAutoDetect.Visibility.NONE)
+ .visibility(SETTER, JsonAutoDetect.Visibility.NONE)
+ .build();
+ }
+}
diff --git a/datamodel/openapi/openapi-api-apache-sample/src/test/java/com/sap/cloud/sdk/services/openapi/apache/SerializationTest.java b/datamodel/openapi/openapi-api-apache-sample/src/test/java/com/sap/cloud/sdk/services/openapi/apache/SerializationTest.java
new file mode 100644
index 000000000..5486d3f06
--- /dev/null
+++ b/datamodel/openapi/openapi-api-apache-sample/src/test/java/com/sap/cloud/sdk/services/openapi/apache/SerializationTest.java
@@ -0,0 +1,111 @@
+package com.sap.cloud.sdk.services.openapi.apache;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
+import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.api.SodasApi;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.Order;
+import com.sap.cloud.sdk.datamodel.openapi.apache.sodastore.model.SodaWithId;
+
+@WireMockTest
+class SerializationTest
+{
+
+ private SodasApi sut;
+ private String expected;
+
+ @BeforeEach
+ void setUp( WireMockRuntimeInfo wmRuntimeInfo )
+ {
+ sut = new SodasApi(DefaultHttpDestination.builder(wmRuntimeInfo.getHttpBaseUrl()).build());
+ WireMock.stubFor(WireMock.put("/sodas").willReturn(WireMock.created()));
+ }
+
+ @Test
+ void testPutPayload()
+ {
+ expected = """
+ {
+ "name": "Cola",
+ "brand": "Coca-Cola",
+ "quantity": 100,
+ "packaging" : null,
+ "price": 1.5,
+ "id": 0
+ }
+ """;
+
+ final SodaWithId obj = SodaWithId.create().name("Cola").brand("Coca-Cola").quantity(100).price(1.5f).id(0L);
+
+ sut.sodasPut(obj);
+
+ verify(expected);
+ }
+
+ @Test
+ void testJacksonSerializeSodaWithId()
+ throws JsonProcessingException
+ {
+ expected = """
+ {
+ "name": "Cola",
+ "brand": "Coca-Cola",
+ "quantity": 100,
+ "packaging" : "can",
+ "price": 1.5,
+ "id": 0
+ }
+ """;
+
+ final SodaWithId obj =
+ SodaWithId
+ .create()
+ .name("Cola")
+ .brand("Coca-Cola")
+ .quantity(100)
+ .price(1.5f)
+ .id(0L)
+ .packaging(SodaWithId.PackagingEnum.CAN);
+
+ assertThat(new ObjectMapper().writeValueAsString(obj)).isEqualToIgnoringWhitespace(expected);
+ }
+
+ @Test
+ void testJacksonSerializeOrder()
+ throws JsonProcessingException
+ {
+ expected = """
+ {
+ "productId": 100,
+ "quantity": 5,
+ "totalPrice": 6.0,
+ "typelessProperty":null,
+ "nullableProperty":null,
+ "shoesize": 44
+ }
+ """;
+ final Order order = Order.create().productId(100L).quantity(5).totalPrice(6.0f);
+ order.setCustomField("shoesize", 44);
+ assertThat(new ObjectMapper().writeValueAsString(order)).isEqualToIgnoringWhitespace(expected);
+ assertThat(new ObjectMapper().readValue(expected, Order.class)).isEqualTo(order);
+ }
+
+ private void verify( String requestBody )
+ {
+ WireMock
+ .verify(
+ WireMock
+ .putRequestedFor(WireMock.urlEqualTo("/sodas"))
+ .withHeader("Content-Type", WireMock.equalTo("application/json; charset=UTF-8"))
+ .withRequestBody(WireMock.equalToJson(requestBody)));
+ }
+
+}
diff --git a/datamodel/openapi/openapi-api-sample/pom.xml b/datamodel/openapi/openapi-api-sample/pom.xml
index 1bff0e213..251db764b 100644
--- a/datamodel/openapi/openapi-api-sample/pom.xml
+++ b/datamodel/openapi/openapi-api-sample/pom.xml
@@ -126,7 +126,6 @@
File=byte[]
create
-
protected
true
true
diff --git a/datamodel/openapi/openapi-api-sample/src/test/java/com/sap/cloud/sdk/datamodel/openapi/sample/api/OneOfDeserializationTest.java b/datamodel/openapi/openapi-api-sample/src/test/java/com/sap/cloud/sdk/datamodel/openapi/sample/api/OneOfDeserializationTest.java
index 5a0611253..b705bee84 100644
--- a/datamodel/openapi/openapi-api-sample/src/test/java/com/sap/cloud/sdk/datamodel/openapi/sample/api/OneOfDeserializationTest.java
+++ b/datamodel/openapi/openapi-api-sample/src/test/java/com/sap/cloud/sdk/datamodel/openapi/sample/api/OneOfDeserializationTest.java
@@ -48,7 +48,9 @@ class OneOfDeserializationTest
private static final String COLA_JSON = """
{
"sodaType": "Cola",
- "caffeine": true
+ "caffeine": true,
+ "logo": null,
+ "barCode": null
}""";
private static final String FANTA_JSON = """
{
@@ -259,7 +261,7 @@ void testColaSerialization()
throws JsonProcessingException
{
var expected = objectMapper.readValue(COLA_JSON, JsonNode.class);
- var actual = objectMapper.valueToTree(expected);
+ var actual = objectMapper.valueToTree(COLA_OBJECT);
assertThat(actual).isEqualTo(expected);
}
@@ -268,8 +270,8 @@ void testColaSerialization()
void testFantaSerialization()
throws JsonProcessingException
{
- var expected = objectMapper.readValue(FANTA_JSON, JsonNode.class);
- var actual = objectMapper.valueToTree(expected);
+ JsonNode expected = objectMapper.readValue(FANTA_JSON, JsonNode.class);
+ JsonNode actual = objectMapper.valueToTree(FANTA_OBJECT);
assertThat(actual).isEqualTo(expected);
}
diff --git a/datamodel/openapi/openapi-core/pom.xml b/datamodel/openapi/openapi-core/pom.xml
index 603a7db05..5c43b2765 100644
--- a/datamodel/openapi/openapi-core/pom.xml
+++ b/datamodel/openapi/openapi-core/pom.xml
@@ -59,15 +59,21 @@
org.springframework
spring-core
+ true
org.springframework
spring-web
+ true
com.fasterxml.jackson.core
jackson-core
+
+ com.google.guava
+ guava
+
org.projectlombok
@@ -98,9 +104,13 @@
org.apache.httpcomponents.core5
httpcore5
- test
-
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
+
diff --git a/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/ApiClient.java b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/ApiClient.java
new file mode 100644
index 000000000..f2262678f
--- /dev/null
+++ b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/ApiClient.java
@@ -0,0 +1,577 @@
+/*
+ * Prompt Registry API
+ * Prompt Storage service for Design time & Runtime prompt templates.
+ *
+ * The version of the OpenAPI document: 0.0.1
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.services.openapi.apache;
+
+import static com.sap.cloud.sdk.services.openapi.apache.DefaultApiResponseHandler.isJsonMime;
+import static lombok.AccessLevel.PRIVATE;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.Method;
+import org.apache.hc.core5.http.NameValuePair;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
+import org.apache.hc.core5.http.io.entity.FileEntity;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
+import org.apache.hc.core5.http.message.BasicNameValuePair;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.google.common.annotations.Beta;
+import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5Accessor;
+import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
+import com.sap.cloud.sdk.services.openapi.apiclient.RFC3339DateFormat;
+import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.ToString;
+import lombok.With;
+
+/**
+ * API client for executing HTTP requests using Apache HttpClient 5.
+ */
+@AllArgsConstructor( access = PRIVATE )
+@EqualsAndHashCode
+@ToString
+public class ApiClient
+{
+ @Nonnull
+ private final CloseableHttpClient httpClient;
+
+ @With
+ @Getter
+ @Nonnull
+ private final String basePath;
+
+ @With( onMethod_ = @Beta )
+ @Nonnull
+ private final ObjectMapper objectMapper;
+
+ @With
+ @Nullable
+ private final String tempFolderPath;
+
+ // Methods that can have a request body
+ private static final Set BODY_METHODS = Set.of(Method.POST, Method.PUT, Method.PATCH, Method.DELETE);
+ private static final String DEFAULT_BASE_PATH = "http://localhost";
+
+ /**
+ * Creates an ApiClient instance from an existing HttpClient.
+ *
+ * @param httpClient
+ * The HttpClient to use for requests
+ * @return A new ApiClient instance
+ */
+ @Nonnull
+ public static ApiClient fromHttpClient( @Nonnull final CloseableHttpClient httpClient )
+ {
+ return new ApiClient(httpClient, DEFAULT_BASE_PATH, createDefaultObjectMapper(), null);
+ }
+
+ /**
+ * Creates an ApiClient instance configured for the given destination.
+ *
+ * @param destination
+ * The destination to use for requests
+ * @return A new ApiClient instance configured with the destination
+ */
+ @Nonnull
+ public static ApiClient create( @Nonnull final Destination destination )
+ {
+ return fromHttpClient((CloseableHttpClient) ApacheHttpClient5Accessor.getHttpClient(destination))
+ .withBasePath(destination.asHttp().getUri().toString());
+
+ }
+
+ /**
+ * Creates an ApiClient instance with default configuration.
+ *
+ * @return A new ApiClient instance
+ */
+ @Nonnull
+ public static ApiClient create()
+ {
+ return fromHttpClient((CloseableHttpClient) ApacheHttpClient5Accessor.getHttpClient());
+ }
+
+ @Nonnull
+ private static ObjectMapper createDefaultObjectMapper()
+ {
+ return JsonMapper
+ .builder()
+ .addModule(new JavaTimeModule())
+ .defaultDateFormat(new RFC3339DateFormat())
+ .visibility(PropertyAccessor.GETTER, Visibility.NONE)
+ .visibility(PropertyAccessor.SETTER, Visibility.NONE)
+ .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ .disable(MapperFeature.DEFAULT_VIEW_INCLUSION)
+ .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .build();
+ }
+
+ /**
+ * Format the given Date object into string.
+ *
+ * @param date
+ * Date
+ * @return Date in string format
+ */
+ @Nonnull
+ private static String formatDate( @Nonnull final Date date )
+ {
+ return new RFC3339DateFormat().format(date);
+ }
+
+ /**
+ * Format the given parameter object into string.
+ *
+ * @param param
+ * Object
+ * @return Object in string format
+ */
+ @Nonnull
+ public static String parameterToString( @Nullable final Object param )
+ {
+ if( param == null ) {
+ return "";
+ } else if( param instanceof Date date ) {
+ return formatDate(date);
+ } else if( param instanceof Collection ) {
+ final StringBuilder b = new StringBuilder();
+ for( final Object o : (Collection>) param ) {
+ if( !b.isEmpty() ) {
+ b.append(',');
+ }
+ b.append(o);
+ }
+ return b.toString();
+ } else {
+ return String.valueOf(param);
+ }
+ }
+
+ /**
+ * Formats the specified query parameter to a list containing a single {@code Pair} object.
+ *
+ * Note that {@code value} must not be a collection.
+ *
+ * @param name
+ * The name of the parameter.
+ * @param value
+ * The value of the parameter.
+ * @return A list containing a single {@code Pair} object.
+ */
+ @Nonnull
+ public static List parameterToPair( @Nullable final String name, @Nullable final Object value )
+ {
+ final List params = new ArrayList<>();
+
+ // preconditions
+ if( name == null || name.isEmpty() || value == null || value instanceof Collection ) {
+ return params;
+ }
+
+ params.add(new Pair(name, escapeString(parameterToString(value))));
+ return params;
+ }
+
+ /**
+ * Formats the specified collection query parameters to a list of {@code Pair} objects.
+ *
+ * Note that the values of each of the returned Pair objects are percent-encoded.
+ *
+ * @param collectionFormat
+ * The collection format of the parameter.
+ * @param name
+ * The name of the parameter.
+ * @param value
+ * The value of the parameter.
+ * @return A list of {@code Pair} objects.
+ */
+ @Nonnull
+ public static List parameterToPairs(
+ @Nonnull final String collectionFormat,
+ @Nullable final String name,
+ @Nullable final Collection> value )
+ {
+ final List params = new ArrayList<>();
+
+ // preconditions
+ if( name == null || name.isEmpty() || value == null || value.isEmpty() ) {
+ return params;
+ }
+
+ // create the params based on the collection format
+ if( "multi".equals(collectionFormat) ) {
+ for( final Object item : value ) {
+ params.add(new Pair(name, escapeString(parameterToString(item))));
+ }
+ return params;
+ }
+
+ // collectionFormat is assumed to be "csv" by default
+ final String delimiter = switch( collectionFormat ) {
+ case "ssv" -> escapeString(" ");
+ case "tsv" -> escapeString("\t");
+ case "pipes" -> escapeString("|");
+ default -> ",";
+ // escape all delimiters except commas, which are URI reserved characters
+ };
+
+ final StringBuilder sb = new StringBuilder();
+ for( final Object item : value ) {
+ sb.append(delimiter);
+ sb.append(escapeString(parameterToString(item)));
+ }
+
+ params.add(new Pair(name, sb.substring(delimiter.length())));
+
+ return params;
+ }
+
+ /**
+ * Select the Accept header's value from the given accepts array: if JSON exists in the given array, use it;
+ * otherwise use all of them (joining into a string)
+ *
+ * @param accepts
+ * The accepts array to select from
+ * @return The Accept header to use. If the given array is empty, null will be returned (not to set the Accept
+ * header explicitly).
+ */
+ @Nullable
+ public static String selectHeaderAccept( @Nonnull final String[] accepts )
+ {
+ if( accepts.length == 0 ) {
+ return null;
+ }
+ for( final String accept : accepts ) {
+ if( isJsonMime(accept) ) {
+ return accept;
+ }
+ }
+ return String.join(",", accepts);
+ }
+
+ /**
+ * Select the Content-Type header's value from the given array: if JSON exists in the given array, use it; otherwise
+ * use the first one of the array.
+ *
+ * @param contentTypes
+ * The Content-Type array to select from
+ * @return The Content-Type header to use. If the given array is empty, or matches "any", JSON will be used.
+ */
+ @Nonnull
+ public static String selectHeaderContentType( @Nonnull final String[] contentTypes )
+ {
+ if( contentTypes.length == 0 || contentTypes[0].equals("*/*") ) {
+ return "application/json";
+ }
+ for( final String contentType : contentTypes ) {
+ if( isJsonMime(contentType) ) {
+ return contentType;
+ }
+ }
+ return contentTypes[0];
+ }
+
+ /**
+ * Escape the given string to be used as URL query value.
+ *
+ * @param str
+ * String
+ * @return Escaped string
+ */
+ @Nonnull
+ public static String escapeString( @Nonnull final String str )
+ {
+ return URLEncoder.encode(str, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
+ }
+
+ /**
+ * Parse content type object from header value
+ */
+ @Nonnull
+ private ContentType getContentType( @Nonnull final String headerValue )
+ throws OpenApiRequestException
+ {
+ try {
+ return ContentType.parse(headerValue);
+ }
+ catch( UnsupportedCharsetException e ) {
+ throw new OpenApiRequestException("Could not parse content type " + headerValue, e);
+ }
+ }
+
+ /**
+ * Serialize the given Java object into string according the given Content-Type (only JSON is supported for now).
+ *
+ * @param obj
+ * Object
+ * @param contentType
+ * Content type
+ * @param formParams
+ * Form parameters
+ * @return Object
+ * @throws OpenApiRequestException
+ * API exception
+ */
+ @Nonnull
+ private HttpEntity serialize(
+ @Nullable final Object obj,
+ @Nonnull final Map formParams,
+ @Nonnull final ContentType contentType )
+ throws OpenApiRequestException
+ {
+ final String mimeType = contentType.getMimeType();
+ if( isJsonMime(mimeType) ) {
+ try {
+ return new StringEntity(
+ objectMapper.writeValueAsString(obj),
+ contentType.withCharset(StandardCharsets.UTF_8));
+ }
+ catch( JsonProcessingException e ) {
+ throw new OpenApiRequestException(e);
+ }
+ } else if( mimeType.equals(ContentType.MULTIPART_FORM_DATA.getMimeType()) ) {
+ final MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create();
+ for( final Entry paramEntry : formParams.entrySet() ) {
+ final Object value = paramEntry.getValue();
+ if( value instanceof File file ) {
+ multiPartBuilder.addBinaryBody(paramEntry.getKey(), file);
+ } else if( value instanceof byte[] byteArray ) {
+ multiPartBuilder.addBinaryBody(paramEntry.getKey(), byteArray);
+ } else {
+ final Charset charset = contentType.getCharset();
+ if( charset != null ) {
+ final ContentType customContentType =
+ ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), charset);
+ multiPartBuilder
+ .addTextBody(
+ paramEntry.getKey(),
+ parameterToString(paramEntry.getValue()),
+ customContentType);
+ } else {
+ multiPartBuilder.addTextBody(paramEntry.getKey(), parameterToString(paramEntry.getValue()));
+ }
+ }
+ }
+ return multiPartBuilder.build();
+ } else if( mimeType.equals(ContentType.APPLICATION_FORM_URLENCODED.getMimeType()) ) {
+ final List formValues = new ArrayList<>();
+ for( final Entry paramEntry : formParams.entrySet() ) {
+ formValues.add(new BasicNameValuePair(paramEntry.getKey(), parameterToString(paramEntry.getValue())));
+ }
+ return new UrlEncodedFormEntity(formValues, contentType.getCharset());
+ } else {
+ // Handle files with unknown content type
+ if( obj instanceof File file ) {
+ return new FileEntity(file, contentType);
+ } else if( obj instanceof byte[] byteArray ) {
+ return new ByteArrayEntity(byteArray, contentType);
+ }
+ throw new OpenApiRequestException("Serialization for content type '" + contentType + "' not supported");
+ }
+ }
+
+ /**
+ * Build full URL by concatenating base URL, the given sub path and query parameters.
+ *
+ * @param path
+ * The sub path
+ * @param queryParams
+ * The query parameters
+ * @param collectionQueryParams
+ * The collection query parameters
+ * @param urlQueryDeepObject
+ * URL query string of the deep object parameters
+ * @return The full URL
+ */
+ @Nonnull
+ private String buildUrl(
+ @Nonnull final String path,
+ @Nullable final List queryParams,
+ @Nullable final List collectionQueryParams,
+ @Nullable final String urlQueryDeepObject )
+ {
+ final StringBuilder url = new StringBuilder();
+ if( basePath.endsWith("/") && path.startsWith("/") ) {
+ url.append(basePath, 0, basePath.length() - 1);
+ } else {
+ url.append(basePath);
+ }
+ url.append(path);
+
+ if( queryParams != null && !queryParams.isEmpty() ) {
+ // support (constant) query string in `path`, e.g. "/posts?draft=1"
+ String prefix = path.contains("?") ? "&" : "?";
+ for( final Pair param : queryParams ) {
+ if( prefix != null ) {
+ url.append(prefix);
+ prefix = null;
+ } else {
+ url.append("&");
+ }
+ final String value = parameterToString(param.getValue());
+ // query parameter value already escaped as part of parameterToPair
+ url.append(escapeString(param.getName())).append("=").append(value);
+ }
+ }
+
+ if( collectionQueryParams != null && !collectionQueryParams.isEmpty() ) {
+ String prefix = url.toString().contains("?") ? "&" : "?";
+ for( final Pair param : collectionQueryParams ) {
+ if( prefix != null ) {
+ url.append(prefix);
+ prefix = null;
+ } else {
+ url.append("&");
+ }
+ final String value = parameterToString(param.getValue());
+ // collection query parameter value already escaped as part of parameterToPairs
+ url.append(escapeString(param.getName())).append("=").append(value);
+ }
+ }
+
+ if( urlQueryDeepObject != null && !urlQueryDeepObject.isEmpty() ) {
+ url.append(url.toString().contains("?") ? "&" : "?");
+ url.append(urlQueryDeepObject);
+ }
+
+ return url.toString();
+ }
+
+ private static boolean isBodyAllowed( @Nonnull final Method method )
+ {
+ return BODY_METHODS.contains(method);
+ }
+
+ /**
+ * Invoke API by sending HTTP request with the given options.
+ *
+ * @param
+ * Type
+ * @param path
+ * The sub-path of the HTTP URL
+ * @param method
+ * The request method, one of "GET", "POST", "PUT", and "DELETE"
+ * @param queryParams
+ * The query parameters
+ * @param collectionQueryParams
+ * The collection query parameters
+ * @param urlQueryDeepObject
+ * A URL query string for deep object parameters
+ * @param body
+ * The request body object - if it is not binary, otherwise null
+ * @param headerParams
+ * The header parameters
+ * @param formParams
+ * The form parameters
+ * @param accept
+ * The request's Accept header
+ * @param contentType
+ * The request's Content-Type header
+ * @param returnType
+ * Return type
+ * @return The response body in type of string
+ * @throws OpenApiRequestException
+ * API exception
+ */
+ @Beta
+ @Nullable
+ public T invokeAPI(
+ @Nonnull final String path,
+ @Nonnull final String method,
+ @Nullable final List queryParams,
+ @Nullable final List collectionQueryParams,
+ @Nullable final String urlQueryDeepObject,
+ @Nullable final Object body,
+ @Nonnull final Map headerParams,
+ @Nonnull final Map formParams,
+ @Nullable final String accept,
+ @Nonnull final String contentType,
+ @Nonnull final TypeReference returnType )
+ throws OpenApiRequestException
+ {
+ if( body != null && !formParams.isEmpty() ) {
+ throw new OpenApiRequestException("Cannot have body and form params");
+ }
+
+ final String url = buildUrl(path, queryParams, collectionQueryParams, urlQueryDeepObject);
+
+ final ClassicRequestBuilder builder = ClassicRequestBuilder.create(method);
+ builder.setUri(url);
+
+ if( accept != null ) {
+ builder.addHeader("Accept", accept);
+ }
+ for( final Entry keyValue : headerParams.entrySet() ) {
+ builder.addHeader(keyValue.getKey(), keyValue.getValue());
+ }
+
+ final HttpClientContext context = HttpClientContext.create();
+
+ final ContentType contentTypeObj = getContentType(contentType);
+ if( body != null || !formParams.isEmpty() ) {
+ if( isBodyAllowed(Method.valueOf(method)) ) {
+ // Add entity if we have content and a valid method
+ builder.setEntity(serialize(body, formParams, contentTypeObj));
+ } else {
+ throw new OpenApiRequestException("method " + method + " does not support a request body");
+ }
+ } else {
+ // for empty body
+ builder.setEntity(new StringEntity("", contentTypeObj));
+ }
+
+ try {
+ final HttpClientResponseHandler responseHandler =
+ new DefaultApiResponseHandler<>(objectMapper, tempFolderPath, returnType);
+ return httpClient.execute(builder.build(), context, responseHandler);
+ }
+ catch( IOException e ) {
+ throw new OpenApiRequestException(e);
+ }
+ }
+}
diff --git a/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/BaseApi.java b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/BaseApi.java
new file mode 100644
index 000000000..c189867e6
--- /dev/null
+++ b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/BaseApi.java
@@ -0,0 +1,58 @@
+/*
+ * Prompt Registry API
+ * Prompt Storage service for Design time & Runtime prompt templates.
+ *
+ * The version of the OpenAPI document: 0.0.1
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.services.openapi.apache;
+
+import javax.annotation.Nonnull;
+
+import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
+
+/**
+ * Base class for generated API classes, providing common functionality for API client management.
+ */
+public abstract class BaseApi
+{
+ /**
+ * The API client used to execute HTTP requests.
+ */
+ protected final ApiClient apiClient;
+
+ /**
+ * Creates a new BaseApi instance with default configuration.
+ */
+ protected BaseApi()
+ {
+ this(ApiClient.create());
+ }
+
+ /**
+ * Creates a new BaseApi instance configured for the given destination.
+ *
+ * @param destination
+ * The destination to use for API requests
+ */
+ protected BaseApi( @Nonnull final Destination destination )
+ {
+ this(ApiClient.create(destination));
+ }
+
+ /**
+ * Creates a new BaseApi instance with the given API client.
+ *
+ * @param apiClient
+ * The API client to use for requests
+ */
+ protected BaseApi( @Nonnull final ApiClient apiClient )
+ {
+ this.apiClient = apiClient;
+ }
+}
diff --git a/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/DefaultApiResponseHandler.java b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/DefaultApiResponseHandler.java
new file mode 100644
index 000000000..20c96f58f
--- /dev/null
+++ b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/DefaultApiResponseHandler.java
@@ -0,0 +1,344 @@
+/*
+ * Prompt Registry API
+ * Prompt Storage service for Design time & Runtime prompt templates.
+ *
+ * The version of the OpenAPI document: 0.0.1
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.services.openapi.apache;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.ParseException;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.message.StatusLine;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException;
+
+/**
+ * Handles HTTP response processing for API client operations. This class encapsulates response deserialization, error
+ * handling, and file download functionality.
+ *
+ * @param
+ * The type of object to deserialize the response into
+ */
+class DefaultApiResponseHandler implements HttpClientResponseHandler
+{
+ private final ObjectMapper objectMapper;
+ private final String tempFolderPath;
+ private final TypeReference returnType;
+
+ /**
+ * Creates a new response handler with the specified configuration.
+ *
+ * @param objectMapper
+ * The Jackson ObjectMapper for JSON deserialization
+ * @param tempFolderPath
+ * The temporary folder path for file downloads (null for system default)
+ * @param returnType
+ * The type reference for response deserialization
+ */
+ DefaultApiResponseHandler(
+ @Nonnull final ObjectMapper objectMapper,
+ @Nullable final String tempFolderPath,
+ @Nonnull final TypeReference returnType )
+ {
+ this.objectMapper = objectMapper;
+ this.tempFolderPath = tempFolderPath;
+ this.returnType = returnType;
+ }
+
+ @Nullable
+ @Override
+ public T handleResponse( @Nonnull final ClassicHttpResponse response )
+ throws IOException
+ {
+ try {
+ return processResponse(response);
+ }
+ catch( ParseException | OpenApiRequestException e ) {
+ // Wrap exceptions as IOException since handler can only throw IOException
+ throw new IOException("Failed to process response: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Processes the HTTP response and returns the deserialized result.
+ *
+ * @param response
+ * The HTTP response to process
+ * @return The deserialized response object
+ * @throws OpenApiRequestException
+ * if the response indicates an error
+ * @throws IOException
+ * if an I/O error occurs
+ * @throws ParseException
+ * if response parsing fails
+ */
+ @SuppressWarnings( "unchecked" )
+ @Nullable
+ private T processResponse( @Nonnull final ClassicHttpResponse response )
+ throws OpenApiRequestException,
+ IOException,
+ ParseException
+ {
+ final int statusCode = response.getCode();
+ if( statusCode == HttpStatus.SC_NO_CONTENT ) {
+ if( returnType.getType().equals(OpenApiResponse.class) ) {
+ return (T) new OpenApiResponse(statusCode, transformResponseHeaders(response.getHeaders()));
+ }
+ return null;
+ }
+
+ if( isSuccessfulStatus(statusCode) ) {
+ return deserialize(response);
+ } else {
+ final Map> responseHeaders = transformResponseHeaders(response.getHeaders());
+ final String message = new StatusLine(response).toString();
+ throw new OpenApiRequestException(message)
+ .statusCode(statusCode)
+ .responseHeaders(responseHeaders)
+ .responseBody(EntityUtils.toString(response.getEntity()));
+ }
+ }
+
+ /**
+ * Deserializes the response body to a Java object according to the Content-Type.
+ *
+ * @param response
+ * The HTTP response to deserialize
+ * @return The deserialized object
+ * @throws OpenApiRequestException
+ * if deserialization fails
+ * @throws IOException
+ * if an I/O error occurs
+ * @throws ParseException
+ * if response parsing fails
+ */
+ @Nullable
+ @SuppressWarnings( "unchecked" )
+ private T deserialize( @Nonnull final ClassicHttpResponse response )
+ throws OpenApiRequestException,
+ IOException,
+ ParseException
+ {
+
+ final Type valueRawType = returnType.getType();
+ if( valueRawType.equals(OpenApiResponse.class) ) {
+ final int statusCode = response.getCode();
+ final Map> headers = transformResponseHeaders(response.getHeaders());
+ return (T) new OpenApiResponse(statusCode, headers);
+ }
+
+ final HttpEntity entity = response.getEntity();
+ if( valueRawType.equals(byte[].class) ) {
+ return (T) EntityUtils.toByteArray(entity);
+ } else if( valueRawType.equals(File.class) ) {
+ return (T) downloadFileFromResponse(response);
+ }
+ final String mimeType = getResponseMimeType(response);
+ if( mimeType == null || isJsonMime(mimeType) ) {
+ // Assume json if no mime type
+ // convert input stream to string
+ final String content = EntityUtils.toString(entity);
+
+ if( "".equals(content) ) { // returns null for empty body
+ return null;
+ }
+
+ return objectMapper.readValue(content, returnType);
+ } else if( mimeType.toLowerCase().startsWith("text/") ) {
+ // convert input stream to string
+ return (T) EntityUtils.toString(entity);
+ } else {
+ final Map> responseHeaders = transformResponseHeaders(response.getHeaders());
+ throw new OpenApiRequestException(
+ "Deserialization for content type '" + mimeType + "' not supported for type '" + returnType + "'")
+ .statusCode(response.getCode())
+ .responseHeaders(responseHeaders)
+ .responseBody(EntityUtils.toString(entity));
+ }
+ }
+
+ /**
+ * Downloads a file from the HTTP response.
+ *
+ * @param response
+ * The HTTP response containing the file
+ * @return The downloaded file
+ * @throws IOException
+ * if an I/O error occurs during download
+ */
+ @Nonnull
+ private File downloadFileFromResponse( @Nonnull final ClassicHttpResponse response )
+ throws IOException
+ {
+ final Header contentDispositionHeader = response.getFirstHeader("Content-Disposition");
+ final String contentDisposition = contentDispositionHeader == null ? null : contentDispositionHeader.getValue();
+ final File file = prepareDownloadFile(contentDisposition);
+ Files.copy(response.getEntity().getContent(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ return file;
+ }
+
+ /**
+ * Prepares a temporary file for downloading response content.
+ *
+ * @param contentDisposition
+ * The Content-Disposition header value (may be null)
+ * @return A temporary file for storing the download
+ * @throws IOException
+ * if the temporary file cannot be created
+ */
+ @Nonnull
+ private File prepareDownloadFile( @Nullable final String contentDisposition )
+ throws IOException
+ {
+ String filename = null;
+ if( contentDisposition != null && !contentDisposition.isEmpty() ) {
+ // Get filename from the Content-Disposition header.
+ final Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?");
+ final Matcher matcher = pattern.matcher(contentDisposition);
+ if( matcher.find() ) {
+ filename = matcher.group(1);
+ }
+ }
+
+ String prefix;
+ String suffix = null;
+ if( filename == null ) {
+ prefix = "download-";
+ suffix = "";
+ } else {
+ final int pos = filename.lastIndexOf('.');
+ if( pos == -1 ) {
+ prefix = filename + "-";
+ } else {
+ prefix = filename.substring(0, pos) + "-";
+ suffix = filename.substring(pos);
+ }
+ // Files.createTempFile requires the prefix to be at least three characters long
+ if( prefix.length() < 3 ) {
+ prefix = "download-";
+ }
+ }
+
+ if( tempFolderPath == null ) {
+ return Files.createTempFile(prefix, suffix).toFile();
+ }
+ return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile();
+ }
+
+ /**
+ * Gets the MIME type from the response Content-Type header.
+ *
+ * @param response
+ * The HTTP response
+ * @return The MIME type, or null if not present
+ * @throws OpenApiRequestException
+ * if the content type cannot be parsed
+ */
+ @Nullable
+ private String getResponseMimeType( @Nonnull final HttpResponse response )
+ throws OpenApiRequestException
+ {
+ final Header contentTypeHeader = response.getFirstHeader("Content-Type");
+ if( contentTypeHeader != null ) {
+ return parseContentType(contentTypeHeader.getValue()).getMimeType();
+ }
+ return null;
+ }
+
+ /**
+ * Parses a Content-Type header value into a ContentType object.
+ *
+ * @param headerValue
+ * The Content-Type header value
+ * @return The parsed ContentType object
+ * @throws OpenApiRequestException
+ * if the content type cannot be parsed
+ */
+ @Nonnull
+ private static ContentType parseContentType( @Nonnull final String headerValue )
+ throws OpenApiRequestException
+ {
+ try {
+ return ContentType.parse(headerValue);
+ }
+ catch( UnsupportedCharsetException e ) {
+ throw new OpenApiRequestException("Could not parse content type " + headerValue, e);
+ }
+ }
+
+ /**
+ * Transforms response headers into map.
+ *
+ * @param headers
+ * HTTP headers
+ * @return a map of string array
+ */
+ @Nonnull
+ private static Map> transformResponseHeaders( @Nonnull final Header[] headers )
+ {
+ final Map> headersMap = new HashMap<>();
+ for( final Header header : headers ) {
+ List valuesList = headersMap.get(header.getName());
+ if( valuesList != null ) {
+ valuesList.add(header.getValue());
+ } else {
+ valuesList = new ArrayList<>();
+ valuesList.add(header.getValue());
+ headersMap.put(header.getName(), valuesList);
+ }
+ }
+ return headersMap;
+ }
+
+ private static boolean isSuccessfulStatus( final int statusCode )
+ {
+ return statusCode >= 200 && statusCode < 300;
+ }
+
+ /**
+ * Check if the given MIME is a JSON MIME. JSON MIME examples: application/json application/json; charset=UTF8
+ * APPLICATION/JSON application/vnd.company+json
+ *
+ * @param mime
+ * MIME
+ * @return True if MIME type is boolean
+ */
+ static boolean isJsonMime( @Nullable final String mime )
+ {
+ final String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
+ return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
+ }
+
+}
diff --git a/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/OpenApiResponse.java b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/OpenApiResponse.java
new file mode 100644
index 000000000..f4cc3c35d
--- /dev/null
+++ b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/OpenApiResponse.java
@@ -0,0 +1,30 @@
+package com.sap.cloud.sdk.services.openapi.apache;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import lombok.Getter;
+
+/**
+ * Response object for Apache HTTP client OpenAPI calls containing status code and headers
+ */
+@Getter
+public class OpenApiResponse
+{
+
+ private final int statusCode;
+
+ @Nonnull
+ private final Map> headers;
+
+ /**
+ * Create a new OpenApiResponse with status code and headers.
+ */
+ OpenApiResponse( final int statusCode, @Nonnull final Map> headers )
+ {
+ this.statusCode = statusCode;
+ this.headers = Map.copyOf(headers);
+ }
+}
diff --git a/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/Pair.java b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/Pair.java
new file mode 100644
index 000000000..c0acc45b3
--- /dev/null
+++ b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/apache/Pair.java
@@ -0,0 +1,29 @@
+/*
+ * Prompt Registry API
+ * Prompt Storage service for Design time & Runtime prompt templates.
+ *
+ * The version of the OpenAPI document: 0.0.1
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.sap.cloud.sdk.services.openapi.apache;
+
+import javax.annotation.Nonnull;
+
+import lombok.Value;
+
+/**
+ * Represents a name-value pair used for query parameters and form data.
+ */
+@Value
+public class Pair
+{
+ @Nonnull
+ String name;
+ @Nonnull
+ String value;
+}
diff --git a/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/core/OpenApiRequestException.java b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/core/OpenApiRequestException.java
index c22e6a505..6237641e1 100644
--- a/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/core/OpenApiRequestException.java
+++ b/datamodel/openapi/openapi-core/src/main/java/com/sap/cloud/sdk/services/openapi/core/OpenApiRequestException.java
@@ -1,14 +1,32 @@
package com.sap.cloud.sdk.services.openapi.core;
+import java.util.List;
+import java.util.Map;
+
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
/**
* Thrown if an error occurs during the invocation of a OpenAPI service.
*/
+@Accessors( fluent = true )
+@Getter
+@Setter
public class OpenApiRequestException extends RuntimeException
{
private static final long serialVersionUID = -8248392392632616674L;
+ @Nullable
+ private Integer statusCode;
+ @Nullable
+ private transient Map> responseHeaders;
+ @Nullable
+ private transient String responseBody;
+
/**
* Thrown if an error occurs during the invocation of a OpenAPI service.
*
diff --git a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApacheApiClientViaConstructorTest.java b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApacheApiClientViaConstructorTest.java
new file mode 100644
index 000000000..ae2912fd0
--- /dev/null
+++ b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApacheApiClientViaConstructorTest.java
@@ -0,0 +1,190 @@
+package com.sap.cloud.sdk.services.openapi.apiclient;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
+import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5FactoryBuilder;
+import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5FactoryBuilder.TlsUpgrade;
+import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination;
+import com.sap.cloud.sdk.services.openapi.apache.ApiClient;
+import com.sap.cloud.sdk.services.openapi.apache.BaseApi;
+import com.sap.cloud.sdk.services.openapi.apache.Pair;
+
+import jdk.jfr.Description;
+
+@WireMockTest
+class ApacheApiClientViaConstructorTest
+{
+
+ private static final String RELATIVE_PATH = "/apiEndpoint";
+ private static final String SUCCESS_BODY = "success";
+
+ @Test
+ @Description( "Verify ApiClient's ObjectMapper ignores getters to avoid duplicate JSON properties." )
+ void testApiClientDefaultObjectMapperIgnoresGetters( WireMockRuntimeInfo wm )
+ {
+ final String baseUrl = wm.getHttpBaseUrl();
+ final String requestBody = "{\"Return\":\"Hello, World!\"}";
+ WireMock
+ .stubFor(
+ post(urlEqualTo(RELATIVE_PATH))
+ .withRequestBody(equalTo(requestBody))
+ .willReturn(ok().withHeader("Content-Type", "text/plain").withBody(SUCCESS_BODY)));
+
+ final MyDto myTestDto = new MyDto();
+ myTestDto.setReturn("Hello, World!");
+
+ final var apiClient = ApiClient.create().withBasePath(baseUrl);
+ final var testApi = new MyTestApacheOpenApiService(apiClient, baseUrl);
+ testApi.invokeApiEndpoint(myTestDto);
+
+ WireMock.verify(1, postRequestedFor(urlEqualTo(RELATIVE_PATH)).withRequestBody(equalTo(requestBody)));
+ }
+
+ @Test
+ void testApiClientWithQueryParams( WireMockRuntimeInfo wm )
+ {
+ final String baseUrl = wm.getHttpBaseUrl();
+ final String filterQueryValue = "emails.value eq \"my.email@test.com\"";
+ final String filterQueryParam = "filter";
+
+ final List queryParams = ApiClient.parameterToPair(filterQueryParam, filterQueryValue);
+
+ WireMock
+ .stubFor(
+ get(urlPathEqualTo(RELATIVE_PATH))
+ .withQueryParam(filterQueryParam, equalTo(filterQueryValue))
+ .willReturn(ok().withHeader("Content-Type", "text/plain").withBody(SUCCESS_BODY)));
+
+ final var apiClient = ApiClient.create().withBasePath(baseUrl);
+ final var testApi = new MyTestApacheOpenApiService(apiClient, baseUrl);
+ testApi.invokeApiEndpoint("GET", null, queryParams);
+
+ WireMock
+ .verify(
+ 1,
+ getRequestedFor(urlPathEqualTo(RELATIVE_PATH))
+ .withQueryParam(filterQueryParam, equalTo(filterQueryValue)));
+ }
+
+ @Test
+ @Description( "Verify that the TlsUpgrade configuration is transmitted in HTTP requests." )
+ void testHttpRequestConfigIsTransmitted( WireMockRuntimeInfo wm )
+ {
+ httpRequest(TlsUpgrade.DISABLED, wm.getHttpBaseUrl());
+ verify(getRequestedFor(anyUrl()).withoutHeader("Upgrade"));
+
+ httpRequest(TlsUpgrade.AUTOMATIC, wm.getHttpBaseUrl());
+ verify(getRequestedFor(anyUrl()).withoutHeader("Upgrade"));
+ }
+
+ private static void httpRequest( TlsUpgrade toggle, String url )
+ {
+ final var httpClientFactory = new ApacheHttpClient5FactoryBuilder().tlsUpgrade(toggle).build();
+ final var httpClient = httpClientFactory.createHttpClient(DefaultHttpDestination.builder(url).build());
+ var apiClient = ApiClient.fromHttpClient((CloseableHttpClient) httpClient);
+ apiClient = apiClient.withBasePath(url);
+
+ stubFor(get(anyUrl()).willReturn(ok().withHeader("Content-Type", "text/plain").withBody(SUCCESS_BODY)));
+
+ assertThat(
+ apiClient
+ .invokeAPI(
+ RELATIVE_PATH,
+ "GET",
+ List.of(),
+ List.of(),
+ "",
+ null,
+ Map.of(),
+ Map.of(),
+ "text/plain",
+ "text/plain",
+ new TypeReference()
+ {
+ }))
+ .isEqualTo(SUCCESS_BODY);
+ }
+
+ private static class MyDto
+ {
+ @JsonProperty( "Return" )
+ private String _return;
+
+ public String getReturn()
+ {
+ return _return;
+ }
+
+ public void setReturn( String _return )
+ {
+ this._return = _return;
+ }
+ }
+
+ private static class MyTestApacheOpenApiService extends BaseApi
+ {
+ private final String expectedBasePath;
+
+ MyTestApacheOpenApiService( ApiClient apiClient, String expectedBasePath )
+ {
+ super(apiClient);
+ this.expectedBasePath = expectedBasePath;
+ }
+
+ void invokeApiEndpoint( @Nullable Object body )
+ {
+ invokeApiEndpoint("POST", body, List.of());
+ }
+
+ //make it apache reliant
+ void invokeApiEndpoint( String method, Object body, List queryParams )
+ {
+ assertThat(apiClient.getBasePath()).isEqualTo(expectedBasePath);
+
+ final TypeReference returnType = new TypeReference()
+ {
+ };
+
+ final String s =
+ apiClient
+ .invokeAPI(
+ RELATIVE_PATH,
+ method,
+ queryParams,
+ List.of(),
+ "",
+ body,
+ Map.of(),
+ Map.of(),
+ "application/json",
+ "application/json",
+ returnType);
+
+ assertThat(s).isEqualTo(SUCCESS_BODY);
+ }
+ }
+}
diff --git a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientExtensionsDeserializationTest.java b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientExtensionsDeserializationTest.java
index 599ce214c..e4e27e010 100644
--- a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientExtensionsDeserializationTest.java
+++ b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientExtensionsDeserializationTest.java
@@ -5,12 +5,14 @@
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.StringJoiner;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -31,17 +33,57 @@
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
+import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+import com.sap.cloud.sdk.services.openapi.apache.BaseApi;
+import com.sap.cloud.sdk.services.openapi.apache.Pair;
import com.sap.cloud.sdk.services.openapi.core.AbstractOpenApiService;
+import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException;
+import jdk.jfr.Description;
import lombok.Getter;
import lombok.Setter;
+@WireMockTest
class ApiClientExtensionsDeserializationTest
{
@Nonnull
private static final String BASE_PATH = "http://localhost:8080";
@Nonnull
private static final String RELATIVE_PATH = "/outer";
+ @Nonnull
+ private static final String RESPONSE = """
+ {
+ "message": "Hello from the outer level.",
+ "code": 1337,
+ "inner": {
+ "message": "Hello from the inner level.",
+ "code": 7331,
+ "innerComplexExtension": {
+ "innerString": "inner",
+ "innerInteger": 24
+ },
+ "innerListExtension": [
+ "oof",
+ "rab",
+ "zab"
+ ],
+ "innerPrimitiveExtension": "additionalInnerValue"
+ },
+ "outerComplexExtension": {
+ "outerString": "outer",
+ "outerInteger": 42
+ },
+ "outerListExtension": [
+ "foo",
+ "bar",
+ "baz"
+ ],
+ "outerPrimitiveExtension": "additionalOuterValue"
+ }
+ """;
@Test
void testDeserializeResponseWithNestedExtensions()
@@ -53,42 +95,33 @@ void testDeserializeResponseWithNestedExtensions()
server
.expect(ExpectedCount.once(), requestTo(BASE_PATH + RELATIVE_PATH))
.andExpect(method(HttpMethod.GET))
- .andRespond(MockRestResponseCreators.withSuccess("""
- {
- "message": "Hello from the outer level.",
- "code": 1337,
- "inner": {
- "message": "Hello from the inner level.",
- "code": 7331,
- "innerComplexExtension": {
- "innerString": "inner",
- "innerInteger": 24
- },
- "innerListExtension": [
- "oof",
- "rab",
- "zab"
- ],
- "innerPrimitiveExtension": "additionalInnerValue"
- },
- "outerComplexExtension": {
- "outerString": "outer",
- "outerInteger": 42
- },
- "outerListExtension": [
- "foo",
- "bar",
- "baz"
- ],
- "outerPrimitiveExtension": "additionalOuterValue"
- }
- """, MediaType.APPLICATION_JSON));
-
- final TestApi api = new TestApi(apiClient);
+ .andRespond(MockRestResponseCreators.withSuccess(RESPONSE, MediaType.APPLICATION_JSON));
+
+ final TestSpringApi api = new TestSpringApi(apiClient);
final Outer result = api.getOuter();
server.verify();
+ assertResult(result);
+ }
+
+ @Test
+ @Description( "Tests deserialization of responses with nested extensions using the Apache HTTP client based ApiClient." )
+ void testDeserializeResponseWithNestedExtensionsApache( WireMockRuntimeInfo wmInfo )
+ {
+
+ WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(RELATIVE_PATH)).willReturn(WireMock.okJson(RESPONSE)));
+ final var apiClient =
+ com.sap.cloud.sdk.services.openapi.apache.ApiClient.create().withBasePath(wmInfo.getHttpBaseUrl());
+
+ final TestApacheApi api = new TestApacheApi(apiClient);
+ final Outer result = api.getOuter();
+
+ WireMock.verify(1, WireMock.getRequestedFor(WireMock.urlEqualTo(RELATIVE_PATH)));
+ assertResult(result);
+ }
+ private static void assertResult( Outer result )
+ {
assertThat(result.getMessage()).isEqualTo("Hello from the outer level.");
assertThat(result.getCode()).isEqualTo(1337);
assertThat(result.getCustomFieldNames())
@@ -128,9 +161,61 @@ void testDeserializeResponseWithNestedExtensions()
});
}
- private static class TestApi extends AbstractOpenApiService
+ private static class TestApacheApi extends BaseApi
+ {
+ public TestApacheApi( final com.sap.cloud.sdk.services.openapi.apache.ApiClient apiClient )
+ {
+ super(apiClient);
+ }
+
+ @Nonnull
+ public Outer getOuter()
+ throws OpenApiRequestException
+ {
+ final Object localVarPostBody = null;
+
+ // create path and map variables
+ final String localVarPath = RELATIVE_PATH;
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ String localVarQueryParameterBaseName;
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/json" };
+ final String localVarAccept =
+ com.sap.cloud.sdk.services.openapi.apache.ApiClient.selectHeaderAccept(localVarAccepts);
+
+ final String[] localVarContentTypes = {
+
+ };
+ final String localVarContentType =
+ com.sap.cloud.sdk.services.openapi.apache.ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference localVarReturnType = new TypeReference()
+ {
+ };
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "GET",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ localVarPostBody,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+ }
+
+ private static class TestSpringApi extends AbstractOpenApiService
{
- public TestApi( final ApiClient apiClient )
+ public TestSpringApi( final ApiClient apiClient )
{
super(apiClient);
}
diff --git a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientFromDestinationTest.java b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientFromDestinationTest.java
index faa905633..8135e9c6e 100644
--- a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientFromDestinationTest.java
+++ b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientFromDestinationTest.java
@@ -11,6 +11,7 @@
import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination;
import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;
+import com.sap.cloud.sdk.services.openapi.apache.BaseApi;
import com.sap.cloud.sdk.services.openapi.core.AbstractOpenApiService;
class ApiClientFromDestinationTest
@@ -24,9 +25,12 @@ void testServiceInvocation()
{
final HttpDestination testDestination = DefaultHttpDestination.builder(SERVER.baseUrl()).build();
- final MyTestAbstractOpenApiService service = new MyTestAbstractOpenApiService(testDestination);
+ final MyTestAbstractOpenApiService springService = new MyTestAbstractOpenApiService(testDestination);
+ final MyTestAbstractApacheOpenApiService apacheService =
+ new MyTestAbstractApacheOpenApiService(testDestination);
- service.foo();
+ springService.foo();
+ apacheService.foo();
}
@Test
@@ -34,12 +38,16 @@ void testExceptionIsThrown()
{
final HttpDestination testDestination = DefaultHttpDestination.builder(SERVER.baseUrl()).build();
- final MyExceptionThrowingServiceAbstract service = new MyExceptionThrowingServiceAbstract(testDestination);
+ final MyExceptionThrowingSpringServiceAbstract springService =
+ new MyExceptionThrowingSpringServiceAbstract(testDestination);
+ final MyExceptionThrowingApacheServiceAbstract apacheService =
+ new MyExceptionThrowingApacheServiceAbstract(testDestination);
- assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(service::foo);
+ assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(springService::foo);
+ assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(apacheService::foo);
}
- private class MyTestAbstractOpenApiService extends AbstractOpenApiService
+ private static class MyTestAbstractOpenApiService extends AbstractOpenApiService
{
public MyTestAbstractOpenApiService( final Destination destination )
{
@@ -52,9 +60,36 @@ void foo()
}
}
- private static class MyExceptionThrowingServiceAbstract extends AbstractOpenApiService
+ private static class MyExceptionThrowingSpringServiceAbstract extends AbstractOpenApiService
{
- public MyExceptionThrowingServiceAbstract( final Destination destination )
+ public MyExceptionThrowingSpringServiceAbstract( final Destination destination )
+ {
+ super(destination);
+ }
+
+ void foo()
+ throws IllegalAccessException
+ {
+ throw new IllegalAccessException("Something went horribly wrong");
+ }
+ }
+
+ private static class MyTestAbstractApacheOpenApiService extends BaseApi
+ {
+ public MyTestAbstractApacheOpenApiService( final Destination destination )
+ {
+ super(destination);
+ }
+
+ void foo()
+ {
+ assertThat(apiClient.getBasePath()).isEqualTo(SERVER.baseUrl());
+ }
+ }
+
+ private static class MyExceptionThrowingApacheServiceAbstract extends BaseApi
+ {
+ public MyExceptionThrowingApacheServiceAbstract( final Destination destination )
{
super(destination);
}
diff --git a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientViaConstructorTest.java b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/SpringApiClientViaConstructorTest.java
similarity index 99%
rename from datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientViaConstructorTest.java
rename to datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/SpringApiClientViaConstructorTest.java
index b7cda71d3..e0a169533 100644
--- a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/ApiClientViaConstructorTest.java
+++ b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/apiclient/SpringApiClientViaConstructorTest.java
@@ -38,7 +38,7 @@
import com.sap.cloud.sdk.services.openapi.core.AbstractOpenApiService;
@WireMockTest
-class ApiClientViaConstructorTest
+class SpringApiClientViaConstructorTest
{
private static final String RELATIVE_PATH = "/apiEndpoint";
private static final String SUCCESS_BODY = "success";
diff --git a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericparameter/GenericParameterTest.java b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericparameter/GenericParameterTest.java
index f50df180f..035effa39 100644
--- a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericparameter/GenericParameterTest.java
+++ b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericparameter/GenericParameterTest.java
@@ -7,7 +7,11 @@
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -25,6 +29,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRawValue;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.client.WireMock;
@@ -32,6 +37,9 @@
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination;
import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
+import com.sap.cloud.sdk.services.openapi.apache.ApiClient;
+import com.sap.cloud.sdk.services.openapi.apache.BaseApi;
+import com.sap.cloud.sdk.services.openapi.apache.Pair;
import com.sap.cloud.sdk.services.openapi.core.AbstractOpenApiService;
import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException;
@@ -41,23 +49,24 @@
@WireMockTest
class GenericParameterTest
{
+ final static String EXPECTED_BODY = """
+ {\
+ "id":"foo",\
+ "fieldPopulatedAsStringWithAnnotation":{"foo": "bar"},\
+ "fieldPopulatedAsStringWithoutAnnotation":"{\\"foo\\": \\"bar\\"}",\
+ "fieldPopulatedAsJacksonJsonNode":{"foo":"bar"}\
+ }\
+ """;
+
@Test
void testInvocationWithGenericParameter( @Nonnull final WireMockRuntimeInfo wm )
throws JsonProcessingException
{
- final String expectedBody = """
- {\
- "id":"foo",\
- "fieldPopulatedAsStringWithAnnotation":{"foo": "bar"},\
- "fieldPopulatedAsStringWithoutAnnotation":"{\\"foo\\": \\"bar\\"}",\
- "fieldPopulatedAsJacksonJsonNode":{"foo":"bar"}\
- }\
- """;
WireMock
.stubFor(
post(urlEqualTo("/api"))
- .withRequestBody(equalTo(expectedBody))
+ .withRequestBody(equalTo(EXPECTED_BODY))
.willReturn(aResponse().withStatus(HttpStatus.SC_OK)));
final DefaultHttpDestination httpDestination = DefaultHttpDestination.builder(wm.getHttpBaseUrl()).build();
@@ -67,16 +76,18 @@ void testInvocationWithGenericParameter( @Nonnull final WireMockRuntimeInfo wm )
//this is how you pass a JSON representation into a parameter of type Object
final JsonNode jacksonJsonNode = new ObjectMapper().readTree(jsonString);
- new TestApi(httpDestination)
- .testMethod(
- TestModelPOST
- .builder()
- .id("foo")
- .fieldPopulatedAsStringWithAnnotation(jsonString)
- .fieldPopulatedAsStringWithoutAnnotation(jsonString)
- .fieldPopulatedAsJacksonJsonNode(jacksonJsonNode)
- .build());
- verify(postRequestedFor(urlEqualTo("/api")).withRequestBody(equalTo(expectedBody)));
+ final TestModelPOST testModelPOST =
+ TestModelPOST
+ .builder()
+ .id("foo")
+ .fieldPopulatedAsStringWithAnnotation(jsonString)
+ .fieldPopulatedAsStringWithoutAnnotation(jsonString)
+ .fieldPopulatedAsJacksonJsonNode(jacksonJsonNode)
+ .build();
+
+ new TestSpringApi(httpDestination).testMethod(testModelPOST);
+ new TestApacheApi(httpDestination).testMethod(testModelPOST);
+ verify(2, postRequestedFor(urlEqualTo("/api")).withRequestBody(equalTo(EXPECTED_BODY)));
}
@Value
@@ -97,9 +108,64 @@ private static class TestModelPOST
Object fieldPopulatedAsJacksonJsonNode;
}
- private static class TestApi extends AbstractOpenApiService
+ private static class TestApacheApi extends BaseApi
+ {
+ public TestApacheApi( @Nonnull final Destination destination )
+ {
+ super(destination);
+ }
+
+ @Nullable
+ public TestModel testMethod( @Nonnull final TestModelPOST body )
+ throws OpenApiRequestException
+ {
+ final Object localVarPostBody = body;
+
+ // verify the required parameter 'pet' is set
+ if( body == null ) {
+ throw new OpenApiRequestException("Missing the required parameter 'pet' when calling addPet")
+ .statusCode(400);
+ }
+
+ // create path and map variables
+ final String localVarPath = "/api";
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ String localVarQueryParameterBaseName;
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map localVarFormParams = new HashMap();
+
+ final String[] localVarAccepts = { "application/json" };
+ final String localVarAccept = ApiClient.selectHeaderAccept(localVarAccepts);
+
+ final String[] localVarContentTypes = { "application/json" };
+ final String localVarContentType = ApiClient.selectHeaderContentType(localVarContentTypes);
+
+ final TypeReference localVarReturnType = new TypeReference()
+ {
+ };
+ return apiClient
+ .invokeAPI(
+ localVarPath,
+ "POST",
+ localVarQueryParams,
+ localVarCollectionQueryParams,
+ localVarQueryStringJoiner.toString(),
+ localVarPostBody,
+ localVarHeaderParams,
+ localVarFormParams,
+ localVarAccept,
+ localVarContentType,
+ localVarReturnType);
+ }
+
+ }
+
+ private static class TestSpringApi extends AbstractOpenApiService
{
- public TestApi( @Nonnull final Destination httpDestination )
+ public TestSpringApi( @Nonnull final Destination httpDestination )
{
super(httpDestination);
}
diff --git a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericreturntype/GenericReturnTypeTest.java b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericreturntype/GenericReturnTypeTest.java
index 0a7b3f87d..4d909438b 100644
--- a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericreturntype/GenericReturnTypeTest.java
+++ b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericreturntype/GenericReturnTypeTest.java
@@ -8,10 +8,15 @@
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Stream;
import javax.annotation.Nonnull;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
@@ -42,16 +47,31 @@
@WireMockTest
class GenericReturnTypeTest
{
- @Test
- void testGenericAccessToNonNestedJsonObject( @Nonnull final WireMockRuntimeInfo wm )
+
+ HttpDestination httpDestination;
+
+ @BeforeEach
+ void setUp( @Nonnull final WireMockRuntimeInfo wm )
{
- final String responseBody = "{\"firstname\":\"John\",\"lastname\":\"Doe\"}";
+ httpDestination = DefaultHttpDestination.builder(wm.getHttpBaseUrl()).build();
+ }
- final HttpDestination httpDestination = DefaultHttpDestination.builder(wm.getHttpBaseUrl()).build();
+ static Stream provideContext()
+ {
+ return Stream
+ .of(
+ Arguments.of((Function) ( des ) -> new TestSpringApi(des).testMethod()),
+ Arguments.of((Function) ( des ) -> new TestApacheApi(des).testMethod()));
+ }
+ @MethodSource( "provideContext" )
+ @ParameterizedTest
+ void testGenericAccessToNonNestedJsonObject( @Nonnull final Function contextFactory )
+ {
+ final String responseBody = "{\"firstname\":\"John\",\"lastname\":\"Doe\"}";
stubFor(get(urlEqualTo("/endpoint")).willReturn(okJson(responseBody)));
- final Object context = new TestApi(httpDestination).testMethod();
+ final Object context = contextFactory.apply(httpDestination);
@SuppressWarnings( "unchecked" )
final LinkedHashMap castedReturnObject = (LinkedHashMap) context;
@@ -60,16 +80,15 @@ void testGenericAccessToNonNestedJsonObject( @Nonnull final WireMockRuntimeInfo
assertThat(castedReturnObject.get("lastname")).isEqualTo("Doe");
}
- @Test
- void testGenericAccessToNestedJsonObject( @Nonnull final WireMockRuntimeInfo wm )
+ @MethodSource( "provideContext" )
+ @ParameterizedTest
+ void testGenericAccessToNestedJsonObject( @Nonnull final Function contextFactory )
{
final String responseBody = "{" + "\"foo\": \"bar\"," + "\"bar\": {" + "\"foobar\": \"barfoo\"" + "}" + "}";
- final HttpDestination httpDestination = DefaultHttpDestination.builder(wm.getHttpBaseUrl()).build();
-
stubFor(get(urlEqualTo("/endpoint")).willReturn(okJson(responseBody)));
- final Object context = new TestApi(httpDestination).testMethod();
+ final Object context = contextFactory.apply(httpDestination);
@SuppressWarnings( "unchecked" )
final LinkedHashMap castedReturnObject = (LinkedHashMap) context;
@@ -83,16 +102,15 @@ void testGenericAccessToNestedJsonObject( @Nonnull final WireMockRuntimeInfo wm
assertThat(castedNestedReturnObject.get("foobar")).isEqualTo("barfoo");
}
- @Test
- void testGenericAccessToArray( @Nonnull final WireMockRuntimeInfo wm )
+ @MethodSource( "provideContext" )
+ @ParameterizedTest
+ void testGenericAccessToArray( @Nonnull final Function contextFactory )
{
final String responseBody = "[\"foo\", \"bar\", \"foo\", \"bar\"]";
- final HttpDestination httpDestination = DefaultHttpDestination.builder(wm.getHttpBaseUrl()).build();
-
stubFor(get(urlEqualTo("/endpoint")).willReturn(okJson(responseBody)));
- final Object context = new TestApi(httpDestination).testMethod();
+ final Object context = contextFactory.apply(httpDestination);
@SuppressWarnings( "unchecked" )
final List castedReturnObject = (List) context;
diff --git a/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericreturntype/TestApacheApi.java b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericreturntype/TestApacheApi.java
new file mode 100644
index 000000000..6e3f10aca
--- /dev/null
+++ b/datamodel/openapi/openapi-core/src/test/java/com/sap/cloud/sdk/services/openapi/genericreturntype/TestApacheApi.java
@@ -0,0 +1,65 @@
+package com.sap.cloud.sdk.services.openapi.genericreturntype;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+
+import javax.annotation.Nonnull;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
+import com.sap.cloud.sdk.services.openapi.apache.BaseApi;
+import com.sap.cloud.sdk.services.openapi.apache.Pair;
+
+class TestApacheApi extends BaseApi
+{
+
+ TestApacheApi( @Nonnull final Destination destination )
+ {
+ super(destination);
+ }
+
+ Object testMethod()
+ {
+ final Object localVarPostBody = null;
+
+ // create path and map variables
+ final String localVarPath = "/endpoint";
+
+ final StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
+ String localVarQueryParameterBaseName;
+ final List localVarQueryParams = new ArrayList();
+ final List localVarCollectionQueryParams = new ArrayList();
+ final Map localVarHeaderParams = new HashMap();
+ final Map