All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.simpleflatmapper.csv.CsvParser Maven / Gradle / Ivy

package org.simpleflatmapper.csv;

import org.simpleflatmapper.map.mapper.AbstractColumnDefinitionProvider;
import org.simpleflatmapper.csv.impl.CsvColumnDefinitionProviderImpl;
import org.simpleflatmapper.csv.impl.DynamicCsvMapper;
import org.simpleflatmapper.csv.parser.*;
import org.simpleflatmapper.map.CaseInsensitiveFieldKeyNamePredicate;
import org.simpleflatmapper.map.property.KeyProperty;
import org.simpleflatmapper.reflect.ReflectionService;
import org.simpleflatmapper.tuple.Tuple2;
import org.simpleflatmapper.tuple.Tuple3;
import org.simpleflatmapper.tuple.Tuple4;
import org.simpleflatmapper.tuple.Tuple5;
import org.simpleflatmapper.tuple.Tuple6;
import org.simpleflatmapper.tuple.Tuple7;
import org.simpleflatmapper.tuple.Tuple8;
import org.simpleflatmapper.tuple.Tuples;
import org.simpleflatmapper.util.ConstantUnaryFactory;
import org.simpleflatmapper.util.TypeReference;
import org.simpleflatmapper.reflect.meta.ClassMeta;
import org.simpleflatmapper.util.CloseableIterator;
import org.simpleflatmapper.util.Predicate;
import org.simpleflatmapper.util.CheckedConsumer;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.*;
//IFJAVA8_START
import java.util.function.Function;
import java.util.stream.Stream;
//IFJAVA8_END

