package org.mongodb.morphia.converters;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.junit.Assert;
import org.junit.Test;
import org.mongodb.morphia.TestBase;
import org.mongodb.morphia.annotations.Converters;
import org.mongodb.morphia.mapping.MappedField;
import org.mongodb.morphia.testutil.TestEntity;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
/**
* @author Uwe Schaefer
*/
public class CustomConverterInEmbedTest extends TestBase {
@Test
public void testConversionInList() throws Exception {
final FooConverter fc = new FooConverter();
getMorphia().getMapper().getConverters().addConverter(fc);
final E1 e = new E1();
e.foo.add(new Foo("bar"));
getDs().save(e);
Assert.assertTrue(fc.didConversion());
}
@Test
public void testConversionInMap() throws Exception {
final FooConverter fc = new FooConverter();
getMorphia().getMapper().getConverters().addConverter(fc);
E2 e = new E2();
e.foo.put("bar", new Foo("bar"));
getDs().save(e);
Assert.assertTrue(fc.didConversion());
e = getDs().find(E2.class).get();
Assert.assertNotNull(e.foo);
Assert.assertFalse(e.foo.isEmpty());
Assert.assertTrue(e.foo.containsKey("bar"));
Assert.assertEquals("bar", e.foo.get("bar").string);
}
@Test
public void testEmbeddedComplexArrayType() throws Exception {
ArrayBar bar = new ArrayBar();
bar.foo = new ArrayFoo("firstValue", "secondValue");
getDs().save(bar);
ArrayBar fromDb = getDs().get(ArrayBar.class, bar.getId());
assertThat("bar is not null", fromDb, notNullValue());
assertThat("foo is not null", fromDb.foo, notNullValue());
assertThat("foo has the correct first value", fromDb.foo.first(), equalTo("firstValue"));
assertThat("foo has the correct second value", fromDb.foo.second(), equalTo("secondValue"));
}
@Test
public void testEmbeddedComplexType() throws Exception {
ComplexBar bar = new ComplexBar();
bar.foo = new ComplexFoo("firstValue", "secondValue");
getDs().save(bar);
ComplexBar fromDb = getDs().get(ComplexBar.class, bar.getId());
assertThat("bar is not null", fromDb, notNullValue());
assertThat("foo is not null", fromDb.foo, notNullValue());
assertThat("foo has the correct first value", fromDb.foo.first(), equalTo("firstValue"));
assertThat("foo has the correct second value", fromDb.foo.second(), equalTo("secondValue"));
}
//FIXME issue 101
public static class E1 extends TestEntity {
private final List<Foo> foo = new LinkedList<Foo>();
}
public static class E2 extends TestEntity {
private final Map<String, Foo> foo = new HashMap<String, Foo>();
}
// unknown type to convert
public static class Foo {
private String string;
Foo() {
}
public Foo(final String string) {
this.string = string;
}
@Override
public String toString() {
return string;
}
}
public static class FooConverter extends TypeConverter implements SimpleValueConverter {
private boolean done;
public FooConverter() {
super(Foo.class);
}
@Override
public Object decode(final Class targetClass, final Object fromDBObject, final MappedField optionalExtraInfo) {
return new Foo((String) fromDBObject);
}
public boolean didConversion() {
return done;
}
@Override
public Object encode(final Object value, final MappedField optionalExtraInfo) {
done = true;
return value.toString();
}
}
/**
* A type that contains a complex custom type, represented as an object.
*
* @author Christian Trimble
*/
@Converters(ComplexFooConverter.class)
public static class ComplexBar extends TestEntity {
private ComplexFoo foo;
}
/**
* A type that contains a complex custom type, represented as an array.
*
* @author Christian Trimble
*/
@Converters(ComplexArrayFooConverter.class)
public static class ArrayBar extends TestEntity {
private ArrayFoo foo;
}
/**
* A complex embedded type, represented as an object
*
* @author Christian Trimble
*/
public static class ComplexFoo {
private String first;
private String second;
ComplexFoo() {
}
public ComplexFoo(final String first, final String second) {
this.first = first;
this.second = second;
}
String first() {
return first;
}
String second() {
return second;
}
}
/**
* A complex embedded type, represented as an array
*
* @author Christian Trimble
*/
public static class ArrayFoo {
private String first;
private String second;
ArrayFoo() {
}
public ArrayFoo(final String first, final String second) {
this.first = first;
this.second = second;
}
String first() {
return first;
}
String second() {
return second;
}
}
/**
* A converter that does not implement SimpleValueConverter and converts ComplexFoo into an object type.
*
* @author Christian Trimble
*/
public static class ComplexFooConverter extends TypeConverter {
public ComplexFooConverter() {
super(ComplexFoo.class);
}
@Override
public Object decode(final Class targetClass, final Object fromDBObject, final MappedField optionalExtraInfo) {
DBObject dbObject = (DBObject) fromDBObject;
return new ComplexFoo((String) dbObject.get("first"), (String) dbObject.get("second"));
}
@Override
public Object encode(final Object value, final MappedField optionalExtraInfo) {
ComplexFoo complex = (ComplexFoo) value;
BasicDBObject dbObject = new BasicDBObject();
dbObject.put("first", complex.first());
dbObject.put("second", complex.second());
return dbObject;
}
}
/**
* A converter that does not implement SimpleValueConverter and converts ArrayFoo into an array type.
*
* @author Christian Trimble
*/
public static class ComplexArrayFooConverter extends TypeConverter {
public ComplexArrayFooConverter() {
super(ArrayFoo.class);
}
@Override
public Object decode(final Class targetClass, final Object fromDBObject, final MappedField optionalExtraInfo) {
BasicDBList dbObject = (BasicDBList) fromDBObject;
return new ArrayFoo((String) dbObject.get(1), (String) dbObject.get(2));
}
@Override
public Object encode(final Object value, final MappedField optionalExtraInfo) {
ArrayFoo complex = (ArrayFoo) value;
BasicDBList dbObject = new BasicDBList();
dbObject.put(1, complex.first());
dbObject.put(2, complex.second());
return dbObject;
}
}
}