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;
020import org.jpos.iso.packager.GenericPackagerParams;
021import org.xml.sax.Attributes;
022
023import java.io.IOException;
024import java.io.InputStream;
025
026public class IFEP_LLLBINARY extends ISOBinaryFieldPackager implements GenericPackagerParams {
027    Integer fieldId = null;
028
029    private static final int TAG_HEADER_LENGTH = 2;
030    private final int prefixerPackedLength;
031
032    public IFEP_LLLBINARY() {
033        super();
034        prefixerPackedLength = 3;
035    }
036
037    public IFEP_LLLBINARY(int length, String description) {
038        super(length, description, LiteralBinaryInterpreter.INSTANCE, EbcdicPrefixer.LLL);
039        checkLength(length, 999);
040        prefixerPackedLength = EbcdicPrefixer.LLL.getPackedLength();
041    }
042
043    public IFEP_LLLBINARY(int length, String description, BinaryInterpreter binaryInterpreter, Prefixer prefixer) {
044        super(length, description, binaryInterpreter, prefixer);
045        checkLength(length, 999);
046        prefixerPackedLength = prefixer.getPackedLength();
047    }
048
049    @Override
050    public void setGenericPackagerParams(Attributes atts) {
051        fieldId = Integer.parseInt(atts.getValue("id"));
052    }
053
054    /**
055     * @param c - a component
056     * @return packed component
057     * @exception ISOException
058     */
059    public byte[] pack (ISOComponent c) throws ISOException {
060        int len = ((byte[]) c.getValue()).length;
061        String key = fieldId != null ? fieldId.toString() : c.getKey().toString();
062        if (len > getLength())
063            throw new ISOException (
064                "invalid len "+len +" packing IFEP_LLLBINARY field "
065                +c.getKey().toString()
066            );
067
068        byte[] b = new byte[len + prefixerPackedLength + TAG_HEADER_LENGTH];
069        byte[] llltt = 
070            ISOUtil.asciiToEbcdic (
071              ISOUtil.zeropad(Integer.toString(len+ TAG_HEADER_LENGTH), prefixerPackedLength)
072              +ISOUtil.zeropad(key, TAG_HEADER_LENGTH));
073
074        System.arraycopy(llltt, 0, b, 0, TAG_HEADER_LENGTH + prefixerPackedLength);
075        System.arraycopy(c.getValue(), 0, b, TAG_HEADER_LENGTH + prefixerPackedLength, len);
076        return b;
077    }
078
079    /**
080     * @param c - the Component to unpack
081     * @param b - binary image
082     * @param offset - starting offset within the binary image
083     * @return consumed bytes
084     * @exception ISOException
085     */
086    public int unpack (ISOComponent c, byte[] b, int offset)
087        throws ISOException
088    {
089        int len = Integer.parseInt(ISOUtil.ebcdicToAscii(b, offset, prefixerPackedLength)) - TAG_HEADER_LENGTH;
090        if (!(c instanceof ISOBinaryField))
091            throw new ISOException 
092                (c.getClass().getName() + " is not an ISOBinaryField");
093
094        c.setFieldNumber (
095            Integer.parseInt(ISOUtil.ebcdicToAscii (b, offset+prefixerPackedLength, TAG_HEADER_LENGTH))
096        );
097        byte[] value = new byte[len];
098        System.arraycopy(b, offset + prefixerPackedLength + TAG_HEADER_LENGTH , value, 0, len);
099        c.setValue (value);
100        return len + prefixerPackedLength + TAG_HEADER_LENGTH;
101    }
102    public void unpack (ISOComponent c, InputStream in) 
103        throws IOException, ISOException
104    {
105
106        if (!(c instanceof ISOField))
107            throw new ISOException 
108                (c.getClass().getName() + " is not an ISOField");
109
110        int len   = Integer.parseInt(ISOUtil.ebcdicToAscii(readBytes (in, prefixerPackedLength))) - TAG_HEADER_LENGTH;
111        int fldno = Integer.parseInt(ISOUtil.ebcdicToAscii(readBytes (in, TAG_HEADER_LENGTH)));
112        c.setFieldNumber (fldno);
113        c.setValue (readBytes(in, len));
114    }
115    public int getMaxPackedLength() {
116        return getLength() + prefixerPackedLength + TAG_HEADER_LENGTH;
117    }
118}