package org.simpleflatmapper.csv.mapper;
import org.simpleflatmapper.csv.parser.CellConsumer;
import org.simpleflatmapper.map.ConsumerErrorHandler;
import org.simpleflatmapper.util.CheckedConsumer;
import java.util.Collection;
public final class CsvMapperCellConsumer<T> implements CellConsumer {
private final CsvMapperCellHandler<T> mapperSetters;
protected final ConsumerErrorHandler consumerErrorHandlers;
protected final BreakDetector breakDetector;
protected final CheckedConsumer<? super T> handler;
protected final CsvMapperCellConsumer[] children;
protected int cellIndex = 0;
private boolean calledHandler = false;
@SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
public CsvMapperCellConsumer(
CsvMapperCellHandler<T> csvMapperCellHandler,
ConsumerErrorHandler consumerErrorHandlers,
CheckedConsumer<? super T> handler,
BreakDetector breakDetector, Collection<CsvMapperCellConsumer<?>> children) {
super();
this.mapperSetters = csvMapperCellHandler;
this.consumerErrorHandlers = consumerErrorHandlers;
this.handler = handler;
this.breakDetector = breakDetector;
this.children = children.toArray(new CsvMapperCellConsumer[0]);
}
@Override
public final boolean endOfRow() {
composeInstance();
resetConsumer();
boolean calledHandler = this.calledHandler;
this.calledHandler = false;
return calledHandler;
}
public final T getCurrentInstance() {
return mapperSetters.getCurrentInstance();
}
protected final boolean hasData() {
return cellIndex > 0;
}
protected final void callHandler() {
calledHandler = true;
if (handler == null) return;
try {
handler.accept(getCurrentInstance());
} catch (Exception e) {
consumerErrorHandlers.handlerError(e, getCurrentInstance());
}
}
@Override
public final void end() {
endOfRow();
afterEnd();
}
@Override
public final void newCell(char[] chars, int offset, int length) {
int index = cellIndex;
newCell(chars, offset, length, index);
afterNewCell(index);
}
public final void newCell(char[] chars, int offset, int length, int cellIndex) {
if (mapperSetters.isDelayedSetter(cellIndex)) {
mapperSetters.delayedCellValue(chars, offset, length, cellIndex);
} else if (isNotNull()) {
mapperSetters.cellValue(chars, offset, length, cellIndex);
}
this.cellIndex = cellIndex + 1;
}
private boolean isNotNull() {
if (breakDetector == null) {
mapperSetters.createInstanceIfNull();
return true;
} else {
return breakDetector.isNotNull();
}
}
public final BreakDetector getBreakDetector() {
return breakDetector;
}
private void resetConsumer() {
for (CsvMapperCellConsumer<?> child : children) {
child.resetConsumer();
}
if (breakDetector != null) {
breakDetector.reset();
} else {
mapperSetters.resetCurrentInstance();
}
cellIndex = 0;
}
private void composeInstance() {
if (hasData()) {
if (breakDetector == null || breakDetector.isNotNull()) {
for (CsvMapperCellConsumer<?> child : children) {
child.composeInstance();
}
mapperSetters.createInstanceIfNull();
mapperSetters.applyDelayedSetters();
if (breakDetector == null) {
callHandler();
}
}
}
}
protected void afterEnd() {
if (breakDetector != null && mapperSetters.hasInstance()) {
callHandler();
}
}
protected void afterNewCell(int index) {
if (breakDetector == null) return;
updateBreakStatus(index);
}
private void updateBreakStatus(int cellIndex) {
if (breakDetector == null || breakDetector.updateStatus(mapperSetters, cellIndex)) {
if (breakDetector == null || breakDetector.broken()) {
if (mapperSetters.hasInstance()) {
callHandler();
mapperSetters.resetCurrentInstance();
}
updateChildrenStatus(cellIndex);
if (breakDetector == null || breakDetector.isNotNull()) {
mapperSetters.createInstance();
}
return;
}
}
updateChildrenStatus(cellIndex);
}
private void updateChildrenStatus(int cellIndex) {
for (CsvMapperCellConsumer consumer : children) {
consumer.updateBreakStatus(cellIndex);
}
}
}