More small changes

This commit is contained in:
Paul Schaub 2019-11-23 21:16:03 +01:00
parent c1538bc04c
commit dc6d9f106e
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
39 changed files with 514 additions and 628 deletions

View File

@ -3,7 +3,7 @@ package org.mercury_im.messenger.di.module;
import android.app.Application;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.data.di.RequeryModule;
import org.mercury_im.messenger.data.di.RepositoryModule;
import javax.inject.Singleton;
@ -11,7 +11,7 @@ import dagger.Module;
import dagger.Provides;
@Module(includes = {
RequeryModule.class
RepositoryModule.class
})
public class AppModule {

View File

@ -16,7 +16,6 @@ import com.google.android.material.navigation.NavigationView;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.data.model.AccountModel;
import org.mercury_im.messenger.data.repository.ChatRepository;
import org.mercury_im.messenger.ui.chatlist.ChatListFragment;
import org.mercury_im.messenger.ui.login.AccountsFragment;
import org.mercury_im.messenger.ui.roster.RosterFragment;

View File

@ -28,7 +28,6 @@ import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.core.centers.ConnectionCenter;
import org.mercury_im.messenger.data.repository.ChatRepository;
import java.util.logging.Level;
import java.util.logging.Logger;

View File

@ -11,9 +11,7 @@ import org.mercury_im.messenger.xmpp.model.ChatModel;
import org.mercury_im.messenger.xmpp.model.ContactModel;
import org.mercury_im.messenger.xmpp.model.EntityModel;
import org.mercury_im.messenger.xmpp.model.MessageModel;
import org.mercury_im.messenger.data.repository.ChatRepository;
import org.mercury_im.messenger.data.repository.MessageRepository;
import org.mercury_im.messenger.data.repository.RosterRepository;
import org.mercury_im.messenger.data.repository.XmppContactRepository;
import java.util.List;
@ -31,7 +29,7 @@ public class ChatViewModel extends ViewModel {
MessageRepository messageRepository;
@Inject
RosterRepository rosterRepository;
XmppContactRepository xmppContactRepository;
@Inject
ChatRepository chatRepository;
@ -51,13 +49,13 @@ public class ChatViewModel extends ViewModel {
}
public void init(long accountId, EntityBareJid jid) {
disposable.add(rosterRepository.getOrCreateEntity(accountId, jid)
disposable.add(xmppContactRepository.getOrCreateEntity(accountId, jid)
.subscribe((Consumer<EntityModel>) this::init));
}
public void init(EntityModel entityModel) {
disposable.add(rosterRepository.getContact(entityModel.getAccount().getId(), entityModel.getJid())
disposable.add(xmppContactRepository.getContact(entityModel.getAccount().getId(), entityModel.getJid())
.subscribe(reactiveResult -> {
ContactModel model = reactiveResult.first();
ChatViewModel.this.contact.setValue(model);

View File

@ -6,8 +6,6 @@ import androidx.lifecycle.ViewModel;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.xmpp.model.ChatModel;
import org.mercury_im.messenger.data.repository.ChatRepository;
import org.mercury_im.messenger.data.repository.MessageRepository;
import java.util.List;

View File

@ -7,14 +7,14 @@ import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import org.mercury_im.messenger.xmpp.model.ContactModel;
import org.mercury_im.messenger.data.repository.RosterRepository;
import org.mercury_im.messenger.data.repository.XmppContactRepository;
import javax.inject.Inject;
public class ContactListItemViewModel extends AndroidViewModel {
@Inject
RosterRepository contactRepository;
XmppContactRepository contactRepository;
private LiveData<ContactModel> contact;

View File

@ -8,7 +8,7 @@ import androidx.lifecycle.ViewModel;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.xmpp.model.ContactModel;
import org.mercury_im.messenger.data.repository.RosterRepository;
import org.mercury_im.messenger.data.repository.XmppContactRepository;
import java.util.List;
@ -22,7 +22,7 @@ import io.reactivex.schedulers.Schedulers;
public class ContactListViewModel extends ViewModel {
@Inject
RosterRepository rosterRepository;
XmppContactRepository xmppContactRepository;
private final MutableLiveData<List<ContactModel>> rosterEntryList = new MutableLiveData<>();
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
@ -32,7 +32,7 @@ public class ContactListViewModel extends ViewModel {
MercuryImApplication.getApplication().getAppComponent().inject(this);
Log.d("ContactListViewModel", "Start observing database");
// Subscribe to changes to the contacts table and update the LiveData object for the UI.
compositeDisposable.add(rosterRepository.getAllContacts()
compositeDisposable.add(xmppContactRepository.getAllContacts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(o -> {

View File

@ -1,14 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@ -30,7 +29,7 @@ allprojects {
// Smack nightly unique snapshots repo
//maven {
// url 'https://igniterealtime.org/repo/'
// }
// }
}
configurations {

View File

@ -11,6 +11,9 @@ dependencies {
implementation project(":entity")
implementation project(':domain')
compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
// RxJava2
implementation "io.reactivex.rxjava2:rxjava:$rxJava2Version"

View File

@ -0,0 +1,32 @@
package org.mercury_im.messenger.data.di;
import org.mercury_im.messenger.data.mapping.AccountMapping;
import org.mercury_im.messenger.data.mapping.DirectChatMapping;
import org.mercury_im.messenger.data.mapping.PeerMapping;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class MappingModule {
@Provides
@Singleton
public static AccountMapping accountMapping() {
return new AccountMapping();
}
@Provides
@Singleton
public static PeerMapping peerMapping() {
return new PeerMapping();
}
@Provides
@Singleton
public static DirectChatMapping directChatMapping() {
return new DirectChatMapping();
}
}

View File

@ -0,0 +1,55 @@
package org.mercury_im.messenger.data.di;
import org.mercury_im.messenger.data.repository.AccountRepository;
import org.mercury_im.messenger.data.repository.ContactRepository;
import org.mercury_im.messenger.data.repository.DirectChatRepository;
import org.mercury_im.messenger.data.repository.EntityCapsRepository;
import org.mercury_im.messenger.data.repository.XmppAccountRepository;
import org.mercury_im.messenger.data.repository.XmppDirectChatRepository;
import org.mercury_im.messenger.data.repository.XmppContactRepository;
import org.mercury_im.messenger.util.ThreadUtils;
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import io.reactivex.Scheduler;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
@Module
public class RepositoryModule {
@Provides
@Singleton
public static AccountRepository provideAccountRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler) {
return new XmppAccountRepository(data, ioScheduler, uiScheduler);
}
@Provides
@Singleton
public static DirectChatRepository provideChatRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler) {
return new XmppDirectChatRepository(data, ioScheduler, uiScheduler);
}
@Provides
@Singleton
public static EntityCapsRepository provideCapsRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler) {
return new EntityCapsRepository(data, ioScheduler, uiScheduler);
}
@Provides
@Singleton
public static ContactRepository provideRosterRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler) {
return new XmppContactRepository(data, ioScheduler, uiScheduler);
}
}

View File

@ -1,52 +0,0 @@
package org.mercury_im.messenger.data.di;
import org.mercury_im.messenger.data.repository.ChatRepository;
import org.mercury_im.messenger.data.repository.EntityCapsRepository;
import org.mercury_im.messenger.data.repository.ReactiveXmppAccountRepository;
import org.mercury_im.messenger.data.repository.RosterRepository;
import org.mercury_im.messenger.util.ThreadUtils;
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import io.reactivex.Scheduler;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
@Module
public class RequeryModule {
@Provides
@Singleton
public static ReactiveXmppAccountRepository provideAccountRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler) {
return new ReactiveXmppAccountRepository(data, ioScheduler, uiScheduler);
}
@Provides
@Singleton
public static ChatRepository provideChatRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler) {
return new ChatRepository(data, ioScheduler, uiScheduler);
}
@Provides
@Singleton
public static EntityCapsRepository provideCapsRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler) {
return new EntityCapsRepository(data, ioScheduler, uiScheduler);
}
@Provides
@Singleton
public static RosterRepository provideRosterRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler) {
return new RosterRepository(data, ioScheduler, uiScheduler);
}
}

View File

@ -5,9 +5,25 @@ import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.entity.IAccount;
import org.mercury_im.messenger.entity.PasswordAuthentication;
public class AccountMapping {
public class AccountMapping implements Mapping<Account, AccountModel> {
public static Account modelToEntity(AccountModel model) {
@Override
public AccountModel entityToData(Account entity) {
if (entity == null) {
return null;
}
AccountModel model = new AccountModel();
model.setId(entity.getId());
model.setPassword(entity.getAuthentication().getPassword());
model.setAddress(entity.getAddress());
model.setEnabled(entity.isEnabled());
return model;
}
@Override
public Account dataToEntity(AccountModel model) {
if (model == null) {
return null;
}
@ -20,17 +36,4 @@ public class AccountMapping {
return entity;
}
public static AccountModel createModelFromEntity(Account entity) {
if (entity == null) {
return null;
}
AccountModel model = new AccountModel();
model.setPassword(entity.getAuthentication().getPassword());
model.setAddress(entity.getAddress());
model.setEnabled(entity.isEnabled());
return model;
}
}

View File

@ -0,0 +1,35 @@
package org.mercury_im.messenger.data.mapping;
import org.mercury_im.messenger.data.model.DirectChatModel;
import org.mercury_im.messenger.entity.chat.DirectChat;
import org.mercury_im.messenger.entity.chat.IDirectChat;
import org.mercury_im.messenger.entity.contact.Peer;
import javax.inject.Inject;
public class DirectChatMapping implements Mapping<DirectChat, DirectChatModel> {
@Inject
AccountMapping accountMapping;
@Inject
PeerMapping peerMapping;
@Override
public DirectChatModel entityToData(DirectChat entity) {
DirectChatModel model = new DirectChatModel();
model.setPeer(peerMapping.entityToData(entity.getPeer()));
//TODO: set iD
return model;
}
@Override
public DirectChat dataToEntity(DirectChatModel data) {
IDirectChat entity = new IDirectChat();
entity.setId(data.getId());
Peer peer = peerMapping.dataToEntity(data.getPeer());
entity.setPeer(peer);
entity.setAccount(peer.getAccount());
return entity;
}
}

View File

@ -0,0 +1,8 @@
package org.mercury_im.messenger.data.mapping;
public interface Mapping<E, D> {
D entityToData(E entity);
E dataToEntity(D data);
}

View File

@ -0,0 +1,31 @@
package org.mercury_im.messenger.data.mapping;
import org.mercury_im.messenger.data.model.PeerModel;
import org.mercury_im.messenger.entity.contact.IPeer;
import org.mercury_im.messenger.entity.contact.Peer;
import javax.inject.Inject;
public class PeerMapping implements Mapping<Peer, PeerModel> {
@Inject
AccountMapping accountMapping;
@Override
public PeerModel entityToData(Peer entity) {
PeerModel model = new PeerModel();
model.setAccount(accountMapping.entityToData(entity.getAccount()));
model.setAddress(entity.getAddress());
return model;
}
@Override
public Peer dataToEntity(PeerModel data) {
Peer peer = new IPeer();
peer.setAccount(accountMapping.dataToEntity(data.getAccount()));
peer.setAddress(data.getAddress());
peer.setId(data.getId());
return peer;
}
}

View File

@ -6,12 +6,14 @@ import io.requery.Generated;
import io.requery.Key;
import io.requery.Persistable;
import io.requery.Table;
import lombok.Getter;
import lombok.Setter;
@Table(name = "accounts")
@Entity
public abstract class AbstractAccountModel implements Persistable {
@Key @Generated
@Key
long id;
@Column(nullable = false)
@ -21,7 +23,7 @@ public abstract class AbstractAccountModel implements Persistable {
String password;
boolean enabled;
String rosterVersion;
@Override

View File

@ -11,12 +11,15 @@ import io.requery.Key;
import io.requery.OneToOne;
import io.requery.Persistable;
import io.requery.Table;
import lombok.Setter;
@Entity
@Table(name = "contacts")
public abstract class AbstractContactModel implements Persistable {
@Key @Generated
@Key
@Generated
@Setter
long id;
@OneToOne

View File

@ -7,16 +7,18 @@ import io.requery.Key;
import io.requery.OneToOne;
import io.requery.Persistable;
import io.requery.Table;
import lombok.Setter;
@Entity
@Table(name = "chats")
public abstract class AbstractChatModel implements Persistable {
public abstract class AbstractDirectChatModel implements Persistable {
@Key @Generated
@Setter
long id;
@OneToOne
@ForeignKey
@ForeignKey(referencedColumn = "id")
PeerModel peer;
boolean displayed;

View File

@ -0,0 +1,27 @@
package org.mercury_im.messenger.data.model;
import io.requery.Entity;
import io.requery.ForeignKey;
import io.requery.Generated;
import io.requery.Key;
import io.requery.ManyToOne;
import io.requery.OneToOne;
import io.requery.Table;
import lombok.Setter;
@Entity
@Table(name = "direct_messages")
public class AbstractDirectMessagesRelation {
@Key @Generated
@Setter
long id;
@OneToOne
@ForeignKey(referencedColumn = "id")
DirectChatModel chat;
@ManyToOne
@ForeignKey(referencedColumn = "id")
MessageModel message;
}

View File

@ -2,15 +2,19 @@ package org.mercury_im.messenger.data.model;
import io.requery.Column;
import io.requery.Entity;
import io.requery.Generated;
import io.requery.Key;
import io.requery.Persistable;
import io.requery.Table;
import lombok.Setter;
@Table(name = "entity_caps")
@Entity
public abstract class AbstractEntityCapsModel implements Persistable {
@Key
@Generated
@Setter
String nodeVer;
@Column(nullable = false)

View File

@ -0,0 +1,29 @@
package org.mercury_im.messenger.data.model;
import io.requery.Column;
import io.requery.Entity;
import io.requery.Generated;
import io.requery.Key;
import io.requery.Persistable;
import io.requery.Table;
import lombok.Setter;
@Entity
@Table(name = "groupchats")
public abstract class AbstractGroupChatModel implements Persistable {
@Key @Generated
@Setter
long id;
// TODO: Add Account?
@Column(nullable = false)
String address;
@Column
String name;
@Column
boolean auto_join;
}

View File

@ -0,0 +1,27 @@
package org.mercury_im.messenger.data.model;
import io.requery.Entity;
import io.requery.ForeignKey;
import io.requery.Generated;
import io.requery.Key;
import io.requery.ManyToOne;
import io.requery.OneToOne;
import io.requery.Table;
import lombok.Setter;
@Entity
@Table(name = "group_messages")
public class AbstractGroupMessagesRelation {
@Key @Generated
@Setter
long id;
@OneToOne
@ForeignKey(referencedColumn = "id")
GroupChatModel chat;
@ManyToOne
@ForeignKey(referencedColumn = "id")
MessageModel message;
}

View File

@ -1,22 +0,0 @@
package org.mercury_im.messenger.data.model;
import io.requery.Entity;
import io.requery.ForeignKey;
import io.requery.Key;
import io.requery.OneToOne;
import io.requery.Persistable;
import io.requery.Table;
@Entity
@Table(name = "last_messages")
public abstract class AbstractLastChatMessageRelation implements Persistable {
@Key
@OneToOne
@ForeignKey
ChatModel chat;
@OneToOne
@ForeignKey
MessageModel message;
}

View File

@ -1,22 +0,0 @@
package org.mercury_im.messenger.data.model;
import io.requery.Entity;
import io.requery.ForeignKey;
import io.requery.Key;
import io.requery.OneToOne;
import io.requery.Persistable;
import io.requery.Table;
@Entity
@Table(name = "last_read_messages")
public abstract class AbstractLastReadChatMessageRelation implements Persistable {
@Key
@OneToOne
@ForeignKey
ChatModel chat;
@OneToOne
@ForeignKey
MessageModel message;
}

View File

@ -10,18 +10,16 @@ import io.requery.Key;
import io.requery.ManyToOne;
import io.requery.Persistable;
import io.requery.Table;
import lombok.Setter;
@Entity
@Table(name = "messages")
public abstract class AbstractMessageModel implements Persistable {
@Key @Generated
@Setter
long id;
@ForeignKey(referencedColumn = "id")
@ManyToOne
ChatModel chat;
String body;
@Column(name = "\"timestamp\"", nullable = false)

View File

@ -2,20 +2,24 @@ package org.mercury_im.messenger.data.model;
import io.requery.Column;
import io.requery.Entity;
import io.requery.ForeignKey;
import io.requery.Generated;
import io.requery.Key;
import io.requery.ManyToOne;
import io.requery.Persistable;
import io.requery.Table;
import lombok.Setter;
@Entity
@Table(name = "peers")
public abstract class AbstractPeerModel implements Persistable {
@Key @Generated
@Setter
long id;
@ManyToOne
@ForeignKey(referencedColumn = "id")
AccountModel account;
@Column(nullable = false)

View File

@ -7,6 +7,7 @@ import io.requery.Key;
import io.requery.ManyToOne;
import io.requery.Persistable;
import io.requery.Table;
import lombok.Setter;
@Entity
@Table(name = "sasl_auth")
@ -14,6 +15,7 @@ public abstract class AbstractSaslAuthenticationResultModel implements Persistab
@Key
@ManyToOne
@Setter
AccountModel account;
SaslCondition saslCondition;

View File

@ -1,89 +0,0 @@
package org.mercury_im.messenger.data.repository;
import org.mercury_im.messenger.util.ThreadUtils;
import javax.inject.Named;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.Single;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
import io.requery.reactivex.ReactiveResult;
public abstract class AbstractRepository<E extends Persistable> extends RequeryRepository {
private final Class<E> modelType;
protected AbstractRepository(Class<E> modelType,
ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(data, subscriberScheduler, observerScheduler);
this.modelType = modelType;
}
// CRUD
public Single<E> insert(E model) {
return data().insert(model)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Single<Iterable<E>> insert(Iterable<E> models) {
return data().insert(models)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Single<E> upsert(E model) {
return data().upsert(model)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Single<Iterable<E>> upsert(Iterable<E> models) {
return data().upsert(models)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Single<E> update(E model) {
return data().update(model)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Single<Iterable<E>> update(Iterable<E> models) {
return data().update(models)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<ReactiveResult<E>> getAll() {
return data().select(modelType)
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Completable delete(E model) {
return data().delete(model)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Completable delete(Iterable<E> models) {
return data().delete(models)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Single<Integer> deleteAll() {
return data().delete(modelType)
.get().single();
}
}

View File

@ -1,91 +0,0 @@
package org.mercury_im.messenger.data.repository;
import org.mercury_im.messenger.data.model.ChatModel;
import org.mercury_im.messenger.data.model.ContactModel;
import org.mercury_im.messenger.data.model.PeerModel;
import org.mercury_im.messenger.util.ThreadUtils;
import org.mercury_im.messenger.data.util.ChatAndPossiblyContact;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
import io.requery.reactivex.ReactiveResult;
public class ChatRepository extends AbstractRepository<ChatModel> {
private final Logger LOGGER = Logger.getLogger(ChatRepository.class.getName());
@Inject
public ChatRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(ChatModel.class, data, subscriberScheduler, observerScheduler);
}
public Observable<ReactiveResult<ChatModel>> getChatWith(PeerModel entityModel) {
return getChatWith(entityModel.getAccount().getId(), entityModel.getAddress());
}
public Observable<ReactiveResult<ChatModel>> getChatWith(long accountId, String address) {
return data().select(ChatModel.class).join(PeerModel.class).on(ChatModel.PEER_ID.eq(PeerModel.ID))
.where(PeerModel.ACCOUNT_ID.eq(accountId).and(PeerModel.ADDRESS.eq(address)))
.get().observableResult()
.doOnError(error -> LOGGER.log(Level.WARNING, "An error occurred while getting chat", error))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<ReactiveResult<ChatModel>> getVisibleChats() {
return data().select(ChatModel.class).where(ChatModel.DISPLAYED.eq(true))
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<List<ChatAndPossiblyContact>> getChatsAndContacts() {
return Observable.fromCallable(() -> {
List<ChatModel> chats = data().select(ChatModel.class)
.from(ChatModel.class).leftJoin(ContactModel.class).on(ChatModel.PEER_ID.eq(ContactModel.ENTITY_ID))
.get().toList();
List<ChatAndPossiblyContact> chatsAndContacts = new ArrayList<>(chats.size());
for (ChatModel chatModel : chats) {
ContactModel contactModel = data().select(ContactModel.class).from(ContactModel.class).where(ContactModel.ENTITY_ID.eq(chatModel.getPeer().getId()))
.get().first();
chatsAndContacts.add(new ChatAndPossiblyContact(chatModel, contactModel));
}
return chatsAndContacts;
})
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<ChatAndPossiblyContact> getChatAndContact(long accountId, String address) {
return Observable.fromCallable(() -> {
ChatModel chat = data().select(ChatModel.class)
.from(ChatModel.class).join(PeerModel.class).on(ChatModel.PEER_ID.eq(PeerModel.ID))
.leftJoin(ContactModel.class).on(PeerModel.ID.eq(ContactModel.ENTITY_ID))
.where(PeerModel.ACCOUNT_ID.eq(accountId).and(PeerModel.ADDRESS.eq(address)))
.get().firstOrNull();
if (chat == null) {
return null;
}
ContactModel contactModel = data().select(ContactModel.class).from(ContactModel.class)
.where(ContactModel.ENTITY_ID.eq(chat.getPeer().getId()))
.get().firstOrNull();
return new ChatAndPossiblyContact(chat, contactModel);
})
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
}

View File

@ -1,6 +1,5 @@
package org.mercury_im.messenger.data.repository;
import org.mercury_im.messenger.data.model.EntityCapsModel;
import org.mercury_im.messenger.util.ThreadUtils;
import javax.inject.Inject;
@ -10,12 +9,12 @@ import io.reactivex.Scheduler;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
public class EntityCapsRepository extends AbstractRepository<EntityCapsModel> {
public class EntityCapsRepository extends RequeryRepository {
@Inject
public EntityCapsRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(EntityCapsModel.class, data, subscriberScheduler, observerScheduler);
super(data, subscriberScheduler, observerScheduler);
}
}

View File

@ -1,66 +0,0 @@
package org.mercury_im.messenger.data.repository;
import org.mercury_im.messenger.data.model.ChatModel;
import org.mercury_im.messenger.data.model.ContactModel;
import org.mercury_im.messenger.data.model.MessageModel;
import org.mercury_im.messenger.data.model.PeerModel;
import org.mercury_im.messenger.util.ThreadUtils;
import javax.inject.Inject;
import javax.inject.Named;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
import io.requery.reactivex.ReactiveResult;
public class MessageRepository extends AbstractRepository<MessageModel> {
@Inject
public MessageRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(MessageModel.class, data, subscriberScheduler, observerScheduler);
}
public Observable<ReactiveResult<MessageModel>> getAllMessagesOfChat(ChatModel chat) {
return getAllMessagesOfChat(chat.getId());
}
public Observable<ReactiveResult<MessageModel>> getAllMessagesOfChat(long chatId) {
return data().select(MessageModel.class).where(MessageModel.CHAT_ID.eq(chatId))
.orderBy(MessageModel.TIMESTAMP.asc())
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<ReactiveResult<MessageModel>> getAllMessagesOfEntity(PeerModel entity) {
return getAllMessagesOfEntity(entity.getId());
}
public Observable<ReactiveResult<MessageModel>> getAllMessagesOfEntity(long entityId) {
return data().select(MessageModel.class).from(MessageModel.class)
.join(ChatModel.class).on(MessageModel.CHAT_ID.eq(ChatModel.ID))
.where(ChatModel.PEER_ID.eq(entityId))
.orderBy(MessageModel.TIMESTAMP.asc())
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<ReactiveResult<MessageModel>> getAllMessagesOfContact(ContactModel contact) {
return getAllMessagesOfContact(contact.getId());
}
public Observable<ReactiveResult<MessageModel>> getAllMessagesOfContact(long contactId) {
return data().select(MessageModel.class).join(ChatModel.class).on(MessageModel.CHAT_ID.eq(ChatModel.ID))
.join(PeerModel.class).on(ChatModel.PEER_ID.eq(PeerModel.ID))
.join(ContactModel.class).on(PeerModel.ID.eq(ContactModel.ENTITY_ID))
.orderBy(MessageModel.TIMESTAMP.asc())
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
}

View File

@ -1,200 +0,0 @@
package org.mercury_im.messenger.data.repository;
import org.mercury_im.messenger.data.model.AccountModel;
import org.mercury_im.messenger.data.model.ContactModel;
import org.mercury_im.messenger.data.model.PeerModel;
import org.mercury_im.messenger.util.ThreadUtils;
import javax.inject.Inject;
import javax.inject.Named;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.Single;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
import io.requery.reactivex.ReactiveResult;
public class RosterRepository extends RequeryRepository {
@Inject
public RosterRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(data, subscriberScheduler, observerScheduler);
}
/*
ContactModel related methods
*/
public Observable<ReactiveResult<ContactModel>> getAllContactsOfAccount(AccountModel accountModel) {
return getAllContactsOfAccount(accountModel.getId());
}
public Observable<ReactiveResult<ContactModel>> getAllContactsOfAccount(long accountId) {
return data().select(ContactModel.class).join(PeerModel.class).on(ContactModel.ENTITY_ID.eq(PeerModel.ID))
.where(PeerModel.ACCOUNT_ID.eq(accountId))
.get().observableResult()
.subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
public Single<ContactModel> upsertContact(ContactModel contact) {
return data().upsert(contact).subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
public Completable deleteContact(ContactModel contact) {
return data().delete(contact).subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
public Completable deleteContact(long accountId, String address) {
return data().delete(ContactModel.class).from(ContactModel.class)
.join(PeerModel.class).on(ContactModel.ENTITY_ID.eq(PeerModel.ID))
.where(PeerModel.ACCOUNT_ID.eq(accountId).and(PeerModel.ADDRESS.eq(address)))
.get().single().ignoreElement()
.subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
public Single<Integer> deleteAllContactsOfAccount(AccountModel account) {
return deleteAllContactsOfAccount(account.getId());
}
public Single<Integer> deleteAllContactsOfAccount(long accountId) {
return data().delete(ContactModel.class).from(ContactModel.class)
.join(PeerModel.class).on(ContactModel.ENTITY_ID.eq(PeerModel.ID))
.where(PeerModel.ACCOUNT_ID.eq(accountId))
.get().single()
.subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
/*
PeerModel related methods
*/
public Observable<ReactiveResult<PeerModel>> getAllEntitiesOfAccount(AccountModel account) {
return getAllEntitiesOfAccount(account.getId());
}
public Observable<ReactiveResult<PeerModel>> getAllEntitiesOfAccount(long accountId) {
return data().select(PeerModel.class).where(PeerModel.ACCOUNT_ID.eq(accountId))
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<ReactiveResult<PeerModel>> getEntityById(long entityId) {
return data().select(PeerModel.class).where(PeerModel.ID.eq(entityId))
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<ReactiveResult<PeerModel>> getEntityByJid(AccountModel account, String address) {
return getEntityByJid(account.getId(), address);
}
public Observable<ReactiveResult<PeerModel>> getEntityByJid(long accountId, String address) {
return data().select(PeerModel.class)
.where(PeerModel.ACCOUNT_ID.eq(accountId).and(PeerModel.ADDRESS.eq(address)))
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Single<PeerModel> getOrCreateEntity(long accountId, String address) {
return Single.fromCallable(() -> {
AccountModel account = data().select(AccountModel.class).where(AccountModel.ID.eq(accountId))
.get().first();
return getOrCreateEntity(account, address).blockingGet();
})
.observeOn(observerScheduler())
.subscribeOn(subscriberScheduler());
}
public Single<PeerModel> getOrCreateEntity(AccountModel account, String address) {
return Single.fromCallable(() -> {
PeerModel entity = data().select(PeerModel.class)
.where(PeerModel.ACCOUNT_ID.eq(account.getId()).and(PeerModel.ADDRESS.eq(address)))
.get().firstOrNull();
if (entity == null) {
entity = new PeerModel();
entity.setAccount(account);
entity.setAddress(address);
entity = data().insert(entity).blockingGet();
}
return entity;
})
.observeOn(observerScheduler())
.subscribeOn(subscriberScheduler());
}
public Single<PeerModel> upsertEntity(PeerModel entity) {
return data().upsert(entity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Completable deleteEntity(PeerModel entity) {
return data().delete(entity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
/*
RosterVersion related methods
*/
public Single<Integer> updateRosterVersion(long accountId, String rosterVer) {
return data().update(AccountModel.class).set(AccountModel.ROSTER_VERSION, rosterVer)
.where(AccountModel.ID.eq(accountId))
.get().single()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<String> getRosterVersion(AccountModel account) {
return getRosterVersion(account.getId());
}
public Observable<String> getRosterVersion(long accountId) {
return data().select(AccountModel.class).where(AccountModel.ID.eq(accountId))
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler())
.map(accountModels -> {
AccountModel accountModel = accountModels.firstOrNull();
if (accountModel == null || accountModel.getRosterVersion() == null) {
return "";
}
return accountModel.getRosterVersion();
});
}
public Single<AccountModel> updateRosterVersion(AccountModel account, String rosterVersion) {
account.setRosterVersion(rosterVersion);
return data().upsert(account)
.subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
public Observable<ReactiveResult<ContactModel>> getContact(AccountModel account, String address) {
return getContact(account.getId(), address);
}
public Observable<ReactiveResult<ContactModel>> getContact(long accountId, String address) {
return data().select(ContactModel.class).from(ContactModel.class)
.join(PeerModel.class).on(ContactModel.ENTITY_ID.eq(PeerModel.ID))
.where(PeerModel.ACCOUNT_ID.eq(accountId).and(PeerModel.ADDRESS.eq(address)))
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<ReactiveResult<ContactModel>> getAllContacts() {
return data().select(ContactModel.class)
.get().observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
}

View File

@ -21,22 +21,24 @@ import io.requery.Persistable;
import io.requery.query.ResultDelegate;
import io.requery.reactivex.ReactiveEntityStore;
public class ReactiveXmppAccountRepository
public class XmppAccountRepository
extends RequeryRepository
implements AccountRepository {
@Inject
public ReactiveXmppAccountRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
AccountMapping mapping;
@Inject
public XmppAccountRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(data, subscriberScheduler, observerScheduler);
}
@Override
public Single<Account> insertAccount(Account account) {
return data().insert(AccountMapping.createModelFromEntity(account))
.map(AccountMapping::modelToEntity)
return data().insert(mapping.entityToData(account))
.map(mapping::dataToEntity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -46,7 +48,7 @@ public class ReactiveXmppAccountRepository
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(accountId))
.get().observableResult()
.map(result -> new Optional<>(AccountMapping.modelToEntity(result.firstOrNull())))
.map(result -> new Optional<>(mapping.dataToEntity(result.firstOrNull())))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -56,7 +58,7 @@ public class ReactiveXmppAccountRepository
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(accountId))
.get().maybe()
.map(AccountMapping::modelToEntity)
.map(mapping::dataToEntity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -66,7 +68,7 @@ public class ReactiveXmppAccountRepository
return data().select(AccountModel.class)
.where(AccountModel.ADDRESS.eq(address))
.get().observableResult()
.map(result -> new Optional<>(AccountMapping.modelToEntity(result.firstOrNull())))
.map(result -> new Optional<>(mapping.dataToEntity(result.firstOrNull())))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -76,7 +78,7 @@ public class ReactiveXmppAccountRepository
return data().select(AccountModel.class)
.where(AccountModel.ADDRESS.eq(address))
.get().maybe()
.map(AccountMapping::modelToEntity)
.map(mapping::dataToEntity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -89,7 +91,7 @@ public class ReactiveXmppAccountRepository
.map(list -> {
List<Account> entities = new ArrayList<>(list.size());
for (AccountModel model : list) {
entities.add(AccountMapping.modelToEntity(model));
entities.add(mapping.dataToEntity(model));
}
return entities;
})
@ -113,7 +115,7 @@ public class ReactiveXmppAccountRepository
model.setAddress(account.getAddress());
// write the updated model back
model = data().update(model).blockingGet();
return AccountMapping.modelToEntity(model);
return mapping.dataToEntity(model);
})
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
@ -126,7 +128,7 @@ public class ReactiveXmppAccountRepository
.where(AccountModel.ID.eq(account.getId()))
.get().maybe()
// If it does not exist, create a new model from the entity
.switchIfEmpty(data().insert(AccountMapping.createModelFromEntity(account)))
.switchIfEmpty(data().insert(mapping.entityToData(account)))
// finally
.map(model -> {
// update the model
@ -135,7 +137,7 @@ public class ReactiveXmppAccountRepository
model.setAddress(account.getAddress());
// write the updated model back
model = data().update(model).blockingGet();
return AccountMapping.modelToEntity(model);
return mapping.dataToEntity(model);
})
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());

View File

@ -0,0 +1,75 @@
package org.mercury_im.messenger.data.repository;
import org.mercury_im.messenger.data.util.Optional;
import org.mercury_im.messenger.entity.contact.Contact;
import org.mercury_im.messenger.util.ThreadUtils;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.Single;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
public class XmppContactRepository
extends RequeryRepository
implements ContactRepository {
@Inject
public XmppContactRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(data, subscriberScheduler, observerScheduler);
}
@Override
public Single<Contact> insertContact(Contact contact) {
return null;
}
@Override
public Observable<Optional<Contact>> observeContact(long contactId) {
return null;
}
@Override
public Maybe<Contact> getContact(long contactId) {
return null;
}
@Override
public Observable<Optional<Contact>> observeContactByAddress(String address) {
return null;
}
@Override
public Maybe<Contact> getContactByAddress(String address) {
return null;
}
@Override
public Observable<List<Contact>> observeAllContacts() {
return null;
}
@Override
public Single<Contact> updateContact(Contact contact) {
return null;
}
@Override
public Single<Contact> upsertContact(Contact contact) {
return null;
}
@Override
public Completable deleteContact(Contact contact) {
return null;
}
}

View File

@ -0,0 +1,99 @@
package org.mercury_im.messenger.data.repository;
import org.mercury_im.messenger.data.util.Optional;
import org.mercury_im.messenger.entity.chat.DirectChat;
import org.mercury_im.messenger.entity.contact.Peer;
import org.mercury_im.messenger.entity.message.Message;
import java.util.List;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.Single;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
public class XmppDirectChatRepository
extends RequeryRepository
implements DirectChatRepository {
public XmppDirectChatRepository(
ReactiveEntityStore<Persistable> data,
Scheduler subscriberScheduler,
Scheduler observerScheduler) {
super(data, subscriberScheduler, observerScheduler);
}
@Override
public Single<DirectChat> insertDirectChat(DirectChat chat) {
return null;
}
@Override
public Observable<Optional<DirectChat>> observeDirectChat(long chatId) {
return null;
}
@Override
public Maybe<DirectChat> getDirectChat(long chatId) {
return null;
}
@Override
public Observable<Optional<DirectChat>> observeDirectChatByInterlocutor(Peer peer) {
return null;
}
@Override
public Maybe<DirectChat> getDirectChatByInterlocutor(Peer peer) {
return null;
}
@Override
public Observable<List<DirectChat>> observeAllDirectChats() {
return null;
}
@Override
public Single<DirectChat> updateDirectChat(DirectChat chat) {
return null;
}
@Override
public Single<DirectChat> upsertDirectChat(DirectChat chat) {
return null;
}
@Override
public Completable deleteDirectChat(DirectChat chat) {
return null;
}
@Override
public Single<Message> insertMessage(DirectChat chat, Message message) {
return null;
}
@Override
public Observable<List<Message>> observeMessages(DirectChat chat) {
return null;
}
@Override
public Single<Message> updateMessage(Message message) {
return null;
}
@Override
public Single<Message> upsertMessage(DirectChat chat, Message message) {
return null;
}
@Override
public Completable deleteMessage(Message message) {
return null;
}
}

View File

@ -1,24 +0,0 @@
package org.mercury_im.messenger.data.util;
import org.mercury_im.messenger.data.model.ChatModel;
import org.mercury_im.messenger.data.model.ContactModel;
public class ChatAndPossiblyContact {
private final ChatModel chat;
private final ContactModel contact;
public ChatAndPossiblyContact(ChatModel chat, ContactModel contact) {
this.chat = chat;
this.contact = contact;
}
public ChatModel getChat() {
return chat;
}
public ContactModel getContact() {
return contact;
}
}

View File

@ -0,0 +1,14 @@
package org.mercury_im.messenger.di.component;
import org.mercury_im.messenger.Messenger;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component
public interface MessengerComponent {
void inject(Messenger messenger);
}

View File

@ -0,0 +1,5 @@
package org.mercury_im.messenger.di.module;
public class MessengerModule {
}