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 2016/03/22 16:33:07 UTC

camel git commit: CAMEL-6163: camel-bindy add custom data converter. Thanks to Roberto Coral Azambuja for the patch.

Repository: camel
Updated Branches:
  refs/heads/master 274957ad6 -> 1f9dc80da


CAMEL-6163: camel-bindy add custom data converter. Thanks to Roberto Coral Azambuja for the patch.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/1f9dc80d
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/1f9dc80d
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/1f9dc80d

Branch: refs/heads/master
Commit: 1f9dc80da113ea4fd29b9bde6a5fe12dc346df5d
Parents: 274957a
Author: Claus Ibsen <da...@apache.org>
Authored: Tue Mar 22 16:32:54 2016 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Tue Mar 22 16:32:54 2016 +0100

----------------------------------------------------------------------
 .../camel/dataformat/bindy/BindyCsvFactory.java |   9 +-
 .../bindy/BindyFixedLengthFactory.java          | 115 +++++++--------
 .../bindy/BindyKeyValuePairFactory.java         |  21 +--
 .../camel/dataformat/bindy/FormatFactory.java   |  13 +-
 .../bindy/annotation/BindyConverter.java        |  34 +++++
 .../fixed/converter/BindyConverterTest.java     | 139 +++++++++++++++++++
 6 files changed, 261 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/1f9dc80d/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 a699c04..045970d 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
@@ -27,6 +27,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TreeMap;
 
+import org.apache.camel.dataformat.bindy.annotation.BindyConverter;
 import org.apache.camel.dataformat.bindy.annotation.CsvRecord;
 import org.apache.camel.dataformat.bindy.annotation.DataField;
 import org.apache.camel.dataformat.bindy.annotation.Link;
@@ -155,6 +156,7 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
         }
     }
 
+    @Override
     public void bind(List<String> tokens, Map<String, Object> model, int line) throws Exception {
 
         int pos = 1;
@@ -190,7 +192,7 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
             }
 
             // Create format object to format the field
-            Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), dataField);
+            Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), dataField, field.getAnnotation(BindyConverter.class));
 
             // field object to be set
             Object modelField = model.get(field.getDeclaringClass().getName());
@@ -232,6 +234,7 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
 
     }
 
+    @Override
     public String unbind(Map<String, Object> model) throws Exception {
 
         StringBuilder buffer = new StringBuilder();
@@ -393,7 +396,7 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
                     Class<?> type = field.getType();
 
                     // Create format
-                    Format<?> format = FormatFactory.getFormat(type, getLocale(), datafield);
+                    Format<?> format = FormatFactory.getFormat(type, getLocale(), datafield, field.getAnnotation(BindyConverter.class));
 
                     // Get field value
                     Object value = field.get(obj);
@@ -586,7 +589,7 @@ public class BindyCsvFactory extends BindyAbstractFactory implements BindyFactor
             DataField dataField = dataFields.get(i);
             Object modelField = model.get(field.getDeclaringClass().getName());
             if (field.get(modelField) == null && !dataField.defaultValue().isEmpty()) {
-                Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), dataField);
+                Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), dataField, field.getAnnotation(BindyConverter.class));
                 Object value = format.parse(dataField.defaultValue());
                 field.set(modelField, value);
             }

http://git-wip-us.apache.org/repos/asf/camel/blob/1f9dc80d/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java
index 920d9e6..d6b8aed 100644
--- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java
+++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TreeMap;
 
+import org.apache.camel.dataformat.bindy.annotation.BindyConverter;
 import org.apache.camel.dataformat.bindy.annotation.DataField;
 import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
 import org.apache.camel.dataformat.bindy.annotation.Link;
@@ -48,7 +49,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
 
     private Map<Integer, DataField> dataFields = new TreeMap<Integer, DataField>();
     private Map<Integer, Field> annotatedFields = new TreeMap<Integer, Field>();
-   
+
     private int numberOptionalFields;
     private int numberMandatoryFields;
     private int totalFields;
@@ -62,27 +63,27 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
     private char paddingChar;
     private int recordLength;
     private boolean ignoreTrailingChars;
-    
+
     private Class<?> header;
     private Class<?> footer;
 
     public BindyFixedLengthFactory(Class<?> type) throws Exception {
         super(type);
-        
+
         header = void.class;
         footer = void.class;
-        
+
         // initialize specific parameters of the fixed length model
         initFixedLengthModel();
     }
-    
+
     /**
      * method uses to initialize the model representing the classes who will
      * bind the data. This process will scan for classes according to the
      * package name provided, check the annotated classes and fields
      */
-    public void initFixedLengthModel() throws Exception {      
-        
+    public void initFixedLengthModel() throws Exception {
+
         // Find annotated fields declared in the Model classes
         initAnnotatedFields();
 
@@ -91,6 +92,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
         initFixedLengthRecordParameters();
     }
 
+    @Override
     public void initAnnotatedFields() {
 
         for (Class<?> cl : models) {
@@ -104,7 +106,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
             for (Field field : cl.getDeclaredFields()) {
                 DataField dataField = field.getAnnotation(DataField.class);
                 if (dataField != null) {
-                    
+
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Position defined in the class: {}, position: {}, Field: {}", new Object[]{cl.getName(), dataField.pos(), dataField});
                     }
@@ -144,9 +146,9 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
 
         }
     }
-    
+
     // Will not be used in the case of a Fixed Length record
-    // as we provide the content of the record and 
+    // as we provide the content of the record and
     // we don't split it as this is the case for a CSV record
     @Override
     public void bind(List<String> data, Map<String, Object> model, int line) throws Exception {
@@ -175,7 +177,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
             dataField = itr.next();
             length = dataField.length();
             delimiter = dataField.delimiter();
-            
+
             if (length == 0 && dataField.lengthPos() != 0) {
                 Field lengthField = annotatedFields.get(dataField.lengthPos());
                 lengthField.setAccessible(true);
@@ -196,7 +198,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
                 LOG.debug("skipping ahead [" + (dataField.pos() - offset) + "] chars.");
                 offset = dataField.pos();
             }
-            
+
             if (length > 0) {
                 token = record.substring(offset - 1, offset + length - 1);
                 offset += length;
@@ -227,7 +229,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
                                                        + " is empty for the line: " + line);
                 }
             }
-            
+
             // Get Field to be set
             field = annotatedFields.get(dataField.pos());
             field.setAccessible(true);
@@ -237,7 +239,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
             }
 
             // Create format object to format the field
-            Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), dataField);
+            Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), dataField, field.getAnnotation(BindyConverter.class));
 
             // field object to be set
             Object modelField = model.get(field.getDeclaringClass().getName());
@@ -258,11 +260,11 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
             }
 
             field.set(modelField, value);
-            
+
             ++pos;
-        
+
         }
-        
+
         // check for unmapped non-whitespace data at the end of the line
         if (offset <= record.length() && !(record.substring(offset - 1, record.length())).trim().equals("") && !isIgnoreTrailingChars()) {
             throw new IllegalArgumentException("Unexpected / unmapped characters found at the end of the fixed-length record at line : " + line);
@@ -276,10 +278,11 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
 
         if (counterMandatoryFields < numberMandatoryFields) {
             throw new IllegalArgumentException("Some mandatory fields are missing, line: " + line);
-        }  
-        
+        }
+
     }
 
+    @Override
     public String unbind(Map<String, Object> model) throws Exception {
 
         StringBuilder buffer = new StringBuilder();
@@ -312,15 +315,15 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
             // Get list of values
             List<String> val = entry.getValue();
             String value = val.get(0);
-            
+
             buffer.append(value);
         }
-        
+
         return buffer.toString();
     }
 
     /**
-     * 
+     *
      * Generate a table containing the data formatted and sorted with their position/offset
      * The result is placed in the Map<Integer, List> results
      */
@@ -342,7 +345,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
                     Class<?> type = field.getType();
 
                     // Create format
-                    Format<?> format = FormatFactory.getFormat(type, getLocale(), datafield);
+                    Format<?> format = FormatFactory.getFormat(type, getLocale(), datafield, field.getAnnotation(BindyConverter.class));
 
                     // Get field value
                     Object value = field.get(obj);
@@ -353,19 +356,19 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
                     if (datafield.trim()) {
                         result = result.trim();
                     }
-                    
+
                     int fieldLength = datafield.length();
-                    
+
                     if (fieldLength == 0 && (datafield.lengthPos() > 0)) {
                         List<String> resultVals = results.get(datafield.lengthPos());
                         fieldLength = Integer.valueOf(resultVals.get(0));
                     }
-                    
+
                     if (fieldLength <= 0 && datafield.delimiter().equals("") && datafield.lengthPos() == 0) {
-                        throw new IllegalArgumentException("Either a delimiter value or length for the field: " 
+                        throw new IllegalArgumentException("Either a delimiter value or length for the field: "
                                 + field.getName() + " is mandatory.");
                     }
-                    
+
                     if (!datafield.delimiter().equals("")) {
                         result = result + datafield.delimiter();
                     } else {
@@ -375,10 +378,10 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
                         char padChar;
 
                         StringBuilder temp = new StringBuilder();
-    
+
                         // Check if we must pad
                         if (result.length() < fieldLength) {
-    
+
                             // No padding defined for the field
                             if (padCharField == 0) {
                                 // We use the padding defined for the Record
@@ -386,7 +389,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
                             } else {
                                 padChar = padCharField;
                             }
-    
+
                             if (align.contains("R")) {
                                 temp.append(generatePaddingChars(padChar, fieldLength, result.length()));
                                 temp.append(result);
@@ -397,11 +400,11 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
                                 throw new IllegalArgumentException("Alignment for the field: " + field.getName()
                                         + " must be equal to R for RIGHT or L for LEFT");
                             }
-    
+
                             result = temp.toString();
                         } else if (result.length() > fieldLength) {
                             // we are bigger than allowed
-    
+
                             // is clipped enabled? if so clip the field
                             if (datafield.clip()) {
                                 result = result.substring(0, fieldLength);
@@ -437,7 +440,7 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
         }
 
     }
-    
+
     private String generatePaddingChars(char pad, int lengthField, int lengthString) {
         StringBuilder buffer = new StringBuilder();
         int size = lengthField - lengthString;
@@ -467,28 +470,28 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
 
                 // Get header parameter
                 header =  record.header();
-                LOG.debug("Header: {}", header);                
+                LOG.debug("Header: {}", header);
                 hasHeader = header != void.class;
                 LOG.debug("Has Header: {}", hasHeader);
-                                
+
                 // Get skipHeader parameter
                 skipHeader = record.skipHeader();
                 LOG.debug("Skip Header: {}", skipHeader);
 
                 // Get footer parameter
                 footer =  record.footer();
-                LOG.debug("Footer: {}", footer);                
+                LOG.debug("Footer: {}", footer);
                 hasFooter = record.footer() != void.class;
                 LOG.debug("Has Footer: {}", hasFooter);
-                
+
                 // Get skipFooter parameter
                 skipFooter = record.skipFooter();
                 LOG.debug("Skip Footer: {}", skipFooter);
-                
+
                 // Get isHeader parameter
                 isHeader = hasHeader ? cl.equals(header) : false;
                 LOG.debug("Is Header: {}", isHeader);
-                
+
                 // Get isFooter parameter
                 isFooter = hasFooter ? cl.equals(footer) : false;
                 LOG.debug("Is Footer: {}", isFooter);
@@ -506,80 +509,80 @@ public class BindyFixedLengthFactory extends BindyAbstractFactory implements Bin
                 LOG.debug("Ignore trailing chars: {}", ignoreTrailingChars);
             }
         }
-        
+
         if (hasHeader && isHeader) {
             throw new java.lang.IllegalArgumentException("Record can not be configured with both 'isHeader=true' and 'hasHeader=true'");
         }
-        
+
         if (hasFooter && isFooter) {
             throw new java.lang.IllegalArgumentException("Record can not be configured with both 'isFooter=true' and 'hasFooter=true'");
         }
-        
+
         if ((isHeader || isFooter) && (skipHeader || skipFooter)) {
             throw new java.lang.IllegalArgumentException(
                     "skipHeader and/or skipFooter can not be configured on a record where 'isHeader=true' or 'isFooter=true'");
         }
-        
+
     }
-       
+
     /**
-     * 
+     *
      * @return
      */
     public Class<?> header() {
         return header;
     }
-    
+
     /**
      * Flag indicating if we have a header
      */
     public boolean hasHeader() {
         return hasHeader;
-    } 
-    
+    }
+
     /**
-     * 
+     *
      * @return
      */
     public Class<?> footer() {
         return footer;
     }
-    
+
     /**
      * Flag indicating if we have a footer
      */
     public boolean hasFooter() {
         return hasFooter;
     }
-    
+
     /**
      * Flag indicating whether to skip the header parsing
      */
     public boolean skipHeader() {
         return skipHeader;
     }
-    
+
     /**
      * Flag indicating whether to skip the footer processing
      */
     public boolean skipFooter() {
         return skipFooter;
     }
-    
+
     /**
      * Flag indicating whether this factory is for a header
      */
     public boolean isHeader() {
         return isHeader;
     }
-    
+
     /**
      * Flag indicating whether this factory is for a footer
      */
     public boolean isFooter() {
         return isFooter;
     }
-    
+
     /**
      * Padding char used to fill the field
      */

http://git-wip-us.apache.org/repos/asf/camel/blob/1f9dc80d/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyKeyValuePairFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyKeyValuePairFactory.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyKeyValuePairFactory.java
index 625a415..6625be0 100644
--- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyKeyValuePairFactory.java
+++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyKeyValuePairFactory.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
+import org.apache.camel.dataformat.bindy.annotation.BindyConverter;
 import org.apache.camel.dataformat.bindy.annotation.KeyValuePairField;
 import org.apache.camel.dataformat.bindy.annotation.Link;
 import org.apache.camel.dataformat.bindy.annotation.Message;
@@ -54,7 +55,7 @@ public class BindyKeyValuePairFactory extends BindyAbstractFactory implements Bi
     private String pairSeparator;
     private boolean messageOrdered;
 
-    
+
     public BindyKeyValuePairFactory(Class<?> type) throws Exception {
         super(type);
 
@@ -67,7 +68,7 @@ public class BindyKeyValuePairFactory extends BindyAbstractFactory implements Bi
      * bind the data This process will scan for classes according to the package
      * name provided, check the annotated classes and fields. Next, we retrieve
      * the parameters required like : Pair Separator & key value pair separator
-     * 
+     *
      * @throws Exception
      */
     public void initKeyValuePairModel() throws Exception {
@@ -80,6 +81,7 @@ public class BindyKeyValuePairFactory extends BindyAbstractFactory implements Bi
 
     }
 
+    @Override
     public void initAnnotatedFields() {
 
         for (Class<?> cl : models) {
@@ -277,7 +279,7 @@ public class BindyKeyValuePairFactory extends BindyAbstractFactory implements Bi
                             if (value != null) {
 
                                 // Create format object to format the field
-                                Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), keyValuePairField);
+                                Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), keyValuePairField, field.getAnnotation(BindyConverter.class));
 
                                 // format the value of the key received
                                 result = formatField(format, value, key, line);
@@ -313,7 +315,7 @@ public class BindyKeyValuePairFactory extends BindyAbstractFactory implements Bi
                                     value = values.get(i);
 
                                     // Create format object to format the field
-                                    Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), keyValuePairField);
+                                    Format<?> format = FormatFactory.getFormat(field.getType(), getLocale(), keyValuePairField, field.getAnnotation(BindyConverter.class));
 
                                     // format the value of the key received
                                     Object result = formatField(format, value, key, line);
@@ -399,8 +401,9 @@ public class BindyKeyValuePairFactory extends BindyAbstractFactory implements Bi
     }
 
     /**
-     * 
+     *
      */
+    @Override
     public String unbind(Map<String, Object> model) throws Exception {
 
         StringBuilder builder = new StringBuilder();
@@ -441,7 +444,7 @@ public class BindyKeyValuePairFactory extends BindyAbstractFactory implements Bi
 
             // Create format
             @SuppressWarnings("unchecked")
-            Format<Object> format = (Format<Object>)FormatFactory.getFormat(type, getLocale(), keyValuePairField);
+            Format<Object> format = (Format<Object>)FormatFactory.getFormat(type, getLocale(), keyValuePairField, field.getAnnotation(BindyConverter.class));
 
             // Get object to be formatted
             Object obj = model.get(field.getDeclaringClass().getName());
@@ -456,9 +459,9 @@ public class BindyKeyValuePairFactory extends BindyAbstractFactory implements Bi
                     // and the position of the field
                     Integer key1 = sections.get(obj.getClass().getName());
                     Integer key2 = keyValuePairField.position();
-                    
+
                     LOG.debug("Key of the section: {}, and the field: {}", key1, key2);
-                 
+
                     Integer keyGenerated = generateKey(key1, key2);
 
                     if (LOG.isDebugEnabled()) {
@@ -575,7 +578,7 @@ public class BindyKeyValuePairFactory extends BindyAbstractFactory implements Bi
 
     /**
      * Flag indicating if the message must be ordered
-     * 
+     *
      * @return boolean
      */
     public boolean isMessageOrdered() {

http://git-wip-us.apache.org/repos/asf/camel/blob/1f9dc80d/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/FormatFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/FormatFactory.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/FormatFactory.java
index 48230a1..7a63f77 100755
--- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/FormatFactory.java
+++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/FormatFactory.java
@@ -22,6 +22,7 @@ import java.math.BigInteger;
 import java.util.Date;
 import java.util.Locale;
 
+import org.apache.camel.dataformat.bindy.annotation.BindyConverter;
 import org.apache.camel.dataformat.bindy.annotation.DataField;
 import org.apache.camel.dataformat.bindy.annotation.KeyValuePairField;
 import org.apache.camel.dataformat.bindy.format.BigDecimalFormat;
@@ -128,7 +129,11 @@ public final class FormatFactory {
      * @return Format the formatter
      * @throws IllegalArgumentException if not suitable formatter is found
      */
-    public static Format<?> getFormat(Class<?> clazz, String locale, DataField data) throws Exception {
+    public static Format<?> getFormat(Class<?> clazz, String locale, DataField data, BindyConverter converter) throws Exception {
+        if (converter != null) {
+            return converter.value().newInstance();
+        }
+
         String pattern = data.pattern();
         String timezone = data.timezone();
         int precision = data.precision();
@@ -148,7 +153,11 @@ public final class FormatFactory {
      * @throws IllegalArgumentException if not suitable formatter is found
      * TODO : Check if KeyValuePair could also use decimal/groupingSeparator/rounding for BigDecimal
      */
-    public static Format<?> getFormat(Class<?> clazz, String locale, KeyValuePairField data) throws Exception {
+    public static Format<?> getFormat(Class<?> clazz, String locale, KeyValuePairField data, BindyConverter converter) throws Exception {
+        if (converter != null) {
+            return converter.value().newInstance();
+        }
+
         String pattern = data.pattern();
         String timezone = data.timezone();
         int precision = data.precision();

http://git-wip-us.apache.org/repos/asf/camel/blob/1f9dc80d/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/BindyConverter.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/BindyConverter.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/BindyConverter.java
new file mode 100644
index 0000000..7dfed7e
--- /dev/null
+++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/BindyConverter.java
@@ -0,0 +1,34 @@
+/**
+ * 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.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import org.apache.camel.dataformat.bindy.Format;
+
+
+/**
+ * An annotation used to identify which converter class will be used to convert
+ * the String field to the attribute's data type.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+public @interface BindyConverter {
+    Class<? extends Format<?>> value();
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/1f9dc80d/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/converter/BindyConverterTest.java
----------------------------------------------------------------------
diff --git a/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/converter/BindyConverterTest.java b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/converter/BindyConverterTest.java
new file mode 100644
index 0000000..7ff80b3
--- /dev/null
+++ b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/converter/BindyConverterTest.java
@@ -0,0 +1,139 @@
+/**
+ * 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.fixed.converter;
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+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.Format;
+import org.apache.camel.dataformat.bindy.annotation.BindyConverter;
+import org.apache.camel.dataformat.bindy.annotation.DataField;
+import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
+import org.apache.camel.model.dataformat.BindyDataFormat;
+import org.apache.camel.model.dataformat.BindyType;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+
+@ContextConfiguration
+public class BindyConverterTest extends CamelTestSupport {
+
+    public static final String URI_DIRECT_MARSHALL         = "direct:marshall";
+    public static final String URI_DIRECT_UNMARSHALL       = "direct:unmarshall";
+    public static final String URI_MOCK_MARSHALL_RESULT    = "mock:marshall-result";
+    public static final String URI_MOCK_UNMARSHALL_RESULT  = "mock:unmarshall-result";
+
+    // *************************************************************************
+    //
+    // *************************************************************************
+
+    @Produce(uri = URI_DIRECT_MARSHALL)
+    private ProducerTemplate mtemplate;
+
+    @EndpointInject(uri = URI_MOCK_MARSHALL_RESULT)
+    private MockEndpoint mresult;
+
+    @Produce(uri = URI_DIRECT_UNMARSHALL)
+    private ProducerTemplate utemplate;
+
+    @EndpointInject(uri = URI_MOCK_UNMARSHALL_RESULT)
+    private MockEndpoint uresult;
+
+    // *************************************************************************
+    // TEST
+    // *************************************************************************
+
+    @Test
+    @DirtiesContext
+    public void testMarshall() throws Exception {
+        DataModel rec = new DataModel();
+        rec.field1 = "0123456789";
+        mresult.expectedBodiesReceived("9876543210\r\n");
+
+        mtemplate.sendBody(rec);
+        mresult.assertIsSatisfied();
+    }
+
+    @Test
+    @DirtiesContext
+    public void testUnMarshall() throws Exception {
+        utemplate.sendBody("9876543210\r\n");
+
+        uresult.expectedMessageCount(1);
+        uresult.assertIsSatisfied();
+
+        // check the model
+        Exchange  exc  = uresult.getReceivedExchanges().get(0);
+        DataModel data = exc.getIn().getBody(DataModel.class);
+
+        Assert.assertEquals("0123456789", data.field1);
+    }
+
+    // *************************************************************************
+    // ROUTES
+    // *************************************************************************
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        RouteBuilder routeBuilder = new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                BindyDataFormat bindy = new BindyDataFormat();
+                bindy.setClassType(DataModel.class);
+                bindy.setType(BindyType.Fixed);
+
+                from(URI_DIRECT_MARSHALL)
+                    .marshal(bindy)
+                    .to(URI_MOCK_MARSHALL_RESULT);
+                from(URI_DIRECT_UNMARSHALL)
+                    .unmarshal().bindy(BindyType.Fixed, DataModel.class)
+                    .to(URI_MOCK_UNMARSHALL_RESULT);
+            }
+        };
+
+        return routeBuilder;
+    }
+
+    // *************************************************************************
+    // DATA MODEL
+    // *************************************************************************
+
+    @FixedLengthRecord(length = 10, paddingChar = ' ')
+    public static class DataModel {
+        @DataField(pos =  1, length = 10, trim = true)
+        @BindyConverter(CustomConverter.class)
+        public String field1;
+    }
+
+    public static class CustomConverter implements Format<String> {
+        @Override
+        public String format(String object) throws Exception {
+            return (new StringBuilder(object)).reverse().toString();
+        }
+
+        @Override
+        public String parse(String string) throws Exception {
+            return (new StringBuilder(string)).reverse().toString();
+        }
+    }
+}