Skip to content

Commit

Permalink
[CSV] Update to latest Commons CSV and refactor wiith tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Phillipus committed Dec 2, 2023
1 parent ea557e7 commit e1b8f43
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 48 deletions.
4 changes: 2 additions & 2 deletions com.archimatetool.csv/.classpath
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="lib" path="lib/commons-csv-1.6.jar" sourcepath="lib/commons-csv-1.6-sources.jar"/>
<classpathentry exported="true" kind="lib" path="lib/commons-io-2.6.jar"/>
<classpathentry exported="true" kind="lib" path="lib/commons-csv-1.10.0.jar" sourcepath="lib/commons-csv-1.10.0-sources.jar"/>
<classpathentry exported="true" kind="lib" path="lib/commons-io-2.14.0.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
Expand Down
4 changes: 2 additions & 2 deletions com.archimatetool.csv/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ Export-Package: com.archimatetool.csv,
Bundle-Activator: com.archimatetool.csv.CSVImportExportPlugin
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .,
lib/commons-csv-1.6.jar,
lib/commons-io-2.6.jar
lib/commons-csv-1.10.0.jar,
lib/commons-io-2.14.0.jar
Automatic-Module-Name: com.archimatetool.csv
4 changes: 2 additions & 2 deletions com.archimatetool.csv/build.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ bin.includes = META-INF/,\
LICENSE.txt,\
plugin.properties,\
lib/LICENSE.txt,\
lib/commons-csv-1.6.jar,\
lib/commons-io-2.6.jar
lib/commons-csv-1.10.0.jar,\
lib/commons-io-2.14.0.jar
source.. = src/
output.. = bin/
Binary file not shown.
Binary file added com.archimatetool.csv/lib/commons-csv-1.10.0.jar
Binary file not shown.
Binary file not shown.
Binary file removed com.archimatetool.csv/lib/commons-csv-1.6.jar
Binary file not shown.
Binary file added com.archimatetool.csv/lib/commons-io-2.14.0.jar
Binary file not shown.
Binary file removed com.archimatetool.csv/lib/commons-io-2.6.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
Expand All @@ -17,6 +18,7 @@
import java.util.Map.Entry;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVFormat.Builder;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.io.input.BOMInputStream;
Expand Down Expand Up @@ -461,59 +463,38 @@ else if(JUNCTION_TYPE.equals(key) && propertiesObject instanceof IJunction) {

/**
* Get all records for a CSV file.
* This is a brute-force approach to try with a comma delimiter first. If that fails then
* try a semicolon, and if that fails, a tab.
* This is a brute-force approach to try with a comma delimiter first.
* If that fails then try a semicolon, and if that fails, a tab.
*
* @param file The file to open
* @return Records, which may be empty but never null
* @return list of CSVRecord
* @throws IOException
*/
private List<CSVRecord> getRecords(File file) throws IOException {
List<CSVRecord> records = new ArrayList<CSVRecord>();
CSVParser parser = null;
List<CSVRecord> getRecords(File file) throws IOException {
final String expectedErrorMessage = "invalid char between encapsulated token and delimiter"; //$NON-NLS-1$
final char[] delimiters = {',', ';', '\t'};

final String errorMessage = "invalid char between encapsulated token and delimiter"; //$NON-NLS-1$
IOException ex = new IOException();

try {
InputStreamReader is = new InputStreamReader(new BOMInputStream(new FileInputStream(file)), "UTF-8"); //$NON-NLS-1$
parser = new CSVParser(is, CSVFormat.DEFAULT);
records = parser.getRecords();
}
catch(IOException ex) {
if(parser != null) {
parser.close();
for(char delimiter : delimiters) {
BOMInputStream bomIn = BOMInputStream.builder().setInputStream(new FileInputStream(file)).get();
InputStreamReader is = new InputStreamReader(bomIn, "UTF-8"); //$NON-NLS-1$
CSVFormat csvFormat = Builder.create().setDelimiter(delimiter).build();

try(CSVParser parser = new CSVParser(is, csvFormat)) {
return parser.getRecords();
}
if(ex.getMessage() != null && ex.getMessage().contains(errorMessage)) {
try {
InputStreamReader is = new InputStreamReader(new BOMInputStream(new FileInputStream(file)), "UTF-8"); //$NON-NLS-1$
parser = new CSVParser(is, CSVFormat.DEFAULT.withDelimiter(';'));
records = parser.getRecords();
catch(UncheckedIOException ex1) {
ex = ex1.getCause();
// If it's not the expected Exception then break and throw it
if(!(ex.getMessage() != null && ex.getMessage().contains(expectedErrorMessage))) {
break;
}
catch(IOException ex2) {
if(parser != null) {
parser.close();
}
if(ex2.getMessage() != null && ex2.getMessage().contains(errorMessage)) {
InputStreamReader is = new InputStreamReader(new BOMInputStream(new FileInputStream(file)), "UTF-8"); //$NON-NLS-1$
parser = new CSVParser(is, CSVFormat.DEFAULT.withDelimiter('\t'));
records = parser.getRecords();
}
else {
throw ex2;
}
}
}
else {
throw ex;
}
}
finally {
if(parser != null) {
parser.close();
}
}

return records;
// If we got here then we failed, so throw the exception
throw ex;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Map.Entry;

import org.apache.commons.csv.CSVRecord;
import org.eclipse.gef.commands.CommandStack;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -444,4 +447,36 @@ public void testGetProperty() {
assertEquals(property, importer.getProperty(element, "key"));
assertNull(importer.getProperty(element, "key2"));
}

@Test
public void testGetRecordsWithDelimiters() throws Exception {
testGetRecords(',');
testGetRecords(';');
testGetRecords('\t');
}

@Test
public void testGetRecordsWithWrongDelimiterShouldThrowException() {
IOException ex = assertThrows(IOException.class, () -> {
testGetRecords(' ');
});

assertTrue(ex.getMessage().contains("invalid char between encapsulated token and delimiter"));
}

private void testGetRecords(char delimiter) throws Exception {
String csv = "\"Field 1\",\"Field 2\",\"Field 3\"";
csv = csv.replace(',', delimiter);

File file = TestUtils.createTempFile(".csv");
Files.writeString(file.toPath(), csv);

List<CSVRecord> records = importer.getRecords(file);
assertNotNull(records);
assertEquals(1, records.size());
CSVRecord rec = records.get(0);
assertEquals("Field 1", rec.get(0));
assertEquals("Field 2", rec.get(1));
assertEquals("Field 3", rec.get(2));
}
}

0 comments on commit e1b8f43

Please sign in to comment.