ActionSupport.java

package com.github.dakusui.actionunit.core;

import com.github.dakusui.actionunit.actions.*;
import com.github.dakusui.actionunit.actions.cmd.CommanderConfig;
import com.github.dakusui.actionunit.actions.cmd.UnixCommanderFactory;
import com.github.dakusui.actionunit.actions.cmd.unix.Cmd;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

import static com.github.dakusui.actionunit.core.context.ContextConsumer.NOP_CONSUMER;
import static com.github.dakusui.actionunit.utils.InternalUtils.toStringIfOverriddenOrNoname;
import static com.github.dakusui.printables.PrintableFunctionals.printableConsumer;
import static java.util.Arrays.asList;
import static java.util.Objects.requireNonNull;

/**
 * A utility class to build various actions.
 */
public enum ActionSupport {
  ;

  /**
   * Creates an action that does nothing.
   *
   * @return A nop action.
   */
  public static Action nop() {
    // Needs to be instantiated each time this method is called.
    // Otherwise, multiple nops cannot be identified in an action tree.
    return Leaf.of(NOP_CONSUMER);
  }

  public static Action leaf(Consumer<Context> consumer) {
    return Leaf.of(consumer);
  }

  /**
   * Returns an action named with a given string `name`.
   *
   * @param name   A name given to `action`.
   * @param action An action to be named.
   * @return A named action.
   */
  public static Action named(String name, Action action) {
    return Named.of(name, action);
  }

  public static Attempt.Builder attempt(Action action) {
    return new Attempt.Builder(action);
  }

  public static <E> ForEach.Builder<E> forEach(Function<Context, Stream<E>> streamGenerator) {
    return forEach("i", streamGenerator);
  }

  /**
   * Note that the `variableName` is only used for printing the variable in an action tree.
   * Not used for identifying a corresponding entry in the context.
   *
   * @param variableName    A name of variable.
   * @param streamGenerator A function to return stream.
   * @param <E>             The type of the loop variable.
   * @return A builder for `ForEach2` action
   */
  public static <E> ForEach.Builder<E> forEach(String variableName, Function<Context, Stream<E>> streamGenerator) {
    return new ForEach.Builder<>(variableName, streamGenerator);
  }

  /**
   * Returns a builder to create an action repeated while `condition` is satisfied.
   *
   * @param condition A condition to make an action repeated.
   * @return A builder for `While` action.
   * @see While
   * @see While.Builder
   */
  public static While.Builder repeatWhile(Predicate<Context> condition) {
    return new While.Builder(condition);
  }

  /**
   * Returns a builder to create an action performed when `condition` is satisfied.
   *
   * @param cond A condition to make an actiono performed.
   * @return A builder for `When` action
   * @see When
   * @see When.Builder
   */
  public static When.Builder when(Predicate<Context> cond) {
    return new When.Builder(cond);
  }

  public static <T> With.Builder<T> with(Function<Context, T> value) {
    return with("i", value);
  }

  /**
   * Note that `variableName` won't be used to resolve a value of a variable, it is
   * merely intended to be printed in an action-tree or logs.
   *
   * @param variableName human-readable variable name.
   * @param value        A function to give a value to be used a context under the returned action.
   * @param <T>          The type of the variable
   * @return A builder for a `with` action.
   */
  public static <T> With.Builder<T> with(String variableName, Function<Context, T> value) {
    return new With.Builder<>(variableName, value);
  }

  public static Retry.Builder retry(Action action) {
    return new Retry.Builder(action);
  }

  public static TimeOut.Builder timeout(Action action) {
    return new TimeOut.Builder(action);
  }

  public static Action sequential(List<Action> actions) {
    return new Composite.Builder(actions).build();
  }

  public static Action parallel(List<Action> actions) {
    return new Composite.Builder(actions).parallel().build();
  }

  public static Cmd cmd(String program, ContextVariable... knownVariables) {
    return cmd(program, CommanderConfig.DEFAULT, knownVariables);
  }

  public static Cmd cmd(String program, CommanderConfig config, ContextVariable... knownVariables) {
    Cmd ret = new Cmd(config).commandName(requireNonNull(program).trim());
    for (ContextVariable each : knownVariables)
      ret = ret.declareVariable(each);
    return ret.append(" ");
  }

  public static UnixCommanderFactory unix() {
    return unix(CommanderConfig.DEFAULT);
  }

  public static UnixCommanderFactory unix(CommanderConfig config) {
    return UnixCommanderFactory.create(config);
  }

  public static Action simple(String name, Consumer<Context> consumer) {
    return leaf(printableConsumer(consumer).describe(name + ":" + toStringIfOverriddenOrNoname(consumer)));
  }

  /**
   * Creates an action that performs given actions one by one sequentially.
   *
   * @param actions Actions to be performed.
   * @return An action that performs `actions`.
   */
  public static Action sequential(Action... actions) {
    return sequential(asList(actions));
  }

  /**
   * Creates an action that performs given actions one by one sequentially.
   *
   * @param actions Actions to be performed.
   * @return An action that performs `actions`.
   */
  public static Action parallel(Action... actions) {
    return parallel(asList(actions));
  }

  /**
   * Returns an action to build `Ensured` action.
   * By adding actions to the returned builder's methods, you can construct an `Ensured` action, whose
   * target action's success is ensured by those added actions.
   *
   * @param target An action ensured to be successful.
   * @return A builder for an `Ensured` action.
   * @see Ensured
   */
  public static Ensured.Builder ensure(Action target) {
    Ensured.Builder b = new Ensured.Builder();
    b.target(target);
    return b;
  }
}