/* # Licensed Materials - Property of IBM # Copyright IBM Corp. 2015 */ package com.ibm.streamsx.topology.test.api; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; import org.junit.Test; import com.ibm.streamsx.topology.TStream; import com.ibm.streamsx.topology.TWindow; import com.ibm.streamsx.topology.Topology; import com.ibm.streamsx.topology.function.BiFunction; import com.ibm.streamsx.topology.function.Function; import com.ibm.streamsx.topology.function.Supplier; import com.ibm.streamsx.topology.function.UnaryOperator; import com.ibm.streamsx.topology.logic.Logic; import com.ibm.streamsx.topology.streams.StringStreams; import com.ibm.streamsx.topology.test.TestTopology; public class JoinTest extends TestTopology { @Test public void testJoin() throws Exception { final Topology t = newTopology(); TStream<String> strings = t.strings("a", "b", "c", "d", "e"); TWindow<String,?> window = strings.last(3); TStream<Number> main = t.numbers(0,134,76); main = main.throttle(1, TimeUnit.SECONDS); TStream<List<String>> joined = _jointest(main, window); TStream<String> asString = StringStreams.toString(joined); completeAndValidate(asString, 12, "[c-134, d-134, e-134]", "[c-76, d-76, e-76]"); } @Test public void testEmptyJoin() throws Exception { final Topology t = newTopology(); TStream<String> strings = t.strings(); TWindow<String,?> window = strings.last(3); TStream<Number> main = t.numbers(0,134,76); main = main.throttle(1, TimeUnit.SECONDS); TStream<List<String>> joined = _jointest(main, window); TStream<String> asString = StringStreams.toString(joined); completeAndValidate(asString, 12, "[empty-134]", "[empty-76]"); } private static TStream<List<String>> _jointest(TStream<Number> main, TWindow<String,?> window) { return main.join(window, new BiFunction<Number, List<String>, List<String>>() { /** * */ private static final long serialVersionUID = 1L; @Override public List<String> apply(Number v1, List<String> v2) { // Skip the first value to ensure the window contents are stable. if (v1.intValue() == 0) return null; if (v2.isEmpty()) return Collections.singletonList("empty-" + v1.toString()); List<String> tuple = new ArrayList<>(); for (String s : v2) tuple.add(s + "-" + v1.toString()); return tuple; } }); } @Test public void testJoinLast() throws Exception { final Topology t = newTopology(); TStream<String> strings = t.strings("a", "b", "c", "d", "e"); TStream<Number> main = t.numbers(0,134,76); main = main.throttle(1, TimeUnit.SECONDS); TStream<List<String>> joined = _joinLasttest(main, strings); TStream<String> asString = StringStreams.toString(joined); completeAndValidate(asString, 12, "[e-134]", "[e-76]"); } @Test public void testEmptyJoinLast() throws Exception { final Topology t = newTopology(); TStream<String> strings = t.strings(); TStream<Number> main = t.numbers(0,134,76); main = main.throttle(1, TimeUnit.SECONDS); TStream<List<String>> joined = _joinLasttest(main, strings); TStream<String> asString = StringStreams.toString(joined); completeAndValidate(asString, 12, "[empty-134]", "[empty-76]"); } private static TStream<List<String>> _joinLasttest(TStream<Number> main, TStream<String> other) { return main.joinLast(other, new BiFunction<Number, String, List<String>>() { /** * */ private static final long serialVersionUID = 1L; @Override public List<String> apply(Number v1, String v2) { // Skip the first value to ensure the window contents are stable. if (v1.intValue() == 0) return null; if (v2 == null) return Collections.singletonList("empty-" + v1.toString()); List<String> tuple = new ArrayList<>(); tuple.add(v2 + "-" + v1.toString()); return tuple; } }); } @Test public void testKeyedJoin() throws Exception { final Topology t = newTopology(); TStream<String> strings = t.strings("a", "b", "c", "a", "a", "c"); TStream<String> main = delayedList(t, "a", "b", "c", "d"); TStream<Integer> joined = _testKeyedJoin(main, strings.last(3).key()); TStream<String> asString = StringStreams.toString(joined); completeAndValidate(asString, 25, "3", "1", "2", "0"); } private static TStream<String> delayedList(Topology t, String ...strings) { final ArrayList<String> data = new ArrayList<>(); for (String s : strings) data.add(s); return t.source(new Supplier<Iterable<String>>() { /** * */ private static final long serialVersionUID = 1L; @Override public Iterable<String> get() { try { Thread.sleep(2000); } catch (InterruptedException e) { return null; } return data ; }}); } private static TStream<Integer> _testKeyedJoin(TStream<String> main, TWindow<String,String> window) { UnaryOperator<String> selfKeyed = Logic.identity(); return main.join(selfKeyed, window, new BiFunction<String, List<String>, Integer>() { /** * */ private static final long serialVersionUID = 1L; @Override public Integer apply(String v1, List<String> v2) { for (String wt : v2) if (!v1.equals(wt)) return -1; return v2.size(); } }); } @Test public void testKeyedJoinLast() throws Exception { final Topology t = newTopology(); TStream<String> strings = t.strings("a1", "b1", "c1", "a2", "a3", "c2"); TStream<String> main = delayedList(t, "a", "b", "c", "d"); TStream<String> joined = _testKeyedJoinLast(main, strings); TStream<String> asString = StringStreams.toString(joined); completeAndValidate(asString, 25, "a3", "b1", "c2", "empty"); } @SuppressWarnings("serial") private static TStream<String> _testKeyedJoinLast(TStream<String> main, TStream<String> strings) { UnaryOperator<String> sk = Logic.identity(); UnaryOperator<String> selfKeyed = new UnaryOperator<String>() { @Override public String apply(String v) { return v; }}; Function<String,String> firstChar = new Function<String,String>() { @Override public String apply(String v) { return v.substring(0, 1); }}; return main.joinLast(selfKeyed, strings, firstChar, new BiFunction<String, String, String>() { /** * */ private static final long serialVersionUID = 1L; @Override public String apply(String v1, String v2) { if (v2 == null) return "empty"; return v2; } }); } }