You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ni...@apache.org on 2006/12/13 18:35:25 UTC

svn commit: r486765 - in /jakarta/commons/proper/validator/trunk: src/share/org/apache/commons/validator/ src/share/org/apache/commons/validator/routines/ src/test/org/apache/commons/validator/routines/ xdocs/

Author: niallp
Date: Wed Dec 13 09:35:23 2006
New Revision: 486765

URL: http://svn.apache.org/viewvc?view=rev&rev=486765
Log:
Re-write of the ISBNValidator using the new CodeValidator and CheckDigit routines. Removes the dependency on Jakarta ORO and now caters for the new ISBN-13 format. Existing ISBNValidator is now deprecated.
Fixes VALIDATOR-188 and VALIDATOR-191

Modified:
    jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/ISBNValidator.java
    jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/ISBNValidator.java
    jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/package.html
    jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/ISBNValidatorTest.java
    jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/RoutinesTestSuite.java
    jakarta/commons/proper/validator/trunk/xdocs/changes.xml

Modified: jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/ISBNValidator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/ISBNValidator.java?view=diff&rev=486765&r1=486764&r2=486765
==============================================================================
--- jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/ISBNValidator.java (original)
+++ jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/ISBNValidator.java Wed Dec 13 09:35:23 2006
@@ -24,25 +24,15 @@
  * <a href="http://www.isbn.org/standards/home/isbn/international/html/usm4.htm">
  * algorithm</a>
  *
+ * <b>NOTE:</b> This has been replaced by the new
+ *  {@link org.apache.commons.validator.routines.ISBNValidator}.
+ *
  * @version $Revision$ $Date$
  * @since Validator 1.2.0
+ * @deprecated Use the new ISBNValidator in the routines package
  */
 public class ISBNValidator {
 
-    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})";
-    private static final String CHECK = "([0-9X])";
-
-    /**
-     * ISBN 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.
-     */
-    private static final String ISBN_PATTERN =
-        "/^" + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + CHECK + "$/";
-
     /**
      * Default Constructor.
      */
@@ -61,73 +51,7 @@
      * @return true if the string is a valid ISBN code.
      */
     public boolean isValid(String isbn) {
-        if (isbn == null || isbn.length() < 10 || isbn.length() > 13) {
-            return false;
-        }
-
-        if (isFormatted(isbn) && !isValidPattern(isbn)) {
-            return false;
-        }
-
-        isbn = clean(isbn);
-        if (isbn.length() != 10) {
-            return false;
-        }
-
-        return (sum(isbn) % 11) == 0;
-    }
-    
-    /**
-     * Returns the sum of the weighted ISBN characters.
-     */
-    private int sum(String isbn) {
-        int total = 0;
-        for (int i = 0; i < 9; i++) {
-            int weight = 10 - i;
-            total += (weight * toInt(isbn.charAt(i)));
-        }
-        total += toInt(isbn.charAt(9)); // add check digit
-        return total;
-    }
-
-    /**
-     * Removes all non-digit characters except for 'X' which is a valid ISBN
-     * character. 
-     */
-    private String clean(String isbn) {
-        StringBuffer buf = new StringBuffer(10);
-        
-        for (int i = 0; i < isbn.length(); i++) {
-            char digit = isbn.charAt(i);
-            if (Character.isDigit(digit) || (digit == 'X')) {
-                buf.append(digit);
-            }
-        }
-
-        return buf.toString();
-    }
-
-    /**
-     * Returns the numeric value represented by the character.  If the 
-     * character is not a digit but an 'X', 10 is returned.
-     */
-    private int toInt(char ch) {
-        return (ch == 'X') ? 10 : Character.getNumericValue(ch);
-    }
-    
-    /**
-     * Returns true if the ISBN contains one of the separator characters space
-     * or dash.
-     */
-    private boolean isFormatted(String isbn) {
-        return ((isbn.indexOf('-') != -1) || (isbn.indexOf(' ') != -1));
-    }
-
-    /**
-     * Returns true if the ISBN is formatted properly.
-     */
-    private boolean isValidPattern(String isbn) {
-        return new Perl5Util().match(ISBN_PATTERN, isbn);
+        return org.apache.commons.validator.routines.ISBNValidator.getInstance().isValidISBN10(isbn);
     }
 
 }

