You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@edgent.apache.org by dl...@apache.org on 2016/03/25 19:48:52 UTC

[1/3] incubator-quarks git commit: [QUARKS-79] tidy up Range

Repository: incubator-quarks
Updated Branches:
  refs/heads/master b3ca7ee93 -> 0b58e1531


[QUARKS-79] tidy up Range

- clarify wrt Guava Range 
- cleanup Range
- pull test code out into RangeTest

Project: http://git-wip-us.apache.org/repos/asf/incubator-quarks/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quarks/commit/31263522
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quarks/tree/31263522
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quarks/diff/31263522

Branch: refs/heads/master
Commit: 3126352211766f3e26db12be4c7a56c06d7861b0
Parents: 2f9cbe9
Author: Dale LaBossiere <dl...@us.ibm.com>
Authored: Fri Mar 25 12:50:31 2016 -0400
Committer: Dale LaBossiere <dl...@us.ibm.com>
Committed: Fri Mar 25 12:50:31 2016 -0400

----------------------------------------------------------------------
 .../samples/apps/ApplicationUtilities.java      |   2 +-
 .../main/java/quarks/samples/apps/Range.java    | 446 ++++++++++---------
 .../java/quarks/samples/apps/RangeTest.java     | 327 ++++++++++++++
 3 files changed, 563 insertions(+), 212 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/31263522/samples/apps/src/main/java/quarks/samples/apps/ApplicationUtilities.java
