/*
* Copyright (C) 2015 SoftIndex LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.datakernel.async;
import io.datakernel.util.Function;
import java.util.Iterator;
/**
* This class contains static utility methods that operate on or return objects
* of type AsyncIterators. Except as noted, each method has a corresponding
* Iterable-based method.
*/
@SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
public final class AsyncIterators {
private AsyncIterators() {}
/**
* Returns the AsyncIterator which in first calling returns value, and after that after calling
* next() calls end() from callback
*
* @param value single value for returning
* @param <T> type of value
*/
public static <T> AsyncIterator<T> asyncIteratorOfValue(final T value) {
return new AsyncIterator<T>() {
boolean hasNext = true;
@Override
public void next(IteratorCallback<T> callback) {
if (hasNext) {
hasNext = false;
callback.setNext(value);
} else {
callback.setEnd();
}
}
};
}
/**
* Returns the AsyncIterable which has only one AsyncIterator which has only one value
*
* @param value single value for returning
* @param <T> type of value
*/
public static <T> AsyncIterable<T> asyncIterableOfValue(final T value) {
return new AsyncIterable<T>() {
@Override
public AsyncIterator<T> asyncIterator() {
return asyncIteratorOfValue(value);
}
};
}
/**
* Returns the AsyncIterator which iterates result of calling method get() from callable
*
* @param callable callable for iterate
* @param <T> type of result
*/
public static <T> AsyncIterator<T> asyncIteratorOfCallable(final AsyncCallable<T> callable) {
return new AsyncIterator<T>() {
boolean hasNext = true;
@Override
public void next(final IteratorCallback<T> callback) {
if (hasNext) {
hasNext = false;
callable.call(new ResultCallback<T>() {
@Override
protected void onResult(T result) {
callback.setNext(result);
}
@Override
protected void onException(Exception exception) {
callback.setException(exception);
}
});
} else {
callback.setEnd();
}
}
};
}
/**
* Returns the AsyncIterable with iterator asyncIteratorOfCallable
*
* @param callable callable for iterate
* @param <T> type of result
*/
public static <T> AsyncIterable<T> asyncIterableOfCallable(final AsyncCallable<T> callable) {
return new AsyncIterable<T>() {
@Override
public AsyncIterator<T> asyncIterator() {
return asyncIteratorOfCallable(callable);
}
};
}
/**
* Returns the AsyncIterator which can iterate other non-asynchronous iterator
*
* @param iterator iterator for iterating
* @param <T> type of elements in iterator
*/
public static <T> AsyncIterator<T> asyncIteratorOfIterator(final Iterator<T> iterator) {
return new AsyncIterator<T>() {
@Override
public void next(IteratorCallback<T> callback) {
if (iterator.hasNext())
callback.setNext(iterator.next());
else
callback.setEnd();
}
};
}
/**
* Returns the AsyncIterable from other non-asynchronous iterable
*
* @param iterable iterable for wrapping
* @param <T> type of elements in iterator
*/
public static <T> AsyncIterable<T> asyncIterableOfIterable(final Iterable<T> iterable) {
return new AsyncIterable<T>() {
@Override
public AsyncIterator<T> asyncIterator() {
return asyncIteratorOfIterator(iterable.iterator());
}
};
}
/**
* Creates the AsyncIterable with AsyncIterator from argument
*
* @param asyncIterator AsyncIterator for new AsyncIterable
* @param <T> type of elements in iterator
*/
public static <T> AsyncIterable<T> asyncIterableOfAsyncIterator(final AsyncIterator<T> asyncIterator) {
return new AsyncIterable<T>() {
@Override
public AsyncIterator<T> asyncIterator() {
return asyncIterator;
}
};
}
/**
* Creates the AsyncIterable with other non-asynchronous iterator
*
* @param iterator other non-asynchronous iterator for new iterable
* @param <T> type of elements in iterator
*/
public static <T> AsyncIterable<T> asyncIterableOfIterator(final Iterator<T> iterator) {
return new AsyncIterable<T>() {
@Override
public AsyncIterator<T> asyncIterator() {
return asyncIteratorOfIterator(iterator);
}
};
}
/**
* Creates the AsyncIterator from non-asynchronous iterator of asyncCallables
*
* @param asyncCallables non-asynchronous iterator of asyncCallables
* @param <T> type of result of callable
*/
public static <T> AsyncIterator<T> asyncIteratorOfCallables(final Iterator<AsyncCallable<T>> asyncCallables) {
return new AsyncIterator<T>() {
@Override
public void next(final IteratorCallback<T> callback) {
if (asyncCallables.hasNext()) {
AsyncCallable<T> asyncCallable = asyncCallables.next();
asyncCallable.call(new ResultCallback<T>() {
@Override
protected void onResult(T result) {
callback.setNext(result);
}
@Override
protected void onException(Exception exception) {
callback.setException(exception);
}
});
} else {
callback.setEnd();
}
}
};
}
/**
* Creates the AsyncIterable from non-asynchronous iterable of asyncCallables
*
* @param callables non-asynchronous iterable of asyncCallables
* @param <T> type of result of callable
*/
public static <T> AsyncIterable<T> asyncIterableOfCallables(final Iterable<AsyncCallable<T>> callables) {
return new AsyncIterable<T>() {
@Override
public AsyncIterator<T> asyncIterator() {
return asyncIteratorOfCallables(callables.iterator());
}
};
}
/**
* Creates a new AsyncIterator which is combining of asyncIterators from iterator from argument
*
* @param asyncIterators asyncIterators for combining
* @param <T> type of elements in iterator
*/
public static <T> AsyncIterator<T> concat(final Iterator<AsyncIterator<T>> asyncIterators) {
return new AsyncIterator<T>() {
@Override
public void next(final IteratorCallback<T> callback) {
if (asyncIterators.hasNext()) {
final AsyncIterator<T> asyncIterator = asyncIterators.next();
asyncIterator.next(new IteratorCallback<T>() {
@Override
protected void onNext(T result) {
callback.setNext(result);
asyncIterator.next(this);
}
@Override
protected void onEnd() {
next(callback);
}
@Override
protected void onException(Exception e) {
callback.setException(e);
}
});
} else {
callback.setEnd();
}
}
};
}
/**
* Creates a new AsyncIterator which is combining of asyncIterators from iterable from argument
*
* @param asyncIterators asyncIterators for combining
* @param <T> type of elements in iterator
*/
public static <T> AsyncIterator<T> concat(final Iterable<AsyncIterator<T>> asyncIterators) {
return concat(asyncIterators.iterator());
}
/**
* Creates a new AsyncIterator which applying function from argument to asyncIterator and calls
* callback with result of this function
*
* @param asyncIterator iterator with initial values
* @param function non-asynchronous function for transforming
* @param <F> type of elements in asyncIterator, and type to input from function
* @param <T> type for output function
*/
public static <F, T> AsyncIterator<T> transform(final AsyncIterator<F> asyncIterator, final Function<F, T> function) {
return new AsyncIterator<T>() {
@Override
public void next(final IteratorCallback<T> callback) {
asyncIterator.next(new IteratorCallback<F>() {
@Override
protected void onNext(F from) {
T to = function.apply(from);
callback.setNext(to);
}
@Override
protected void onEnd() {
callback.setEnd();
}
@Override
protected void onException(Exception e) {
callback.setException(e);
}
});
}
};
}
/**
* Creates a new AsyncIterable which is applying function from argument to asyncIterable and calls
* callback with result of this function
*
* @param asyncIterable iterable with initial values
* @param function non-asynchronous function for transforming
* @param <F> type of elements in asyncIterable, and type to input from function
* @param <T> type for output function
*/
public static <F, T> AsyncIterable<T> transform(final AsyncIterable<F> asyncIterable, final Function<F, T> function) {
return new AsyncIterable<T>() {
@Override
public AsyncIterator<T> asyncIterator() {
return transform(asyncIterable.asyncIterator(), function);
}
};
}
/**
* Creates a new AsyncIterator which is applying AsyncFunction from argument to asyncIterator and calls
* callback with result of this function
*
* @param asyncIterator iterator with initial values
* @param asyncFunction asynchronous function for transforming
* @param <F> type of elements in asyncIterator, and type to input from function
* @param <T> type for output function
*/
public static <F, T> AsyncIterator<T> transform(final AsyncIterator<F> asyncIterator, final AsyncFunction<F, T> asyncFunction) {
return new AsyncIterator<T>() {
@Override
public void next(final IteratorCallback<T> callback) {
asyncIterator.next(new IteratorCallback<F>() {
@Override
protected void onNext(F from) {
asyncFunction.apply(from, new ResultCallback<T>() {
@Override
protected void onResult(T to) {
callback.setNext(to);
}
@Override
protected void onException(Exception exception) {
callback.setException(exception);
}
});
}
@Override
protected void onEnd() {
callback.setEnd();
}
@Override
protected void onException(Exception e) {
callback.setException(e);
}
});
}
};
}
public static <F, T> AsyncIterator<T> transform(final Iterator<F> iterator, final AsyncFunction<F, T> asyncFunction) {
return new AsyncIterator<T>() {
@Override
public void next(final IteratorCallback<T> callback) {
if (iterator.hasNext()) {
F from = iterator.next();
asyncFunction.apply(from, new ResultCallback<T>() {
@Override
protected void onResult(T to) {
callback.setNext(to);
}
@Override
protected void onException(Exception exception) {
callback.setException(exception);
}
});
} else
callback.setEnd();
}
};
}
/**
* Creates a new AsyncIterable which is applying AsyncFunction from argument to asyncIterable and calls
* callback with result of this function
*
* @param asyncIterable iterable with initial values
* @param asyncFunction asynchronous function for transforming
* @param <F> type of elements in asyncIterator, and type to input from function
* @param <T> type for output function
*/
public static <F, T> AsyncIterable<T> transform(final AsyncIterable<F> asyncIterable, final AsyncFunction<F, T> asyncFunction) {
return new AsyncIterable<T>() {
@Override
public AsyncIterator<T> asyncIterator() {
return transform(asyncIterable.asyncIterator(), asyncFunction);
}
};
}
}