Skip to content

Commit a0e510d

Browse files
authored
Merge branch 'main' into gzip
2 parents f4d2f7b + 7c47325 commit a0e510d

3 files changed

Lines changed: 55 additions & 2 deletions

File tree

datamodel/odata-v4/odata-v4-core/src/main/java/com/sap/cloud/sdk/datamodel/odatav4/adapter/ODataGenericConverter.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ final class ODataGenericConverter<JavaT> extends AbstractTypeConverter<JavaT, St
5353
new ODataGenericConverter<>(Duration.class, Duration::toString, Duration::parse);
5454

5555
private static final ODataGenericConverter<byte[]> BINARY =
56-
new ODataGenericConverter<>(byte[].class, Base64.getEncoder()::encodeToString, Base64.getDecoder()::decode);
56+
new ODataGenericConverter<>(
57+
byte[].class,
58+
Base64.getEncoder()::encodeToString,
59+
ODataGenericConverter::decodeBinary);
5760

5861
private static final ODataGenericConverter<String> STRING =
5962
new ODataGenericConverter<>(String.class, Function.identity(), Function.identity());
@@ -73,6 +76,15 @@ final class ODataGenericConverter<JavaT> extends AbstractTypeConverter<JavaT, St
7376
private final Function<JavaT, String> serializer;
7477
private final Function<String, JavaT> deserializer;
7578

79+
@Nonnull
80+
private static byte[] decodeBinary( @Nonnull final String value )
81+
{
82+
// Normalize URL-safe characters to standard Base64
83+
final String normalized = value.replace('-', '+').replace('_', '/');
84+
85+
return Base64.getDecoder().decode(normalized);
86+
}
87+
7688
@Nonnull
7789
@Override
7890
public ConvertedObject<String> toDomainNonNull( @Nonnull final JavaT object )

datamodel/odata-v4/odata-v4-core/src/test/java/com/sap/cloud/sdk/datamodel/odatav4/core/FieldSerializationTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.time.LocalDate;
99
import java.time.LocalTime;
1010
import java.time.OffsetDateTime;
11+
import java.util.Base64;
1112
import java.util.Map;
1213
import java.util.Objects;
1314
import java.util.UUID;
@@ -158,6 +159,15 @@ public static class ReferenceObject extends VdmEntity<ReferenceObject>
158159
"GeographyPoint":{"type":"Point","coordinates":[142.1,64.1]}\
159160
}\
160161
""";
162+
163+
private static final String PAYLOAD_ODATA_REFERENCE_BASE64URL =
164+
PAYLOAD_ODATA_REFERENCE.replace("\"BinaryValue\":\"AQID\"", "\"BinaryValue\":\"-__v\"");
165+
166+
private static final String PAYLOAD_ODATA_REFERENCE_MIXED_BASE64_ALPHABET =
167+
PAYLOAD_ODATA_REFERENCE.replace("\"BinaryValue\":\"AQID\"", "\"BinaryValue\":\"+__v\"");
168+
169+
static final String Base_64 = "+//v";
170+
static final String Base_64_Url = "-__v";
161171
}
162172

163173
@Test
@@ -174,6 +184,21 @@ void testBinaryFieldParsingFromResponsePayload()
174184
assertThat(ser).isEqualTo(ReferenceObject.PAYLOAD_ODATA_REFERENCE);
175185
}
176186

187+
@Test
188+
void testBinaryFieldParsingFromBase64UrlResponsePayload()
189+
{
190+
final ODataRequestResultGeneric result = mockRequestResult(ReferenceObject.PAYLOAD_ODATA_REFERENCE_BASE64URL);
191+
final ReferenceObject referenceResult = result.as(ReferenceObject.class);
192+
193+
Objects.requireNonNull(referenceResult);
194+
assertThat(referenceResult.getBinaryValue())
195+
.isEqualTo(Base64.getUrlDecoder().decode(ReferenceObject.Base_64_Url));
196+
197+
final String ser =
198+
new CreateRequestBuilder<>("/", referenceResult, "EntityCollection").toRequest().getSerializedEntity();
199+
assertThat(ser).contains("\"BinaryValue\":\"" + ReferenceObject.Base_64 + "\"");
200+
}
201+
177202
@Test
178203
void testCustomFieldParsingFromResponsePayload()
179204
{
@@ -186,6 +211,21 @@ void testCustomFieldParsingFromResponsePayload()
186211
assertThat(referenceResult.<Object> getCustomField("GeographyPoint")).isInstanceOf(Map.class);
187212
}
188213

214+
@Test
215+
void testBinaryFieldParsingFromMixedBase64AlphabetNormalized()
216+
{
217+
final ODataRequestResultGeneric result =
218+
mockRequestResult(ReferenceObject.PAYLOAD_ODATA_REFERENCE_MIXED_BASE64_ALPHABET);
219+
final ReferenceObject referenceResult = result.as(ReferenceObject.class);
220+
221+
Objects.requireNonNull(referenceResult);
222+
assertThat(referenceResult.getBinaryValue()).isEqualTo(Base64.getDecoder().decode(ReferenceObject.Base_64));
223+
224+
final String ser =
225+
new CreateRequestBuilder<>("/", referenceResult, "EntityCollection").toRequest().getSerializedEntity();
226+
assertThat(ser).contains("\"BinaryValue\":\"" + ReferenceObject.Base_64 + "\"");
227+
}
228+
189229
@SneakyThrows
190230
private static ODataRequestResultGeneric mockRequestResult( final String payload )
191231
{

release_notes.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
### ✨ New Functionality
1515

1616
- [OpenAPI] Cloud SDK OpenAPI Generator now supports `apache-httpclient` library besides Spring RestTemplate through the newly introduced module `openapi-core-apache`.
17+
- [IAS] Add `IasOptions.withTokenFormat()` to allow specifying token format
1718

1819
### 📈 Improvements
1920

2021
-
2122

2223
### 🐛 Fixed Issues
2324

24-
-
25+
- [OData v4] Binary deserialization can now handle both `Base64URL` and `Base64`.

0 commit comments

Comments
 (0)