----------------------------------------------------------------------
diff --git a/samples/apps/src/main/java/quarks/samples/apps/ApplicationUtilities.java b/samples/apps/src/main/java/quarks/samples/apps/ApplicationUtilities.java
index 084712c..f12b0dd 100644
--- a/samples/apps/src/main/java/quarks/samples/apps/ApplicationUtilities.java
+++ b/samples/apps/src/main/java/quarks/samples/apps/ApplicationUtilities.java
@@ -124,7 +124,7 @@ public class ApplicationUtilities {
      * @param clazz the Range's type (e.g., Integer.class)
      * @return the Range<T>
      */
-    public <T> Range<T> getRange(String sensorId, String label, Class<T> clazz) {
+    public <T extends Comparable<?>> Range<T> getRange(String sensorId, String label, Class<T> clazz) {
         String name = getSensorPropertyName(sensorId, label, "range");
         String val = config().getProperty(name);
         if (val==null)

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/31263522/samples/apps/src/main/java/quarks/samples/apps/Range.java
----------------------------------------------------------------------
diff --git a/samples/apps/src/main/java/quarks/samples/apps/Range.java b/samples/apps/src/main/java/quarks/samples/apps/Range.java
index 5079b53..e9a58fe 100644
--- a/samples/apps/src/main/java/quarks/samples/apps/Range.java
+++ b/samples/apps/src/main/java/quarks/samples/apps/Range.java
@@ -4,33 +4,97 @@
 */
 package quarks.samples.apps;
 
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.util.Comparator;
+import java.util.Objects;
 
 /**
- * A range of values and and a way to check for containment.
+ * A range of values and a way to check a value for containment in the range.
  * <p>
- * Useful in filtering in predicates.  
+ * Useful in filtering in predicates.  This is a lightweight implementation
+ * of a subset of the Guava Range API.
  * <p> 
- * Poor mans Guava Range.  No analog in Apache Math?
- * TODO remove this and directly use Guava Range.
- * 
  * e.g.
  * <pre>{@code
  * Range.open(2,4).contains(2);      // returns false
- * Range.closed(2,4).contains(2);    // returns false
+ * Range.closed(2,4).contains(2);    // returns true
  * Range.atLeast(2).contains(2);     // returns true
  * Range.greaterThan(2).contains(2); // returns false
  * Range.atMost(2).contains(2);      // returns true
  * Range.lessThan(2).contains(2);    // returns false
+ * 
+ * String s = Range.closed(2,4).toString();
+ * Range<Integer> range = Range.valueOf(s, Integer.class);
+ * 
+ * TStream<Integer> intStream = ...;
+ * TStream<Integer> filtered = intStream.filter(tuple -> !range.contains(tuple));
+ * 
+ * TStream<JsonObject> jStream = ...;
+ * TStream<JsonObject> filtered = jStream.filter(json -> !range.contains(json.getProperty("reading").asInteger());
  * }</pre>
+ * 
+ * <p>
+ * Compared to Guava Range:
+ * <ul>
+ * <li>Guava Range doesn't mention any constraints with respect to types for {@code <T>}.
+ *     This Range currently supports: Integer,Long,Short,Byte,Float,Double,BigInteger,BigDecimal.
+ *     <br>String and Character, of questionable value to Quarks apps,
+ *     are avoided at this time due to the Guava toString()/from-string
+ *     items noted below.</li>
+ * <li>Guava Range doesn't support unsigned type ranges.
+ *     <br>This Range adds {@link #contains(Comparable, Comparator)}.
+ * <li>Guava Range lacks a "Range from Range.toString()" function: https://github.com/google/guava/issues/1911.
+ *     <br>This Range adds {@link #valueOf(String, Class) valueOf}.
+ *     Possibly consider: (a) migrating this to a new Ranges class,
+ *     (b) introducing convenience forms - e.g., {@code valueOfInteger(String)}.</li>
+ * <li>Guava Range has issues with to/from Json with Gson: 
+ *     https://github.com/google/guava/issues/1911.
+ *     <br>This Range works but as doc'd by Gson, use {@code Gson#fromJson(String, java.lang.reflect.Type)} Don't know about this Range :-)</li>
+ * <li>Guava Range's {@code apply(T value)} is documented as deprecated 
+ *     so this Range does not "implement Predicate". 
+ * <li>Guava Range.toString()
+ *     <ul>
+ *     <li> Guava uses some unprintable characters.
+ *          Up to the latest Guava release - 19.0, Range.toString() uses \u2025 for
+ *          the ".." separator and uses +/-\u221E for infinity.  That's caused problems:
+ *          https://github.com/google/guava/issues/2376.
+ *          Guava Range.toString() has been change to use ".." instead of \u2025.
+ *          It still uses the unicode char for infinity.
+ *          <br>This Range uses ".." for the separator like the not-yet-released Guava change.
+ *          For convenience to users, this Range uses "*" and no leading +/- for infinity.</li>
+ *      <li>Guava does not decorate String or Character values with \" or \' respectively.
+ *          It does not generate an escaped encoding of the
+ *          range separator if it is present in a value.
+ *          Hard to guess whether this may change if/when Guava adds a
+ *          "Range from Range.toString()" capability.
+ *          <br>To avoid arbitrary deviations for Range types that may not be
+ *          particularly interesting to Quarks users, at this time 
+ *          this Range does not support String or Character.
+ *          </li>
+ *      </ul>
+ *      </li>
+ * </ul>
  *
- * @param <T> value type
+ * @param <T> value type  N.B. at this time {@code T} must be one of:
+ *        Integer,Long,Short,Byte,Float,Double,BigInteger,BigDecimal
+ * <p>
+ *        An IllegalArgumentException is thrown if an unsupported type
+ *        is specified when constructing the Range.
  */
-public class Range<T> {
-    private final T lowerBound;
-    private final T upperBound;
+public class Range<T extends Comparable<?>> implements Serializable {
+    private static final long serialVersionUID = 1L;
+    
+    private final T lowerBound;  // null for infinity
+    private final T upperBound;  // null for infinity
     private final BoundType lbt;
     private final BoundType ubt;
+    private transient int hashCode;
+    private static final Class<?> supportedTypes[] = {
+            Integer.class, Short.class, Byte.class, Long.class,
+            Float.class, Double.class, BigInteger.class, BigDecimal.class
+    };
     
     private enum BoundType {/** exclusive */ OPEN, /** inclusive */ CLOSED};
     
@@ -39,55 +103,162 @@ public class Range<T> {
         this.upperBound = upperBound;
         this.lbt = lbt;
         this.ubt = ubt;
+        checkSupportedType(lowerBound);
+        checkSupportedType(upperBound);
+        if (lowerBound != null && upperBound != null) {
+            if (lowerBound.getClass() != upperBound.getClass())
+                throw new IllegalArgumentException("lowerBound and upperBound are not the same type");
+        }
+    }
+    
+    private void checkSupportedType(Object obj) {
+        if (obj==null) return;
+        Class<?> objClass = obj.getClass();
+        for (Class<?> c : supportedTypes) {
+            if (c == objClass)
+                return;
+        }
+        throw new IllegalArgumentException("unsupported type: "+objClass);
     }
     
-    // TODO defer making these public
-    private static <T> Range<T> range(T lowerBound, BoundType b1, T upperBound, BoundType b2) {  return new Range<T>(lowerBound, b1, upperBound, b2); }
+    // TODO defer making these public due to BoundType
+    private static <T extends Comparable<?>> Range<T> range(T lowerBound, BoundType b1, T upperBound, BoundType b2) {  return new Range<T>(lowerBound, b1, upperBound, b2); }
 //    public static <T> Range<T> downTo(T v, BoundType b) { return range(v, b, null, null); }
 //    public static <T> Range<T> upTo(T v, BoundType b) { return range(null, null, v, b); }
 
     /** (a..b) (both exclusive) */
-    public static <T> Range<T> open(T lowerBound, T upperBound) { return range(lowerBound, BoundType.OPEN, upperBound, BoundType.OPEN); }
+    public static <T extends Comparable<?>> Range<T> open(T lowerBound, T upperBound) { 
+        return range(lowerBound, BoundType.OPEN, upperBound, BoundType.OPEN);
+    }
     /** [a..b] (both inclusive) */
-    public static <T> Range<T> closed(T lowerBound, T upperBound) { return range(lowerBound, BoundType.CLOSED, upperBound, BoundType.CLOSED); }
+    public static <T extends Comparable<?>> Range<T> closed(T lowerBound, T upperBound) {
+        return range(lowerBound, BoundType.CLOSED, upperBound, BoundType.CLOSED); 
+    }
     /** (a..b] (exclusive,inclusive) */
-    public static <T> Range<T> openClosed(T lowerBound, T upperBound) { return range(lowerBound, BoundType.OPEN, upperBound, BoundType.CLOSED); }
+    public static <T extends Comparable<?>> Range<T> openClosed(T lowerBound, T upperBound) {
+        return range(lowerBound, BoundType.OPEN, upperBound, BoundType.CLOSED);
+    }
     /** [a..b) (inclusive,exclusive)*/
-    public static <T> Range<T> closedOpen(T lowerBound, T upperBound) { return range(lowerBound, BoundType.CLOSED, upperBound, BoundType.OPEN); }
-    /** (a..+INF) (exclusive) */
-    public static <T> Range<T> greaterThan(T v) { return range(v, BoundType.OPEN, null, null); }
-    /** [a..+INF) (inclusive) */
-    public static <T> Range<T> atLeast(T v) { return range(v, BoundType.CLOSED, null, null); }
-    /** (-INF..b) (exclusive) */
-    public static <T> Range<T> lessThan(T v) { return range(null, null, v, BoundType.OPEN); }
-    /** (-INF..b] (inclusive) */
-    public static <T> Range<T> atMost(T v) { return range(null, null, v, BoundType.CLOSED); }
+    public static <T extends Comparable<?>> Range<T> closedOpen(T lowerBound, T upperBound) {
+        return range(lowerBound, BoundType.CLOSED, upperBound, BoundType.OPEN);
+    }
+    /** (a..*) (exclusive) */
+    public static <T extends Comparable<?>> Range<T> greaterThan(T v) {
+        return range(v, BoundType.OPEN, null, BoundType.OPEN);
+    }
+    /** [a..*) (inclusive) */
+    public static <T extends Comparable<?>> Range<T> atLeast(T v) {
+        return range(v, BoundType.CLOSED, null, BoundType.OPEN);
+    }
+    /** (*..b) (exclusive) */
+    public static <T extends Comparable<?>> Range<T> lessThan(T v) {
+        return range(null, BoundType.OPEN, v, BoundType.OPEN);
+    }
+    /** (*..b] (inclusive) */
+    public static <T extends Comparable<?>> Range<T> atMost(T v) {
+        return range(null, BoundType.OPEN, v, BoundType.CLOSED);
+    }
+    /** [v..v] (both inclusive) */
+    public static  <T extends Comparable<?>> Range<T> singleton(T v) {
+        return range(v, BoundType.CLOSED, v, BoundType.CLOSED);
+    }
     
-    public T lowerBound() {
-        return lowerBound;
+    /**
+     * Returns true if o is a range having the same endpoints and bound types as this range.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (o == null) return false;
+        if (o instanceof Range) {
+            Range<?> r = (Range<?>) o;
+            return r.lbt.equals(lbt)
+                   && r.ubt.equals(ubt)
+                   && (r.lowerBound==null ? r.lowerBound == lowerBound
+                                          : r.lowerBound.equals(lowerBound))
+                   && (r.upperBound==null ? r.upperBound == upperBound
+                                          : r.upperBound.equals(upperBound));
+        }
+        return false;
     }
     
-    public T upperBound() {
-        return upperBound;
+    @Override
+    public int hashCode() {
+        if (hashCode == 0)
+            hashCode = Objects.hash(lbt, lowerBound, ubt, upperBound);
+        return hashCode;
     }
+
+    // Avoid making the Guava {lower,upper}Endpoint() methods public for now.
+    // It's not clear they have value in the absence of {lower,upper}BoundType()
+    // and at this time we're avoiding exposing our BoundType
+    
+//    /**
+//     * @return true iff the Range's lower endpoint isn't unbounded.
+//     */
+//    public boolean hasLowerEndpoint() {
+//        return lowerBound != null;
+//    }
+//    
+//    /**
+//     * Get the range's lower endpoint / bound.
+//     * @return the endpoint.
+//     * @throws IllegalStateException if hasLowerEndpoint()==false
+//     */
+//    public T lowerEndpoint() {
+//        if (hasLowerEndpoint())
+//            return lowerBound;
+//        throw new IllegalStateException("unbounded");
+//    }
+//    
+//    /**
+//     * @return true iff the Range's upper endpoint isn't unbounded.
+//     */
+//    public boolean hasUpperEndpoint() {
+//        return upperBound != null;
+//    }
+//    
+//    /**
+//     * Get the range's upper endpoint / bound.
+//     * @return the endpoint.
+//     * @throws IllegalStateException if hasUpperEndpoint()==false
+//     */
+//    public T upperEndpoint() {
+//        if (hasUpperEndpoint())
+//            return upperBound;
+//        throw new IllegalStateException("unbounded");
+//    }
     
     /**
      * Determine if the Region contains the value.
      * <p>
-     * For typical numeric types, and String and Character,
-     * {@code contains(v)} typically sufficies.  Though this
-     * can be useful for unsigned integer comparasons.
+     * {@code contains(v)} typically suffices.  This
+     * is useful in the case where the Comparable's default
+     * {@code Comparable.compareTo()} isn't sufficient.
+     * e.g., for unsigned byte comparisons
+     * <pre>
+     * Comparator<Byte> unsignedByteComparator = new Comparator<Byte>() {
+     *     public int compare(Byte b1, Byte b2) {
+     *         return Integer.compareUnsigned(b1.toUnsignedInt(), b2.toUnsignedInt());
+     *     }
+     *     public boolean equals(Object o2) { return o2==this; }
+     *     };
+     * Range<Byte> unsignedByteRange = ...;
+     * unsignedByteRange.contains(value, unsignedByteComparator);
+     * </pre>
+     * <p>
+     * N.B. Guava Range lacks such a method.
      * <p>
      * @param v the value to check for containment
      * @param cmp the Comparator to use
      * @return true if the Region contains the value
      */
     public boolean contains(T v, Comparator<T> cmp) {
-        if (lbt==null) {
+        if (lowerBound==null) {
             int r = cmp.compare(v, upperBound);
             return ubt == BoundType.OPEN ? r < 0 : r <= 0; 
         }
-        if (ubt==null) {
+        if (upperBound==null) {
             int r = cmp.compare(v, lowerBound);
             return lbt == BoundType.OPEN ? r > 0 : r >= 0; 
         }
@@ -101,15 +272,12 @@ public class Range<T> {
     /**
      * Determine if the Region contains the value.
      * <p>
-     * For typical numeric types, and String and Character.
      * The Comparator used is the default one for the type
      * (e.g., {@code Integer#compareTo(Integer)}.
      * <p>
-     * Use {@link #contains(Object, Comparator)} for other
-     * types or to use a non-default Comparator.
-     * <p>
      * @param v the value to check for containment
      * @return true if the Region contains the value
+     * @see #contains(T, Comparator)
      */
     public boolean contains(T v) {
         Comparator<T> cmp = getComparator(v);
@@ -129,19 +297,27 @@ public class Range<T> {
             return (lowerBound,upperBound) -> ((Short)lowerBound).compareTo((Short)upperBound);
         if (v instanceof Byte) 
             return (lowerBound,upperBound) -> ((Byte)lowerBound).compareTo((Byte)upperBound);
-        if (v instanceof String) 
-            return (lowerBound,upperBound) -> ((String)lowerBound).compareTo((String)upperBound);
-        if (v instanceof Character) 
-            return (lowerBound,upperBound) -> ((Character)lowerBound).compareTo((Character)upperBound);
+//        if (v instanceof String) 
+//            return (lowerBound,upperBound) -> ((String)lowerBound).compareTo((String)upperBound);
+//        if (v instanceof Character) 
+//            return (lowerBound,upperBound) -> ((Character)lowerBound).compareTo((Character)upperBound);
+        if (v instanceof BigDecimal) 
+            return (lowerBound,upperBound) -> ((BigDecimal)lowerBound).compareTo((BigDecimal)upperBound);
+        if (v instanceof BigInteger) 
+            return (lowerBound,upperBound) -> ((BigInteger)lowerBound).compareTo((BigInteger)upperBound);
         throw new IllegalArgumentException("Unsupported type: "+v.getClass());
     }
     
     /**
      * Create a Range from a string produced by toString()
+     * <p>
+     * N.B. See note in classdoc wrt Guava Range behavior. i.e., it
+     * currently lacks a "Range from Range.toString() analog".
+     * <p>
      * @param s value from toString()
      * @param clazz the class of the values in {@code s}
      */
-    public static <T> Range<T> valueOf(String s, Class<T> clazz) {
+    public static <T extends Comparable<?>> Range<T> valueOf(String s, Class<T> clazz) {
         char lbm = s.charAt(0);
         if (lbm != '[' && lbm != '(')
             throw new IllegalArgumentException(s);
@@ -154,7 +330,10 @@ public class Range<T> {
         
         s = s.substring(1,s.length()-1);
         // this parsing is weak - broken for String bounds with embedded ".."
+        // not an issue right now since we don't support String
         String[] parts = s.split("\\.\\.");
+        if (parts.length != 2)
+            throw new IllegalArgumentException("The range string bound values contains the separator sequence \"..\": " + s);
         
         String lbs = parts[0];
         String ubs = parts[1];
@@ -166,7 +345,7 @@ public class Range<T> {
     }
     
     @SuppressWarnings("unchecked")
-    private static <T> T boundValue(String strVal, Class<T> clazz) {
+    private static <T extends Comparable<?>> T boundValue(String strVal, Class<T> clazz) {
         if (strVal.equals("*"))
             return null;
         if (clazz.equals(Integer.class))
@@ -181,21 +360,31 @@ public class Range<T> {
             return (T) Float.valueOf(strVal);
         if (clazz.equals(Double.class))
             return (T) Double.valueOf(strVal);
+//        if (clazz.equals(String.class))
+//            return (T) String.valueOf(strVal);
+//        if (clazz.equals(Character.class))
+//            return (T) Character.valueOf(strVal.charAt(0));
+        if (clazz.equals(BigInteger.class))
+            return (T) new BigInteger(strVal);
+        if (clazz.equals(BigDecimal.class))
+            return (T) new BigDecimal(strVal);
         throw new IllegalArgumentException("Unhandled type "+clazz);
     }
     
     /**
      * Yields {@code <lowerBoundMarker><lowerBound>..<upperBound><upperBoundMarker>}.
      * <p>
-     * Where the lowerBoundMarker is either "[" (inclusive) or "(" (exclusive)
-     * and the upperBoundMarker is  either "]" (inclusive) or ")" (exclusive)
+     * Where the lowerBoundMarker is either "[" (inclusive/closed) or "(" (exclusive/open)
+     * and the upperBoundMarker is  either "]" (inclusive/closed) or ")" (exclusive/open)
      * <p>
      * The bound value "*" is used to indicate an infinite value.
      * <p>
+     * N.B. See note in classdoc wrt Guava Range behavior.
+     * <p>
      * .e.g.,
      * <pre>
      * "[120..156)"  // lowerBound=120 inclusive, upperBound=156 exclusive
-     * "[120..*]"    // an "atLeast" 120 range
+     * "[120..*)"    // an "atLeast" 120 range
      * </pre> 
      */
     public String toString() {
@@ -212,169 +401,4 @@ public class Range<T> {
         return parts[0]+parts[1]+".."+parts[2]+parts[3];
     }
     
-    private static <T> boolean testContains(Range<T> range, T v, Boolean expected) {
-        boolean act = range.contains(v);
-        boolean pass = act==expected;
-        String passLabel = pass ? "PASS" : "FAIL";
-        System.out.println(String.format("[%s] test range%s.contains(%s)==%s", passLabel, range.toString(), v.toString(), expected.toString()));
-        return pass;
-    }
-    
-    private static <T> boolean testToString(Range<T> range, String expected) {
-        String act = range.toString();
-        boolean pass = act.equals(expected);
-        String passLabel = pass ? "PASS" : "FAIL";
-        System.out.println(String.format("[%s] test Range.toString() actual=\"%s\" expected=\"%s\"", passLabel, range.toString(), expected));
-        return pass;
-    }
-
-    private static <T> boolean testValueOf(String str, Class<T> clazz) {
-        Range<T> range = Range.valueOf(str, clazz);
-        String s2 = range.toString();
-        boolean pass = s2.equals(str);
-
-        pass &= range.lowerBound() == null || clazz.isInstance(range.lowerBound());
-        pass &= range.upperBound() == null || clazz.isInstance(range.upperBound());
-        String passLabel = pass ? "PASS" : "FAIL";
-        System.out.println(String.format("[%s] test Range.valueOf(\"%s\", %s) yields Range with toString()=>\"%s\"", passLabel, str, clazz.getName(), range.toString()));
-        return pass;
-    }
-
-    public static void main(String[] args) {
-        boolean pass = true;
-
-        System.out.println("open()");
-        pass &= testContains(Range.open(2,4), 1, false);
-        pass &= testContains(Range.open(2,4), 2, false);
-        pass &= testContains(Range.open(2,4), 3, true);
-        pass &= testContains(Range.open(2,4), 4, false);
-        pass &= testContains(Range.open(2,4), 5, false);
-
-        System.out.println("closed()");
-        pass &= testContains(Range.closed(2,4), 1, false);
-        pass &= testContains(Range.closed(2,4), 2, true);
-        pass &= testContains(Range.closed(2,4), 3, true);
-        pass &= testContains(Range.closed(2,4), 4, true);
-        pass &= testContains(Range.closed(2,4), 5, false);
-
-        System.out.println("openClosed()");
-        pass &= testContains(Range.openClosed(2,4), 1, false);
-        pass &= testContains(Range.openClosed(2,4), 2, false);
-        pass &= testContains(Range.openClosed(2,4), 3, true);
-        pass &= testContains(Range.openClosed(2,4), 4, true);
-        pass &= testContains(Range.openClosed(2,4), 5, false);
-
-        System.out.println("closedOpen()");
-        pass &= testContains(Range.closedOpen(2,4), 1, false);
-        pass &= testContains(Range.closedOpen(2,4), 2, true);
-        pass &= testContains(Range.closedOpen(2,4), 3, true);
-        pass &= testContains(Range.closedOpen(2,4), 4, false);
-        pass &= testContains(Range.closedOpen(2,4), 5, false);
-
-        System.out.println("greaterThan()");
-        pass &= testContains(Range.greaterThan(2), 1, false);
-        pass &= testContains(Range.greaterThan(2), 2, false);
-        pass &= testContains(Range.greaterThan(2), 3, true);
-
-        System.out.println("atLeast()");
-        pass &= testContains(Range.atLeast(2), 1, false);
-        pass &= testContains(Range.atLeast(2), 2, true);
-        pass &= testContains(Range.atLeast(2), 3, true);
-
-        System.out.println("lessThan()");
-        pass &= testContains(Range.lessThan(2), 1, true);
-        pass &= testContains(Range.lessThan(2), 2, false);
-        pass &= testContains(Range.lessThan(2), 3, false);
-
-        System.out.println("atMost()");
-        pass &= testContains(Range.atMost(2), 1, true);
-        pass &= testContains(Range.atMost(2), 2, true);
-        pass &= testContains(Range.atMost(2), 3, false);
-        
-        System.out.println("Byte open()");
-        pass &= testContains(Range.open((byte)2,(byte)4), (byte)1, false);
-        pass &= testContains(Range.open((byte)2,(byte)4), (byte)2, false);
-        pass &= testContains(Range.open((byte)2,(byte)4), (byte)3, true);
-        pass &= testContains(Range.open((byte)2,(byte)4), (byte)4, false);
-        pass &= testContains(Range.open((byte)2,(byte)4), (byte)5, false);
-        
-        System.out.println("Short open()");
-        pass &= testContains(Range.open((short)2,(short)4), (short)1, false);
-        pass &= testContains(Range.open((short)2,(short)4), (short)2, false);
-        pass &= testContains(Range.open((short)2,(short)4), (short)3, true);
-        pass &= testContains(Range.open((short)2,(short)4), (short)4, false);
-        pass &= testContains(Range.open((short)2,(short)4), (short)5, false);
-        
-        System.out.println("Long open()");
-        pass &= testContains(Range.open(2L,4L), 1L, false);
-        pass &= testContains(Range.open(2L,4L), 2L, false);
-        pass &= testContains(Range.open(2L,4L), 3L, true);
-        pass &= testContains(Range.open(2L,4L), 4L, false);
-        pass &= testContains(Range.open(2L,4L), 5L, false);
-        
-        System.out.println("Float open()");
-        pass &= testContains(Range.open(2f,4f), 1f, false);
-        pass &= testContains(Range.open(2f,4f), 2f, false);
-        pass &= testContains(Range.open(2f,4f), 2.001f, true);
-        pass &= testContains(Range.open(2f,4f), 3.999f, true);
-        pass &= testContains(Range.open(2f,4f), 4f, false);
-        pass &= testContains(Range.open(2f,4f), 5f, false);
-        
-        System.out.println("Double open()");
-        pass &= testContains(Range.open(2d,4d), 1d, false);
-        pass &= testContains(Range.open(2d,4d), 2d, false);
-        pass &= testContains(Range.open(2d,4d), 2.001d, true);
-        pass &= testContains(Range.open(2d,4d), 3.999d, true);
-        pass &= testContains(Range.open(2d,4d), 4d, false);
-        pass &= testContains(Range.open(2d,4d), 5d, false);
-        
-        System.out.println("Character open()");
-        pass &= testContains(Range.open('b','d'), 'a', false);
-        pass &= testContains(Range.open('b','d'), 'b', false);
-        pass &= testContains(Range.open('b','d'), 'c', true);
-        pass &= testContains(Range.open('b','d'), 'd', false);
-        pass &= testContains(Range.open('b','d'), 'e', false);
-        
-        System.out.println("String open()");
-        pass &= testContains(Range.open("b","d"), "a", false);
-        pass &= testContains(Range.open("b","d"), "b", false);
-        pass &= testContains(Range.open("b","d"), "bc", true);
-        pass &= testContains(Range.open("b","d"), "c", true);
-        pass &= testContains(Range.open("b","d"), "cd", true);
-        pass &= testContains(Range.open("b","d"), "d", false);
-        pass &= testContains(Range.open("b","d"), "de", false);
-        pass &= testContains(Range.open("b","d"), "e", false);
-        
-        System.out.println("toString()");
-        pass &= testToString(Range.open(2,4), "(2..4)");
-        pass &= testToString(Range.closed(2,4), "[2..4]");
-        pass &= testToString(Range.openClosed(2,4), "(2..4]");
-        pass &= testToString(Range.closedOpen(2,4), "[2..4)");
-        pass &= testToString(Range.greaterThan(2), "(2..*)");
-        pass &= testToString(Range.atLeast(2), "[2..*)");
-        pass &= testToString(Range.lessThan(2), "(*..2)");
-        pass &= testToString(Range.atMost(2), "(*..2]");
-        
-        System.out.println("Integer valueOf()");
-        pass &= testValueOf("(2..4)", Integer.class);
-        pass &= testValueOf("[2..4]", Integer.class);
-        pass &= testValueOf("(2..4]", Integer.class);
-        pass &= testValueOf("[2..4)", Integer.class);
-        pass &= testValueOf("(2..*)", Integer.class);
-        pass &= testValueOf("[2..*)", Integer.class);
-        pass &= testValueOf("(*..2)", Integer.class);
-        pass &= testValueOf("(*..2]", Integer.class);
-        
-        System.out.println("Float valueOf()");
-        pass &= testValueOf("(2.128..4.25)", Float.class);
-        
-        System.out.println("Double valueOf()");
-        pass &= testValueOf("(2.128..4.25)", Double.class);
-        
-        if (!pass)
-            throw new IllegalStateException("Tests did not pass");
-        else
-            System.out.println("All passed.");
-    }
-    
 }

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/31263522/samples/apps/src/main/java/quarks/samples/apps/RangeTest.java
----------------------------------------------------------------------
diff --git a/samples/apps/src/main/java/quarks/samples/apps/RangeTest.java b/samples/apps/src/main/java/quarks/samples/apps/RangeTest.java
new file mode 100644
index 0000000..146d72d
--- /dev/null
+++ b/samples/apps/src/main/java/quarks/samples/apps/RangeTest.java
@@ -0,0 +1,327 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package quarks.samples.apps;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.junit.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import quarks.function.Supplier;
+
+/**
+ * Test Range.
+ */
+public class RangeTest {
+    
+    private <T extends Comparable<?>> void testContains(Range<T> range, T v, Boolean expected) {
+        assertEquals("range"+range+".contains(range"+v+")", expected, range.contains(v));
+    }
+    
+    private <T extends Comparable<?>> void testToString(Range<T> range, String expected) {
+        assertEquals("range.toString()", expected, range.toString());
+    }
+
+    private <T extends Comparable<?>> void testValueOf(String str, Class<T> clazz, Range<T> expected) {
+        assertEquals("Range.valueOf("+clazz.getSimpleName()+")", 
+                Range.valueOf(str, clazz), expected);
+    }
+    
+    private <T extends Comparable<?>> void testEquals(Range<T> r1, Range<T> r2, Boolean expected) {
+        assertEquals("range"+r1+".equals(range"+r2+")", expected, r1.equals(r2));
+    }
+    
+    private <T extends Comparable<?>> void testHashCode(Range<T> range, int hashCode, Boolean expected) {
+        if (expected)
+            assertEquals("range"+range+".hashCode()", hashCode, range.hashCode());
+        else
+            assertNotEquals("range"+range+".hashCode()", hashCode, range.hashCode());
+    }
+
+    private <T extends Comparable<?>> void testSupportedType(Supplier<Range<T>> range, Class<T> clazz, Boolean expected) {
+        boolean act;
+        try {
+            range.get();
+            act = true;
+        }
+        catch (IllegalArgumentException e) {
+            act = false;
+        }
+        assertEquals("supported type "+clazz.toString(), expected, act);
+    }
+    
+    private <T extends Comparable<?>> void testJson(Range<T> r1, Type typeOfT) {
+        String json = new Gson().toJson(r1);
+        Range<T> r2 = new Gson().fromJson(json, typeOfT);
+        assertEquals("json="+json+" typeOfT="+typeOfT, r1, r2);
+    }
+    
+    @Test
+    public void testSupportedTypes() {
+        testSupportedType(() -> Range.closed("a", "f"), String.class, false);
+        testSupportedType(() -> Range.closed('a', 'f'), Character.class, false);
+        testSupportedType(() -> Range.closed(1, 10), Integer.class, true);
+        testSupportedType(() -> Range.closed((short)1, (short)10), Short.class, true);
+        testSupportedType(() -> Range.closed((byte)1, (byte)10), Byte.class, true);
+        testSupportedType(() -> Range.closed(1L, 10L), Long.class, true);
+        testSupportedType(() -> Range.closed(1f, 10f), Float.class, true);
+        testSupportedType(() -> Range.closed(1d, 10d), Double.class, true);
+        testSupportedType(() -> Range.closed(BigInteger.valueOf(1), BigInteger.valueOf(10)), BigInteger.class, true);
+        testSupportedType(() -> Range.closed(BigDecimal.valueOf(1), BigDecimal.valueOf(10)), BigDecimal.class, true);
+    }
+    
+    @Test
+    public void testContainsOpen() {
+        testContains(Range.open(2,4), 1, false);
+        testContains(Range.open(2,4), 2, false);
+        testContains(Range.open(2,4), 3, true);
+        testContains(Range.open(2,4), 4, false);
+        testContains(Range.open(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsClosed() {
+        testContains(Range.closed(2,4), 1, false);
+        testContains(Range.closed(2,4), 2, true);
+        testContains(Range.closed(2,4), 3, true);
+        testContains(Range.closed(2,4), 4, true);
+        testContains(Range.closed(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsOpenClosed() {
+        testContains(Range.openClosed(2,4), 1, false);
+        testContains(Range.openClosed(2,4), 2, false);
+        testContains(Range.openClosed(2,4), 3, true);
+        testContains(Range.openClosed(2,4), 4, true);
+        testContains(Range.openClosed(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsClosedOpen() {
+        testContains(Range.closedOpen(2,4), 1, false);
+        testContains(Range.closedOpen(2,4), 2, true);
+        testContains(Range.closedOpen(2,4), 3, true);
+        testContains(Range.closedOpen(2,4), 4, false);
+        testContains(Range.closedOpen(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsGreaterThan() {
+        testContains(Range.greaterThan(2), 1, false);
+        testContains(Range.greaterThan(2), 2, false);
+        testContains(Range.greaterThan(2), 3, true);
+    }
+
+    @Test
+    public void testContainsAtLeast() {
+        testContains(Range.atLeast(2), 1, false);
+        testContains(Range.atLeast(2), 2, true);
+        testContains(Range.atLeast(2), 3, true);
+    }
+
+    @Test
+    public void testContainsLessThan() {
+        testContains(Range.lessThan(2), 1, true);
+        testContains(Range.lessThan(2), 2, false);
+        testContains(Range.lessThan(2), 3, false);
+    }
+
+    @Test
+    public void testContainsAtMost() {
+        testContains(Range.atMost(2), 1, true);
+        testContains(Range.atMost(2), 2, true);
+        testContains(Range.atMost(2), 3, false);
+    }
+
+    @Test
+    public void testContainsSingleton() {
+        testContains(Range.singleton(2), 1, false);
+        testContains(Range.singleton(2), 2, true);
+        testContains(Range.singleton(2), 3, false);
+    }
+
+    @Test
+    public void testEquals() {
+        testEquals(Range.closed(2,4), Range.closed(2,4), true);
+        testEquals(Range.closed(2,4), Range.closed(2,3), false);
+        testEquals(Range.closed(3,4), Range.closed(2,4), false);
+        testEquals(Range.atMost(2), Range.atMost(2), true);
+        testEquals(Range.atMost(2), Range.atMost(3), false);
+        testEquals(Range.atLeast(2), Range.atLeast(2), true);
+        testEquals(Range.atLeast(2), Range.atLeast(3), false);
+        testEquals(Range.closed(2,2), Range.singleton(2), true);
+    }
+
+    @Test
+    public void testHashCode() {
+        testHashCode(Range.atMost(2), Range.atMost(2).hashCode(), true);
+        testHashCode(Range.atMost(2), 0, false);
+        testHashCode(Range.atMost(2), Range.atMost(3).hashCode(), false);
+        testHashCode(Range.atLeast(2), Range.atMost(2).hashCode(), false);
+    }
+
+    @Test
+    public void testToString() {
+        testToString(Range.open(2,4), "(2..4)");
+        testToString(Range.closed(2,4), "[2..4]");
+        testToString(Range.openClosed(2,4), "(2..4]");
+        testToString(Range.closedOpen(2,4), "[2..4)");
+        testToString(Range.greaterThan(2), "(2..*)");
+        testToString(Range.atLeast(2), "[2..*)");
+        testToString(Range.lessThan(2), "(*..2)");
+        testToString(Range.atMost(2), "(*..2]");
+    }
+
+    @Test
+    public void testValueOf() {
+        testValueOf("(2..4)", Integer.class, Range.open(2, 4));
+        testValueOf("[2..4]", Integer.class, Range.closed(2, 4));
+        testValueOf("(2..4]", Integer.class, Range.openClosed(2, 4));
+        testValueOf("[2..4)", Integer.class, Range.closedOpen(2, 4));
+        testValueOf("(2..*)", Integer.class, Range.greaterThan(2));
+        testValueOf("[2..*)", Integer.class, Range.atLeast(2));
+        testValueOf("(*..2)", Integer.class, Range.lessThan(2));
+        testValueOf("(*..2]", Integer.class, Range.atMost(2));
+    }
+
+    @Test
+    public void testContainsOtherByte() {
+        testContains(Range.open((byte)2,(byte)4), (byte)1, false);
+        testContains(Range.open((byte)2,(byte)4), (byte)2, false);
+        testContains(Range.open((byte)2,(byte)4), (byte)3, true);
+        testContains(Range.open((byte)2,(byte)4), (byte)4, false);
+        testContains(Range.open((byte)2,(byte)4), (byte)5, false);
+    }
+
+    @Test
+    public void testContainsOtherShort() {
+        testContains(Range.open((short)2,(short)4), (short)1, false);
+        testContains(Range.open((short)2,(short)4), (short)2, false);
+        testContains(Range.open((short)2,(short)4), (short)3, true);
+        testContains(Range.open((short)2,(short)4), (short)4, false);
+        testContains(Range.open((short)2,(short)4), (short)5, false);
+    }
+
+    @Test
+    public void testContainsOtherLong() {
+        testContains(Range.open(2L,4L), 1L, false);
+        testContains(Range.open(2L,4L), 2L, false);
+        testContains(Range.open(2L,4L), 3L, true);
+        testContains(Range.open(2L,4L), 4L, false);
+        testContains(Range.open(2L,4L), 5L, false);
+    }
+
+    @Test
+    public void testContainsOtherFloat() {
+        testContains(Range.open(2f,4f), 1f, false);
+        testContains(Range.open(2f,4f), 2f, false);
+        testContains(Range.open(2f,4f), 2.001f, true);
+        testContains(Range.open(2f,4f), 3.999f, true);
+        testContains(Range.open(2f,4f), 4f, false);
+        testContains(Range.open(2f,4f), 5f, false);
+    }
+
+    @Test
+    public void testContainsOtherDouble() {
+        testContains(Range.open(2d,4d), 1d, false);
+        testContains(Range.open(2d,4d), 2d, false);
+        testContains(Range.open(2d,4d), 2.001d, true);
+        testContains(Range.open(2d,4d), 3.999d, true);
+        testContains(Range.open(2d,4d), 4d, false);
+        testContains(Range.open(2d,4d), 5d, false);
+    }
+
+    @Test
+    public void testContainsOtherBigInteger() {
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(1), false);
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(2), false);
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(3), true);
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(4), false);
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(5), false);
+    }
+
+    @Test
+    public void testContainsOtherBigDecimal() {
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(1), false);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2), false);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2.001), true);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(3.999), true);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(4), false);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(5), false);
+    }
+
+//  @Test
+//  public void testContainsOtherString() {
+//      testContains(Range.open("b","d"), "a", false);
+//      testContains(Range.open("b","d"), "b", false);
+//      testContains(Range.open("b","d"), "bc", true);
+//      testContains(Range.open("b","d"), "c", true);
+//      testContains(Range.open("b","d"), "cd", true);
+//      testContains(Range.open("b","d"), "d", false);
+//      testContains(Range.open("b","d"), "de", false);
+//      testContains(Range.open("b","d"), "e", false);
+//  }
+
+//  @Test
+//  public void testContainsOtherCharacter() {
+//      testContains(Range.open('b','d'), 'a', false);
+//      testContains(Range.open('b','d'), 'b', false);
+//      testContains(Range.open('b','d'), 'c', true);
+//      testContains(Range.open('b','d'), 'd', false);
+//      testContains(Range.open('b','d'), 'e', false);
+//  }
+
+    @Test
+    public void testValueOfOther() {
+        testValueOf("(2..4)", Short.class, Range.open((short)2, (short)4));
+        testValueOf("(2..4)", Byte.class, Range.open((byte)2, (byte)4));
+        testValueOf("(2..4)", Long.class, Range.open(2L, 4L));
+        testValueOf("(2.128..4.25)", Float.class, Range.open(2.128f, 4.25f));
+        testValueOf("(2.128..4.25)", Double.class, Range.open(2.128d, 4.25d));
+        testValueOf("(2..4)", BigInteger.class, Range.open(BigInteger.valueOf(2), BigInteger.valueOf(4)));
+        testValueOf("(2.5..4.25)", BigDecimal.class, Range.open(new BigDecimal(2.5), new BigDecimal(4.25)));
+//        testValueOf("(ab..fg)", String.class, Range.open("ab", "fg"));
+//        testValueOf("(ab..c..fg)", String.class, Range.open("ab..c", "fg")); // yikes
+//        testValueOf("(a..f)", Character.class, Range.open('a', 'f'));
+    }
+
+    @Test
+    public void testJsonAllTypes() {
+        testJson(Range.closed(1, 10), new TypeToken<Range<Integer>>(){}.getType());
+        testJson(Range.closed((short)1, (short)10), new TypeToken<Range<Short>>(){}.getType());
+        testJson(Range.closed((byte)1, (byte)10), new TypeToken<Range<Byte>>(){}.getType());
+        testJson(Range.closed(1L, 10L), new TypeToken<Range<Long>>(){}.getType());
+        testJson(Range.closed(1f, 10f), new TypeToken<Range<Float>>(){}.getType());
+        testJson(Range.closed(1d, 10d), new TypeToken<Range<Double>>(){}.getType());
+        testJson(Range.closed(BigInteger.valueOf(1), BigInteger.valueOf(10)), new TypeToken<Range<BigInteger>>(){}.getType());
+        testJson(Range.closed(BigDecimal.valueOf(1), BigDecimal.valueOf(10)), new TypeToken<Range<BigDecimal>>(){}.getType());
+//        testJson(Range("ab", "fg"), new TypeToken<Range<String>>(){}.getType());
+//        testJson(Range("ab..c", "fg"), new TypeToken<Range<String>>(){}.getType());
+//        testJson(Range('a', 'f'), new TypeToken<Range<Character>>(){}.getType());
+    }
+
+}



[3/3] incubator-quarks git commit: Merge pull request #46

Posted by dl...@apache.org.
Merge pull request #46

This closes #46


Project: http://git-wip-us.apache.org/repos/asf/incubator-quarks/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quarks/commit/0b58e153
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quarks/tree/0b58e153
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quarks/diff/0b58e153

Branch: refs/heads/master
Commit: 0b58e1531137d0a661b16532545bbdcfc03f780b
Parents: b3ca7ee 5d4cc17
Author: Dale LaBossiere <dl...@us.ibm.com>
Authored: Fri Mar 25 14:48:42 2016 -0400
Committer: Dale LaBossiere <dl...@us.ibm.com>
Committed: Fri Mar 25 14:48:42 2016 -0400

----------------------------------------------------------------------
 samples/.classpath                              |   1 +
 .../samples/apps/ApplicationUtilities.java      |   2 +-
 .../main/java/quarks/samples/apps/Range.java    | 446 ++++++++++---------
 .../quarks/test/samples/apps/RangeTest.java     | 328 ++++++++++++++
 4 files changed, 565 insertions(+), 212 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/0b58e153/samples/apps/src/main/java/quarks/samples/apps/ApplicationUtilities.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/0b58e153/samples/apps/src/main/java/quarks/samples/apps/Range.java
----------------------------------------------------------------------


[2/3] incubator-quarks git commit: move RangeTest to test package

Posted by dl...@apache.org.
move RangeTest to test package

Project: http://git-wip-us.apache.org/repos/asf/incubator-quarks/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quarks/commit/5d4cc179
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quarks/tree/5d4cc179
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quarks/diff/5d4cc179

Branch: refs/heads/master
Commit: 5d4cc179b0523f93c39b379e693df6a40f2b2d5a
Parents: 3126352
Author: Dale LaBossiere <dl...@us.ibm.com>
Authored: Fri Mar 25 13:17:35 2016 -0400
Committer: Dale LaBossiere <dl...@us.ibm.com>
Committed: Fri Mar 25 13:17:35 2016 -0400

----------------------------------------------------------------------
 samples/.classpath                              |   1 +
 .../main/java/quarks/samples/apps/Range.java    |   2 +-
 .../java/quarks/samples/apps/RangeTest.java     | 327 ------------------
 .../quarks/test/samples/apps/RangeTest.java     | 328 +++++++++++++++++++
 4 files changed, 330 insertions(+), 328 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/5d4cc179/samples/.classpath
----------------------------------------------------------------------
diff --git a/samples/.classpath b/samples/.classpath
index 9fb15d8..cb5a6c9 100644
--- a/samples/.classpath
+++ b/samples/.classpath
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="apps/src/main/java"/>
+	<classpathentry kind="src" path="apps/src/test/java"/>
 	<classpathentry kind="src" path="connectors/src/main/java"/>
 	<classpathentry kind="src" path="console/src/main/java"/>
 	<classpathentry kind="src" path="topology/src/main/java"/>

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/5d4cc179/samples/apps/src/main/java/quarks/samples/apps/Range.java
----------------------------------------------------------------------
diff --git a/samples/apps/src/main/java/quarks/samples/apps/Range.java b/samples/apps/src/main/java/quarks/samples/apps/Range.java
index e9a58fe..d10991d 100644
--- a/samples/apps/src/main/java/quarks/samples/apps/Range.java
+++ b/samples/apps/src/main/java/quarks/samples/apps/Range.java
@@ -277,7 +277,7 @@ public class Range<T extends Comparable<?>> implements Serializable {
      * <p>
      * @param v the value to check for containment
      * @return true if the Region contains the value
-     * @see #contains(T, Comparator)
+     * @see #contains(Comparable, Comparator)
      */
     public boolean contains(T v) {
         Comparator<T> cmp = getComparator(v);

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/5d4cc179/samples/apps/src/main/java/quarks/samples/apps/RangeTest.java
----------------------------------------------------------------------
diff --git a/samples/apps/src/main/java/quarks/samples/apps/RangeTest.java b/samples/apps/src/main/java/quarks/samples/apps/RangeTest.java
deleted file mode 100644
index 146d72d..0000000
--- a/samples/apps/src/main/java/quarks/samples/apps/RangeTest.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-  
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-package quarks.samples.apps;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-
-import quarks.function.Supplier;
-
-/**
- * Test Range.
- */
-public class RangeTest {
-    
-    private <T extends Comparable<?>> void testContains(Range<T> range, T v, Boolean expected) {
-        assertEquals("range"+range+".contains(range"+v+")", expected, range.contains(v));
-    }
-    
-    private <T extends Comparable<?>> void testToString(Range<T> range, String expected) {
-        assertEquals("range.toString()", expected, range.toString());
-    }
-
-    private <T extends Comparable<?>> void testValueOf(String str, Class<T> clazz, Range<T> expected) {
-        assertEquals("Range.valueOf("+clazz.getSimpleName()+")", 
-                Range.valueOf(str, clazz), expected);
-    }
-    
-    private <T extends Comparable<?>> void testEquals(Range<T> r1, Range<T> r2, Boolean expected) {
-        assertEquals("range"+r1+".equals(range"+r2+")", expected, r1.equals(r2));
-    }
-    
-    private <T extends Comparable<?>> void testHashCode(Range<T> range, int hashCode, Boolean expected) {
-        if (expected)
-            assertEquals("range"+range+".hashCode()", hashCode, range.hashCode());
-        else
-            assertNotEquals("range"+range+".hashCode()", hashCode, range.hashCode());
-    }
-
-    private <T extends Comparable<?>> void testSupportedType(Supplier<Range<T>> range, Class<T> clazz, Boolean expected) {
-        boolean act;
-        try {
-            range.get();
-            act = true;
-        }
-        catch (IllegalArgumentException e) {
-            act = false;
-        }
-        assertEquals("supported type "+clazz.toString(), expected, act);
-    }
-    
-    private <T extends Comparable<?>> void testJson(Range<T> r1, Type typeOfT) {
-        String json = new Gson().toJson(r1);
-        Range<T> r2 = new Gson().fromJson(json, typeOfT);
-        assertEquals("json="+json+" typeOfT="+typeOfT, r1, r2);
-    }
-    
-    @Test
-    public void testSupportedTypes() {
-        testSupportedType(() -> Range.closed("a", "f"), String.class, false);
-        testSupportedType(() -> Range.closed('a', 'f'), Character.class, false);
-        testSupportedType(() -> Range.closed(1, 10), Integer.class, true);
-        testSupportedType(() -> Range.closed((short)1, (short)10), Short.class, true);
-        testSupportedType(() -> Range.closed((byte)1, (byte)10), Byte.class, true);
-        testSupportedType(() -> Range.closed(1L, 10L), Long.class, true);
-        testSupportedType(() -> Range.closed(1f, 10f), Float.class, true);
-        testSupportedType(() -> Range.closed(1d, 10d), Double.class, true);
-        testSupportedType(() -> Range.closed(BigInteger.valueOf(1), BigInteger.valueOf(10)), BigInteger.class, true);
-        testSupportedType(() -> Range.closed(BigDecimal.valueOf(1), BigDecimal.valueOf(10)), BigDecimal.class, true);
-    }
-    
-    @Test
-    public void testContainsOpen() {
-        testContains(Range.open(2,4), 1, false);
-        testContains(Range.open(2,4), 2, false);
-        testContains(Range.open(2,4), 3, true);
-        testContains(Range.open(2,4), 4, false);
-        testContains(Range.open(2,4), 5, false);
-    }
-
-    @Test
-    public void testContainsClosed() {
-        testContains(Range.closed(2,4), 1, false);
-        testContains(Range.closed(2,4), 2, true);
-        testContains(Range.closed(2,4), 3, true);
-        testContains(Range.closed(2,4), 4, true);
-        testContains(Range.closed(2,4), 5, false);
-    }
-
-    @Test
-    public void testContainsOpenClosed() {
-        testContains(Range.openClosed(2,4), 1, false);
-        testContains(Range.openClosed(2,4), 2, false);
-        testContains(Range.openClosed(2,4), 3, true);
-        testContains(Range.openClosed(2,4), 4, true);
-        testContains(Range.openClosed(2,4), 5, false);
-    }
-
-    @Test
-    public void testContainsClosedOpen() {
-        testContains(Range.closedOpen(2,4), 1, false);
-        testContains(Range.closedOpen(2,4), 2, true);
-        testContains(Range.closedOpen(2,4), 3, true);
-        testContains(Range.closedOpen(2,4), 4, false);
-        testContains(Range.closedOpen(2,4), 5, false);
-    }
-
-    @Test
-    public void testContainsGreaterThan() {
-        testContains(Range.greaterThan(2), 1, false);
-        testContains(Range.greaterThan(2), 2, false);
-        testContains(Range.greaterThan(2), 3, true);
-    }
-
-    @Test
-    public void testContainsAtLeast() {
-        testContains(Range.atLeast(2), 1, false);
-        testContains(Range.atLeast(2), 2, true);
-        testContains(Range.atLeast(2), 3, true);
-    }
-
-    @Test
-    public void testContainsLessThan() {
-        testContains(Range.lessThan(2), 1, true);
-        testContains(Range.lessThan(2), 2, false);
-        testContains(Range.lessThan(2), 3, false);
-    }
-
-    @Test
-    public void testContainsAtMost() {
-        testContains(Range.atMost(2), 1, true);
-        testContains(Range.atMost(2), 2, true);
-        testContains(Range.atMost(2), 3, false);
-    }
-
-    @Test
-    public void testContainsSingleton() {
-        testContains(Range.singleton(2), 1, false);
-        testContains(Range.singleton(2), 2, true);
-        testContains(Range.singleton(2), 3, false);
-    }
-
-    @Test
-    public void testEquals() {
-        testEquals(Range.closed(2,4), Range.closed(2,4), true);
-        testEquals(Range.closed(2,4), Range.closed(2,3), false);
-        testEquals(Range.closed(3,4), Range.closed(2,4), false);
-        testEquals(Range.atMost(2), Range.atMost(2), true);
-        testEquals(Range.atMost(2), Range.atMost(3), false);
-        testEquals(Range.atLeast(2), Range.atLeast(2), true);
-        testEquals(Range.atLeast(2), Range.atLeast(3), false);
-        testEquals(Range.closed(2,2), Range.singleton(2), true);
-    }
-
-    @Test
-    public void testHashCode() {
-        testHashCode(Range.atMost(2), Range.atMost(2).hashCode(), true);
-        testHashCode(Range.atMost(2), 0, false);
-        testHashCode(Range.atMost(2), Range.atMost(3).hashCode(), false);
-        testHashCode(Range.atLeast(2), Range.atMost(2).hashCode(), false);
-    }
-
-    @Test
-    public void testToString() {
-        testToString(Range.open(2,4), "(2..4)");
-        testToString(Range.closed(2,4), "[2..4]");
-        testToString(Range.openClosed(2,4), "(2..4]");
-        testToString(Range.closedOpen(2,4), "[2..4)");
-        testToString(Range.greaterThan(2), "(2..*)");
-        testToString(Range.atLeast(2), "[2..*)");
-        testToString(Range.lessThan(2), "(*..2)");
-        testToString(Range.atMost(2), "(*..2]");
-    }
-
-    @Test
-    public void testValueOf() {
-        testValueOf("(2..4)", Integer.class, Range.open(2, 4));
-        testValueOf("[2..4]", Integer.class, Range.closed(2, 4));
-        testValueOf("(2..4]", Integer.class, Range.openClosed(2, 4));
-        testValueOf("[2..4)", Integer.class, Range.closedOpen(2, 4));
-        testValueOf("(2..*)", Integer.class, Range.greaterThan(2));
-        testValueOf("[2..*)", Integer.class, Range.atLeast(2));
-        testValueOf("(*..2)", Integer.class, Range.lessThan(2));
-        testValueOf("(*..2]", Integer.class, Range.atMost(2));
-    }
-
-    @Test
-    public void testContainsOtherByte() {
-        testContains(Range.open((byte)2,(byte)4), (byte)1, false);
-        testContains(Range.open((byte)2,(byte)4), (byte)2, false);
-        testContains(Range.open((byte)2,(byte)4), (byte)3, true);
-        testContains(Range.open((byte)2,(byte)4), (byte)4, false);
-        testContains(Range.open((byte)2,(byte)4), (byte)5, false);
-    }
-
-    @Test
-    public void testContainsOtherShort() {
-        testContains(Range.open((short)2,(short)4), (short)1, false);
-        testContains(Range.open((short)2,(short)4), (short)2, false);
-        testContains(Range.open((short)2,(short)4), (short)3, true);
-        testContains(Range.open((short)2,(short)4), (short)4, false);
-        testContains(Range.open((short)2,(short)4), (short)5, false);
-    }
-
-    @Test
-    public void testContainsOtherLong() {
-        testContains(Range.open(2L,4L), 1L, false);
-        testContains(Range.open(2L,4L), 2L, false);
-        testContains(Range.open(2L,4L), 3L, true);
-        testContains(Range.open(2L,4L), 4L, false);
-        testContains(Range.open(2L,4L), 5L, false);
-    }
-
-    @Test
-    public void testContainsOtherFloat() {
-        testContains(Range.open(2f,4f), 1f, false);
-        testContains(Range.open(2f,4f), 2f, false);
-        testContains(Range.open(2f,4f), 2.001f, true);
-        testContains(Range.open(2f,4f), 3.999f, true);
-        testContains(Range.open(2f,4f), 4f, false);
-        testContains(Range.open(2f,4f), 5f, false);
-    }
-
-    @Test
-    public void testContainsOtherDouble() {
-        testContains(Range.open(2d,4d), 1d, false);
-        testContains(Range.open(2d,4d), 2d, false);
-        testContains(Range.open(2d,4d), 2.001d, true);
-        testContains(Range.open(2d,4d), 3.999d, true);
-        testContains(Range.open(2d,4d), 4d, false);
-        testContains(Range.open(2d,4d), 5d, false);
-    }
-
-    @Test
-    public void testContainsOtherBigInteger() {
-        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(1), false);
-        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(2), false);
-        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(3), true);
-        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(4), false);
-        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(5), false);
-    }
-
-    @Test
-    public void testContainsOtherBigDecimal() {
-        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(1), false);
-        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2), false);
-        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2.001), true);
-        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(3.999), true);
-        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(4), false);
-        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(5), false);
-    }
-
-//  @Test
-//  public void testContainsOtherString() {
-//      testContains(Range.open("b","d"), "a", false);
-//      testContains(Range.open("b","d"), "b", false);
-//      testContains(Range.open("b","d"), "bc", true);
-//      testContains(Range.open("b","d"), "c", true);
-//      testContains(Range.open("b","d"), "cd", true);
-//      testContains(Range.open("b","d"), "d", false);
-//      testContains(Range.open("b","d"), "de", false);
-//      testContains(Range.open("b","d"), "e", false);
-//  }
-
-//  @Test
-//  public void testContainsOtherCharacter() {
-//      testContains(Range.open('b','d'), 'a', false);
-//      testContains(Range.open('b','d'), 'b', false);
-//      testContains(Range.open('b','d'), 'c', true);
-//      testContains(Range.open('b','d'), 'd', false);
-//      testContains(Range.open('b','d'), 'e', false);
-//  }
-
-    @Test
-    public void testValueOfOther() {
-        testValueOf("(2..4)", Short.class, Range.open((short)2, (short)4));
-        testValueOf("(2..4)", Byte.class, Range.open((byte)2, (byte)4));
-        testValueOf("(2..4)", Long.class, Range.open(2L, 4L));
-        testValueOf("(2.128..4.25)", Float.class, Range.open(2.128f, 4.25f));
-        testValueOf("(2.128..4.25)", Double.class, Range.open(2.128d, 4.25d));
-        testValueOf("(2..4)", BigInteger.class, Range.open(BigInteger.valueOf(2), BigInteger.valueOf(4)));
-        testValueOf("(2.5..4.25)", BigDecimal.class, Range.open(new BigDecimal(2.5), new BigDecimal(4.25)));
-//        testValueOf("(ab..fg)", String.class, Range.open("ab", "fg"));
-//        testValueOf("(ab..c..fg)", String.class, Range.open("ab..c", "fg")); // yikes
-//        testValueOf("(a..f)", Character.class, Range.open('a', 'f'));
-    }
-
-    @Test
-    public void testJsonAllTypes() {
-        testJson(Range.closed(1, 10), new TypeToken<Range<Integer>>(){}.getType());
-        testJson(Range.closed((short)1, (short)10), new TypeToken<Range<Short>>(){}.getType());
-        testJson(Range.closed((byte)1, (byte)10), new TypeToken<Range<Byte>>(){}.getType());
-        testJson(Range.closed(1L, 10L), new TypeToken<Range<Long>>(){}.getType());
-        testJson(Range.closed(1f, 10f), new TypeToken<Range<Float>>(){}.getType());
-        testJson(Range.closed(1d, 10d), new TypeToken<Range<Double>>(){}.getType());
-        testJson(Range.closed(BigInteger.valueOf(1), BigInteger.valueOf(10)), new TypeToken<Range<BigInteger>>(){}.getType());
-        testJson(Range.closed(BigDecimal.valueOf(1), BigDecimal.valueOf(10)), new TypeToken<Range<BigDecimal>>(){}.getType());
-//        testJson(Range("ab", "fg"), new TypeToken<Range<String>>(){}.getType());
-//        testJson(Range("ab..c", "fg"), new TypeToken<Range<String>>(){}.getType());
-//        testJson(Range('a', 'f'), new TypeToken<Range<Character>>(){}.getType());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/5d4cc179/samples/apps/src/test/java/quarks/test/samples/apps/RangeTest.java
----------------------------------------------------------------------
diff --git a/samples/apps/src/test/java/quarks/test/samples/apps/RangeTest.java b/samples/apps/src/test/java/quarks/test/samples/apps/RangeTest.java
new file mode 100644
index 0000000..090852b
--- /dev/null
+++ b/samples/apps/src/test/java/quarks/test/samples/apps/RangeTest.java
@@ -0,0 +1,328 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package quarks.test.samples.apps;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.junit.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import quarks.function.Supplier;
+import quarks.samples.apps.Range;
+
+/**
+ * Test Range.
+ */
+public class RangeTest {
+    
+    private <T extends Comparable<?>> void testContains(Range<T> range, T v, Boolean expected) {
+        assertEquals("range"+range+".contains(range"+v+")", expected, range.contains(v));
+    }
+    
+    private <T extends Comparable<?>> void testToString(Range<T> range, String expected) {
+        assertEquals("range.toString()", expected, range.toString());
+    }
+
+    private <T extends Comparable<?>> void testValueOf(String str, Class<T> clazz, Range<T> expected) {
+        assertEquals("Range.valueOf("+clazz.getSimpleName()+")", 
+                Range.valueOf(str, clazz), expected);
+    }
+    
+    private <T extends Comparable<?>> void testEquals(Range<T> r1, Range<T> r2, Boolean expected) {
+        assertEquals("range"+r1+".equals(range"+r2+")", expected, r1.equals(r2));
+    }
+    
+    private <T extends Comparable<?>> void testHashCode(Range<T> range, int hashCode, Boolean expected) {
+        if (expected)
+            assertEquals("range"+range+".hashCode()", hashCode, range.hashCode());
+        else
+            assertFalse("range"+range+".hashCode()", hashCode == range.hashCode());
+    }
+
+    private <T extends Comparable<?>> void testSupportedType(Supplier<Range<T>> range, Class<T> clazz, Boolean expected) {
+        boolean act;
+        try {
+            range.get();
+            act = true;
+        }
+        catch (IllegalArgumentException e) {
+            act = false;
+        }
+        assertEquals("supported type "+clazz.toString(), expected, act);
+    }
+    
+    private <T extends Comparable<?>> void testJson(Range<T> r1, Type typeOfT) {
+        String json = new Gson().toJson(r1);
+        Range<T> r2 = new Gson().fromJson(json, typeOfT);
+        assertEquals("json="+json+" typeOfT="+typeOfT, r1, r2);
+    }
+    
+    @Test
+    public void testSupportedTypes() {
+        testSupportedType(() -> Range.closed("a", "f"), String.class, false);
+        testSupportedType(() -> Range.closed('a', 'f'), Character.class, false);
+        testSupportedType(() -> Range.closed(1, 10), Integer.class, true);
+        testSupportedType(() -> Range.closed((short)1, (short)10), Short.class, true);
+        testSupportedType(() -> Range.closed((byte)1, (byte)10), Byte.class, true);
+        testSupportedType(() -> Range.closed(1L, 10L), Long.class, true);
+        testSupportedType(() -> Range.closed(1f, 10f), Float.class, true);
+        testSupportedType(() -> Range.closed(1d, 10d), Double.class, true);
+        testSupportedType(() -> Range.closed(BigInteger.valueOf(1), BigInteger.valueOf(10)), BigInteger.class, true);
+        testSupportedType(() -> Range.closed(BigDecimal.valueOf(1), BigDecimal.valueOf(10)), BigDecimal.class, true);
+    }
+    
+    @Test
+    public void testContainsOpen() {
+        testContains(Range.open(2,4), 1, false);
+        testContains(Range.open(2,4), 2, false);
+        testContains(Range.open(2,4), 3, true);
+        testContains(Range.open(2,4), 4, false);
+        testContains(Range.open(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsClosed() {
+        testContains(Range.closed(2,4), 1, false);
+        testContains(Range.closed(2,4), 2, true);
+        testContains(Range.closed(2,4), 3, true);
+        testContains(Range.closed(2,4), 4, true);
+        testContains(Range.closed(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsOpenClosed() {
+        testContains(Range.openClosed(2,4), 1, false);
+        testContains(Range.openClosed(2,4), 2, false);
+        testContains(Range.openClosed(2,4), 3, true);
+        testContains(Range.openClosed(2,4), 4, true);
+        testContains(Range.openClosed(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsClosedOpen() {
+        testContains(Range.closedOpen(2,4), 1, false);
+        testContains(Range.closedOpen(2,4), 2, true);
+        testContains(Range.closedOpen(2,4), 3, true);
+        testContains(Range.closedOpen(2,4), 4, false);
+        testContains(Range.closedOpen(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsGreaterThan() {
+        testContains(Range.greaterThan(2), 1, false);
+        testContains(Range.greaterThan(2), 2, false);
+        testContains(Range.greaterThan(2), 3, true);
+    }
+
+    @Test
+    public void testContainsAtLeast() {
+        testContains(Range.atLeast(2), 1, false);
+        testContains(Range.atLeast(2), 2, true);
+        testContains(Range.atLeast(2), 3, true);
+    }
+
+    @Test
+    public void testContainsLessThan() {
+        testContains(Range.lessThan(2), 1, true);
+        testContains(Range.lessThan(2), 2, false);
+        testContains(Range.lessThan(2), 3, false);
+    }
+
+    @Test
+    public void testContainsAtMost() {
+        testContains(Range.atMost(2), 1, true);
+        testContains(Range.atMost(2), 2, true);
+        testContains(Range.atMost(2), 3, false);
+    }
+
+    @Test
+    public void testContainsSingleton() {
+        testContains(Range.singleton(2), 1, false);
+        testContains(Range.singleton(2), 2, true);
+        testContains(Range.singleton(2), 3, false);
+    }
+
+    @Test
+    public void testEquals() {
+        testEquals(Range.closed(2,4), Range.closed(2,4), true);
+        testEquals(Range.closed(2,4), Range.closed(2,3), false);
+        testEquals(Range.closed(3,4), Range.closed(2,4), false);
+        testEquals(Range.atMost(2), Range.atMost(2), true);
+        testEquals(Range.atMost(2), Range.atMost(3), false);
+        testEquals(Range.atLeast(2), Range.atLeast(2), true);
+        testEquals(Range.atLeast(2), Range.atLeast(3), false);
+        testEquals(Range.closed(2,2), Range.singleton(2), true);
+    }
+
+    @Test
+    public void testHashCode() {
+        testHashCode(Range.atMost(2), Range.atMost(2).hashCode(), true);
+        testHashCode(Range.atMost(2), 0, false);
+        testHashCode(Range.atMost(2), Range.atMost(3).hashCode(), false);
+        testHashCode(Range.atLeast(2), Range.atMost(2).hashCode(), false);
+    }
+
+    @Test
+    public void testToString() {
+        testToString(Range.open(2,4), "(2..4)");
+        testToString(Range.closed(2,4), "[2..4]");
+        testToString(Range.openClosed(2,4), "(2..4]");
+        testToString(Range.closedOpen(2,4), "[2..4)");
+        testToString(Range.greaterThan(2), "(2..*)");
+        testToString(Range.atLeast(2), "[2..*)");
+        testToString(Range.lessThan(2), "(*..2)");
+        testToString(Range.atMost(2), "(*..2]");
+    }
+
+    @Test
+    public void testValueOf() {
+        testValueOf("(2..4)", Integer.class, Range.open(2, 4));
+        testValueOf("[2..4]", Integer.class, Range.closed(2, 4));
+        testValueOf("(2..4]", Integer.class, Range.openClosed(2, 4));
+        testValueOf("[2..4)", Integer.class, Range.closedOpen(2, 4));
+        testValueOf("(2..*)", Integer.class, Range.greaterThan(2));
+        testValueOf("[2..*)", Integer.class, Range.atLeast(2));
+        testValueOf("(*..2)", Integer.class, Range.lessThan(2));
+        testValueOf("(*..2]", Integer.class, Range.atMost(2));
+    }
+
+    @Test
+    public void testContainsOtherByte() {
+        testContains(Range.open((byte)2,(byte)4), (byte)1, false);
+        testContains(Range.open((byte)2,(byte)4), (byte)2, false);
+        testContains(Range.open((byte)2,(byte)4), (byte)3, true);
+        testContains(Range.open((byte)2,(byte)4), (byte)4, false);
+        testContains(Range.open((byte)2,(byte)4), (byte)5, false);
+    }
+
+    @Test
+    public void testContainsOtherShort() {
+        testContains(Range.open((short)2,(short)4), (short)1, false);
+        testContains(Range.open((short)2,(short)4), (short)2, false);
+        testContains(Range.open((short)2,(short)4), (short)3, true);
+        testContains(Range.open((short)2,(short)4), (short)4, false);
+        testContains(Range.open((short)2,(short)4), (short)5, false);
+    }
+
+    @Test
+    public void testContainsOtherLong() {
+        testContains(Range.open(2L,4L), 1L, false);
+        testContains(Range.open(2L,4L), 2L, false);
+        testContains(Range.open(2L,4L), 3L, true);
+        testContains(Range.open(2L,4L), 4L, false);
+        testContains(Range.open(2L,4L), 5L, false);
+    }
+
+    @Test
+    public void testContainsOtherFloat() {
+        testContains(Range.open(2f,4f), 1f, false);
+        testContains(Range.open(2f,4f), 2f, false);
+        testContains(Range.open(2f,4f), 2.001f, true);
+        testContains(Range.open(2f,4f), 3.999f, true);
+        testContains(Range.open(2f,4f), 4f, false);
+        testContains(Range.open(2f,4f), 5f, false);
+    }
+
+    @Test
+    public void testContainsOtherDouble() {
+        testContains(Range.open(2d,4d), 1d, false);
+        testContains(Range.open(2d,4d), 2d, false);
+        testContains(Range.open(2d,4d), 2.001d, true);
+        testContains(Range.open(2d,4d), 3.999d, true);
+        testContains(Range.open(2d,4d), 4d, false);
+        testContains(Range.open(2d,4d), 5d, false);
+    }
+
+    @Test
+    public void testContainsOtherBigInteger() {
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(1), false);
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(2), false);
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(3), true);
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(4), false);
+        testContains(Range.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(5), false);
+    }
+
+    @Test
+    public void testContainsOtherBigDecimal() {
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(1), false);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2), false);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2.001), true);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(3.999), true);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(4), false);
+        testContains(Range.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(5), false);
+    }
+
+//  @Test
+//  public void testContainsOtherString() {
+//      testContains(Range.open("b","d"), "a", false);
+//      testContains(Range.open("b","d"), "b", false);
+//      testContains(Range.open("b","d"), "bc", true);
+//      testContains(Range.open("b","d"), "c", true);
+//      testContains(Range.open("b","d"), "cd", true);
+//      testContains(Range.open("b","d"), "d", false);
+//      testContains(Range.open("b","d"), "de", false);
+//      testContains(Range.open("b","d"), "e", false);
+//  }
+
+//  @Test
+//  public void testContainsOtherCharacter() {
+//      testContains(Range.open('b','d'), 'a', false);
+//      testContains(Range.open('b','d'), 'b', false);
+//      testContains(Range.open('b','d'), 'c', true);
+//      testContains(Range.open('b','d'), 'd', false);
+//      testContains(Range.open('b','d'), 'e', false);
+//  }
+
+    @Test
+    public void testValueOfOther() {
+        testValueOf("(2..4)", Short.class, Range.open((short)2, (short)4));
+        testValueOf("(2..4)", Byte.class, Range.open((byte)2, (byte)4));
+        testValueOf("(2..4)", Long.class, Range.open(2L, 4L));
+        testValueOf("(2.128..4.25)", Float.class, Range.open(2.128f, 4.25f));
+        testValueOf("(2.128..4.25)", Double.class, Range.open(2.128d, 4.25d));
+        testValueOf("(2..4)", BigInteger.class, Range.open(BigInteger.valueOf(2), BigInteger.valueOf(4)));
+        testValueOf("(2.5..4.25)", BigDecimal.class, Range.open(new BigDecimal(2.5), new BigDecimal(4.25)));
+//        testValueOf("(ab..fg)", String.class, Range.open("ab", "fg"));
+//        testValueOf("(ab..c..fg)", String.class, Range.open("ab..c", "fg")); // yikes
+//        testValueOf("(a..f)", Character.class, Range.open('a', 'f'));
+    }
+
+    @Test
+    public void testJsonAllTypes() {
+        testJson(Range.closed(1, 10), new TypeToken<Range<Integer>>(){}.getType());
+        testJson(Range.closed((short)1, (short)10), new TypeToken<Range<Short>>(){}.getType());
+        testJson(Range.closed((byte)1, (byte)10), new TypeToken<Range<Byte>>(){}.getType());
+        testJson(Range.closed(1L, 10L), new TypeToken<Range<Long>>(){}.getType());
+        testJson(Range.closed(1f, 10f), new TypeToken<Range<Float>>(){}.getType());
+        testJson(Range.closed(1d, 10d), new TypeToken<Range<Double>>(){}.getType());
+        testJson(Range.closed(BigInteger.valueOf(1), BigInteger.valueOf(10)), new TypeToken<Range<BigInteger>>(){}.getType());
+        testJson(Range.closed(BigDecimal.valueOf(1), BigDecimal.valueOf(10)), new TypeToken<Range<BigDecimal>>(){}.getType());
+//        testJson(Range("ab", "fg"), new TypeToken<Range<String>>(){}.getType());
+//        testJson(Range("ab..c", "fg"), new TypeToken<Range<String>>(){}.getType());
+//        testJson(Range('a', 'f'), new TypeToken<Range<Character>>(){}.getType());
+    }
+
+}