Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

TeeTime Configuration Builder

With the TeeTime configuration builder you can simply connect your stages in a short, type-safe, and fluent way.

How to use it

Typically, you create your configurations by instantiating all stages and connecting them via lines of connectPorts(...) calls.

public class MyConfiguration extends Configuration {

	public MyConfiguration(final List<String> strings) {
		final InitialElementProducer<String> producer = new InitialElementProducer<>(strings);
		final ToLowerCase toLowerCase = new ToLowerCase();
		final WordcharacterFilter wordcharacterFilter = new WordcharacterFilter();
		final WordCounter wordCounter = new WordCounter();
		final Printer<CountingMap<String>> printer = new Printer<>();

		this.connectPorts(producer.getOutputPort(), toLowerCase.getInputPort());
		this.connectPorts(toLowerCase.getOutputPort(), wordcharacterFilter.getInputPort());
		this.connectPorts(wordcharacterFilter.getOutputPort(), wordCounter.getInputPort());
		this.connectPorts(wordCounter.getOutputPort(), printer.getInputPort());
	}

}

With the TeeTime configuration builder you can simply connect the stages by calling from(...), to(...), and end(...).

public MyConfiguration(final List<String> strings) {
	final InitialElementProducer<String> producer = new InitialElementProducer<>(strings);
	final ToLowerCase toLowerCase = new ToLowerCase();
	final WordcharacterFilter wordcharacterFilter = new WordcharacterFilter();
	final WordCounter wordCounter = new WordCounter();
	final Printer<CountingMap<String>> printer = new Printer<>();

	this.from(producer).to(toLowerCase).to(wordcharacterFilter).to(wordCounter).end(printer);
}

In addition to shorter and more expressive code, the configuration builder forces you to use every stage port exactly once. Furthermore, you do not have to declare all your stages as local variables if you do not need access to them.

public MyConfiguration(final List<String> strings) {
	this.from(new InitialElementProducer<>(strings))
		.to(new ToLowerCase())
		.to(new WordcharacterFilter())
		.to(new WordCounter())
		.end(new Printer<>());
}

If you do not need an own class for your configuration, you can create configurations straightforward by using the ConfigurationBuilder.from(...) method as shown in the next example.

final Configuration myConfiguration = ConfigurationBuilder
				.from(new InitialElementProducer<>(strings))
				.to(new ToLowerCase())
				.to(new WordcharacterFilter())
				.to(new WordCounter())
				.end(new Printer<>());

You may want to use stages that do implement the ITransformation interface, for example, because they have multiple output ports like the InstanceOfFilter. For this case you an alternative form of the to(..) method, in which you can specify the stage´s input and output port you want use. This is done via a lambda function as shown below.

final Configuration myConfiguration = ConfigurationBuilder
				.from(new MyProducerStage())
				.to(new MyFilterStage(), s -> s.getMyInputPort(), s -> s.getMyOutputPort())
				.end(new MyConsumerStage());

Future Work

  • Support for distribution/merging
    • .distribute(strategy) and .merge(strategy)
  • Introduction of a composite stage builder
    • both builders are more or less equal, but have different return types (Configuration or CompositeStage)
    • possible solution: Write one single builder which is type parameterized
      • (CompositeStageBuilder<T extends CompositeStage)
      • get builder by static CompositeStage.builder() or Configuration.builder() respectively
  • .toActive(stage) and .endActive(stage) methods that connect the stage and additionally set it active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.