package org.simpleflatmapper.poi.impl; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.simpleflatmapper.reflect.getter.GetterFactory; import org.simpleflatmapper.csv.CsvColumnKey; import org.simpleflatmapper.map.MapperConfig; import org.simpleflatmapper.map.property.FieldMapperColumnDefinition; import org.simpleflatmapper.map.mapper.MapperKey; import org.simpleflatmapper.map.mapper.MapperCache; import org.simpleflatmapper.poi.SheetMapper; import org.simpleflatmapper.poi.SheetMapperBuilder; import org.simpleflatmapper.reflect.meta.ClassMeta; import org.simpleflatmapper.util.CheckedConsumer; import org.simpleflatmapper.csv.CsvColumnKeyMapperKeyComparator; import java.util.ArrayList; import java.util.Iterator; import java.util.List; //IFJAVA8_START import java.util.stream.Stream; //IFJAVA8_END public class DynamicSheetMapper<T> implements SheetMapper<T> { private final int startRow = 0; private final MapperCache<CsvColumnKey, SheetMapper<T>> mapperCache = new MapperCache<CsvColumnKey, SheetMapper<T>>(CsvColumnKeyMapperKeyComparator.INSTANCE); private final ClassMeta<T> classMeta; private final MapperConfig<CsvColumnKey, FieldMapperColumnDefinition<CsvColumnKey>> mapperConfig; private final GetterFactory<Row, CsvColumnKey> getterFactory; public DynamicSheetMapper( ClassMeta<T> classMeta, MapperConfig<CsvColumnKey, FieldMapperColumnDefinition<CsvColumnKey>> mapperConfig, GetterFactory<Row, CsvColumnKey> getterFactory) { this.classMeta = classMeta; this.mapperConfig = mapperConfig; this.getterFactory = getterFactory; } @Override public Iterator<T> iterator(Sheet sheet) { return iterator(startRow, sheet); } @Override public Iterator<T> iterator(int startRow, Sheet sheet) { return getPoiMapper(startRow, sheet).iterator(startRow + 1 , sheet); } @Override public <RH extends CheckedConsumer<T>> RH forEach(Sheet sheet, RH consumer) { return forEach(startRow, sheet, consumer); } @Override public <RH extends CheckedConsumer<T>> RH forEach(int startRow, Sheet sheet, RH consumer) { return getPoiMapper(startRow, sheet).forEach(startRow + 1, sheet, consumer); } //IFJAVA8_START @Override public Stream<T> stream(Sheet sheet) { return stream(startRow, sheet); } @Override public Stream<T> stream(int startRow, Sheet sheet) { return getPoiMapper(startRow, sheet).stream(startRow + 1, sheet); } //IFJAVA8_END private SheetMapper<T> getPoiMapper(int startRow, Sheet sheet) { Row row = sheet.getRow(startRow); List<CsvColumnKey> keys = new ArrayList<CsvColumnKey>(row.getLastCellNum() - row.getFirstCellNum()); for(short i = row.getFirstCellNum(); i <= row.getLastCellNum(); i++) { Cell cell = row.getCell(i); if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK) { keys.add(new CsvColumnKey(cell.getStringCellValue(), i)); } } return getPoiMapper(new MapperKey<CsvColumnKey>(keys.toArray(new CsvColumnKey[0]))); } private SheetMapper<T> getPoiMapper(MapperKey<CsvColumnKey> key) { SheetMapper<T> mapper = mapperCache.get(key); if (mapper == null) { final SheetMapperBuilder<T> builder = new SheetMapperBuilder<T>( classMeta, mapperConfig, getterFactory); for(CsvColumnKey k : key.getColumns()) { builder.addMapping(k, FieldMapperColumnDefinition.<CsvColumnKey>identity()); } mapper = builder.mapper(); mapperCache.add(key, mapper); } return mapper; } }