package io.burt.jmespath.function;

import io.burt.jmespath.Expression;

public abstract class FunctionArgument<T> {
  private static class V<U> extends FunctionArgument<U> {
    private final U value;

    public V(U value) {
      this.value = value;
    }

    public U value() { return value; }

    public boolean isValue() { return true; }
  }

  private static class E<U> extends FunctionArgument<U> {
    private final Expression<U> expression;

    public E(Expression<U> expression) {
      this.expression = expression;
    }

    public Expression<U> expression() { return expression; }

    public boolean isExpression() { return true; }
  }

  public static <U> FunctionArgument<U> of(U value) {
    return new V<U>(value);
  }

  public static <U> FunctionArgument<U> of(Expression<U> expression) {
    return new E<U>(expression);
  }

  private FunctionArgument() { }

  public Expression<T> expression() { return null; };

  public T value() { return null; }

  public boolean isExpression() { return false; }

  public boolean isValue() { return false; }
}

package io.burt.jmespath.function;

import io.burt.jmespath.Expression;

/**
 * In JMESPath most functions take regular values as arguments, but some are
 * higher order functions and take expressions. This class exists so that
 * argument lists can have a single type, while still contain a mix of values
 * and expressions.
 */
public abstract class FunctionArgument<T> {
  private static class V<U> extends FunctionArgument<U> {
    private final U value;

    public V(U value) {
      this.value = value;
    }

    public U value() { return value; }

    public boolean isValue() { return true; }
  }

  private static class E<U> extends FunctionArgument<U> {
    private final Expression<U> expression;

    public E(Expression<U> expression) {
      this.expression = expression;
    }

    public Expression<U> expression() { return expression; }

    public boolean isExpression() { return true; }
  }

  /**
   * Creates a new function argument that contains a value.
   */
  public static <U> FunctionArgument<U> of(U value) {
    return new V<U>(value);
  }

  /**
   * Creates a new function argument that contains an expression.
   */
  public static <U> FunctionArgument<U> of(Expression<U> expression) {
    return new E<U>(expression);
  }

  private FunctionArgument() { }

  /**
   * Returns the expression contained in this argument, or null if this argument
   * is not an expression argument.
   */
  public Expression<T> expression() { return null; };

  /**
   * Returns the value contained in this argument, or null if this argument is
   * not a value argument.
   */
  public T value() { return null; }

  /** Returns true when this argument contains an expression */
  public boolean isExpression() { return false; }

  /** Returns true when this argument contains a value */
  public boolean isValue() { return false; }
}

Add API docs to FunctionArgument