Rework Roster storage
This commit is contained in:
parent
83aa428a66
commit
e661ffdf65
|
@ -7,6 +7,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.mercury_im.messenger.core.ConnectionCenter;
|
||||
import org.mercury_im.messenger.di.component.AppComponent;
|
||||
import org.mercury_im.messenger.di.component.DaggerAppComponent;
|
||||
|
@ -33,6 +34,7 @@ public class MercuryImApplication extends Application {
|
|||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
SmackConfiguration.DEBUG = true;
|
||||
super.onCreate();
|
||||
|
||||
INSTANCE = this;
|
||||
|
|
|
@ -6,17 +6,15 @@ import androidx.annotation.NonNull;
|
|||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.LiveData;
|
||||
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactModel;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IContactAttributesRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IContactRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IRosterRepository;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class RosterItemViewModel extends AndroidViewModel {
|
||||
|
||||
@Inject
|
||||
IContactRepository contactRepository;
|
||||
IRosterRepository contactRepository;
|
||||
|
||||
private LiveData<RoomContactModel> contact;
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ public class RosterRecyclerViewAdapter
|
|||
}
|
||||
|
||||
void bind(RoomContactModel contactModel) {
|
||||
String nick = contactModel.getContact().getNickname();
|
||||
String nick = contactModel.getNickname();
|
||||
nicknameView.setText(nick != null ? nick : "");
|
||||
EntityBareJid jid = contactModel.getEntity().getJid();
|
||||
jidView.setText(jid.toString());
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
package org.mercury_im.messenger.ui.roster;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import org.mercury_im.messenger.MercuryImApplication;
|
||||
import org.mercury_im.messenger.persistence.repository.ContactRepository;
|
||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactModel;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IContactRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -15,12 +17,13 @@ import javax.inject.Inject;
|
|||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class RosterViewModel extends ViewModel {
|
||||
|
||||
@Inject
|
||||
ContactRepository contactRepository;
|
||||
RosterRepository rosterRepository;
|
||||
|
||||
private final MutableLiveData<List<RoomContactModel>> rosterEntryList = new MutableLiveData<>();
|
||||
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
@ -28,12 +31,15 @@ public class RosterViewModel extends ViewModel {
|
|||
public RosterViewModel() {
|
||||
super();
|
||||
MercuryImApplication.getApplication().getAppComponent().inject(this);
|
||||
|
||||
Log.d("RosterViewModel", "Start observing database");
|
||||
// Subscribe to changes to the contacts table and update the LiveData object for the UI.
|
||||
compositeDisposable.add(contactRepository.getAllContacts()
|
||||
compositeDisposable.add(rosterRepository.getAllContacts()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(o -> rosterEntryList.setValue((List<RoomContactModel>) o)));
|
||||
.subscribe((Consumer<List<? extends ContactModel>>) o -> {
|
||||
Log.d("RosterViewModel", "Room changed contacts: " + o.size());
|
||||
rosterEntryList.setValue((List<RoomContactModel>) o);
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
|||
import org.jivesoftware.smackx.caps.EntityCapsManager;
|
||||
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -32,6 +33,7 @@ public class ConnectionCenter {
|
|||
// Injected
|
||||
private final AccountRepository accountRepository;
|
||||
private final EntityCapsStore entityCapsStore;
|
||||
private final RosterRepository rosterRepository;
|
||||
|
||||
// Connections
|
||||
private final Map<Long, MercuryConnection> connectionMap =
|
||||
|
@ -43,10 +45,11 @@ public class ConnectionCenter {
|
|||
private final AtomicBoolean started = new AtomicBoolean(false);
|
||||
|
||||
@Inject
|
||||
public ConnectionCenter(EntityCapsStore capsStore, AccountRepository accountRepository) {
|
||||
public ConnectionCenter(EntityCapsStore capsStore, AccountRepository accountRepository, RosterRepository rosterRepository) {
|
||||
LOGGER.log(Level.INFO, "ConnectionCenter initialized");
|
||||
this.accountRepository = accountRepository;
|
||||
this.entityCapsStore = capsStore;
|
||||
this.rosterRepository = rosterRepository;
|
||||
|
||||
EntityCapsManager.setPersistentCache(capsStore);
|
||||
startUp();
|
||||
|
@ -66,35 +69,42 @@ public class ConnectionCenter {
|
|||
}
|
||||
|
||||
// otherwise subscribe to accounts and create connections.
|
||||
disposable.add(accountRepository.getAllAccounts()
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.subscribe((Consumer<List<? extends AccountModel>>) accounts -> {
|
||||
Set<Long> accountIds = new HashSet<>();
|
||||
// Add missing connections to the map
|
||||
for (AccountModel account : accounts) {
|
||||
accountIds.add(account.getId());
|
||||
if (connectionMap.get(account.getId()) != null) {
|
||||
continue;
|
||||
}
|
||||
MercuryConnection connection = createConnection(account);
|
||||
connectionMap.put(account.getId(), connection);
|
||||
disposable.add(
|
||||
accountRepository.getAllAccounts()
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.subscribe((Consumer<List<? extends AccountModel>>) accounts -> {
|
||||
LOGGER.log(Level.INFO, "Accounts changed.");
|
||||
Set<Long> accountIds = new HashSet<>();
|
||||
// Add missing connections to the map
|
||||
for (AccountModel account : accounts) {
|
||||
accountIds.add(account.getId());
|
||||
if (connectionMap.get(account.getId()) != null) {
|
||||
continue;
|
||||
}
|
||||
LOGGER.log(Level.INFO, "Add new connection " + account.getJid().toString() + " to ConnectionCenter list.");
|
||||
MercuryConnection connection = createConnection(account);
|
||||
connectionMap.put(account.getId(), connection);
|
||||
RosterStore rosterStore = new RosterStore(rosterRepository);
|
||||
rosterStore.setAccountId(account.getId());
|
||||
rosterStore.subscribe();
|
||||
connection.getRoster().setRosterStore(rosterStore);
|
||||
|
||||
if (account.getEnabled()) {
|
||||
connection.connect();
|
||||
}
|
||||
}
|
||||
if (account.getEnabled()) {
|
||||
connection.connect();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove unwanted connections from the map
|
||||
for (long connectionId : connectionMap.keySet()) {
|
||||
if (!accountIds.contains(connectionId)) {
|
||||
AbstractXMPPConnection con =
|
||||
(AbstractXMPPConnection) connectionMap.get(connectionId).getConnection();
|
||||
con.disconnect();
|
||||
connectionMap.remove(connectionId);
|
||||
}
|
||||
}
|
||||
}));
|
||||
// Remove unwanted connections from the map
|
||||
for (long connectionId : connectionMap.keySet()) {
|
||||
if (!accountIds.contains(connectionId)) {
|
||||
AbstractXMPPConnection con =
|
||||
(AbstractXMPPConnection) connectionMap.get(connectionId).getConnection();
|
||||
con.disconnect();
|
||||
connectionMap.remove(connectionId);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public MercuryConnection getConnection(AccountModel account) {
|
||||
|
@ -115,8 +125,8 @@ public class ConnectionCenter {
|
|||
.setHost(accountModel.getJid().getDomain().toString())
|
||||
.setXmppAddressAndPassword(accountModel.getJid(), accountModel.getPassword())
|
||||
.setConnectTimeout(2 * 60 * 1000)
|
||||
//.setEnabledSSLCiphers(MercuryConfiguration.enabledCiphers)
|
||||
//.setEnabledSSLProtocols(MercuryConfiguration.enabledProtocols)
|
||||
.setEnabledSSLCiphers(MercuryConfiguration.enabledCiphers)
|
||||
.setEnabledSSLProtocols(MercuryConfiguration.enabledProtocols)
|
||||
.build();
|
||||
|
||||
AbstractXMPPConnection tcpConnection = new XMPPTCPConnection(configuration);
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.mercury_im.messenger.core;
|
|||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||
import org.jivesoftware.smack.xml.SmackXmlParser;
|
||||
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||
import org.jivesoftware.smackx.caps.EntityCapsManager;
|
||||
import org.jivesoftware.smackx.caps.cache.EntityCapsPersistentCache;
|
||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.disco.provider.DiscoverInfoProvider;
|
||||
|
@ -15,8 +14,6 @@ import java.io.StringReader;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
|
|
@ -3,25 +3,21 @@ package org.mercury_im.messenger.core;
|
|||
public class MercuryConfiguration {
|
||||
|
||||
public static final String[] enabledCiphers = {
|
||||
"ECDHE-RSA-AES256-GCM-SHA384",
|
||||
"ECDHE-RSA-AES128-GCM-SHA256",
|
||||
"ECDHE-RSA-AES256-SHA384",
|
||||
"ECDHE-RSA-AES128-SHA256",
|
||||
"ECDHE-RSA-AES256-SHA",
|
||||
"ECDHE-RSA-AES128-SHA",
|
||||
"DHE-RSA-AES256-GCM-SHA384",
|
||||
"DHE-RSA-AES128-GCM-SHA256",
|
||||
"DHE-RSA-AES256-SHA256",
|
||||
"DHE-RSA-AES128-SHA256",
|
||||
"DHE-RSA-AES256-SHA",
|
||||
"DHE-RSA-CAMELLIA256-SHA",
|
||||
"DHE-RSA-AES128-SHA",
|
||||
"DHE-RSA-SEED-SHA",
|
||||
"DHE-RSA-CAMELLIA128-SHA"
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"
|
||||
};
|
||||
|
||||
public static final String[] enabledProtocols = {
|
||||
"TLSv1.1",
|
||||
"TLSv1.2",
|
||||
"TLSv1.3"
|
||||
};
|
||||
|
|
|
@ -49,6 +49,7 @@ public class MercuryConnection {
|
|||
reconnectionManager.enableAutomaticReconnection();
|
||||
|
||||
this.roster = Roster.getInstanceFor(connection);
|
||||
roster.setRosterLoadedAtLogin(true);
|
||||
this.chatManager = ChatManager.getInstanceFor(connection);
|
||||
this.carbonManager = CarbonManager.getInstanceFor(connection);
|
||||
this.stanzaIdManager = StableUniqueStanzaIdManager.getInstanceFor(connection);
|
||||
|
@ -57,7 +58,6 @@ public class MercuryConnection {
|
|||
this.serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
VersionManager.getInstanceFor(connection).setVersion("Mercury", "0.0.1-stealth", "Android");
|
||||
serviceDiscoveryManager.setIdentity(new DiscoverInfo.Identity("client", "Mercury", "phone"));
|
||||
roster.setRosterLoadedAtLogin(true);
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
|
|
|
@ -2,37 +2,77 @@ package org.mercury_im.messenger.core;
|
|||
|
||||
import org.jivesoftware.smack.roster.packet.RosterPacket;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
import org.mercury_im.messenger.persistence.repository.ContactRepository;
|
||||
import org.mercury_im.messenger.persistence.model.RosterInformationModel;
|
||||
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.reactivex.MaybeObserver;
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.Scheduler;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.RosterStore {
|
||||
|
||||
private final ContactRepository contactRepository;
|
||||
private static final Logger LOGGER = Logger.getLogger(RosterStore.class.getName());
|
||||
|
||||
private final RosterRepository rosterRepository;
|
||||
private long accountId;
|
||||
|
||||
@Inject
|
||||
public RosterStore(ContactRepository contactRepository) {
|
||||
this.contactRepository = contactRepository;
|
||||
private CompositeDisposable disposable = null;
|
||||
|
||||
contactRepository.getAllContactsOfAccount(accountId)
|
||||
private final Map<Jid, RosterPacket.Item> itemMap = new HashMap<>();
|
||||
private String rosterVersion;
|
||||
|
||||
@Inject
|
||||
public RosterStore(RosterRepository rosterRepository) {
|
||||
this.rosterRepository = rosterRepository;
|
||||
}
|
||||
|
||||
public void subscribe() {
|
||||
LOGGER.log(Level.INFO, "Subscribing...");
|
||||
if (disposable != null) {
|
||||
return;
|
||||
}
|
||||
disposable = new CompositeDisposable();
|
||||
|
||||
disposable.add(rosterRepository.getAllContactsOfAccount(accountId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
.subscribe((Consumer<List<? extends ContactModel>>) o -> {
|
||||
itemMap.clear();
|
||||
for (ContactModel c : o) {
|
||||
rosterRepository.getEntityForContact(c.getId()).subscribeOn(Schedulers.io())
|
||||
.subscribe((Consumer<EntityModel>) o1 -> itemMap.put(o1.getJid(), fromModel(c)));
|
||||
LOGGER.log(Level.INFO, "Populate itemMap with " + o.size() + " items");
|
||||
|
||||
}
|
||||
}));
|
||||
|
||||
disposable.add(rosterRepository.getRosterInformationForAccount(accountId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe((Consumer<RosterInformationModel>) s -> {
|
||||
LOGGER.log(Level.INFO, "Set rosterVer = " + s.getRosterVersion());
|
||||
rosterVersion = s.getRosterVersion();
|
||||
}));
|
||||
}
|
||||
|
||||
public void unsubscribe() {
|
||||
if (disposable == null) {
|
||||
return;
|
||||
}
|
||||
disposable.dispose();
|
||||
disposable = null;
|
||||
}
|
||||
|
||||
public void setAccountId(long accountId) {
|
||||
|
@ -41,70 +81,116 @@ public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.Ro
|
|||
|
||||
@Override
|
||||
public List<RosterPacket.Item> getEntries() {
|
||||
|
||||
return new ArrayList<>(itemMap.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RosterPacket.Item getEntry(Jid bareJid) {
|
||||
return null;
|
||||
return itemMap.get(bareJid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRosterVersion() {
|
||||
return null;
|
||||
return rosterVersion != null ? rosterVersion : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addEntry(RosterPacket.Item item, String version) {
|
||||
return false;
|
||||
LOGGER.log(Level.INFO, "Add entry " + item.toXML().toString());
|
||||
// Update database
|
||||
ContactModel contact = toModel(item);
|
||||
rosterRepository.updateOrInsertContact(contact)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
rosterRepository.updateRosterVersionForAccount(accountId, version)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resetEntries(Collection<RosterPacket.Item> items, String version) {
|
||||
return false;
|
||||
// Update database
|
||||
for (RosterPacket.Item item : items) {
|
||||
rosterRepository.updateOrInsertContact(toModel(item))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
}
|
||||
rosterRepository.updateRosterVersionForAccount(accountId, version)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeEntry(Jid bareJid, String version) {
|
||||
return false;
|
||||
rosterRepository.deleteContact(accountId, bareJid.asEntityBareJidOrThrow())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
rosterRepository.updateRosterVersionForAccount(accountId, version)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetStore() {
|
||||
|
||||
rosterRepository.deleteAllContactsOfAccount(accountId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
rosterRepository.updateRosterVersionForAccount(accountId, "")
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
public RosterPacket.Item fromModel(ContactModel contactModel) {
|
||||
RosterPacket.Item item = new RosterPacket.Item(contactModel.getEntity().getJid(), contactModel.getContact().getRosterName());
|
||||
item.setItemType(convert(contactModel.getContact().getDirection()));
|
||||
item.setApproved(contactModel.getContact().isApproved());
|
||||
item.setSubscriptionPending(contactModel.getContact().isSubscriptionPending());
|
||||
RosterPacket.Item item = new RosterPacket.Item(
|
||||
contactModel.getEntity().getJid(),
|
||||
contactModel.getRosterName());
|
||||
if (contactModel.getDirection() != null) {
|
||||
item.setItemType(convert(contactModel.getDirection()));
|
||||
}
|
||||
item.setApproved(contactModel.isApproved());
|
||||
item.setSubscriptionPending(contactModel.isSubscriptionPending());
|
||||
return item;
|
||||
}
|
||||
|
||||
public ContactModel toModel(RosterPacket.Item item) {
|
||||
ContactModel contact = contactRepository.newContactModel();
|
||||
ContactModel contact = rosterRepository.newContactModel();
|
||||
contact.setAccountId(accountId);
|
||||
|
||||
ContactAttributes attributes = contactRepository.newAttributesModel();
|
||||
ContactModel attributes = rosterRepository.newContactModel();
|
||||
attributes.setRosterName(item.getName());
|
||||
attributes.setDirection(convert(item.getItemType()));
|
||||
if (item.getItemType() != null) {
|
||||
attributes.setDirection(convert(item.getItemType()));
|
||||
}
|
||||
attributes.setApproved(item.isApproved());
|
||||
attributes.setSubscriptionPending(item.isSubscriptionPending());
|
||||
|
||||
EntityModel entity = contactRepository.newEntityModel();
|
||||
EntityModel entity = rosterRepository.newEntityModel();
|
||||
entity.setAccountId(accountId);
|
||||
entity.setJid(item.getJid().asEntityBareJidOrThrow());
|
||||
|
||||
contact.setContact(attributes);
|
||||
contact.setEntity(entity);
|
||||
|
||||
return contact;
|
||||
}
|
||||
|
||||
public ContactAttributes.DIRECTION convert(RosterPacket.ItemType type) {
|
||||
return ContactAttributes.DIRECTION.valueOf(type.toString());
|
||||
public ContactModel.DIRECTION convert(RosterPacket.ItemType type) {
|
||||
return ContactModel.DIRECTION.valueOf(type.toString());
|
||||
}
|
||||
|
||||
public RosterPacket.ItemType convert(ContactAttributes.DIRECTION direction) {
|
||||
public RosterPacket.ItemType convert(ContactModel.DIRECTION direction) {
|
||||
return RosterPacket.ItemType.fromString(direction.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package org.mercury_im.messenger.core.di;
|
|||
import org.mercury_im.messenger.core.ConnectionCenter;
|
||||
import org.mercury_im.messenger.core.EntityCapsStore;
|
||||
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.EntityCapsRepository;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
|
@ -16,8 +16,8 @@ public class CenterModule {
|
|||
|
||||
@Singleton
|
||||
@Provides
|
||||
static ConnectionCenter provideConnectionCenter(EntityCapsStore capsStore, AccountRepository accountRepository) {
|
||||
return new ConnectionCenter(capsStore, accountRepository);
|
||||
static ConnectionCenter provideConnectionCenter(EntityCapsStore capsStore, AccountRepository accountRepository, RosterRepository rosterRepository) {
|
||||
return new ConnectionCenter(capsStore, accountRepository, rosterRepository);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
|
|
|
@ -27,6 +27,11 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility 1.8
|
||||
targetCompatibility 1.8
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "606370403d8f862397c7c75b88be193e",
|
||||
"identityHash": "cc1de3c4fd3350ea0e894d02f30312f3",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "contacts",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_contact_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `fk_account_id` INTEGER NOT NULL, `fk_entity_id` INTEGER NOT NULL, `rostername` TEXT, `nickname` TEXT, FOREIGN KEY(`fk_account_id`) REFERENCES `accounts`(`pk_account_id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`fk_entity_id`) REFERENCES `entities`(`pk_entity_id`) ON UPDATE NO ACTION ON DELETE RESTRICT )",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_contact_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `fk_account_id` INTEGER NOT NULL, `fk_entity_id` INTEGER NOT NULL, `rostername` TEXT, `nickname` TEXT, `direction` TEXT, `sub_pending` INTEGER NOT NULL, `approved` INTEGER NOT NULL, FOREIGN KEY(`fk_account_id`) REFERENCES `accounts`(`pk_account_id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`fk_entity_id`) REFERENCES `entities`(`pk_entity_id`) ON UPDATE NO ACTION ON DELETE RESTRICT )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
|
@ -37,6 +37,24 @@
|
|||
"columnName": "nickname",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "direction",
|
||||
"columnName": "direction",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "subscriptionPending",
|
||||
"columnName": "sub_pending",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "approved",
|
||||
"columnName": "approved",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
|
@ -473,12 +491,47 @@
|
|||
}
|
||||
],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "roster_information",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_account_id` INTEGER NOT NULL, `roster_version` TEXT, PRIMARY KEY(`pk_account_id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "accountId",
|
||||
"columnName": "pk_account_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "rosterVersion",
|
||||
"columnName": "roster_version",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"pk_account_id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_roster_information_pk_account_id",
|
||||
"unique": true,
|
||||
"columnNames": [
|
||||
"pk_account_id"
|
||||
],
|
||||
"createSql": "CREATE UNIQUE INDEX `index_roster_information_pk_account_id` ON `${TABLE_NAME}` (`pk_account_id`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '606370403d8f862397c7c75b88be193e')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'cc1de3c4fd3350ea0e894d02f30312f3')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package org.mercury_im.messenger.persistence.room;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
@ -9,19 +8,15 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IAccountRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IContactAttributesRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IRosterRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IMessageRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.functions.Predicate;
|
||||
import io.reactivex.observers.DefaultObserver;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
@ -41,7 +36,7 @@ public class ExampleInstrumentedTest {
|
|||
|
||||
AppDatabase appDatabase = AppDatabase.getDatabase(context);
|
||||
IAccountRepository accountRepository = new IAccountRepository(appDatabase.accountDao());
|
||||
IContactAttributesRepository rosterRepository = new IContactAttributesRepository(appDatabase.rosterEntryDao());
|
||||
IRosterRepository rosterRepository = new IRosterRepository(appDatabase.rosterEntryDao());
|
||||
IMessageRepository messageRepository = new IMessageRepository(appDatabase.messageDao());
|
||||
|
||||
Observable<List<RoomAccountModel>> accounts = accountRepository.getAllAccounts();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.mercury_im.messenger.persistence.room;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.room.Database;
|
||||
import androidx.room.Room;
|
||||
|
@ -9,26 +10,31 @@ import androidx.room.RoomDatabase;
|
|||
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.AvatarDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ChatDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ContactAttributesDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.EntityCapsDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.EntityDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.MessageDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.RosterInformationDao;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomAvatarModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomChatModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomEntityCapsModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomEntityModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomMessageModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomRosterInformationModel;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Database(version = 1,
|
||||
entities = {
|
||||
RoomContactAttributes.class,
|
||||
RoomAccountModel.class,
|
||||
RoomEntityModel.class,
|
||||
RoomContactModel.class,
|
||||
RoomRosterInformationModel.class,
|
||||
RoomChatModel.class,
|
||||
RoomMessageModel.class,
|
||||
RoomEntityModel.class,
|
||||
RoomAvatarModel.class,
|
||||
RoomEntityCapsModel.class
|
||||
})
|
||||
|
@ -39,6 +45,7 @@ public abstract class AppDatabase extends RoomDatabase {
|
|||
|
||||
public static AppDatabase getDatabase(final Context context) {
|
||||
if (INSTANCE == null) {
|
||||
Logger.getLogger("DATABASE").log(Level.INFO, context.getApplicationContext().getDatabasePath(DB_NAME).getAbsolutePath());
|
||||
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
|
||||
AppDatabase.class, DB_NAME)
|
||||
.build();
|
||||
|
@ -46,19 +53,59 @@ public abstract class AppDatabase extends RoomDatabase {
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
public abstract ContactAttributesDao rosterEntryDao();
|
||||
|
||||
public abstract ChatDao chatDao();
|
||||
|
||||
public abstract MessageDao messageDao();
|
||||
|
||||
/**
|
||||
* Return an instance of {@link AccountDao}.
|
||||
*
|
||||
* @return accountDao
|
||||
*/
|
||||
public abstract AccountDao accountDao();
|
||||
|
||||
/**
|
||||
* Return an instance of {@link EntityDao}.
|
||||
*
|
||||
* @return entityDao
|
||||
*/
|
||||
public abstract EntityDao entityDao();
|
||||
|
||||
/**
|
||||
* Return an instance of {@link ContactDao}.
|
||||
*
|
||||
* @return contactDao
|
||||
*/
|
||||
public abstract ContactDao contactDao();
|
||||
|
||||
/**
|
||||
* Return an instance of {@link RosterInformationDao}.
|
||||
*
|
||||
* @return rosterInformationDao
|
||||
*/
|
||||
public abstract RosterInformationDao rosterInformationDao();
|
||||
|
||||
/**
|
||||
* Return an instance of {@link ChatDao}.
|
||||
*
|
||||
* @return chatDao
|
||||
*/
|
||||
public abstract ChatDao chatDao();
|
||||
|
||||
/**
|
||||
* Return an instance of {@link MessageDao}.
|
||||
*
|
||||
* @return messageDao
|
||||
*/
|
||||
public abstract MessageDao messageDao();
|
||||
|
||||
/**
|
||||
* Return an instance of {@link AvatarDao}.
|
||||
*
|
||||
* @return avatarDao
|
||||
*/
|
||||
public abstract AvatarDao avatarDao();
|
||||
|
||||
/**
|
||||
* Return an instance of {@link EntityCapsDao}.
|
||||
*
|
||||
* @return entityCapsDao
|
||||
*/
|
||||
public abstract EntityCapsDao entityCapsDao();
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ import android.app.Application;
|
|||
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.AvatarDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ChatDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ContactAttributesDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.EntityCapsDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.EntityDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.MessageDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.RosterInformationDao;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -44,8 +44,8 @@ public class RoomModule {
|
|||
|
||||
@Singleton
|
||||
@Provides
|
||||
ContactAttributesDao provideRosterEntryDao() {
|
||||
return mAppDatabase.rosterEntryDao();
|
||||
ContactDao provideContactDao() {
|
||||
return mAppDatabase.contactDao();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
|
@ -68,14 +68,14 @@ public class RoomModule {
|
|||
|
||||
@Singleton
|
||||
@Provides
|
||||
ContactDao provideContactAndEntityDao() {
|
||||
return mAppDatabase.contactDao();
|
||||
AvatarDao providerAvatarDao() {
|
||||
return mAppDatabase.avatarDao();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
AvatarDao providerAvatarDao() {
|
||||
return mAppDatabase.avatarDao();
|
||||
RosterInformationDao provideRosterInformationDao() {
|
||||
return mAppDatabase.rosterInformationDao();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
|
|
|
@ -3,26 +3,22 @@ package org.mercury_im.messenger.persistence.room;
|
|||
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.AvatarRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.ChatRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.ContactAttributesRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.ContactRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.EntityCapsRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.EntityRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.MessageRepository;
|
||||
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.AvatarDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ChatDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ContactAttributesDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.EntityCapsDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.EntityDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.MessageDao;
|
||||
import org.mercury_im.messenger.persistence.room.dao.RosterInformationDao;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IAccountRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IAvatarRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IChatRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IContactAttributesRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IContactRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IRosterRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IEntityCapsRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IEntityRepository;
|
||||
import org.mercury_im.messenger.persistence.room.repository.IMessageRepository;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
@ -39,18 +35,6 @@ public class RoomRepositoryModule {
|
|||
return new IAccountRepository(dao);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
EntityRepository provideEntityRepository(EntityDao dao) {
|
||||
return new IEntityRepository(dao);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
ContactAttributesRepository provideContactAttributesRepository(ContactAttributesDao dao) {
|
||||
return new IContactAttributesRepository(dao);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
ChatRepository provideChatRepository(ChatDao dao) {
|
||||
|
@ -65,8 +49,8 @@ public class RoomRepositoryModule {
|
|||
|
||||
@Singleton
|
||||
@Provides
|
||||
ContactRepository provideContactRepository(ContactDao dao) {
|
||||
return new IContactRepository(dao);
|
||||
RosterRepository provideContactRepository(EntityDao entityDao, ContactDao contactDao, RosterInformationDao rosterInformationDao) {
|
||||
return new IRosterRepository(entityDao, contactDao, rosterInformationDao);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
package org.mercury_im.messenger.persistence.room.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.TypeConverters;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidConverter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
import static androidx.room.OnConflictStrategy.REPLACE;
|
||||
|
||||
@Dao
|
||||
@TypeConverters(EntityBareJidConverter.class)
|
||||
public interface ContactAttributesDao extends BaseDao<RoomContactAttributes> {
|
||||
|
||||
@Override
|
||||
@Insert(onConflict = REPLACE)
|
||||
Single<Long> insert(RoomContactAttributes entity);
|
||||
|
||||
@Query("SELECT * FROM contacts WHERE pk_contact_id = :id")
|
||||
Maybe<RoomContactAttributes> getContact(long id);
|
||||
|
||||
@Query("SELECT * FROM contacts WHERE fk_entity_id = :entityId")
|
||||
Maybe<RoomContactAttributes> getContactForEntityId(long entityId);
|
||||
|
||||
/**
|
||||
* Return a {@link Observable} wrapping a {@link List} of all {@link RoomContactAttributes RosterEntries}
|
||||
* which are currently found in the database.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Query("SELECT * FROM contacts")
|
||||
Observable<List<RoomContactAttributes>> getAllContacts();
|
||||
|
||||
@Query("SELECT contacts.* FROM contacts JOIN entities " +
|
||||
"WHERE contacts.fk_account_id = :accountId AND jid = :jid")
|
||||
Maybe<RoomContactAttributes> getContactByJid(long accountId, EntityBareJid jid);
|
||||
|
||||
@Query("SELECT * FROM contacts WHERE fk_account_id = :accountId")
|
||||
Observable<List<RoomContactAttributes>> getContactsForAccount(long accountId);
|
||||
}
|
|
@ -1,14 +1,16 @@
|
|||
package org.mercury_im.messenger.persistence.room.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Delete;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.TypeConverters;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
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.RoomRosterInformation;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomRosterInformationModel;
|
||||
import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidConverter;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -16,46 +18,49 @@ import java.util.List;
|
|||
import io.reactivex.Completable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
import static androidx.room.OnConflictStrategy.REPLACE;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.PREFIX;
|
||||
|
||||
@Dao
|
||||
@TypeConverters(EntityBareJidConverter.class)
|
||||
public interface ContactDao {
|
||||
|
||||
@Query("SELECT contacts.*, " +
|
||||
"entities." + RoomEntityModel.KEY_ID + " AS " + PREFIX + RoomEntityModel.KEY_ID + ", " +
|
||||
"entities." + RoomEntityModel.KEY_ACCOUNT_ID + " AS " + PREFIX + RoomEntityModel.KEY_ACCOUNT_ID + ", " +
|
||||
"entities." + RoomEntityModel.KEY_JID + " AS " + PREFIX + RoomEntityModel.KEY_JID + ", " +
|
||||
"entities." + RoomEntityModel.KEY_AVATAR + " AS " + PREFIX + RoomEntityModel.KEY_AVATAR + " " +
|
||||
"FROM contacts INNER JOIN entities ON contacts.fk_entity_id = entities.pk_entity_id " +
|
||||
"WHERE entities.fk_account_id = :accountId AND entities.jid = :bareJid")
|
||||
Maybe<RoomContactModel> getContactAndEntity(long accountId, EntityBareJid bareJid);
|
||||
|
||||
@Query("SELECT contacts.*, " +
|
||||
"entities." + RoomEntityModel.KEY_ID + " AS " + PREFIX + RoomEntityModel.KEY_ID + ", " +
|
||||
"entities." + RoomEntityModel.KEY_ACCOUNT_ID + " AS " + PREFIX + RoomEntityModel.KEY_ACCOUNT_ID + ", " +
|
||||
"entities." + RoomEntityModel.KEY_JID + " AS " + PREFIX + RoomEntityModel.KEY_JID + ", " +
|
||||
"entities." + RoomEntityModel.KEY_AVATAR + " AS " + PREFIX + RoomEntityModel.KEY_AVATAR + " " +
|
||||
"FROM contacts INNER JOIN entities ON contacts.fk_entity_id = entities.pk_entity_id " +
|
||||
"WHERE entities.fk_account_id = :accountId")
|
||||
Observable<List<RoomContactModel>> getAllContactAndEntities(long accountId);
|
||||
|
||||
@Query("SELECT contacts.*, " +
|
||||
"entities." + RoomEntityModel.KEY_ID + " AS " + PREFIX + RoomEntityModel.KEY_ID + ", " +
|
||||
"entities." + RoomEntityModel.KEY_ACCOUNT_ID + " AS " + PREFIX + RoomEntityModel.KEY_ACCOUNT_ID + ", " +
|
||||
"entities." + RoomEntityModel.KEY_JID + " AS " + PREFIX + RoomEntityModel.KEY_JID + ", " +
|
||||
"entities." + RoomEntityModel.KEY_AVATAR + " AS " + PREFIX + RoomEntityModel.KEY_AVATAR + " " +
|
||||
"FROM contacts INNER JOIN entities ON contacts.fk_entity_id = entities.pk_entity_id")
|
||||
Observable<List<RoomContactModel>> getAllContactAndEntities();
|
||||
|
||||
@Query("SELECT * FROM roster_information")
|
||||
Observable<List<RoomRosterInformation>> getAllRosterInformation();
|
||||
|
||||
@Query("SELECT * FROM roster_information WHERE pk_account_id = :accountId")
|
||||
Maybe<RoomRosterInformation> getRosterInformation(long accountId);
|
||||
public interface ContactDao extends BaseDao<RoomContactModel> {
|
||||
|
||||
@Override
|
||||
@Insert(onConflict = REPLACE)
|
||||
Completable insertRosterInformation(RoomRosterInformation information);
|
||||
Single<Long> insert(RoomContactModel entity);
|
||||
|
||||
@Query("SELECT * FROM contacts WHERE pk_contact_id = :id")
|
||||
Maybe<RoomContactModel> getContact(long id);
|
||||
|
||||
@Query("SELECT * FROM contacts WHERE fk_entity_id = :entityId")
|
||||
Maybe<RoomContactModel> getContactForEntityId(long entityId);
|
||||
|
||||
@Query("SELECT * FROM contacts")
|
||||
Observable<List<RoomContactModel>> getAllContacts();
|
||||
|
||||
@Query("SELECT contacts.* FROM contacts JOIN entities " +
|
||||
"WHERE contacts.fk_account_id = :accountId AND jid = :jid")
|
||||
Maybe<RoomContactModel> getContactByJid(long accountId, EntityBareJid jid);
|
||||
|
||||
@Query("SELECT * FROM contacts WHERE fk_account_id = :accountId")
|
||||
Observable<List<RoomContactModel>> getContactsForAccount(long accountId);
|
||||
|
||||
@Query("DELETE FROM contacts WHERE pk_contact_id = :id")
|
||||
Completable deleteContact(long id);
|
||||
|
||||
@Query("DELETE FROM contacts WHERE fk_entity_id = :entityId")
|
||||
Completable deleteContactForEntity(long entityId);
|
||||
|
||||
@Query("DELETE FROM contacts")
|
||||
Completable deleteAll();
|
||||
|
||||
@Query("DELETE FROM contacts WHERE fk_account_id = :accountId")
|
||||
Completable deleteAllForAccount(long accountId);
|
||||
|
||||
@Query("DELETE FROM contacts WHERE pk_contact_id IN(:ids)")
|
||||
Completable deleteContacts(long[] ids);
|
||||
|
||||
@Query("SELECT entities.* FROM contacts INNER JOIN entities ON contacts.fk_entity_id = entities.pk_entity_id WHERE contacts.pk_contact_id = :contactId")
|
||||
Single<RoomEntityModel> getEntityForContactId(long contactId);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package org.mercury_im.messenger.persistence.room.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Query;
|
||||
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomRosterInformationModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
import static androidx.room.OnConflictStrategy.REPLACE;
|
||||
|
||||
@Dao
|
||||
public interface RosterInformationDao extends BaseDao<RoomRosterInformationModel> {
|
||||
|
||||
@Query("SELECT * FROM roster_information")
|
||||
Observable<List<RoomRosterInformationModel>> getAllRosterInformation();
|
||||
|
||||
@Query("SELECT * FROM roster_information WHERE pk_account_id = :accountId")
|
||||
Observable<RoomRosterInformationModel> getRosterInformation(long accountId);
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
Single<Long> insertRosterInformation(RoomRosterInformationModel information);
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
package org.mercury_im.messenger.persistence.room.model;
|
||||
|
||||
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
import androidx.room.TypeConverter;
|
||||
import androidx.room.TypeConverters;
|
||||
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.room.type_converter.DirectionConverter;
|
||||
|
||||
import static androidx.room.ForeignKey.CASCADE;
|
||||
import static androidx.room.ForeignKey.RESTRICT;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactAttributes.KEY_ACCOUNT_ID;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactAttributes.KEY_ID;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactAttributes.KEY_ENTITY_ID;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactAttributes.TABLE;
|
||||
|
||||
@Entity(tableName = TABLE,
|
||||
indices = {
|
||||
@Index(value = KEY_ID),
|
||||
@Index(value = KEY_ACCOUNT_ID),
|
||||
@Index(value = KEY_ENTITY_ID),
|
||||
@Index(value = {KEY_ID, KEY_ENTITY_ID}, unique = true)
|
||||
},
|
||||
foreignKeys = {
|
||||
@ForeignKey(entity = RoomAccountModel.class,
|
||||
parentColumns = RoomAccountModel.KEY_ID,
|
||||
childColumns = KEY_ACCOUNT_ID,
|
||||
onDelete = CASCADE),
|
||||
@ForeignKey(entity = RoomEntityModel.class,
|
||||
parentColumns = RoomEntityModel.KEY_ID,
|
||||
childColumns = KEY_ENTITY_ID,
|
||||
onDelete = RESTRICT)})
|
||||
public class RoomContactAttributes implements ContactAttributes {
|
||||
|
||||
public static final String TABLE = "contacts";
|
||||
public static final String KEY_ID = "pk_contact_id";
|
||||
public static final String KEY_ACCOUNT_ID = "fk_account_id";
|
||||
public static final String KEY_ENTITY_ID = "fk_entity_id";
|
||||
public static final String KEY_ROSTER_NAME = "rostername";
|
||||
public static final String KEY_NICKNAME = "nickname";
|
||||
public static final String KEY_DIRECTION = "direction";
|
||||
public static final String KEY_SUB_PENDING = "sub_pending";
|
||||
public static final String KEY_APPROVED = "approved";
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = KEY_ID)
|
||||
private long id;
|
||||
|
||||
@ColumnInfo(name = KEY_ACCOUNT_ID)
|
||||
private long accountId;
|
||||
|
||||
@ColumnInfo(name = KEY_ENTITY_ID)
|
||||
private long entityId;
|
||||
|
||||
@ColumnInfo(name = KEY_ROSTER_NAME)
|
||||
private String rosterName;
|
||||
|
||||
@ColumnInfo(name = KEY_NICKNAME)
|
||||
private String nickname;
|
||||
|
||||
@ColumnInfo(name = KEY_DIRECTION)
|
||||
@TypeConverters(DirectionConverter.class)
|
||||
private DIRECTION direction;
|
||||
|
||||
@ColumnInfo(name = KEY_SUB_PENDING)
|
||||
private boolean subscriptionPending;
|
||||
|
||||
@ColumnInfo(name = KEY_APPROVED)
|
||||
private boolean approved;
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccountId(long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEntityId(long id) {
|
||||
this.entityId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRosterName() {
|
||||
return rosterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRosterName(String rosterName) {
|
||||
this.rosterName = rosterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DIRECTION getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDirection(DIRECTION direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSubscriptionPending() {
|
||||
return subscriptionPending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubscriptionPending(boolean pending) {
|
||||
this.subscriptionPending = pending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApproved() {
|
||||
return approved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApproved(boolean approved) {
|
||||
this.approved = approved;
|
||||
}
|
||||
}
|
|
@ -1,34 +1,173 @@
|
|||
package org.mercury_im.messenger.persistence.room.model;
|
||||
|
||||
import androidx.room.Embedded;
|
||||
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
import androidx.room.TypeConverters;
|
||||
|
||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
import org.mercury_im.messenger.persistence.room.type_converter.DirectionConverter;
|
||||
|
||||
public class RoomContactModel implements ContactModel<RoomContactAttributes, RoomEntityModel> {
|
||||
import static androidx.room.ForeignKey.CASCADE;
|
||||
import static androidx.room.ForeignKey.RESTRICT;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.KEY_ACCOUNT_ID;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.KEY_ID;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.KEY_ENTITY_ID;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.TABLE;
|
||||
|
||||
public static final String PREFIX = "e_";
|
||||
@Entity(tableName = TABLE,
|
||||
indices = {
|
||||
@Index(value = KEY_ID),
|
||||
@Index(value = KEY_ACCOUNT_ID),
|
||||
@Index(value = KEY_ENTITY_ID),
|
||||
@Index(value = {KEY_ID, KEY_ENTITY_ID}, unique = true)
|
||||
},
|
||||
foreignKeys = {
|
||||
@ForeignKey(entity = RoomAccountModel.class,
|
||||
parentColumns = RoomAccountModel.KEY_ID,
|
||||
childColumns = KEY_ACCOUNT_ID,
|
||||
onDelete = CASCADE),
|
||||
@ForeignKey(entity = RoomEntityModel.class,
|
||||
parentColumns = RoomEntityModel.KEY_ID,
|
||||
childColumns = KEY_ENTITY_ID,
|
||||
onDelete = RESTRICT)})
|
||||
public class RoomContactModel implements ContactModel {
|
||||
|
||||
@Embedded(prefix = PREFIX)
|
||||
private RoomEntityModel entity;
|
||||
public static final String TABLE = "contacts";
|
||||
public static final String KEY_ID = "pk_contact_id";
|
||||
public static final String KEY_ACCOUNT_ID = "fk_account_id";
|
||||
public static final String KEY_ENTITY_ID = "fk_entity_id";
|
||||
public static final String KEY_ROSTER_NAME = "rostername";
|
||||
public static final String KEY_NICKNAME = "nickname";
|
||||
public static final String KEY_DIRECTION = "direction";
|
||||
public static final String KEY_SUB_PENDING = "sub_pending";
|
||||
public static final String KEY_APPROVED = "approved";
|
||||
|
||||
@Embedded()
|
||||
private RoomContactAttributes contact;
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = KEY_ID)
|
||||
private long id;
|
||||
|
||||
@ColumnInfo(name = KEY_ACCOUNT_ID)
|
||||
private long accountId;
|
||||
|
||||
@ColumnInfo(name = KEY_ENTITY_ID)
|
||||
private long entityId;
|
||||
|
||||
@ColumnInfo(name = KEY_ROSTER_NAME)
|
||||
private String rosterName;
|
||||
|
||||
@ColumnInfo(name = KEY_NICKNAME)
|
||||
private String nickname;
|
||||
|
||||
@ColumnInfo(name = KEY_DIRECTION)
|
||||
@TypeConverters(DirectionConverter.class)
|
||||
private DIRECTION direction;
|
||||
|
||||
@ColumnInfo(name = KEY_SUB_PENDING)
|
||||
private boolean subscriptionPending;
|
||||
|
||||
@ColumnInfo(name = KEY_APPROVED)
|
||||
private boolean approved;
|
||||
|
||||
/**
|
||||
* This field is ignored by room and must instead be populated manually by calling
|
||||
* {@link #setEntity(EntityModel)}.
|
||||
*/
|
||||
@Ignore
|
||||
private EntityModel entityModel;
|
||||
|
||||
@Override
|
||||
public RoomContactAttributes getContact() {
|
||||
return contact;
|
||||
}
|
||||
|
||||
public void setContact(RoomContactAttributes contact) {
|
||||
this.contact = contact;
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoomEntityModel getEntity() {
|
||||
return entity;
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setEntity(RoomEntityModel entity) {
|
||||
this.entity = entity;
|
||||
@Override
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccountId(long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEntityId(long id) {
|
||||
this.entityId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRosterName() {
|
||||
return rosterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRosterName(String rosterName) {
|
||||
this.rosterName = rosterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DIRECTION getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDirection(DIRECTION direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSubscriptionPending() {
|
||||
return subscriptionPending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubscriptionPending(boolean pending) {
|
||||
this.subscriptionPending = pending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApproved() {
|
||||
return approved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApproved(boolean approved) {
|
||||
this.approved = approved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityModel getEntity() {
|
||||
return entityModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEntity(EntityModel entity) {
|
||||
this.entityModel = entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ import androidx.room.PrimaryKey;
|
|||
|
||||
import org.mercury_im.messenger.persistence.model.RosterInformationModel;
|
||||
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomRosterInformation.KEY_ID;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomRosterInformation.TABLE;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomRosterInformationModel.KEY_ID;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomRosterInformationModel.TABLE;
|
||||
|
||||
@Entity(tableName = TABLE, indices = {
|
||||
@Index(value = KEY_ID, unique = true)
|
||||
})
|
||||
public class RoomRosterInformation implements RosterInformationModel {
|
||||
public class RoomRosterInformationModel implements RosterInformationModel {
|
||||
|
||||
public static final String TABLE = "roster_information";
|
||||
public static final String KEY_ID = "pk_account_id";
|
|
@ -1,6 +1,5 @@
|
|||
package org.mercury_im.messenger.persistence.room.repository;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.mercury_im.messenger.persistence.room.repository;
|
|||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
import org.mercury_im.messenger.persistence.repository.ChatRepository;
|
||||
|
@ -51,14 +50,9 @@ public class IChatRepository implements ChatRepository<RoomChatModel> {
|
|||
return chatDao.getChatWithJid(account.getId(), jid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomChatModel> getChatWith(ContactAttributes contact) {
|
||||
return chatDao.getChatWithContact(contact.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomChatModel> getChatWith(ContactModel contact) {
|
||||
return getChatWith(contact.getContact());
|
||||
return chatDao.getChatWithContact(contact.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
package org.mercury_im.messenger.persistence.room.repository;
|
||||
|
||||
import org.mercury_im.messenger.persistence.repository.ContactAttributesRepository;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ContactAttributesDao;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactAttributes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
public class IContactAttributesRepository implements ContactAttributesRepository<RoomContactAttributes> {
|
||||
|
||||
private final ContactAttributesDao contactAttributesDao;
|
||||
|
||||
public IContactAttributesRepository(ContactAttributesDao dao) {
|
||||
this.contactAttributesDao = dao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoomContactAttributes newContactAttributesModel() {
|
||||
return new RoomContactAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<List<RoomContactAttributes>> getAllContactAttributes() {
|
||||
return contactAttributesDao.getAllContacts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<Long> updateOrInsertContactAttributes(RoomContactAttributes attributes) {
|
||||
return contactAttributesDao.insert(attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomContactAttributes> getContactAttributes(long id) {
|
||||
return contactAttributesDao.getContact(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomContactAttributes> getContactAttributesForEntity(long entityId) {
|
||||
return contactAttributesDao.getContactForEntityId(entityId);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package org.mercury_im.messenger.persistence.room.repository;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
import org.mercury_im.messenger.persistence.model.RosterInformationModel;
|
||||
import org.mercury_im.messenger.persistence.repository.ContactRepository;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactAttributes;
|
||||
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.RoomRosterInformation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public class IContactRepository implements ContactRepository<RoomContactModel, RoomRosterInformation> {
|
||||
|
||||
private final ContactDao dao;
|
||||
|
||||
@Inject
|
||||
public IContactRepository(ContactDao dao) {
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoomContactModel newContactModel() {
|
||||
return new RoomContactModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactAttributes newAttributesModel() {
|
||||
return new RoomContactAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityModel newEntityModel() {
|
||||
return new RoomEntityModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomContactModel> getContact(long accountId, EntityBareJid jid) {
|
||||
return dao.getContactAndEntity(accountId, jid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomContactModel> getContactForEntity(EntityModel entityModel) {
|
||||
return getContact(entityModel.getAccountId(), entityModel.getJid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<List<RoomContactModel>> getAllContactsOfAccount(long accountId) {
|
||||
return dao.getAllContactAndEntities(accountId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<List<RoomContactModel>> getAllContacts() {
|
||||
return dao.getAllContactAndEntities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<List<RoomRosterInformation>> getAllRosterInformation() {
|
||||
return dao.getAllRosterInformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Completable insertRosterInformation(RoomRosterInformation rosterInfo) {
|
||||
return dao.insertRosterInformation(rosterInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomRosterInformation> getRosterInformation(long accountId) {
|
||||
return dao.getRosterInformation(accountId);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package org.mercury_im.messenger.persistence.room.repository;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.repository.EntityRepository;
|
||||
import org.mercury_im.messenger.persistence.room.dao.EntityDao;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomEntityModel;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.reactivex.Maybe;
|
||||
|
||||
public class IEntityRepository implements EntityRepository<RoomEntityModel> {
|
||||
|
||||
private final EntityDao dao;
|
||||
|
||||
@Inject
|
||||
public IEntityRepository(EntityDao dao) {
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoomEntityModel newEntityModel() {
|
||||
return new RoomEntityModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C extends ContactAttributes> Maybe<RoomEntityModel> getEntity(C contact) {
|
||||
return dao.getEntity(contact.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomEntityModel> getEntity(long accountId, EntityBareJid jid) {
|
||||
return dao.getEntityFor(accountId, jid);
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@ import org.mercury_im.messenger.persistence.room.model.RoomMessageModel;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
@ -15,6 +17,7 @@ public class IMessageRepository implements MessageRepository<RoomMessageModel> {
|
|||
|
||||
private final MessageDao messageDao;
|
||||
|
||||
@Inject
|
||||
public IMessageRepository(MessageDao messageDao) {
|
||||
this.messageDao = messageDao;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
package org.mercury_im.messenger.persistence.room.repository;
|
||||
|
||||
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.CompletableSource;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.functions.Function;
|
||||
|
||||
public class IRosterRepository extends RosterRepository<RoomEntityModel, RoomContactModel, RoomRosterInformationModel> {
|
||||
|
||||
private final EntityDao entityDao;
|
||||
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> updateOrInsertContact(RoomContactModel contact) {
|
||||
return entityDao.insert((RoomEntityModel) contact.getEntity())
|
||||
.flatMap(entityId -> {
|
||||
contact.getEntity().setId(entityId);
|
||||
contact.setEntityId(entityId);
|
||||
return contactDao.insert(contact);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<RoomEntityModel> getEntityForContact(long contactId) {
|
||||
Single<RoomEntityModel> s = contactDao.getEntityForContactId(contactId);
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomContactModel> getContact(long id) {
|
||||
return contactDao.getContact(id)
|
||||
// Set the entity
|
||||
.zipWith(getEntityForContact(id).toMaybe(),
|
||||
(contact, entity) -> {
|
||||
contact.setEntity(entity);
|
||||
contact.setEntityId(entity.getId());
|
||||
return contact;
|
||||
});
|
||||
}
|
||||
|
||||
@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 = getEntity(accountId, jid.asEntityBareJidOrThrow());
|
||||
return entity.flatMapCompletable(new Function<RoomEntityModel, CompletableSource>() {
|
||||
@Override
|
||||
public CompletableSource apply(RoomEntityModel entityModel) {
|
||||
return 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);
|
||||
}
|
||||
|
||||
/*
|
||||
RoomEntityModel
|
||||
*/
|
||||
|
||||
@Override
|
||||
public RoomEntityModel newEntityModel() {
|
||||
return new RoomEntityModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomEntityModel> getEntity(long id) {
|
||||
return entityDao.getEntity(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomEntityModel> getEntity(long accountId, EntityBareJid jid) {
|
||||
return entityDao.getEntityFor(accountId, jid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<Long> insertOrReplaceEntity(RoomEntityModel entity) {
|
||||
return entityDao.insert(entity);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,17 +2,17 @@ package org.mercury_im.messenger.persistence.room.type_converter;
|
|||
|
||||
import androidx.room.TypeConverter;
|
||||
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
|
||||
public class DirectionConverter {
|
||||
|
||||
@TypeConverter
|
||||
public static String toString(ContactAttributes.DIRECTION direction) {
|
||||
return direction.toString();
|
||||
public static String toString(ContactModel.DIRECTION direction) {
|
||||
return direction != null ? direction.toString() : null;
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
public static ContactAttributes.DIRECTION fromString(String string) {
|
||||
return ContactAttributes.DIRECTION.valueOf(string);
|
||||
public static ContactModel.DIRECTION fromString(String string) {
|
||||
return string != null ? ContactModel.DIRECTION.valueOf(string) : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package org.mercury_im.messenger.persistence.model;
|
||||
|
||||
public interface ContactAttributes {
|
||||
|
||||
long getId();
|
||||
|
||||
void setId(long id);
|
||||
|
||||
long getAccountId();
|
||||
|
||||
void setAccountId(long id);
|
||||
|
||||
long getEntityId();
|
||||
|
||||
void setEntityId(long id);
|
||||
|
||||
String getRosterName();
|
||||
|
||||
void setRosterName(String rosterName);
|
||||
|
||||
String getNickname();
|
||||
|
||||
void setNickname(String nickname);
|
||||
|
||||
DIRECTION getDirection();
|
||||
|
||||
void setDirection(DIRECTION direction);
|
||||
|
||||
boolean isSubscriptionPending();
|
||||
|
||||
void setSubscriptionPending(boolean pending);
|
||||
|
||||
boolean isApproved();
|
||||
|
||||
void setApproved(boolean approved);
|
||||
|
||||
enum DIRECTION {
|
||||
none,
|
||||
to,
|
||||
from,
|
||||
both,
|
||||
remove
|
||||
}
|
||||
}
|
|
@ -1,12 +1,48 @@
|
|||
package org.mercury_im.messenger.persistence.model;
|
||||
|
||||
public interface ContactModel<C extends ContactAttributes, E extends EntityModel> {
|
||||
public interface ContactModel<E extends EntityModel> {
|
||||
|
||||
C getContact();
|
||||
long getId();
|
||||
|
||||
void setContact(C contact);
|
||||
void setId(long id);
|
||||
|
||||
long getAccountId();
|
||||
|
||||
void setAccountId(long id);
|
||||
|
||||
long getEntityId();
|
||||
|
||||
void setEntityId(long id);
|
||||
|
||||
String getRosterName();
|
||||
|
||||
void setRosterName(String rosterName);
|
||||
|
||||
String getNickname();
|
||||
|
||||
void setNickname(String nickname);
|
||||
|
||||
DIRECTION getDirection();
|
||||
|
||||
void setDirection(DIRECTION direction);
|
||||
|
||||
boolean isSubscriptionPending();
|
||||
|
||||
void setSubscriptionPending(boolean pending);
|
||||
|
||||
boolean isApproved();
|
||||
|
||||
void setApproved(boolean approved);
|
||||
|
||||
E getEntity();
|
||||
|
||||
void setEntity(E entity);
|
||||
|
||||
enum DIRECTION {
|
||||
none,
|
||||
to,
|
||||
from,
|
||||
both,
|
||||
remove
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.mercury_im.messenger.persistence.repository;
|
|||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||
import org.mercury_im.messenger.persistence.model.ChatModel;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
|
||||
|
@ -25,8 +24,6 @@ public interface ChatRepository<E extends ChatModel> {
|
|||
|
||||
Maybe<E> getChatWith(EntityModel identity);
|
||||
|
||||
Maybe<E> getChatWith(ContactAttributes contact);
|
||||
|
||||
Maybe<E> getChatWith(ContactModel contact);
|
||||
|
||||
Completable closeChat(E chat);
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package org.mercury_im.messenger.persistence.repository;
|
||||
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
public interface ContactAttributesRepository<E extends ContactAttributes> {
|
||||
|
||||
E newContactAttributesModel();
|
||||
|
||||
Observable<List<E>> getAllContactAttributes();
|
||||
|
||||
Single<Long> updateOrInsertContactAttributes(E attributes);
|
||||
|
||||
Maybe<E> getContactAttributes(long id);
|
||||
|
||||
Maybe<E> getContactAttributesForEntity(long entityId);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package org.mercury_im.messenger.persistence.repository;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
import org.mercury_im.messenger.persistence.model.RosterInformationModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public interface ContactRepository<CE extends ContactModel<? extends ContactAttributes, ? extends EntityModel>, I extends RosterInformationModel> {
|
||||
|
||||
CE newContactModel();
|
||||
|
||||
ContactAttributes newAttributesModel();
|
||||
|
||||
EntityModel newEntityModel();
|
||||
|
||||
Maybe<CE> getContact(long accountId, EntityBareJid jid);
|
||||
|
||||
Maybe<CE> getContactForEntity(EntityModel entityModel);
|
||||
|
||||
Observable<List<CE>> getAllContactsOfAccount(long accountId);
|
||||
|
||||
Observable<List<CE>> getAllContacts();
|
||||
|
||||
Observable<List<I>> getAllRosterInformation();
|
||||
|
||||
Maybe<I> getRosterInformation(long accountId);
|
||||
|
||||
Completable insertRosterInformation(I rosterInfo);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package org.mercury_im.messenger.persistence.repository;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
|
||||
import io.reactivex.Maybe;
|
||||
|
||||
public interface EntityRepository<E extends EntityModel> {
|
||||
|
||||
E newEntityModel();
|
||||
|
||||
<C extends ContactAttributes> Maybe<E> getEntity(C contact);
|
||||
|
||||
Maybe<E> getEntity(long accountId, EntityBareJid jid);
|
||||
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
package org.mercury_im.messenger.persistence.repository;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
import org.mercury_im.messenger.persistence.model.RosterInformationModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
public abstract class RosterRepository<E extends EntityModel, C extends ContactModel, V extends RosterInformationModel> {
|
||||
|
||||
/*
|
||||
ContactModel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a new empty concrete {@link ContactModel}.
|
||||
* This method is used as a factory method, as the core module will not know about any concrete
|
||||
* implementations of {@link ContactModel}.
|
||||
*
|
||||
* @return new empty {@link ContactModel}
|
||||
*/
|
||||
public abstract C newContactModel();
|
||||
|
||||
/**
|
||||
* Return an observable list of {@link ContactModel ContactModels}.
|
||||
* Note: This method will return all contacts of all accounts.
|
||||
*
|
||||
* @return ALL {@link ContactModel ContactModels} currently in the database.
|
||||
*/
|
||||
public abstract Observable<List<C>> getAllContacts();
|
||||
|
||||
/**
|
||||
* Return an observable list of all {@link ContactModel ContactModels} that belong to
|
||||
* the account with the given accountId.
|
||||
*
|
||||
* @param accountId ID of the account
|
||||
* @return all {@link ContactModel ContactModels} of the account
|
||||
*/
|
||||
public abstract Observable<List<C>> getAllContactsOfAccount(long accountId);
|
||||
|
||||
/**
|
||||
* Return an observable list of all {@link ContactModel ContactModels} that belong to the
|
||||
* given {@link AccountModel}.
|
||||
*
|
||||
* @param account account
|
||||
* @return all {@link ContactModel ContactModels} of the account
|
||||
*/
|
||||
public Observable<List<C>> getAllContactsOfAccount(AccountModel account) {
|
||||
return getAllContactsOfAccount(account.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update or insert an {@link ContactModel}.
|
||||
* The method returns a {@link Single} which wraps the ID assigned to the {@link ContactModel}.
|
||||
*
|
||||
* @param contact contact
|
||||
* @return single wrapping the contacts ID
|
||||
*/
|
||||
public abstract Single<Long> updateOrInsertContact(C contact);
|
||||
|
||||
/**
|
||||
* Return the {@link ContactModel} corresponding to the given ID wrapped in a {@link Maybe}.
|
||||
*
|
||||
* @param id ID of the contact
|
||||
* @return {@link Maybe} wrapping the {@link ContactModel}
|
||||
*/
|
||||
public abstract Maybe<C> getContact(long id);
|
||||
|
||||
/**
|
||||
* Return the {@link ContactModel} which belongs to the given entityId, wrapped in a {@link Maybe}.
|
||||
*
|
||||
* @param entityId ID of the entity
|
||||
* @return {@link Maybe} wrapping the {@link ContactModel}.
|
||||
*/
|
||||
public abstract Maybe<C> getContactForEntity(long entityId);
|
||||
|
||||
public Maybe<C> getContactForEntity(EntityModel entityModel) {
|
||||
return getContactForEntity(entityModel.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a {@link ContactModel} from the database.
|
||||
* This method returns a {@link Completable} which will invoke {@link Completable#complete()}
|
||||
* once the {@link ContactModel} was successfully deleted, or will invoke
|
||||
* {@link Completable#error(Throwable)} if an error occurs.
|
||||
*
|
||||
* @param id ID of the {@link ContactModel}
|
||||
* @return {@link Completable}
|
||||
*/
|
||||
public abstract Completable deleteContact(long id);
|
||||
|
||||
/**
|
||||
* Delete a {@link ContactModel} from the database.
|
||||
* This method returns a {@link Completable} which will invoke {@link Completable#complete()}
|
||||
* once the {@link ContactModel} was successfully deleted, or will invoke
|
||||
* {@link Completable#error(Throwable)} if an error occurs.
|
||||
*
|
||||
* @param contact the {@link ContactModel} to be deleted
|
||||
* @return {@link Completable}
|
||||
*/
|
||||
public Completable deleteContact(C contact) {
|
||||
return deleteContact(contact.getId());
|
||||
}
|
||||
|
||||
public abstract Completable deleteContact(long accountId, EntityBareJid jid);
|
||||
|
||||
public abstract Completable deleteAllContacts();
|
||||
|
||||
public abstract Completable deleteAllContactsOfAccount(long accountId);
|
||||
|
||||
public Completable deleteAllContactsOfAccount(AccountModel account) {
|
||||
return deleteAllContactsOfAccount(account.getId());
|
||||
}
|
||||
|
||||
public abstract Completable deleteContacts(long[] ids);
|
||||
|
||||
public Completable deleteContacts(C[] contacts) {
|
||||
long[] ids = new long[contacts.length];
|
||||
for (int i = 0; i < contacts.length; i++) {
|
||||
ids[i] = contacts[i].getId();
|
||||
}
|
||||
return deleteContacts(ids);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
RosterInformationModel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create an empty, concrete implementation of {@link RosterInformationModel}.
|
||||
* This method is used as a factory method, as the core module may not know about the concrete
|
||||
* implementation of {@link RosterInformationModel} in use.
|
||||
*
|
||||
* @return concrete, empty {@link RosterInformationModel}
|
||||
*/
|
||||
public abstract V newRosterInformationModel();
|
||||
|
||||
/**
|
||||
* Return an {@link Observable} wrapping the {@link RosterInformationModel} for the given
|
||||
* account id.
|
||||
*
|
||||
* @param accountId ID of the account
|
||||
* @return {@link Observable} wrapping the {@link RosterInformationModel}.
|
||||
*/
|
||||
public abstract Observable<V> getRosterInformationForAccount(long accountId);
|
||||
|
||||
/**
|
||||
* Return an {@link Observable} wrapping the {@link RosterInformationModel} for the given
|
||||
* account.
|
||||
*
|
||||
* @param account account
|
||||
* @return {@link Observable} wrapping the {@link RosterInformationModel}.
|
||||
*/
|
||||
public Observable<V> getRosterInformationForAccount(AccountModel account) {
|
||||
return getRosterInformationForAccount(account.getId());
|
||||
}
|
||||
|
||||
public abstract Single<Long> updateRosterInformation(V rosterInformation);
|
||||
|
||||
public Single<Long> updateRosterVersionForAccount(long accountID, String rosterVersion) {
|
||||
V info = newRosterInformationModel();
|
||||
info.setAccountId(accountID);
|
||||
info.setRosterVersion(rosterVersion);
|
||||
return updateRosterInformation(info);
|
||||
}
|
||||
|
||||
public Single<Long> updateRosterVersionForAccount(AccountModel accountModel, String rosterVersion) {
|
||||
return updateRosterVersionForAccount(accountModel.getId(), rosterVersion);
|
||||
}
|
||||
|
||||
/*
|
||||
EntityModel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create an empty instance of a concrete implementation of the {@link EntityModel} class.
|
||||
* This method is used as a factory method, as the core module may not know about the concrete
|
||||
* implementation of {@link EntityModel} in use.
|
||||
*
|
||||
* @return new empty concrete implementation object.
|
||||
*/
|
||||
public abstract E newEntityModel();
|
||||
|
||||
/**
|
||||
* Return the {@link EntityModel} with the given ID wrapped in a {@link Maybe}.
|
||||
*
|
||||
* @param id ID of the {@link EntityModel}
|
||||
* @return {@link Maybe} wrapping the {@link EntityModel}
|
||||
*/
|
||||
public abstract Maybe<E> getEntity(long id);
|
||||
|
||||
/**
|
||||
* Return the {@link EntityModel} which belongs to the given {@link ContactModel}.
|
||||
* This method returns a {@link Single} instead of a {@link Maybe}, as per definition a
|
||||
* {@link ContactModel} MUST have a corresponding {@link EntityModel} in the database.
|
||||
*
|
||||
* @param contact {@link ContactModel} of which we want to have the {@link EntityModel}
|
||||
* @return {@link Single} wrapping the {@link EntityModel}
|
||||
*/
|
||||
public Single<E> getEntity(C contact) {
|
||||
return getEntity(contact.getEntityId()).toSingle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link EntityModel} which belongs to the given accountID and jid, wrapped in a
|
||||
* {@link Maybe}.
|
||||
*
|
||||
* @param accountId ID of the {@link AccountModel} to which the {@link EntityModel} points with
|
||||
* a foreign key
|
||||
* @param jid {@link EntityBareJid} of the {@link EntityModel}
|
||||
* @return
|
||||
*/
|
||||
public abstract Maybe<E> getEntity(long accountId, EntityBareJid jid);
|
||||
|
||||
/**
|
||||
* Return the {@link EntityModel} which has foreign keys pointing to the {@link AccountModel}
|
||||
* and {@link EntityBareJid}, wrapped in a {@link Maybe}.
|
||||
*
|
||||
* @param account {@link AccountModel}
|
||||
* @param jid {@link EntityBareJid}
|
||||
* @return
|
||||
*/
|
||||
public Maybe<E> getEntity(AccountModel account, EntityBareJid jid) {
|
||||
return getEntity(account.getId(), jid);
|
||||
}
|
||||
|
||||
public abstract Single<E> getEntityForContact(long contactId);
|
||||
|
||||
public Single<E> getEntityForContact(C contact) {
|
||||
return getEntityForContact(contact.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert or replace a {@link EntityModel} in the database.
|
||||
*
|
||||
* @param entity {@link EntityModel} which we want to insert or replace in the database
|
||||
* @return {@link Single} which wraps the ID assigned to the entity
|
||||
*/
|
||||
public abstract Single<Long> insertOrReplaceEntity(E entity);
|
||||
|
||||
}
|
Loading…
Reference in New Issue