You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2013/10/17 11:13:48 UTC
[2/2] git commit: CAMEL-6381: Added autospanLine option to bindy CSV
format. Thanks to Asbjorn Aarrestad for patch.
CAMEL-6381: Added autospanLine option to bindy CSV format. Thanks to Asbjorn Aarrestad for patch.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/fa3f68b6
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/fa3f68b6
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/fa3f68b6
Branch: refs/heads/master
Commit: fa3f68b6135b50e2fb83fbdbfb719b9947ed1ee1
Parents: 7d3ee9b
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Oct 17 11:13:02 2013 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Oct 17 11:13:57 2013 +0200
----------------------------------------------------------------------
.../csv/BindySimpleCsvAutospanLineTest.java | 78 ++++++++++++++++++++
.../simple/spanLastRecord/SpanLastRecord.java | 45 +++++++++++
.../camel/dataformat/bindy/BindyCsvFactory.java | 32 +++++---
.../dataformat/bindy/annotation/CsvRecord.java | 5 ++
.../bindy/csv/BindyCsvDataFormat.java | 47 ++++++++++--
5 files changed, 192 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/fa3f68b6/components/camel-bindy/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/csv/BindySimpleCsvAutospanLineTest.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/csv/BindySimpleCsvAutospanLineTest.java b/components/camel-bindy/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/csv/BindySimpleCsvAutospanLineTest.java
new file mode 100644
index 0000000..0df3f6d
--- /dev/null
+++ b/components/camel-bindy/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/csv/BindySimpleCsvAutospanLineTest.java
@@ -0,0 +1,78 @@
+/**
+ * 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.csv;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.dataformat.bindy.model.simple.spanLastRecord.SpanLastRecord;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.CastUtils;
+import org.junit.Test;
+
+public class BindySimpleCsvAutospanLineTest extends CamelTestSupport {
+
+ @Test
+ public void testUnmarshalNoNeedToSpanLine() throws Exception {
+ final MockEndpoint mock = getMockEndpoint("mock:unmarshal");
+ mock.expectedMessageCount(1);
+
+ template.sendBody("direct:unmarshal", "1,hei,kommentar");
+
+ assertMockEndpointsSatisfied();
+
+ final List<Map<?, SpanLastRecord>> rows = CastUtils.cast(mock.getReceivedExchanges().get(0).getIn().getBody(List.class));
+ final SpanLastRecord order = rows.get(0).get(SpanLastRecord.class.getName());
+
+ assertEquals(1, order.getRecordId());
+ assertEquals("hei", order.getName());
+ assertEquals("kommentar", order.getComment());
+ }
+
+ @Test
+ public void testUnmarshalSpanningLine() throws Exception {
+ final MockEndpoint mock = getMockEndpoint("mock:unmarshal");
+ mock.expectedMessageCount(1);
+
+ template.sendBody("direct:unmarshal", "1,hei,kommentar,test,noe,hei");
+
+ assertMockEndpointsSatisfied();
+
+ final List<Map<?, SpanLastRecord>> rows = CastUtils.cast(mock.getReceivedExchanges().get(0).getIn().getBody(List.class));
+ final SpanLastRecord order = rows.get(0).get(SpanLastRecord.class.getName());
+
+ assertEquals(1, order.getRecordId());
+ assertEquals("hei", order.getName());
+ assertEquals("kommentar,test,noe,hei", order.getComment());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ final BindyCsvDataFormat bindy = new BindyCsvDataFormat("org.apache.camel.dataformat.bindy.model.simple.spanLastRecord");
+
+ from("direct:unmarshal")
+ .unmarshal(bindy)
+ .to("mock:unmarshal");
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/fa3f68b6/components/camel-bindy/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/model/simple/spanLastRecord/SpanLastRecord.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/model/simple/spanLastRecord/SpanLastRecord.java b/components/camel-bindy/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/model/simple/spanLastRecord/SpanLastRecord.java
new file mode 100644
index 0000000..bcb01ee
--- /dev/null
+++ b/components/camel-bindy/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/model/simple/spanLastRecord/SpanLastRecord.java
@@ -0,0 +1,45 @@
+package org.apache.camel.dataformat.bindy.model.simple.spanLastRecord;
+
+import org.apache.camel.dataformat.bindy.annotation.CsvRecord;
+import org.apache.camel.dataformat.bindy.annotation.DataField;
+
+@CsvRecord(separator = ",", autospanLine = true)
+public class SpanLastRecord {
+
+ @DataField(pos = 1)
+ private int recordId;
+ @DataField(pos = 2)
+ private String name;
+ @DataField(pos = 3)
+ private String comment;
+
+ public int getRecordId() {
+ return recordId;
+ }
+
+ public void setRecordId(final int recordId) {
+ this.recordId = recordId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getComment() {
+ return comment;
+ }
+
+ public void setComment(final String comment) {
+ this.comment = comment;
+ }
+
+ @Override
+ public String toString() {
+ return "SpanLastRecord [recordId=" + recordId + ", name=" + name + ", comment=" + comment + "]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/fa3f68b6/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyCsvFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyCsvFactory.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyCsvFactory.java
index 75fd63a2..29b3bcf 100755
--- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyCsvFactory.java
+++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyCsvFactory.java
@@ -16,7 +16,6 @@
*/
package org.apache.camel.dataformat.bindy;
-
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
@@ -40,7 +39,6 @@ import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
/**
* The BindyCsvFactory is the class who allows to : Generate a model associated
* to a CSV record, bind data from a record to the POJOs, export data of POJOs
@@ -60,6 +58,7 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
private int numberOptionalFields;
private int numberMandatoryFields;
private int totalFields;
+ private int maxpos;
private String separator;
private boolean skipFirstLine;
@@ -67,6 +66,7 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
private boolean messageOrdered;
private String quote;
private boolean quoting;
+ private boolean autospanLine;
public BindyCsvFactory(PackageScanClassResolver resolver, String... packageNames) throws Exception {
super(resolver, packageNames);
@@ -87,7 +87,7 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
* bind the data. This process will scan for classes according to the
* package name provided, check the annotated classes and fields and
* retrieve the separator of the CSV record
- *
+ *
* @throws Exception
*/
public void initCsvModel() throws Exception {
@@ -100,9 +100,10 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
initCsvRecordParameters();
}
+ @Override
public void initAnnotatedFields() {
- int maxpos = 0;
+ maxpos = 0;
for (Class<?> cl : models) {
List<Field> linkFields = new ArrayList<Field>();
@@ -176,7 +177,7 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
if (dataField.trim()) {
data = data.trim();
}
-
+
if (dataField.required()) {
// Increment counter of mandatory fields
++counterMandatoryFields;
@@ -377,7 +378,6 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
}
/**
- *
* Generate a table containing the data formatted and sorted with their position/offset
* If the model is Ordered than a key is created combining the annotation @Section and Position of the field
* If a relation @OneToMany is defined, than we iterate recursively through this function
@@ -482,10 +482,10 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
}
}
-
+
/**
* Generate for the first line the headers of the columns
- *
+ *
* @return the headers columns
*/
public String generateHeader() {
@@ -564,6 +564,9 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
quoting = record.quoting();
LOG.debug("CSV will be quoted: {}", messageOrdered);
+
+ autospanLine = record.autospanLine();
+ LOG.debug("Autospan line in last record: {}", autospanLine);
}
if (section != null) {
@@ -620,8 +623,15 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
}
/**
+ * If last record is to span the rest of the line
+ */
+ public boolean getAutospanLine() {
+ return autospanLine;
+ }
+
+ /**
* Flag indicating if the message must be ordered
- *
+ *
* @return boolean
*/
public boolean isMessageOrdered() {
@@ -631,4 +641,8 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
public String getQuote() {
return quote;
}
+
+ public int getMaxpos() {
+ return maxpos;
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/fa3f68b6/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/CsvRecord.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/CsvRecord.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/CsvRecord.java
index 238ec58..d6573e7 100755
--- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/CsvRecord.java
+++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/CsvRecord.java
@@ -80,4 +80,9 @@ public @interface CsvRecord {
*/
boolean quoting() default false;
+ /**
+ * Last record spans rest of line (optional)
+ */
+ boolean autospanLine() default false;
+
}
http://git-wip-us.apache.org/repos/asf/camel/blob/fa3f68b6/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/csv/BindyCsvDataFormat.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/csv/BindyCsvDataFormat.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/csv/BindyCsvDataFormat.java
index 5e1cac9..312ddd0 100755
--- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/csv/BindyCsvDataFormat.java
+++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/csv/BindyCsvDataFormat.java
@@ -150,7 +150,7 @@ public class BindyCsvDataFormat extends BindyAbstractDataFormat {
// Create POJO where CSV data will be stored
model = factory.factory();
-
+
// Split the CSV record according to the separator defined in
// annotated class @CSVRecord
String[] tokens = line.split(separator, -1);
@@ -160,13 +160,15 @@ public class BindyCsvDataFormat extends BindyAbstractDataFormat {
if (result.size() == 0 || result.isEmpty()) {
throw new java.lang.IllegalArgumentException("No records have been defined in the CSV");
- }
-
- if (result.size() > 0) {
+ } else {
if (LOG.isDebugEnabled()) {
LOG.debug("Size of the record splitted : {}", result.size());
}
+ if (factory.getAutospanLine()) {
+ result = autospanLine(result, factory.getMaxpos(), separator);
+ }
+
// Bind data from CSV record with model classes
factory.bind(result, model, count);
@@ -196,6 +198,38 @@ public class BindyCsvDataFormat extends BindyAbstractDataFormat {
}
/**
+ * Concatenate "the rest of the line" as the last record. Works similar as if quoted
+ *
+ * @param result input result set
+ * @param maxpos position of maximum record
+ * @param separator csv separator char
+ * @return List<String> with concatenated last record
+ */
+ private static List<String> autospanLine(final List<String> result, final int maxpos, final String separator) {
+ if (result.size() <= maxpos) {
+ return result;
+ }
+
+ final List<String> answer = new ArrayList<String>();
+ final StringBuilder lastRecord = new StringBuilder();
+
+ final Iterator<String> it = result.iterator();
+ for (int counter = 0; counter < maxpos - 1; counter++) {
+ answer.add(it.next());
+ }
+
+ while (it.hasNext()) {
+ lastRecord.append(it.next());
+ if (it.hasNext()) {
+ lastRecord.append(separator);
+ }
+ }
+ answer.add(lastRecord.toString());
+
+ return answer;
+ }
+
+ /**
* Unquote the tokens, by removing leading and trailing quote chars,
* as will handling fixing broken tokens which may have been split
* by a separator inside a quote.
@@ -224,7 +258,7 @@ public class BindyCsvDataFormat extends BindyAbstractDataFormat {
// are we in progress of rebuilding a broken token
boolean currentInProgress = current.length() > 0;
- // situation when field ending with a separator symbol.
+ // situation when field ending with a separator symbol.
if (currentInProgress && startQuote && s.isEmpty()) {
// Add separator, append current and reset it
current.append(separator);
@@ -232,7 +266,7 @@ public class BindyCsvDataFormat extends BindyAbstractDataFormat {
current.setLength(0);
continue;
}
-
+
// if we hit a start token then rebuild a broken token
if (currentInProgress || startQuote) {
// append to current if we are in the middle of a start quote
@@ -266,6 +300,7 @@ public class BindyCsvDataFormat extends BindyAbstractDataFormat {
return answer;
}
+ @Override
protected BindyAbstractFactory createModelFactory(PackageScanClassResolver resolver) throws Exception {
if (getClassType() != null) {
return new BindyCsvFactory(resolver, getClassType());