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.util.Objects;
022
023/**
024 * Implements a parser for card's service code as per ISO/IEC 7813:2006(E).
025 * 
026 * @version $Revision$ $Date$
027 */
028public class ServiceCode {
029
030    final private char[] value;
031   
032    /**
033     * Creates a ServiceCode instance.
034     * 
035     * @param value Three-digit service code value.
036     */
037    public ServiceCode(String value) {
038
039        Objects.requireNonNull(value);
040
041        if (!value.matches("^\\d{3}$")) {
042            throw new IllegalArgumentException("Invalid service code.");
043        }
044
045        this.value = value.toCharArray();
046    }
047
048    /**
049     * Indicates whether the first digit signals private interchange (digit 7).
050     *
051     * @return {@code true} if the first digit is {@code '7'}
052     */
053    public boolean isPrivate() {
054        return value[0] == '7';
055    }
056
057    /**
058     * Indicates whether the first digit signals test (digit 9).
059     *
060     * @return {@code true} if the first digit is {@code '9'}
061     */
062    public boolean isTest() {
063        return value[0] == '9';
064    }
065
066    /**
067     * Indicates whether the first digit signals an ICC-capable card (digits 2, 6).
068     *
069     * @return {@code true} if the first digit is {@code '2'} or {@code '6'}
070     */
071    public boolean isICC() {
072        return value[0] == '2' || value[0] == '6';
073    }
074
075    /**
076     * Indicates whether the first digit signals international interchange (digits 1, 2).
077     *
078     * @return {@code true} if the first digit is {@code '1'} or {@code '2'}
079     */
080    public boolean isInternational() {
081        return value[0] == '1' || value[0] == '2';
082    }
083
084    /**
085     * Indicates whether the first digit signals national interchange (digits 5, 6).
086     *
087     * @return {@code true} if the first digit is {@code '5'} or {@code '6'}
088     */
089    public boolean isNational() {
090        return value[0] == '5' || value[0] == '6';
091    }
092
093    /**
094     * Indicates whether the third digit allows transactions with no restrictions (digits 0, 1, 6).
095     *
096     * @return {@code true} when no service restrictions apply
097     */
098    public boolean hasNoRestrictions() {
099        return value[2] == '0' || value[2] == '1' || value[2] == '6';
100    }
101
102    /**
103     * Indicates whether the third digit restricts use to goods and services (digits 2, 5, 7).
104     *
105     * @return {@code true} for goods-and-services-only service codes
106     */
107    public boolean isGoodsAndServicesOnly() {
108        return value[2] == '2' || value[2] == '5' || value[2] == '7';
109    }
110
111    /**
112     * Indicates whether the third digit restricts use to ATMs (digit 3).
113     *
114     * @return {@code true} for ATM-only service codes
115     */
116    public boolean isATMOnly() {
117        return value[2] == '3';
118    }
119
120    /**
121     * Indicates whether the third digit restricts use to cash transactions (digit 4).
122     *
123     * @return {@code true} for cash-only service codes
124     */
125    public boolean isCashOnly() {
126        return value[2] == '4';
127    }
128
129    /**
130     * Indicates whether a PIN is required for transactions with this service code.
131     *
132     * @return {@code true} when the third digit is {@code '0'}, {@code '3'}, or {@code '5'}
133     */
134    public boolean isPINRequired() {
135        return value[2] == '0' || value[2] == '3' || value[2] == '5';
136    }
137
138    /**
139     * Indicates whether the cardholder must be prompted for a PIN when a PED is available.
140     *
141     * @return {@code true} when the third digit is {@code '6'} or {@code '7'}
142     */
143    public boolean mustPromptForPINIfPEDPresent() {
144        return value[2] == '6' || value[2] == '7';
145    }
146
147    /**
148     * Indicates whether the second digit signals normal authorization processing (digit 0).
149     *
150     * @return {@code true} for normal authorization
151     */
152    public boolean isNormalAuthorization() {
153        return value[1] == '0';
154    }
155
156    /**
157     * Indicates whether the second digit signals issuer authorization is required (digit 2).
158     *
159     * @return {@code true} when issuer authorization is required
160     */
161    public boolean isIssuerAuthorization() {
162        return value[1] == '2';
163    }
164}