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 org.jpos.util.FSDMsg;
022import org.jdom2.JDOMException;
023
024import java.io.*;
025import java.util.Iterator;
026import java.util.Map;
027import java.util.concurrent.locks.Lock;
028import java.util.concurrent.locks.ReentrantLock;
029
030/** An ISOMsg backed by a {@link org.jpos.util.FSDMsg} for fixed-schema message processing. */
031public class FSDISOMsg extends ISOMsg implements Cloneable  {
032    /** The underlying FSDMsg containing the field data. */
033    FSDMsg fsd;
034    Lock isLock = new ReentrantLock();
035    /** Default constructor. */
036    public  FSDISOMsg () {
037        super();
038    }
039    /**
040     * Creates an FSDISOMsg wrapping the given FSDMsg.
041     * @param fsd the FSDMsg to wrap
042     */
043    public FSDISOMsg (FSDMsg fsd) {
044        super();
045        this.fsd = fsd;
046    }
047    public String getMTI() {
048        return getString(0);
049    }
050    public byte[] pack() throws ISOException {
051        try {
052            return fsd.packToBytes();
053        } catch (Exception e) {
054            throw new ISOException (e);
055        }
056    }
057    public int unpack(byte[] b) throws ISOException {
058        try {
059            fsd.unpack (b);
060            return b.length;
061        } catch (Exception e) {
062            throw new ISOException (e);
063        }
064    }
065    public void unpack (InputStream in) throws IOException, ISOException {
066        isLock.lock();
067        try {
068            fsd.unpack(in);
069        } catch (JDOMException e) {
070            throw new ISOException (e);
071        } finally {
072            isLock.unlock();
073        }
074    }
075
076    /**
077     * Returns the underlying FSDMsg instance.
078     * @return the underlying FSDMsg
079     */
080    public FSDMsg getFSDMsg() {
081        return fsd;
082    }
083    public String getString (int fldno) {
084        return fsd.get (Integer.toString(fldno));
085    }
086    public String getString (String fld) {
087        return fsd.get (fld);
088    }
089    public boolean hasField (int fldno) {
090        return getString(fldno) != null;
091    }
092    public boolean hasField (String fld) {
093        return getString(fld) != null;
094    }
095    public void dump (PrintStream p, String indent) {
096        if (fsd != null)
097            fsd.dump (p, indent);
098    }
099    public void writeExternal (ObjectOutput out) throws IOException {
100        out.writeByte (0);  // reserved for future expansion (version id)
101        out.writeUTF (fsd.getBasePath());
102        out.writeUTF (fsd.getBaseSchema());
103        out.writeObject (fsd.getMap());
104    }
105    public void readExternal  (ObjectInput in) 
106        throws IOException, ClassNotFoundException
107    {
108        in.readByte();  // ignore version for now
109        String basePath = in.readUTF();
110        String baseSchema = in.readUTF();
111        fsd = new FSDMsg (basePath, baseSchema);
112        Map map = (Map) in.readObject();
113        Iterator iter = map.entrySet().iterator();
114        while (iter.hasNext()) {
115            Map.Entry entry = (Map.Entry) iter.next();
116            fsd.set ((String) entry.getKey(), (String) entry.getValue());
117        }
118    }
119    public Object clone() {
120        FSDISOMsg m = (FSDISOMsg) super.clone();
121        m.fsd = (FSDMsg) fsd.clone();
122        return m;
123    }
124    public Object clone(int[] fields) {
125        FSDISOMsg m = (FSDISOMsg) super.clone();
126        m.fsd = new FSDMsg(fsd.getBasePath(), fsd.getBaseSchema());
127        for (int field : fields) {
128            String f = Integer.toString(field);
129            m.fsd.set(f, fsd.get(f));
130        }
131        return m;
132    }
133    public void merge (ISOMsg m) {
134        if (m instanceof FSDISOMsg) {
135            fsd.merge (((FSDISOMsg)m).getFSDMsg());
136        } else {
137            for (int i=0; i<=m.getMaxField(); i++) {
138                if (m.hasField(i))
139                    fsd.set (Integer.toString(i), m.getString(i));
140            }
141        }
142    }
143    public void setResponseMTI() {
144        try {
145            super.setResponseMTI();
146        } catch (ISOException ignored) { }               
147    }
148    public void set (String name, String value) {
149        if (value != null)
150            this.fsd.set (name, value);
151    }   
152    private static final long serialVersionUID = 1L;
153}
154