IoContext.java
package com.github.dakusui.thincrest.metamor;
import com.github.dakusui.thincrest_pcond.core.Evaluator;
import com.github.dakusui.thincrest_pcond.core.printable.PrintableFunction;
import com.github.dakusui.thincrest_pcond.forms.Printables;
import java.util.function.Function;
import java.util.function.IntFunction;
import static java.util.Objects.requireNonNull;
public interface IoContext<I, O> {
String prefix();
default String name() {
return this.prefix() + ":" + this.input().name() + "=>" + this.output().name();
}
Dataset<I> input();
Dataset<O> output();
enum Utils {
;
public static <I, O> Function<Dataset<I>, Ongoing<I, O>> toContextFunction(String contextName, String outputContextName) {
return Printables.function("begin:" + contextName, input -> new Ongoing.Impl<>(contextName, input, outputContextName));
}
public static <I, O> Function<Ongoing<I, O>, Ongoing<I, O>> toContextEndomorphicFunction(Function<IoContext<I, O>, Function<I, O>> mapper, int numItems, IntFunction<String> variableNameFormatter) {
requireNonNull(mapper);
Function<Ongoing<I, O>, Ongoing<I, O>> ret = null;
for (int i = 0; i < numItems; i++) {
Function<Ongoing<I, O>, Ongoing<I, O>> cur = mapperToEndomorphicProcessor(mapper, i, variableNameFormatter);
if (ret == null) {
ret = cur;
} else
ret = ret.andThen(cur);
}
assert ret != null;
return ret;
}
public static <I, O> Function<Ongoing<I, O>, Ongoing<I, O>> mapperToEndomorphicProcessor(Function<IoContext<I, O>, Function<I, O>> mapper, int i, IntFunction<String> variableNameFormatter) {
return getOngoingOngoingFunction(mapper, i, variableNameFormatter);
}
private static <I, O> Function<Ongoing<I, O>, Ongoing<I, O>> getOngoingOngoingFunction(Function<IoContext<I, O>, Function<I, O>> mapper, int i, IntFunction<String> variableNameFormatter) {
return Printables.function(
() -> String.format("%s(%s)", mapper, variableNameFormatter.apply(i)),
c -> {
I in = c.input().get(i);
O out = mapper.apply(c).apply(in);
c.output().add(out);
return c.cloneObject();
});
}
public static <I, O> Function<Ongoing<I, O>, IoContext<I, O>> toCloseFunction(String contextName) {
// close
return ((PrintableFunction<Ongoing<I, O>, IoContext<I, O>>) Printables.<Ongoing<I, O>, IoContext<I, O>>function(() -> "end:" + contextName, Ongoing::close)).makeTrivial();
}
public static <I, O> Function<IoContext<I, O>, Dataset<O>> toOutputExtractorFunction(String contextName) {
return Printables.function(() -> "output(" + contextName + ")", IoContext::output);
}
}
interface Closed<I, O> extends IoContext<I, O> {
class Impl<I, O> implements Closed<I, O> {
private final Dataset<I> input;
private final Dataset<O> output;
private final String prefix;
public Impl(String prefix, Dataset<I> input, Dataset<O> output) {
this.prefix = prefix;
this.input = input;
this.output = output;
}
@Override
public String prefix() {
return this.prefix;
}
@Override
public Dataset<I> input() {
return input;
}
@Override
public Dataset<O> output() {
return output;
}
@Override
public String toString() {
return "(context:" + name() + ")";
}
}
}
interface Ongoing<I, O> extends IoContext<I, O>, Evaluator.Snapshottable {
@Override
Dataset.OnGoing<O> output();
default Ongoing<I, O> cloneObject() {
return new Impl<>(this.prefix(), input(), output());
}
default IoContext<I, O> close() {
return new Closed.Impl<>(this.prefix(), this.input(), this.output().close());
}
class Snapshot {
final private Object in;
final private Object out;
public Snapshot(Object in, Object out) {
this.in = in;
this.out = out;
}
public Object in() {
return this.in;
}
public Object out() {
return this.out;
}
public String toString() {
return String.format("%s=>%s", this.in, this.out);
}
}
class Impl<I, O> implements Ongoing<I, O> {
private final String prefix;
private final Dataset<I> input;
private final Dataset.OnGoing<O> output;
public Impl(String prefix, Dataset<I> input, String outputDatasetName) {
this.prefix = prefix;
this.input = requireNonNull(input);
this.output = new Dataset.OnGoing.Impl<>(outputDatasetName);
}
public Impl(String prefix, Dataset<I> input, Dataset<O> output) {
this.prefix = prefix;
this.input = requireNonNull(input);
this.output = new Dataset.OnGoing.Impl<>(output.name(), output);
}
@Override
public String prefix() {
return this.prefix;
}
@Override
public Dataset<I> input() {
return this.input;
}
@Override
public Dataset.OnGoing<O> output() {
assert this.output != null;
return this.output;
}
@Override
public Object snapshot() {
if (this.output.size() == 0)
return new Object() {
@Override
public String toString() {
return String.format("(context:%s)", Impl.this.name());
}
};
return new Snapshot(this.input.get(this.output.size() - 1), this.output.last());
}
@Override
public String toString() {
if (this.output.size() == 0)
return "(empty)";
return String.format("in: <%s>%nout:<%s>", this.input.get(this.output.size() - 1), this.output.last());
}
}
}
}