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
021/** Formats tagged-field headers where tag and length can appear in either order. */
022public class IsoFieldHeaderFormatter {
023
024    private boolean tagFirst;
025
026    /** Constructs a formatter.
027     * @param tagFirst if true, the tag field comes before the length
028     */
029    public IsoFieldHeaderFormatter(boolean tagFirst) {
030        this.tagFirst = tagFirst;
031    }
032
033
034    /** Returns whether tag comes before length.
035     * @return true if tag-first ordering
036     */
037    public boolean isTagFirst() {
038        return tagFirst;
039    }
040
041    /**
042     *
043     * Formats tag/length fields according to the configured ordering.
044     * @param tagPrefixer the tag part prefixer
045     * @param lengthPrefixer the length part prefixer
046     * @param tagData byte array containing the tag value bytes
047     * @param lengthData byte array containing the length value bytes
048     * @return byte array containing the header (tag and length), size of returned bytes is just the header length
049     */
050    public byte[] format(final Prefixer tagPrefixer, final Prefixer lengthPrefixer, final byte[] tagData, final byte[] lengthData) {
051        if (tagPrefixer != null && lengthPrefixer != null && tagData != null && lengthData != null) {
052            final byte[] destinationData = new byte[tagPrefixer.getPackedLength() + lengthPrefixer.getPackedLength()];
053            format(tagPrefixer, lengthPrefixer, tagData, lengthData, destinationData);
054            return destinationData;
055        }
056        return null;
057    }
058
059    /** Formats the tag and length prefixers into the output.
060     * @param tagPrefixer    the tag length prefixer
061     * @param lengthPrefixer the data length prefixer
062     * @param tagData        the tag byte array
063     * @param lengthData     the length byte array
064     * @param destinationData the output byte array
065     */
066    public void format(final Prefixer tagPrefixer, final Prefixer lengthPrefixer, final byte[] tagData, final byte[] lengthData, final byte[] destinationData) {
067        if (tagPrefixer != null && lengthPrefixer != null && tagData != null && lengthData != null && destinationData != null) {
068            System.arraycopy(tagData, 0, destinationData, tagFirst ? 0 : lengthPrefixer.getPackedLength(), tagPrefixer.getPackedLength());
069            System.arraycopy(lengthData, 0, destinationData, tagFirst ? tagPrefixer.getPackedLength() : 0, lengthPrefixer.getPackedLength());
070        }
071    }
072
073    /** Returns the index of the tag prefixer relative to length.
074     * @param lengthPrefixer the length prefixer
075     * @return the tag index
076     */
077    public int getTagIndex(Prefixer lengthPrefixer) {
078        return tagFirst ? 0 : lengthPrefixer.getPackedLength();
079    }
080
081    /** Returns the index of the length prefixer relative to tag.
082     * @param tagPrefixer the tag prefixer
083     * @return the length index
084     */
085    public int getLengthIndex(Prefixer tagPrefixer) {
086        return tagFirst ? tagPrefixer.getPackedLength() : 0;
087    }
088
089    /** Formatter with tag before length. */
090    public static IsoFieldHeaderFormatter TAG_FIRST = new IsoFieldHeaderFormatter(true);
091    /** Formatter with length before tag. */
092    public static IsoFieldHeaderFormatter LENGTH_FIRST = new IsoFieldHeaderFormatter(false);
093
094    /**
095     * Returns the total length of tag and length fields.
096     * @param tagPrefixer    the tag prefixer
097     * @param prefixer       the length prefixer
098     * @return total length in bytes
099     */
100    public int getTotalLength(final Prefixer tagPrefixer, final Prefixer prefixer) {
101        if (tagPrefixer == null || prefixer == null) {
102            throw new IllegalArgumentException("Neither tag or length prefixer was provided.");
103        }
104        return tagPrefixer.getPackedLength() + prefixer.getPackedLength();
105    }
106}