001/*
002 *  jDTAUS Banking RI DTAUS
003 *  Copyright (C) 2005 Christian Schulte
004 *  <cs@schulte.it>
005 *
006 *  This library is free software; you can redistribute it and/or
007 *  modify it under the terms of the GNU Lesser General Public
008 *  License as published by the Free Software Foundation; either
009 *  version 2.1 of the License, or any later version.
010 *
011 *  This library is distributed in the hope that it will be useful,
012 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 *  Lesser General Public License for more details.
015 *
016 *  You should have received a copy of the GNU Lesser General Public
017 *  License along with this library; if not, write to the Free Software
018 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
019 *
020 */
021package org.jdtaus.banking.dtaus.ri.zka;
022
023import java.io.IOException;
024import java.math.BigInteger;
025import java.util.ArrayList;
026import java.util.Calendar;
027import java.util.Currency;
028import java.util.Date;
029import java.util.List;
030import java.util.Locale;
031import org.jdtaus.banking.AlphaNumericText27;
032import org.jdtaus.banking.Bankleitzahl;
033import org.jdtaus.banking.Kontonummer;
034import org.jdtaus.banking.Referenznummer10;
035import org.jdtaus.banking.Referenznummer11;
036import org.jdtaus.banking.Textschluessel;
037import org.jdtaus.banking.dtaus.Checksum;
038import org.jdtaus.banking.dtaus.CorruptedException;
039import org.jdtaus.banking.dtaus.Header;
040import org.jdtaus.banking.dtaus.LogicalFileType;
041import org.jdtaus.banking.dtaus.PhysicalFileFactory;
042import org.jdtaus.banking.dtaus.Transaction;
043import org.jdtaus.banking.dtaus.spi.Fields;
044import org.jdtaus.banking.messages.IllegalDataMessage;
045import org.jdtaus.core.container.ContainerFactory;
046import org.jdtaus.core.container.Implementation;
047import org.jdtaus.core.container.ModelFactory;
048import org.jdtaus.core.logging.spi.Logger;
049import org.jdtaus.core.text.Message;
050
051/**
052 * Anlage 3.1.2 DTAUS: Zahlungsverkehrssammelauftrag Magnetbandformat.
053 *
054 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
055 * @version $JDTAUS: DTAUSTape.java 8817 2013-06-07 19:37:52Z schulte $
056 */
057public final class DTAUSTape extends AbstractLogicalFile
058{
059
060    /**
061     * Index = A Datensatz-Feld - 1,
062     * Wert = Offset relativ zum Anfang des Satzabschnittes.
063     */
064    protected static final int[] ARECORD_OFFSETS =
065    {
066        0, 2, 4, 5, 7, 12, 17, 44, 48, 52, 58, 68, 83, 91, 149
067    };
068
069    /**
070     * Index = A Datensatz-Feld - 1,
071     * Wert = Länge des Feldes in Byte.
072     */
073    protected static final int[] ARECORD_LENGTH =
074    {
075        2, 2, 1, 2, 5, 5, 27, 4, 4, 6, 10, 15, 8, 58, 1
076    };
077
078    /**
079     * Index = E Datensatz-Feld - 1,
080     * Wert = Offset relativ zum Anfang des Satzabschnittes.
081     */
082    protected static final int[] ERECORD_OFFSETS =
083    {
084        0, 2, 4, 5, 10, 14, 21, 30, 39, 46
085    };
086
087    /**
088     * Index = E Datensatz-Feld -1,
089     * Wert = Länge des Feldes in Byte.
090     */
091    protected static final int[] ERECORD_LENGTH =
092    {
093        2, 2, 1, 5, 4, 7, 9, 9, 7, 104
094    };
095
096    /** Länge des konstanten Teiles eines C Datensatzes in Byte. */
097    protected static final int CRECORD_CONST_LENGTH = 150;
098
099    /** 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}