Begin work on stricter clean architecture.

* Created modules entity, entity_xmpp, which contain entities and their respective XMPP implementations
* Started process of inverting dependency between core and persistence layers
This commit is contained in:
Paul Schaub 2019-11-03 06:33:52 +01:00
parent e5dfa3c030
commit da9179b049
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
96 changed files with 1227 additions and 206 deletions

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>

View File

@ -80,11 +80,12 @@
<option value="$PROJECT_DIR$/libs/Smack/smack-xmlparser" />
<option value="$PROJECT_DIR$/libs/Smack/smack-xmlparser-stax" />
<option value="$PROJECT_DIR$/libs/Smack/smack-xmlparser-xpp3" />
<option value="$PROJECT_DIR$/persistence" />
<option value="$PROJECT_DIR$/thread_utils" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="testRunner" value="PLATFORM" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/classes" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK" />
</project>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/libs/Smack" vcs="Git" />
</component>
</project>

View File

@ -9,13 +9,13 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.persistence.requery.entity.AccountModel;
import org.mercury_im.messenger.persistence.requery.entity.ChatModel;
import org.mercury_im.messenger.persistence.requery.entity.ContactModel;
import org.mercury_im.messenger.persistence.requery.entity.EntityModel;
import org.mercury_im.messenger.persistence.requery.entity.LastReadChatMessageRelation;
import org.mercury_im.messenger.persistence.requery.entity.MessageModel;
import org.mercury_im.messenger.persistence.requery.entity.Models;
import org.mercury_im.messenger.xmpp.requery.entity.AccountModel;
import org.mercury_im.messenger.xmpp.requery.entity.ChatModel;
import org.mercury_im.messenger.xmpp.requery.entity.ContactModel;
import org.mercury_im.messenger.xmpp.requery.entity.EntityModel;
import org.mercury_im.messenger.xmpp.requery.entity.LastReadChatMessageRelation;
import org.mercury_im.messenger.xmpp.requery.entity.MessageModel;
import org.mercury_im.messenger.xmpp.requery.entity.Models;
import org.mercury_im.messenger.core.requery.enums.SubscriptionDirection;
import io.reactivex.disposables.Disposable;

View File

@ -11,7 +11,7 @@ import android.os.Build;
import org.mercury_im.messenger.core.centers.ConnectionCenter;
import org.mercury_im.messenger.core.connection.MercuryConfiguration;
import org.mercury_im.messenger.persistence.util.ChatAndPossiblyContact;
import org.mercury_im.messenger.xmpp.util.ChatAndPossiblyContact;
import org.mercury_im.messenger.core.util.ContactNameUtil;
import org.mercury_im.messenger.di.component.AppComponent;
import org.mercury_im.messenger.di.component.DaggerAppComponent;

View File

@ -7,7 +7,7 @@ import android.content.Intent;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import org.mercury_im.messenger.persistence.entity.ChatModel;
import org.mercury_im.messenger.xmpp.model.ChatModel;
import org.mercury_im.messenger.ui.chat.ChatActivity;
public class Notifications {

View File

@ -3,7 +3,7 @@ package org.mercury_im.messenger.di.module;
import android.app.Application;
import org.mercury_im.messenger.BuildConfig;
import org.mercury_im.messenger.persistence.entity.Models;
import org.mercury_im.messenger.xmpp.model.Models;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import javax.inject.Named;

View File

@ -8,7 +8,7 @@ import dagger.Provides;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.core.NotificationManager;
import org.mercury_im.messenger.core.di.CenterModule;
import org.mercury_im.messenger.persistence.di.RequeryModule;
import org.mercury_im.messenger.xmpp.di.RequeryModule;
import javax.inject.Singleton;

View File

@ -15,8 +15,8 @@ import com.google.android.material.navigation.NavigationView;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.persistence.repository.ChatRepository;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import org.mercury_im.messenger.xmpp.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

@ -11,7 +11,6 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -23,14 +22,13 @@ import io.reactivex.schedulers.Schedulers;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.packet.Message;
import org.jxmpp.jid.EntityBareJid;
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.persistence.repository.ChatRepository;
import org.mercury_im.messenger.xmpp.repository.ChatRepository;
import java.util.logging.Level;
import java.util.logging.Logger;

View File

@ -7,13 +7,13 @@ import androidx.lifecycle.ViewModel;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.core.centers.ConnectionCenter;
import org.mercury_im.messenger.persistence.entity.ChatModel;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.persistence.entity.EntityModel;
import org.mercury_im.messenger.persistence.entity.MessageModel;
import org.mercury_im.messenger.persistence.repository.ChatRepository;
import org.mercury_im.messenger.persistence.repository.MessageRepository;
import org.mercury_im.messenger.persistence.repository.RosterRepository;
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.xmpp.repository.ChatRepository;
import org.mercury_im.messenger.xmpp.repository.MessageRepository;
import org.mercury_im.messenger.xmpp.repository.RosterRepository;
import java.util.List;

View File

@ -10,7 +10,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.entity.MessageModel;
import org.mercury_im.messenger.xmpp.model.MessageModel;
import org.mercury_im.messenger.ui.util.MessageBackgroundDrawable;
import java.util.ArrayList;

View File

@ -16,7 +16,7 @@ import androidx.appcompat.view.ActionMode;
import androidx.recyclerview.widget.RecyclerView;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.entity.ChatModel;
import org.mercury_im.messenger.xmpp.model.ChatModel;
import org.mercury_im.messenger.ui.chat.ChatActivity;
import org.mercury_im.messenger.ui.util.AbstractRecyclerViewAdapter;
import org.mercury_im.messenger.util.ColorUtil;

View File

@ -5,9 +5,9 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.persistence.entity.ChatModel;
import org.mercury_im.messenger.persistence.repository.ChatRepository;
import org.mercury_im.messenger.persistence.repository.MessageRepository;
import org.mercury_im.messenger.xmpp.model.ChatModel;
import org.mercury_im.messenger.xmpp.repository.ChatRepository;
import org.mercury_im.messenger.xmpp.repository.MessageRepository;
import java.util.List;

View File

@ -17,7 +17,7 @@ import com.google.android.material.floatingactionbutton.ExtendedFloatingActionBu
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import butterknife.BindView;
import butterknife.ButterKnife;

View File

@ -13,7 +13,7 @@ import androidx.recyclerview.widget.RecyclerView;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import org.mercury_im.messenger.ui.login.AccountsFragment.OnAccountListItemClickListener;
import org.mercury_im.messenger.util.AbstractDiffCallback;
import org.mercury_im.messenger.util.ColorUtil;

View File

@ -10,8 +10,8 @@ import androidx.lifecycle.MutableLiveData;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.core.centers.ConnectionCenter;
import org.mercury_im.messenger.core.connection.MercuryConnection;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import org.mercury_im.messenger.xmpp.repository.RequeryAccountRepository;
import java.util.List;
@ -22,7 +22,7 @@ import io.reactivex.disposables.CompositeDisposable;
public class AccountsViewModel extends AndroidViewModel {
@Inject
AccountRepository repository;
RequeryAccountRepository repository;
@Inject
ConnectionCenter connectionCenter;

View File

@ -15,7 +15,7 @@ import com.google.android.material.textfield.TextInputEditText;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import org.mercury_im.messenger.util.TextChangedListener;
import butterknife.BindView;

View File

@ -17,15 +17,15 @@ import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.core.centers.ConnectionCenter;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import org.mercury_im.messenger.xmpp.repository.RequeryAccountRepository;
import javax.inject.Inject;
public class LoginViewModel extends ViewModel {
@Inject
AccountRepository accountRepository;
RequeryAccountRepository accountRepository;
@Inject
ConnectionCenter connectionCenter;

View File

@ -6,8 +6,8 @@ import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.persistence.repository.RosterRepository;
import org.mercury_im.messenger.xmpp.model.ContactModel;
import org.mercury_im.messenger.xmpp.repository.RosterRepository;
import javax.inject.Inject;

View File

@ -13,7 +13,7 @@ import androidx.recyclerview.widget.RecyclerView;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.xmpp.model.ContactModel;
import org.mercury_im.messenger.ui.chat.ChatActivity;
import org.mercury_im.messenger.ui.util.AbstractRecyclerViewAdapter;
import org.mercury_im.messenger.util.ColorUtil;

View File

@ -7,8 +7,8 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.persistence.repository.RosterRepository;
import org.mercury_im.messenger.xmpp.model.ContactModel;
import org.mercury_im.messenger.xmpp.repository.RosterRepository;
import java.util.List;

View File

@ -8,8 +8,9 @@ sourceSets {
dependencies {
api project(':entity') // Entities
api project(':repository') // Repository
api project(":thread_utils")
api project(":persistence")
// Smack
// Not all of those are needed, but it may be a good idea to define those versions explicitly

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.core;
import org.mercury_im.messenger.persistence.util.ChatAndPossiblyContact;
import org.mercury_im.messenger.xmpp.util.ChatAndPossiblyContact;
public interface NotificationManager {

View File

@ -11,10 +11,10 @@ import org.jivesoftware.smackx.csi.ClientStateIndicationManager;
import org.jivesoftware.smackx.mam.MamManager;
import org.mercury_im.messenger.core.connection.MercuryConfiguration;
import org.mercury_im.messenger.core.connection.MercuryConnection;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.persistence.entity.ChatModel;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.persistence.repository.RosterRepository;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import org.mercury_im.messenger.xmpp.model.ChatModel;
import org.mercury_im.messenger.xmpp.repository.RequeryAccountRepository;
import org.mercury_im.messenger.xmpp.repository.RosterRepository;
import org.mercury_im.messenger.core.stores.EntityCapsStore;
import org.mercury_im.messenger.core.stores.PlainMessageStore;
import org.mercury_im.messenger.core.stores.RosterStore;
@ -41,7 +41,7 @@ public class ConnectionCenter {
private static final Logger LOGGER = Logger.getLogger(ConnectionCenter.class.getName());
// Injected
private final AccountRepository accountRepository;
private final RequeryAccountRepository accountRepository;
private final RosterRepository rosterRepository;
private final PlainMessageStore messageStore;
private final EntityCapsStore entityCapsStore;
@ -58,7 +58,7 @@ public class ConnectionCenter {
@Inject
public ConnectionCenter(EntityCapsStore capsStore,
PlainMessageStore messageStore,
AccountRepository accountRepository,
RequeryAccountRepository accountRepository,
RosterRepository rosterRepository) {
LOGGER.log(Level.INFO, "ConnectionCenter initialized");
this.entityCapsStore = capsStore;

View File

@ -2,11 +2,7 @@ package org.mercury_im.messenger.core.di;
import org.mercury_im.messenger.core.NotificationManager;
import org.mercury_im.messenger.core.centers.ConnectionCenter;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.persistence.repository.ChatRepository;
import org.mercury_im.messenger.persistence.repository.EntityCapsRepository;
import org.mercury_im.messenger.persistence.repository.MessageRepository;
import org.mercury_im.messenger.persistence.repository.RosterRepository;
import org.mercury_im.messenger.core.repository.AccountRepository;
import org.mercury_im.messenger.core.stores.EntityCapsStore;
import org.mercury_im.messenger.core.stores.PlainMessageStore;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.core.di;
import org.mercury_im.messenger.persistence.di.RequeryModule;
import org.mercury_im.messenger.xmpp.di.RequeryModule;
import javax.inject.Singleton;

View File

@ -4,13 +4,12 @@ import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smackx.caps.cache.EntityCapsPersistentCache;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
import org.mercury_im.messenger.persistence.entity.EntityCapsModel;
import org.mercury_im.messenger.persistence.repository.EntityCapsRepository;
import org.mercury_im.messenger.xmpp.model.EntityCapsModel;
import org.mercury_im.messenger.xmpp.repository.EntityCapsRepository;
import java.io.StringReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;

View File

@ -14,15 +14,15 @@ import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.core.NotificationManager;
import org.mercury_im.messenger.core.connection.MercuryConnection;
import org.mercury_im.messenger.persistence.entity.ChatModel;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.persistence.entity.EntityModel;
import org.mercury_im.messenger.persistence.entity.LastChatMessageRelation;
import org.mercury_im.messenger.persistence.entity.MessageModel;
import org.mercury_im.messenger.persistence.repository.ChatRepository;
import org.mercury_im.messenger.persistence.repository.MessageRepository;
import org.mercury_im.messenger.persistence.repository.RosterRepository;
import org.mercury_im.messenger.persistence.util.ChatAndPossiblyContact;
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.LastChatMessageRelation;
import org.mercury_im.messenger.xmpp.model.MessageModel;
import org.mercury_im.messenger.xmpp.repository.ChatRepository;
import org.mercury_im.messenger.xmpp.repository.MessageRepository;
import org.mercury_im.messenger.xmpp.repository.RosterRepository;
import org.mercury_im.messenger.xmpp.util.ChatAndPossiblyContact;
import java.util.ArrayList;
import java.util.Date;

View File

@ -2,12 +2,12 @@ package org.mercury_im.messenger.core.stores;
import org.jivesoftware.smack.roster.packet.RosterPacket;
import org.jxmpp.jid.Jid;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.persistence.entity.EntityModel;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.persistence.repository.RosterRepository;
import org.mercury_im.messenger.persistence.enums.SubscriptionDirection;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import org.mercury_im.messenger.xmpp.model.ContactModel;
import org.mercury_im.messenger.xmpp.model.EntityModel;
import org.mercury_im.messenger.xmpp.repository.RequeryAccountRepository;
import org.mercury_im.messenger.xmpp.repository.RosterRepository;
import org.mercury_im.messenger.xmpp.enums.SubscriptionDirection;
import java.util.ArrayList;
import java.util.Arrays;
@ -20,9 +20,7 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import io.reactivex.Scheduler;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Action;
import io.reactivex.schedulers.Schedulers;
public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.RosterStore {
@ -30,7 +28,7 @@ public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.Ro
private static final Logger LOGGER = Logger.getLogger(RosterStore.class.getName());
private final RosterRepository rosterRepository;
private final AccountRepository accountRepository;
private final RequeryAccountRepository accountRepository;
private AccountModel account;
private CompositeDisposable disposable = null;
@ -38,7 +36,7 @@ public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.Ro
private String rosterVersion;
@Inject
public RosterStore(RosterRepository rosterRepository, AccountRepository accountRepository) {
public RosterStore(RosterRepository rosterRepository, RequeryAccountRepository accountRepository) {
this.rosterRepository = rosterRepository;
this.accountRepository = accountRepository;
}

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.core.util;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.persistence.entity.EntityModel;
import org.mercury_im.messenger.xmpp.model.ContactModel;
import org.mercury_im.messenger.xmpp.model.EntityModel;
public class ContactNameUtil {

5
entity/README.md Normal file
View File

@ -0,0 +1,5 @@
# Entity
This module contains entity definitions for MercuryIM.
According to Robert C. Martins "Clean Architecture", entities form the inner most layer of the
program.

8
entity/build.gradle Normal file
View File

@ -0,0 +1,8 @@
apply plugin: 'java-library'
dependencies {
}
sourceCompatibility = "8"
targetCompatibility = "8"

View File

@ -0,0 +1,53 @@
package org.mercury_im.messenger.core.entity;
public abstract class AbstractAccount<
AD extends Address.UserAddress,
AU extends Account.AuthMethod>
implements Account<AD, AU> {
protected long id;
protected AD address;
protected AU authentication;
protected boolean enabled;
@Override
public void setId(long id) {
this.id = id;
}
@Override
public long getId() {
return id;
}
@Override
public void setAddress(AD address) {
this.address = address;
}
@Override
public AD getAddress() {
return address;
}
@Override
public void setAuthentication(AU authentication) {
this.authentication = authentication;
}
@Override
public AU getAuthentication() {
return authentication;
}
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public boolean isEnabled() {
return enabled;
}
}

View File

@ -0,0 +1,42 @@
package org.mercury_im.messenger.core.entity;
public class AbstractDirectChat<
IL extends Interlocutor<AC, AD>,
AC extends Account<AD, ?>,
AD extends Address.UserAddress>
implements DirectChat<IL, AC, AD> {
protected long id;
protected IL interlocutor;
protected AC account;
@Override
public IL getInterlocutor() {
return interlocutor;
}
@Override
public void setInterlocutor(IL interlocutor) {
this.interlocutor = interlocutor;
}
@Override
public long getId() {
return id;
}
@Override
public void setId(long id) {
this.id = id;
}
@Override
public AC getAccount() {
return account;
}
@Override
public void setAccount(AC account) {
this.account = account;
}
}

View File

@ -0,0 +1,53 @@
package org.mercury_im.messenger.core.entity;
public class AbstractGroupChat<
AC extends Account<AD, ?>,
AD extends Address.UserAddress,
RA extends Address.RoomAddress>
implements GroupChat<AC, AD, RA> {
private long id;
private AC account;
private RA roomAddress;
private String roomName;
@Override
public RA getRoomAddress() {
return roomAddress;
}
@Override
public void setRoomAddress(RA roomAddress) {
this.roomAddress = roomAddress;
}
@Override
public String getRoomName() {
return roomName;
}
@Override
public void setRoomName(String roomName) {
this.roomName = roomName;
}
@Override
public long getId() {
return id;
}
@Override
public void setId(long id) {
this.id = id;
}
@Override
public AC getAccount() {
return account;
}
@Override
public void setAccount(AC account) {
this.account = account;
}
}

View File

@ -0,0 +1,52 @@
package org.mercury_im.messenger.core.entity;
public class AbstractInterlocutor<
AC extends Account<AD, ?>,
AD extends Address.UserAddress>
implements Interlocutor<AC, AD> {
protected long id;
protected AC account;
protected AD address;
protected String name;
@Override
public long getId() {
return id;
}
@Override
public void setId(long id) {
this.id = id;
}
@Override
public AC getAccount() {
return account;
}
@Override
public void setAccount(AC account) {
this.account = account;
}
@Override
public AD getAddress() {
return address;
}
@Override
public void setAddress(AD address) {
this.address = address;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,84 @@
package org.mercury_im.messenger.core.entity;
import java.util.Date;
public class AbstractMessage<AD extends Address, MM extends MessageMetadata> implements Message<AD, MM> {
protected long id;
protected AD sender;
protected AD recipient;
protected Date timestamp;
protected String body;
protected MessageDeliveryState deliveryState;
protected MM metadata;
@Override
public long getId() {
return id;
}
@Override
public void setId(long id) {
this.id = id;
}
@Override
public AD getSender() {
return sender;
}
@Override
public void setSender(AD address) {
this.sender = address;
}
@Override
public AD getRecipient() {
return recipient;
}
@Override
public void setRecipient(AD recipient) {
this.recipient = recipient;
}
@Override
public Date getTimestamp() {
return timestamp;
}
@Override
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
@Override
public String getBody() {
return body;
}
@Override
public void setBody(String body) {
this.body = body;
}
@Override
public MessageDeliveryState getDeliveryState() {
return deliveryState;
}
@Override
public void setDeliveryState(MessageDeliveryState deliveryState) {
this.deliveryState = deliveryState;
}
@Override
public MM getMetadata() {
return metadata;
}
@Override
public void setMetadata(MM metadata) {
this.metadata = metadata;
}
}

View File

@ -0,0 +1,34 @@
package org.mercury_im.messenger.core.entity;
/**
* User Account entity.
*
* @param <AD> UserAddress Type. This type describes the accounts address.
* @param <AU> AuthMethod Type. This type describes details about the accounts authentication method.
*/
public interface Account<AD extends Address.UserAddress, AU extends Account.AuthMethod> {
void setId(long id);
long getId();
void setAddress(AD address);
AD getAddress();
void setAuthentication(AU authentication);
AU getAuthentication();
void setEnabled(boolean enabled);
boolean isEnabled();
/**
* Interface to allow protocol-specific authentication information, like passwords, parameters,
* certificates etc.
*/
interface AuthMethod {
}
}

View File

@ -0,0 +1,24 @@
package org.mercury_im.messenger.core.entity;
public interface Address {
String toString();
/**
* Address of a user.
*/
interface UserAddress extends Address {
}
/**
* Address of a chat room / group chat.
*/
interface RoomAddress extends Address {
}
interface RoomParticipantAddress extends Address {
}
}

View File

@ -0,0 +1,15 @@
package org.mercury_im.messenger.core.entity;
public interface Chat<
AC extends Account<AD, ?>,
AD extends Address.UserAddress> {
long getId();
void setId(long id);
AC getAccount();
void setAccount(AC account);
}

View File

@ -0,0 +1,43 @@
package org.mercury_im.messenger.core.entity;
public interface Contact<
AC extends Account<AD, ?>,
AD extends Address.UserAddress>
extends Interlocutor<AC, AD> {
SubscriptionMode getSubscriptionMode();
void setSubscriptionMode(SubscriptionMode mode);
enum SubscriptionMode {
/**
* No subscription between us an them.
*/
NONE,
/**
* We sent a subscription request, which is now pending to be accepted.
*/
TO_THEM_PENDING,
/**
* We sent a subscription request and they accepted it.
*/
TO_THEM_ACCEPTED,
/**
* They sent us a subscription request, but we did not yet accept it.
*/
FROM_THEM_PENDING,
/**
* They sent us a subscription request and we accepted it.
*/
FROM_THEM_ACCEPTED,
/**
* They accepted us and we accepted them.
*/
BIDIRECTIONAL
}
}

View File

@ -0,0 +1,13 @@
package org.mercury_im.messenger.core.entity;
public interface DirectChat<
IL extends Interlocutor<AC, AD>,
AC extends Account<AD, ?>,
AD extends Address.UserAddress>
extends Chat<AC, AD> {
IL getInterlocutor();
void setInterlocutor(IL interlocutor);
}

View File

@ -0,0 +1,16 @@
package org.mercury_im.messenger.core.entity;
public interface GroupChat<
AC extends Account<AD, ?>,
AD extends Address.UserAddress,
RA extends Address.RoomAddress>
extends Chat<AC, AD> {
RA getRoomAddress();
void setRoomAddress(RA roomAddress);
String getRoomName();
void setRoomName(String roomName);
}

View File

@ -0,0 +1,28 @@
package org.mercury_im.messenger.core.entity;
/**
* Defines a user on the network (eg. a contact, chat partner etc).
*
* @param <AC> Account Type
* @param <AD> UserAddress Type
*/
public interface Interlocutor<
AC extends Account<AD, ?>,
AD extends Address.UserAddress> {
long getId();
void setId(long id);
AC getAccount();
void setAccount(AC account);
AD getAddress();
void setAddress(AD address);
String getName();
void setName(String name);
}

View File

@ -0,0 +1,35 @@
package org.mercury_im.messenger.core.entity;
import java.util.Date;
public interface Message<MA extends Address, MM extends MessageMetadata> {
long getId();
void setId(long id);
MA getSender();
void setSender(MA address);
MA getRecipient();
void setRecipient(MA recipient);
Date getTimestamp();
void setTimestamp(Date timestamp);
String getBody();
void setBody(String body);
MessageDeliveryState getDeliveryState();
void setDeliveryState(MessageDeliveryState deliveryState);
MM getMetadata();
void setMetadata(MM metadata);
}

View File

@ -0,0 +1,10 @@
package org.mercury_im.messenger.core.entity;
public enum MessageDeliveryState {
pending_delivery,
delivered_to_server,
delivered_to_peer,
read,
delivery_error,
;
}

View File

@ -0,0 +1,9 @@
package org.mercury_im.messenger.core.entity;
/**
* Interface to allow additional, protocol specific metadata to be attached to the message.
* In case of XMPP this might be origin/stanza id, encryption information etc.
*/
public interface MessageMetadata {
}

1
entity_xmpp/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

11
entity_xmpp/build.gradle Normal file
View File

@ -0,0 +1,11 @@
apply plugin: 'java-library'
dependencies {
api project(":entity")
// JXMPP for Jid types. Version comes from smacks version.gradle
api("org.jxmpp:jxmpp-jid:$jxmppVersion")
}
sourceCompatibility = "8"
targetCompatibility = "8"

View File

@ -0,0 +1,7 @@
package org.mercury_im.messenger.xmpp.entity;
import org.mercury_im.messenger.core.entity.AbstractAccount;
public class XmppAccount extends AbstractAccount<XmppAddress.XmppUserAddress, XmppAuthMethod> {
}

View File

@ -0,0 +1,46 @@
package org.mercury_im.messenger.xmpp.entity;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import org.mercury_im.messenger.core.entity.Address;
public class XmppAddress implements Address {
private EntityBareJid jid;
public XmppAddress(EntityBareJid jid) {
this.jid = jid;
}
public EntityBareJid getJid() {
return jid;
}
public static class XmppUserAddress extends XmppAddress implements Address.UserAddress {
public XmppUserAddress(EntityBareJid jid) {
super(jid);
}
}
public static class XmppRoomAddress extends XmppAddress implements Address.RoomAddress {
public XmppRoomAddress(EntityBareJid jid) {
super(jid);
}
}
public static class XmppRoomParticipantAddress implements Address.RoomParticipantAddress {
private EntityFullJid jid;
public XmppRoomParticipantAddress(EntityFullJid jid) {
this.jid = jid;
}
public EntityFullJid getJid() {
return jid;
}
}
}

View File

@ -0,0 +1,24 @@
package org.mercury_im.messenger.xmpp.entity;
import org.mercury_im.messenger.core.entity.Account;
public abstract class XmppAuthMethod implements Account.AuthMethod {
public static class AuthPassword extends XmppAuthMethod {
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public static AuthPassword fromPassword(String password) {
AuthPassword auth = new AuthPassword();
auth.setPassword(password);
return auth;
}
}
}

View File

@ -0,0 +1,7 @@
package org.mercury_im.messenger.xmpp.entity;
import org.mercury_im.messenger.core.entity.AbstractDirectChat;
public class XmppDirectChat extends AbstractDirectChat<XmppInterlocutor, XmppAccount, XmppAddress.XmppUserAddress> {
}

View File

@ -0,0 +1,7 @@
package org.mercury_im.messenger.xmpp.entity;
import org.mercury_im.messenger.core.entity.AbstractGroupChat;
public class XmppGroupChat extends AbstractGroupChat<XmppAccount, XmppAddress.XmppUserAddress, XmppAddress.XmppRoomAddress> {
}

View File

@ -0,0 +1,7 @@
package org.mercury_im.messenger.xmpp.entity;
import org.mercury_im.messenger.core.entity.AbstractInterlocutor;
public class XmppInterlocutor extends AbstractInterlocutor<XmppAccount, XmppAddress.XmppUserAddress> {
}

View File

@ -0,0 +1,7 @@
package org.mercury_im.messenger.xmpp.entity;
import org.mercury_im.messenger.core.entity.AbstractMessage;
public class XmppMessage extends AbstractMessage<XmppAddress, XmppMessageMetadata> {
}

View File

@ -0,0 +1,7 @@
package org.mercury_im.messenger.xmpp.entity;
import org.mercury_im.messenger.core.entity.MessageMetadata;
public class XmppMessageMetadata implements MessageMetadata {
}

View File

@ -1,50 +0,0 @@
package org.mercury_im.messenger.persistence.repository;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import javax.inject.Inject;
import javax.inject.Named;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
import io.requery.reactivex.ReactiveResult;
public class AccountRepository extends AbstractRepository<AccountModel> {
@Inject
public AccountRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(AccountModel.class, data, subscriberScheduler, observerScheduler);
}
public Observable<ReactiveResult<AccountModel>> getAccountByJid(EntityBareJid jid) {
return data().select(AccountModel.class)
.where(AccountModel.JID.eq(jid))
.get()
.observableResult()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Observable<ReactiveResult<AccountModel>> getAccount(long accountId) {
return data().select(AccountModel.class).where(AccountModel.ID.eq(accountId))
.get().observableResult()
.subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
public Completable delete(long accountId) {
return data().delete(AccountModel.class)
.where(AccountModel.ID.eq(accountId))
.get()
.single()
.ignoreElement()
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
}

1
repository/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

12
repository/build.gradle Normal file
View File

@ -0,0 +1,12 @@
apply plugin: 'java-library'
dependencies {
api project(":entity")
api project(":thread_utils")
// RxJava 2
api "io.reactivex.rxjava2:rxjava:$rxJava2Version"
}
sourceCompatibility = "8"
targetCompatibility = "8"

View File

@ -0,0 +1,36 @@
package org.mercury_im.messenger.core.repository;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.util.Optional;
import java.util.List;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Single;
public interface AccountRepository<
AC extends Account<AD, ?>,
AD extends Address.UserAddress> {
Single<AC> insertAccount(AC account);
Observable<Optional<AC>> observeAccount(long accountId);
Maybe<AC> getAccount(long accountId);
Observable<Optional<AC>> observeAccountByAddress(AD address);
Maybe<AC> getAccountByAddress(AD address);
Observable<List<AC>> observeAllAccounts();
Single<AC> updateAccount(AC account);
Single<AC> upsertAccount(AC account);
Completable deleteAccount(AC account);
}

View File

@ -0,0 +1,37 @@
package org.mercury_im.messenger.core.repository;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.Contact;
import org.mercury_im.messenger.core.util.Optional;
import java.util.List;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Single;
public interface ContactRepository<
AC extends Account<AD, ?>,
AD extends Address.UserAddress,
C extends Contact<AC, AD>> {
Single<C> insertContact(C contact);
Observable<Optional<C>> observeContact(long contactId);
Maybe<C> getContact(long contactId);
Observable<Optional<C>> observeContactByAddress(AD address);
Maybe<C> getContactByAddress(AD address);
Observable<List<C>> observeAllContacts();
Single<C> updateContact(C contact);
Single<C> upsertContact(C contact);
Completable deleteContact(C contact);
}

View File

@ -0,0 +1,55 @@
package org.mercury_im.messenger.core.repository;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.DirectChat;
import org.mercury_im.messenger.core.entity.Interlocutor;
import org.mercury_im.messenger.core.entity.Message;
import org.mercury_im.messenger.core.entity.MessageMetadata;
import org.mercury_im.messenger.core.util.Optional;
import java.util.List;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Single;
public interface DirectChatRepository<
DC extends DirectChat<IL, AC, AD>,
IL extends Interlocutor<AC, AD>,
AC extends Account<AD, ?>,
AD extends Address.UserAddress,
M extends Message<AD, MM>,
MM extends MessageMetadata> {
Single<DC> insertDirectChat(DC chat);
Observable<Optional<DC>> observeDirectChat(long chatId);
Maybe<DC> getDirectChat(long chatId);
Observable<Optional<DC>> observeDirectChatByInterlocutor(IL interlocutor);
Maybe<DC> getDirectChatByInterlocutor(IL interlocutor);
Observable<List<DC>> observeAllDirectChats();
Single<DC> updateDirectChat(DC chat);
Single<DC> upsertDirectChat(DC chat);
Completable deleteDirectChat(DC chat);
// Messages
Single<M> insertMessage(DC chat, M message);
Observable<List<M>> observeMessages(DC chat);
Single<M> updateMessage(M message);
Single<M> upsertMessage(DC chat, M message);
Completable deleteMessage(M message);
}

View File

@ -0,0 +1,54 @@
package org.mercury_im.messenger.core.repository;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.GroupChat;
import org.mercury_im.messenger.core.entity.Message;
import org.mercury_im.messenger.core.entity.MessageMetadata;
import org.mercury_im.messenger.core.util.Optional;
import java.util.List;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Single;
public interface GroupChatRepository<
GC extends GroupChat<AC, AD, RA>,
AC extends Account<AD, ?>,
AD extends Address.UserAddress,
RA extends Address.RoomAddress,
M extends Message<AD, MM>,
MM extends MessageMetadata> {
Single<GC> insertGroupChat(GC chat);
Observable<Optional<GC>> observeGroupChat(long chatId);
Maybe<GC> getGroupChat(long chatId);
Observable<Optional<GC>> observeGroupChatByRoomAddress(RA roomAddress);
Maybe<GC> getGroupChatByRoomAddress(RA roomAddress);
Observable<List<GC>> observeAllGroupChats();
Single<GC> updateGroupChat(GC chat);
Single<GC> upsertGroupChat(GC chat);
Completable deleteGroupChat(GC chat);
// Messages
Single<M> insertMessage(GC chat, M message);
Observable<List<M>> observeMessages(GC chat);
Single<M> updateMessage(M message);
Single<M> upsertMessage(GC chat, M message);
Completable deleteMessage(M message);
}

View File

@ -0,0 +1,23 @@
package org.mercury_im.messenger.core.util;
/**
* Since j.u.Optional is only available on Android since API lvl 24, we need this utility class.
*
* @param <T> type of wrapped object.
*/
public class Optional<T> {
private final T item;
public Optional(T item) {
this.item = item;
}
public T getItem() {
return item;
}
public boolean isPresent() {
return item != null;
}
}

1
repository_xmpp/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -8,6 +8,9 @@ sourceSets {
dependencies {
implementation project(":core")
implementation project(":entity_xmpp")
// JXMPP for Jid types. Version comes from smacks version.gradle
api("org.jxmpp:jxmpp-jid:$jxmppVersion")

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.persistence.converter;
package org.mercury_im.messenger.xmpp.converter;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.persistence.converter;
package org.mercury_im.messenger.xmpp.converter;
import org.mercury_im.messenger.persistence.enums.SaslCondition;
import org.mercury_im.messenger.xmpp.enums.SaslCondition;
import io.requery.Converter;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.persistence.converter;
package org.mercury_im.messenger.xmpp.converter;
import org.mercury_im.messenger.persistence.enums.SubscriptionDirection;
import org.mercury_im.messenger.xmpp.enums.SubscriptionDirection;
import io.requery.Converter;

View File

@ -0,0 +1,32 @@
package org.mercury_im.messenger.xmpp.converter;
import org.jxmpp.jid.impl.JidCreate;
import io.requery.Converter;
public class XmppAddressConverter implements Converter<XmppAddress, String> {
@Override
public Class<XmppAddress> getMappedType() {
return XmppAddress.class;
}
@Override
public Class<String> getPersistedType() {
return String.class;
}
@Override
public Integer getPersistedSize() {
return null;
}
@Override
public String convertToPersisted(XmppAddress address) {
return address == null ? null : address.toString();
}
@Override
public XmppAddress convertToMapped(Class<? extends XmppAddress> aClass, String string) {
return string == null ? null : new XmppAddress(JidCreate.entityBareFromOrThrowUnchecked(string));
}
}

View File

@ -1,9 +1,9 @@
package org.mercury_im.messenger.persistence.di;
package org.mercury_im.messenger.xmpp.di;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.persistence.repository.ChatRepository;
import org.mercury_im.messenger.persistence.repository.EntityCapsRepository;
import org.mercury_im.messenger.persistence.repository.RosterRepository;
import org.mercury_im.messenger.xmpp.repository.ReactiveXmppAccountRepository;
import org.mercury_im.messenger.xmpp.repository.ChatRepository;
import org.mercury_im.messenger.xmpp.repository.EntityCapsRepository;
import org.mercury_im.messenger.xmpp.repository.RosterRepository;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import javax.inject.Named;
@ -20,10 +20,10 @@ public class RequeryModule {
@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 AccountRepository(data, ioScheduler, uiScheduler);
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

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.persistence.enums;
package org.mercury_im.messenger.xmpp.enums;
public enum SaslCondition {

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.persistence.enums;
package org.mercury_im.messenger.xmpp.enums;
public enum SubscriptionDirection {
none,

View File

@ -0,0 +1,36 @@
package org.mercury_im.messenger.xmpp.mapping;
import org.mercury_im.messenger.xmpp.entity.XmppAccount;
import org.mercury_im.messenger.xmpp.entity.XmppAddress;
import org.mercury_im.messenger.xmpp.entity.XmppAuthMethod;
import org.mercury_im.messenger.xmpp.model.AccountModel;
public class AccountMapping {
public static XmppAccount modelToEntity(AccountModel model) {
if (model == null) {
return null;
}
XmppAccount entity = new XmppAccount();
entity.setId(model.getId());
entity.setAddress(new XmppAddress.XmppUserAddress(model.getJid()));
entity.setEnabled(model.isEnabled());
entity.setAuthentication(XmppAuthMethod.AuthPassword.fromPassword(model.getPassword()));
return entity;
}
public static AccountModel createModelFromEntity(XmppAccount entity) {
if (entity == null) {
return null;
}
AccountModel model = new AccountModel();
model.setPassword(((XmppAuthMethod.AuthPassword) entity.getAuthentication()).getPassword());
model.setJid(entity.getAddress().getJid());
model.setEnabled(entity.isEnabled());
return model;
}
}

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.persistence.entity;
package org.mercury_im.messenger.xmpp.model;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.converter.EntityBareJidConverter;
import org.mercury_im.messenger.xmpp.converter.EntityBareJidConverter;
import io.requery.Column;
import io.requery.Convert;
@ -20,7 +20,7 @@ public abstract class AbstractAccountModel implements Persistable {
@Column(nullable = false)
@Convert(EntityBareJidConverter.class)
EntityBareJid jid;
EntityBareJid address;
@Column(nullable = false)
String password;
@ -32,7 +32,7 @@ public abstract class AbstractAccountModel implements Persistable {
@Override
public String toString() {
return "Account[" + id + ", " +
jid + ", " +
address + ", " +
(enabled ? "enabled" : "disabled") + "]";
}
}

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.persistence.entity;
package org.mercury_im.messenger.xmpp.model;
import io.requery.Entity;
import io.requery.ForeignKey;

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.persistence.entity;
package org.mercury_im.messenger.xmpp.model;
import org.mercury_im.messenger.persistence.converter.SubscriptionDirectionConverter;
import org.mercury_im.messenger.persistence.enums.SubscriptionDirection;
import org.mercury_im.messenger.xmpp.converter.SubscriptionDirectionConverter;
import org.mercury_im.messenger.xmpp.enums.SubscriptionDirection;
import io.requery.Convert;
import io.requery.Entity;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.persistence.entity;
package org.mercury_im.messenger.xmpp.model;
import io.requery.Column;
import io.requery.Entity;

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.persistence.entity;
package org.mercury_im.messenger.xmpp.model;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.converter.EntityBareJidConverter;
import org.mercury_im.messenger.xmpp.converter.EntityBareJidConverter;
import io.requery.Column;
import io.requery.Convert;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.persistence.entity;
package org.mercury_im.messenger.xmpp.model;
import io.requery.Entity;
import io.requery.ForeignKey;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.persistence.entity;
package org.mercury_im.messenger.xmpp.model;
import io.requery.Entity;
import io.requery.ForeignKey;

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.persistence.entity;
package org.mercury_im.messenger.xmpp.model;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.converter.EntityBareJidConverter;
import org.mercury_im.messenger.xmpp.converter.EntityBareJidConverter;
import java.util.Date;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.persistence.entity;
package org.mercury_im.messenger.xmpp.model;
import org.mercury_im.messenger.persistence.enums.SaslCondition;
import org.mercury_im.messenger.xmpp.enums.SaslCondition;
import io.requery.Entity;
import io.requery.Key;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.persistence.repository;
package org.mercury_im.messenger.xmpp.repository;
import org.mercury_im.messenger.thread_utils.ThreadUtils;

View File

@ -1,27 +1,23 @@
package org.mercury_im.messenger.persistence.repository;
package org.mercury_im.messenger.xmpp.repository;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.entity.ChatModel;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.persistence.entity.EntityModel;
import org.mercury_im.messenger.persistence.util.ChatAndPossiblyContact;
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.util.ChatAndPossiblyContact;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.functions.Function;
import io.requery.Persistable;
import io.requery.query.Tuple;
import io.requery.reactivex.ReactiveEntityStore;
import io.requery.reactivex.ReactiveResult;

View File

@ -1,17 +1,14 @@
package org.mercury_im.messenger.persistence.repository;
package org.mercury_im.messenger.xmpp.repository;
import org.mercury_im.messenger.persistence.entity.EntityCapsModel;
import org.mercury_im.messenger.xmpp.model.EntityCapsModel;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import javax.inject.Inject;
import javax.inject.Named;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;
import io.requery.reactivex.ReactiveResult;
public class EntityCapsRepository extends AbstractRepository<EntityCapsModel> {

View File

@ -1,19 +1,16 @@
package org.mercury_im.messenger.persistence.repository;
package org.mercury_im.messenger.xmpp.repository;
import org.mercury_im.messenger.persistence.entity.ChatModel;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.persistence.entity.EntityModel;
import org.mercury_im.messenger.persistence.entity.MessageModel;
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.thread_utils.ThreadUtils;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
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;

View File

@ -0,0 +1,152 @@
package org.mercury_im.messenger.xmpp.repository;
import org.mercury_im.messenger.core.repository.AccountRepository;
import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import org.mercury_im.messenger.xmpp.entity.XmppAccount;
import org.mercury_im.messenger.xmpp.entity.XmppAddress;
import org.mercury_im.messenger.xmpp.entity.XmppAuthMethod;
import org.mercury_im.messenger.xmpp.mapping.AccountMapping;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.Single;
import io.requery.Persistable;
import io.requery.query.ResultDelegate;
import io.requery.reactivex.ReactiveEntityStore;
public class ReactiveXmppAccountRepository extends RequeryRepository implements AccountRepository<XmppAccount, XmppAddress.XmppUserAddress> {
@Inject
public ReactiveXmppAccountRepository(ReactiveEntityStore<Persistable> data,
@Named(value = ThreadUtils.SCHEDULER_IO) Scheduler subscriberScheduler,
@Named(value = ThreadUtils.SCHEDULER_UI) Scheduler observerScheduler) {
super(data, subscriberScheduler, observerScheduler);
}
@Override
public Single<XmppAccount> insertAccount(XmppAccount account) {
return data().insert(AccountMapping.createModelFromEntity(account))
.map(AccountMapping::modelToEntity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Observable<Optional<XmppAccount>> observeAccount(long accountId) {
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(accountId))
.get().observableResult()
.map(result -> new Optional<>(AccountMapping.modelToEntity(result.firstOrNull())))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Maybe<XmppAccount> getAccount(long accountId) {
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(accountId))
.get().maybe()
.map(AccountMapping::modelToEntity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Observable<Optional<XmppAccount>> observeAccountByAddress(XmppAddress.XmppUserAddress address) {
return data().select(AccountModel.class)
.where(AccountModel.JID.eq(address.getJid()))
.get().observableResult()
.map(result -> new Optional<>(AccountMapping.modelToEntity(result.firstOrNull())))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Maybe<XmppAccount> getAccountByAddress(XmppAddress.XmppUserAddress address) {
return data().select(AccountModel.class)
.where(AccountModel.JID.eq(address.getJid()))
.get().maybe()
.map(AccountMapping::modelToEntity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Observable<List<XmppAccount>> observeAllAccounts() {
return data().select(AccountModel.class)
.get().observableResult()
.map(ResultDelegate::toList)
.map(list -> {
List<XmppAccount> entities = new ArrayList<>(list.size());
list.forEach(model -> entities.add(AccountMapping.modelToEntity(model)));
return entities;
})
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Single<XmppAccount> updateAccount(XmppAccount account) {
// Since we cannot access setId() of AccountModel, we have to query the model by ID and update it manually.
// https://github.com/requery/requery/issues/616#issuecomment-315685460
// fetch model
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(account.getId()))
.get().maybe().toSingle() // to single
.map(model -> {
// update it
model.setEnabled(account.isEnabled());
model.setPassword(((XmppAuthMethod.AuthPassword) account.getAuthentication()).getPassword());
model.setJid(account.getAddress().getJid());
// write the updated model back
model = data().update(model).blockingGet();
return AccountMapping.modelToEntity(model);
})
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Single<XmppAccount> upsertAccount(XmppAccount account) {
// Try to fetch model
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(account.getId()))
.get().maybe()
// If it does not exist, create a new model from the entity
.switchIfEmpty(data().insert(AccountMapping.createModelFromEntity(account)))
// finally
.map(model -> {
// update the model
model.setEnabled(account.isEnabled());
model.setPassword(((XmppAuthMethod.AuthPassword) account.getAuthentication()).getPassword());
model.setJid(account.getAddress().getJid());
// write the updated model back
model = data().update(model).blockingGet();
return AccountMapping.modelToEntity(model);
})
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@Override
public Completable deleteAccount(XmppAccount account) {
return data().delete(AccountModel.class)
.where(AccountModel.ID.eq(account.getId()))
.get().single().ignoreElement() // to completable
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
}

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.persistence.repository;
package org.mercury_im.messenger.xmpp.repository;
import io.reactivex.Scheduler;
import io.requery.Persistable;

View File

@ -1,9 +1,9 @@
package org.mercury_im.messenger.persistence.repository;
package org.mercury_im.messenger.xmpp.repository;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.entity.AccountModel;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.persistence.entity.EntityModel;
import org.mercury_im.messenger.xmpp.model.AccountModel;
import org.mercury_im.messenger.xmpp.model.ContactModel;
import org.mercury_im.messenger.xmpp.model.EntityModel;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import javax.inject.Inject;

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.persistence.util;
package org.mercury_im.messenger.xmpp.util;
import org.mercury_im.messenger.persistence.entity.ChatModel;
import org.mercury_im.messenger.persistence.entity.ContactModel;
import org.mercury_im.messenger.xmpp.model.ChatModel;
import org.mercury_im.messenger.xmpp.model.ContactModel;
public class ChatAndPossiblyContact {

View File

@ -1,5 +1,9 @@
include ':app', ':thread_utils',
':core',
':persistence'
include ':entity',
':entity_xmpp',
':repository',
':repository_xmpp',
':app',
':thread_utils',
':core'
includeBuild 'libs/Smack'