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;
023import java.io.OutputStream;
024import java.io.PrintStream;
025import java.util.Collections;
026import java.util.Map;
027
028/**
029 * implements a <b>Component</b>
030 * within a <b>Composite pattern</b>
031 *
032 * See 
033 * <a href="/doc/javadoc/overview-summary.html">Overview</a> for details.
034 *
035 * @author apr@cs.com.uy
036 * @version $Id$
037 * @see ISOMsg
038 * @see ISOField
039 * @see ISOException
040 */
041public abstract class ISOComponent implements Cloneable {
042    /** Default constructor; no instance state to initialise. */
043    protected ISOComponent() {}
044    /**
045     * Set a field within this message
046     * @param c - a component
047     * @exception ISOException always thrown by leaves; composites override this
048     */
049    public void set (ISOComponent c) throws ISOException {
050        throw new ISOException ("Can't add to Leaf");
051    }
052    /**
053     * Unset a field
054     * @param fldno - the field number
055     * @exception ISOException always thrown by leaves; composites override this
056     */
057    public void unset (int fldno) throws ISOException {
058        throw new ISOException ("Can't remove from Leaf");
059    }
060    /**
061     * In order to interchange <b>Composites</b> and <b>Leafs</b> we use
062     * getComposite(). A <b>Composite component</b> returns itself and
063     * a Leaf returns null. The base class ISOComponent provides
064     * <b>Leaf</b> functionality.
065     *
066     * @return ISOComponent
067     */
068    public ISOComponent getComposite() {
069        return null;
070    }
071    /**
072     * valid on Leafs only.
073     * The value returned is used by ISOMsg as a key
074     * to this field.
075     *
076     * @return object representing the field number
077     * @exception ISOException thrown by composites; leaves return their key
078     */
079    public Object getKey() throws ISOException {
080        throw new ISOException ("N/A in Composite");
081    }
082    /**
083     * valid on Leafs only.
084     * @return object representing the field value
085     * @exception ISOException thrown by composites; leaves return their value
086     */
087    public Object getValue() throws ISOException {
088        throw new ISOException ("N/A in Composite");
089    }
090    /**
091     * get Value as bytes (when possible)
092     * @return byte[] representing this field
093     * @exception ISOException thrown by composites or when the value cannot be rendered as bytes
094     */
095    public byte[] getBytes() throws ISOException {
096        throw new ISOException ("N/A in Composite");
097    }
098    /**
099     * a Composite must override this function
100     * @return the max field number associated with this message
101     */
102    public int getMaxField() {
103        return 0;
104    }
105    /**
106     * dummy behaviour - return empty map
107     * @return children (in this case 0 children)
108     */
109    public Map getChildren() {
110        return Collections.emptyMap();
111    }
112    /**
113     * changes this Component field number<br>
114     * Use with care, this method does not change
115     * any reference held by a Composite.
116     * @param fieldNumber new field number
117     */
118    public abstract void setFieldNumber (int fieldNumber);
119    /**
120     * Returns the field number this component occupies within its container.
121     *
122     * @return the field number
123     */
124    public abstract int getFieldNumber ();
125    /**
126     * Sets the value of this component.
127     *
128     * @param obj new value
129     * @throws ISOException if the value is rejected by the component implementation
130     */
131    public abstract void setValue(Object obj) throws ISOException;
132    /**
133     * Packs this component into its on-wire byte representation.
134     *
135     * @return packed bytes
136     * @throws ISOException if packing fails
137     */
138    public abstract byte[] pack() throws ISOException;
139    /**
140     * Unpacks this component from {@code b} starting at offset 0.
141     *
142     * @param b packed bytes
143     * @return number of bytes consumed
144     * @throws ISOException if unpacking fails
145     */
146    public abstract int unpack(byte[] b) throws ISOException;
147    /**
148     * Writes a human-readable dump of this component for diagnostics.
149     *
150     * @param p destination stream
151     * @param indent prefix to apply to every emitted line
152     */
153    public abstract void dump (PrintStream p, String indent);
154    /**
155     * Packs this component and writes it to {@code out}.
156     *
157     * @param out destination stream
158     * @throws IOException if writing fails
159     * @throws ISOException if packing fails
160     */
161    public void pack (OutputStream out) throws IOException, ISOException {
162        out.write (pack ());
163    }
164    /**
165     * Unpacks this component by reading from {@code in}.
166     *
167     * @param in source stream
168     * @throws IOException if reading fails
169     * @throws ISOException if unpacking fails
170     */
171    public abstract void unpack (InputStream in) throws IOException, ISOException;
172}