All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.valid8j.metamor.IoContext Maven / Gradle / Ivy

Go to download

Java Library Providing Uniformed Programming Experiences across DbC, Value Checking, and Test Assertions

The newest version!
package com.github.valid8j.metamor;

import com.github.valid8j.pcond.core.Evaluator;
import com.github.valid8j.pcond.core.printable.PrintableFunction;
import com.github.valid8j.pcond.forms.Printables;

import java.util.function.Function;
import java.util.function.IntFunction;

import static java.util.Objects.requireNonNull;

public interface IoContext {
  String prefix();

  default String name() {
    return this.prefix() + ":" + this.input().name() + "=>" + this.output().name();
  }

  Dataset input();

  Dataset output();

  enum Utils {
    ;

    public static  Function, Ongoing> toContextFunction(String contextName, String outputContextName) {
      return Printables.function("begin:" + contextName, input -> new Ongoing.Impl<>(contextName, input, outputContextName));
    }

    public static  Function, Ongoing> toContextEndomorphicFunction(Function, Function> mapper, int numItems, IntFunction variableNameFormatter) {
      requireNonNull(mapper);
      Function, Ongoing> ret = null;
      for (int i = 0; i < numItems; i++) {
        Function, Ongoing> cur = mapperToEndomorphicProcessor(mapper, i, variableNameFormatter);
        if (ret == null) {
          ret = cur;
        } else
          ret = ret.andThen(cur);
      }
      assert ret != null;
      return ret;
    }

    public static  Function, Ongoing> mapperToEndomorphicProcessor(Function, Function> mapper, int i, IntFunction variableNameFormatter) {
      return getOngoingOngoingFunction(mapper, i, variableNameFormatter);
    }

    private static  Function, Ongoing> getOngoingOngoingFunction(Function, Function> mapper, int i, IntFunction 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  Function, IoContext> toCloseFunction(String contextName) {
      // close
      return ((PrintableFunction, IoContext>) Printables., IoContext>function(() -> "end:" + contextName, Ongoing::close)).markSquashable();
    }

    public static  Function, Dataset> toOutputExtractorFunction(String contextName) {
      return Printables.function(() -> "output(" + contextName + ")", IoContext::output);
    }
  }

  interface Closed extends IoContext {
    class Impl implements Closed {
      private final Dataset input;
      private final Dataset output;
      private final String     prefix;

      public Impl(String prefix, Dataset input, Dataset output) {
        this.prefix = prefix;
        this.input = input;
        this.output = output;
      }

      @Override
      public String prefix() {
        return this.prefix;
      }

      @Override
      public Dataset input() {
        return input;
      }

      @Override
      public Dataset output() {
        return output;
      }


      @Override
      public String toString() {
        return "(context:" + name() + ")";
      }
    }
  }

  interface Ongoing extends IoContext, Evaluator.Snapshottable {
    @Override
    Dataset.OnGoing output();

    default Ongoing cloneObject() {
      return new Impl<>(this.prefix(), input(), output());
    }

    default IoContext 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 implements Ongoing {
      private final String prefix;
      private final Dataset         input;
      private final Dataset.OnGoing output;

      public Impl(String prefix, Dataset input, String outputDatasetName) {
        this.prefix = prefix;
        this.input = requireNonNull(input);
        this.output = new Dataset.OnGoing.Impl<>(outputDatasetName);
      }

      public Impl(String prefix, Dataset input, Dataset 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 input() {
        return this.input;
      }

      @Override
      public Dataset.OnGoing 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());
      }
    }
  }
}