| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.validator.routines; |
| |
| import java.io.Serializable; |
| import java.util.Arrays; |
| import java.util.Locale; |
| |
| import org.apache.commons.validator.routines.checkdigit.ISINCheckDigit; |
| |
| /** |
| * <b>ISIN</b> (International Securities Identifying Number) validation. |
| * |
| * <p> |
| * ISIN Numbers are 12 character alphanumeric codes used to identify Securities. |
| * </p> |
| * |
| * <p> |
| * ISINs consist of two alphabetic characters, |
| * which are the ISO 3166-1 alpha-2 code for the issuing country, |
| * nine alpha-numeric characters (the National Securities Identifying Number, or NSIN, which identifies the security), |
| * and one numerical check digit. |
| * They are 12 characters in length. |
| * </p> |
| * |
| * <p> |
| * See <a href="https://en.wikipedia.org/wiki/ISIN">Wikipedia - ISIN</a> |
| * for more details. |
| * </p> |
| * |
| * @since 1.7 |
| */ |
| public class ISINValidator implements Serializable { |
| |
| private static final long serialVersionUID = -5964391439144260936L; |
| |
| private static final String ISIN_REGEX = "([A-Z]{2}[A-Z0-9]{9}[0-9])"; |
| |
| private static final CodeValidator VALIDATOR = new CodeValidator(ISIN_REGEX, 12, ISINCheckDigit.ISIN_CHECK_DIGIT); |
| |
| /** ISIN Code Validator (no countryCode check) */ |
| private static final ISINValidator ISIN_VALIDATOR_FALSE = new ISINValidator(false); |
| |
| /** ISIN Code Validator (with countryCode check) */ |
| private static final ISINValidator ISIN_VALIDATOR_TRUE = new ISINValidator(true); |
| |
| private static final String [] CCODES = Locale.getISOCountries(); |
| |
| private static final String [] SPECIALS = { |
| "EZ", // http://www.anna-web.org/standards/isin-iso-6166/ |
| "XS", // https://www.isin.org/isin/ |
| }; |
| |
| static { |
| Arrays.sort(CCODES); // we cannot assume the codes are sorted |
| Arrays.sort(SPECIALS); // Just in case ... |
| } |
| |
| /** |
| * Gets the singleton instance of the ISIN validator. |
| * |
| * @param checkCountryCode whether to check the country-code prefix or not |
| * @return A singleton instance of the appropriate ISIN validator. |
| */ |
| public static ISINValidator getInstance(final boolean checkCountryCode) { |
| return checkCountryCode ? ISIN_VALIDATOR_TRUE : ISIN_VALIDATOR_FALSE; |
| } |
| |
| private final boolean checkCountryCode; |
| |
| private ISINValidator(final boolean checkCountryCode) { |
| this.checkCountryCode = checkCountryCode; |
| } |
| |
| private boolean checkCode(final String code) { |
| return Arrays.binarySearch(CCODES, code) >= 0 |
| || |
| Arrays.binarySearch(SPECIALS, code) >= 0 |
| ; |
| } |
| |
| /** |
| * Tests whether the code is a valid ISIN code after any transformation |
| * by the validate routine. |
| * |
| * @param code The code to validate. |
| * @return {@code true} if a valid ISIN |
| * code, otherwise {@code false}. |
| */ |
| public boolean isValid(final String code) { |
| final boolean valid = VALIDATOR.isValid(code); |
| if (valid && checkCountryCode) { |
| return checkCode(code.substring(0,2)); |
| } |
| return valid; |
| } |
| |
| /** |
| * Checks the code is valid ISIN code. |
| * |
| * @param code The code to validate. |
| * @return A valid ISIN code if valid, otherwise {@code null}. |
| */ |
| public Object validate(final String code) { |
| final Object validate = VALIDATOR.validate(code); |
| if (validate != null && checkCountryCode) { |
| return checkCode(code.substring(0,2)) ? validate : null; |
| } |
| return validate; |
| } |
| |
| } |