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 2017/04/09 07:58:13 UTC
[2/6] camel git commit: CAMEL-11065 Cannot parse CSV record starting
with separator character Changed Camel Bindy BindyCsvDataFormat#unquoteTokens
function.
CAMEL-11065 Cannot parse CSV record starting with separator character
Changed Camel Bindy BindyCsvDataFormat#unquoteTokens function.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/4e36bb99
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/4e36bb99
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/4e36bb99
Branch: refs/heads/master
Commit: 4e36bb998feeb68c8cb9c375eeff7e722d2c6fa8
Parents: 91bb1c3
Author: Sami Nurminen <sn...@gmail.com>
Authored: Thu Apr 6 21:57:57 2017 +0300
Committer: Claus Ibsen <da...@apache.org>
Committed: Sun Apr 9 09:54:47 2017 +0200
----------------------------------------------------------------------
.../bindy/csv/BindyCsvDataFormat.java | 79 ++++++++++--------
.../bindy/csv/BindySimpleCsvCAMEL11065Test.java | 84 ++++++++++++++++++++
.../bindy/model/csv/MyCsvRecord2.java | 61 ++++++++++++++
3 files changed, 189 insertions(+), 35 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/4e36bb99/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 45b4cd3..d56f243 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
@@ -238,54 +238,63 @@ public class BindyCsvDataFormat extends BindyAbstractDataFormat {
// if the separator char is also inside a quoted token, therefore we need
// to fix this afterwards
StringBuilder current = new StringBuilder();
-
+ boolean inProgress = false;
List<String> answer = new ArrayList<String>();
+
+ //parsing assumes matching close and end quotes
for (String s : result) {
- boolean startQuote = false;
- boolean endQuote = false;
+ boolean canStart = false;
+ boolean canClose = false;
+ boolean cutStart = false;
+ boolean cutEnd = false;
if (s.startsWith(quote)) {
- s = s.substring(1);
- startQuote = true;
+ //token is just a quote
+ if (s.length() == 1) {
+ s = "";
+ //if token is a quote then it can only close processing if it has begun
+ if (inProgress) {
+ canClose = true;
+ } else {
+ canStart = true;
+ }
+ } else {
+ //quote+"not empty"
+ cutStart = true;
+ canStart = true;
+ }
}
+
+ //"not empty"+quote
if (s.endsWith(quote)) {
- s = s.substring(0, s.length() - 1);
- endQuote = true;
+ cutEnd = true;
+ canClose = true;
}
- // are we in progress of rebuilding a broken token
- boolean currentInProgress = current.length() > 0;
+ //optimize to only substring once
+ if (cutEnd || cutStart) {
+ s = s.substring(cutStart ? 1 : 0, cutEnd ? s.length() - 1 : s.length());
+ }
- // situation when field ending with a separator symbol.
- if (currentInProgress && startQuote && s.isEmpty()) {
- // Add separator, append current and reset it
+ // are we in progress of rebuilding a broken token
+ if (inProgress) {
current.append(separator);
- answer.add(current.toString());
- current.setLength(0);
- continue;
- }
+ current.append(s);
- // 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
- if (currentInProgress) {
- // must append separator back as this is a quoted token that was broken
- // but a separator inside the quotes
- current.append(separator);
+ if (canClose) {
+ answer.add(current.toString());
+ current.setLength(0);
+ inProgress = false;
+ }
+ } else {
+ if (canStart && !canClose) {
+ current.append(s);
+ inProgress = true;
+ } else {
+ //case where no quotes
+ answer.add(s);
}
- current.append(s);
}
- // are we in progress of rebuilding a broken token
- currentInProgress = current.length() > 0;
-
- if (endQuote) {
- // we hit end quote so append current and reset it
- answer.add(current.toString());
- current.setLength(0);
- } else if (!currentInProgress) {
- // not rebuilding so add directly as is
- answer.add(s);
- }
}
// any left over from current?
http://git-wip-us.apache.org/repos/asf/camel/blob/4e36bb99/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/csv/BindySimpleCsvCAMEL11065Test.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/csv/BindySimpleCsvCAMEL11065Test.java b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/csv/BindySimpleCsvCAMEL11065Test.java
new file mode 100755
index 0000000..adbd29f
--- /dev/null
+++ b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/csv/BindySimpleCsvCAMEL11065Test.java
@@ -0,0 +1,84 @@
+/**
+ * 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.math.BigDecimal;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.dataformat.bindy.model.csv.MyCsvRecord2;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class BindySimpleCsvCAMEL11065Test extends CamelTestSupport {
+
+ @EndpointInject(uri = "mock:result")
+ private MockEndpoint mockEndPoint;
+
+ @Test
+ public void testUnMarshallMessage() throws Exception {
+
+ mockEndPoint.expectedMessageCount(4);
+
+ template.sendBody("direct:start", "'text1',',text2',1");
+ template.sendBody("direct:start", "',',',text2',2");
+ template.sendBody("direct:start", "',','text2,',3");
+ template.sendBody("direct:start", "'',',text2,',4");
+
+
+ mockEndPoint.assertIsSatisfied();
+
+ MyCsvRecord2 rc = mockEndPoint.getExchanges().get(0).getIn().getBody(MyCsvRecord2.class);
+ assertEquals("text1", rc.getText1());
+ assertEquals(",text2", rc.getText2());
+ assertEquals(BigDecimal.valueOf(1), rc.getNumber());
+
+ rc = mockEndPoint.getExchanges().get(1).getIn().getBody(MyCsvRecord2.class);
+ assertEquals(",", rc.getText1());
+ assertEquals(",text2", rc.getText2());
+ assertEquals(BigDecimal.valueOf(2), rc.getNumber());
+
+ rc = mockEndPoint.getExchanges().get(2).getIn().getBody(MyCsvRecord2.class);
+ assertEquals(",", rc.getText1());
+ assertEquals("text2,", rc.getText2());
+ assertEquals(BigDecimal.valueOf(3), rc.getNumber());
+
+ rc = mockEndPoint.getExchanges().get(3).getIn().getBody(MyCsvRecord2.class);
+ assertEquals(null, rc.getText1());
+ assertEquals(",text2,", rc.getText2());
+ assertEquals(BigDecimal.valueOf(4), rc.getNumber());
+
+
+
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ BindyCsvDataFormat camelDataFormat =
+ new BindyCsvDataFormat(MyCsvRecord2.class);
+ from("direct:start").unmarshal(camelDataFormat).to("mock:result");
+ }
+ };
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/4e36bb99/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/model/csv/MyCsvRecord2.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/model/csv/MyCsvRecord2.java b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/model/csv/MyCsvRecord2.java
new file mode 100644
index 0000000..3214595
--- /dev/null
+++ b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/model/csv/MyCsvRecord2.java
@@ -0,0 +1,61 @@
+/**
+ * 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.model.csv;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+import org.apache.camel.dataformat.bindy.annotation.CsvRecord;
+import org.apache.camel.dataformat.bindy.annotation.DataField;
+
+//from https://issues.apache.org/jira/browse/CAMEL-11065
+@CsvRecord(separator = ",", quote = "'")
+public class MyCsvRecord2 implements Serializable {
+
+ @DataField(pos = 1)
+ private String text1;
+
+ @DataField(pos = 2)
+ private String text2;
+
+ @DataField(pos = 3, pattern = "########.##")
+ private BigDecimal number;
+
+ public String getText1() {
+ return text1;
+ }
+
+ public void setText1(String text1) {
+ this.text1 = text1;
+ }
+
+ public String getText2() {
+ return text2;
+ }
+
+ public void setText2(String text2) {
+ this.text2 = text2;
+ }
+
+ public BigDecimal getNumber() {
+ return number;
+ }
+
+ public void setNumber(BigDecimal number) {
+ this.number = number;
+ }
+}