View Javadoc
1   /*
2    *  jDTAUS Banking RI DTAUS
3    *  Copyright (C) 2005 Christian Schulte
4    *  <cs@schulte.it>
5    *
6    *  This library is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public
8    *  License as published by the Free Software Foundation; either
9    *  version 2.1 of the License, or any later version.
10   *
11   *  This library is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this library; if not, write to the Free Software
18   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19   *
20   */
21  package org.jdtaus.banking.dtaus.ri.zka;
22  
23  import java.io.IOException;
24  import java.math.BigInteger;
25  import java.util.ArrayList;
26  import java.util.Currency;
27  import java.util.Date;
28  import java.util.List;
29  import org.jdtaus.banking.AlphaNumericText27;
30  import org.jdtaus.banking.Bankleitzahl;
31  import org.jdtaus.banking.Kontonummer;
32  import org.jdtaus.banking.Referenznummer10;
33  import org.jdtaus.banking.Referenznummer11;
34  import org.jdtaus.banking.Textschluessel;
35  import org.jdtaus.banking.dtaus.Checksum;
36  import org.jdtaus.banking.dtaus.CorruptedException;
37  import org.jdtaus.banking.dtaus.Header;
38  import org.jdtaus.banking.dtaus.LogicalFileType;
39  import org.jdtaus.banking.dtaus.PhysicalFileFactory;
40  import org.jdtaus.banking.dtaus.Transaction;
41  import org.jdtaus.banking.dtaus.spi.Fields;
42  import org.jdtaus.banking.messages.IllegalDataMessage;
43  import org.jdtaus.core.container.ContainerFactory;
44  import org.jdtaus.core.container.Implementation;
45  import org.jdtaus.core.container.ModelFactory;
46  import org.jdtaus.core.logging.spi.Logger;
47  import org.jdtaus.core.text.Message;
48  
49  /**
50   * Anlage 3 - 1.1 DTAUS0: Zahlungsverkehrssammelauftrag Diskettenformat.
51   *
52   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
53   * @version $JDTAUS: DTAUSDisk.java 8817 2013-06-07 19:37:52Z schulte $
54   */
55  public final class DTAUSDisk extends AbstractLogicalFile
56  {
57  
58      /** Länge des konstanten Teiles eines C Datensatzes in Byte. */
59      protected static final int CRECORD_CONST_LENGTH = 187;
60  
61      /** Länge eines Erweiterungsteiles in Byte. */
62      protected static final int CRECORD_EXT_LENGTH = 29;
63  
64      /**
65       * Index = A Datensatz-Feld - 1,
66       * Wert = Offset relativ zum Anfang des Satzabschnittes.
67       */
68      protected static final int[] ARECORD_OFFSETS =
69      {
70          0, 4, 5, 7, 15, 23, 50, 56, 60, 70, 80, 95, 103, 127
71      };
72  
73      /**
74       * Index = A Datensatz-Feld - 1,
75       * Wert = Länge des Feldes in Byte.
76       */
77      protected static final int[] ARECORD_LENGTH =
78      {
79          4, 1, 2, 8, 8, 27, 6, 4, 10, 10, 15, 8, 24, 1
80      };
81  
82      /**
83       * Index = E Datensatz-Feld - 1,
84       * Wert = Offset relativ zum Anfang des Satzabschnittes.
85       */
86      protected static final int[] ERECORD_OFFSETS =
87      {
88          0, 4, 5, 10, 17, 30, 47, 64, 77
89      };
90  
91      /**
92       * Index = E Datensatz-Feld -1,
93       * Wert = Länge des Feldes in Byte.
94       */
95      protected static final int[] ERECORD_LENGTH =
96      {
97          4, 1, 5, 7, 13, 17, 17, 13, 51
98      };
99  
100     /**
101      * Index = C Datensatz-Feld - 1,
102      * Wert = Offset relativ zum ersten Satzabschnitt.
103      */
104     protected static final int[] CRECORD_OFFSETS1 =
105     {
106         0, 4, 5, 13, 21, 32, 44, 49, 50, 61, 69, 79, 90, 93, 120
107     };
108 
109     /**
110      * Index = C Datensatz-Feld - 1 (erster Satzabschnitt),
111      * Wert = Länge des Feldes in Byte.
112      */
113     protected static final int[] CRECORD_LENGTH1 =
114     {
115         4, 1, 8, 8, 10, 11, 5, 1, 11, 8, 10, 11, 3, 27, 8
116     };
117 
118     /**
119      * Index = C Datensatz-Feld des zweiten Satzabschnittes - 1,
120      * Wert = Offset relativ zum zweiten Satzabschnitt.
121      */
122     protected static final int[] CRECORD_OFFSETS2 =
123     {
124         0, 27, 54, 55, 57, 59, 61, 88, 90, 117
125     };
126 
127     /**
128      * Index = C Datensatz-Feld des zweiten Satzabschnittes - 1,
129      * Wert = Länge des Feldes in Byte.
130      */
131     protected static final int[] CRECORD_LENGTH2 =
132     {
133         27, 27, 1, 2, 2, 2, 27, 2, 27, 11
134     };
135 
136     /**
137      * Index = C Datensatz-Feld des 3., 4., 5. und 6. Satzabschnittes - 1,
138      * Wert = Offset relativ zum Anfang des 3., 4., 5. und 6. Satzabschnittes.
139      */
140     protected static final int[] CRECORD_OFFSETS_EXT =
141     {
142         0, 2, 29, 31, 58, 60, 87, 89, 116
143     };
144 
145     /**
146      * Index = C Datensatz-Feld des 3., 4., 5. und 6. Satzabschnittes - 1,
147      * Wert = Länge des Feldes in Byte.
148      */
149     protected static final int[] CRECORD_LENGTH_EXT =
150     {
151         2, 27, 2, 27, 2, 27, 2, 27, 12
152     };
153 
154     /**
155      * Index = Anzahl Erweiterungsteile,
156      * Wert = Anzahl benötigter Satzabschnitte.
157      */
158     protected static final int[] CRECORD_EXTENSIONCOUNT_TO_BLOCKCOUNT =
159     {
160         2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6
161     };
162 
163     /**
164      * Index = Index Erweiterungsteil,
165      * Wert = Satzabschnitt-Offset zu Transaktionsbeginn.
166      */
167     protected static final int[] CRECORD_EXTINDEX_TO_BLOCKOFFSET =
168     {
169         1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
170     };
171 
172     /**
173      * Index = Index Erweiterungsteil,
174      * Wert = Anfangsposition des Erweiterungsteils relativ zum Anfang des Satzabschnittes.
175      */
176     protected static final int[] CRECORD_EXTINDEX_TO_TYPEOFFSET =
177     {
178         CRECORD_OFFSETS2[5], CRECORD_OFFSETS2[7], CRECORD_OFFSETS_EXT[0], CRECORD_OFFSETS_EXT[2],
179         CRECORD_OFFSETS_EXT[4], CRECORD_OFFSETS_EXT[6], CRECORD_OFFSETS_EXT[0], CRECORD_OFFSETS_EXT[2],
180         CRECORD_OFFSETS_EXT[4], CRECORD_OFFSETS_EXT[6], CRECORD_OFFSETS_EXT[0], CRECORD_OFFSETS_EXT[2],
181         CRECORD_OFFSETS_EXT[4], CRECORD_OFFSETS_EXT[6], CRECORD_OFFSETS_EXT[0], CRECORD_OFFSETS_EXT[2],
182         CRECORD_OFFSETS_EXT[4], CRECORD_OFFSETS_EXT[6]
183     };
184 
185     /**
186      * Index = Index Erweiterungsteil,
187      * Wert = Anfangsposition des Erweiterungsteils relativ zum Anfang des Satzabschnittes.
188      */
189     protected static final int[] CRECORD_EXTINDEX_TO_TYPELENGTH =
190     {
191         CRECORD_LENGTH2[5], CRECORD_LENGTH2[7], CRECORD_LENGTH_EXT[0], CRECORD_LENGTH_EXT[2],
192         CRECORD_LENGTH_EXT[4], CRECORD_LENGTH_EXT[6], CRECORD_LENGTH_EXT[0], CRECORD_LENGTH_EXT[2],
193         CRECORD_LENGTH_EXT[4], CRECORD_LENGTH_EXT[6], CRECORD_LENGTH_EXT[0], CRECORD_LENGTH_EXT[2],
194         CRECORD_LENGTH_EXT[4], CRECORD_LENGTH_EXT[6], CRECORD_LENGTH_EXT[0], CRECORD_LENGTH_EXT[2],
195         CRECORD_LENGTH_EXT[4], CRECORD_LENGTH_EXT[6]
196     };
197 
198     /**
199      * Index = Index Erweiterungsteil,
200      * Wert = Anfangsposition des Erweiterungsteils relativ zum Anfang des Satzabschnittes.
201      */
202     protected static final int[] CRECORD_EXTINDEX_TO_VALUEOFFSET =
203     {
204         CRECORD_OFFSETS2[6], CRECORD_OFFSETS2[8], CRECORD_OFFSETS_EXT[1], CRECORD_OFFSETS_EXT[3],
205         CRECORD_OFFSETS_EXT[5], CRECORD_OFFSETS_EXT[7], CRECORD_OFFSETS_EXT[1], CRECORD_OFFSETS_EXT[3],
206         CRECORD_OFFSETS_EXT[5], CRECORD_OFFSETS_EXT[7], CRECORD_OFFSETS_EXT[1], CRECORD_OFFSETS_EXT[3],
207         CRECORD_OFFSETS_EXT[5], CRECORD_OFFSETS_EXT[7], CRECORD_OFFSETS_EXT[1], CRECORD_OFFSETS_EXT[3],
208         CRECORD_OFFSETS_EXT[5], CRECORD_OFFSETS_EXT[7]
209     };
210 
211     /**
212      * Index = Index Erweiterungsteil,
213      * Wert = Anfangsposition des Erweiterungsteils relativ zum Anfang des Satzabschnittes.
214      */
215     protected static final int[] CRECORD_EXTINDEX_TO_VALUELENGTH =
216     {
217         CRECORD_LENGTH2[6], CRECORD_LENGTH2[8], CRECORD_LENGTH_EXT[1], CRECORD_LENGTH_EXT[3],
218         CRECORD_LENGTH_EXT[5], CRECORD_LENGTH_EXT[7], CRECORD_LENGTH_EXT[1], CRECORD_LENGTH_EXT[3],
219         CRECORD_LENGTH_EXT[5], CRECORD_LENGTH_EXT[7], CRECORD_LENGTH_EXT[1], CRECORD_LENGTH_EXT[3],
220         CRECORD_LENGTH_EXT[5], CRECORD_LENGTH_EXT[7], CRECORD_LENGTH_EXT[1], CRECORD_LENGTH_EXT[3],
221         CRECORD_LENGTH_EXT[5], CRECORD_LENGTH_EXT[7]
222     };
223 
224     /**
225      * Index = Index Erweiterungsteil,
226      * Wert = Anzahl der folgenden Erweiterungsteile im selben Satzabschnitt.
227      */
228     protected static final int[] CRECORD_EXTINDEX_TO_FOLLOWINGEXTENSIONS =
229     {
230         1, 0, 3, 2, 1, 0, 3, 2, 1, 0, 3, 2, 1, 0, 3, 2, 1, 0
231     };
232 
233     /**
234      * Index = Index Erweiterungsteil,
235      * Wert = Feld-Konstante für das Typen-Feld des Erweiterungsteils.
236      */
237     protected static final int[] CRECORD_EXTINDEX_TO_TYPEFIELD =
238     {
239         Fields.FIELD_C19, Fields.FIELD_C21, Fields.FIELD_C24, Fields.FIELD_C26, Fields.FIELD_C28, Fields.FIELD_C30,
240         Fields.FIELD_C33, Fields.FIELD_C35, Fields.FIELD_C37, Fields.FIELD_C39, Fields.FIELD_C42, Fields.FIELD_C44,
241         Fields.FIELD_C46, Fields.FIELD_C48, Fields.FIELD_C51, Fields.FIELD_C53, Fields.FIELD_C55, Fields.FIELD_C57,
242         Fields.FIELD_C59
243     };
244 
245     /**
246      * Index = Index Erweiterungsteil,
247      * Wert = Feld-Konstante für das Werte-Feld des Erweiterungsteils.
248      */
249     protected static final int[] CRECORD_EXTINDEX_TO_VALUEFIELD =
250     {
251         Fields.FIELD_C20, Fields.FIELD_C22, Fields.FIELD_C25, Fields.FIELD_C27, Fields.FIELD_C29, Fields.FIELD_C31,
252         Fields.FIELD_C34, Fields.FIELD_C36, Fields.FIELD_C38, Fields.FIELD_C40, Fields.FIELD_C43, Fields.FIELD_C45,
253         Fields.FIELD_C47, Fields.FIELD_C49, Fields.FIELD_C52, Fields.FIELD_C54, Fields.FIELD_C56, Fields.FIELD_C58
254     };
255 
256     /** Erzeugt eine neue {@code DTAUSDisk} Instanz. */
257     public DTAUSDisk()
258     {
259         super();
260     }
261 
262     protected char getBlockType( final long position ) throws IOException
263     {
264         // Feld 2
265         final AlphaNumericText27 txt = this.readAlphaNumeric(
266             Fields.FIELD_A2, position + ARECORD_OFFSETS[1], ARECORD_LENGTH[1], ENCODING_ASCII );
267 
268         char ret = '?';
269 
270         if ( txt != null )
271         {
272             if ( txt.length() != 1 )
273             {
274                 if ( ThreadLocalMessages.isErrorsEnabled() )
275                 {
276                     throw new CorruptedException( this.getImplementation(), position + ARECORD_OFFSETS[1] );
277                 }
278                 else
279                 {
280                     final Message msg = new IllegalDataMessage(
281                         Fields.FIELD_A2, IllegalDataMessage.TYPE_CONSTANT, position + ARECORD_OFFSETS[1],
282                         txt.format() );
283 
284                     ThreadLocalMessages.getMessages().addMessage( msg );
285                 }
286             }
287             else
288             {
289                 ret = txt.charAt( 0 );
290             }
291         }
292 
293         return ret;
294     }
295 
296     protected Header readHeader() throws IOException
297     {
298         Long num;
299         AlphaNumericText27 txt;
300         final Header ret = new Header();
301 
302         // Feld 1
303         num = this.readNumber(
304             Fields.FIELD_A1, this.getHeaderPosition() + ARECORD_OFFSETS[0], ARECORD_LENGTH[0], ENCODING_ASCII );
305 
306         if ( num.longValue() != NO_NUMBER && num.intValue() != this.getBlockSize() )
307         {
308             if ( ThreadLocalMessages.isErrorsEnabled() )
309             {
310                 throw new CorruptedException( this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[0] );
311             }
312             else
313             {
314                 final Message msg = new IllegalDataMessage(
315                     Fields.FIELD_A1, IllegalDataMessage.TYPE_CONSTANT, this.getHeaderPosition() + ARECORD_OFFSETS[0],
316                     num.toString() );
317 
318                 ThreadLocalMessages.getMessages().addMessage( msg );
319             }
320         }
321 
322         // Feld 2
323         txt = this.readAlphaNumeric(
324             Fields.FIELD_A2, this.getHeaderPosition() + ARECORD_OFFSETS[1], ARECORD_LENGTH[1], ENCODING_ASCII );
325 
326         if ( txt != null && ( txt.length() != 1 || txt.charAt( 0 ) != 'A' ) )
327         {
328             if ( ThreadLocalMessages.isErrorsEnabled() )
329             {
330                 throw new CorruptedException( this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[1] );
331             }
332             else
333             {
334                 final Message msg = new IllegalDataMessage(
335                     Fields.FIELD_A2, IllegalDataMessage.TYPE_CONSTANT, this.getHeaderPosition() + ARECORD_OFFSETS[1],
336                     txt.format() );
337 
338                 ThreadLocalMessages.getMessages().addMessage( msg );
339             }
340         }
341 
342         // Feld 3
343         txt = this.readAlphaNumeric(
344             Fields.FIELD_A3, this.getHeaderPosition() + ARECORD_OFFSETS[2], ARECORD_LENGTH[2], ENCODING_ASCII );
345 
346         ret.setType( null );
347         if ( txt != null )
348         {
349             final LogicalFileType label = LogicalFileType.valueOf( txt.format() );
350 
351             if ( label == null )
352             {
353                 if ( ThreadLocalMessages.isErrorsEnabled() )
354                 {
355                     throw new CorruptedException(
356                         this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[2] );
357 
358                 }
359                 else
360                 {
361                     final Message msg = new IllegalDataMessage(
362                         Fields.FIELD_A3, IllegalDataMessage.TYPE_FILETYPE, this.getHeaderPosition() + ARECORD_OFFSETS[2],
363                         txt.format() );
364 
365                     ThreadLocalMessages.getMessages().addMessage( msg );
366                 }
367             }
368             else
369             {
370                 ret.setType( label );
371             }
372         }
373 
374         // Feld 4
375         num = this.readNumber(
376             Fields.FIELD_A4, this.getHeaderPosition() + ARECORD_OFFSETS[3], ARECORD_LENGTH[3], ENCODING_ASCII );
377 
378         ret.setBank( null );
379         if ( num.longValue() != NO_NUMBER )
380         {
381             if ( !Bankleitzahl.checkBankleitzahl( num ) )
382             {
383                 if ( ThreadLocalMessages.isErrorsEnabled() )
384                 {
385                     throw new CorruptedException(
386                         this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[3] );
387 
388                 }
389                 else
390                 {
391                     final Message msg = new IllegalDataMessage(
392                         Fields.FIELD_A4, IllegalDataMessage.TYPE_BANKLEITZAHL,
393                         this.getHeaderPosition() + ARECORD_OFFSETS[3], num.toString() );
394 
395                     ThreadLocalMessages.getMessages().addMessage( msg );
396                 }
397             }
398             else
399             {
400                 ret.setBank( Bankleitzahl.valueOf( num ) );
401             }
402         }
403 
404         // Feld 5
405         // Nur belegt wenn Absender Kreditinistitut ist, sonst 0.
406         num = this.readNumber(
407             Fields.FIELD_A5, this.getHeaderPosition() + ARECORD_OFFSETS[4], ARECORD_LENGTH[4], ENCODING_ASCII );
408 
409         ret.setBankData( null );
410         if ( num.longValue() != NO_NUMBER && ret.getType() != null && ret.getType().isSendByBank() )
411         {
412             if ( !Bankleitzahl.checkBankleitzahl( num ) )
413             {
414                 if ( ThreadLocalMessages.isErrorsEnabled() )
415                 {
416                     throw new CorruptedException(
417                         this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[4] );
418 
419                 }
420                 else
421                 {
422                     final Message msg = new IllegalDataMessage(
423                         Fields.FIELD_A5, IllegalDataMessage.TYPE_BANKLEITZAHL,
424                         this.getHeaderPosition() + ARECORD_OFFSETS[4], num.toString() );
425 
426                     ThreadLocalMessages.getMessages().addMessage( msg );
427                 }
428             }
429             else
430             {
431                 ret.setBankData( Bankleitzahl.valueOf( num ) );
432             }
433         }
434 
435         // Feld 6
436         txt = this.readAlphaNumeric(
437             Fields.FIELD_A6, this.getHeaderPosition() + ARECORD_OFFSETS[5], ARECORD_LENGTH[5], ENCODING_ASCII );
438 
439         ret.setCustomer( txt );
440 
441         // Feld 7
442         final Date createDate = this.readShortDate(
443             Fields.FIELD_A7, this.getHeaderPosition() + ARECORD_OFFSETS[6], ENCODING_ASCII );
444 
445         if ( createDate == null )
446         {
447             if ( ThreadLocalMessages.isErrorsEnabled() )
448             {
449                 throw new CorruptedException( this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[6] );
450             }
451             else
452             {
453                 ThreadLocalMessages.getMessages().addMessage( new IllegalDataMessage(
454                     Fields.FIELD_A7, IllegalDataMessage.TYPE_SHORTDATE, this.getHeaderPosition() + ARECORD_OFFSETS[6],
455                     "      " ) );
456 
457             }
458         }
459 
460         // Feld 8
461         // Nur belegt wenn Absender Kreditinistitut ist, sonst "".
462         txt = this.readAlphaNumeric(
463             Fields.FIELD_A8, this.getHeaderPosition() + ARECORD_OFFSETS[7], ARECORD_LENGTH[7], ENCODING_ASCII );
464 
465         // Feld 9
466         num = this.readNumber(
467             Fields.FIELD_A9, this.getHeaderPosition() + ARECORD_OFFSETS[8], ARECORD_LENGTH[8], ENCODING_ASCII );
468 
469         ret.setAccount( null );
470         if ( num.longValue() != NO_NUMBER )
471         {
472             if ( !Kontonummer.checkKontonummer( num ) )
473             {
474                 if ( ThreadLocalMessages.isErrorsEnabled() )
475                 {
476                     throw new CorruptedException(
477                         this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[8] );
478 
479                 }
480                 else
481                 {
482                     final Message msg = new IllegalDataMessage(
483                         Fields.FIELD_A9, IllegalDataMessage.TYPE_KONTONUMMER,
484                         this.getHeaderPosition() + ARECORD_OFFSETS[8], num.toString() );
485 
486                     ThreadLocalMessages.getMessages().addMessage( msg );
487                 }
488             }
489             else
490             {
491                 ret.setAccount( Kontonummer.valueOf( num ) );
492             }
493         }
494 
495         // Feld 10
496         num = this.readNumber(
497             Fields.FIELD_A10, this.getHeaderPosition() + ARECORD_OFFSETS[9], ARECORD_LENGTH[9], ENCODING_ASCII );
498 
499         ret.setReference( null );
500         if ( num.longValue() != NO_NUMBER )
501         {
502             if ( !Referenznummer10.checkReferenznummer10( num ) )
503             {
504                 if ( ThreadLocalMessages.isErrorsEnabled() )
505                 {
506                     throw new CorruptedException(
507                         this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[9] );
508 
509                 }
510                 else
511                 {
512                     final Message msg = new IllegalDataMessage(
513                         Fields.FIELD_A10, IllegalDataMessage.TYPE_REFERENZNUMMER,
514                         this.getHeaderPosition() + ARECORD_OFFSETS[9], num.toString() );
515 
516                     ThreadLocalMessages.getMessages().addMessage( msg );
517                 }
518             }
519             else
520             {
521                 ret.setReference( Referenznummer10.valueOf( num ) );
522             }
523         }
524 
525         // Feld 11b
526         final Date executionDate = this.readLongDate(
527             Fields.FIELD_A11B, this.getHeaderPosition() + ARECORD_OFFSETS[11], ENCODING_ASCII );
528 
529         ret.setCreateDate( createDate );
530         ret.setExecutionDate( executionDate );
531 
532         ret.setCurrency( null );
533         if ( createDate != null )
534         {
535             // Feld 12
536             txt = this.readAlphaNumeric(
537                 Fields.FIELD_A12, this.getHeaderPosition() + ARECORD_OFFSETS[13], ARECORD_LENGTH[13], ENCODING_ASCII );
538 
539             if ( txt != null )
540             {
541                 if ( txt.length() != 1 )
542                 {
543                     if ( ThreadLocalMessages.isErrorsEnabled() )
544                     {
545                         throw new CorruptedException(
546                             this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[13] );
547 
548                     }
549                     else
550                     {
551                         final Message msg = new IllegalDataMessage(
552                             Fields.FIELD_A12, IllegalDataMessage.TYPE_CURRENCY,
553                             this.getHeaderPosition() + ARECORD_OFFSETS[13], txt.format() );
554 
555                         ThreadLocalMessages.getMessages().addMessage( msg );
556                     }
557                 }
558                 else
559                 {
560                     final char c = txt.charAt( 0 );
561                     final Currency cur = this.getCurrencyMapper().getDtausCurrency( c, createDate );
562 
563                     if ( cur == null )
564                     {
565                         if ( ThreadLocalMessages.isErrorsEnabled() )
566                         {
567                             throw new CorruptedException(
568                                 this.getImplementation(), this.getHeaderPosition() + ARECORD_OFFSETS[13] );
569 
570                         }
571                         else
572                         {
573                             final Message msg = new IllegalDataMessage(
574                                 Fields.FIELD_A12, IllegalDataMessage.TYPE_CURRENCY,
575                                 this.getHeaderPosition() + ARECORD_OFFSETS[13], txt.format() );
576 
577                             ThreadLocalMessages.getMessages().addMessage( msg );
578                         }
579                     }
580 
581                     ret.setCurrency( cur );
582                 }
583             }
584         }
585 
586         return ret;
587     }
588 
589     protected void writeHeader( final Header header ) throws IOException
590     {
591         final LogicalFileType label = header.getType();
592 
593         // Feld 1
594         this.writeNumber(
595             Fields.FIELD_A1, this.getHeaderPosition() + ARECORD_OFFSETS[0], ARECORD_LENGTH[0], this.getBlockSize(),
596             ENCODING_ASCII );
597 
598         // Feld 2
599         this.writeAlphaNumeric(
600             Fields.FIELD_A2, this.getHeaderPosition() + ARECORD_OFFSETS[1], ARECORD_LENGTH[1], "A", ENCODING_ASCII );
601 
602         // Feld 3
603         this.writeAlphaNumeric(
604             Fields.FIELD_A3, this.getHeaderPosition() + ARECORD_OFFSETS[2], ARECORD_LENGTH[2], label.getCode(),
605             ENCODING_ASCII );
606 
607         // Feld 4
608         this.writeNumber(
609             Fields.FIELD_A4, this.getHeaderPosition() + ARECORD_OFFSETS[3], ARECORD_LENGTH[3],
610             header.getBank().intValue(), ENCODING_ASCII );
611 
612         // Feld 5
613         this.writeNumber(
614             Fields.FIELD_A5, this.getHeaderPosition() + ARECORD_OFFSETS[4],
615             ARECORD_LENGTH[4], ( label.isSendByBank() && header.getBankData() != null
616                                  ? header.getBankData().intValue() : 0 ), ENCODING_ASCII );
617 
618         // Feld 6
619         this.writeAlphaNumeric(
620             Fields.FIELD_A6, this.getHeaderPosition() + ARECORD_OFFSETS[5], ARECORD_LENGTH[5],
621             header.getCustomer().format(), ENCODING_ASCII );
622 
623         // Feld 7
624         this.writeShortDate(
625             Fields.FIELD_A7, this.getHeaderPosition() + ARECORD_OFFSETS[6], header.getCreateDate(), ENCODING_ASCII );
626 
627         // Feld 8
628         this.writeAlphaNumeric(
629             Fields.FIELD_A8, this.getHeaderPosition() + ARECORD_OFFSETS[7], ARECORD_LENGTH[7], "", ENCODING_ASCII );
630 
631         // Feld 9
632         this.writeNumber(
633             Fields.FIELD_A9, this.getHeaderPosition() + ARECORD_OFFSETS[8], ARECORD_LENGTH[8],
634             header.getAccount().longValue(), ENCODING_ASCII );
635 
636         // Feld 10
637         this.writeNumber(
638             Fields.FIELD_A10, this.getHeaderPosition() + ARECORD_OFFSETS[9], ARECORD_LENGTH[9],
639             ( header.getReference() != null ? header.getReference().longValue() : 0L ), ENCODING_ASCII );
640 
641         // Feld 11a
642         this.writeAlphaNumeric(
643             Fields.FIELD_A11A, this.getHeaderPosition() + ARECORD_OFFSETS[10], ARECORD_LENGTH[10], "", ENCODING_ASCII );
644 
645         // Feld 11b
646         this.writeLongDate(
647             Fields.FIELD_A11B, this.getHeaderPosition() + ARECORD_OFFSETS[11], header.getExecutionDate(),
648             ENCODING_ASCII );
649 
650         // Feld 11c
651         this.writeAlphaNumeric(
652             Fields.FIELD_A11C, this.getHeaderPosition() + ARECORD_OFFSETS[12], ARECORD_LENGTH[12], "", ENCODING_ASCII );
653 
654         // Feld 12
655         this.writeAlphaNumeric(
656             Fields.FIELD_A12, this.getHeaderPosition() + ARECORD_OFFSETS[13], ARECORD_LENGTH[13],
657             Character.toString( this.getCurrencyMapper().getDtausCode( header.getCurrency(), header.getCreateDate() ) ),
658             ENCODING_ASCII );
659 
660     }
661 
662     protected Checksum readChecksum() throws IOException
663     {
664         Long num;
665         final AlphaNumericText27 txt;
666         final Checksum checksum;
667         checksum = new Checksum();
668 
669         // Feld 1
670         num = this.readNumber(
671             Fields.FIELD_E1, this.getChecksumPosition() + ERECORD_OFFSETS[0], ERECORD_LENGTH[0], ENCODING_ASCII );
672 
673         if ( num.longValue() != NO_NUMBER && num.intValue() != this.getBlockSize() )
674         {
675             if ( ThreadLocalMessages.isErrorsEnabled() )
676             {
677                 throw new CorruptedException(
678                     this.getImplementation(), this.getChecksumPosition() + ERECORD_OFFSETS[0] );
679 
680             }
681             else
682             {
683                 final Message msg = new IllegalDataMessage(
684                     Fields.FIELD_E1, IllegalDataMessage.TYPE_CONSTANT, this.getChecksumPosition() + ERECORD_OFFSETS[0],
685                     num.toString() );
686 
687                 ThreadLocalMessages.getMessages().addMessage( msg );
688             }
689         }
690 
691         // Feld 2
692         txt = this.readAlphaNumeric(
693             Fields.FIELD_E2, this.getChecksumPosition() + ERECORD_OFFSETS[1], ERECORD_LENGTH[1], ENCODING_ASCII );
694 
695         if ( txt != null && ( txt.length() != 1 || txt.charAt( 0 ) != 'E' ) )
696         {
697             if ( ThreadLocalMessages.isErrorsEnabled() )
698             {
699                 throw new CorruptedException(
700                     this.getImplementation(), this.getChecksumPosition() + ERECORD_OFFSETS[1] );
701 
702             }
703             else
704             {
705                 final Message msg = new IllegalDataMessage(
706                     Fields.FIELD_E2, IllegalDataMessage.TYPE_CONSTANT, this.getChecksumPosition() + ERECORD_OFFSETS[1],
707                     txt.format() );
708 
709                 ThreadLocalMessages.getMessages().addMessage( msg );
710             }
711         }
712 
713         // Feld 4
714         num = this.readNumber(
715             Fields.FIELD_E4, this.getChecksumPosition() + ERECORD_OFFSETS[3], ERECORD_LENGTH[3], ENCODING_ASCII );
716 
717         if ( num.longValue() != NO_NUMBER )
718         {
719             checksum.setTransactionCount( num.intValue() );
720         }
721 
722         // Feld 6
723         num = this.readNumber(
724             Fields.FIELD_E6, this.getChecksumPosition() + ERECORD_OFFSETS[5], ERECORD_LENGTH[5], ENCODING_ASCII );
725 
726         if ( num.longValue() != NO_NUMBER )
727         {
728             checksum.setSumTargetAccount( num.longValue() );
729         }
730 
731         // Feld 7
732         num = this.readNumber(
733             Fields.FIELD_E7, this.getChecksumPosition() + ERECORD_OFFSETS[6], ERECORD_LENGTH[6], ENCODING_ASCII );
734 
735         if ( num.longValue() != NO_NUMBER )
736         {
737             checksum.setSumTargetBank( num.longValue() );
738         }
739 
740         // Feld 8
741         num = this.readNumber(
742             Fields.FIELD_E8, this.getChecksumPosition() + ERECORD_OFFSETS[7], ERECORD_LENGTH[7], ENCODING_ASCII );
743 
744         if ( num.longValue() != NO_NUMBER )
745         {
746             checksum.setSumAmount( num.longValue() );
747         }
748 
749         return checksum;
750     }
751 
752     protected void writeChecksum( final Checksum checksum ) throws IOException
753     {
754         // Feld 1
755         this.writeNumber(
756             Fields.FIELD_E1, this.getChecksumPosition() + ERECORD_OFFSETS[0], ERECORD_LENGTH[0], this.getBlockSize(),
757             ENCODING_ASCII );
758 
759         // Feld 2
760         this.writeAlphaNumeric(
761             Fields.FIELD_E2, this.getChecksumPosition() + ERECORD_OFFSETS[1], ERECORD_LENGTH[1], "E", ENCODING_ASCII );
762 
763         // Feld 3
764         this.writeAlphaNumeric(
765             Fields.FIELD_E3, this.getChecksumPosition() + ERECORD_OFFSETS[2], ERECORD_LENGTH[2], "", ENCODING_ASCII );
766 
767         // Feld 4
768         this.writeNumber(
769             Fields.FIELD_E4, this.getChecksumPosition() + ERECORD_OFFSETS[3], ERECORD_LENGTH[3],
770             checksum.getTransactionCount(), ENCODING_ASCII );
771 
772         // Feld 5
773         this.writeNumber(
774             Fields.FIELD_E5, this.getChecksumPosition() + ERECORD_OFFSETS[4], ERECORD_LENGTH[4], 0L, ENCODING_ASCII );
775 
776         // Feld 6
777         this.writeNumber(
778             Fields.FIELD_E6, this.getChecksumPosition() + ERECORD_OFFSETS[5], ERECORD_LENGTH[5],
779             checksum.getSumTargetAccount(), ENCODING_ASCII );
780 
781         // Feld 7
782         this.writeNumber(
783             Fields.FIELD_E7, this.getChecksumPosition() + ERECORD_OFFSETS[6], ERECORD_LENGTH[6],
784             checksum.getSumTargetBank(), ENCODING_ASCII );
785 
786         // Feld 8
787         this.writeNumber(
788             Fields.FIELD_E8, this.getChecksumPosition() + ERECORD_OFFSETS[7], ERECORD_LENGTH[7],
789             checksum.getSumAmount(), ENCODING_ASCII );
790 
791         // Feld 9
792         this.writeAlphaNumeric(
793             Fields.FIELD_E9, this.getChecksumPosition() + ERECORD_OFFSETS[8], ERECORD_LENGTH[8], "", ENCODING_ASCII );
794 
795     }
796 
797     protected Transaction readTransaction( final long position,
798                                            final Transaction transaction )
799         throws IOException
800     {
801         Long num;
802         AlphaNumericText27 txt;
803         final List desc = new ArrayList( 14 );
804 
805         transaction.setExecutiveExt( null );
806         transaction.setTargetExt( null );
807 
808         final long extCount = this.readNumber(
809             Fields.FIELD_C18, position + this.getBlockSize() + CRECORD_OFFSETS2[4], CRECORD_LENGTH2[4],
810             ENCODING_ASCII ).longValue();
811 
812         if ( extCount != NO_NUMBER && extCount > this.getMaximumExtensionCount() )
813         {
814             if ( ThreadLocalMessages.isErrorsEnabled() )
815             {
816                 throw new CorruptedException( this.getImplementation(),
817                                               position + this.getBlockSize() + CRECORD_OFFSETS2[4] );
818 
819             }
820             else
821             {
822                 final Message msg = new IllegalDataMessage(
823                     Fields.FIELD_C18, IllegalDataMessage.TYPE_CONSTANT,
824                     position + this.getBlockSize() + CRECORD_OFFSETS2[4], Long.toString( extCount ) );
825 
826                 ThreadLocalMessages.getMessages().addMessage( msg );
827             }
828         }
829 
830         // Konstanter Teil - Satzaschnitt 1 - Feld 1
831         num = this.readNumber(
832             Fields.FIELD_C1, position + CRECORD_OFFSETS1[0], CRECORD_LENGTH1[0], ENCODING_ASCII );
833 
834         if ( num.longValue() != NO_NUMBER && extCount != NO_NUMBER
835              && num.intValue() != CRECORD_CONST_LENGTH + extCount * CRECORD_EXT_LENGTH )
836         {
837             if ( ThreadLocalMessages.isErrorsEnabled() )
838             {
839                 throw new CorruptedException( this.getImplementation(), position + CRECORD_OFFSETS1[0] );
840             }
841             else
842             {
843                 final Message msg = new IllegalDataMessage(
844                     Fields.FIELD_C1, IllegalDataMessage.TYPE_NUMERIC, position + CRECORD_OFFSETS1[0], num.toString() );
845 
846                 ThreadLocalMessages.getMessages().addMessage( msg );
847             }
848         }
849 
850         // Konstanter Teil - Satzaschnitt 1 - Feld 2
851         txt = this.readAlphaNumeric(
852             Fields.FIELD_C2, position + CRECORD_OFFSETS1[1], CRECORD_LENGTH1[1], ENCODING_ASCII );
853 
854         if ( txt != null && ( txt.length() != 1 || txt.charAt( 0 ) != 'C' ) )
855         {
856             if ( ThreadLocalMessages.isErrorsEnabled() )
857             {
858                 throw new CorruptedException( this.getImplementation(), position + CRECORD_OFFSETS1[1] );
859             }
860             else
861             {
862                 final Message msg = new IllegalDataMessage(
863                     Fields.FIELD_C2, IllegalDataMessage.TYPE_CONSTANT, position + CRECORD_OFFSETS1[1], txt.format() );
864 
865                 ThreadLocalMessages.getMessages().addMessage( msg );
866             }
867         }
868 
869         // Konstanter Teil - Satzaschnitt 1 - Feld 3
870         num = this.readNumber( Fields.FIELD_C3, position + CRECORD_OFFSETS1[2], CRECORD_LENGTH1[2], ENCODING_ASCII );
871 
872         transaction.setPrimaryBank( null );
873         if ( num.longValue() != NO_NUMBER && num.longValue() != 0L )
874         {
875             if ( !Bankleitzahl.checkBankleitzahl( num ) )
876             {
877                 if ( ThreadLocalMessages.isErrorsEnabled() )
878                 {
879                     throw new CorruptedException(
880                         this.getImplementation(), position + CRECORD_OFFSETS1[2] );
881 
882                 }
883                 else
884                 {
885                     final Message msg = new IllegalDataMessage(
886                         Fields.FIELD_C3, IllegalDataMessage.TYPE_BANKLEITZAHL, position + CRECORD_OFFSETS1[2],
887                         num.toString() );
888 
889                     ThreadLocalMessages.getMessages().addMessage( msg );
890                 }
891             }
892             else
893             {
894                 transaction.setPrimaryBank( Bankleitzahl.valueOf( num ) );
895             }
896         }
897 
898         // Konstanter Teil - Satzaschnitt 1 - Feld 4
899         num = this.readNumber(
900             Fields.FIELD_C4, position + CRECORD_OFFSETS1[3], CRECORD_LENGTH1[3], ENCODING_ASCII );
901 
902         transaction.setTargetBank( null );
903         if ( num.longValue() != NO_NUMBER )
904         {
905             if ( !Bankleitzahl.checkBankleitzahl( num ) )
906             {
907                 if ( ThreadLocalMessages.isErrorsEnabled() )
908                 {
909                     throw new CorruptedException( this.getImplementation(), position + CRECORD_OFFSETS1[3] );
910                 }
911                 else
912                 {
913                     final Message msg = new IllegalDataMessage(
914                         Fields.FIELD_C4, IllegalDataMessage.TYPE_BANKLEITZAHL, position + CRECORD_OFFSETS1[3],
915                         num.toString() );
916 
917                     ThreadLocalMessages.getMessages().addMessage( msg );
918                 }
919             }
920             else
921             {
922                 transaction.setTargetBank( Bankleitzahl.valueOf( num ) );
923             }
924         }
925 
926         // Konstanter Teil - Satzaschnitt 1 - Feld 5
927         num = this.readNumber(
928             Fields.FIELD_C5, position + CRECORD_OFFSETS1[4], CRECORD_LENGTH1[4], ENCODING_ASCII );
929 
930         transaction.setTargetAccount( null );
931         if ( num.longValue() != NO_NUMBER )
932         {
933             if ( !Kontonummer.checkKontonummer( num ) )
934             {
935                 if ( ThreadLocalMessages.isErrorsEnabled() )
936                 {
937                     throw new CorruptedException( this.getImplementation(), position + CRECORD_OFFSETS1[4] );
938                 }
939                 else
940                 {
941                     final Message msg = new IllegalDataMessage(
942                         Fields.FIELD_C5, IllegalDataMessage.TYPE_KONTONUMMER, position + CRECORD_OFFSETS1[4],
943                         num.toString() );
944 
945                     ThreadLocalMessages.getMessages().addMessage( msg );
946                 }
947             }
948             else
949             {
950                 transaction.setTargetAccount( Kontonummer.valueOf( num ) );
951             }
952         }
953 
954         // Konstanter Teil - Satzaschnitt 1 - Feld 6
955         num = this.readNumber(
956             Fields.FIELD_C6, position + CRECORD_OFFSETS1[5], CRECORD_LENGTH1[5], ENCODING_ASCII );
957 
958         transaction.setReference( null );
959         if ( num.longValue() != NO_NUMBER )
960         {
961             if ( !Referenznummer11.checkReferenznummer11( num ) )
962             {
963                 if ( ThreadLocalMessages.isErrorsEnabled() )
964                 {
965                     throw new CorruptedException( this.getImplementation(), position + CRECORD_OFFSETS1[5] );
966                 }
967                 else
968                 {
969                     final Message msg = new IllegalDataMessage(
970                         Fields.FIELD_C6, IllegalDataMessage.TYPE_REFERENZNUMMER, position + CRECORD_OFFSETS1[5],
971                         num.toString() );
972 
973                     ThreadLocalMessages.getMessages().addMessage( msg );
974                 }
975             }
976             else
977             {
978                 transaction.setReference( Referenznummer11.valueOf( num ) );
979             }
980         }
981 
982         // Konstanter Teil - Satzaschnitt 1 - Felder 7a & 7b
983         final Long keyType = this.readNumber(
984             Fields.FIELD_C7A, position + CRECORD_OFFSETS1[6], 2, ENCODING_ASCII );
985 
986         num = this.readNumber(
987             Fields.FIELD_C7B, position + CRECORD_OFFSETS1[6] + 2, CRECORD_LENGTH1[6] - 2, ENCODING_ASCII );
988 
989         transaction.setType( null );
990 
991         if ( keyType.longValue() != NO_NUMBER && num.longValue() != NO_NUMBER
992              && this.getHeader().getCreateDate() != null )
993         {
994             final Textschluessel type = this.getTextschluesselVerzeichnis().getTextschluessel(
995                 keyType.intValue(), num.intValue(), this.getHeader().getCreateDate() );
996 
997             if ( type == null )
998             {
999                 if ( ThreadLocalMessages.isErrorsEnabled() )
1000                 {
1001                     throw new CorruptedException( this.getImplementation(), position + CRECORD_OFFSETS1[6] );
1002                 }
1003                 else
1004                 {
1005                     final Message msg = new IllegalDataMessage(
1006                         Fields.FIELD_C7A, IllegalDataMessage.TYPE_TEXTSCHLUESSEL, position + CRECORD_OFFSETS1[6],
1007                         keyType.toString() + num.toString() );
1008 
1009                     ThreadLocalMessages.getMessages().addMessage( msg );
1010                 }
1011             }
1012             else
1013             {
1014                 transaction.setType( type );
1015             }
1016         }
1017 
1018         // Konstanter Teil - Satzaschnitt 1 - Feld 10
1019         num = this.readNumber( Fields.FIELD_C10, position + CRECORD_OFFSETS1[9], CRECORD_LENGTH1[9], ENCODING_ASCII );
1020 
1021         transaction.setExecutiveBank( null );
1022         if ( num.longValue() != NO_NUMBER )
1023         {
1024             if ( !Bankleitzahl.checkBankleitzahl( num ) )
1025             {
1026                 if ( ThreadLocalMessages.isErrorsEnabled() )
1027                 {
1028                     throw new CorruptedException( this.getImplementation(), position + CRECORD_OFFSETS1[9] );
1029                 }
1030                 else
1031                 {
1032                     final Message msg = new IllegalDataMessage(
1033                         Fields.FIELD_C10, IllegalDataMessage.TYPE_BANKLEITZAHL, position + CRECORD_OFFSETS1[9],
1034                         num.toString() );
1035 
1036                     ThreadLocalMessages.getMessages().addMessage( msg );
1037                 }
1038             }
1039             else
1040             {
1041                 transaction.setExecutiveBank( Bankleitzahl.valueOf( num ) );
1042             }
1043         }
1044 
1045         // Konstanter Teil - Satzaschnitt 1 - Feld 11
1046         num = this.readNumber(
1047             Fields.FIELD_C11, position + CRECORD_OFFSETS1[10], CRECORD_LENGTH1[10], ENCODING_ASCII );
1048 
1049         transaction.setExecutiveAccount( null );
1050         if ( num.longValue() != NO_NUMBER )
1051         {
1052             if ( !Kontonummer.checkKontonummer( num ) )
1053             {
1054                 if ( ThreadLocalMessages.isErrorsEnabled() )
1055                 {
1056                     throw new CorruptedException( this.getImplementation(), position + CRECORD_OFFSETS1[10] );
1057                 }
1058                 else
1059                 {
1060                     final Message msg = new IllegalDataMessage(
1061                         Fields.FIELD_C11, IllegalDataMessage.TYPE_KONTONUMMER, position + CRECORD_OFFSETS1[10],
1062                         num.toString() );
1063 
1064                     ThreadLocalMessages.getMessages().addMessage( msg );
1065                 }
1066             }
1067             else
1068             {
1069                 transaction.setExecutiveAccount( Kontonummer.valueOf( num ) );
1070             }
1071         }
1072 
1073         // Konstanter Teil - Satzaschnitt 1 - Feld 12
1074         num = this.readNumber(
1075             Fields.FIELD_C12, position + CRECORD_OFFSETS1[11], CRECORD_LENGTH1[11], ENCODING_ASCII );
1076 
1077         transaction.setAmount(
1078             num.longValue() == NO_NUMBER
1079             ? null : BigInteger.valueOf( num.longValue() ) );
1080 
1081         // Konstanter Teil - Satzaschnitt 1 - Feld 14a
1082         txt = this.readAlphaNumeric(
1083             Fields.FIELD_C14A, position + CRECORD_OFFSETS1[13], CRECORD_LENGTH1[13], ENCODING_ASCII );
1084 
1085         transaction.setTargetName( txt );
1086 
1087         // Konstanter Teil - Satzaschnitt 2 - Feld 15(1)
1088         txt = this.readAlphaNumeric(
1089             Fields.FIELD_C15, position + this.getBlockSize() + CRECORD_OFFSETS2[0], CRECORD_LENGTH2[0],
1090             ENCODING_ASCII );
1091 
1092         transaction.setExecutiveName( txt );
1093 
1094         // Konstanter Teil - Satzaschnitt 2 - Feld 16(2)
1095         txt = this.readAlphaNumeric(
1096             Fields.FIELD_C16, position + this.getBlockSize() + CRECORD_OFFSETS2[1], CRECORD_LENGTH2[1],
1097             ENCODING_ASCII );
1098 
1099         if ( txt != null )
1100         {
1101             desc.add( txt );
1102         }
1103 
1104         // Konstanter Teil - Satzaschnitt 2 - Feld 17a(3)
1105         txt = this.readAlphaNumeric(
1106             Fields.FIELD_C17A, position + this.getBlockSize() + CRECORD_OFFSETS2[2], CRECORD_LENGTH2[2],
1107             ENCODING_ASCII );
1108 
1109         transaction.setCurrency( null );
1110 
1111         if ( txt != null )
1112         {
1113             if ( txt.length() != 1 )
1114             {
1115                 if ( ThreadLocalMessages.isErrorsEnabled() )
1116                 {
1117                     throw new CorruptedException(
1118                         this.getImplementation(), position + this.getBlockSize() + CRECORD_OFFSETS1[10] );
1119 
1120                 }
1121                 else
1122                 {
1123                     final Message msg = new IllegalDataMessage(
1124                         Fields.FIELD_C17A, IllegalDataMessage.TYPE_CURRENCY,
1125                         position + this.getBlockSize() + CRECORD_OFFSETS1[10], txt.format() );
1126 
1127                     ThreadLocalMessages.getMessages().addMessage( msg );
1128                 }
1129             }
1130             else if ( this.getHeader().getCreateDate() != null )
1131             {
1132                 final char c = txt.charAt( 0 );
1133                 final Currency cur = this.getCurrencyMapper().getDtausCurrency( c, this.getHeader().getCreateDate() );
1134 
1135                 if ( cur == null )
1136                 {
1137                     if ( ThreadLocalMessages.isErrorsEnabled() )
1138                     {
1139                         throw new CorruptedException(
1140                             this.getImplementation(), position + this.getBlockSize() + CRECORD_OFFSETS1[10] );
1141 
1142                     }
1143                     else
1144                     {
1145                         final Message msg = new IllegalDataMessage(
1146                             Fields.FIELD_C17A, IllegalDataMessage.TYPE_CURRENCY,
1147                             position + this.getBlockSize() + CRECORD_OFFSETS1[10], txt.format() );
1148 
1149                         ThreadLocalMessages.getMessages().addMessage( msg );
1150                     }
1151                 }
1152 
1153                 transaction.setCurrency( cur );
1154             }
1155         }
1156 
1157         //if(header.getLabel().isBank()) {
1158         // Konstanter Teil - Satzaschnitt 1 - Feld 8
1159         //    num = this.readNumber(block, DTAUSDisk.CRECORD_OFFSETS1[7],
1160         //        DTAUSDisk.CRECORD_LENGTH1[7]);
1161 
1162         //    transaction.set
1163         //
1164         //}
1165 
1166         // Erweiterungsteile des 2., 3., 4., 5. und 6. Satzabschnittes.
1167         for ( int i = 0; i < extCount && extCount != NO_NUMBER; i++ )
1168         {
1169             final long extPos = position + CRECORD_EXTINDEX_TO_BLOCKOFFSET[i] * this.getBlockSize();
1170 
1171             num = this.readNumber(
1172                 CRECORD_EXTINDEX_TO_TYPEFIELD[i], extPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[i],
1173                 CRECORD_EXTINDEX_TO_TYPELENGTH[i], ENCODING_ASCII );
1174 
1175             txt = this.readAlphaNumeric(
1176                 CRECORD_EXTINDEX_TO_VALUEFIELD[i], extPos + CRECORD_EXTINDEX_TO_VALUEOFFSET[i],
1177                 CRECORD_EXTINDEX_TO_VALUELENGTH[i], ENCODING_ASCII );
1178 
1179             if ( num.longValue() == 1L )
1180             {
1181                 if ( transaction.getTargetExt() != null )
1182                 {
1183                     if ( ThreadLocalMessages.isErrorsEnabled() )
1184                     {
1185                         throw new CorruptedException(
1186                             this.getImplementation(), extPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[i] );
1187 
1188                     }
1189                     else
1190                     {
1191                         final Message msg = new IllegalDataMessage(
1192                             CRECORD_EXTINDEX_TO_TYPEFIELD[i], IllegalDataMessage.TYPE_CONSTANT,
1193                             extPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[i], num.toString() );
1194 
1195                         ThreadLocalMessages.getMessages().addMessage( msg );
1196                     }
1197                 }
1198                 else
1199                 {
1200                     transaction.setTargetExt( txt );
1201                 }
1202             }
1203             else if ( num.longValue() == 2L )
1204             {
1205                 if ( txt != null )
1206                 {
1207                     desc.add( txt );
1208                 }
1209             }
1210             else if ( num.longValue() == 3L )
1211             {
1212                 if ( transaction.getExecutiveExt() != null )
1213                 {
1214                     if ( ThreadLocalMessages.isErrorsEnabled() )
1215                     {
1216                         throw new CorruptedException(
1217                             this.getImplementation(), extPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[i] );
1218 
1219                     }
1220                     else
1221                     {
1222                         final Message msg = new IllegalDataMessage(
1223                             CRECORD_EXTINDEX_TO_TYPEFIELD[i], IllegalDataMessage.TYPE_CONSTANT,
1224                             extPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[i], num.toString() );
1225 
1226                         ThreadLocalMessages.getMessages().addMessage( msg );
1227                     }
1228                 }
1229                 else
1230                 {
1231                     transaction.setExecutiveExt( txt );
1232                 }
1233             }
1234             else if ( num.longValue() != NO_NUMBER )
1235             {
1236                 if ( ThreadLocalMessages.isErrorsEnabled() )
1237                 {
1238                     throw new CorruptedException(
1239                         this.getImplementation(), extPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[i] );
1240 
1241                 }
1242                 else
1243                 {
1244                     final Message msg = new IllegalDataMessage(
1245                         CRECORD_EXTINDEX_TO_TYPEFIELD[i], IllegalDataMessage.TYPE_CONSTANT,
1246                         extPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[i], num.toString() );
1247 
1248                     ThreadLocalMessages.getMessages().addMessage( msg );
1249                 }
1250             }
1251         }
1252 
1253         transaction.setDescriptions( (AlphaNumericText27[]) desc.toArray( new AlphaNumericText27[ desc.size() ] ) );
1254         return transaction;
1255     }
1256 
1257     protected void writeTransaction( final long position, final Transaction transaction ) throws IOException
1258     {
1259         AlphaNumericText27 txt;
1260         final AlphaNumericText27[] desc = transaction.getDescriptions();
1261         final Textschluessel type = transaction.getType();
1262         int extCount = desc.length > 0 ? desc.length - 1 : 0;
1263 
1264         if ( transaction.getExecutiveExt() != null )
1265         {
1266             extCount++;
1267         }
1268 
1269         if ( transaction.getTargetExt() != null )
1270         {
1271             extCount++;
1272         }
1273 
1274         // Konstanter Teil - 1. Satzabschnitt - Feld 1
1275         this.writeNumber( Fields.FIELD_C1, position + CRECORD_OFFSETS1[0], CRECORD_LENGTH1[0],
1276                           CRECORD_CONST_LENGTH + extCount * CRECORD_EXT_LENGTH, ENCODING_ASCII );
1277 
1278         // Konstanter Teil - 1. Satzabschnitt - Feld 2
1279         this.writeAlphaNumeric( Fields.FIELD_C2, position + CRECORD_OFFSETS1[1], CRECORD_LENGTH1[1], "C",
1280                                 ENCODING_ASCII );
1281 
1282         // Konstanter Teil - 1. Satzabschnitt - Feld 3
1283         this.writeNumber( Fields.FIELD_C3, position + CRECORD_OFFSETS1[2], CRECORD_LENGTH1[2],
1284                           transaction.getPrimaryBank() != null ? transaction.getPrimaryBank().intValue() : 0,
1285                           ENCODING_ASCII );
1286 
1287         // Konstanter Teil - 1. Satzabschnitt - Feld 4
1288         this.writeNumber( Fields.FIELD_C4, position + CRECORD_OFFSETS1[3], CRECORD_LENGTH1[3],
1289                           transaction.getTargetBank().intValue(), ENCODING_ASCII );
1290 
1291         // Konstanter Teil - 1. Satzabschnitt - Feld 5
1292         this.writeNumber( Fields.FIELD_C5, position + CRECORD_OFFSETS1[4], CRECORD_LENGTH1[4],
1293                           transaction.getTargetAccount().longValue(), ENCODING_ASCII );
1294 
1295         // Konstanter Teil - 1. Satzabschnitt - Feld 6
1296         this.writeNumber( Fields.FIELD_C6A, position + CRECORD_OFFSETS1[5] - 1, 1, 0L, ENCODING_ASCII );
1297 
1298         this.writeNumber( Fields.FIELD_C6, position + CRECORD_OFFSETS1[5], CRECORD_LENGTH1[5],
1299                           transaction.getReference() != null ? transaction.getReference().longValue() : 0L,
1300                           ENCODING_ASCII );
1301 
1302         this.writeNumber( Fields.FIELD_C6C, position + CRECORD_OFFSETS1[6] - 1, 1, 0L, ENCODING_ASCII );
1303 
1304         // Konstanter Teil - 1. Satzabschnitt - Felder 7a & 7b
1305         // TODO -3, +/- 2
1306         this.writeNumber( Fields.FIELD_C7A, position + CRECORD_OFFSETS1[6], CRECORD_LENGTH1[6] - 3, type.getKey(),
1307                           ENCODING_ASCII );
1308 
1309         this.writeNumber( Fields.FIELD_C7B, position + CRECORD_OFFSETS1[6] + 2, CRECORD_LENGTH1[6] - 2,
1310                           type.getExtension(), ENCODING_ASCII );
1311 
1312         // Konstanter Teil - 1. Satzabschnitt - Feld 8
1313         this.writeAlphaNumeric( Fields.FIELD_C8, position + CRECORD_OFFSETS1[7], CRECORD_LENGTH1[7], "",
1314                                 ENCODING_ASCII );
1315 
1316         // Konstanter Teil - 1. Satzabschnitt - Feld 9
1317         this.writeNumber( Fields.FIELD_C9, position + CRECORD_OFFSETS1[8], CRECORD_LENGTH1[8], 0L, ENCODING_ASCII );
1318 
1319         // Konstanter Teil - 1. Satzabschnitt - Feld 10
1320         this.writeNumber( Fields.FIELD_C10, position + CRECORD_OFFSETS1[9], CRECORD_LENGTH1[9],
1321                           transaction.getExecutiveBank().intValue(), ENCODING_ASCII );
1322 
1323         // Konstanter Teil - 1. Satzabschnitt - Feld 11
1324         this.writeNumber( Fields.FIELD_C11, position + CRECORD_OFFSETS1[10], CRECORD_LENGTH1[10],
1325                           transaction.getExecutiveAccount().longValue(), ENCODING_ASCII );
1326 
1327         // Konstanter Teil - 1. Satzabschnitt - Feld 12
1328         this.writeNumber( Fields.FIELD_C12, position + CRECORD_OFFSETS1[11], CRECORD_LENGTH1[11],
1329                           transaction.getAmount().longValue(), ENCODING_ASCII ); // TODO longValueExact()
1330 
1331         // Konstanter Teil - 1. Satzabschnitt - Feld 13
1332         this.writeAlphaNumeric( Fields.FIELD_C13, position + CRECORD_OFFSETS1[12], CRECORD_LENGTH1[12], "",
1333                                 ENCODING_ASCII );
1334 
1335         // Konstanter Teil - 1. Satzabschnitt - Feld 14a
1336         this.writeAlphaNumeric( Fields.FIELD_C14A, position + CRECORD_OFFSETS1[13], CRECORD_LENGTH1[13],
1337                                 transaction.getTargetName().format(), ENCODING_ASCII );
1338 
1339         // Konstanter Teil - 1. Satzabschnitt - Feld 14b
1340         this.writeAlphaNumeric( Fields.FIELD_C14B, position + CRECORD_OFFSETS1[14], CRECORD_LENGTH1[14], "",
1341                                 ENCODING_ASCII );
1342 
1343         // Konstanter Teil - 2. Satzabschnitt - Feld 15(1)
1344         this.writeAlphaNumeric( Fields.FIELD_C15, position + this.getBlockSize() + CRECORD_OFFSETS2[0],
1345                                 CRECORD_LENGTH2[0], transaction.getExecutiveName().format(), ENCODING_ASCII );
1346 
1347         // Konstanter Teil - 2. Satzabschnitt - Feld 16(2)
1348         this.writeAlphaNumeric( Fields.FIELD_C16, position + this.getBlockSize() + CRECORD_OFFSETS2[1],
1349                                 CRECORD_LENGTH2[1], desc.length > 0 ? desc[0].format() : "", ENCODING_ASCII );
1350 
1351         // Konstanter Teil - 2. Satzabschnitt - Feld 17a(3)
1352         this.writeAlphaNumeric(
1353             Fields.FIELD_C17A, position + this.getBlockSize() + CRECORD_OFFSETS2[2],
1354             CRECORD_LENGTH2[2], Character.toString( this.getCurrencyMapper().getDtausCode(
1355             transaction.getCurrency(), this.getHeader().getCreateDate() ) ), ENCODING_ASCII );
1356 
1357         // Konstanter Teil - 2. Satzabschnitt - Feld 17b(4)
1358         this.writeAlphaNumeric( Fields.FIELD_C17B, position + this.getBlockSize() + CRECORD_OFFSETS2[3],
1359                                 CRECORD_LENGTH2[3], "", ENCODING_ASCII );
1360 
1361         // Konstanter Teil - 2. Satzabschnitt - Feld 18(5)
1362         this.writeNumber( Fields.FIELD_C18, position + this.getBlockSize() + CRECORD_OFFSETS2[4],
1363                           CRECORD_LENGTH2[4], extCount, ENCODING_ASCII );
1364 
1365         // Erweiterungs-Teile im zweiten Satzabschnitt initialisieren.
1366         this.initializeExtensionBlock( position + this.getBlockSize(), 1 );
1367 
1368         // Erweiterungs-Teile.
1369         int extIndex = 0;
1370         int blockOffset = CRECORD_EXTINDEX_TO_BLOCKOFFSET[extIndex];
1371         int lastBlockOffset = blockOffset;
1372         long blockPos = position + blockOffset * this.getBlockSize();
1373 
1374         // Erweiterung des beteiligten Kontos als ersten Erweiterungsteil.
1375         if ( ( txt = transaction.getTargetExt() ) != null )
1376         {
1377             this.writeNumber(
1378                 CRECORD_EXTINDEX_TO_TYPEFIELD[extIndex], blockPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[extIndex],
1379                 CRECORD_EXTINDEX_TO_TYPELENGTH[extIndex], 1L, ENCODING_ASCII );
1380 
1381             this.writeAlphaNumeric(
1382                 CRECORD_EXTINDEX_TO_VALUEFIELD[extIndex], blockPos + CRECORD_EXTINDEX_TO_VALUEOFFSET[extIndex],
1383                 CRECORD_EXTINDEX_TO_VALUELENGTH[extIndex], txt.format(), ENCODING_ASCII );
1384 
1385             extIndex++;
1386         }
1387 
1388         // Verwendungszweck-Zeilen des 2., 3., 4., 5. und 6. Satzabschnittes.
1389         for ( int i = 1; i < desc.length; i++, extIndex++ )
1390         {
1391             blockOffset = CRECORD_EXTINDEX_TO_BLOCKOFFSET[extIndex];
1392             blockPos = position + blockOffset * this.getBlockSize();
1393 
1394             if ( blockOffset != lastBlockOffset )
1395             {
1396                 // Nächsten Satzabschnitt initialisieren.
1397                 this.initializeExtensionBlock( blockPos, blockOffset );
1398             }
1399 
1400             this.writeNumber( CRECORD_EXTINDEX_TO_TYPEFIELD[extIndex],
1401                               blockPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[extIndex],
1402                               CRECORD_EXTINDEX_TO_TYPELENGTH[extIndex], 2L, ENCODING_ASCII );
1403 
1404             this.writeAlphaNumeric( CRECORD_EXTINDEX_TO_VALUEFIELD[extIndex],
1405                                     blockPos + CRECORD_EXTINDEX_TO_VALUEOFFSET[extIndex],
1406                                     CRECORD_EXTINDEX_TO_VALUELENGTH[extIndex], desc[i].format(), ENCODING_ASCII );
1407 
1408             lastBlockOffset = blockOffset;
1409         }
1410 
1411         // Erweiterung des Auftraggeber-Kontos im letzten Erweiterungsteil.
1412         if ( ( txt = transaction.getExecutiveExt() ) != null )
1413         {
1414             blockOffset = CRECORD_EXTINDEX_TO_BLOCKOFFSET[extIndex];
1415             blockPos = position + blockOffset * this.getBlockSize();
1416 
1417             if ( blockOffset != lastBlockOffset )
1418             {
1419                 // Nächsten Satzabschnitt initialisieren.
1420                 this.initializeExtensionBlock( blockPos, blockOffset );
1421             }
1422 
1423             this.writeNumber(
1424                 CRECORD_EXTINDEX_TO_TYPEFIELD[extIndex], blockPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[extIndex],
1425                 CRECORD_EXTINDEX_TO_TYPELENGTH[extIndex], 3L, ENCODING_ASCII );
1426 
1427             this.writeAlphaNumeric(
1428                 CRECORD_EXTINDEX_TO_VALUEFIELD[extIndex], blockPos + CRECORD_EXTINDEX_TO_VALUEOFFSET[extIndex],
1429                 CRECORD_EXTINDEX_TO_VALUELENGTH[extIndex], txt.format(), ENCODING_ASCII );
1430 
1431             extIndex++;
1432             lastBlockOffset = blockOffset;
1433         }
1434     }
1435 
1436     protected int byteCount( final Transaction transaction )
1437     {
1438         int extCount = transaction.getDescriptions().length > 0 ? transaction.getDescriptions().length - 1 : 0;
1439 
1440         if ( transaction.getExecutiveExt() != null )
1441         {
1442             extCount++;
1443         }
1444         if ( transaction.getTargetExt() != null )
1445         {
1446             extCount++;
1447         }
1448 
1449         return CRECORD_EXTENSIONCOUNT_TO_BLOCKCOUNT[extCount] * this.getBlockSize();
1450     }
1451 
1452     protected int getBlockSize()
1453     {
1454         return PhysicalFileFactory.FORMAT_DISK;
1455     }
1456 
1457     private void initializeExtensionBlock( final long blockPos, final int blockOffset ) throws IOException
1458     {
1459         int extIndex;
1460         int startingExt;
1461         int endingExt;
1462         int reservedField;
1463         int reservedOffset;
1464         int reservedLength;
1465 
1466         if ( blockOffset == 1 )
1467         {
1468             startingExt = 0;
1469             endingExt = 1;
1470             reservedField = Fields.FIELD_C23;
1471             reservedOffset = CRECORD_OFFSETS2[9];
1472             reservedLength = CRECORD_LENGTH2[9];
1473         }
1474         else if ( blockOffset == 2 )
1475         {
1476             startingExt = 2;
1477             endingExt = 5;
1478             reservedField = Fields.FIELD_C32;
1479             reservedOffset = CRECORD_OFFSETS_EXT[8];
1480             reservedLength = CRECORD_LENGTH_EXT[8];
1481         }
1482         else if ( blockOffset == 3 )
1483         {
1484             startingExt = 6;
1485             endingExt = 9;
1486             reservedField = Fields.FIELD_C41;
1487             reservedOffset = CRECORD_OFFSETS_EXT[8];
1488             reservedLength = CRECORD_LENGTH_EXT[8];
1489         }
1490         else if ( blockOffset == 4 )
1491         {
1492             startingExt = 10;
1493             endingExt = 13;
1494             reservedField = Fields.FIELD_C50;
1495             reservedOffset = CRECORD_OFFSETS_EXT[8];
1496             reservedLength = CRECORD_LENGTH_EXT[8];
1497         }
1498         else if ( blockOffset == 5 )
1499         {
1500             startingExt = 14;
1501             endingExt = 17;
1502             reservedField = Fields.FIELD_C59;
1503             reservedOffset = CRECORD_OFFSETS_EXT[8];
1504             reservedLength = CRECORD_LENGTH_EXT[8];
1505         }
1506         else
1507         {
1508             throw new IllegalArgumentException( Integer.toString( blockOffset ) );
1509         }
1510 
1511         // Erweiterungsteile leeren.
1512         for ( extIndex = startingExt; extIndex <= endingExt; extIndex++ )
1513         {
1514             this.writeNumber(
1515                 CRECORD_EXTINDEX_TO_TYPEFIELD[extIndex], blockPos + CRECORD_EXTINDEX_TO_TYPEOFFSET[extIndex],
1516                 CRECORD_EXTINDEX_TO_TYPELENGTH[extIndex], 0L, ENCODING_ASCII );
1517 
1518             this.writeAlphaNumeric(
1519                 CRECORD_EXTINDEX_TO_VALUEFIELD[extIndex], blockPos + CRECORD_EXTINDEX_TO_VALUEOFFSET[extIndex],
1520                 CRECORD_EXTINDEX_TO_VALUELENGTH[extIndex], "", ENCODING_ASCII );
1521 
1522         }
1523 
1524         // Reserve-Feld initialisieren.
1525         this.writeAlphaNumeric( reservedField, blockPos + reservedOffset, reservedLength, "", ENCODING_ASCII );
1526     }
1527 
1528     protected Implementation getImplementation()
1529     {
1530         return ModelFactory.getModel().getModules().
1531             getImplementation( DTAUSDisk.class.getName() );
1532 
1533     }
1534 
1535     //--Dependencies------------------------------------------------------------
1536 
1537 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies
1538     // This section is managed by jdtaus-container-mojo.
1539 
1540     /**
1541      * Gets the configured <code>Logger</code> implementation.
1542      *
1543      * @return The configured <code>Logger</code> implementation.
1544      */
1545     protected Logger getLogger()
1546     {
1547         return (Logger) ContainerFactory.getContainer().
1548             getDependency( this, "Logger" );
1549 
1550     }
1551 
1552 // </editor-fold>//GEN-END:jdtausDependencies
1553 
1554     //------------------------------------------------------------Dependencies--
1555 }