apache-camelbindy

Convert csv to xml using bindy


I have csv like this:

31  name    2018-11-01  2018-10-31 12:05:16 3   
1   10  1.00    13.00       14  
2   20  1.00    14.00       14  
3   30  1.00    15.00       14  

fields in one line are separated by tab

and next I have another lines, separated tab too. Every line is separated by '\n'

How should me classes looks like?

I did something like this:

public class Order {

    private int id;
    private String name;
    private String date1;
    private int date2;
    private char numerOfFile;
    private List<OrderBody> orderBodyList;
}

public class OrderBody {

    private int lp;
    private int id;
    private BigDecimal priceByOne;
    private BigDecimal count;
    private int foreignId;
}

Solution

  • This is actually possible with camel-bindy using FixedLengthRecord model with tab as delimiter. Last field in the model seems to need a length but the others can use tab as a delimiter....

    Here's an example code:

    OrderHeader:

    import java.util.Date;
    
    import org.apache.camel.dataformat.bindy.annotation.DataField;
    import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
    
    @FixedLengthRecord()
    public class OrderHeader {
    
        @DataField(pos = 1, delimiter = "\t")
        private int id;
    
        @DataField(pos = 2, delimiter = "\t")
        private String name;
    
        @DataField(pos = 3, delimiter = "\t", pattern = "yyyy-MM-dd")
        private Date date1;
    
        @DataField(pos = 4, delimiter = "\t", pattern = "yyyy-MM-dd hh:mm:ss")
        private Date date2;
    
        @DataField(pos = 5, length = 1)
        private int numerOfFile;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Date getDate1() {
            return date1;
        }
    
        public void setDate1(Date date1) {
            this.date1 = date1;
        }
    
        public Date getDate2() {
            return date2;
        }
    
        public void setDate2(Date date2) {
            this.date2 = date2;
        }
    
        public int getNumerOfFile() {
            return numerOfFile;
        }
    
        public void setNumerOfFile(int numerOfFile) {
            this.numerOfFile = numerOfFile;
        }
    
    }
    

    Order:

    import java.math.BigDecimal;
    
    import org.apache.camel.dataformat.bindy.annotation.DataField;
    import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
    
    @FixedLengthRecord(header = OrderHeader.class)
    public class Order {
    
        @DataField(pos = 1, delimiter = "\t")
        private int lp;
    
        @DataField(pos = 2, delimiter = "\t")
        private int id;
    
        @DataField(pos = 3, delimiter = "\t")
        private BigDecimal priceByOne;
    
        @DataField(pos = 4, delimiter = "\t")
        private BigDecimal count;
    
        @DataField(pos = 5, length = 2)
        private int foreignId;
    
        public int getLp() {
            return lp;
        }
    
        public void setLp(int lp) {
            this.lp = lp;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public BigDecimal getPriceByOne() {
            return priceByOne;
        }
    
        public void setPriceByOne(BigDecimal priceByOne) {
            this.priceByOne = priceByOne;
        }
    
        public BigDecimal getCount() {
            return count;
        }
    
        public void setCount(BigDecimal count) {
            this.count = count;
        }
    
        public int getForeignId() {
            return foreignId;
        }
    
        public void setForeignId(int foreignId) {
            this.foreignId = foreignId;
        }
    
        @Override
        public String toString() {
            StringBuilder str = new StringBuilder();
            str.append("...lp:").append(lp).append("\n");
            str.append("...id:").append(id).append("\n");
            str.append("...priceByOne:").append(priceByOne).append("\n");
            str.append("...count:").append(count).append("\n");
            str.append("...foreignId:").append(foreignId).append("\n");
            return str.toString();
        }
    

    XmlOrder:

    import java.util.List;
    
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class XmlOrder extends OrderHeader {
    
        public XmlOrder() {
        }
    
        private List<Order> line;
    
        public XmlOrder(OrderHeader header, List<Order> lines) {
            this.setDate1(header.getDate1());
            this.setDate2(header.getDate2());
            this.setId(header.getId());
            this.setName(header.getName());
            this.setNumerOfFile(header.getNumerOfFile());
            this.setLines(lines);
        }
    
        public List<Order> getLines() {
            return line;
        }
    
        public void setLines(List<Order> lines) {
            this.line = lines;
        }
    
    }
    

    Route:

    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    
    import org.apache.camel.builder.RouteBuilder;
    import org.apache.camel.converter.jaxb.JaxbDataFormat;
    import org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat;
    
    import com.stefan.test.fixedlengthtest.model.Order;
    import com.stefan.test.fixedlengthtest.model.XmlOrder;
    import com.stefan.test.fixedlengthtest.processors.ProcessOrder;
    
    /**
     * A Camel Java8 DSL Router
     */
    public class MyRouteBuilder extends RouteBuilder {
    
        public void configure() throws JAXBException {
    
            // Initialize JAXB
            JAXBContext jaxbContext = JAXBContext.newInstance(XmlOrder.class);
            JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(jaxbContext);
    
            //@formatter:off
            from("file:testdir").routeId("data-route")
                .unmarshal(new BindyFixedLengthDataFormat(Order.class))
    
                .to("log:test?showAll=true")
    
                .log("Loop through data")
    
                .process(new ProcessOrder())
    
                .marshal(jaxbDataFormat)
                .log("Order: \n${body}")
    
                .log("DATA processed")
            ;
        }
    }
    

    OrderProcessor:

    import java.util.List;
    import java.util.Map;
    
    import org.apache.camel.Exchange;
    import org.apache.camel.Processor;
    import org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.stefan.test.fixedlengthtest.model.OrderHeader;
    import com.stefan.test.fixedlengthtest.model.XmlOrder;
    
    public class ProcessOrder implements Processor {
    
        private static final Logger logger = LoggerFactory.getLogger(ProcessOrder.class);
    
        @Override
        public void process(Exchange exchange) throws Exception {
            Map<String, OrderHeader> headermap = exchange.getIn()
                    .getHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_HEADER, Map.class);
    
            OrderHeader header = headermap.get(OrderHeader.class.getName());
    
            logger.info("Processing order: {}", header.getId());
            logger.info("...date1: {}", header.getDate1());
            logger.info("...date2: {}", header.getDate2());
            logger.info("...numberOfFile: {}", header.getNumerOfFile());
    
            XmlOrder xmlorder = new XmlOrder(header, exchange.getIn().getBody(List.class));
            exchange.getIn().setBody(xmlorder);
        }
    }
    

    This example route will output something like:

    [                          main] ProcessOrder                   INFO  Processing order: 31
    [                          main] ProcessOrder                   INFO  ...date1: 2018-11-01T00:00:00.000+0200
    [                          main] ProcessOrder                   INFO  ...date2: 2018-10-31T00:05:16.000+0200
    [                          main] ProcessOrder                   INFO  ...numberOfFile: 3
    [                          main] data-route                     INFO  Order: 
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xmlOrder>
        <date1>2018-11-01T00:00:00+02:00</date1>
        <date2>2018-10-31T00:05:16+02:00</date2>
        <id>31</id>
        <name>name</name>
        <numerOfFile>3</numerOfFile>
        <lines>
            <count>13</count>
            <foreignId>14</foreignId>
            <id>10</id>
            <lp>1</lp>
            <priceByOne>1</priceByOne>
        </lines>
        <lines>
            <count>14</count>
            <foreignId>14</foreignId>
            <id>20</id>
            <lp>2</lp>
            <priceByOne>1</priceByOne>
        </lines>
        <lines>
            <count>15</count>
            <foreignId>14</foreignId>
            <id>30</id>
            <lp>3</lp>
            <priceByOne>1</priceByOne>
        </lines>
    </xmlOrder>
    
    [                          main] data-route                     INFO  DATA processed
    

    You can check full sources for this in github