Restructure modules, remove generics hell from entities

This commit is contained in:
Paul Schaub 2019-11-18 00:04:28 +01:00
parent baeabc0602
commit 2755b2de8f
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
101 changed files with 905 additions and 982 deletions

View File

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.android.tools.build:gradle:3.5.2'
// NOTE: Do not place your application dependencies here; they belong

View File

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

View File

@ -1,33 +0,0 @@
package org.mercury_im.core.usecase;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.chat.DirectChat;
import org.mercury_im.messenger.core.entity.contact.Interlocutor;
import org.mercury_im.messenger.core.entity.message.Message;
import org.mercury_im.messenger.core.entity.message.MessageMetadata;
public class SendDirectMessage<
M extends Message<AD, MM>,
C extends DirectChat<IL, AC, AD>,
AD extends Address.UserAddress,
MM extends MessageMetadata,
IL extends Interlocutor<AC, AD, AD>,
AC extends Account<AD, ?>> {
private final M message;
private final C chat;
public SendDirectMessage(M message, C chat) {
this.message = message;
this.chat = chat;
}
public M getMessage() {
return message;
}
public C getChat() {
return chat;
}
}

View File

View File

@ -2,7 +2,6 @@ apply plugin: 'java-library'
dependencies {
api project(":entity")
api project(":thread_utils")
// RxJava 2
api "io.reactivex.rxjava2:rxjava:$rxJava2Version"

View File

@ -0,0 +1,33 @@
package org.mercury_im.messenger.core.repository;
import org.mercury_im.messenger.core.entity.Account;
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 {
Single<Account> insertAccount(Account account);
Observable<Optional<Account>> observeAccount(long accountId);
Maybe<Account> getAccount(long accountId);
Observable<Optional<Account>> observeAccountByAddress(String address);
Maybe<Account> getAccountByAddress(String address);
Observable<List<Account>> observeAllAccounts();
Single<Account> updateAccount(Account account);
Single<Account> upsertAccount(Account account);
Completable deleteAccount(Account account);
}

View File

@ -0,0 +1,32 @@
package org.mercury_im.messenger.core.repository;
import org.mercury_im.messenger.core.entity.contact.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 {
Single<Contact> insertContact(Contact contact);
Observable<Optional<Contact>> observeContact(long contactId);
Maybe<Contact> getContact(long contactId);
Observable<Optional<Contact>> observeContactByAddress(String address);
Maybe<Contact> getContactByAddress(String address);
Observable<List<Contact>> observeAllContacts();
Single<Contact> updateContact(Contact contact);
Single<Contact> upsertContact(Contact contact);
Completable deleteContact(Contact contact);
}

View File

@ -0,0 +1,46 @@
package org.mercury_im.messenger.core.repository;
import org.mercury_im.messenger.core.entity.chat.DirectChat;
import org.mercury_im.messenger.core.entity.contact.Peer;
import org.mercury_im.messenger.core.entity.message.Message;
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 {
Single<DirectChat> insertDirectChat(DirectChat chat);
Observable<Optional<DirectChat>> observeDirectChat(long chatId);
Maybe<DirectChat> getDirectChat(long chatId);
Observable<Optional<DirectChat>> observeDirectChatByInterlocutor(Peer peer);
Maybe<DirectChat> getDirectChatByInterlocutor(Peer peer);
Observable<List<DirectChat>> observeAllDirectChats();
Single<DirectChat> updateDirectChat(DirectChat chat);
Single<DirectChat> upsertDirectChat(DirectChat chat);
Completable deleteDirectChat(DirectChat chat);
// Messages
Single<Message> insertMessage(DirectChat chat, Message message);
Observable<List<Message>> observeMessages(DirectChat chat);
Single<Message> updateMessage(Message message);
Single<Message> upsertMessage(DirectChat chat, Message message);
Completable deleteMessage(Message message);
}

View File

@ -0,0 +1,45 @@
package org.mercury_im.messenger.core.repository;
import org.mercury_im.messenger.core.entity.chat.GroupChat;
import org.mercury_im.messenger.core.entity.message.Message;
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 {
Single<GroupChat> insertGroupChat(GroupChat chat);
Observable<Optional<GroupChat>> observeGroupChat(long chatId);
Maybe<GroupChat> getGroupChat(long chatId);
Observable<Optional<GroupChat>> observeGroupChatByRoomAddress(String roomAddress);
Maybe<GroupChat> getGroupChatByRoomAddress(String roomAddress);
Observable<List<GroupChat>> observeAllGroupChats();
Single<GroupChat> updateGroupChat(GroupChat chat);
Single<GroupChat> upsertGroupChat(GroupChat chat);
Completable deleteGroupChat(GroupChat chat);
// Messages
Single<Message> insertMessage(GroupChat chat, Message message);
Observable<List<Message>> observeMessages(GroupChat chat);
Single<Message> updateMessage(Message message);
Single<Message> upsertMessage(GroupChat chat, Message message);
Completable deleteMessage(Message message);
}

View File

@ -3,8 +3,7 @@ apply plugin: 'java-library'
dependencies {
implementation project(':entity')
implementation project(':repository')
implementation project(":thread_utils")
implementation project(':data')
// RxJava2
implementation "io.reactivex.rxjava2:rxjava:$rxJava2Version"

View File

@ -0,0 +1,17 @@
package org.mercury_im.core;
import org.mercury_im.core.transport.connection.ConnectionMethod;
import org.mercury_im.core.transport.listener.IncomingDirectMessageListener;
import org.mercury_im.messenger.core.entity.chat.Chat;
import org.mercury_im.messenger.core.entity.message.Message;
import io.reactivex.Completable;
public interface MessageCenter<C extends Chat> {
Messenger getMessenger();
Completable sendMessage(Message message, C chat);
void addIncomingMessageListener(IncomingDirectMessageListener listener);
}

View File

@ -1,6 +1,7 @@
package org.mercury_im.core;
import org.mercury_im.core.connection.ConnectionMethod;
import org.mercury_im.core.transport.connection.ConnectionMethod;
import org.mercury_im.messenger.core.entity.Account;
import java.util.HashMap;
import java.util.Map;
@ -13,5 +14,8 @@ public class Messenger {
connections.put(connection.getAccount().getId(), connection);
}
public ConnectionMethod getConnection(Account account) {
return connections.get(account.getId());
}
}

View File

@ -0,0 +1,22 @@
package org.mercury_im.core.transport;
public enum ConnectionType {
// Smack Connection Types from module transport_xmpp.
/**
* Underlying connection is a Smack XMPPTCPConnection.
*/
SMACK_TCP,
/**
* Underlying connection is a Smack XMPPBOSHConnection.
* @deprecated Not yet implemented.
*/
SMACK_BOSH,
/**
* Underlying connection is a Smack XMPPWebsocketConnection.
* @deprecated Not yet implemented.
*/
SMACK_WEBSOCKETS,
;
}

View File

@ -0,0 +1,26 @@
package org.mercury_im.core.transport.connection;
import org.mercury_im.core.Messenger;
import org.mercury_im.messenger.core.entity.Account;
public abstract class AbstractConnectionMethod
implements ConnectionMethod {
protected final Account account;
protected final Messenger messenger;
public AbstractConnectionMethod(Account account, Messenger messenger) {
this.account = account;
this.messenger = messenger;
}
@Override
public Account getAccount() {
return account;
}
@Override
public Messenger getMessenger() {
return messenger;
}
}

View File

@ -0,0 +1,13 @@
package org.mercury_im.core.transport.connection;
import org.mercury_im.core.Messenger;
import org.mercury_im.messenger.core.entity.Account;
public interface ConnectionFactory<
CM extends ConnectionMethod> {
Messenger getMessenger();
CM provideConnection(Account account);
}

View File

@ -0,0 +1,18 @@
package org.mercury_im.core.transport.connection;
import org.mercury_im.core.Messenger;
import org.mercury_im.core.transport.ConnectionType;
import org.mercury_im.messenger.core.entity.Account;
import io.reactivex.Completable;
public interface ConnectionMethod {
Account getAccount();
Messenger getMessenger();
Completable connect();
ConnectionType getConnectionType();
}

View File

@ -1,4 +1,4 @@
package org.mercury_im.core.connection.exception;
package org.mercury_im.core.transport.connection.exception;
public class ConnectionFailedException extends Exception {

View File

@ -0,0 +1,11 @@
package org.mercury_im.core.transport.listener;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.chat.DirectChat;
import org.mercury_im.messenger.core.entity.message.Message;
public interface IncomingDirectMessageListener {
void onIncomingDirectMessage(Account account, DirectChat chat, Message message);
}

View File

@ -0,0 +1,11 @@
package org.mercury_im.core.transport.listener;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.chat.GroupChat;
import org.mercury_im.messenger.core.entity.message.Message;
public interface IncomingGroupChatMessageListener {
void onIncomingDirectMessage(Account account, GroupChat chat, Message message);
}

View File

@ -0,0 +1,9 @@
package org.mercury_im.core.transport.listener;
import org.mercury_im.messenger.core.entity.chat.Chat;
import org.mercury_im.messenger.core.entity.event.TypingEvent;
public interface TypingEventListener {
void onTypingEventReceived(Chat chat, TypingEvent typingEvent);
}

View File

@ -0,0 +1,23 @@
package org.mercury_im.core.usecase;
import org.mercury_im.messenger.core.entity.chat.DirectChat;
import org.mercury_im.messenger.core.entity.message.Message;
public class SendDirectMessage {
private final Message message;
private final DirectChat chat;
public SendDirectMessage(Message message, DirectChat chat) {
this.message = message;
this.chat = chat;
}
public Message getMessage() {
return message;
}
public DirectChat getChat() {
return chat;
}
}

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.thread_utils;
package org.mercury_im.core.util;
/**
* Name constants used by dagger in combination with the @Named annotation.

View File

@ -2,23 +2,20 @@ 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> {
public interface Account {
void setId(long id);
long getId();
void setAddress(AD address);
void setAddress(String address);
AD getAddress();
String getAddress();
void setAuthentication(AU authentication);
void setAuthentication(AuthMethod authentication);
AU getAuthentication();
AuthMethod getAuthentication();
void setEnabled(boolean enabled);
@ -30,5 +27,6 @@ public interface Account<AD extends Address.UserAddress, AU extends Account.Auth
*/
interface AuthMethod {
String getPassword();
}
}

View File

@ -1,24 +0,0 @@
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

@ -1,13 +1,10 @@
package org.mercury_im.messenger.core.entity;
public abstract class AbstractAccount<
AD extends Address.UserAddress,
AU extends Account.AuthMethod>
implements Account<AD, AU> {
public class IAccount implements Account {
protected long id;
protected AD address;
protected AU authentication;
protected String address;
protected AuthMethod authentication;
protected boolean enabled;
@Override
@ -22,22 +19,22 @@ public abstract class AbstractAccount<
}
@Override
public void setAddress(AD address) {
public void setAddress(String address) {
this.address = address;
}
@Override
public AD getAddress() {
public String getAddress() {
return address;
}
@Override
public void setAuthentication(AU authentication) {
public void setAuthentication(AuthMethod authentication) {
this.authentication = authentication;
}
@Override
public AU getAuthentication() {
public AuthMethod getAuthentication() {
return authentication;
}

View File

@ -0,0 +1,15 @@
package org.mercury_im.messenger.core.entity;
public class PasswordAuthentication implements Account.AuthMethod {
private String password;
public PasswordAuthentication(String password) {
this.password = password;
}
@Override
public String getPassword() {
return password;
}
}

View File

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

View File

@ -4,15 +4,15 @@ public interface ChatPreferences {
NotificationPreferences getNotificationPreference();
boolean setNotificationPreference(NotificationPreferences notificationPreferences);
void setNotificationPreference(NotificationPreferences notificationPreferences);
boolean isTypingNotificationsSupported();
void setTypingNotificationsSupported(boolean typingNotificationsSupported);
boolean isSendTypingNotifications();
boolean isSendTypingNotificationsEnabled();
void setSendTypingNotifications(boolean sendTypingNotifications);
void setSendTypingNotificationsEnabled(boolean sendTypingNotifications);
boolean isReadNotificationsSupported();

View File

@ -1,17 +1,11 @@
package org.mercury_im.messenger.core.entity.chat;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.contact.Interlocutor;
import org.mercury_im.messenger.core.entity.contact.Peer;
public interface DirectChat<
IL extends Interlocutor<AC, AD, AD>,
AC extends Account<AD, ?>,
AD extends Address.UserAddress>
extends Chat<AC, AD> {
public interface DirectChat extends Chat {
IL getInterlocutor();
Peer getPeer();
void setInterlocutor(IL interlocutor);
void setPeer(Peer peer);
}

View File

@ -1,26 +1,18 @@
package org.mercury_im.messenger.core.entity.chat;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.contact.Interlocutor;
import org.mercury_im.messenger.core.entity.contact.Peer;
import java.util.Set;
public interface GroupChat<
AC extends Account<AD, ?>,
AD extends Address.UserAddress,
RA extends Address.RoomAddress,
PA extends Address.RoomParticipantAddress,
IL extends Interlocutor<AC, PA, AD>>
extends Chat<AC, AD> {
public interface GroupChat extends Chat {
Set<IL> getParticipants();
Set<Peer> getParticipants();
void setParticipants(Set<IL> participants);
void setParticipants(Set<Peer> participants);
RA getRoomAddress();
String getRoomAddress();
void setRoomAddress(RA roomAddress);
void setRoomAddress(String roomAddress);
String getRoomName();

View File

@ -0,0 +1,60 @@
package org.mercury_im.messenger.core.entity.chat;
public class IChatPreferences implements ChatPreferences {
protected NotificationPreferences notificationPreferences;
protected boolean typingNotificationsSupported;
protected boolean sendTypingNotificationsEnabled;
protected boolean readNotificationsSupported;
protected boolean sendReadNotificationsEnabled;
@Override
public NotificationPreferences getNotificationPreference() {
return notificationPreferences;
}
@Override
public void setNotificationPreference(NotificationPreferences notificationPreferences) {
this.notificationPreferences = notificationPreferences;
}
@Override
public boolean isTypingNotificationsSupported() {
return typingNotificationsSupported;
}
@Override
public void setTypingNotificationsSupported(boolean typingNotificationsSupported) {
this.typingNotificationsSupported = typingNotificationsSupported;
}
@Override
public boolean isSendTypingNotificationsEnabled() {
return sendTypingNotificationsEnabled;
}
@Override
public void setSendTypingNotificationsEnabled(boolean sendTypingNotifications) {
this.sendTypingNotificationsEnabled = sendTypingNotifications;
}
@Override
public boolean isReadNotificationsSupported() {
return readNotificationsSupported;
}
@Override
public void setReadNotificationsSupported(boolean readNotificationsSupported) {
this.readNotificationsSupported = readNotificationsSupported;
}
@Override
public boolean isSendReadNotifications() {
return sendReadNotificationsEnabled;
}
@Override
public void setSendReadNotifications(boolean sendReadNotifications) {
this.sendReadNotificationsEnabled = sendReadNotifications;
}
}

View File

@ -1,28 +1,23 @@
package org.mercury_im.messenger.core.entity.chat;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.contact.Interlocutor;
import org.mercury_im.messenger.core.entity.contact.Peer;
public abstract class AbstractDirectChat<
IL extends Interlocutor<AC, AD>,
AC extends Account<AD, ?>,
AD extends Address.UserAddress>
implements DirectChat<IL, AC, AD> {
public class IDirectChat implements DirectChat {
protected long id;
protected IL interlocutor;
protected AC account;
protected Peer peer;
protected Account account;
protected ChatPreferences preferences;
@Override
public IL getInterlocutor() {
return interlocutor;
public Peer getPeer() {
return peer;
}
@Override
public void setInterlocutor(IL interlocutor) {
this.interlocutor = interlocutor;
public void setPeer(Peer peer) {
this.peer = peer;
}
@Override
@ -36,12 +31,12 @@ public abstract class AbstractDirectChat<
}
@Override
public AC getAccount() {
public Account getAccount() {
return account;
}
@Override
public void setAccount(AC account) {
public void setAccount(Account account) {
this.account = account;
}

View File

@ -1,27 +1,36 @@
package org.mercury_im.messenger.core.entity.chat;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.contact.Peer;
public abstract class AbstractGroupChat<
AC extends Account<AD, ?>,
AD extends Address.UserAddress,
RA extends Address.RoomAddress>
implements GroupChat<AC, AD, RA> {
import java.util.Set;
public class IGroupChat implements GroupChat {
private long id;
private AC account;
private RA roomAddress;
private Account account;
private String roomAddress;
private String roomName;
protected ChatPreferences preferences;
protected Set<Peer> participants;
@Override
public RA getRoomAddress() {
public Set<Peer> getParticipants() {
return participants;
}
@Override
public void setParticipants(Set<Peer> participants) {
this.participants = participants;
}
@Override
public String getRoomAddress() {
return roomAddress;
}
@Override
public void setRoomAddress(RA roomAddress) {
public void setRoomAddress(String roomAddress) {
this.roomAddress = roomAddress;
}
@ -46,12 +55,12 @@ public abstract class AbstractGroupChat<
}
@Override
public AC getAccount() {
public Account getAccount() {
return account;
}
@Override
public void setAccount(AC account) {
public void setAccount(Account account) {
this.account = account;
}
@ -63,7 +72,7 @@ public abstract class AbstractGroupChat<
@Override
public void setChatPreferences(ChatPreferences chatPreferences) {
this.preferences = preferences;
this.preferences = chatPreferences;
}
}

View File

@ -0,0 +1,27 @@
package org.mercury_im.messenger.core.entity.chat;
public class INotificationPreferences implements ChatPreferences.NotificationPreferences {
protected boolean notifyOnMessage;
protected boolean notifyOnMention;
@Override
public boolean isNotifyOnMessage() {
return notifyOnMessage;
}
@Override
public void setNotifyOnMessage(boolean notify) {
this.notifyOnMessage = notify;
}
@Override
public boolean isNotifyOnMention() {
return notifyOnMention;
}
@Override
public void setNotifyOnMention(boolean notify) {
this.notifyOnMention = notify;
}
}

View File

@ -1,12 +1,6 @@
package org.mercury_im.messenger.core.entity.contact;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
public interface Contact<
AC extends Account<AD, ?>,
AD extends Address.UserAddress>
extends Interlocutor<AC, AD, AD> {
public interface Contact extends Peer {
SubscriptionMode getSubscriptionMode();

View File

@ -0,0 +1,62 @@
package org.mercury_im.messenger.core.entity.contact;
import org.mercury_im.messenger.core.entity.Account;
public class IContact implements Contact {
protected long id;
protected Account account;
protected String address;
protected String name;
protected SubscriptionMode subscriptionMode;
@Override
public SubscriptionMode getSubscriptionMode() {
return subscriptionMode;
}
@Override
public void setSubscriptionMode(SubscriptionMode mode) {
this.subscriptionMode = mode;
}
@Override
public long getId() {
return id;
}
@Override
public void setId(long id) {
this.id = id;
}
@Override
public Account getAccount() {
return account;
}
@Override
public void setAccount(Account account) {
this.account = account;
}
@Override
public String getAddress() {
return address;
}
@Override
public void setAddress(String address) {
this.address = address;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
}

View File

@ -1,17 +1,12 @@
package org.mercury_im.messenger.core.entity.contact;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
public abstract class AbstractInterlocutor<
AC extends Account<AD, ?>,
IA extends Address,
AD extends Address.UserAddress>
implements Interlocutor<AC, IA, AD> {
public class IPeer implements Peer {
protected long id;
protected AC account;
protected IA address;
protected Account account;
protected String address;
protected String name;
@Override
@ -25,22 +20,22 @@ public abstract class AbstractInterlocutor<
}
@Override
public AC getAccount() {
public Account getAccount() {
return account;
}
@Override
public void setAccount(AC account) {
public void setAccount(Account account) {
this.account = account;
}
@Override
public IA getAddress() {
public String getAddress() {
return address;
}
@Override
public void setAddress(IA address) {
public void setAddress(String address) {
this.address = address;
}

View File

@ -1,34 +0,0 @@
package org.mercury_im.messenger.core.entity.contact;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
/**
* Defines a user on the network (eg. a contact, chat partner, group chat member etc).
* Basically anyone that may send you a message is an Interlocutor.
*
* @param <AC> Account Type
* @param <IA> Address type for the Interlocutor
* @param <AD> UserAddress type for the account
*/
public interface Interlocutor<
AC extends Account<AD, ?>,
IA extends Address,
AD extends Address.UserAddress> {
long getId();
void setId(long id);
AC getAccount();
void setAccount(AC account);
IA getAddress();
void setAddress(IA address);
String getName();
void setName(String name);
}

View File

@ -0,0 +1,26 @@
package org.mercury_im.messenger.core.entity.contact;
import org.mercury_im.messenger.core.entity.Account;
/**
* Defines a user on the network (eg. a contact, chat partner, group chat member etc).
* Basically anyone that may send you a message is a Peer.
*/
public interface Peer {
long getId();
void setId(long id);
Account getAccount();
void setAccount(Account account);
String getAddress();
void setAddress(String address);
String getName();
void setName(String name);
}

View File

@ -0,0 +1,20 @@
package org.mercury_im.messenger.core.entity.event;
import org.mercury_im.messenger.core.entity.contact.Peer;
import java.util.Map;
public class ITypingEvent implements TypingEvent {
public Map<Peer, TypingState> typingStates;
@Override
public Map<Peer, TypingState> getTypingStates() {
return typingStates;
}
@Override
public void setTypingStates(Map<Peer, TypingState> typingStates) {
this.typingStates = typingStates;
}
}

View File

@ -0,0 +1,12 @@
package org.mercury_im.messenger.core.entity.event;
import org.mercury_im.messenger.core.entity.contact.Peer;
import java.util.Map;
public interface TypingEvent {
Map<Peer, TypingState> getTypingStates();
void setTypingStates(Map<Peer, TypingState> typingStates);
}

View File

@ -0,0 +1,24 @@
package org.mercury_im.messenger.core.entity.event;
public enum TypingState {
/**
* The peer is typing.
*/
typing,
/**
* The peer was typing and is now pausing for a short amount of time.
*/
pause,
/**
* The peer is deleting from their input field.
*/
deleting,
/**
* The peer stopped typing completely.
* TODO: Makes sense?
*/
stop
}

View File

@ -1,22 +1,17 @@
package org.mercury_im.messenger.core.entity.message;
import org.mercury_im.messenger.core.entity.Address;
import java.util.Date;
import java.util.List;
public abstract class AbstractMessage<
AD extends Address,
MM extends MessageMetadata>
implements Message<AD, MM> {
public class IMessage implements Message {
protected long id;
protected AD sender;
protected AD recipient;
protected String sender;
protected String recipient;
protected Date timestamp;
protected List<MessagePayload> payloads;
protected MessageDeliveryState deliveryState;
protected MM metadata;
protected MessageMetadata metadata;
@Override
public long getId() {
@ -29,22 +24,22 @@ public abstract class AbstractMessage<
}
@Override
public AD getSender() {
public String getSender() {
return sender;
}
@Override
public void setSender(AD address) {
public void setSender(String address) {
this.sender = address;
}
@Override
public AD getRecipient() {
public String getRecipient() {
return recipient;
}
@Override
public void setRecipient(AD recipient) {
public void setRecipient(String recipient) {
this.recipient = recipient;
}
@ -79,12 +74,12 @@ public abstract class AbstractMessage<
}
@Override
public MM getMetadata() {
public MessageMetadata getMetadata() {
return metadata;
}
@Override
public void setMetadata(MM metadata) {
public void setMetadata(MessageMetadata metadata) {
this.metadata = metadata;
}
}

View File

@ -0,0 +1,20 @@
package org.mercury_im.messenger.core.entity.message;
import org.mercury_im.messenger.core.entity.message.content.MessageContent;
import java.util.List;
public class IMessagePayload implements MessagePayload {
protected List<MessageContent> contents;
@Override
public List<MessageContent> getMessageContents() {
return contents;
}
@Override
public void setMessageContents(List<MessageContent> messageContents) {
this.contents = messageContents;
}
}

View File

@ -1,23 +1,21 @@
package org.mercury_im.messenger.core.entity.message;
import org.mercury_im.messenger.core.entity.Address;
import java.util.Date;
import java.util.List;
public interface Message<MA extends Address, MM extends MessageMetadata> {
public interface Message {
long getId();
void setId(long id);
MA getSender();
String getSender();
void setSender(MA address);
void setSender(String address);
MA getRecipient();
String getRecipient();
void setRecipient(MA recipient);
void setRecipient(String recipient);
Date getTimestamp();
@ -31,7 +29,7 @@ public interface Message<MA extends Address, MM extends MessageMetadata> {
void setDeliveryState(MessageDeliveryState deliveryState);
MM getMetadata();
MessageMetadata getMetadata();
void setMetadata(MM metadata);
void setMetadata(MessageMetadata metadata);
}

View File

@ -1,11 +1,21 @@
package org.mercury_im.messenger.core.entity.message;
import org.mercury_im.messenger.core.entity.message.content.MessageContent;
import java.util.List;
/**
* Defines the payload of a message.
* A payload can either be a plaintext container or an encrypted container and contains
* MessageContents.
* A message may contain encrypted and unencrypted contents. Those could then be represented by
* two different MessageContents.
*/
public interface MessagePayload {
List<MessageContent> getMessageContents();
void setMessageContents(List<MessageContent> messageContents);
}

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.entity.message;
package org.mercury_im.messenger.core.entity.message.content;
public interface MessageContent {

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.entity.message;
package org.mercury_im.messenger.core.entity.message.content;
public class TextMessageContent implements MessageContent.Body {

View File

@ -1,11 +0,0 @@
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

@ -1,7 +0,0 @@
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

@ -1,46 +0,0 @@
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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,30 +0,0 @@
package org.mercury_im.messenger.xmpp.entity.message;
import org.mercury_im.messenger.core.entity.message.AbstractMessage;
import org.mercury_im.messenger.xmpp.entity.XmppAddress;
public final class XmppMessage {
private XmppMessage() {
}
public class DirectMessage extends AbstractMessage<
XmppAddress.XmppUserAddress,
XmppMessageMetadata> {
}
public class MucMessage extends AbstractMessage<
XmppAddress.XmppRoomParticipantAddress,
XmppMessageMetadata> {
}
// Maybe?
public class MixMessage extends AbstractMessage<
XmppAddress.XmppRoomParticipantAddress,
XmppMessageMetadata> {
}
}

View File

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

View File

@ -1 +0,0 @@
/build

View File

@ -1,36 +0,0 @@
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

@ -1,37 +0,0 @@
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.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

@ -1,57 +0,0 @@
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.chat.DirectChat;
import org.mercury_im.messenger.core.entity.contact.Interlocutor;
import org.mercury_im.messenger.core.entity.message.Message;
import org.mercury_im.messenger.core.entity.message.MessageMetadata;
import org.mercury_im.messenger.core.entity.message.MessagePayload;
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, MP>,
MM extends MessageMetadata,
MP extends MessagePayload> {
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

@ -1,56 +0,0 @@
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.chat.GroupChat;
import org.mercury_im.messenger.core.entity.message.Message;
import org.mercury_im.messenger.core.entity.message.MessageMetadata;
import org.mercury_im.messenger.core.entity.message.MessagePayload;
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, MP>,
MM extends MessageMetadata,
MP extends MessagePayload> {
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

@ -8,12 +8,9 @@ sourceSets {
dependencies {
// implementation project(":core")
implementation project(":entity_xmpp")
implementation project(":repository")
// JXMPP for Jid types. Version comes from smacks version.gradle
api("org.jxmpp:jxmpp-jid:$jxmppVersion")
implementation project(":entity")
implementation project(':domain')
implementation project(':data')
// RxJava2
api "io.reactivex.rxjava2:rxjava:$rxJava2Version"
@ -28,7 +25,6 @@ dependencies {
// JUnit for testing
testImplementation "junit:junit:$junitVersion"
implementation project(':thread_utils')
}
sourceCompatibility = "8"

View File

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

View File

@ -1,32 +0,0 @@
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

@ -4,7 +4,7 @@ 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 org.mercury_im.core.util.ThreadUtils;
import javax.inject.Named;
import javax.inject.Singleton;

View File

@ -1,34 +1,34 @@
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.core.entity.Account;
import org.mercury_im.messenger.core.entity.IAccount;
import org.mercury_im.messenger.core.entity.PasswordAuthentication;
import org.mercury_im.messenger.xmpp.model.AccountModel;
public class AccountMapping {
public static XmppAccount modelToEntity(AccountModel model) {
public static Account modelToEntity(AccountModel model) {
if (model == null) {
return null;
}
XmppAccount entity = new XmppAccount();
IAccount entity = new IAccount();
entity.setId(model.getId());
entity.setAddress(new XmppAddress.XmppUserAddress(model.getJid()));
entity.setAddress(model.getAddress());
entity.setEnabled(model.isEnabled());
entity.setAuthentication(XmppAuthMethod.AuthPassword.fromPassword(model.getPassword()));
entity.setAuthentication(new PasswordAuthentication(model.getPassword()));
return entity;
}
public static AccountModel createModelFromEntity(XmppAccount entity) {
public static AccountModel createModelFromEntity(Account entity) {
if (entity == null) {
return null;
}
AccountModel model = new AccountModel();
model.setPassword(((XmppAuthMethod.AuthPassword) entity.getAuthentication()).getPassword());
model.setJid(entity.getAddress().getJid());
model.setPassword(entity.getAuthentication().getPassword());
model.setAddress(entity.getAddress());
model.setEnabled(entity.isEnabled());
return model;

View File

@ -1,10 +1,6 @@
package org.mercury_im.messenger.xmpp.model;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.xmpp.converter.EntityBareJidConverter;
import io.requery.Column;
import io.requery.Convert;
import io.requery.Entity;
import io.requery.Generated;
import io.requery.Key;
@ -19,8 +15,7 @@ public abstract class AbstractAccountModel implements Persistable {
long id;
@Column(nullable = false)
@Convert(EntityBareJidConverter.class)
EntityBareJid address;
String address;
@Column(nullable = false)
String password;

View File

@ -17,7 +17,7 @@ public abstract class AbstractChatModel implements Persistable {
@OneToOne
@ForeignKey
EntityModel peer;
PeerModel peer;
boolean displayed;
}

View File

@ -21,7 +21,7 @@ public abstract class AbstractContactModel implements Persistable {
@OneToOne
@ForeignKey(referencedColumn = "id")
EntityModel entity;
PeerModel entity;
String rostername;

View File

@ -1,12 +1,8 @@
package org.mercury_im.messenger.xmpp.model;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.xmpp.converter.EntityBareJidConverter;
import java.util.Date;
import io.requery.Column;
import io.requery.Convert;
import io.requery.Entity;
import io.requery.ForeignKey;
import io.requery.Generated;
@ -31,13 +27,11 @@ public abstract class AbstractMessageModel implements Persistable {
@Column(name = "\"timestamp\"", nullable = false)
Date timestamp;
@Convert(EntityBareJidConverter.class)
@Column(nullable = false)
EntityBareJid sender;
String sender;
@Convert(EntityBareJidConverter.class)
@Column(nullable = false)
EntityBareJid recipient;
String recipient;
boolean incoming;
@ -50,6 +44,5 @@ public abstract class AbstractMessageModel implements Persistable {
String stanzaId;
@Convert(EntityBareJidConverter.class)
EntityBareJid stanzaIdBy;
String stanzaIdBy;
}

View File

@ -1,10 +1,6 @@
package org.mercury_im.messenger.xmpp.model;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.xmpp.converter.EntityBareJidConverter;
import io.requery.Column;
import io.requery.Convert;
import io.requery.Entity;
import io.requery.Generated;
import io.requery.Key;
@ -13,8 +9,8 @@ import io.requery.Persistable;
import io.requery.Table;
@Entity
@Table(name = "entities")
public abstract class AbstractEntityModel implements Persistable {
@Table(name = "peers")
public abstract class AbstractPeerModel implements Persistable {
@Key @Generated
long id;
@ -22,14 +18,13 @@ public abstract class AbstractEntityModel implements Persistable {
@ManyToOne
AccountModel account;
@Convert(EntityBareJidConverter.class)
@Column(nullable = false)
EntityBareJid jid;
String address;
@Override
public String toString() {
return "Entity[" + id + ", " +
jid + ", " +
address + ", " +
account + "]";
}
}

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.xmpp.repository;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import org.mercury_im.core.util.ThreadUtils;
import javax.inject.Named;

View File

@ -1,11 +1,10 @@
package org.mercury_im.messenger.xmpp.repository;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.core.util.ThreadUtils;
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.PeerModel;
import org.mercury_im.messenger.xmpp.util.ChatAndPossiblyContact;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import java.util.ArrayList;
import java.util.List;
@ -32,13 +31,13 @@ public class ChatRepository extends AbstractRepository<ChatModel> {
super(ChatModel.class, data, subscriberScheduler, observerScheduler);
}
public Observable<ReactiveResult<ChatModel>> getChatWith(EntityModel entityModel) {
return getChatWith(entityModel.getAccount().getId(), entityModel.getJid());
public Observable<ReactiveResult<ChatModel>> getChatWith(PeerModel entityModel) {
return getChatWith(entityModel.getAccount().getId(), entityModel.getAddress());
}
public Observable<ReactiveResult<ChatModel>> getChatWith(long accountId, EntityBareJid jid) {
return data().select(ChatModel.class).join(EntityModel.class).on(ChatModel.PEER_ID.eq(EntityModel.ID))
.where(EntityModel.ACCOUNT_ID.eq(accountId).and(EntityModel.JID.eq(jid)))
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())
@ -69,13 +68,13 @@ public class ChatRepository extends AbstractRepository<ChatModel> {
.observeOn(observerScheduler());
}
public Observable<ChatAndPossiblyContact> getChatAndContact(long accountId, EntityBareJid jid) {
public Observable<ChatAndPossiblyContact> getChatAndContact(long accountId, String address) {
return Observable.fromCallable(() -> {
ChatModel chat = data().select(ChatModel.class)
.from(ChatModel.class).join(EntityModel.class).on(ChatModel.PEER_ID.eq(EntityModel.ID))
.leftJoin(ContactModel.class).on(EntityModel.ID.eq(ContactModel.ENTITY_ID))
.where(EntityModel.ACCOUNT_ID.eq(accountId).and(EntityModel.JID.eq(jid)))
.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;

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.xmpp.repository;
import org.mercury_im.messenger.xmpp.model.EntityCapsModel;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import org.mercury_im.core.util.ThreadUtils;
import javax.inject.Inject;
import javax.inject.Named;

View File

@ -2,9 +2,9 @@ package org.mercury_im.messenger.xmpp.repository;
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.PeerModel;
import org.mercury_im.messenger.xmpp.model.MessageModel;
import org.mercury_im.messenger.thread_utils.ThreadUtils;
import org.mercury_im.core.util.ThreadUtils;
import javax.inject.Inject;
import javax.inject.Named;
@ -36,7 +36,7 @@ public class MessageRepository extends AbstractRepository<MessageModel> {
.observeOn(observerScheduler());
}
public Observable<ReactiveResult<MessageModel>> getAllMessagesOfEntity(EntityModel entity) {
public Observable<ReactiveResult<MessageModel>> getAllMessagesOfEntity(PeerModel entity) {
return getAllMessagesOfEntity(entity.getId());
}
@ -56,8 +56,8 @@ public class MessageRepository extends AbstractRepository<MessageModel> {
public Observable<ReactiveResult<MessageModel>> getAllMessagesOfContact(long contactId) {
return data().select(MessageModel.class).join(ChatModel.class).on(MessageModel.CHAT_ID.eq(ChatModel.ID))
.join(EntityModel.class).on(ChatModel.PEER_ID.eq(EntityModel.ID))
.join(ContactModel.class).on(EntityModel.ID.eq(ContactModel.ENTITY_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())

View File

@ -1,11 +1,9 @@
package org.mercury_im.messenger.xmpp.repository;
import org.mercury_im.messenger.core.entity.Account;
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.core.util.ThreadUtils;
import org.mercury_im.messenger.xmpp.mapping.AccountMapping;
import org.mercury_im.messenger.xmpp.model.AccountModel;
@ -24,7 +22,9 @@ import io.requery.Persistable;
import io.requery.query.ResultDelegate;
import io.requery.reactivex.ReactiveEntityStore;
public class ReactiveXmppAccountRepository extends RequeryRepository implements AccountRepository<XmppAccount, XmppAddress.XmppUserAddress> {
public class ReactiveXmppAccountRepository
extends RequeryRepository
implements AccountRepository {
@Inject
public ReactiveXmppAccountRepository(ReactiveEntityStore<Persistable> data,
@ -34,7 +34,7 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
}
@Override
public Single<XmppAccount> insertAccount(XmppAccount account) {
public Single<Account> insertAccount(Account account) {
return data().insert(AccountMapping.createModelFromEntity(account))
.map(AccountMapping::modelToEntity)
@ -43,7 +43,7 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
}
@Override
public Observable<Optional<XmppAccount>> observeAccount(long accountId) {
public Observable<Optional<Account>> observeAccount(long accountId) {
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(accountId))
.get().observableResult()
@ -54,7 +54,7 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
}
@Override
public Maybe<XmppAccount> getAccount(long accountId) {
public Maybe<Account> getAccount(long accountId) {
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(accountId))
.get().maybe()
@ -64,9 +64,9 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
}
@Override
public Observable<Optional<XmppAccount>> observeAccountByAddress(XmppAddress.XmppUserAddress address) {
public Observable<Optional<Account>> observeAccountByAddress(String address) {
return data().select(AccountModel.class)
.where(AccountModel.JID.eq(address.getJid()))
.where(AccountModel.ADDRESS.eq(address))
.get().observableResult()
.map(result -> new Optional<>(AccountMapping.modelToEntity(result.firstOrNull())))
.subscribeOn(subscriberScheduler())
@ -74,9 +74,9 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
}
@Override
public Maybe<XmppAccount> getAccountByAddress(XmppAddress.XmppUserAddress address) {
public Maybe<Account> getAccountByAddress(String address) {
return data().select(AccountModel.class)
.where(AccountModel.JID.eq(address.getJid()))
.where(AccountModel.ADDRESS.eq(address))
.get().maybe()
.map(AccountMapping::modelToEntity)
.subscribeOn(subscriberScheduler())
@ -84,12 +84,12 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
}
@Override
public Observable<List<XmppAccount>> observeAllAccounts() {
public Observable<List<Account>> observeAllAccounts() {
return data().select(AccountModel.class)
.get().observableResult()
.map(ResultDelegate::toList)
.map(list -> {
List<XmppAccount> entities = new ArrayList<>(list.size());
List<Account> entities = new ArrayList<>(list.size());
list.forEach(model -> entities.add(AccountMapping.modelToEntity(model)));
return entities;
})
@ -98,7 +98,7 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
}
@Override
public Single<XmppAccount> updateAccount(XmppAccount account) {
public Single<Account> updateAccount(Account 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
@ -109,8 +109,8 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
.map(model -> {
// update it
model.setEnabled(account.isEnabled());
model.setPassword(((XmppAuthMethod.AuthPassword) account.getAuthentication()).getPassword());
model.setJid(account.getAddress().getJid());
model.setPassword(account.getAuthentication().getPassword());
model.setAddress(account.getAddress());
// write the updated model back
model = data().update(model).blockingGet();
return AccountMapping.modelToEntity(model);
@ -120,7 +120,7 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
}
@Override
public Single<XmppAccount> upsertAccount(XmppAccount account) {
public Single<Account> upsertAccount(Account account) {
// Try to fetch model
return data().select(AccountModel.class)
.where(AccountModel.ID.eq(account.getId()))
@ -131,8 +131,8 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
.map(model -> {
// update the model
model.setEnabled(account.isEnabled());
model.setPassword(((XmppAuthMethod.AuthPassword) account.getAuthentication()).getPassword());
model.setJid(account.getAddress().getJid());
model.setPassword(account.getAuthentication().getPassword());
model.setAddress(account.getAddress());
// write the updated model back
model = data().update(model).blockingGet();
return AccountMapping.modelToEntity(model);
@ -142,7 +142,7 @@ public class ReactiveXmppAccountRepository extends RequeryRepository implements
}
@Override
public Completable deleteAccount(XmppAccount account) {
public Completable deleteAccount(Account account) {
return data().delete(AccountModel.class)
.where(AccountModel.ID.eq(account.getId()))
.get().single().ignoreElement() // to completable

View File

@ -1,10 +1,9 @@
package org.mercury_im.messenger.xmpp.repository;
import org.jxmpp.jid.EntityBareJid;
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 org.mercury_im.messenger.xmpp.model.PeerModel;
import org.mercury_im.core.util.ThreadUtils;
import javax.inject.Inject;
import javax.inject.Named;
@ -35,8 +34,8 @@ public class RosterRepository extends RequeryRepository {
}
public Observable<ReactiveResult<ContactModel>> getAllContactsOfAccount(long accountId) {
return data().select(ContactModel.class).join(EntityModel.class).on(ContactModel.ENTITY_ID.eq(EntityModel.ID))
.where(EntityModel.ACCOUNT_ID.eq(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());
}
@ -49,10 +48,10 @@ public class RosterRepository extends RequeryRepository {
return data().delete(contact).subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
public Completable deleteContact(long accountId, EntityBareJid jid) {
public Completable deleteContact(long accountId, String address) {
return data().delete(ContactModel.class).from(ContactModel.class)
.join(EntityModel.class).on(ContactModel.ENTITY_ID.eq(EntityModel.ID))
.where(EntityModel.ACCOUNT_ID.eq(accountId).and(EntityModel.JID.eq(jid)))
.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());
}
@ -63,66 +62,66 @@ public class RosterRepository extends RequeryRepository {
public Single<Integer> deleteAllContactsOfAccount(long accountId) {
return data().delete(ContactModel.class).from(ContactModel.class)
.join(EntityModel.class).on(ContactModel.ENTITY_ID.eq(EntityModel.ID))
.where(EntityModel.ACCOUNT_ID.eq(accountId))
.join(PeerModel.class).on(ContactModel.ENTITY_ID.eq(PeerModel.ID))
.where(PeerModel.ACCOUNT_ID.eq(accountId))
.get().single()
.subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
/*
EntityModel related methods
PeerModel related methods
*/
public Observable<ReactiveResult<EntityModel>> getAllEntitiesOfAccount(AccountModel account) {
public Observable<ReactiveResult<PeerModel>> getAllEntitiesOfAccount(AccountModel account) {
return getAllEntitiesOfAccount(account.getId());
}
public Observable<ReactiveResult<EntityModel>> getAllEntitiesOfAccount(long accountId) {
return data().select(EntityModel.class).where(EntityModel.ACCOUNT_ID.eq(accountId))
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<EntityModel>> getEntityById(long entityId) {
return data().select(EntityModel.class).where(EntityModel.ID.eq(entityId))
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<EntityModel>> getEntityByJid(AccountModel account, EntityBareJid jid) {
return getEntityByJid(account.getId(), jid);
public Observable<ReactiveResult<PeerModel>> getEntityByJid(AccountModel account, String address) {
return getEntityByJid(account.getId(), address);
}
public Observable<ReactiveResult<EntityModel>> getEntityByJid(long accountId, EntityBareJid jid) {
return data().select(EntityModel.class)
.where(EntityModel.ACCOUNT_ID.eq(accountId).and(EntityModel.JID.eq(jid)))
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<EntityModel> getOrCreateEntity(long accountId, EntityBareJid jid) {
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, jid).blockingGet();
return getOrCreateEntity(account, address).blockingGet();
})
.observeOn(observerScheduler())
.subscribeOn(subscriberScheduler());
}
public Single<EntityModel> getOrCreateEntity(AccountModel account, EntityBareJid jid) {
public Single<PeerModel> getOrCreateEntity(AccountModel account, String address) {
return Single.fromCallable(() -> {
EntityModel entity = data().select(EntityModel.class)
.where(EntityModel.ACCOUNT_ID.eq(account.getId()).and(EntityModel.JID.eq(jid)))
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 EntityModel();
entity = new PeerModel();
entity.setAccount(account);
entity.setJid(jid);
entity.setAddress(address);
entity = data().insert(entity).blockingGet();
}
return entity;
@ -132,13 +131,13 @@ public class RosterRepository extends RequeryRepository {
}
public Single<EntityModel> upsertEntity(EntityModel entity) {
public Single<PeerModel> upsertEntity(PeerModel entity) {
return data().upsert(entity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
public Completable deleteEntity(EntityModel entity) {
public Completable deleteEntity(PeerModel entity) {
return data().delete(entity)
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
@ -180,14 +179,14 @@ public class RosterRepository extends RequeryRepository {
.subscribeOn(subscriberScheduler()).observeOn(observerScheduler());
}
public Observable<ReactiveResult<ContactModel>> getContact(AccountModel account, EntityBareJid jid) {
return getContact(account.getId(), jid);
public Observable<ReactiveResult<ContactModel>> getContact(AccountModel account, String address) {
return getContact(account.getId(), address);
}
public Observable<ReactiveResult<ContactModel>> getContact(long accountId, EntityBareJid jid) {
public Observable<ReactiveResult<ContactModel>> getContact(long accountId, String address) {
return data().select(ContactModel.class).from(ContactModel.class)
.join(EntityModel.class).on(ContactModel.ENTITY_ID.eq(EntityModel.ID))
.where(EntityModel.ACCOUNT_ID.eq(accountId).and(EntityModel.JID.eq(jid)))
.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());

View File

@ -1,12 +1,9 @@
include ':entity',
':entity_xmpp',
':repository',
':data',
':repository_xmpp',
':core',
':transport',
':domain',
':transport_xmpp',
':app',
':thread_utils',
':core-old',
':view_entity'

View File

@ -1 +0,0 @@
/build

View File

@ -1,5 +0,0 @@
The purpose of this module is to hold the `ThreadUtils` class,
on which both modules `persistence` as well as `core` depend.
By moving that class into a separate module, we prevent a circular
dependency between `core` and `persistence`.

View File

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

View File

@ -1 +0,0 @@
/build

View File

@ -1,21 +0,0 @@
apply plugin: 'java-library'
dependencies {
implementation project(':entity')
implementation project(':repository')
implementation project(":thread_utils")
// RxJava2
implementation "io.reactivex.rxjava2:rxjava:$rxJava2Version"
// Dagger 2 for dependency injection
implementation "com.google.dagger:dagger:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
// JUnit for testing
testImplementation "junit:junit:$junitVersion"
}
sourceCompatibility = "8"
targetCompatibility = "8"

View File

@ -1,17 +0,0 @@
package org.mercury_im.core;
import org.mercury_im.core.connection.ConnectionMethod;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
public interface ConnectionFactory<
CM extends ConnectionMethod<AC, AD>,
AC extends Account<AD, AU>,
AD extends Address.UserAddress,
AU extends Account.AuthMethod> {
Messenger getMessenger();
CM provideConnection(AC account);
}

View File

@ -1,29 +0,0 @@
package org.mercury_im.core.connection;
import org.mercury_im.core.Messenger;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
public abstract class AbstractConnectionMethod<
AC extends Account<AD, ?>,
AD extends Address.UserAddress>
implements ConnectionMethod<AC, AD> {
protected final AC account;
protected final Messenger messenger;
public AbstractConnectionMethod(AC account, Messenger messenger) {
this.account = account;
this.messenger = messenger;
}
@Override
public AC getAccount() {
return account;
}
@Override
public Messenger getMessenger() {
return messenger;
}
}

View File

@ -1,19 +0,0 @@
package org.mercury_im.core.connection;
import org.mercury_im.core.Messenger;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
import io.reactivex.Completable;
public interface ConnectionMethod<
AC extends Account<AD, ?>,
AD extends Address.UserAddress> {
AC getAccount();
Messenger getMessenger();
Completable connect();
}

View File

@ -1,16 +0,0 @@
package org.mercury_im.core.listener;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.chat.DirectChat;
import org.mercury_im.messenger.core.entity.contact.Interlocutor;
import org.mercury_im.messenger.core.entity.message.AbstractMessage;
public interface IncomingDirectMessageListener<
AC extends Account<AD, ?>,
AD extends Address.UserAddress,
IL extends Interlocutor<AC, AD, AD>> {
void onIncomingDirectMessage(AC account, DirectChat<IL, AC, AD> chat, AbstractMessage<AD, ?> message);
}

View File

@ -1,19 +0,0 @@
package org.mercury_im.core.listener;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.chat.DirectChat;
import org.mercury_im.messenger.core.entity.chat.GroupChat;
import org.mercury_im.messenger.core.entity.contact.Interlocutor;
import org.mercury_im.messenger.core.entity.message.AbstractMessage;
public interface IncomingGroupChatMessageListener<
AC extends Account<AD, ?>,
AD extends Address.UserAddress,
RA extends Address.RoomAddress,
PA extends Address.RoomParticipantAddress,
IL extends Interlocutor<AC, PA, AD>> {
void onIncomingDirectMessage(AC account, GroupChat<AC, AD, RA, PA, IL> chat, AbstractMessage<PA, ?> message);
}

View File

@ -1,5 +0,0 @@
package org.mercury_im.core.listener;
public interface TypingEventListener {
}

View File

@ -1,21 +0,0 @@
package org.mercury_im.core.message;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.messenger.core.entity.Address;
import org.mercury_im.messenger.core.entity.chat.Chat;
import org.mercury_im.messenger.core.entity.message.Message;
import org.mercury_im.messenger.core.entity.message.MessageMetadata;
import io.reactivex.Completable;
public interface MessageCenter<
M extends Message<AD, MM>,
C extends Chat<AC, AD>,
AD extends Address.UserAddress,
MM extends MessageMetadata,
AC extends Account<AD, ?>> {
Completable sendMessage(M message, C chat);
void addIncomingMessageListener();
}

View File

@ -1,9 +1,9 @@
apply plugin: 'java-library'
dependencies {
implementation project(":entity")
implementation project(':domain')
implementation project(":repository_xmpp")
implementation project(":entity_xmpp")
implementation project(":transport")
// Smack
// Not all of those are needed, but it may be a good idea to define those versions explicitly

View File

@ -2,13 +2,12 @@ package org.mercury_im.xmpp.connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.mercury_im.core.ConnectionFactory;
import org.mercury_im.core.Messenger;
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.core.transport.connection.ConnectionFactory;
import org.mercury_im.messenger.core.entity.Account;
public abstract class XmppConnectionFactory implements ConnectionFactory<XmppConnectionMethod, XmppAccount, XmppAddress.XmppUserAddress, XmppAuthMethod> {
public abstract class XmppConnectionFactory<CF extends ConnectionConfiguration>
implements ConnectionFactory<XmppTcpConnectionMethod> {
protected final Messenger messenger;
@ -21,9 +20,11 @@ public abstract class XmppConnectionFactory implements ConnectionFactory<XmppCon
}
@Override
public XmppConnectionMethod provideConnection(XmppAccount account) {
return new XmppConnectionMethod(account, getMessenger(), createXmppConnection());
public XmppTcpConnectionMethod provideConnection(Account account) {
return new XmppTcpConnectionMethod(account, getMessenger(), createXmppConnection(getConfiguration(account)));
}
protected abstract XMPPConnection createXmppConnection(ConnectionConfiguration connectionConfiguration);
protected abstract CF getConfiguration(Account account);
protected abstract XMPPConnection createXmppConnection(CF connectionConfiguration);
}

View File

@ -1,29 +0,0 @@
package org.mercury_im.xmpp.connection;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.XMPPConnection;
import org.mercury_im.core.Messenger;
import org.mercury_im.core.connection.AbstractConnectionMethod;
import org.mercury_im.messenger.xmpp.entity.XmppAccount;
import org.mercury_im.messenger.xmpp.entity.XmppAddress;
import io.reactivex.Completable;
public class XmppConnectionMethod extends AbstractConnectionMethod<XmppAccount, XmppAddress.XmppUserAddress> {
private XMPPConnection connection;
public XmppConnectionMethod(XmppAccount account, Messenger messenger, XMPPConnection connection) {
super(account, messenger);
this.connection = connection;
}
@Override
public Completable connect() {
if (connection.isConnected()) {
return Completable.complete();
}
return Completable.fromAction(() -> ((AbstractXMPPConnection) connection).connect().login());
}
}

View File

@ -1,20 +1,36 @@
package org.mercury_im.xmpp.connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.core.Messenger;
import org.mercury_im.messenger.core.entity.Account;
import org.mercury_im.xmpp.entity.XmppAuthMethod;
public class XmppTcpConnectionFactory extends XmppConnectionFactory {
public class XmppTcpConnectionFactory extends XmppConnectionFactory<XMPPTCPConnectionConfiguration> {
public XmppTcpConnectionFactory(Messenger messenger) {
super(messenger);
}
@Override
protected XMPPConnection createXmppConnection(ConnectionConfiguration configuration) {
XMPPTCPConnectionConfiguration tcpConfiguration = (XMPPTCPConnectionConfiguration) configuration;
return new XMPPTCPConnection(tcpConfiguration);
protected XMPPTCPConnectionConfiguration getConfiguration(Account account) {
XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
configBuilder.setConnectTimeout(20 * 1000);
if (account.getAuthentication() instanceof XmppAuthMethod.AuthPassword) {
XmppAuthMethod.AuthPassword authPassword = (XmppAuthMethod.AuthPassword) account.getAuthentication();
EntityBareJid accountAddress = JidCreate.entityBareFromOrThrowUnchecked(account.getAddress());
configBuilder.setXmppAddressAndPassword(accountAddress, authPassword.getPassword());
}
return configBuilder.build();
}
@Override
protected XMPPConnection createXmppConnection(XMPPTCPConnectionConfiguration configuration) {
return new XMPPTCPConnection(configuration);
}
}

View File

@ -0,0 +1,59 @@
package org.mercury_im.xmpp.connection;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.XMPPConnection;
import org.mercury_im.core.Messenger;
import org.mercury_im.core.transport.ConnectionType;
import org.mercury_im.core.transport.connection.AbstractConnectionMethod;
import org.mercury_im.messenger.core.entity.Account;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.reactivex.Completable;
public class XmppTcpConnectionMethod extends AbstractConnectionMethod {
private static final Logger LOGGER = Logger.getLogger(XmppTcpConnectionMethod.class.getName());
private XMPPConnection connection;
public XmppTcpConnectionMethod(Account account, Messenger messenger, XMPPConnection connection) {
super(account, messenger);
this.connection = connection;
}
@Override
public Completable connect() {
if (connection.isConnected()) {
return Completable.complete();
}
return Completable.fromAction(
() -> {
AbstractXMPPConnection con = (AbstractXMPPConnection) connection;
try {
con.connect();
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception while connecting to XMPP account " + account.getId(), e);
throw e;
}
try {
con.login();
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception while logging into XMPP account " + account.getId(), e);
throw e;
}
});
}
public XMPPConnection getConnection() {
return connection;
}
@Override
public ConnectionType getConnectionType() {
return ConnectionType.SMACK_TCP;
}
}

View File

@ -2,49 +2,61 @@ package org.mercury_im.xmpp.connection.message;
import org.jivesoftware.smack.chat2.Chat;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.sid.element.OriginIdElement;
import org.mercury_im.core.message.MessageCenter;
import org.mercury_im.messenger.xmpp.entity.XmppAccount;
import org.mercury_im.messenger.xmpp.entity.XmppAddress;
import org.mercury_im.messenger.xmpp.entity.chat.XmppDirectChat;
import org.mercury_im.messenger.xmpp.entity.message.XmppMessage;
import org.mercury_im.messenger.xmpp.entity.message.XmppMessageMetadata;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.core.Messenger;
import org.mercury_im.core.transport.listener.IncomingDirectMessageListener;
import org.mercury_im.messenger.core.entity.message.Message;
import org.mercury_im.core.MessageCenter;
import org.mercury_im.messenger.core.entity.chat.DirectChat;
import org.mercury_im.xmpp.connection.XmppTcpConnectionMethod;
import io.reactivex.Completable;
public class XmppDirectMessageCenter
implements MessageCenter<
XmppMessage.DirectMessage,
XmppDirectChat,
XmppAddress.XmppUserAddress,
XmppMessageMetadata,
XmppAccount> {
implements MessageCenter<DirectChat> {
private final Messenger messenger;
public XmppDirectMessageCenter(Messenger messenger) {
this.messenger = messenger;
}
@Override
public Completable sendMessage(XmppMessage.DirectMessage message, XmppDirectChat chat) {
public Messenger getMessenger() {
return messenger;
}
@Override
public Completable sendMessage(Message message, DirectChat chat) {
ChatManager chatManager = getChatManager(chat);
Message smackMessage = new Message();
smackMessage.setFrom(chat.getAccount().getAddress().getJid());
smackMessage.setTo(chat.getInterlocutor().getAddress().getJid());
smackMessage.setType(Message.Type.chat);
EntityBareJid accountAddress =
JidCreate.entityBareFromOrThrowUnchecked(chat.getAccount().getAddress());
EntityBareJid peerAddress =
JidCreate.entityBareFromOrThrowUnchecked(chat.getPeer().getAddress());
org.jivesoftware.smack.packet.Message smackMessage = new org.jivesoftware.smack.packet.Message();
smackMessage.setFrom(accountAddress);
smackMessage.setTo(peerAddress);
smackMessage.setType(org.jivesoftware.smack.packet.Message.Type.chat);
OriginIdElement.addOriginId(smackMessage);
Chat smackChat = chatManager.chatWith(chat.getInterlocutor().getAddress().getJid());
Chat smackChat = chatManager.chatWith(peerAddress);
return Completable.fromAction(
() -> smackChat.send(smackMessage));
}
@Override
public void addIncomingMessageListener() {
public void addIncomingMessageListener(IncomingDirectMessageListener listener) {
}
protected ChatManager getChatManager(XmppDirectChat chat) {
return null;
protected ChatManager getChatManager(DirectChat chat) {
XmppTcpConnectionMethod connectionMethod = (XmppTcpConnectionMethod) getMessenger().getConnection(chat.getAccount());
return ChatManager.getInstanceFor(connectionMethod.getConnection());
}
}

Some files were not shown because too many files have changed in this diff Show More