Modified: jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/ISBNValidator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/ISBNValidator.java?view=diff&rev=486765&r1=486764&r2=486765
==============================================================================
--- jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/ISBNValidator.java (original)
+++ jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/ISBNValidator.java Wed Dec 13 09:35:23 2006
@@ -16,118 +16,241 @@
  */
 package org.apache.commons.validator.routines;
 
-import org.apache.oro.text.perl.Perl5Util;
+import java.io.Serializable;
+import org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit;
+import org.apache.commons.validator.routines.checkdigit.ISBN10CheckDigit;
+import org.apache.commons.validator.routines.checkdigit.CheckDigitException;
 
 /**
- * A class for validating 10 digit ISBN codes.
- * Based on this 
- * <a href="http://www.isbn.org/standards/home/isbn/international/html/usm4.htm">
- * algorithm</a>
+ * <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$ $Date$
- * @since Validator 1.2.0
+ * @since Validator 1.4
  */
-public class ISBNValidator {
+public class ISBNValidator implements Serializable {
 
-    private static final String SEP = "(\\-|\\s)";
+    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})";
-    private static final String CHECK = "([0-9X])";
 
     /**
-     * ISBN consists of 4 groups of numbers separated by either dashes (-)
+     * 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.
      */
-    private static final String ISBN_PATTERN =
-        "/^" + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + CHECK + "$/";
+    static final String ISBN10_REGEX     = 
+                  "^(?:(\\d{9}[0-9X])|(?:" + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + "([0-9X])))$";
 
     /**
-     * Default Constructor.
+     * 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.
      */
-    public ISBNValidator() {
-        super();
-    }
+    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.INSTANCE);
+
+    /** ISBN-13 Code Validator */
+    private CodeValidator isbn13Validator = new CodeValidator(ISBN13_REGEX, 13, EAN13CheckDigit.INSTANCE);
+
+    private boolean convert = true;
 
     /**
-     * If the ISBN is formatted with space or dash separators its format is
-     * validated.  Then the digits in the number are weighted, summed, and
-     * divided by 11 according to the ISBN algorithm.  If the result is zero,
-     * the ISBN is valid.  This method accepts formatted or raw ISBN codes.
+     * Return a singleton instance of the ISBN validator which
+     * converts ISBN-10 codes to ISBN-13.
      *
-     * @param isbn Candidate ISBN number to be validated. <code>null</code> is
-     * considered invalid.
-     * @return true if the string is a valid ISBN code.
+     * @return A singleton instance of the ISBN validator.
      */
-    public boolean isValid(String isbn) {
-        if (isbn == null || isbn.length() < 10 || isbn.length() > 13) {
-            return false;
-        }
+    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);
+    }
 
-        if (isFormatted(isbn) && !isValidPattern(isbn)) {
-            return false;
-        }
+    /**
+     * Construct an ISBN validator which converts ISBN-10 codes
+     * to ISBN-13.
+     */
+    public ISBNValidator() {
+        this(true);
+    }
 
-        isbn = clean(isbn);
-        if (isbn.length() != 10) {
-            return false;
-        }
+    /**
+     * 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;
+    }
 
-        return (sum(isbn) % 11) == 0;
+    /**
+     * 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));
     }
-    
+
     /**
-     * Returns the sum of the weighted ISBN characters.
+     * 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>.
      */
