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