package org.mercury_im.messenger.data.repository; import org.mercury_im.messenger.data.mapping.DirectChatMapping; import org.mercury_im.messenger.data.model.DirectChatModel; import org.mercury_im.messenger.data.repository.dao.DirectChatDao; import org.mercury_im.messenger.util.Optional; import org.mercury_im.messenger.entity.chat.DirectChat; import org.mercury_im.messenger.entity.chat.IDirectChat; import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.util.ThreadUtils; import java.util.ArrayList; import java.util.List; import java.util.UUID; 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; import io.requery.reactivex.ReactiveResult; public class XmppDirectChatRepository extends RequeryRepository implements DirectChatRepository { private final DirectChatMapping directChatMapping; private final DirectChatDao dao; @Inject public XmppDirectChatRepository( ReactiveEntityStore data, @Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler, @Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler, DirectChatMapping directChatMapping) { super(data, subscriberScheduler, observerScheduler); this.directChatMapping = directChatMapping; this.dao = new DirectChatDao(data); } @Override public Single insertDirectChat(DirectChat chat) { return Single.just(chat) // map entity to model .map(directChatMapping::toModel) .flatMap(dao::insert) // map back to entity .map(model -> directChatMapping.toEntity(model, chat)) .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } @Override public Observable> observeDirectChat(UUID chatId) { return dao.get(chatId).observableResult() .map(result -> new Optional<>(result.firstOrNull())) .map(directChatMapping::toEntity) .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } @Override public Maybe getDirectChat(UUID chatId) { return dao.get(chatId).maybe() .map(directChatMapping::toEntity) .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } @Override public Single getOrCreateChatWithPeer(Peer peer) { return getDirectChatByPeer(peer) .switchIfEmpty(Single.just(new IDirectChat()) .map(chat -> { chat.setAccount(peer.getAccount()); chat.setPeer(peer); return chat; }) .flatMap(this::insertDirectChat)) .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } @Override public Observable> observeDirectChatByPeer(Peer peer) { return dao.getByPeer(peer.getId()).observableResult() .map(result -> new Optional<>(result.firstOrNull())) .map(directChatMapping::toEntity) .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } @Override public Maybe getDirectChatByPeer(Peer peer) { return dao.getByPeer(peer.getId()).maybe() .map(directChatMapping::toEntity) .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } @Override public Observable> observeAllDirectChats() { return dao.getAll().observableResult() .map(ResultDelegate::toList) .map(this::chatModelsToEntities) .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } private List chatModelsToEntities(List models) { List entities = new ArrayList<>(models.size()); for (DirectChatModel model : models) { entities.add(directChatMapping.toEntity(model)); } return entities; } @Override public Single updateDirectChat(DirectChat chat) { return dao.get(chat.getId()).maybe().toSingle() .map(model -> directChatMapping.toModel(chat, model)) .flatMap(data()::update) .map(model -> directChatMapping.toEntity(model, chat)) .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } @Override public Single upsertDirectChat(DirectChat chat) { return dao.get(chat.getId()).maybe() .switchIfEmpty(dao.insert(directChatMapping.toModel(chat))) .map(directChatModel -> directChatMapping.toModel(chat, directChatModel)) .flatMap(data()::update) .map(model -> directChatMapping.toEntity(model, chat)) .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } @Override public Completable deleteDirectChat(UUID chatId) { return dao.delete(chatId) .ignoreElement() .subscribeOn(subscriberScheduler()) .observeOn(observerScheduler()); } }