From 33dc6ba4acae4b598556e40bf83389489ea052c0 Mon Sep 17 00:00:00 2001 From: kske Date: Sat, 8 Feb 2020 13:53:58 +0100 Subject: [PATCH 01/10] Implemented user search response --- pom.xml | 2 +- src/main/java/envoy/server/data/User.java | 4 +-- .../server/database/PersistenceManager.java | 4 +++ .../processors/ContactsRequestProcesor.java | 33 +++++++++++++++++++ .../processors/LoginCredentialProcessor.java | 3 +- 5 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 src/main/java/envoy/server/processors/ContactsRequestProcesor.java diff --git a/pom.xml b/pom.xml index db5b8da..da0d59a 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ com.github.informatik-ag-ngl envoy-common - develop-SNAPSHOT + f~contacts-SNAPSHOT com.github.informatik-ag-ngl diff --git a/src/main/java/envoy/server/data/User.java b/src/main/java/envoy/server/data/User.java index 877a699..6a07bcf 100644 --- a/src/main/java/envoy/server/data/User.java +++ b/src/main/java/envoy/server/data/User.java @@ -22,8 +22,8 @@ import javax.persistence.*; @Table(name = "users") @NamedQueries( { @NamedQuery(query = "SELECT u FROM User u WHERE u.name = :name", name = "getUserByName"), - @NamedQuery(query = "SELECT u.contacts FROM User u WHERE u = :user", name = "getContactsOfUser")// not tested - } + @NamedQuery(query = "SELECT u.contacts FROM User u WHERE u = :user", name = "getContactsOfUser"), // not tested + @NamedQuery(query = "SELECT u FROM User u WHERE lower(u.name) LIKE lower(:searchPhrase)", name = "searchUsers") } ) public class User { diff --git a/src/main/java/envoy/server/database/PersistenceManager.java b/src/main/java/envoy/server/database/PersistenceManager.java index 84587e6..32a5219 100644 --- a/src/main/java/envoy/server/database/PersistenceManager.java +++ b/src/main/java/envoy/server/database/PersistenceManager.java @@ -176,6 +176,10 @@ public class PersistenceManager { return entityManager.createNamedQuery("getUnreadMessages").setParameter("recipient", user).getResultList(); } + public List searchUsers(String searchPhrase) { + return entityManager.createNamedQuery("searchUsers").setParameter("searchPhrase", searchPhrase).getResultList(); + } + /** * @param user the User whose contacts should be retrieved * @return the contacts of this User - currently everyone using Envoy diff --git a/src/main/java/envoy/server/processors/ContactsRequestProcesor.java b/src/main/java/envoy/server/processors/ContactsRequestProcesor.java new file mode 100644 index 0000000..7757345 --- /dev/null +++ b/src/main/java/envoy/server/processors/ContactsRequestProcesor.java @@ -0,0 +1,33 @@ +package envoy.server.processors; + +import java.io.IOException; +import java.util.stream.Collectors; + +import envoy.event.ContactsRequest; +import envoy.server.ObjectProcessor; +import envoy.server.database.PersistenceManager; +import envoy.server.net.ObjectWriteProxy; + +/** + * Project: envoy-server-standalone
+ * File: ContactsRequestProcesor.java
+ * Created: 08.02.2020
+ * + * @author Kai S. K. Engelbart + * @since Envoy Server Standalone v0.1-alpha + */ +public class ContactsRequestProcesor implements ObjectProcessor { + + @Override + public void process(ContactsRequest request, long socketId, ObjectWriteProxy writeProxy) throws IOException { + writeProxy.write(socketId, + PersistenceManager.getPersistenceManager() + .searchUsers(request.get()) + .stream() + .map(envoy.server.data.User::toCommonUser) + .collect(Collectors.toList())); + } + + @Override + public Class getInputClass() { return ContactsRequest.class; } +} diff --git a/src/main/java/envoy/server/processors/LoginCredentialProcessor.java b/src/main/java/envoy/server/processors/LoginCredentialProcessor.java index 4a7f2c8..2bad4e4 100644 --- a/src/main/java/envoy/server/processors/LoginCredentialProcessor.java +++ b/src/main/java/envoy/server/processors/LoginCredentialProcessor.java @@ -52,8 +52,7 @@ public class LoginCredentialProcessor implements ObjectProcessor Date: Sat, 8 Feb 2020 14:27:21 +0100 Subject: [PATCH 02/10] Fixed user search --- src/main/java/envoy/server/Startup.java | 8 +++++++- .../java/envoy/server/database/PersistenceManager.java | 2 +- .../envoy/server/processors/ContactsRequestProcesor.java | 5 +++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/envoy/server/Startup.java b/src/main/java/envoy/server/Startup.java index 8ccbe5e..f4e5bc7 100644 --- a/src/main/java/envoy/server/Startup.java +++ b/src/main/java/envoy/server/Startup.java @@ -10,7 +10,12 @@ import envoy.server.data.ConfigItem; import envoy.server.database.PersistenceManager; import envoy.server.net.ObjectMessageProcessor; import envoy.server.net.ObjectMessageReader; -import envoy.server.processors.*; +import envoy.server.processors.ContactsRequestProcesor; +import envoy.server.processors.IdGeneratorRequestProcessor; +import envoy.server.processors.LoginCredentialProcessor; +import envoy.server.processors.MessageProcessor; +import envoy.server.processors.MessageStatusChangeProcessor; +import envoy.server.processors.UserStatusChangeProcessor; /** * Starts the server.
@@ -38,6 +43,7 @@ public class Startup { processors.add(new MessageStatusChangeProcessor()); processors.add(new UserStatusChangeProcessor()); processors.add(new IdGeneratorRequestProcessor()); + processors.add(new ContactsRequestProcesor()); Server server = new Server(8080, () -> new ObjectMessageReader(), new ObjectMessageProcessor(processors)); initializeCurrentMessageId(); diff --git a/src/main/java/envoy/server/database/PersistenceManager.java b/src/main/java/envoy/server/database/PersistenceManager.java index 32a5219..91c7b19 100644 --- a/src/main/java/envoy/server/database/PersistenceManager.java +++ b/src/main/java/envoy/server/database/PersistenceManager.java @@ -177,7 +177,7 @@ public class PersistenceManager { } public List searchUsers(String searchPhrase) { - return entityManager.createNamedQuery("searchUsers").setParameter("searchPhrase", searchPhrase).getResultList(); + return entityManager.createNamedQuery("searchUsers").setParameter("searchPhrase", searchPhrase + "%").getResultList(); } /** diff --git a/src/main/java/envoy/server/processors/ContactsRequestProcesor.java b/src/main/java/envoy/server/processors/ContactsRequestProcesor.java index 7757345..13bda86 100644 --- a/src/main/java/envoy/server/processors/ContactsRequestProcesor.java +++ b/src/main/java/envoy/server/processors/ContactsRequestProcesor.java @@ -3,6 +3,7 @@ package envoy.server.processors; import java.io.IOException; import java.util.stream.Collectors; +import envoy.data.Contacts; import envoy.event.ContactsRequest; import envoy.server.ObjectProcessor; import envoy.server.database.PersistenceManager; @@ -21,11 +22,11 @@ public class ContactsRequestProcesor implements ObjectProcessor @Override public void process(ContactsRequest request, long socketId, ObjectWriteProxy writeProxy) throws IOException { writeProxy.write(socketId, - PersistenceManager.getPersistenceManager() + new Contacts(PersistenceManager.getPersistenceManager() .searchUsers(request.get()) .stream() .map(envoy.server.data.User::toCommonUser) - .collect(Collectors.toList())); + .collect(Collectors.toList()))); } @Override From 24c0cdd38dd49248becea7477392ceba923b653c Mon Sep 17 00:00:00 2001 From: kske Date: Sat, 8 Feb 2020 15:03:03 +0100 Subject: [PATCH 03/10] Added ContactOperationProcessor for the ADD operation --- .../server/database/PersistenceManager.java | 9 +++++ .../processors/ContactOperationProcessor.java | 33 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/main/java/envoy/server/processors/ContactOperationProcessor.java diff --git a/src/main/java/envoy/server/database/PersistenceManager.java b/src/main/java/envoy/server/database/PersistenceManager.java index 91c7b19..9815ebe 100644 --- a/src/main/java/envoy/server/database/PersistenceManager.java +++ b/src/main/java/envoy/server/database/PersistenceManager.java @@ -180,6 +180,15 @@ public class PersistenceManager { return entityManager.createNamedQuery("searchUsers").setParameter("searchPhrase", searchPhrase + "%").getResultList(); } + public void addContact(long userId, long contactId) { + User c1 = getUserById(userId); + User c2 = getUserById(contactId); + c1.getContacts().add(c2); + c2.getContacts().add(c1); + updateUser(c1); + updateUser(c2); + } + /** * @param user the User whose contacts should be retrieved * @return the contacts of this User - currently everyone using Envoy diff --git a/src/main/java/envoy/server/processors/ContactOperationProcessor.java b/src/main/java/envoy/server/processors/ContactOperationProcessor.java new file mode 100644 index 0000000..577a176 --- /dev/null +++ b/src/main/java/envoy/server/processors/ContactOperationProcessor.java @@ -0,0 +1,33 @@ +package envoy.server.processors; + +import java.io.IOException; + +import envoy.event.ContactOperation; +import envoy.event.ContactOperation.Operation; +import envoy.server.ConnectionManager; +import envoy.server.ObjectProcessor; +import envoy.server.database.PersistenceManager; +import envoy.server.net.ObjectWriteProxy; + +/** + * Project: envoy-server-standalone
+ * File: ContactOperationProcessor.java
+ * Created: 08.02.2020
+ * + * @author Kai S. K. Engelbart + * @since Envoy Server Standalone v0.1-alpha + */ +public class ContactOperationProcessor implements ObjectProcessor { + + @Override + public void process(ContactOperation operation, long socketId, ObjectWriteProxy writeProxy) throws IOException { + if (operation.getOperationType() == Operation.ADD) { + long userId = ConnectionManager.getInstance().getUserIdBySocketId(socketId); + System.out.printf("Adding user %s to the contact list of user %d", operation.get(), userId); + PersistenceManager.getPersistenceManager().addContact(userId, operation.get().getId()); + } + } + + @Override + public Class getInputClass() { return ContactOperation.class; } +} From 8d4de87dbbd562c06a7c785e02a43adc4bf1213c Mon Sep 17 00:00:00 2001 From: kske Date: Sun, 9 Feb 2020 16:01:05 +0100 Subject: [PATCH 04/10] Fixed incorrect online status User objects were created with the status ONLINE even if the actual status in the database was a different one. This issue has been fixed. --- src/main/java/envoy/server/data/User.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/envoy/server/data/User.java b/src/main/java/envoy/server/data/User.java index 877a699..7b9cbd7 100644 --- a/src/main/java/envoy/server/data/User.java +++ b/src/main/java/envoy/server/data/User.java @@ -64,7 +64,7 @@ public class User { * @return a database {@link User} converted into an {@link envoy.data.User} * @since Envoy Server Standalone v0.1-alpha */ - public envoy.data.User toCommonUser() { return new envoy.data.User(id, name); } + public envoy.data.User toCommonUser() { return new envoy.data.User(id, name, status); } /** * @return the id of a {link envoy.data.User} From 37f1594989226a4c3190c6816dcc293409bd4008 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sun, 9 Feb 2020 22:16:33 +0100 Subject: [PATCH 05/10] Implemented AddContact mechanism on the server (currently unfinished an not working see stack trace for current problem) --- src/main/java/envoy/server/Startup.java | 2 ++ src/main/java/envoy/server/data/User.java | 12 +++++++++++- .../envoy/server/database/PersistenceManager.java | 4 +++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/envoy/server/Startup.java b/src/main/java/envoy/server/Startup.java index f4e5bc7..8039f24 100644 --- a/src/main/java/envoy/server/Startup.java +++ b/src/main/java/envoy/server/Startup.java @@ -10,6 +10,7 @@ import envoy.server.data.ConfigItem; import envoy.server.database.PersistenceManager; import envoy.server.net.ObjectMessageProcessor; import envoy.server.net.ObjectMessageReader; +import envoy.server.processors.ContactOperationProcessor; import envoy.server.processors.ContactsRequestProcesor; import envoy.server.processors.IdGeneratorRequestProcessor; import envoy.server.processors.LoginCredentialProcessor; @@ -44,6 +45,7 @@ public class Startup { processors.add(new UserStatusChangeProcessor()); processors.add(new IdGeneratorRequestProcessor()); processors.add(new ContactsRequestProcesor()); + processors.add(new ContactOperationProcessor()); Server server = new Server(8080, () -> new ObjectMessageReader(), new ObjectMessageProcessor(processors)); initializeCurrentMessageId(); diff --git a/src/main/java/envoy/server/data/User.java b/src/main/java/envoy/server/data/User.java index 6a07bcf..9865978 100644 --- a/src/main/java/envoy/server/data/User.java +++ b/src/main/java/envoy/server/data/User.java @@ -3,7 +3,17 @@ package envoy.server.data; import java.util.Date; import java.util.List; -import javax.persistence.*; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; /** * This class serves as a way to let Hibernate communicate with the server diff --git a/src/main/java/envoy/server/database/PersistenceManager.java b/src/main/java/envoy/server/database/PersistenceManager.java index 9815ebe..0ec57d6 100644 --- a/src/main/java/envoy/server/database/PersistenceManager.java +++ b/src/main/java/envoy/server/database/PersistenceManager.java @@ -194,7 +194,9 @@ public class PersistenceManager { * @return the contacts of this User - currently everyone using Envoy * @since Envoy Server Standalone v0.1-alpha */ - public List getContacts(User user) { return entityManager.createQuery("FROM User").getResultList(); } + public List getContacts(User user) { + return entityManager.createNamedQuery("getContactsOfUser").setParameter("user", user).getResultList(); + } // TODO current solution gets all users, not just contacts. Should be changed to // entityManager.createNamedQuery("getContactsOfUser").setParameter("user", // user).getResultList(); From a96199ccd7c7734a545b525e1386843a170be453 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Mon, 10 Feb 2020 20:02:05 +0100 Subject: [PATCH 06/10] Implemented contact adding mechanism + database update on both clients. * Added filtering on searchRequest response (temporary: has to be done in query not manually in ContactsRequestProcessor.) --- src/main/java/envoy/server/data/User.java | 7 ++-- .../server/database/PersistenceManager.java | 8 ++--- .../processors/ContactsRequestProcesor.java | 33 +++++++++++++++---- .../processors/LoginCredentialProcessor.java | 2 +- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/main/java/envoy/server/data/User.java b/src/main/java/envoy/server/data/User.java index 9865978..a7e9bb5 100644 --- a/src/main/java/envoy/server/data/User.java +++ b/src/main/java/envoy/server/data/User.java @@ -8,9 +8,9 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.ManyToMany; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; -import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; @@ -26,13 +26,14 @@ import javax.persistence.TemporalType; * Created: 02.01.2020
* * @author Kai S. K. Engelbart + * @author Maximilian Käfer * @since Envoy Server Standalone v0.1-alpha */ @Entity @Table(name = "users") @NamedQueries( { @NamedQuery(query = "SELECT u FROM User u WHERE u.name = :name", name = "getUserByName"), - @NamedQuery(query = "SELECT u.contacts FROM User u WHERE u = :user", name = "getContactsOfUser"), // not tested + @NamedQuery(query = "SELECT u.contacts FROM User u WHERE u = :user", name = "getContactsOfUser"), @NamedQuery(query = "SELECT u FROM User u WHERE lower(u.name) LIKE lower(:searchPhrase)", name = "searchUsers") } ) public class User { @@ -47,7 +48,7 @@ public class User { private Date lastSeen; private envoy.data.User.UserStatus status; - @OneToMany(targetEntity = User.class, cascade = CascadeType.ALL, orphanRemoval = true) + @ManyToMany(targetEntity = User.class, cascade = CascadeType.ALL) // , orphanRemoval = true private List contacts; /** diff --git a/src/main/java/envoy/server/database/PersistenceManager.java b/src/main/java/envoy/server/database/PersistenceManager.java index 0ec57d6..a5cb160 100644 --- a/src/main/java/envoy/server/database/PersistenceManager.java +++ b/src/main/java/envoy/server/database/PersistenceManager.java @@ -172,10 +172,12 @@ public class PersistenceManager { * @return all messages that the client does not yet have (unread messages) * @since Envoy Server Standalone v0.1-alpha */ + @SuppressWarnings("unchecked") public List getUnreadMessages(User user) { return entityManager.createNamedQuery("getUnreadMessages").setParameter("recipient", user).getResultList(); } + @SuppressWarnings("unchecked") public List searchUsers(String searchPhrase) { return entityManager.createNamedQuery("searchUsers").setParameter("searchPhrase", searchPhrase + "%").getResultList(); } @@ -191,13 +193,11 @@ public class PersistenceManager { /** * @param user the User whose contacts should be retrieved - * @return the contacts of this User - currently everyone using Envoy + * @return the contacts of this User * @since Envoy Server Standalone v0.1-alpha */ + @SuppressWarnings("unchecked") public List getContacts(User user) { return entityManager.createNamedQuery("getContactsOfUser").setParameter("user", user).getResultList(); } - // TODO current solution gets all users, not just contacts. Should be changed to - // entityManager.createNamedQuery("getContactsOfUser").setParameter("user", - // user).getResultList(); } \ No newline at end of file diff --git a/src/main/java/envoy/server/processors/ContactsRequestProcesor.java b/src/main/java/envoy/server/processors/ContactsRequestProcesor.java index 13bda86..32e9714 100644 --- a/src/main/java/envoy/server/processors/ContactsRequestProcesor.java +++ b/src/main/java/envoy/server/processors/ContactsRequestProcesor.java @@ -1,11 +1,14 @@ package envoy.server.processors; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.stream.Collectors; import envoy.data.Contacts; import envoy.event.ContactsRequest; import envoy.server.ObjectProcessor; +import envoy.server.data.User; import envoy.server.database.PersistenceManager; import envoy.server.net.ObjectWriteProxy; @@ -15,18 +18,36 @@ import envoy.server.net.ObjectWriteProxy; * Created: 08.02.2020
* * @author Kai S. K. Engelbart + * @author Maximilian Käfer * @since Envoy Server Standalone v0.1-alpha */ public class ContactsRequestProcesor implements ObjectProcessor { @Override public void process(ContactsRequest request, long socketId, ObjectWriteProxy writeProxy) throws IOException { - writeProxy.write(socketId, - new Contacts(PersistenceManager.getPersistenceManager() - .searchUsers(request.get()) - .stream() - .map(envoy.server.data.User::toCommonUser) - .collect(Collectors.toList()))); + // Creating a List containing all searchResults + List resultList = PersistenceManager.getPersistenceManager().searchUsers(request.get()); + // Creating a List containing all contacts of the client this event comes from. + List clientContacts = PersistenceManager.getPersistenceManager() + .getContacts(PersistenceManager.getPersistenceManager().getUserById(request.getClient().getId())); + List returnList = new ArrayList(); + + // Checking for already existing users in the contacts of the client an only + // adding the ones not included to the returnList. + if (clientContacts.size() != 0) { + for (int i = 0; i < resultList.size(); i++) { + for (int j = 0; j < clientContacts.size(); j++) { + if (resultList.get(i).getId() != clientContacts.get(j).getId()) { returnList.add(resultList.get(i)); } + } + } + } else { + for (int i = 0; i < resultList.size(); i++) { + returnList.add(resultList.get(i)); + } + } + // Create new Contacts object from returnList + Contacts contacts = new Contacts(returnList.stream().map(envoy.server.data.User::toCommonUser).collect(Collectors.toList())); + writeProxy.write(socketId, contacts); } @Override diff --git a/src/main/java/envoy/server/processors/LoginCredentialProcessor.java b/src/main/java/envoy/server/processors/LoginCredentialProcessor.java index 2bad4e4..1c16070 100644 --- a/src/main/java/envoy/server/processors/LoginCredentialProcessor.java +++ b/src/main/java/envoy/server/processors/LoginCredentialProcessor.java @@ -80,8 +80,8 @@ public class LoginCredentialProcessor implements ObjectProcessor Date: Mon, 10 Feb 2020 22:29:34 +0100 Subject: [PATCH 07/10] Refactored contact search, added Javadoc --- pom.xml | 2 +- src/main/java/envoy/server/Startup.java | 10 +--- src/main/java/envoy/server/data/User.java | 24 +++----- .../server/database/PersistenceManager.java | 41 ++++++++++---- .../processors/ContactOperationProcessor.java | 14 ++--- .../ContactsRequestEventProcessor.java | 44 +++++++++++++++ .../processors/ContactsRequestProcesor.java | 55 ------------------- .../processors/LoginCredentialProcessor.java | 6 +- 8 files changed, 94 insertions(+), 102 deletions(-) create mode 100644 src/main/java/envoy/server/processors/ContactsRequestEventProcessor.java delete mode 100644 src/main/java/envoy/server/processors/ContactsRequestProcesor.java diff --git a/pom.xml b/pom.xml index da0d59a..db5b8da 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ com.github.informatik-ag-ngl envoy-common - f~contacts-SNAPSHOT + develop-SNAPSHOT com.github.informatik-ag-ngl diff --git a/src/main/java/envoy/server/Startup.java b/src/main/java/envoy/server/Startup.java index 8039f24..e23bf69 100644 --- a/src/main/java/envoy/server/Startup.java +++ b/src/main/java/envoy/server/Startup.java @@ -10,13 +10,7 @@ import envoy.server.data.ConfigItem; import envoy.server.database.PersistenceManager; import envoy.server.net.ObjectMessageProcessor; import envoy.server.net.ObjectMessageReader; -import envoy.server.processors.ContactOperationProcessor; -import envoy.server.processors.ContactsRequestProcesor; -import envoy.server.processors.IdGeneratorRequestProcessor; -import envoy.server.processors.LoginCredentialProcessor; -import envoy.server.processors.MessageProcessor; -import envoy.server.processors.MessageStatusChangeProcessor; -import envoy.server.processors.UserStatusChangeProcessor; +import envoy.server.processors.*; /** * Starts the server.
@@ -44,7 +38,7 @@ public class Startup { processors.add(new MessageStatusChangeProcessor()); processors.add(new UserStatusChangeProcessor()); processors.add(new IdGeneratorRequestProcessor()); - processors.add(new ContactsRequestProcesor()); + processors.add(new ContactsRequestEventProcessor()); processors.add(new ContactOperationProcessor()); Server server = new Server(8080, () -> new ObjectMessageReader(), new ObjectMessageProcessor(processors)); diff --git a/src/main/java/envoy/server/data/User.java b/src/main/java/envoy/server/data/User.java index a7e9bb5..543fec7 100644 --- a/src/main/java/envoy/server/data/User.java +++ b/src/main/java/envoy/server/data/User.java @@ -3,17 +3,7 @@ package envoy.server.data; import java.util.Date; import java.util.List; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.ManyToMany; -import javax.persistence.NamedQueries; -import javax.persistence.NamedQuery; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import javax.persistence.*; /** * This class serves as a way to let Hibernate communicate with the server @@ -32,9 +22,13 @@ import javax.persistence.TemporalType; @Entity @Table(name = "users") @NamedQueries( - { @NamedQuery(query = "SELECT u FROM User u WHERE u.name = :name", name = "getUserByName"), - @NamedQuery(query = "SELECT u.contacts FROM User u WHERE u = :user", name = "getContactsOfUser"), - @NamedQuery(query = "SELECT u FROM User u WHERE lower(u.name) LIKE lower(:searchPhrase)", name = "searchUsers") } + { @NamedQuery(query = "SELECT u FROM User u WHERE u.name = :name", name = "getUserByName"), @NamedQuery( + query = "SELECT u.contacts FROM User u WHERE u = :user", + name = "getContactsOfUser" + ), @NamedQuery( + query = "SELECT u FROM User u WHERE (lower(u.name) LIKE lower(:searchPhrase) AND u <> :context AND NOT :context in elements(u.contacts))", + name = "searchUsers" + ) } ) public class User { @@ -48,7 +42,7 @@ public class User { private Date lastSeen; private envoy.data.User.UserStatus status; - @ManyToMany(targetEntity = User.class, cascade = CascadeType.ALL) // , orphanRemoval = true + @ManyToMany(targetEntity = User.class, cascade = CascadeType.ALL) private List contacts; /** diff --git a/src/main/java/envoy/server/database/PersistenceManager.java b/src/main/java/envoy/server/database/PersistenceManager.java index a5cb160..8943f52 100644 --- a/src/main/java/envoy/server/database/PersistenceManager.java +++ b/src/main/java/envoy/server/database/PersistenceManager.java @@ -172,23 +172,41 @@ public class PersistenceManager { * @return all messages that the client does not yet have (unread messages) * @since Envoy Server Standalone v0.1-alpha */ - @SuppressWarnings("unchecked") public List getUnreadMessages(User user) { return entityManager.createNamedQuery("getUnreadMessages").setParameter("recipient", user).getResultList(); } - @SuppressWarnings("unchecked") - public List searchUsers(String searchPhrase) { - return entityManager.createNamedQuery("searchUsers").setParameter("searchPhrase", searchPhrase + "%").getResultList(); + /** + * Searches for users matching a search phrase. Contacts of the attached user + * and the attached user is ignored. + * + * @param searchPhrase the search phrase + * @param userId the ID of the user in whose context the search is + * performed + * @return a list of all users who matched the criteria + * @since Envoy Server Standalone v0.1-alpha + */ + public List searchUsers(String searchPhrase, long userId) { + return entityManager.createNamedQuery("searchUsers") + .setParameter("searchPhrase", searchPhrase + "%") + .setParameter("context", getUserById(userId)) + .getResultList(); } - public void addContact(long userId, long contactId) { - User c1 = getUserById(userId); - User c2 = getUserById(contactId); - c1.getContacts().add(c2); - c2.getContacts().add(c1); - updateUser(c1); - updateUser(c2); + /** + * Adds a user to the contact list of another user and vice versa. + * + * @param userId1 the ID of the first user + * @param userId2 the ID of the second user + * @since Envoy Server Standalone v0.1-alpha + */ + public void addContact(long userId1, long userId2) { + User u1 = getUserById(userId1); + User u2 = getUserById(userId2); + u1.getContacts().add(u2); + u2.getContacts().add(u1); + updateUser(u1); + updateUser(u2); } /** @@ -196,7 +214,6 @@ public class PersistenceManager { * @return the contacts of this User * @since Envoy Server Standalone v0.1-alpha */ - @SuppressWarnings("unchecked") public List getContacts(User user) { return entityManager.createNamedQuery("getContactsOfUser").setParameter("user", user).getResultList(); } diff --git a/src/main/java/envoy/server/processors/ContactOperationProcessor.java b/src/main/java/envoy/server/processors/ContactOperationProcessor.java index 577a176..475f8a2 100644 --- a/src/main/java/envoy/server/processors/ContactOperationProcessor.java +++ b/src/main/java/envoy/server/processors/ContactOperationProcessor.java @@ -2,8 +2,8 @@ package envoy.server.processors; import java.io.IOException; -import envoy.event.ContactOperation; -import envoy.event.ContactOperation.Operation; +import envoy.event.ContactOperationEvent; +import envoy.event.ContactOperationEvent.Operation; import envoy.server.ConnectionManager; import envoy.server.ObjectProcessor; import envoy.server.database.PersistenceManager; @@ -13,21 +13,21 @@ import envoy.server.net.ObjectWriteProxy; * Project: envoy-server-standalone
* File: ContactOperationProcessor.java
* Created: 08.02.2020
- * + * * @author Kai S. K. Engelbart * @since Envoy Server Standalone v0.1-alpha */ -public class ContactOperationProcessor implements ObjectProcessor { +public class ContactOperationProcessor implements ObjectProcessor { @Override - public void process(ContactOperation operation, long socketId, ObjectWriteProxy writeProxy) throws IOException { + public void process(ContactOperationEvent operation, long socketId, ObjectWriteProxy writeProxy) throws IOException { if (operation.getOperationType() == Operation.ADD) { long userId = ConnectionManager.getInstance().getUserIdBySocketId(socketId); - System.out.printf("Adding user %s to the contact list of user %d", operation.get(), userId); + System.out.printf("Adding user %s to the contact list of user %d.%n", operation.get(), userId); PersistenceManager.getPersistenceManager().addContact(userId, operation.get().getId()); } } @Override - public Class getInputClass() { return ContactOperation.class; } + public Class getInputClass() { return ContactOperationEvent.class; } } diff --git a/src/main/java/envoy/server/processors/ContactsRequestEventProcessor.java b/src/main/java/envoy/server/processors/ContactsRequestEventProcessor.java new file mode 100644 index 0000000..06a2d11 --- /dev/null +++ b/src/main/java/envoy/server/processors/ContactsRequestEventProcessor.java @@ -0,0 +1,44 @@ +package envoy.server.processors; + +import java.io.IOException; +import java.util.stream.Collectors; + +import envoy.data.Contacts; +import envoy.event.ContactSearchRequest; +import envoy.server.ConnectionManager; +import envoy.server.ObjectProcessor; +import envoy.server.data.User; +import envoy.server.database.PersistenceManager; +import envoy.server.net.ObjectWriteProxy; + +/** + * Project: envoy-server-standalone
+ * File: ContactsRequestEventProcessor.java
+ * Created: 08.02.2020
+ * + * @author Kai S. K. Engelbart + * @author Maximilian Käfer + * @since Envoy Server Standalone v0.1-alpha + */ +public class ContactsRequestEventProcessor implements ObjectProcessor { + + /** + * Writes a {@link Contacts} list to the client containing all {@link User}s + * matching the search phrase contained inside the request. The client and their + * contacts are excluded from the result. + * + * @since Envoy Server Standalone v0.1-alpha + */ + @Override + public void process(ContactSearchRequest request, long socketId, ObjectWriteProxy writeProxy) throws IOException { + writeProxy.write(socketId, + new Contacts(PersistenceManager.getPersistenceManager() + .searchUsers(request.get(), ConnectionManager.getInstance().getUserIdBySocketId(socketId)) + .stream() + .map(User::toCommonUser) + .collect(Collectors.toList()))); + } + + @Override + public Class getInputClass() { return ContactSearchRequest.class; } +} diff --git a/src/main/java/envoy/server/processors/ContactsRequestProcesor.java b/src/main/java/envoy/server/processors/ContactsRequestProcesor.java deleted file mode 100644 index 32e9714..0000000 --- a/src/main/java/envoy/server/processors/ContactsRequestProcesor.java +++ /dev/null @@ -1,55 +0,0 @@ -package envoy.server.processors; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import envoy.data.Contacts; -import envoy.event.ContactsRequest; -import envoy.server.ObjectProcessor; -import envoy.server.data.User; -import envoy.server.database.PersistenceManager; -import envoy.server.net.ObjectWriteProxy; - -/** - * Project: envoy-server-standalone
- * File: ContactsRequestProcesor.java
- * Created: 08.02.2020
- * - * @author Kai S. K. Engelbart - * @author Maximilian Käfer - * @since Envoy Server Standalone v0.1-alpha - */ -public class ContactsRequestProcesor implements ObjectProcessor { - - @Override - public void process(ContactsRequest request, long socketId, ObjectWriteProxy writeProxy) throws IOException { - // Creating a List containing all searchResults - List resultList = PersistenceManager.getPersistenceManager().searchUsers(request.get()); - // Creating a List containing all contacts of the client this event comes from. - List clientContacts = PersistenceManager.getPersistenceManager() - .getContacts(PersistenceManager.getPersistenceManager().getUserById(request.getClient().getId())); - List returnList = new ArrayList(); - - // Checking for already existing users in the contacts of the client an only - // adding the ones not included to the returnList. - if (clientContacts.size() != 0) { - for (int i = 0; i < resultList.size(); i++) { - for (int j = 0; j < clientContacts.size(); j++) { - if (resultList.get(i).getId() != clientContacts.get(j).getId()) { returnList.add(resultList.get(i)); } - } - } - } else { - for (int i = 0; i < resultList.size(); i++) { - returnList.add(resultList.get(i)); - } - } - // Create new Contacts object from returnList - Contacts contacts = new Contacts(returnList.stream().map(envoy.server.data.User::toCommonUser).collect(Collectors.toList())); - writeProxy.write(socketId, contacts); - } - - @Override - public Class getInputClass() { return ContactsRequest.class; } -} diff --git a/src/main/java/envoy/server/processors/LoginCredentialProcessor.java b/src/main/java/envoy/server/processors/LoginCredentialProcessor.java index 1c16070..c7475e9 100644 --- a/src/main/java/envoy/server/processors/LoginCredentialProcessor.java +++ b/src/main/java/envoy/server/processors/LoginCredentialProcessor.java @@ -1,9 +1,7 @@ package envoy.server.processors; import java.io.IOException; -import java.util.Arrays; -import java.util.Date; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import envoy.data.Contacts; @@ -81,7 +79,7 @@ public class LoginCredentialProcessor implements ObjectProcessor()); } else { user = persistenceManager.getUserByName(credentials.getName()); // TODO: Implement error when user does not exist From e2e9253413cd09ff3356826540d089f7a3d4d9d4 Mon Sep 17 00:00:00 2001 From: kske Date: Tue, 11 Feb 2020 17:17:45 +0100 Subject: [PATCH 08/10] Adjusted to event system refactoring --- .../envoy/server/processors/ContactsRequestEventProcessor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/envoy/server/processors/ContactsRequestEventProcessor.java b/src/main/java/envoy/server/processors/ContactsRequestEventProcessor.java index 06a2d11..e96c16e 100644 --- a/src/main/java/envoy/server/processors/ContactsRequestEventProcessor.java +++ b/src/main/java/envoy/server/processors/ContactsRequestEventProcessor.java @@ -5,6 +5,7 @@ import java.util.stream.Collectors; import envoy.data.Contacts; import envoy.event.ContactSearchRequest; +import envoy.event.ContactSearchResult; import envoy.server.ConnectionManager; import envoy.server.ObjectProcessor; import envoy.server.data.User; @@ -32,7 +33,7 @@ public class ContactsRequestEventProcessor implements ObjectProcessor Date: Tue, 11 Feb 2020 17:44:58 +0100 Subject: [PATCH 09/10] Implemented online contact notification about contact list modification --- .../processors/ContactOperationProcessor.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/main/java/envoy/server/processors/ContactOperationProcessor.java b/src/main/java/envoy/server/processors/ContactOperationProcessor.java index 475f8a2..0395026 100644 --- a/src/main/java/envoy/server/processors/ContactOperationProcessor.java +++ b/src/main/java/envoy/server/processors/ContactOperationProcessor.java @@ -1,9 +1,10 @@ package envoy.server.processors; import java.io.IOException; +import java.util.Arrays; +import envoy.data.Contacts; import envoy.event.ContactOperationEvent; -import envoy.event.ContactOperationEvent.Operation; import envoy.server.ConnectionManager; import envoy.server.ObjectProcessor; import envoy.server.database.PersistenceManager; @@ -19,12 +20,25 @@ import envoy.server.net.ObjectWriteProxy; */ public class ContactOperationProcessor implements ObjectProcessor { + private static final ConnectionManager connectionManager = ConnectionManager.getInstance(); + @Override - public void process(ContactOperationEvent operation, long socketId, ObjectWriteProxy writeProxy) throws IOException { - if (operation.getOperationType() == Operation.ADD) { - long userId = ConnectionManager.getInstance().getUserIdBySocketId(socketId); - System.out.printf("Adding user %s to the contact list of user %d.%n", operation.get(), userId); - PersistenceManager.getPersistenceManager().addContact(userId, operation.get().getId()); + public void process(ContactOperationEvent evt, long socketId, ObjectWriteProxy writeProxy) throws IOException { + switch (evt.getOperationType()) { + case ADD: + final long userId = ConnectionManager.getInstance().getUserIdBySocketId(socketId); + final long contactId = evt.get().getId(); + + System.out.printf("Adding user %s to the contact list of user %d.%n", evt.get(), userId); + PersistenceManager.getPersistenceManager().addContact(userId, contactId); + + // Notify the contact + // TODO: cache notification for offline mode + if (ConnectionManager.getInstance().isOnline(contactId)) writeProxy.write(connectionManager.getSocketId(contactId), + new Contacts(Arrays.asList(PersistenceManager.getPersistenceManager().getUserById(userId).toCommonUser()))); + break; + default: + System.err.printf("Received %s with an unsupported operation.%n", evt); } } From e2ed5706a7958f5a0f5c2d8082a12fd605302204 Mon Sep 17 00:00:00 2001 From: kske Date: Tue, 11 Feb 2020 18:15:19 +0100 Subject: [PATCH 10/10] Removed unnecessary TODO --- .../envoy/server/processors/ContactOperationProcessor.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/envoy/server/processors/ContactOperationProcessor.java b/src/main/java/envoy/server/processors/ContactOperationProcessor.java index 0395026..48ec6d9 100644 --- a/src/main/java/envoy/server/processors/ContactOperationProcessor.java +++ b/src/main/java/envoy/server/processors/ContactOperationProcessor.java @@ -32,8 +32,7 @@ public class ContactOperationProcessor implements ObjectProcessor