001package com.github.theholywaffle.teamspeak3.api;
002
003/*
004 * #%L
005 * TeamSpeak 3 Java API
006 * %%
007 * Copyright (C) 2014 Bert De Geyter
008 * %%
009 * Permission is hereby granted, free of charge, to any person obtaining a copy
010 * of this software and associated documentation files (the "Software"), to deal
011 * in the Software without restriction, including without limitation the rights
012 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
013 * copies of the Software, and to permit persons to whom the Software is
014 * furnished to do so, subject to the following conditions:
015 * 
016 * The above copyright notice and this permission notice shall be included in
017 * all copies or substantial portions of the Software.
018 * 
019 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
020 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
021 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
022 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
023 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
024 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
025 * THE SOFTWARE.
026 * #L%
027 */
028
029import com.github.theholywaffle.teamspeak3.TS3ApiAsync;
030import com.github.theholywaffle.teamspeak3.api.exception.TS3Exception;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033
034import java.util.Arrays;
035import java.util.Collection;
036import java.util.Iterator;
037import java.util.List;
038import java.util.concurrent.CancellationException;
039import java.util.concurrent.Future;
040import java.util.concurrent.TimeUnit;
041import java.util.concurrent.TimeoutException;
042import java.util.concurrent.atomic.AtomicInteger;
043import java.util.function.Function;
044
045/**
046 * Represents the result of an asynchronous execution of a query command.
047 * <p>
048 * Basically, this class is a container for a server response which will
049 * arrive at some time in the future. It also accounts for the possibility
050 * that a command might fail and that a future might be cancelled by a user.
051 * </p>
052 * A {@code CommandFuture} can therefore have 4 different states:
053 * <ul>
054 * <li><b>Waiting</b> - No response from the server has arrived yet</li>
055 * <li><b>Cancelled</b> - A user cancelled this future before a response from the server could arrive</li>
056 * <li><b>Failed</b> - The server received the command but responded with an error message</li>
057 * <li><b>Succeeded</b> - The server successfully processed the command and sent back a result</li>
058 * </ul>
059 * You can check the state of the future using the methods {@link #isDone()},
060 * {@link #isSuccessful()}, {@link #hasFailed()} and {@link #isCancelled()}.
061 * <p>
062 * A {@code CommandFuture}'s value can be retrieved by calling {@link #get()}
063 * or {@link #get(long, TimeUnit)}, which block the current thread until the
064 * server response arrives. The method with a timeout should be preferred
065 * as there's no guarantee that a proper response (or an error message)
066 * will ever arrive, e.g. in case of a permanent disconnect.
067 * There are also variations of these methods which ignore thread interrupts,
068 * {@link #getUninterruptibly()} and {@link #getUninterruptibly(long, TimeUnit)}.
069 * </p><p>
070 * Note that <b>these methods</b> all wait for the response to arrive and thereby
071 * <b>revert to synchronous</b> execution. If you want to handle the server response
072 * asynchronously, you need to register success and failure listeners.
073 * These listeners will be called in a separate thread once a response arrives.
074 * </p><p>
075 * Each {@code CommandFuture} can only ever have one {@link SuccessListener} and
076 * one {@link FailureListener} registered. All {@link TS3ApiAsync} methods are
077 * guaranteed to return a {@code CommandFuture} with no listeners registered.
078 * </p><p>
079 * To set the value of a {@code CommandFuture}, the {@link #set(Object)} method is used;
080 * to notify it of a failure, {@link #fail(TS3Exception)} is used. You usually
081 * shouldn't call these methods yourself, however. That's the job of the API.
082 * </p><p>
083 * {@code CommandFuture}s are thread-safe. All state-changing methods are synchronized.
084 * </p>
085 *
086 * @param <V>
087 *              the type of the value
088 *
089 * @see TS3ApiAsync
090 */
091public class CommandFuture<V> implements Future<V> {
092
093        private static final Logger log = LoggerFactory.getLogger(CommandFuture.class);
094
095        private enum FutureState {
096                WAITING,
097                CANCELLED,
098                FAILED,
099                SUCCEEDED
100        }
101
102        /**
103         * Just a plain object used for its monitor to synchronize access to the
104         * critical sections of this future and to signal state changes to any
105         * threads waiting in {@link #get()} and {@link #getUninterruptibly()} methods.
106         */
107        private final Object monitor = new Object();
108
109        /**
110         * The current state of the future. Marked as volatile so {@link #isDone()}
111         * and similar functions can work without synchronization.
112         * State transitions and check-then-acts must be guarded by monitor.
113         */
114        private volatile FutureState state = FutureState.WAITING;
115
116        // All guarded by monitor
117        private V value = null;
118        private TS3Exception exception = null;
119        private SuccessListener<? super V> successListener = null;
120        private FailureListener failureListener = null;
121
122        /**
123         * Waits indefinitely until the command completes.
124         * <p>
125         * If the thread is interrupted while waiting for the command
126         * to complete, this method will throw an {@code InterruptedException}
127         * and the thread's interrupt flag will be cleared.
128         * </p><p><i>
129         * Please note that this method is blocking and thus negates
130         * the advantage of the asynchronous nature of this class.
131         * Consider using {@link #onSuccess(SuccessListener)} and
132         * {@link #onFailure(FailureListener)} instead.
133         * </i></p>
134         *
135         * @throws InterruptedException
136         *              if the method is interrupted by calling {@link Thread#interrupt()}.
137         *              The interrupt flag will be cleared
138         */
139        public void await() throws InterruptedException {
140                synchronized (monitor) {
141                        while (state == FutureState.WAITING) {
142                                monitor.wait();
143                        }
144                }
145        }
146
147        /**
148         * Waits for at most the given time until the command completes.
149         * <p>
150         * If the thread is interrupted while waiting for the command
151         * to complete, this method will throw an {@code InterruptedException}
152         * and the thread's interrupt flag will be cleared.
153         * </p><p><i>
154         * Please note that this method is blocking and thus negates
155         * the advantage of the asynchronous nature of this class.
156         * Consider using {@link #onSuccess(SuccessListener)} and
157         * {@link #onFailure(FailureListener)} instead.
158         * </i></p>
159         *
160         * @param timeout
161         *              the maximum amount of the given time unit to wait
162         * @param unit
163         *              the time unit of the timeout argument
164         *
165         * @throws InterruptedException
166         *              if the method is interrupted by calling {@link Thread#interrupt()}.
167         *              The interrupt flag will be cleared
168         * @throws TimeoutException
169         *              if the given time elapsed without the command completing
170         */
171        public void await(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
172                synchronized (monitor) {
173                        final long end = System.currentTimeMillis() + unit.toMillis(timeout);
174                        while (state == FutureState.WAITING && System.currentTimeMillis() < end) {
175                                monitor.wait(end - System.currentTimeMillis());
176                        }
177
178                        if (state == FutureState.WAITING) throw new TimeoutException();
179                }
180        }
181
182        /**
183         * Waits indefinitely until the command completes.
184         * <p>
185         * If the thread is interrupted while waiting for the command
186         * to complete, the interrupt is simply ignored and no
187         * {@link InterruptedException} is thrown.
188         * </p><p><i>
189         * Please note that this method is blocking and thus negates
190         * the advantage of the asynchronous nature of this class.
191         * Consider using {@link #onSuccess(SuccessListener)} and
192         * {@link #onFailure(FailureListener)} instead.
193         * </i></p>
194         */
195        public void awaitUninterruptibly() {
196                synchronized (monitor) {
197                        boolean interrupted = false;
198                        while (state == FutureState.WAITING) {
199                                try {
200                                        monitor.wait();
201                                } catch (InterruptedException e) {
202                                        interrupted = true;
203                                }
204                        }
205
206                        if (interrupted) {
207                                // Restore the interrupt for the caller
208                                Thread.currentThread().interrupt();
209                        }
210                }
211        }
212
213        /**
214         * Waits for at most the given time until the command completes.
215         * <p>
216         * If the thread is interrupted while waiting for the command
217         * to complete, the interrupt is simply ignored and no
218         * {@link InterruptedException} is thrown.
219         * </p><p><i>
220         * Please note that this method is blocking and thus negates
221         * the advantage of the asynchronous nature of this class.
222         * Consider using {@link #onSuccess(SuccessListener)} and
223         * {@link #onFailure(FailureListener)} instead.
224         * </i></p>
225         *
226         * @param timeout
227         *              the maximum amount of the given time unit to wait
228         * @param unit
229         *              the time unit of the timeout argument
230         *
231         * @throws TimeoutException
232         *              if the given time elapsed without the command completing
233         */
234        public void awaitUninterruptibly(long timeout, TimeUnit unit) throws TimeoutException {
235                synchronized (monitor) {
236                        final long end = System.currentTimeMillis() + unit.toMillis(timeout);
237                        boolean interrupted = false;
238
239                        while (state == FutureState.WAITING && System.currentTimeMillis() < end) {
240                                try {
241                                        monitor.wait(end - System.currentTimeMillis());
242                                } catch (InterruptedException e) {
243                                        interrupted = true;
244                                }
245                        }
246
247                        if (interrupted) {
248                                // Restore the interrupt for the caller
249                                Thread.currentThread().interrupt();
250                        }
251
252                        if (state == FutureState.WAITING) throw new TimeoutException();
253                }
254        }
255
256        /**
257         * Waits indefinitely until the command completes
258         * and returns the result of the command.
259         * <p>
260         * If the thread is interrupted while waiting for the command
261         * to complete, this method will throw an {@code InterruptedException}
262         * and the thread's interrupt flag will be cleared.
263         * </p><p><i>
264         * Please note that this method is blocking and thus negates
265         * the advantage of the asynchronous nature of this class.
266         * Consider using {@link #onSuccess(SuccessListener)} and
267         * {@link #onFailure(FailureListener)} instead.
268         * </i></p>
269         *
270         * @return the server response to the command
271         *
272         * @throws InterruptedException
273         *              if the method is interrupted by calling {@link Thread#interrupt()}.
274         *              The interrupt flag will be cleared
275         * @throws CancellationException
276         *              if the {@code CommandFuture} was cancelled before the command completed
277         * @throws TS3Exception
278         *              if the command fails
279         */
280        @Override
281        public V get() throws InterruptedException {
282                synchronized (monitor) {
283                        await();
284
285                        checkForFailure();
286                        return value;
287                }
288        }
289
290        /**
291         * Waits for at most the given time until the command completes
292         * and returns the result of the command.
293         * <p>
294         * If the thread is interrupted while waiting for the command
295         * to complete, this method will throw an {@code InterruptedException}
296         * and the thread's interrupt flag will be cleared.
297         * </p><p><i>
298         * Please note that this method is blocking and thus negates
299         * the advantage of the asynchronous nature of this class.
300         * Consider using {@link #onSuccess(SuccessListener)} and
301         * {@link #onFailure(FailureListener)} instead.
302         * </i></p>
303         *
304         * @param timeout
305         *              the maximum amount of the given time unit to wait
306         * @param unit
307         *              the time unit of the timeout argument
308         *
309         * @return the server response to the command
310         *
311         * @throws InterruptedException
312         *              if the method is interrupted by calling {@link Thread#interrupt()}.
313         *              The interrupt flag will be cleared
314         * @throws TimeoutException
315         *              if the given time elapsed without the command completing
316         * @throws CancellationException
317         *              if the {@code CommandFuture} was cancelled before the command completed
318         * @throws TS3Exception
319         *              if the command fails
320         */
321        @Override
322        public V get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
323                synchronized (monitor) {
324                        await(timeout, unit);
325
326                        checkForFailure();
327                        return value;
328                }
329        }
330
331        /**
332         * Waits indefinitely until the command completes
333         * and returns the result of the command.
334         * <p>
335         * If the thread is interrupted while waiting for the command
336         * to complete, the interrupt is simply ignored and no
337         * {@link InterruptedException} is thrown.
338         * </p><p><i>
339         * Please note that this method is blocking and thus negates
340         * the advantage of the asynchronous nature of this class.
341         * Consider using {@link #onSuccess(SuccessListener)} and
342         * {@link #onFailure(FailureListener)} instead.
343         * </i></p>
344         *
345         * @return the server response to the command
346         *
347         * @throws CancellationException
348         *              if the {@code CommandFuture} was cancelled before the command completed
349         * @throws TS3Exception
350         *              if the command fails
351         */
352        public V getUninterruptibly() {
353                synchronized (monitor) {
354                        awaitUninterruptibly();
355
356                        checkForFailure();
357                        return value;
358                }
359        }
360
361        /**
362         * Waits for at most the given time until the command completes
363         * and returns the result of the command.
364         * <p>
365         * If the thread is interrupted while waiting for the command
366         * to complete, the interrupt is simply ignored and no
367         * {@link InterruptedException} is thrown.
368         * </p><p><i>
369         * Please note that this method is blocking and thus negates
370         * the advantage of the asynchronous nature of this class.
371         * Consider using {@link #onSuccess(SuccessListener)} and
372         * {@link #onFailure(FailureListener)} instead.
373         * </i></p>
374         *
375         * @param timeout
376         *              the maximum amount of the given time unit to wait
377         * @param unit
378         *              the time unit of the timeout argument
379         *
380         * @return the server response to the command
381         *
382         * @throws TimeoutException
383         *              if the given time elapsed without the command completing
384         * @throws CancellationException
385         *              if the {@code CommandFuture} was cancelled before the command completed
386         * @throws TS3Exception
387         *              if the command fails
388         */
389        public V getUninterruptibly(long timeout, TimeUnit unit) throws TimeoutException {
390                synchronized (monitor) {
391                        awaitUninterruptibly(timeout, unit);
392
393                        checkForFailure();
394                        return value;
395                }
396        }
397
398        /**
399         * Throws an exception if the future was either cancelled or the command failed.
400         * <p>
401         * <strong>Must be called with the monitor lock held!</strong>
402         * </p>
403         *
404         * @throws CancellationException
405         *              if the future was cancelled
406         * @throws TS3Exception
407         *              if the command failed
408         */
409        private void checkForFailure() {
410                if (state == FutureState.CANCELLED) {
411                        throw new CancellationException();
412                } else if (state == FutureState.FAILED) {
413                        // Make the stack trace of the exception point to this method and not
414                        // SocketReader#run -> TS3ApiAsync#hasFailed, which wouldn't be helpful
415                        exception.fillInStackTrace();
416                        throw exception;
417                }
418        }
419
420        @Override
421        public boolean isDone() {
422                return state != FutureState.WAITING;
423        }
424
425        /**
426         * Returns {@code true} if this command completed successfully,
427         * i.e. the future wasn't cancelled and the command completed without throwing an exception.
428         *
429         * @return {@code true} if the command completed successfully
430         */
431        public boolean isSuccessful() {
432                return state == FutureState.SUCCEEDED;
433        }
434
435        @Override
436        public boolean isCancelled() {
437                return state == FutureState.CANCELLED;
438        }
439
440        /**
441         * Returns {@code true} if the command failed and threw a {@link TS3Exception}.
442         *
443         * @return {@code true} if the command failed
444         */
445        public boolean hasFailed() {
446                return state == FutureState.FAILED;
447        }
448
449        /**
450         * Sets the value of this future. This will mark the future as successful.
451         * <p>
452         * Furthermore, this will run the {@link SuccessListener}, if one is registered.
453         * All exceptions thrown from the body of the {@code SuccessListener} are caught
454         * so no exceptions can leak into user code.
455         * </p><p>
456         * Note that a future's value can only be set once. Subsequent calls to
457         * this method will be ignored.
458         * </p>
459         *
460         * @param value
461         *              the value to set this future to
462         *
463         * @return {@code true} if the command was marked as successful
464         */
465        public boolean set(V value) {
466                SuccessListener<? super V> listener;
467
468                synchronized (monitor) {
469                        if (isDone()) return false; // Ignore
470
471                        this.state = FutureState.SUCCEEDED;
472                        this.value = value;
473                        listener = successListener;
474                        monitor.notifyAll();
475                }
476
477                if (listener != null) {
478                        try {
479                                listener.handleSuccess(value);
480                        } catch (Exception e) {
481                                // Whatever happens, we do not want a user error to leak into our logic
482                                log.error("SuccessListener threw an exception", e);
483                        }
484                }
485                return true;
486        }
487
488        /**
489         * Notifies this future that the command has failed.
490         * <p>
491         * Furthermore, this will run the {@link FailureListener}, if one is registered.
492         * All exceptions thrown from the body of the {@code FailureListener} are caught
493         * so no exceptions can leak into user code.
494         * </p><p>
495         * Note that a future can only fail once. Subsequent calls to this method will be ignored.
496         * </p>
497         *
498         * @param exception
499         *              the exception that occurred while executing this command
500         *
501         * @return {@code true} if the command was marked as failed
502         */
503        public boolean fail(TS3Exception exception) {
504                FailureListener listener;
505
506                synchronized (monitor) {
507                        if (isDone()) return false; // Ignore
508
509                        this.state = FutureState.FAILED;
510                        this.exception = exception;
511                        listener = failureListener;
512                        monitor.notifyAll();
513                }
514
515                if (listener != null) {
516                        try {
517                                listener.handleFailure(exception);
518                        } catch (Exception e) {
519                                // Whatever happens, we do not want a user error to leak into our logic
520                                log.error("FailureListener threw an exception", e);
521                        }
522                }
523                return true;
524        }
525
526        /**
527         * {@inheritDoc}
528         * <p>
529         * Cancelling a {@code CommandFuture} will <b>not</b> actually cancel the
530         * execution of the command which was sent to the TeamSpeak server.
531         * </p><p>
532         * It will, however, prevent the {@link SuccessListener} and the
533         * {@link FailureListener} from firing, provided a response from the
534         * server has not yet arrived.
535         * </p>
536         */
537        @Override
538        public boolean cancel(boolean mayInterruptIfRunning) {
539                synchronized (monitor) {
540                        if (isDone()) return false; // Ignore
541
542                        this.state = FutureState.CANCELLED;
543                        monitor.notifyAll();
544                }
545
546                return true;
547        }
548
549        /**
550         * Sets a {@link SuccessListener} which will be notified when this future
551         * succeeded and a value has been set.
552         * <p>
553         * If this future has already succeeded, this method will immediately call
554         * the listener method, which will be executed synchronously.
555         * </p>
556         *
557         * @param listener
558         *              the listener to notify of a success
559         *
560         * @return this object for chaining
561         */
562        public CommandFuture<V> onSuccess(SuccessListener<? super V> listener) {
563                boolean runSuccessListener;
564                V successValue;
565
566                synchronized (monitor) {
567                        if (successListener != null) {
568                                throw new IllegalStateException("Listener already set");
569                        }
570                        successListener = listener;
571
572                        runSuccessListener = isSuccessful();
573                        successValue = value;
574                }
575
576                if (runSuccessListener) {
577                        listener.handleSuccess(successValue);
578                }
579
580                return this;
581        }
582
583        /**
584         * Sets a {@link FailureListener} which will be notified when this future
585         * fails because of a error returned by the TeamSpeak server.
586         * <p>
587         * If this future has already failed, this method will immediately call
588         * the listener method, which will be executed synchronously.
589         * </p>
590         *
591         * @param listener
592         *              the listener to notify of a failure
593         *
594         * @return this object for chaining
595         */
596        public CommandFuture<V> onFailure(FailureListener listener) {
597                boolean runFailureListener;
598                TS3Exception failureException;
599
600                synchronized (monitor) {
601                        if (failureListener != null) {
602                                throw new IllegalStateException("Listener already set");
603                        }
604                        failureListener = listener;
605
606                        runFailureListener = hasFailed();
607                        failureException = exception;
608                }
609
610                if (runFailureListener) {
611                        listener.handleFailure(failureException);
612                }
613
614                return this;
615        }
616
617        /**
618         * Forwards a success to another future by calling {@link #set(Object)} on
619         * that future with the value this future was set to.
620         * <p>
621         * This will register a {@link SuccessListener}, meaning that you will not
622         * be able to register another {@code SuccessListener}.
623         * </p>
624         *
625         * @param otherFuture
626         *              the future to forward a success to
627         *
628         * @return this object for chaining
629         */
630        public CommandFuture<V> forwardSuccess(final CommandFuture<? super V> otherFuture) {
631                return onSuccess(otherFuture::set);
632        }
633
634        /**
635         * Forwards a failure to another future by calling {@link #fail(TS3Exception)}
636         * on that future with the error that caused this future to fail.
637         * <p>
638         * This will register a {@link FailureListener}, meaning that you will not
639         * be able to register another {@code FailureListener}.
640         * </p>
641         *
642         * @param otherFuture
643         *              the future to forward a failure to
644         *
645         * @return this object for chaining
646         */
647        public CommandFuture<V> forwardFailure(final CommandFuture<?> otherFuture) {
648                return onFailure(otherFuture::fail);
649        }
650
651        /**
652         * Forwards both a success as well as a failure to another {@code CommandFuture}.
653         * This method just calls both {@link #forwardSuccess(CommandFuture)} and
654         * {@link #forwardFailure(CommandFuture)}.
655         * <p>
656         * This will set both a {@link SuccessListener} as well as a {@link FailureListener},
657         * so no other listeners can be registered.
658         * </p>
659         *
660         * @param otherFuture
661         *              the future which should be notified about
662         */
663        public void forwardResult(final CommandFuture<V> otherFuture) {
664                forwardSuccess(otherFuture).forwardFailure(otherFuture);
665        }
666
667        /**
668         * Creates a new {@code CommandFuture} that succeeds with {@code fn(result)}
669         * if the original future succeeded with a value {@code result}, and fails
670         * if the original future failed or if the mapping function {@code fn} threw
671         * an exception.
672         *
673         * @param fn
674         *              a function that maps the result value of type {@code V} to a value of type {@code F}
675         * @param <F>
676         *              the result type of {@code fn}
677         *
678         * @return a new {@code CommandFuture} that will hold the return value of {@code fn}
679         */
680        public <F> CommandFuture<F> map(Function<? super V, ? extends F> fn) {
681                CommandFuture<F> target = new CommandFuture<>();
682                onSuccess(result -> {
683                        F output;
684                        try {
685                                output = fn.apply(result);
686                        } catch (Exception ex) {
687                                target.fail(new TS3Exception("CommandFuture 'map' function threw an exception", ex));
688                                return;
689                        }
690                        target.set(output);
691                }).forwardFailure(target);
692                return target;
693        }
694
695        /**
696         * Creates a new {@code CommandFuture} that succeeds with the result value of
697         * the {@code CommandFuture} returned by {@code fn} if both the original future
698         * and the future returned by {@code fn} succeed.
699         * <p>
700         * The created {@code CommandFuture} fails if the original future failed,
701         * the future returned by {@code fn} fails, or if {@code fn} throws an exception.
702         * </p><p>
703         * If {@code fn} returns {@code null}, the created {@code CommandFuture}
704         * will immediately succeed with a value of {@code null}. To create this effect
705         * with non-null values, return an {@link #immediate(Object)} future instead.
706         * </p>
707         *
708         * @param fn
709         *              a function that maps the result value of type {@code V} to a {@code CommandFuture<F>}
710         * @param <F>
711         *              the result type of the future returned by {@code fn}
712         *
713         * @return a new {@code CommandFuture} that will hold the result of the future returned by {@code fn}
714         */
715        public <F> CommandFuture<F> then(Function<? super V, CommandFuture<F>> fn) {
716                CommandFuture<F> target = new CommandFuture<>();
717                onSuccess(result -> {
718                        CommandFuture<F> nextFuture;
719                        try {
720                                nextFuture = fn.apply(result);
721                        } catch (Exception ex) {
722                                target.fail(new TS3Exception("CommandFuture 'then' function threw an exception", ex));
723                                return;
724                        }
725
726                        if (nextFuture == null) {
727                                target.set(null); // Propagate null shortcut
728                        } else {
729                                nextFuture.forwardResult(target);
730                        }
731                }).forwardFailure(target);
732                return target;
733        }
734
735        /**
736         * Returns a new {@code CommandFuture} that already has a value set.
737         *
738         * @param value
739         *              the default value for the new {@code CommandFuture}
740         * @param <V>
741         *              the dynamic type of the value, will usually be inferred
742         *
743         * @return a new {@code CommandFuture} with a default value
744         */
745        public static <V> CommandFuture<V> immediate(V value) {
746                final CommandFuture<V> future = new CommandFuture<>();
747                future.set(value);
748                return future;
749        }
750
751        /**
752         * Combines multiple {@code CommandFuture}s into a single future, which will
753         * succeed if all futures succeed and fail as soon as one future fails.
754         *
755         * @param futures
756         *              the futures to combine
757         * @param <F>
758         *              the common return type of the futures
759         *
760         * @return a future which succeeds if all supplied futures succeed
761         */
762        @SafeVarargs
763        public static <F> CommandFuture<List<F>> ofAll(CommandFuture<F>... futures) {
764                return ofAll(Arrays.asList(futures));
765        }
766
767        /**
768         * Combines a collection of {@code CommandFuture}s into a single future, which will
769         * succeed if all futures succeed and fail as soon as one future fails.
770         *
771         * @param futures
772         *              the futures to combine
773         * @param <F>
774         *              the common return type of the futures
775         *
776         * @return a future which succeeds if all supplied futures succeed
777         */
778        public static <F> CommandFuture<List<F>> ofAll(final Collection<CommandFuture<F>> futures) {
779                if (futures.isEmpty()) throw new IllegalArgumentException("Requires at least 1 future");
780
781                @SuppressWarnings("unchecked") final F[] results = (F[]) new Object[futures.size()];
782                final AtomicInteger successCounter = new AtomicInteger(futures.size());
783                final CommandFuture<List<F>> combined = new CommandFuture<>();
784
785                final Iterator<CommandFuture<F>> iterator = futures.iterator();
786                for (int i = 0; iterator.hasNext(); ++i) {
787                        final int index = i;
788                        final CommandFuture<F> future = iterator.next();
789
790                        future.forwardFailure(combined).onSuccess(result -> {
791                                results[index] = result;
792
793                                if (successCounter.decrementAndGet() == 0) {
794                                        combined.set(Arrays.asList(results));
795                                }
796                        });
797                }
798
799                return combined;
800        }
801
802        /**
803         * Combines multiple {@code CommandFuture}s into a single future, which will
804         * succeed if any of the futures succeeds and fail if all of the futures fail.
805         *
806         * @param futures
807         *              the futures to combine
808         * @param <F>
809         *              the common return type of the futures
810         *
811         * @return a future which succeeds if one of the supplied futures succeeds
812         */
813        @SafeVarargs
814        public static <F> CommandFuture<F> ofAny(CommandFuture<F>... futures) {
815                return ofAny(Arrays.asList(futures));
816        }
817
818        /**
819         * Combines a collection of {@code CommandFuture}s into a single future, which will
820         * succeed as soon as one of the futures succeeds and fail if all futures fail.
821         *
822         * @param futures
823         *              the futures to combine
824         * @param <F>
825         *              the common return type of the futures
826         *
827         * @return a future which succeeds if one of the supplied futures succeeds
828         */
829        public static <F> CommandFuture<F> ofAny(final Collection<CommandFuture<F>> futures) {
830                if (futures.isEmpty()) throw new IllegalArgumentException("Requires at least 1 future");
831
832                final CommandFuture<F> any = new CommandFuture<>();
833                final AtomicInteger failureCounter = new AtomicInteger(futures.size());
834
835                for (CommandFuture<F> future : futures) {
836                        future.forwardSuccess(any).onFailure(exception -> {
837                                if (failureCounter.decrementAndGet() == 0) {
838                                        any.fail(exception);
839                                }
840                        });
841                }
842
843                return any;
844        }
845
846        /**
847         * A listener which will be notified if the {@link CommandFuture} succeeded.
848         * In that case, {@link #handleSuccess(Object)} will be called with the value
849         * the future has been set to.
850         * <p>
851         * A {@code CommandFuture}'s {@code SuccessListener} can be set by calling
852         * {@link #onSuccess(SuccessListener)}.
853         * </p>
854         *
855         * @param <V>
856         *              the type of the value
857         */
858        @FunctionalInterface
859        public interface SuccessListener<V> {
860
861                /**
862                 * The method to be executed when the command succeeds.
863                 *
864                 * @param result
865                 *              the result of the command
866                 */
867                void handleSuccess(V result);
868        }
869
870        /**
871         * A listener which will be notified if the {@link CommandFuture} failed.
872         * In that case, {@link #handleFailure(TS3Exception)} will be called with
873         * the exception that occurred while executing this command.
874         * <p>
875         * A {@code CommandFuture}'s {@code FailureListener} can be set by calling
876         * {@link #onFailure(FailureListener)}.
877         * </p>
878         */
879        @FunctionalInterface
880        public interface FailureListener {
881
882                /**
883                 * The method to be executed when the command failed.
884                 *
885                 * @param exception
886                 *              the exception that occurred while executing this command
887                 */
888                void handleFailure(TS3Exception exception);
889        }
890}