Skip to content

Instantly share code, notes, and snippets.

@andrewrlee
Last active October 18, 2016 22:18
Show Gist options
  • Save andrewrlee/44444c075cbec48c01a9029e2735a944 to your computer and use it in GitHub Desktop.
Save andrewrlee/44444c075cbec48c01a9029e2735a944 to your computer and use it in GitHub Desktop.
Generic Task Tree - type safe chaining functions
package uk.co.optimisticpanda.configtaskchain.model;
import static java.util.stream.Collectors.toList;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.function.Supplier;
public class GenericTree<TI, O> {
private Function<TI, O> previousFunction;
public GenericTree(Function<TI, O> previousFunction) {
this.previousFunction = previousFunction;
}
public O doIt(TI input) {
return previousFunction.apply(input);
}
public <R> GenericTree<TI, R> addTask(Function<O, R> child) {
return new GenericTree<>(previousFunction.andThen(child));
}
public <R> GenericTree<TI, R> addStandalone(Supplier<R> child) {
return new GenericTree<>(inputIgnored -> child.get());
}
public <R1, R2> MultiBuilder<TI, O, R1, R2> mergeFollowingWith(Function<List<R1>, R2> merger) {
return new MultiBuilder<>(previousFunction, merger);
}
public static class MultiBuilder<TI, O, R1, R2> {
private final List<GenericTree<O, R1>> children = new ArrayList<>();
private final Function<TI, O> previousFunction;
private Function<List<R1>, R2> merger;
private MultiBuilder(Function<TI, O> previousFunction, Function<List<R1>, R2> merger) {
this.previousFunction = previousFunction;
this.merger = merger;
}
public MultiBuilder<TI, O, R1, R2> addTask(Function<O, R1> child) {
this.children.add(new GenericTree<>(child));
return this;
}
public MultiBuilder<TI, O, R1, R2> addStandaloneTask(Supplier<R1> child) {
this.children.add(new GenericTree<>(ignore -> child.get()));
return this;
}
public GenericTree<TI, R2> end() {
return new GenericTree<TI, R2>(input -> {
O result = previousFunction.apply(input);
List<R1> results = children.stream().map(child -> child.doIt(result)).collect(toList());
return merger.apply(results);
});
}
}
public static void main(String[] args) {
Function<String, Integer> stringLength = String::length;
Function<List<Integer>, Integer> merger = list -> list.stream().reduce(0, (i1, i2) -> i1 + i2);
UnaryOperator<Integer> add2 = i -> i + 2;
UnaryOperator<Integer> minus1 = i -> i - 1;
Supplier<Integer> returns3 = () -> 3;
GenericTree<String, String> tree = new GenericTree<>(stringLength) // -> 9
.mergeFollowingWith(merger)
.addTask(minus1) // -> 9 - 1 = 8
.addStandaloneTask(returns3) // -> = 3
.addTask(add2) // -> 9 + 2 = 11
.end() // -> reduce([8, 3, 11], +) = 22
.addTask(result -> "The result is: " + result); // -> The result is: 22
System.out.println(tree.doIt("123456789"));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment