// Path: src/main/java/com/optimaize/command4j/lang/Duration.java
// @Immutable
// public final class Duration {
// 
//     private final long time;
//     @NotNull
//     private final TimeUnit timeUnit;
// 
//     @NotNull
//     public static Duration of(long time, @NotNull TimeUnit unit) {
//         return new Duration(time, unit);
//     }
// 
//     @NotNull
//     public static Duration millis(long time) {
//         return of(time, TimeUnit.MILLISECONDS);
//     }
// 
//     @NotNull
//     public static Duration seconds(long time) {
//         return of(time, TimeUnit.SECONDS);
//     }
// 
//     private Duration(long time, @NotNull TimeUnit timeUnit) {
//         this.time = time;
//         this.timeUnit = timeUnit;
//     }
// 
// 
//     public long getTime() {
//         return time;
//     }
// 
//     @NotNull
//     public TimeUnit getTimeUnit() {
//         return timeUnit;
//     }
// 
//     public long toMillis() {
//         return timeUnit.toMillis(time);
//     }
// 
//     public boolean isZero() {
//         return time==0;
//     }
// 
//     @Override
//     public String toString() {
//         return "Duration[" + time + toString(timeUnit) + ']';
//     }
// 
//     @NotNull
//     private String toString(@NotNull TimeUnit timeUnit) {
//         switch (timeUnit) {
//             case MILLISECONDS:
//                 return "ms";
//             case SECONDS:
//                 return "s";
//             case MINUTES:
//                 return "m";
//             case HOURS:
//                 return "h";
//             case DAYS:
//                 return "d";
//             default:
//                 return timeUnit.name();
//         }
//     }
// }


import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.optimaize.command4j.lang.Duration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
package com.optimaize.command4j;



/**
 * An executor service for executing {@link Command}s.
 *
 * <p>This does not extend java.util.concurrent.ExecutorService, but it uses one
 * (actually a Guava {@link ListeningExecutorService}). It offers just a fraction of Guava's interface.</p>
 *
 * @author Eike Kettner
 * @author Fabian Kessler
 */
public interface CommandExecutorService {

    /**
     * Submits a command and returns instantly with a Future as the result.
     */
    @NotNull
    <A, V> ListenableFuture<Optional<V>> submit(@NotNull Command<A, V> cmd,
                                                @NotNull Mode mode,
                                                @Nullable A arg);

    /**
     * Executes a command and blocks until the command finishes successfully, aborts by throwing an exception,
     * the timeout occurs (which throws an exception too), or the command is cancelled before any of these occur.
     */
    @NotNull
    <A, V> Optional<V> submitAndWait(@NotNull Command<A, V> cmd,
                                     @NotNull Mode mode,
                                     @Nullable A arg,
// Path: src/main/java/com/optimaize/command4j/lang/Duration.java
// @Immutable
// public final class Duration {
// 
//     private final long time;
//     @NotNull
//     private final TimeUnit timeUnit;
// 
//     @NotNull
//     public static Duration of(long time, @NotNull TimeUnit unit) {
//         return new Duration(time, unit);
//     }
// 
//     @NotNull
//     public static Duration millis(long time) {
//         return of(time, TimeUnit.MILLISECONDS);
//     }
// 
//     @NotNull
//     public static Duration seconds(long time) {
//         return of(time, TimeUnit.SECONDS);
//     }
// 
//     private Duration(long time, @NotNull TimeUnit timeUnit) {
//         this.time = time;
//         this.timeUnit = timeUnit;
//     }
// 
// 
//     public long getTime() {
//         return time;
//     }
// 
//     @NotNull
//     public TimeUnit getTimeUnit() {
//         return timeUnit;
//     }
// 
//     public long toMillis() {
//         return timeUnit.toMillis(time);
//     }
// 
//     public boolean isZero() {
//         return time==0;
//     }
// 
//     @Override
//     public String toString() {
//         return "Duration[" + time + toString(timeUnit) + ']';
//     }
// 
//     @NotNull
//     private String toString(@NotNull TimeUnit timeUnit) {
//         switch (timeUnit) {
//             case MILLISECONDS:
//                 return "ms";
//             case SECONDS:
//                 return "s";
//             case MINUTES:
//                 return "m";
//             case HOURS:
//                 return "h";
//             case DAYS:
//                 return "d";
//             default:
//                 return timeUnit.name();
//         }
//     }
// }


// Path: src/main/java/com/optimaize/command4j/CommandExecutorService.java
import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.optimaize.command4j.lang.Duration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

package com.optimaize.command4j;



/**
 * An executor service for executing {@link Command}s.
 *
 * <p>This does not extend java.util.concurrent.ExecutorService, but it uses one
 * (actually a Guava {@link ListeningExecutorService}). It offers just a fraction of Guava's interface.</p>
 *
 * @author Eike Kettner
 * @author Fabian Kessler
 */
public interface CommandExecutorService {

    /**
     * Submits a command and returns instantly with a Future as the result.
     */
    @NotNull
    <A, V> ListenableFuture<Optional<V>> submit(@NotNull Command<A, V> cmd,
                                                @NotNull Mode mode,
                                                @Nullable A arg);

    /**
     * Executes a command and blocks until the command finishes successfully, aborts by throwing an exception,
     * the timeout occurs (which throws an exception too), or the command is cancelled before any of these occur.
     */
    @NotNull
    <A, V> Optional<V> submitAndWait(@NotNull Command<A, V> cmd,
                                     @NotNull Mode mode,
                                     @Nullable A arg,
                                     @NotNull Duration timeout) throws InterruptedException, TimeoutException, Exception;