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