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.iso.packager.XMLPackager;
022
023import java.io.*;
024
025/**
026 * implements <b>Leaf</b> for binary fields
027 *
028 * See the
029 * <a href="API_users_guide.html">API User's Guide</a>
030 * for details.
031 *
032 * @author apr@cs.com.uy
033 * @version $Id$
034 * @see ISOComponent
035 */
036public class ISOBinaryField 
037    extends ISOComponent 
038    implements Cloneable, Externalizable
039{
040
041    private static final long serialVersionUID = 7702505828876640372L;
042    protected int fieldNumber;
043    protected byte[] value;
044
045    /**
046     * No args constructor 
047     * <font size="-1">(required by Externalizable support on ISOMsg)</font>
048     */
049    public ISOBinaryField () {
050        fieldNumber = -1;
051    }
052    /**
053     * @param n - the FieldNumber
054     */
055    public ISOBinaryField(int n) {
056        fieldNumber = n;
057    }
058    /**
059     * @param n - fieldNumber
060     * @param v - fieldValue
061     */
062    public ISOBinaryField(int n, byte[] v) {
063        fieldNumber = n;
064        value = v;
065    }
066    /**
067     * @param n - fieldNumber
068     * @param v - fieldValue
069     * @param offset - starting offset
070     * @param len    - field length
071     */
072    public ISOBinaryField(int n, byte[] v, int offset, int len) {
073        byte[] b = new byte[len];
074        System.arraycopy (v, offset, b, 0, len);
075        fieldNumber = n;
076        value = b;
077    }
078    /**
079     * changes this Component field number<br>
080     * Use with care, this method does not change
081     * any reference held by a Composite.
082     * @param fieldNumber new field number
083     */
084    public void setFieldNumber (int fieldNumber) {
085        this.fieldNumber = fieldNumber;
086    }
087
088    @Override
089    public int getFieldNumber () {
090        return fieldNumber;
091    }
092
093    /**
094     * not available on Leaf - always throw ISOException
095     * @exception ISOException
096     */
097    public byte[] pack() throws ISOException {
098        throw new ISOException ("Not available on Leaf");
099    }
100    /**
101     * not available on Leaf - always throw ISOException
102     * @exception ISOException
103     */
104    public int unpack(byte[] b) throws ISOException {
105        throw new ISOException ("Not available on Leaf");
106    }
107    /**
108     * not available on Leaf - always throw ISOException
109     * @exception ISOException
110     */
111    public void unpack(InputStream in) throws ISOException {
112        throw new ISOException ("Not available on Leaf");
113    }
114    /**
115     * @return Object representing this field number
116     */
117    public Object getKey() {
118        return fieldNumber;
119    }
120    /**
121     * @return Object representing this field value
122     */
123    public Object getValue() {
124        return value;
125    }
126    /**
127     * @param obj - Object representing this field value
128     * @exception ISOException
129     */
130    public void setValue (Object obj) throws ISOException {
131        if (obj instanceof String)
132            value = ((String) obj).getBytes(ISOUtil.CHARSET);
133        else
134            value = (byte[]) obj;
135    }
136    /**
137     * @return byte[] representing this field
138     */
139    public byte[] getBytes() {
140        return value;
141    }
142    /**
143     * dump this field to PrintStream. The output is sorta
144     * XML, intended to be easily parsed.
145     * @param p - print stream
146     * @param indent - optional indent string
147     */
148    public void dump (PrintStream p, String indent) {
149        p.println (indent +"<"+XMLPackager.ISOFIELD_TAG + " " +
150            XMLPackager.ID_ATTR +"=\"" +fieldNumber +"\" "+
151            XMLPackager.VALUE_ATTR +"=\"" +this.toString() + "\" " +
152            XMLPackager.TYPE_ATTR +"=\"" + XMLPackager.TYPE_BINARY + "\"/>"
153        );
154    }
155    public String toString() {
156        return ISOUtil.hexString(value);
157    }
158    public void writeExternal (ObjectOutput out) throws IOException {
159        out.writeShort (fieldNumber);
160        out.writeShort (value.length);
161        out.write (value);
162    }
163    public void readExternal  (ObjectInput in) 
164        throws IOException, ClassNotFoundException
165    {
166        fieldNumber = in.readShort ();
167        value = new byte[in.readShort()];
168        in.readFully (value);
169    }
170}