You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2003/08/02 20:18:33 UTC

cvs commit: jakarta-commons/lang/src/test/org/apache/commons/lang CharSetTest.java CharRangeTest.java LangTestSuite.java

scolebourne    2003/08/02 11:18:33

  Modified:    lang/src/java/org/apache/commons/lang CharSetUtils.java
                        CharSet.java CharRange.java
               lang/src/test/org/apache/commons/lang LangTestSuite.java
  Added:       lang/src/test/org/apache/commons/lang CharSetTest.java
                        CharRangeTest.java
  Log:
  Completely rework CharRange and CharSet.
  Add multiple tests to fully define the set syntax.
  
  Revision  Changes    Path
  1.20      +8 -4      jakarta-commons/lang/src/java/org/apache/commons/lang/CharSetUtils.java
  
  Index: CharSetUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/lang/src/java/org/apache/commons/lang/CharSetUtils.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- CharSetUtils.java	1 Aug 2003 20:45:17 -0000	1.19
  +++ CharSetUtils.java	2 Aug 2003 18:18:33 -0000	1.20
  @@ -98,12 +98,14 @@
        *
        * @param set  the set, may be null
        * @return a CharSet instance, <code>null</code> if null input
  +     * @deprecated Use {@link CharSet#getInstance(String)}.
  +     *             Method will be removed in Commons Lang 3.0.
        */
  -    public static CharSet evaluateSet(String set) {
  -        if (set == null) {
  +    public static CharSet evaluateSet(String setStr) {
  +        if (setStr == null) {
               return null;
           }
  -        return new CharSet(new String[] {set}); 
  +        return CharSet.getInstance(setStr); 
       }
   
       /**
  @@ -125,6 +127,8 @@
        *
        * @param set  the set, may be null
        * @return a CharSet instance, <code>null</code> if null input
  +     * @deprecated Use {@link CharSet#getInstance(String)}.
  +     *             Method will be removed in Commons Lang 3.0.
        */
       public static CharSet evaluateSet(String[] set) {
           if (set == null) {
  
  
  
  1.10      +213 -64   jakarta-commons/lang/src/java/org/apache/commons/lang/CharSet.java
  
  Index: CharSet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/lang/src/java/org/apache/commons/lang/CharSet.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- CharSet.java	31 Jul 2003 21:32:47 -0000	1.9
  +++ CharSet.java	2 Aug 2003 18:18:33 -0000	1.10
  @@ -53,117 +53,266 @@
    */
   package org.apache.commons.lang;
   
  +import java.io.Serializable;
  +import java.util.HashMap;
  +import java.util.HashSet;
   import java.util.Iterator;
  -import java.util.LinkedList;
  -import java.util.List;
  +import java.util.Map;
  +import java.util.Set;
   
   /**
    * <p>A set of characters.</p>
  + * 
  + * <p>This class is immutable, but subclasses may not be.</p>
    *
  - * @author <a href="bayard@generationjava.com">Henri Yandell</a>
  + * @author Henri Yandell
    * @author Stephen Colebourne
    * @since 1.0
    * @version $Id$
    */
  -public class CharSet {
  +public class CharSet implements Serializable {
   
  -    private List set = new LinkedList();
  +    /** Serialization lock, Lang version 2.0 */
  +    static final long serialVersionUID = 5947847346149275958L;
  +    
  +    /** A CharSet defining no characters */
  +    public static final CharSet EMPTY = new CharSet((String) null);
  +    /** A CharSet defining ASCII alphabetic characters "a-zA-Z" */
  +    public static final CharSet ASCII_ALPHA = new CharSet("a-zA-Z");
  +    /** A CharSet defining ASCII alphabetic characters "a-z" */
  +    public static final CharSet ASCII_ALPHA_LOWER = new CharSet("a-z");
  +    /** A CharSet defining ASCII alphabetic characters "A-Z" */
  +    public static final CharSet ASCII_ALPHA_UPPER = new CharSet("A-Z");
  +    /** A CharSet defining ASCII alphabetic characters "0-9" */
  +    public static final CharSet ASCII_NUMERIC = new CharSet("0-9");
  +    
  +    /**
  +     * A Map of the common cases used in the factory.
  +     * Subclasses can add more common patterns if desired.
  +     */
  +    protected static final Map COMMON = new HashMap();
  +    static {
  +        COMMON.put(null, EMPTY);
  +        COMMON.put("", EMPTY);
  +        COMMON.put("a-zA-Z", ASCII_ALPHA);
  +        COMMON.put("A-Za-z", ASCII_ALPHA);
  +        COMMON.put("a-z", ASCII_ALPHA_LOWER);
  +        COMMON.put("A-Z", ASCII_ALPHA_UPPER);
  +        COMMON.put("0-9", ASCII_NUMERIC);
  +    }
  +    
  +    /** Shared range for the dash character */
  +    private static final CharRange DASH = new CharRange('-');
  +    /** Shared range for the negate character */
  +    private static final CharRange NEGATE = new CharRange('^');
  +    
  +    /** The set of CharRange objects */
  +    private Set set = new HashSet();
   
  +    //-----------------------------------------------------------------------
       /**
  -     * <p>Restricted constructor.</p>
  +     * <p>Factory method to create a new CharSet using a special syntax.</p>
  +     * 
  +     * <ul>
  +     *  <li><code>null</code> or empty string ("")
  +     * - set containing no characters</li>
  +     *  <li>Single character, such as "a"
  +     *  - set containing just that character</li>
  +     *  <li>Multi character, such as "a-e"
  +     *  - set containing characters from one character to the other</li>
  +     *  <li>Negated, such as "^a" or "^a-e"
  +     *  - set containing all characters except those defined</li>
  +     *  <li>Combinations, such as "abe-g"
  +     *  - set containing all the characters from the individual sets</li>
  +     * </ul>
  +     * 
  +     * <p>If the same range is defined twice using the same syntax, only
  +     * one range will be kept.
  +     * Thus, "a-ca-c" creates only one range of "a-c".
  +     * However, "a-cabc" creates two ranges as they are defined differently.</p>
        *
  -     * <p>Use the factory method
  -     * {@link CharSetUtils#evaluateSet(java.lang.String[])}.</p>
  +     * <p>All CharSet objects returned by this method will be immutable.</p>
  +     * 
  +     * @param setStr  the String describing the set, may be null
        */
  -    protected CharSet(String set) {
  -        add(set);
  +    public static CharSet getInstance(String setStr) {
  +        Object set = COMMON.get(setStr);
  +        if (set != null) {
  +            return (CharSet) set;
  +        }
  +        return new CharSet(setStr);
       }
   
  +    //-----------------------------------------------------------------------
       /**
  -     * <p>Restricted constructor.</p>
  +     * <p>Constructs a new CharSet using the set syntax.</p>
        *
  -     * <p>Use the factory method
  -     * {@link CharSetUtils#evaluateSet(java.lang.String[])}.</p>
  +     * @param setStr  the String describing the set, may be null
  +     */
  +    protected CharSet(String setStr) {
  +        super();
  +        add(setStr);
  +    }
  +
  +    /**
  +     * <p>Constructs a new CharSet using the set syntax.
  +     * Each string is merged in with the set.</p>
        *
        * @throws NullPointerException if set is <code>null</code>
        */
       protected CharSet(String[] set) {
  +        super();
           int sz = set.length;
           for (int i = 0; i < sz; i++) {
               add(set[i]);
           }
       }
   
  +    //-----------------------------------------------------------------------
  +    /**
  +     * <p>Add a set definition string to the <code>CharSet</code>.</p>
  +     * 
  +     * @param str  set definition string
  +     */
  +    protected void add(String str) {
  +        if (str == null) {
  +            return;
  +        }
  +
  +        int len = str.length();
  +        switch (len) {
  +            case 0:
  +            // do nothing
  +            break;
  +            
  +            case 1:
  +            set.add(new CharRange(str.charAt(0)));
  +            break;
  +            
  +            default:
  +            int start = -1;
  +            boolean negated = false;
  +            for (int i = 0; i < len; i++) {
  +                char ch = str.charAt(i);
  +                if (ch == '-') {
  +                    if (start == -1) {
  +                        // dash found not as range separator
  +                        // treat as ordinary start block char
  +                        start = ch; 
  +                    } else if (i == len - 1) {
  +                        // dash is last character, store two single characters
  +                        set.add(new CharRange((char) start, (char) start, negated));
  +                        set.add(DASH);
  +                        start = -1;
  +                        negated = false;
  +                    } else {
  +                        // range block found, store it
  +                        set.add(new CharRange((char) start, str.charAt(++i), negated));
  +                        start = -1;
  +                        negated = false;
  +                    }
  +                } else if (ch == '^') {
  +                    if (start == -1) {
  +                        if (negated) {
  +                            // double negate, treat second as ordinary start block char
  +                            start = ch;
  +                        } else {
  +                            // negate next block
  +                            negated = true;
  +                        }
  +                    } else {
  +                        // previous block has ended, store it
  +                        set.add(new CharRange((char) start, (char) start, negated));
  +                        start = -1;
  +                        negated = true;
  +                    }
  +                } else {
  +                    if (start == -1) {
  +                        // start of block
  +                        start = ch;
  +                    } else {
  +                        // previous block has ended, store it, and start next block
  +                        set.add(new CharRange((char) start, (char) start, negated));
  +                        start = ch;
  +                        negated = false;
  +                    }
  +                }
  +            }
  +            // handle leftovers
  +            if (start != -1) {
  +                set.add(new CharRange((char) start, (char) start, negated));
  +            } else if (negated) {
  +                set.add(NEGATE);
  +            }
  +            break;
  +        }
  +    }
  +
  +    //-----------------------------------------------------------------------
  +    /**
  +     * <p>Gets the internal set as an array of CharRange objects.</p>
  +     * 
  +     * @return an array of immutable CharRange objects
  +     */
  +    public CharRange[] getCharRanges() {
  +        return (CharRange[]) set.toArray(new CharRange[set.size()]);
  +    }
  +    
  +    //-----------------------------------------------------------------------
       /**
        * <p>Does the <code>CharSet</code> contain the specified
        * character <code>ch</code>.</p>
        * 
        * @param ch  the character to check for
  -     * @return <code>true</code> if it does contain the character
  -     *  <code>ch</code>
  +     * @return <code>true</code> if the set contains the characters
        */
       public boolean contains(char ch) {
  -        Iterator iterator = set.iterator();
  -        boolean bool = false;
  -        while (iterator.hasNext()) {
  -            CharRange range = (CharRange) iterator.next();
  -            if (range.isNegated()) {
  -                if (!range.inRange(ch)) {
  -                    bool = true;
  -                }
  -            } else {
  -                if (range.inRange(ch)) {
  -                    bool = true;
  -                }
  +        for (Iterator it = set.iterator(); it.hasNext();) {
  +            CharRange range = (CharRange) it.next();
  +            if (range.contains(ch)) {
  +                return true;
               }
           }
  -        return bool;
  +        return false;
       }
   
  +    // Basics
  +    //-----------------------------------------------------------------------
       /**
  -     * <p>Add a set definition string to the <code>CharSet</code>.</p>
  +     * <p>Compares two CharSet objects, returning true if they represent
  +     * exactly the same set of characters defined in the same way.</p>
        * 
  -     * @param str  set definition string
  +     * <p>The two sets <code>abc</code> and <code>a-c</code> are <i>not</i>
  +     * equal according to this method.</p>
  +     * 
  +     * 
  +     * @param obj  the object to compare to
  +     * @return true if equal
        */
  -    protected void add(String str) {
  -        if (str == null) {
  -            return;
  +    public boolean equals(Object obj) {
  +        if (obj == this) {
  +            return true;
           }
  -        int sz = str.length();
  -        CharRange range = null;
  -
  -        if ("-".equals(str)) {
  -            range = new CharRange('-');
  -            set.add(range);
  -            return;
  -        }
  -
  -        boolean end = false;
  -        boolean negated = false;
  -        for (int i = 0; i < sz; i++) {
  -            char ch = str.charAt(i);
  -            if (ch == '-') {
  -                end = true;
  -                continue;
  -            }
  -            if (end) {
  -                range.setEnd(ch);
  -                continue;
  -            }
  -            if (ch == '^') {
  -                negated = true;
  -                continue;
  -            }
  -            range = new CharRange(ch);
  -            range.setNegated(negated);
  -            set.add(range);
  +        if (obj instanceof CharSet == false) {
  +            return false;
           }
  +        CharSet other = (CharSet) obj;
  +        return (set.equals(other.set));
       }
   
       /**
  -     * <p>Returns a string representation of the set.</p>
  +     * <p>Gets a hashCode compatable with the equals method.</p>
  +     * 
  +     * @return a suitable hashCode
  +     */
  +    public int hashCode() {
  +        return 89 + set.hashCode();
  +    }
  +    
  +    /**
  +     * <p>Gets a string representation of the set.</p>
        * 
  -     * @return string representation
  +     * @return string representation of the set
        */
       public String toString() {
           return set.toString();
  
  
  
  1.10      +127 -86   jakarta-commons/lang/src/java/org/apache/commons/lang/CharRange.java
  
  Index: CharRange.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/lang/src/java/org/apache/commons/lang/CharRange.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- CharRange.java	2 Aug 2003 11:20:49 -0000	1.9
  +++ CharRange.java	2 Aug 2003 18:18:33 -0000	1.10
  @@ -53,159 +53,200 @@
    */
   package org.apache.commons.lang;
   
  +import java.io.Serializable;
  +
   /**
  - * <p>A range of characters. Able to understand the idea of a contiguous
  - * sublist of an alphabet, a negated concept, and a set of characters.</p>
  - *
  - * <p>Used by <code>CharSet</code> to handle sets of characters.</p>
  + * <p>A contiguous range of characters, optionally negated.</p>
  + * 
  + * <p>This class is immutable.</p>
    *
  - * @author <a href="bayard@generationjava.com">Henri Yandell</a>
  + * @author Henri Yandell
    * @author Stephen Colebourne
    * @author Chris Feldhacker
    * @since 1.0
    * @version $Id$
    */
  -class CharRange {
  -
  -    /**
  -     * <p>Used internally to represent <code>null</code> in a char.</p>
  -     */
  -    private static final char UNSET = 0;
  +public final class CharRange implements Serializable {
   
  -    private char start;
  -    private char close;
  -    private boolean negated;
  +    /** Serialization lock, Lang version 2.0 */
  +    static final long serialVersionUID = 8270183163158333422L;
  +    
  +    /** The first character, inclusive, in the range */
  +    private final char start;
  +    /** The last character, inclusive, in the range */
  +    private final char end;
  +    /** True if the range is everything except the characters specified */
  +    private final boolean negated;
  +    
  +    /** Cached toString */
  +    private transient String iToString;
   
  +    //-----------------------------------------------------------------------
       /**
  -     * <p>Construct a <code>CharRange</code> over a single character.</p>
  +     * <p>Constructs a <code>CharRange</code> over a single character.</p>
        *
  -     * @param start char over which this range is placed
  +     * @param ch  only character in this range
        */
  -    public CharRange(char start) {
  -        this.start = start;
  +    public CharRange(char ch) {
  +        this(ch, ch, false);
       }
   
       /**
  -     * <p>Construct a <code>CharRange</code> over a set of characters.</p>
  +     * <p>Constructs a <code>CharRange</code> over a set of characters.</p>
        *
  -     * @param start  char start character in this range. inclusive
  -     * @param close  char close character in this range. inclusive
  +     * @param start  first character, inclusive, in this range
  +     * @param end  last character, inclusive, in this range
        */
  -    public CharRange(char start, char close) {
  -        this.start = start;
  -        this.close = close;
  +    public CharRange(char start, char end) {
  +        this(start, end, false);
       }
   
       /**
  -     * <p>Construct a <code>CharRange</code> over a set of characters.</p>
  +     * <p>Constructs a <code>CharRange</code> over a set of characters,
  +     * optionally negating the range.</p>
  +     *
  +     * <p>A negated range includes everything except that defined by the
  +     * start and end characters.</p>
  +     * 
  +     * <p>If start and end are in the wrong order, they are reversed.
  +     * Thus <code>a-e</code> is the same as <code>e-a</code>.</p>
        *
  -     * @param start  String start first character is in this range (inclusive).
  -     * @param close  String first character is close character in this
  -     *  range (inclusive).
  -     * @throws NullPointerException if either String is <code>null</code>
  +     * @param start  first character, inclusive, in this range
  +     * @param end  last character, inclusive, in this range
  +     * @param negated  true to express everything except the range
        */
  -    public CharRange(String start, String close) {
  -        this.start = start.charAt(0);
  -        this.close = close.charAt(0);
  +    public CharRange(char start, char end, boolean negated) {
  +        super();
  +        if (start > end) {
  +            char temp = start;
  +            start = end;
  +            end = temp;
  +        }
  +        
  +        this.start = start;
  +        this.end = end;
  +        this.negated = negated;
       }
   
  +    // Accessors
  +    //-----------------------------------------------------------------------
       /**
  -     * <p>Get the start character for this character range.</p>
  +     * <p>Gets the start character for this character range.</p>
        * 
  -     * @return start char (inclusive)
  +     * @return the start char (inclusive)
        */
       public char getStart() {
           return this.start;
       }
   
       /**
  -     * <p>Get the end character for this character range.</p>
  +     * <p>Gets the end character for this character range.</p>
        * 
  -     * @return end char (inclusive)
  +     * @return the end char (inclusive)
        */
       public char getEnd() {
  -        return this.close;
  +        return this.end;
       }
   
       /**
  -     * <p>Set the start character for this character range.</p>
  +     * <p>Is this <code>CharRange</code> negated.</p>
        * 
  -     * @param ch  start char (inclusive)
  -     */
  -    public void setStart(char ch) {
  -        this.start = ch;
  -    }
  -
  -    /**
  -     * <p>Set the end character for this character range.</p>
  -     * 
  -     * @param ch  start char (inclusive)
  +     * <p>A negated range includes everything except that defined by the
  +     * start and end characters.</p>
  +     *
  +     * @return <code>true</code> is negated
        */
  -    public void setEnd(char ch) {
  -        this.close = ch;
  +    public boolean isNegated() {
  +        return negated;
       }
   
  +    // Contains
  +    //-----------------------------------------------------------------------
       /**
  -     * <p>Is this <code>CharRange</code> over many characters.</p>
  +     * <p>Is the character specified contained in this range.</p>
        *
  -     * @return boolean <code>true</code> is many characters
  +     * @param ch  the character to check
  +     * @return <code>true</code> if this range contains the input character
        */
  -    public boolean isRange() {
  -        return this.close != UNSET;
  +    public boolean contains(char ch) {
  +        return ((ch >= start && ch <= end) != negated);
       }
   
       /**
  -     * <p>Is the passed in character <code>ch</code> inside
  +     * <p>Are all the characters of the passed in range contained in
        * this range.</p>
        *
  -     * @param ch character to test for
  -     * @return boolean <code>true</code> is in range
  -     */
  -    public boolean inRange(char ch) {
  -        if( isRange() ) {
  -            return ((ch >= start) && (ch <= close));
  +     * @param range  the range to check against
  +     * @return <code>true</code> if this range entirely contains the input range
  +     * @throws IllegalArgumentException if <code>null</code> input
  +     */
  +    public boolean contains(CharRange range) {
  +        if (range == null) {
  +            throw new IllegalArgumentException("The Range must not be null");
  +        }
  +        if (negated) {
  +            if (range.negated) {
  +                return (start >= range.start && end <= range.end);
  +            } else {
  +                return (range.end < start || range.start > end);
  +            }
           } else {
  -            return start == ch;
  +            if (range.negated) {
  +                return (start == 0 && end == Character.MAX_VALUE);
  +            } else {
  +                return (start <= range.start && end >= range.end);
  +            }
           }
       }
   
  +    // Basics
  +    //-----------------------------------------------------------------------
       /**
  -     * <p>Checks if this <code>CharRange</code> is negated.</p>
  -     *
  -     * @return boolean <code>true</code> is negated
  +     * <p>Compares two CharRange objects, returning true if they represent
  +     * exactly the same range of characters defined in the same way.</p>
  +     * 
  +     * @param obj  the object to compare to
  +     * @return true if equal
        */
  -    public boolean isNegated() {
  -        return negated;
  +    public boolean equals(Object obj) {
  +        if (obj == this) {
  +            return true;
  +        }
  +        if (obj instanceof CharRange == false) {
  +            return false;
  +        }
  +        CharRange other = (CharRange) obj;
  +        return (start == other.start && end == other.end && negated == other.negated);
       }
   
       /**
  -     * <p>Sets this character range to be negated or not.</p>
  -     *
  -     * <p>This implies that this <code>CharRange</code> is over
  -     * all characters except the ones in this range.</p>
  +     * <p>Gets a hashCode compatable with the equals method.</p>
        * 
  -     * @param negated  <code>true</code> to negate the range
  +     * @return a suitable hashCode
        */
  -    public void setNegated(boolean negated) {
  -        this.negated = negated;
  +    public int hashCode() {
  +        return 83 + start + 7 * end + (negated ? 1 : 0);
       }
  -
  +    
       /**
  -     * <p>Output a string representation of the character range.</p>
  +     * <p>Gets a string representation of the character range.</p>
        * 
        * @return string representation of this range
        */
       public String toString() {
  -        StringBuffer buf = new StringBuffer(4);
  -        if (isNegated()) {
  -            buf.append('^');
  -        }
  -        buf.append(start);
  -        if (isRange()) {
  -            buf.append('-');
  -            buf.append(close);
  +        if (iToString == null) {
  +            StringBuffer buf = new StringBuffer(4);
  +            if (isNegated()) {
  +                buf.append('^');
  +            }
  +            buf.append(start);
  +            if (start != end) {
  +                buf.append('-');
  +                buf.append(end);
  +            }
  +            iToString = buf.toString();
           }
  -        return buf.toString();
  +        return iToString;
       }
       
   }
  
  
  
  1.19      +3 -1      jakarta-commons/lang/src/test/org/apache/commons/lang/LangTestSuite.java
  
  Index: LangTestSuite.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/lang/src/test/org/apache/commons/lang/LangTestSuite.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- LangTestSuite.java	24 May 2003 12:11:02 -0000	1.18
  +++ LangTestSuite.java	2 Aug 2003 18:18:33 -0000	1.19
  @@ -90,6 +90,8 @@
           suite.setName("Commons-Lang Tests");
           suite.addTest(ArrayUtilsTest.suite());
           suite.addTest(BooleanUtilsTest.suite());
  +        suite.addTest(CharRangeTest.suite());
  +        suite.addTest(CharSetTest.suite());
           suite.addTest(CharSetUtilsTest.suite());
           suite.addTest(ClassUtilsTest.suite());
           suite.addTest(EntitiesTest.suite());
  
  
  
  1.1                  jakarta-commons/lang/src/test/org/apache/commons/lang/CharSetTest.java
  
  Index: CharSetTest.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.commons.lang;
  
  import java.lang.reflect.Modifier;
  
  import junit.framework.Test;
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  import junit.textui.TestRunner;
  
  /**
   * Unit tests {@link org.apache.commons.lang.CharSet}.
   *
   * @author Stephen Colebourne
   * @version $Id: CharSetTest.java,v 1.1 2003/08/02 18:18:33 scolebourne Exp $
   */
  public class CharSetTest extends TestCase {
      
      public CharSetTest(String name) {
          super(name);
      }
  
      public static void main(String[] args) {
          TestRunner.run(suite());
      }
  
      public static Test suite() {
          TestSuite suite = new TestSuite(CharSetTest.class);
          suite.setName("CharSet Tests");
          return suite;
      }
  
      protected void setUp() throws Exception {
          super.setUp();
      }
  
      protected void tearDown() throws Exception {
          super.tearDown();
      }
  
      //-----------------------------------------------------------------------
      public void testClass() {
          assertEquals(true, Modifier.isPublic(CharSet.class.getModifiers()));
          assertEquals(false, Modifier.isFinal(CharSet.class.getModifiers()));
      }
      
      //-----------------------------------------------------------------------
      public void testGetInstance() {
          assertSame(CharSet.EMPTY, CharSet.getInstance(null));
          assertSame(CharSet.EMPTY, CharSet.getInstance(""));
          assertSame(CharSet.ASCII_ALPHA, CharSet.getInstance("a-zA-Z"));
          assertSame(CharSet.ASCII_ALPHA, CharSet.getInstance("A-Za-z"));
          assertSame(CharSet.ASCII_ALPHA_LOWER, CharSet.getInstance("a-z"));
          assertSame(CharSet.ASCII_ALPHA_UPPER, CharSet.getInstance("A-Z"));
          assertSame(CharSet.ASCII_NUMERIC, CharSet.getInstance("0-9"));
      }
              
      //-----------------------------------------------------------------------
      public void testConstructor_String_simple() {
          CharSet set;
          CharRange[] array;
          
          set = CharSet.getInstance((String) null);
          array = set.getCharRanges();
          assertEquals("[]", set.toString());
          assertEquals(0, array.length);
          
          set = CharSet.getInstance("");
          array = set.getCharRanges();
          assertEquals("[]", set.toString());
          assertEquals(0, array.length);
          
          set = CharSet.getInstance("a");
          array = set.getCharRanges();
          assertEquals("[a]", set.toString());
          assertEquals(1, array.length);
          assertEquals("a", array[0].toString());
          
          set = CharSet.getInstance("^a");
          array = set.getCharRanges();
          assertEquals("[^a]", set.toString());
          assertEquals(1, array.length);
          assertEquals("^a", array[0].toString());
          
          set = CharSet.getInstance("a-e");
          array = set.getCharRanges();
          assertEquals("[a-e]", set.toString());
          assertEquals(1, array.length);
          assertEquals("a-e", array[0].toString());
          
          set = CharSet.getInstance("^a-e");
          array = set.getCharRanges();
          assertEquals("[^a-e]", set.toString());
          assertEquals(1, array.length);
          assertEquals("^a-e", array[0].toString());
      }
      
      public void testConstructor_String_combo() {
          CharSet set;
          CharRange[] array;
          
          set = CharSet.getInstance("abc");
          array = set.getCharRanges();
          assertEquals(3, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('b')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('c')));
          
          set = CharSet.getInstance("a-ce-f");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', 'c')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('e', 'f')));
          
          set = CharSet.getInstance("ae-f");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('e', 'f')));
          
          set = CharSet.getInstance("e-fa");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('e', 'f')));
          
          set = CharSet.getInstance("ae-fm-pz");
          array = set.getCharRanges();
          assertEquals(4, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('e', 'f')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('m', 'p')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('z')));
      }
      
      public void testConstructor_String_comboNegated() {
          CharSet set;
          CharRange[] array;
          
          set = CharSet.getInstance("^abc");
          array = set.getCharRanges();
          assertEquals(3, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', 'a', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('b')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('c')));
          
          set = CharSet.getInstance("b^ac");
          array = set.getCharRanges();
          assertEquals(3, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('b')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', 'a', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('c')));
          
          set = CharSet.getInstance("db^ac");
          array = set.getCharRanges();
          assertEquals(4, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('d')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('b')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', 'a', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('c')));
          
          set = CharSet.getInstance("^b^a");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('b', 'b', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', 'a', true)));
          
          set = CharSet.getInstance("b^a-c^z");
          array = set.getCharRanges();
          assertEquals(3, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', 'c', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('z', 'z', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('b')));
      }
          
      public void testConstructor_String_oddDash() {
          CharSet set;
          CharRange[] array;
          
          set = CharSet.getInstance("-");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('-')));
          
          set = CharSet.getInstance("--");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('-')));
          
          set = CharSet.getInstance("---");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('-')));
          
          set = CharSet.getInstance("----");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('-')));
          
          set = CharSet.getInstance("-a");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('-')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a')));
          
          set = CharSet.getInstance("a-");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('-')));
          
          set = CharSet.getInstance("a--");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', '-')));
          
          set = CharSet.getInstance("--a");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('-', 'a')));
      }
      
      public void testConstructor_String_oddNegate() {
          CharSet set;
          CharRange[] array;
          set = CharSet.getInstance("^");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('^')));
          
          set = CharSet.getInstance("^^");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('^', '^', true)));
          
          set = CharSet.getInstance("^^^");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('^', '^', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('^', '^')));
          
          set = CharSet.getInstance("^^^^");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('^', '^', true)));
          
          set = CharSet.getInstance("a^");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('^')));
          
          set = CharSet.getInstance("^a-");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', 'a', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('-')));
          
          set = CharSet.getInstance("^^-c");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('^', 'c', true)));
          
          set = CharSet.getInstance("^c-^");
          array = set.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('c', '^', true)));
          
          set = CharSet.getInstance("^c-^d");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('c', '^', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('d')));
          
          set = CharSet.getInstance("^^-");
          array = set.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('^', '^', true)));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('-')));
      }
      
      //-----------------------------------------------------------------------    
      public void testEquals_Object() {
          CharSet abc = CharSet.getInstance("abc");
          CharSet abc2 = CharSet.getInstance("abc");
          CharSet atoc = CharSet.getInstance("a-c");
          CharSet atoc2 = CharSet.getInstance("a-c");
          CharSet notatoc = CharSet.getInstance("^a-c");
          CharSet notatoc2 = CharSet.getInstance("^a-c");
          
          assertEquals(false, abc.equals(null));
          
          assertEquals(true, abc.equals(abc));
          assertEquals(true, abc.equals(abc2));
          assertEquals(false, abc.equals(atoc));
          assertEquals(false, abc.equals(notatoc));
          
          assertEquals(false, atoc.equals(abc));
          assertEquals(true, atoc.equals(atoc));
          assertEquals(true, atoc.equals(atoc2));
          assertEquals(false, atoc.equals(notatoc));
          
          assertEquals(false, notatoc.equals(abc));
          assertEquals(false, notatoc.equals(atoc));
          assertEquals(true, notatoc.equals(notatoc));
          assertEquals(true, notatoc.equals(notatoc2));
      }
              
      public void testHashCode() {
          CharSet abc = CharSet.getInstance("abc");
          CharSet abc2 = CharSet.getInstance("abc");
          CharSet atoc = CharSet.getInstance("a-c");
          CharSet atoc2 = CharSet.getInstance("a-c");
          CharSet notatoc = CharSet.getInstance("^a-c");
          CharSet notatoc2 = CharSet.getInstance("^a-c");
          
          assertEquals(abc.hashCode(), abc.hashCode());
          assertEquals(abc.hashCode(), abc2.hashCode());
          assertEquals(atoc.hashCode(), atoc.hashCode());
          assertEquals(atoc.hashCode(), atoc2.hashCode());
          assertEquals(notatoc.hashCode(), notatoc.hashCode());
          assertEquals(notatoc.hashCode(), notatoc2.hashCode());
      }
      
      //-----------------------------------------------------------------------    
      public void testContains_Char() {
          CharSet btod = CharSet.getInstance("b-d");
          CharSet bcd = CharSet.getInstance("bcd");
          CharSet bd = CharSet.getInstance("bd");
          CharSet notbtod = CharSet.getInstance("^b-d");
          
          assertEquals(false, btod.contains('a'));
          assertEquals(true, btod.contains('b'));
          assertEquals(true, btod.contains('c'));
          assertEquals(true, btod.contains('d'));
          assertEquals(false, btod.contains('e'));
          
          assertEquals(false, bcd.contains('a'));
          assertEquals(true, bcd.contains('b'));
          assertEquals(true, bcd.contains('c'));
          assertEquals(true, bcd.contains('d'));
          assertEquals(false, bcd.contains('e'));
          
          assertEquals(false, bd.contains('a'));
          assertEquals(true, bd.contains('b'));
          assertEquals(false, bd.contains('c'));
          assertEquals(true, bd.contains('d'));
          assertEquals(false, bd.contains('e'));
          
          assertEquals(true, notbtod.contains('a'));
          assertEquals(false, notbtod.contains('b'));
          assertEquals(false, notbtod.contains('c'));
          assertEquals(false, notbtod.contains('d'));
          assertEquals(true, notbtod.contains('e'));
      }
      
      //-----------------------------------------------------------------------    
      public void testSerialization() {
          CharSet set = CharSet.getInstance("a");
          assertEquals(set, SerializationUtils.clone(set)); 
          set = CharSet.getInstance("a-e");
          assertEquals(set, SerializationUtils.clone(set)); 
          set = CharSet.getInstance("be-f^a-z");
          assertEquals(set, SerializationUtils.clone(set)); 
      }
      
      //-----------------------------------------------------------------------    
      public void testStatics() {
          CharRange[] array;
          
          array = CharSet.EMPTY.getCharRanges();
          assertEquals(0, array.length);
          
          array = CharSet.ASCII_ALPHA.getCharRanges();
          assertEquals(2, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', 'z')));
          assertEquals(true, ArrayUtils.contains(array, new CharRange('A', 'Z')));
          
          array = CharSet.ASCII_ALPHA_LOWER.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('a', 'z')));
          
          array = CharSet.ASCII_ALPHA_UPPER.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('A', 'Z')));
          
          array = CharSet.ASCII_NUMERIC.getCharRanges();
          assertEquals(1, array.length);
          assertEquals(true, ArrayUtils.contains(array, new CharRange('0', '9')));
      }
      
  }
  
  
  
  1.1                  jakarta-commons/lang/src/test/org/apache/commons/lang/CharRangeTest.java
  
  Index: CharRangeTest.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.commons.lang;
  
  import java.lang.reflect.Modifier;
  
  import junit.framework.Test;
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  import junit.textui.TestRunner;
  
  /**
   * Unit tests {@link org.apache.commons.lang.CharRange}.
   *
   * @author Stephen Colebourne
   * @version $Id: CharRangeTest.java,v 1.1 2003/08/02 18:18:33 scolebourne Exp $
   */
  public class CharRangeTest extends TestCase {
      
      public CharRangeTest(String name) {
          super(name);
      }
  
      public static void main(String[] args) {
          TestRunner.run(suite());
      }
  
      public static Test suite() {
          TestSuite suite = new TestSuite(CharRangeTest.class);
          suite.setName("CharRange Tests");
          return suite;
      }
  
      protected void setUp() throws Exception {
          super.setUp();
      }
  
      protected void tearDown() throws Exception {
          super.tearDown();
      }
  
      //-----------------------------------------------------------------------
      public void testClass() {
          assertEquals(true, Modifier.isPublic(CharRange.class.getModifiers()));
          assertEquals(true, Modifier.isFinal(CharRange.class.getModifiers()));
      }
      
      //-----------------------------------------------------------------------
      public void testConstructorAccessors_Char() {
          CharRange rangea = new CharRange('a');
          CharRange rangeb = new CharRange('b');
          assertEquals('a', rangea.getStart());
          assertEquals('a', rangea.getEnd());
          assertEquals(false, rangea.isNegated());
          assertEquals("a", rangea.toString());
      }
      
      public void testConstructorAccessors_CharChar_Same() {
          CharRange rangea = new CharRange('a', 'a');
          assertEquals('a', rangea.getStart());
          assertEquals('a', rangea.getEnd());
          assertEquals(false, rangea.isNegated());
          assertEquals("a", rangea.toString());
      }
      
      public void testConstructorAccessors_CharChar_Normal() {
          CharRange rangea = new CharRange('a', 'e');
          assertEquals('a', rangea.getStart());
          assertEquals('e', rangea.getEnd());
          assertEquals(false, rangea.isNegated());
          assertEquals("a-e", rangea.toString());
      }
      
      public void testConstructorAccessors_CharChar_Reversed() {
          CharRange rangea = new CharRange('e', 'a');
          assertEquals('a', rangea.getStart());
          assertEquals('e', rangea.getEnd());
          assertEquals(false, rangea.isNegated());
          assertEquals("a-e", rangea.toString());
      }
      
      public void testConstructorAccessors_CharCharBoolean_Same() {
          CharRange rangea = new CharRange('a', 'a', false);
          assertEquals('a', rangea.getStart());
          assertEquals('a', rangea.getEnd());
          assertEquals(false, rangea.isNegated());
          assertEquals("a", rangea.toString());
      }
      
      public void testConstructorAccessors_CharCharBoolean_Normal() {
          CharRange rangea = new CharRange('a', 'e', false);
          assertEquals('a', rangea.getStart());
          assertEquals('e', rangea.getEnd());
          assertEquals(false, rangea.isNegated());
          assertEquals("a-e", rangea.toString());
      }
      
      public void testConstructorAccessors_CharCharBoolean_Reversed() {
          CharRange rangea = new CharRange('e', 'a', false);
          assertEquals('a', rangea.getStart());
          assertEquals('e', rangea.getEnd());
          assertEquals(false, rangea.isNegated());
          assertEquals("a-e", rangea.toString());
      }
      
      public void testConstructorAccessors_CharCharBoolean_SameNegated() {
          CharRange rangea = new CharRange('a', 'a', true);
          assertEquals('a', rangea.getStart());
          assertEquals('a', rangea.getEnd());
          assertEquals(true, rangea.isNegated());
          assertEquals("^a", rangea.toString());
      }
      
      public void testConstructorAccessors_CharCharBoolean_NormalNegated() {
          CharRange rangea = new CharRange('a', 'e', true);
          assertEquals('a', rangea.getStart());
          assertEquals('e', rangea.getEnd());
          assertEquals(true, rangea.isNegated());
          assertEquals("^a-e", rangea.toString());
      }
      
      public void testConstructorAccessors_CharCharBoolean_ReversedNegated() {
          CharRange rangea = new CharRange('e', 'a', true);
          assertEquals('a', rangea.getStart());
          assertEquals('e', rangea.getEnd());
          assertEquals(true, rangea.isNegated());
          assertEquals("^a-e", rangea.toString());
      }
  
      //-----------------------------------------------------------------------    
      public void testEquals_Object() {
          CharRange rangea = new CharRange('a');
          CharRange rangeae = new CharRange('a', 'e');
          CharRange rangenotbf = new CharRange('b', 'f', false);
          
          assertEquals(false, rangea.equals(null));
          
          assertEquals(true, rangea.equals(rangea));
          assertEquals(true, rangea.equals(new CharRange('a')));
          assertEquals(true, rangeae.equals(rangeae));
          assertEquals(true, rangeae.equals(new CharRange('a', 'e')));
          assertEquals(true, rangenotbf.equals(rangenotbf));
          assertEquals(true, rangenotbf.equals(new CharRange('b', 'f', false)));
          
          assertEquals(false, rangea.equals(rangeae));
          assertEquals(false, rangea.equals(rangenotbf));
          assertEquals(false, rangeae.equals(rangea));
          assertEquals(false, rangeae.equals(rangenotbf));
          assertEquals(false, rangenotbf.equals(rangea));
          assertEquals(false, rangenotbf.equals(rangeae));
      }
              
      public void testHashCode() {
          CharRange rangea = new CharRange('a');
          CharRange rangeae = new CharRange('a', 'e');
          CharRange rangenotbf = new CharRange('b', 'f', false);
          
          assertEquals(true, rangea.hashCode() == rangea.hashCode());
          assertEquals(true, rangea.hashCode() == new CharRange('a').hashCode());
          assertEquals(true, rangeae.hashCode() == rangeae.hashCode());
          assertEquals(true, rangeae.hashCode() == new CharRange('a', 'e').hashCode());
          assertEquals(true, rangenotbf.hashCode() == rangenotbf.hashCode());
          assertEquals(true, rangenotbf.hashCode() == new CharRange('b', 'f', false).hashCode());
          
          assertEquals(false, rangea.hashCode() == rangeae.hashCode());
          assertEquals(false, rangea.hashCode() == rangenotbf.hashCode());
          assertEquals(false, rangeae.hashCode() == rangea.hashCode());
          assertEquals(false, rangeae.hashCode() == rangenotbf.hashCode());
          assertEquals(false, rangenotbf.hashCode() == rangea.hashCode());
          assertEquals(false, rangenotbf.hashCode() == rangeae.hashCode());
      }
      
      //-----------------------------------------------------------------------    
      public void testContains_Char() {
          CharRange range = new CharRange('c');
          assertEquals(false, range.contains('b'));
          assertEquals(true, range.contains('c'));
          assertEquals(false, range.contains('d'));
          assertEquals(false, range.contains('e'));
          
          range = new CharRange('c', 'd');
          assertEquals(false, range.contains('b'));
          assertEquals(true, range.contains('c'));
          assertEquals(true, range.contains('d'));
          assertEquals(false, range.contains('e'));
          
          range = new CharRange('d', 'c');
          assertEquals(false, range.contains('b'));
          assertEquals(true, range.contains('c'));
          assertEquals(true, range.contains('d'));
          assertEquals(false, range.contains('e'));
          
          range = new CharRange('c', 'd', false);
          assertEquals(false, range.contains('b'));
          assertEquals(true, range.contains('c'));
          assertEquals(true, range.contains('d'));
          assertEquals(false, range.contains('e'));
          
          range = new CharRange('c', 'd', true);
          assertEquals(true, range.contains('b'));
          assertEquals(false, range.contains('c'));
          assertEquals(false, range.contains('d'));
          assertEquals(true, range.contains('e'));
          assertEquals(true, range.contains((char) 0));
          assertEquals(true, range.contains(Character.MAX_VALUE));
      }
      
      //-----------------------------------------------------------------------    
      public void testContains_Charrange() {
          CharRange a = new CharRange('a');
          CharRange b = new CharRange('b');
          CharRange c = new CharRange('c');
          CharRange c2 = new CharRange('c');
          CharRange d = new CharRange('d');
          CharRange e = new CharRange('e');
          CharRange cd = new CharRange('c', 'd');
          CharRange bd = new CharRange('b', 'd');
          CharRange bc = new CharRange('b', 'c');
          CharRange ab = new CharRange('a', 'b');
          CharRange de = new CharRange('d', 'e');
          CharRange ef = new CharRange('e', 'f');
          CharRange ae = new CharRange('a', 'e');
          
          // normal/normal
          assertEquals(false, c.contains(b));
          assertEquals(true, c.contains(c));
          assertEquals(true, c.contains(c2));
          assertEquals(false, c.contains(d));
          
          assertEquals(false, c.contains(cd));
          assertEquals(false, c.contains(bd));
          assertEquals(false, c.contains(bc));
          assertEquals(false, c.contains(ab));
          assertEquals(false, c.contains(de));
          
          assertEquals(true, cd.contains(c));
          assertEquals(true, bd.contains(c));
          assertEquals(true, bc.contains(c));
          assertEquals(false, ab.contains(c));
          assertEquals(false, de.contains(c));
  
          assertEquals(true, ae.contains(b));
          assertEquals(true, ae.contains(ab));
          assertEquals(true, ae.contains(bc));
          assertEquals(true, ae.contains(cd));
          assertEquals(true, ae.contains(de));
          
          CharRange notb = new CharRange('b', 'b', true);
          CharRange notc = new CharRange('c', 'c', true);
          CharRange notd = new CharRange('d', 'd', true);
          CharRange notab = new CharRange('a', 'b', true);
          CharRange notbc = new CharRange('b', 'c', true);
          CharRange notbd = new CharRange('b', 'd', true);
          CharRange notcd = new CharRange('c', 'd', true);
          CharRange notde = new CharRange('d', 'e', true);
          CharRange notae = new CharRange('a', 'e', true);
          CharRange all = new CharRange((char) 0, Character.MAX_VALUE);
          CharRange allbutfirst = new CharRange((char) 1, Character.MAX_VALUE);
          
          // normal/negated
          assertEquals(false, c.contains(notc));
          assertEquals(false, c.contains(notbd));
          assertEquals(true, all.contains(notc));
          assertEquals(true, all.contains(notbd));
          assertEquals(false, allbutfirst.contains(notc));
          assertEquals(false, allbutfirst.contains(notbd));
          
          // negated/normal
          assertEquals(true, notc.contains(a));
          assertEquals(true, notc.contains(b));
          assertEquals(false, notc.contains(c));
          assertEquals(true, notc.contains(d));
          assertEquals(true, notc.contains(e));
          
          assertEquals(true, notc.contains(ab));
          assertEquals(false, notc.contains(bc));
          assertEquals(false, notc.contains(bd));
          assertEquals(false, notc.contains(cd));
          assertEquals(true, notc.contains(de));
          assertEquals(false, notc.contains(ae));
          assertEquals(false, notc.contains(all));
          assertEquals(false, notc.contains(allbutfirst));
          
          assertEquals(true, notbd.contains(a));
          assertEquals(false, notbd.contains(b));
          assertEquals(false, notbd.contains(c));
          assertEquals(false, notbd.contains(d));
          assertEquals(true, notbd.contains(e));
          
          assertEquals(true, notcd.contains(ab));
          assertEquals(false, notcd.contains(bc));
          assertEquals(false, notcd.contains(bd));
          assertEquals(false, notcd.contains(cd));
          assertEquals(false, notcd.contains(de));
          assertEquals(false, notcd.contains(ae));
          assertEquals(true, notcd.contains(ef));
          assertEquals(false, notcd.contains(all));
          assertEquals(false, notcd.contains(allbutfirst));
          
          // negated/negated
          assertEquals(false, notc.contains(notb));
          assertEquals(true, notc.contains(notc));
          assertEquals(false, notc.contains(notd));
          
          assertEquals(false, notc.contains(notab));
          assertEquals(true, notc.contains(notbc));
          assertEquals(true, notc.contains(notbd));
          assertEquals(true, notc.contains(notcd));
          assertEquals(false, notc.contains(notde));
          
          assertEquals(false, notbd.contains(notb));
          assertEquals(false, notbd.contains(notc));
          assertEquals(false, notbd.contains(notd));
          
          assertEquals(false, notbd.contains(notab));
          assertEquals(false, notbd.contains(notbc));
          assertEquals(true, notbd.contains(notbd));
          assertEquals(false, notbd.contains(notcd));
          assertEquals(false, notbd.contains(notde));
          assertEquals(true, notbd.contains(notae));
      }
      
      //-----------------------------------------------------------------------    
      public void testSerialization() {
          CharRange range = new CharRange('a');
          assertEquals(range, SerializationUtils.clone(range)); 
          range = new CharRange('a', 'e');
          assertEquals(range, SerializationUtils.clone(range)); 
          range = new CharRange('a', 'e', true);
          assertEquals(range, SerializationUtils.clone(range)); 
      }
      
  }