package org.simpleflatmapper.map.mapper;
import org.simpleflatmapper.map.FieldKey;
import org.simpleflatmapper.map.MappingContext;
import org.simpleflatmapper.map.MappingException;
import org.simpleflatmapper.map.SetRowMapper;
import org.simpleflatmapper.util.ErrorHelper;
import org.simpleflatmapper.util.UnaryFactory;
import org.simpleflatmapper.util.CheckedConsumer;
import org.simpleflatmapper.util.UnaryFactoryWithException;
import java.util.Iterator;
//IFJAVA8_START
import java.util.stream.Stream;
//IFJAVA8_END
public class DynamicSetRowMapper<ROW, SET, T, E extends Exception, K extends FieldKey<K>> implements SetRowMapper<ROW, SET, T, E> {
private final MapperCache<K, SetRowMapper<ROW, SET, T, E>> mapperCache;
private final UnaryFactory<MapperKey<K>, SetRowMapper<ROW, SET, T, E>> mapperFactory;
private final UnaryFactoryWithException<ROW, MapperKey<K>, E> mapperKeyFromRow;
private final UnaryFactoryWithException<SET, MapperKey<K>, E> mapperKeyFromSet;
public DynamicSetRowMapper(
UnaryFactory<MapperKey<K>, SetRowMapper<ROW, SET, T, E>> mapperFactory,
UnaryFactoryWithException<ROW, MapperKey<K>, E> mapperKeyFromRow,
UnaryFactoryWithException<SET, MapperKey<K>, E> mapperKeyFromSet,
MapperKeyComparator<K> keyComparator) {
this.mapperFactory = mapperFactory;
this.mapperKeyFromRow = mapperKeyFromRow;
this.mapperKeyFromSet = mapperKeyFromSet;
this.mapperCache = new MapperCache<K, SetRowMapper<ROW, SET, T, E>>(keyComparator);
}
@Override
public final T map(ROW row) throws MappingException {
try {
return getMapperFromRow(row).map(row);
} catch(Exception e) {
ErrorHelper.rethrow(e);
return null;
}
}
@Override
public final T map(ROW row, MappingContext<? super ROW> context) throws MappingException {
try {
return getMapperFromRow(row).map(row, context);
} catch(Exception e) {
ErrorHelper.rethrow(e);
return null;
}
}
@Override
public final void mapTo(ROW row, T target, MappingContext<? super ROW> context) throws Exception {
getMapperFromRow(row).mapTo(row, target, context);
}
@Override
public final Iterator<T> iterator(SET rs) throws E, MappingException {
return getMapperFromSet(rs).iterator(rs);
}
//IFJAVA8_START
@Override
public final Stream<T> stream(SET set) throws E, MappingException {
return getMapperFromSet(set).stream(set);
}
//IFJAVA8_END
@Override
public final <H extends CheckedConsumer<? super T>> H forEach(SET set, H handler) throws E, MappingException {
return getMapperFromSet(set).forEach(set, handler);
}
@Override
public String toString() {
return "DynamicMapper{mapperFactory=" + mapperFactory
+ ", " + mapperCache +
'}';
}
private SetRowMapper<ROW, SET, T, E> getMapperFromSet(SET set) throws E {
return getMapper(mapperKeyFromSet.newInstance(set));
}
private SetRowMapper<ROW, SET, T, E> getMapperFromRow(ROW row) throws E {
return getMapper(mapperKeyFromRow.newInstance(row));
}
public SetRowMapper<ROW, SET, T, E> getMapper(MapperKey<K> key) throws E {
SetRowMapper<ROW, SET, T, E> mapper = mapperCache.get(key);
if (mapper == null) {
mapper = mapperFactory.newInstance(key);
mapperCache.add(key, mapper);
}
return mapper;
}
}