diff --git a/src/main/java/org/springframework/data/aerospike/convert/AerospikeConverter.java b/src/main/java/org/springframework/data/aerospike/convert/AerospikeConverter.java index a5bf74069..8365f75ba 100644 --- a/src/main/java/org/springframework/data/aerospike/convert/AerospikeConverter.java +++ b/src/main/java/org/springframework/data/aerospike/convert/AerospikeConverter.java @@ -16,6 +16,7 @@ package org.springframework.data.aerospike.convert; import org.springframework.core.convert.ConversionService; +import org.springframework.data.aerospike.config.AerospikeDataSettings; import org.springframework.data.convert.EntityConverter; /** @@ -31,4 +32,11 @@ public interface AerospikeConverter extends AerospikeReader, AerospikeWr * @return the underlying {@link ConversionService} used by the converter */ ConversionService getConversionService(); + + /** + * Access Aerospike-specific data settings. + * + * @return the underlying {@link AerospikeDataSettings} used by the converter + */ + AerospikeDataSettings getAerospikeDataSettings(); } diff --git a/src/main/java/org/springframework/data/aerospike/convert/MappingAerospikeConverter.java b/src/main/java/org/springframework/data/aerospike/convert/MappingAerospikeConverter.java index ce9bc5f74..4afb64787 100644 --- a/src/main/java/org/springframework/data/aerospike/convert/MappingAerospikeConverter.java +++ b/src/main/java/org/springframework/data/aerospike/convert/MappingAerospikeConverter.java @@ -15,8 +15,8 @@ */ package org.springframework.data.aerospike.convert; +import lombok.Getter; import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.aerospike.config.AerospikeDataSettings; @@ -40,7 +40,10 @@ public class MappingAerospikeConverter implements InitializingBean, AerospikeConverter { private final CustomConversions conversions; + @Getter private final GenericConversionService conversionService; + @Getter + private final AerospikeDataSettings aerospikeDataSettings; private final MappingAerospikeReadConverter readConverter; private final MappingAerospikeWriteConverter writeConverter; @@ -52,6 +55,7 @@ public MappingAerospikeConverter(AerospikeMappingContext mappingContext, CustomC AerospikeDataSettings aerospikeDataSettings) { this.conversions = conversions; this.conversionService = new DefaultConversionService(); + this.aerospikeDataSettings = aerospikeDataSettings; EntityInstantiators entityInstantiators = new EntityInstantiators(); TypeMapper> typeMapper = new DefaultTypeMapper<>(aerospikeTypeAliasAccessor, @@ -69,11 +73,6 @@ public void afterPropertiesSet() { conversions.registerConvertersIn(conversionService); } - @Override - public ConversionService getConversionService() { - return conversionService; - } - @Override public R read(Class type, final AerospikeReadData data) { return readConverter.read(type, data); diff --git a/src/main/java/org/springframework/data/aerospike/convert/MappingAerospikeWriteConverter.java b/src/main/java/org/springframework/data/aerospike/convert/MappingAerospikeWriteConverter.java index e8d797e09..9d8f6279b 100644 --- a/src/main/java/org/springframework/data/aerospike/convert/MappingAerospikeWriteConverter.java +++ b/src/main/java/org/springframework/data/aerospike/convert/MappingAerospikeWriteConverter.java @@ -17,6 +17,7 @@ import com.aerospike.client.AerospikeException; import com.aerospike.client.Key; +import lombok.extern.slf4j.Slf4j; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.aerospike.config.AerospikeDataSettings; import org.springframework.data.aerospike.mapping.AerospikeMappingContext; @@ -44,6 +45,7 @@ import static com.aerospike.client.ResultCode.OP_NOT_APPLICABLE; import static org.springframework.data.aerospike.utility.TimeUtils.unixTimeToOffsetInSeconds; +@Slf4j public class MappingAerospikeWriteConverter implements EntityWriter { private final TypeMapper> typeMapper; @@ -128,6 +130,7 @@ public Optional getNewKey(AerospikeWriteData data, // Store record key as it is (if Aerospike supports it natively and configured) if (aerospikeDataSettings.isKeepOriginalKeyTypes() && isValidAerospikeRecordKeyType(idProperty.getType())) { + log.debug("Attempt to construct record key with original key type"); Object nativeTypeId = accessor.getProperty(idProperty, idProperty.getType()); Assert.notNull(nativeTypeId, "Id must not be null!"); Key aerospikeRecordKey = constructAerospikeRecordKey(data.getNamespace(), setName, nativeTypeId); @@ -138,6 +141,7 @@ public Optional getNewKey(AerospikeWriteData data, // Store record key as a String (Used for unsupported Aerospike key types and older versions) String stringId = accessor.getProperty(idProperty, String.class); Assert.notNull(stringId, "Id must not be null!"); + log.debug("Attempt to construct record key as String"); return Optional.of(new Key(data.getNamespace(), setName, stringId)); } else { // id is mandatory diff --git a/src/test/java/org/springframework/data/aerospike/convert/BaseMappingAerospikeConverterTest.java b/src/test/java/org/springframework/data/aerospike/convert/BaseMappingAerospikeConverterTest.java index f2b2c5322..e2df2d5d0 100644 --- a/src/test/java/org/springframework/data/aerospike/convert/BaseMappingAerospikeConverterTest.java +++ b/src/test/java/org/springframework/data/aerospike/convert/BaseMappingAerospikeConverterTest.java @@ -23,8 +23,16 @@ public abstract class BaseMappingAerospikeConverterTest { protected static final String NAMESPACE = "namespace"; public final AerospikeDataSettings aerospikeDataSettings = AerospikeDataSettings.builder().build(); + public final AerospikeDataSettings aerospikeDataSettingsReversedKeyTypesOption = AerospikeDataSettings.builder() + .keepOriginalKeyTypes(!aerospikeDataSettings.isKeepOriginalKeyTypes()).build(); protected final MappingAerospikeConverter converter = getMappingAerospikeConverter( + aerospikeDataSettings, + new SampleClasses.ComplexIdToStringConverter(), + new SampleClasses.StringToComplexIdConverter()); + + protected final MappingAerospikeConverter converterReversedKeyTypes = getMappingAerospikeConverter( + aerospikeDataSettingsReversedKeyTypesOption, new SampleClasses.ComplexIdToStringConverter(), new SampleClasses.StringToComplexIdConverter()); @@ -38,12 +46,21 @@ protected static Record aeroRecord(Map bins) { return new Record(bins, 0, 0); } - protected MappingAerospikeConverter getMappingAerospikeConverter(Converter... customConverters) { - return getMappingAerospikeConverter(new AerospikeTypeAliasAccessor(), customConverters); + protected MappingAerospikeConverter getAerospikeMappingConverterByOption(int converterOption) { + if (converterOption == 0) { + return converter; + } + return converterReversedKeyTypes; } - protected MappingAerospikeConverter getMappingAerospikeConverter(AerospikeTypeAliasAccessor typeAliasAccessor, + protected MappingAerospikeConverter getMappingAerospikeConverter(AerospikeDataSettings aerospikeDataSettings, Converter... customConverters) { + return getMappingAerospikeConverter(aerospikeDataSettings, new AerospikeTypeAliasAccessor(), customConverters); + } + + protected MappingAerospikeConverter getMappingAerospikeConverter(AerospikeDataSettings aerospikeDataSettings, + AerospikeTypeAliasAccessor typeAliasAccessor, + Converter... customConverters) { AerospikeMappingContext mappingContext = new AerospikeMappingContext(); mappingContext.setApplicationContext(getApplicationContext()); CustomConversions customConversions = new AerospikeCustomConversions(asList(customConverters)); diff --git a/src/test/java/org/springframework/data/aerospike/convert/MappingAerospikeConverterTests.java b/src/test/java/org/springframework/data/aerospike/convert/MappingAerospikeConverterTests.java index 10a100bd1..b90fa292f 100644 --- a/src/test/java/org/springframework/data/aerospike/convert/MappingAerospikeConverterTests.java +++ b/src/test/java/org/springframework/data/aerospike/convert/MappingAerospikeConverterTests.java @@ -110,7 +110,7 @@ public void usesDocumentsStoredTypeIfSubtypeOfRequest() { @Test public void shouldWriteAndReadUsingCustomConverter() { MappingAerospikeConverter converter = - getMappingAerospikeConverter(new UserToAerospikeWriteDataConverter(), + getMappingAerospikeConverter(aerospikeDataSettings, new UserToAerospikeWriteDataConverter(), new AerospikeReadDataToUserConverter()); AerospikeWriteData forWrite = AerospikeWriteData.forWrite(NAMESPACE); @@ -137,7 +137,7 @@ class TestName { } MappingAerospikeConverter converter = - getMappingAerospikeConverter(new UserToAerospikeWriteDataConverter(), + getMappingAerospikeConverter(aerospikeDataSettings, new UserToAerospikeWriteDataConverter(), new AerospikeReadDataToUserConverter()); AerospikeWriteData forWrite = AerospikeWriteData.forWrite(NAMESPACE); @@ -150,7 +150,7 @@ class TestName { @Test public void shouldWriteAndReadUsingCustomConverterOnNestedMapKeyObject() { MappingAerospikeConverter converter = - getMappingAerospikeConverter(new SampleClasses.SomeIdToStringConverter(), + getMappingAerospikeConverter(aerospikeDataSettings, new SampleClasses.SomeIdToStringConverter(), new SampleClasses.StringToSomeIdConverter()); AerospikeWriteData forWrite = AerospikeWriteData.forWrite(NAMESPACE); @@ -194,7 +194,7 @@ public void shouldWriteAndReadUsingCustomConverterOnNestedMapKeyObject() { @Test public void shouldWriteAndReadIfTypeKeyIsNull() { MappingAerospikeConverter converter = - getMappingAerospikeConverter(new AerospikeTypeAliasAccessor(null)); + getMappingAerospikeConverter(aerospikeDataSettings, new AerospikeTypeAliasAccessor(null)); AerospikeWriteData forWrite = AerospikeWriteData.forWrite(NAMESPACE); User user = new User(678L, null, null); @@ -369,7 +369,7 @@ public void shouldReadObjectWithByteArrayFieldWithOneValueInData() { @Test public void getConversionService() { MappingAerospikeConverter mappingAerospikeConverter = - getMappingAerospikeConverter(new AerospikeTypeAliasAccessor()); + getMappingAerospikeConverter(aerospikeDataSettings, new AerospikeTypeAliasAccessor()); assertThat(mappingAerospikeConverter.getConversionService()).isNotNull() .isInstanceOf(DefaultConversionService.class); } diff --git a/src/test/java/org/springframework/data/aerospike/convert/MappingAerospikeConverterTypesTests.java b/src/test/java/org/springframework/data/aerospike/convert/MappingAerospikeConverterTypesTests.java index 31836d7da..e356177a9 100644 --- a/src/test/java/org/springframework/data/aerospike/convert/MappingAerospikeConverterTypesTests.java +++ b/src/test/java/org/springframework/data/aerospike/convert/MappingAerospikeConverterTypesTests.java @@ -2,9 +2,11 @@ import com.aerospike.client.Bin; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.data.aerospike.assertions.KeyAssert; import org.springframework.data.aerospike.sample.SampleClasses; import org.springframework.data.aerospike.sample.SampleClasses.*; -import org.springframework.data.aerospike.assertions.KeyAssert; import org.testcontainers.shaded.com.google.common.collect.ImmutableList; import java.math.BigDecimal; @@ -18,9 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.springframework.data.aerospike.AsCollections.list; -import static org.springframework.data.aerospike.AsCollections.of; -import static org.springframework.data.aerospike.AsCollections.set; +import static org.springframework.data.aerospike.AsCollections.*; import static org.springframework.data.aerospike.sample.SampleClasses.SimpleClass.SIMPLESET; import static org.springframework.data.aerospike.sample.SampleClasses.SimpleClassWithPersistenceConstructor.SIMPLESET2; import static org.springframework.data.aerospike.sample.SampleClasses.User.SIMPLESET3; @@ -28,91 +28,101 @@ public class MappingAerospikeConverterTypesTests extends BaseMappingAerospikeConverterTest { private final String id = "my-id"; - @Test - void nullObjectIfAerospikeDataNull() { - SimpleClass actual = converter.read(SimpleClass.class, null); + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void nullObjectIfAerospikeDataNull(int converterOption) { + SimpleClass actual = getAerospikeMappingConverterByOption(converterOption).read(SimpleClass.class, null); assertThat(actual).isNull(); } - @Test - void primitiveIntId() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void primitiveIntId(int converterOption) { DocumentWithPrimitiveIntId object = new DocumentWithPrimitiveIntId(5); - assertWriteAndRead(object, "DocumentWithPrimitiveIntId", 5, + assertWriteAndRead(converterOption, object, "DocumentWithPrimitiveIntId", 5, new Bin("@_class", DocumentWithPrimitiveIntId.class.getName()) ); } - @Test - void primitiveLongId() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void primitiveLongId(int converterOption) { DocumentWithPrimitiveLongId object = new DocumentWithPrimitiveLongId(5L); - assertWriteAndRead(object, "DocumentWithPrimitiveLongId", 5L, + assertWriteAndRead(converterOption, object, "DocumentWithPrimitiveLongId", 5L, new Bin("@_class", DocumentWithPrimitiveLongId.class.getName()) ); } - @Test - void integerId() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void integerId(int converterOption) { DocumentWithIntegerId object = new DocumentWithIntegerId(5); - assertWriteAndRead(object, "DocumentWithIntegerId", 5, + assertWriteAndRead(converterOption, object, "DocumentWithIntegerId", 5, new Bin("@_class", DocumentWithIntegerId.class.getName()) ); } - @Test - void longId() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void longId(int converterOption) { DocumentWithLongId object = new DocumentWithLongId(5L); - assertWriteAndRead(object, "DocumentWithLongId", 5L, + assertWriteAndRead(converterOption, object, "DocumentWithLongId", 5L, new Bin("@_class", DocumentWithLongId.class.getName()) ); } - @Test - void stringId() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void stringId(int converterOption) { DocumentWithStringId object = new DocumentWithStringId("my-amazing-string-id"); - assertWriteAndRead(object, "DocumentWithStringId", "my-amazing-string-id", - new Bin("@_class", DocumentWithStringId.class.getName()) + assertWriteAndRead(converterOption, object, "DocumentWithStringId", + "my-amazing-string-id", new Bin("@_class", DocumentWithStringId.class.getName()) ); } - @Test - void byteArrayId() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void byteArrayId(int converterOption) { DocumentWithByteArrayId object = new DocumentWithByteArrayId(new byte[]{1, 0, 0, 1, 1, 1, 0, 0}); - assertWriteAndRead(object, "DocumentWithByteArrayId", new byte[]{1, 0, 0, 1, 1, 1, 0, 0}, - new Bin("@_class", DocumentWithByteArrayId.class.getName()) + assertWriteAndRead(converterOption, object, "DocumentWithByteArrayId", + new byte[]{1, 0, 0, 1, 1, 1, 0, 0}, new Bin("@_class", DocumentWithByteArrayId.class.getName()) ); } - @Test - void setWithSimpleValue() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void setWithSimpleValue(int converterOption) { SetWithSimpleValue object = new SetWithSimpleValue(1L, set("a", "b", "c", null)); - assertWriteAndRead(object, "SetWithSimpleValue", 1L, + assertWriteAndRead(converterOption, object, "SetWithSimpleValue", 1L, new Bin("collectionWithSimpleValues", list(null, "a", "b", "c")), new Bin("@_class", SetWithSimpleValue.class.getName()) ); } - @Test - void mapWithSimpleValue() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void mapWithSimpleValue(int converterOption) { Map map = of("key1", "value1", "key2", "value2", "key3", null); MapWithSimpleValue object = new MapWithSimpleValue(10L, map); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, MapWithSimpleValue.class.getSimpleName(), 10L, new Bin("mapWithSimpleValue", of("key1", "value1", "key2", "value2", "key3", null)), new Bin("@_class", MapWithSimpleValue.class.getName()) ); } - @Test - void idClassConverterNotFound() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void idClassConverterNotFound(int converterOption) { SampleClasses.SomeId someId1 = new SampleClasses.SomeId("partA", "partB1"); SampleClasses.SomeEntity someEntity1 = new SampleClasses.SomeEntity(someId1, "fieldA", 42L); Map entityMap = new HashMap<>(); @@ -120,7 +130,8 @@ void idClassConverterNotFound() { DocumentExample id = new DocumentExample("id", entityMap); DocumentExampleIdClass object = new DocumentExampleIdClass(id, 1L, 1234567890, 10L); - assertThatThrownBy(() -> assertWriteAndRead(object, DocumentExampleIdClass.class.getSimpleName(), 10L, + assertThatThrownBy(() -> assertWriteAndRead(converterOption, object, + DocumentExampleIdClass.class.getSimpleName(), 10L, new Bin("counter", 1L), new Bin("@_version", 1234567890), new Bin("update", 10L), @@ -131,25 +142,27 @@ void idClassConverterNotFound() { "[org.springframework.data.aerospike.sample.SampleClasses$DocumentExample] to type [java.lang.String]"); } - @Test - void mapWithCollectionValues() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void mapWithCollectionValues(int converterOption) { Map> map = of("key1", list(), "key2", list("a", "b", "c")); MapWithCollectionValue object = new MapWithCollectionValue(10L, map); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, MapWithCollectionValue.class.getSimpleName(), 10L, new Bin("mapWithCollectionValue", of("key1", list(), "key2", list("a", "b", "c"))), new Bin("@_class", MapWithCollectionValue.class.getName()) ); } - @Test - void mapWithNonSimpleValue() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void mapWithNonSimpleValue(int converterOption) { Map map = of("key1", new Address(new Street("Gogolya str.", 15), 567), "key2", new Address(new Street("Shakespeare str.", 40), 765)); MapWithGenericValue
object = new MapWithGenericValue<>(10L, map); - assertWriteAndRead(object, MapWithGenericValue.class.getSimpleName(), 10L, + assertWriteAndRead(converterOption, object, MapWithGenericValue.class.getSimpleName(), 10L, new Bin("mapWithNonSimpleValue", of( "key1", of("street", of("name", "Gogolya str.", "number", 15, "@_class", Street.class.getName()), "apartment", 567, "@_class", Address.class.getName()), @@ -159,14 +172,15 @@ void mapWithNonSimpleValue() { ); } - @Test - void listsAndMapsWithObjectValue() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void listsAndMapsWithObjectValue(int converterOption) { CustomTypeWithListAndMap object = new CustomTypeWithListAndMap(id, ImmutableList.of("firstItem", of("keyInList", "valueInList"), new Address(new Street("Gogolya str.", 15), 567)), of("map", of("key", "value"))); - assertWriteAndRead(object, "CustomTypeWithListAndMap", id, + assertWriteAndRead(converterOption, object, "CustomTypeWithListAndMap", id, new Bin("listOfObjects", list("firstItem", of("keyInList", "valueInList"), of("street", of("name", "Gogolya str.", "number", 15, "@_class", Street.class.getName()), @@ -176,14 +190,15 @@ void listsAndMapsWithObjectValue() { ); } - @Test - void customTypeWithCustomType() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void customTypeWithCustomType(int converterOption) { CustomTypeWithCustomType object = new CustomTypeWithCustomType(id, new ImmutableListAndMap( ImmutableList.of("firstItem", of("keyInList", "valueInList")), of("map", of("key", "value"), "address", new Address(new Street("Gogolya str.", 15), 567)))); - assertWriteAndRead(object, "CustomTypeWithCustomType", id, + assertWriteAndRead(converterOption, object, "CustomTypeWithCustomType", id, new Bin("field", of( "@_class", ImmutableListAndMap.class.getName(), "listOfObjects", list("firstItem", of("keyInList", "valueInList")), @@ -195,27 +210,29 @@ void customTypeWithCustomType() { ); } - @Test - void listsAndMapsWithObjectImmutable() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void listsAndMapsWithObjectImmutable(int converterOption) { CustomTypeWithListAndMapImmutable object = new CustomTypeWithListAndMapImmutable(id, ImmutableList.of("firstItem", of("keyInList", "valueInList")), of("map", of("key", "value"))); - assertWriteAndRead(object, "CustomTypeWithListAndMapImmutable", id, + assertWriteAndRead(converterOption, object, "CustomTypeWithListAndMapImmutable", id, new Bin("listOfObjects", list("firstItem", of("keyInList", "valueInList"))), new Bin("mapWithObjectValue", of("map", of("key", "value"))), new Bin("@_class", CustomTypeWithListAndMapImmutable.class.getName()) ); } - @Test - void objectWithSimpleFields() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithSimpleFields(int converterOption) { Set field9 = set("val1", "val2"); Set> field10 = set(set("1", "2"), set("3", "4"), set()); SimpleClass object = new SimpleClass(777L, "abyrvalg", 13, 14L, (float) 15, 16.0, true, new Date(8878888), TYPES.SECOND, field9, field10, (byte) 1, '3', 'd'); - assertWriteAndRead(object, SIMPLESET, 777L, + assertWriteAndRead(converterOption, object, SIMPLESET, 777L, new Bin("field1", "abyrvalg"), new Bin("field2", 13), new Bin("field3", 14L), @@ -233,23 +250,25 @@ void objectWithSimpleFields() { ); } - @Test - void objectWithPersistenceConstructor() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithPersistenceConstructor(int converterOption) { SimpleClassWithPersistenceConstructor object = new SimpleClassWithPersistenceConstructor(17, "abyrvalg", 13); - assertWriteAndRead(object, SIMPLESET2, 17, + assertWriteAndRead(converterOption, object, SIMPLESET2, 17, new Bin("@_class", SimpleClassWithPersistenceConstructor.class.getName()), new Bin("field1", "abyrvalg"), new Bin("field2", 13)); } - @Test - void complexClass() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void complexClass(int converterOption) { Name name = new Name("Vasya", "Pupkin"); Address address = new Address(new Street("Gogolya street", 24), 777); User object = new User(10, name, address); - assertWriteAndRead(object, SIMPLESET3, 10, + assertWriteAndRead(converterOption, object, SIMPLESET3, 10, new Bin("@_class", User.class.getName()), new Bin("name", of("firstName", "Vasya", "lastName", "Pupkin", "@_class", Name.class.getName())), @@ -260,14 +279,15 @@ void complexClass() { ); } - @Test - void setWithComplexValue() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void setWithComplexValue(int converterOption) { Set
addresses = set( new Address(new Street("Southwark Street", 110), 876), new Address(new Street("Finsbury Pavement", 125), 13)); Person object = new Person("kate-01", addresses); - assertWriteAndRead(object, "Person", "kate-01", + assertWriteAndRead(converterOption, object, "Person", "kate-01", new Bin("@_class", Person.class.getName()), new Bin("addresses", list( of("street", @@ -279,14 +299,15 @@ void setWithComplexValue() { ))); } - @Test - void enumProperties() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void enumProperties(int converterOption) { List list = list(TYPES.FIRST, TYPES.SECOND); EnumSet set = EnumSet.allOf(TYPES.class); EnumMap map = new EnumMap(of(TYPES.FIRST, "a", TYPES.SECOND, "b")); ClassWithEnumProperties object = new ClassWithEnumProperties("id", TYPES.SECOND, list, set, map); - assertWriteAndRead(object, "ClassWithEnumProperties", "id", + assertWriteAndRead(converterOption, object, "ClassWithEnumProperties", "id", new Bin("@_class", ClassWithEnumProperties.class.getName()), new Bin("type", "SECOND"), new Bin("list", list("FIRST", "SECOND")), @@ -295,25 +316,27 @@ void enumProperties() { ); } - @Test - void sortedMapWithSimpleValue() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void sortedMapWithSimpleValue(int converterOption) { SortedMap map = new TreeMap<>(of("a", "b", "c", "d")); SortedMapWithSimpleValue object = new SortedMapWithSimpleValue(id, map); - assertWriteAndRead(object, "SortedMapWithSimpleValue", id, + assertWriteAndRead(converterOption, object, "SortedMapWithSimpleValue", id, new Bin("@_class", SortedMapWithSimpleValue.class.getName()), new Bin("map", of("a", "b", "c", "d")) ); } - @Test - void nestedMapsWithSimpleValue() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void nestedMapsWithSimpleValue(int converterOption) { Map>> map = of( "level-1", of("level-1-1", of("1", "2")), "level-2", of("level-2-2", of("1", "2"))); NestedMapsWithSimpleValue object = new NestedMapsWithSimpleValue(id, map); - assertWriteAndRead(object, "NestedMapsWithSimpleValue", id, + assertWriteAndRead(converterOption, object, "NestedMapsWithSimpleValue", id, new Bin("@_class", NestedMapsWithSimpleValue.class.getName()), new Bin("nestedMaps", of( "level-1", of("level-1-1", of("1", "2")), @@ -321,33 +344,36 @@ void nestedMapsWithSimpleValue() { ); } - @Test - void genericType() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void genericType(int converterOption) { //noinspection rawtypes @SuppressWarnings("unchecked") GenericType> object = new GenericType(id, "string"); - assertWriteAndRead(object, "GenericType", id, + assertWriteAndRead(converterOption, object, "GenericType", id, new Bin("@_class", GenericType.class.getName()), new Bin("content", "string") ); } - @Test - void listOfLists() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void listOfLists(int converterOption) { ListOfLists object = new ListOfLists(id, list(list("a", "b", "c"), list("d", "e"), list())); - assertWriteAndRead(object, "ListOfLists", id, + assertWriteAndRead(converterOption, object, "ListOfLists", id, new Bin("@_class", ListOfLists.class.getName()), new Bin("listOfLists", list(list("a", "b", "c"), list("d", "e"), list())) ); } - @Test - void listOfMaps() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void listOfMaps(int converterOption) { ListOfMaps object = new ListOfMaps(id, list(of("vasya", new Name("Vasya", "Pukin")), of("nastya", new Name("Nastya", "Smirnova")))); - assertWriteAndRead(object, "ListOfMaps", id, + assertWriteAndRead(converterOption, object, "ListOfMaps", id, new Bin("@_class", ListOfMaps.class.getName()), new Bin("listOfMaps", list( of("vasya", of("firstName", "Vasya", "lastName", "Pukin", "@_class", Name.class.getName())), @@ -355,12 +381,13 @@ void listOfMaps() { ))); } - @Test - void containerOfCustomFieldNames() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void containerOfCustomFieldNames(int converterOption) { ContainerOfCustomFieldNames object = new ContainerOfCustomFieldNames(id, "value", new CustomFieldNames(1 , "2")); - assertWriteAndRead(object, "ContainerOfCustomFieldNames", id, + assertWriteAndRead(converterOption, object, "ContainerOfCustomFieldNames", id, new Bin("@_class", ContainerOfCustomFieldNames.class.getName()), new Bin("property", "value"), new Bin("customFieldNames", of("property1", 1, "property2", "2", "@_class", @@ -368,58 +395,64 @@ void containerOfCustomFieldNames() { ); } - @Test - void classWithComplexId() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void classWithComplexId(int converterOption) { ClassWithComplexId object = new ClassWithComplexId(new ComplexId(10L)); - assertWriteAndRead(object, ClassWithComplexId.class.getSimpleName(), "id::10", + assertWriteAndRead(converterOption, object, ClassWithComplexId.class.getSimpleName(), "id::10", new Bin("@_class", ClassWithComplexId.class.getName()) ); } - @Test - void idFieldOfNonDocumentClass() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void idFieldOfNonDocumentClass(int converterOption) { MapWithGenericValue object = new MapWithGenericValue<>(788L, of("key", new ClassWithIdField(45L, "v"))); - assertWriteAndRead(object, MapWithGenericValue.class.getSimpleName(), 788L, + assertWriteAndRead(converterOption, object, MapWithGenericValue.class.getSimpleName(), 788L, new Bin("@_class", MapWithGenericValue.class.getName()), new Bin("mapWithNonSimpleValue", of("key", of("id", 45L, "field", "v", "@_class", ClassWithIdField.class.getName()))) ); } - @Test - void objectWithByteArrayField() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithByteArrayField(int converterOption) { DocumentWithByteArray object = new DocumentWithByteArray(id, new byte[]{1, 0, 0, 1, 1, 1, 0, 0}); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, "DocumentWithByteArray", id, new Bin("@_class", DocumentWithByteArray.class.getName()), new Bin("array", new byte[]{1, 0, 0, 1, 1, 1, 0, 0})); } - @Test - void objectWithArrayField() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithArrayField(int converterOption) { int[] array = new int[]{1, 0, 0, 1, 1, 1, 0, 0}; DocumentWithIntArray object = new DocumentWithIntArray(id, array); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, "DocumentWithIntArray", id, new Bin("@_class", DocumentWithIntArray.class.getName()), new Bin("array", Arrays.stream(array).boxed().toList())); } - @Test - void objectWithAtomicField() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithAtomicField(int converterOption) { AtomicInteger atomicInteger = new AtomicInteger(10); AtomicLong atomicLong = new AtomicLong(10L); DocumentWithAtomicFields object = new DocumentWithAtomicFields(id, atomicInteger, atomicLong); - DocumentWithAtomicFields readDoc = readObjectAfterWriting(object, + DocumentWithAtomicFields readDoc = readObjectAfterWriting(converterOption, object, "DocumentWithAtomicFields", id, new Bin("@_class", DocumentWithAtomicFields.class.getName()), - new Bin("atomicInteger", AerospikeConverters.AtomicIntegerToIntegerConverter.INSTANCE.convert(atomicInteger)), + new Bin("atomicInteger", + AerospikeConverters.AtomicIntegerToIntegerConverter.INSTANCE.convert(atomicInteger)), new Bin("atomicLong", AerospikeConverters.AtomicLongToLongConverter.INSTANCE.convert(atomicLong))); @@ -428,8 +461,9 @@ void objectWithAtomicField() { assertThat(readDoc.getAtomicLong().longValue()).isEqualTo(object.getAtomicLong().longValue()); } - @Test - void objectWithURLField() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithURLField(int converterOption) { URL url; try { url = new URL("http://example.com"); @@ -438,77 +472,83 @@ void objectWithURLField() { } DocumentWithURL object = new DocumentWithURL(id, url); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, "DocumentWithURL", id, new Bin("@_class", DocumentWithURL.class.getName()), new Bin("url", AerospikeConverters.URLToStringConverter.INSTANCE.convert(url))); } - @Test - void objectWithUUIDField() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithUUIDField(int converterOption) { UUID uuid = new UUID(10L, 5L); DocumentWithUUID object = new DocumentWithUUID(id, uuid); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, "DocumentWithUUID", id, new Bin("@_class", DocumentWithUUID.class.getName()), new Bin("uuid", AerospikeConverters.UuidToStringConverter.INSTANCE.convert(uuid))); } - @Test - void objectWithCurrencyField() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithCurrencyField(int converterOption) { Currency currency = Currency.getInstance("USD"); DocumentWithCurrency object = new DocumentWithCurrency(id, currency); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, "DocumentWithCurrency", id, new Bin("@_class", DocumentWithCurrency.class.getName()), new Bin("currency", AerospikeConverters.CurrencyToStringConverter.INSTANCE.convert(currency))); } - @Test - void objectWithDateField() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithDateField(int converterOption) { Date date = Date.from(Instant.now()); DocumentWithDate object = new DocumentWithDate(id, date); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, "DocumentWithDate", id, new Bin("@_class", DocumentWithDate.class.getName()), new Bin("date", DateConverters.DateToLongConverter.INSTANCE.convert(date))); } - @Test - void objectWithCalendarField() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithCalendarField(int converterOption) { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("PTC")); calendar.setTime(Date.from(Instant.now())); DocumentWithCalendar object = new DocumentWithCalendar(id, calendar); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, "DocumentWithCalendar", id, new Bin("@_class", DocumentWithCalendar.class.getName()), new Bin("calendar", DateConverters.CalendarToMapConverter.INSTANCE.convert(calendar))); } - @Test - void objectWithDurationField() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithDurationField(int converterOption) { Duration duration = Duration.ofSeconds(12345678910L); DocumentWithDuration object = new DocumentWithDuration(id, duration); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, "DocumentWithDuration", id, new Bin("@_class", DocumentWithDuration.class.getName()), new Bin("duration", DateConverters.DurationToStringConverter.INSTANCE.convert(duration))); } - @Test - void objectWithBigDecimal() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithBigDecimal(int converterOption) { Map bigDecimalMap = new HashMap<>(); bigDecimalMap.put("big-decimal-val", new BigDecimal("767867678687678")); List bigDecimalList = List.of(new BigDecimal("988687642340235")); BigDecimal bigDecimal = new BigDecimal("999999999999999999999999998746"); BigDecimalContainer object = new BigDecimalContainer(id, bigDecimal, bigDecimalMap, bigDecimalList); - assertWriteAndRead(object, + assertWriteAndRead(converterOption, object, "BigDecimalContainer", id, new Bin("@_class", BigDecimalContainer.class.getName()), new Bin("collection", list("988687642340235")), @@ -517,11 +557,12 @@ void objectWithBigDecimal() { ); } - @Test - void objectWithByteArrayFieldWithOneValueInData() { + @ParameterizedTest() + @ValueSource(ints = {0, 1}) + void objectWithByteArrayFieldWithOneValueInData(int converterOption) { DocumentWithByteArray object = new DocumentWithByteArray(id, new byte[]{1}); - assertWriteAndRead(object, "DocumentWithByteArray", id, + assertWriteAndRead(converterOption, object, "DocumentWithByteArray", id, new Bin("@_class", DocumentWithByteArray.class.getName()), new Bin("array", new byte[]{1}) ); @@ -530,7 +571,7 @@ void objectWithByteArrayFieldWithOneValueInData() { @Test void shouldWriteAsArrayListAndReadAsByteArray() { MappingAerospikeConverter converter = - getMappingAerospikeConverter(new AerospikeTypeAliasAccessor(null)); + getMappingAerospikeConverter(aerospikeDataSettings, new AerospikeTypeAliasAccessor(null)); AerospikeWriteData forWrite = AerospikeWriteData.forWrite(NAMESPACE); DocumentWithByteArrayList docToWrite = new DocumentWithByteArrayList("user-id", Arrays.asList((byte) 1, @@ -550,7 +591,7 @@ void shouldWriteAsArrayListAndReadAsByteArray() { @Test void shouldWriteAsByteArrayAndReadAsArrayList() { MappingAerospikeConverter converter = - getMappingAerospikeConverter(new AerospikeTypeAliasAccessor(null)); + getMappingAerospikeConverter(aerospikeDataSettings, new AerospikeTypeAliasAccessor(null)); AerospikeWriteData forWrite = AerospikeWriteData.forWrite(NAMESPACE); DocumentWithByteArray docToWrite = new DocumentWithByteArray("user-id", new byte[]{1, 2, 3}); @@ -567,41 +608,45 @@ void shouldWriteAsByteArrayAndReadAsArrayList() { (byte) 3))); } - private void assertWriteAndRead(T object, + private void assertWriteAndRead(int converterOption, + T object, String expectedSet, Object expectedUserKey, Bin... expectedBins) { - + MappingAerospikeConverter aerospikeConverter = getAerospikeMappingConverterByOption(converterOption); AerospikeWriteData forWrite = AerospikeWriteData.forWrite(NAMESPACE); - converter.write(object, forWrite); + aerospikeConverter.write(object, forWrite); - KeyAssert.assertThat(forWrite.getKey()).consistsOf(aerospikeDataSettings, NAMESPACE, expectedSet, expectedUserKey); + KeyAssert.assertThat(forWrite.getKey()).consistsOf(aerospikeConverter.getAerospikeDataSettings(), NAMESPACE, + expectedSet, expectedUserKey); assertThat(forWrite.getBins()).containsOnly(expectedBins); AerospikeReadData forRead = AerospikeReadData.forRead(forWrite.getKey(), aeroRecord(forWrite.getBins())); - @SuppressWarnings("unchecked") T actual = (T) converter.read(object.getClass(), forRead); + @SuppressWarnings("unchecked") T actual = (T) aerospikeConverter.read(object.getClass(), forRead); assertThat(actual).isEqualTo(object); } @SuppressWarnings("SameParameterValue") - private T readObjectAfterWriting(T object, - String expectedSet, - Object expectedUserKey, - Bin... expectedBins) { - + private T readObjectAfterWriting(int converterOption, + T object, + String expectedSet, + Object expectedUserKey, + Bin... expectedBins) { + MappingAerospikeConverter aerospikeConverter = getAerospikeMappingConverterByOption(converterOption); AerospikeWriteData forWrite = AerospikeWriteData.forWrite(NAMESPACE); - converter.write(object, forWrite); + aerospikeConverter.write(object, forWrite); - KeyAssert.assertThat(forWrite.getKey()).consistsOf(aerospikeDataSettings, NAMESPACE, expectedSet, expectedUserKey); + KeyAssert.assertThat(forWrite.getKey()).consistsOf(aerospikeConverter.getAerospikeDataSettings(), NAMESPACE, + expectedSet, expectedUserKey); assertThat(forWrite.getBins()).containsOnly(expectedBins); AerospikeReadData forRead = AerospikeReadData.forRead(forWrite.getKey(), aeroRecord(forWrite.getBins())); - @SuppressWarnings("unchecked") T actual = (T) converter.read(object.getClass(), forRead); + @SuppressWarnings("unchecked") T actual = (T) aerospikeConverter.read(object.getClass(), forRead); return actual; }