/*
* Copyright 2015-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.core.convert;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.domain.Example.*;
import static org.springframework.data.domain.ExampleMatcher.*;
import static org.springframework.data.mongodb.core.DocumentTestUtils.*;
import static org.springframework.data.mongodb.test.util.IsBsonObject.*;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import org.bson.conversions.Bson;
import org.hamcrest.core.Is;
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.data.annotation.Id;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers;
import org.springframework.data.domain.ExampleMatcher.StringMatcher;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.QueryMapperUnitTests.ClassWithGeoTypes;
import org.springframework.data.mongodb.core.convert.QueryMapperUnitTests.WithDBRef;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.test.util.IsBsonObject;
/**
* @author Christoph Strobl
* @author Mark Paluch
*/
@RunWith(MockitoJUnitRunner.class)
public class MongoExampleMapperUnitTests {
MongoExampleMapper mapper;
MongoMappingContext context;
MappingMongoConverter converter;
@Mock MongoDbFactory factory;
@Before
public void setUp() {
this.context = new MongoMappingContext();
this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context);
this.converter.afterPropertiesSet();
this.mapper = new MongoExampleMapper(converter);
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIdIsSet() {
FlatDocument probe = new FlatDocument();
probe.id = "steelheart";
IsBsonObject<Bson> expected = isBsonObject().containing("_id", "steelheart");
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenMultipleValuesSet() {
FlatDocument probe = new FlatDocument();
probe.id = "steelheart";
probe.stringValue = "firefight";
probe.intValue = 100;
IsBsonObject<Bson> expected = isBsonObject().//
containing("_id", "steelheart").//
containing("stringValue", "firefight").//
containing("intValue", 100);
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIdIsNotSet() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "firefight";
probe.intValue = 100;
IsBsonObject<Bson> expected = isBsonObject().//
containing("stringValue", "firefight").//
containing("intValue", 100);
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenListHasValues() {
FlatDocument probe = new FlatDocument();
probe.listOfString = Arrays.asList("Prof", "Tia", "David");
List list = (Arrays.asList("Prof", "Tia", "David"));
IsBsonObject<Bson> expected = isBsonObject().//
containing("listOfString", list);
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenFieldNameIsCustomized() {
FlatDocument probe = new FlatDocument();
probe.customNamedField = "Mitosis";
IsBsonObject<Bson> expected = isBsonObject().containing("custom_field_name", "Mitosis");
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(FlatDocument.class)),
is(expected));
}
@Test // DATAMONGO-1245
public void typedExampleShouldContainTypeRestriction() {
WrapperDocument probe = new WrapperDocument();
probe.flatDoc = new FlatDocument();
probe.flatDoc.stringValue = "conflux";
org.bson.Document document = mapper.getMappedExample(Example.of(probe),
context.getRequiredPersistentEntity(WrapperDocument.class));
assertThat(document,
isBsonObject().containing("_class", new org.bson.Document("$in", new String[] { probe.getClass().getName() })));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedAsFlatMapWhenGivenNestedElementsWithLenientMatchMode() {
WrapperDocument probe = new WrapperDocument();
probe.flatDoc = new FlatDocument();
probe.flatDoc.stringValue = "conflux";
IsBsonObject<Bson> expected = isBsonObject().containing("flatDoc\\.stringValue", "conflux");
assertThat(mapper.getMappedExample(of(probe), context.getRequiredPersistentEntity(WrapperDocument.class)),
is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedAsExactObjectWhenGivenNestedElementsWithStrictMatchMode() {
WrapperDocument probe = new WrapperDocument();
probe.flatDoc = new FlatDocument();
probe.flatDoc.stringValue = "conflux";
Example<?> example = Example.of(probe, matching().withIncludeNullValues());
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(WrapperDocument.class)), //
isBsonObject().containing("flatDoc.stringValue", "conflux"));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeIsStarting() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "firefight";
probe.intValue = 100;
Example<?> example = Example.of(probe, matching().withStringMatcher(StringMatcher.STARTING));
IsBsonObject<Bson> expected = isBsonObject().//
containing("stringValue.$regex", "^firefight").//
containing("intValue", 100);
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeContainingDotsWhenStringMatchModeIsStarting() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "fire.ight";
probe.intValue = 100;
Example<?> example = Example.of(probe, matching().withStringMatcher(StringMatcher.STARTING));
IsBsonObject<Bson> expected = isBsonObject().//
containing("stringValue.$regex", "^" + Pattern.quote("fire.ight")).//
containing("intValue", 100);
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeIsEnding() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "firefight";
probe.intValue = 100;
Example<?> example = Example.of(probe, matching().withStringMatcher(StringMatcher.ENDING));
IsBsonObject<Bson> expected = isBsonObject().//
containing("stringValue.$regex", "firefight$").//
containing("intValue", 100);
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenStringMatchModeRegex() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "firefight";
probe.customNamedField = "^(cat|dog).*shelter\\d?";
Example<?> example = Example.of(probe, matching().withStringMatcher(StringMatcher.REGEX));
IsBsonObject<Bson> expected = isBsonObject().//
containing("stringValue.$regex", "firefight").//
containing("custom_field_name.$regex", "^(cat|dog).*shelter\\d?");
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIgnoreCaseEnabledAndMatchModeSet() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "firefight";
probe.intValue = 100;
Example<?> example = Example.of(probe, matching().withStringMatcher(StringMatcher.ENDING).withIgnoreCase());
IsBsonObject<Bson> expected = isBsonObject().//
containing("stringValue", new org.bson.Document("$regex", "firefight$").append("$options", "i")).//
containing("intValue", 100);
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyForFlatTypeWhenIgnoreCaseEnabled() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "firefight";
probe.intValue = 100;
Example<?> example = Example.of(probe, matching().withIgnoreCase());
IsBsonObject<Bson> expected = isBsonObject().//
containing("stringValue", new org.bson.Document("$regex", Pattern.quote("firefight")).append("$options", "i")).//
containing("intValue", 100);
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedWhenContainingDBRef() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "steelheart";
probe.referenceDocument = new ReferenceDocument();
probe.referenceDocument.id = "200";
org.bson.Document document = mapper.getMappedExample(of(probe),
context.getRequiredPersistentEntity(WithDBRef.class));
com.mongodb.DBRef reference = getTypedValue(document, "referenceDocument", com.mongodb.DBRef.class);
assertThat(reference.getId(), Is.<Object> is("200"));
assertThat(reference.getCollectionName(), is("refDoc"));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedWhenDBRefIsNull() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "steelheart";
org.bson.Document document = mapper.getMappedExample(of(probe),
context.getRequiredPersistentEntity(FlatDocument.class));
assertThat(document, isBsonObject().containing("stringValue", "steelheart"));
}
@Test // DATAMONGO-1245
public void exampleShouldBeMappedCorrectlyWhenContainingLegacyPoint() {
ClassWithGeoTypes probe = new ClassWithGeoTypes();
probe.legacyPoint = new Point(10D, 20D);
org.bson.Document document = mapper.getMappedExample(of(probe),
context.getRequiredPersistentEntity(WithDBRef.class));
assertThat(document.get("legacyPoint.x"), Is.<Object> is(10D));
assertThat(document.get("legacyPoint.y"), Is.<Object> is(20D));
}
@Test // DATAMONGO-1245
public void mappingShouldExcludeFieldWithCustomNameCorrectly() {
FlatDocument probe = new FlatDocument();
probe.customNamedField = "foo";
probe.intValue = 10;
probe.stringValue = "string";
Example<?> example = Example.of(probe, matching().withIgnorePaths("customNamedField"));
IsBsonObject<Bson> expected = isBsonObject().//
containing("stringValue", "string").//
containing("intValue", 10);
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
}
@Test // DATAMONGO-1245
public void mappingShouldExcludeFieldCorrectly() {
FlatDocument probe = new FlatDocument();
probe.customNamedField = "foo";
probe.intValue = 10;
probe.stringValue = "string";
Example<?> example = Example.of(probe, matching().withIgnorePaths("stringValue"));
IsBsonObject<Bson> expected = isBsonObject().//
containing("custom_field_name", "foo").//
containing("intValue", 10);
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
}
@Test // DATAMONGO-1245
public void mappingShouldExcludeNestedFieldCorrectly() {
WrapperDocument probe = new WrapperDocument();
probe.flatDoc = new FlatDocument();
probe.flatDoc.customNamedField = "foo";
probe.flatDoc.intValue = 10;
probe.flatDoc.stringValue = "string";
Example<?> example = Example.of(probe, matching().withIgnorePaths("flatDoc.stringValue"));
IsBsonObject<Bson> expected = isBsonObject().//
containing("flatDoc\\.custom_field_name", "foo").//
containing("flatDoc\\.intValue", 10);
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(WrapperDocument.class)),
is(expected));
}
@Test // DATAMONGO-1245
public void mappingShouldExcludeNestedFieldWithCustomNameCorrectly() {
WrapperDocument probe = new WrapperDocument();
probe.flatDoc = new FlatDocument();
probe.flatDoc.customNamedField = "foo";
probe.flatDoc.intValue = 10;
probe.flatDoc.stringValue = "string";
Example<?> example = Example.of(probe, matching().withIgnorePaths("flatDoc.customNamedField"));
IsBsonObject<Bson> expected = isBsonObject().//
containing("flatDoc\\.stringValue", "string").//
containing("flatDoc\\.intValue", 10);
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(WrapperDocument.class)),
is(expected));
}
@Test // DATAMONGO-1245
public void mappingShouldFavorFieldSpecificationStringMatcherOverDefaultStringMatcher() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "firefight";
probe.customNamedField = "steelheart";
Example<?> example = Example.of(probe, matching().withMatcher("stringValue", GenericPropertyMatchers.contains()));
IsBsonObject<Bson> expected = isBsonObject().//
containing("stringValue.$regex", ".*firefight.*").//
containing("custom_field_name", "steelheart");
assertThat(mapper.getMappedExample(example, context.getRequiredPersistentEntity(FlatDocument.class)), is(expected));
}
@Test // DATAMONGO-1245
public void mappingShouldIncludePropertiesFromHierarchicalDocument() {
HierachicalDocument probe = new HierachicalDocument();
probe.stringValue = "firefight";
probe.customNamedField = "steelheart";
probe.anotherStringValue = "calamity";
org.bson.Document document = mapper.getMappedExample(of(probe),
context.getRequiredPersistentEntity(FlatDocument.class));
assertThat(document, isBsonObject().containing("anotherStringValue", "calamity"));
}
@Test // DATAMONGO-1459
public void mapsAnyMatchingExampleCorrectly() {
FlatDocument probe = new FlatDocument();
probe.stringValue = "firefight";
probe.customNamedField = "steelheart";
Example<FlatDocument> example = Example.of(probe, ExampleMatcher.matchingAny());
assertThat(mapper.getMappedExample(example), isBsonObject().containing("$or").containing("_class"));
}
static class FlatDocument {
@Id String id;
String stringValue;
@Field("custom_field_name") String customNamedField;
Integer intValue;
List<String> listOfString;
@DBRef ReferenceDocument referenceDocument;
}
static class HierachicalDocument extends FlatDocument {
String anotherStringValue;
}
static class WrapperDocument {
@Id String id;
FlatDocument flatDoc;
}
@Document(collection = "refDoc")
static class ReferenceDocument {
@Id String id;
String value;
}
}