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

org.sfm.csv.DynamicCsvMapper Maven / Gradle / Ivy

package org.sfm.csv;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.sfm.csv.cell.StringCellValueReader;
import org.sfm.csv.parser.CharsCellHandler;
import org.sfm.csv.parser.CsvParser;
import org.sfm.map.FieldMapperErrorHandler;
import org.sfm.map.MapperBuilderErrorHandler;
import org.sfm.map.MapperCache;
import org.sfm.map.MapperKey;
import org.sfm.map.MappingException;
import org.sfm.reflect.ReflectionService;
import org.sfm.reflect.meta.ClassMeta;
import org.sfm.utils.RowHandler;

public class DynamicCsvMapper implements CsvMapper {
	
	public final class DynamicCellHandler implements CharsCellHandler {
		private final RowHandler handle;
		private final int rowStart;
		private final int limit;

		private CsvMapperCellHandler cellHandler;
		private List columns = new ArrayList();
		private int currentRow;
		
		public DynamicCellHandler(RowHandler handle, int rowStart, int limit) {
			this.handle = handle;
			this.rowStart = rowStart;
			this.limit = limit;
		}

		@Override
		public boolean endOfRow() {
			if (rowStart == -1 || currentRow >= rowStart) {
				if (cellHandler == null) {
					MapperKey key = new MapperKey(columns.toArray(new String[columns.size()]));
					CsvMapperImpl csvMapperImpl = mapperCache.get(key);
					if (csvMapperImpl == null) {
						csvMapperImpl = buildeMapper(key);
						mapperCache.add(key, csvMapperImpl);
					}
					cellHandler = csvMapperImpl.newCellHandler(handle);
				} else {
					cellHandler.endOfRow();
				}
			}
			
			return continueProcessing();
		}

		private boolean continueProcessing() {
			boolean continueProcessing =  limit == -1 || (currentRow - rowStart) < limit;
			currentRow++;
			return continueProcessing;
		}

		@Override
		public void newCell(char[] chars, int offset, int length) {
			if (rowStart == -1 || currentRow >= rowStart) {
				if (cellHandler == null) {
					columns.add(StringCellValueReader.readString(chars, offset, length));
				} else {
					cellHandler.newCell(chars, offset, length);
				}
			}
		}

		@Override
		public void end() {
			if (cellHandler != null) {
				cellHandler.end();
			}
		}
	}

	private final ClassMeta classMeta;
	private final Class target;

	private final CsvParser csvParser;

	private final FieldMapperErrorHandler fieldMapperErrorHandler;

	private final MapperBuilderErrorHandler mapperBuilderErrorHandler;
	
	private final String defaultDateFormat;
	
	private MapperCache> mapperCache = new MapperCache>();
	private final Map aliases;
	private final Map> customReaders;

	public DynamicCsvMapper(final Class target, final ReflectionService reflectionService, 
			final FieldMapperErrorHandler fieldMapperErrorHandler, 
			final MapperBuilderErrorHandler mapperBuilderErrorHandler, String defaultDateFormat, 
			Map aliases, Map> customReaders) {
		this.classMeta = reflectionService.getClassMeta(target);
		this.target = target;
		this.fieldMapperErrorHandler = fieldMapperErrorHandler;
		this.mapperBuilderErrorHandler = mapperBuilderErrorHandler;
		this.csvParser = new CsvParser();
		this.defaultDateFormat = defaultDateFormat;
		this.aliases = aliases;
		this.customReaders = customReaders;
	}

	@Override
	public > H forEach(final Reader reader, final H handler) throws IOException, MappingException {
		return forEach(reader, handler, 0, -1);
	}
	
	@Override
	public > H forEach(final Reader reader, final H handler, final int rowStart) throws IOException, MappingException {
		return forEach(reader, handler, rowStart, -1);
	}
	
	@Override
	public > H forEach(final Reader reader, final H handler, final int rowStart, final int limit) throws IOException, MappingException {
		csvParser.parse(reader, new DynamicCellHandler(handler, rowStart, limit));
		return handler;
	}
	
	private CsvMapperImpl buildeMapper(MapperKey key) {
		CsvMapperBuilder builder = new CsvMapperBuilder(target, classMeta, aliases, customReaders);
		builder.fieldMapperErrorHandler(fieldMapperErrorHandler);
		builder.mapperBuilderErrorHandler(mapperBuilderErrorHandler);
		builder.setDefaultDateFormat(defaultDateFormat);
		for(String col : key.getColumns()) {
			builder.addMapping(col);
		}
		return (CsvMapperImpl)builder.mapper();
	}


	@Override
	public > H forEach(InputStream is, H handle)
			throws IOException, MappingException {
		return forEach(new InputStreamReader(is), handle);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy