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/02/07 18:59:43 UTC

svn commit: r1443631 [1/2] - in /camel/trunk/components/camel-bindy/src: main/java/org/apache/camel/dataformat/bindy/ main/java/org/apache/camel/dataformat/bindy/annotation/ main/java/org/apache/camel/dataformat/bindy/fixed/ main/java/org/apache/camel/...

Author: davsclaus
Date: Thu Feb  7 17:59:42 2013
New Revision: 1443631

URL: http://svn.apache.org/r1443631
Log:
CAMEL-6039: fixed length record improvements. Thanks to Rich Newcomb for the patch.

Added:
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/delimited/
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/delimited/BindyFixedLengthDelimitedFieldTest.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/dynamic/
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/dynamic/BindyFixedLengthDynamicFieldTest.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/BindySimpleFixedLengthHeaderFooterTest.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/Order.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderFooter.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderHeader.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/ordinal/
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/ordinal/BindySimpleFixedLengthOrdinalPosTest.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/skipheader/
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/skipheader/BindyFixedLengthHeaderFooterSkipHeaderTest.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/skipheader/Order.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/skipheader/OrderFooter.java   (with props)
    camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/skipheader/OrderHeader.java   (with props)
Modified:
    camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractFactory.java
    camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java
    camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/DataField.java
    camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/FixedLengthRecord.java
    camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/fixed/BindyFixedLengthDataFormat.java
    camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/util/AnnotationModelLoader.java

Modified: camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractFactory.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractFactory.java?rev=1443631&r1=1443630&r2=1443631&view=diff
==============================================================================
--- camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractFactory.java (original)
+++ camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyAbstractFactory.java Thu Feb  7 17:59:42 2013
@@ -19,6 +19,7 @@ package org.apache.camel.dataformat.bind
 import java.lang.reflect.Field;
 import java.text.NumberFormat;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -26,6 +27,7 @@ import java.util.Set;
 
 import org.apache.camel.dataformat.bindy.util.AnnotationModelLoader;
 import org.apache.camel.spi.PackageScanClassResolver;
+import org.apache.camel.spi.PackageScanFilter;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -38,9 +40,10 @@ public abstract class BindyAbstractFacto
     private static final transient Logger LOG = LoggerFactory.getLogger(BindyAbstractFactory.class);
     protected final Map<String, List<Field>> annotatedLinkFields = new LinkedHashMap<String, List<Field>>();
     protected Set<Class<?>> models;
+    protected Set<String> modelClassNames;
     protected String crlf;
-
     private AnnotationModelLoader modelsLoader;
+    
     private String[] packageNames;
     private String locale;
     private Class<?> type;
@@ -57,14 +60,38 @@ public abstract class BindyAbstractFacto
 
         initModel();
     }
-
+    
     public BindyAbstractFactory(PackageScanClassResolver resolver, Class<?> type) throws Exception {
         this.modelsLoader = new AnnotationModelLoader(resolver);
         this.type = type;
+        
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Class name: {}", type.getName());
+        }
+        
+        initModel();
+    }
 
+    public BindyAbstractFactory(PackageScanClassResolver resolver, Class<?> type, PackageScanFilter scanFilter) throws Exception {
+        this.modelsLoader = new AnnotationModelLoader(resolver, scanFilter);
+        this.type = type;
+        
         if (LOG.isDebugEnabled()) {
             LOG.debug("Class name: {}", type.getName());
         }
+        
+        initModel();
+    }
+
+    public BindyAbstractFactory(PackageScanClassResolver resolver, String[] packageNames, PackageScanFilter scanFilter) throws Exception {
+        this.modelsLoader = new AnnotationModelLoader(resolver, scanFilter);
+        this.packageNames = packageNames;
+        
+        if (LOG.isDebugEnabled()) {
+            for (String str : this.packageNames) {
+                LOG.debug("Package name: {}", str);
+            }
+        }
 
         initModel();
     }
@@ -84,9 +111,15 @@ public abstract class BindyAbstractFacto
             // use the package name from the type as it may refer to types in the same package
             String pckName = type.getPackage().getName();
             initModelClasses(pckName);
+
         } else {
             throw new IllegalArgumentException("Either packagenames or type should be configured");
         }
+        
+        modelClassNames = new HashSet<String>();
+        for (Class<?> clazz : models) {
+            modelClassNames.add(clazz.getName());
+        }
     }
 
     /**
@@ -150,6 +183,15 @@ public abstract class BindyAbstractFacto
 
         return mapModel;
     }
+    
+    /**
+     * Indicates whether this factory can support a row comprised of the identified classes
+     * @param classes  the names of the classes in the row
+     * @return true if the model supports the identified classes
+     */
+    public boolean supportsModel(Set<String> classes) {
+        return modelClassNames.containsAll(classes);
+    }
 
     /**
      * Generate a unique key
@@ -217,7 +259,7 @@ public abstract class BindyAbstractFacto
     /**
      * Format the object into a string according to the format rule defined
      */
-    @SuppressWarnings({"unchecked", "rawtypes"})
+    @SuppressWarnings({"unchecked"})
     public String formatString(Format format, Object value) throws Exception {
         String strValue = "";
 

Modified: camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java?rev=1443631&r1=1443630&r2=1443631&view=diff
==============================================================================
--- camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java (original)
+++ camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/BindyFixedLengthFactory.java Thu Feb  7 17:59:42 2013
@@ -28,12 +28,12 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TreeMap;
 
-
 import org.apache.camel.dataformat.bindy.annotation.DataField;
 import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
 import org.apache.camel.dataformat.bindy.annotation.Link;
 import org.apache.camel.dataformat.bindy.format.FormatException;
 import org.apache.camel.spi.PackageScanClassResolver;
+import org.apache.camel.spi.PackageScanFilter;
 import org.apache.camel.util.ObjectHelper;
 
 import org.slf4j.Logger;
@@ -53,13 +53,17 @@ public class BindyFixedLengthFactory ext
 
     private Map<Integer, DataField> dataFields = new LinkedHashMap<Integer, DataField>();
     private Map<Integer, Field> annotatedFields = new LinkedHashMap<Integer, Field>();
-
+   
     private int numberOptionalFields;
     private int numberMandatoryFields;
     private int totalFields;
 
     private boolean hasHeader;
+    private boolean skipHeader;
+    private boolean isHeader;
     private boolean hasFooter;
+    private boolean skipFooter;
+    private boolean isFooter;
     private char paddingChar;
     private int recordLength;
 
@@ -69,14 +73,24 @@ public class BindyFixedLengthFactory ext
         // initialize specific parameters of the fixed length model
         initFixedLengthModel();
     }
+    
+    public BindyFixedLengthFactory(PackageScanClassResolver resolver, PackageScanFilter scanFilter, String... packageNames) throws Exception {
+        super(resolver, packageNames, scanFilter);
+        initFixedLengthModel();
+    }
 
     public BindyFixedLengthFactory(PackageScanClassResolver resolver, Class<?> type) throws Exception {
         super(resolver, type);
-
+        
         // initialize specific parameters of the fixed length model
         initFixedLengthModel();
     }
 
+    public BindyFixedLengthFactory(PackageScanClassResolver resolver, PackageScanFilter scanFilter, Class<?> type) throws Exception  {
+        super(resolver, type, scanFilter);
+        initFixedLengthModel();
+    }
+
     /**
      * method uses to initialize the model representing the classes who will
      * bind the data. This process will scan for classes according to the
@@ -105,6 +119,7 @@ public class BindyFixedLengthFactory ext
             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});
                     }
@@ -159,8 +174,9 @@ public class BindyFixedLengthFactory ext
         int counterMandatoryFields = 0;
         DataField dataField;
         String token;
-        int offset;
+        int offset = 1;
         int length;
+        String delimiter;
         Field field;
 
         // Iterate through the list of positions
@@ -169,20 +185,41 @@ public class BindyFixedLengthFactory ext
         Collection<DataField> c = dataFields.values();
         Iterator<DataField> itr = c.iterator();
 
+        // this iterator is for a link list that was built using items in order
         while (itr.hasNext()) {
             dataField = itr.next();
-            offset = dataField.pos();
             length = dataField.length();
+            delimiter = dataField.delimiter();
 
             ObjectHelper.notNull(offset, "Position/offset is not defined for the field: " + dataField.toString());
-            ObjectHelper.notNull(offset, "Length is not defined for the field: " + dataField.toString());
-
+            
+            if (length == 0 && dataField.lengthPos() != 0) {
+                Field lengthField = annotatedFields.get(dataField.lengthPos());
+                lengthField.setAccessible(true);
+                Object modelObj = model.get(lengthField.getDeclaringClass().getName());
+                Object lengthObj =  (Integer) lengthField.get(modelObj);
+                length = ((Integer)lengthObj).intValue();
+            }
+            if (length < 1 && delimiter == null && dataField.lengthPos() == 0) {
+                throw new IllegalArgumentException("Either length or delimiter must be specified for the field : " + dataField.toString());
+            }
             if (offset - 1 <= -1) {
                 throw new IllegalArgumentException("Offset/Position of the field " + dataField.toString()
                                                    + " cannot be negative");
             }
-
-            token = record.substring(offset - 1, offset + length - 1);
+            
+            if (length > 0) {
+                token = record.substring(offset - 1, offset + length - 1);
+                offset += length;
+            } else if (!delimiter.equals("")) {
+                String tempToken = record.substring(offset - 1, record.length());
+                token = tempToken.substring(0, tempToken.indexOf(delimiter));
+                // include the delimiter in the offset calculation
+                offset += token.length() + 1;
+            } else {
+                // defined as a zero-length field
+                token = "";
+            }
 
             if (dataField.trim()) {
                 token = token.trim();
@@ -202,8 +239,8 @@ public class BindyFixedLengthFactory ext
                 }
             }
             
-            // Get Field to be setted
-            field = annotatedFields.get(offset);
+            // Get Field to be set
+            field = annotatedFields.get(dataField.pos());
             field.setAccessible(true);
 
             if (LOG.isDebugEnabled()) {
@@ -232,7 +269,7 @@ public class BindyFixedLengthFactory ext
             }
 
             field.set(modelField, value);
-
+            
             ++pos;
         
         }
@@ -322,20 +359,32 @@ public class BindyFixedLengthFactory ext
                     if (datafield.trim()) {
                         result = result.trim();
                     }
-
-                    // Get length of the field, alignment (LEFT or RIGHT), pad
+                    
                     int fieldLength = datafield.length();
-                    String align = datafield.align();
-                    char padCharField = datafield.paddingChar();
-                    char padChar;
                     
-                    if (fieldLength > 0) {
-                       
-                        StringBuilder temp = new StringBuilder();
+                    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: " 
+                                + field.getName() + " is mandatory.");
+                    }
+                    
+                    if (!datafield.delimiter().equals("")) {
+                        result = result + datafield.delimiter();
+                    } else {
+                        // Get length of the field, alignment (LEFT or RIGHT), pad
+                        String align = datafield.align();
+                        char padCharField = datafield.paddingChar();
+                        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
@@ -343,7 +392,7 @@ public class BindyFixedLengthFactory ext
                             } else {
                                 padChar = padCharField;
                             }
-
+    
                             if (align.contains("R")) {
                                 temp.append(generatePaddingChars(padChar, fieldLength, result.length()));
                                 temp.append(result);
@@ -354,11 +403,11 @@ public class BindyFixedLengthFactory ext
                                 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);
@@ -367,10 +416,6 @@ public class BindyFixedLengthFactory ext
                                         + " must not be larger than allowed, was: " + result.length() + ", allowed: " + fieldLength);
                             }
                         }
-
-                    } else {
-                        throw new IllegalArgumentException("Length of the field: " + field.getName()
-                                + " is a mandatory field and cannot be equal to zero or to be negative, was: " + fieldLength);
                     }
 
                     if (LOG.isDebugEnabled()) {
@@ -429,10 +474,22 @@ public class BindyFixedLengthFactory ext
                 // Get hasHeader parameter
                 hasHeader = record.hasHeader();
                 LOG.debug("Has Header: {}", hasHeader);
+                
+                // Get skipHeader parameter
+                skipHeader = record.skipHeader();
 
                 // Get hasFooter parameter
                 hasFooter = record.hasFooter();
                 LOG.debug("Has Footer: {}", hasFooter);
+                
+                // Get skipFooter parameter
+                skipFooter = record.skipFooter();
+                
+                // Get isHeader parameter
+                isHeader = record.isHeader();
+                
+                // Get isFooter parameter
+                isFooter = record.isFooter();
 
                 // Get padding character
                 paddingChar = record.paddingChar();
@@ -447,8 +504,22 @@ public class BindyFixedLengthFactory ext
                 LOG.debug("Length of the record: {}", recordLength);
             }
         }
+        
+        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'");
+        }
+        
     }
-
+        
     /**
      * Flag indicating if we have a header
      */
@@ -464,6 +535,34 @@ public class BindyFixedLengthFactory ext
     }
     
     /**
+     * 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
      */
     public char paddingchar() {

Modified: camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/DataField.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/DataField.java?rev=1443631&r1=1443630&r2=1443631&view=diff
==============================================================================
--- camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/DataField.java (original)
+++ camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/DataField.java Thu Feb  7 17:59:42 2013
@@ -31,7 +31,9 @@ import java.lang.annotation.RetentionPol
  * precision(optional) reflects the precision to be used with BigDecimal number
  * The position (optional) identify the position of the field in the CSV
  * generated The required (optional) property identifies a field which is
- * mandatory.
+ * mandatory. The lengthPos (optional) identifies a field in this record that 
+ * defines the fixed length for this field.  The delimiter (optional) defines a
+ * character that is used to demarcate the field, if it has a variable length.
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
@@ -63,6 +65,11 @@ public @interface DataField {
     int length() default 0;
     
     /**
+     * Identifies a data field in the record that defines the expected fixed length for this field
+     */
+    int lengthPos() default 0;
+    
+    /**
      * Align the text to the right or left. Use values <tt>R</tt> or <tt>L</tt>.
      */
     String align() default "R";
@@ -98,6 +105,11 @@ public @interface DataField {
     boolean clip() default false;
     
     /**
+     * Optional delimiter to be used if the field has a variable length
+     */
+    String delimiter() default "";
+    
+    /**
      * Field's default value in case no value is set 
      */
     String defaultValue() default "";

Modified: camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/FixedLengthRecord.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/FixedLengthRecord.java?rev=1443631&r1=1443630&r2=1443631&view=diff
==============================================================================
--- camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/FixedLengthRecord.java (original)
+++ camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/annotation/FixedLengthRecord.java Thu Feb  7 17:59:42 2013
@@ -56,8 +56,34 @@ public @interface FixedLengthRecord {
      */
     int length() default 0;
 
+    /**
+     * Indicates that the record(s) of this type may be preceded by a single header record at the beginning of in the file
+     */
     boolean hasHeader() default false;
     
+    /**
+     * Indicates that the record(s) of this type may be followed by a single footer record at the end of the file
+     */
     boolean hasFooter() default false;
+    
+    /**
+     * Configures the data format to skip marshalling / unmarshalling of the header record
+     */
+    boolean skipHeader() default false;
+    
+    /**
+     * Configures the data format to skip marshalling / unmarshalling of the footer record
+     */
+    boolean skipFooter() default false;
+    
+    /**
+     * Identifies this FixedLengthRecord as a header record, which may precede all other records in the file
+     */
+    boolean isHeader() default false;
+    
+    /**
+     * Identifies this FixedLengthRecord as a footer record, which may be used as the last record in the file
+     */
+    boolean isFooter() default false;
 
 }

Modified: camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/fixed/BindyFixedLengthDataFormat.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/fixed/BindyFixedLengthDataFormat.java?rev=1443631&r1=1443630&r2=1443631&view=diff
==============================================================================
--- camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/fixed/BindyFixedLengthDataFormat.java (original)
+++ camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/fixed/BindyFixedLengthDataFormat.java Thu Feb  7 17:59:42 2013
@@ -25,16 +25,21 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Scanner;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.dataformat.bindy.BindyAbstractDataFormat;
 import org.apache.camel.dataformat.bindy.BindyAbstractFactory;
 import org.apache.camel.dataformat.bindy.BindyFixedLengthFactory;
+import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
 import org.apache.camel.dataformat.bindy.util.ConverterUtils;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.spi.PackageScanClassResolver;
+import org.apache.camel.spi.PackageScanFilter;
 import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.ObjectHelper;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -43,8 +48,15 @@ import org.slf4j.LoggerFactory;
  * {@link DataFormat}) using Bindy to marshal to and from Fixed Length
  */
 public class BindyFixedLengthDataFormat extends BindyAbstractDataFormat {
-    private static final transient Logger LOG = LoggerFactory.getLogger(BindyFixedLengthDataFormat.class);
+    
+    public static final String CAMEL_BINDY_FIXED_LENGTH_HEADER = "CamelBindyFixedLengthHeader";
+    public static final String CAMEL_BINDY_FIXED_LENGTH_FOOTER = "CamelBindyFixedLengthFooter";
 
+    private static final transient Logger LOG = LoggerFactory.getLogger(BindyFixedLengthDataFormat.class);
+    
+    private BindyFixedLengthFactory headerFactory;
+    private BindyFixedLengthFactory footerFactory;
+    
     public BindyFixedLengthDataFormat() {
     }
 
@@ -58,8 +70,8 @@ public class BindyFixedLengthDataFormat 
 
     @SuppressWarnings("unchecked")
     public void marshal(Exchange exchange, Object body, OutputStream outputStream) throws Exception {
-
-        BindyFixedLengthFactory factory = (BindyFixedLengthFactory) getFactory(exchange.getContext().getPackageScanClassResolver());
+        PackageScanClassResolver resolver = exchange.getContext().getPackageScanClassResolver();
+        BindyFixedLengthFactory factory = (BindyFixedLengthFactory) getFactory(resolver);
         ObjectHelper.notNull(factory, "not instantiated");
 
         // Get CRLF
@@ -82,11 +94,55 @@ public class BindyFixedLengthDataFormat 
             // cast to the expected type
             models = (List<Map<String, Object>>) body;
         }
+        
+        // add the header if it is in the exchange header
+        Map<String, Object> headerRow = (Map<String, Object>) exchange.getIn().getHeader(CAMEL_BINDY_FIXED_LENGTH_HEADER);
+        if (headerRow != null) {
+            models.add(0, headerRow);
+        }
+        
+        // add the footer if it is in the exchange header
+        Map<String, Object> footerRow = (Map<String, Object>) exchange.getIn().getHeader(CAMEL_BINDY_FIXED_LENGTH_FOOTER);
+        if (headerRow != null) {
+            models.add(models.size(), footerRow);
+        }
 
+        int row = 0;
         for (Map<String, Object> model : models) {
-
-            String result = factory.unbind(model);
-
+            row++;
+            String result = null;
+            
+            if (row == 1 && headerFactory != null) {
+                // marshal the first row as a header if the models match
+                Set<String> modelClassNames = model.keySet();
+                // only use the header factory if the row is the header
+                if (headerFactory.supportsModel(modelClassNames)) {
+                    if (factory.skipHeader())  {
+                        LOG.warn("Skipping marshal of header row; 'skipHeader=true'");
+                        continue;
+                    } else {
+                        result = headerFactory.unbind(model);
+                    }    
+                }
+            } else if (row == models.size() && footerFactory != null) {
+                // marshal the last row as a footer if the models match
+                Set<String> modelClassNames = model.keySet();
+                // only use the header factory if the row is the header
+                if (footerFactory.supportsModel(modelClassNames)) {
+                    if (factory.skipFooter()) {
+                        LOG.warn("Skipping marshal of footer row; 'skipFooter=true'");
+                        continue;
+                    } else {
+                        result = footerFactory.unbind(model);
+                    }
+                }
+            }
+            
+            if (result == null) {
+                // marshal as a normal / default row
+                result = factory.unbind(model);
+            }
+            
             byte[] bytes = exchange.getContext().getTypeConverter().convertTo(byte[].class, exchange, result);
             outputStream.write(bytes);
 
@@ -96,9 +152,10 @@ public class BindyFixedLengthDataFormat 
     }
 
     public Object unmarshal(Exchange exchange, InputStream inputStream) throws Exception {
-        BindyFixedLengthFactory factory = (BindyFixedLengthFactory) getFactory(exchange.getContext().getPackageScanClassResolver());
+        PackageScanClassResolver resolver = exchange.getContext().getPackageScanClassResolver();
+        BindyFixedLengthFactory factory = (BindyFixedLengthFactory) getFactory(resolver);
         ObjectHelper.notNull(factory, "not instantiated");
-
+        
         // List of Pojos
         List<Map<String, Object>> models = new ArrayList<Map<String, Object>>();
 
@@ -110,52 +167,59 @@ public class BindyFixedLengthDataFormat 
         // Scanner is used to read big file
         Scanner scanner = new Scanner(in);
 
-        int count = 0;
+        AtomicInteger count = new AtomicInteger(0);
 
         try {
 
-            // TODO Test if we have a Header
-            // TODO Test if we have a Footer (containing by example checksum)
-
-            while (scanner.hasNextLine()) {
-                String line;
+            // Parse the header if it exists
+            if (scanner.hasNextLine() && factory.hasHeader()) {
                 
                 // Read the line (should not trim as its fixed length)
-                line = scanner.nextLine();
-
-                if (ObjectHelper.isEmpty(line)) {
-                    // skip if line is empty
-                    continue;
-                }
-
-                // Increment counter
-                count++;
+                String line = getNextNonEmptyLine(scanner, count);
                 
-                // Check if the record length corresponds to the parameter
-                // provided in the @FixedLengthRecord
-                if ((line.length() < factory.recordLength()) || (line.length() > factory.recordLength())) {
-                    throw new java.lang.IllegalArgumentException("Size of the record: " + line.length() + " is not equal to the value provided in the model: " + factory.recordLength());
+                if (!factory.skipHeader()) {
+                    Map<String, Object> headerObjMap = createModel(headerFactory, line, count.intValue());
+                    exchange.getOut().setHeader(CAMEL_BINDY_FIXED_LENGTH_HEADER, headerObjMap);
                 }
+            }
 
-                // Create POJO where Fixed data will be stored
-                model = factory.factory();
-                
-                // Bind data from Fixed record with model classes
-                factory.bind(line, model, count);
+            String thisLine = getNextNonEmptyLine(scanner, count);
 
-                // Link objects together
-                factory.link(model);
+            String nextLine = null;
+            if (thisLine != null) {
+                nextLine = getNextNonEmptyLine(scanner, count);
+            }
+
+            // Parse the main file content
+            while (thisLine != null && nextLine != null) {
+                
+                model = createModel(factory, thisLine, count.intValue());
 
                 // Add objects graph to the list
                 models.add(model);
 
-                LOG.debug("Graph of objects created: {}", model);
+                thisLine = nextLine;
+                nextLine = getNextNonEmptyLine(scanner, count);
+            }
+            
+            // this line should be the last non-empty line from the file
+            // optionally parse the line as a footer
+            if (thisLine != null) {
+                if (factory.hasFooter()) {
+                    if (!factory.skipFooter()) {
+                        Map<String, Object> footerObjMap = createModel(footerFactory, thisLine, count.intValue());
+                        exchange.getOut().setHeader(CAMEL_BINDY_FIXED_LENGTH_FOOTER, footerObjMap);
+                    }
+                } else {
+                    model = createModel(factory, thisLine, count.intValue());
+                    models.add(model);
+                }
             }
 
             // Test if models list is empty or not
             // If this is the case (correspond to an empty stream, ...)
             if (models.size() == 0) {
-                throw new java.lang.IllegalArgumentException("No records have been defined in the CSV");
+                throw new java.lang.IllegalArgumentException("No records have been defined in the the file");
             } else {
                 return extractUnmarshalResult(models);
             }
@@ -167,13 +231,98 @@ public class BindyFixedLengthDataFormat 
 
     }
 
+    private String getNextNonEmptyLine(Scanner scanner, AtomicInteger count) {
+        String line = "";
+        while (ObjectHelper.isEmpty(line) && scanner.hasNextLine()) {
+            count.incrementAndGet();
+            line = scanner.nextLine();
+        }
+        
+        if (ObjectHelper.isEmpty(line)) {
+            return null;
+        } else {
+            return line;
+        }
+    }
+
+    protected Map<String, Object> createModel(BindyFixedLengthFactory factory, String line, int count) throws Exception {
+        // Check if the record length corresponds to the parameter
+        // provided in the @FixedLengthRecord
+        if (factory.recordLength() > 0) {
+            if ((line.length() < factory.recordLength()) || (line.length() > factory.recordLength())) {
+                throw new java.lang.IllegalArgumentException("Size of the record: " + line.length() 
+                        + " is not equal to the value provided in the model: " + factory.recordLength());
+            }
+        }
+
+        // Create POJO where Fixed data will be stored
+        Map<String, Object> model = factory.factory();
+        
+        // Bind data from Fixed record with model classes
+        factory.bind(line, model, count);
+
+        // Link objects together
+        factory.link(model);
+        
+        LOG.debug("Graph of objects created: {}", model);
+        return model;
+    }
+
     @Override
     protected BindyAbstractFactory createModelFactory(PackageScanClassResolver resolver) throws Exception {
+        
+        // Initialize the primary (body) model factory ignoring header and footer model classes
+        PackageScanFilter defaultRecordScanFilter = new PackageScanFilter() {
+            @Override
+            public boolean matches(Class<?> type) {
+                FixedLengthRecord record = type.getAnnotation(FixedLengthRecord.class);
+                return record != null && !record.isFooter() && !record.isHeader();
+            }
+        };
+
+        BindyFixedLengthFactory factory;
         if (getClassType() != null) {
-            return new BindyFixedLengthFactory(resolver, getClassType());
+            factory = new BindyFixedLengthFactory(resolver, defaultRecordScanFilter, getClassType());
         } else {
-            return new BindyFixedLengthFactory(resolver, getPackages());
+            factory = new BindyFixedLengthFactory(resolver, defaultRecordScanFilter, getPackages());
+        }
+        
+        // Optionally initialize the header factory... using header model classes
+        if (factory.hasHeader()) {
+            PackageScanFilter headerScanFilter = new PackageScanFilter() {
+                @Override
+                public boolean matches(Class<?> type) {
+                    FixedLengthRecord record = type.getAnnotation(FixedLengthRecord.class);
+                    return record != null && record.isHeader();
+                }
+            };
+            
+            if (getClassType() != null) {
+                this.headerFactory = new BindyFixedLengthFactory(resolver, headerScanFilter, getClassType());
+            } else {
+                this.headerFactory = new BindyFixedLengthFactory(resolver, headerScanFilter, getPackages());
+            }
         }
+        
+        // Optionally initialize the footer factory... using footer model classes
+        if (factory.hasFooter()) {
+            
+            PackageScanFilter footerScanFilter = new PackageScanFilter() {
+                @Override
+                public boolean matches(Class<?> type) {
+                    FixedLengthRecord record = type.getAnnotation(FixedLengthRecord.class);
+                    return record != null && record.isFooter();
+                }
+            };
+            
+            if (getClassType() != null) {
+                this.footerFactory = new BindyFixedLengthFactory(resolver, footerScanFilter, getClassType());
+            } else {
+                this.footerFactory = new BindyFixedLengthFactory(resolver, footerScanFilter, getPackages());
+            }
+        }
+        
+        return factory;
     }
-
+    
 }

Modified: camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/util/AnnotationModelLoader.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/util/AnnotationModelLoader.java?rev=1443631&r1=1443630&r2=1443631&view=diff
==============================================================================
--- camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/util/AnnotationModelLoader.java (original)
+++ camel/trunk/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/util/AnnotationModelLoader.java Thu Feb  7 17:59:42 2013
@@ -17,6 +17,7 @@
 package org.apache.camel.dataformat.bindy.util;
 
 import java.lang.annotation.Annotation;
+import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
@@ -26,6 +27,7 @@ import org.apache.camel.dataformat.bindy
 import org.apache.camel.dataformat.bindy.annotation.Message;
 import org.apache.camel.dataformat.bindy.annotation.Section;
 import org.apache.camel.spi.PackageScanClassResolver;
+import org.apache.camel.spi.PackageScanFilter;
 
 /**
  * Annotation based loader for model classes with Bindy annotations.
@@ -33,6 +35,7 @@ import org.apache.camel.spi.PackageScanC
 public class AnnotationModelLoader {
 
     private PackageScanClassResolver resolver;
+    private PackageScanFilter filter;
     private Set<Class<? extends Annotation>> annotations;
 
     public AnnotationModelLoader(PackageScanClassResolver resolver) {
@@ -45,8 +48,27 @@ public class AnnotationModelLoader {
         annotations.add(Section.class);
         annotations.add(FixedLengthRecord.class);
     }
+    
+    public AnnotationModelLoader(PackageScanClassResolver resolver, PackageScanFilter filter) {
+        this(resolver);
+        this.filter = filter;
+    }
 
     public Set<Class<?>> loadModels(String... packageNames) throws Exception {
-        return resolver.findAnnotated(annotations, packageNames);
+        Set<Class<?>> results = resolver.findAnnotated(annotations, packageNames);
+        
+        //TODO;  this logic could be moved into the PackageScanClassResolver by creating:
+        //          findAnnotated(annotations, packageNames, filter) 
+        Set<Class<?>> resultsToRemove = new HashSet<Class<?>>();
+        if (filter != null) {
+            for (Class<?> clazz : results) {
+                if (!filter.matches(clazz)) {
+                    resultsToRemove.add(clazz);
+                }
+            }
+        }
+        results.removeAll(resultsToRemove);
+        return results;
     }
+    
 }

Added: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/delimited/BindyFixedLengthDelimitedFieldTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/delimited/BindyFixedLengthDelimitedFieldTest.java?rev=1443631&view=auto
==============================================================================
--- camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/delimited/BindyFixedLengthDelimitedFieldTest.java (added)
+++ camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/delimited/BindyFixedLengthDelimitedFieldTest.java Thu Feb  7 17:59:42 2013
@@ -0,0 +1,254 @@
+/**
+ * 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.delimited;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import org.apache.camel.EndpointInject;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.dataformat.bindy.annotation.DataField;
+import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
+
+import org.apache.camel.model.dataformat.BindyType;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * This test validates the marshalling / unmarshalling of delimited, variable-length fields within a 'fixed-length' record. 
+ */
+public class BindyFixedLengthDelimitedFieldTest 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";
+    
+    private static final String TEST_RECORD = "10A9Pauline^M^ISINXD12345678BUYShare000002500.45USD01-08-2009\r\n";
+
+    @EndpointInject(uri = URI_MOCK_MARSHALL_RESULT)
+    private MockEndpoint marshallResult;
+
+    @EndpointInject(uri = URI_MOCK_UNMARSHALL_RESULT)
+    private MockEndpoint unmarshallResult;
+
+    // *************************************************************************
+    // TESTS
+    // *************************************************************************
+    @Test
+    public void testUnmarshallMessage() throws Exception {
+
+        unmarshallResult.expectedMessageCount(1);
+        template.sendBody(URI_DIRECT_UNMARSHALL, TEST_RECORD);
+        
+        unmarshallResult.assertIsSatisfied();
+
+        // check the model
+        BindyFixedLengthDelimitedFieldTest.Order order = 
+            (BindyFixedLengthDelimitedFieldTest.Order) unmarshallResult.getReceivedExchanges().get(0).getIn().getBody();
+        Assert.assertEquals(10, order.getOrderNr());
+        Assert.assertEquals("Pauline", order.getFirstName());
+        Assert.assertEquals("M", order.getLastName());
+    }
+    
+    @Test
+    public void testMarshallMessage() throws Exception {
+        BindyFixedLengthDelimitedFieldTest.Order order = new Order();
+        order.setOrderNr(10);
+        order.setOrderType("BUY");
+        order.setClientNr("A9");
+        order.setFirstName("Pauline");
+        order.setLastName("M");
+        order.setAmount(new BigDecimal("2500.45"));
+        order.setInstrumentCode("ISIN");
+        order.setInstrumentNumber("XD12345678");
+        order.setInstrumentType("Share");
+        order.setCurrency("USD");
+        Calendar calendar = new GregorianCalendar();
+        calendar.set(2009, 7, 1);
+        order.setOrderDate(calendar.getTime());
+        
+        marshallResult.expectedMessageCount(1);
+        marshallResult.expectedBodiesReceived(Arrays.asList(new String[] {TEST_RECORD}));
+        template.sendBody(URI_DIRECT_MARSHALL, order);
+        marshallResult.assertIsSatisfied();
+    }
+    
+    // *************************************************************************
+    // ROUTES
+    // *************************************************************************
+    
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        RouteBuilder routeBuilder = new RouteBuilder() {
+
+            @Override
+            public void configure() throws Exception {      
+                from(URI_DIRECT_MARSHALL)
+                    .marshal().bindy(BindyType.Fixed, BindyFixedLengthDelimitedFieldTest.Order.class)
+                    .to(URI_MOCK_MARSHALL_RESULT);
+            
+                from(URI_DIRECT_UNMARSHALL)
+                    .unmarshal().bindy(BindyType.Fixed, BindyFixedLengthDelimitedFieldTest.Order.class)
+                    .to(URI_MOCK_UNMARSHALL_RESULT);
+            }
+        };
+        
+        return routeBuilder;
+    }
+
+    // *************************************************************************
+    // DATA MODEL
+    // *************************************************************************
+    @FixedLengthRecord()
+    public static class Order {
+
+        @DataField(pos = 1, length = 2)
+        private int orderNr;
+
+        @DataField(pos = 2, length = 2)
+        private String clientNr;
+
+        @DataField(pos = 3, delimiter = "^")
+        private String firstName;
+
+        @DataField(pos = 4, delimiter = "^")
+        private String lastName;
+
+        @DataField(pos = 5, length = 4)
+        private String instrumentCode;
+
+        @DataField(pos = 6, length = 10)
+        private String instrumentNumber;
+
+        @DataField(pos = 7, length = 3)
+        private String orderType;
+
+        @DataField(pos = 8, length = 5)
+        private String instrumentType;
+
+        @DataField(pos = 9, precision = 2, length = 12, paddingChar = '0')
+        private BigDecimal amount;
+
+        @DataField(pos = 10, length = 3)
+        private String currency;
+
+        @DataField(pos = 11, length = 10, pattern = "dd-MM-yyyy")
+        private Date orderDate;
+
+        public int getOrderNr() {
+            return orderNr;
+        }
+
+        public void setOrderNr(int orderNr) {
+            this.orderNr = orderNr;
+        }
+
+        public String getClientNr() {
+            return clientNr;
+        }
+
+        public void setClientNr(String clientNr) {
+            this.clientNr = clientNr;
+        }
+
+        public String getFirstName() {
+            return firstName;
+        }
+
+        public void setFirstName(String firstName) {
+            this.firstName = firstName;
+        }
+
+        public String getLastName() {
+            return lastName;
+        }
+
+        public void setLastName(String lastName) {
+            this.lastName = lastName;
+        }
+
+        public String getInstrumentCode() {
+            return instrumentCode;
+        }
+
+        public void setInstrumentCode(String instrumentCode) {
+            this.instrumentCode = instrumentCode;
+        }
+
+        public String getInstrumentNumber() {
+            return instrumentNumber;
+        }
+
+        public void setInstrumentNumber(String instrumentNumber) {
+            this.instrumentNumber = instrumentNumber;
+        }
+
+        public String getOrderType() {
+            return orderType;
+        }
+
+        public void setOrderType(String orderType) {
+            this.orderType = orderType;
+        }
+
+        public String getInstrumentType() {
+            return instrumentType;
+        }
+
+        public void setInstrumentType(String instrumentType) {
+            this.instrumentType = instrumentType;
+        }
+
+        public BigDecimal getAmount() {
+            return amount;
+        }
+
+        public void setAmount(BigDecimal amount) {
+            this.amount = amount;
+        }
+
+        public String getCurrency() {
+            return currency;
+        }
+
+        public void setCurrency(String currency) {
+            this.currency = currency;
+        }
+
+        public Date getOrderDate() {
+            return orderDate;
+        }
+
+        public void setOrderDate(Date orderDate) {
+            this.orderDate = orderDate;
+        }
+
+        @Override
+        public String toString() {
+            return "Model : " + Order.class.getName() + " : " + this.orderNr + ", " + this.orderType + ", " + String.valueOf(this.amount) + ", " + this.instrumentCode + ", "
+                   + this.instrumentNumber + ", " + this.instrumentType + ", " + this.currency + ", " + this.clientNr + ", " + this.firstName + ", " + this.lastName + ", "
+                   + String.valueOf(this.orderDate);
+        }
+    }
+
+}

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/delimited/BindyFixedLengthDelimitedFieldTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/delimited/BindyFixedLengthDelimitedFieldTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/dynamic/BindyFixedLengthDynamicFieldTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/dynamic/BindyFixedLengthDynamicFieldTest.java?rev=1443631&view=auto
==============================================================================
--- camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/dynamic/BindyFixedLengthDynamicFieldTest.java (added)
+++ camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/dynamic/BindyFixedLengthDynamicFieldTest.java Thu Feb  7 17:59:42 2013
@@ -0,0 +1,271 @@
+/**
+ * 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.dynamic;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import org.apache.camel.EndpointInject;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.dataformat.bindy.annotation.DataField;
+import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
+
+import org.apache.camel.model.dataformat.BindyType;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Assert;
+import org.junit.Test;
+
+
+/**
+ * This test validates the marshalling / unmarshalling of a fixed-length data field for which the length of the
+ * field is defined by the value of another field in the record.
+ */
+public class BindyFixedLengthDynamicFieldTest 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";
+    
+    private static final String TEST_RECORD = "10A9Pauline^M^ISIN10XD12345678BUYShare000002500.45USD01-08-2009\r\n";
+
+    @EndpointInject(uri = URI_MOCK_MARSHALL_RESULT)
+    private MockEndpoint marshallResult;
+
+    @EndpointInject(uri = URI_MOCK_UNMARSHALL_RESULT)
+    private MockEndpoint unmarshallResult;
+
+    // *************************************************************************
+    // TESTS
+    // *************************************************************************
+    
+    @Test
+    public void testUnmarshallMessage() throws Exception {
+
+        unmarshallResult.expectedMessageCount(1);
+        template.sendBody(URI_DIRECT_UNMARSHALL, TEST_RECORD);
+        
+        unmarshallResult.assertIsSatisfied();
+
+        // check the model
+        BindyFixedLengthDynamicFieldTest.Order order = 
+            (BindyFixedLengthDynamicFieldTest.Order) unmarshallResult.getReceivedExchanges().get(0).getIn().getBody();
+        Assert.assertEquals(10, order.getOrderNr());
+        // the field is not trimmed
+        Assert.assertEquals("Pauline", order.getFirstName());
+        Assert.assertEquals("M", order.getLastName());
+        Assert.assertEquals("XD12345678", order.getInstrumentNumber());
+    }
+    
+    @Test
+    public void testMarshallMessage() throws Exception {
+        BindyFixedLengthDynamicFieldTest.Order order = new Order();
+        order.setOrderNr(10);
+        order.setOrderType("BUY");
+        order.setClientNr("A9");
+        order.setFirstName("Pauline");
+        order.setLastName("M");
+        order.setAmount(new BigDecimal("2500.45"));
+        order.setInstrumentCode("ISIN");
+        order.setInstrumentNumberLen(10);
+        order.setInstrumentNumber("XD12345678");
+        order.setInstrumentType("Share");
+        order.setCurrency("USD");
+        Calendar calendar = new GregorianCalendar();
+        calendar.set(2009, 7, 1);
+        order.setOrderDate(calendar.getTime());
+        
+        marshallResult.expectedMessageCount(1);
+        marshallResult.expectedBodiesReceived(Arrays.asList(new String[] {TEST_RECORD}));
+        template.sendBody(URI_DIRECT_MARSHALL, order);
+        marshallResult.assertIsSatisfied();
+    }
+    
+    // *************************************************************************
+    // ROUTES
+    // *************************************************************************
+    
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        RouteBuilder routeBuilder = new RouteBuilder() {
+
+            @Override
+            public void configure() throws Exception {      
+                from(URI_DIRECT_MARSHALL)
+                    .marshal().bindy(BindyType.Fixed, BindyFixedLengthDynamicFieldTest.Order.class)
+                    .to(URI_MOCK_MARSHALL_RESULT);
+            
+                from(URI_DIRECT_UNMARSHALL)
+                    .unmarshal().bindy(BindyType.Fixed, BindyFixedLengthDynamicFieldTest.Order.class)
+                    .to(URI_MOCK_UNMARSHALL_RESULT);
+            }
+        };
+        
+        return routeBuilder;
+    }
+
+    // *************************************************************************
+    // DATA MODEL
+    // *************************************************************************
+    @FixedLengthRecord()
+    public static class Order {
+
+        @DataField(pos = 1, length = 2)
+        private int orderNr;
+
+        @DataField(pos = 2, length = 2)
+        private String clientNr;
+
+        @DataField(pos = 3, delimiter = "^")
+        private String firstName;
+
+        @DataField(pos = 4, delimiter = "^")
+        private String lastName;
+
+        @DataField(pos = 5, length = 4)
+        private String instrumentCode;
+
+        @DataField(pos = 6, length = 2, align = "R", paddingChar = '0')
+        private int instrumentNumberLen;
+        
+        @DataField(pos = 7, length = 10)
+        private String instrumentNumber;
+
+        @DataField(pos = 8, length = 3)
+        private String orderType;
+
+        @DataField(pos = 9, length = 5)
+        private String instrumentType;
+
+        @DataField(pos = 10, precision = 2, length = 12, paddingChar = '0')
+        private BigDecimal amount;
+
+        @DataField(pos = 11, length = 3)
+        private String currency;
+
+        @DataField(pos = 12, length = 10, pattern = "dd-MM-yyyy")
+        private Date orderDate;
+
+        public int getOrderNr() {
+            return orderNr;
+        }
+
+        public void setOrderNr(int orderNr) {
+            this.orderNr = orderNr;
+        }
+
+        public String getClientNr() {
+            return clientNr;
+        }
+
+        public void setClientNr(String clientNr) {
+            this.clientNr = clientNr;
+        }
+
+        public String getFirstName() {
+            return firstName;
+        }
+
+        public void setFirstName(String firstName) {
+            this.firstName = firstName;
+        }
+
+        public String getLastName() {
+            return lastName;
+        }
+
+        public void setLastName(String lastName) {
+            this.lastName = lastName;
+        }
+
+        public String getInstrumentCode() {
+            return instrumentCode;
+        }
+
+        public void setInstrumentCode(String instrumentCode) {
+            this.instrumentCode = instrumentCode;
+        }
+        
+        public void setInstrumentNumberLen(int instrumentNumberLen) {
+            this.instrumentNumberLen = instrumentNumberLen;
+        }
+
+        public int getInstrumentNumberLen() {
+            return instrumentNumberLen;
+        }
+
+        public String getInstrumentNumber() {
+            return instrumentNumber;
+        }
+
+        public void setInstrumentNumber(String instrumentNumber) {
+            this.instrumentNumber = instrumentNumber;
+        }
+
+        public String getOrderType() {
+            return orderType;
+        }
+
+        public void setOrderType(String orderType) {
+            this.orderType = orderType;
+        }
+
+        public String getInstrumentType() {
+            return instrumentType;
+        }
+
+        public void setInstrumentType(String instrumentType) {
+            this.instrumentType = instrumentType;
+        }
+
+        public BigDecimal getAmount() {
+            return amount;
+        }
+
+        public void setAmount(BigDecimal amount) {
+            this.amount = amount;
+        }
+
+        public String getCurrency() {
+            return currency;
+        }
+
+        public void setCurrency(String currency) {
+            this.currency = currency;
+        }
+
+        public Date getOrderDate() {
+            return orderDate;
+        }
+
+        public void setOrderDate(Date orderDate) {
+            this.orderDate = orderDate;
+        }
+
+        @Override
+        public String toString() {
+            return "Model : " + Order.class.getName() + " : " + this.orderNr + ", " + this.orderType + ", " + String.valueOf(this.amount) + ", " + this.instrumentCode + ", "
+                   + this.instrumentNumber + ", " + this.instrumentType + ", " + this.currency + ", " + this.clientNr + ", " + this.firstName + ", " + this.lastName + ", "
+                   + String.valueOf(this.orderDate);
+        }
+    }
+
+}

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/dynamic/BindyFixedLengthDynamicFieldTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/dynamic/BindyFixedLengthDynamicFieldTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/BindySimpleFixedLengthHeaderFooterTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/BindySimpleFixedLengthHeaderFooterTest.java?rev=1443631&view=auto
==============================================================================
--- camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/BindySimpleFixedLengthHeaderFooterTest.java (added)
+++ camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/BindySimpleFixedLengthHeaderFooterTest.java Thu Feb  7 17:59:42 2013
@@ -0,0 +1,224 @@
+/**
+ * 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.headerfooter;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat;
+
+import org.apache.camel.model.dataformat.BindyType;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+/**
+ * This test validates that header and footer records are successfully marshalled / unmarshalled in conjunction
+ * with the primary data records defined for the bindy data format.
+ */
+public class BindySimpleFixedLengthHeaderFooterTest 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";
+    
+    private static final String TEST_HEADER = "101-08-2009\r\n";
+    private static final String TEST_RECORD = "10A9  PaulineM    ISINXD12345678BUYShare000002500.45USD01-08-2009\r\n";
+    private static final String TEST_FOOTER = "9000000001\r\n";
+
+    @EndpointInject(uri = URI_MOCK_MARSHALL_RESULT)
+    private MockEndpoint marshallResult;
+
+    @EndpointInject(uri = URI_MOCK_UNMARSHALL_RESULT)
+    private MockEndpoint unmarshallResult;
+
+    // *************************************************************************
+    // TESTS
+    // *************************************************************************
+    
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testUnmarshallMessage() throws Exception {
+
+        StringBuffer buff = new StringBuffer();
+        buff.append(TEST_HEADER).append(TEST_RECORD).append(TEST_FOOTER);
+        
+        unmarshallResult.expectedMessageCount(1);
+        
+        template.sendBody(URI_DIRECT_UNMARSHALL, buff.toString());
+        
+        unmarshallResult.assertIsSatisfied();
+
+        // check the model
+        Exchange exchange = unmarshallResult.getReceivedExchanges().get(0);
+        Order order = (Order) exchange.getIn().getBody();
+        assertEquals(10, order.getOrderNr());
+        // the field is not trimmed
+        assertEquals("  Pauline", order.getFirstName());
+        assertEquals("M    ", order.getLastName());
+        
+        Map<String, Object> receivedHeaderMap = 
+            (Map<String, Object>) exchange.getIn().getHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_HEADER);
+        
+        Map<String, Object> receivedFooterMap = 
+            (Map<String, Object>) exchange.getIn().getHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_FOOTER);
+        
+        assertNotNull(receivedHeaderMap);
+        assertNotNull(receivedFooterMap);
+        
+        OrderHeader receivedHeader = (OrderHeader) receivedHeaderMap.get(OrderHeader.class.getName());
+        OrderFooter receivedFooter = (OrderFooter) receivedFooterMap.get(OrderFooter.class.getName());
+        
+        assertNotNull(receivedHeader);
+        assertNotNull(receivedFooter);
+        
+        OrderHeader expectedHeader = new OrderHeader();
+        Calendar calendar = new GregorianCalendar();
+        calendar.set(2009, 7, 1, 0, 0, 0);
+        calendar.clear(Calendar.MILLISECOND);
+        expectedHeader.setRecordDate(calendar.getTime());
+        
+        assertEquals(receivedHeader.getRecordType(), expectedHeader.getRecordType());   
+        assertTrue(receivedHeader.getRecordDate().equals(expectedHeader.getRecordDate()));
+    }
+    
+    /**
+     * Verifies that header & footer provided as part of message body are marshalled successfully
+     */
+    @Test
+    public void testMarshallMessageWithDirectHeaderAndFooterInput() throws Exception {
+        Order order = new Order();
+        order.setOrderNr(10);
+        order.setOrderType("BUY");
+        order.setClientNr("A9");
+        order.setFirstName("Pauline");
+        order.setLastName("M");
+        order.setAmount(new BigDecimal("2500.45"));
+        order.setInstrumentCode("ISIN");
+        order.setInstrumentNumber("XD12345678");
+        order.setInstrumentType("Share");
+        order.setCurrency("USD");
+        Calendar calendar = new GregorianCalendar();
+        calendar.set(2009, 7, 1, 0, 0, 0);
+        order.setOrderDate(calendar.getTime());
+        
+        ArrayList<Map<String, Object>> input = new ArrayList<Map<String, Object>>();
+        Map<String, Object> bodyRow = new HashMap<String, Object>();
+        bodyRow.put(Order.class.getName(), order);
+        input.add(createHeaderRow());
+        input.add(bodyRow);
+        input.add(createFooterRow());
+        
+        marshallResult.expectedMessageCount(1);
+        StringBuffer buff = new StringBuffer();
+        buff.append(TEST_HEADER).append(TEST_RECORD).append(TEST_FOOTER);
+        marshallResult.expectedBodiesReceived(Arrays.asList(new String[] {buff.toString()}));
+        template.sendBody(URI_DIRECT_MARSHALL, input);
+        marshallResult.assertIsSatisfied();
+    }
+    
+    /**
+     * Verifies that header & footer provided via message headers are marshalled successfully
+     */
+    @Test
+    public void testMarshallMessageWithIndirectHeaderAndFooterInput() throws Exception {
+        Order order = new Order();
+        order.setOrderNr(10);
+        order.setOrderType("BUY");
+        order.setClientNr("A9");
+        order.setFirstName("Pauline");
+        order.setLastName("M");
+        order.setAmount(new BigDecimal("2500.45"));
+        order.setInstrumentCode("ISIN");
+        order.setInstrumentNumber("XD12345678");
+        order.setInstrumentType("Share");
+        order.setCurrency("USD");
+        Calendar calendar = new GregorianCalendar();
+        calendar.set(2009, 7, 1, 0, 0, 0);
+        order.setOrderDate(calendar.getTime());
+        
+        ArrayList<Map<String, Object>> input = new ArrayList<Map<String, Object>>();
+        Map<String, Object> bodyRow = new HashMap<String, Object>();
+        bodyRow.put(Order.class.getName(), order);
+
+        input.add(bodyRow);
+        
+        Map<String, Object> headers = new HashMap<String, Object>();
+        headers.put(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_HEADER, createHeaderRow());
+        headers.put(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_FOOTER, createFooterRow());
+        
+        marshallResult.reset();
+        marshallResult.expectedMessageCount(1);
+        StringBuffer buff = new StringBuffer();
+        buff.append(TEST_HEADER).append(TEST_RECORD).append(TEST_FOOTER);
+        marshallResult.expectedBodiesReceived(Arrays.asList(new String[] {buff.toString()}));
+        template.sendBodyAndHeaders(URI_DIRECT_MARSHALL, input, headers);
+        marshallResult.assertIsSatisfied();
+    }
+        
+    private Map<String, Object> createHeaderRow() {
+        Map<String, Object> headerMap = new HashMap<String, Object>();
+        OrderHeader header = new OrderHeader();
+        Calendar calendar = new GregorianCalendar();
+        calendar.set(2009, 7, 1, 0, 0, 0);
+        header.setRecordDate(calendar.getTime());
+        headerMap.put(OrderHeader.class.getName(), header);
+        return headerMap;
+    }
+   
+    private Map<String, Object> createFooterRow() {
+        Map<String, Object> footerMap = new HashMap<String, Object>();
+        OrderFooter footer = new OrderFooter();
+        footer.setNumberOfRecordsInTheFile(1);
+        footerMap.put(OrderFooter.class.getName(), footer);
+        return footerMap;
+    }
+    
+    // *************************************************************************
+    // ROUTES
+    // *************************************************************************
+    
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        RouteBuilder routeBuilder = new RouteBuilder() {
+
+            @Override
+            public void configure() throws Exception {      
+                from(URI_DIRECT_MARSHALL)
+                    .marshal().bindy(BindyType.Fixed, Order.class)
+                    .to(URI_MOCK_MARSHALL_RESULT);
+            
+                from(URI_DIRECT_UNMARSHALL)
+                    .unmarshal().bindy(BindyType.Fixed, Order.class)
+                    .to(URI_MOCK_UNMARSHALL_RESULT);
+                
+            }
+        };
+        
+        return routeBuilder;
+    }
+}

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/BindySimpleFixedLengthHeaderFooterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/BindySimpleFixedLengthHeaderFooterTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/Order.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/Order.java?rev=1443631&view=auto
==============================================================================
--- camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/Order.java (added)
+++ camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/Order.java Thu Feb  7 17:59:42 2013
@@ -0,0 +1,156 @@
+/**
+ * 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.headerfooter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import org.apache.camel.dataformat.bindy.annotation.DataField;
+import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
+
+@FixedLengthRecord(hasHeader = true, hasFooter = true)
+public class Order {
+
+    @DataField(pos = 1, length = 2)
+    private int orderNr;
+
+    @DataField(pos = 2, length = 2)
+    private String clientNr;
+
+    @DataField(pos = 3, length = 9)
+    private String firstName;
+
+    @DataField(pos = 4, length = 5, align = "L")
+    private String lastName;
+
+    @DataField(pos = 5, length = 4)
+    private String instrumentCode;
+
+    @DataField(pos = 6, length = 10)
+    private String instrumentNumber;
+
+    @DataField(pos = 7, length = 3)
+    private String orderType;
+
+    @DataField(pos = 8, length = 5)
+    private String instrumentType;
+
+    @DataField(pos = 9, precision = 2, length = 12, paddingChar = '0')
+    private BigDecimal amount;
+
+    @DataField(pos = 10, length = 3)
+    private String currency;
+
+    @DataField(pos = 11, length = 10, pattern = "dd-MM-yyyy")
+    private Date orderDate;
+
+    public int getOrderNr() {
+        return orderNr;
+    }
+
+    public void setOrderNr(int orderNr) {
+        this.orderNr = orderNr;
+    }
+
+    public String getClientNr() {
+        return clientNr;
+    }
+
+    public void setClientNr(String clientNr) {
+        this.clientNr = clientNr;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public String getInstrumentCode() {
+        return instrumentCode;
+    }
+
+    public void setInstrumentCode(String instrumentCode) {
+        this.instrumentCode = instrumentCode;
+    }
+
+    public String getInstrumentNumber() {
+        return instrumentNumber;
+    }
+
+    public void setInstrumentNumber(String instrumentNumber) {
+        this.instrumentNumber = instrumentNumber;
+    }
+
+    public String getOrderType() {
+        return orderType;
+    }
+
+    public void setOrderType(String orderType) {
+        this.orderType = orderType;
+    }
+
+    public String getInstrumentType() {
+        return instrumentType;
+    }
+
+    public void setInstrumentType(String instrumentType) {
+        this.instrumentType = instrumentType;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public void setAmount(BigDecimal amount) {
+        this.amount = amount;
+    }
+
+    public String getCurrency() {
+        return currency;
+    }
+
+    public void setCurrency(String currency) {
+        this.currency = currency;
+    }
+
+    public Date getOrderDate() {
+        return orderDate;
+    }
+
+    public void setOrderDate(Date orderDate) {
+        this.orderDate = orderDate;
+    }
+
+    @Override
+    public String toString() {
+        return "Model : " + Order.class.getName() + " : " + this.orderNr + ", " + this.orderType + ", " + String.valueOf(this.amount) + ", " + this.instrumentCode + ", "
+               + this.instrumentNumber + ", " + this.instrumentType + ", " + this.currency + ", " + this.clientNr + ", " + this.firstName + ", " + this.lastName + ", "
+               + String.valueOf(this.orderDate);
+    }
+}
+

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/Order.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/Order.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderFooter.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderFooter.java?rev=1443631&view=auto
==============================================================================
--- camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderFooter.java (added)
+++ camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderFooter.java Thu Feb  7 17:59:42 2013
@@ -0,0 +1,46 @@
+/**
+ * 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.headerfooter;
+
+import org.apache.camel.dataformat.bindy.annotation.DataField;
+import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
+
+@FixedLengthRecord(isFooter = true)
+public class OrderFooter {
+    
+    @DataField(pos = 1, length = 1)
+    private int recordType = 9;
+    
+    @DataField(pos = 2, length = 9, align = "R", paddingChar = '0')
+    private int numberOfRecordsInTheFile;
+
+    public int getRecordType() {
+        return recordType;
+    }
+
+    public void setRecordType(int recordType) {
+        this.recordType = recordType;
+    }
+
+    public int getNumberOfRecordsInTheFile() {
+        return numberOfRecordsInTheFile;
+    }
+
+    public void setNumberOfRecordsInTheFile(int numberOfRecordsInTheFile) {
+        this.numberOfRecordsInTheFile = numberOfRecordsInTheFile;
+    }
+}

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderFooter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderFooter.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderHeader.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderHeader.java?rev=1443631&view=auto
==============================================================================
--- camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderHeader.java (added)
+++ camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderHeader.java Thu Feb  7 17:59:42 2013
@@ -0,0 +1,47 @@
+/**
+ * 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.headerfooter;
+
+import java.util.Date;
+
+import org.apache.camel.dataformat.bindy.annotation.DataField;
+import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
+
+@FixedLengthRecord(isHeader = true)
+public  class OrderHeader {
+    @DataField(pos = 1, length = 1)
+    private int recordType = 1;
+    
+    @DataField(pos = 2, length = 10, pattern = "dd-MM-yyyy")
+    private Date recordDate;
+    
+    public int getRecordType() {
+        return recordType;
+    }
+
+    public void setRecordType(int recordType) {
+        this.recordType = recordType;
+    }
+
+    public void setRecordDate(Date recordDate) {
+        this.recordDate = recordDate;
+    }
+
+    public Date getRecordDate() {
+        return recordDate;
+    }
+}

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderHeader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/fixed/headerfooter/OrderHeader.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date