/* * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.data.cassandra.convert; import static org.assertj.core.api.Assertions.*; import static org.junit.Assume.*; import static org.mockito.Mockito.*; import static org.springframework.data.cassandra.RowMockUtil.*; import static org.springframework.data.cassandra.repository.support.BasicMapId.*; import lombok.AllArgsConstructor; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.cassandra.core.PrimaryKeyType; import org.springframework.core.SpringVersion; import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.data.cassandra.RowMockUtil; import org.springframework.data.cassandra.domain.CompositeKey; import org.springframework.data.cassandra.domain.Person; import org.springframework.data.cassandra.domain.TypeWithCompositeKey; import org.springframework.data.cassandra.domain.TypeWithKeyClass; import org.springframework.data.cassandra.domain.TypeWithMapId; import org.springframework.data.cassandra.domain.UserToken; import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext; import org.springframework.data.cassandra.mapping.CassandraMappingContext; import org.springframework.data.cassandra.mapping.CassandraType; import org.springframework.data.cassandra.mapping.PrimaryKey; import org.springframework.data.cassandra.mapping.PrimaryKeyClass; import org.springframework.data.cassandra.mapping.PrimaryKeyColumn; import org.springframework.data.cassandra.mapping.Table; import org.springframework.data.util.Version; import org.springframework.test.util.ReflectionTestUtils; import com.datastax.driver.core.DataType; import com.datastax.driver.core.DataType.Name; import com.datastax.driver.core.LocalDate; import com.datastax.driver.core.Row; import com.datastax.driver.core.querybuilder.Assignment; import com.datastax.driver.core.querybuilder.BuiltStatement; import com.datastax.driver.core.querybuilder.Clause; import com.datastax.driver.core.querybuilder.Delete; import com.datastax.driver.core.querybuilder.Delete.Where; import com.datastax.driver.core.querybuilder.Insert; import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.Update; import com.datastax.driver.core.querybuilder.Update.Assignments; /** * Unit tests for {@link MappingCassandraConverter}. * * @author Mark Paluch * @soundtrack Outlandich - Dont Leave Me Feat Cyt (Sun Kidz Electrocore Mix) */ @SuppressWarnings("Since15") @RunWith(MockitoJUnitRunner.class) public class MappingCassandraConverterUnitTests { private static final Version VERSION_4_3 = Version.parse("4.3"); @Rule public final ExpectedException expectedException = ExpectedException.none(); @Mock Row rowMock; CassandraMappingContext mappingContext; MappingCassandraConverter mappingCassandraConverter; @Before public void setUp() throws Exception { mappingContext = new BasicCassandraMappingContext(); mappingCassandraConverter = new MappingCassandraConverter(mappingContext); mappingCassandraConverter.afterPropertiesSet(); } @Test // DATACASS-260 public void insertEnumShouldMapToString() { WithEnumColumns withEnumColumns = new WithEnumColumns(); withEnumColumns.setCondition(Condition.MINT); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(withEnumColumns, insert); assertThat(getValues(insert)).contains("MINT"); } @Test // DATACASS-260 public void insertEnumDoesNotMapToOrdinalBeforeSpring43() { assumeTrue(Version.parse(SpringVersion.getVersion()).isLessThan(VERSION_4_3)); expectedException.expect(ConverterNotFoundException.class); UnsupportedEnumToOrdinalMapping unsupportedEnumToOrdinalMapping = new UnsupportedEnumToOrdinalMapping(); unsupportedEnumToOrdinalMapping.setAsOrdinal(Condition.MINT); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(unsupportedEnumToOrdinalMapping, insert); } @Test // DATACASS-255 public void insertEnumMapsToOrdinalWithSpring43AndHiger() { assumeTrue(Version.parse(SpringVersion.getVersion()).isGreaterThanOrEqualTo(VERSION_4_3)); UnsupportedEnumToOrdinalMapping unsupportedEnumToOrdinalMapping = new UnsupportedEnumToOrdinalMapping(); unsupportedEnumToOrdinalMapping.setAsOrdinal(Condition.USED); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(unsupportedEnumToOrdinalMapping, insert); assertThat(getValues(insert)).contains((Object) Integer.valueOf(Condition.USED.ordinal())); } @Test // DATACASS-260 public void insertEnumAsPrimaryKeyShouldMapToString() { EnumPrimaryKey key = new EnumPrimaryKey(); key.setCondition(Condition.MINT); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(key, insert); assertThat(getValues(insert)).contains((Object) "MINT"); } @Test // DATACASS-260 public void insertEnumInCompositePrimaryKeyShouldMapToString() { EnumCompositePrimaryKey key = new EnumCompositePrimaryKey(); key.setCondition(Condition.MINT); CompositeKeyThing composite = new CompositeKeyThing(); composite.setKey(key); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(composite, insert); assertThat(getValues(insert)).contains((Object) "MINT"); } @Test // DATACASS-260 public void updateEnumShouldMapToString() { WithEnumColumns withEnumColumns = new WithEnumColumns(); withEnumColumns.setCondition(Condition.MINT); Update update = QueryBuilder.update("table"); mappingCassandraConverter.write(withEnumColumns, update); assertThat(getAssignmentValues(update)).contains((Object) "MINT"); } @Test // DATACASS-260 public void updateEnumAsPrimaryKeyShouldMapToString() { EnumPrimaryKey key = new EnumPrimaryKey(); key.setCondition(Condition.MINT); Update update = QueryBuilder.update("table"); mappingCassandraConverter.write(key, update); assertThat(getWhereValues(update)).contains((Object) "MINT"); } @Test // DATACASS-260 public void updateEnumInCompositePrimaryKeyShouldMapToString() { EnumCompositePrimaryKey key = new EnumCompositePrimaryKey(); key.setCondition(Condition.MINT); CompositeKeyThing composite = new CompositeKeyThing(); composite.setKey(key); Update update = QueryBuilder.update("table"); mappingCassandraConverter.write(composite, update); assertThat(getWhereValues(update)).contains((Object) "MINT"); } @Test // DATACASS-260 public void whereEnumAsPrimaryKeyShouldMapToString() { EnumPrimaryKey key = new EnumPrimaryKey(); key.setCondition(Condition.MINT); Where where = QueryBuilder.delete().from("table").where(); mappingCassandraConverter.write(key, where); assertThat(getWhereValues(where)).contains((Object) "MINT"); } @Test // DATACASS-260 public void whereEnumInCompositePrimaryKeyShouldMapToString() { EnumCompositePrimaryKey key = new EnumCompositePrimaryKey(); key.setCondition(Condition.MINT); CompositeKeyThing composite = new CompositeKeyThing(); composite.setKey(key); Where where = QueryBuilder.delete().from("table").where(); mappingCassandraConverter.write(composite, where); assertThat(getWhereValues(where)).contains((Object) "MINT"); } @Test // DATACASS-280 public void shouldReadStringCorrectly() { when(rowMock.getString(0)).thenReturn("foo"); String result = mappingCassandraConverter.readRow(String.class, rowMock); assertThat(result).isEqualTo("foo"); } @Test // DATACASS-280 public void shouldReadIntegerCorrectly() { when(rowMock.getObject(0)).thenReturn(2); Integer result = mappingCassandraConverter.readRow(Integer.class, rowMock); assertThat(result).isEqualTo(2); } @Test // DATACASS-280 public void shouldReadLongCorrectly() { when(rowMock.getObject(0)).thenReturn(2); Long result = mappingCassandraConverter.readRow(Long.class, rowMock); assertThat(result).isEqualTo(2L); } @Test // DATACASS-280 public void shouldReadDoubleCorrectly() { when(rowMock.getObject(0)).thenReturn(2D); Double result = mappingCassandraConverter.readRow(Double.class, rowMock); assertThat(result).isEqualTo(2D); } @Test // DATACASS-280 public void shouldReadFloatCorrectly() { when(rowMock.getObject(0)).thenReturn(2F); Float result = mappingCassandraConverter.readRow(Float.class, rowMock); assertThat(result).isEqualTo(2F); } @Test // DATACASS-280 public void shouldReadBigIntegerCorrectly() { when(rowMock.getObject(0)).thenReturn(BigInteger.valueOf(2)); BigInteger result = mappingCassandraConverter.readRow(BigInteger.class, rowMock); assertThat(result).isEqualTo(BigInteger.valueOf(2)); } @Test // DATACASS-280 public void shouldReadBigDecimalCorrectly() { when(rowMock.getObject(0)).thenReturn(BigDecimal.valueOf(2)); BigDecimal result = mappingCassandraConverter.readRow(BigDecimal.class, rowMock); assertThat(result).isEqualTo(BigDecimal.valueOf(2)); } @Test // DATACASS-280 public void shouldReadUUIDCorrectly() { UUID uuid = UUID.randomUUID(); when(rowMock.getUUID(0)).thenReturn(uuid); UUID result = mappingCassandraConverter.readRow(UUID.class, rowMock); assertThat(result).isEqualTo(uuid); } @Test // DATACASS-280 public void shouldReadInetAddressCorrectly() throws UnknownHostException { InetAddress localHost = InetAddress.getLocalHost(); when(rowMock.getInet(0)).thenReturn(localHost); InetAddress result = mappingCassandraConverter.readRow(InetAddress.class, rowMock); assertThat(result).isEqualTo(localHost); } @Test // DATACASS-280, DATACASS-271 public void shouldReadTimestampCorrectly() { Date date = new Date(1); when(rowMock.getTimestamp(0)).thenReturn(date); Date result = mappingCassandraConverter.readRow(Date.class, rowMock); assertThat(result).isEqualTo(date); } @Test // DATACASS-271 public void shouldReadDateCorrectly() { LocalDate date = LocalDate.fromDaysSinceEpoch(1234); when(rowMock.getDate(0)).thenReturn(date); LocalDate result = mappingCassandraConverter.readRow(LocalDate.class, rowMock); assertThat(result).isEqualTo(date); } @Test // DATACASS-280 public void shouldReadBooleanCorrectly() { when(rowMock.getBool(0)).thenReturn(true); Boolean result = mappingCassandraConverter.readRow(Boolean.class, rowMock); assertThat(result).isEqualTo(true); } @Test // DATACASS-296 public void shouldReadLocalDateCorrectly() { LocalDateTime now = LocalDateTime.now(); Instant instant = now.toInstant(ZoneOffset.UTC); Row rowMock = RowMockUtil.newRowMock(column("id", "my-id", DataType.ascii()), column("localdate", Date.from(instant), DataType.timestamp())); TypeWithLocalDate result = mappingCassandraConverter.readRow(TypeWithLocalDate.class, rowMock); assertThat(result.localDate).isNotNull(); assertThat(result.localDate.getYear()).isEqualTo(now.getYear()); assertThat(result.localDate.getMonthValue()).isEqualTo(now.getMonthValue()); } @Test // DATACASS-296 public void shouldCreateInsertWithLocalDateCorrectly() { java.time.LocalDate now = java.time.LocalDate.now(); TypeWithLocalDate typeWithLocalDate = new TypeWithLocalDate(); typeWithLocalDate.localDate = now; Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(typeWithLocalDate, insert); assertThat(getValues(insert)) .contains(LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())); } @Test // DATACASS-296 public void shouldCreateUpdateWithLocalDateCorrectly() { java.time.LocalDate now = java.time.LocalDate.now(); TypeWithLocalDate typeWithLocalDate = new TypeWithLocalDate(); typeWithLocalDate.localDate = now; Update update = QueryBuilder.update("table"); mappingCassandraConverter.write(typeWithLocalDate, update); assertThat(getAssignmentValues(update)) .contains(LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())); } @Test // DATACASS-296 public void shouldCreateInsertWithLocalDateListUsingCassandraDate() { java.time.LocalDate now = java.time.LocalDate.now(); java.time.LocalDate localDate = java.time.LocalDate.of(2010, 7, 4); TypeWithLocalDate typeWithLocalDate = new TypeWithLocalDate(); typeWithLocalDate.list = Arrays.asList(now, localDate); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(typeWithLocalDate, insert); List<LocalDate> dates = getListValue(insert); assertThat(dates).contains(LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())); assertThat(dates).contains(LocalDate.fromYearMonthDay(2010, 7, 4)); } @Test // DATACASS-296 public void shouldCreateInsertWithLocalDateSetUsingCassandraDate() { java.time.LocalDate now = java.time.LocalDate.now(); java.time.LocalDate localDate = java.time.LocalDate.of(2010, 7, 4); TypeWithLocalDate typeWithLocalDate = new TypeWithLocalDate(); typeWithLocalDate.set = new HashSet<>(Arrays.asList(now, localDate)); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(typeWithLocalDate, insert); Set<LocalDate> dates = getSetValue(insert); assertThat(dates).contains(LocalDate.fromYearMonthDay(now.getYear(), now.getMonthValue(), now.getDayOfMonth())); assertThat(dates).contains(LocalDate.fromYearMonthDay(2010, 7, 4)); } @Test // DATACASS-296 public void shouldReadLocalDateTimeUsingCassandraDateCorrectly() { Row rowMock = RowMockUtil.newRowMock(column("id", "my-id", DataType.ascii()), column("localDate", LocalDate.fromYearMonthDay(2010, 7, 4), DataType.date())); TypeWithLocalDateMappedToDate result = mappingCassandraConverter.readRow(TypeWithLocalDateMappedToDate.class, rowMock); assertThat(result.localDate).isNotNull(); assertThat(result.localDate.getYear()).isEqualTo(2010); assertThat(result.localDate.getMonthValue()).isEqualTo(7); assertThat(result.localDate.getDayOfMonth()).isEqualTo(4); } @Test // DATACASS-296, DATACASS-400 public void shouldCreateInsertWithLocalDateUsingCassandraDateCorrectly() { TypeWithLocalDateMappedToDate typeWithLocalDate = new TypeWithLocalDateMappedToDate(null, java.time.LocalDate.of(2010, 7, 4)); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(typeWithLocalDate, insert); assertThat(getValues(insert).contains(LocalDate.fromYearMonthDay(2010, 7, 4))).isTrue(); } @Test // DATACASS-296 public void shouldCreateUpdateWithLocalDateUsingCassandraDateCorrectly() { TypeWithLocalDateMappedToDate typeWithLocalDate = new TypeWithLocalDateMappedToDate(null, java.time.LocalDate.of(2010, 7, 4)); Update update = QueryBuilder.update("table"); mappingCassandraConverter.write(typeWithLocalDate, update); assertThat(getAssignmentValues(update)).contains(LocalDate.fromYearMonthDay(2010, 7, 4)); } @Test // DATACASS-296 public void shouldReadLocalDateTimeCorrectly() { LocalDateTime now = LocalDateTime.now(); Instant instant = now.toInstant(ZoneOffset.UTC); Row rowMock = RowMockUtil.newRowMock(column("id", "my-id", DataType.ascii()), column("localDateTime", Date.from(instant), DataType.timestamp())); TypeWithLocalDate result = mappingCassandraConverter.readRow(TypeWithLocalDate.class, rowMock); assertThat(result.localDateTime).isNotNull(); assertThat(result.localDateTime.getYear()).isEqualTo(now.getYear()); assertThat(result.localDateTime.getMinute()).isEqualTo(now.getMinute()); } @Test // DATACASS-296 public void shouldReadInstantCorrectly() { LocalDateTime now = LocalDateTime.now(); Instant instant = now.toInstant(ZoneOffset.UTC); Row rowMock = RowMockUtil.newRowMock(column("id", "my-id", DataType.ascii()), column("instant", Date.from(instant), DataType.timestamp())); TypeWithInstant result = mappingCassandraConverter.readRow(TypeWithInstant.class, rowMock); assertThat(result.instant).isNotNull(); assertThat(result.instant.getEpochSecond()).isEqualTo(instant.getEpochSecond()); } @Test // DATACASS-296 public void shouldReadZoneIdCorrectly() { Row rowMock = RowMockUtil.newRowMock(column("id", "my-id", DataType.ascii()), column("zoneId", "Europe/Paris", DataType.varchar())); TypeWithZoneId result = mappingCassandraConverter.readRow(TypeWithZoneId.class, rowMock); assertThat(result.zoneId).isNotNull(); assertThat(result.zoneId.getId()).isEqualTo("Europe/Paris"); } @Test // DATACASS-296 public void shouldReadJodaLocalDateTimeUsingCassandraDateCorrectly() { Row rowMock = RowMockUtil.newRowMock(column("id", "my-id", DataType.ascii()), column("localDate", LocalDate.fromYearMonthDay(2010, 7, 4), DataType.date())); TypeWithJodaLocalDateMappedToDate result = mappingCassandraConverter .readRow(TypeWithJodaLocalDateMappedToDate.class, rowMock); assertThat(result.localDate).isNotNull(); assertThat(result.localDate.getYear()).isEqualTo(2010); assertThat(result.localDate.getMonthOfYear()).isEqualTo(7); assertThat(result.localDate.getDayOfMonth()).isEqualTo(4); } @Test // DATACASS-296 public void shouldCreateInsertWithJodaLocalDateUsingCassandraDateCorrectly() { TypeWithJodaLocalDateMappedToDate typeWithLocalDate = new TypeWithJodaLocalDateMappedToDate(); typeWithLocalDate.localDate = new org.joda.time.LocalDate(2010, 7, 4); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(typeWithLocalDate, insert); assertThat(getValues(insert).contains(LocalDate.fromYearMonthDay(2010, 7, 4))).isTrue(); } @Test // DATACASS-296 public void shouldCreateUpdateWithJodaLocalDateUsingCassandraDateCorrectly() { TypeWithJodaLocalDateMappedToDate typeWithLocalDate = new TypeWithJodaLocalDateMappedToDate(); typeWithLocalDate.localDate = new org.joda.time.LocalDate(2010, 7, 4); Update update = QueryBuilder.update("table"); mappingCassandraConverter.write(typeWithLocalDate, update); assertThat(getAssignmentValues(update)).contains(LocalDate.fromYearMonthDay(2010, 7, 4)); } @Test // DATACASS-296 public void shouldReadThreeTenBpLocalDateTimeUsingCassandraDateCorrectly() { Row rowMock = RowMockUtil.newRowMock(column("id", "my-id", DataType.ascii()), column("localDate", LocalDate.fromYearMonthDay(2010, 7, 4), DataType.date())); TypeWithThreeTenBpLocalDateMappedToDate result = mappingCassandraConverter .readRow(TypeWithThreeTenBpLocalDateMappedToDate.class, rowMock); assertThat(result.localDate).isNotNull(); assertThat(result.localDate.getYear()).isEqualTo(2010); assertThat(result.localDate.getMonthValue()).isEqualTo(7); assertThat(result.localDate.getDayOfMonth()).isEqualTo(4); } @Test // DATACASS-296 public void shouldCreateInsertWithThreeTenBpLocalDateUsingCassandraDateCorrectly() { TypeWithThreeTenBpLocalDateMappedToDate typeWithLocalDate = new TypeWithThreeTenBpLocalDateMappedToDate(); typeWithLocalDate.localDate = org.threeten.bp.LocalDate.of(2010, 7, 4); Insert insert = QueryBuilder.insertInto("table"); mappingCassandraConverter.write(typeWithLocalDate, insert); assertThat(getValues(insert).contains(LocalDate.fromYearMonthDay(2010, 7, 4))).isTrue(); } @Test // DATACASS-296 public void shouldCreateUpdateWithThreeTenBpLocalDateUsingCassandraDateCorrectly() { TypeWithThreeTenBpLocalDateMappedToDate typeWithLocalDate = new TypeWithThreeTenBpLocalDateMappedToDate(); typeWithLocalDate.localDate = org.threeten.bp.LocalDate.of(2010, 7, 4); Update update = QueryBuilder.update("table"); mappingCassandraConverter.write(typeWithLocalDate, update); assertThat(getAssignmentValues(update)).contains(LocalDate.fromYearMonthDay(2010, 7, 4)); } @Test // DATACASS-206 public void updateShouldUseSpecifiedColumnNames() { UserToken userToken = new UserToken(); userToken.setUserId(UUID.randomUUID()); userToken.setToken(UUID.randomUUID()); userToken.setAdminComment("admin comment"); userToken.setUserComment("user comment"); Update update = QueryBuilder.update("table"); mappingCassandraConverter.write(userToken, update); assertThat(getAssignments(update)).containsEntry("admincomment", "admin comment"); assertThat(getAssignments(update)).containsEntry("user_comment", "user comment"); assertThat(getWherePredicates(update)).containsEntry("user_id", userToken.getUserId()); } @Test // DATACASS-206 public void deleteShouldUseSpecifiedColumnNames() { UserToken userToken = new UserToken(); userToken.setUserId(UUID.randomUUID()); userToken.setToken(UUID.randomUUID()); userToken.setAdminComment("admin comment"); userToken.setUserComment("user comment"); Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write(userToken, delete.where()); assertThat(getWherePredicates(delete)).containsEntry("user_id", userToken.getUserId()); } @Test // DATACASS-308 public void shouldWriteWhereConditionUsingPlainId() { Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write("42", delete.where(), mappingContext.getRequiredPersistentEntity(Person.class)); assertThat(getWherePredicates(delete)).containsEntry("id", "42"); } @Test // DATACASS-308 public void shouldWriteWhereConditionUsingEntity() { Delete delete = QueryBuilder.delete().from("table"); Person person = new Person(); person.setId("42"); mappingCassandraConverter.write(person, delete.where(), mappingContext.getRequiredPersistentEntity(Person.class)); assertThat(getWherePredicates(delete)).containsEntry("id", "42"); } @Test(expected = IllegalArgumentException.class) // DATACASS-308 public void shouldFailWriteWhereConditionUsingEntityWithNullId() { Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write(new Person(), delete.where(), mappingContext.getRequiredPersistentEntity(Person.class)); } @Test // DATACASS-308 public void shouldWriteWhereConditionUsingMapId() { Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write(id("id", "42"), delete.where(), mappingContext.getRequiredPersistentEntity(Person.class)); assertThat(getWherePredicates(delete)).containsEntry("id", "42"); } @Test // DATACASS-308 public void shouldWriteWhereConditionForCompositeKeyUsingEntity() { Delete delete = QueryBuilder.delete().from("table"); TypeWithCompositeKey entity = new TypeWithCompositeKey(); entity.setFirstname("Walter"); entity.setLastname("White"); mappingCassandraConverter.write(entity, delete.where(), mappingContext.getRequiredPersistentEntity(TypeWithCompositeKey.class)); assertThat(getWherePredicates(delete)).containsEntry("firstname", "Walter"); assertThat(getWherePredicates(delete)).containsEntry("lastname", "White"); } @Test // DATACASS-308 public void shouldWriteWhereConditionForCompositeKeyUsingMapId() { Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write(id("firstname", "Walter").with("lastname", "White"), delete.where(), mappingContext.getRequiredPersistentEntity(TypeWithCompositeKey.class)); assertThat(getWherePredicates(delete)).containsEntry("firstname", "Walter"); assertThat(getWherePredicates(delete)).containsEntry("lastname", "White"); } @Test // DATACASS-308 public void shouldWriteWhereConditionForMapIdKeyUsingEntity() { Delete delete = QueryBuilder.delete().from("table"); TypeWithMapId entity = new TypeWithMapId(); entity.setFirstname("Walter"); entity.setLastname("White"); mappingCassandraConverter.write(entity, delete.where(), mappingContext.getRequiredPersistentEntity(TypeWithMapId.class)); assertThat(getWherePredicates(delete)).containsEntry("firstname", "Walter"); assertThat(getWherePredicates(delete)).containsEntry("lastname", "White"); } @Test // DATACASS-308 public void shouldWriteEnumWhereCondition() { Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write(Condition.MINT, delete.where(), mappingContext.getRequiredPersistentEntity(EnumPrimaryKey.class)); assertThat(getWherePredicates(delete)).containsEntry("condition", "MINT"); } @Test // DATACASS-308 public void shouldWriteWhereConditionForMapIdKeyUsingMapId() { Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write(id("firstname", "Walter").with("lastname", "White"), delete.where(), mappingContext.getRequiredPersistentEntity(TypeWithMapId.class)); assertThat(getWherePredicates(delete)).containsEntry("firstname", "Walter"); assertThat(getWherePredicates(delete)).containsEntry("lastname", "White"); } @Test // DATACASS-308 public void shouldWriteWhereConditionForTypeWithPkClassKeyUsingEntity() { Delete delete = QueryBuilder.delete().from("table"); CompositeKey key = new CompositeKey(); key.setFirstname("Walter"); key.setLastname("White"); TypeWithKeyClass entity = new TypeWithKeyClass(); entity.setKey(key); mappingCassandraConverter.write(entity, delete.where(), mappingContext.getRequiredPersistentEntity(TypeWithKeyClass.class)); assertThat(getWherePredicates(delete)).containsEntry("first_name", "Walter"); assertThat(getWherePredicates(delete)).containsEntry("lastname", "White"); } @Test(expected = IllegalArgumentException.class) // DATACASS-308 public void shouldFailWritingWhereConditionForTypeWithPkClassKeyUsingEntityWithNullId() { Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write(new TypeWithKeyClass(), delete.where(), mappingContext.getRequiredPersistentEntity(TypeWithKeyClass.class)); } @Test // DATACASS-308 public void shouldWriteWhereConditionForTypeWithPkClassKeyUsingKey() { Delete delete = QueryBuilder.delete().from("table"); CompositeKey key = new CompositeKey(); key.setFirstname("Walter"); key.setLastname("White"); mappingCassandraConverter.write(key, delete.where(), mappingContext.getRequiredPersistentEntity(TypeWithKeyClass.class)); assertThat(getWherePredicates(delete)).containsEntry("first_name", "Walter"); assertThat(getWherePredicates(delete)).containsEntry("lastname", "White"); } @Test // DATACASS-308 public void shouldWriteWhereConditionForTypeWithPkClassKeyUsingMapId() { Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write(id("firstname", "Walter").with("lastname", "White"), delete.where(), mappingContext.getRequiredPersistentEntity(TypeWithKeyClass.class)); assertThat(getWherePredicates(delete)).containsEntry("first_name", "Walter"); assertThat(getWherePredicates(delete)).containsEntry("lastname", "White"); } @Test(expected = IllegalArgumentException.class) // DATACASS-308 public void shouldFailWhereConditionForTypeWithPkClassKeyUsingMapIdHavingUnknownProperty() { Delete delete = QueryBuilder.delete().from("table"); mappingCassandraConverter.write(id("unknown", "Walter"), delete.where(), mappingContext.getRequiredPersistentEntity(TypeWithMapId.class)); } @SuppressWarnings("unchecked") private <T> List<T> getListValue(Insert statement) { List<Object> values = getValues(statement); return (List<T>) values.stream().filter(value -> value instanceof List).findFirst().orElse(null); } @SuppressWarnings("unchecked") private <T> Set<T> getSetValue(Insert statement) { List<Object> values = getValues(statement); return (Set<T>) values.stream().filter(value -> value instanceof Set).findFirst().orElse(null); } @SuppressWarnings("unchecked") private List<Object> getValues(Insert statement) { return (List<Object>) ReflectionTestUtils.getField(statement, "values"); } @SuppressWarnings("unchecked") private Collection<Object> getAssignmentValues(Update statement) { return getAssignments(statement).values(); } @SuppressWarnings("unchecked") private Map<String, Object> getAssignments(Update statement) { Map<String, Object> result = new LinkedHashMap<>(); Assignments assignments = (Assignments) ReflectionTestUtils.getField(statement, "assignments"); List<Assignment> listOfAssignments = (List<Assignment>) ReflectionTestUtils.getField(assignments, "assignments"); for (Assignment assignment : listOfAssignments) { result.put(assignment.getColumnName(), ReflectionTestUtils.getField(assignment, "value")); } return result; } private Collection<Object> getWhereValues(Update update) { return getWherePredicates(update.where()).values(); } private Collection<Object> getWhereValues(BuiltStatement where) { return getWherePredicates(where).values(); } private Map<String, Object> getWherePredicates(Update statement) { return getWherePredicates(statement.where()); } private Map<String, Object> getWherePredicates(Delete statement) { return getWherePredicates(statement.where()); } @SuppressWarnings("unchecked") private Map<String, Object> getWherePredicates(BuiltStatement where) { Map<String, Object> result = new LinkedHashMap<>(); List<Clause> clauses = (List<Clause>) ReflectionTestUtils.getField(where, "clauses"); for (Clause clause : clauses) { result.put(ReflectionTestUtils.invokeMethod(clause, "name"), ReflectionTestUtils.getField(clause, "value")); } return result; } @Table public static class UnsupportedEnumToOrdinalMapping { @PrimaryKey private String id; @CassandraType(type = Name.INT) private Condition asOrdinal; public String getId() { return id; } public void setId(String id) { this.id = id; } public Condition getAsOrdinal() { return asOrdinal; } public void setAsOrdinal(Condition asOrdinal) { this.asOrdinal = asOrdinal; } } @Table public static class WithEnumColumns { @PrimaryKey private String id; private Condition condition; public String getId() { return id; } public void setId(String id) { this.id = id; } public Condition getCondition() { return condition; } public void setCondition(Condition condition) { this.condition = condition; } } @PrimaryKeyClass public static class EnumCompositePrimaryKey implements Serializable { @PrimaryKeyColumn(ordinal = 1, type = PrimaryKeyType.PARTITIONED) private Condition condition; public EnumCompositePrimaryKey() {} public EnumCompositePrimaryKey(Condition condition) { this.condition = condition; } public Condition getCondition() { return condition; } public void setCondition(Condition condition) { this.condition = condition; } } @Table public static class EnumPrimaryKey { @PrimaryKey private Condition condition; public Condition getCondition() { return condition; } public void setCondition(Condition condition) { this.condition = condition; } } @Table public static class CompositeKeyThing { @PrimaryKey private EnumCompositePrimaryKey key; public CompositeKeyThing() {} public CompositeKeyThing(EnumCompositePrimaryKey key) { this.key = key; } public EnumCompositePrimaryKey getKey() { return key; } public void setKey(EnumCompositePrimaryKey key) { this.key = key; } } public enum Condition { MINT, USED } @Table public static class TypeWithLocalDate { @PrimaryKey private String id; java.time.LocalDate localDate; java.time.LocalDateTime localDateTime; List<java.time.LocalDate> list; Set<java.time.LocalDate> set; } /** * Uses Cassandra's {@link Name#DATE} which maps by default to {@link LocalDate} */ @Table @AllArgsConstructor public static class TypeWithLocalDateMappedToDate { @PrimaryKey private String id; @CassandraType(type = Name.DATE) java.time.LocalDate localDate; } /** * Uses Cassandra's {@link Name#DATE} which maps by default to Joda {@link LocalDate} */ @Table public static class TypeWithJodaLocalDateMappedToDate { @PrimaryKey private String id; @CassandraType(type = Name.DATE) org.joda.time.LocalDate localDate; } /** * Uses Cassandra's {@link Name#DATE} which maps by default to Joda {@link LocalDate} */ @Table public static class TypeWithThreeTenBpLocalDateMappedToDate { @PrimaryKey private String id; @CassandraType(type = Name.DATE) org.threeten.bp.LocalDate localDate; } @Table public static class TypeWithInstant { @PrimaryKey private String id; Instant instant; } @Table public static class TypeWithZoneId { @PrimaryKey private String id; ZoneId zoneId; } }