I have created a MappingsBean class where all the columns of the CSV file are specified. Next I parse XML files and create a list of mappingbeans. Then I write that data int
I wanted to achieve bi-directional import/export - to be able to import generated CSV back to POJO and visa versa.
I was not able to use @CsvBindByPosition for this, because in this case - ColumnPositionMappingStrategy was selected automatically. Per documents: this strategy requires that the file does NOT have a header.
HeaderColumnNameMappingStrategy
mappingStrategy.setColumnOrderOnWrite(Comparator writeOrder)
CsvUtils to read/write csv
import com.opencsv.CSVWriter;
import com.opencsv.bean.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.List;
public class CsvUtils {
private CsvUtils() {
}
public static String convertToCsv(List entitiesList, MappingStrategy mappingStrategy) throws Exception {
try (Writer writer = new StringWriter()) {
StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer)
.withMappingStrategy(mappingStrategy)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.build();
beanToCsv.write(entitiesList);
return writer.toString();
}
}
@SuppressWarnings("unchecked")
public static List convertFromCsv(MultipartFile file, Class clazz) throws IOException {
try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
CsvToBean csvToBean = new CsvToBeanBuilder(reader).withType(clazz).build();
return csvToBean.parse();
}
}
}
POJO for import/export
public class LocalBusinessTrainingPairDTO {
//this is used for CSV columns ordering on exporting LocalBusinessTrainingPairs
public static final String[] FIELDS_ORDER = {"leftId", "leftName", "rightId", "rightName"};
@CsvBindByName(column = "leftId")
private int leftId;
@CsvBindByName(column = "leftName")
private String leftName;
@CsvBindByName(column = "rightId")
private int rightId;
@CsvBindByName(column = "rightName")
private String rightName;
// getters/setters omitted, do not forget to add them
}
Custom comparator for predefined String ordering:
public class OrderedComparatorIgnoringCase implements Comparator {
private List predefinedOrder;
public OrderedComparatorIgnoringCase(String[] predefinedOrder) {
this.predefinedOrder = new ArrayList<>();
for (String item : predefinedOrder) {
this.predefinedOrder.add(item.toLowerCase());
}
}
@Override
public int compare(String o1, String o2) {
return predefinedOrder.indexOf(o1.toLowerCase()) - predefinedOrder.indexOf(o2.toLowerCase());
}
}
Ordered writing for POJO (answer to initial question)
public static void main(String[] args) throws Exception {
List localBusinessTrainingPairsDTO = new ArrayList<>();
LocalBusinessTrainingPairDTO localBusinessTrainingPairDTO = new LocalBusinessTrainingPairDTO();
localBusinessTrainingPairDTO.setLeftId(1);
localBusinessTrainingPairDTO.setLeftName("leftName");
localBusinessTrainingPairDTO.setRightId(2);
localBusinessTrainingPairDTO.setRightName("rightName");
localBusinessTrainingPairsDTO.add(localBusinessTrainingPairDTO);
//Creating HeaderColumnNameMappingStrategy
HeaderColumnNameMappingStrategy mappingStrategy = new HeaderColumnNameMappingStrategy<>();
mappingStrategy.setType(LocalBusinessTrainingPairDTO.class);
//Setting predefined order using String comparator
mappingStrategy.setColumnOrderOnWrite(new OrderedComparatorIgnoringCase(LocalBusinessTrainingPairDTO.FIELDS_ORDER));
String csv = convertToCsv(localBusinessTrainingPairsDTO, mappingStrategy);
System.out.println(csv);
}
Read exported CSV back to POJO (addition to original answer)
Important: CSV can be unordered, as we are still using binding by name:
public static void main(String[] args) throws Exception {
//omitted code from writing
String csv = convertToCsv(localBusinessTrainingPairsDTO, mappingStrategy);
//Exported CSV should be compatible for further import
File temp = File.createTempFile("tempTrainingPairs", ".csv");
temp.deleteOnExit();
BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
bw.write(csv);
bw.close();
MultipartFile multipartFile = new MockMultipartFile("tempTrainingPairs.csv", new FileInputStream(temp));
List localBusinessTrainingPairDTOList = convertFromCsv(multipartFile, LocalBusinessTrainingPairDTO.class);
}