1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.validator.routines.checkdigit;
18
19 /**
20 * International Standard Serial Number (ISSN)
21 * is an eight-digit serial number used to
22 * uniquely identify a serial publication.
23 * <pre>
24 * The format is:
25 *
26 * ISSN dddd-dddC
27 * where:
28 * d = decimal digit (0-9)
29 * C = checksum (0-9 or X)
30 *
31 * The checksum is formed by adding the first 7 digits multiplied by
32 * the position in the entire number (counting from the right).
33 * For example, abcd-efg would be 8a + 7b + 6c + 5d + 4e +3f +2g.
34 * The check digit is modulus 11, where the value 10 is represented by 'X'
35 * For example:
36 * ISSN 0317-8471
37 * ISSN 1050-124X
38 * </pre>
39 * <p>
40 * <strong>Note:</strong> This class expects the input to be numeric only,
41 * with all formatting removed.
42 * For example:
43 * </p>
44 * <pre>
45 * 03178471
46 * 1050124X
47 * </pre>
48 *
49 * @since 1.5.0
50 */
51 public final class ISSNCheckDigit extends ModulusCheckDigit {
52
53 private static final long serialVersionUID = 1L;
54
55 /** An ISSN is exactly eight characters: seven digits plus the check digit. */
56 private static final int ISSN_LEN = 8;
57
58 /**
59 * Singleton ISSN Check Digit instance.
60 */
61 public static final CheckDigit ISSN_CHECK_DIGIT = new ISSNCheckDigit();
62
63 /**
64 * Creates the instance using a checkdigit modulus of 11.
65 */
66 public ISSNCheckDigit() {
67 super(MODULUS_11);
68 }
69
70 /**
71 * {@inheritDoc}
72 *
73 * <p>
74 * The {@code 9 - leftPos} weighting gives a ninth character a weight of zero, so an over-length code left the
75 * trailing characters unweighted and still passed the modulus test (for example every {@code 03178471} + digit
76 * validated). The length is checked here so only a genuine eight-character ISSN reaches the check digit test.
77 * </p>
78 */
79 @Override
80 public boolean isValid(final String code) {
81 return isLength(code, ISSN_LEN) && super.isValid(code);
82 }
83
84 @Override
85 protected String toCheckDigit(final int charValue) throws CheckDigitException {
86 if (charValue == 10) { // CHECKSTYLE IGNORE MagicNumber
87 return "X";
88 }
89 return super.toCheckDigit(charValue);
90 }
91
92 @Override
93 protected int toInt(final char character, final int leftPos, final int rightPos)
94 throws CheckDigitException {
95 if (rightPos == 1 && character == 'X') {
96 return 10; // CHECKSTYLE IGNORE MagicNumber
97 }
98 return super.toInt(character, leftPos, rightPos);
99 }
100
101 @Override
102 protected int weightedValue(final int charValue, final int leftPos, final int rightPos) throws CheckDigitException {
103 return charValue * (9 - leftPos); // CHECKSTYLE IGNORE MagicNumber
104 }
105 }