org.sfm.csv.impl.CsvMapperImpl Maven / Gradle / Ivy
Show all versions of simpleFlatMapper Show documentation
package org.sfm.csv.impl;
import org.sfm.csv.CsvColumnKey;
import org.sfm.csv.CsvMapper;
import org.sfm.csv.CsvParser;
import org.sfm.csv.CsvReader;
import org.sfm.csv.parser.CellConsumer;
import org.sfm.map.MappingException;
import org.sfm.map.RowHandlerErrorHandler;
import org.sfm.utils.ErrorHelper;
import org.sfm.utils.RowHandler;
import java.io.IOException;
import java.io.Reader;
import java.util.*;
//IFJAVA8_START
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
//IFJAVA8_END
public final class CsvMapperImpl implements CsvMapper {
private static final DelayedCellSetter[] EMPTY_DELAYED_CELL_SETTERS = new DelayedCellSetter[0];
private final DelayedCellSetterFactory[] delayedCellSetterFactories;
private final CellSetter[] setters;
private final CsvColumnKey[] joinKeys;
private final RowHandlerErrorHandler rowHandlerErrorHandlers;
protected final CsvMapperCellHandlerFactory csvMapperCellHandlerFactory;
private final boolean hasSetterSubProperties;
private final boolean hasSubProperties;
public CsvMapperImpl(CsvMapperCellHandlerFactory csvMapperCellHandlerFactory,
DelayedCellSetterFactory[] delayedCellSetterFactories,
CellSetter[] setters,
CsvColumnKey[] joinKeys,
RowHandlerErrorHandler rowHandlerErrorHandlers) {
super();
this.csvMapperCellHandlerFactory = csvMapperCellHandlerFactory;
this.delayedCellSetterFactories = delayedCellSetterFactories;
this.setters = setters;
this.joinKeys = joinKeys;
this.rowHandlerErrorHandlers = rowHandlerErrorHandlers;
this.hasSetterSubProperties = hasSetterSubProperties(setters);
this.hasSubProperties = hasSetterSubProperties || hasDelayedMarker(delayedCellSetterFactories);
}
private boolean hasDelayedMarker(DelayedCellSetterFactory[] delayedCellSetterFactories) {
for(DelayedCellSetterFactory setter : delayedCellSetterFactories) {
if (setter instanceof DelegateMarkerDelayedCellSetterFactory) {
return true;
}
}
return false;
}
private boolean hasSetterSubProperties(CellSetter[] setters) {
for(CellSetter setter : setters) {
if (setter instanceof DelegateMarkerSetter) {
return true;
}
}
return false;
}
@Override
public final > H forEach(final Reader reader, final H handler) throws IOException, MappingException {
return forEach(CsvParser.reader(reader), handler);
}
@Override
public > H forEach(CsvReader reader, H handle) throws IOException, MappingException {
reader.parseAll(newCellConsumer(handle));
return handle;
}
@Override
public final > H forEach(final Reader reader, final H handler, final int skip) throws IOException, MappingException {
return forEach(CsvParser.skip(skip).reader(reader), handler);
}
@Override
public final > H forEach(final Reader reader, final H handler, final int skip, final int limit) throws IOException, MappingException {
return forEach(CsvParser.skip(skip).reader(reader), handler, limit);
}
@Override
public final > H forEach(CsvReader reader, H handle, int limit) throws IOException, MappingException {
reader.parseRows(newCellConsumer(handle), limit);
return handle;
}
@Override
public Iterator iterator(Reader reader) throws IOException {
return iterator(CsvParser.reader(reader));
}
@Override
public Iterator iterator(CsvReader csvReader) {
return new CsvMapperIterator(csvReader, this);
}
@Override
public Iterator iterator(Reader reader, int skip) throws IOException {
return iterator(CsvParser.skip(skip).reader(reader));
}
//IFJAVA8_START
@Override
public Stream stream(Reader reader) throws IOException {
return stream(CsvParser.reader(reader));
}
@Override
public Stream stream(CsvReader csvReader) {
return StreamSupport.stream(new CsvSpliterator(csvReader), false);
}
@Override
public Stream stream(Reader reader, int skip) throws IOException {
return stream(CsvParser.skip(skip).reader(reader));
}
public class CsvSpliterator implements Spliterator {
private final CsvReader csvReader;
private final CellConsumer cellConsumer;
private T current;
public CsvSpliterator(CsvReader csvReader) {
this.csvReader = csvReader;
this.cellConsumer = newCellConsumer(new RowHandler() {
@Override
public void handle(T t) throws Exception {
current = t;
}
});
}
@Override
public boolean tryAdvance(Consumer super T> action) {
current = null;
try {
csvReader.parseRow(cellConsumer);
} catch (IOException e) {
return ErrorHelper.rethrow(e);
}
if (current != null) {
action.accept(current);
return true;
} else {
return false;
}
}
@Override
public void forEachRemaining(Consumer super T> action) {
try {
csvReader.parseAll(newCellConsumer(new RowHandler() {
@Override
public void handle(T t) throws Exception {
action.accept(t);
}
}));
} catch (IOException e) {
ErrorHelper.rethrow(e);
}
}
@Override
public Spliterator trySplit() {
return null;
}
@Override
public long estimateSize() {
return Long.MAX_VALUE;
}
@Override
public int characteristics() {
return Spliterator.ORDERED | Spliterator.NONNULL;
}
}
//IFJAVA8_END
protected CsvMapperCellConsumer newCellConsumer(final RowHandler super T> handler) {
return newCellConsumer(handler, null);
}
protected CsvMapperCellConsumer newCellConsumer(final RowHandler super T> handler, BreakDetector parentBreakDetector) {
CsvMapperCellConsumer>[] cellHandlers = null;
if (hasSubProperties) {
cellHandlers = new CsvMapperCellConsumer>[delayedCellSetterFactories.length + setters.length];
}
final BreakDetector breakDetector = newBreakDetector(parentBreakDetector, delayedCellSetterFactories.length - 1);
DelayedCellSetter[] outDelayedCellSetters = getDelayedCellSetters(cellHandlers, breakDetector);
CellSetter[] outSetters = getCellSetters(cellHandlers, breakDetector);
CsvMapperCellHandler mapperSetters = csvMapperCellHandlerFactory.newInstance(outDelayedCellSetters, outSetters);
return new CsvMapperCellConsumer(mapperSetters,
rowHandlerErrorHandlers,
handler,
breakDetector, toList(cellHandlers));
}
@SuppressWarnings("unchecked")
private DelayedCellSetter[] getDelayedCellSetters(CsvMapperCellConsumer>[] cellHandlers, BreakDetector breakDetector) {
if (delayedCellSetterFactories.length == 0) {
return EMPTY_DELAYED_CELL_SETTERS;
} else {
return buildDelayedCellSetters(cellHandlers, breakDetector);
}
}
@SuppressWarnings("unchecked")
private DelayedCellSetter[] buildDelayedCellSetters(CsvMapperCellConsumer>[] cellHandlers, BreakDetector breakDetector) {
DelayedCellSetter[] outDelayedCellSetters = new DelayedCellSetter[delayedCellSetterFactories.length];
for(int i = delayedCellSetterFactories.length - 1; i >= 0 ; i--) {
DelayedCellSetterFactory delayedCellSetterFactory = delayedCellSetterFactories[i];
if (delayedCellSetterFactory != null) {
outDelayedCellSetters[i] = delayedCellSetterFactory.newCellSetter(breakDetector, cellHandlers);
}
}
return outDelayedCellSetters;
}
private Collection> toList(CsvMapperCellConsumer>[] cellHandlers) {
if (cellHandlers == null) return Collections.emptyList();
List> consumers = new ArrayList>();
for(CsvMapperCellConsumer> consumer : cellHandlers) {
if (consumer != null) {
consumers.add(consumer);
}
}
return consumers;
}
@SuppressWarnings("unchecked")
private CellSetter[] getCellSetters(CsvMapperCellConsumer>[] cellHandlers, BreakDetector breakDetector) {
if (hasSetterSubProperties) {
return rebuildCellSetters(cellHandlers, breakDetector);
} else {
return setters;
}
}
@SuppressWarnings("unchecked")
private CellSetter[] rebuildCellSetters(CsvMapperCellConsumer>[] cellHandlers, BreakDetector breakDetector) {
CellSetter[] outSetters = new CellSetter[setters.length];
for(int i = setters.length - 1; i >= 0 ; i--) {
if (setters[i] instanceof DelegateMarkerSetter) {
DelegateCellSetter delegateCellSetter = getDelegateCellSetter((DelegateMarkerSetter)setters[i], cellHandlers, breakDetector, i);
outSetters[i] = delegateCellSetter;
} else {
outSetters[i] = setters[i];
}
}
return outSetters;
}
@SuppressWarnings("unchecked")
private DelegateCellSetter getDelegateCellSetter(DelegateMarkerSetter marker, CsvMapperCellConsumer>[] cellHandlers, BreakDetector breakDetector, int i) {
final int parent = marker.getParent();
final int cellIndex = i + delayedCellSetterFactories.length;
if(parent == cellIndex) {
final DelegateCellSetter tpDelegateCellSetter = new DelegateCellSetter(marker, cellIndex, breakDetector);
cellHandlers[cellIndex] = tpDelegateCellSetter.getCellConsumer();
return tpDelegateCellSetter;
} else {
final CsvMapperCellConsumer> cellHandler = cellHandlers[parent];
if (cellHandler==null) {
throw new NullPointerException("No cell handler on parent " + parent);
}
return new DelegateCellSetter(marker, (CsvMapperCellConsumer) cellHandler, cellIndex);
}
}
private BreakDetector newBreakDetector(BreakDetector parentBreakDetector, int delayedSetterEnd) {
if (parentBreakDetector != null || joinKeys.length > 0) {
return new BreakDetector(joinKeys, parentBreakDetector, delayedSetterEnd);
} else {
return null;
}
}
@Override
public String toString() {
return "CsvMapperImpl{" +
"targetSettersFactory=" + csvMapperCellHandlerFactory +
", delayedCellSetters=" + Arrays.toString(delayedCellSetterFactories) +
", setters=" + Arrays.toString(setters) +
'}';
}
}