package sushi.csv.importer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import sushi.event.SushiEvent;
import sushi.event.attribute.SushiAttribute;
import sushi.event.attribute.SushiAttributeTypeEnum;
import sushi.event.collection.SushiMapTree;
import sushi.excel.importer.FileNormalizer;
import sushi.excel.importer.SushiImportEvent;
/**
* Adapter for CSV Files
*/
public class CSVImporter extends FileNormalizer{
private static final long serialVersionUID = 1L;
private char maskChar = '"';
private char separator = ';';
@Override
public List<String> getColumnTitlesFromFile(String filePath) {
String line;
String[] split;
try {
FileReader file = new FileReader(filePath);
BufferedReader data = new BufferedReader(file);
line = data.readLine();
//if seperator is defined replace default seperator (;) and move one row forward
if (line.startsWith("sep=")){
split = line.split("=");
separator = split[1].charAt(0);
line = data.readLine();
}
return getElementsFromLine(line);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
public List<SushiImportEvent> importEventsForPreviewFromFile(String filePath, List<String> selectedColumnTitles) {
String seperator = ";";
String line;
String[] split;
List<String> lineElements;
List<SushiImportEvent> eventList = new ArrayList<SushiImportEvent>();
List<Integer> selectedColumnIndexes = new ArrayList<Integer>();
List<String> columnTitles = getColumnTitlesFromFile(filePath);
String timestampName = getTimestampColumn(columnTitles);
try {
FileReader file = new FileReader(filePath);
BufferedReader data = new BufferedReader(file);
line = data.readLine();
// if separator is defined replace default separator (;) and move one row forward
if (line.startsWith("sep=")){
split = line.split("=");
separator = split[1].charAt(0);
line = data.readLine();
}
lineElements = getElementsFromLine(line);
for(int i = 0; i < lineElements.size(); i++){
if(selectedColumnTitles.contains(lineElements.get(i))) selectedColumnIndexes.add(i);
}
while ((line = data.readLine()) != null) {
lineElements = getElementsFromLine(line);
eventList.add(generateImportEventFromRow(lineElements, columnTitles, selectedColumnIndexes, timestampName));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return eventList;
}
@Override
public List<SushiEvent> importEventsFromFile(String filePath, List<SushiAttribute> selectedAttributes, String timestamp) {
String seperator = ";";
String line;
String[] split;
List<String> lineElements;
List<SushiEvent> eventList = new ArrayList<SushiEvent>();
List<Integer> selectedColumnIndexes = new ArrayList<Integer>();
List<String> columnTitles = getColumnTitlesFromFile(filePath);
List<String> selectedColumnTitles = new ArrayList<String>();
int timeStampColumnIndex = columnTitles.indexOf(timestamp);
for (SushiAttribute attribute : selectedAttributes) {
selectedColumnTitles.add(attribute.getName());
}
try {
FileReader file = new FileReader(filePath);
BufferedReader data = new BufferedReader(file);
line = data.readLine();
//if seperator is defined replace default seperator (;) and move one row forward
if (line.contains("sep")){
split = line.split("=");
seperator = split[1];
line = data.readLine();
}
split = line.split(seperator);
for(int i = 0; i < split.length; i++){
if(selectedColumnTitles.contains(split[i])) selectedColumnIndexes.add(i);
}
while ((line = data.readLine()) != null) {
split = line.split(seperator);
lineElements = getElementsFromLine(line);
eventList.add(generateEventFromRow(lineElements, columnTitles, selectedAttributes, selectedColumnIndexes, timeStampColumnIndex));
}
} catch (IOException e) {
e.printStackTrace();
}
return eventList;
}
private SushiImportEvent generateImportEventFromRow(List<String> rowSplit, List<String> columnTitles, List<Integer> selectedColumnIndexes, String timestampName) {
Date timestamp = null;
SimpleDateFormat sdfToDate = new SimpleDateFormat("dd.MM.yyyy HH:mm");
int timestampColumnIndex = columnTitles.indexOf(timestampName);
if(timestampColumnIndex > -1){
try {
timestamp = sdfToDate.parse(rowSplit.get(timestampColumnIndex));
} catch (ParseException e) {
e.printStackTrace();
}
}
SushiMapTree<String, Serializable> values = generateValueTree(rowSplit, columnTitles, selectedColumnIndexes, timestampColumnIndex);
SushiImportEvent event = new SushiImportEvent(timestamp, values, timestampName, new Date());
return event;
}
private SushiEvent generateEventFromRow(List<String> rowSplit, List<String> columnTitles, List<SushiAttribute> selectedAttributes, List<Integer> selectedColumnIndexes, int timeStampColumnIndex) {
//Default value
Date timestamp = new Date();
SimpleDateFormat sdfToDate = new SimpleDateFormat("dd.MM.yyyy HH:mm");
if(timeStampColumnIndex > -1){
try {
timestamp = sdfToDate.parse(rowSplit.get(timeStampColumnIndex));
} catch (ParseException e) {
e.printStackTrace();
}
}
SushiMapTree<String, Serializable> values = generateValueTree(rowSplit, columnTitles, selectedAttributes, selectedColumnIndexes, timeStampColumnIndex);
SushiEvent event = new SushiEvent(timestamp, values);
return event;
}
private SushiMapTree<String, Serializable> generateValueTree(List<String> rowSplit, List<String> columnTitles, List<Integer> selectedColumnIndexes, int timeStampColumnIndex) {
SushiMapTree<String, Serializable> values = new SushiMapTree<String, Serializable>();
for(int i : selectedColumnIndexes){
if(i != timeStampColumnIndex){
values.addRootElement(columnTitles.get(i), rowSplit.get(i));
}
}
return values;
}
private SushiMapTree<String, Serializable> generateValueTree(List<String> rowSplit, List<String> columnTitles, List<SushiAttribute> selectedAttributes, List<Integer> selectedColumnIndexes, int timeStampColumnIndex) {
SushiMapTree<String, Serializable> values = new SushiMapTree<String, Serializable>();
SushiAttributeTypeEnum attributeType = null;
for (int i : selectedColumnIndexes) {
if (i != timeStampColumnIndex) {
String attributeName = columnTitles.get(i);
for (SushiAttribute attribute : selectedAttributes) {
if (attribute.getName().equals(attributeName)) {
attributeType = attribute.getType();
}
}
Serializable attributeValue = rowSplit.get(i);
if (attributeType != null) {
if (attributeType.equals(SushiAttributeTypeEnum.DATE)) {
SimpleDateFormat sdfToDate = new SimpleDateFormat("dd.MM.yyyy HH:mm");
try {
attributeValue = sdfToDate.parse(rowSplit.get(i));
} catch (ParseException e) {
e.printStackTrace();
}
} else if (attributeType.equals(SushiAttributeTypeEnum.INTEGER)) {
attributeValue = Integer.parseInt(rowSplit.get(i));
} else {
attributeValue = rowSplit.get(i);
}
}
values.addRootElement(attributeName, attributeValue);
}
}
return values;
}
private List<String> getElementsFromLine(String line){
List<String> elements = new ArrayList<String>();
boolean entryMasked = false;
char lastCharacter;
char currentCharacter = 0;
StringBuilder currentElement = new StringBuilder();
for(int i = 0; i < line.length(); i++){
lastCharacter = currentCharacter;
currentCharacter = line.charAt(i);
// Wenn ein Element mit einem Maskierungszeichen beginnt, ist es maskiert
if(currentCharacter == maskChar && currentElement.length() == 0){
entryMasked = true;
} else if(currentCharacter==separator){
if(!entryMasked || lastCharacter == maskChar){
String currentElementString = currentElement.toString();
if(entryMasked){
currentElementString = currentElement.substring(1, (currentElement.length() -1));
}
elements.add(currentElementString);
currentElement = new StringBuilder();
currentCharacter = 0;
continue;
}
}
if(currentCharacter==maskChar && lastCharacter==maskChar){
currentCharacter = 0;
continue;
}
currentElement.append(currentCharacter);
}
//Letztes Element auch noch ausgeben
String currentElementString = currentElement.toString();
if(entryMasked){
currentElementString = currentElement.substring(1, (currentElement.length() -1));
}
elements.add(currentElementString);
//TODO: Maskierungszeichen und Whitespaces entfernen
return elements;
}
}