Repository: camel Updated Branches: refs/heads/master f245ab072 -> 18f3e27d8
CAMEL-9843: camel-beanio - Add BeanIOSplitter Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/18f3e27d Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/18f3e27d Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/18f3e27d Branch: refs/heads/master Commit: 18f3e27d847abe2fc39cc66cc4edd230cbecfc83 Parents: f245ab0 Author: Claus Ibsen <davscl...@apache.org> Authored: Fri Apr 8 18:04:53 2016 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Fri Apr 8 18:04:53 2016 +0200 ---------------------------------------------------------------------- .../dataformat/beanio/BeanIODataFormat.java | 4 + .../camel/dataformat/beanio/BeanIOIterator.java | 63 ++++++++++++ .../camel/dataformat/beanio/BeanIOSplitter.java | 75 ++++++++++++++ .../dataformat/beanio/BeanIOSplitterTest.java | 101 +++++++++++++++++++ .../camel/dataformat/beanio/Employee.java | 11 ++ 5 files changed, 254 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/18f3e27d/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java ---------------------------------------------------------------------- diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java index 5af26f7..d27df2d 100644 --- a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java +++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java @@ -113,6 +113,10 @@ public class BeanIODataFormat extends ServiceSupport implements DataFormat, Data this.camelContext = camelContext; } + StreamFactory getFactory() { + return factory; + } + public void marshal(Exchange exchange, Object body, OutputStream stream) throws Exception { List<Object> models = getModels(exchange, body); writeModels(stream, models); http://git-wip-us.apache.org/repos/asf/camel/blob/18f3e27d/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOIterator.java ---------------------------------------------------------------------- diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOIterator.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOIterator.java new file mode 100644 index 0000000..6a9c5c7 --- /dev/null +++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOIterator.java @@ -0,0 +1,63 @@ +/** + * 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.beanio; + +import java.io.Closeable; +import java.io.IOException; +import java.util.Iterator; + +import org.beanio.BeanReader; + +public class BeanIOIterator implements Iterator<Object>, Closeable { + + private BeanReader reader; + private transient Object next; + + public BeanIOIterator(BeanReader reader) { + this.reader = reader; + this.next = next(); + } + + @Override + public void close() throws IOException { + if (reader != null) { + reader.close(); + reader = null; + } + } + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public Object next() { + Object answer = next; + if (answer == null) { + answer = reader.read(); + } else { + next = reader.read(); + } + return answer; + } + + @Override + public void remove() { + // noop + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/18f3e27d/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOSplitter.java ---------------------------------------------------------------------- diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOSplitter.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOSplitter.java new file mode 100644 index 0000000..bb153cc --- /dev/null +++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOSplitter.java @@ -0,0 +1,75 @@ +/** + * 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.beanio; + +import java.io.File; +import java.io.Reader; + +import org.apache.camel.Exchange; +import org.apache.camel.Expression; +import org.apache.camel.InvalidPayloadException; +import org.apache.camel.Message; +import org.apache.camel.WrappedFile; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.ServiceHelper; +import org.beanio.BeanReader; +import org.beanio.StreamFactory; + +public class BeanIOSplitter implements Expression { + + // TODO: should not reuse dataformat but have its own configuration likely + // TODO: need some way of starting to load the stream factory + private BeanIODataFormat dataFormat; + + public BeanIOSplitter(BeanIODataFormat dataFormat) throws Exception { + this.dataFormat = dataFormat; + ServiceHelper.startService(dataFormat); + } + + public Object evaluate(Exchange exchange) throws InvalidPayloadException { + Message msg = exchange.getIn(); + Object body = msg.getBody(); + + StreamFactory sf = dataFormat.getFactory(); + + BeanReader beanReader = null; + if (body instanceof WrappedFile) { + body = ((WrappedFile) body).getFile(); + } + if (body instanceof File) { + File file = (File) body; + beanReader = sf.createReader(dataFormat.getStreamName(), file); + } + if (beanReader == null) { + Reader reader = msg.getMandatoryBody(Reader.class); + beanReader = sf.createReader(dataFormat.getStreamName(), reader); + } + + return new BeanIOIterator(beanReader); + } + + @Override + public <T> T evaluate(Exchange exchange, Class<T> type) { + try { + Object result = evaluate(exchange); + return exchange.getContext().getTypeConverter().convertTo(type, exchange, result); + } catch (InvalidPayloadException e) { + throw ObjectHelper.wrapRuntimeCamelException(e); + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/18f3e27d/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterTest.java ---------------------------------------------------------------------- diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterTest.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterTest.java new file mode 100644 index 0000000..2ecb4c4 --- /dev/null +++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterTest.java @@ -0,0 +1,101 @@ +/** + * 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.beanio; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class BeanIOSplitterTest extends CamelTestSupport { + + // START SNIPPET: e2 + private static final String FIXED_DATA = + "Joe,Smith,Developer,75000,10012009" + LS + + "Jane,Doe,Architect,80000,01152008" + LS + + "Jon,Anderson,Manager,85000,03182007" + LS; + // END SNIPPET: e2 + + @Test + public void testSplit() throws Exception { + List<Employee> employees = getEmployees(); + + MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal"); + mock.expectedBodiesReceived(employees); + + template.sendBody("direct:unmarshal", FIXED_DATA); + + mock.assertIsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // START SNIPPET: e1 + // setup beanio data format using the mapping file, loaded from the classpath + BeanIODataFormat format = new BeanIODataFormat( + "org/apache/camel/dataformat/beanio/mappings.xml", + "employeeFile"); + format.setCamelContext(context); + + // a route which uses the bean io data format to format a CSV data + // to java objects + from("direct:unmarshal") + // and then split the message body so we get a message for each row + .split(new BeanIOSplitter(format)).streaming() + .to("log:line") + .to("mock:beanio-unmarshal"); + // END SNIPPET: e1 + } + }; + } + + private List<Employee> getEmployees() throws ParseException { + List<Employee> employees = new ArrayList<Employee>(); + Employee one = new Employee(); + one.setFirstName("Joe"); + one.setLastName("Smith"); + one.setTitle("Developer"); + one.setSalary(75000); + one.setHireDate(new SimpleDateFormat("MMddyyyy").parse("10012009")); + employees.add(one); + + Employee two = new Employee(); + two.setFirstName("Jane"); + two.setLastName("Doe"); + two.setTitle("Architect"); + two.setSalary(80000); + two.setHireDate(new SimpleDateFormat("MMddyyyy").parse("01152008")); + employees.add(two); + + Employee three = new Employee(); + three.setFirstName("Jon"); + three.setLastName("Anderson"); + three.setTitle("Manager"); + three.setSalary(85000); + three.setHireDate(new SimpleDateFormat("MMddyyyy").parse("03182007")); + employees.add(three); + return employees; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/18f3e27d/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Employee.java ---------------------------------------------------------------------- diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Employee.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Employee.java index 8a952e6..cb7cb16 100644 --- a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Employee.java +++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Employee.java @@ -97,4 +97,15 @@ public class Employee { && this.getSalary() == e.getSalary() && this.getHireDate().equals(e.getHireDate()); } + + @Override + public String toString() { + return "Employee{" + + "firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", title='" + title + '\'' + + ", salary=" + salary + + ", hireDate=" + hireDate + + '}'; + } } \ No newline at end of file