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

consulting.omnia.util.file.FlatFileDataReader Maven / Gradle / Ivy

The newest version!
package consulting.omnia.util.file;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import consulting.omnia.util.cast.CastUtil;
import consulting.omnia.util.converter.Converter;
import consulting.omnia.util.converter.annotation.DataConverter;
import consulting.omnia.util.file.annotation.FixedSizeField;
import consulting.omnia.util.file.record.RecordType;
import consulting.omnia.util.format.StringUtil;
import consulting.omnia.util.reflection.ReflectionUtil;

public class FlatFileDataReader {

	private static final FlatFileDataReader INSTANCE = new FlatFileDataReader();

	private InputStream is;
	private Integer fileSizeInBytes;
	private Integer totalRecords;
	private Integer remainder;
	private LineFeedType lineFeedType;
	
	private FlatFileDataReader() {
	}

	public static FlatFileDataReader getInstance() {
		return INSTANCE;
	}
	
	public void prepare(final InputStream is, final Integer recordSize) throws IOException {
		this.is = is;
		this.fileSizeInBytes = is.available();
		this.totalRecords = fileSizeInBytes / recordSize;
		this.remainder = fileSizeInBytes % recordSize;
		this.lineFeedType = inferLineFeedType(totalRecords, remainder);
	}

	public  List readRecords(final Class clazz, final Comparator comparator, final RecordType recordType) throws Exception {
		switch(recordType) {
		case HEADER:
		case TRAILLER: 
			final T record = readRecord(is, clazz, comparator);		
			lineFeed(is, lineFeedType);
			return Collections.singletonList(record);
		case DETAIL_ONLY:
			return readDetailRecords(clazz, comparator, totalRecords);
		case DETAIL_HEADER:
		case DETAIL_TRAILLER:
			return readDetailRecords(clazz, comparator, totalRecords - 1);
		case DETAIL:
			return readDetailRecords(clazz, comparator, totalRecords - 2);
		default:
			throw new UnsupportedOperationException("Unknow record type: [" + recordType + "]");
		}
	}

	private  List readDetailRecords(final Class clazz, final Comparator comparator, final Integer recordsToRead) throws Exception {
		final List result = new LinkedList();
		for(int recordIndex = 0; recordIndex < recordsToRead; recordIndex++) {
			final T record = readRecord(is, clazz, comparator);
			lineFeed(is, lineFeedType);
			result.add(record);
		}
		return result;			

	}
	
	private LineFeedType inferLineFeedType(final Integer totalRecords, final Integer remainder) {
		final int _remainder = remainder % totalRecords;
		int size = 0;
		
		if(_remainder == 0) {
			size = remainder / totalRecords;
		} else {
			size = remainder / (totalRecords - 1);
		}

		switch(size) {
		case 0:
			 return null;
		case 1:
			return LineFeedType.UNIX_LIKE;
		case 2:
			return LineFeedType.WINDOWS_LIKE;
		default:
			throw new IllegalArgumentException("I don't know any line feed with a such size: [" + size + "]");
		}
		
	}

	private void lineFeed(final InputStream is, final LineFeedType lineFeedType) throws IOException {
		if(lineFeedType == null) {
			return;
		}
		
		switch (lineFeedType) {
		case UNIX_LIKE:
			readLineFeedByte(is);
			break;

		case WINDOWS_LIKE:
			readLineFeedByte(is);
			readLineFeedByte(is);
			break;
			
		default:
			throw new IllegalArgumentException("Unkown line feed type: [" + lineFeedType + "]");
		}
		 
	}

	private void readLineFeedByte(final InputStream is) throws IOException {
		is.read();
	}
		
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private  T readRecord(final InputStream is, final Class clazz, final Comparator comparator) throws Exception {
		final T record = clazz.newInstance();
		for (final Field field : ReflectionUtil.listAllFields(record, comparator)) {
			if(field.isAnnotationPresent(FixedSizeField.class)) {
				final FixedSizeField annotation = field.getAnnotation(FixedSizeField.class);
				Object value = read(is, annotation.pos(), annotation.length(), field.getType());
				if(field.isAnnotationPresent(DataConverter.class)) {
					final DataConverter dataConverter = field.getAnnotation(DataConverter.class);
					final Class converterClass = dataConverter.converter();
					final Object converter = converterClass.newInstance();
					value = ((Converter) converter).parse(value);
				}
				
				if(Modifier.isFinal(field.getModifiers())) {
					continue;
				}
				
				field.setAccessible(true);
				field.set(record, value);
			}
		}
		return record;
	}

	private Object read(final InputStream is, final int pos, final int size, final Class clazz) throws IOException, ParseException {
		byte[] buffer = new byte[size];
		is.read(buffer, 0, size);
		final String value = new String(buffer).trim();
		
		if(StringUtil.isEmpty(value)) {
			return null;
		}
		
		return CastUtil.castAs(value, clazz);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy