/* * Copyright 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.mockito.Matchers.any; import static org.mockito.Mockito.*; import lombok.AllArgsConstructor; import java.util.Collection; import java.util.Collections; import java.util.Currency; import java.util.List; import java.util.Locale; import java.util.stream.Collectors; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.cassandra.core.cql.CqlIdentifier; import org.springframework.data.annotation.Id; import org.springframework.data.cassandra.core.query.ColumnName; import org.springframework.data.cassandra.core.query.Columns; import org.springframework.data.cassandra.core.query.Columns.Selector; import org.springframework.data.cassandra.core.query.Criteria; import org.springframework.data.cassandra.core.query.CriteriaDefinition; import org.springframework.data.cassandra.core.query.CriteriaDefinition.Operators; import org.springframework.data.cassandra.core.query.Filter; import org.springframework.data.cassandra.core.query.Query; import org.springframework.data.cassandra.domain.TypeWithKeyClass; import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext; import org.springframework.data.cassandra.mapping.CassandraPersistentEntity; import org.springframework.data.cassandra.mapping.Column; import org.springframework.data.cassandra.mapping.UserDefinedType; import org.springframework.data.cassandra.mapping.UserTypeResolver; import org.springframework.data.cassandra.support.UserTypeBuilder; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Order; import com.datastax.driver.core.DataType; import com.datastax.driver.core.UDTValue; import com.datastax.driver.core.UserType; /** * Unit tests for {@link QueryMapper}. * * @author Mark Paluch */ @RunWith(MockitoJUnitRunner.class) public class QueryMapperUnitTests { BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext(); CassandraPersistentEntity<?> persistentEntity; MappingCassandraConverter cassandraConverter; QueryMapper queryMapper; @Mock UserTypeResolver userTypeResolver; UserType userType = UserTypeBuilder.forName("address").withField("street", DataType.varchar()).build(); @Before public void before() throws Exception { CassandraCustomConversions customConversions = new CassandraCustomConversions(Collections.singletonList(CurrencyConverter.INSTANCE)); mappingContext.setCustomConversions(customConversions); mappingContext.setUserTypeResolver(userTypeResolver); cassandraConverter = new MappingCassandraConverter(mappingContext); cassandraConverter.setCustomConversions(customConversions); cassandraConverter.afterPropertiesSet(); queryMapper = new QueryMapper(cassandraConverter); when(userTypeResolver.resolveType(any(CqlIdentifier.class))).thenReturn(userType); persistentEntity = mappingContext.getRequiredPersistentEntity(Person.class); } @Test // DATACASS-343 public void shouldMapSimpleQuery() { Query query = Query.query(Criteria.where("foo_name").is("bar")); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.EQ); assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isEqualTo("bar"); } @Test // DATACASS-343 public void shouldMapEnumToString() { Query query = Query.query(Criteria.where("foo_name").is(State.Active)); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(String.class).isEqualTo("Active"); } @Test // DATACASS-343 public void shouldMapEnumToNumber() { Query query = Query.query(Criteria.where("number").is(State.Inactive)); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(Integer.class).isEqualTo(1); } @Test // DATACASS-343 public void shouldMapEnumToNumberIn() { Query query = Query.query(Criteria.where("number").in(State.Inactive)); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(Collection.class) .isEqualTo(Collections.singletonList(1)); } @Test // DATACASS-343 public void shouldMapApplyingCustomConversion() { Query query = Query.query(Criteria.where("foo_name").is(Currency.getInstance("EUR"))); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.EQ); assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isEqualTo("Euro"); } @Test // DATACASS-343 public void shouldMapApplyingCustomConversionInCollection() { Query query = Query.query(Criteria.where("foo_name").in(Currency.getInstance("EUR"))); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.IN); assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isEqualTo(Collections.singletonList("Euro")); } @Test // DATACASS-343 public void shouldMapApplyingUdtValueConversion() { Query query = Query.query(Criteria.where("address").is(new Address("21 Jump-Street"))); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.EQ); assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(UDTValue.class); assertThat(mappedCriteriaDefinition.getPredicate().getValue().toString()).isEqualTo("{street:'21 Jump-Street'}"); } @Test // DATACASS-343 public void shouldMapApplyingUdtValueCollectionConversion() { Query query = Query.query(Criteria.where("address").in(new Address("21 Jump-Street"))); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.IN); assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(Collection.class); assertThat(mappedCriteriaDefinition.getPredicate().getValue().toString()).isEqualTo("[{street:'21 Jump-Street'}]"); } @Test // DATACASS-343 public void shouldMapCollectionApplyingUdtValueCollectionConversion() { Query query = Query.query(Criteria.where("addresses").in(new Address("21 Jump-Street"))); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getPredicate().getOperator()).isEqualTo(Operators.IN); assertThat(mappedCriteriaDefinition.getPredicate().getValue()).isInstanceOf(Collection.class); assertThat(mappedCriteriaDefinition.getPredicate().getValue().toString()).isEqualTo("[{street:'21 Jump-Street'}]"); } @Test // DATACASS-343 public void shouldMapPropertyToColumnName() { Query query = Query.query(Criteria.where("firstName").is("bar")); Filter mappedObject = queryMapper.getMappedObject(query, persistentEntity); CriteriaDefinition mappedCriteriaDefinition = mappedObject.iterator().next(); assertThat(mappedCriteriaDefinition.getColumnName()).isEqualTo(ColumnName.from(CqlIdentifier.cqlId("first_name"))); assertThat(mappedCriteriaDefinition.getColumnName().toString()).isEqualTo("first_name"); } @Test // DATACASS-343 public void shouldCreateSelectExpression() { List<Selector> selectors = queryMapper.getMappedSelectors(Columns.empty(), persistentEntity); assertThat(selectors).isEmpty(); } @Test // DATACASS-343 public void shouldCreateSelectExpressionWithTTL() { List<String> selectors = queryMapper .getMappedSelectors(Columns.from("number", "foo").ttl("firstName"), mappingContext.getRequiredPersistentEntity(Person.class)) .stream().map(Selector::toString).collect(Collectors.toList()); assertThat(selectors).contains("number").contains("foo").contains("TTL(first_name)"); } @Test // DATACASS-343 public void shouldIncludeColumnsSelectExpressionWithTTL() { List<String> selectors = queryMapper.getMappedColumnNames(Columns.from("number", "foo").ttl("firstName"), persistentEntity); assertThat(selectors).contains("number").contains("foo").hasSize(2); } @Test // DATACASS-343 public void shouldMapQueryWithCompositePrimaryKeyClass() { Filter filter = Filter.from(Criteria.where("key.firstname").is("foo")); Filter mappedObject = queryMapper.getMappedObject(filter, mappingContext.getRequiredPersistentEntity(TypeWithKeyClass.class)); assertThat(mappedObject).contains(Criteria.where("first_name").is("foo")); } @Test // DATACASS-343 public void shouldMapSortWithCompositePrimaryKeyClass() { Sort sort = Sort.by("key.firstname"); Sort mappedObject = queryMapper.getMappedSort(sort, mappingContext.getRequiredPersistentEntity(TypeWithKeyClass.class)); assertThat(mappedObject).contains(new Order(Direction.ASC, "first_name")); } @Test(expected = IllegalArgumentException.class) // DATACASS-343 public void shouldFailMappingSortByCompositePrimaryKeyClass() { Sort sort = Sort.by("key"); queryMapper.getMappedSort(sort, mappingContext.getRequiredPersistentEntity(TypeWithKeyClass.class)); } @Test // DATACASS-343 public void shouldMapColumnWithCompositePrimaryKeyClass() { Columns columnNames = Columns.from("key.firstname"); List<String> mappedObject = queryMapper.getMappedColumnNames(columnNames, mappingContext.getRequiredPersistentEntity(TypeWithKeyClass.class)); assertThat(mappedObject).contains("first_name"); } static class Person { @Id String id; Address address; List<Address> addresses; Currency currency; State state; Integer number; @Column("first_name") String firstName; } @UserDefinedType @AllArgsConstructor static class Address { String street; } enum State { Active, Inactive; } }