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/07/21 13:17:49 UTC

[48/54] [abbrv] [partial] incubator-quarks git commit: add "org.apache." prefix to edgent package names

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/analytics/sensors/src/test/java/edgent/test/analytics/sensors/FiltersTest.java
----------------------------------------------------------------------
diff --git a/analytics/sensors/src/test/java/edgent/test/analytics/sensors/FiltersTest.java b/analytics/sensors/src/test/java/edgent/test/analytics/sensors/FiltersTest.java
deleted file mode 100644
index 247d197..0000000
--- a/analytics/sensors/src/test/java/edgent/test/analytics/sensors/FiltersTest.java
+++ /dev/null
@@ -1,214 +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 edgent.test.analytics.sensors;
-
-import static edgent.function.Functions.identity;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.junit.Test;
-
-import com.google.gson.JsonObject;
-
-import edgent.analytics.sensors.Deadtime;
-import edgent.analytics.sensors.Filters;
-import edgent.test.providers.direct.DirectTestSetup;
-import edgent.test.topology.TopologyAbstractTest;
-import edgent.topology.TStream;
-import edgent.topology.Topology;
-import edgent.topology.tester.Condition;
-
-public class FiltersTest  extends TopologyAbstractTest implements DirectTestSetup {
-	@Test
-	public void testDeadbandIdentity() throws Exception {
-	    Topology topology = newTopology("testDeadband");
-	    
-	    TStream<Double> values = topology.of(12.9, 3.4, 12.3, 15.6, 18.4, -3.7, -4.5, 15.0, 16.0, 30.0, 42.0 );
-	    
-	    TStream<Double> filtered = Filters.deadband(values, identity(),
-	    		v -> v >= 10.0 && v <= 30.0);
-	    
-        Condition<Long> count = topology.getTester().tupleCount(filtered, 7);
-        Condition<List<Double>> contents = topology.getTester().streamContents(filtered, 12.9, 3.4, 12.3, -3.7, -4.5, 15.0, 42.0 );
-        complete(topology, count);
-        assertTrue(count.valid());
-        assertTrue(contents.valid());
-	}
-	@Test
-	public void testDeadbandFunction() throws Exception {
-	    Topology topology = newTopology("testDeadbandFunction");
-	    
-	    TStream<Double> values = topology.of(3.4, 12.3, 15.6, 18.4, -3.7, -4.5, 15.0, 16.0, 30.0, 42.0 );
-	    
-	    TStream<JsonObject> vj = values.map(d -> {JsonObject j = new JsonObject(); j.addProperty("id", "A"); j.addProperty("reading", d);return j;});
-	    
-	    TStream<JsonObject> filtered = Filters.deadband(vj,
-	    		tuple -> tuple.get("reading").getAsDouble(),
-	    		v -> v >= 10.0 && v <= 30.0);
-	    
-        Condition<Long> count = topology.getTester().tupleCount(filtered, 6);
-        Condition<List<JsonObject>> contents = topology.getTester().streamContents(filtered);
-        complete(topology, count);
-        assertTrue(count.valid());
-        
-        List<JsonObject> results = contents.getResult();
-        assertEquals(6, results.size());
-        
-        assertEquals("A", results.get(0).get("id").getAsString());
-        assertEquals(3.4, results.get(0).get("reading").getAsDouble(), 0.0);
-        
-        // First value after a period out of range
-        assertEquals("A", results.get(1).get("id").getAsString());
-        assertEquals(12.3, results.get(1).get("reading").getAsDouble(), 0.0);
-        
-        assertEquals("A", results.get(2).get("id").getAsString());
-        assertEquals(-3.7, results.get(2).get("reading").getAsDouble(), 0.0);
-        
-        assertEquals("A", results.get(3).get("id").getAsString());
-        assertEquals(-4.5, results.get(3).get("reading").getAsDouble(), 0.0);
-        
-        assertEquals("A", results.get(4).get("id").getAsString());
-        assertEquals(15.0, results.get(4).get("reading").getAsDouble(), 0.0);
-        
-        assertEquals("A", results.get(5).get("id").getAsString());
-        assertEquals(42.0, results.get(5).get("reading").getAsDouble(), 0.0);
-	}
-	
-	@Test
-	public void testDeadbandMaxSuppression() throws Exception {
-	    Topology topology = newTopology("testDeadbandMaxSuppression");
-	    
-	    TStream<Double> values = topology.of(12.9, 3.4, 12.3, 15.6, 18.4, -3.7, -4.5, 15.0, 16.0, 30.0, 42.0 );
-	    
-	    // 18.4 will be included as it is delayed since the last inband value.
-	    values = values.modify(tuple -> {if (tuple == 18.4)
-			try {
-				Thread.sleep(5000);
-			} catch (Exception e) {
-				throw new RuntimeException(e);
-			} return tuple;});
-	    
-	    TStream<Double> filtered = Filters.deadband(values, identity(),
-	    		v -> v >= 10.0 && v <= 30.0, 3, TimeUnit.SECONDS);
-	    
-        Condition<Long> count = topology.getTester().tupleCount(filtered, 8);
-        Condition<List<Double>> contents = topology.getTester().streamContents(filtered, 12.9, 3.4, 12.3, 18.4, -3.7, -4.5, 15.0, 42.0 );
-        complete(topology, count);
-        assertTrue(count.valid());
-        assertTrue(contents.valid());
-	}
-    
-    @Test
-    public void testDeadtime() throws Exception {
-        Topology topology = newTopology("testDeadtime");
-        
-        int maxTupleCnt = 10;
-        AtomicInteger cnt = new AtomicInteger();
-        
-        TStream<Integer> values = topology.poll(() -> {
-            int curCnt = cnt.incrementAndGet();
-            if (curCnt > maxTupleCnt)
-                return null;
-            return curCnt;
-            }, 100, TimeUnit.MILLISECONDS);
-        
-        // use a deadtime value that causes filtering of every other tuple
-        TStream<Integer> filtered = Filters.deadtime(values, 150, TimeUnit.MILLISECONDS);
-        
-        Condition<Long> count = topology.getTester().tupleCount(filtered, maxTupleCnt/2);
-        Condition<List<Integer>> contents = topology.getTester().streamContents(filtered, 1, 3, 5, 7, 9 );
-        complete(topology, count);
-        
-        assertTrue(contents.getResult().toString(), contents.valid());
-    }
-    
-    @Test
-    public void testDeadtimeNoDeadtime() throws Exception {
-        Topology topology = newTopology("testDeadtimeNoDeadtime");
-        
-        TStream<Integer> values = topology.of(1,2,3,4,5,6,7,8,9,10);
-        
-        // no deadtime
-        TStream<Integer> filtered = Filters.deadtime(values, 0, TimeUnit.MILLISECONDS);
-        
-        Condition<Long> count = topology.getTester().tupleCount(filtered, 10);
-        Condition<List<Integer>> contents = topology.getTester().streamContents(filtered, 1,2,3,4,5,6,7,8,9,10 );
-        complete(topology, count);
-        
-        assertTrue(contents.getResult().toString(), contents.valid());
-    }
-    
-    @Test
-    public void testDeadtimeTooShort() throws Exception {
-        Topology topology = newTopology("testDeadtimeTooShort");
-        
-        TStream<Integer> values = topology.of(1,2,3,4,5,6,7,8,9,10);
-        
-        // no deadtime due to < 1ms
-        TStream<Integer> filtered = Filters.deadtime(values, 999, TimeUnit.MICROSECONDS);
-        
-        Condition<Long> count = topology.getTester().tupleCount(filtered, 10);
-        Condition<List<Integer>> contents = topology.getTester().streamContents(filtered, 1,2,3,4,5,6,7,8,9,10 );
-        complete(topology, count);
-        
-        assertTrue(contents.getResult().toString(), contents.valid());
-    }
-    
-    @Test
-    public void testDeadtimeDynamic() throws Exception {
-        // Timing variances on shared machines can cause this test to fail
-        assumeTrue(!Boolean.getBoolean("edgent.build.ci"));
-        
-        Topology topology = newTopology("testDeadtimeDynamic");
-
-        // initial deadtime to consume 5 tuples. get 1, skip 2-6, get 7, skip 8-10
-        Deadtime<Integer> deadtime = new Deadtime<>(500, TimeUnit.MILLISECONDS);
-
-        int maxTupleCnt = 10;
-        AtomicInteger cnt = new AtomicInteger();
-        
-        TStream<Integer> values = topology.poll(() -> {
-            int curCnt = cnt.incrementAndGet();
-            if (curCnt > maxTupleCnt)
-                return null;
-            if (curCnt == 4) {
-                // shorten deadtime, so should now get tup 4,6,8,10
-                deadtime.setPeriod(150, TimeUnit.MILLISECONDS);
-            }
-            else if (curCnt == 7) {
-                // lengthen deadtime, so should now exclude 8 too and then 10
-                deadtime.setPeriod(250, TimeUnit.MILLISECONDS);
-            }
-            return curCnt;
-            }, 100, TimeUnit.MILLISECONDS);
-        
-        TStream<Integer> filtered = values.filter(deadtime);
-        
-        Condition<Long> count = topology.getTester().tupleCount(filtered, 4);
-        Condition<List<Integer>> contents = topology.getTester().streamContents(filtered, 1, 4, 6, 9 );
-        complete(topology, count);
-        
-        assertTrue(contents.getResult().toString(), contents.valid());
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/analytics/sensors/src/test/java/edgent/test/analytics/sensors/RangeTest.java
----------------------------------------------------------------------
diff --git a/analytics/sensors/src/test/java/edgent/test/analytics/sensors/RangeTest.java b/analytics/sensors/src/test/java/edgent/test/analytics/sensors/RangeTest.java
deleted file mode 100644
index a96cfd8..0000000
--- a/analytics/sensors/src/test/java/edgent/test/analytics/sensors/RangeTest.java
+++ /dev/null
@@ -1,462 +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 edgent.test.analytics.sensors;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertTrue;
-
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Comparator;
-
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-
-import edgent.analytics.sensors.Range;
-import edgent.analytics.sensors.Ranges;
-import edgent.function.Function;
-
-/**
- * Test Range and Ranges
- */
-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 testPredicate(Range<T> range, T v, Boolean expected) {
-        assertEquals("range"+range+".test(range"+v+")", expected, range.test(v));
-    }
-    
-    private <T extends Comparable<?>> void testToString(Range<T> range, String expected) {
-        assertEquals("range.toString()", expected, range.toString());
-    }
-    
-    private <T extends Comparable<?>> void testToStringUnsigned(Range<T> range, String expected) {
-        assertEquals("range.toString()", expected, range.toStringUnsigned());
-    }
-
-    private <T extends Comparable<?>> void testValueOf(Function<String,Range<T>> valueOf, Range<T> expected) {
-        assertEquals("Ranges.valueOf(\""+expected.toString()+"\")", 
-                valueOf.apply(expected.toString()), 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 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);
-    }
-    
-    /*
-     * Thoroughly test all aspects of Range/Ranges for Integers
-     */
-    
-    @Test
-    public void testContainsOpen() {
-        testContains(Ranges.open(2,4), 1, false);
-        testContains(Ranges.open(2,4), 2, false);
-        testContains(Ranges.open(2,4), 3, true);
-        testContains(Ranges.open(2,4), 4, false);
-        testContains(Ranges.open(2,4), 5, false);
-    }
-
-    @Test
-    public void testContainsClosed() {
-        testContains(Ranges.closed(2,4), 1, false);
-        testContains(Ranges.closed(2,4), 2, true);
-        testContains(Ranges.closed(2,4), 3, true);
-        testContains(Ranges.closed(2,4), 4, true);
-        testContains(Ranges.closed(2,4), 5, false);
-    }
-
-    @Test
-    public void testContainsOpenClosed() {
-        testContains(Ranges.openClosed(2,4), 1, false);
-        testContains(Ranges.openClosed(2,4), 2, false);
-        testContains(Ranges.openClosed(2,4), 3, true);
-        testContains(Ranges.openClosed(2,4), 4, true);
-        testContains(Ranges.openClosed(2,4), 5, false);
-    }
-
-    @Test
-    public void testContainsClosedOpen() {
-        testContains(Ranges.closedOpen(2,4), 1, false);
-        testContains(Ranges.closedOpen(2,4), 2, true);
-        testContains(Ranges.closedOpen(2,4), 3, true);
-        testContains(Ranges.closedOpen(2,4), 4, false);
-        testContains(Ranges.closedOpen(2,4), 5, false);
-    }
-
-    @Test
-    public void testContainsGreaterThan() {
-        testContains(Ranges.greaterThan(2), 1, false);
-        testContains(Ranges.greaterThan(2), 2, false);
-        testContains(Ranges.greaterThan(2), 3, true);
-    }
-
-    @Test
-    public void testContainsAtLeast() {
-        testContains(Ranges.atLeast(2), 1, false);
-        testContains(Ranges.atLeast(2), 2, true);
-        testContains(Ranges.atLeast(2), 3, true);
-    }
-
-    @Test
-    public void testContainsLessThan() {
-        testContains(Ranges.lessThan(2), 1, true);
-        testContains(Ranges.lessThan(2), 2, false);
-        testContains(Ranges.lessThan(2), 3, false);
-    }
-
-    @Test
-    public void testContainsAtMost() {
-        testContains(Ranges.atMost(2), 1, true);
-        testContains(Ranges.atMost(2), 2, true);
-        testContains(Ranges.atMost(2), 3, false);
-    }
-
-    @Test
-    public void testContainsSingleton() {
-        testContains(Ranges.singleton(2), 1, false);
-        testContains(Ranges.singleton(2), 2, true);
-        testContains(Ranges.singleton(2), 3, false);
-    }
-    
-    @Test
-    public void testPredicate() {
-        testPredicate(Ranges.closed(2,4), 1, false);
-        testPredicate(Ranges.closed(2,4), 2, true);
-        testPredicate(Ranges.closed(2,4), 3, true);
-        testPredicate(Ranges.closed(2,4), 4, true);
-        testPredicate(Ranges.closed(2,4), 5, false);
-    }
-
-    @Test
-    public void testEquals() {
-        testEquals(Ranges.closed(2,4), Ranges.closed(2,4), true);
-        testEquals(Ranges.closed(2,4), Ranges.closed(2,3), false);
-        testEquals(Ranges.closed(3,4), Ranges.closed(2,4), false);
-        testEquals(Ranges.atMost(2), Ranges.atMost(2), true);
-        testEquals(Ranges.atMost(2), Ranges.atMost(3), false);
-        testEquals(Ranges.atLeast(2), Ranges.atLeast(2), true);
-        testEquals(Ranges.atLeast(2), Ranges.atLeast(3), false);
-        testEquals(Ranges.closed(2,2), Ranges.singleton(2), true);
-    }
-
-    @Test
-    public void testHashCode() {
-        testHashCode(Ranges.atMost(2), Ranges.atMost(2).hashCode(), true);
-        testHashCode(Ranges.atMost(2), 0, false);
-        testHashCode(Ranges.atMost(2), Ranges.atMost(3).hashCode(), false);
-        testHashCode(Ranges.atLeast(2), Ranges.atMost(2).hashCode(), false);
-    }
-    
-    @Test
-    public void testEndpointAccess() {
-        // {lower,upper}Endpoint(),
-        // has{Lower,Upper}Endpoint()
-        // {lower,upper}BoundType()
-        Range<Integer> r1 = Ranges.openClosed(2,4);
-        assertEquals(Range.BoundType.OPEN, r1.lowerBoundType());
-        assertTrue(r1.hasLowerEndpoint());
-        assertEquals(2, r1.lowerEndpoint().intValue());
-        assertTrue(r1.hasUpperEndpoint());
-        assertEquals(4, r1.upperEndpoint().intValue());
-        assertEquals(Range.BoundType.CLOSED, r1.upperBoundType());
-
-        Range<Integer> r2 = Ranges.openClosed(2,4);
-        assertNotSame(r1, r2);
-        
-        Range<Integer> r3 = Ranges.atMost(2);
-        assertFalse(r3.hasLowerEndpoint());
-        try {
-            r3.lowerEndpoint();
-            assertTrue(false);
-        }
-        catch (IllegalStateException e) {
-            // expected
-        }
-        
-        r3 = Ranges.atLeast(2);
-        assertFalse(r3.hasUpperEndpoint());
-        try {
-            r3.upperEndpoint();
-            assertTrue(false);
-        }
-        catch (IllegalStateException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void testToString() {
-        testToString(Ranges.open(2,4), "(2..4)");
-        testToString(Ranges.closed(2,4), "[2..4]");
-        testToString(Ranges.openClosed(2,4), "(2..4]");
-        testToString(Ranges.closedOpen(2,4), "[2..4)");
-        testToString(Ranges.greaterThan(2), "(2..*)");
-        testToString(Ranges.atLeast(2), "[2..*)");
-        testToString(Ranges.lessThan(2), "(*..2)");
-        testToString(Ranges.atMost(2), "(*..2]");
-    }
-
-    @Test
-    public void testValueOf() {
-        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.open(2, 4));
-        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.closed(2, 4));
-        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.openClosed(2, 4));
-        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.closedOpen(2, 4));
-        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.greaterThan(2));
-        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.atLeast(2));
-        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.lessThan(2));
-        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.atMost(2));
-    }
-
-    
-    /*
-     * Thoroughly test contains() and valueOf() for other types of T
-     */
-
-    @Test
-    public void testContainsOtherByte() {
-        testContains(Ranges.open((byte)2,(byte)4), (byte)1, false);
-        testContains(Ranges.open((byte)2,(byte)4), (byte)2, false);
-        testContains(Ranges.open((byte)2,(byte)4), (byte)3, true);
-        testContains(Ranges.open((byte)2,(byte)4), (byte)4, false);
-        testContains(Ranges.open((byte)2,(byte)4), (byte)5, false);
-    }
-
-    @Test
-    public void testContainsOtherShort() {
-        testContains(Ranges.open((short)2,(short)4), (short)1, false);
-        testContains(Ranges.open((short)2,(short)4), (short)2, false);
-        testContains(Ranges.open((short)2,(short)4), (short)3, true);
-        testContains(Ranges.open((short)2,(short)4), (short)4, false);
-        testContains(Ranges.open((short)2,(short)4), (short)5, false);
-    }
-
-    @Test
-    public void testContainsOtherLong() {
-        testContains(Ranges.open(2L,4L), 1L, false);
-        testContains(Ranges.open(2L,4L), 2L, false);
-        testContains(Ranges.open(2L,4L), 3L, true);
-        testContains(Ranges.open(2L,4L), 4L, false);
-        testContains(Ranges.open(2L,4L), 5L, false);
-    }
-
-    @Test
-    public void testContainsOtherFloat() {
-        testContains(Ranges.open(2f,4f), 1f, false);
-        testContains(Ranges.open(2f,4f), 2f, false);
-        testContains(Ranges.open(2f,4f), 2.001f, true);
-        testContains(Ranges.open(2f,4f), 3.999f, true);
-        testContains(Ranges.open(2f,4f), 4f, false);
-        testContains(Ranges.open(2f,4f), 5f, false);
-    }
-
-    @Test
-    public void testContainsOtherDouble() {
-        testContains(Ranges.open(2d,4d), 1d, false);
-        testContains(Ranges.open(2d,4d), 2d, false);
-        testContains(Ranges.open(2d,4d), 2.001d, true);
-        testContains(Ranges.open(2d,4d), 3.999d, true);
-        testContains(Ranges.open(2d,4d), 4d, false);
-        testContains(Ranges.open(2d,4d), 5d, false);
-    }
-
-    @Test
-    public void testContainsOtherBigInteger() {
-        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(1), false);
-        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(2), false);
-        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(3), true);
-        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(4), false);
-        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(5), false);
-    }
-
-    @Test
-    public void testContainsOtherBigDecimal() {
-        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(1), false);
-        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2), false);
-        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2.001), true);
-        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(3.999), true);
-        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(4), false);
-        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(5), false);
-    }
-
-    @Test
-    public void testContainsOtherString() {
-        testContains(Ranges.open("b","d"), "a", false);
-        testContains(Ranges.open("b","d"), "b", false);
-        testContains(Ranges.open("b","d"), "bc", true);
-        testContains(Ranges.open("b","d"), "c", true);
-        testContains(Ranges.open("b","d"), "cd", true);
-        testContains(Ranges.open("b","d"), "d", false);
-        testContains(Ranges.open("b","d"), "de", false);
-        testContains(Ranges.open("b","d"), "e", false);
-    }
-
-    @Test
-    public void testContainsOtherCharacter() {
-        testContains(Ranges.open('b','d'), 'a', false);
-        testContains(Ranges.open('b','d'), 'b', false);
-        testContains(Ranges.open('b','d'), 'c', true);
-        testContains(Ranges.open('b','d'), 'd', false);
-        testContains(Ranges.open('b','d'), 'e', false);
-    }
-
-    @Test
-    public void testValueOfOtherT() {
-        testValueOf(s -> Ranges.valueOfShort(s), Ranges.open((short)2, (short)4));
-        testValueOf(s -> Ranges.valueOfByte(s), Ranges.open((byte)2, (byte)4));
-        testValueOf(s -> Ranges.valueOfLong(s), Ranges.open(2L, 4L));
-        testValueOf(s -> Ranges.valueOfFloat(s), Ranges.open(2.128f, 4.25f));
-        testValueOf(s -> Ranges.valueOfDouble(s), Ranges.open(2.128d, 4.25d));
-        testValueOf(s -> Ranges.valueOfBigInteger(s), Ranges.open(BigInteger.valueOf(2), BigInteger.valueOf(4)));
-        testValueOf(s -> Ranges.valueOfBigDecimal(s), Ranges.open(new BigDecimal(2.5), new BigDecimal(4.25)));
-        testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab", "fg"));
-        testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab", "."));
-        testValueOf(s -> Ranges.valueOfString(s), Ranges.open(".", "ab"));
-        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('a', 'f'));
-        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('a', '.'));
-        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('.', '.'));
-        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('.', 'f'));
-
-        // problem cases Range<String> with embedded ".."
-        try { 
-            testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab..c", "fg"));
-            assertTrue(false);
-        } catch (IllegalArgumentException e) { /* expected */ }
-        try { 
-            testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab", "fg..h"));
-            assertTrue(false);
-        } catch (IllegalArgumentException e) { /* expected */ }
-        try { 
-            testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab..c", "fg..h"));
-            assertTrue(false);
-        } catch (IllegalArgumentException e) { /* expected */ }
-    }
-    
-    /*
-     * Test unsigned handling.
-     * toUnsignedString() and compare(T, Comparator<T>)
-     */
-
-    @Test
-    public void testToUnsignedString() {
-        testToStringUnsigned(Ranges.open((byte)0,(byte)255), "(0..255)");
-        testToStringUnsigned(Ranges.closed((byte)0,(byte)255), "[0..255]");
-        testToStringUnsigned(Ranges.open((short)0,(short)0xFFFF), "(0..65535)");
-        testToStringUnsigned(Ranges.open(0,0xFFFFFFFF), "(0.."+Integer.toUnsignedString(0xFFFFFFFF)+")");
-        testToStringUnsigned(Ranges.open(0L,0xFFFFFFFFFFFFFFFFL), "(0.."+Long.toUnsignedString(0xFFFFFFFFFFFFFFFFL)+")");
-    }
-
-    @Test
-    public void testContainsUnsigned() {
-        // Unsigned Byte ======================
-        Comparator<Byte> unsignedByteComparator = new Comparator<Byte>() {
-            public int compare(Byte v1, Byte v2) {
-                return Integer.compareUnsigned(Byte.toUnsignedInt(v1), Byte.toUnsignedInt(v2));
-            }
-            public boolean equals(Object o2) { return o2==this; }
-            };
-            
-        Range<Byte> byteRange = Ranges.closed((byte)5, (byte)255); // intend unsigned
-        assertFalse(byteRange.contains((byte)6));  // not <= -1
-        assertTrue(byteRange.contains((byte)6, unsignedByteComparator));
-        assertFalse(byteRange.contains((byte)0xF0)); // not >= 5
-        assertTrue(byteRange.contains((byte)0xF0, unsignedByteComparator));
-        
-        // Unsigned Short ======================
-        Comparator<Short> unsignedShortComparator = new Comparator<Short>() {
-            public int compare(Short v1, Short v2) {
-                return Integer.compareUnsigned(Short.toUnsignedInt(v1), Short.toUnsignedInt(v2));
-            }
-            public boolean equals(Object o2) { return o2==this; }
-            };
-        Range<Short> shortRange = Ranges.closed((short)5, (short)0xFFFF); // intend unsigned
-        assertFalse(shortRange.contains((short)6));  // not <= -1
-        assertTrue(shortRange.contains((short)6, unsignedShortComparator));
-        assertFalse(shortRange.contains((short)0xFFF0)); // not >= 5
-        assertTrue(shortRange.contains((short)0xFFF0, unsignedShortComparator));
-        
-        // Unsigned Integer ======================
-        Comparator<Integer> unsignedIntegerComparator = new Comparator<Integer>() {
-            public int compare(Integer v1, Integer v2) {
-                return Integer.compareUnsigned(v1, v2);
-            }
-            public boolean equals(Object o2) { return o2==this; }
-            };
-        Range<Integer> intRange = Ranges.closed(5, 0xFFFFFFFF); // intend unsigned
-        assertFalse(intRange.contains(6));  // not <= -1
-        assertTrue(intRange.contains(6, unsignedIntegerComparator));
-        assertFalse(intRange.contains(0xFFFFFFF0)); // not >= 5
-        assertTrue(intRange.contains(0xFFFFFFF0, unsignedIntegerComparator));
-        
-        // Unsigned Long ======================
-        Comparator<Long> unsignedLongComparator = new Comparator<Long>() {
-            public int compare(Long v1, Long v2) {
-                return Long.compareUnsigned(v1, v2);
-            }
-            public boolean equals(Object o2) { return o2==this; }
-            };
-        Range<Long> longRange = Ranges.closed(5L, 0xFFFFFFFFFFFFFFFFL); // intend unsigned
-        assertFalse(longRange.contains(6L));  // not <= -1
-        assertTrue(longRange.contains(6L, unsignedLongComparator));
-        assertFalse(longRange.contains(0xFFFFFFFFFFFFFFF0L));  // not >= 5
-        assertTrue(longRange.contains(0xFFFFFFFFFFFFFFF0L, unsignedLongComparator));
-    }
-
-    @Test
-    public void testJsonAllTypes() {
-        // json = new Gson().toJson(Range<T>);
-        // range = new Gson().fromJson(json, typeOfT);
-        testJson(Ranges.closed(1, 10), new TypeToken<Range<Integer>>(){}.getType());
-        testJson(Ranges.closed((short)1, (short)10), new TypeToken<Range<Short>>(){}.getType());
-        testJson(Ranges.closed((byte)1, (byte)10), new TypeToken<Range<Byte>>(){}.getType());
-        testJson(Ranges.closed(1L, 10L), new TypeToken<Range<Long>>(){}.getType());
-        testJson(Ranges.closed(1f, 10f), new TypeToken<Range<Float>>(){}.getType());
-        testJson(Ranges.closed(1d, 10d), new TypeToken<Range<Double>>(){}.getType());
-        testJson(Ranges.closed(BigInteger.valueOf(1), BigInteger.valueOf(10)), new TypeToken<Range<BigInteger>>(){}.getType());
-        testJson(Ranges.closed(BigDecimal.valueOf(1), BigDecimal.valueOf(10)), new TypeToken<Range<BigDecimal>>(){}.getType());
-        testJson(Ranges.closed("ab", "fg"), new TypeToken<Range<String>>(){}.getType());
-        testJson(Ranges.closed("ab..c", "fg"), new TypeToken<Range<String>>(){}.getType());
-        testJson(Ranges.closed('a', 'f'), new TypeToken<Range<Character>>(){}.getType());
-        testJson(Ranges.closed('.', 'f'), new TypeToken<Range<Character>>(){}.getType());
-        testJson(Ranges.closed('.', '.'), new TypeToken<Range<Character>>(){}.getType());
-        testJson(Ranges.closed('a', '.'), new TypeToken<Range<Character>>(){}.getType());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/analytics/sensors/src/test/java/org/apache/edgent/test/analytics/sensors/FiltersTest.java
----------------------------------------------------------------------
diff --git a/analytics/sensors/src/test/java/org/apache/edgent/test/analytics/sensors/FiltersTest.java b/analytics/sensors/src/test/java/org/apache/edgent/test/analytics/sensors/FiltersTest.java
new file mode 100644
index 0000000..f91f7fa
--- /dev/null
+++ b/analytics/sensors/src/test/java/org/apache/edgent/test/analytics/sensors/FiltersTest.java
@@ -0,0 +1,213 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.edgent.test.analytics.sensors;
+
+import static org.apache.edgent.function.Functions.identity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.edgent.analytics.sensors.Deadtime;
+import org.apache.edgent.analytics.sensors.Filters;
+import org.apache.edgent.test.providers.direct.DirectTestSetup;
+import org.apache.edgent.test.topology.TopologyAbstractTest;
+import org.apache.edgent.topology.TStream;
+import org.apache.edgent.topology.Topology;
+import org.apache.edgent.topology.tester.Condition;
+import org.junit.Test;
+
+import com.google.gson.JsonObject;
+
+public class FiltersTest  extends TopologyAbstractTest implements DirectTestSetup {
+	@Test
+	public void testDeadbandIdentity() throws Exception {
+	    Topology topology = newTopology("testDeadband");
+	    
+	    TStream<Double> values = topology.of(12.9, 3.4, 12.3, 15.6, 18.4, -3.7, -4.5, 15.0, 16.0, 30.0, 42.0 );
+	    
+	    TStream<Double> filtered = Filters.deadband(values, identity(),
+	    		v -> v >= 10.0 && v <= 30.0);
+	    
+        Condition<Long> count = topology.getTester().tupleCount(filtered, 7);
+        Condition<List<Double>> contents = topology.getTester().streamContents(filtered, 12.9, 3.4, 12.3, -3.7, -4.5, 15.0, 42.0 );
+        complete(topology, count);
+        assertTrue(count.valid());
+        assertTrue(contents.valid());
+	}
+	@Test
+	public void testDeadbandFunction() throws Exception {
+	    Topology topology = newTopology("testDeadbandFunction");
+	    
+	    TStream<Double> values = topology.of(3.4, 12.3, 15.6, 18.4, -3.7, -4.5, 15.0, 16.0, 30.0, 42.0 );
+	    
+	    TStream<JsonObject> vj = values.map(d -> {JsonObject j = new JsonObject(); j.addProperty("id", "A"); j.addProperty("reading", d);return j;});
+	    
+	    TStream<JsonObject> filtered = Filters.deadband(vj,
+	    		tuple -> tuple.get("reading").getAsDouble(),
+	    		v -> v >= 10.0 && v <= 30.0);
+	    
+        Condition<Long> count = topology.getTester().tupleCount(filtered, 6);
+        Condition<List<JsonObject>> contents = topology.getTester().streamContents(filtered);
+        complete(topology, count);
+        assertTrue(count.valid());
+        
+        List<JsonObject> results = contents.getResult();
+        assertEquals(6, results.size());
+        
+        assertEquals("A", results.get(0).get("id").getAsString());
+        assertEquals(3.4, results.get(0).get("reading").getAsDouble(), 0.0);
+        
+        // First value after a period out of range
+        assertEquals("A", results.get(1).get("id").getAsString());
+        assertEquals(12.3, results.get(1).get("reading").getAsDouble(), 0.0);
+        
+        assertEquals("A", results.get(2).get("id").getAsString());
+        assertEquals(-3.7, results.get(2).get("reading").getAsDouble(), 0.0);
+        
+        assertEquals("A", results.get(3).get("id").getAsString());
+        assertEquals(-4.5, results.get(3).get("reading").getAsDouble(), 0.0);
+        
+        assertEquals("A", results.get(4).get("id").getAsString());
+        assertEquals(15.0, results.get(4).get("reading").getAsDouble(), 0.0);
+        
+        assertEquals("A", results.get(5).get("id").getAsString());
+        assertEquals(42.0, results.get(5).get("reading").getAsDouble(), 0.0);
+	}
+	
+	@Test
+	public void testDeadbandMaxSuppression() throws Exception {
+	    Topology topology = newTopology("testDeadbandMaxSuppression");
+	    
+	    TStream<Double> values = topology.of(12.9, 3.4, 12.3, 15.6, 18.4, -3.7, -4.5, 15.0, 16.0, 30.0, 42.0 );
+	    
+	    // 18.4 will be included as it is delayed since the last inband value.
+	    values = values.modify(tuple -> {if (tuple == 18.4)
+			try {
+				Thread.sleep(5000);
+			} catch (Exception e) {
+				throw new RuntimeException(e);
+			} return tuple;});
+	    
+	    TStream<Double> filtered = Filters.deadband(values, identity(),
+	    		v -> v >= 10.0 && v <= 30.0, 3, TimeUnit.SECONDS);
+	    
+        Condition<Long> count = topology.getTester().tupleCount(filtered, 8);
+        Condition<List<Double>> contents = topology.getTester().streamContents(filtered, 12.9, 3.4, 12.3, 18.4, -3.7, -4.5, 15.0, 42.0 );
+        complete(topology, count);
+        assertTrue(count.valid());
+        assertTrue(contents.valid());
+	}
+    
+    @Test
+    public void testDeadtime() throws Exception {
+        Topology topology = newTopology("testDeadtime");
+        
+        int maxTupleCnt = 10;
+        AtomicInteger cnt = new AtomicInteger();
+        
+        TStream<Integer> values = topology.poll(() -> {
+            int curCnt = cnt.incrementAndGet();
+            if (curCnt > maxTupleCnt)
+                return null;
+            return curCnt;
+            }, 100, TimeUnit.MILLISECONDS);
+        
+        // use a deadtime value that causes filtering of every other tuple
+        TStream<Integer> filtered = Filters.deadtime(values, 150, TimeUnit.MILLISECONDS);
+        
+        Condition<Long> count = topology.getTester().tupleCount(filtered, maxTupleCnt/2);
+        Condition<List<Integer>> contents = topology.getTester().streamContents(filtered, 1, 3, 5, 7, 9 );
+        complete(topology, count);
+        
+        assertTrue(contents.getResult().toString(), contents.valid());
+    }
+    
+    @Test
+    public void testDeadtimeNoDeadtime() throws Exception {
+        Topology topology = newTopology("testDeadtimeNoDeadtime");
+        
+        TStream<Integer> values = topology.of(1,2,3,4,5,6,7,8,9,10);
+        
+        // no deadtime
+        TStream<Integer> filtered = Filters.deadtime(values, 0, TimeUnit.MILLISECONDS);
+        
+        Condition<Long> count = topology.getTester().tupleCount(filtered, 10);
+        Condition<List<Integer>> contents = topology.getTester().streamContents(filtered, 1,2,3,4,5,6,7,8,9,10 );
+        complete(topology, count);
+        
+        assertTrue(contents.getResult().toString(), contents.valid());
+    }
+    
+    @Test
+    public void testDeadtimeTooShort() throws Exception {
+        Topology topology = newTopology("testDeadtimeTooShort");
+        
+        TStream<Integer> values = topology.of(1,2,3,4,5,6,7,8,9,10);
+        
+        // no deadtime due to < 1ms
+        TStream<Integer> filtered = Filters.deadtime(values, 999, TimeUnit.MICROSECONDS);
+        
+        Condition<Long> count = topology.getTester().tupleCount(filtered, 10);
+        Condition<List<Integer>> contents = topology.getTester().streamContents(filtered, 1,2,3,4,5,6,7,8,9,10 );
+        complete(topology, count);
+        
+        assertTrue(contents.getResult().toString(), contents.valid());
+    }
+    
+    @Test
+    public void testDeadtimeDynamic() throws Exception {
+        // Timing variances on shared machines can cause this test to fail
+        assumeTrue(!Boolean.getBoolean("edgent.build.ci"));
+        
+        Topology topology = newTopology("testDeadtimeDynamic");
+
+        // initial deadtime to consume 5 tuples. get 1, skip 2-6, get 7, skip 8-10
+        Deadtime<Integer> deadtime = new Deadtime<>(500, TimeUnit.MILLISECONDS);
+
+        int maxTupleCnt = 10;
+        AtomicInteger cnt = new AtomicInteger();
+        
+        TStream<Integer> values = topology.poll(() -> {
+            int curCnt = cnt.incrementAndGet();
+            if (curCnt > maxTupleCnt)
+                return null;
+            if (curCnt == 4) {
+                // shorten deadtime, so should now get tup 4,6,8,10
+                deadtime.setPeriod(150, TimeUnit.MILLISECONDS);
+            }
+            else if (curCnt == 7) {
+                // lengthen deadtime, so should now exclude 8 too and then 10
+                deadtime.setPeriod(250, TimeUnit.MILLISECONDS);
+            }
+            return curCnt;
+            }, 100, TimeUnit.MILLISECONDS);
+        
+        TStream<Integer> filtered = values.filter(deadtime);
+        
+        Condition<Long> count = topology.getTester().tupleCount(filtered, 4);
+        Condition<List<Integer>> contents = topology.getTester().streamContents(filtered, 1, 4, 6, 9 );
+        complete(topology, count);
+        
+        assertTrue(contents.getResult().toString(), contents.valid());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/analytics/sensors/src/test/java/org/apache/edgent/test/analytics/sensors/RangeTest.java
----------------------------------------------------------------------
diff --git a/analytics/sensors/src/test/java/org/apache/edgent/test/analytics/sensors/RangeTest.java b/analytics/sensors/src/test/java/org/apache/edgent/test/analytics/sensors/RangeTest.java
new file mode 100644
index 0000000..7d4b316
--- /dev/null
+++ b/analytics/sensors/src/test/java/org/apache/edgent/test/analytics/sensors/RangeTest.java
@@ -0,0 +1,461 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.edgent.test.analytics.sensors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Comparator;
+
+import org.apache.edgent.analytics.sensors.Range;
+import org.apache.edgent.analytics.sensors.Ranges;
+import org.apache.edgent.function.Function;
+import org.junit.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * Test Range and Ranges
+ */
+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 testPredicate(Range<T> range, T v, Boolean expected) {
+        assertEquals("range"+range+".test(range"+v+")", expected, range.test(v));
+    }
+    
+    private <T extends Comparable<?>> void testToString(Range<T> range, String expected) {
+        assertEquals("range.toString()", expected, range.toString());
+    }
+    
+    private <T extends Comparable<?>> void testToStringUnsigned(Range<T> range, String expected) {
+        assertEquals("range.toString()", expected, range.toStringUnsigned());
+    }
+
+    private <T extends Comparable<?>> void testValueOf(Function<String,Range<T>> valueOf, Range<T> expected) {
+        assertEquals("Ranges.valueOf(\""+expected.toString()+"\")", 
+                valueOf.apply(expected.toString()), 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 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);
+    }
+    
+    /*
+     * Thoroughly test all aspects of Range/Ranges for Integers
+     */
+    
+    @Test
+    public void testContainsOpen() {
+        testContains(Ranges.open(2,4), 1, false);
+        testContains(Ranges.open(2,4), 2, false);
+        testContains(Ranges.open(2,4), 3, true);
+        testContains(Ranges.open(2,4), 4, false);
+        testContains(Ranges.open(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsClosed() {
+        testContains(Ranges.closed(2,4), 1, false);
+        testContains(Ranges.closed(2,4), 2, true);
+        testContains(Ranges.closed(2,4), 3, true);
+        testContains(Ranges.closed(2,4), 4, true);
+        testContains(Ranges.closed(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsOpenClosed() {
+        testContains(Ranges.openClosed(2,4), 1, false);
+        testContains(Ranges.openClosed(2,4), 2, false);
+        testContains(Ranges.openClosed(2,4), 3, true);
+        testContains(Ranges.openClosed(2,4), 4, true);
+        testContains(Ranges.openClosed(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsClosedOpen() {
+        testContains(Ranges.closedOpen(2,4), 1, false);
+        testContains(Ranges.closedOpen(2,4), 2, true);
+        testContains(Ranges.closedOpen(2,4), 3, true);
+        testContains(Ranges.closedOpen(2,4), 4, false);
+        testContains(Ranges.closedOpen(2,4), 5, false);
+    }
+
+    @Test
+    public void testContainsGreaterThan() {
+        testContains(Ranges.greaterThan(2), 1, false);
+        testContains(Ranges.greaterThan(2), 2, false);
+        testContains(Ranges.greaterThan(2), 3, true);
+    }
+
+    @Test
+    public void testContainsAtLeast() {
+        testContains(Ranges.atLeast(2), 1, false);
+        testContains(Ranges.atLeast(2), 2, true);
+        testContains(Ranges.atLeast(2), 3, true);
+    }
+
+    @Test
+    public void testContainsLessThan() {
+        testContains(Ranges.lessThan(2), 1, true);
+        testContains(Ranges.lessThan(2), 2, false);
+        testContains(Ranges.lessThan(2), 3, false);
+    }
+
+    @Test
+    public void testContainsAtMost() {
+        testContains(Ranges.atMost(2), 1, true);
+        testContains(Ranges.atMost(2), 2, true);
+        testContains(Ranges.atMost(2), 3, false);
+    }
+
+    @Test
+    public void testContainsSingleton() {
+        testContains(Ranges.singleton(2), 1, false);
+        testContains(Ranges.singleton(2), 2, true);
+        testContains(Ranges.singleton(2), 3, false);
+    }
+    
+    @Test
+    public void testPredicate() {
+        testPredicate(Ranges.closed(2,4), 1, false);
+        testPredicate(Ranges.closed(2,4), 2, true);
+        testPredicate(Ranges.closed(2,4), 3, true);
+        testPredicate(Ranges.closed(2,4), 4, true);
+        testPredicate(Ranges.closed(2,4), 5, false);
+    }
+
+    @Test
+    public void testEquals() {
+        testEquals(Ranges.closed(2,4), Ranges.closed(2,4), true);
+        testEquals(Ranges.closed(2,4), Ranges.closed(2,3), false);
+        testEquals(Ranges.closed(3,4), Ranges.closed(2,4), false);
+        testEquals(Ranges.atMost(2), Ranges.atMost(2), true);
+        testEquals(Ranges.atMost(2), Ranges.atMost(3), false);
+        testEquals(Ranges.atLeast(2), Ranges.atLeast(2), true);
+        testEquals(Ranges.atLeast(2), Ranges.atLeast(3), false);
+        testEquals(Ranges.closed(2,2), Ranges.singleton(2), true);
+    }
+
+    @Test
+    public void testHashCode() {
+        testHashCode(Ranges.atMost(2), Ranges.atMost(2).hashCode(), true);
+        testHashCode(Ranges.atMost(2), 0, false);
+        testHashCode(Ranges.atMost(2), Ranges.atMost(3).hashCode(), false);
+        testHashCode(Ranges.atLeast(2), Ranges.atMost(2).hashCode(), false);
+    }
+    
+    @Test
+    public void testEndpointAccess() {
+        // {lower,upper}Endpoint(),
+        // has{Lower,Upper}Endpoint()
+        // {lower,upper}BoundType()
+        Range<Integer> r1 = Ranges.openClosed(2,4);
+        assertEquals(Range.BoundType.OPEN, r1.lowerBoundType());
+        assertTrue(r1.hasLowerEndpoint());
+        assertEquals(2, r1.lowerEndpoint().intValue());
+        assertTrue(r1.hasUpperEndpoint());
+        assertEquals(4, r1.upperEndpoint().intValue());
+        assertEquals(Range.BoundType.CLOSED, r1.upperBoundType());
+
+        Range<Integer> r2 = Ranges.openClosed(2,4);
+        assertNotSame(r1, r2);
+        
+        Range<Integer> r3 = Ranges.atMost(2);
+        assertFalse(r3.hasLowerEndpoint());
+        try {
+            r3.lowerEndpoint();
+            assertTrue(false);
+        }
+        catch (IllegalStateException e) {
+            // expected
+        }
+        
+        r3 = Ranges.atLeast(2);
+        assertFalse(r3.hasUpperEndpoint());
+        try {
+            r3.upperEndpoint();
+            assertTrue(false);
+        }
+        catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testToString() {
+        testToString(Ranges.open(2,4), "(2..4)");
+        testToString(Ranges.closed(2,4), "[2..4]");
+        testToString(Ranges.openClosed(2,4), "(2..4]");
+        testToString(Ranges.closedOpen(2,4), "[2..4)");
+        testToString(Ranges.greaterThan(2), "(2..*)");
+        testToString(Ranges.atLeast(2), "[2..*)");
+        testToString(Ranges.lessThan(2), "(*..2)");
+        testToString(Ranges.atMost(2), "(*..2]");
+    }
+
+    @Test
+    public void testValueOf() {
+        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.open(2, 4));
+        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.closed(2, 4));
+        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.openClosed(2, 4));
+        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.closedOpen(2, 4));
+        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.greaterThan(2));
+        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.atLeast(2));
+        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.lessThan(2));
+        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.atMost(2));
+    }
+
+    
+    /*
+     * Thoroughly test contains() and valueOf() for other types of T
+     */
+
+    @Test
+    public void testContainsOtherByte() {
+        testContains(Ranges.open((byte)2,(byte)4), (byte)1, false);
+        testContains(Ranges.open((byte)2,(byte)4), (byte)2, false);
+        testContains(Ranges.open((byte)2,(byte)4), (byte)3, true);
+        testContains(Ranges.open((byte)2,(byte)4), (byte)4, false);
+        testContains(Ranges.open((byte)2,(byte)4), (byte)5, false);
+    }
+
+    @Test
+    public void testContainsOtherShort() {
+        testContains(Ranges.open((short)2,(short)4), (short)1, false);
+        testContains(Ranges.open((short)2,(short)4), (short)2, false);
+        testContains(Ranges.open((short)2,(short)4), (short)3, true);
+        testContains(Ranges.open((short)2,(short)4), (short)4, false);
+        testContains(Ranges.open((short)2,(short)4), (short)5, false);
+    }
+
+    @Test
+    public void testContainsOtherLong() {
+        testContains(Ranges.open(2L,4L), 1L, false);
+        testContains(Ranges.open(2L,4L), 2L, false);
+        testContains(Ranges.open(2L,4L), 3L, true);
+        testContains(Ranges.open(2L,4L), 4L, false);
+        testContains(Ranges.open(2L,4L), 5L, false);
+    }
+
+    @Test
+    public void testContainsOtherFloat() {
+        testContains(Ranges.open(2f,4f), 1f, false);
+        testContains(Ranges.open(2f,4f), 2f, false);
+        testContains(Ranges.open(2f,4f), 2.001f, true);
+        testContains(Ranges.open(2f,4f), 3.999f, true);
+        testContains(Ranges.open(2f,4f), 4f, false);
+        testContains(Ranges.open(2f,4f), 5f, false);
+    }
+
+    @Test
+    public void testContainsOtherDouble() {
+        testContains(Ranges.open(2d,4d), 1d, false);
+        testContains(Ranges.open(2d,4d), 2d, false);
+        testContains(Ranges.open(2d,4d), 2.001d, true);
+        testContains(Ranges.open(2d,4d), 3.999d, true);
+        testContains(Ranges.open(2d,4d), 4d, false);
+        testContains(Ranges.open(2d,4d), 5d, false);
+    }
+
+    @Test
+    public void testContainsOtherBigInteger() {
+        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(1), false);
+        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(2), false);
+        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(3), true);
+        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(4), false);
+        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(5), false);
+    }
+
+    @Test
+    public void testContainsOtherBigDecimal() {
+        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(1), false);
+        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2), false);
+        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2.001), true);
+        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(3.999), true);
+        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(4), false);
+        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(5), false);
+    }
+
+    @Test
+    public void testContainsOtherString() {
+        testContains(Ranges.open("b","d"), "a", false);
+        testContains(Ranges.open("b","d"), "b", false);
+        testContains(Ranges.open("b","d"), "bc", true);
+        testContains(Ranges.open("b","d"), "c", true);
+        testContains(Ranges.open("b","d"), "cd", true);
+        testContains(Ranges.open("b","d"), "d", false);
+        testContains(Ranges.open("b","d"), "de", false);
+        testContains(Ranges.open("b","d"), "e", false);
+    }
+
+    @Test
+    public void testContainsOtherCharacter() {
+        testContains(Ranges.open('b','d'), 'a', false);
+        testContains(Ranges.open('b','d'), 'b', false);
+        testContains(Ranges.open('b','d'), 'c', true);
+        testContains(Ranges.open('b','d'), 'd', false);
+        testContains(Ranges.open('b','d'), 'e', false);
+    }
+
+    @Test
+    public void testValueOfOtherT() {
+        testValueOf(s -> Ranges.valueOfShort(s), Ranges.open((short)2, (short)4));
+        testValueOf(s -> Ranges.valueOfByte(s), Ranges.open((byte)2, (byte)4));
+        testValueOf(s -> Ranges.valueOfLong(s), Ranges.open(2L, 4L));
+        testValueOf(s -> Ranges.valueOfFloat(s), Ranges.open(2.128f, 4.25f));
+        testValueOf(s -> Ranges.valueOfDouble(s), Ranges.open(2.128d, 4.25d));
+        testValueOf(s -> Ranges.valueOfBigInteger(s), Ranges.open(BigInteger.valueOf(2), BigInteger.valueOf(4)));
+        testValueOf(s -> Ranges.valueOfBigDecimal(s), Ranges.open(new BigDecimal(2.5), new BigDecimal(4.25)));
+        testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab", "fg"));
+        testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab", "."));
+        testValueOf(s -> Ranges.valueOfString(s), Ranges.open(".", "ab"));
+        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('a', 'f'));
+        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('a', '.'));
+        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('.', '.'));
+        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('.', 'f'));
+
+        // problem cases Range<String> with embedded ".."
+        try { 
+            testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab..c", "fg"));
+            assertTrue(false);
+        } catch (IllegalArgumentException e) { /* expected */ }
+        try { 
+            testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab", "fg..h"));
+            assertTrue(false);
+        } catch (IllegalArgumentException e) { /* expected */ }
+        try { 
+            testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab..c", "fg..h"));
+            assertTrue(false);
+        } catch (IllegalArgumentException e) { /* expected */ }
+    }
+    
+    /*
+     * Test unsigned handling.
+     * toUnsignedString() and compare(T, Comparator<T>)
+     */
+
+    @Test
+    public void testToUnsignedString() {
+        testToStringUnsigned(Ranges.open((byte)0,(byte)255), "(0..255)");
+        testToStringUnsigned(Ranges.closed((byte)0,(byte)255), "[0..255]");
+        testToStringUnsigned(Ranges.open((short)0,(short)0xFFFF), "(0..65535)");
+        testToStringUnsigned(Ranges.open(0,0xFFFFFFFF), "(0.."+Integer.toUnsignedString(0xFFFFFFFF)+")");
+        testToStringUnsigned(Ranges.open(0L,0xFFFFFFFFFFFFFFFFL), "(0.."+Long.toUnsignedString(0xFFFFFFFFFFFFFFFFL)+")");
+    }
+
+    @Test
+    public void testContainsUnsigned() {
+        // Unsigned Byte ======================
+        Comparator<Byte> unsignedByteComparator = new Comparator<Byte>() {
+            public int compare(Byte v1, Byte v2) {
+                return Integer.compareUnsigned(Byte.toUnsignedInt(v1), Byte.toUnsignedInt(v2));
+            }
+            public boolean equals(Object o2) { return o2==this; }
+            };
+            
+        Range<Byte> byteRange = Ranges.closed((byte)5, (byte)255); // intend unsigned
+        assertFalse(byteRange.contains((byte)6));  // not <= -1
+        assertTrue(byteRange.contains((byte)6, unsignedByteComparator));
+        assertFalse(byteRange.contains((byte)0xF0)); // not >= 5
+        assertTrue(byteRange.contains((byte)0xF0, unsignedByteComparator));
+        
+        // Unsigned Short ======================
+        Comparator<Short> unsignedShortComparator = new Comparator<Short>() {
+            public int compare(Short v1, Short v2) {
+                return Integer.compareUnsigned(Short.toUnsignedInt(v1), Short.toUnsignedInt(v2));
+            }
+            public boolean equals(Object o2) { return o2==this; }
+            };
+        Range<Short> shortRange = Ranges.closed((short)5, (short)0xFFFF); // intend unsigned
+        assertFalse(shortRange.contains((short)6));  // not <= -1
+        assertTrue(shortRange.contains((short)6, unsignedShortComparator));
+        assertFalse(shortRange.contains((short)0xFFF0)); // not >= 5
+        assertTrue(shortRange.contains((short)0xFFF0, unsignedShortComparator));
+        
+        // Unsigned Integer ======================
+        Comparator<Integer> unsignedIntegerComparator = new Comparator<Integer>() {
+            public int compare(Integer v1, Integer v2) {
+                return Integer.compareUnsigned(v1, v2);
+            }
+            public boolean equals(Object o2) { return o2==this; }
+            };
+        Range<Integer> intRange = Ranges.closed(5, 0xFFFFFFFF); // intend unsigned
+        assertFalse(intRange.contains(6));  // not <= -1
+        assertTrue(intRange.contains(6, unsignedIntegerComparator));
+        assertFalse(intRange.contains(0xFFFFFFF0)); // not >= 5
+        assertTrue(intRange.contains(0xFFFFFFF0, unsignedIntegerComparator));
+        
+        // Unsigned Long ======================
+        Comparator<Long> unsignedLongComparator = new Comparator<Long>() {
+            public int compare(Long v1, Long v2) {
+                return Long.compareUnsigned(v1, v2);
+            }
+            public boolean equals(Object o2) { return o2==this; }
+            };
+        Range<Long> longRange = Ranges.closed(5L, 0xFFFFFFFFFFFFFFFFL); // intend unsigned
+        assertFalse(longRange.contains(6L));  // not <= -1
+        assertTrue(longRange.contains(6L, unsignedLongComparator));
+        assertFalse(longRange.contains(0xFFFFFFFFFFFFFFF0L));  // not >= 5
+        assertTrue(longRange.contains(0xFFFFFFFFFFFFFFF0L, unsignedLongComparator));
+    }
+
+    @Test
+    public void testJsonAllTypes() {
+        // json = new Gson().toJson(Range<T>);
+        // range = new Gson().fromJson(json, typeOfT);
+        testJson(Ranges.closed(1, 10), new TypeToken<Range<Integer>>(){}.getType());
+        testJson(Ranges.closed((short)1, (short)10), new TypeToken<Range<Short>>(){}.getType());
+        testJson(Ranges.closed((byte)1, (byte)10), new TypeToken<Range<Byte>>(){}.getType());
+        testJson(Ranges.closed(1L, 10L), new TypeToken<Range<Long>>(){}.getType());
+        testJson(Ranges.closed(1f, 10f), new TypeToken<Range<Float>>(){}.getType());
+        testJson(Ranges.closed(1d, 10d), new TypeToken<Range<Double>>(){}.getType());
+        testJson(Ranges.closed(BigInteger.valueOf(1), BigInteger.valueOf(10)), new TypeToken<Range<BigInteger>>(){}.getType());
+        testJson(Ranges.closed(BigDecimal.valueOf(1), BigDecimal.valueOf(10)), new TypeToken<Range<BigDecimal>>(){}.getType());
+        testJson(Ranges.closed("ab", "fg"), new TypeToken<Range<String>>(){}.getType());
+        testJson(Ranges.closed("ab..c", "fg"), new TypeToken<Range<String>>(){}.getType());
+        testJson(Ranges.closed('a', 'f'), new TypeToken<Range<Character>>(){}.getType());
+        testJson(Ranges.closed('.', 'f'), new TypeToken<Range<Character>>(){}.getType());
+        testJson(Ranges.closed('.', '.'), new TypeToken<Range<Character>>(){}.getType());
+        testJson(Ranges.closed('a', '.'), new TypeToken<Range<Character>>(){}.getType());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/hardware/src/main/java/edgent/android/hardware/SensorStreams.java
----------------------------------------------------------------------
diff --git a/android/hardware/src/main/java/edgent/android/hardware/SensorStreams.java b/android/hardware/src/main/java/edgent/android/hardware/SensorStreams.java
deleted file mode 100644
index 8fe9caf..0000000
--- a/android/hardware/src/main/java/edgent/android/hardware/SensorStreams.java
+++ /dev/null
@@ -1,71 +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 edgent.android.hardware;
-
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorManager;
-import edgent.android.hardware.runtime.SensorSourceSetup;
-import edgent.topology.TStream;
-import edgent.topology.TopologyElement;
-
-/**
- * Create streams from sensors.
- *
- */
-public class SensorStreams {
-    
-    /**
-     * Declare a stream of sensor events.
-     * A listener is registered with {@code sensorManager}
-     * using {@code SensorManager.SENSOR_DELAY_NORMAL}.
-     * Each sensor event will result in a tuple on
-     * the returned stream.
-     *
-     * @param te Topology element for stream's topology
-     * @param sensorManager Sensor manager
-     * @param sensorTypes Which sensors to listen for. 
-     * @return Stream that will contain events from the sensors.
-     */
-    public static TStream<SensorEvent> sensors(TopologyElement te, SensorManager sensorManager, int ... sensorTypes) {
-        Sensor[] sensors = new Sensor[sensorTypes.length];
-        
-        for (int i = 0; i < sensorTypes.length; i++)
-            sensors[i] = sensorManager.getDefaultSensor(sensorTypes[i]);
-        
-        return sensors(te, sensorManager, sensors);
-    }
-    
-    /**
-     * Declare a stream of sensor events.
-     * A listener is registered with {@code sensorManager}
-     * using {@code SensorManager.SENSOR_DELAY_NORMAL}.
-     * Each sensor event will result in a tuple on
-     * the returned stream.
-     *
-     * @param te Topology element for stream's topology
-     * @param sensorManager Sensor manager
-     * @param sensors Which sensors to listen for. 
-     * @return Stream that will contain events from the sensors.
-     */
-    public static TStream<SensorEvent> sensors(TopologyElement te, SensorManager sensorManager, Sensor ... sensors) {        
-        return te.topology().events(
-                new SensorSourceSetup(sensorManager, sensors));
-    } 
-}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/hardware/src/main/java/edgent/android/hardware/runtime/SensorChangeEvents.java
----------------------------------------------------------------------
diff --git a/android/hardware/src/main/java/edgent/android/hardware/runtime/SensorChangeEvents.java b/android/hardware/src/main/java/edgent/android/hardware/runtime/SensorChangeEvents.java
deleted file mode 100644
index 5ba71d8..0000000
--- a/android/hardware/src/main/java/edgent/android/hardware/runtime/SensorChangeEvents.java
+++ /dev/null
@@ -1,49 +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 edgent.android.hardware.runtime;
-
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-
-import edgent.function.Consumer;
-
-/**
- * Sensor event listener that submits sensor
- * change events as tuples using a Consumer.
- * 
- */
-public class SensorChangeEvents implements SensorEventListener {
-    private final Consumer<SensorEvent> eventSubmitter;
-    
-    /**
-     * @param eventSubmitter How events are submitted to a stream.
-     */
-    public SensorChangeEvents(Consumer<SensorEvent> eventSubmitter) {
-        this.eventSubmitter = eventSubmitter;
-    }
-    @Override
-    public void onSensorChanged(SensorEvent event) {
-        eventSubmitter.accept(event);
-    }
-
-    @Override
-    public void onAccuracyChanged(Sensor sensor, int accuracy) {
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/hardware/src/main/java/edgent/android/hardware/runtime/SensorSourceSetup.java
----------------------------------------------------------------------
diff --git a/android/hardware/src/main/java/edgent/android/hardware/runtime/SensorSourceSetup.java b/android/hardware/src/main/java/edgent/android/hardware/runtime/SensorSourceSetup.java
deleted file mode 100644
index ae3331a..0000000
--- a/android/hardware/src/main/java/edgent/android/hardware/runtime/SensorSourceSetup.java
+++ /dev/null
@@ -1,54 +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 edgent.android.hardware.runtime;
-
-import edgent.function.Consumer;
-
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorManager;
-
-/**
- * 
- */
-public class SensorSourceSetup implements Consumer<Consumer<SensorEvent>> {
-    private static final long serialVersionUID = 1L;
-    
-    private final SensorManager mSensorManager;
-    private final Sensor[] sensors;
-    private final int samplingPeriodUs;
-    private SensorChangeEvents events;
-    
-
-    public SensorSourceSetup(SensorManager mSensorManager, int samplingPeriodUs,
-            Sensor ... sensors) {
-        this.mSensorManager = mSensorManager;
-        this.sensors = sensors;
-        this.samplingPeriodUs = samplingPeriodUs;     
-    }
-    public SensorSourceSetup(SensorManager mSensorManager, Sensor ... sensors) {
-        this(mSensorManager , SensorManager.SENSOR_DELAY_NORMAL, sensors);  
-    }
-
-    public void accept(Consumer<SensorEvent> submitter) {
-        events = new SensorChangeEvents(submitter);
-        for (Sensor sensor : sensors)
-            mSensorManager.registerListener(events, sensor, samplingPeriodUs);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/hardware/src/main/java/org/apache/edgent/android/hardware/SensorStreams.java
----------------------------------------------------------------------
diff --git a/android/hardware/src/main/java/org/apache/edgent/android/hardware/SensorStreams.java b/android/hardware/src/main/java/org/apache/edgent/android/hardware/SensorStreams.java
new file mode 100644
index 0000000..e7cc85a
--- /dev/null
+++ b/android/hardware/src/main/java/org/apache/edgent/android/hardware/SensorStreams.java
@@ -0,0 +1,71 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.edgent.android.hardware;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorManager;
+import edgent.android.hardware.runtime.SensorSourceSetup;
+import edgent.topology.TStream;
+import edgent.topology.TopologyElement;
+
+/**
+ * Create streams from sensors.
+ *
+ */
+public class SensorStreams {
+    
+    /**
+     * Declare a stream of sensor events.
+     * A listener is registered with {@code sensorManager}
+     * using {@code SensorManager.SENSOR_DELAY_NORMAL}.
+     * Each sensor event will result in a tuple on
+     * the returned stream.
+     *
+     * @param te Topology element for stream's topology
+     * @param sensorManager Sensor manager
+     * @param sensorTypes Which sensors to listen for. 
+     * @return Stream that will contain events from the sensors.
+     */
+    public static TStream<SensorEvent> sensors(TopologyElement te, SensorManager sensorManager, int ... sensorTypes) {
+        Sensor[] sensors = new Sensor[sensorTypes.length];
+        
+        for (int i = 0; i < sensorTypes.length; i++)
+            sensors[i] = sensorManager.getDefaultSensor(sensorTypes[i]);
+        
+        return sensors(te, sensorManager, sensors);
+    }
+    
+    /**
+     * Declare a stream of sensor events.
+     * A listener is registered with {@code sensorManager}
+     * using {@code SensorManager.SENSOR_DELAY_NORMAL}.
+     * Each sensor event will result in a tuple on
+     * the returned stream.
+     *
+     * @param te Topology element for stream's topology
+     * @param sensorManager Sensor manager
+     * @param sensors Which sensors to listen for. 
+     * @return Stream that will contain events from the sensors.
+     */
+    public static TStream<SensorEvent> sensors(TopologyElement te, SensorManager sensorManager, Sensor ... sensors) {        
+        return te.topology().events(
+                new SensorSourceSetup(sensorManager, sensors));
+    } 
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/hardware/src/main/java/org/apache/edgent/android/hardware/runtime/SensorChangeEvents.java
----------------------------------------------------------------------
diff --git a/android/hardware/src/main/java/org/apache/edgent/android/hardware/runtime/SensorChangeEvents.java b/android/hardware/src/main/java/org/apache/edgent/android/hardware/runtime/SensorChangeEvents.java
new file mode 100644
index 0000000..e563180
--- /dev/null
+++ b/android/hardware/src/main/java/org/apache/edgent/android/hardware/runtime/SensorChangeEvents.java
@@ -0,0 +1,49 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.edgent.android.hardware.runtime;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+
+import edgent.function.Consumer;
+
+/**
+ * Sensor event listener that submits sensor
+ * change events as tuples using a Consumer.
+ * 
+ */
+public class SensorChangeEvents implements SensorEventListener {
+    private final Consumer<SensorEvent> eventSubmitter;
+    
+    /**
+     * @param eventSubmitter How events are submitted to a stream.
+     */
+    public SensorChangeEvents(Consumer<SensorEvent> eventSubmitter) {
+        this.eventSubmitter = eventSubmitter;
+    }
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        eventSubmitter.accept(event);
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/hardware/src/main/java/org/apache/edgent/android/hardware/runtime/SensorSourceSetup.java
----------------------------------------------------------------------
diff --git a/android/hardware/src/main/java/org/apache/edgent/android/hardware/runtime/SensorSourceSetup.java b/android/hardware/src/main/java/org/apache/edgent/android/hardware/runtime/SensorSourceSetup.java
new file mode 100644
index 0000000..3d92dca
--- /dev/null
+++ b/android/hardware/src/main/java/org/apache/edgent/android/hardware/runtime/SensorSourceSetup.java
@@ -0,0 +1,54 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.edgent.android.hardware.runtime;
+
+import edgent.function.Consumer;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorManager;
+
+/**
+ * 
+ */
+public class SensorSourceSetup implements Consumer<Consumer<SensorEvent>> {
+    private static final long serialVersionUID = 1L;
+    
+    private final SensorManager mSensorManager;
+    private final Sensor[] sensors;
+    private final int samplingPeriodUs;
+    private SensorChangeEvents events;
+    
+
+    public SensorSourceSetup(SensorManager mSensorManager, int samplingPeriodUs,
+            Sensor ... sensors) {
+        this.mSensorManager = mSensorManager;
+        this.sensors = sensors;
+        this.samplingPeriodUs = samplingPeriodUs;     
+    }
+    public SensorSourceSetup(SensorManager mSensorManager, Sensor ... sensors) {
+        this(mSensorManager , SensorManager.SENSOR_DELAY_NORMAL, sensors);  
+    }
+
+    public void accept(Consumer<SensorEvent> submitter) {
+        events = new SensorChangeEvents(submitter);
+        for (Sensor sensor : sensors)
+            mSensorManager.registerListener(events, sensor, samplingPeriodUs);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/topology/src/main/java/edgent/android/oplet/RunOnUIThread.java
----------------------------------------------------------------------
diff --git a/android/topology/src/main/java/edgent/android/oplet/RunOnUIThread.java b/android/topology/src/main/java/edgent/android/oplet/RunOnUIThread.java
deleted file mode 100644
index ab3f985..0000000
--- a/android/topology/src/main/java/edgent/android/oplet/RunOnUIThread.java
+++ /dev/null
@@ -1,41 +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 edgent.android.oplet;
-
-import android.app.Activity;
-import edgent.oplet.core.Pipe;
-
-public class RunOnUIThread<T> extends Pipe<T,T> {
-
-    private static final long serialVersionUID = 1L;
-    
-    private final Activity activity;
-    public RunOnUIThread(Activity activity) {
-        this.activity = activity;
-    }
-
-    @Override
-    public void accept(T value) {       
-        activity.runOnUiThread(() -> getDestination().accept(value));
-    }
-
-    @Override
-    public void close() throws Exception {
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/topology/src/main/java/edgent/android/topology/ActivityStreams.java
----------------------------------------------------------------------
diff --git a/android/topology/src/main/java/edgent/android/topology/ActivityStreams.java b/android/topology/src/main/java/edgent/android/topology/ActivityStreams.java
deleted file mode 100644
index b766629..0000000
--- a/android/topology/src/main/java/edgent/android/topology/ActivityStreams.java
+++ /dev/null
@@ -1,83 +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 edgent.android.topology;
-
-import android.app.Activity;
-import edgent.android.oplet.RunOnUIThread;
-import edgent.function.Consumer;
-import edgent.function.Function;
-import edgent.topology.TSink;
-import edgent.topology.TStream;
-import edgent.topology.plumbing.PlumbingStreams;
-
-/**
- * Stream utilities for an Android {@code Activity}.
- */
-public class ActivityStreams {
-    
-    /**
-    * Sink a stream executing the sinker function on the
-    * activity's UI thread.
-    * <BR>
-    * For each tuple {@code t} on {@code stream}
-    * the method {@code sinker.accept(t)} will be
-    * called on the UI thread.
-    *
-    * @param activity Activity
-    * @param stream Stream to be sinked.
-    * @param sinker Function that will be executed on the UI thread.
-    *
-    * @see edgent.topology.TStream#sink(edgent.function.Consumer)
-    */
-    public static <T> TSink sinkOnUIThread(Activity activity, TStream<T> stream, Consumer<T> sinker) { 
-        return stream.pipe(new RunOnUIThread<>(activity)).sink(sinker);
-    }
-    
-    /**
-    * Map tuples on a stream executing the mapper function on the
-    * activity's UI thread.
-    * <BR>
-    * For each tuple {@code t} on {@code stream}
-    * the method {@code mapper.apply(t)} will be
-    * called on the UI thread. The return from the
-    * method will be present on the returned stream
-    * if it is not null. Any processing downstream
-    * executed against the returned stream is executed
-    * on a different thread to the UI thread.
-    *
-    * @param activity Activity
-    * @param stream Stream to be sinked.
-    * @param mapper Function that will be executed on the UI thread.
-    * @param ordered True if tuple ordering must be maintained after the
-    * execution on the UI thread. False if ordering is not required.
-    *
-    * @see edgent.topology.TStream#map(edgent.function.Function)
-    */
-    public static <T,U> TStream<U> mapOnUIThread(Activity activity, TStream<T> stream, Function<T,U> mapper, boolean ordered) {  
-        
-        // Switch to the UI thread
-        stream = stream.pipe(new RunOnUIThread<>(activity));
-        
-        // execute the map on the UI thread
-        TStream<U> resultStream = stream.map(mapper);
-        
-        // Switch back to a non-ui thread
-        return PlumbingStreams.isolate(resultStream, ordered);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/topology/src/main/java/org/apache/edgent/android/oplet/RunOnUIThread.java
----------------------------------------------------------------------
diff --git a/android/topology/src/main/java/org/apache/edgent/android/oplet/RunOnUIThread.java b/android/topology/src/main/java/org/apache/edgent/android/oplet/RunOnUIThread.java
new file mode 100644
index 0000000..a17610e
--- /dev/null
+++ b/android/topology/src/main/java/org/apache/edgent/android/oplet/RunOnUIThread.java
@@ -0,0 +1,41 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.edgent.android.oplet;
+
+import android.app.Activity;
+import edgent.oplet.core.Pipe;
+
+public class RunOnUIThread<T> extends Pipe<T,T> {
+
+    private static final long serialVersionUID = 1L;
+    
+    private final Activity activity;
+    public RunOnUIThread(Activity activity) {
+        this.activity = activity;
+    }
+
+    @Override
+    public void accept(T value) {       
+        activity.runOnUiThread(() -> getDestination().accept(value));
+    }
+
+    @Override
+    public void close() throws Exception {
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/a129aa16/android/topology/src/main/java/org/apache/edgent/android/topology/ActivityStreams.java
----------------------------------------------------------------------
diff --git a/android/topology/src/main/java/org/apache/edgent/android/topology/ActivityStreams.java b/android/topology/src/main/java/org/apache/edgent/android/topology/ActivityStreams.java
new file mode 100644
index 0000000..060b72d
--- /dev/null
+++ b/android/topology/src/main/java/org/apache/edgent/android/topology/ActivityStreams.java
@@ -0,0 +1,83 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.edgent.android.topology;
+
+import android.app.Activity;
+import edgent.android.oplet.RunOnUIThread;
+import edgent.function.Consumer;
+import edgent.function.Function;
+import edgent.topology.TSink;
+import edgent.topology.TStream;
+import edgent.topology.plumbing.PlumbingStreams;
+
+/**
+ * Stream utilities for an Android {@code Activity}.
+ */
+public class ActivityStreams {
+    
+    /**
+    * Sink a stream executing the sinker function on the
+    * activity's UI thread.
+    * <BR>
+    * For each tuple {@code t} on {@code stream}
+    * the method {@code sinker.accept(t)} will be
+    * called on the UI thread.
+    *
+    * @param activity Activity
+    * @param stream Stream to be sinked.
+    * @param sinker Function that will be executed on the UI thread.
+    *
+    * @see org.apache.edgent.topology.TStream#sink(edgent.function.Consumer)
+    */
+    public static <T> TSink sinkOnUIThread(Activity activity, TStream<T> stream, Consumer<T> sinker) { 
+        return stream.pipe(new RunOnUIThread<>(activity)).sink(sinker);
+    }
+    
+    /**
+    * Map tuples on a stream executing the mapper function on the
+    * activity's UI thread.
+    * <BR>
+    * For each tuple {@code t} on {@code stream}
+    * the method {@code mapper.apply(t)} will be
+    * called on the UI thread. The return from the
+    * method will be present on the returned stream
+    * if it is not null. Any processing downstream
+    * executed against the returned stream is executed
+    * on a different thread to the UI thread.
+    *
+    * @param activity Activity
+    * @param stream Stream to be sinked.
+    * @param mapper Function that will be executed on the UI thread.
+    * @param ordered True if tuple ordering must be maintained after the
+    * execution on the UI thread. False if ordering is not required.
+    *
+    * @see org.apache.edgent.topology.TStream#map(edgent.function.Function)
+    */
+    public static <T,U> TStream<U> mapOnUIThread(Activity activity, TStream<T> stream, Function<T,U> mapper, boolean ordered) {  
+        
+        // Switch to the UI thread
+        stream = stream.pipe(new RunOnUIThread<>(activity));
+        
+        // execute the map on the UI thread
+        TStream<U> resultStream = stream.map(mapper);
+        
+        // Switch back to a non-ui thread
+        return PlumbingStreams.isolate(resultStream, ordered);
+    }
+}