# MultipleColumnsReader.java

    package org.codefilarete.stalactite.sql.result;

    import java.sql.ResultSet;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    import java.util.function.Function;

    import org.codefilarete.tool.collection.Iterables;

    /**
     * Reader of several columns (by their name) from a {@link java.sql.ResultSet}.
     * Based on a collection of {@link SingleColumnReader}s.
     *
     * @author Guillaume Mary
     * @param <C>
     */
    public class MultipleColumnsReader<C> implements ColumnReader<C> {

    	private final Set<SingleColumnReader> columnReaders;

    	private final Function<Map<String, Object>, C> assembler;

    	/**
    	 * Default constructor
    	 *
    	 * @param columnReaders readers to be used for reading {@link ResultSet} rows per column
    	 * @param assembler function to assemble row values to create the bean of a row,
    	 * will consume {@link ResultSet} values by the form of a column name to value mapping
    	 */
    	public MultipleColumnsReader(Set<SingleColumnReader> columnReaders, Function<Map<String, Object> /* ResultSet row values */, C> assembler) {
    		this.columnReaders = columnReaders;
    		this.assembler = assembler;
    	}

    	@Override
    	public C read(ResultSet resultSet) {
    		Map<String, Object> rowValues = Iterables.map(columnReaders, SingleColumnReader::getColumnName, reader -> reader.read(resultSet));
    		return assembler.apply(rowValues);
    	}

    	@Override
    	public MultipleColumnsReader<C> copyWithAliases(Function<String, String> columnMapping) {
    		Set<SingleColumnReader> resultColumnReaders = Iterables.collect(columnReaders, r -> r.copyWithAliases(columnMapping), HashSet::new);
    		return new MultipleColumnsReader<>(resultColumnReaders, assembler);
    	}
    }