-    private int sum(String isbn) {
-        int total = 0;
-        for (int i = 0; i < 9; i++) {
-            int weight = 10 - i;
-            total += (weight * toInt(isbn.charAt(i)));
-        }
-        total += toInt(isbn.charAt(9)); // add check digit
-        return total;
+    public boolean isValidISBN10(String code) {
+        return isbn10Validator.isValid(code);
     }
 
     /**
-     * Removes all non-digit characters except for 'X' which is a valid ISBN
-     * character. 
+     * 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>.
      */
-    private String clean(String isbn) {
-        StringBuffer buf = new StringBuffer(10);
-        
-        for (int i = 0; i < isbn.length(); i++) {
-            char digit = isbn.charAt(i);
-            if (Character.isDigit(digit) || (digit == 'X')) {
-                buf.append(digit);
+    public String validate(String code) {
+        String result = validateISBN13(code);
+        if (result == null) {
+            result = validateISBN10(code);
+            if (result != null && convert) {
+                result = convertToISBN13(result);
             }
         }
-
-        return buf.toString();
+        return result;
     }
 
     /**
-     * Returns the numeric value represented by the character.  If the 
-     * character is not a digit but an 'X', 10 is returned.
+     * 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>.
      */
-    private int toInt(char ch) {
-        return (ch == 'X') ? 10 : Character.getNumericValue(ch);
+    public String validateISBN10(String code) {
+        Object result = isbn10Validator.validate(code);
+        return (result == null ? null : result.toString());
     }
-    
+
     /**
-     * Returns true if the ISBN contains one of the separator characters space
-     * or dash.
+     * 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>.
      */
-    private boolean isFormatted(String isbn) {
-        return ((isbn.indexOf('-') != -1) || (isbn.indexOf(' ') != -1));
+    public String validateISBN13(String code) {
+        Object result = isbn13Validator.validate(code);
+        return (result == null ? null : result.toString());
     }
 
     /**
-     * Returns true if the ISBN is formatted properly.
+     * 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
      */
-    private boolean isValidPattern(String isbn) {
-        return new Perl5Util().match(ISBN_PATTERN, isbn);
+    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 {
+            char checkDigit = isbn13Validator.getCheckDigit().calculate(isbn13);
+            isbn13 += checkDigit;
+            return isbn13;
+        } catch (CheckDigitException e) {
+            throw new IllegalArgumentException("Check digit error for '" + input + "' - " + e.getMessage());
+        }
+
     }
 
 }

Modified: jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/package.html
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/package.html?view=diff&rev=486765&r1=486764&r2=486765
==============================================================================
--- jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/package.html (original)
+++ jakarta/commons/proper/validator/trunk/src/share/org/apache/commons/validator/routines/package.html Wed Dec 13 09:35:23 2006
@@ -47,6 +47,7 @@
     <li>4.2 <a href="#other.regex">Regular Expression validation</a></li>
     <li>4.3 <a href="#other.checkdigit">Check Digit Validation/Calculation</a></li>
     <li>4.4 <a href="#other.code">General Code Validation</a></li>
+    <li>4.5 <a href="#other.isbn">ISBN Validation</a></li>
     </ul></li>
 </ul>
 
@@ -422,6 +423,8 @@
        check digits (i.e. EAN/UPC, credit card, ISBN).</li>
    <li><a href="#other.code">Code Validation</a> - provides generic
      code validation - format, minimum/maximum length and check digit.</li>
+   <li><a href="#other.isbn">ISBN Validation</a> - provides ISBN-10
+       and ISBN-13 validation.</li>
 </ul>
 
 <a name="other.regex"></a>
@@ -609,6 +612,56 @@
       if (!validator.isValid(code)) {
           ... // invalid
       }
+
+</pre>
+
+<a name="other.isbn"></a>
+<h3>4.5 ISBN validation</h3>
+<p>
+   <a href="ISBNValidator.html">ISBNValidator</a> provides ISBN-10
+   and ISBN-13 validation and can <i>optionally</i> convert
+   ISBN-10 codes to ISBN-13.
+</p>
+<ul>
+    <li><b>ISBN-10</b> - validates using a
+        <a href="CodeValidator.html">CodeValidator</a> with the
+        <a href="checkdigit/ISBN10CheckDigit.html">ISBN10CheckDigit</a>
+        routine.</li>
+        <ul>
+            <li><code>isValidISBN10(<i>value</i>)</code> - returns a boolean</li>
+            <li><code>validateISBN10(<i>value</i>)</code> - returns a reformatted ISBN-10 code</li>
+        </ul>
+    <li><b>ISBN-13</b> - validates using a
+        <a href="CodeValidator.html">CodeValidator</a> with the
+        <a href="checkdigit/EAN13CheckDigit.html">EAN13CheckDigit</a>
+        routine.</li>
+        <ul>
+            <li><code>isValidISBN13(<i>value</i>)</code> - returns a boolean</li>
+            <li><code>validateISBN13(<i>value</i>)</code> - returns a reformatted ISBN-13 code</li>
+        </ul>
+    <li><b>ISBN-10</b> and <b>ISBN-13</b> - validates codes are either
+        valid ISBN-10 or valid ISBN-13 - optionally can convert ISBN-10 codes to ISBN-13.</li>
+        <ul>
+            <li><code>isValid(<i>value</i>)</code> - returns a boolean</li>
+            <li><code>validate(<i>value</i>)</code> - returns a reformatted ISBN code
+                (converts ISBN-10 to ISBN-13 if the <i>convert</i> option is <code>true</code>).</li>
+        </ul>
+</ul>
+<p>
+   For example to validate
+</p>
+<pre>
+
+      // Validate an ISBN-10 or ISBN-13 code
+      if (!ISBNValidator.getInstance().isValid(code)) {
+          ... // invalid
+      }
+
+      // Validate an ISBN-10 or ISBN-13 code (converting to ISBN-13)
+      String code = ISBNValidator.getInstance().validate(code);
+
+      // Validate an ISBN-10 or ISBN-13 code (not converting)
+      String code = ISBNValidator.getInstance(false).validate(code);
 
 </pre>
 

Modified: jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/ISBNValidatorTest.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/ISBNValidatorTest.java?view=diff&rev=486765&r1=486764&r2=486765
==============================================================================
--- jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/ISBNValidatorTest.java (original)
+++ jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/ISBNValidatorTest.java Wed Dec 13 09:35:23 2006
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.validator.routines;
 
+import java.util.regex.Pattern;
 import junit.framework.TestCase;
 
 /**
@@ -25,34 +26,301 @@
  */
 public class ISBNValidatorTest extends TestCase {
 
-    private static final String VALID_ISBN_RAW = "1930110995";
-    private static final String VALID_ISBN_DASHES = "1-930110-99-5";
-    private static final String VALID_ISBN_SPACES = "1 930110 99 5";
-    private static final String VALID_ISBN_X = "0-201-63385-X";
-    private static final String INVALID_ISBN = "068-556-98-45";
+    private String[] validISBN10Format = new String[] {
+            "1234567890",
+            "123456789X",
+            "12345-1234567-123456-X",
+            "12345 1234567 123456 X",
+            "1-2-3-4",
+            "1 2 3 4",
+            };
 
+    private String[] invalidISBN10Format = new String[] {
+            "",                        // empty
+            "   ",                     // empty
+            "1",                       // too short
+            "123456789",               // too short
+            "12345678901",             // too long
+            "12345678X0",              // X not at end
+            "123456-1234567-123456-X", // Group too long
+            "12345-12345678-123456-X", // Publisher too long
+            "12345-1234567-1234567-X", // Title too long
+            "12345-1234567-123456-X2", // Check Digit too long
+            "--1 930110 99 5",         // format
+            "1 930110 99 5--",         // format
+            "1 930110-99 5-",          // format
+            "1.2.3.4",                 // Invalid Separator
+            "1=2=3=4",                 // Invalid Separator
+            "1_2_3_4",                 // Invalid Separator
+            "123456789Y",              // Other character at the end
+            "dsasdsadsa",              // invalid characters
+            "I love sparrows!",        // invalid characters
+            "068-556-98-45"            // format
+            };
+
+    private String[] validISBN13Format = new String[] {
+            "9781234567890",
+            "9791234567890",
+            "978-12345-1234567-123456-1",
+            "979-12345-1234567-123456-1",
+            "978 12345 1234567 123456 1",
+            "979 12345 1234567 123456 1",
+            "978-1-2-3-4",
+            "979-1-2-3-4",
+            "978 1 2 3 4",
+            "979 1 2 3 4",
+            };
+
+    private String[] invalidISBN13Format = new String[] {
+            "",                            // empty
+            "   ",                         // empty
+            "1",                           // too short
+            "978123456789",                // too short
+            "97812345678901",              // too long
+            "978-123456-1234567-123456-1", // Group too long
+            "978-12345-12345678-123456-1", // Publisher too long
+            "978-12345-1234567-1234567-1", // Title too long
+            "978-12345-1234567-123456-12", // Check Digit too long
+            "--978 1 930110 99 1",         // format
+            "978 1 930110 99 1--",         // format
+            "978 1 930110-99 1-",          // format
+            "123-4-567890-12-8",           // format
+            "978.1.2.3.4",                 // Invalid Separator
+            "978=1=2=3=4",                 // Invalid Separator
+            "978_1_2_3_4",                 // Invalid Separator
+            "978123456789X",               // invalid character
+            "978-0-201-63385-X",           // invalid character
+            "dsasdsadsadsa",               // invalid characters
+            "I love sparrows!",            // invalid characters
+            "979-1-234-567-89-6"           // format
+            };
+
+    /**
+     * Create a test case with the specified name.
+     * @param name The name of the test
+     */
     public ISBNValidatorTest(String name) {
         super(name);
     }
 
-    public void testIsValid() throws Exception {
-        ISBNValidator validator = new ISBNValidator();
-        assertFalse(validator.isValid(null));
-        assertFalse(validator.isValid(""));
-        assertFalse(validator.isValid("1"));
-        assertFalse(validator.isValid("12345678901234"));
-        assertFalse(validator.isValid("dsasdsadsads"));
-        assertFalse(validator.isValid("535365"));
-        assertFalse(validator.isValid("I love sparrows!"));
-        assertFalse(validator.isValid("--1 930110 99 5"));
-        assertFalse(validator.isValid("1 930110 99 5--"));
-        assertFalse(validator.isValid("1 930110-99 5-"));
-
-        assertTrue(validator.isValid(VALID_ISBN_RAW));
-        assertTrue(validator.isValid(VALID_ISBN_DASHES));
-        assertTrue(validator.isValid(VALID_ISBN_SPACES));
-        assertTrue(validator.isValid(VALID_ISBN_X));
-        assertFalse(validator.isValid(INVALID_ISBN));
+    /**
+     * Test Valid ISBN-10 formats.
+     */
+    public void testValidISBN10Format() {
+        Pattern pattern = Pattern.compile(ISBNValidator.ISBN10_REGEX);
+        for (int i = 0; i < validISBN10Format.length; i++) {
+            assertTrue("Pattern[" + i + "]=" + validISBN10Format[i], pattern.matcher(validISBN10Format[i]).matches());
+        }
+    }
+
+    /**
+     * Test Invalid ISBN-10 formats.
+     */
+    public void testInvalidISBN10Format() {
+        ISBNValidator validator = ISBNValidator.getInstance();
+        Pattern pattern = Pattern.compile(ISBNValidator.ISBN10_REGEX);
+        for (int i = 0; i < invalidISBN10Format.length; i++) {
+            assertFalse("Pattern[" + i + "]=" + invalidISBN10Format[i],       pattern.matcher(invalidISBN10Format[i]).matches());
+            assertFalse("isValidISBN10[" + i + "]=" + invalidISBN10Format[i], validator.isValidISBN10(invalidISBN10Format[i]));
+            assertNull("validateISBN10[" + i + "]=" + invalidISBN10Format[i], validator.validateISBN10(invalidISBN10Format[i]));
+        }
+    }
+
+    /**
+     * Test Valid ISBN-13 formats.
+     */
+    public void testValidISBN13Format() {
+        Pattern pattern = Pattern.compile(ISBNValidator.ISBN13_REGEX);
+        for (int i = 0; i < validISBN13Format.length; i++) {
+            assertTrue("Pattern[" + i + "]=" + validISBN13Format[i], pattern.matcher(validISBN13Format[i]).matches());
+        }
+    }
+
+    /**
+     * Test Invalid ISBN-13 formats.
+     */
+    public void testInvalidISBN13Format() {
+        Pattern pattern = Pattern.compile(ISBNValidator.ISBN13_REGEX);
+        ISBNValidator validator = ISBNValidator.getInstance();
+        for (int i = 0; i < invalidISBN13Format.length; i++) {
+            assertFalse("Pattern[" + i + "]=" + invalidISBN13Format[i],       pattern.matcher(invalidISBN13Format[i]).matches());
+            assertFalse("isValidISBN13[" + i + "]=" + invalidISBN13Format[i], validator.isValidISBN13(invalidISBN13Format[i]));
+            assertNull("validateISBN13[" + i + "]=" + invalidISBN13Format[i], validator.validateISBN13(invalidISBN13Format[i]));
+        }
+    }
+
+    /**
+     * Test isValid() ISBN-10 codes
+     */
+    public void testIsValidISBN10() {
+        ISBNValidator validator = ISBNValidator.getInstance();
+        assertTrue("isValidISBN10-1", validator.isValidISBN10("1930110995"));
+        assertTrue("isValidISBN10-2", validator.isValidISBN10("1-930110-99-5"));
+        assertTrue("isValidISBN10-3", validator.isValidISBN10("1 930110 99 5"));
+        assertTrue("isValidISBN10-4", validator.isValidISBN10("020163385X"));
+        assertTrue("isValidISBN10-5", validator.isValidISBN10("0-201-63385-X"));
+        assertTrue("isValidISBN10-6", validator.isValidISBN10("0 201 63385 X"));
+
+        assertTrue("isValid-1", validator.isValid("1930110995"));
+        assertTrue("isValid-2", validator.isValid("1-930110-99-5"));
+        assertTrue("isValid-3", validator.isValid("1 930110 99 5"));
+        assertTrue("isValid-4", validator.isValid("020163385X"));
+        assertTrue("isValid-5", validator.isValid("0-201-63385-X"));
+        assertTrue("isValid-6", validator.isValid("0 201 63385 X"));
+    }
+
+    /**
+     * Test isValid() ISBN-13 codes
+     */
+    public void testIsValidISBN13() {
+        ISBNValidator validator = ISBNValidator.getInstance();
+        assertTrue("isValidISBN13-1", validator.isValidISBN13("9781930110991"));
+        assertTrue("isValidISBN13-2", validator.isValidISBN13("978-1-930110-99-1"));
+        assertTrue("isValidISBN13-3", validator.isValidISBN13("978 1 930110 99 1"));
+        assertTrue("isValidISBN13-4", validator.isValidISBN13("9780201633856"));
+        assertTrue("isValidISBN13-5", validator.isValidISBN13("978-0-201-63385-6"));
+        assertTrue("isValidISBN13-6", validator.isValidISBN13("978 0 201 63385 6"));
+
+        assertTrue("isValid-1", validator.isValid("9781930110991"));
+        assertTrue("isValid-2", validator.isValid("978-1-930110-99-1"));
+        assertTrue("isValid-3", validator.isValid("978 1 930110 99 1"));
+        assertTrue("isValid-4", validator.isValid("9780201633856"));
+        assertTrue("isValid-5", validator.isValid("978-0-201-63385-6"));
+        assertTrue("isValid-6", validator.isValid("978 0 201 63385 6"));
+    }
+
+    /**
+     * Test validate() ISBN-10 codes (don't convert)
+     */
+    public void testValidateISBN10() {
+        ISBNValidator validator = ISBNValidator.getInstance(false);
+        assertEquals("validateISBN10-1", "1930110995", validator.validateISBN10("1930110995"));
+        assertEquals("validateISBN10-2", "1930110995", validator.validateISBN10("1-930110-99-5"));
+        assertEquals("validateISBN10-3", "1930110995", validator.validateISBN10("1 930110 99 5"));
+        assertEquals("validateISBN10-4", "020163385X", validator.validateISBN10("020163385X"));
+        assertEquals("validateISBN10-5", "020163385X", validator.validateISBN10("0-201-63385-X"));
+        assertEquals("validateISBN10-6", "020163385X", validator.validateISBN10("0 201 63385 X"));
+
+        assertEquals("validate-1", "1930110995", validator.validate("1930110995"));
+        assertEquals("validate-2", "1930110995", validator.validate("1-930110-99-5"));
+        assertEquals("validate-3", "1930110995", validator.validate("1 930110 99 5"));
+        assertEquals("validate-4", "020163385X", validator.validate("020163385X"));
+        assertEquals("validate-5", "020163385X", validator.validate("0-201-63385-X"));
+        assertEquals("validate-6", "020163385X", validator.validate("0 201 63385 X"));
+    }
+
+    /**
+     * Test validate() ISBN-10 codes (convert)
+     */
+    public void testValidateISBN10Convert() {
+        ISBNValidator validator = ISBNValidator.getInstance();
+        assertEquals("validate-1", "9781930110991", validator.validate("1930110995"));
+        assertEquals("validate-2", "9781930110991", validator.validate("1-930110-99-5"));
+        assertEquals("validate-3", "9781930110991", validator.validate("1 930110 99 5"));
+        assertEquals("validate-4", "9780201633856", validator.validate("020163385X"));
+        assertEquals("validate-5", "9780201633856", validator.validate("0-201-63385-X"));
+        assertEquals("validate-6", "9780201633856", validator.validate("0 201 63385 X"));
+    }
+
+    /**
+     * Test validate() ISBN-13 codes
+     */
+    public void testValidateISBN13() {
+        ISBNValidator validator = ISBNValidator.getInstance();
+        assertEquals("validateISBN13-1", "9781930110991", validator.validateISBN13("9781930110991"));
+        assertEquals("validateISBN13-2", "9781930110991", validator.validateISBN13("978-1-930110-99-1"));
+        assertEquals("validateISBN13-3", "9781930110991", validator.validateISBN13("978 1 930110 99 1"));
+        assertEquals("validateISBN13-4", "9780201633856", validator.validateISBN13("9780201633856"));
+        assertEquals("validateISBN13-5", "9780201633856", validator.validateISBN13("978-0-201-63385-6"));
+        assertEquals("validateISBN13-6", "9780201633856", validator.validateISBN13("978 0 201 63385 6"));
+
+        assertEquals("validate-1", "9781930110991", validator.validate("9781930110991"));
+        assertEquals("validate-2", "9781930110991", validator.validate("978-1-930110-99-1"));
+        assertEquals("validate-3", "9781930110991", validator.validate("978 1 930110 99 1"));
+        assertEquals("validate-4", "9780201633856", validator.validate("9780201633856"));
+        assertEquals("validate-5", "9780201633856", validator.validate("978-0-201-63385-6"));
+        assertEquals("validate-6", "9780201633856", validator.validate("978 0 201 63385 6"));
+    }
+
+    /**
+     * Test null values
+     */
+    public void testNull() {
+        ISBNValidator validator = ISBNValidator.getInstance();
+        assertFalse("isValid",        validator.isValid(null));
+        assertFalse("isValidISBN10",  validator.isValidISBN10(null));
+        assertFalse("isValidISBN13",  validator.isValidISBN13(null));
+        assertNull("validate",        validator.validate(null));
+        assertNull("validateISBN10",  validator.validateISBN10(null));
+        assertNull("validateISBN13",  validator.validateISBN13(null));
+        assertNull("convertToISBN13", validator.convertToISBN13(null));
+    }
+
+    /**
+     * Test Invalid ISBN-10 codes
+     */
+    public void testInvalid() {
+        ISBNValidator validator = ISBNValidator.getInstance();
+        String baseCode = "193011099";
+        assertFalse("ISBN10-0", validator.isValid(baseCode + "0"));
+        assertFalse("ISBN10-1", validator.isValid(baseCode + "1"));
+        assertFalse("ISBN10-2", validator.isValid(baseCode + "2"));
+        assertFalse("ISBN10-3", validator.isValid(baseCode + "3"));
+        assertFalse("ISBN10-4", validator.isValid(baseCode + "4"));
+        assertTrue("ISBN10-5",  validator.isValid(baseCode + "5")); // valid check digit
+        assertFalse("ISBN10-6", validator.isValid(baseCode + "6"));
+        assertFalse("ISBN10-7", validator.isValid(baseCode + "7"));
+        assertFalse("ISBN10-8", validator.isValid(baseCode + "8"));
+        assertFalse("ISBN10-9", validator.isValid(baseCode + "9"));
+        assertFalse("ISBN10-X", validator.isValid(baseCode + "X"));
+
+        baseCode = "978193011099";
+        assertFalse("ISBN13-0", validator.isValid(baseCode + "0"));
+        assertTrue("ISBN13-1",  validator.isValid(baseCode + "1")); // valid check digit
+        assertFalse("ISBN13-2", validator.isValid(baseCode + "2"));
+        assertFalse("ISBN13-3", validator.isValid(baseCode + "3"));
+        assertFalse("ISBN13-4", validator.isValid(baseCode + "4"));
+        assertFalse("ISBN13-5", validator.isValid(baseCode + "5"));
+        assertFalse("ISBN13-6", validator.isValid(baseCode + "6"));
+        assertFalse("ISBN13-7", validator.isValid(baseCode + "7"));
+        assertFalse("ISBN13-8", validator.isValid(baseCode + "8"));
+        assertFalse("ISBN13-9", validator.isValid(baseCode + "9"));
+    }
+
+    /**
+     * Test method for {@link org.apache.commons.validator.routines.ISBNValidator#convertToISBN13(java.lang.String)}.
+     */
+    public void testConversionErrors() {
+        ISBNValidator validator = ISBNValidator.getInstance();
+        String input = null;
+        try {
+            input = "123456789 ";
+            validator.convertToISBN13(input);
+            fail("Expected IllegalArgumentException for '" + input + "'"); 
+        } catch (IllegalArgumentException e) {
+            // expected result
+        }
+        try {
+            input = "12345678901";
+            validator.convertToISBN13(input);
+            fail("Expected IllegalArgumentException for '" + input + "'"); 
+        } catch (IllegalArgumentException e) {
+            // expected result
+        }
+        try {
+            input = "";
+            validator.convertToISBN13(input);
+            fail("Expected IllegalArgumentException for '" + input + "'"); 
+        } catch (IllegalArgumentException e) {
+            // expected result
+        }
+        try {
+            input = "X234567890";
+            validator.convertToISBN13(input);
+            fail("Expected IllegalArgumentException for '" + input + "'"); 
+        } catch (IllegalArgumentException e) {
+            // expected result
+        }
     }
 
 }

Modified: jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/RoutinesTestSuite.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/RoutinesTestSuite.java?view=diff&rev=486765&r1=486764&r2=486765
==============================================================================
--- jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/RoutinesTestSuite.java (original)
+++ jakarta/commons/proper/validator/trunk/src/test/org/apache/commons/validator/routines/RoutinesTestSuite.java Wed Dec 13 09:35:23 2006
@@ -49,6 +49,7 @@
        suite.addTestSuite(DateValidatorTest.class);
        suite.addTestSuite(DoubleValidatorTest.class);
        suite.addTestSuite(FloatValidatorTest.class);
+       suite.addTestSuite(ISBNValidatorTest.class);
        suite.addTestSuite(IntegerValidatorTest.class);
        suite.addTestSuite(LongValidatorTest.class);
        suite.addTestSuite(PercentValidatorTest.class);

Modified: jakarta/commons/proper/validator/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/validator/trunk/xdocs/changes.xml?view=diff&rev=486765&r1=486764&r2=486765
==============================================================================
--- jakarta/commons/proper/validator/trunk/xdocs/changes.xml (original)
+++ jakarta/commons/proper/validator/trunk/xdocs/changes.xml Wed Dec 13 09:35:23 2006
@@ -40,6 +40,23 @@
   <body>
 
     <release version="1.4-SNAPSHOT" date="in SVN" description="JDK 1.4 (minimum)">
+      <action dev="niallp" type="update">
+          <a href="apidocs/org/apache/commons/validator/routines/ISBNValidator.html">ISBN Validator</a>
+          <ul>
+             <li>Moved to the new 
+                 <a href="apidocs/org/apache/commons/validator/routines/package-summary.html">routines</a> package.</li>
+             <li>Re-written to use the new 
+                <a href="apidocs/org/apache/commons/validator/routines/CodeValidator.html">CodeValidator</a> and
+                <a href="apidocs/org/apache/commons/validator/routines/checkdigit/package-summary.html">Check Digit</a> routines.</li>
+             <li>Enhanced for the new <a href="http://issues.apache.org/jira/browse/VALIDATOR-188">ISBN-13 format</a>.</li>
+             <li><a href="http://jakarta.apache.org/oro/">Jakarta ORO</a> dependency removed.</li>
+          </ul>
+        <fixes issue="VALIDATOR-197"/>
+        <fixes issue="VALIDATOR-188"/>
+        <fixes issue="VALIDATOR-191"/>
+        <dueto name="Gabriel Belingueres"/>
+        <dueto name="Matthias Wessendorf"/>
+      </action>
       <action dev="niallp" type="add" issue="VALIDATOR-215">
           <b>Code Validator</b> - new generic code validator that validates format,
           length and Check Digit for a code, see



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org