Search code examples
javalistcsvsupercsv

Custom Cell Processor for Lists


I am trying to create a custom cell processor for SuperCSV that will handle a list from a field within the file. I have altered the bean constructor to accommodate the lists, now I just need to create the processor and I was wondering if anyone had experience with this. I've read the documentation...any help is appreciated!

Bean Constructor:

public class CustomerBean {
private String name;
private List<String> manufacturer;
private String model;
private List<String> owner;

public CustomerBean() {
}
public CustomerBean(final String name, final List<String> manufacturer,
    final String model, final List<String> owner,
    public String getName() { 
    return name;
}
public void setName(String name) {
    this.name = name;
}
public List<String> getManufacturer() {
    return manufacturer;
}
public void setManufacturer(List<String> manufacturer) {
    this.manufacturer = manufacturer;
}
public String getModel() {
    return model;
}
public void setModel(String model) {
    this.model = model;
}
public List<String> getOwner() {
    return owner;
}
public void setOwner(List<String> owner) {
    this.owner = owner;
}

public String toString() {
    return String
            .format("[Name=%s, Manufacturer=%s, Model=%s, Owner=%s]",
                    getName(), getManufacturer(), getModel(), getOwner());
}

Processor:

public class ParseHandler {

private static CellProcessor[] getProcessors() {

    final CellProcessor[] processors = new CellProcessor[] {

            new Optional(), //name
            new Optional(), //manufacturer - needs to be processed as a list!
            new Optional(), //model
            new Optional(), //owner - needs to be processed as a list!
            new Optional(), //integration team
            new Optional(), //shipping
            new Optional(), //hardware/software
            new Optional(), //subsystem
            new Optional(), //plane
            new Optional(), //integration stand-alone
            new Optional(), //integration interface
            new Optional(), //function
            new Optional(), //help links
            new Optional(), //installation instructions
            new Optional(), //test steps
            new Optional(), //lead engineer
    };
    return processors;
}

public static CustomerBean readWithCsvBeanReader(Path path) throws IOException {
    ICsvBeanReader beanReader = null;
    CustomerBean customer = null;
    System.out.println("Processing File: " + path);
    try {
        beanReader = new CsvBeanReader(new FileReader(path.toString()), CsvPreference.STANDARD_PREFERENCE);
        //header elements are the same as the bean property names
        final String[] header = {"name", "manufacturer", "model", "owner", "integrationTeam", "shipping", "hardwareSoftware", "subsystem", "plane", "integrationStandalone", 
                "integrationInterface", "function", "helpLinks", "installationInstructions", "testSteps", "leadEngineer"}; 
                 beanReader.getHeader(true);
        final CellProcessor[] processors = getProcessors();

        if ((customer = beanReader.read(CustomerBean.class, header, processors)) != null) {
            System.out.println(String.format("%s", customer.toString()));
        }
    } finally {
        if (beanReader != null) {
            beanReader.close();
        }
    } return customer;
}
}

Solution

  • As the documentation for creating a custom cell processor shows, you just need to create a new cell processor whose execute() method returns the object as a List of Strings.

    public class ParseStringList extends CellProcessorAdaptor {
    
            public ParseStringList() {
                    super();
            }
    
            public Object execute(Object value, CsvContext context) {
                    validateInputNotNull(value, context);  // throws an Exception if the input is null
                    List<String> result = new ArrayList<String>();
                    result.add((String) object);
                    return result;
            }
    }
    

    Then you can use new Optional(new ParseStringList()) as the processor for the manufacturer column.

    Alternatively (no custom cell processor required), you could just use CsvDozerBeanReader and indexed mapping (e.g. manufacturer[0]) as shown in the documentation.