1

I'm trying create a List from especific positions in the csv file, instead parentheses.

class Person {//
@Parsed
private String name;
@??
private Address address;
@Convert(conversionClass = Emails2.class, args = { "," , "5,6" })
@Parsed
private List<String> emails;
}

csv format:

name,email1,email2,email3,street,number,neighborhood
Maria,ma@gmail.com,ma@hotmail.com,,Regent Street,12,downtown
Ana,ana@gmail.com,a@hotmail.com,,Bird Street,,east side

I need read the csv file and create a list of emails and an object of Address. I was trying to use @Convert,

public class Emails2 implements Conversion<String, Set<String>> {

    private final String separator;
    private final Set<String> positions;

    public Emails2(String... args) {
        String separator = ",";
        Set<String> positions = null;

        if (args.length == 1) {
            separator = args[0];
        }

        if (args.length == 2) {
            positions = new HashSet<String>();
            String[] posi = args[1].split(",");
            for (String string : posi) {
                positions.add(string);
            }
        }
        this.separator = separator;
        this.positions = positions;
    }

    public Emails2(String separator, Set<String> positions) {
        this.separator = separator;
        this.positions = positions;
    }
//this method is not called, I don't know why
    public Set<String> execute(String input) { //I would like add the list and Address object inside this method to get it done in beanProcessed(...)
        if (input == null) {
            return Collections.emptySet();
        }

        Set<String> out = new TreeSet<String>();
        for (String token : input.split(separator)) {
            for (String word : token.trim().split("\\s")) {
                out.add(word.trim());
            }
        }
        return out;
    }

    public String revert(Set<String> input) {
        return revert(input);
    }

}

How i'm doing

    public static void main(String[] args) {

            BeanProcessor<Person> rowProcessor = new BeanProcessor<Person>(Person.class) {
                @Override
                public void beanProcessed(Person c, ParsingContext context) {
                    System.out.println(c.getName());

                    String[] positions = context.currentParsedContent().split(","); 
                    System.out.println(positions[5]);
//I'm using fixed position here, I'd like get the position from @Convert or another way by configuration
                    System.out.println(positions[6]);
                    List<String> list = new ArrayList<>();
                    list.add(positions[5]);
                    list.add(positions[6]);
                    c.setEmails(list);
                }

            };

            CsvParserSettings parserSettings = new CsvParserSettings();
            parserSettings.setRowProcessor(rowProcessor);
            parserSettings.setHeaderExtractionEnabled(true);
            CsvParser parser2 = new CsvParser(parserSettings);
            parser2.parse(getReader("/var/lib/cob/test2.csv"));

        }
Eve
  • 37
  • 9
  • It's not very clear what you are intending to do. Can you please update the question to include the implementation of your custom conversion and any relevant methods/classes, along with the input and expected output? – Jeronimo Backes Feb 24 '17 at 11:55

2 Answers2

0

You are trying to assign values of multiple columns (email1, email2, email3) into a single attribute (Person.emails) via your custom Conversion, but that is not supported as the conversion targets a single field (or column of your input) instead of the entire row.

Additionally, the execute method in your custom conversion will not be called because there is no emails header in the input. When you annotate an attribute with the @Parsed annotation without providing a header name to match, the attribute name itself will be used. If you rename the attribute from emails to email1 you will see that your conversion class will be called, or if you simply provide the field name in the annotation, like this:

@Parsed(field = "email1")
private List<String> emails;

It will also be called.

I see what you are trying to do here and opened this issue to provide better support for this sort of requirement.

Hope this helps.

Jeronimo Backes
  • 6,141
  • 2
  • 25
  • 29
0

I achieved what I want in another way, not like I would like, but it worked. I used MultiBeanProcessor and created dummy classes(my boss won't like) to represent my csv positions.

My real csv has headers like:

email1,email2,email3,dddcel1,dddcel2,dddcel3,dddcel4,dddtel1,dddtel2,dddtel3,firstName,document,v_atu,ofe_cc,ignore1,bank,agency,ignore2,invoiceNumber,contactPhone,address,neighborhood,zip,city,state

    class Email{
    @Parsed 
    private String email1;
    @Parsed 
    private String email2;
     @Parsed
    private String email3;
    }

class Mobile{
    @Parsed
    private String dddcel1;
    @Parsed
    private String dddcel2;
    @Parsed
    private String dddcel3;
    @Parsed
    private String dddcel4;
}

And MultiBeanProcessor

 MultiBeanProcessor processor = new MultiBeanProcessor(Customer.class, Address.class, Email.class, Mobile.class, Phone.class) {
            private Customer customer;
            private Address address;
            private Email email;
            private Mobile mobile;
            private Phone phone;

            @Override
            public void beanProcessed(Class<?> beanType, Object beanInstance, ParsingContext context) {

                if (beanType == Customer.class) {
                    customer = (Customer) beanInstance;
                    customer.set_id(UUID.randomUUID().toString());
                    customer.setStatus(CustomerStatusType.PENDING);
                    customer.setDiscountValue(customer.getInvoiceValue() - customer.getTotalValue());
                    customer.setToken(UUID.randomUUID().toString());
                    try {
                        customer.setCreated(new java.text.SimpleDateFormat("yyyy-MM-dd")
                                .parse((new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date()))));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }

                    customer.setDomain("???????????");
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("banco", customer.getBank());
                    map.put("agencia", customer.getAgency());
                    customer.setInvoiceDetail(map);

                }

                if (beanType == Address.class) {
                    address = (Address) beanInstance;
                    customer.setAddress(address);
                }

                if (beanType == Email.class) {
                    email = (Email) beanInstance;
                    customer.setEmails(Arrays.asList(email.getEmail1(), email.getEmail2(), email.getEmail3()));
                }

                if (beanType == Mobile.class) {
                    mobile = (Mobile) beanInstance;
                    customer.setMobiles(Arrays.asList(mobile.getDddcel1(), mobile.getDddcel2(), mobile.getDddcel3(), mobile.getDddcel4()));

                }

                if (beanType == Phone.class) {
                    phone = (Phone) beanInstance;
                    customer.setPhones(Arrays.asList(phone.getDddtel1(), phone.getDddtel2(), phone.getDddtel3()));
                }

                if (customer != null && address != null && email != null && mobile != null & phone != null) {
                    System.out.println(customer);//save customer object
                    customer = null;
                    address = null;
                    email = null;
                    phone = null;
                    mobile = null;
                }

            }
        };

I'm testing yet, I hope it work for 500k lines :)

Eve
  • 37
  • 9