/**
 * CsvParser provides an fluent DSL to parse or map csv content.

* It is possible to customize the quote char, the separator, skip lines,and specified the size of the buffer
*
* * CsvParser *
    .quote('\'') *
    .separator(';') *
    .skip(2) *
    .bufferSize(256) *
    .stream(new StringReader("1;1\n2;2\n3;3\n4;4\n5;5")) *
    .map(Arrays::toString) *
    .forEach(System.out::println); *
    // output *
    // [3, 3] *
    // [4, 4] *
    // [5, 5] *
*
*
* the limit settings does not affect streams or iterator, only parse on DSL and forEach on the mapTo/mapWith DSL. *

* The DSL provides way to mapTo an object

* * CsvParser.mapTo(MyClass.class).stream(reader).forEach(System.out::println);
*
*

* using static mapping when no headers

* * CsvParser.mapTo(MyClass.class).addHeaders("id", "field").stream(reader).forEach(System.out::println);
* // using the addMapping
* CsvParser.mapTo(MyClass.class).addMapping("id").addMapping("field").stream(reader).forEach(System.out::println);
*
*

* using static mapping and ignoring source header

* * CsvParser.mapTo(MyClass.class).overrideHeaders("id", "field").stream(reader).forEach(System.out::println);
* // using the addMapping
* CsvParser.skip(1).mapTo(MyClass.class).addMapping("id").addMapping("field").stream(reader).forEach(System.out::println);
*
*

* or mapping with a predefined jdbcMapper.

* * CsvMapper<MyClass> jdbcMapper = CsvMapperFactory.newInstance().newMapper(MyClass.class);
* CsvParser.mapWith(jdbcMapper).stream(reader).forEach(System.out::println);
*
* *

* Each call to the DSL return an immutable representation of the current setup. So that it is possible to cache step of the DSL without side effect.

* * CsvParser.DSL semiColumnParser = CsvParser.separator(';');
*
* try (Reader r = new FileReader(file)) {
*     // the limit does not modify to the semiColumnParser object
*     semiColumnParser.limit(3).stream(r);
* } *
* * */ public final class CsvParser { public static final int DEFAULT_MAX_BUFFER_SIZE_8M = 1 << 23; public static final int DEFAULT_BUFFER_SIZE_4K = 1024 * 4; /** * * @param c the separator char * @return the DSL object */ public static DSL separator(char c) { return dsl().separator(c); } public static DSL bufferSize(int size) { return dsl().bufferSize(size); } public static DSL maxBufferSize(int size) { return dsl().maxBufferSize(size); } public static DSL quote(char c) { return dsl().quote(c); } public static DSL skip(int skip) { return dsl().skip(skip); } public static DSL dsl() { return new DSL(); } public static DSL limit(int limit) { return dsl().limit(limit); } public static MapToDSL mapTo(Type type) { return dsl().mapTo(type); } public static MapToDSL mapTo(Class type) { return dsl().mapTo(type); } public static MapToDSL mapTo(TypeReference type) { return dsl().mapTo(type); } public static MapToDSL> mapTo(Class class1, Class class2) { return dsl().mapTo(class1, class2); } public static MapToDSL> mapTo(Class class1, Class class2, Class class3) { return dsl().mapTo(class1, class2, class3); } public static MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4) { return dsl().mapTo(class1, class2, class3, class4); } public static MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4, Class class5) { return dsl().mapTo(class1, class2, class3, class4, class5); } public static MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4, Class class5, Class class6) { return dsl().mapTo(class1, class2, class3, class4, class5, class6); } public static MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4, Class class5, Class class6, Class class7) { return dsl().mapTo(class1, class2, class3, class4, class5, class6, class7); } public static MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4, Class class5, Class class6, Class class7, Class class8) { return dsl().mapTo(class1, class2, class3, class4, class5, class6, class7, class8); } public static MapWithDSL mapWith(CsvMapper mapper) { return dsl().mapWith(mapper); } /** * @param reader the reader * @return a csv reader based on the default setup. * @throws java.io.IOException if an error occurs reading the data */ public static CsvReader reader(Reader reader) throws IOException { return dsl().reader(reader); } public static CsvReader reader(CharSequence content) throws IOException { return dsl().reader(content); } public static CsvReader reader(String content) throws IOException { return dsl().reader(content); } public static CloseableCsvReader reader(File file) throws IOException { return dsl().reader(file); } public static Iterator iterator(Reader reader) throws IOException { return dsl().iterator(reader); } public static Iterator iterator(CharSequence content) throws IOException { return dsl().iterator(content); } public static CloseableIterator iterator(File file) throws IOException { return dsl().iterator(file); } public static > H forEach(Reader reader, H consumer) throws IOException { return dsl().forEach(reader, consumer); } public static > H forEach(CharSequence content, H consumer) throws IOException { return dsl().forEach(content, consumer); } public static > H forEach(File file, H consumer) throws IOException { return dsl().forEach(file, consumer); } public static CC parse(Reader reader, CC cellConsumer) throws IOException { return dsl().parse(reader, cellConsumer); } public static CC parse(CharSequence content, CC cellConsumer) throws IOException { return dsl().parse(content, cellConsumer); } public static CC parse(String content, CC cellConsumer) throws IOException { return dsl().parse(content, cellConsumer); } public static CC parse(File file, CC cellConsumer) throws IOException { return dsl().parse(file, cellConsumer); } //IFJAVA8_START public static Stream stream(Reader r) throws IOException { return dsl().stream(r); } @Deprecated public static Stream stream(File file) throws IOException { return dsl().stream(file); } public static R stream(File file, Function, R> function) throws IOException { return dsl().stream(file, function); } public static Stream stream(String content) throws IOException { return dsl().stream(content); } //IFJAVA8_END protected static abstract class AbstractDSL> { protected final char separatorChar; protected final char quoteChar; protected final int bufferSize; protected final int skip; protected final int limit; protected final int maxBufferSize; protected final StringPostProcessing stringPostProcessing; protected final org.simpleflatmapper.util.Function cellConsumerWrapper; protected final boolean yamlComment; protected enum StringPostProcessing { NONE, UNESCAPE, TRIM_AND_UNESCAPE} protected AbstractDSL() { separatorChar = ','; quoteChar= '"'; bufferSize = DEFAULT_BUFFER_SIZE_4K; skip = 0; limit = -1; maxBufferSize = DEFAULT_MAX_BUFFER_SIZE_8M; stringPostProcessing = StringPostProcessing.UNESCAPE; cellConsumerWrapper = null; yamlComment = false; } protected AbstractDSL(char separatorChar, char quoteChar, int bufferSize, int skip, int limit, int maxBufferSize, StringPostProcessing stringPostProcessing, org.simpleflatmapper.util.Function cellConsumerWrapper, boolean yamlComment) { this.separatorChar = separatorChar; this.quoteChar = quoteChar; this.bufferSize = bufferSize; this.skip = skip; this.limit = limit; this.maxBufferSize = maxBufferSize; this.stringPostProcessing = stringPostProcessing; this.cellConsumerWrapper = cellConsumerWrapper; this.yamlComment = yamlComment; } /** * Parse the content from the reader as a csv and call back the cellConsumer with the cell values. * @param reader the reader * @param cellConsumer the callback object for each cell value * @param the type of the cell consumer * @return cellConsumer * @throws IOException if and error occurs in the reader */ public final CC parse(Reader reader, CC cellConsumer) throws IOException { return parse(charBuffer(reader), cellConsumer); } public final CC parse(String content, CC cellConsumer) throws IOException { return parse(charBuffer(content), cellConsumer); } public final CC parse(CharSequence content, CC cellConsumer) throws IOException { return parse(charBuffer(content), cellConsumer); } private CC parse(CharBuffer charBuffer, CC cellConsumer) throws IOException { CsvReader csvreader = reader(charBuffer); if (limit == -1) { return csvreader.parseAll(cellConsumer); } else { return csvreader.parseRows(cellConsumer, limit); } } public final CC parse(File file, CC cellConsumer) throws IOException { Reader reader = new FileReader(file); try { return parse(reader, cellConsumer); } finally { try { reader.close(); } catch(IOException e) { /* ignore*/ } } } /** * Create a CsvReader and the specified reader. Will skip the number of specified rows. * @param reader the content * @return a CsvReader on the reader. * @throws IOException if an io error occurs */ public final CsvReader reader(Reader reader) throws IOException { return reader(charBuffer(reader)); } public final CsvReader reader(CharSequence content) throws IOException { return reader(charBuffer(content)); } public final CsvReader reader(String content) throws IOException { return reader(charBuffer(content)); } private CsvReader reader(CharBuffer charBuffer) throws IOException { CsvReader csvReader = new CsvReader(charConsumer(charBuffer), cellConsumerWrapper); csvReader.skipRows(skip); return csvReader; } protected CharBuffer charBuffer(Reader reader) throws IOException { return new ReaderCharBuffer(bufferSize, maxBufferSize, reader); } protected CharBuffer charBuffer(CharSequence content) throws IOException { return new CharSequenceCharBuffer(content); } protected CharBuffer charBuffer(String content) throws IOException { return new CharSequenceCharBuffer(content); } public final CloseableCsvReader reader(File file) throws IOException { return onReader(file, this, CREATE_CLOSEABLE_CSV_READER); } public final Iterator iterator(Reader reader) throws IOException { return reader(reader).iterator(); } public final Iterator iterator(CharSequence content) throws IOException { return reader(content).iterator(); } public final Iterator iterator(String content) throws IOException { return reader(content).iterator(); } public final CloseableIterator iterator(File file) throws IOException { return onReader(file, this, CREATE_CLOSEABLE_ITERATOR); } public final > H forEach(Reader reader, H consumer) throws IOException { return reader(reader).read(consumer); } public final > H forEach(CharSequence content, H consumer) throws IOException { return reader(content).read(consumer); } public final > H forEach(String content, H consumer) throws IOException { return reader(content).read(consumer); } public final > H forEach(File file, H consumer) throws IOException { CloseableCsvReader csvReader = reader(file); try { csvReader.read(consumer); } finally { csvReader.close(); } return consumer; } public final MapToDSL mapTo(Type target) { return new MapToDSL(this, target); } public final MapToDSL mapTo(Class target) { return mapTo((Type)target); } public final MapToDSL mapTo(TypeReference target) { return mapTo(target.getType()); } public final MapToDSL> mapTo(Class class1, Class class2) { return new MapToDSL>(this, Tuples.typeDef(class1, class2)); } public final MapToDSL> mapTo(Class class1, Class class2, Class class3) { return new MapToDSL>(this, Tuples.typeDef(class1, class2, class3)); } public final MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4) { return new MapToDSL>(this, Tuples.typeDef(class1, class2, class3, class4)); } public final MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4, Class class5) { return new MapToDSL>(this, Tuples.typeDef(class1, class2, class3, class4, class5)); } public final MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4, Class class5, Class class6) { return new MapToDSL>(this, Tuples.typeDef(class1, class2, class3, class4, class5, class6)); } public final MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4, Class class5, Class class6, Class class7) { return new MapToDSL>(this, Tuples.typeDef(class1, class2, class3, class4, class5, class6, class7)); } public final MapToDSL> mapTo(Class class1, Class class2, Class class3, Class class4, Class class5, Class class6, Class class7, Class class8) { return new MapToDSL>(this, Tuples.typeDef(class1, class2, class3, class4, class5, class6, class7, class8)); } public final MapWithDSL mapWith(CsvMapper mapper) { return new MapWithDSL(this, mapper); } //IFJAVA8_START public final Stream stream(Reader reader) throws IOException { return reader(reader).stream(); } public final Stream stream(CharSequence content) throws IOException { return reader(content).stream(); } public final Stream stream(String content) throws IOException { return reader(content).stream(); } //IFJAVA8_END /** * Use @see AbstractDSL#stream(File, Function). * @param file the file * @return a stream of String[] */ //IFJAVA8_START @Deprecated public final Stream stream(File file) throws IOException { return onReader(file, this, (reader, dsl) -> dsl.stream(reader).onClose(() -> { try { reader.close(); } catch (IOException e) {} })); } public final R stream(File file, Function, R> function) throws IOException { Reader reader = new FileReader(file); try { return function.apply(stream(reader)); } catch(IOException ioe) { try { reader.close(); } catch(IOException ioe2) { } throw ioe; } } //IFJAVA8_END protected final CharConsumer charConsumer(CharBuffer charBuffer) throws IOException { final TextFormat textFormat = getTextFormat(); return new CharConsumer(charBuffer, textFormat, getCellTransformer(textFormat, stringPostProcessing)); } protected TextFormat getTextFormat() { return new TextFormat(separatorChar, quoteChar, yamlComment); } protected CellPreProcessor getCellTransformer(TextFormat textFormat, StringPostProcessing stringPostProcessing) { switch (stringPostProcessing) { case TRIM_AND_UNESCAPE: return new TrimCellPreProcessor(getUnescapeCellTransformer(textFormat)); case UNESCAPE: return getUnescapeCellTransformer(textFormat); case NONE: return NoopCellPreProcessor.INSTANCE; default: throw new IllegalStateException("Could not instantiate char consumer " + stringPostProcessing); } } protected CellPreProcessor getUnescapeCellTransformer(TextFormat textFormat) { return new UnescapeCellPreProcessor(textFormat); } public final int maxBufferSize() { return maxBufferSize; } public final int bufferSize() { return bufferSize; } public final int limit() { return limit; } public final int skip() { return skip; } public final char separator() { return separatorChar; } public final char quote() { return quoteChar; } /** * set the separator character. the default value is ','. * @param c the new separator character * @return this */ public D separator(char c) { return newDSL(c, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } /** * set the quote character. the default value is '"'. * @param c the quote character * @return this */ public D quote(char c) { return newDSL(separatorChar, c, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } /** * set the size of the char buffer to read from. * @param size the size in bytes * @return this */ public D bufferSize(int size) { return newDSL(separatorChar, quoteChar, size, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } /** * set the number of line to skip. * @param skip number of line to skip. * @return this */ public D skip(int skip) { return newDSL(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } /** * set the number of row to process. limit does not affect stream or iterator. * @param limit number of row to process * @return this */ public D limit(int limit) { return newDSL(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } /** * set the maximum size of the content the parser will handle before failing to avoid OOM. * @param maxBufferSize the maximum size the buffer will grow, default 8M * @return this */ public D maxBufferSize(int maxBufferSize) { return newDSL(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } protected abstract D newDSL(char separatorChar, char quoteChar, int bufferSize, int skip, int limit, int maxBufferSize, StringPostProcessing stringPostProcessing, org.simpleflatmapper.util.Function cellConsumerWrapper, boolean yamlComment); } /** * DSL for csv parsing. * @see CsvParser */ public static final class DSL extends AbstractDSL { protected DSL() { } protected DSL(char separatorChar, char quoteChar, int bufferSize, int skip, int limit, int maxBufferSize, StringPostProcessing stringPostProcessing, org.simpleflatmapper.util.Function cellConsumerWrapper, boolean yamlComment) { super(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } public DSL trimSpaces() { return new DSL(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, StringPostProcessing.TRIM_AND_UNESCAPE, cellConsumerWrapper, yamlComment); } /** * will parse line starting with # as yaml comment. * comments line will be ignored unless using the special foreach call. * @return */ public DSLYamlComment withYamlComments() { return new DSLYamlComment(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, new org.simpleflatmapper.util.Function() { @Override public CellConsumer apply(CellConsumer cellConsumer) { TextFormat textFormat = getTextFormat(); return new YamlCellPreProcessor.YamlCellConsumer(cellConsumer, null, getCellTransformer(textFormat, stringPostProcessing)); } }, true); } /** * will parse line starting with # as yaml comment. * comments line will be come as a row of 1 cell. * @return */ public DSLYamlComment withYamlCommentsAsCell() { return new DSLYamlComment(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, new org.simpleflatmapper.util.Function() { @Override public CellConsumer apply(CellConsumer cellConsumer) { TextFormat textFormat = getTextFormat(); return new YamlCellPreProcessor.YamlCellConsumer(cellConsumer, cellConsumer, getCellTransformer(textFormat, stringPostProcessing)); } }, true); } public DSL disableUnescaping() { return new DSL(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, StringPostProcessing.NONE, cellConsumerWrapper, yamlComment); } @Override protected DSL newDSL(char separatorChar, char quoteChar, int bufferSize, int skip, int limit, int maxBufferSize, StringPostProcessing stringPostProcessing, org.simpleflatmapper.util.Function cellConsumerWrapper, boolean yamlComment) { return new DSL(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } } public static final class DSLYamlComment extends AbstractDSL { protected DSLYamlComment(char separatorChar, char quoteChar, int bufferSize, int skip, int limit, int maxBufferSize, StringPostProcessing stringPostProcessing, org.simpleflatmapper.util.Function cellConsumerWrapper, boolean yamlComment) { super(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } private CsvReader rawReader(CharBuffer charBuffer) throws IOException { CsvReader csvReader = new CsvReader(charConsumer(charBuffer), null); csvReader.skipRows(skip); return csvReader; } public void forEach(Reader reader, CheckedConsumer rowConsumer, CheckedConsumer commentConsumer) throws IOException { _forEach(rawReader(charBuffer(reader)), rowConsumer, commentConsumer); } public void forEach(CharSequence content, CheckedConsumer rowConsumer, CheckedConsumer commentConsumer) throws IOException { _forEach(rawReader(charBuffer(content)), rowConsumer, commentConsumer); } public void forEach(String content, CheckedConsumer rowConsumer, CheckedConsumer commentConsumer) throws IOException { _forEach(rawReader(charBuffer(content)), rowConsumer, commentConsumer); } private void _forEach(CsvReader reader, CheckedConsumer rowConsumer, CheckedConsumer commentConsumer) throws IOException { reader.parseAll(newYamlCellConsumer(rowConsumer, commentConsumer)); } private YamlCellPreProcessor.YamlCellConsumer newYamlCellConsumer(CheckedConsumer rowConsumer, CheckedConsumer commentConsumer) { TextFormat textFormat = getTextFormat(); return new YamlCellPreProcessor.YamlCellConsumer( StringArrayCellConsumer.newInstance(rowConsumer), YamlCellPreProcessor.commentConsumerToCellConsumer(commentConsumer), superGetCellTransformer(textFormat, stringPostProcessing)); } private CellPreProcessor superGetCellTransformer(TextFormat textFormat, StringPostProcessing stringPostProcessing) { return super.getCellTransformer(textFormat, stringPostProcessing); } @Override protected CellPreProcessor getCellTransformer(TextFormat textFormat, StringPostProcessing stringPostProcessing) { return new YamlCellPreProcessor(stringPostProcessing == StringPostProcessing.TRIM_AND_UNESCAPE); } public void forEach(File file, CheckedConsumer rowConsumer, CheckedConsumer commentConsumer) throws IOException { CloseableCsvReader csvReader = rawReader(file); try { csvReader.parseAll(newYamlCellConsumer(rowConsumer, commentConsumer)); } finally { csvReader.close(); } } private final CloseableCsvReader rawReader(File file) throws IOException { return onReader(file, this, CREATE_CLOSEABLE_CSV_RAW_READER); } private static final OnReaderFactory CREATE_CLOSEABLE_CSV_RAW_READER = new OnReaderFactory() { @Override public CloseableCsvReader apply(Reader reader, DSLYamlComment dsl) throws IOException { return new CloseableCsvReader(dsl.rawReader(dsl.charBuffer(reader)), reader); } }; @Override protected DSLYamlComment newDSL(char separatorChar, char quoteChar, int bufferSize, int skip, int limit, int maxBufferSize, StringPostProcessing stringPostProcessing, org.simpleflatmapper.util.Function cellConsumerWrapper, boolean yamlComment) { return new DSLYamlComment(separatorChar, quoteChar, bufferSize, skip, limit, maxBufferSize, stringPostProcessing, cellConsumerWrapper, yamlComment); } } /** * DSL for csv mapping to a dynamic jdbcMapper. * @see CsvParser * @see CsvMapper */ public static final class MapToDSL extends MapWithDSL { private final ClassMeta classMeta; private final Type mapToClass; private final CsvColumnDefinitionProviderImpl columnDefinitionProvider; public MapToDSL(AbstractDSL dsl, Type mapToClass) { this(dsl, ReflectionService.newInstance().getClassMeta(mapToClass), mapToClass, new CsvColumnDefinitionProviderImpl()); } private MapToDSL(AbstractDSL dsl, ClassMeta classMeta, Type mapToClass, CsvColumnDefinitionProviderImpl columnDefinitionProvider) { super(dsl, new DynamicCsvMapper(mapToClass, classMeta, columnDefinitionProvider)); this.mapToClass = mapToClass; this.classMeta = classMeta; this.columnDefinitionProvider = columnDefinitionProvider; } public StaticMapToDSL headers(String... headers) { return headers(headers, getDsl()); } public StaticMapToDSL overrideHeaders(String... headers) { return headers(headers, getDsl().skip(1)); } private StaticMapToDSL headers(String[] headers, AbstractDSL csvDsl) { return new StaticMapToDSL(csvDsl, classMeta, mapToClass, getColumnDefinitions(headers), columnDefinitionProvider); } public StaticMapToDSL defaultHeaders() { return defaultHeaders(getDsl()); } public StaticMapToDSL overrideWithDefaultHeaders() { return defaultHeaders(getDsl().skip(1)); } private StaticMapToDSL defaultHeaders(AbstractDSL csvDsl) { return new StaticMapToDSL( csvDsl, classMeta, mapToClass, newDefaultStaticMapper(mapToClass, classMeta, columnDefinitionProvider), columnDefinitionProvider); } private List> getColumnDefinitions(String[] headers) { List> columns = new ArrayList>(); for(String header : headers) { columns.add(new Tuple2(header, CsvColumnDefinition.identity())); } return columns; } public MapToDSL columnDefinition(String column, CsvColumnDefinition columnDefinition) { return new MapToDSL(getDsl(), classMeta, mapToClass, newColumnDefinitionProvider(column, columnDefinition)); } public MapToDSL columnDefinition(Predicate predicate, CsvColumnDefinition columnDefinition) { return new MapToDSL(getDsl(), classMeta, mapToClass, newColumnDefinitionProvider(predicate, columnDefinition)); } public MapWithDSL addKeys(String... keys) { CsvColumnDefinitionProviderImpl newProvider = columnDefinitionProvider.copy(); for(String key : keys) { newProvider.addColumnProperty(key, KeyProperty.DEFAULT); } return new MapToDSL(getDsl(), classMeta, mapToClass, newProvider); } private CsvColumnDefinitionProviderImpl newColumnDefinitionProvider(String name, CsvColumnDefinition columnDefinition) { CsvColumnDefinitionProviderImpl newProvider = columnDefinitionProvider.copy(); newProvider.addColumnDefinition(name, columnDefinition); return newProvider; } private CsvColumnDefinitionProviderImpl newColumnDefinitionProvider(Predicate predicate, CsvColumnDefinition columnDefinition) { CsvColumnDefinitionProviderImpl newProvider = columnDefinitionProvider.copy(); newProvider.addColumnDefinition(predicate, columnDefinition); return newProvider; } public StaticMapToDSL addMapping(String column) { return staticMapper().addMapping(column); } public StaticMapToDSL addKey(String key) { return staticMapper().addKey(key); } public StaticMapToDSL addMapping(String column, CsvColumnDefinition columnDefinition) { return staticMapper().addMapping(column, columnDefinition); } private StaticMapToDSL staticMapper() { return headers(new String[0], getDsl().skip(1)); } } /** * DSL for csv mapping to a static jdbcMapper. * @see CsvParser * @see CsvMapper */ public static final class StaticMapToDSL extends MapWithDSL { private final ClassMeta classMeta; private final Type mapToClass; private final CsvColumnDefinitionProviderImpl columnDefinitionProvider; private final List> columns; private StaticMapToDSL(AbstractDSL dsl, ClassMeta classMeta, Type mapToClass, CsvMapper mapper, CsvColumnDefinitionProviderImpl columnDefinitionProvider) { super(dsl, mapper); this.classMeta = classMeta; this.mapToClass = mapToClass; this.columns = new ArrayList>(); this.columnDefinitionProvider = columnDefinitionProvider; } private StaticMapToDSL(AbstractDSL dsl, ClassMeta classMeta, Type mapToClass, List> columns, CsvColumnDefinitionProviderImpl columnDefinitionProvider) { super(dsl, newStaticMapper(mapToClass, classMeta, columns, columnDefinitionProvider)); this.classMeta = classMeta; this.mapToClass = mapToClass; this.columns = columns; this.columnDefinitionProvider = columnDefinitionProvider; } public StaticMapToDSL addMapping(String column) { return addMapping(column, CsvColumnDefinition.identity()); } public StaticMapToDSL addMapping(String column, CsvColumnDefinition columnDefinition) { List> newColumns = new ArrayList>(columns); newColumns.add(new Tuple2(column, columnDefinition)); return new StaticMapToDSL(getDsl(), classMeta, mapToClass, newColumns, columnDefinitionProvider); } public StaticMapToDSL addKey(String key) { return addMapping(key, CsvColumnDefinition.key()); } } /** * DSL for csv mapping to a provided jdbcMapper. * @see CsvParser * @see CsvMapper */ public static class MapWithDSL { private final AbstractDSL dsl; private final CsvMapper mapper; public MapWithDSL(AbstractDSL dsl, CsvMapper mapper) { this.dsl = dsl; this.mapper = mapper; } protected final AbstractDSL getDsl() { return dsl; } public final Iterator iterator(Reader reader) throws IOException { return mapper.iterator(dsl.reader(reader)); } public final Iterator iterator(CharSequence content) throws IOException { return mapper.iterator(dsl.reader(content)); } public final Iterator iterator(String content) throws IOException { return mapper.iterator(dsl.reader(content)); } public final CloseableIterator iterator(File file) throws IOException { OnReaderFactory, AbstractDSL> factory = new OnReaderFactory, AbstractDSL>() { @Override public CloseableIterator apply(Reader reader, AbstractDSL dsl) throws IOException { return new CloseableIterator(iterator(reader), reader); } }; return onReader(file, dsl, factory); } public final > H forEach(File file, H consumer) throws IOException { Reader reader = new FileReader(file); try { return forEach(reader, consumer); } finally { try { reader.close(); } catch (IOException e) { } } } public final > H forEach(Reader reader, H consumer) throws IOException { return forEach(consumer, dsl.reader(reader)); } public final > H forEach(CharSequence content, H consumer) throws IOException { return forEach(consumer, dsl.reader(content)); } public final > H forEach(String content, H consumer) throws IOException { return forEach(consumer, dsl.reader(content)); } private > H forEach(H consumer, CsvReader csvReader) throws IOException { if (dsl.limit == -1) { mapper.forEach(csvReader, consumer); } else { mapper.forEach(csvReader, consumer, dsl.limit); } return consumer; } //IFJAVA8_START public final Stream stream(Reader reader) throws IOException { return mapper.stream(dsl.reader(reader)); } public final Stream stream(CharSequence content) throws IOException { return mapper.stream(dsl.reader(content)); } public final Stream stream(String content) throws IOException { return mapper.stream(dsl.reader(content)); } //IFJAVA8_END /** * use @see MapWithDSL#stream(File, Function) * @param file the file * @return a stream of T */ //IFJAVA8_START @Deprecated public final Stream stream(File file) throws IOException { OnReaderFactory, AbstractDSL> factory = new OnReaderFactory, AbstractDSL>() { @Override public Stream apply(Reader reader, AbstractDSL dsl) throws IOException { return stream(reader).onClose(() -> { try { reader.close(); } catch (IOException e) { // ignore } }); } }; return onReader(file, dsl, factory); } public final R stream(File file, Function, R> function) throws IOException { Reader reader = new FileReader(file); try { return function.apply(stream(reader)); } catch(IOException ioe) { try { reader.close(); } catch(IOException ioe2) { } throw ioe; } } //IFJAVA8_END } private static final OnReaderFactory> CREATE_CLOSEABLE_CSV_READER = new OnReaderFactory>() { @Override public CloseableCsvReader apply(Reader reader, AbstractDSL dsl) throws IOException { return new CloseableCsvReader(dsl.reader(reader), reader); } }; private static final OnReaderFactory, AbstractDSL> CREATE_CLOSEABLE_ITERATOR = new OnReaderFactory, AbstractDSL>() { @Override public CloseableIterator apply(Reader reader, AbstractDSL dsl) throws IOException { return new CloseableIterator(dsl.iterator(reader), reader); } }; interface OnReaderFactory> { T apply(Reader reader, D dsl) throws IOException; } protected static > R onReader(File file, D dsl, OnReaderFactory factory) throws IOException { Reader reader = new FileReader(file); try { return factory.apply(reader, dsl); } catch(IOException ioe) { try { reader.close(); } catch(IOException ioe2) { /* ignore*/ } throw ioe; } } private static CsvMapper newDefaultStaticMapper(Type mapToClass, ClassMeta classMeta, CsvColumnDefinitionProviderImpl columnDefinitionProvider) { CsvMapperBuilder builder = new CsvMapperBuilder(mapToClass, classMeta, columnDefinitionProvider); builder.addDefaultHeaders(); return builder.mapper(); } private static CsvMapper newStaticMapper(Type mapToClass, ClassMeta classMeta, List> columns, CsvColumnDefinitionProviderImpl columnDefinitionProvider) { CsvMapperBuilder builder = new CsvMapperBuilder(mapToClass, classMeta, columnDefinitionProvider); for(Tuple2 col: columns) { builder.addMapping(col.first(), col.second()); } return builder.mapper(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy