001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package org.gbif.api.util.validators.identifierschemes; 015 016import java.util.regex.Pattern; 017 018/** 019 * Util class that generates a validates Mod11,2 checksums. 020 */ 021public abstract class Mod112 { 022 023 private static final Pattern NORMALIZE_PATTERN = Pattern.compile("-|\\s+"); 024 025 /** 026 * Private constructor. 027 */ 028 private Mod112() { 029 //do nothing 030 } 031 032 /** 033 * Validates that value contains an valid checksum digit according to ISO 7064 11,2. 034 */ 035 static boolean hasValidChecksumDigit(String value) { 036 String normalized = NORMALIZE_PATTERN.matcher(value).replaceAll(""); 037 return normalized.charAt(normalized.length() - 1) == 038 generateChecksumDigit(normalized.substring(0, normalized.length() - 1)); 039 } 040 041 /** 042 * Generates check digit as per ISO 7064 11,2. 043 * 044 */ 045 static char generateChecksumDigit(String baseDigits) { 046 int total = 0; 047 for (int i = 0; i < baseDigits.length(); i++) { 048 int digit = Character.getNumericValue(baseDigits.charAt(i)); 049 total = (total + digit) << 1; 050 } 051 int remainder = total % 11; 052 int result = (12 - remainder) % 11; 053 return result == 10 ? 'X' : Character.forDigit(result, 10); 054 } 055 056 public abstract boolean isValid(String value); 057 058 public String normalize(String value) { 059 return NORMALIZE_PATTERN.matcher(value).replaceAll(""); 060 } 061 062}