From 43c1edae3937fd6c3d560ea8bab01138245bd49c Mon Sep 17 00:00:00 2001 From: kske Date: Thu, 16 Jul 2020 18:32:40 +0200 Subject: [PATCH] Adjust message queries for handshake sync This causes problems with group messages as the received date is null sometimes even though the status is RECEIVED. The ReceivedMessageProcessor on the client filters out the synced messages at the moment. --- common/src/main/java/envoy/data/Contact.java | 17 +++---- common/src/main/java/envoy/data/Group.java | 5 +- common/src/main/java/envoy/data/User.java | 4 +- .../main/java/envoy/server/data/Contact.java | 2 +- .../java/envoy/server/data/GroupMessage.java | 8 ++-- .../main/java/envoy/server/data/Message.java | 32 +++++++------ .../processors/LoginCredentialProcessor.java | 46 +++++++++++-------- 7 files changed, 64 insertions(+), 50 deletions(-) diff --git a/common/src/main/java/envoy/data/Contact.java b/common/src/main/java/envoy/data/Contact.java index 9a5fd0a..3fe71da 100644 --- a/common/src/main/java/envoy/data/Contact.java +++ b/common/src/main/java/envoy/data/Contact.java @@ -17,9 +17,10 @@ import java.util.Set; */ public abstract class Contact implements Serializable { - private final long id; - private final transient Set contacts; - private String name; + protected final long id; + protected final transient Set contacts; + + protected String name; private static final long serialVersionUID = 0L; @@ -55,19 +56,13 @@ public abstract class Contact implements Serializable { */ public void setName(String name) { this.name = name; } - /** - * {@inheritDoc} - */ - @Override - public String toString() { return String.format("Contact[id=%d,name=%s, contacts=%s]", id, name, contacts); } - /** * Provides a hash code based on the ID of this contact. * * @since Envoy Common v0.1-beta */ @Override - public int hashCode() { return Objects.hash(id); } + public final int hashCode() { return Objects.hash(id); } /** * Tests equality to another object. If that object is a contact as well, @@ -77,7 +72,7 @@ public abstract class Contact implements Serializable { * @return {code true} if both objects are contacts and have identical IDs */ @Override - public boolean equals(Object obj) { + public final boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Contact)) return false; return id == ((Contact) obj).id; diff --git a/common/src/main/java/envoy/data/Group.java b/common/src/main/java/envoy/data/Group.java index 4eb6b02..53f816f 100644 --- a/common/src/main/java/envoy/data/Group.java +++ b/common/src/main/java/envoy/data/Group.java @@ -36,6 +36,9 @@ public final class Group extends Contact { */ public Group(long id, String name, Set members) { super(id, name, members); } + @Override + public String toString() { return String.format("Group[id=%d,name=%s,%d member(s)]", id, name, contacts.size()); } + private void readObject(ObjectInputStream inputStream) throws Exception { inputStream.defaultReadObject(); var contacts = Contact.class.getDeclaredField("contacts"); @@ -51,5 +54,5 @@ public final class Group extends Contact { @SuppressWarnings("unchecked") @Override - public Set getContacts() { return (Set) super.getContacts(); } + public Set getContacts() { return (Set) contacts; } } diff --git a/common/src/main/java/envoy/data/User.java b/common/src/main/java/envoy/data/User.java index 7751ce3..a423934 100644 --- a/common/src/main/java/envoy/data/User.java +++ b/common/src/main/java/envoy/data/User.java @@ -99,7 +99,9 @@ public final class User extends Contact { } @Override - public String toString() { return String.format("User[id=%d,name=%s,status=%s,contacts=%s]", getID(), getName(), status, getContacts()); } + public String toString() { + return String.format("User[id=%d,name=%s,status=%s", id, name, status) + (contacts.isEmpty() ? "]" : "," + contacts.size() + " contact(s)]"); + } /** * @return the current status of this user diff --git a/server/src/main/java/envoy/server/data/Contact.java b/server/src/main/java/envoy/server/data/Contact.java index 79cd720..43a9983 100644 --- a/server/src/main/java/envoy/server/data/Contact.java +++ b/server/src/main/java/envoy/server/data/Contact.java @@ -103,5 +103,5 @@ public abstract class Contact { public void setCreationDate(Instant creationDate) { this.creationDate = creationDate; } @Override - public String toString() { return String.format("%s[id=%d,name=%s, %d contact(s)]", getClass().getSimpleName(), id, name, contacts.size()); } + public String toString() { return String.format("%s[id=%d,name=%s,%d contact(s)]", getClass().getSimpleName(), id, name, contacts.size()); } } diff --git a/server/src/main/java/envoy/server/data/GroupMessage.java b/server/src/main/java/envoy/server/data/GroupMessage.java index bb96895..45be27d 100644 --- a/server/src/main/java/envoy/server/data/GroupMessage.java +++ b/server/src/main/java/envoy/server/data/GroupMessage.java @@ -19,10 +19,10 @@ import envoy.data.Group; @Entity @NamedQuery( name = GroupMessage.getPendingGroupMsg, - query = "SELECT m FROM GroupMessage m JOIN m.memberMessageStatus s WHERE (KEY(s) = :userId) AND ((m.creationDate > :lastSeen)" - + "OR ((m.status = envoy.data.Message$MessageStatus.RECEIVED) AND (m.receivedDate > :lastSeen))" - + "OR ((m.status = envoy.data.Message$MessageStatus.READ) AND (m.readDate > :lastSeen))" - + "OR ((m.lastStatusChangeDate > :lastSeen)))" + query = "SELECT m FROM GroupMessage m JOIN m.memberMessageStatus s WHERE KEY(s) = :userId AND (m.creationDate > :lastSeen " + + "OR m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen " + + "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen " + + "OR m.lastStatusChangeDate > :lastSeen)" ) public class GroupMessage extends Message { diff --git a/server/src/main/java/envoy/server/data/Message.java b/server/src/main/java/envoy/server/data/Message.java index d99b3b0..fc564a2 100755 --- a/server/src/main/java/envoy/server/data/Message.java +++ b/server/src/main/java/envoy/server/data/Message.java @@ -12,11 +12,15 @@ import envoy.data.Message.MessageStatus; import envoy.data.MessageBuilder; /** - * This class serves as a way to let Hibernate communicate with the server - * without bringing the dependency of JPA/Hibernate into the client.
- * It will be referenced as "database message" to clarify between the different - * message objects.
- *
+ * This JPA entity, which will be referred to as database message, stores the + * information contained inside a {@link envoy.data.Message} inside the + * database, while having a slightly different data layout. + *

+ * A message can be converted to a database message by using the + * {@link Message#Message(envoy.data.Message)} constructor. A database message + * can be converted to a regular message using the {@link Message#toCommon()} + * method. In both cases, the objects will not contain references to each other. + *

* Project: envoy-server-standalone
* File: Message.java
* Created: 02.01.2020
@@ -29,9 +33,14 @@ import envoy.data.MessageBuilder; @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @NamedQuery( name = Message.getPending, - query = "SELECT m FROM Message m WHERE (m.recipient = :user AND m.status = envoy.data.Message$MessageStatus.SENT) " - + "OR (m.sender = :user) AND ((m.status = envoy.data.Message$MessageStatus.RECEIVED) AND (m.receivedDate > :lastSeen)" - + "OR (m.status = envoy.data.Message$MessageStatus.READ) AND (m.readDate > :lastSeen))" + query = "SELECT m FROM Message m WHERE " + // Send to or by the user before last seen + + "(m.sender = :user OR m.recipient = :user) AND m.creationDate > :lastSeen " + // SENT to the user + + "OR m.recipient = :user AND m.status = envoy.data.Message$MessageStatus.SENT " + // Sent by the user and RECEIVED / READ after last seen + + "OR m.sender = :user AND (m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen " + + "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen)" ) public class Message { @@ -107,17 +116,14 @@ public class Message { * message * @since Envoy Server Standalone v0.1-alpha */ - public envoy.data.Message toCommon() { - return prepareBuilder().build(); - } + public envoy.data.Message toCommon() { return prepareBuilder().build(); } /** * @return a message builder containing the state of this message * @since Envoy Server Standalone v0.1-beta */ MessageBuilder prepareBuilder() { - var builder = new MessageBuilder(sender.getID(), recipient.getID(), id).setText( - text) + var builder = new MessageBuilder(sender.getID(), recipient.getID(), id).setText(text) .setCreationDate(creationDate) .setReceivedDate(receivedDate) .setReadDate(readDate) diff --git a/server/src/main/java/envoy/server/processors/LoginCredentialProcessor.java b/server/src/main/java/envoy/server/processors/LoginCredentialProcessor.java index 479e249..f7ee34e 100755 --- a/server/src/main/java/envoy/server/processors/LoginCredentialProcessor.java +++ b/server/src/main/java/envoy/server/processors/LoginCredentialProcessor.java @@ -123,7 +123,11 @@ public final class LoginCredentialProcessor implements ObjectProcessor - writeProxy.write(socketID, new GroupMessageStatusChange(gmsg.getID(), memberStatus, gmsg.getLastStatusChangeDate(), memberID))); + gmsg.getMemberMessageStatus() + .forEach((memberID, memberStatus) -> writeProxy.write(socketID, + new GroupMessageStatusChange(gmsg.getID(), memberStatus, gmsg.getLastStatusChangeDate(), memberID))); } // Deliver just a status change instead of the whole message