package org.sigmah.server.servlet.importer;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.util.List;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.sigmah.server.servlet.exporter.utils.CsvParser;
import org.sigmah.shared.dispatch.FunctionalException;
import org.sigmah.shared.dispatch.FunctionalException.ErrorCode;
import org.sigmah.shared.dto.ImportDetails;
import org.sigmah.shared.dto.referential.ImportationSchemeImportType;
/**
* CSV implementation of {@link Importer}.
*
* @author Guerline Jean-Baptiste (gjbaptiste@ideia.fr)
* @author Raphaƫl Calabro (rcalabro@ideia.fr) v2.0
*/
public class CsvImporter extends Importer {
private List<String[]> lines;
private Integer cursor;
/**
* {@inheritDoc}
*/
@Override
public void setInputStream(InputStream inputStream) throws IOException {
final String stringFromStream = inputStreamToString(inputStream, "UTF-8");
this.lines = new CsvParser().parseCsv(stringFromStream);
}
/**
* {@inheritDoc}
*/
@Override
public ImportDetails next() {
if (scheme.getImportType() != ImportationSchemeImportType.ROW) {
logWarnFormatImportTypeIncoherence();
return null;
}
if (cursor == null || cursor == lines.size()) {
nextSchemeModel();
cursor = Math.max(scheme.getFirstRow() - 1, 0);
}
if (cursor < lines.size()) {
return getCorrespondancePerSheetOrLine(cursor++, null);
} else {
return null;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNext() {
return hasNextLine() || hasNextSchemeModel();
}
/**
* {@inheritDoc}
*/
@Override
public String getValueFromVariable(String reference, Integer lineNumber, String sheetName) throws FunctionalException {
String columnValue = "";
if (reference != null && !reference.isEmpty()) {
switch (scheme.getImportType()) {
case ROW:
// Get First Row and sheet name
if(lineNumber != null && lineNumber >= 0 && lineNumber < lines.size()) {
final String[] line = lines.get(lineNumber);
try {
final int column = Integer.valueOf(reference);
if(column >= 0 && column < line.length) {
columnValue = line[column];
}
} catch(NumberFormatException nfe) {
throw new FunctionalException(nfe, ErrorCode.IMPORT_INVALID_COLUMN_REFERENCE, reference);
}
}
break;
default:
logWarnFormatImportTypeIncoherence();
break;
}
}
return columnValue;
}
/**
* Read fully the given input stream and return it as a <code>String</code>.
*
* The input stream is not closed by this method.
*
* @param inputStream
* Stream to read.
* @param encoding
* Encoding to use.
* @return The content of the input stream as a <code>String</code>.
* @throws IOException If an error occur while reading the stream.
*/
private String inputStreamToString(final InputStream inputStream, final String encoding) throws IOException {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final byte[] bytes = new byte[1024];
int length = inputStream.read(bytes);
while(length > 0) {
outputStream.write(bytes, 0, length);
length = inputStream.read(bytes);
}
return outputStream.toString(encoding);
}
/**
* Verify if the stream has more rows to read before moving on to the next
* scheme model.
*
* @return <code>true</code> if there is more lignes,
* <code>false</code> otherwise.
*/
private boolean hasNextLine() {
return cursor == null || cursor < lines.size();
}
}