/*
* Copyright 2010-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.mongodb.repository.support;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.domain.ExampleMatcher.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.ExampleMatcher.*;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.repository.Address;
import org.springframework.data.mongodb.repository.Person;
import org.springframework.data.mongodb.repository.Person.Sex;
import org.springframework.data.mongodb.repository.User;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.util.ReflectionTestUtils;
/**
* @author A. B. M. Kowser
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
public class SimpleMongoRepositoryTests {
@Autowired private MongoTemplate template;
private Person oliver, dave, carter, boyd, stefan, leroi, alicia;
private List<Person> all;
private MongoEntityInformation<Person, String> personEntityInformation = new CustomizedPersonInformation();
private SimpleMongoRepository<Person, String> repository;
@Before
public void setUp() {
repository = new SimpleMongoRepository<Person, String>(personEntityInformation, template);
repository.deleteAll();
oliver = new Person("Oliver August", "Matthews", 4);
dave = new Person("Dave", "Matthews", 42);
carter = new Person("Carter", "Beauford", 49);
boyd = new Person("Boyd", "Tinsley", 45);
stefan = new Person("Stefan", "Lessard", 34);
leroi = new Person("Leroi", "Moore", 41);
alicia = new Person("Alicia", "Keys", 30, Sex.FEMALE);
all = repository.saveAll(Arrays.asList(oliver, dave, carter, boyd, stefan, leroi, alicia));
}
@Test
public void findALlFromCustomCollectionName() {
assertThat(repository.findAll()).hasSize(all.size());
}
@Test
public void findOneFromCustomCollectionName() {
assertThat(repository.findById(dave.getId()).get()).isEqualTo(dave);
}
@Test
public void deleteFromCustomCollectionName() {
repository.delete(dave);
assertThat(repository.findAll()).hasSize(all.size() - 1).doesNotContain(dave);
}
@Test
public void deleteByIdFromCustomCollectionName() {
repository.deleteById(dave.getId());
assertThat(repository.findAll()).hasSize(all.size() - 1).doesNotContain(dave);
}
@Test // DATAMONGO-1054
public void shouldInsertSingle() {
String randomId = UUID.randomUUID().toString();
Person person1 = new Person("First1" + randomId, "Last2" + randomId, 42);
person1 = repository.insert(person1);
assertThat(repository.findById(person1.getId())).contains(person1);
}
@Test // DATAMONGO-1054
public void shouldInsertMultipleFromList() {
String randomId = UUID.randomUUID().toString();
Map<String, Person> idToPerson = new HashMap<String, Person>();
List<Person> persons = new ArrayList<Person>();
for (int i = 0; i < 10; i++) {
Person person = new Person("First" + i + randomId, "Last" + randomId + i, 42 + i);
idToPerson.put(person.getId(), person);
persons.add(person);
}
List<Person> saved = repository.insert(persons);
assertThat(saved).hasSize(persons.size());
assertThatAllReferencePersonsWereStoredCorrectly(idToPerson, saved);
}
@Test // DATAMONGO-1054
public void shouldInsertMutlipleFromSet() {
String randomId = UUID.randomUUID().toString();
Map<String, Person> idToPerson = new HashMap<String, Person>();
Set<Person> persons = new HashSet<Person>();
for (int i = 0; i < 10; i++) {
Person person = new Person("First" + i + randomId, "Last" + i + randomId, 42 + i);
idToPerson.put(person.getId(), person);
persons.add(person);
}
List<Person> saved = repository.insert(persons);
assertThat(saved).hasSize(persons.size());
assertThatAllReferencePersonsWereStoredCorrectly(idToPerson, saved);
}
@Test // DATAMONGO-1245, DATAMONGO-1464
public void findByExampleShouldLookUpEntriesCorrectly() {
Person sample = new Person();
sample.setLastname("Matthews");
trimDomainType(sample, "id", "createdAt", "email");
Page<Person> result = repository.findAll(Example.of(sample), PageRequest.of(0, 10));
assertThat(result.getContent()).hasSize(2).contains(dave, oliver);
assertThat(result.getTotalPages()).isEqualTo(1);
}
@Test // DATAMONGO-1464
public void findByExampleMultiplePagesShouldLookUpEntriesCorrectly() {
Person sample = new Person();
sample.setLastname("Matthews");
trimDomainType(sample, "id", "createdAt", "email");
Page<Person> result = repository.findAll(Example.of(sample), PageRequest.of(0, 1));
assertThat(result.getContent()).hasSize(1);
assertThat(result.getTotalPages()).isEqualTo(2);
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldLookUpEntriesCorrectly() {
Person sample = new Person();
sample.setLastname("Matthews");
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.findAll(Example.of(sample))).hasSize(2).contains(dave, oliver);
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingNestedObject() {
dave.setAddress(new Address("1600 Pennsylvania Ave NW", "20500", "Washington"));
repository.save(dave);
oliver.setAddress(new Address("East Capitol St NE & First St SE", "20004", "Washington"));
repository.save(oliver);
Person sample = new Person();
sample.setAddress(dave.getAddress());
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.findAll(Example.of(sample))).hasSize(1).contains(dave);
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingPartialNestedObject() {
dave.setAddress(new Address("1600 Pennsylvania Ave NW", "20500", "Washington"));
repository.save(dave);
oliver.setAddress(new Address("East Capitol St NE & First St SE", "20004", "Washington"));
repository.save(oliver);
Person sample = new Person();
sample.setAddress(new Address(null, null, "Washington"));
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.findAll(Example.of(sample))).hasSize(2).contains(dave, oliver);
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldNotFindEntriesWhenUsingPartialNestedObjectInStrictMode() {
dave.setAddress(new Address("1600 Pennsylvania Ave NW", "20500", "Washington"));
repository.save(dave);
Person sample = new Person();
sample.setAddress(new Address(null, null, "Washington"));
trimDomainType(sample, "id", "createdAt", "email");
Example<Person> example = Example.of(sample, matching().withIncludeNullValues());
assertThat(repository.findAll(example)).isEmpty();
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldLookUpEntriesCorrectlyWhenUsingNestedObjectInStrictMode() {
dave.setAddress(new Address("1600 Pennsylvania Ave NW", "20500", "Washington"));
repository.save(dave);
Person sample = new Person();
sample.setAddress(dave.getAddress());
trimDomainType(sample, "id", "createdAt", "email");
Example<Person> example = Example.of(sample, matching().withIncludeNullValues());
assertThat(repository.findAll(example)).hasSize(1).contains(dave);
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldRespectStringMatchMode() {
Person sample = new Person();
sample.setLastname("Mat");
trimDomainType(sample, "id", "createdAt", "email");
Example<Person> example = Example.of(sample, matching().withStringMatcher(StringMatcher.STARTING));
assertThat(repository.findAll(example)).hasSize(2).contains(dave, oliver);
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldResolveDbRefCorrectly() {
User user = new User();
user.setId("c0nf1ux");
user.setUsername("conflux");
template.save(user);
Person megan = new Person("megan", "tarash");
megan.setCreator(user);
repository.save(megan);
Person sample = new Person();
sample.setCreator(user);
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.findAll(Example.of(sample))).hasSize(1).contains(megan);
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldResolveLegacyCoordinatesCorrectly() {
Person megan = new Person("megan", "tarash");
megan.setLocation(new Point(41.85003D, -87.65005D));
repository.save(megan);
Person sample = new Person();
sample.setLocation(megan.getLocation());
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.findAll(Example.of(sample))).hasSize(1).contains(megan);
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldResolveGeoJsonCoordinatesCorrectly() {
Person megan = new Person("megan", "tarash");
megan.setLocation(new GeoJsonPoint(41.85003D, -87.65005D));
repository.save(megan);
Person sample = new Person();
sample.setLocation(megan.getLocation());
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.findAll(Example.of(sample))).hasSize(1).contains(megan);
}
@Test // DATAMONGO-1245
public void findAllByExampleShouldProcessInheritanceCorrectly() {
PersonExtended reference = new PersonExtended();
reference.setLastname("Matthews");
repository.save(reference);
PersonExtended sample = new PersonExtended();
sample.setLastname("Matthews");
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.findAll(Example.of(sample))).hasSize(1).contains(reference);
}
@Test // DATAMONGO-1245
public void findOneByExampleShouldLookUpEntriesCorrectly() {
Person sample = new Person();
sample.setFirstname("Dave");
sample.setLastname("Matthews");
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.findOne(Example.of(sample))).isPresent().contains(dave);
}
@Test // DATAMONGO-1245
public void existsByExampleShouldLookUpEntriesCorrectly() {
Person sample = new Person();
sample.setFirstname("Dave");
sample.setLastname("Matthews");
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.exists(Example.of(sample))).isTrue();
}
@Test // DATAMONGO-1245
public void countByExampleShouldLookUpEntriesCorrectly() {
Person sample = new Person();
sample.setLastname("Matthews");
trimDomainType(sample, "id", "createdAt", "email");
assertThat(repository.count(Example.of(sample))).isEqualTo(2L);
}
private void assertThatAllReferencePersonsWereStoredCorrectly(Map<String, Person> references, List<Person> saved) {
for (Person person : saved) {
Person reference = references.get(person.getId());
assertThat(person).isEqualTo(reference);
}
}
private void trimDomainType(Object source, String... attributes) {
for (String attribute : attributes) {
ReflectionTestUtils.setField(source, attribute, null);
}
}
private static class CustomizedPersonInformation implements MongoEntityInformation<Person, String> {
@Override
public boolean isNew(Person entity) {
return entity.getId() == null;
}
@Override
public Optional<String> getId(Person entity) {
return Optional.ofNullable(entity.getId());
}
@Override
public Class<String> getIdType() {
return String.class;
}
@Override
public Class<Person> getJavaType() {
return Person.class;
}
@Override
public String getCollectionName() {
return "customizedPerson";
}
@Override
public String getIdAttribute() {
return "id";
}
}
@Document
static class PersonExtended extends Person {}
}