package org.simpleflatmapper.test.map.mapper;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.junit.Assert;
import org.junit.Test;
import org.simpleflatmapper.map.FieldMapper;
import org.simpleflatmapper.map.Mapper;
import org.simpleflatmapper.map.MapperBuildingException;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.reflect.meta.PropertyMeta;
import org.simpleflatmapper.test.beans.DbListObject;
import org.simpleflatmapper.test.map.SampleFieldKey;
import org.simpleflatmapper.map.context.KeySourceGetter;
import org.simpleflatmapper.map.context.MappingContextFactoryBuilder;
import org.simpleflatmapper.map.mapper.*;
import org.simpleflatmapper.map.property.DefaultValueProperty;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.map.property.GetterProperty;
import org.simpleflatmapper.reflect.Getter;
import org.simpleflatmapper.reflect.ReflectionService;
import org.simpleflatmapper.reflect.getter.GetterFactory;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.reflect.meta.DefaultPropertyNameMatcher;
import org.simpleflatmapper.test.beans.DbFinal1DeepObject;
import org.simpleflatmapper.test.beans.DbFinalObject;
import org.simpleflatmapper.test.beans.DbObject;
import org.simpleflatmapper.test.beans.DbObjectConstructorAndSetter;
import org.simpleflatmapper.test.beans.DbPartialFinalObject;
import org.simpleflatmapper.test.beans.FinalObjectWith1ParamConstruction;
import org.simpleflatmapper.test.beans.FinalObjectWith1ParamConstructionWithLoop;
import org.simpleflatmapper.test.beans.ObjectWith1ParamConstruction;
import org.simpleflatmapper.test.beans.ObjectWith1ParamConstructionWithLoop;
import org.simpleflatmapper.tuple.Tuple2;
import org.simpleflatmapper.util.ArrayEnumarable;
import org.simpleflatmapper.util.ConstantPredicate;
import org.simpleflatmapper.util.ConstantUnaryFactory;
import org.simpleflatmapper.util.Enumarable;
import org.simpleflatmapper.util.Predicate;
import org.simpleflatmapper.util.Supplier;
import org.simpleflatmapper.util.TypeHelper;
import org.simpleflatmapper.util.TypeReference;
import org.simpleflatmapper.util.UnaryFactory;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
//IFJAVA8_START
import java.util.Optional;
//IFJAVA8_END
import static org.junit.Assert.*;
public class AbstractMapperBuilderTest {
@Test
public void testConversionDateToJodaTime() {
ClassMeta<List<DateTime>> classMeta =
ReflectionService.disableAsm().<List<DateTime>>getClassMeta(new TypeReference<List<DateTime>>() {}.getType());
Mapper<Object[] , List<DateTime>> mapper =
new SampleMapperBuilder<List<DateTime>>(classMeta)
.addMapping(new SampleFieldKey("0", 0, new Class[0], Date.class)).mapper();
Object[] objects = new Object[] { new Date() };
List<DateTime> map = mapper.map(objects);
assertEquals(objects[0], map.get(0).toDate());
}
@Test
public void testConversionCharacterToJodaTime() {
ClassMeta<List<DateTime>> classMeta =
ReflectionService.disableAsm().<List<DateTime>>getClassMeta(new TypeReference<List<DateTime>>() {}.getType());
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyyMMdd HH:mm:ss.SSSS Z");
Mapper<Object[] , List<DateTime>> mapper =
new SampleMapperBuilder<List<DateTime>>(classMeta)
.addMapping(new SampleFieldKey("0", 0, new Class[0], String.class), dateTimeFormatter).mapper();
DateTime now = DateTime.now();
Object[] objects = new Object[] { dateTimeFormatter.print(now) };
List<DateTime> map = mapper.map(objects);
assertEquals(now, map.get(0));
}
//IFJAVA8_START
@Test
public void testOptionalDbObject() {
ClassMeta<Optional<DbObject>> classMeta =
ReflectionService.disableAsm().<Optional<DbObject>>getClassMeta(new TypeReference<Optional<DbObject>>() {}.getType());
Mapper<Object[], Optional<DbObject>> mapper =
new SampleMapperBuilder<Optional<DbObject>>(classMeta)
.addMapping("id")
.addMapping("name")
.mapper();
Optional<DbObject> map = mapper.map(new Object[]{1l, "name1"});
assertEquals(1l, map.get().getId());
assertEquals("name1", map.get().getName());
}
//IFJAVA8_END
@Test
public void testArrayDbObject() {
ClassMeta<DbObject[]> classMeta =
ReflectionService.disableAsm().<DbObject[]>getClassMeta(DbObject[].class);
Mapper<Object[], DbObject[]> mapper =
new SampleMapperBuilder<DbObject[]>(classMeta)
.addMapping("1_id")
.addMapping("1_name")
.addMapping("2_id")
.addMapping("2_name")
.mapper();
DbObject[] map = mapper.map(new Object[]{1l, "name1", 2l, "name2"});
assertEquals(3, map.length);
assertEquals(1l, map[1].getId());
assertEquals("name1", map[1].getName());
assertEquals(2l, map[2].getId());
assertEquals("name2", map[2].getName());
}
@Test
public void testListDbObject() {
ClassMeta<List<DbObject>> classMeta =
ReflectionService.disableAsm().<List<DbObject>>getClassMeta(new TypeReference<List<DbObject>>() {}.getType());
Mapper<Object[], List<DbObject>> mapper =
new SampleMapperBuilder<List<DbObject>>(classMeta)
.addMapping("1_id")
.addMapping("1_name")
.addMapping("2_id")
.addMapping("2_name")
.mapper();
List<DbObject> map = mapper.map(new Object[]{1l, "name1", 2l, "name2"});
assertEquals(3, map.size());
assertEquals(1l, map.get(1).getId());
assertEquals("name1", map.get(1).getName());
assertEquals(2l, map.get(2).getId());
assertEquals("name2", map.get(2).getName());
}
@Test
public void testSetDbObject() {
ClassMeta<Set<DbObject>> classMeta =
ReflectionService.disableAsm().<Set<DbObject>>getClassMeta(new TypeReference<Set<DbObject>>() {}.getType());
Mapper<Object[], Set<DbObject>> mapper =
new SampleMapperBuilder<Set<DbObject>>(classMeta)
.addMapping("1_id")
.addMapping("1_name")
.addMapping("2_id")
.addMapping("2_name")
.mapper();
Set<DbObject> map = mapper.map(new Object[]{1l, "name1", 2l, "name2"});
assertEquals(2, map.size());
Iterator<DbObject> it = map.iterator();
DbObject o = it.next();
if (o.getId() == 1l) {
assertEquals("name1", o.getName());
o = it.next();
assertEquals(2l, o.getId());
assertEquals("name2", o.getName());
} else {
assertEquals("name2", o.getName());
o = it.next();
assertEquals(1l, o.getId());
assertEquals("name1", o.getName());
}
}
@Test
public void testMapDbObject() {
ClassMeta<Map<Long, DbObject>> classMeta =
ReflectionService.disableAsm().<Map<Long, DbObject>>getClassMeta(new TypeReference<Map<Long, DbObject>>() {}.getType());
Mapper<Object[], Map<Long, DbObject>> mapper =
new SampleMapperBuilder<Map<Long, DbObject>>(classMeta)
.addMapping("1_id")
.addMapping("1_name")
.addMapping("2_id")
.addMapping("2_name")
.mapper();
Map<Long, DbObject> map = mapper.map(new Object[]{1l, "name1", 2l, "name2"});
assertEquals(2, map.size());
assertEquals(1l, map.get(1l).getId());
assertEquals("name1", map.get(1l).getName());
assertEquals(2l, map.get(2l).getId());
assertEquals("name2", map.get(2l).getName());
}
@Test
public void testFinalObjectWithOneConstructor() {
ClassMeta<FinalObjectWith1ParamConstruction> classMeta = ReflectionService.newInstance().<FinalObjectWith1ParamConstruction>getClassMeta(FinalObjectWith1ParamConstruction.class);
Mapper<Object[], FinalObjectWith1ParamConstruction> mapper =
new SampleMapperBuilder<FinalObjectWith1ParamConstruction>(classMeta)
.addMapping("id")
.addMapping("o1p")
.addMapping("o2p")
.mapper();
FinalObjectWith1ParamConstruction map = mapper.map(new Object[]{1l, "v1", "v2"});
assertEquals(1l, map.id);
assertEquals("v1", map.o1p.getValue());
assertEquals("v2", map.o2p.getO1p().getValue());
}
@Test
public void testObjectWithOneConstructor() {
ClassMeta<ObjectWith1ParamConstruction> classMeta = ReflectionService.newInstance().<ObjectWith1ParamConstruction>getClassMeta(ObjectWith1ParamConstruction.class);
Mapper<Object[], ObjectWith1ParamConstruction> mapper =
new SampleMapperBuilder<ObjectWith1ParamConstruction>(classMeta)
.addMapping("id")
.addMapping("o1p")
.addMapping("o2p")
.mapper();
ObjectWith1ParamConstruction map = mapper.map(new Object[]{1l, "v1", "v2"});
assertEquals(1l, map.id);
assertEquals("v1", map.o1p.getValue());
assertEquals("v2", map.o2p.getO1p().getValue());
}
@Test
public void testObjectWithOneConstructorWithLoop() {
try {
ClassMeta<ObjectWith1ParamConstructionWithLoop> classMeta = ReflectionService.newInstance().<ObjectWith1ParamConstructionWithLoop>getClassMeta(ObjectWith1ParamConstructionWithLoop.class);
Mapper<Object[], ObjectWith1ParamConstructionWithLoop> mapper =
new SampleMapperBuilder<ObjectWith1ParamConstructionWithLoop>(classMeta)
.addMapping("id")
.addMapping("o1p")
.mapper();
fail();
} catch (MapperBuildingException e) {}
try {
ClassMeta<FinalObjectWith1ParamConstructionWithLoop> classMeta = ReflectionService.newInstance().<FinalObjectWith1ParamConstructionWithLoop>getClassMeta(FinalObjectWith1ParamConstructionWithLoop.class);
Mapper<Object[], FinalObjectWith1ParamConstructionWithLoop> mapper =
new SampleMapperBuilder<FinalObjectWith1ParamConstructionWithLoop>(classMeta)
.addMapping("id")
.addMapping("o1p")
.mapper();
fail();
} catch (MapperBuildingException e) {}
}
@Test
public void testDbFinal1DeepObject() throws Exception {
ClassMeta<DbFinal1DeepObject> classMeta = ReflectionService.newInstance().<DbFinal1DeepObject>getClassMeta(DbFinal1DeepObject.class);
Mapper<Object[], DbFinal1DeepObject> mapper =
new SampleMapperBuilder<DbFinal1DeepObject>(classMeta)
.addMapping("id")
.addMapping("value")
.addMapping("dbObject_id")
.addMapping("dbObject_name")
.mapper();
DbFinal1DeepObject map = mapper.map(new Object[]{1, "vvv", 2l, "wwww"});
assertEquals(1, map.getId());
assertEquals("vvv", map.getValue());
assertEquals(2l, map.getDbObject().getId());
assertEquals("wwww", map.getDbObject().getName());
}
@Test
public void testJoinDbListObject() throws Exception {
ClassMeta<DbListObject> classMeta = ReflectionService.newInstance(false).<DbListObject>getClassMeta(DbListObject.class);
SampleMapperBuilder<DbListObject> builder = new SampleMapperBuilder<DbListObject>(classMeta);
JoinMapper<Object[], Object[][], DbListObject, RuntimeException> mapper =
(JoinMapper<Object[], Object[][], DbListObject, RuntimeException>) builder
.addKey("id")
.addKey("objects_id")
.addMapping("objects_name")
.mapper();
checkDbListJoinMapper(mapper);
}
@Test
public void testJoinDbListObjectMissingKey() throws Exception {
ClassMeta<DbListObject> classMeta = ReflectionService.newInstance().<DbListObject>getClassMeta(DbListObject.class);
JoinMapper<Object[], Object[][], DbListObject, RuntimeException> mapper =
(JoinMapper<Object[], Object[][], DbListObject, RuntimeException>) new SampleMapperBuilder<DbListObject>(classMeta)
.addKey("id")
.addMapping("objects_id")
.addMapping("objects_name")
.mapper();
checkDbListJoinMapper(mapper);
}
private void checkDbListJoinMapper(JoinMapper<Object[], Object[][], DbListObject, RuntimeException> mapper) {
Iterator<DbListObject> iterator = mapper.iterator(new Object[][]{
{1, 1l, "n1"},
{1, 2l, "n2"},
{2, 1l, "n1"}
});
DbListObject dbListObject = iterator.next();
assertEquals(1, dbListObject.getId());
assertEquals(2, dbListObject.getObjects().size());
assertEquals(1l, dbListObject.getObjects().get(0).getId());
assertEquals("n1", dbListObject.getObjects().get(0).getName());
assertEquals(2l, dbListObject.getObjects().get(1).getId());
assertEquals("n2", dbListObject.getObjects().get(1).getName());
dbListObject = iterator.next();
assertEquals(2, dbListObject.getId());
assertEquals(1, dbListObject.getObjects().size());
assertEquals(1l, dbListObject.getObjects().get(0).getId());
assertEquals("n1", dbListObject.getObjects().get(0).getName());
}
@Test
public void testDefaultValue() throws Exception {
ClassMeta<DbObject> classMeta = ReflectionService.newInstance().<DbObject>getClassMeta(DbObject.class);
FieldMapperColumnDefinitionProviderImpl<SampleFieldKey> definitionProvider = new FieldMapperColumnDefinitionProviderImpl<SampleFieldKey>();
definitionProvider.addColumnProperty("type_name", new DefaultValueProperty<DbObject.Type>(DbObject.Type.type4));
MapperConfig<SampleFieldKey, FieldMapperColumnDefinition<SampleFieldKey>> mapperConfig =
MapperConfig.<SampleFieldKey>fieldMapperConfig().columnDefinitions(definitionProvider);
Mapper<Object[], DbObject> mapper =
new SampleMapperBuilder<DbObject>(classMeta, mapperConfig)
.addMapping("id")
.mapper();
Object[] data = new Object[] {3l};
DbObject dbObject = mapper.map(data);
assertEquals(3l, dbObject.getId());
assertEquals(DbObject.Type.type4, dbObject.getTypeName());
}
@Test
public void testDbObject() throws Exception {
testDbObjectxxxMapper(new Supplier<DbObject>() {
@Override
public DbObject get() {
return DbObject.newInstance();
}
}, true);
}
@Test
public void testDbObjectConstructorAndSetter() throws Exception {
testDbObjectxxxMapper(new Supplier<DbObjectConstructorAndSetter>() {
@Override
public DbObjectConstructorAndSetter get() {
return DbObjectConstructorAndSetter.newInstance();
}
}, true);
}
@Test
public void testDbFinalObject() throws Exception {
testDbObjectxxxMapper(new Supplier<DbFinalObject>() {
@Override
public DbFinalObject get() {
return DbFinalObject.newInstance();
}
}, false);
}
@Test
public void testDbPartialFinalObject() throws Exception {
testDbObjectxxxMapper(new Supplier<DbPartialFinalObject>() {
@Override
public DbPartialFinalObject get() {
return DbPartialFinalObject.newInstance();
}
}, false);
}
@Test
public void testCustomization() throws Exception {
ClassMeta<DbObject> classMeta = ReflectionService.newInstance().getClassMeta(DbObject.class);
Mapper<Object[], DbObject> mapper =
new SampleMapperBuilder<DbObject>(classMeta)
.addKey("id")
.addMapper(new FieldMapper<Object[], DbObject>() {
@Override
public void mapTo(Object[] source, DbObject target, MappingContext<? super Object[]> context) throws Exception {
target.setName("fieldMapper");
}
})
.addMapping("email", new GetterProperty(new Getter<Object, String>() {
@Override
public String get(Object target) throws Exception {
return "getterEmail";
}
})).mapper();
DbObject dbObject = mapper.map(new Object[] { 1l });
assertEquals(1, dbObject.getId());
assertEquals("fieldMapper", dbObject.getName());
assertEquals("getterEmail", dbObject.getEmail());
mapper =
new SampleMapperBuilder<DbObject>(classMeta)
.addKey("id")
.addMapping("email",
(Object)FieldMapperColumnDefinition.<SampleFieldKey>identity().add(
new GetterProperty(new Getter<Object, String>() {
@Override
public String get(Object target) throws Exception {
return "getterEmail";
}
})))
.addMapping("name",
FieldMapperColumnDefinition.<SampleFieldKey>identity().add(
new GetterProperty(new Getter<Object, String>() {
@Override
public String get(Object target) throws Exception {
return "getterName";
}
}))).mapper();
dbObject = mapper.map(new Object[] { 1l});
assertEquals(1, dbObject.getId());
assertEquals("getterEmail", dbObject.getEmail());
assertEquals("getterName", dbObject.getName());
}
private <T> void testDbObjectxxxMapper(Supplier<T> supplier, boolean mapTo) throws Exception {
testDbObjectxxxMapper(supplier, mapTo, false, DbObject.HEADERS);
testDbObjectxxxMapper(supplier, mapTo, true, DbObject.HEADERS);
}
private <T> void testDbObjectxxxMapper(Supplier<T> supplier, boolean mapTo, boolean useAsm, String[] headers) throws Exception {
T instance1 = supplier.get();
T instance2 = supplier.get();
ClassMeta<T> classMeta = ReflectionService.newInstance(useAsm).<T>getClassMeta(instance1.getClass());
SampleMapperBuilder<T> builder = new SampleMapperBuilder<T>(classMeta);
SampleMapperBuilder<T> builderIndexed = new SampleMapperBuilder<T>(classMeta);
Object[] row = new Object[headers.length];
for(int i = 0; i < headers.length; i++) {
String str = headers[i];
builder.addMapping(str);
builderIndexed.addMapping(str, i);
row[i] = classMeta.newPropertyFinder(ConstantPredicate.<PropertyMeta<?, ?>>truePredicate()).findProperty(DefaultPropertyNameMatcher.of(str)).getGetter().get(instance1);
}
Mapper<Object[], T> mapper = builder.mapper();
assertEquals(instance1, mapper.map(row));
Assert.assertEquals(instance1, builderIndexed.mapper().map(row));
assertNotEquals(instance1, instance2);
if (mapTo) {
mapper.mapTo(row, instance2, null);
assertEquals(instance1, instance2);
}
}
@Test
// https://github.com/arnaudroger/SimpleFlatMapper/issues/416
public void testEmptyAndFullConstructor() {
AbstractMapperFactoryTest.MapperFactory mapperFactory = new AbstractMapperFactoryTest.MapperFactory();
testCanBuildMapper(mapperFactory.getClassMeta(new TypeReference<Tuple2<AA, String>>() { }));
testCanBuildMapper(mapperFactory.getClassMeta(new TypeReference<List<AA>>() { }));
//IFJAVA8_START
testCanBuildMapper(mapperFactory.getClassMeta(new TypeReference<Optional<AA>>() { }));
//IFJAVA8_END
testCanBuildMapper(mapperFactory.getClassMeta(new TypeReference<Map<String, AA>>() { }), "aa_");
}
private <T> void testCanBuildMapper(ClassMeta<T> classMeta) {
testCanBuildMapper(classMeta, "");
}
private <T> void testCanBuildMapper(ClassMeta<T> classMeta, String prefix) {
SampleMapperBuilder<T> builderTuple = new SampleMapperBuilder<T>(classMeta);
assertNotNull(
builderTuple
.addMapping(prefix + "id")
.addMapping(prefix + "value")
.mapper()); // fails
}
public static class AA {
private String value;
private int id;
public AA() {
}
public AA(int id, String value) {
this.id = id;
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
public static final GetterFactory<Object[], SampleFieldKey> GETTER_FACTORY = new GetterFactory<Object[], SampleFieldKey>() {
@Override
public <P> Getter<Object[], P> newGetter(Type target, final SampleFieldKey key, Object... properties) {
Class<?> aClass = TypeHelper.toClass(target);
Package p = aClass.getPackage();
if (!Enum.class.isAssignableFrom(aClass) && !aClass.isPrimitive() &&(p == null || ! p.getName().startsWith("java"))) return null;
return new Getter<Object[], P>() {
@Override
public P get(Object[] target) throws Exception {
return (P) target[key.getIndex()];
}
};
}
};
public static final KeyFactory<SampleFieldKey> KEY_FACTORY = new KeyFactory<SampleFieldKey>() {
@Override
public SampleFieldKey newKey(String name, int i) {
return new SampleFieldKey(name, i);
}
};
public static class SampleMapperBuilder<T> extends AbstractMapperBuilder<Object[], T, SampleFieldKey, Mapper<Object[], T>, SampleMapperBuilder<T>> {
public SampleMapperBuilder(ClassMeta<T> classMeta, MapperConfig<SampleFieldKey, FieldMapperColumnDefinition<SampleFieldKey>> mapperConfig) {
super(classMeta, new MappingContextFactoryBuilder<Object[], SampleFieldKey>(new KeySourceGetter<SampleFieldKey, Object[]>() {
@Override
public Object getValue(SampleFieldKey key, Object[] source) throws Exception {
return source[key.getIndex()];
}
}), mapperConfig.failOnAsm(true), new MapperSourceImpl<Object[], SampleFieldKey>(Object[].class, GETTER_FACTORY),
KEY_FACTORY, 0);
}
public SampleMapperBuilder(ClassMeta<T> classMeta) {
this(classMeta, MapperConfig.<SampleFieldKey>fieldMapperConfig());
}
@Override
protected Mapper<Object[], T> newJoinMapper(Mapper<Object[], T> mapper) {
return new JoinMapper<Object[], Object[][], T, RuntimeException>(mapper,
mapperConfig.consumerErrorHandler(),
mappingContextFactoryBuilder.newFactory(),
new UnaryFactory<Object[][], Enumarable<Object[]>>() {
@Override
public Enumarable<Object[]> newInstance(Object[][] objects) {
return new ArrayEnumarable<Object[]>(objects);
}
});
}
@Override
protected Mapper<Object[], T> newStaticMapper(Mapper<Object[], T> mapper) {
return mapper;
}
}
}