// Path: src/main/java/com/optimaize/command4j/Command.java
// public interface Command<A, R> {
// 
//     /**
//      * Runs the remote command.
//      *
//      * <p>This method always blocks until either the command finishes successfully, aborts by throwing an
//      * exception, or is cancelled early. (The {@link CommandExecutorService} allows you to execute
//      * commands in a non-blocking way.)</p>
//      *
//      * @param arg The {@link Optional} argument. If you need more than 1 argument then you may create a
//      *            request class as container, or maybe it's enough to just use {@link Tuples tuples}.
//      * @param ec
//      * @return Commands may return null, since null values are handled by the framework in that they're wrapped
//      *         into an {@link Optional}.
//      * @throws Exception
//      *
//      * TODO Eike: The return value is nullable and the framework makes an Optional out of it.
//      *            Why not the same for the argument? We could make the interface more consistent.
//      *            Is there a reason against that?
//      */
//     @Nullable
//     R call(@NotNull Optional<A> arg, @NotNull ExecutionContext ec) throws Exception;
// 
//     /**
//      * Like Java's Thread, a Command has a name.
//      *
//      * <p>Because toString() can become long with all the interceptors wrapping a base command, this
//      * keeps it simple to what it actually does.</p>
//      *
//      * <p>Certain kinds of combined commands, like a ComposedCommand or a ConditionCommand, don't have a single
//      * name, they show the names of the contained commands.</p>
//      *
//      * @return an identifier, not unique but usually distinguishable
//      */
//     String getName();
// }
// 
// Path: src/main/java/com/optimaize/command4j/ExecutionContext.java
// public interface ExecutionContext {
// 
//     /**
//      * @return the mode that was supplied to the initial invocation.
//      */
//     @NotNull
//     Mode getMode();
// 
//     /**
//      * @return the global cache to store/retrieve objects to/from.
//      */
//     @NotNull
//     ExecutorCache getCache();
// 
//     /**
//      * Overloaded method that uses the same <code>mode</code> as supplied
//      * to the parent invocation.
//      *
//      * @see #execute(Command, Mode, com.google.common.base.Optional)
//      */
//     @NotNull
//     <A, R> Optional<R> execute(@NotNull Command<A, R> task, Optional<A> arg) throws Exception;
// 
//     /**
//      * Runs the given <code>command</code> using the given <code>mode</code>.
//      *
//      * <p>This method is for commands that want to execute yet another command.
//      * One example is an auto-retry extension that executes the command again.
//      * </p>
//      */
//     @NotNull
//     <A, R> Optional<R> execute(@NotNull Command<A, R> task, @NotNull Mode mode, Optional<A> arg) throws Exception;
// 
// }


import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.optimaize.command4j.Command;
import com.optimaize.command4j.ExecutionContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
package com.optimaize.command4j.commands;


/**
 * Executes the first, and if the result matches the condition then the result is returned.
 * Otherwise the second is executed and its result is returned.
 *
 * @param <A> the optional Argument's data type
 * @param <R> the Result's data type
 * @author Eike Kettner
 * @author Fabian Kessler
 */
final class ConditionCommand<A, R> extends BaseCommand<A, R> {

    @NotNull
    private final Command<A, R> primary;
    @NotNull
    private final Command<A, R> secondary;
    @NotNull
    private final Predicate<R> condition;

    ConditionCommand(@NotNull Command<A, R> primary, @NotNull Command<A, R> secondary, @NotNull Predicate<R> condition) {
        this.primary = primary;
        this.secondary = secondary;
        this.condition = condition;
    }

