org.apache.commons.validator.routines.ISBNValidator.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.commons.validator.routines.ISBNValidator.java

Source

/*
 * 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 org.apache.commons.validator.routines.checkdigit.CheckDigitException;
import org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit;
import org.apache.commons.validator.routines.checkdigit.ISBN10CheckDigit;

/**
 * <b>ISBN-10</b> and <b>ISBN-13</b> Code Validation.
 * <p>
 * This validator validates the code is either a valid ISBN-10 (using a {@link CodeValidator} with the {@link ISBN10CheckDigit})
 * or a valid ISBN-13 code (using a {@link CodeValidator} with the the {@link EAN13CheckDigit} routine).
 * <p>
 * The <code>validate()</code> methods return the ISBN code with formatting characters removed if valid or <code>null</code> if
 * invalid.
 * <p>
 * This validator also provides the facility to convert ISBN-10 codes to ISBN-13 if the <code>convert</code> property is
 * <code>true</code>.
 * <p>
 * From 1st January 2007 the book industry will start to use a new 13 digit ISBN number (rather than this 10 digit ISBN number).
 * ISBN-13 codes are <a href="http://en.wikipedia.org/wiki/European_Article_Number">EAN</a> codes, for more information see:
 * </p>
 * 
 * <ul>
 * <li><a href="http://en.wikipedia.org/wiki/ISBN">Wikipedia - International Standard Book Number (ISBN)</a>.</li>
 * <li>EAN - see <a href="http://en.wikipedia.org/wiki/European_Article_Number">Wikipedia - European Article Number</a>.</li>
 * <li><a href="http://www.isbn.org/standards/home/isbn/transition.asp">ISBN-13 Transition details</a>.</li>
 * </ul>
 * 
 * @version $Revision: 909009 $ $Date: 2010-02-11 14:59:45 +0000 (Qui, 11 Fev 2010) $
 * @since Validator 1.4
 */
public class ISBNValidator implements Serializable {

    private static final String SEP = "(?:\\-|\\s)";
    private static final String GROUP = "(\\d{1,5})";
    private static final String PUBLISHER = "(\\d{1,7})";
    private static final String TITLE = "(\\d{1,6})";

    /**
     * ISBN-10 consists of 4 groups of numbers separated by either dashes (-)
     * or spaces. The first group is 1-5 characters, second 1-7, third 1-6,
     * and fourth is 1 digit or an X.
     */
    static final String ISBN10_REGEX = "^(?:(\\d{9}[0-9X])|(?:" + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP
            + "([0-9X])))$";

    /**
     * ISBN-13 consists of 5 groups of numbers separated by either dashes (-)
     * or spaces. The first group is 978 or 979, the second group is
     * 1-5 characters, third 1-7, fourth 1-6, and fifth is 1 digit.
     */
    static final String ISBN13_REGEX = "^(978|979)(?:(\\d{10})|(?:" + SEP + GROUP + SEP + PUBLISHER + SEP + TITLE
            + SEP + "([0-9])))$";

    /** ISBN Code Validator (which converts ISBN-10 codes to ISBN-13 */
    private static final ISBNValidator ISBN_VALIDATOR = new ISBNValidator();

    /** ISBN Code Validator (which converts ISBN-10 codes to ISBN-13 */
    private static final ISBNValidator ISBN_VALIDATOR_NO_CONVERT = new ISBNValidator(false);

    /** ISBN-10 Code Validator */
    private CodeValidator isbn10Validator = new CodeValidator(ISBN10_REGEX, 10,
            ISBN10CheckDigit.ISBN10_CHECK_DIGIT);

    /** ISBN-13 Code Validator */
    private CodeValidator isbn13Validator = new CodeValidator(ISBN13_REGEX, 13, EAN13CheckDigit.EAN13_CHECK_DIGIT);

    private final boolean convert;

    /**
     * Return a singleton instance of the ISBN validator which
     * converts ISBN-10 codes to ISBN-13.
     * 
     * @return A singleton instance of the ISBN validator.
     */
    public static ISBNValidator getInstance() {
        return ISBN_VALIDATOR;
    }

    /**
     * Return a singleton instance of the ISBN validator specifying
     * whether ISBN-10 codes should be converted to ISBN-13.
     * 
     * @param convert <code>true</code> if valid ISBN-10 codes
     *            should be converted to ISBN-13 codes or <code>false</code> if valid ISBN-10 codes should be returned unchanged.
     * @return A singleton instance of the ISBN validator.
     */
    public static ISBNValidator getInstance(boolean convert) {
        return (convert ? ISBN_VALIDATOR : ISBN_VALIDATOR_NO_CONVERT);
    }

    /**
     * Construct an ISBN validator which converts ISBN-10 codes
     * to ISBN-13.
     */
    public ISBNValidator() {
        this(true);
    }

    /**
     * Construct an ISBN validator indicating whether
     * ISBN-10 codes should be converted to ISBN-13.
     * 
     * @param convert <code>true</code> if valid ISBN-10 codes
     *            should be converted to ISBN-13 codes or <code>false</code> if valid ISBN-10 codes should be returned unchanged.
     */
    public ISBNValidator(boolean convert) {
        this.convert = convert;
    }

    /**
     * Check the code is either a valid ISBN-10 or ISBN-13 code.
     * 
     * @param code The code to validate.
     * @return <code>true</code> if a valid ISBN-10 or
     *         ISBN-13 code, otherwise <code>false</code>.
     */
    public boolean isValid(String code) {
        return (isValidISBN13(code) || isValidISBN10(code));
    }

    /**
     * Check the code is a valid ISBN-10 code.
     * 
     * @param code The code to validate.
     * @return <code>true</code> if a valid ISBN-10
     *         code, otherwise <code>false</code>.
     */
    public boolean isValidISBN10(String code) {
        return isbn10Validator.isValid(code);
    }

    /**
     * Check the code is a valid ISBN-13 code.
     * 
     * @param code The code to validate.
     * @return <code>true</code> if a valid ISBN-13
     *         code, otherwise <code>false</code>.
     */
    public boolean isValidISBN13(String code) {
        return isbn13Validator.isValid(code);
    }

    /**
     * Check the code is either a valid ISBN-10 or ISBN-13 code.
     * <p>
     * If valid, this method returns the ISBN code with formatting characters removed (i.e. space or hyphen).
     * <p>
     * Converts an ISBN-10 codes to ISBN-13 if <code>convertToISBN13</code> is <code>true</code>.
     * 
     * @param code The code to validate.
     * @return A valid ISBN code if valid, otherwise <code>null</code>.
     */
    public String validate(String code) {
        String result = validateISBN13(code);
        if (result == null) {
            result = validateISBN10(code);
            if (result != null && convert) {
                result = convertToISBN13(result);
            }
        }
        return result;
    }

    /**
     * Check the code is a valid ISBN-10 code.
     * <p>
     * If valid, this method returns the ISBN-10 code with formatting characters removed (i.e. space or hyphen).
     * 
     * @param code The code to validate.
     * @return A valid ISBN-10 code if valid,
     *         otherwise <code>null</code>.
     */
    public String validateISBN10(String code) {
        Object result = isbn10Validator.validate(code);
        return (result == null ? null : result.toString());
    }

    /**
     * Check the code is a valid ISBN-13 code.
     * <p>
     * If valid, this method returns the ISBN-13 code with formatting characters removed (i.e. space or hyphen).
     * 
     * @param code The code to validate.
     * @return A valid ISBN-13 code if valid,
     *         otherwise <code>null</code>.
     */
    public String validateISBN13(String code) {
        Object result = isbn13Validator.validate(code);
        return (result == null ? null : result.toString());
    }

    /**
     * Convert an ISBN-10 code to an ISBN-13 code.
     * <p>
     * This method requires a valid ISBN-10 with NO formatting characters.
     * 
     * @param isbn10 The ISBN-10 code to convert
     * @return A converted ISBN-13 code or <code>null</code> if the ISBN-10 code is not valid
     */
    public String convertToISBN13(String isbn10) {

        if (isbn10 == null) {
            return null;
        }

        String input = isbn10.trim();
        if (input.length() != 10) {
            throw new IllegalArgumentException("Invalid length " + input.length() + " for '" + input + "'");
        }

        // Calculate the new ISBN-13 code
        String isbn13 = "978" + input.substring(0, 9);
        try {
            String checkDigit = isbn13Validator.getCheckDigit().calculate(isbn13);
            isbn13 += checkDigit;
            return isbn13;
        } catch (CheckDigitException e) {
            throw new IllegalArgumentException("Check digit error for '" + input + "' - " + e.getMessage());
        }

    }

}