/*
* Copyright 2017 requery.io
*
* 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.requery.reactivex;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.requery.BlockingEntityStore;
import io.requery.meta.Attribute;
import io.requery.meta.QueryAttribute;
import io.requery.query.Deletion;
import io.requery.query.Expression;
import io.requery.query.InsertInto;
import io.requery.query.Insertion;
import io.requery.query.Result;
import io.requery.query.Return;
import io.requery.query.Scalar;
import io.requery.query.Selection;
import io.requery.query.Tuple;
import io.requery.query.Update;
import io.requery.query.element.QueryElement;
import io.requery.util.Objects;
import io.requery.util.function.Function;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
/**
* Implementation of {@link ReactiveEntityStore} where all operations are passed through a
* {@link BlockingEntityStore} instance. All observables are 'cold' and must be subscribed to
* invoke the operation.
*
* @param <T> base type of all entities
*
* @author Nikhil Purushe
*/
@ParametersAreNonnullByDefault
class WrappedEntityStore<T> extends ReactiveEntityStore<T> {
private final BlockingEntityStore<T> delegate;
WrappedEntityStore(BlockingEntityStore<T> delegate) {
this.delegate = Objects.requireNotNull(delegate);
}
@Override
public <E extends T> Single<E> insert(final E entity) {
return Single.fromCallable(new Callable<E>() {
@Override
public E call() throws Exception {
return delegate.insert(entity);
}
});
}
@Override
public <E extends T> Single<Iterable<E>> insert(final Iterable<E> entities) {
return Single.fromCallable(new Callable<Iterable<E>>() {
@Override
public Iterable<E> call() throws Exception {
return delegate.insert(entities);
}
});
}
@Override
public <K, E extends T> Single<K> insert(final E entity, final Class<K> keyClass) {
return Single.fromCallable(new Callable<K>() {
@Override
public K call() throws Exception {
return delegate.insert(entity, keyClass);
}
});
}
@Override
public <K, E extends T> Single<Iterable<K>> insert(final Iterable<E> entities,
final Class<K> keyClass) {
return Single.fromCallable(new Callable<Iterable<K>>() {
@Override
public Iterable<K> call() throws Exception {
return delegate.insert(entities, keyClass);
}
});
}
@Override
public <E extends T> Single<E> update(final E entity) {
return Single.fromCallable(new Callable<E>() {
@Override
public E call() throws Exception {
return delegate.update(entity);
}
});
}
@Override
public <E extends T> Single<E> update(final E entity, final Attribute<?, ?>... attributes) {
return Single.fromCallable(new Callable<E>() {
@Override
public E call() throws Exception {
return delegate.update(entity, attributes);
}
});
}
@Override
public <E extends T> Single<Iterable<E>> update(final Iterable<E> entities) {
return Single.fromCallable(new Callable<Iterable<E>>() {
@Override
public Iterable<E> call() throws Exception {
return delegate.update(entities);
}
});
}
@Override
public <E extends T> Single<E> upsert(final E entity) {
return Single.fromCallable(new Callable<E>() {
@Override
public E call() throws Exception {
return delegate.upsert(entity);
}
});
}
@Override
public <E extends T> Single<Iterable<E>> upsert(final Iterable<E> entities) {
return Single.fromCallable(new Callable<Iterable<E>>() {
@Override
public Iterable<E> call() throws Exception {
return delegate.upsert(entities);
}
});
}
@Override
public <E extends T> Single<E> refresh(final E entity) {
return Single.fromCallable(new Callable<E>() {
@Override
public E call() throws Exception {
return delegate.refresh(entity);
}
});
}
@Override
public <E extends T> Single<E> refresh(final E entity,
final Attribute<?, ?>... attributes) {
return Single.fromCallable(new Callable<E>() {
@Override
public E call() throws Exception {
return delegate.refresh(entity, attributes);
}
});
}
@Override
public <E extends T> Single<Iterable<E>> refresh(final Iterable<E> entities,
final Attribute<?, ?>... attributes) {
return Single.fromCallable(new Callable<Iterable<E>>() {
@Override
public Iterable<E> call() throws Exception {
return delegate.refresh(entities, attributes);
}
});
}
@Override
public <E extends T> Single<E> refreshAll(final E entity) {
return Single.fromCallable(new Callable<E>() {
@Override
public E call() throws Exception {
return delegate.refreshAll(entity);
}
});
}
@Override
public <E extends T> Completable delete(final E entity) {
return Completable.fromCallable(new Callable<Void>() {
@Override
public Void call() throws Exception {
delegate.delete(entity);
return null;
}
});
}
@Override
public <E extends T> Completable delete(final Iterable<E> entities) {
return Completable.fromCallable(new Callable<Void>() {
@Override
public Void call() throws Exception {
delegate.delete(entities);
return null;
}
});
}
@Override
public <E extends T, K> Maybe<E> findByKey(final Class<E> type, final K key) {
return Maybe.fromCallable(new Callable<E>() {
@Override
public E call() throws Exception {
return delegate.findByKey(type, key);
}
});
}
@Override
public void close() {
delegate.close();
}
@Override
public Selection<ReactiveResult<Tuple>> select(Expression<?>... attributes) {
return result(delegate.select(attributes));
}
@Override
public Selection<ReactiveResult<Tuple>> select(Set<? extends Expression<?>> expressions) {
return result(delegate.select(expressions));
}
@Override
public Update<ReactiveScalar<Integer>> update() {
return scalar(delegate.update());
}
@Override
public Deletion<ReactiveScalar<Integer>> delete() {
return scalar(delegate.delete());
}
@Override
public <E extends T> Selection<ReactiveResult<E>> select(
Class<E> type, QueryAttribute<?, ?>... attributes) {
return result(delegate.select(type, attributes));
}
@Override
public <E extends T> Selection<ReactiveResult<E>> select(
Class<E> type, Set<? extends QueryAttribute<E, ?>> attributes) {
return result(delegate.select(type, attributes));
}
@Override
public <E extends T> Insertion<ReactiveResult<Tuple>> insert(Class<E> type) {
return result(delegate.insert(type));
}
@Override
public <E extends T> InsertInto<ReactiveResult<Tuple>> insert(Class<E> type, QueryAttribute<?, ?>... attributes) {
return result(delegate.insert(type, attributes));
}
@Override
public <E extends T> Update<ReactiveScalar<Integer>> update(Class<E> type) {
return scalar(delegate.update(type));
}
@Override
public <E extends T> Deletion<ReactiveScalar<Integer>> delete(Class<E> type) {
return scalar(delegate.delete(type));
}
@Override
public <E extends T> Selection<ReactiveScalar<Integer>> count(Class<E> type) {
return scalar(delegate.count(type));
}
@Override
public Selection<ReactiveScalar<Integer>> count(QueryAttribute<?, ?>... attributes) {
return scalar(delegate.count(attributes));
}
@Override
public ReactiveResult<Tuple> raw(String query, Object... parameters) {
return new ReactiveResult<>(delegate.raw(query, parameters));
}
@Override
public <E extends T> ReactiveResult<E> raw(Class<E> type, String query, Object... parameters) {
return new ReactiveResult<>(delegate.raw(type, query, parameters));
}
@Override
public BlockingEntityStore<T> toBlocking() {
return delegate;
}
@Override
public final <E> Observable<E> runInTransaction(final List<Single<? extends E>> elements) {
Objects.requireNotNull(elements);
Observable<E> startTransaction = Completable.fromCallable(new Callable<Object>() {
@Override
public Object call() throws Exception {
if (!delegate.transaction().active()) {
delegate.transaction().begin();
}
return delegate;
}
}).toObservable();
Observable<E> commitTransaction = Completable.fromCallable(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
delegate.transaction().commit();
} finally {
delegate.transaction().close();
}
return delegate;
}
}).toObservable();
Observable<E> current = startTransaction;
for (Single<? extends E> single : elements) {
current = current.concatWith(single.toObservable());
}
return current.concatWith(commitTransaction);
}
private static <E> QueryElement<ReactiveResult<E>> result(Return<? extends Result<E>> query) {
@SuppressWarnings("unchecked")
QueryElement<Result<E>> element = (QueryElement<Result<E>>) query;
return element.extend(new Function<Result<E>, ReactiveResult<E>>() {
@Override
public ReactiveResult<E> apply(Result<E> result) {
return new ReactiveResult<>(result);
}
});
}
private static <E> QueryElement<ReactiveScalar<E>> scalar(Return<? extends Scalar<E>> query) {
@SuppressWarnings("unchecked")
QueryElement<Scalar<E>> element = (QueryElement<Scalar<E>>) query;
return element.extend(new Function<Scalar<E>, ReactiveScalar<E>>() {
@Override
public ReactiveScalar<E> apply(Scalar<E> result) {
return new ReactiveScalar<>(result);
}
});
}
}