Mercury-IM/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/repository/IRosterRepository.java

264 lines
9.4 KiB
Java

package org.mercury_im.messenger.persistence.room.repository;
import android.util.Log;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.repository.RosterRepository;
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
import org.mercury_im.messenger.persistence.room.dao.EntityDao;
import org.mercury_im.messenger.persistence.room.dao.RosterInformationDao;
import org.mercury_im.messenger.persistence.room.model.RoomContactModel;
import org.mercury_im.messenger.persistence.room.model.RoomEntityModel;
import org.mercury_im.messenger.persistence.room.model.RoomRosterInformationModel;
import java.util.List;
import javax.inject.Inject;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Single;
import static org.mercury_im.messenger.persistence.room.AppDatabase.TAG;
public class IRosterRepository extends RosterRepository<RoomEntityModel, RoomContactModel, RoomRosterInformationModel> {
private final EntityDao entityDao;
@Override
public Observable<RoomContactModel> getContact(long accountId, EntityBareJid jid) {
return contactDao.getContactByJid(accountId, jid);
}
private final ContactDao contactDao;
private final RosterInformationDao rosterInformationDao;
@Inject
public IRosterRepository(EntityDao entityDao, ContactDao contactDao, RosterInformationDao rosterInformationDao) {
this.contactDao = contactDao;
this.entityDao = entityDao;
this.rosterInformationDao = rosterInformationDao;
}
/*
RoomContactModel
*/
@Override
public RoomContactModel newContactModel() {
return new RoomContactModel();
}
@Override
public Observable<List<RoomContactModel>> getAllContacts() {
return contactDao.getAllContacts()
.flatMap(list -> {
for (RoomContactModel contact : list) {
RoomEntityModel entity = getEntityForContact(contact).blockingGet();
contact.setEntity(entity);
}
return Observable.just(list);
});
}
@Override
public Observable<List<RoomContactModel>> getAllContactsOfAccount(long accountId) {
return contactDao.getContactsForAccount(accountId)
.flatMap(list -> {
for (RoomContactModel contact : list) {
RoomEntityModel entity = getEntityForContact(contact).blockingGet();
contact.setEntity(entity);
}
return Observable.just(list);
});
}
@Override
public Single<Long> upsertContact(RoomContactModel contact) {
return Single.fromCallable(() -> {
RoomEntityModel existingEntityModel = entityDao
.getEntityFor(contact.getEntity().getAccountId(), contact.getEntity().getJid())
.blockingGet();
if (existingEntityModel == null) {
// Insert missing entity
existingEntityModel = (RoomEntityModel) contact.getEntity();
long entityId = insertEntity(existingEntityModel).blockingGet();
existingEntityModel.setId(entityId);
contact.setEntity(existingEntityModel);
} else {
contact.getEntity().setId(existingEntityModel.getId());
contact.setEntityId(existingEntityModel.getId());
entityDao.update((RoomEntityModel) contact.getEntity())
.doOnSubscribe(ignore -> Log.v(TAG, "Updating entity " + contact.getEntity()))
.blockingAwait();
}
RoomContactModel existingContactModel = contactDao.getContactForEntityId(existingEntityModel.getId()).blockingGet();
if (existingContactModel == null) {
// Insert missing contact
existingContactModel = contact;
return insertContact(existingContactModel).blockingGet();
} else {
contact.setId(existingContactModel.getId());
contactDao.update(contact)
.doOnSubscribe(ignore -> Log.v(TAG, "Updating contact " + contact))
.doOnComplete(() -> Log.v(TAG, "Update complete"))
.blockingAwait();
}
return existingContactModel.getId();
});
}
@Override
public Single<Long> insertContact(RoomContactModel contact) {
return contactDao.insert(contact)
.map(contactId -> {
contact.setId(contactId);
return contactId;
})
.doOnSubscribe(ignore -> Log.v(TAG, "Insert " + contact))
.doAfterSuccess(cid -> Log.v(TAG, "Assigned ID " + cid + " to " + contact));
}
@Override
public Single<RoomEntityModel> getEntityForContact(long contactId) {
Single<RoomEntityModel> s = contactDao.getEntityForContactId(contactId);
return s;
}
@Override
public Observable<RoomContactModel> getContact(long contactId) {
return contactDao.getContact(contactId)
.map(contact -> {
contact.setEntity(getEntityForContact(contactId).toMaybe().blockingGet());
contact.setEntityId(contact.getEntity().getId());
return contact;
});
}
@Override
public Maybe<RoomContactModel> maybeGetContact(long id) {
return contactDao.maybeGetContact(id)
// Set the entity
.zipWith(getEntityForContact(id).toMaybe(),
(contact, entity) -> {
contact.setEntity(entity);
contact.setEntityId(entity.getId());
return contact;
});
}
@Override
public Single<RoomEntityModel> getOrCreateEntityForAccountAndJid(long accountId, EntityBareJid jid) {
return Single.fromCallable(() -> {
RoomEntityModel existing = getEntityForAccountAndJid(accountId, jid).blockingGet();
if (existing == null) {
existing = newEntityModel();
existing.setAccountId(accountId);
existing.setJid(jid);
existing.setId(insertEntity(existing).blockingGet());
}
return existing;
});
}
@Override
public Maybe<RoomContactModel> getContactForEntity(long entityId) {
return contactDao.getContactForEntityId(entityId)
// Set the entity
.zipWith(getEntity(entityId),
(contact, entity) -> {
contact.setEntity(entity);
contact.setEntityId(entityId);
return contact;
});
}
@Override
public Completable deleteContact(long id) {
return contactDao.deleteContact(id);
}
@Override
public Completable deleteContact(RoomContactModel contact) {
return contactDao.delete(contact);
}
@Override
public Completable deleteContact(long accountId, EntityBareJid jid) {
// Since Room does not support "DELETE x FROM X x INNER JOIN Y...", we have to get the
// entity for the jid first and then delete by using its entityId
final Maybe<RoomEntityModel> entity = getEntityForAccountAndJid(accountId, jid.asEntityBareJidOrThrow());
return entity.flatMapCompletable(entityModel -> contactDao.deleteContactForEntity(entityModel.getId()));
}
@Override
public Completable deleteAllContacts() {
return contactDao.deleteAll();
}
@Override
public Completable deleteAllContactsOfAccount(long accountId) {
return contactDao.deleteAllForAccount(accountId);
}
@Override
public Completable deleteContacts(long[] ids) {
return contactDao.deleteContacts(ids);
}
/*
RoomRosterInformationModel
*/
@Override
public RoomRosterInformationModel newRosterInformationModel() {
return new RoomRosterInformationModel();
}
@Override
public Observable<RoomRosterInformationModel> getRosterInformationForAccount(long accountId) {
return rosterInformationDao.getRosterInformation(accountId);
}
@Override
public Single<Long> updateRosterInformation(RoomRosterInformationModel rosterInformation) {
return rosterInformationDao.insertRosterInformation(rosterInformation)
.doOnSubscribe(ignore -> Log.v(TAG, "Insert " + rosterInformation));
}
/*
RoomEntityModel
*/
@Override
public RoomEntityModel newEntityModel() {
return new RoomEntityModel();
}
@Override
public Maybe<RoomEntityModel> getEntity(long id) {
return entityDao.getEntity(id);
}
@Override
public Maybe<RoomEntityModel> getEntityForAccountAndJid(long accountId, EntityBareJid jid) {
return entityDao.getEntityFor(accountId, jid);
}
public Single<Long> insertEntity(RoomEntityModel entityModel) {
return entityDao.insert(entityModel)
.map(entityId -> {
entityModel.setId(entityId);
return entityId;
})
.doOnSubscribe(ignore -> Log.v(TAG, "Insert " + entityModel))
.doAfterSuccess(entityId -> Log.v(TAG, "Assign ID " + entityId + " to " + entityModel));
}
}