package org.simpleflatmapper.csv.impl; import org.simpleflatmapper.csv.*; import org.simpleflatmapper.csv.parser.CellConsumer; import org.simpleflatmapper.map.MapperConfig; import org.simpleflatmapper.map.MappingException; import org.simpleflatmapper.map.mapper.ColumnDefinitionProvider; import org.simpleflatmapper.map.mapper.MapperCache; import org.simpleflatmapper.map.mapper.MapperKey; import org.simpleflatmapper.reflect.meta.ClassMeta; import org.simpleflatmapper.util.CheckedConsumer; import java.io.IOException; import java.io.Reader; import java.lang.reflect.Type; import java.util.Iterator; //IFJAVA8_START import java.util.stream.Stream; import java.util.stream.StreamSupport; //IFJAVA8_END import static org.simpleflatmapper.util.Asserts.requireNonNull; public final class DynamicCsvMapper<T> implements CsvMapper<T> { private final ClassMeta<T> classMeta; private final Type target; private final String defaultDateFormat; private final CellValueReaderFactory cellValueReaderFactory; private final MapperConfig<CsvColumnKey, CsvColumnDefinition> mapperConfig; private final MapperCache<CsvColumnKey, CsvMapperImpl<T>> mapperCache = new MapperCache<CsvColumnKey, CsvMapperImpl<T>>(CsvColumnKeyMapperKeyComparator.INSTANCE); public DynamicCsvMapper(final Type target, final ClassMeta<T> classMeta, String defaultDateFormat, CellValueReaderFactory cellValueReaderFactory, MapperConfig<CsvColumnKey, CsvColumnDefinition> mapperConfig ) { this.classMeta = requireNonNull("classMeta", classMeta); this.target = requireNonNull("target", target); this.defaultDateFormat = defaultDateFormat; this.mapperConfig = mapperConfig; this.cellValueReaderFactory = cellValueReaderFactory; } public DynamicCsvMapper(Type target, ClassMeta<T> classMeta, ColumnDefinitionProvider<CsvColumnDefinition, CsvColumnKey> columnDefinitionProvider) { this(target, classMeta, "yyyy-MM-dd HH:mm:ss", new CellValueReaderFactoryImpl(), MapperConfig.<CsvColumnKey, CsvColumnDefinition>config(columnDefinitionProvider)); } @Override public <H extends CheckedConsumer<? super T>> H forEach(Reader reader, H handle) throws IOException, MappingException { return forEach(CsvParser.reader(reader), handle); } @Override public <H extends CheckedConsumer<? super T>> H forEach(CsvReader csvReader, H handle) throws IOException { CellConsumer mapperCellConsumer = getDelegateMapper(csvReader).newCellConsumer(handle); csvReader.parseAll(mapperCellConsumer); return handle; } @Override public <H extends CheckedConsumer<? super T>> H forEach(Reader reader, H handle, int skip) throws IOException, MappingException { return forEach(CsvParser.skip(skip).reader(reader), handle); } @Override public <H extends CheckedConsumer<? super T>> H forEach(CsvReader csvReader, H handle, int limit) throws IOException { CellConsumer mapperCellConsumer = getDelegateMapper(csvReader).newCellConsumer(handle); csvReader.parseRows(mapperCellConsumer, limit); return handle; } @Override public <H extends CheckedConsumer<? super T>> H forEach(Reader reader, H handle, int skip, int limit) throws IOException, MappingException { return forEach(CsvParser.skip(skip).reader(reader), handle, limit); } @Override public Iterator<T> iterator(Reader reader) throws IOException { CsvReader csvReader = CsvParser.reader(reader); return iterator(csvReader); } @Override public Iterator<T> iterator(CsvReader csvReader) throws IOException { CsvMapperImpl<T> mapper = getDelegateMapper(csvReader); return new CsvMapperIterator<T>(csvReader, mapper); } @Override public Iterator<T> iterator(Reader reader, int skip) throws IOException { return iterator(CsvParser.skip(skip).reader(reader)); } private CsvMapperImpl<T> getDelegateMapper(CsvReader reader) throws IOException { ColumnsMapperKeyBuilderCellConsumer keyBuilderCellConsumer = new ColumnsMapperKeyBuilderCellConsumer(); reader.parseRow(keyBuilderCellConsumer); return getCsvMapper(keyBuilderCellConsumer.getKey()); } //IFJAVA8_START @Override public Stream<T> stream(Reader reader) throws IOException { CsvReader csvReader = CsvParser.reader(reader); return stream(csvReader); } @Override public Stream<T> stream(CsvReader csvReader) throws IOException { CsvMapperImpl<T> mapper = getDelegateMapper(csvReader); return StreamSupport.stream(mapper.new CsvSpliterator(csvReader), false); } @Override public Stream<T> stream(Reader reader, int skip) throws IOException { return stream(CsvParser.skip(skip).reader(reader)); } //IFJAVA8_END protected CsvMapperImpl<T> getCsvMapper(MapperKey<CsvColumnKey> key) { CsvMapperImpl<T> csvMapperImpl = mapperCache.get(key); if (csvMapperImpl == null) { csvMapperImpl = buildMapper(key); mapperCache.add(key, csvMapperImpl); } return csvMapperImpl; } private CsvMapperImpl<T> buildMapper(MapperKey<CsvColumnKey> key) { CsvMapperBuilder<T> builder = new CsvMapperBuilder<T>(target, classMeta, 0, cellValueReaderFactory, mapperConfig); builder.setDefaultDateFormat(defaultDateFormat); for(CsvColumnKey col : key.getColumns()) { builder.addMapping(col, CsvColumnDefinition.identity()); } return (CsvMapperImpl<T>)builder.mapper(); } @Override public String toString() { return "DynamicCsvMapper{" + "target=" + target + ", mapperCache=" + mapperCache + '}'; } }