Mercury-IM/data/src/main/java/org/mercury_im/messenger/data/repository/XmppAccountRepository.java

150 lines
6.0 KiB
Java

package org.mercury_im.messenger.data.repository;
import org.mercury_im.messenger.data.model.AccountModel;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.data.util.Optional;
import org.mercury_im.messenger.entity.IAccount;
import org.mercury_im.messenger.util.ThreadUtils;
import org.mercury_im.messenger.data.mapping.AccountMapping;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.Single;
import io.requery.Persistable;
import io.requery.query.ResultDelegate;
import io.requery.reactivex.ReactiveEntityStore;
public class XmppAccountRepository
extends RequeryRepository
implements AccountRepository {
@Inject
AccountMapping accountMapping;
@Inject
public XmppAccountRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(data, subscriberScheduler, observerScheduler);
}
@Override
public Single<Account> insertAccount(Account account) {
return data().insert(accountMapping.entityToModel(account, new AccountModel()))
.map(model -> accountMapping.modelToEntity(model, account))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Observable<Optional<Account>> observeAccount(long accountId) {
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(accountId))
.get().observableResult()
.map(result -> new Optional<>(accountMapping.modelToEntity(result.firstOrNull(), new IAccount())))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Maybe<Account> getAccount(long accountId) {
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(accountId))
.get().maybe()
.map(model -> accountMapping.modelToEntity(model, new IAccount()))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Observable<Optional<Account>> observeAccountByAddress(String address) {
return data().select(AccountModel.class)
.where(AccountModel.ADDRESS.eq(address))
.get().observableResult()
.map(result -> new Optional<>(accountMapping.modelToEntity(result.firstOrNull(), new IAccount())))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Maybe<Account> getAccountByAddress(String address) {
return data().select(AccountModel.class)
.where(AccountModel.ADDRESS.eq(address))
.get().maybe()
.map(model -> accountMapping.modelToEntity(model, new IAccount()))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Observable<List<Account>> observeAllAccounts() {
return data().select(AccountModel.class)
.get().observableResult()
.map(ResultDelegate::toList)
.map(list -> {
List<Account> entities = new ArrayList<>(list.size());
for (AccountModel model : list) {
entities.add(accountMapping.modelToEntity(model, new IAccount()));
}
return entities;
})
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Single<Account> updateAccount(Account account) {
// Since we cannot access setId() of AccountModel, we have to query the model by ID and update it manually.
// https://github.com/requery/requery/issues/616#issuecomment-315685460
// fetch model
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(account.getId()))
.get().maybe().toSingle() // to single
.flatMap(model -> {
// copy changes from the entity to the model
model = accountMapping.entityToModel(account, model);
// write the updated model back
return data().update(model);
}).map(model -> accountMapping.modelToEntity(model, account))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Single<Account> upsertAccount(Account account) {
// Try to fetch model
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(account.getId()))
.get().maybe()
// If it does not exist, create a new model from the entity
.switchIfEmpty(data().insert(accountMapping.entityToModel(account, new AccountModel())))
.flatMap(model -> {
// update the model
model = accountMapping.entityToModel(account, model);
// write the updated model back
return data().update(model);
})
.map(model -> accountMapping.modelToEntity(model, account))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Completable deleteAccount(Account account) {
return data().delete(AccountModel.class)
.where(AccountModel.ID.eq(account.getId()))
.get().single().ignoreElement() // to completable
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
}