    @Override @Nullable
    public R call(@NotNull Optional<A> arg, @NotNull ExecutionContext ec) throws Exception {
        R pr = primary.call(arg, ec);
        if (condition.apply(pr)) {
            return pr;
        } else {
            return secondary.call(arg, ec);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ConditionCommand that = (ConditionCommand) o;

        if (!condition.equals(that.condition)) return false;
// Path: src/main/java/com/optimaize/command4j/Command.java
// public interface Command<A, R> {
// 
//     /**
//      * Runs the remote command.
//      *
//      * <p>This method always blocks until either the command finishes successfully, aborts by throwing an
//      * exception, or is cancelled early. (The {@link CommandExecutorService} allows you to execute
//      * commands in a non-blocking way.)</p>
//      *
//      * @param arg The {@link Optional} argument. If you need more than 1 argument then you may create a
//      *            request class as container, or maybe it's enough to just use {@link Tuples tuples}.
//      * @param ec
//      * @return Commands may return null, since null values are handled by the framework in that they're wrapped
//      *         into an {@link Optional}.
//      * @throws Exception
//      *
//      * TODO Eike: The return value is nullable and the framework makes an Optional out of it.
//      *            Why not the same for the argument? We could make the interface more consistent.
//      *            Is there a reason against that?
//      */
//     @Nullable
//     R call(@NotNull Optional<A> arg, @NotNull ExecutionContext ec) throws Exception;
// 
//     /**
//      * Like Java's Thread, a Command has a name.
//      *
//      * <p>Because toString() can become long with all the interceptors wrapping a base command, this
//      * keeps it simple to what it actually does.</p>
//      *
//      * <p>Certain kinds of combined commands, like a ComposedCommand or a ConditionCommand, don't have a single
//      * name, they show the names of the contained commands.</p>
//      *
//      * @return an identifier, not unique but usually distinguishable
//      */
//     String getName();
// }
// 
// Path: src/main/java/com/optimaize/command4j/ExecutionContext.java
// public interface ExecutionContext {
// 
//     /**
//      * @return the mode that was supplied to the initial invocation.
//      */
//     @NotNull
//     Mode getMode();
// 
//     /**
//      * @return the global cache to store/retrieve objects to/from.
//      */
//     @NotNull
//     ExecutorCache getCache();
// 
//     /**
//      * Overloaded method that uses the same <code>mode</code> as supplied
//      * to the parent invocation.
//      *
//      * @see #execute(Command, Mode, com.google.common.base.Optional)
//      */
//     @NotNull
//     <A, R> Optional<R> execute(@NotNull Command<A, R> task, Optional<A> arg) throws Exception;
// 
//     /**
//      * Runs the given <code>command</code> using the given <code>mode</code>.
//      *
//      * <p>This method is for commands that want to execute yet another command.
//      * One example is an auto-retry extension that executes the command again.
//      * </p>
//      */
//     @NotNull
//     <A, R> Optional<R> execute(@NotNull Command<A, R> task, @NotNull Mode mode, Optional<A> arg) throws Exception;
// 
// }


// Path: src/main/java/com/optimaize/command4j/commands/ConditionCommand.java
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.optimaize.command4j.Command;
import com.optimaize.command4j.ExecutionContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

package com.optimaize.command4j.commands;


/**
 * Executes the first, and if the result matches the condition then the result is returned.
 * Otherwise the second is executed and its result is returned.
 *
 * @param <A> the optional Argument's data type
 * @param <R> the Result's data type
 * @author Eike Kettner
 * @author Fabian Kessler
 */
final class ConditionCommand<A, R> extends BaseCommand<A, R> {

    @NotNull
    private final Command<A, R> primary;
    @NotNull
    private final Command<A, R> secondary;
    @NotNull
    private final Predicate<R> condition;

    ConditionCommand(@NotNull Command<A, R> primary, @NotNull Command<A, R> secondary, @NotNull Predicate<R> condition) {
        this.primary = primary;
        this.secondary = secondary;
        this.condition = condition;
    }

    @Override @Nullable
    public R call(@NotNull Optional<A> arg, @NotNull ExecutionContext ec) throws Exception {
        R pr = primary.call(arg, ec);
        if (condition.apply(pr)) {
            return pr;
        } else {
            return secondary.call(arg, ec);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ConditionCommand that = (ConditionCommand) o;

        if (!condition.equals(that.condition)) return false;
        if (!primary.equals(that.primary)) return false;