/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.content.imports; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import com.enonic.esl.util.StringUtil; import com.enonic.cms.core.content.contenttype.CtyImportConfig; import com.enonic.cms.core.content.contenttype.CtyImportMappingConfig; import com.enonic.cms.core.content.imports.sourcevalueholders.AbstractSourceValue; import com.enonic.cms.core.content.imports.sourcevalueholders.StringArraySourceValue; import com.enonic.cms.core.content.imports.sourcevalueholders.StringSourceValue; public class ImportDataReaderCsv extends AbstractImportDataReader { private final List<ImportDataEntry> entries = new ArrayList<ImportDataEntry>(); private ImportDataEntry prefetchedNextDataEntry; public ImportDataReaderCsv( final CtyImportConfig config, final InputStream data ) throws ImportCSVSourceException { super( config ); readAllLines( data ); } public ImportDataEntry getNextEntry() { return fetchNextEntry(); } public boolean hasMoreEntries() { ImportDataEntry next; if ( prefetchedNextDataEntry != null ) { next = prefetchedNextDataEntry; } else { next = fetchNextEntry(); prefetchedNextDataEntry = next; } return next != null; } private ImportDataEntry fetchNextEntry() { if ( prefetchedNextDataEntry != null ) { ImportDataEntry next = prefetchedNextDataEntry; prefetchedNextDataEntry = null; return next; } if ( entries.size() == 0 ) { return null; } return entries.remove( 0 ); } private void readAllLines( final InputStream data ) throws ImportCSVSourceException { BufferedReader br; try { br = new BufferedReader( new InputStreamReader( data, "UTF-8" ) ); } catch ( IOException e ) { throw new ImportCSVSourceException( "Failed to create input stream: " + e.getMessage(), e ); } int lineNumber = 1; String line = readNextLine( br, lineNumber ); while ( line != null ) { if ( lineNumber <= config.getSkip() ) { lineNumber++; line = readNextLine( br, lineNumber ); continue; } else if ( StringUtils.isBlank( line ) ) { // skipping blank lines lineNumber++; line = readNextLine( br, lineNumber ); continue; } else { final LineParser lineParser = new LineParser( lineNumber, line ); final ImportDataEntry entry = lineParser.parse(); entries.add( entry ); lineNumber++; line = readNextLine( br, lineNumber ); } } } private String readNextLine( BufferedReader br, int lineNumber ) { try { return br.readLine(); } catch ( IOException e ) { throw new ImportCSVSourceException( lineNumber, e ); } } private class LineParser { private int lineNumber; private String line; private LineParser( int lineNumber, String line ) { this.lineNumber = lineNumber; this.line = line; } private ImportDataEntry parse() { final ImportDataEntry entry = new ImportDataEntry( config.getSyncMapping() ); final String[] columnValues = StringUtil.splitString( line, config.getSeparator(), true ); addMappings( entry, columnValues ); addMetadataMappings( entry, columnValues ); return entry; } private void addMappings( final ImportDataEntry entry, final String[] fields ) { for ( CtyImportMappingConfig mapping : config.getMappings() ) { AbstractSourceValue value = getSourceValue( fields, mapping ); entry.add( mapping, value ); } } private void addMetadataMappings( final ImportDataEntry entry, final String[] columnValues ) { for ( CtyImportMappingConfig metadataMapping : config.getMetadataMappings() ) { AbstractSourceValue value = getSourceValue( columnValues, metadataMapping ); entry.addMetadata( metadataMapping, value ); } } private AbstractSourceValue getSourceValue( final String[] columnValues, final CtyImportMappingConfig mapping ) { AbstractSourceValue value = null; int index = Integer.valueOf( mapping.getSource() ) - 1; if ( index < columnValues.length ) { String columnValue = columnValues[index]; if ( !mapping.isMetaDataMapping() && mapping.isMultiple() && mapping.getSeparator() != null ) { final String[] values = StringUtil.splitString( columnValue, mapping.getSeparator(), false ); value = new StringArraySourceValue( values ); } else { value = new StringSourceValue( columnValue ); } } else { throw new ImportCSVSourceException( lineNumber, line, "No column at position " + mapping.getSource() + " (destination = '" + mapping.getDestination() + "')." ); } if ( mapping.hasAdditionalSource() ) { int exIndex = Integer.valueOf( mapping.getAdditionalSource() ) - 1; if ( exIndex < columnValues.length ) { value.setAdditionalValue( columnValues[exIndex] ); } } return value; } } }