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

com.github.skjolber.stcsv.CsvMapper2 Maven / Gradle / Ivy

There is a newer version: 1.0.25
Show newest version
package com.github.skjolber.stcsv;

import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.ASTORE;
import static org.objectweb.asm.Opcodes.GETFIELD;

import java.io.Reader;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;

import com.github.skjolber.stcsv.builder.CsvMappingBuilder2;

/**
 * 
 * Dynamic CSV parser generator. Adapts the underlying implementation according 
 * to the first (header) line.
 * 

* Uses ASM to build the parser implementations. *

* Thread-safe. */ public class CsvMapper2 extends AbstractCsvMapper { protected final Class intermediate; protected final String intermediateInternalName; protected final Map> factories = new ConcurrentHashMap<>(); public static CsvMappingBuilder2 builder(Class cls, Class delegate) { return new CsvMappingBuilder2(cls, delegate); } public CsvMapper2(Class cls, Class intermediate, char divider, char quoteCharacter, char escapeCharacter, List columns, boolean skipEmptyLines, boolean skipComments, boolean skippableFieldsWithoutLinebreaks, ClassLoader classLoader, int bufferLength) { super(cls, divider, quoteCharacter, escapeCharacter, columns, skipEmptyLines, skipComments, skippableFieldsWithoutLinebreaks, classLoader, bufferLength); this.intermediate = intermediate; this.intermediateInternalName = getInternalName(intermediate); } public CsvReader create(Reader reader, H helper) throws Exception { // avoid multiple calls to read when locating the first line // so read a full buffer char[] current = new char[bufferLength + 1]; int start = 0; int end = 0; do { int read = reader.read(current, start, bufferLength - start); if(read == -1) { return new EmptyCsvReader<>(); } else { end += read; } for(int i = start; i < end; i++) { if(current[i] == '\n') { return create(reader, new String(current, 0, i), current, i + 1, end, helper); } } start += end; } while(end < bufferLength); throw new CsvException("No linebreak found in " + current.length + " characters"); } public CsvReader create(Reader reader, String header, char[] current, int offset, int length, H helper) throws Exception { StaticCsvMapper2 constructor = factories.get(header); // note: using the stringbuilder as a key does not work if(constructor == null) { boolean carriageReturns = header.length() > 1 && header.charAt(header.length() - 1) == '\r'; List fields = parseColumnNames(header); constructor = buildStaticCsvMapper(carriageReturns, fields); if(constructor == null) { return new EmptyCsvReader<>(); } factories.put(header, constructor); } if(helper != null) { return constructor.newInstance(reader, current, offset, length, helper); } return constructor.newInstance(reader, current, offset, length, helper); } @SuppressWarnings({ "rawtypes", "unchecked" }) public StaticCsvMapper2 buildDefaultStaticCsvMapper(boolean carriageReturns) throws Exception { return new DefaultStaticCsvMapper2(super.createDefaultReaderClass(carriageReturns), intermediate); } @SuppressWarnings({ "rawtypes", "unchecked" }) public StaticCsvMapper2 buildStaticCsvMapper(String firstLine) throws Exception { boolean carriageReturns = firstLine.charAt(firstLine.length() - 2) == '\r'; String line; if(carriageReturns) { line = firstLine.substring(0, firstLine.length() - 2); } else { line = firstLine.substring(0, firstLine.length() - 1); } return new DefaultStaticCsvMapper2(super.createReaderClass(carriageReturns, line), intermediate); } @SuppressWarnings({ "rawtypes", "unchecked" }) public StaticCsvMapper2 buildStaticCsvMapper(boolean carriageReturns, String header) throws Exception { return new DefaultStaticCsvMapper2(super.createReaderClass(carriageReturns, header), intermediate); } @SuppressWarnings({ "rawtypes", "unchecked" }) public StaticCsvMapper2 buildStaticCsvMapper(boolean carriageReturns, List csvFileFieldNames) throws Exception { return new DefaultStaticCsvMapper2(super.createReaderClass(carriageReturns, csvFileFieldNames), intermediate); } @Override protected void addConstructors(ClassWriter classWriter, String subClassInternalName) { super.addConstructors(classWriter, subClassInternalName, intermediateInternalName); } protected void writeTriConsumerVariable(String subClassInternalName, MethodVisitor mv) { mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, subClassInternalName, "intermediate", "L" + intermediateInternalName + ";"); mv.visitVarInsn(ASTORE, intermediateIndex); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy