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/**
022 * Base class for fixed-byte flag fields (e.g. POS data codes), exposing a
023 * shared {@link #setFlags(boolean, Flag...)} helper that toggles bits within
024 * a packed byte buffer.
025 */
026@SuppressWarnings("unused")
027public abstract class PosFlags {
028    /** Default constructor; no instance state to initialise. */
029    protected PosFlags() {}
030
031    /** Single flag identified by its byte offset and bit-mask within {@link #getBytes()}. */
032    public interface Flag {
033        /**
034         * Returns the byte offset within {@link #getBytes()} where this flag's mask starts.
035         *
036         * @return byte offset
037         */
038        int getOffset();
039        /**
040         * Returns the multi-byte bit mask for this flag (low byte applied at {@link #getOffset()}).
041         *
042         * @return bit mask as a packed integer
043         */
044        int intValue();
045    }
046
047    /**
048     * Sets or unsets a set of flags according to value
049     * @param value if true flags are set, else unset
050     * @param flags flag set to set or unset
051     */
052    protected void setFlags(boolean value, Flag... flags) {
053        byte[] b = getBytes();
054        if (value) {
055            for (Flag flag  : flags) {
056                for (int v = flag.intValue(), offset = flag.getOffset(); v != 0; v >>>= 8, offset++) {
057                    if (offset < b.length)
058                        b[offset] |= (byte) v;
059                }
060            }
061        } else {
062            for (Flag flag  : flags) {
063                for (int v = flag.intValue(), offset = flag.getOffset(); v != 0; v >>>= 8, offset++) {
064                    if (offset < b.length)
065                        b[offset] &= (byte) ~v;
066                }
067            }
068        }
069    }
070    /**
071     * Returns the underlying byte buffer holding the packed flags.
072     *
073     * @return live byte array (callers may modify it)
074     */
075    public abstract byte[] getBytes();
076
077    public String toString() {
078        return super.toString() + "[" + ISOUtil.hexString (getBytes())+ "]";
079    }
080}