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;
020
021import java.io.IOException;
022import java.io.InputStream;
023
024/**
025 * ISOMsgFieldPackager is a packager able to pack compound ISOMsgs
026 * (one message inside another one, and so on...)
027 *
028 * @author apr@cs.com.uy
029 * @version $Id$
030 * @see org.jpos.iso.packager.PostPackager
031 */
032public class ISOMsgFieldPackager extends ISOFieldPackager {
033    protected ISOPackager msgPackager;
034    protected ISOFieldPackager fieldPackager;
035
036    /**
037     * @param fieldPackager low level field packager
038     * @param msgPackager ISOMsgField default packager
039     */
040    public ISOMsgFieldPackager (
041            ISOFieldPackager fieldPackager,
042            ISOPackager msgPackager)
043    {
044        super(fieldPackager.getLength(), fieldPackager.getDescription());
045        this.msgPackager = msgPackager;
046        this.fieldPackager = fieldPackager;
047    }
048    /**
049     * @param c - a component
050     * @return packed component
051     * @exception ISOException
052     */
053    @Override
054    public byte[] pack (ISOComponent c) throws ISOException {
055        if (c instanceof ISOMsg) {
056            ISOMsg m = (ISOMsg) c;
057            m.recalcBitMap();
058
059            // honor ISOMsg's current position in hierarchy
060            int mfn = m.getFieldNumber() >= 0 ? m.getFieldNumber() : 0;
061            ISOBinaryField f = new ISOBinaryField(mfn, msgPackager.pack(m));
062
063            if (msgPackager instanceof ISOSubFieldPackager) {
064                ISOSubFieldPackager sfp = (ISOSubFieldPackager) msgPackager;
065
066                // If this ISOMsg needs to be packed as part of some non-bitmapped tagged format
067                // (not all types covered here), or if the ISOSubFieldPackager has been configured
068                // with a specific field number, overriding the one in the ISOMsg.
069                if (fieldPackager instanceof TaggedFieldPackagerBase    ||
070                    fieldPackager instanceof TaggedFieldPackager        ||
071                    fieldPackager instanceof ISOTagStringFieldPackager  ||
072                    fieldPackager instanceof ISOTagBinaryFieldPackager  ||
073                    sfp.getFieldNumber() > -1)
074                {
075                    f.setFieldNumber(sfp.getFieldNumber());
076                }
077            }
078
079            return fieldPackager.pack(f);
080        }
081        return fieldPackager.pack(c);
082    }
083
084    /**
085     * @param c - the Component to unpack
086     * @param b - binary image
087     * @param offset - starting offset within the binary image
088     * @return consumed bytes
089     * @exception ISOException
090     */
091    @Override
092    public int unpack (ISOComponent c, byte[] b, int offset)
093        throws ISOException
094    {
095        ISOBinaryField f = new ISOBinaryField(0);
096        if(msgPackager instanceof ISOSubFieldPackager) {
097            ISOSubFieldPackager sfp = (ISOSubFieldPackager) msgPackager;
098            f.setFieldNumber(sfp.getFieldNumber());
099        }
100        int consumed = fieldPackager.unpack(f, b, offset);
101        if (f.getValue() != null && c instanceof ISOMsg)
102            msgPackager.unpack(c, (byte[]) f.getValue());
103        return consumed;
104    }
105
106    /**
107     * @param c  - the Component to unpack
108     * @param in - input stream
109     * @throws org.jpos.iso.ISOException
110     * @throws java.io.IOException
111     */
112    @Override
113    public void unpack (ISOComponent c, InputStream in)
114        throws IOException, ISOException
115    {
116        ISOBinaryField f = new ISOBinaryField(0);
117        if(msgPackager instanceof ISOSubFieldPackager) {
118            ISOSubFieldPackager sfp = (ISOSubFieldPackager) msgPackager;
119            f.setFieldNumber(sfp.getFieldNumber());
120        }
121        fieldPackager.unpack (f, in);
122        if (f.getValue() != null && c instanceof ISOMsg)
123            msgPackager.unpack(c, (byte[]) f.getValue());
124    }
125
126    @Override
127    public ISOComponent createComponent(int fieldNumber) {
128        ISOMsg m = new ISOMsg(fieldNumber);
129        m.setPackager(msgPackager);
130        return m;
131    }
132
133    @Override
134    public int getMaxPackedLength() {
135        return fieldPackager.getLength();
136    }
137    public ISOPackager getISOMsgPackager() {
138        return msgPackager;
139    }
140    public ISOFieldPackager getISOFieldPackager() {
141        return fieldPackager;
142    }
143}