Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,26 @@
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.eclipse.epsilon.common.util.FileUtil;
import org.eclipse.epsilon.common.util.StringProperties;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.exceptions.models.*;
import org.eclipse.epsilon.eol.exceptions.models.EolEnumerationValueNotFoundException;
import org.eclipse.epsilon.eol.exceptions.models.EolModelElementTypeNotFoundException;
import org.eclipse.epsilon.eol.exceptions.models.EolModelLoadingException;
import org.eclipse.epsilon.eol.exceptions.models.EolNotInstantiableModelElementTypeException;
import org.eclipse.epsilon.eol.models.CachedModel;
import org.eclipse.epsilon.eol.models.IRelativePathResolver;

Expand Down Expand Up @@ -58,6 +70,26 @@
*/
public class CsvModel extends CachedModel<Map<String, Object>> {

/**
* Various Epsilon languages assume that different model
* elements will have different hashcodes (e.g. ETL). This
* subclass of LinkedHashMap reverts to system identity-based
* hashcodes, to ensure that.
*/
protected static class Row extends LinkedHashMap<String, Object> {
private static final long serialVersionUID = 1L;

@Override
public int hashCode() {
return System.identityHashCode(this);
}

@Override
public boolean equals(Object other) {
return this == other;
}
}

public static final String HEADERLESS_FIELD_NAME = "field";

/** The Constant PROPERTY_FILE. */
Expand Down Expand Up @@ -357,7 +389,7 @@ private String concatenateMap() {
StringBuilder output = new StringBuilder();
if (this.knownHeaders) {
// First line is the headers
Iterator<String> keyIt = ((LinkedList<Map<String, Object>>) rows).getFirst().keySet().iterator();
Iterator<String> keyIt = rows.get(0).keySet().iterator();
output.append(keyIt.next());
while (keyIt.hasNext()) {
output.append(this.fieldSeparator);
Expand Down Expand Up @@ -412,12 +444,13 @@ protected Collection<Map<String, Object>> getAllOfKindFromModel(String kind) thr
* @see org.eclipse.epsilon.eol.models.CachedModel#createInstanceInModel(java.lang.String)
*/
@Override
protected Map<String, Object> createInstanceInModel(String type) throws EolModelElementTypeNotFoundException, EolNotInstantiableModelElementTypeException {
protected Row createInstanceInModel(String type) throws EolModelElementTypeNotFoundException, EolNotInstantiableModelElementTypeException {
if (!"Row".equals(type)) {
throw new EolModelElementTypeNotFoundException(this.name, type);
}
Map<String, Object> returnVal = new LinkedHashMap<>();
for (String key : ((LinkedList<Map<String, Object>>) rows).getFirst().keySet()) {

Row returnVal = new Row();
for (String key : rows.get(0).keySet()) {
returnVal.put(key, "");
}
rows.add(returnVal);
Expand All @@ -440,7 +473,7 @@ public boolean hasProperty(String type, String property) throws EolModelElementT
if (!this.knownHeaders) {
return property.equals(HEADERLESS_FIELD_NAME);
} else {
return ((LinkedHashMap<String, Object>) ((LinkedList<Map<String, Object>>) rows).getFirst()).keySet().contains(property);
return rows.get(0).keySet().contains(property);
}
}

Expand Down Expand Up @@ -471,7 +504,7 @@ protected static List<Map<String, Object>> createRows(BufferedReader reader,
try (CSVParser records = csvFormat.parse(reader)) {
if (knownHeaders) {
for (CSVRecord record : records) {
LinkedHashMap<String, Object> row = new LinkedHashMap<>();
Row row = new Row();
if (!varargsHeaders) {
for (Map.Entry<String, String> entry : record.toMap().entrySet()) {
row.put(entry.getKey(), entry.getValue());
Expand Down Expand Up @@ -502,7 +535,7 @@ protected static List<Map<String, Object>> createRows(BufferedReader reader,
for (CSVRecord record : records) {
List<String> values = new ArrayList<>();
record.iterator().forEachRemaining(values::add);
LinkedHashMap<String, Object> row = new LinkedHashMap<>();
Row row = new Row();
row.put("field", values);
rows.add(row);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;
Expand All @@ -25,8 +27,8 @@
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.eclipse.epsilon.eol.exceptions.models.EolModelElementTypeNotFoundException;
import org.eclipse.epsilon.eol.exceptions.models.EolNotInstantiableModelElementTypeException;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
Expand Down Expand Up @@ -373,7 +375,7 @@ public void testGetAllOfKindFromModelString() throws Exception {
}

@Test
public void testCreateInstanceInModelString() throws Exception, EolNotInstantiableModelElementTypeException {
public void testCreateInstanceInModelString() throws Exception {
Map<String, Object> newRow = model.createInstanceInModel("Row");
for (String key : headers) {
assertTrue(String.format("Field %s should be empty", key), ((String) newRow.get(key)).isEmpty());
Expand All @@ -382,6 +384,20 @@ public void testCreateInstanceInModelString() throws Exception, EolNotInstantiab
newRow = model.createInstanceInModel("TypeA");
}

@Test
public void testDifferentRowsHaveDifferentHashcodes() throws Exception {
Map<String, Object> newRow1 = model.createInstanceInModel("Row");
Map<String, Object> newRow2 = model.createInstanceInModel("Row");

/*
* Different rows should have different hashcodes and be considered not to be
* equal to each other. Otherwise, this may cause issues in some Epsilon
* languages, such as ETL.
*/
assertNotEquals(newRow1.hashCode(), newRow2.hashCode());
assertNotEquals(newRow1, newRow2);
}

@Test
public void testHasProperty() throws Exception {
for (String key : headers) {
Expand Down
Loading