Repository: camel Updated Branches: refs/heads/master 3938344aa -> 5fcb5ab20
CAMEL-10030: BindyKeyValuePairDataFormat shold detect if the body is a map, a list of map or a simple value when marshalling Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/5fcb5ab2 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/5fcb5ab2 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/5fcb5ab2 Branch: refs/heads/master Commit: 5fcb5ab20e87ec263f1169984509ef6dd49f1bdd Parents: 3938344 Author: lburgazzoli <lburgazz...@gmail.com> Authored: Wed Jun 8 12:13:27 2016 +0200 Committer: lburgazzoli <lburgazz...@gmail.com> Committed: Wed Jun 8 12:16:05 2016 +0200 ---------------------------------------------------------------------- .../bindy/BindyAbstractDataFormat.java | 10 +- .../bindy/kvp/BindyKeyValuePairDataFormat.java | 32 +++-- .../fix/BindySimpleKeyValuePairFixTest.java | 134 +++++++++++++++++++ .../BindySimpleKeyValuePairFixTest-context.xml | 32 +++++ 4 files changed, 195 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/5fcb5ab2/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractDataFormat.java ---------------------------------------------------------------------- diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractDataFormat.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractDataFormat.java index c55084e..8ae6dce 100644 --- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractDataFormat.java +++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractDataFormat.java @@ -134,16 +134,22 @@ public abstract class BindyAbstractDataFormat extends ServiceSupport implements protected Map<String, Object> createLinkedFieldsModel(Object model) throws IllegalAccessException { Map<String, Object> row = new HashMap<>(); + createLinkedFieldsModel(model, row); + return row; + } + + protected void createLinkedFieldsModel(Object model, Map<String, Object> row) throws IllegalAccessException { for (Field field : model.getClass().getDeclaredFields()) { Link linkField = field.getAnnotation(Link.class); if (linkField != null) { boolean accessible = field.isAccessible(); field.setAccessible(true); - row.put(field.getType().getName(), field.get(model)); + if (!row.containsKey(field.getType().getName())) { + row.put(field.getType().getName(), field.get(model)); + } field.setAccessible(accessible); } } - return row; } protected abstract BindyAbstractFactory createModelFactory(FormatFactory formatFactory) throws Exception; http://git-wip-us.apache.org/repos/asf/camel/blob/5fcb5ab2/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/kvp/BindyKeyValuePairDataFormat.java ---------------------------------------------------------------------- diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/kvp/BindyKeyValuePairDataFormat.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/kvp/BindyKeyValuePairDataFormat.java index 6fb8a76..1d35957 100644 --- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/kvp/BindyKeyValuePairDataFormat.java +++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/kvp/BindyKeyValuePairDataFormat.java @@ -21,12 +21,15 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Scanner; import org.apache.camel.Exchange; +import org.apache.camel.TypeConverter; import org.apache.camel.dataformat.bindy.BindyAbstractDataFormat; import org.apache.camel.dataformat.bindy.BindyAbstractFactory; import org.apache.camel.dataformat.bindy.BindyKeyValuePairFactory; @@ -60,19 +63,26 @@ public class BindyKeyValuePairDataFormat extends BindyAbstractDataFormat { @SuppressWarnings("unchecked") public void marshal(Exchange exchange, Object body, OutputStream outputStream) throws Exception { - BindyAbstractFactory factory = getFactory(); - List<Map<String, Object>> models = (ArrayList<Map<String, Object>>)body; - byte[] crlf; - - // Get CRLF - crlf = ConverterUtils.getByteReturn(factory.getCarriageReturn()); + final BindyAbstractFactory factory = getFactory(); + final byte[] crlf = ConverterUtils.getByteReturn(factory.getCarriageReturn()); + final TypeConverter converter = exchange.getContext().getTypeConverter(); + + // the body may not be a prepared list of map that bindy expects so help + // a bit here and create one if needed + final Iterator<Object> it = ObjectHelper.createIterator(body); + while (it.hasNext()) { + Object model = it.next(); + + Map<String, Object> row; + if (model instanceof Map) { + row = (Map<String, Object>) model; + } else { + row = Collections.singletonMap(model.getClass().getName(), model); + } - for (Map<String, Object> model : models) { - String result = factory.unbind(model); - byte[] bytes = exchange.getContext().getTypeConverter().convertTo(byte[].class, exchange, result); - outputStream.write(bytes); + String result = factory.unbind(row); - // Add a carriage return + outputStream.write(converter.convertTo(byte[].class, exchange, result)); outputStream.write(crlf); } } http://git-wip-us.apache.org/repos/asf/camel/blob/5fcb5ab2/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fix/BindySimpleKeyValuePairFixTest.java ---------------------------------------------------------------------- diff --git a/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fix/BindySimpleKeyValuePairFixTest.java b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fix/BindySimpleKeyValuePairFixTest.java new file mode 100644 index 0000000..6c5368c --- /dev/null +++ b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fix/BindySimpleKeyValuePairFixTest.java @@ -0,0 +1,134 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.dataformat.bindy.fix; + +import java.util.Collections; + +import org.apache.camel.EndpointInject; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.Produce; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.dataformat.bindy.annotation.KeyValuePairField; +import org.apache.camel.dataformat.bindy.annotation.Message; +import org.apache.camel.dataformat.bindy.kvp.BindyKeyValuePairDataFormat; +import org.apache.camel.spi.DataFormat; +import org.junit.Test; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; + + +@ContextConfiguration +public class BindySimpleKeyValuePairFixTest extends AbstractJUnit4SpringContextTests { + private static final String[] FIX_REQUESTS = new String[] { + "8=FIX.4.1 37=1 38=1 40=butter", + "8=FIX.4.1 37=2 38=2 40=milk", + "8=FIX.4.1 37=3 38=3 40=bread" + }; + private static final String[] FIX_RESPONSES = new String[] { + "37=1 38=2 40=butter \r\n", + "37=2 38=4 40=milk \r\n", + "37=3 38=6 40=bread \r\n" + }; + + @Produce(uri = "direct:fix") + private ProducerTemplate template; + + @EndpointInject(uri = "mock:result") + private MockEndpoint mock; + + @Test + @DirtiesContext + public void testUnMarshallMessage() throws Exception { + mock.expectedMessageCount(FIX_RESPONSES.length); + mock.expectedBodiesReceived(FIX_RESPONSES); + + for (String request : FIX_REQUESTS) { + template.sendBody("direct:fix", request); + } + + mock.assertIsSatisfied(); + } + + public static class ContextConfig extends RouteBuilder { + @Override + public void configure() { + DataFormat bindy = new BindyKeyValuePairDataFormat(FixOrder.class); + from("direct:fix") + .unmarshal(bindy) + .process(new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + FixOrder order = exchange.getIn().getBody(FixOrder.class); + Object body = exchange.getIn().getBody(); + + if (order.getProduct().equals("butter")) { + order.setQuantity("2"); + body = order; + } else if (order.getProduct().equals("milk")) { + order.setQuantity("4"); + body = Collections.singletonMap(order.getClass().getName(), order); + } else if (order.getProduct().equals("bread")) { + order.setQuantity("6"); + body = Collections.singletonList(Collections.singletonMap(order.getClass().getName(), order)); + } + + exchange.getIn().setBody(body); + } + }) + .marshal(bindy) + .to("mock:result"); + } + } + + @Message(keyValuePairSeparator = "=", pairSeparator = " ", type = "FIX", version = "4.1") + public static class FixOrder { + @KeyValuePairField(tag = 37) + private String id; + @KeyValuePairField(tag = 40) + private String product; + @KeyValuePairField(tag = 38) + private String quantity; + + public String getId() { + return id; + } + + public void setId(String id) { + id = id; + } + + public String getProduct() { + return product; + } + + public void setProduct(String product) { + this.product = product; + } + + public String getQuantity() { + return quantity; + } + + public void setQuantity(String quantity) { + this.quantity = quantity; + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/5fcb5ab2/components/camel-bindy/src/test/resources/org/apache/camel/dataformat/bindy/fix/BindySimpleKeyValuePairFixTest-context.xml ---------------------------------------------------------------------- diff --git a/components/camel-bindy/src/test/resources/org/apache/camel/dataformat/bindy/fix/BindySimpleKeyValuePairFixTest-context.xml b/components/camel-bindy/src/test/resources/org/apache/camel/dataformat/bindy/fix/BindySimpleKeyValuePairFixTest-context.xml new file mode 100755 index 0000000..f5bd4cb --- /dev/null +++ b/components/camel-bindy/src/test/resources/org/apache/camel/dataformat/bindy/fix/BindySimpleKeyValuePairFixTest-context.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring + http://camel.apache.org/schema/spring/camel-spring.xsd"> + + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <routeBuilder ref="myBuilder" /> + </camelContext> + + <bean id="myBuilder" class="org.apache.camel.dataformat.bindy.fix.BindySimpleKeyValuePairFixTest$ContextConfig"/> + +</beans> \ No newline at end of file