001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.iso.header;
020
021import org.jpos.iso.ISOUtil;
022
023/*
024 * BASE1 Header
025 * <pre>
026 *   0 hlen;         Fld  1: Header Length        1B      (Byte     0)
027 *   1 hformat;      Fld  2: Header Format        8N,bit  (Byte     1)
028 *   2 format;       Fld  3: Text Format          1B      (Byte     2)
029 *   3 len[2];       Fld  4: Total Message Length 2B      (Byte  3- 4)
030 *   5 dstId[3];     Fld  5: Destination Id       6N,BCD  (Byte  5- 7)
031 *   8 srcId[3];     Fld  6: Source Id            6N,BCD  (Byte  8-10)
032 *  11 rtCtl;        Fld  7: Round-Trip Ctrl Info 8N,bit  (Byte    11)
033 *  12 flags[2];     Fld  8: BASE I Flags        16N,bit  (Byte 12-13)
034 *  14 status[3];    Fld  9: Message Status Flags 24bits  (Byte 14-16)
035 *  17 batchNbr;     Fld 10: Batch Number        1B       (Byte    17)
036 *  18 reserved[3];  Fld 11: Reserved            3B       (Byte 18-20)
037 *  21 userInfo;     Fld 12: User Info           1B       (Byte    21)
038 *  The following fields are only presend in a reject message
039 *  22 bitmap;       Fld 13: Bitmap              2B       (Byte 22-23)
040 *  24 rejectdata;   Fld 14: Reject Data Group   2B       (Byte 24-25)
041 * </pre>
042 *
043 */
044public class BASE1Header extends BaseHeader {
045
046    private static final long serialVersionUID = 6466427524726021374L;
047    public static final int LENGTH = 22;
048
049    public BASE1Header() {
050        this("000000", "000000");
051    }
052    public BASE1Header(String source, String destination) {
053        super();
054        header = new byte[LENGTH];
055        header[0] = LENGTH; // hlen
056        setHFormat(1);
057        setFormat(2);
058        setSource(source);
059        setDestination(destination);
060    }
061    public BASE1Header(String source, String destination, int format) {
062        super();
063        header = new byte[LENGTH];
064        header[0] = LENGTH; // hlen
065        setHFormat(1);
066        setFormat(format);
067        setSource(source);
068        setDestination(destination);
069    }
070    public BASE1Header(byte[] header) {
071        super(header);
072    }
073
074    public int getHLen() {
075        return header[0] & 0xFF;
076    }
077    public void setHFormat(int hformat) {
078        header[1] = (byte) hformat;
079    }
080    public int getFormat() {
081        return header[2] & 0xFF;
082    }
083    public void setRtCtl(int i) {
084        header[11] = (byte) i;
085    }
086    public void setFlags(int i) {
087        header[12] = (byte) (i >> 8 & 0xFF);
088        header[13] = (byte) (i & 0xFF);
089    }
090    public void setStatus(int i) {
091        header[14] = (byte) (i >> 16 & 0xFF);
092        header[15] = (byte) (i >> 8 & 0xFF);
093        header[16] = (byte) (i & 0xFF);
094    }
095    public void setBatchNumber(int i) {
096        header[17] = (byte) (i & 0xFF);
097    }
098    public void setFormat(int format) {
099        header[2] = (byte) format;
100    }
101    public void setLen(int len) {
102        len += header.length;
103        header[3]  = (byte) (len >> 8 & 0xff);
104        header[4]  = (byte) (len        & 0xff);
105    }
106    public void setDestination(String dest) {
107        byte[] d = ISOUtil.str2bcd(dest, true);
108        System.arraycopy(d, 0, header, 5, 3);
109    }
110    public void setSource(String src) {
111        byte[] d = ISOUtil.str2bcd(src, true);
112        System.arraycopy(d, 0, header, 8, 3);
113    }
114    public String getSource() {
115        return ISOUtil.bcd2str (this.header, 8, 6, false);
116    }
117    public String getDestination() {
118        return ISOUtil.bcd2str (this.header, 5, 6, false);
119    }
120    public void swapDirection() {
121        if (header != null && header.length >= LENGTH) {
122            byte[] source = new byte[3];
123            System.arraycopy(header, 8, source, 0, 3);
124            System.arraycopy(header, 5, header, 8, 3);
125            System.arraycopy(source, 0, header, 5, 3);
126        }
127    }
128    public boolean isRejected() {
129        // Header length must be 26 or gerater
130        // And header field 13 bit 1 must be 1 (field 13 starts at byte 22)
131        return getLength() >= 26 && (header[22] & 0x80) == 0x80;
132    }
133        
134    /**
135     * Gets the BASE 1 Reject Code.
136     * 
137     * @return If the message is a reject return the Reject Code Otherwise return "" 
138     */ 
139    public String getRejectCode() {
140        return isRejected() ? ISOUtil.bcd2str (this.header, 24, 4, false) : "";
141    }
142
143    /*
144     * parse header contributed by santhoshvee@yahoo.co.uk in jpos-dev mailing list
145     */
146    public String formatHeader() {
147        String h = ISOUtil.hexString(this.header);
148        String lf = System.getProperty("line.separator");
149        StringBuffer d = new StringBuffer();
150        d.append(lf);
151        d.append("[H 01] Header length         "); d.append(h.substring(0, 2));   d.append(lf);
152        d.append("[H 02] Header format         "); d.append(h.substring(2, 4));   d.append(lf);
153        d.append("[H 03] Text format           "); d.append(h.substring(4, 6));   d.append(lf);
154        d.append("[H 04] Total length          "); d.append(h.substring(6, 10));  d.append(lf);
155        d.append("[H 05] Destination ID        "); d.append(h.substring(10, 16)); d.append(lf);
156        d.append("[H 06] Source ID             "); d.append(h.substring(16, 22)); d.append(lf);
157        d.append("[H 07] Round-trip ctrl info  "); d.append(h.substring(22, 24)); d.append(lf);
158        d.append("[H 08] BASE I flags          "); d.append(h.substring(24, 28)); d.append(lf);
159        d.append("[H 09] Message status flags  "); d.append(h.substring(28, 34)); d.append(lf);
160        d.append("[H 10] Batch number          "); d.append(h.substring(34, 36)); d.append(lf);
161        d.append("[H 11] Reserved              "); d.append(h.substring(36, 42)); d.append(lf);
162        d.append("[H 12] User info             "); d.append(h.substring(42, 44)); d.append(lf);
163        if (isRejected()) {
164            d.append("[H 13] Bitmap                "); d.append(h.substring(44, 48)); d.append(lf);
165            d.append("[H 14] Reject data group     "); d.append(h.substring(48, 52)); d.append(lf);
166            d.append("Original header              "); d.append(h.substring(52)); d.append(lf);
167        }
168        return d.toString();
169    }
170}