package envoy.server.data; import java.time.LocalDateTime; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import envoy.data.User.UserStatus; import envoy.server.net.ConnectionManager; /** * Project: envoy-server-standalone
* File: PersistenceManager.java
* Created: 1 Jan 2020
* * @author Leon Hofmeister * @author Maximilian Käfer * @since Envoy Server Standalone v0.1-alpha */ public class PersistenceManager { private final EntityManager entityManager = Persistence.createEntityManagerFactory("envoy").createEntityManager(); private final EntityTransaction transaction = entityManager.getTransaction(); private static final PersistenceManager persistenceManager = new PersistenceManager(); /** * Creates the singleton instance of the @link{PersistenceManager}. * * @since Envoy Server Standalone v0.1-alpha */ private PersistenceManager() { Runtime.getRuntime().addShutdownHook(new Thread(() -> { transaction.begin(); ConnectionManager.getInstance() .getOnlineUsers() .stream() .map(this::getUserByID) .forEach(user -> { user.setStatus(UserStatus.OFFLINE); user.setLastSeen(LocalDateTime.now()); entityManager.merge(user); }); transaction.commit(); })); } /** * @return the {@link PersistenceManager} singleton * @since Envoy Server Standalone v0.1-alpha */ public static PersistenceManager getInstance() { return persistenceManager; } /** * Adds a {@link Contact} to the database. * * @param contact the {@link Contact} to add to the database * @since Envoy Server Standalone v0.1-alpha */ public void addContact(Contact contact) { persist(contact); } /** * Adds a {@link Message} to the database. * * @param message the {@link Message} to add to the database * @since Envoy Server Standalone v0.1-alpha */ public void addMessage(Message message) { persist(message); } /** * Adds a {@link ConfigItem} to the database. * * @param configItem the {@link ConfigItem} to add to the database * @since Envoy Server Standalone v0.1-alpha */ public void addConfigItem(ConfigItem configItem) { persist(configItem); } /** * Updates a {@link Contact} in the database * * @param contact the {@link Contact} to add to the database * @since Envoy Server Standalone v0.1-alpha */ public void updateContact(Contact contact) { merge(contact); } /** * Updates a {@link Message} in the database. * * @param message the message to update * @since Envoy Server Standalone v0.1-alpha */ public void updateMessage(Message message) { merge(message); } /** * Updates a {@link ConfigItem} in the database. * * @param configItem the configItem to update * @since Envoy Server Standalone v0.1-alpha */ public void updateConfigItem(ConfigItem configItem) { merge(configItem); } /** * Deletes a {@link Contact} in the database. * * @param contact the {@link Contact} to delete * @since Envoy Server Standalone v0.1-alpha */ public void deleteContact(Contact contact) { remove(contact); } /** * Deletes a {@link Message} in the database. * * @param message the {@link Message} to delete * @since Envoy Server Standalone v0.1-alpha */ public void deleteMessage(Message message) { remove(message); } /** * Searches for a {@link User} with a specific ID. * * @param id the id to search for * @return the user with the specified ID or {@code null} if none was found * @since Envoy Server Standalone v0.1-alpha */ public User getUserByID(long id) { return entityManager.find(User.class, id); } /** * Searches for a {@link Group} with a specific ID. * * @param id the id to search for * @return the group with the specified ID or {@code null} if none was found * @since Envoy Server Standalone v0.1-beta */ public Group getGroupByID(long id) { return entityManager.find(Group.class, id); } /** * Searches for a {@link Contact} with a specific ID. * * @param id the id to search for * @return the contact with the specified ID or {@code null} if none was found * @since Envoy Server Standalone v0.1-beta */ public Contact getContactByID(long id) { return entityManager.find(Contact.class, id); } /** * Searched for a {@link User} with a specific name. * * @param name the name of the user * @return the user with the specified name * @since Envoy Server Standalone v0.1-alpha */ public User getUserByName(String name) { return (User) entityManager.createNamedQuery(User.findByName).setParameter("name", name).getSingleResult(); } /** * Searched for a {@link Group} with a specific name. * * @param name the name of the group * @return the group with the specified name * @since Envoy Server Standalone v0.1-alpha */ public Group getGroupByName(String name) { return (Group) entityManager.createNamedQuery(Group.findByName).setParameter("name", name).getSingleResult(); } /** * Searches for a {@link Message} with a specific id. * * @param id the id to search for * @return the message with the specified ID or {@code null} if none is found * @since Envoy Server Standalone v0.1-alpha */ public Message getMessageByID(long id) { return entityManager.find(Message.class, id); } /** * @param key the name of this {@link ConfigItem} * @return the {@link ConfigItem} with the given name * @since Envoy Server Standalone v0.1-alpha */ public ConfigItem getConfigItemByID(String key) { return entityManager.find(ConfigItem.class, key); } /** * Returns all messages received while being offline or the ones that have * changed. * * @param user the user who wants to receive his unread messages * @return all messages that the client does not yet have (unread messages) * @since Envoy Server Standalone v0.1-alpha */ public List getPendingMessages(User user) { return entityManager .createNamedQuery(Message.getPending) .setParameter("user", user) .setParameter("lastSeen", user.getLastSeen()) .getResultList(); } /** * Returns all groupMessages received while being offline or the ones that have * changed. * * @param user the user who wants to receive his unread groupMessages * @return all groupMessages that the client does not yet have (unread * groupMessages) * @since Envoy Server Standalone v0.1-alpha */ public List getPendingGroupMessages(User user) { return entityManager.createNamedQuery(GroupMessage.getPendingGroupMsg) .setParameter("userId", user.getID()) .setParameter("lastSeen", user.getLastSeen()) .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( User.searchByName) .setParameter("searchPhrase", searchPhrase + "%") .setParameter("context", getUserByID(userId)) .getResultList(); } /** * Adds a contact to the contact list of another contact and vice versa. * * @param contactID1 the ID of the first contact * @param contactID2 the ID of the second contact * @since Envoy Server Standalone v0.1-alpha */ public void addContactBidirectional(long contactID1, long contactID2) { // Get users by ID Contact c1 = getContactByID(contactID1); Contact c2 = getContactByID(contactID2); // Add users to each others contact lists c1.getContacts().add(c2); c2.getContacts().add(c1); // Synchronize changes with the database transaction.begin(); entityManager.merge(c1); entityManager.merge(c2); transaction.commit(); } /** * @param user the User whose contacts should be retrieved * @return the contacts of this User * @since Envoy Server Standalone v0.1-alpha */ public List getContacts(User user) { return entityManager.createNamedQuery(User.findContacts).setParameter("user", user).getResultList(); } private void persist(Object obj) { transaction.begin(); entityManager.persist(obj); transaction.commit(); } private void merge(Object obj) { transaction.begin(); entityManager.merge(obj); transaction.commit(); } private void remove(Object obj) { transaction.begin(); entityManager.remove(obj); transaction.commit(); } }