Below you can see the repetition going on in my DataCsvLoader.
I've got a method getCsvAsMap which isnt in use. All the T are red because obviously while it might be getting a Map ... compiler doesnt know how to get that T type out of there...Is there a way to pass it?
Is the only way to create another class as a handler.. specifically for the getCsvAsMap method?
Sincrerely, Tricky4me
DataCsvLoader:
//
// Read and cache CSVs
//
public Map<Integer, CourseEntity> getAllCourses() {
String csvPath = "courses.csv";
// Create a new course Map with the right Entity type
Map<Integer, CourseEntity> entityMap = new HashMap<>();
repositoryInMem.put(csvPath, entityMap);
// Get data from CSV
EntityLoader<CourseEntity> entityLoader = new EntityLoader<>();
entityMap = entityLoader.readCsv(csvPath);
return entityMap;
}
public Map<Integer, StudentEntity> getAllStudents() {
String csvPath = "students.csv";
// Create a new course Map with the right Entity type
Map<Integer, StudentEntity> entityMap = new HashMap<>();
repositoryInMem.put(csvPath, entityMap);
// Get data from CSV
EntityLoader<StudentEntity> entityLoader = new EntityLoader<>();
entityMap = entityLoader.readCsv(csvPath);
return entityMap;
}
public Map<Integer, TestEntity> getAllTests() {
String csvPath = "tests.csv";
// Create a new course Map with the right Entity type
Map<Integer, TestEntity> entityMap = new HashMap<>();
repositoryInMem.put(csvPath, entityMap);
// Get data from CSV
EntityLoader<TestEntity> entityLoader = new EntityLoader<>();
entityMap = entityLoader.readCsv(csvPath);
return entityMap;
}
public Map<Integer, MarkEntity> getAllMarks() {
String csvPath = "marks.csv";
// Create a new course Map with the right Entity type
Map<Integer, MarkEntity> entityMap = new HashMap<>();
repositoryInMem.put(csvPath, entityMap);
// Get data from CSV
EntityLoader<MarkEntity> entityLoader = new EntityLoader<>();
entityMap = entityLoader.readCsv(csvPath);
return entityMap;
}
public Map<Integer, T> getCsvAsMap(String fileName, Map<Integer, T> entityMap){
// Add the Entity map to the repository in Mem
// The key to each entity map is just it's filename
repositoryInMem.put(fileName, entityMap);
// Get data from CSV
EntityLoader<T> entityLoader = new EntityLoader<T>();
entityMap = entityLoader.readCsv(fileName);
return entityMap;
}
EntityLoader:
public class EntityLoader<T> {
public Map<Integer, T> readCsv(String csvFile){
Map<Integer, T> table = new HashMap<>(); // Fits entire CSV table
int rowCount=0;
try {
String row;
BufferedReader csvReader = new BufferedReader(new FileReader(csvFile));
while ((row = csvReader.readLine()) != null) {
String[] data = row.split(",");
table.put(rowCount++, Arrays.asList(data));
}
csvReader.close();
}catch (FileNotFoundException e){
System.err.println("No file with name " + csvFile +
"Are the CSV files in the root folder? Ex: ReportCard\\courses.csv");
}catch (IOException e) {
System.err.println(e.getMessage());
}
}
}
Looks like you are not doing things the Object Oriented way. Classes that has similar properties should use abstraction.
Follow the given steps to solve the issue.
- Create an interface
IEntity
and implement the same on all entities. For example,MarkEntity
can be defined as
public class MarkEntity implements IEntity {
// class implementation
}
- Change the
getCsvAsMap()
to the following
public Map<Integer, IEntity> getCsvAsMap(String fileName, Map<Integer, IEntity> entityMap){
}
- Change the
EntityLoader
class to
public class EntityLoader<T extends IEntity> {
// Class implementation
}
That should do.
Edit
If abstraction is not possible, as entities don't share any features, or if the getCsvMap()
should return the same return type as the second argument, then the following replacement should work just fine.
public <T> Map<Integer, T> getCsvAsMap(String fileName, Map<Integer, T> entityMap)